All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/9] drm: Extract drm_encoder.[hc]
@ 2016-08-29  8:27 Daniel Vetter
  2016-08-29  8:27 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

Same treatment as before. Only hiccup is drm_crtc_mask, which
unfortunately can't be resolved until drm_crtc.h is less of a monster.
Untangle the header loop with a forward declaration for that static
inline.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst       |   9 ++
 drivers/gpu/drm/Makefile            |   3 +-
 drivers/gpu/drm/drm_crtc.c          | 193 -------------------------------
 drivers/gpu/drm/drm_crtc_internal.h |  10 +-
 drivers/gpu/drm/drm_encoder.c       | 220 ++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h              | 134 +---------------------
 include/drm/drm_encoder.h           | 167 +++++++++++++++++++++++++++
 7 files changed, 407 insertions(+), 329 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_encoder.c
 create mode 100644 include/drm/drm_encoder.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index fa948b4e029b..7f788caebea3 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -125,6 +125,15 @@ Connector Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_connector.c
    :export:
 
+Encoder Abstraction
+===================
+
+.. kernel-doc:: include/drm/drm_encoder.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_encoder.c
+   :export:
+
 KMS Initialization and Cleanup
 ==============================
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 4054c94a2301..8aa3a7800560 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -13,7 +13,8 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_trace_points.o drm_global.o drm_prime.o \
 		drm_rect.o drm_vma_manager.o drm_flip_work.o \
 		drm_modeset_lock.o drm_atomic.o drm_bridge.o \
-		drm_framebuffer.o drm_connector.o drm_blend.o
+		drm_framebuffer.o drm_connector.o drm_blend.o \
+		drm_encoder.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 7ebe549051a6..389d013dcb36 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -54,18 +54,6 @@ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
 	{ DRM_PLANE_TYPE_CURSOR, "Cursor" },
 };
 
-static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
-	{ DRM_MODE_ENCODER_NONE, "None" },
-	{ DRM_MODE_ENCODER_DAC, "DAC" },
-	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
-	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
-	{ DRM_MODE_ENCODER_TVDAC, "TV" },
-	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
-	{ DRM_MODE_ENCODER_DSI, "DSI" },
-	{ DRM_MODE_ENCODER_DPMST, "DP MST" },
-	{ DRM_MODE_ENCODER_DPI, "DPI" },
-};
-
 /*
  * Optional properties
  */
@@ -419,117 +407,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_cleanup);
 
-static int drm_encoder_register_all(struct drm_device *dev)
-{
-	struct drm_encoder *encoder;
-	int ret = 0;
-
-	drm_for_each_encoder(encoder, dev) {
-		if (encoder->funcs->late_register)
-			ret = encoder->funcs->late_register(encoder);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static void drm_encoder_unregister_all(struct drm_device *dev)
-{
-	struct drm_encoder *encoder;
-
-	drm_for_each_encoder(encoder, dev) {
-		if (encoder->funcs->early_unregister)
-			encoder->funcs->early_unregister(encoder);
-	}
-}
-
-/**
- * drm_encoder_init - Init a preallocated encoder
- * @dev: drm device
- * @encoder: the encoder to init
- * @funcs: callbacks for this encoder
- * @encoder_type: user visible type of the encoder
- * @name: printf style format string for the encoder name, or NULL for default name
- *
- * Initialises a preallocated encoder. Encoder should be
- * subclassed as part of driver encoder objects.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_encoder_init(struct drm_device *dev,
-		      struct drm_encoder *encoder,
-		      const struct drm_encoder_funcs *funcs,
-		      int encoder_type, const char *name, ...)
-{
-	int ret;
-
-	drm_modeset_lock_all(dev);
-
-	ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
-	if (ret)
-		goto out_unlock;
-
-	encoder->dev = dev;
-	encoder->encoder_type = encoder_type;
-	encoder->funcs = funcs;
-	if (name) {
-		va_list ap;
-
-		va_start(ap, name);
-		encoder->name = kvasprintf(GFP_KERNEL, name, ap);
-		va_end(ap);
-	} else {
-		encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
-					  drm_encoder_enum_list[encoder_type].name,
-					  encoder->base.id);
-	}
-	if (!encoder->name) {
-		ret = -ENOMEM;
-		goto out_put;
-	}
-
-	list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
-	encoder->index = dev->mode_config.num_encoder++;
-
-out_put:
-	if (ret)
-		drm_mode_object_unregister(dev, &encoder->base);
-
-out_unlock:
-	drm_modeset_unlock_all(dev);
-
-	return ret;
-}
-EXPORT_SYMBOL(drm_encoder_init);
-
-/**
- * drm_encoder_cleanup - cleans up an initialised encoder
- * @encoder: encoder to cleanup
- *
- * Cleans up the encoder but doesn't free the object.
- */
-void drm_encoder_cleanup(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-
-	/* Note that the encoder_list is considered to be static; should we
-	 * remove the drm_encoder at runtime we would have to decrement all
-	 * the indices on the drm_encoder after us in the encoder_list.
-	 */
-
-	drm_modeset_lock_all(dev);
-	drm_mode_object_unregister(dev, &encoder->base);
-	kfree(encoder->name);
-	list_del(&encoder->head);
-	dev->mode_config.num_encoder--;
-	drm_modeset_unlock_all(dev);
-
-	memset(encoder, 0, sizeof(*encoder));
-}
-EXPORT_SYMBOL(drm_encoder_cleanup);
-
 static unsigned int drm_num_planes(struct drm_device *dev)
 {
 	unsigned int num = 0;
@@ -1167,76 +1044,6 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
 	return 0;
 }
 
-static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
-{
-	struct drm_connector *connector;
-	struct drm_device *dev = encoder->dev;
-	bool uses_atomic = false;
-
-	/* For atomic drivers only state objects are synchronously updated and
-	 * protected by modeset locks, so check those first. */
-	drm_for_each_connector(connector, dev) {
-		if (!connector->state)
-			continue;
-
-		uses_atomic = true;
-
-		if (connector->state->best_encoder != encoder)
-			continue;
-
-		return connector->state->crtc;
-	}
-
-	/* Don't return stale data (e.g. pending async disable). */
-	if (uses_atomic)
-		return NULL;
-
-	return encoder->crtc;
-}
-
-/**
- * drm_mode_getencoder - get encoder configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Construct a encoder configuration structure to return to the user.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getencoder(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	struct drm_mode_get_encoder *enc_resp = data;
-	struct drm_encoder *encoder;
-	struct drm_crtc *crtc;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	encoder = drm_encoder_find(dev, enc_resp->encoder_id);
-	if (!encoder)
-		return -ENOENT;
-
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	crtc = drm_encoder_get_crtc(encoder);
-	if (crtc)
-		enc_resp->crtc_id = crtc->base.id;
-	else
-		enc_resp->crtc_id = 0;
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
-
-	enc_resp->encoder_type = encoder->encoder_type;
-	enc_resp->encoder_id = encoder->base.id;
-	enc_resp->possible_crtcs = encoder->possible_crtcs;
-	enc_resp->possible_clones = encoder->possible_clones;
-
-	return 0;
-}
-
 /**
  * drm_mode_getplane_res - enumerate all plane resources
  * @dev: DRM device
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 97b00312a3cf..69f2b21ddad3 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -105,8 +105,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
 			      void *data, struct drm_file *file_priv);
 int drm_mode_destroyblob_ioctl(struct drm_device *dev,
 			       void *data, struct drm_file *file_priv);
-int drm_mode_getencoder(struct drm_device *dev,
-			void *data, struct drm_file *file_priv);
 int drm_mode_gamma_get_ioctl(struct drm_device *dev,
 			     void *data, struct drm_file *file_priv);
 int drm_mode_gamma_set_ioctl(struct drm_device *dev,
@@ -115,6 +113,14 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 int drm_mode_page_flip_ioctl(struct drm_device *dev,
 			     void *data, struct drm_file *file_priv);
 
+/* drm_encoder.c */
+int drm_encoder_register_all(struct drm_device *dev);
+void drm_encoder_unregister_all(struct drm_device *dev);
+
+/* IOCTL */
+int drm_mode_getencoder(struct drm_device *dev,
+			void *data, struct drm_file *file_priv);
+
 /* drm_connector.c */
 void drm_connector_ida_init(void);
 void drm_connector_ida_destroy(void);
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
new file mode 100644
index 000000000000..bce781b7bb5f
--- /dev/null
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include <drm/drmP.h>
+#include <drm/drm_encoder.h>
+
+#include "drm_crtc_internal.h"
+
+static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
+	{ DRM_MODE_ENCODER_NONE, "None" },
+	{ DRM_MODE_ENCODER_DAC, "DAC" },
+	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
+	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
+	{ DRM_MODE_ENCODER_TVDAC, "TV" },
+	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
+	{ DRM_MODE_ENCODER_DSI, "DSI" },
+	{ DRM_MODE_ENCODER_DPMST, "DP MST" },
+	{ DRM_MODE_ENCODER_DPI, "DPI" },
+};
+
+int drm_encoder_register_all(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+	int ret = 0;
+
+	drm_for_each_encoder(encoder, dev) {
+		if (encoder->funcs->late_register)
+			ret = encoder->funcs->late_register(encoder);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void drm_encoder_unregister_all(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+
+	drm_for_each_encoder(encoder, dev) {
+		if (encoder->funcs->early_unregister)
+			encoder->funcs->early_unregister(encoder);
+	}
+}
+
+/**
+ * drm_encoder_init - Init a preallocated encoder
+ * @dev: drm device
+ * @encoder: the encoder to init
+ * @funcs: callbacks for this encoder
+ * @encoder_type: user visible type of the encoder
+ * @name: printf style format string for the encoder name, or NULL for default name
+ *
+ * Initialises a preallocated encoder. Encoder should be
+ * subclassed as part of driver encoder objects.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_encoder_init(struct drm_device *dev,
+		      struct drm_encoder *encoder,
+		      const struct drm_encoder_funcs *funcs,
+		      int encoder_type, const char *name, ...)
+{
+	int ret;
+
+	drm_modeset_lock_all(dev);
+
+	ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
+	if (ret)
+		goto out_unlock;
+
+	encoder->dev = dev;
+	encoder->encoder_type = encoder_type;
+	encoder->funcs = funcs;
+	if (name) {
+		va_list ap;
+
+		va_start(ap, name);
+		encoder->name = kvasprintf(GFP_KERNEL, name, ap);
+		va_end(ap);
+	} else {
+		encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
+					  drm_encoder_enum_list[encoder_type].name,
+					  encoder->base.id);
+	}
+	if (!encoder->name) {
+		ret = -ENOMEM;
+		goto out_put;
+	}
+
+	list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
+	encoder->index = dev->mode_config.num_encoder++;
+
+out_put:
+	if (ret)
+		drm_mode_object_unregister(dev, &encoder->base);
+
+out_unlock:
+	drm_modeset_unlock_all(dev);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_encoder_init);
+
+/**
+ * drm_encoder_cleanup - cleans up an initialised encoder
+ * @encoder: encoder to cleanup
+ *
+ * Cleans up the encoder but doesn't free the object.
+ */
+void drm_encoder_cleanup(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+
+	/* Note that the encoder_list is considered to be static; should we
+	 * remove the drm_encoder at runtime we would have to decrement all
+	 * the indices on the drm_encoder after us in the encoder_list.
+	 */
+
+	drm_modeset_lock_all(dev);
+	drm_mode_object_unregister(dev, &encoder->base);
+	kfree(encoder->name);
+	list_del(&encoder->head);
+	dev->mode_config.num_encoder--;
+	drm_modeset_unlock_all(dev);
+
+	memset(encoder, 0, sizeof(*encoder));
+}
+EXPORT_SYMBOL(drm_encoder_cleanup);
+
+static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_device *dev = encoder->dev;
+	bool uses_atomic = false;
+
+	/* For atomic drivers only state objects are synchronously updated and
+	 * protected by modeset locks, so check those first. */
+	drm_for_each_connector(connector, dev) {
+		if (!connector->state)
+			continue;
+
+		uses_atomic = true;
+
+		if (connector->state->best_encoder != encoder)
+			continue;
+
+		return connector->state->crtc;
+	}
+
+	/* Don't return stale data (e.g. pending async disable). */
+	if (uses_atomic)
+		return NULL;
+
+	return encoder->crtc;
+}
+
+/**
+ * drm_mode_getencoder - get encoder configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Construct a encoder configuration structure to return to the user.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getencoder(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_get_encoder *enc_resp = data;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	encoder = drm_encoder_find(dev, enc_resp->encoder_id);
+	if (!encoder)
+		return -ENOENT;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	crtc = drm_encoder_get_crtc(encoder);
+	if (crtc)
+		enc_resp->crtc_id = crtc->base.id;
+	else
+		enc_resp->crtc_id = 0;
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+	enc_resp->encoder_type = encoder->encoder_type;
+	enc_resp->encoder_id = encoder->base.id;
+	enc_resp->possible_crtcs = encoder->possible_crtcs;
+	enc_resp->possible_clones = encoder->possible_clones;
+
+	return 0;
+}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 6ac1630d6499..7a53b053cbe7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -40,6 +40,7 @@
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_modes.h>
 #include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
 
 struct drm_device;
 struct drm_mode_set;
@@ -662,97 +663,6 @@ struct drm_crtc {
 };
 
 /**
- * struct drm_encoder_funcs - encoder controls
- *
- * Encoders sit between CRTCs and connectors.
- */
-struct drm_encoder_funcs {
-	/**
-	 * @reset:
-	 *
-	 * Reset encoder hardware and software state to off. This function isn't
-	 * called by the core directly, only through drm_mode_config_reset().
-	 * It's not a helper hook only for historical reasons.
-	 */
-	void (*reset)(struct drm_encoder *encoder);
-
-	/**
-	 * @destroy:
-	 *
-	 * Clean up encoder resources. This is only called at driver unload time
-	 * through drm_mode_config_cleanup() since an encoder cannot be
-	 * hotplugged in DRM.
-	 */
-	void (*destroy)(struct drm_encoder *encoder);
-
-	/**
-	 * @late_register:
-	 *
-	 * This optional hook can be used to register additional userspace
-	 * interfaces attached to the encoder like debugfs interfaces.
-	 * It is called late in the driver load sequence from drm_dev_register().
-	 * Everything added from this callback should be unregistered in
-	 * the early_unregister callback.
-	 *
-	 * Returns:
-	 *
-	 * 0 on success, or a negative error code on failure.
-	 */
-	int (*late_register)(struct drm_encoder *encoder);
-
-	/**
-	 * @early_unregister:
-	 *
-	 * This optional hook should be used to unregister the additional
-	 * userspace interfaces attached to the encoder from
-	 * late_unregister(). It is called from drm_dev_unregister(),
-	 * early in the driver unload sequence to disable userspace access
-	 * before data structures are torndown.
-	 */
-	void (*early_unregister)(struct drm_encoder *encoder);
-};
-
-/**
- * struct drm_encoder - central DRM encoder structure
- * @dev: parent DRM device
- * @head: list management
- * @base: base KMS object
- * @name: human readable name, can be overwritten by the driver
- * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
- * @possible_crtcs: bitmask of potential CRTC bindings
- * @possible_clones: bitmask of potential sibling encoders for cloning
- * @crtc: currently bound CRTC
- * @bridge: bridge associated to the encoder
- * @funcs: control functions
- * @helper_private: mid-layer private data
- *
- * CRTCs drive pixels to encoders, which convert them into signals
- * appropriate for a given connector or set of connectors.
- */
-struct drm_encoder {
-	struct drm_device *dev;
-	struct list_head head;
-
-	struct drm_mode_object base;
-	char *name;
-	int encoder_type;
-
-	/**
-	 * @index: Position inside the mode_config.list, can be used as an array
-	 * index. It is invariant over the lifetime of the encoder.
-	 */
-	unsigned index;
-
-	uint32_t possible_crtcs;
-	uint32_t possible_clones;
-
-	struct drm_crtc *crtc;
-	struct drm_bridge *bridge;
-	const struct drm_encoder_funcs *funcs;
-	const struct drm_encoder_helper_funcs *helper_private;
-};
-
-/**
  * struct drm_plane_state - mutable plane state
  * @plane: backpointer to the plane
  * @crtc: currently bound CRTC, NULL if disabled
@@ -2120,7 +2030,6 @@ struct drm_mode_config {
 		for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder)))
 
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
-#define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
 #define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
 #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
 #define obj_to_property(x) container_of(x, struct drm_property, base)
@@ -2165,37 +2074,6 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
 	return 1 << drm_crtc_index(crtc);
 }
 
-extern __printf(5, 6)
-int drm_encoder_init(struct drm_device *dev,
-		     struct drm_encoder *encoder,
-		     const struct drm_encoder_funcs *funcs,
-		     int encoder_type, const char *name, ...);
-
-/**
- * drm_encoder_index - find the index of a registered encoder
- * @encoder: encoder to find index for
- *
- * Given a registered encoder, return the index of that encoder within a DRM
- * device's list of encoders.
- */
-static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
-{
-	return encoder->index;
-}
-
-/**
- * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
- * @encoder: encoder to test
- * @crtc: crtc to test
- *
- * Return false if @encoder can't be driven by @crtc, true otherwise.
- */
-static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
-				       struct drm_crtc *crtc)
-{
-	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
-}
-
 extern __printf(8, 9)
 int drm_universal_plane_init(struct drm_device *dev,
 			     struct drm_plane *plane,
@@ -2231,8 +2109,6 @@ extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
 extern int drm_crtc_force_disable(struct drm_crtc *crtc);
 extern int drm_crtc_force_disable_all(struct drm_device *dev);
 
-extern void drm_encoder_cleanup(struct drm_encoder *encoder);
-
 extern void drm_mode_config_init(struct drm_device *dev);
 extern void drm_mode_config_reset(struct drm_device *dev);
 extern void drm_mode_config_cleanup(struct drm_device *dev);
@@ -2344,14 +2220,6 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
 	return mo ? obj_to_crtc(mo) : NULL;
 }
 
-static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
-	uint32_t id)
-{
-	struct drm_mode_object *mo;
-	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
-	return mo ? obj_to_encoder(mo) : NULL;
-}
-
 static inline struct drm_property *drm_property_find(struct drm_device *dev,
 		uint32_t id)
 {
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
new file mode 100644
index 000000000000..2712fd1a686b
--- /dev/null
+++ b/include/drm/drm_encoder.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef __DRM_ENCODER_H__
+#define __DRM_ENCODER_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <drm/drm_modeset.h>
+
+/**
+ * struct drm_encoder_funcs - encoder controls
+ *
+ * Encoders sit between CRTCs and connectors.
+ */
+struct drm_encoder_funcs {
+	/**
+	 * @reset:
+	 *
+	 * Reset encoder hardware and software state to off. This function isn't
+	 * called by the core directly, only through drm_mode_config_reset().
+	 * It's not a helper hook only for historical reasons.
+	 */
+	void (*reset)(struct drm_encoder *encoder);
+
+	/**
+	 * @destroy:
+	 *
+	 * Clean up encoder resources. This is only called at driver unload time
+	 * through drm_mode_config_cleanup() since an encoder cannot be
+	 * hotplugged in DRM.
+	 */
+	void (*destroy)(struct drm_encoder *encoder);
+
+	/**
+	 * @late_register:
+	 *
+	 * This optional hook can be used to register additional userspace
+	 * interfaces attached to the encoder like debugfs interfaces.
+	 * It is called late in the driver load sequence from drm_dev_register().
+	 * Everything added from this callback should be unregistered in
+	 * the early_unregister callback.
+	 *
+	 * Returns:
+	 *
+	 * 0 on success, or a negative error code on failure.
+	 */
+	int (*late_register)(struct drm_encoder *encoder);
+
+	/**
+	 * @early_unregister:
+	 *
+	 * This optional hook should be used to unregister the additional
+	 * userspace interfaces attached to the encoder from
+	 * late_unregister(). It is called from drm_dev_unregister(),
+	 * early in the driver unload sequence to disable userspace access
+	 * before data structures are torndown.
+	 */
+	void (*early_unregister)(struct drm_encoder *encoder);
+};
+
+/**
+ * struct drm_encoder - central DRM encoder structure
+ * @dev: parent DRM device
+ * @head: list management
+ * @base: base KMS object
+ * @name: human readable name, can be overwritten by the driver
+ * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
+ * @possible_crtcs: bitmask of potential CRTC bindings
+ * @possible_clones: bitmask of potential sibling encoders for cloning
+ * @crtc: currently bound CRTC
+ * @bridge: bridge associated to the encoder
+ * @funcs: control functions
+ * @helper_private: mid-layer private data
+ *
+ * CRTCs drive pixels to encoders, which convert them into signals
+ * appropriate for a given connector or set of connectors.
+ */
+struct drm_encoder {
+	struct drm_device *dev;
+	struct list_head head;
+
+	struct drm_mode_object base;
+	char *name;
+	int encoder_type;
+
+	/**
+	 * @index: Position inside the mode_config.list, can be used as an array
+	 * index. It is invariant over the lifetime of the encoder.
+	 */
+	unsigned index;
+
+	uint32_t possible_crtcs;
+	uint32_t possible_clones;
+
+	struct drm_crtc *crtc;
+	struct drm_bridge *bridge;
+	const struct drm_encoder_funcs *funcs;
+	const struct drm_encoder_helper_funcs *helper_private;
+};
+
+#define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
+
+__printf(5, 6)
+int drm_encoder_init(struct drm_device *dev,
+		     struct drm_encoder *encoder,
+		     const struct drm_encoder_funcs *funcs,
+		     int encoder_type, const char *name, ...);
+
+/**
+ * drm_encoder_index - find the index of a registered encoder
+ * @encoder: encoder to find index for
+ *
+ * Given a registered encoder, return the index of that encoder within a DRM
+ * device's list of encoders.
+ */
+static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
+{
+	return encoder->index;
+}
+
+/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
+static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc);
+
+/**
+ * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
+ * @encoder: encoder to test
+ * @crtc: crtc to test
+ *
+ * Return false if @encoder can't be driven by @crtc, true otherwise.
+ */
+static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+				       struct drm_crtc *crtc)
+{
+	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
+}
+
+static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
+	uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+	return mo ? obj_to_encoder(mo) : NULL;
+}
+
+void drm_encoder_cleanup(struct drm_encoder *encoder);
+
+#endif
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/9] drm/doc: Polish kerneldoc for encoders
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-09-15  4:47   ` [2/9] " Pandiyan, Dhinakaran
  2016-08-29  8:27 ` [PATCH 3/9] drm: Extract drm_mode_object.[hc] Daniel Vetter
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- Move missing bits into struct drm_encoder docs.
- Explain that encoders are 95% internal and only 5% uapi, and that in
  general the uapi part is broken.
- Remove verbose comments for functions not exposed to drivers.

v2: Review from Archit:
- Appease checkpatch in the moved code.
- Make it clearer that bridges are not exposed to userspace.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst | 46 ++++------------------------
 drivers/gpu/drm/drm_encoder.c | 48 ++++++++++++++++++-----------
 include/drm/drm_encoder.h     | 70 +++++++++++++++++++++++++++++++++++++++----
 3 files changed, 101 insertions(+), 63 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 7f788caebea3..47c2835b7c2d 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -128,6 +128,12 @@ Connector Functions Reference
 Encoder Abstraction
 ===================
 
+.. kernel-doc:: drivers/gpu/drm/drm_encoder.c
+   :doc: overview
+
+Encoder Functions Reference
+---------------------------
+
 .. kernel-doc:: include/drm/drm_encoder.h
    :internal:
 
@@ -207,46 +213,6 @@ future); drivers that do not wish to provide special handling for
 primary planes may make use of the helper functions described in ? to
 create and register a primary plane with standard capabilities.
 
-Encoders (:c:type:`struct drm_encoder <drm_encoder>`)
------------------------------------------------------
-
-An encoder takes pixel data from a CRTC and converts it to a format
-suitable for any attached connectors. On some devices, it may be
-possible to have a CRTC send data to more than one encoder. In that
-case, both encoders would receive data from the same scanout buffer,
-resulting in a "cloned" display configuration across the connectors
-attached to each encoder.
-
-Encoder Initialization
-~~~~~~~~~~~~~~~~~~~~~~
-
-As for CRTCs, a KMS driver must create, initialize and register at least
-one :c:type:`struct drm_encoder <drm_encoder>` instance. The
-instance is allocated and zeroed by the driver, possibly as part of a
-larger structure.
-
-Drivers must initialize the :c:type:`struct drm_encoder
-<drm_encoder>` possible_crtcs and possible_clones fields before
-registering the encoder. Both fields are bitmasks of respectively the
-CRTCs that the encoder can be connected to, and sibling encoders
-candidate for cloning.
-
-After being initialized, the encoder must be registered with a call to
-:c:func:`drm_encoder_init()`. The function takes a pointer to the
-encoder functions and an encoder type. Supported types are
-
--  DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
--  DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
--  DRM_MODE_ENCODER_LVDS for display panels
--  DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
-   Component, SCART)
--  DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
-
-Encoders must be attached to a CRTC to be used. DRM drivers leave
-encoders unattached at initialization time. Applications (or the fbdev
-compatibility layer when implemented) are responsible for attaching the
-encoders they want to use to a CRTC.
-
 Cleanup
 -------
 
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index bce781b7bb5f..998a6743a586 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -26,6 +26,30 @@
 
 #include "drm_crtc_internal.h"
 
+/**
+ * DOC: overview
+ *
+ * Encoders represent the connecting element between the CRTC (as the overall
+ * pixel pipeline, represented by struct &drm_crtc) and the connectors (as the
+ * generic sink entity, represented by struct &drm_connector). Encoders are
+ * objects exposed to userspace, originally to allow userspace to infer cloning
+ * and connector/CRTC restrictions. Unfortunately almost all drivers get this
+ * wrong, making the uabi pretty much useless. On top of that the exposed
+ * restrictions are too simple for todays hardware, and the recommend way to
+ * infer restrictions is by using the DRM_MODE_ATOMIC_TEST_ONLY flag for the
+ * atomic IOCTL.
+ *
+ * Otherwise encoders aren't used in the uapi at all (any modeset request from
+ * userspace directly connects a connector with a CRTC), drivers are therefore
+ * free to use them however they wish. Modeset helper libraries make strong use
+ * of encoders to facilitate code sharing. But for more complex settings it is
+ * usually better to move shared code into a separate &drm_bridge. Compared to
+ * encoders bridges also have the benefit of not being purely an internal
+ * abstraction since they are not exposed to userspace at all.
+ *
+ * Encoders are initialized with drm_encoder_init() and cleaned up using
+ * drm_encoder_cleanup().
+ */
 static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
 	{ DRM_MODE_ENCODER_NONE, "None" },
 	{ DRM_MODE_ENCODER_DAC, "DAC" },
@@ -71,16 +95,17 @@ void drm_encoder_unregister_all(struct drm_device *dev)
  * @encoder_type: user visible type of the encoder
  * @name: printf style format string for the encoder name, or NULL for default name
  *
- * Initialises a preallocated encoder. Encoder should be
- * subclassed as part of driver encoder objects.
+ * Initialises a preallocated encoder. Encoder should be subclassed as part of
+ * driver encoder objects. At driver unload time drm_encoder_cleanup() should be
+ * called from the driver's destroy hook in &drm_encoder_funcs.
  *
  * Returns:
  * Zero on success, error code on failure.
  */
 int drm_encoder_init(struct drm_device *dev,
-		      struct drm_encoder *encoder,
-		      const struct drm_encoder_funcs *funcs,
-		      int encoder_type, const char *name, ...)
+		     struct drm_encoder *encoder,
+		     const struct drm_encoder_funcs *funcs,
+		     int encoder_type, const char *name, ...)
 {
 	int ret;
 
@@ -176,19 +201,6 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
 	return encoder->crtc;
 }
 
-/**
- * drm_mode_getencoder - get encoder configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Construct a encoder configuration structure to return to the user.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
 int drm_mode_getencoder(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 2712fd1a686b..3d7350f1fcc1 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -84,9 +84,6 @@ struct drm_encoder_funcs {
  * @head: list management
  * @base: base KMS object
  * @name: human readable name, can be overwritten by the driver
- * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
- * @possible_crtcs: bitmask of potential CRTC bindings
- * @possible_clones: bitmask of potential sibling encoders for cloning
  * @crtc: currently bound CRTC
  * @bridge: bridge associated to the encoder
  * @funcs: control functions
@@ -101,6 +98,32 @@ struct drm_encoder {
 
 	struct drm_mode_object base;
 	char *name;
+	/**
+	 * @encoder_type:
+	 *
+	 * One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following
+	 * encoder types are defined thus far:
+	 *
+	 * - DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A.
+	 *
+	 * - DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort.
+	 *
+	 * - DRM_MODE_ENCODER_LVDS for display panels, or in general any panel
+	 *   with a proprietary parallel connector.
+	 *
+	 * - DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
+	 *   Component, SCART).
+	 *
+	 * - DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
+	 *
+	 * - DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus.
+	 *
+	 * - DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel
+	 *   bus.
+	 *
+	 * - DRM_MODE_ENCODER_DPMST for special fake encoders used to allow
+	 *   mutliple DP MST streams to share one physical encoder.
+	 */
 	int encoder_type;
 
 	/**
@@ -109,7 +132,34 @@ struct drm_encoder {
 	 */
 	unsigned index;
 
+	/**
+	 * @possible_crtcs: Bitmask of potential CRTC bindings, using
+	 * drm_crtc_index() as the index into the bitfield. The driver must set
+	 * the bits for all &drm_crtc objects this encoder can be connected to
+	 * before calling drm_encoder_init().
+	 *
+	 * In reality almost every driver gets this wrong.
+	 *
+	 * Note that since CRTC objects can't be hotplugged the assigned indices
+	 * are stable and hence known before registering all objects.
+	 */
 	uint32_t possible_crtcs;
+
+	/**
+	 * @possible_clones: Bitmask of potential sibling encoders for cloning,
+	 * using drm_encoder_index() as the index into the bitfield. The driver
+	 * must set the bits for all &drm_encoder objects which can clone a
+	 * &drm_crtc together with this encoder before calling
+	 * drm_encoder_init(). Drivers should set the bit representing the
+	 * encoder itself, too. Cloning bits should be set such that when two
+	 * encoders can be used in a cloned configuration, they both should have
+	 * each another bits set.
+	 *
+	 * In reality almost every driver gets this wrong.
+	 *
+	 * Note that since encoder objects can't be hotplugged the assigned indices
+	 * are stable and hence known before registering all objects.
+	 */
 	uint32_t possible_clones;
 
 	struct drm_crtc *crtc;
@@ -146,7 +196,7 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc);
  * @encoder: encoder to test
  * @crtc: crtc to test
  *
- * Return false if @encoder can't be driven by @crtc, true otherwise.
+ * Returns false if @encoder can't be driven by @crtc, true otherwise.
  */
 static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 				       struct drm_crtc *crtc)
@@ -154,11 +204,21 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
 }
 
+/**
+ * drm_encoder_find - find a &drm_encoder
+ * @dev: DRM device
+ * @id: encoder id
+ *
+ * Returns the encoder with @id, NULL if it doesn't exist. Simple wrapper around
+ * drm_mode_object_find().
+ */
 static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
-	uint32_t id)
+						   uint32_t id)
 {
 	struct drm_mode_object *mo;
+
 	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+
 	return mo ? obj_to_encoder(mo) : NULL;
 }
 
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/9] drm: Extract drm_mode_object.[hc]
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
  2016-08-29  8:27 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-08-29  8:27 ` [PATCH 4/9] drm: Remove drm_mode_object->atomic_count Daniel Vetter
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

Just for the struct drm_mode_object base class. The header file was
already partially extracted to help untangle the include loops.

v2:
- Also move the generic get/set property ioctls. At first this seemed
  like a bad idea since it requires making drm_mode_crtc_set_obj_prop
  non-static. But eventually that will get split away too (like
  the connector version already is) for both crtc and planes. Hence I
  reconsidered.

- drm_mode_object.[hc] instead of drm_modeset.[hc], which requires
  renaming the drm_modeset.h header I already started building up.
  This is more consistent (matches the name of the main structure),
  and I want to be able to use drm_modeset.[hc] for the basic modeset
  init/cleanup functionality like drm_mode_config_init.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst                    |   9 +
 drivers/gpu/drm/Makefile                         |   2 +-
 drivers/gpu/drm/drm_crtc.c                       | 413 +--------------------
 drivers/gpu/drm/drm_crtc_internal.h              |  52 +--
 drivers/gpu/drm/drm_mode_object.c                | 435 +++++++++++++++++++++++
 include/drm/drm_connector.h                      |   2 +-
 include/drm/drm_crtc.h                           |  12 +-
 include/drm/drm_encoder.h                        |   2 +-
 include/drm/drm_framebuffer.h                    |   2 +-
 include/drm/{drm_modeset.h => drm_mode_object.h} |  10 +
 include/drm/drm_modes.h                          |   2 +-
 11 files changed, 492 insertions(+), 449 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_mode_object.c
 rename include/drm/{drm_modeset.h => drm_mode_object.h} (87%)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 47c2835b7c2d..b164472f2157 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -15,6 +15,15 @@ be setup by initializing the following fields.
 -  struct drm_mode_config_funcs \*funcs;
    Mode setting functions.
 
+Modeset Base Object Abstraction
+===============================
+
+.. kernel-doc:: include/drm/drm_mode_object.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_mode_object.c
+   :export:
+
 KMS Data Structures
 ===================
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8aa3a7800560..8d379565ac8e 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_rect.o drm_vma_manager.o drm_flip_work.o \
 		drm_modeset_lock.o drm_atomic.o drm_bridge.o \
 		drm_framebuffer.o drm_connector.o drm_blend.o \
-		drm_encoder.o
+		drm_encoder.o drm_mode_object.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 389d013dcb36..7ec9f7e7a077 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -57,162 +57,6 @@ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
 /*
  * Optional properties
  */
-/*
- * Internal function to assign a slot in the object idr and optionally
- * register the object into the idr.
- */
-int drm_mode_object_get_reg(struct drm_device *dev,
-			    struct drm_mode_object *obj,
-			    uint32_t obj_type,
-			    bool register_obj,
-			    void (*obj_free_cb)(struct kref *kref))
-{
-	int ret;
-
-	mutex_lock(&dev->mode_config.idr_mutex);
-	ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL);
-	if (ret >= 0) {
-		/*
-		 * Set up the object linking under the protection of the idr
-		 * lock so that other users can't see inconsistent state.
-		 */
-		obj->id = ret;
-		obj->type = obj_type;
-		if (obj_free_cb) {
-			obj->free_cb = obj_free_cb;
-			kref_init(&obj->refcount);
-		}
-	}
-	mutex_unlock(&dev->mode_config.idr_mutex);
-
-	return ret < 0 ? ret : 0;
-}
-
-/**
- * drm_mode_object_get - allocate a new modeset identifier
- * @dev: DRM device
- * @obj: object pointer, used to generate unique ID
- * @obj_type: object type
- *
- * Create a unique identifier based on @ptr in @dev's identifier space.  Used
- * for tracking modes, CRTCs and connectors. Note that despite the _get postfix
- * modeset identifiers are _not_ reference counted. Hence don't use this for
- * reference counted modeset objects like framebuffers.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_mode_object_get(struct drm_device *dev,
-			struct drm_mode_object *obj, uint32_t obj_type)
-{
-	return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
-}
-
-void drm_mode_object_register(struct drm_device *dev,
-			      struct drm_mode_object *obj)
-{
-	mutex_lock(&dev->mode_config.idr_mutex);
-	idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
-	mutex_unlock(&dev->mode_config.idr_mutex);
-}
-
-/**
- * drm_mode_object_unregister - free a modeset identifer
- * @dev: DRM device
- * @object: object to free
- *
- * Free @id from @dev's unique identifier pool.
- * This function can be called multiple times, and guards against
- * multiple removals.
- * These modeset identifiers are _not_ reference counted. Hence don't use this
- * for reference counted modeset objects like framebuffers.
- */
-void drm_mode_object_unregister(struct drm_device *dev,
-			 struct drm_mode_object *object)
-{
-	mutex_lock(&dev->mode_config.idr_mutex);
-	if (object->id) {
-		idr_remove(&dev->mode_config.crtc_idr, object->id);
-		object->id = 0;
-	}
-	mutex_unlock(&dev->mode_config.idr_mutex);
-}
-
-struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
-					       uint32_t id, uint32_t type)
-{
-	struct drm_mode_object *obj = NULL;
-
-	mutex_lock(&dev->mode_config.idr_mutex);
-	obj = idr_find(&dev->mode_config.crtc_idr, id);
-	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
-		obj = NULL;
-	if (obj && obj->id != id)
-		obj = NULL;
-
-	if (obj && obj->free_cb) {
-		if (!kref_get_unless_zero(&obj->refcount))
-			obj = NULL;
-	}
-	mutex_unlock(&dev->mode_config.idr_mutex);
-
-	return obj;
-}
-
-/**
- * drm_mode_object_find - look up a drm object with static lifetime
- * @dev: drm device
- * @id: id of the mode object
- * @type: type of the mode object
- *
- * This function is used to look up a modeset object. It will acquire a
- * reference for reference counted objects. This reference must be dropped again
- * by callind drm_mode_object_unreference().
- */
-struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
-		uint32_t id, uint32_t type)
-{
-	struct drm_mode_object *obj = NULL;
-
-	obj = __drm_mode_object_find(dev, id, type);
-	return obj;
-}
-EXPORT_SYMBOL(drm_mode_object_find);
-
-/**
- * drm_mode_object_unreference - decr the object refcnt
- * @obj: mode_object
- *
- * This functions decrements the object's refcount if it is a refcounted modeset
- * object. It is a no-op on any other object. This is used to drop references
- * acquired with drm_mode_object_reference().
- */
-void drm_mode_object_unreference(struct drm_mode_object *obj)
-{
-	if (obj->free_cb) {
-		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
-		kref_put(&obj->refcount, obj->free_cb);
-	}
-}
-EXPORT_SYMBOL(drm_mode_object_unreference);
-
-/**
- * drm_mode_object_reference - incr the object refcnt
- * @obj: mode_object
- *
- * This functions increments the object's refcount if it is a refcounted modeset
- * object. It is a no-op on any other object. References should be dropped again
- * by calling drm_mode_object_unreference().
- */
-void drm_mode_object_reference(struct drm_mode_object *obj)
-{
-	if (obj->free_cb) {
-		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
-		kref_get(&obj->refcount);
-	}
-}
-EXPORT_SYMBOL(drm_mode_object_reference);
-
 /**
  * drm_crtc_force_disable - Forcibly turn off a CRTC
  * @crtc: CRTC to turn off
@@ -1005,45 +849,6 @@ int drm_mode_getcrtc(struct drm_device *dev,
 	return 0;
 }
 
-/* helper for getconnector and getproperties ioctls */
-int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
-				   uint32_t __user *prop_ptr,
-				   uint64_t __user *prop_values,
-				   uint32_t *arg_count_props)
-{
-	int props_count;
-	int i, ret, copied;
-
-	props_count = obj->properties->count;
-	if (!atomic)
-		props_count -= obj->properties->atomic_count;
-
-	if ((*arg_count_props >= props_count) && props_count) {
-		for (i = 0, copied = 0; copied < props_count; i++) {
-			struct drm_property *prop = obj->properties->properties[i];
-			uint64_t val;
-
-			if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
-				continue;
-
-			ret = drm_object_property_get_value(obj, prop, &val);
-			if (ret)
-				return ret;
-
-			if (put_user(prop->base.id, prop_ptr + copied))
-				return -EFAULT;
-
-			if (put_user(val, prop_values + copied))
-				return -EFAULT;
-
-			copied++;
-		}
-	}
-	*arg_count_props = props_count;
-
-	return 0;
-}
-
 /**
  * drm_mode_getplane_res - enumerate all plane resources
  * @dev: DRM device
@@ -2286,105 +2091,6 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
 EXPORT_SYMBOL(drm_property_destroy);
 
 /**
- * drm_object_attach_property - attach a property to a modeset object
- * @obj: drm modeset object
- * @property: property to attach
- * @init_val: initial value of the property
- *
- * This attaches the given property to the modeset object with the given initial
- * value. Currently this function cannot fail since the properties are stored in
- * a statically sized array.
- */
-void drm_object_attach_property(struct drm_mode_object *obj,
-				struct drm_property *property,
-				uint64_t init_val)
-{
-	int count = obj->properties->count;
-
-	if (count == DRM_OBJECT_MAX_PROPERTY) {
-		WARN(1, "Failed to attach object property (type: 0x%x). Please "
-			"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
-			"you see this message on the same object type.\n",
-			obj->type);
-		return;
-	}
-
-	obj->properties->properties[count] = property;
-	obj->properties->values[count] = init_val;
-	obj->properties->count++;
-	if (property->flags & DRM_MODE_PROP_ATOMIC)
-		obj->properties->atomic_count++;
-}
-EXPORT_SYMBOL(drm_object_attach_property);
-
-/**
- * drm_object_property_set_value - set the value of a property
- * @obj: drm mode object to set property value for
- * @property: property to set
- * @val: value the property should be set to
- *
- * This functions sets a given property on a given object. This function only
- * changes the software state of the property, it does not call into the
- * driver's ->set_property callback.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_object_property_set_value(struct drm_mode_object *obj,
-				  struct drm_property *property, uint64_t val)
-{
-	int i;
-
-	for (i = 0; i < obj->properties->count; i++) {
-		if (obj->properties->properties[i] == property) {
-			obj->properties->values[i] = val;
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(drm_object_property_set_value);
-
-/**
- * drm_object_property_get_value - retrieve the value of a property
- * @obj: drm mode object to get property value from
- * @property: property to retrieve
- * @val: storage for the property value
- *
- * This function retrieves the softare state of the given property for the given
- * property. Since there is no driver callback to retrieve the current property
- * value this might be out of sync with the hardware, depending upon the driver
- * and property.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_object_property_get_value(struct drm_mode_object *obj,
-				  struct drm_property *property, uint64_t *val)
-{
-	int i;
-
-	/* read-only properties bypass atomic mechanism and still store
-	 * their value in obj->properties->values[].. mostly to avoid
-	 * having to deal w/ EDID and similar props in atomic paths:
-	 */
-	if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) &&
-			!(property->flags & DRM_MODE_PROP_IMMUTABLE))
-		return drm_atomic_get_property(obj, property, val);
-
-	for (i = 0; i < obj->properties->count; i++) {
-		if (obj->properties->properties[i] == property) {
-			*val = obj->properties->values[i];
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(drm_object_property_get_value);
-
-/**
  * drm_mode_getproperty_ioctl - get the property metadata
  * @dev: DRM device
  * @data: ioctl data
@@ -2929,9 +2635,9 @@ void drm_property_change_valid_put(struct drm_property *property,
 		drm_property_unreference_blob(obj_to_blob(ref));
 }
 
-static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
-				      struct drm_property *property,
-				      uint64_t value)
+int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
+			       struct drm_property *property,
+			       uint64_t value)
 {
 	int ret = -EINVAL;
 	struct drm_crtc *crtc = obj_to_crtc(obj);
@@ -2974,119 +2680,6 @@ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
 EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
 
 /**
- * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function retrieves the current value for an object's property. Compared
- * to the connector specific ioctl this one is extended to also work on crtc and
- * plane objects.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
-				      struct drm_file *file_priv)
-{
-	struct drm_mode_obj_get_properties *arg = data;
-	struct drm_mode_object *obj;
-	int ret = 0;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	drm_modeset_lock_all(dev);
-
-	obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
-	if (!obj) {
-		ret = -ENOENT;
-		goto out;
-	}
-	if (!obj->properties) {
-		ret = -EINVAL;
-		goto out_unref;
-	}
-
-	ret = drm_mode_object_get_properties(obj, file_priv->atomic,
-			(uint32_t __user *)(unsigned long)(arg->props_ptr),
-			(uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
-			&arg->count_props);
-
-out_unref:
-	drm_mode_object_unreference(obj);
-out:
-	drm_modeset_unlock_all(dev);
-	return ret;
-}
-
-int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
-				    struct drm_file *file_priv)
-{
-	struct drm_mode_obj_set_property *arg = data;
-	struct drm_mode_object *arg_obj;
-	struct drm_mode_object *prop_obj;
-	struct drm_property *property;
-	int i, ret = -EINVAL;
-	struct drm_mode_object *ref;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	drm_modeset_lock_all(dev);
-
-	arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
-	if (!arg_obj) {
-		ret = -ENOENT;
-		goto out;
-	}
-	if (!arg_obj->properties)
-		goto out_unref;
-
-	for (i = 0; i < arg_obj->properties->count; i++)
-		if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
-			break;
-
-	if (i == arg_obj->properties->count)
-		goto out_unref;
-
-	prop_obj = drm_mode_object_find(dev, arg->prop_id,
-					DRM_MODE_OBJECT_PROPERTY);
-	if (!prop_obj) {
-		ret = -ENOENT;
-		goto out_unref;
-	}
-	property = obj_to_property(prop_obj);
-
-	if (!drm_property_change_valid_get(property, arg->value, &ref))
-		goto out_unref;
-
-	switch (arg_obj->type) {
-	case DRM_MODE_OBJECT_CONNECTOR:
-		ret = drm_mode_connector_set_obj_prop(arg_obj, property,
-						      arg->value);
-		break;
-	case DRM_MODE_OBJECT_CRTC:
-		ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
-		break;
-	case DRM_MODE_OBJECT_PLANE:
-		ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
-						  property, arg->value);
-		break;
-	}
-
-	drm_property_change_valid_put(property, ref);
-
-out_unref:
-	drm_mode_object_unreference(arg_obj);
-out:
-	drm_modeset_unlock_all(dev);
-	return ret;
-}
-
-/**
  * drm_mode_crtc_set_gamma_size - set the gamma table size
  * @crtc: CRTC to set the gamma table size for
  * @gamma_size: size of the gamma table
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 69f2b21ddad3..26ea7b5e3684 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -33,29 +33,14 @@
 
 
 /* drm_crtc.c */
-int drm_mode_object_get_reg(struct drm_device *dev,
-			    struct drm_mode_object *obj,
-			    uint32_t obj_type,
-			    bool register_obj,
-			    void (*obj_free_cb)(struct kref *kref));
-void drm_mode_object_register(struct drm_device *dev,
-			      struct drm_mode_object *obj);
-int drm_mode_object_get(struct drm_device *dev,
-			struct drm_mode_object *obj, uint32_t obj_type);
-struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
-					       uint32_t id, uint32_t type);
-void drm_mode_object_unregister(struct drm_device *dev,
-				struct drm_mode_object *object);
-int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
-				   uint32_t __user *prop_ptr,
-				   uint64_t __user *prop_values,
-				   uint32_t *arg_count_props);
+int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
+			       struct drm_property *property,
+			       uint64_t value);
 bool drm_property_change_valid_get(struct drm_property *property,
 				   uint64_t value,
 				   struct drm_mode_object **ref);
 void drm_property_change_valid_put(struct drm_property *property,
 				   struct drm_mode_object *ref);
-
 int drm_plane_check_pixel_format(const struct drm_plane *plane,
 				 u32 format);
 int drm_crtc_check_viewport(const struct drm_crtc *crtc,
@@ -76,11 +61,6 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 
 /* IOCTLs */
-int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
-				      struct drm_file *file_priv);
-int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
-				    struct drm_file *file_priv);
-
 int drm_mode_getresources(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
 int drm_mode_getplane_res(struct drm_device *dev, void *data,
@@ -113,6 +93,32 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 int drm_mode_page_flip_ioctl(struct drm_device *dev,
 			     void *data, struct drm_file *file_priv);
 
+/* drm_mode_object.c */
+int drm_mode_object_get_reg(struct drm_device *dev,
+			    struct drm_mode_object *obj,
+			    uint32_t obj_type,
+			    bool register_obj,
+			    void (*obj_free_cb)(struct kref *kref));
+void drm_mode_object_register(struct drm_device *dev,
+			      struct drm_mode_object *obj);
+int drm_mode_object_get(struct drm_device *dev,
+			struct drm_mode_object *obj, uint32_t obj_type);
+struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type);
+void drm_mode_object_unregister(struct drm_device *dev,
+				struct drm_mode_object *object);
+int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
+				   uint32_t __user *prop_ptr,
+				   uint64_t __user *prop_values,
+				   uint32_t *arg_count_props);
+
+/* IOCTL */
+
+int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
+				      struct drm_file *file_priv);
+int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+
 /* drm_encoder.c */
 int drm_encoder_register_all(struct drm_device *dev);
 void drm_encoder_unregister_all(struct drm_device *dev);
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
new file mode 100644
index 000000000000..cef9104e8285
--- /dev/null
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include <drm/drmP.h>
+#include <drm/drm_mode_object.h>
+
+#include "drm_crtc_internal.h"
+
+/*
+ * Internal function to assign a slot in the object idr and optionally
+ * register the object into the idr.
+ */
+int drm_mode_object_get_reg(struct drm_device *dev,
+			    struct drm_mode_object *obj,
+			    uint32_t obj_type,
+			    bool register_obj,
+			    void (*obj_free_cb)(struct kref *kref))
+{
+	int ret;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL);
+	if (ret >= 0) {
+		/*
+		 * Set up the object linking under the protection of the idr
+		 * lock so that other users can't see inconsistent state.
+		 */
+		obj->id = ret;
+		obj->type = obj_type;
+		if (obj_free_cb) {
+			obj->free_cb = obj_free_cb;
+			kref_init(&obj->refcount);
+		}
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	return ret < 0 ? ret : 0;
+}
+
+/**
+ * drm_mode_object_get - allocate a new modeset identifier
+ * @dev: DRM device
+ * @obj: object pointer, used to generate unique ID
+ * @obj_type: object type
+ *
+ * Create a unique identifier based on @ptr in @dev's identifier space.  Used
+ * for tracking modes, CRTCs and connectors. Note that despite the _get postfix
+ * modeset identifiers are _not_ reference counted. Hence don't use this for
+ * reference counted modeset objects like framebuffers.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_mode_object_get(struct drm_device *dev,
+			struct drm_mode_object *obj, uint32_t obj_type)
+{
+	return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
+}
+
+void drm_mode_object_register(struct drm_device *dev,
+			      struct drm_mode_object *obj)
+{
+	mutex_lock(&dev->mode_config.idr_mutex);
+	idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
+	mutex_unlock(&dev->mode_config.idr_mutex);
+}
+
+/**
+ * drm_mode_object_unregister - free a modeset identifer
+ * @dev: DRM device
+ * @object: object to free
+ *
+ * Free @id from @dev's unique identifier pool.
+ * This function can be called multiple times, and guards against
+ * multiple removals.
+ * These modeset identifiers are _not_ reference counted. Hence don't use this
+ * for reference counted modeset objects like framebuffers.
+ */
+void drm_mode_object_unregister(struct drm_device *dev,
+			 struct drm_mode_object *object)
+{
+	mutex_lock(&dev->mode_config.idr_mutex);
+	if (object->id) {
+		idr_remove(&dev->mode_config.crtc_idr, object->id);
+		object->id = 0;
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+}
+
+struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)
+{
+	struct drm_mode_object *obj = NULL;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	obj = idr_find(&dev->mode_config.crtc_idr, id);
+	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
+		obj = NULL;
+	if (obj && obj->id != id)
+		obj = NULL;
+
+	if (obj && obj->free_cb) {
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	return obj;
+}
+
+/**
+ * drm_mode_object_find - look up a drm object with static lifetime
+ * @dev: drm device
+ * @id: id of the mode object
+ * @type: type of the mode object
+ *
+ * This function is used to look up a modeset object. It will acquire a
+ * reference for reference counted objects. This reference must be dropped again
+ * by callind drm_mode_object_unreference().
+ */
+struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
+		uint32_t id, uint32_t type)
+{
+	struct drm_mode_object *obj = NULL;
+
+	obj = __drm_mode_object_find(dev, id, type);
+	return obj;
+}
+EXPORT_SYMBOL(drm_mode_object_find);
+
+/**
+ * drm_mode_object_unreference - decr the object refcnt
+ * @obj: mode_object
+ *
+ * This functions decrements the object's refcount if it is a refcounted modeset
+ * object. It is a no-op on any other object. This is used to drop references
+ * acquired with drm_mode_object_reference().
+ */
+void drm_mode_object_unreference(struct drm_mode_object *obj)
+{
+	if (obj->free_cb) {
+		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
+		kref_put(&obj->refcount, obj->free_cb);
+	}
+}
+EXPORT_SYMBOL(drm_mode_object_unreference);
+
+/**
+ * drm_mode_object_reference - incr the object refcnt
+ * @obj: mode_object
+ *
+ * This functions increments the object's refcount if it is a refcounted modeset
+ * object. It is a no-op on any other object. References should be dropped again
+ * by calling drm_mode_object_unreference().
+ */
+void drm_mode_object_reference(struct drm_mode_object *obj)
+{
+	if (obj->free_cb) {
+		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
+		kref_get(&obj->refcount);
+	}
+}
+EXPORT_SYMBOL(drm_mode_object_reference);
+
+/**
+ * drm_object_attach_property - attach a property to a modeset object
+ * @obj: drm modeset object
+ * @property: property to attach
+ * @init_val: initial value of the property
+ *
+ * This attaches the given property to the modeset object with the given initial
+ * value. Currently this function cannot fail since the properties are stored in
+ * a statically sized array.
+ */
+void drm_object_attach_property(struct drm_mode_object *obj,
+				struct drm_property *property,
+				uint64_t init_val)
+{
+	int count = obj->properties->count;
+
+	if (count == DRM_OBJECT_MAX_PROPERTY) {
+		WARN(1, "Failed to attach object property (type: 0x%x). Please "
+			"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
+			"you see this message on the same object type.\n",
+			obj->type);
+		return;
+	}
+
+	obj->properties->properties[count] = property;
+	obj->properties->values[count] = init_val;
+	obj->properties->count++;
+	if (property->flags & DRM_MODE_PROP_ATOMIC)
+		obj->properties->atomic_count++;
+}
+EXPORT_SYMBOL(drm_object_attach_property);
+
+/**
+ * drm_object_property_set_value - set the value of a property
+ * @obj: drm mode object to set property value for
+ * @property: property to set
+ * @val: value the property should be set to
+ *
+ * This functions sets a given property on a given object. This function only
+ * changes the software state of the property, it does not call into the
+ * driver's ->set_property callback.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_object_property_set_value(struct drm_mode_object *obj,
+				  struct drm_property *property, uint64_t val)
+{
+	int i;
+
+	for (i = 0; i < obj->properties->count; i++) {
+		if (obj->properties->properties[i] == property) {
+			obj->properties->values[i] = val;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(drm_object_property_set_value);
+
+/**
+ * drm_object_property_get_value - retrieve the value of a property
+ * @obj: drm mode object to get property value from
+ * @property: property to retrieve
+ * @val: storage for the property value
+ *
+ * This function retrieves the softare state of the given property for the given
+ * property. Since there is no driver callback to retrieve the current property
+ * value this might be out of sync with the hardware, depending upon the driver
+ * and property.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_object_property_get_value(struct drm_mode_object *obj,
+				  struct drm_property *property, uint64_t *val)
+{
+	int i;
+
+	/* read-only properties bypass atomic mechanism and still store
+	 * their value in obj->properties->values[].. mostly to avoid
+	 * having to deal w/ EDID and similar props in atomic paths:
+	 */
+	if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) &&
+			!(property->flags & DRM_MODE_PROP_IMMUTABLE))
+		return drm_atomic_get_property(obj, property, val);
+
+	for (i = 0; i < obj->properties->count; i++) {
+		if (obj->properties->properties[i] == property) {
+			*val = obj->properties->values[i];
+			return 0;
+		}
+
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(drm_object_property_get_value);
+
+/* helper for getconnector and getproperties ioctls */
+int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
+				   uint32_t __user *prop_ptr,
+				   uint64_t __user *prop_values,
+				   uint32_t *arg_count_props)
+{
+	int props_count;
+	int i, ret, copied;
+
+	props_count = obj->properties->count;
+	if (!atomic)
+		props_count -= obj->properties->atomic_count;
+
+	if ((*arg_count_props >= props_count) && props_count) {
+		for (i = 0, copied = 0; copied < props_count; i++) {
+			struct drm_property *prop = obj->properties->properties[i];
+			uint64_t val;
+
+			if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
+				continue;
+
+			ret = drm_object_property_get_value(obj, prop, &val);
+			if (ret)
+				return ret;
+
+			if (put_user(prop->base.id, prop_ptr + copied))
+				return -EFAULT;
+
+			if (put_user(val, prop_values + copied))
+				return -EFAULT;
+
+			copied++;
+		}
+	}
+	*arg_count_props = props_count;
+
+	return 0;
+}
+
+/**
+ * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * This function retrieves the current value for an object's property. Compared
+ * to the connector specific ioctl this one is extended to also work on crtc and
+ * plane objects.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
+				      struct drm_file *file_priv)
+{
+	struct drm_mode_obj_get_properties *arg = data;
+	struct drm_mode_object *obj;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	drm_modeset_lock_all(dev);
+
+	obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
+	if (!obj) {
+		ret = -ENOENT;
+		goto out;
+	}
+	if (!obj->properties) {
+		ret = -EINVAL;
+		goto out_unref;
+	}
+
+	ret = drm_mode_object_get_properties(obj, file_priv->atomic,
+			(uint32_t __user *)(unsigned long)(arg->props_ptr),
+			(uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
+			&arg->count_props);
+
+out_unref:
+	drm_mode_object_unreference(obj);
+out:
+	drm_modeset_unlock_all(dev);
+	return ret;
+}
+
+int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv)
+{
+	struct drm_mode_obj_set_property *arg = data;
+	struct drm_mode_object *arg_obj;
+	struct drm_mode_object *prop_obj;
+	struct drm_property *property;
+	int i, ret = -EINVAL;
+	struct drm_mode_object *ref;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	drm_modeset_lock_all(dev);
+
+	arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
+	if (!arg_obj) {
+		ret = -ENOENT;
+		goto out;
+	}
+	if (!arg_obj->properties)
+		goto out_unref;
+
+	for (i = 0; i < arg_obj->properties->count; i++)
+		if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
+			break;
+
+	if (i == arg_obj->properties->count)
+		goto out_unref;
+
+	prop_obj = drm_mode_object_find(dev, arg->prop_id,
+					DRM_MODE_OBJECT_PROPERTY);
+	if (!prop_obj) {
+		ret = -ENOENT;
+		goto out_unref;
+	}
+	property = obj_to_property(prop_obj);
+
+	if (!drm_property_change_valid_get(property, arg->value, &ref))
+		goto out_unref;
+
+	switch (arg_obj->type) {
+	case DRM_MODE_OBJECT_CONNECTOR:
+		ret = drm_mode_connector_set_obj_prop(arg_obj, property,
+						      arg->value);
+		break;
+	case DRM_MODE_OBJECT_CRTC:
+		ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
+		break;
+	case DRM_MODE_OBJECT_PLANE:
+		ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
+						  property, arg->value);
+		break;
+	}
+
+	drm_property_change_valid_put(property, ref);
+
+out_unref:
+	drm_mode_object_unreference(arg_obj);
+out:
+	drm_modeset_unlock_all(dev);
+	return ret;
+}
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index f1576db6c044..66b7d6744dd2 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -25,7 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
-#include <drm/drm_modeset.h>
+#include <drm/drm_mode_object.h>
 
 struct drm_connector_helper_funcs;
 struct drm_device;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7a53b053cbe7..b3c3f0c7b449 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -36,7 +36,7 @@
 #include <uapi/drm/drm_fourcc.h>
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_rect.h>
-#include <drm/drm_modeset.h>
+#include <drm/drm_mode_object.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_modes.h>
 #include <drm/drm_connector.h>
@@ -2122,16 +2122,6 @@ static inline bool drm_property_type_is(struct drm_property *property,
 	return property->flags & type;
 }
 
-extern int drm_object_property_set_value(struct drm_mode_object *obj,
-					 struct drm_property *property,
-					 uint64_t val);
-extern int drm_object_property_get_value(struct drm_mode_object *obj,
-					 struct drm_property *property,
-					 uint64_t *value);
-
-extern void drm_object_attach_property(struct drm_mode_object *obj,
-				       struct drm_property *property,
-				       uint64_t init_val);
 extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
 						const char *name, int num_values);
 extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 3d7350f1fcc1..fce0203094f7 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -25,7 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
-#include <drm/drm_modeset.h>
+#include <drm/drm_mode_object.h>
 
 /**
  * struct drm_encoder_funcs - encoder controls
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index 50deb40d3bfd..b2554c50a903 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -25,7 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
-#include <drm/drm_modeset.h>
+#include <drm/drm_mode_object.h>
 
 struct drm_framebuffer;
 struct drm_file;
diff --git a/include/drm/drm_modeset.h b/include/drm/drm_mode_object.h
similarity index 87%
rename from include/drm/drm_modeset.h
rename to include/drm/drm_mode_object.h
index fe910d5efe12..c0e4414299f7 100644
--- a/include/drm/drm_modeset.h
+++ b/include/drm/drm_mode_object.h
@@ -67,4 +67,14 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 void drm_mode_object_reference(struct drm_mode_object *obj);
 void drm_mode_object_unreference(struct drm_mode_object *obj);
 
+int drm_object_property_set_value(struct drm_mode_object *obj,
+				  struct drm_property *property,
+				  uint64_t val);
+int drm_object_property_get_value(struct drm_mode_object *obj,
+				  struct drm_property *property,
+				  uint64_t *value);
+
+void drm_object_attach_property(struct drm_mode_object *obj,
+				struct drm_property *property,
+				uint64_t init_val);
 #endif
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 1621e9b32330..011f199d3bcf 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -27,7 +27,7 @@
 #ifndef __DRM_MODES_H__
 #define __DRM_MODES_H__
 
-#include <drm/drm_modeset.h>
+#include <drm/drm_mode_object.h>
 #include <drm/drm_connector.h>
 
 /*
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/9] drm: Remove drm_mode_object->atomic_count
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
  2016-08-29  8:27 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
  2016-08-29  8:27 ` [PATCH 3/9] drm: Extract drm_mode_object.[hc] Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-08-29  8:27 ` [PATCH 5/9] drm/doc: Polish docs for drm_mode_object Daniel Vetter
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

It's only used in drm_mode_object_get_properties, and we can compute
it there directly with a bit of code shuffling.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_mode_object.c | 31 ++++++++++++-------------------
 include/drm/drm_mode_object.h     |  2 +-
 2 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index cef9104e8285..a92aeed51156 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -209,8 +209,6 @@ void drm_object_attach_property(struct drm_mode_object *obj,
 	obj->properties->properties[count] = property;
 	obj->properties->values[count] = init_val;
 	obj->properties->count++;
-	if (property->flags & DRM_MODE_PROP_ATOMIC)
-		obj->properties->atomic_count++;
 }
 EXPORT_SYMBOL(drm_object_attach_property);
 
@@ -288,35 +286,30 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
 				   uint64_t __user *prop_values,
 				   uint32_t *arg_count_props)
 {
-	int props_count;
-	int i, ret, copied;
+	int i, ret, count;
 
-	props_count = obj->properties->count;
-	if (!atomic)
-		props_count -= obj->properties->atomic_count;
+	for (i = 0, count = 0; i < obj->properties->count; i++) {
+		struct drm_property *prop = obj->properties->properties[i];
+		uint64_t val;
 
-	if ((*arg_count_props >= props_count) && props_count) {
-		for (i = 0, copied = 0; copied < props_count; i++) {
-			struct drm_property *prop = obj->properties->properties[i];
-			uint64_t val;
-
-			if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
-				continue;
+		if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
+			continue;
 
+		if (*arg_count_props > count) {
 			ret = drm_object_property_get_value(obj, prop, &val);
 			if (ret)
 				return ret;
 
-			if (put_user(prop->base.id, prop_ptr + copied))
+			if (put_user(prop->base.id, prop_ptr + count))
 				return -EFAULT;
 
-			if (put_user(val, prop_values + copied))
+			if (put_user(val, prop_values + count))
 				return -EFAULT;
-
-			copied++;
 		}
+
+		count++;
 	}
-	*arg_count_props = props_count;
+	*arg_count_props = count;
 
 	return 0;
 }
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index c0e4414299f7..b8adb6425f2a 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -37,7 +37,7 @@ struct drm_mode_object {
 
 #define DRM_OBJECT_MAX_PROPERTY 24
 struct drm_object_properties {
-	int count, atomic_count;
+	int 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
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/9] drm/doc: Polish docs for drm_mode_object
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
                   ` (2 preceding siblings ...)
  2016-08-29  8:27 ` [PATCH 4/9] drm: Remove drm_mode_object->atomic_count Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-08-29  8:27 ` [PATCH 6/9] drm: move drm_mode_legacy_fb_format to drm_fourcc.c Daniel Vetter
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

I figured an overview section here is overkill, and better
to just document the 2 structures themselves well enough.

v2: Review from Archit:
- Appease checkpatch in moved code.
- Spelling fixes in the kerneldoc.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_mode_object.c | 17 +++++++++----
 include/drm/drm_mode_object.h     | 50 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index a92aeed51156..6edda8382a4c 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -97,7 +97,7 @@ void drm_mode_object_register(struct drm_device *dev,
  * for reference counted modeset objects like framebuffers.
  */
 void drm_mode_object_unregister(struct drm_device *dev,
-			 struct drm_mode_object *object)
+				struct drm_mode_object *object)
 {
 	mutex_lock(&dev->mode_config.idr_mutex);
 	if (object->id) {
@@ -152,7 +152,7 @@ EXPORT_SYMBOL(drm_mode_object_find);
  * drm_mode_object_unreference - decr the object refcnt
  * @obj: mode_object
  *
- * This functions decrements the object's refcount if it is a refcounted modeset
+ * This function decrements the object's refcount if it is a refcounted modeset
  * object. It is a no-op on any other object. This is used to drop references
  * acquired with drm_mode_object_reference().
  */
@@ -169,7 +169,7 @@ EXPORT_SYMBOL(drm_mode_object_unreference);
  * drm_mode_object_reference - incr the object refcnt
  * @obj: mode_object
  *
- * This functions increments the object's refcount if it is a refcounted modeset
+ * This function increments the object's refcount if it is a refcounted modeset
  * object. It is a no-op on any other object. References should be dropped again
  * by calling drm_mode_object_unreference().
  */
@@ -218,10 +218,16 @@ EXPORT_SYMBOL(drm_object_attach_property);
  * @property: property to set
  * @val: value the property should be set to
  *
- * This functions sets a given property on a given object. This function only
+ * This function sets a given property on a given object. This function only
  * changes the software state of the property, it does not call into the
  * driver's ->set_property callback.
  *
+ * Note that atomic drivers should not have any need to call this, the core will
+ * ensure consistency of values reported back to userspace through the
+ * appropriate ->atomic_get_property callback. Only legacy drivers should call
+ * this function to update the tracked value (after clamping and other
+ * restrictions have been applied).
+ *
  * Returns:
  * Zero on success, error code on failure.
  */
@@ -252,6 +258,9 @@ EXPORT_SYMBOL(drm_object_property_set_value);
  * value this might be out of sync with the hardware, depending upon the driver
  * and property.
  *
+ * Atomic drivers should never call this function directly, the core will read
+ * out property values through the various ->atomic_get_property callbacks.
+ *
  * Returns:
  * Zero on success, error code on failure.
  */
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index b8adb6425f2a..be3d93839ae2 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -27,6 +27,28 @@
 struct drm_object_properties;
 struct drm_property;
 
+/**
+ * struct drm_mode_object - base structure for modeset objects
+ * @id: userspace visible identifier
+ * @type: type of the object, one of DRM_MODE_OBJECT\_\*
+ * @properties: properties attached to this object, including values
+ * @refcount: reference count for objects which with dynamic lifetime
+ * @free_cb: free function callback, only set for objects with dynamic lifetime
+ *
+ * Base structure for modeset objects visible to userspace. Objects can be
+ * looked up using drm_mode_object_find(). Besides basic uapi interface
+ * properties like @id and @type it provides two services:
+ *
+ * - It tracks attached properties and their values. This is used by &drm_crtc,
+ *   &drm_plane and &drm_connector. Properties are attached by calling
+ *   drm_object_attach_property() before the object is visible to userspace.
+ *
+ * - For objects with dynamic lifetimes (as indicated by a non-NULL @free_cb) it
+ *   provides reference counting through drm_mode_object_reference() and
+ *   drm_mode_object_unreference(). This is used by &drm_framebuffer,
+ *   &drm_connector and &drm_property_blob. These objects provide specialized
+ *   reference counting wrappers.
+ */
 struct drm_mode_object {
 	uint32_t id;
 	uint32_t type;
@@ -36,16 +58,38 @@ struct drm_mode_object {
 };
 
 #define DRM_OBJECT_MAX_PROPERTY 24
+/**
+ * struct drm_object_properties - property tracking for &drm_mode_object
+ */
 struct drm_object_properties {
+	/**
+	 * @count: number of valid properties, must be less than or equal to
+	 * DRM_OBJECT_MAX_PROPERTY.
+	 */
+
 	int count;
-	/* NOTE: if we ever start dynamically destroying properties (ie.
+	/**
+	 * @properties: Array of pointers to &drm_property.
+	 *
+	 * 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
 	 * dangling property pointers:
 	 */
 	struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
-	/* do not read/write values directly, but use drm_object_property_get_value()
-	 * and drm_object_property_set_value():
+
+	/**
+	 * @values: Array to store the property values, matching @properties. Do
+	 * not read/write values directly, but use
+	 * drm_object_property_get_value() and drm_object_property_set_value().
+	 *
+	 * Note that atomic drivers do not store mutable properties in this
+	 * array, but only the decoded values in the corresponding state
+	 * structure. The decoding is done using the ->atomic_get_property and
+	 * ->atomic_set_property hooks of the corresponding object. Hence atomic
+	 * drivers should not use drm_object_property_set_value() and
+	 * drm_object_property_get_value() on mutable objects, i.e. those
+	 * without the DRM_MODE_PROP_IMMUTABLE flag set.
 	 */
 	uint64_t values[DRM_OBJECT_MAX_PROPERTY];
 };
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 6/9] drm: move drm_mode_legacy_fb_format to drm_fourcc.c
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
                   ` (3 preceding siblings ...)
  2016-08-29  8:27 ` [PATCH 5/9] drm/doc: Polish docs for drm_mode_object Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-08-29  8:27 ` [PATCH 7/9] drm: Extract drm_property.[hc] Daniel Vetter
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Laurent Pinchart, Daniel Vetter

It's part of the drm fourcc handling code, mapping the old depth/bpp
values to new fourcc codes.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc.c   | 43 -------------------------------------------
 drivers/gpu/drm/drm_fourcc.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h       |  2 --
 include/drm/drm_fourcc.h     |  1 +
 4 files changed, 44 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 7ec9f7e7a077..59491fc843b6 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1666,49 +1666,6 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev,
 	return drm_mode_cursor_common(dev, req, file_priv);
 }
 
-/**
- * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
- * @bpp: bits per pixels
- * @depth: bit depth per pixel
- *
- * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
- * Useful in fbdev emulation code, since that deals in those values.
- */
-uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
-{
-	uint32_t fmt;
-
-	switch (bpp) {
-	case 8:
-		fmt = DRM_FORMAT_C8;
-		break;
-	case 16:
-		if (depth == 15)
-			fmt = DRM_FORMAT_XRGB1555;
-		else
-			fmt = DRM_FORMAT_RGB565;
-		break;
-	case 24:
-		fmt = DRM_FORMAT_RGB888;
-		break;
-	case 32:
-		if (depth == 24)
-			fmt = DRM_FORMAT_XRGB8888;
-		else if (depth == 30)
-			fmt = DRM_FORMAT_XRGB2101010;
-		else
-			fmt = DRM_FORMAT_ARGB8888;
-		break;
-	default:
-		DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
-		fmt = DRM_FORMAT_XRGB8888;
-		break;
-	}
-
-	return fmt;
-}
-EXPORT_SYMBOL(drm_mode_legacy_fb_format);
-
 static bool drm_property_type_valid(struct drm_property *property)
 {
 	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index c81546c15c93..29c56b4331e0 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -36,6 +36,49 @@ static char printable_char(int c)
 }
 
 /**
+ * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
+ * @bpp: bits per pixels
+ * @depth: bit depth per pixel
+ *
+ * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
+ * Useful in fbdev emulation code, since that deals in those values.
+ */
+uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
+{
+	uint32_t fmt;
+
+	switch (bpp) {
+	case 8:
+		fmt = DRM_FORMAT_C8;
+		break;
+	case 16:
+		if (depth == 15)
+			fmt = DRM_FORMAT_XRGB1555;
+		else
+			fmt = DRM_FORMAT_RGB565;
+		break;
+	case 24:
+		fmt = DRM_FORMAT_RGB888;
+		break;
+	case 32:
+		if (depth == 24)
+			fmt = DRM_FORMAT_XRGB8888;
+		else if (depth == 30)
+			fmt = DRM_FORMAT_XRGB2101010;
+		else
+			fmt = DRM_FORMAT_ARGB8888;
+		break;
+	default:
+		DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
+		fmt = DRM_FORMAT_XRGB8888;
+		break;
+	}
+
+	return fmt;
+}
+EXPORT_SYMBOL(drm_mode_legacy_fb_format);
+
+/**
  * drm_get_format_name - return a string for drm fourcc format
  * @format: format to compute name of
  *
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b3c3f0c7b449..0c3fa89afd11 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -2164,8 +2164,6 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
 
 extern int drm_mode_set_config_internal(struct drm_mode_set *set);
 
-extern uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
-
 extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
 							 char topology[8]);
 extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index b106337de1bf..30c30fa87ee8 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <uapi/drm/drm_fourcc.h>
 
+uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp);
 int drm_format_num_planes(uint32_t format);
 int drm_format_plane_cpp(uint32_t format, int plane);
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 7/9] drm: Extract drm_property.[hc]
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
                   ` (4 preceding siblings ...)
  2016-08-29  8:27 ` [PATCH 6/9] drm: move drm_mode_legacy_fb_format to drm_fourcc.c Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-08-29  8:27 ` [PATCH 8/9] drm: Unify handling of blob and object properties Daniel Vetter
  2016-08-29  8:27 ` [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob Daniel Vetter
  7 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

This just contains the base property classes and all the code to
handle blobs. I think for any kind of standardized/shared properties
it's better to have separate files - this is fairly big already as-is.

v2: resurrect misplaced hunk (Daniel Stone)

Cc: Daniel Stone <daniel@fooishbar.org>
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst       |   9 +
 drivers/gpu/drm/Makefile            |   2 +-
 drivers/gpu/drm/drm_crtc.c          | 926 -----------------------------------
 drivers/gpu/drm/drm_crtc_internal.h |  32 +-
 drivers/gpu/drm/drm_property.c      | 953 ++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h              |  88 +---
 include/drm/drm_property.h          | 120 +++++
 7 files changed, 1102 insertions(+), 1028 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_property.c
 create mode 100644 include/drm/drm_property.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index b164472f2157..e07a2667ab61 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -389,6 +389,15 @@ connector and plane objects by calling the
 pointer to the target object, a pointer to the previously created
 property and an initial instance value.
 
+Property Types and Blob Property Support
+----------------------------------------
+
+.. kernel-doc:: include/drm/drm_property.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_property.c
+   :export:
+
 Blending and Z-Position properties
 ----------------------------------
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8d379565ac8e..439d89b25ae0 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_rect.o drm_vma_manager.o drm_flip_work.o \
 		drm_modeset_lock.o drm_atomic.o drm_bridge.o \
 		drm_framebuffer.o drm_connector.o drm_blend.o \
-		drm_encoder.o drm_mode_object.o
+		drm_encoder.o drm_mode_object.o drm_property.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 59491fc843b6..0fad433f4d2d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1666,932 +1666,6 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev,
 	return drm_mode_cursor_common(dev, req, file_priv);
 }
 
-static bool drm_property_type_valid(struct drm_property *property)
-{
-	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
-		return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
-	return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
-}
-
-/**
- * drm_property_create - create a new property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- * @num_values: number of pre-defined values
- *
- * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Note that the DRM core keeps a per-device list of properties and that, if
- * drm_mode_config_cleanup() is called, it will destroy all properties created
- * by the driver.
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create(struct drm_device *dev, int flags,
-					 const char *name, int num_values)
-{
-	struct drm_property *property = NULL;
-	int ret;
-
-	property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
-	if (!property)
-		return NULL;
-
-	property->dev = dev;
-
-	if (num_values) {
-		property->values = kcalloc(num_values, sizeof(uint64_t),
-					   GFP_KERNEL);
-		if (!property->values)
-			goto fail;
-	}
-
-	ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
-	if (ret)
-		goto fail;
-
-	property->flags = flags;
-	property->num_values = num_values;
-	INIT_LIST_HEAD(&property->enum_list);
-
-	if (name) {
-		strncpy(property->name, name, DRM_PROP_NAME_LEN);
-		property->name[DRM_PROP_NAME_LEN-1] = '\0';
-	}
-
-	list_add_tail(&property->head, &dev->mode_config.property_list);
-
-	WARN_ON(!drm_property_type_valid(property));
-
-	return property;
-fail:
-	kfree(property->values);
-	kfree(property);
-	return NULL;
-}
-EXPORT_SYMBOL(drm_property_create);
-
-/**
- * drm_property_create_enum - create a new enumeration property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- * @props: enumeration lists with property values
- * @num_values: number of pre-defined values
- *
- * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Userspace is only allowed to set one of the predefined values for enumeration
- * properties.
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
-					 const char *name,
-					 const struct drm_prop_enum_list *props,
-					 int num_values)
-{
-	struct drm_property *property;
-	int i, ret;
-
-	flags |= DRM_MODE_PROP_ENUM;
-
-	property = drm_property_create(dev, flags, name, num_values);
-	if (!property)
-		return NULL;
-
-	for (i = 0; i < num_values; i++) {
-		ret = drm_property_add_enum(property, i,
-				      props[i].type,
-				      props[i].name);
-		if (ret) {
-			drm_property_destroy(dev, property);
-			return NULL;
-		}
-	}
-
-	return property;
-}
-EXPORT_SYMBOL(drm_property_create_enum);
-
-/**
- * drm_property_create_bitmask - create a new bitmask property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- * @props: enumeration lists with property bitflags
- * @num_props: size of the @props array
- * @supported_bits: bitmask of all supported enumeration values
- *
- * This creates a new bitmask drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Compared to plain enumeration properties userspace is allowed to set any
- * or'ed together combination of the predefined property bitflag values
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
-					 int flags, const char *name,
-					 const struct drm_prop_enum_list *props,
-					 int num_props,
-					 uint64_t supported_bits)
-{
-	struct drm_property *property;
-	int i, ret, index = 0;
-	int num_values = hweight64(supported_bits);
-
-	flags |= DRM_MODE_PROP_BITMASK;
-
-	property = drm_property_create(dev, flags, name, num_values);
-	if (!property)
-		return NULL;
-	for (i = 0; i < num_props; i++) {
-		if (!(supported_bits & (1ULL << props[i].type)))
-			continue;
-
-		if (WARN_ON(index >= num_values)) {
-			drm_property_destroy(dev, property);
-			return NULL;
-		}
-
-		ret = drm_property_add_enum(property, index++,
-				      props[i].type,
-				      props[i].name);
-		if (ret) {
-			drm_property_destroy(dev, property);
-			return NULL;
-		}
-	}
-
-	return property;
-}
-EXPORT_SYMBOL(drm_property_create_bitmask);
-
-static struct drm_property *property_create_range(struct drm_device *dev,
-					 int flags, const char *name,
-					 uint64_t min, uint64_t max)
-{
-	struct drm_property *property;
-
-	property = drm_property_create(dev, flags, name, 2);
-	if (!property)
-		return NULL;
-
-	property->values[0] = min;
-	property->values[1] = max;
-
-	return property;
-}
-
-/**
- * drm_property_create_range - create a new unsigned ranged property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- * @min: minimum value of the property
- * @max: maximum value of the property
- *
- * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Userspace is allowed to set any unsigned integer value in the (min, max)
- * range inclusive.
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
-					 const char *name,
-					 uint64_t min, uint64_t max)
-{
-	return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
-			name, min, max);
-}
-EXPORT_SYMBOL(drm_property_create_range);
-
-/**
- * drm_property_create_signed_range - create a new signed ranged property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- * @min: minimum value of the property
- * @max: maximum value of the property
- *
- * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Userspace is allowed to set any signed integer value in the (min, max)
- * range inclusive.
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
-					 int flags, const char *name,
-					 int64_t min, int64_t max)
-{
-	return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
-			name, I642U64(min), I642U64(max));
-}
-EXPORT_SYMBOL(drm_property_create_signed_range);
-
-/**
- * drm_property_create_object - create a new object property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- * @type: object type from DRM_MODE_OBJECT_* defines
- *
- * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Userspace is only allowed to set this to any property value of the given
- * @type. Only useful for atomic properties, which is enforced.
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create_object(struct drm_device *dev,
-					 int flags, const char *name, uint32_t type)
-{
-	struct drm_property *property;
-
-	flags |= DRM_MODE_PROP_OBJECT;
-
-	if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
-		return NULL;
-
-	property = drm_property_create(dev, flags, name, 1);
-	if (!property)
-		return NULL;
-
-	property->values[0] = type;
-
-	return property;
-}
-EXPORT_SYMBOL(drm_property_create_object);
-
-/**
- * drm_property_create_bool - create a new boolean property type
- * @dev: drm device
- * @flags: flags specifying the property type
- * @name: name of the property
- *
- * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * This is implemented as a ranged property with only {0, 1} as valid values.
- *
- * Returns:
- * A pointer to the newly created property on success, NULL on failure.
- */
-struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
-					 const char *name)
-{
-	return drm_property_create_range(dev, flags, name, 0, 1);
-}
-EXPORT_SYMBOL(drm_property_create_bool);
-
-/**
- * drm_property_add_enum - add a possible value to an enumeration property
- * @property: enumeration property to change
- * @index: index of the new enumeration
- * @value: value of the new enumeration
- * @name: symbolic name of the new enumeration
- *
- * This functions adds enumerations to a property.
- *
- * It's use is deprecated, drivers should use one of the more specific helpers
- * to directly create the property with all enumerations already attached.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_property_add_enum(struct drm_property *property, int index,
-			  uint64_t value, const char *name)
-{
-	struct drm_property_enum *prop_enum;
-
-	if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
-		return -EINVAL;
-
-	/*
-	 * Bitmask enum properties have the additional constraint of values
-	 * from 0 to 63
-	 */
-	if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
-			(value > 63))
-		return -EINVAL;
-
-	if (!list_empty(&property->enum_list)) {
-		list_for_each_entry(prop_enum, &property->enum_list, head) {
-			if (prop_enum->value == value) {
-				strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
-				prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
-				return 0;
-			}
-		}
-	}
-
-	prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
-	if (!prop_enum)
-		return -ENOMEM;
-
-	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
-	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
-	prop_enum->value = value;
-
-	property->values[index] = value;
-	list_add_tail(&prop_enum->head, &property->enum_list);
-	return 0;
-}
-EXPORT_SYMBOL(drm_property_add_enum);
-
-/**
- * drm_property_destroy - destroy a drm property
- * @dev: drm device
- * @property: property to destry
- *
- * This function frees a property including any attached resources like
- * enumeration values.
- */
-void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
-{
-	struct drm_property_enum *prop_enum, *pt;
-
-	list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
-		list_del(&prop_enum->head);
-		kfree(prop_enum);
-	}
-
-	if (property->num_values)
-		kfree(property->values);
-	drm_mode_object_unregister(dev, &property->base);
-	list_del(&property->head);
-	kfree(property);
-}
-EXPORT_SYMBOL(drm_property_destroy);
-
-/**
- * drm_mode_getproperty_ioctl - get the property metadata
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function retrieves the metadata for a given property, like the different
- * possible values for an enum property or the limits for a range property.
- *
- * Blob properties are special
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getproperty_ioctl(struct drm_device *dev,
-			       void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_get_property *out_resp = data;
-	struct drm_property *property;
-	int enum_count = 0;
-	int value_count = 0;
-	int ret = 0, i;
-	int copied;
-	struct drm_property_enum *prop_enum;
-	struct drm_mode_property_enum __user *enum_ptr;
-	uint64_t __user *values_ptr;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	drm_modeset_lock_all(dev);
-	property = drm_property_find(dev, out_resp->prop_id);
-	if (!property) {
-		ret = -ENOENT;
-		goto done;
-	}
-
-	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-		list_for_each_entry(prop_enum, &property->enum_list, head)
-			enum_count++;
-	}
-
-	value_count = property->num_values;
-
-	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
-	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
-	out_resp->flags = property->flags;
-
-	if ((out_resp->count_values >= value_count) && value_count) {
-		values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
-		for (i = 0; i < value_count; i++) {
-			if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
-				ret = -EFAULT;
-				goto done;
-			}
-		}
-	}
-	out_resp->count_values = value_count;
-
-	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-		if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
-			copied = 0;
-			enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
-			list_for_each_entry(prop_enum, &property->enum_list, head) {
-
-				if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
-					ret = -EFAULT;
-					goto done;
-				}
-
-				if (copy_to_user(&enum_ptr[copied].name,
-						 &prop_enum->name, DRM_PROP_NAME_LEN)) {
-					ret = -EFAULT;
-					goto done;
-				}
-				copied++;
-			}
-		}
-		out_resp->count_enum_blobs = enum_count;
-	}
-
-	/*
-	 * NOTE: The idea seems to have been to use this to read all the blob
-	 * property values. But nothing ever added them to the corresponding
-	 * list, userspace always used the special-purpose get_blob ioctl to
-	 * read the value for a blob property. It also doesn't make a lot of
-	 * sense to return values here when everything else is just metadata for
-	 * the property itself.
-	 */
-	if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
-		out_resp->count_enum_blobs = 0;
-done:
-	drm_modeset_unlock_all(dev);
-	return ret;
-}
-
-static void drm_property_free_blob(struct kref *kref)
-{
-	struct drm_property_blob *blob =
-		container_of(kref, struct drm_property_blob, base.refcount);
-
-	mutex_lock(&blob->dev->mode_config.blob_lock);
-	list_del(&blob->head_global);
-	mutex_unlock(&blob->dev->mode_config.blob_lock);
-
-	drm_mode_object_unregister(blob->dev, &blob->base);
-
-	kfree(blob);
-}
-
-/**
- * drm_property_create_blob - Create new blob property
- *
- * Creates a new blob property for a specified DRM device, optionally
- * copying data.
- *
- * @dev: DRM device to create property for
- * @length: Length to allocate for blob data
- * @data: If specified, copies data into blob
- *
- * Returns:
- * New blob property with a single reference on success, or an ERR_PTR
- * value on failure.
- */
-struct drm_property_blob *
-drm_property_create_blob(struct drm_device *dev, size_t length,
-			 const void *data)
-{
-	struct drm_property_blob *blob;
-	int ret;
-
-	if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
-		return ERR_PTR(-EINVAL);
-
-	blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
-	if (!blob)
-		return ERR_PTR(-ENOMEM);
-
-	/* This must be explicitly initialised, so we can safely call list_del
-	 * on it in the removal handler, even if it isn't in a file list. */
-	INIT_LIST_HEAD(&blob->head_file);
-	blob->length = length;
-	blob->dev = dev;
-
-	if (data)
-		memcpy(blob->data, data, length);
-
-	ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
-				      true, drm_property_free_blob);
-	if (ret) {
-		kfree(blob);
-		return ERR_PTR(-EINVAL);
-	}
-
-	mutex_lock(&dev->mode_config.blob_lock);
-	list_add_tail(&blob->head_global,
-	              &dev->mode_config.property_blob_list);
-	mutex_unlock(&dev->mode_config.blob_lock);
-
-	return blob;
-}
-EXPORT_SYMBOL(drm_property_create_blob);
-
-/**
- * drm_property_unreference_blob - Unreference a blob property
- *
- * Drop a reference on a blob property. May free the object.
- *
- * @blob: Pointer to blob property
- */
-void drm_property_unreference_blob(struct drm_property_blob *blob)
-{
-	if (!blob)
-		return;
-
-	drm_mode_object_unreference(&blob->base);
-}
-EXPORT_SYMBOL(drm_property_unreference_blob);
-
-/**
- * drm_property_destroy_user_blobs - destroy all blobs created by this client
- * @dev:       DRM device
- * @file_priv: destroy all blobs owned by this file handle
- */
-void drm_property_destroy_user_blobs(struct drm_device *dev,
-				     struct drm_file *file_priv)
-{
-	struct drm_property_blob *blob, *bt;
-
-	/*
-	 * When the file gets released that means no one else can access the
-	 * blob list any more, so no need to grab dev->blob_lock.
-	 */
-	list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
-		list_del_init(&blob->head_file);
-		drm_property_unreference_blob(blob);
-	}
-}
-
-/**
- * drm_property_reference_blob - Take a reference on an existing property
- *
- * Take a new reference on an existing blob property.
- *
- * @blob: Pointer to blob property
- */
-struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
-{
-	drm_mode_object_reference(&blob->base);
-	return blob;
-}
-EXPORT_SYMBOL(drm_property_reference_blob);
-
-/**
- * drm_property_lookup_blob - look up a blob property and take a reference
- * @dev: drm device
- * @id: id of the blob property
- *
- * If successful, this takes an additional reference to the blob property.
- * callers need to make sure to eventually unreference the returned property
- * again, using @drm_property_unreference_blob.
- */
-struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
-					           uint32_t id)
-{
-	struct drm_mode_object *obj;
-	struct drm_property_blob *blob = NULL;
-
-	obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
-	if (obj)
-		blob = obj_to_blob(obj);
-	return blob;
-}
-EXPORT_SYMBOL(drm_property_lookup_blob);
-
-/**
- * drm_property_replace_global_blob - atomically replace existing blob property
- * @dev: drm device
- * @replace: location of blob property pointer to be replaced
- * @length: length of data for new blob, or 0 for no data
- * @data: content for new blob, or NULL for no data
- * @obj_holds_id: optional object for property holding blob ID
- * @prop_holds_id: optional property holding blob ID
- * @return 0 on success or error on failure
- *
- * This function will atomically replace a global property in the blob list,
- * optionally updating a property which holds the ID of that property. It is
- * guaranteed to be atomic: no caller will be allowed to see intermediate
- * results, and either the entire operation will succeed and clean up the
- * previous property, or it will fail and the state will be unchanged.
- *
- * If length is 0 or data is NULL, no new blob will be created, and the holding
- * property, if specified, will be set to 0.
- *
- * Access to the replace pointer is assumed to be protected by the caller, e.g.
- * by holding the relevant modesetting object lock for its parent.
- *
- * For example, a drm_connector has a 'PATH' property, which contains the ID
- * of a blob property with the value of the MST path information. Calling this
- * function with replace pointing to the connector's path_blob_ptr, length and
- * data set for the new path information, obj_holds_id set to the connector's
- * base object, and prop_holds_id set to the path property name, will perform
- * a completely atomic update. The access to path_blob_ptr is protected by the
- * caller holding a lock on the connector.
- */
-int drm_property_replace_global_blob(struct drm_device *dev,
-				     struct drm_property_blob **replace,
-				     size_t length,
-				     const void *data,
-				     struct drm_mode_object *obj_holds_id,
-				     struct drm_property *prop_holds_id)
-{
-	struct drm_property_blob *new_blob = NULL;
-	struct drm_property_blob *old_blob = NULL;
-	int ret;
-
-	WARN_ON(replace == NULL);
-
-	old_blob = *replace;
-
-	if (length && data) {
-		new_blob = drm_property_create_blob(dev, length, data);
-		if (IS_ERR(new_blob))
-			return PTR_ERR(new_blob);
-	}
-
-	/* This does not need to be synchronised with blob_lock, as the
-	 * get_properties ioctl locks all modesetting objects, and
-	 * obj_holds_id must be locked before calling here, so we cannot
-	 * have its value out of sync with the list membership modified
-	 * below under blob_lock. */
-	if (obj_holds_id) {
-		ret = drm_object_property_set_value(obj_holds_id,
-						    prop_holds_id,
-						    new_blob ?
-						        new_blob->base.id : 0);
-		if (ret != 0)
-			goto err_created;
-	}
-
-	drm_property_unreference_blob(old_blob);
-	*replace = new_blob;
-
-	return 0;
-
-err_created:
-	drm_property_unreference_blob(new_blob);
-	return ret;
-}
-EXPORT_SYMBOL(drm_property_replace_global_blob);
-
-/**
- * drm_mode_getblob_ioctl - get the contents of a blob property value
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function retrieves the contents of a blob property. The value stored in
- * an object's blob property is just a normal modeset object id.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getblob_ioctl(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_get_blob *out_resp = data;
-	struct drm_property_blob *blob;
-	int ret = 0;
-	void __user *blob_ptr;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
-	if (!blob)
-		return -ENOENT;
-
-	if (out_resp->length == blob->length) {
-		blob_ptr = (void __user *)(unsigned long)out_resp->data;
-		if (copy_to_user(blob_ptr, blob->data, blob->length)) {
-			ret = -EFAULT;
-			goto unref;
-		}
-	}
-	out_resp->length = blob->length;
-unref:
-	drm_property_unreference_blob(blob);
-
-	return ret;
-}
-
-/**
- * drm_mode_createblob_ioctl - create a new blob property
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function creates a new blob property with user-defined values. In order
- * to give us sensible validation and checking when creating, rather than at
- * every potential use, we also require a type to be provided upfront.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_createblob_ioctl(struct drm_device *dev,
-			      void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_create_blob *out_resp = data;
-	struct drm_property_blob *blob;
-	void __user *blob_ptr;
-	int ret = 0;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	blob = drm_property_create_blob(dev, out_resp->length, NULL);
-	if (IS_ERR(blob))
-		return PTR_ERR(blob);
-
-	blob_ptr = (void __user *)(unsigned long)out_resp->data;
-	if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
-		ret = -EFAULT;
-		goto out_blob;
-	}
-
-	/* Dropping the lock between create_blob and our access here is safe
-	 * as only the same file_priv can remove the blob; at this point, it is
-	 * not associated with any file_priv. */
-	mutex_lock(&dev->mode_config.blob_lock);
-	out_resp->blob_id = blob->base.id;
-	list_add_tail(&blob->head_file, &file_priv->blobs);
-	mutex_unlock(&dev->mode_config.blob_lock);
-
-	return 0;
-
-out_blob:
-	drm_property_unreference_blob(blob);
-	return ret;
-}
-
-/**
- * drm_mode_destroyblob_ioctl - destroy a user blob property
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Destroy an existing user-defined blob property.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_destroyblob_ioctl(struct drm_device *dev,
-			       void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_destroy_blob *out_resp = data;
-	struct drm_property_blob *blob = NULL, *bt;
-	bool found = false;
-	int ret = 0;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
-	if (!blob)
-		return -ENOENT;
-
-	mutex_lock(&dev->mode_config.blob_lock);
-	/* Ensure the property was actually created by this user. */
-	list_for_each_entry(bt, &file_priv->blobs, head_file) {
-		if (bt == blob) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		ret = -EPERM;
-		goto err;
-	}
-
-	/* We must drop head_file here, because we may not be the last
-	 * reference on the blob. */
-	list_del_init(&blob->head_file);
-	mutex_unlock(&dev->mode_config.blob_lock);
-
-	/* One reference from lookup, and one from the filp. */
-	drm_property_unreference_blob(blob);
-	drm_property_unreference_blob(blob);
-
-	return 0;
-
-err:
-	mutex_unlock(&dev->mode_config.blob_lock);
-	drm_property_unreference_blob(blob);
-
-	return ret;
-}
-
-/* Some properties could refer to dynamic refcnt'd objects, or things that
- * need special locking to handle lifetime issues (ie. to ensure the prop
- * value doesn't become invalid part way through the property update due to
- * race).  The value returned by reference via 'obj' should be passed back
- * to drm_property_change_valid_put() after the property is set (and the
- * object to which the property is attached has a chance to take it's own
- * reference).
- */
-bool drm_property_change_valid_get(struct drm_property *property,
-					 uint64_t value, struct drm_mode_object **ref)
-{
-	int i;
-
-	if (property->flags & DRM_MODE_PROP_IMMUTABLE)
-		return false;
-
-	*ref = NULL;
-
-	if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
-		if (value < property->values[0] || value > property->values[1])
-			return false;
-		return true;
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
-		int64_t svalue = U642I64(value);
-
-		if (svalue < U642I64(property->values[0]) ||
-				svalue > U642I64(property->values[1]))
-			return false;
-		return true;
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-		uint64_t valid_mask = 0;
-
-		for (i = 0; i < property->num_values; i++)
-			valid_mask |= (1ULL << property->values[i]);
-		return !(value & ~valid_mask);
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
-		struct drm_property_blob *blob;
-
-		if (value == 0)
-			return true;
-
-		blob = drm_property_lookup_blob(property->dev, value);
-		if (blob) {
-			*ref = &blob->base;
-			return true;
-		} else {
-			return false;
-		}
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
-		/* a zero value for an object property translates to null: */
-		if (value == 0)
-			return true;
-
-		*ref = __drm_mode_object_find(property->dev, value,
-					      property->values[0]);
-		return *ref != NULL;
-	}
-
-	for (i = 0; i < property->num_values; i++)
-		if (property->values[i] == value)
-			return true;
-	return false;
-}
-
-void drm_property_change_valid_put(struct drm_property *property,
-		struct drm_mode_object *ref)
-{
-	if (!ref)
-		return;
-
-	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
-		drm_mode_object_unreference(ref);
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
-		drm_property_unreference_blob(obj_to_blob(ref));
-}
-
 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
 			       struct drm_property *property,
 			       uint64_t value)
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 26ea7b5e3684..131ecfb16d7b 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -36,11 +36,6 @@
 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
 			       struct drm_property *property,
 			       uint64_t value);
-bool drm_property_change_valid_get(struct drm_property *property,
-				   uint64_t value,
-				   struct drm_mode_object **ref);
-void drm_property_change_valid_put(struct drm_property *property,
-				   struct drm_mode_object *ref);
 int drm_plane_check_pixel_format(const struct drm_plane *plane,
 				 u32 format);
 int drm_crtc_check_viewport(const struct drm_crtc *crtc,
@@ -49,8 +44,6 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
 			    const struct drm_framebuffer *fb);
 
 void drm_fb_release(struct drm_file *file_priv);
-void drm_property_destroy_user_blobs(struct drm_device *dev,
-				     struct drm_file *file_priv);
 
 /* dumb buffer support IOCTLs */
 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
@@ -77,6 +70,24 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
 int drm_mode_cursor2_ioctl(struct drm_device *dev,
 			   void *data, struct drm_file *file_priv);
+int drm_mode_gamma_get_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv);
+int drm_mode_gamma_set_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv);
+
+int drm_mode_page_flip_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv);
+
+/* drm_property.c */
+void drm_property_destroy_user_blobs(struct drm_device *dev,
+				     struct drm_file *file_priv);
+bool drm_property_change_valid_get(struct drm_property *property,
+				   uint64_t value,
+				   struct drm_mode_object **ref);
+void drm_property_change_valid_put(struct drm_property *property,
+				   struct drm_mode_object *ref);
+
+/* IOCTL */
 int drm_mode_getproperty_ioctl(struct drm_device *dev,
 			       void *data, struct drm_file *file_priv);
 int drm_mode_getblob_ioctl(struct drm_device *dev,
@@ -85,13 +96,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
 			      void *data, struct drm_file *file_priv);
 int drm_mode_destroyblob_ioctl(struct drm_device *dev,
 			       void *data, struct drm_file *file_priv);
-int drm_mode_gamma_get_ioctl(struct drm_device *dev,
-			     void *data, struct drm_file *file_priv);
-int drm_mode_gamma_set_ioctl(struct drm_device *dev,
-			     void *data, struct drm_file *file_priv);
-
-int drm_mode_page_flip_ioctl(struct drm_device *dev,
-			     void *data, struct drm_file *file_priv);
 
 /* drm_mode_object.c */
 int drm_mode_object_get_reg(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
new file mode 100644
index 000000000000..162cc9032ae5
--- /dev/null
+++ b/drivers/gpu/drm/drm_property.c
@@ -0,0 +1,953 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include <drm/drmP.h>
+#include <drm/drm_property.h>
+
+#include "drm_crtc_internal.h"
+
+static bool drm_property_type_valid(struct drm_property *property)
+{
+	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
+		return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
+	return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
+}
+
+/**
+ * drm_property_create - create a new property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ * @num_values: number of pre-defined values
+ *
+ * This creates a new generic drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * Note that the DRM core keeps a per-device list of properties and that, if
+ * drm_mode_config_cleanup() is called, it will destroy all properties created
+ * by the driver.
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create(struct drm_device *dev, int flags,
+					 const char *name, int num_values)
+{
+	struct drm_property *property = NULL;
+	int ret;
+
+	property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
+	if (!property)
+		return NULL;
+
+	property->dev = dev;
+
+	if (num_values) {
+		property->values = kcalloc(num_values, sizeof(uint64_t),
+					   GFP_KERNEL);
+		if (!property->values)
+			goto fail;
+	}
+
+	ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
+	if (ret)
+		goto fail;
+
+	property->flags = flags;
+	property->num_values = num_values;
+	INIT_LIST_HEAD(&property->enum_list);
+
+	if (name) {
+		strncpy(property->name, name, DRM_PROP_NAME_LEN);
+		property->name[DRM_PROP_NAME_LEN-1] = '\0';
+	}
+
+	list_add_tail(&property->head, &dev->mode_config.property_list);
+
+	WARN_ON(!drm_property_type_valid(property));
+
+	return property;
+fail:
+	kfree(property->values);
+	kfree(property);
+	return NULL;
+}
+EXPORT_SYMBOL(drm_property_create);
+
+/**
+ * drm_property_create_enum - create a new enumeration property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ * @props: enumeration lists with property values
+ * @num_values: number of pre-defined values
+ *
+ * This creates a new generic drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * Userspace is only allowed to set one of the predefined values for enumeration
+ * properties.
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
+					 const char *name,
+					 const struct drm_prop_enum_list *props,
+					 int num_values)
+{
+	struct drm_property *property;
+	int i, ret;
+
+	flags |= DRM_MODE_PROP_ENUM;
+
+	property = drm_property_create(dev, flags, name, num_values);
+	if (!property)
+		return NULL;
+
+	for (i = 0; i < num_values; i++) {
+		ret = drm_property_add_enum(property, i,
+				      props[i].type,
+				      props[i].name);
+		if (ret) {
+			drm_property_destroy(dev, property);
+			return NULL;
+		}
+	}
+
+	return property;
+}
+EXPORT_SYMBOL(drm_property_create_enum);
+
+/**
+ * drm_property_create_bitmask - create a new bitmask property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ * @props: enumeration lists with property bitflags
+ * @num_props: size of the @props array
+ * @supported_bits: bitmask of all supported enumeration values
+ *
+ * This creates a new bitmask drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * Compared to plain enumeration properties userspace is allowed to set any
+ * or'ed together combination of the predefined property bitflag values
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+					 int flags, const char *name,
+					 const struct drm_prop_enum_list *props,
+					 int num_props,
+					 uint64_t supported_bits)
+{
+	struct drm_property *property;
+	int i, ret, index = 0;
+	int num_values = hweight64(supported_bits);
+
+	flags |= DRM_MODE_PROP_BITMASK;
+
+	property = drm_property_create(dev, flags, name, num_values);
+	if (!property)
+		return NULL;
+	for (i = 0; i < num_props; i++) {
+		if (!(supported_bits & (1ULL << props[i].type)))
+			continue;
+
+		if (WARN_ON(index >= num_values)) {
+			drm_property_destroy(dev, property);
+			return NULL;
+		}
+
+		ret = drm_property_add_enum(property, index++,
+				      props[i].type,
+				      props[i].name);
+		if (ret) {
+			drm_property_destroy(dev, property);
+			return NULL;
+		}
+	}
+
+	return property;
+}
+EXPORT_SYMBOL(drm_property_create_bitmask);
+
+static struct drm_property *property_create_range(struct drm_device *dev,
+					 int flags, const char *name,
+					 uint64_t min, uint64_t max)
+{
+	struct drm_property *property;
+
+	property = drm_property_create(dev, flags, name, 2);
+	if (!property)
+		return NULL;
+
+	property->values[0] = min;
+	property->values[1] = max;
+
+	return property;
+}
+
+/**
+ * drm_property_create_range - create a new unsigned ranged property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ * @min: minimum value of the property
+ * @max: maximum value of the property
+ *
+ * This creates a new generic drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * Userspace is allowed to set any unsigned integer value in the (min, max)
+ * range inclusive.
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
+					 const char *name,
+					 uint64_t min, uint64_t max)
+{
+	return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
+			name, min, max);
+}
+EXPORT_SYMBOL(drm_property_create_range);
+
+/**
+ * drm_property_create_signed_range - create a new signed ranged property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ * @min: minimum value of the property
+ * @max: maximum value of the property
+ *
+ * This creates a new generic drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * Userspace is allowed to set any signed integer value in the (min, max)
+ * range inclusive.
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
+					 int flags, const char *name,
+					 int64_t min, int64_t max)
+{
+	return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
+			name, I642U64(min), I642U64(max));
+}
+EXPORT_SYMBOL(drm_property_create_signed_range);
+
+/**
+ * drm_property_create_object - create a new object property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ * @type: object type from DRM_MODE_OBJECT_* defines
+ *
+ * This creates a new generic drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * Userspace is only allowed to set this to any property value of the given
+ * @type. Only useful for atomic properties, which is enforced.
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create_object(struct drm_device *dev,
+					 int flags, const char *name, uint32_t type)
+{
+	struct drm_property *property;
+
+	flags |= DRM_MODE_PROP_OBJECT;
+
+	if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
+		return NULL;
+
+	property = drm_property_create(dev, flags, name, 1);
+	if (!property)
+		return NULL;
+
+	property->values[0] = type;
+
+	return property;
+}
+EXPORT_SYMBOL(drm_property_create_object);
+
+/**
+ * drm_property_create_bool - create a new boolean property type
+ * @dev: drm device
+ * @flags: flags specifying the property type
+ * @name: name of the property
+ *
+ * This creates a new generic drm property which can then be attached to a drm
+ * object with drm_object_attach_property. The returned property object must be
+ * freed with drm_property_destroy.
+ *
+ * This is implemented as a ranged property with only {0, 1} as valid values.
+ *
+ * Returns:
+ * A pointer to the newly created property on success, NULL on failure.
+ */
+struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
+					 const char *name)
+{
+	return drm_property_create_range(dev, flags, name, 0, 1);
+}
+EXPORT_SYMBOL(drm_property_create_bool);
+
+/**
+ * drm_property_add_enum - add a possible value to an enumeration property
+ * @property: enumeration property to change
+ * @index: index of the new enumeration
+ * @value: value of the new enumeration
+ * @name: symbolic name of the new enumeration
+ *
+ * This functions adds enumerations to a property.
+ *
+ * It's use is deprecated, drivers should use one of the more specific helpers
+ * to directly create the property with all enumerations already attached.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_property_add_enum(struct drm_property *property, int index,
+			  uint64_t value, const char *name)
+{
+	struct drm_property_enum *prop_enum;
+
+	if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
+			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
+		return -EINVAL;
+
+	/*
+	 * Bitmask enum properties have the additional constraint of values
+	 * from 0 to 63
+	 */
+	if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
+			(value > 63))
+		return -EINVAL;
+
+	if (!list_empty(&property->enum_list)) {
+		list_for_each_entry(prop_enum, &property->enum_list, head) {
+			if (prop_enum->value == value) {
+				strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
+				prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
+				return 0;
+			}
+		}
+	}
+
+	prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
+	if (!prop_enum)
+		return -ENOMEM;
+
+	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
+	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
+	prop_enum->value = value;
+
+	property->values[index] = value;
+	list_add_tail(&prop_enum->head, &property->enum_list);
+	return 0;
+}
+EXPORT_SYMBOL(drm_property_add_enum);
+
+/**
+ * drm_property_destroy - destroy a drm property
+ * @dev: drm device
+ * @property: property to destry
+ *
+ * This function frees a property including any attached resources like
+ * enumeration values.
+ */
+void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
+{
+	struct drm_property_enum *prop_enum, *pt;
+
+	list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
+		list_del(&prop_enum->head);
+		kfree(prop_enum);
+	}
+
+	if (property->num_values)
+		kfree(property->values);
+	drm_mode_object_unregister(dev, &property->base);
+	list_del(&property->head);
+	kfree(property);
+}
+EXPORT_SYMBOL(drm_property_destroy);
+
+/**
+ * drm_mode_getproperty_ioctl - get the property metadata
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * This function retrieves the metadata for a given property, like the different
+ * possible values for an enum property or the limits for a range property.
+ *
+ * Blob properties are special
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getproperty_ioctl(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_get_property *out_resp = data;
+	struct drm_property *property;
+	int enum_count = 0;
+	int value_count = 0;
+	int ret = 0, i;
+	int copied;
+	struct drm_property_enum *prop_enum;
+	struct drm_mode_property_enum __user *enum_ptr;
+	uint64_t __user *values_ptr;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	drm_modeset_lock_all(dev);
+	property = drm_property_find(dev, out_resp->prop_id);
+	if (!property) {
+		ret = -ENOENT;
+		goto done;
+	}
+
+	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
+			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
+		list_for_each_entry(prop_enum, &property->enum_list, head)
+			enum_count++;
+	}
+
+	value_count = property->num_values;
+
+	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
+	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
+	out_resp->flags = property->flags;
+
+	if ((out_resp->count_values >= value_count) && value_count) {
+		values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
+		for (i = 0; i < value_count; i++) {
+			if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	}
+	out_resp->count_values = value_count;
+
+	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
+			drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
+		if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
+			copied = 0;
+			enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
+			list_for_each_entry(prop_enum, &property->enum_list, head) {
+
+				if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
+					ret = -EFAULT;
+					goto done;
+				}
+
+				if (copy_to_user(&enum_ptr[copied].name,
+						 &prop_enum->name, DRM_PROP_NAME_LEN)) {
+					ret = -EFAULT;
+					goto done;
+				}
+				copied++;
+			}
+		}
+		out_resp->count_enum_blobs = enum_count;
+	}
+
+	/*
+	 * NOTE: The idea seems to have been to use this to read all the blob
+	 * property values. But nothing ever added them to the corresponding
+	 * list, userspace always used the special-purpose get_blob ioctl to
+	 * read the value for a blob property. It also doesn't make a lot of
+	 * sense to return values here when everything else is just metadata for
+	 * the property itself.
+	 */
+	if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
+		out_resp->count_enum_blobs = 0;
+done:
+	drm_modeset_unlock_all(dev);
+	return ret;
+}
+
+static void drm_property_free_blob(struct kref *kref)
+{
+	struct drm_property_blob *blob =
+		container_of(kref, struct drm_property_blob, base.refcount);
+
+	mutex_lock(&blob->dev->mode_config.blob_lock);
+	list_del(&blob->head_global);
+	mutex_unlock(&blob->dev->mode_config.blob_lock);
+
+	drm_mode_object_unregister(blob->dev, &blob->base);
+
+	kfree(blob);
+}
+
+/**
+ * drm_property_create_blob - Create new blob property
+ *
+ * Creates a new blob property for a specified DRM device, optionally
+ * copying data.
+ *
+ * @dev: DRM device to create property for
+ * @length: Length to allocate for blob data
+ * @data: If specified, copies data into blob
+ *
+ * Returns:
+ * New blob property with a single reference on success, or an ERR_PTR
+ * value on failure.
+ */
+struct drm_property_blob *
+drm_property_create_blob(struct drm_device *dev, size_t length,
+			 const void *data)
+{
+	struct drm_property_blob *blob;
+	int ret;
+
+	if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
+		return ERR_PTR(-EINVAL);
+
+	blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
+	if (!blob)
+		return ERR_PTR(-ENOMEM);
+
+	/* This must be explicitly initialised, so we can safely call list_del
+	 * on it in the removal handler, even if it isn't in a file list. */
+	INIT_LIST_HEAD(&blob->head_file);
+	blob->length = length;
+	blob->dev = dev;
+
+	if (data)
+		memcpy(blob->data, data, length);
+
+	ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
+				      true, drm_property_free_blob);
+	if (ret) {
+		kfree(blob);
+		return ERR_PTR(-EINVAL);
+	}
+
+	mutex_lock(&dev->mode_config.blob_lock);
+	list_add_tail(&blob->head_global,
+	              &dev->mode_config.property_blob_list);
+	mutex_unlock(&dev->mode_config.blob_lock);
+
+	return blob;
+}
+EXPORT_SYMBOL(drm_property_create_blob);
+
+/**
+ * drm_property_unreference_blob - Unreference a blob property
+ *
+ * Drop a reference on a blob property. May free the object.
+ *
+ * @blob: Pointer to blob property
+ */
+void drm_property_unreference_blob(struct drm_property_blob *blob)
+{
+	if (!blob)
+		return;
+
+	drm_mode_object_unreference(&blob->base);
+}
+EXPORT_SYMBOL(drm_property_unreference_blob);
+
+/**
+ * drm_property_destroy_user_blobs - destroy all blobs created by this client
+ * @dev:       DRM device
+ * @file_priv: destroy all blobs owned by this file handle
+ */
+void drm_property_destroy_user_blobs(struct drm_device *dev,
+				     struct drm_file *file_priv)
+{
+	struct drm_property_blob *blob, *bt;
+
+	/*
+	 * When the file gets released that means no one else can access the
+	 * blob list any more, so no need to grab dev->blob_lock.
+	 */
+	list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
+		list_del_init(&blob->head_file);
+		drm_property_unreference_blob(blob);
+	}
+}
+
+/**
+ * drm_property_reference_blob - Take a reference on an existing property
+ *
+ * Take a new reference on an existing blob property.
+ *
+ * @blob: Pointer to blob property
+ */
+struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
+{
+	drm_mode_object_reference(&blob->base);
+	return blob;
+}
+EXPORT_SYMBOL(drm_property_reference_blob);
+
+/**
+ * drm_property_lookup_blob - look up a blob property and take a reference
+ * @dev: drm device
+ * @id: id of the blob property
+ *
+ * If successful, this takes an additional reference to the blob property.
+ * callers need to make sure to eventually unreference the returned property
+ * again, using @drm_property_unreference_blob.
+ */
+struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
+					           uint32_t id)
+{
+	struct drm_mode_object *obj;
+	struct drm_property_blob *blob = NULL;
+
+	obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
+	if (obj)
+		blob = obj_to_blob(obj);
+	return blob;
+}
+EXPORT_SYMBOL(drm_property_lookup_blob);
+
+/**
+ * drm_property_replace_global_blob - atomically replace existing blob property
+ * @dev: drm device
+ * @replace: location of blob property pointer to be replaced
+ * @length: length of data for new blob, or 0 for no data
+ * @data: content for new blob, or NULL for no data
+ * @obj_holds_id: optional object for property holding blob ID
+ * @prop_holds_id: optional property holding blob ID
+ * @return 0 on success or error on failure
+ *
+ * This function will atomically replace a global property in the blob list,
+ * optionally updating a property which holds the ID of that property. It is
+ * guaranteed to be atomic: no caller will be allowed to see intermediate
+ * results, and either the entire operation will succeed and clean up the
+ * previous property, or it will fail and the state will be unchanged.
+ *
+ * If length is 0 or data is NULL, no new blob will be created, and the holding
+ * property, if specified, will be set to 0.
+ *
+ * Access to the replace pointer is assumed to be protected by the caller, e.g.
+ * by holding the relevant modesetting object lock for its parent.
+ *
+ * For example, a drm_connector has a 'PATH' property, which contains the ID
+ * of a blob property with the value of the MST path information. Calling this
+ * function with replace pointing to the connector's path_blob_ptr, length and
+ * data set for the new path information, obj_holds_id set to the connector's
+ * base object, and prop_holds_id set to the path property name, will perform
+ * a completely atomic update. The access to path_blob_ptr is protected by the
+ * caller holding a lock on the connector.
+ */
+int drm_property_replace_global_blob(struct drm_device *dev,
+				     struct drm_property_blob **replace,
+				     size_t length,
+				     const void *data,
+				     struct drm_mode_object *obj_holds_id,
+				     struct drm_property *prop_holds_id)
+{
+	struct drm_property_blob *new_blob = NULL;
+	struct drm_property_blob *old_blob = NULL;
+	int ret;
+
+	WARN_ON(replace == NULL);
+
+	old_blob = *replace;
+
+	if (length && data) {
+		new_blob = drm_property_create_blob(dev, length, data);
+		if (IS_ERR(new_blob))
+			return PTR_ERR(new_blob);
+	}
+
+	/* This does not need to be synchronised with blob_lock, as the
+	 * get_properties ioctl locks all modesetting objects, and
+	 * obj_holds_id must be locked before calling here, so we cannot
+	 * have its value out of sync with the list membership modified
+	 * below under blob_lock. */
+	if (obj_holds_id) {
+		ret = drm_object_property_set_value(obj_holds_id,
+						    prop_holds_id,
+						    new_blob ?
+						        new_blob->base.id : 0);
+		if (ret != 0)
+			goto err_created;
+	}
+
+	drm_property_unreference_blob(old_blob);
+	*replace = new_blob;
+
+	return 0;
+
+err_created:
+	drm_property_unreference_blob(new_blob);
+	return ret;
+}
+EXPORT_SYMBOL(drm_property_replace_global_blob);
+
+/**
+ * drm_mode_getblob_ioctl - get the contents of a blob property value
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * This function retrieves the contents of a blob property. The value stored in
+ * an object's blob property is just a normal modeset object id.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getblob_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_get_blob *out_resp = data;
+	struct drm_property_blob *blob;
+	int ret = 0;
+	void __user *blob_ptr;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
+	if (!blob)
+		return -ENOENT;
+
+	if (out_resp->length == blob->length) {
+		blob_ptr = (void __user *)(unsigned long)out_resp->data;
+		if (copy_to_user(blob_ptr, blob->data, blob->length)) {
+			ret = -EFAULT;
+			goto unref;
+		}
+	}
+	out_resp->length = blob->length;
+unref:
+	drm_property_unreference_blob(blob);
+
+	return ret;
+}
+
+/**
+ * drm_mode_createblob_ioctl - create a new blob property
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * This function creates a new blob property with user-defined values. In order
+ * to give us sensible validation and checking when creating, rather than at
+ * every potential use, we also require a type to be provided upfront.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_createblob_ioctl(struct drm_device *dev,
+			      void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_create_blob *out_resp = data;
+	struct drm_property_blob *blob;
+	void __user *blob_ptr;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	blob = drm_property_create_blob(dev, out_resp->length, NULL);
+	if (IS_ERR(blob))
+		return PTR_ERR(blob);
+
+	blob_ptr = (void __user *)(unsigned long)out_resp->data;
+	if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
+		ret = -EFAULT;
+		goto out_blob;
+	}
+
+	/* Dropping the lock between create_blob and our access here is safe
+	 * as only the same file_priv can remove the blob; at this point, it is
+	 * not associated with any file_priv. */
+	mutex_lock(&dev->mode_config.blob_lock);
+	out_resp->blob_id = blob->base.id;
+	list_add_tail(&blob->head_file, &file_priv->blobs);
+	mutex_unlock(&dev->mode_config.blob_lock);
+
+	return 0;
+
+out_blob:
+	drm_property_unreference_blob(blob);
+	return ret;
+}
+
+/**
+ * drm_mode_destroyblob_ioctl - destroy a user blob property
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Destroy an existing user-defined blob property.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_destroyblob_ioctl(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_destroy_blob *out_resp = data;
+	struct drm_property_blob *blob = NULL, *bt;
+	bool found = false;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
+	if (!blob)
+		return -ENOENT;
+
+	mutex_lock(&dev->mode_config.blob_lock);
+	/* Ensure the property was actually created by this user. */
+	list_for_each_entry(bt, &file_priv->blobs, head_file) {
+		if (bt == blob) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		ret = -EPERM;
+		goto err;
+	}
+
+	/* We must drop head_file here, because we may not be the last
+	 * reference on the blob. */
+	list_del_init(&blob->head_file);
+	mutex_unlock(&dev->mode_config.blob_lock);
+
+	/* One reference from lookup, and one from the filp. */
+	drm_property_unreference_blob(blob);
+	drm_property_unreference_blob(blob);
+
+	return 0;
+
+err:
+	mutex_unlock(&dev->mode_config.blob_lock);
+	drm_property_unreference_blob(blob);
+
+	return ret;
+}
+
+/* Some properties could refer to dynamic refcnt'd objects, or things that
+ * need special locking to handle lifetime issues (ie. to ensure the prop
+ * value doesn't become invalid part way through the property update due to
+ * race).  The value returned by reference via 'obj' should be passed back
+ * to drm_property_change_valid_put() after the property is set (and the
+ * object to which the property is attached has a chance to take it's own
+ * reference).
+ */
+bool drm_property_change_valid_get(struct drm_property *property,
+					 uint64_t value, struct drm_mode_object **ref)
+{
+	int i;
+
+	if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+		return false;
+
+	*ref = NULL;
+
+	if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
+		if (value < property->values[0] || value > property->values[1])
+			return false;
+		return true;
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
+		int64_t svalue = U642I64(value);
+
+		if (svalue < U642I64(property->values[0]) ||
+				svalue > U642I64(property->values[1]))
+			return false;
+		return true;
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
+		uint64_t valid_mask = 0;
+
+		for (i = 0; i < property->num_values; i++)
+			valid_mask |= (1ULL << property->values[i]);
+		return !(value & ~valid_mask);
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
+		struct drm_property_blob *blob;
+
+		if (value == 0)
+			return true;
+
+		blob = drm_property_lookup_blob(property->dev, value);
+		if (blob) {
+			*ref = &blob->base;
+			return true;
+		} else {
+			return false;
+		}
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
+		/* a zero value for an object property translates to null: */
+		if (value == 0)
+			return true;
+
+		*ref = __drm_mode_object_find(property->dev, value,
+					      property->values[0]);
+		return *ref != NULL;
+	}
+
+	for (i = 0; i < property->num_values; i++)
+		if (property->values[i] == value)
+			return true;
+	return false;
+}
+
+void drm_property_change_valid_put(struct drm_property *property,
+		struct drm_mode_object *ref)
+{
+	if (!ref)
+		return;
+
+	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
+		drm_mode_object_unreference(ref);
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
+		drm_property_unreference_blob(obj_to_blob(ref));
+}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0c3fa89afd11..4880606e2ffd 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -41,6 +41,7 @@
 #include <drm/drm_modes.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
+#include <drm/drm_property.h>
 
 struct drm_device;
 struct drm_mode_set;
@@ -82,33 +83,6 @@ struct drm_tile_group {
 	u8 group_data[8];
 };
 
-struct drm_property_blob {
-	struct drm_mode_object base;
-	struct drm_device *dev;
-	struct list_head head_global;
-	struct list_head head_file;
-	size_t length;
-	unsigned char data[];
-};
-
-struct drm_property_enum {
-	uint64_t value;
-	struct list_head head;
-	char name[DRM_PROP_NAME_LEN];
-};
-
-struct drm_property {
-	struct list_head head;
-	struct drm_mode_object base;
-	uint32_t flags;
-	char name[DRM_PROP_NAME_LEN];
-	uint32_t num_values;
-	uint64_t *values;
-	struct drm_device *dev;
-
-	struct list_head enum_list;
-};
-
 struct drm_crtc;
 struct drm_encoder;
 struct drm_pending_vblank_event;
@@ -2032,15 +2006,9 @@ struct drm_mode_config {
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
 #define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
 #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
-#define obj_to_property(x) container_of(x, struct drm_property, base)
 #define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-struct drm_prop_enum_list {
-	int type;
-	char *name;
-};
-
 extern __printf(6, 7)
 int drm_crtc_init_with_planes(struct drm_device *dev,
 			      struct drm_crtc *crtc,
@@ -2113,52 +2081,6 @@ extern void drm_mode_config_init(struct drm_device *dev);
 extern void drm_mode_config_reset(struct drm_device *dev);
 extern void drm_mode_config_cleanup(struct drm_device *dev);
 
-static inline bool drm_property_type_is(struct drm_property *property,
-		uint32_t type)
-{
-	/* instanceof for props.. handles extended type vs original types: */
-	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
-		return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
-	return property->flags & type;
-}
-
-extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
-						const char *name, int num_values);
-extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
-					 const char *name,
-					 const struct drm_prop_enum_list *props,
-					 int num_values);
-struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
-					 int flags, const char *name,
-					 const struct drm_prop_enum_list *props,
-					 int num_props,
-					 uint64_t supported_bits);
-struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
-					 const char *name,
-					 uint64_t min, uint64_t max);
-struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
-					 int flags, const char *name,
-					 int64_t min, int64_t max);
-struct drm_property *drm_property_create_object(struct drm_device *dev,
-					 int flags, const char *name, uint32_t type);
-struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
-					 const char *name);
-struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
-                                                   size_t length,
-                                                   const void *data);
-struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
-                                                   uint32_t id);
-int drm_property_replace_global_blob(struct drm_device *dev,
-				     struct drm_property_blob **replace,
-				     size_t length,
-				     const void *data,
-				     struct drm_mode_object *obj_holds_id,
-				     struct drm_property *prop_holds_id);
-struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
-void drm_property_unreference_blob(struct drm_property_blob *blob);
-extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
-extern int drm_property_add_enum(struct drm_property *property, int index,
-				 uint64_t value, const char *name);
 extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
 					 int gamma_size);
 
@@ -2208,14 +2130,6 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
 	return mo ? obj_to_crtc(mo) : NULL;
 }
 
-static inline struct drm_property *drm_property_find(struct drm_device *dev,
-		uint32_t id)
-{
-	struct drm_mode_object *mo;
-	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
-	return mo ? obj_to_property(mo) : NULL;
-}
-
 /*
  * Extract a degamma/gamma LUT value provided by user and round it to the
  * precision supported by the hardware.
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
new file mode 100644
index 000000000000..ac40069358c7
--- /dev/null
+++ b/include/drm/drm_property.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef __DRM_PROPERTY_H__
+#define __DRM_PROPERTY_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <drm/drm_mode_object.h>
+
+struct drm_property_blob {
+	struct drm_mode_object base;
+	struct drm_device *dev;
+	struct list_head head_global;
+	struct list_head head_file;
+	size_t length;
+	unsigned char data[];
+};
+
+struct drm_property_enum {
+	uint64_t value;
+	struct list_head head;
+	char name[DRM_PROP_NAME_LEN];
+};
+
+struct drm_property {
+	struct list_head head;
+	struct drm_mode_object base;
+	uint32_t flags;
+	char name[DRM_PROP_NAME_LEN];
+	uint32_t num_values;
+	uint64_t *values;
+	struct drm_device *dev;
+
+	struct list_head enum_list;
+};
+
+struct drm_prop_enum_list {
+	int type;
+	char *name;
+};
+
+#define obj_to_property(x) container_of(x, struct drm_property, base)
+
+static inline bool drm_property_type_is(struct drm_property *property,
+		uint32_t type)
+{
+	/* instanceof for props.. handles extended type vs original types: */
+	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
+		return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
+	return property->flags & type;
+}
+
+struct drm_property *drm_property_create(struct drm_device *dev, int flags,
+					 const char *name, int num_values);
+struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
+					      const char *name,
+					      const struct drm_prop_enum_list *props,
+					      int num_values);
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+						 int flags, const char *name,
+						 const struct drm_prop_enum_list *props,
+						 int num_props,
+						 uint64_t supported_bits);
+struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
+					       const char *name,
+					       uint64_t min, uint64_t max);
+struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
+						      int flags, const char *name,
+						      int64_t min, int64_t max);
+struct drm_property *drm_property_create_object(struct drm_device *dev,
+						int flags, const char *name, uint32_t type);
+struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
+					      const char *name);
+int drm_property_add_enum(struct drm_property *property, int index,
+			  uint64_t value, const char *name);
+void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
+
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+						   size_t length,
+						   const void *data);
+struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
+						   uint32_t id);
+int drm_property_replace_global_blob(struct drm_device *dev,
+				     struct drm_property_blob **replace,
+				     size_t length,
+				     const void *data,
+				     struct drm_mode_object *obj_holds_id,
+				     struct drm_property *prop_holds_id);
+struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
+void drm_property_unreference_blob(struct drm_property_blob *blob);
+
+static inline struct drm_property *drm_property_find(struct drm_device *dev,
+		uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
+	return mo ? obj_to_property(mo) : NULL;
+}
+
+#endif
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 8/9] drm: Unify handling of blob and object properties
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
                   ` (5 preceding siblings ...)
  2016-08-29  8:27 ` [PATCH 7/9] drm: Extract drm_property.[hc] Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-09-06  9:22   ` Ying Liu
  2016-08-29  8:27 ` [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob Daniel Vetter
  7 siblings, 1 reply; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Stone

They work exactly the same now, after the refcounting unification a bit
ago. The only reason they're distinct is backwards compat with existing
userspace.

Cc: Daniel Stone <daniels@collabora.com>
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_property.c | 23 +++++------------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index 162cc9032ae5..b5521f705b1c 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -911,20 +911,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
 		for (i = 0; i < property->num_values; i++)
 			valid_mask |= (1ULL << property->values[i]);
 		return !(value & ~valid_mask);
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
-		struct drm_property_blob *blob;
-
-		if (value == 0)
-			return true;
-
-		blob = drm_property_lookup_blob(property->dev, value);
-		if (blob) {
-			*ref = &blob->base;
-			return true;
-		} else {
-			return false;
-		}
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB) ||
+		   drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
 		/* a zero value for an object property translates to null: */
 		if (value == 0)
 			return true;
@@ -941,13 +929,12 @@ bool drm_property_change_valid_get(struct drm_property *property,
 }
 
 void drm_property_change_valid_put(struct drm_property *property,
-		struct drm_mode_object *ref)
+				   struct drm_mode_object *ref)
 {
 	if (!ref)
 		return;
 
-	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
+	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT) ||
+	    drm_property_type_is(property, DRM_MODE_PROP_BLOB))
 		drm_mode_object_unreference(ref);
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
-		drm_property_unreference_blob(obj_to_blob(ref));
 }
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob
  2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
                   ` (6 preceding siblings ...)
  2016-08-29  8:27 ` [PATCH 8/9] drm: Unify handling of blob and object properties Daniel Vetter
@ 2016-08-29  8:27 ` Daniel Vetter
  2016-08-29 13:14   ` Archit Taneja
  7 siblings, 1 reply; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29  8:27 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- remove kerneldoc for drm-internal functions
- drm_property_replace_global_blob isn't actually atomic, and doesn't
  need to be. Update docs&comments to match
- document all the types and try to link things a bit better
- nits all over

v2: Appease checkpatch in the moved code (Archit)

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst  |  88 +-----------------
 drivers/gpu/drm/drm_property.c | 153 ++++++++++++--------------------
 include/drm/drm_property.h     | 196 ++++++++++++++++++++++++++++++++++++++---
 3 files changed, 244 insertions(+), 193 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index e07a2667ab61..f9a991bb87d4 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -304,94 +304,12 @@ KMS Locking
 KMS Properties
 ==============
 
-Drivers may need to expose additional parameters to applications than
-those described in the previous sections. KMS supports attaching
-properties to CRTCs, connectors and planes and offers a userspace API to
-list, get and set the property values.
-
-Properties are identified by a name that uniquely defines the property
-purpose, and store an associated value. For all property types except
-blob properties the value is a 64-bit unsigned integer.
-
-KMS differentiates between properties and property instances. Drivers
-first create properties and then create and associate individual
-instances of those properties to objects. A property can be instantiated
-multiple times and associated with different objects. Values are stored
-in property instances, and all other property information are stored in
-the property and shared between all instances of the property.
-
-Every property is created with a type that influences how the KMS core
-handles the property. Supported property types are
-
-DRM_MODE_PROP_RANGE
-    Range properties report their minimum and maximum admissible values.
-    The KMS core verifies that values set by application fit in that
-    range.
-
-DRM_MODE_PROP_ENUM
-    Enumerated properties take a numerical value that ranges from 0 to
-    the number of enumerated values defined by the property minus one,
-    and associate a free-formed string name to each value. Applications
-    can retrieve the list of defined value-name pairs and use the
-    numerical value to get and set property instance values.
-
-DRM_MODE_PROP_BITMASK
-    Bitmask properties are enumeration properties that additionally
-    restrict all enumerated values to the 0..63 range. Bitmask property
-    instance values combine one or more of the enumerated bits defined
-    by the property.
-
-DRM_MODE_PROP_BLOB
-    Blob properties store a binary blob without any format restriction.
-    The binary blobs are created as KMS standalone objects, and blob
-    property instance values store the ID of their associated blob
-    object.
-
-    Blob properties are only used for the connector EDID property and
-    cannot be created by drivers.
-
-To create a property drivers call one of the following functions
-depending on the property type. All property creation functions take
-property flags and name, as well as type-specific arguments.
-
--  struct drm_property \*drm_property_create_range(struct
-   drm_device \*dev, int flags, const char \*name, uint64_t min,
-   uint64_t max);
-   Create a range property with the given minimum and maximum values.
-
--  struct drm_property \*drm_property_create_enum(struct drm_device
-   \*dev, int flags, const char \*name, const struct
-   drm_prop_enum_list \*props, int num_values);
-   Create an enumerated property. The ``props`` argument points to an
-   array of ``num_values`` value-name pairs.
-
--  struct drm_property \*drm_property_create_bitmask(struct
-   drm_device \*dev, int flags, const char \*name, const struct
-   drm_prop_enum_list \*props, int num_values);
-   Create a bitmask property. The ``props`` argument points to an array
-   of ``num_values`` value-name pairs.
-
-Properties can additionally be created as immutable, in which case they
-will be read-only for applications but can be modified by the driver. To
-create an immutable property drivers must set the
-DRM_MODE_PROP_IMMUTABLE flag at property creation time.
-
-When no array of value-name pairs is readily available at property
-creation time for enumerated or range properties, drivers can create the
-property using the :c:func:`drm_property_create()` function and
-manually add enumeration value-name pairs by calling the
-:c:func:`drm_property_add_enum()` function. Care must be taken to
-properly specify the property type through the ``flags`` argument.
-
-After creating properties drivers can attach property instances to CRTC,
-connector and plane objects by calling the
-:c:func:`drm_object_attach_property()`. The function takes a
-pointer to the target object, a pointer to the previously created
-property and an initial instance value.
-
 Property Types and Blob Property Support
 ----------------------------------------
 
+.. kernel-doc:: drivers/gpu/drm/drm_property.c
+   :doc: overview
+
 .. kernel-doc:: include/drm/drm_property.h
    :internal:
 
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index b5521f705b1c..4139afbcc267 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -26,6 +26,30 @@
 
 #include "drm_crtc_internal.h"
 
+/**
+ * DOC: overview
+ *
+ * Properties as represented by &drm_property are used to extend the modeset
+ * interface exposed to userspace. For the atomic modeset IOCTL properties are
+ * even the only way to transport metadata about the desired new modeset
+ * configuration from userspace to the kernel. Properties have a well-defined
+ * value range, which is enforced by the drm core. See the documentation of the
+ * flags member of struct &drm_property for an overview of the different
+ * property types and ranges.
+ *
+ * Properties don't store the current value directly, but need to be
+ * instatiated by attaching them to a &drm_mode_object with
+ * drm_object_attach_property().
+ *
+ * Property values are only 64bit. To support bigger piles of data (like gamma
+ * tables, color correction matrizes or large structures) a property can instead
+ * point at a &drm_property_blob with that additional data
+ *
+ * Properties are defined by their symbolic name, userspace must keep a
+ * per-object mapping from those names to the property ID used in the atomic
+ * IOCTL and in the get/set property IOCTL.
+ */
+
 static bool drm_property_type_valid(struct drm_property *property)
 {
 	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
@@ -42,11 +66,8 @@ static bool drm_property_type_valid(struct drm_property *property)
  *
  * This creates a new generic drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
- *
- * Note that the DRM core keeps a per-device list of properties and that, if
- * drm_mode_config_cleanup() is called, it will destroy all properties created
- * by the driver.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * Returns:
  * A pointer to the newly created property on success, NULL on failure.
@@ -105,7 +126,8 @@ EXPORT_SYMBOL(drm_property_create);
  *
  * This creates a new generic drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * Userspace is only allowed to set one of the predefined values for enumeration
  * properties.
@@ -152,7 +174,8 @@ EXPORT_SYMBOL(drm_property_create_enum);
  *
  * This creates a new bitmask drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * Compared to plain enumeration properties userspace is allowed to set any
  * or'ed together combination of the predefined property bitflag values
@@ -223,7 +246,8 @@ static struct drm_property *property_create_range(struct drm_device *dev,
  *
  * This creates a new generic drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * Userspace is allowed to set any unsigned integer value in the (min, max)
  * range inclusive.
@@ -250,7 +274,8 @@ EXPORT_SYMBOL(drm_property_create_range);
  *
  * This creates a new generic drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * Userspace is allowed to set any signed integer value in the (min, max)
  * range inclusive.
@@ -276,7 +301,8 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
  *
  * This creates a new generic drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * Userspace is only allowed to set this to any property value of the given
  * @type. Only useful for atomic properties, which is enforced.
@@ -285,7 +311,8 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
  * A pointer to the newly created property on success, NULL on failure.
  */
 struct drm_property *drm_property_create_object(struct drm_device *dev,
-					 int flags, const char *name, uint32_t type)
+						int flags, const char *name,
+						uint32_t type)
 {
 	struct drm_property *property;
 
@@ -312,7 +339,8 @@ EXPORT_SYMBOL(drm_property_create_object);
  *
  * This creates a new generic drm property which can then be attached to a drm
  * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy.
+ * freed with drm_property_destroy(), which is done automatically when calling
+ * drm_mode_config_cleanup().
  *
  * This is implemented as a ranged property with only {0, 1} as valid values.
  *
@@ -320,7 +348,7 @@ EXPORT_SYMBOL(drm_property_create_object);
  * A pointer to the newly created property on success, NULL on failure.
  */
 struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
-					 const char *name)
+					      const char *name)
 {
 	return drm_property_create_range(dev, flags, name, 0, 1);
 }
@@ -407,22 +435,6 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
 }
 EXPORT_SYMBOL(drm_property_destroy);
 
-/**
- * drm_mode_getproperty_ioctl - get the property metadata
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function retrieves the metadata for a given property, like the different
- * possible values for an enum property or the limits for a range property.
- *
- * Blob properties are special
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
 int drm_mode_getproperty_ioctl(struct drm_device *dev,
 			       void *data, struct drm_file *file_priv)
 {
@@ -523,14 +535,14 @@ static void drm_property_free_blob(struct kref *kref)
 
 /**
  * drm_property_create_blob - Create new blob property
- *
- * Creates a new blob property for a specified DRM device, optionally
- * copying data.
- *
  * @dev: DRM device to create property for
  * @length: Length to allocate for blob data
  * @data: If specified, copies data into blob
  *
+ * Creates a new blob property for a specified DRM device, optionally
+ * copying data. Note that blob properties are meant to be invariant, hence the
+ * data must be filled out before the blob is used as the value of any property.
+ *
  * Returns:
  * New blob property with a single reference on success, or an ERR_PTR
  * value on failure.
@@ -576,10 +588,9 @@ EXPORT_SYMBOL(drm_property_create_blob);
 
 /**
  * drm_property_unreference_blob - Unreference a blob property
+ * @blob: Pointer to blob property
  *
  * Drop a reference on a blob property. May free the object.
- *
- * @blob: Pointer to blob property
  */
 void drm_property_unreference_blob(struct drm_property_blob *blob)
 {
@@ -590,11 +601,6 @@ void drm_property_unreference_blob(struct drm_property_blob *blob)
 }
 EXPORT_SYMBOL(drm_property_unreference_blob);
 
-/**
- * drm_property_destroy_user_blobs - destroy all blobs created by this client
- * @dev:       DRM device
- * @file_priv: destroy all blobs owned by this file handle
- */
 void drm_property_destroy_user_blobs(struct drm_device *dev,
 				     struct drm_file *file_priv)
 {
@@ -612,10 +618,10 @@ void drm_property_destroy_user_blobs(struct drm_device *dev,
 
 /**
  * drm_property_reference_blob - Take a reference on an existing property
- *
- * Take a new reference on an existing blob property.
- *
  * @blob: Pointer to blob property
+ *
+ * Take a new reference on an existing blob property. Returns @blob, which
+ * allows this to be used as a shorthand in assignments.
  */
 struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
 {
@@ -632,6 +638,9 @@ EXPORT_SYMBOL(drm_property_reference_blob);
  * If successful, this takes an additional reference to the blob property.
  * callers need to make sure to eventually unreference the returned property
  * again, using @drm_property_unreference_blob.
+ *
+ * Return:
+ * NULL on failure, pointer to the blob on success.
  */
 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
 					           uint32_t id)
@@ -647,7 +656,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
 EXPORT_SYMBOL(drm_property_lookup_blob);
 
 /**
- * drm_property_replace_global_blob - atomically replace existing blob property
+ * drm_property_replace_global_blob - replace existing blob property
  * @dev: drm device
  * @replace: location of blob property pointer to be replaced
  * @length: length of data for new blob, or 0 for no data
@@ -656,11 +665,8 @@ EXPORT_SYMBOL(drm_property_lookup_blob);
  * @prop_holds_id: optional property holding blob ID
  * @return 0 on success or error on failure
  *
- * This function will atomically replace a global property in the blob list,
- * optionally updating a property which holds the ID of that property. It is
- * guaranteed to be atomic: no caller will be allowed to see intermediate
- * results, and either the entire operation will succeed and clean up the
- * previous property, or it will fail and the state will be unchanged.
+ * This function will replace a global property in the blob list, optionally
+ * updating a property which holds the ID of that property.
  *
  * If length is 0 or data is NULL, no new blob will be created, and the holding
  * property, if specified, will be set to 0.
@@ -697,11 +703,6 @@ int drm_property_replace_global_blob(struct drm_device *dev,
 			return PTR_ERR(new_blob);
 	}
 
-	/* This does not need to be synchronised with blob_lock, as the
-	 * get_properties ioctl locks all modesetting objects, and
-	 * obj_holds_id must be locked before calling here, so we cannot
-	 * have its value out of sync with the list membership modified
-	 * below under blob_lock. */
 	if (obj_holds_id) {
 		ret = drm_object_property_set_value(obj_holds_id,
 						    prop_holds_id,
@@ -722,20 +723,6 @@ err_created:
 }
 EXPORT_SYMBOL(drm_property_replace_global_blob);
 
-/**
- * drm_mode_getblob_ioctl - get the contents of a blob property value
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function retrieves the contents of a blob property. The value stored in
- * an object's blob property is just a normal modeset object id.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
 int drm_mode_getblob_ioctl(struct drm_device *dev,
 			   void *data, struct drm_file *file_priv)
 {
@@ -765,21 +752,6 @@ unref:
 	return ret;
 }
 
-/**
- * drm_mode_createblob_ioctl - create a new blob property
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This function creates a new blob property with user-defined values. In order
- * to give us sensible validation and checking when creating, rather than at
- * every potential use, we also require a type to be provided upfront.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
 int drm_mode_createblob_ioctl(struct drm_device *dev,
 			      void *data, struct drm_file *file_priv)
 {
@@ -816,19 +788,6 @@ out_blob:
 	return ret;
 }
 
-/**
- * drm_mode_destroyblob_ioctl - destroy a user blob property
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Destroy an existing user-defined blob property.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
 int drm_mode_destroyblob_ioctl(struct drm_device *dev,
 			       void *data, struct drm_file *file_priv)
 {
@@ -885,7 +844,7 @@ err:
  * reference).
  */
 bool drm_property_change_valid_get(struct drm_property *property,
-					 uint64_t value, struct drm_mode_object **ref)
+				   uint64_t value, struct drm_mode_object **ref)
 {
 	int i;
 
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index ac40069358c7..30ab289be05d 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -27,33 +27,192 @@
 #include <linux/ctype.h>
 #include <drm/drm_mode_object.h>
 
-struct drm_property_blob {
-	struct drm_mode_object base;
-	struct drm_device *dev;
-	struct list_head head_global;
-	struct list_head head_file;
-	size_t length;
-	unsigned char data[];
-};
-
+/**
+ * struct drm_property_enum - symbolic values for enumerations
+ * @value: numeric property value for this enum entry
+ * @head: list of enum values, linked to enum_list in &drm_property
+ * @name: symbolic name for the enum
+ *
+ * For enumeration and bitmask properties this structure stores the symbolic
+ * decoding for each value. This is used for example for the rotation property.
+ */
 struct drm_property_enum {
 	uint64_t value;
 	struct list_head head;
 	char name[DRM_PROP_NAME_LEN];
 };
 
+/**
+ * struct drm_property - modeset object property
+ *
+ * This structure represent a modeset object property. It combines both the name
+ * of the property with the set of permissible values. This means that when a
+ * driver wants to use a property with the same name on different objects, but
+ * with different value ranges, then it must create property for each one. An
+ * example would be rotation of &drm_plane, when e.g. the primary plane cannot
+ * be rotated. But if both the name and the value range match, then the same
+ * property structure can be instantiated multiple times for the same object.
+ * Userspace must be able to cope with this and cannot assume that the same
+ * symbolic property will have the same modeset object ID on all modeset
+ * objects.
+ *
+ * Properties are created by one of the special functions, as explained in
+ * detail in the @flags structure member.
+ *
+ * To actually expose a property it must be attached to each object using
+ * drm_object_attach_property(). Currently properties can only be attached to
+ * &drm_connector, &drm_crtc and &drm_plane.
+ *
+ * Properties are also used as the generic metadatatransport for the atomic
+ * IOCTL. Everything that was set directly in structures in the legacy modeset
+ * IOCTLs (like the plane source or destination windows, or e.g. the links to
+ * the CRTC) is exposed as a property with the DRM_MODE_PROP_ATOMIC flag set.
+ */
 struct drm_property {
+	/**
+	 * @head: per-device list of properties, for cleanup.
+	 */
 	struct list_head head;
+
+	/**
+	 * @base: base KMS object
+	 */
 	struct drm_mode_object base;
+
+	/**
+	 * @flags:
+	 *
+	 * Property flags and type. A property needs to be one of the following
+	 * types:
+	 *
+	 * DRM_MODE_PROP_RANGE
+	 *     Range properties report their minimum and maximum admissible unsigned values.
+	 *     The KMS core verifies that values set by application fit in that
+	 *     range. The range is unsigned. Range properties are created using
+	 *     drm_property_create_range().
+	 *
+	 * DRM_MODE_PROP_SIGNED_RANGE
+	 *     Range properties report their minimum and maximum admissible unsigned values.
+	 *     The KMS core verifies that values set by application fit in that
+	 *     range. The range is signed. Range properties are created using
+	 *     drm_property_create_signed_range().
+	 *
+	 * DRM_MODE_PROP_ENUM
+	 *     Enumerated properties take a numerical value that ranges from 0 to
+	 *     the number of enumerated values defined by the property minus one,
+	 *     and associate a free-formed string name to each value. Applications
+	 *     can retrieve the list of defined value-name pairs and use the
+	 *     numerical value to get and set property instance values. Enum
+	 *     properties are created using drm_property_create_enum().
+	 *
+	 * DRM_MODE_PROP_BITMASK
+	 *     Bitmask properties are enumeration properties that additionally
+	 *     restrict all enumerated values to the 0..63 range. Bitmask property
+	 *     instance values combine one or more of the enumerated bits defined
+	 *     by the property. Bitmask properties are created using
+	 *     drm_property_create_bitmask().
+	 *
+	 * DRM_MODE_PROB_OBJECT
+	 *     Object properties are used to link modeset objects. This is used
+	 *     extensively in the atomic support to create the display pipeline,
+	 *     by linking &drm_framebuffer to &drm_plane, &drm_plane to
+	 *     &drm_crtc and &drm_connector to &drm_crtc. An object property can
+	 *     only link to a specific type of &drm_mode_object, this limit is
+	 *     enforced by the core. Object properties are created using
+	 *     drm_property_create_object().
+	 *
+	 *     Object properties work like blob properties, but in a more
+	 *     general fashion. They are limited to atomic drivers and must have
+	 *     the DRM_MODE_PROP_ATOMIC flag set.
+	 *
+	 * DRM_MODE_PROP_BLOB
+	 *     Blob properties store a binary blob without any format restriction.
+	 *     The binary blobs are created as KMS standalone objects, and blob
+	 *     property instance values store the ID of their associated blob
+	 *     object. Blob properties are created by calling
+	 *     drm_property_create() with DRM_MODE_PROP_BLOB as the type.
+	 *
+	 *     Actual blob objects to contain blob data are created using
+	 *     drm_property_create_blob(), or through the corresponding IOCTL.
+	 *
+	 *     Besides the built-in limit to only accept blob objects blob
+	 *     properties work exactly like object properties. The only reasons
+	 *     blob properties exist is backwards compatibility with existing
+	 *     userspace.
+	 *
+	 * In addition a property can have any combination of the below flags:
+	 *
+	 * DRM_MODE_PROP_ATOMIC
+	 *     Set for properties which encode atomic modeset state. Such
+	 *     properties are not exposed to legacy userspace.
+	 *
+	 * DRM_MODE_PROP_IMMUTABLE
+	 *     Set for properties where userspace cannot be changed by
+	 *     userspace. The kernel is allowed to update the value of these
+	 *     properties. This is generally used to expose probe state to
+	 *     usersapce, e.g. the EDID, or the connector path property on DP
+	 *     MST sinks.
+	 */
 	uint32_t flags;
+
+	/**
+	 * @name: symbolic name of the properties
+	 */
 	char name[DRM_PROP_NAME_LEN];
+
+	/**
+	 * @num_values: size of the @values array.
+	 */
 	uint32_t num_values;
+
+	/**
+	 * @values:
+	 *
+	 * Array with limits and values for the property. The
+	 * interpretation of these limits is dependent upon the type per @flags.
+	 */
 	uint64_t *values;
+
+	/**
+	 * @dev: DRM device
+	 */
 	struct drm_device *dev;
 
+	/**
+	 * @enum_list:
+	 *
+	 * List of &drm_prop_enum_list structures with the symbolic names for
+	 * enum and bitmask values.
+	 */
 	struct list_head enum_list;
 };
 
+/**
+ * struct drm_property_blob - Blob data for &drm_property
+ * @base: base KMS object
+ * @dev: DRM device
+ * @head_global: entry on the global blob list in &drm_mode_config
+ *	property_blob_list.
+ * @head_file: entry on the per-file blob list in &drm_file blobs list.
+ * @length: size of the blob in bytes, invariant over the lifetime of the object
+ * @data: actual data, embedded at the end of this structure
+ *
+ * Blobs are used to store bigger values than what fits directly into the 64
+ * bits available for a &drm_property.
+ *
+ * Blobs are reference counted using drm_property_reference_blob() and
+ * drm_property_unreference_blob(). They are created using
+ * drm_property_create_blob().
+ */
+struct drm_property_blob {
+	struct drm_mode_object base;
+	struct drm_device *dev;
+	struct list_head head_global;
+	struct list_head head_file;
+	size_t length;
+	unsigned char data[];
+};
+
 struct drm_prop_enum_list {
 	int type;
 	char *name;
@@ -61,8 +220,16 @@ struct drm_prop_enum_list {
 
 #define obj_to_property(x) container_of(x, struct drm_property, base)
 
+/**
+ * drm_property_type_is - check the type of a property
+ * @property: property to check
+ * @type: property type to compare with
+ *
+ * This is a helper function becauase the uapi encoding of property types is
+ * a bit special for historical reasons.
+ */
 static inline bool drm_property_type_is(struct drm_property *property,
-		uint32_t type)
+					uint32_t type)
 {
 	/* instanceof for props.. handles extended type vs original types: */
 	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
@@ -109,8 +276,15 @@ int drm_property_replace_global_blob(struct drm_device *dev,
 struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
 void drm_property_unreference_blob(struct drm_property_blob *blob);
 
+/**
+ * drm_connector_find - find property object
+ * @dev: DRM device
+ * @id: property object id
+ *
+ * This function looks up the property object specified by id and returns it.
+ */
 static inline struct drm_property *drm_property_find(struct drm_device *dev,
-		uint32_t id)
+						     uint32_t id)
 {
 	struct drm_mode_object *mo;
 	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob
  2016-08-29  8:27 ` [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob Daniel Vetter
@ 2016-08-29 13:14   ` Archit Taneja
  2016-08-29 14:04     ` Daniel Vetter
  0 siblings, 1 reply; 18+ messages in thread
From: Archit Taneja @ 2016-08-29 13:14 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development; +Cc: Daniel Vetter



On 08/29/2016 01:57 PM, Daniel Vetter wrote:
> - remove kerneldoc for drm-internal functions
> - drm_property_replace_global_blob isn't actually atomic, and doesn't
>    need to be. Update docs&comments to match
> - document all the types and try to link things a bit better
> - nits all over
>

Reviewed-by: Archit Taneja <architt@codeaurora.org>

> v2: Appease checkpatch in the moved code (Archit)
>
> Reviewed-by: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>   Documentation/gpu/drm-kms.rst  |  88 +-----------------
>   drivers/gpu/drm/drm_property.c | 153 ++++++++++++--------------------
>   include/drm/drm_property.h     | 196 ++++++++++++++++++++++++++++++++++++++---
>   3 files changed, 244 insertions(+), 193 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index e07a2667ab61..f9a991bb87d4 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -304,94 +304,12 @@ KMS Locking
>   KMS Properties
>   ==============
>
> -Drivers may need to expose additional parameters to applications than
> -those described in the previous sections. KMS supports attaching
> -properties to CRTCs, connectors and planes and offers a userspace API to
> -list, get and set the property values.
> -
> -Properties are identified by a name that uniquely defines the property
> -purpose, and store an associated value. For all property types except
> -blob properties the value is a 64-bit unsigned integer.
> -
> -KMS differentiates between properties and property instances. Drivers
> -first create properties and then create and associate individual
> -instances of those properties to objects. A property can be instantiated
> -multiple times and associated with different objects. Values are stored
> -in property instances, and all other property information are stored in
> -the property and shared between all instances of the property.
> -
> -Every property is created with a type that influences how the KMS core
> -handles the property. Supported property types are
> -
> -DRM_MODE_PROP_RANGE
> -    Range properties report their minimum and maximum admissible values.
> -    The KMS core verifies that values set by application fit in that
> -    range.
> -
> -DRM_MODE_PROP_ENUM
> -    Enumerated properties take a numerical value that ranges from 0 to
> -    the number of enumerated values defined by the property minus one,
> -    and associate a free-formed string name to each value. Applications
> -    can retrieve the list of defined value-name pairs and use the
> -    numerical value to get and set property instance values.
> -
> -DRM_MODE_PROP_BITMASK
> -    Bitmask properties are enumeration properties that additionally
> -    restrict all enumerated values to the 0..63 range. Bitmask property
> -    instance values combine one or more of the enumerated bits defined
> -    by the property.
> -
> -DRM_MODE_PROP_BLOB
> -    Blob properties store a binary blob without any format restriction.
> -    The binary blobs are created as KMS standalone objects, and blob
> -    property instance values store the ID of their associated blob
> -    object.
> -
> -    Blob properties are only used for the connector EDID property and
> -    cannot be created by drivers.
> -
> -To create a property drivers call one of the following functions
> -depending on the property type. All property creation functions take
> -property flags and name, as well as type-specific arguments.
> -
> --  struct drm_property \*drm_property_create_range(struct
> -   drm_device \*dev, int flags, const char \*name, uint64_t min,
> -   uint64_t max);
> -   Create a range property with the given minimum and maximum values.
> -
> --  struct drm_property \*drm_property_create_enum(struct drm_device
> -   \*dev, int flags, const char \*name, const struct
> -   drm_prop_enum_list \*props, int num_values);
> -   Create an enumerated property. The ``props`` argument points to an
> -   array of ``num_values`` value-name pairs.
> -
> --  struct drm_property \*drm_property_create_bitmask(struct
> -   drm_device \*dev, int flags, const char \*name, const struct
> -   drm_prop_enum_list \*props, int num_values);
> -   Create a bitmask property. The ``props`` argument points to an array
> -   of ``num_values`` value-name pairs.
> -
> -Properties can additionally be created as immutable, in which case they
> -will be read-only for applications but can be modified by the driver. To
> -create an immutable property drivers must set the
> -DRM_MODE_PROP_IMMUTABLE flag at property creation time.
> -
> -When no array of value-name pairs is readily available at property
> -creation time for enumerated or range properties, drivers can create the
> -property using the :c:func:`drm_property_create()` function and
> -manually add enumeration value-name pairs by calling the
> -:c:func:`drm_property_add_enum()` function. Care must be taken to
> -properly specify the property type through the ``flags`` argument.
> -
> -After creating properties drivers can attach property instances to CRTC,
> -connector and plane objects by calling the
> -:c:func:`drm_object_attach_property()`. The function takes a
> -pointer to the target object, a pointer to the previously created
> -property and an initial instance value.
> -
>   Property Types and Blob Property Support
>   ----------------------------------------
>
> +.. kernel-doc:: drivers/gpu/drm/drm_property.c
> +   :doc: overview
> +
>   .. kernel-doc:: include/drm/drm_property.h
>      :internal:
>
> diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
> index b5521f705b1c..4139afbcc267 100644
> --- a/drivers/gpu/drm/drm_property.c
> +++ b/drivers/gpu/drm/drm_property.c
> @@ -26,6 +26,30 @@
>
>   #include "drm_crtc_internal.h"
>
> +/**
> + * DOC: overview
> + *
> + * Properties as represented by &drm_property are used to extend the modeset
> + * interface exposed to userspace. For the atomic modeset IOCTL properties are
> + * even the only way to transport metadata about the desired new modeset
> + * configuration from userspace to the kernel. Properties have a well-defined
> + * value range, which is enforced by the drm core. See the documentation of the
> + * flags member of struct &drm_property for an overview of the different
> + * property types and ranges.
> + *
> + * Properties don't store the current value directly, but need to be
> + * instatiated by attaching them to a &drm_mode_object with
> + * drm_object_attach_property().
> + *
> + * Property values are only 64bit. To support bigger piles of data (like gamma
> + * tables, color correction matrizes or large structures) a property can instead
> + * point at a &drm_property_blob with that additional data
> + *
> + * Properties are defined by their symbolic name, userspace must keep a
> + * per-object mapping from those names to the property ID used in the atomic
> + * IOCTL and in the get/set property IOCTL.
> + */
> +
>   static bool drm_property_type_valid(struct drm_property *property)
>   {
>   	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> @@ -42,11 +66,8 @@ static bool drm_property_type_valid(struct drm_property *property)
>    *
>    * This creates a new generic drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> - *
> - * Note that the DRM core keeps a per-device list of properties and that, if
> - * drm_mode_config_cleanup() is called, it will destroy all properties created
> - * by the driver.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * Returns:
>    * A pointer to the newly created property on success, NULL on failure.
> @@ -105,7 +126,8 @@ EXPORT_SYMBOL(drm_property_create);
>    *
>    * This creates a new generic drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * Userspace is only allowed to set one of the predefined values for enumeration
>    * properties.
> @@ -152,7 +174,8 @@ EXPORT_SYMBOL(drm_property_create_enum);
>    *
>    * This creates a new bitmask drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * Compared to plain enumeration properties userspace is allowed to set any
>    * or'ed together combination of the predefined property bitflag values
> @@ -223,7 +246,8 @@ static struct drm_property *property_create_range(struct drm_device *dev,
>    *
>    * This creates a new generic drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * Userspace is allowed to set any unsigned integer value in the (min, max)
>    * range inclusive.
> @@ -250,7 +274,8 @@ EXPORT_SYMBOL(drm_property_create_range);
>    *
>    * This creates a new generic drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * Userspace is allowed to set any signed integer value in the (min, max)
>    * range inclusive.
> @@ -276,7 +301,8 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
>    *
>    * This creates a new generic drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * Userspace is only allowed to set this to any property value of the given
>    * @type. Only useful for atomic properties, which is enforced.
> @@ -285,7 +311,8 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
>    * A pointer to the newly created property on success, NULL on failure.
>    */
>   struct drm_property *drm_property_create_object(struct drm_device *dev,
> -					 int flags, const char *name, uint32_t type)
> +						int flags, const char *name,
> +						uint32_t type)
>   {
>   	struct drm_property *property;
>
> @@ -312,7 +339,8 @@ EXPORT_SYMBOL(drm_property_create_object);
>    *
>    * This creates a new generic drm property which can then be attached to a drm
>    * object with drm_object_attach_property. The returned property object must be
> - * freed with drm_property_destroy.
> + * freed with drm_property_destroy(), which is done automatically when calling
> + * drm_mode_config_cleanup().
>    *
>    * This is implemented as a ranged property with only {0, 1} as valid values.
>    *
> @@ -320,7 +348,7 @@ EXPORT_SYMBOL(drm_property_create_object);
>    * A pointer to the newly created property on success, NULL on failure.
>    */
>   struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
> -					 const char *name)
> +					      const char *name)
>   {
>   	return drm_property_create_range(dev, flags, name, 0, 1);
>   }
> @@ -407,22 +435,6 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
>   }
>   EXPORT_SYMBOL(drm_property_destroy);
>
> -/**
> - * drm_mode_getproperty_ioctl - get the property metadata
> - * @dev: DRM device
> - * @data: ioctl data
> - * @file_priv: DRM file info
> - *
> - * This function retrieves the metadata for a given property, like the different
> - * possible values for an enum property or the limits for a range property.
> - *
> - * Blob properties are special
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>   int drm_mode_getproperty_ioctl(struct drm_device *dev,
>   			       void *data, struct drm_file *file_priv)
>   {
> @@ -523,14 +535,14 @@ static void drm_property_free_blob(struct kref *kref)
>
>   /**
>    * drm_property_create_blob - Create new blob property
> - *
> - * Creates a new blob property for a specified DRM device, optionally
> - * copying data.
> - *
>    * @dev: DRM device to create property for
>    * @length: Length to allocate for blob data
>    * @data: If specified, copies data into blob
>    *
> + * Creates a new blob property for a specified DRM device, optionally
> + * copying data. Note that blob properties are meant to be invariant, hence the
> + * data must be filled out before the blob is used as the value of any property.
> + *
>    * Returns:
>    * New blob property with a single reference on success, or an ERR_PTR
>    * value on failure.
> @@ -576,10 +588,9 @@ EXPORT_SYMBOL(drm_property_create_blob);
>
>   /**
>    * drm_property_unreference_blob - Unreference a blob property
> + * @blob: Pointer to blob property
>    *
>    * Drop a reference on a blob property. May free the object.
> - *
> - * @blob: Pointer to blob property
>    */
>   void drm_property_unreference_blob(struct drm_property_blob *blob)
>   {
> @@ -590,11 +601,6 @@ void drm_property_unreference_blob(struct drm_property_blob *blob)
>   }
>   EXPORT_SYMBOL(drm_property_unreference_blob);
>
> -/**
> - * drm_property_destroy_user_blobs - destroy all blobs created by this client
> - * @dev:       DRM device
> - * @file_priv: destroy all blobs owned by this file handle
> - */
>   void drm_property_destroy_user_blobs(struct drm_device *dev,
>   				     struct drm_file *file_priv)
>   {
> @@ -612,10 +618,10 @@ void drm_property_destroy_user_blobs(struct drm_device *dev,
>
>   /**
>    * drm_property_reference_blob - Take a reference on an existing property
> - *
> - * Take a new reference on an existing blob property.
> - *
>    * @blob: Pointer to blob property
> + *
> + * Take a new reference on an existing blob property. Returns @blob, which
> + * allows this to be used as a shorthand in assignments.
>    */
>   struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
>   {
> @@ -632,6 +638,9 @@ EXPORT_SYMBOL(drm_property_reference_blob);
>    * If successful, this takes an additional reference to the blob property.
>    * callers need to make sure to eventually unreference the returned property
>    * again, using @drm_property_unreference_blob.
> + *
> + * Return:
> + * NULL on failure, pointer to the blob on success.
>    */
>   struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
>   					           uint32_t id)
> @@ -647,7 +656,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
>   EXPORT_SYMBOL(drm_property_lookup_blob);
>
>   /**
> - * drm_property_replace_global_blob - atomically replace existing blob property
> + * drm_property_replace_global_blob - replace existing blob property
>    * @dev: drm device
>    * @replace: location of blob property pointer to be replaced
>    * @length: length of data for new blob, or 0 for no data
> @@ -656,11 +665,8 @@ EXPORT_SYMBOL(drm_property_lookup_blob);
>    * @prop_holds_id: optional property holding blob ID
>    * @return 0 on success or error on failure
>    *
> - * This function will atomically replace a global property in the blob list,
> - * optionally updating a property which holds the ID of that property. It is
> - * guaranteed to be atomic: no caller will be allowed to see intermediate
> - * results, and either the entire operation will succeed and clean up the
> - * previous property, or it will fail and the state will be unchanged.
> + * This function will replace a global property in the blob list, optionally
> + * updating a property which holds the ID of that property.
>    *
>    * If length is 0 or data is NULL, no new blob will be created, and the holding
>    * property, if specified, will be set to 0.
> @@ -697,11 +703,6 @@ int drm_property_replace_global_blob(struct drm_device *dev,
>   			return PTR_ERR(new_blob);
>   	}
>
> -	/* This does not need to be synchronised with blob_lock, as the
> -	 * get_properties ioctl locks all modesetting objects, and
> -	 * obj_holds_id must be locked before calling here, so we cannot
> -	 * have its value out of sync with the list membership modified
> -	 * below under blob_lock. */
>   	if (obj_holds_id) {
>   		ret = drm_object_property_set_value(obj_holds_id,
>   						    prop_holds_id,
> @@ -722,20 +723,6 @@ err_created:
>   }
>   EXPORT_SYMBOL(drm_property_replace_global_blob);
>
> -/**
> - * drm_mode_getblob_ioctl - get the contents of a blob property value
> - * @dev: DRM device
> - * @data: ioctl data
> - * @file_priv: DRM file info
> - *
> - * This function retrieves the contents of a blob property. The value stored in
> - * an object's blob property is just a normal modeset object id.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>   int drm_mode_getblob_ioctl(struct drm_device *dev,
>   			   void *data, struct drm_file *file_priv)
>   {
> @@ -765,21 +752,6 @@ unref:
>   	return ret;
>   }
>
> -/**
> - * drm_mode_createblob_ioctl - create a new blob property
> - * @dev: DRM device
> - * @data: ioctl data
> - * @file_priv: DRM file info
> - *
> - * This function creates a new blob property with user-defined values. In order
> - * to give us sensible validation and checking when creating, rather than at
> - * every potential use, we also require a type to be provided upfront.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>   int drm_mode_createblob_ioctl(struct drm_device *dev,
>   			      void *data, struct drm_file *file_priv)
>   {
> @@ -816,19 +788,6 @@ out_blob:
>   	return ret;
>   }
>
> -/**
> - * drm_mode_destroyblob_ioctl - destroy a user blob property
> - * @dev: DRM device
> - * @data: ioctl data
> - * @file_priv: DRM file info
> - *
> - * Destroy an existing user-defined blob property.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>   int drm_mode_destroyblob_ioctl(struct drm_device *dev,
>   			       void *data, struct drm_file *file_priv)
>   {
> @@ -885,7 +844,7 @@ err:
>    * reference).
>    */
>   bool drm_property_change_valid_get(struct drm_property *property,
> -					 uint64_t value, struct drm_mode_object **ref)
> +				   uint64_t value, struct drm_mode_object **ref)
>   {
>   	int i;
>
> diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
> index ac40069358c7..30ab289be05d 100644
> --- a/include/drm/drm_property.h
> +++ b/include/drm/drm_property.h
> @@ -27,33 +27,192 @@
>   #include <linux/ctype.h>
>   #include <drm/drm_mode_object.h>
>
> -struct drm_property_blob {
> -	struct drm_mode_object base;
> -	struct drm_device *dev;
> -	struct list_head head_global;
> -	struct list_head head_file;
> -	size_t length;
> -	unsigned char data[];
> -};
> -
> +/**
> + * struct drm_property_enum - symbolic values for enumerations
> + * @value: numeric property value for this enum entry
> + * @head: list of enum values, linked to enum_list in &drm_property
> + * @name: symbolic name for the enum
> + *
> + * For enumeration and bitmask properties this structure stores the symbolic
> + * decoding for each value. This is used for example for the rotation property.
> + */
>   struct drm_property_enum {
>   	uint64_t value;
>   	struct list_head head;
>   	char name[DRM_PROP_NAME_LEN];
>   };
>
> +/**
> + * struct drm_property - modeset object property
> + *
> + * This structure represent a modeset object property. It combines both the name
> + * of the property with the set of permissible values. This means that when a
> + * driver wants to use a property with the same name on different objects, but
> + * with different value ranges, then it must create property for each one. An
> + * example would be rotation of &drm_plane, when e.g. the primary plane cannot
> + * be rotated. But if both the name and the value range match, then the same
> + * property structure can be instantiated multiple times for the same object.
> + * Userspace must be able to cope with this and cannot assume that the same
> + * symbolic property will have the same modeset object ID on all modeset
> + * objects.
> + *
> + * Properties are created by one of the special functions, as explained in
> + * detail in the @flags structure member.
> + *
> + * To actually expose a property it must be attached to each object using
> + * drm_object_attach_property(). Currently properties can only be attached to
> + * &drm_connector, &drm_crtc and &drm_plane.
> + *
> + * Properties are also used as the generic metadatatransport for the atomic
> + * IOCTL. Everything that was set directly in structures in the legacy modeset
> + * IOCTLs (like the plane source or destination windows, or e.g. the links to
> + * the CRTC) is exposed as a property with the DRM_MODE_PROP_ATOMIC flag set.
> + */
>   struct drm_property {
> +	/**
> +	 * @head: per-device list of properties, for cleanup.
> +	 */
>   	struct list_head head;
> +
> +	/**
> +	 * @base: base KMS object
> +	 */
>   	struct drm_mode_object base;
> +
> +	/**
> +	 * @flags:
> +	 *
> +	 * Property flags and type. A property needs to be one of the following
> +	 * types:
> +	 *
> +	 * DRM_MODE_PROP_RANGE
> +	 *     Range properties report their minimum and maximum admissible unsigned values.
> +	 *     The KMS core verifies that values set by application fit in that
> +	 *     range. The range is unsigned. Range properties are created using
> +	 *     drm_property_create_range().
> +	 *
> +	 * DRM_MODE_PROP_SIGNED_RANGE
> +	 *     Range properties report their minimum and maximum admissible unsigned values.
> +	 *     The KMS core verifies that values set by application fit in that
> +	 *     range. The range is signed. Range properties are created using
> +	 *     drm_property_create_signed_range().
> +	 *
> +	 * DRM_MODE_PROP_ENUM
> +	 *     Enumerated properties take a numerical value that ranges from 0 to
> +	 *     the number of enumerated values defined by the property minus one,
> +	 *     and associate a free-formed string name to each value. Applications
> +	 *     can retrieve the list of defined value-name pairs and use the
> +	 *     numerical value to get and set property instance values. Enum
> +	 *     properties are created using drm_property_create_enum().
> +	 *
> +	 * DRM_MODE_PROP_BITMASK
> +	 *     Bitmask properties are enumeration properties that additionally
> +	 *     restrict all enumerated values to the 0..63 range. Bitmask property
> +	 *     instance values combine one or more of the enumerated bits defined
> +	 *     by the property. Bitmask properties are created using
> +	 *     drm_property_create_bitmask().
> +	 *
> +	 * DRM_MODE_PROB_OBJECT
> +	 *     Object properties are used to link modeset objects. This is used
> +	 *     extensively in the atomic support to create the display pipeline,
> +	 *     by linking &drm_framebuffer to &drm_plane, &drm_plane to
> +	 *     &drm_crtc and &drm_connector to &drm_crtc. An object property can
> +	 *     only link to a specific type of &drm_mode_object, this limit is
> +	 *     enforced by the core. Object properties are created using
> +	 *     drm_property_create_object().
> +	 *
> +	 *     Object properties work like blob properties, but in a more
> +	 *     general fashion. They are limited to atomic drivers and must have
> +	 *     the DRM_MODE_PROP_ATOMIC flag set.
> +	 *
> +	 * DRM_MODE_PROP_BLOB
> +	 *     Blob properties store a binary blob without any format restriction.
> +	 *     The binary blobs are created as KMS standalone objects, and blob
> +	 *     property instance values store the ID of their associated blob
> +	 *     object. Blob properties are created by calling
> +	 *     drm_property_create() with DRM_MODE_PROP_BLOB as the type.
> +	 *
> +	 *     Actual blob objects to contain blob data are created using
> +	 *     drm_property_create_blob(), or through the corresponding IOCTL.
> +	 *
> +	 *     Besides the built-in limit to only accept blob objects blob
> +	 *     properties work exactly like object properties. The only reasons
> +	 *     blob properties exist is backwards compatibility with existing
> +	 *     userspace.
> +	 *
> +	 * In addition a property can have any combination of the below flags:
> +	 *
> +	 * DRM_MODE_PROP_ATOMIC
> +	 *     Set for properties which encode atomic modeset state. Such
> +	 *     properties are not exposed to legacy userspace.
> +	 *
> +	 * DRM_MODE_PROP_IMMUTABLE
> +	 *     Set for properties where userspace cannot be changed by
> +	 *     userspace. The kernel is allowed to update the value of these
> +	 *     properties. This is generally used to expose probe state to
> +	 *     usersapce, e.g. the EDID, or the connector path property on DP
> +	 *     MST sinks.
> +	 */
>   	uint32_t flags;
> +
> +	/**
> +	 * @name: symbolic name of the properties
> +	 */
>   	char name[DRM_PROP_NAME_LEN];
> +
> +	/**
> +	 * @num_values: size of the @values array.
> +	 */
>   	uint32_t num_values;
> +
> +	/**
> +	 * @values:
> +	 *
> +	 * Array with limits and values for the property. The
> +	 * interpretation of these limits is dependent upon the type per @flags.
> +	 */
>   	uint64_t *values;
> +
> +	/**
> +	 * @dev: DRM device
> +	 */
>   	struct drm_device *dev;
>
> +	/**
> +	 * @enum_list:
> +	 *
> +	 * List of &drm_prop_enum_list structures with the symbolic names for
> +	 * enum and bitmask values.
> +	 */
>   	struct list_head enum_list;
>   };
>
> +/**
> + * struct drm_property_blob - Blob data for &drm_property
> + * @base: base KMS object
> + * @dev: DRM device
> + * @head_global: entry on the global blob list in &drm_mode_config
> + *	property_blob_list.
> + * @head_file: entry on the per-file blob list in &drm_file blobs list.
> + * @length: size of the blob in bytes, invariant over the lifetime of the object
> + * @data: actual data, embedded at the end of this structure
> + *
> + * Blobs are used to store bigger values than what fits directly into the 64
> + * bits available for a &drm_property.
> + *
> + * Blobs are reference counted using drm_property_reference_blob() and
> + * drm_property_unreference_blob(). They are created using
> + * drm_property_create_blob().
> + */
> +struct drm_property_blob {
> +	struct drm_mode_object base;
> +	struct drm_device *dev;
> +	struct list_head head_global;
> +	struct list_head head_file;
> +	size_t length;
> +	unsigned char data[];
> +};
> +
>   struct drm_prop_enum_list {
>   	int type;
>   	char *name;
> @@ -61,8 +220,16 @@ struct drm_prop_enum_list {
>
>   #define obj_to_property(x) container_of(x, struct drm_property, base)
>
> +/**
> + * drm_property_type_is - check the type of a property
> + * @property: property to check
> + * @type: property type to compare with
> + *
> + * This is a helper function becauase the uapi encoding of property types is
> + * a bit special for historical reasons.
> + */
>   static inline bool drm_property_type_is(struct drm_property *property,
> -		uint32_t type)
> +					uint32_t type)
>   {
>   	/* instanceof for props.. handles extended type vs original types: */
>   	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> @@ -109,8 +276,15 @@ int drm_property_replace_global_blob(struct drm_device *dev,
>   struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
>   void drm_property_unreference_blob(struct drm_property_blob *blob);
>
> +/**
> + * drm_connector_find - find property object
> + * @dev: DRM device
> + * @id: property object id
> + *
> + * This function looks up the property object specified by id and returns it.
> + */
>   static inline struct drm_property *drm_property_find(struct drm_device *dev,
> -		uint32_t id)
> +						     uint32_t id)
>   {
>   	struct drm_mode_object *mo;
>   	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob
  2016-08-29 13:14   ` Archit Taneja
@ 2016-08-29 14:04     ` Daniel Vetter
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-08-29 14:04 UTC (permalink / raw)
  To: Archit Taneja; +Cc: Daniel Vetter, DRI Development, Daniel Vetter

On Mon, Aug 29, 2016 at 06:44:46PM +0530, Archit Taneja wrote:
> 
> 
> On 08/29/2016 01:57 PM, Daniel Vetter wrote:
> > - remove kerneldoc for drm-internal functions
> > - drm_property_replace_global_blob isn't actually atomic, and doesn't
> >    need to be. Update docs&comments to match
> > - document all the types and try to link things a bit better
> > - nits all over
> > 
> 
> Reviewed-by: Archit Taneja <architt@codeaurora.org>

All applied to drm-misc, thanks for your review.
-Daniel

> 
> > v2: Appease checkpatch in the moved code (Archit)
> > 
> > Reviewed-by: Archit Taneja <architt@codeaurora.org>
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > ---
> >   Documentation/gpu/drm-kms.rst  |  88 +-----------------
> >   drivers/gpu/drm/drm_property.c | 153 ++++++++++++--------------------
> >   include/drm/drm_property.h     | 196 ++++++++++++++++++++++++++++++++++++++---
> >   3 files changed, 244 insertions(+), 193 deletions(-)
> > 
> > diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> > index e07a2667ab61..f9a991bb87d4 100644
> > --- a/Documentation/gpu/drm-kms.rst
> > +++ b/Documentation/gpu/drm-kms.rst
> > @@ -304,94 +304,12 @@ KMS Locking
> >   KMS Properties
> >   ==============
> > 
> > -Drivers may need to expose additional parameters to applications than
> > -those described in the previous sections. KMS supports attaching
> > -properties to CRTCs, connectors and planes and offers a userspace API to
> > -list, get and set the property values.
> > -
> > -Properties are identified by a name that uniquely defines the property
> > -purpose, and store an associated value. For all property types except
> > -blob properties the value is a 64-bit unsigned integer.
> > -
> > -KMS differentiates between properties and property instances. Drivers
> > -first create properties and then create and associate individual
> > -instances of those properties to objects. A property can be instantiated
> > -multiple times and associated with different objects. Values are stored
> > -in property instances, and all other property information are stored in
> > -the property and shared between all instances of the property.
> > -
> > -Every property is created with a type that influences how the KMS core
> > -handles the property. Supported property types are
> > -
> > -DRM_MODE_PROP_RANGE
> > -    Range properties report their minimum and maximum admissible values.
> > -    The KMS core verifies that values set by application fit in that
> > -    range.
> > -
> > -DRM_MODE_PROP_ENUM
> > -    Enumerated properties take a numerical value that ranges from 0 to
> > -    the number of enumerated values defined by the property minus one,
> > -    and associate a free-formed string name to each value. Applications
> > -    can retrieve the list of defined value-name pairs and use the
> > -    numerical value to get and set property instance values.
> > -
> > -DRM_MODE_PROP_BITMASK
> > -    Bitmask properties are enumeration properties that additionally
> > -    restrict all enumerated values to the 0..63 range. Bitmask property
> > -    instance values combine one or more of the enumerated bits defined
> > -    by the property.
> > -
> > -DRM_MODE_PROP_BLOB
> > -    Blob properties store a binary blob without any format restriction.
> > -    The binary blobs are created as KMS standalone objects, and blob
> > -    property instance values store the ID of their associated blob
> > -    object.
> > -
> > -    Blob properties are only used for the connector EDID property and
> > -    cannot be created by drivers.
> > -
> > -To create a property drivers call one of the following functions
> > -depending on the property type. All property creation functions take
> > -property flags and name, as well as type-specific arguments.
> > -
> > --  struct drm_property \*drm_property_create_range(struct
> > -   drm_device \*dev, int flags, const char \*name, uint64_t min,
> > -   uint64_t max);
> > -   Create a range property with the given minimum and maximum values.
> > -
> > --  struct drm_property \*drm_property_create_enum(struct drm_device
> > -   \*dev, int flags, const char \*name, const struct
> > -   drm_prop_enum_list \*props, int num_values);
> > -   Create an enumerated property. The ``props`` argument points to an
> > -   array of ``num_values`` value-name pairs.
> > -
> > --  struct drm_property \*drm_property_create_bitmask(struct
> > -   drm_device \*dev, int flags, const char \*name, const struct
> > -   drm_prop_enum_list \*props, int num_values);
> > -   Create a bitmask property. The ``props`` argument points to an array
> > -   of ``num_values`` value-name pairs.
> > -
> > -Properties can additionally be created as immutable, in which case they
> > -will be read-only for applications but can be modified by the driver. To
> > -create an immutable property drivers must set the
> > -DRM_MODE_PROP_IMMUTABLE flag at property creation time.
> > -
> > -When no array of value-name pairs is readily available at property
> > -creation time for enumerated or range properties, drivers can create the
> > -property using the :c:func:`drm_property_create()` function and
> > -manually add enumeration value-name pairs by calling the
> > -:c:func:`drm_property_add_enum()` function. Care must be taken to
> > -properly specify the property type through the ``flags`` argument.
> > -
> > -After creating properties drivers can attach property instances to CRTC,
> > -connector and plane objects by calling the
> > -:c:func:`drm_object_attach_property()`. The function takes a
> > -pointer to the target object, a pointer to the previously created
> > -property and an initial instance value.
> > -
> >   Property Types and Blob Property Support
> >   ----------------------------------------
> > 
> > +.. kernel-doc:: drivers/gpu/drm/drm_property.c
> > +   :doc: overview
> > +
> >   .. kernel-doc:: include/drm/drm_property.h
> >      :internal:
> > 
> > diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
> > index b5521f705b1c..4139afbcc267 100644
> > --- a/drivers/gpu/drm/drm_property.c
> > +++ b/drivers/gpu/drm/drm_property.c
> > @@ -26,6 +26,30 @@
> > 
> >   #include "drm_crtc_internal.h"
> > 
> > +/**
> > + * DOC: overview
> > + *
> > + * Properties as represented by &drm_property are used to extend the modeset
> > + * interface exposed to userspace. For the atomic modeset IOCTL properties are
> > + * even the only way to transport metadata about the desired new modeset
> > + * configuration from userspace to the kernel. Properties have a well-defined
> > + * value range, which is enforced by the drm core. See the documentation of the
> > + * flags member of struct &drm_property for an overview of the different
> > + * property types and ranges.
> > + *
> > + * Properties don't store the current value directly, but need to be
> > + * instatiated by attaching them to a &drm_mode_object with
> > + * drm_object_attach_property().
> > + *
> > + * Property values are only 64bit. To support bigger piles of data (like gamma
> > + * tables, color correction matrizes or large structures) a property can instead
> > + * point at a &drm_property_blob with that additional data
> > + *
> > + * Properties are defined by their symbolic name, userspace must keep a
> > + * per-object mapping from those names to the property ID used in the atomic
> > + * IOCTL and in the get/set property IOCTL.
> > + */
> > +
> >   static bool drm_property_type_valid(struct drm_property *property)
> >   {
> >   	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> > @@ -42,11 +66,8 @@ static bool drm_property_type_valid(struct drm_property *property)
> >    *
> >    * This creates a new generic drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > - *
> > - * Note that the DRM core keeps a per-device list of properties and that, if
> > - * drm_mode_config_cleanup() is called, it will destroy all properties created
> > - * by the driver.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * Returns:
> >    * A pointer to the newly created property on success, NULL on failure.
> > @@ -105,7 +126,8 @@ EXPORT_SYMBOL(drm_property_create);
> >    *
> >    * This creates a new generic drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * Userspace is only allowed to set one of the predefined values for enumeration
> >    * properties.
> > @@ -152,7 +174,8 @@ EXPORT_SYMBOL(drm_property_create_enum);
> >    *
> >    * This creates a new bitmask drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * Compared to plain enumeration properties userspace is allowed to set any
> >    * or'ed together combination of the predefined property bitflag values
> > @@ -223,7 +246,8 @@ static struct drm_property *property_create_range(struct drm_device *dev,
> >    *
> >    * This creates a new generic drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * Userspace is allowed to set any unsigned integer value in the (min, max)
> >    * range inclusive.
> > @@ -250,7 +274,8 @@ EXPORT_SYMBOL(drm_property_create_range);
> >    *
> >    * This creates a new generic drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * Userspace is allowed to set any signed integer value in the (min, max)
> >    * range inclusive.
> > @@ -276,7 +301,8 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
> >    *
> >    * This creates a new generic drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * Userspace is only allowed to set this to any property value of the given
> >    * @type. Only useful for atomic properties, which is enforced.
> > @@ -285,7 +311,8 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
> >    * A pointer to the newly created property on success, NULL on failure.
> >    */
> >   struct drm_property *drm_property_create_object(struct drm_device *dev,
> > -					 int flags, const char *name, uint32_t type)
> > +						int flags, const char *name,
> > +						uint32_t type)
> >   {
> >   	struct drm_property *property;
> > 
> > @@ -312,7 +339,8 @@ EXPORT_SYMBOL(drm_property_create_object);
> >    *
> >    * This creates a new generic drm property which can then be attached to a drm
> >    * object with drm_object_attach_property. The returned property object must be
> > - * freed with drm_property_destroy.
> > + * freed with drm_property_destroy(), which is done automatically when calling
> > + * drm_mode_config_cleanup().
> >    *
> >    * This is implemented as a ranged property with only {0, 1} as valid values.
> >    *
> > @@ -320,7 +348,7 @@ EXPORT_SYMBOL(drm_property_create_object);
> >    * A pointer to the newly created property on success, NULL on failure.
> >    */
> >   struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
> > -					 const char *name)
> > +					      const char *name)
> >   {
> >   	return drm_property_create_range(dev, flags, name, 0, 1);
> >   }
> > @@ -407,22 +435,6 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
> >   }
> >   EXPORT_SYMBOL(drm_property_destroy);
> > 
> > -/**
> > - * drm_mode_getproperty_ioctl - get the property metadata
> > - * @dev: DRM device
> > - * @data: ioctl data
> > - * @file_priv: DRM file info
> > - *
> > - * This function retrieves the metadata for a given property, like the different
> > - * possible values for an enum property or the limits for a range property.
> > - *
> > - * Blob properties are special
> > - *
> > - * Called by the user via ioctl.
> > - *
> > - * Returns:
> > - * Zero on success, negative errno on failure.
> > - */
> >   int drm_mode_getproperty_ioctl(struct drm_device *dev,
> >   			       void *data, struct drm_file *file_priv)
> >   {
> > @@ -523,14 +535,14 @@ static void drm_property_free_blob(struct kref *kref)
> > 
> >   /**
> >    * drm_property_create_blob - Create new blob property
> > - *
> > - * Creates a new blob property for a specified DRM device, optionally
> > - * copying data.
> > - *
> >    * @dev: DRM device to create property for
> >    * @length: Length to allocate for blob data
> >    * @data: If specified, copies data into blob
> >    *
> > + * Creates a new blob property for a specified DRM device, optionally
> > + * copying data. Note that blob properties are meant to be invariant, hence the
> > + * data must be filled out before the blob is used as the value of any property.
> > + *
> >    * Returns:
> >    * New blob property with a single reference on success, or an ERR_PTR
> >    * value on failure.
> > @@ -576,10 +588,9 @@ EXPORT_SYMBOL(drm_property_create_blob);
> > 
> >   /**
> >    * drm_property_unreference_blob - Unreference a blob property
> > + * @blob: Pointer to blob property
> >    *
> >    * Drop a reference on a blob property. May free the object.
> > - *
> > - * @blob: Pointer to blob property
> >    */
> >   void drm_property_unreference_blob(struct drm_property_blob *blob)
> >   {
> > @@ -590,11 +601,6 @@ void drm_property_unreference_blob(struct drm_property_blob *blob)
> >   }
> >   EXPORT_SYMBOL(drm_property_unreference_blob);
> > 
> > -/**
> > - * drm_property_destroy_user_blobs - destroy all blobs created by this client
> > - * @dev:       DRM device
> > - * @file_priv: destroy all blobs owned by this file handle
> > - */
> >   void drm_property_destroy_user_blobs(struct drm_device *dev,
> >   				     struct drm_file *file_priv)
> >   {
> > @@ -612,10 +618,10 @@ void drm_property_destroy_user_blobs(struct drm_device *dev,
> > 
> >   /**
> >    * drm_property_reference_blob - Take a reference on an existing property
> > - *
> > - * Take a new reference on an existing blob property.
> > - *
> >    * @blob: Pointer to blob property
> > + *
> > + * Take a new reference on an existing blob property. Returns @blob, which
> > + * allows this to be used as a shorthand in assignments.
> >    */
> >   struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
> >   {
> > @@ -632,6 +638,9 @@ EXPORT_SYMBOL(drm_property_reference_blob);
> >    * If successful, this takes an additional reference to the blob property.
> >    * callers need to make sure to eventually unreference the returned property
> >    * again, using @drm_property_unreference_blob.
> > + *
> > + * Return:
> > + * NULL on failure, pointer to the blob on success.
> >    */
> >   struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
> >   					           uint32_t id)
> > @@ -647,7 +656,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
> >   EXPORT_SYMBOL(drm_property_lookup_blob);
> > 
> >   /**
> > - * drm_property_replace_global_blob - atomically replace existing blob property
> > + * drm_property_replace_global_blob - replace existing blob property
> >    * @dev: drm device
> >    * @replace: location of blob property pointer to be replaced
> >    * @length: length of data for new blob, or 0 for no data
> > @@ -656,11 +665,8 @@ EXPORT_SYMBOL(drm_property_lookup_blob);
> >    * @prop_holds_id: optional property holding blob ID
> >    * @return 0 on success or error on failure
> >    *
> > - * This function will atomically replace a global property in the blob list,
> > - * optionally updating a property which holds the ID of that property. It is
> > - * guaranteed to be atomic: no caller will be allowed to see intermediate
> > - * results, and either the entire operation will succeed and clean up the
> > - * previous property, or it will fail and the state will be unchanged.
> > + * This function will replace a global property in the blob list, optionally
> > + * updating a property which holds the ID of that property.
> >    *
> >    * If length is 0 or data is NULL, no new blob will be created, and the holding
> >    * property, if specified, will be set to 0.
> > @@ -697,11 +703,6 @@ int drm_property_replace_global_blob(struct drm_device *dev,
> >   			return PTR_ERR(new_blob);
> >   	}
> > 
> > -	/* This does not need to be synchronised with blob_lock, as the
> > -	 * get_properties ioctl locks all modesetting objects, and
> > -	 * obj_holds_id must be locked before calling here, so we cannot
> > -	 * have its value out of sync with the list membership modified
> > -	 * below under blob_lock. */
> >   	if (obj_holds_id) {
> >   		ret = drm_object_property_set_value(obj_holds_id,
> >   						    prop_holds_id,
> > @@ -722,20 +723,6 @@ err_created:
> >   }
> >   EXPORT_SYMBOL(drm_property_replace_global_blob);
> > 
> > -/**
> > - * drm_mode_getblob_ioctl - get the contents of a blob property value
> > - * @dev: DRM device
> > - * @data: ioctl data
> > - * @file_priv: DRM file info
> > - *
> > - * This function retrieves the contents of a blob property. The value stored in
> > - * an object's blob property is just a normal modeset object id.
> > - *
> > - * Called by the user via ioctl.
> > - *
> > - * Returns:
> > - * Zero on success, negative errno on failure.
> > - */
> >   int drm_mode_getblob_ioctl(struct drm_device *dev,
> >   			   void *data, struct drm_file *file_priv)
> >   {
> > @@ -765,21 +752,6 @@ unref:
> >   	return ret;
> >   }
> > 
> > -/**
> > - * drm_mode_createblob_ioctl - create a new blob property
> > - * @dev: DRM device
> > - * @data: ioctl data
> > - * @file_priv: DRM file info
> > - *
> > - * This function creates a new blob property with user-defined values. In order
> > - * to give us sensible validation and checking when creating, rather than at
> > - * every potential use, we also require a type to be provided upfront.
> > - *
> > - * Called by the user via ioctl.
> > - *
> > - * Returns:
> > - * Zero on success, negative errno on failure.
> > - */
> >   int drm_mode_createblob_ioctl(struct drm_device *dev,
> >   			      void *data, struct drm_file *file_priv)
> >   {
> > @@ -816,19 +788,6 @@ out_blob:
> >   	return ret;
> >   }
> > 
> > -/**
> > - * drm_mode_destroyblob_ioctl - destroy a user blob property
> > - * @dev: DRM device
> > - * @data: ioctl data
> > - * @file_priv: DRM file info
> > - *
> > - * Destroy an existing user-defined blob property.
> > - *
> > - * Called by the user via ioctl.
> > - *
> > - * Returns:
> > - * Zero on success, negative errno on failure.
> > - */
> >   int drm_mode_destroyblob_ioctl(struct drm_device *dev,
> >   			       void *data, struct drm_file *file_priv)
> >   {
> > @@ -885,7 +844,7 @@ err:
> >    * reference).
> >    */
> >   bool drm_property_change_valid_get(struct drm_property *property,
> > -					 uint64_t value, struct drm_mode_object **ref)
> > +				   uint64_t value, struct drm_mode_object **ref)
> >   {
> >   	int i;
> > 
> > diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
> > index ac40069358c7..30ab289be05d 100644
> > --- a/include/drm/drm_property.h
> > +++ b/include/drm/drm_property.h
> > @@ -27,33 +27,192 @@
> >   #include <linux/ctype.h>
> >   #include <drm/drm_mode_object.h>
> > 
> > -struct drm_property_blob {
> > -	struct drm_mode_object base;
> > -	struct drm_device *dev;
> > -	struct list_head head_global;
> > -	struct list_head head_file;
> > -	size_t length;
> > -	unsigned char data[];
> > -};
> > -
> > +/**
> > + * struct drm_property_enum - symbolic values for enumerations
> > + * @value: numeric property value for this enum entry
> > + * @head: list of enum values, linked to enum_list in &drm_property
> > + * @name: symbolic name for the enum
> > + *
> > + * For enumeration and bitmask properties this structure stores the symbolic
> > + * decoding for each value. This is used for example for the rotation property.
> > + */
> >   struct drm_property_enum {
> >   	uint64_t value;
> >   	struct list_head head;
> >   	char name[DRM_PROP_NAME_LEN];
> >   };
> > 
> > +/**
> > + * struct drm_property - modeset object property
> > + *
> > + * This structure represent a modeset object property. It combines both the name
> > + * of the property with the set of permissible values. This means that when a
> > + * driver wants to use a property with the same name on different objects, but
> > + * with different value ranges, then it must create property for each one. An
> > + * example would be rotation of &drm_plane, when e.g. the primary plane cannot
> > + * be rotated. But if both the name and the value range match, then the same
> > + * property structure can be instantiated multiple times for the same object.
> > + * Userspace must be able to cope with this and cannot assume that the same
> > + * symbolic property will have the same modeset object ID on all modeset
> > + * objects.
> > + *
> > + * Properties are created by one of the special functions, as explained in
> > + * detail in the @flags structure member.
> > + *
> > + * To actually expose a property it must be attached to each object using
> > + * drm_object_attach_property(). Currently properties can only be attached to
> > + * &drm_connector, &drm_crtc and &drm_plane.
> > + *
> > + * Properties are also used as the generic metadatatransport for the atomic
> > + * IOCTL. Everything that was set directly in structures in the legacy modeset
> > + * IOCTLs (like the plane source or destination windows, or e.g. the links to
> > + * the CRTC) is exposed as a property with the DRM_MODE_PROP_ATOMIC flag set.
> > + */
> >   struct drm_property {
> > +	/**
> > +	 * @head: per-device list of properties, for cleanup.
> > +	 */
> >   	struct list_head head;
> > +
> > +	/**
> > +	 * @base: base KMS object
> > +	 */
> >   	struct drm_mode_object base;
> > +
> > +	/**
> > +	 * @flags:
> > +	 *
> > +	 * Property flags and type. A property needs to be one of the following
> > +	 * types:
> > +	 *
> > +	 * DRM_MODE_PROP_RANGE
> > +	 *     Range properties report their minimum and maximum admissible unsigned values.
> > +	 *     The KMS core verifies that values set by application fit in that
> > +	 *     range. The range is unsigned. Range properties are created using
> > +	 *     drm_property_create_range().
> > +	 *
> > +	 * DRM_MODE_PROP_SIGNED_RANGE
> > +	 *     Range properties report their minimum and maximum admissible unsigned values.
> > +	 *     The KMS core verifies that values set by application fit in that
> > +	 *     range. The range is signed. Range properties are created using
> > +	 *     drm_property_create_signed_range().
> > +	 *
> > +	 * DRM_MODE_PROP_ENUM
> > +	 *     Enumerated properties take a numerical value that ranges from 0 to
> > +	 *     the number of enumerated values defined by the property minus one,
> > +	 *     and associate a free-formed string name to each value. Applications
> > +	 *     can retrieve the list of defined value-name pairs and use the
> > +	 *     numerical value to get and set property instance values. Enum
> > +	 *     properties are created using drm_property_create_enum().
> > +	 *
> > +	 * DRM_MODE_PROP_BITMASK
> > +	 *     Bitmask properties are enumeration properties that additionally
> > +	 *     restrict all enumerated values to the 0..63 range. Bitmask property
> > +	 *     instance values combine one or more of the enumerated bits defined
> > +	 *     by the property. Bitmask properties are created using
> > +	 *     drm_property_create_bitmask().
> > +	 *
> > +	 * DRM_MODE_PROB_OBJECT
> > +	 *     Object properties are used to link modeset objects. This is used
> > +	 *     extensively in the atomic support to create the display pipeline,
> > +	 *     by linking &drm_framebuffer to &drm_plane, &drm_plane to
> > +	 *     &drm_crtc and &drm_connector to &drm_crtc. An object property can
> > +	 *     only link to a specific type of &drm_mode_object, this limit is
> > +	 *     enforced by the core. Object properties are created using
> > +	 *     drm_property_create_object().
> > +	 *
> > +	 *     Object properties work like blob properties, but in a more
> > +	 *     general fashion. They are limited to atomic drivers and must have
> > +	 *     the DRM_MODE_PROP_ATOMIC flag set.
> > +	 *
> > +	 * DRM_MODE_PROP_BLOB
> > +	 *     Blob properties store a binary blob without any format restriction.
> > +	 *     The binary blobs are created as KMS standalone objects, and blob
> > +	 *     property instance values store the ID of their associated blob
> > +	 *     object. Blob properties are created by calling
> > +	 *     drm_property_create() with DRM_MODE_PROP_BLOB as the type.
> > +	 *
> > +	 *     Actual blob objects to contain blob data are created using
> > +	 *     drm_property_create_blob(), or through the corresponding IOCTL.
> > +	 *
> > +	 *     Besides the built-in limit to only accept blob objects blob
> > +	 *     properties work exactly like object properties. The only reasons
> > +	 *     blob properties exist is backwards compatibility with existing
> > +	 *     userspace.
> > +	 *
> > +	 * In addition a property can have any combination of the below flags:
> > +	 *
> > +	 * DRM_MODE_PROP_ATOMIC
> > +	 *     Set for properties which encode atomic modeset state. Such
> > +	 *     properties are not exposed to legacy userspace.
> > +	 *
> > +	 * DRM_MODE_PROP_IMMUTABLE
> > +	 *     Set for properties where userspace cannot be changed by
> > +	 *     userspace. The kernel is allowed to update the value of these
> > +	 *     properties. This is generally used to expose probe state to
> > +	 *     usersapce, e.g. the EDID, or the connector path property on DP
> > +	 *     MST sinks.
> > +	 */
> >   	uint32_t flags;
> > +
> > +	/**
> > +	 * @name: symbolic name of the properties
> > +	 */
> >   	char name[DRM_PROP_NAME_LEN];
> > +
> > +	/**
> > +	 * @num_values: size of the @values array.
> > +	 */
> >   	uint32_t num_values;
> > +
> > +	/**
> > +	 * @values:
> > +	 *
> > +	 * Array with limits and values for the property. The
> > +	 * interpretation of these limits is dependent upon the type per @flags.
> > +	 */
> >   	uint64_t *values;
> > +
> > +	/**
> > +	 * @dev: DRM device
> > +	 */
> >   	struct drm_device *dev;
> > 
> > +	/**
> > +	 * @enum_list:
> > +	 *
> > +	 * List of &drm_prop_enum_list structures with the symbolic names for
> > +	 * enum and bitmask values.
> > +	 */
> >   	struct list_head enum_list;
> >   };
> > 
> > +/**
> > + * struct drm_property_blob - Blob data for &drm_property
> > + * @base: base KMS object
> > + * @dev: DRM device
> > + * @head_global: entry on the global blob list in &drm_mode_config
> > + *	property_blob_list.
> > + * @head_file: entry on the per-file blob list in &drm_file blobs list.
> > + * @length: size of the blob in bytes, invariant over the lifetime of the object
> > + * @data: actual data, embedded at the end of this structure
> > + *
> > + * Blobs are used to store bigger values than what fits directly into the 64
> > + * bits available for a &drm_property.
> > + *
> > + * Blobs are reference counted using drm_property_reference_blob() and
> > + * drm_property_unreference_blob(). They are created using
> > + * drm_property_create_blob().
> > + */
> > +struct drm_property_blob {
> > +	struct drm_mode_object base;
> > +	struct drm_device *dev;
> > +	struct list_head head_global;
> > +	struct list_head head_file;
> > +	size_t length;
> > +	unsigned char data[];
> > +};
> > +
> >   struct drm_prop_enum_list {
> >   	int type;
> >   	char *name;
> > @@ -61,8 +220,16 @@ struct drm_prop_enum_list {
> > 
> >   #define obj_to_property(x) container_of(x, struct drm_property, base)
> > 
> > +/**
> > + * drm_property_type_is - check the type of a property
> > + * @property: property to check
> > + * @type: property type to compare with
> > + *
> > + * This is a helper function becauase the uapi encoding of property types is
> > + * a bit special for historical reasons.
> > + */
> >   static inline bool drm_property_type_is(struct drm_property *property,
> > -		uint32_t type)
> > +					uint32_t type)
> >   {
> >   	/* instanceof for props.. handles extended type vs original types: */
> >   	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> > @@ -109,8 +276,15 @@ int drm_property_replace_global_blob(struct drm_device *dev,
> >   struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
> >   void drm_property_unreference_blob(struct drm_property_blob *blob);
> > 
> > +/**
> > + * drm_connector_find - find property object
> > + * @dev: DRM device
> > + * @id: property object id
> > + *
> > + * This function looks up the property object specified by id and returns it.
> > + */
> >   static inline struct drm_property *drm_property_find(struct drm_device *dev,
> > -		uint32_t id)
> > +						     uint32_t id)
> >   {
> >   	struct drm_mode_object *mo;
> >   	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
> > 
> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 8/9] drm: Unify handling of blob and object properties
  2016-08-29  8:27 ` [PATCH 8/9] drm: Unify handling of blob and object properties Daniel Vetter
@ 2016-09-06  9:22   ` Ying Liu
  2016-09-07  9:52     ` [PATCH] Revert "drm: Unify handling of blob and object properties" Maarten Lankhorst
  0 siblings, 1 reply; 18+ messages in thread
From: Ying Liu @ 2016-09-06  9:22 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Stone, DRI Development

On Mon, Aug 29, 2016 at 4:27 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> They work exactly the same now, after the refcounting unification a bit
> ago. The only reason they're distinct is backwards compat with existing
> userspace.
>
> Cc: Daniel Stone <daniels@collabora.com>
> Reviewed-by: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/drm_property.c | 23 +++++------------------
>  1 file changed, 5 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
> index 162cc9032ae5..b5521f705b1c 100644
> --- a/drivers/gpu/drm/drm_property.c
> +++ b/drivers/gpu/drm/drm_property.c
> @@ -911,20 +911,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
>                 for (i = 0; i < property->num_values; i++)
>                         valid_mask |= (1ULL << property->values[i]);
>                 return !(value & ~valid_mask);
> -       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
> -               struct drm_property_blob *blob;
> -
> -               if (value == 0)
> -                       return true;
> -
> -               blob = drm_property_lookup_blob(property->dev, value);

It looks this patch would cause a NULL pointer dereference when we
run kms_atomic test.
Handing property->values[0] over to __drm_mode_object_find() for
blob property seems to be questionable.

Regards,
Liu Ying

> -               if (blob) {
> -                       *ref = &blob->base;
> -                       return true;
> -               } else {
> -                       return false;
> -               }
> -       } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB) ||
> +                  drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
>                 /* a zero value for an object property translates to null: */
>                 if (value == 0)
>                         return true;
> @@ -941,13 +929,12 @@ bool drm_property_change_valid_get(struct drm_property *property,
>  }
>
>  void drm_property_change_valid_put(struct drm_property *property,
> -               struct drm_mode_object *ref)
> +                                  struct drm_mode_object *ref)
>  {
>         if (!ref)
>                 return;
>
> -       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
> +       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT) ||
> +           drm_property_type_is(property, DRM_MODE_PROP_BLOB))
>                 drm_mode_object_unreference(ref);
> -       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
> -               drm_property_unreference_blob(obj_to_blob(ref));
>  }
> --
> 2.9.3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH] Revert "drm: Unify handling of blob and object properties"
  2016-09-06  9:22   ` Ying Liu
@ 2016-09-07  9:52     ` Maarten Lankhorst
  2016-09-07  9:56       ` Ying Liu
  0 siblings, 1 reply; 18+ messages in thread
From: Maarten Lankhorst @ 2016-09-07  9:52 UTC (permalink / raw)
  To: Ying Liu, Daniel Vetter; +Cc: Daniel Stone, DRI Development

This reverts commit 77953bd136d2a70bca2dc93b3ccda07a2b37076f.

This causes a kernel panic when trying to assign a blob to a property,
and has obviously never been tested.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/drm_property.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index 4139afbcc267..a4d81cf4ffa0 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -870,8 +870,20 @@ bool drm_property_change_valid_get(struct drm_property *property,
 		for (i = 0; i < property->num_values; i++)
 			valid_mask |= (1ULL << property->values[i]);
 		return !(value & ~valid_mask);
-	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB) ||
-		   drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
+		struct drm_property_blob *blob;
+
+		if (value == 0)
+			return true;
+
+		blob = drm_property_lookup_blob(property->dev, value);
+		if (blob) {
+			*ref = &blob->base;
+			return true;
+		} else {
+			return false;
+		}
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
 		/* a zero value for an object property translates to null: */
 		if (value == 0)
 			return true;
@@ -888,12 +900,13 @@ bool drm_property_change_valid_get(struct drm_property *property,
 }
 
 void drm_property_change_valid_put(struct drm_property *property,
-				   struct drm_mode_object *ref)
+		struct drm_mode_object *ref)
 {
 	if (!ref)
 		return;
 
-	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT) ||
-	    drm_property_type_is(property, DRM_MODE_PROP_BLOB))
+	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
 		drm_mode_object_unreference(ref);
+	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
+		drm_property_unreference_blob(obj_to_blob(ref));
 }
-- 
2.7.4


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] Revert "drm: Unify handling of blob and object properties"
  2016-09-07  9:52     ` [PATCH] Revert "drm: Unify handling of blob and object properties" Maarten Lankhorst
@ 2016-09-07  9:56       ` Ying Liu
  2016-09-07 11:25         ` Jani Nikula
  0 siblings, 1 reply; 18+ messages in thread
From: Ying Liu @ 2016-09-07  9:56 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: Daniel Vetter, Daniel Stone, DRI Development

On Wed, Sep 7, 2016 at 5:52 PM, Maarten Lankhorst
<maarten.lankhorst@linux.intel.com> wrote:
> This reverts commit 77953bd136d2a70bca2dc93b3ccda07a2b37076f.
>
> This causes a kernel panic when trying to assign a blob to a property,
> and has obviously never been tested.
>
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

Tested-by: Liu Ying <gnuiyl@gmail.com>

> ---
>  drivers/gpu/drm/drm_property.c | 23 ++++++++++++++++++-----
>  1 file changed, 18 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
> index 4139afbcc267..a4d81cf4ffa0 100644
> --- a/drivers/gpu/drm/drm_property.c
> +++ b/drivers/gpu/drm/drm_property.c
> @@ -870,8 +870,20 @@ bool drm_property_change_valid_get(struct drm_property *property,
>                 for (i = 0; i < property->num_values; i++)
>                         valid_mask |= (1ULL << property->values[i]);
>                 return !(value & ~valid_mask);
> -       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB) ||
> -                  drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
> +               struct drm_property_blob *blob;
> +
> +               if (value == 0)
> +                       return true;
> +
> +               blob = drm_property_lookup_blob(property->dev, value);
> +               if (blob) {
> +                       *ref = &blob->base;
> +                       return true;
> +               } else {
> +                       return false;
> +               }
> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
>                 /* a zero value for an object property translates to null: */
>                 if (value == 0)
>                         return true;
> @@ -888,12 +900,13 @@ bool drm_property_change_valid_get(struct drm_property *property,
>  }
>
>  void drm_property_change_valid_put(struct drm_property *property,
> -                                  struct drm_mode_object *ref)
> +               struct drm_mode_object *ref)
>  {
>         if (!ref)
>                 return;
>
> -       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT) ||
> -           drm_property_type_is(property, DRM_MODE_PROP_BLOB))
> +       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
>                 drm_mode_object_unreference(ref);
> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
> +               drm_property_unreference_blob(obj_to_blob(ref));
>  }
> --
> 2.7.4
>
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] Revert "drm: Unify handling of blob and object properties"
  2016-09-07  9:56       ` Ying Liu
@ 2016-09-07 11:25         ` Jani Nikula
  0 siblings, 0 replies; 18+ messages in thread
From: Jani Nikula @ 2016-09-07 11:25 UTC (permalink / raw)
  To: Ying Liu, Maarten Lankhorst; +Cc: Daniel Vetter, Daniel Stone, DRI Development

On Wed, 07 Sep 2016, Ying Liu <gnuiyl@gmail.com> wrote:
> On Wed, Sep 7, 2016 at 5:52 PM, Maarten Lankhorst
> <maarten.lankhorst@linux.intel.com> wrote:
>> This reverts commit 77953bd136d2a70bca2dc93b3ccda07a2b37076f.
>>
>> This causes a kernel panic when trying to assign a blob to a property,
>> and has obviously never been tested.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>
> Tested-by: Liu Ying <gnuiyl@gmail.com>

Pushed to drm-misc with Daniel's irc ack.

BR,
Jani.


>
>> ---
>>  drivers/gpu/drm/drm_property.c | 23 ++++++++++++++++++-----
>>  1 file changed, 18 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
>> index 4139afbcc267..a4d81cf4ffa0 100644
>> --- a/drivers/gpu/drm/drm_property.c
>> +++ b/drivers/gpu/drm/drm_property.c
>> @@ -870,8 +870,20 @@ bool drm_property_change_valid_get(struct drm_property *property,
>>                 for (i = 0; i < property->num_values; i++)
>>                         valid_mask |= (1ULL << property->values[i]);
>>                 return !(value & ~valid_mask);
>> -       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB) ||
>> -                  drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
>> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
>> +               struct drm_property_blob *blob;
>> +
>> +               if (value == 0)
>> +                       return true;
>> +
>> +               blob = drm_property_lookup_blob(property->dev, value);
>> +               if (blob) {
>> +                       *ref = &blob->base;
>> +                       return true;
>> +               } else {
>> +                       return false;
>> +               }
>> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
>>                 /* a zero value for an object property translates to null: */
>>                 if (value == 0)
>>                         return true;
>> @@ -888,12 +900,13 @@ bool drm_property_change_valid_get(struct drm_property *property,
>>  }
>>
>>  void drm_property_change_valid_put(struct drm_property *property,
>> -                                  struct drm_mode_object *ref)
>> +               struct drm_mode_object *ref)
>>  {
>>         if (!ref)
>>                 return;
>>
>> -       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT) ||
>> -           drm_property_type_is(property, DRM_MODE_PROP_BLOB))
>> +       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
>>                 drm_mode_object_unreference(ref);
>> +       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
>> +               drm_property_unreference_blob(obj_to_blob(ref));
>>  }
>> --
>> 2.7.4
>>
>>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [2/9] drm/doc: Polish kerneldoc for encoders
  2016-08-29  8:27 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
@ 2016-09-15  4:47   ` Pandiyan, Dhinakaran
  0 siblings, 0 replies; 18+ messages in thread
From: Pandiyan, Dhinakaran @ 2016-09-15  4:47 UTC (permalink / raw)
  To: daniel.vetter; +Cc: Vetter, Daniel, intel-gfx, dri-devel

I guess it's too late for review now. But, I want to send this anyway.

On Mon, 2016-08-29 at 10:27 +0200, Daniel Vetter wrote:
> - Move missing bits into struct drm_encoder docs.
> - Explain that encoders are 95% internal and only 5% uapi, and that in
>   general the uapi part is broken.
> - Remove verbose comments for functions not exposed to drivers.
> 
> v2: Review from Archit:
> - Appease checkpatch in the moved code.
> - Make it clearer that bridges are not exposed to userspace.
> 
> Reviewed-by: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  Documentation/gpu/drm-kms.rst | 46 ++++------------------------
>  drivers/gpu/drm/drm_encoder.c | 48 ++++++++++++++++++-----------
>  include/drm/drm_encoder.h     | 70 +++++++++++++++++++++++++++++++++++++++----
>  3 files changed, 101 insertions(+), 63 deletions(-)
> 
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 7f788caebea3..47c2835b7c2d 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -128,6 +128,12 @@ Connector Functions Reference
>  Encoder Abstraction
>  ===================
>  
> +.. kernel-doc:: drivers/gpu/drm/drm_encoder.c
> +   :doc: overview
> +
> +Encoder Functions Reference
> +---------------------------
> +
>  .. kernel-doc:: include/drm/drm_encoder.h
>     :internal:
>  
> @@ -207,46 +213,6 @@ future); drivers that do not wish to provide special handling for
>  primary planes may make use of the helper functions described in ? to
>  create and register a primary plane with standard capabilities.
>  
> -Encoders (:c:type:`struct drm_encoder <drm_encoder>`)
> ------------------------------------------------------
> -
> -An encoder takes pixel data from a CRTC and converts it to a format
> -suitable for any attached connectors. On some devices, it may be
> -possible to have a CRTC send data to more than one encoder. In that
> -case, both encoders would receive data from the same scanout buffer,
> -resulting in a "cloned" display configuration across the connectors
> -attached to each encoder.
> -
> -Encoder Initialization
> -~~~~~~~~~~~~~~~~~~~~~~
> -
> -As for CRTCs, a KMS driver must create, initialize and register at least
> -one :c:type:`struct drm_encoder <drm_encoder>` instance. The
> -instance is allocated and zeroed by the driver, possibly as part of a
> -larger structure.
> -
> -Drivers must initialize the :c:type:`struct drm_encoder
> -<drm_encoder>` possible_crtcs and possible_clones fields before
> -registering the encoder. Both fields are bitmasks of respectively the
> -CRTCs that the encoder can be connected to, and sibling encoders
> -candidate for cloning.
> -
> -After being initialized, the encoder must be registered with a call to
> -:c:func:`drm_encoder_init()`. The function takes a pointer to the
> -encoder functions and an encoder type. Supported types are
> -
> --  DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
> --  DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
> --  DRM_MODE_ENCODER_LVDS for display panels
> --  DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
> -   Component, SCART)
> --  DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
> -
> -Encoders must be attached to a CRTC to be used. DRM drivers leave
> -encoders unattached at initialization time. Applications (or the fbdev
> -compatibility layer when implemented) are responsible for attaching the
> -encoders they want to use to a CRTC.
> -
>  Cleanup
>  -------
>  
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index bce781b7bb5f..998a6743a586 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -26,6 +26,30 @@
>  
>  #include "drm_crtc_internal.h"
>  
> +/**
> + * DOC: overview
> + *
> + * Encoders represent the connecting element between the CRTC (as the overall
> + * pixel pipeline, represented by struct &drm_crtc) and the connectors (as the
> + * generic sink entity, represented by struct &drm_connector). Encoders are

Doesn't really say what encoders actually do apart being in between crtc
and connector. This line could have been useful here - "An encoder takes
pixel data from a CRTC and converts it to a format suitable for any
attached connectors." 

> + * objects exposed to userspace, originally to allow userspace to infer cloning
> + * and connector/CRTC restrictions. Unfortunately almost all drivers get this
> + * wrong, making the uabi pretty much useless. On top of that the exposed
> + * restrictions are too simple for todays hardware, and the recommend way to
> + * infer restrictions is by using the DRM_MODE_ATOMIC_TEST_ONLY flag for the
> + * atomic IOCTL.
> + *
> + * Otherwise encoders aren't used in the uapi at all (any modeset request from
> + * userspace directly connects a connector with a CRTC), drivers are therefore
> + * free to use them however they wish. Modeset helper libraries make strong use
> + * of encoders to facilitate code sharing. But for more complex settings it is
> + * usually better to move shared code into a separate &drm_bridge. Compared to
> + * encoders bridges also have the benefit of not being purely an internal
> + * abstraction since they are not exposed to userspace at all.

The last line was not very clear. Did you mean "bridges also have the
benefit of BEING purely an internal abstraction ..."


> + *
> + * Encoders are initialized with drm_encoder_init() and cleaned up using
> + * drm_encoder_cleanup().
> + */
>  static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
>  	{ DRM_MODE_ENCODER_NONE, "None" },
>  	{ DRM_MODE_ENCODER_DAC, "DAC" },
> @@ -71,16 +95,17 @@ void drm_encoder_unregister_all(struct drm_device *dev)
>   * @encoder_type: user visible type of the encoder
>   * @name: printf style format string for the encoder name, or NULL for default name
>   *
> - * Initialises a preallocated encoder. Encoder should be
> - * subclassed as part of driver encoder objects.
> + * Initialises a preallocated encoder. Encoder should be subclassed as part of
> + * driver encoder objects. At driver unload time drm_encoder_cleanup() should be
> + * called from the driver's destroy hook in &drm_encoder_funcs.
>   *
>   * Returns:
>   * Zero on success, error code on failure.
>   */
>  int drm_encoder_init(struct drm_device *dev,
> -		      struct drm_encoder *encoder,
> -		      const struct drm_encoder_funcs *funcs,
> -		      int encoder_type, const char *name, ...)
> +		     struct drm_encoder *encoder,
> +		     const struct drm_encoder_funcs *funcs,
> +		     int encoder_type, const char *name, ...)
>  {
>  	int ret;
>  
> @@ -176,19 +201,6 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
>  	return encoder->crtc;
>  }
>  
> -/**
> - * drm_mode_getencoder - get encoder configuration
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Construct a encoder configuration structure to return to the user.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>  int drm_mode_getencoder(struct drm_device *dev, void *data,
>  			struct drm_file *file_priv)
>  {
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index 2712fd1a686b..3d7350f1fcc1 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -84,9 +84,6 @@ struct drm_encoder_funcs {
>   * @head: list management
>   * @base: base KMS object
>   * @name: human readable name, can be overwritten by the driver
> - * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
> - * @possible_crtcs: bitmask of potential CRTC bindings
> - * @possible_clones: bitmask of potential sibling encoders for cloning
>   * @crtc: currently bound CRTC
>   * @bridge: bridge associated to the encoder
>   * @funcs: control functions
> @@ -101,6 +98,32 @@ struct drm_encoder {
>  
>  	struct drm_mode_object base;
>  	char *name;
> +	/**
> +	 * @encoder_type:
> +	 *
> +	 * One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following
> +	 * encoder types are defined thus far:
> +	 *
> +	 * - DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A.
> +	 *
> +	 * - DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort.
> +	 *
> +	 * - DRM_MODE_ENCODER_LVDS for display panels, or in general any panel
> +	 *   with a proprietary parallel connector.
> +	 *
> +	 * - DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
> +	 *   Component, SCART).
> +	 *
> +	 * - DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
> +	 *
> +	 * - DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus.
> +	 *
> +	 * - DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel
> +	 *   bus.
> +	 *
> +	 * - DRM_MODE_ENCODER_DPMST for special fake encoders used to allow
> +	 *   mutliple DP MST streams to share one physical encoder.
> +	 */
>  	int encoder_type;
>  
>  	/**
> @@ -109,7 +132,34 @@ struct drm_encoder {
>  	 */
>  	unsigned index;
>  
> +	/**
> +	 * @possible_crtcs: Bitmask of potential CRTC bindings, using
> +	 * drm_crtc_index() as the index into the bitfield. The driver must set
> +	 * the bits for all &drm_crtc objects this encoder can be connected to
> +	 * before calling drm_encoder_init().
> +	 *
> +	 * In reality almost every driver gets this wrong.
> +	 *
> +	 * Note that since CRTC objects can't be hotplugged the assigned indices
> +	 * are stable and hence known before registering all objects.
> +	 */
>  	uint32_t possible_crtcs;
> +
> +	/**
> +	 * @possible_clones: Bitmask of potential sibling encoders for cloning,
> +	 * using drm_encoder_index() as the index into the bitfield. The driver
> +	 * must set the bits for all &drm_encoder objects which can clone a
> +	 * &drm_crtc together with this encoder before calling
> +	 * drm_encoder_init(). Drivers should set the bit representing the
> +	 * encoder itself, too. Cloning bits should be set such that when two
> +	 * encoders can be used in a cloned configuration, they both should have
> +	 * each another bits set.
> +	 *

I think, the last three lines explain the bit-setting part a little too
well. How about adding a very short description about what cloning is
and condense the bit-setting part? 

Start with something like, "Cloning involves more than one encoder
connected to the same crtc and this bitmask identifies the possible
sibling encoders for this encoder, including itself..." 



> +	 * In reality almost every driver gets this wrong.
> +	 *
> +	 * Note that since encoder objects can't be hotplugged the assigned indices
> +	 * are stable and hence known before registering all objects.
> +	 */
>  	uint32_t possible_clones;
>  
>  	struct drm_crtc *crtc;
> @@ -146,7 +196,7 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc);
>   * @encoder: encoder to test
>   * @crtc: crtc to test
>   *
> - * Return false if @encoder can't be driven by @crtc, true otherwise.
> + * Returns false if @encoder can't be driven by @crtc, true otherwise.
>   */
>  static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
>  				       struct drm_crtc *crtc)
> @@ -154,11 +204,21 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
>  	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
>  }
>  
> +/**
> + * drm_encoder_find - find a &drm_encoder
> + * @dev: DRM device
> + * @id: encoder id
> + *
> + * Returns the encoder with @id, NULL if it doesn't exist. Simple wrapper around
> + * drm_mode_object_find().
> + */
>  static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
> -	uint32_t id)
> +						   uint32_t id)
>  {
>  	struct drm_mode_object *mo;
> +
>  	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
> +
>  	return mo ? obj_to_encoder(mo) : NULL;
>  }
>  

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/9] drm/doc: Polish kerneldoc for encoders
  2016-08-17 20:55 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
@ 2016-08-25 12:24   ` Archit Taneja
  0 siblings, 0 replies; 18+ messages in thread
From: Archit Taneja @ 2016-08-25 12:24 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development; +Cc: Daniel Vetter, Intel Graphics Development



On 08/18/2016 02:25 AM, Daniel Vetter wrote:
> - Move missing bits into struct drm_encoder docs.
> - Explain that encoders are 95% internal and only 5% uapi, and that in
>    general the uapi part is broken.
> - Remove verbose comments for functions not exposed to drivers.
>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>   Documentation/gpu/drm-kms.rst | 46 ++++--------------------------
>   drivers/gpu/drm/drm_encoder.c | 41 +++++++++++++++++----------
>   include/drm/drm_encoder.h     | 65 ++++++++++++++++++++++++++++++++++++++++---
>   3 files changed, 93 insertions(+), 59 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 7f788caebea3..47c2835b7c2d 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -128,6 +128,12 @@ Connector Functions Reference
>   Encoder Abstraction
>   ===================
>
> +.. kernel-doc:: drivers/gpu/drm/drm_encoder.c
> +   :doc: overview
> +
> +Encoder Functions Reference
> +---------------------------
> +
>   .. kernel-doc:: include/drm/drm_encoder.h
>      :internal:
>
> @@ -207,46 +213,6 @@ future); drivers that do not wish to provide special handling for
>   primary planes may make use of the helper functions described in ? to
>   create and register a primary plane with standard capabilities.
>
> -Encoders (:c:type:`struct drm_encoder <drm_encoder>`)
> ------------------------------------------------------
> -
> -An encoder takes pixel data from a CRTC and converts it to a format
> -suitable for any attached connectors. On some devices, it may be
> -possible to have a CRTC send data to more than one encoder. In that
> -case, both encoders would receive data from the same scanout buffer,
> -resulting in a "cloned" display configuration across the connectors
> -attached to each encoder.
> -
> -Encoder Initialization
> -~~~~~~~~~~~~~~~~~~~~~~
> -
> -As for CRTCs, a KMS driver must create, initialize and register at least
> -one :c:type:`struct drm_encoder <drm_encoder>` instance. The
> -instance is allocated and zeroed by the driver, possibly as part of a
> -larger structure.
> -
> -Drivers must initialize the :c:type:`struct drm_encoder
> -<drm_encoder>` possible_crtcs and possible_clones fields before
> -registering the encoder. Both fields are bitmasks of respectively the
> -CRTCs that the encoder can be connected to, and sibling encoders
> -candidate for cloning.
> -
> -After being initialized, the encoder must be registered with a call to
> -:c:func:`drm_encoder_init()`. The function takes a pointer to the
> -encoder functions and an encoder type. Supported types are
> -
> --  DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
> --  DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
> --  DRM_MODE_ENCODER_LVDS for display panels
> --  DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
> -   Component, SCART)
> --  DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
> -
> -Encoders must be attached to a CRTC to be used. DRM drivers leave
> -encoders unattached at initialization time. Applications (or the fbdev
> -compatibility layer when implemented) are responsible for attaching the
> -encoders they want to use to a CRTC.
> -
>   Cleanup
>   -------
>
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index bce781b7bb5f..977d8cad9321 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -26,6 +26,29 @@
>
>   #include "drm_crtc_internal.h"
>
> +/**
> + * DOC: overview
> + *
> + * Encoders represent the connecting element between the CRTC (as the overall
> + * pixel pipeline, represented by struct &drm_crtc) and the connectors (as the
> + * generic sink entity, represented by struct &drm_connector). Encoders are
> + * objects exposed to userspace, originally to allow userspace to infer cloning
> + * and connector/CRTC restrictions. Unfortunately almost all drivers get this
> + * wrong, making the uabi pretty much useless. On top of that the exposed
> + * restrictions are too simple for todays hardware, and the recommend way to
> + * infer restrictions is by using the DRM_MODE_ATOMIC_TEST_ONLY flag for the
> + * atomic IOCTL.
> + *
> + * Otherwise encoders aren't used in the uapi at all (any modeset request from
> + * userspace directly connects a connector with a CRTC), drivers are therefore
> + * free to use them however they wish. Modeset helper libraries make strong use
> + * of encoders to facilitate code sharing. But for more complex settings it is
> + * usually better to move shared code into a separate &drm_bridge, which also
> + * doesn't have any issues with being exposed to userspace.

I guess the last line could say that the drm_bridge isn't exposed to
userspace at all.

> + *
> + * Encoders are initialized with drm_encoder_init() and cleaned up using
> + * drm_encoder_cleanup().
> + */
>   static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
>   	{ DRM_MODE_ENCODER_NONE, "None" },
>   	{ DRM_MODE_ENCODER_DAC, "DAC" },
> @@ -71,8 +94,9 @@ void drm_encoder_unregister_all(struct drm_device *dev)
>    * @encoder_type: user visible type of the encoder
>    * @name: printf style format string for the encoder name, or NULL for default name
>    *
> - * Initialises a preallocated encoder. Encoder should be
> - * subclassed as part of driver encoder objects.
> + * Initialises a preallocated encoder. Encoder should be subclassed as part of
> + * driver encoder objects. At driver unload time drm_encoder_cleanup() should be
> + * called from the driver's destroy hook in &drm_encoder_funcs.
>    *
>    * Returns:
>    * Zero on success, error code on failure.
> @@ -176,19 +200,6 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
>   	return encoder->crtc;
>   }
>
> -/**
> - * drm_mode_getencoder - get encoder configuration
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Construct a encoder configuration structure to return to the user.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>   int drm_mode_getencoder(struct drm_device *dev, void *data,
>   			struct drm_file *file_priv)
>   {
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index 2712fd1a686b..b049748b2514 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -84,9 +84,6 @@ struct drm_encoder_funcs {
>    * @head: list management
>    * @base: base KMS object
>    * @name: human readable name, can be overwritten by the driver
> - * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
> - * @possible_crtcs: bitmask of potential CRTC bindings
> - * @possible_clones: bitmask of potential sibling encoders for cloning
>    * @crtc: currently bound CRTC
>    * @bridge: bridge associated to the encoder
>    * @funcs: control functions
> @@ -101,6 +98,31 @@ struct drm_encoder {
>
>   	struct drm_mode_object base;
>   	char *name;
> +	/**
> +	 * @encoder_type:
> +	 *
> +	 * One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following
> +	 * encoder types are defined thus far:
> +	 *
> +	 * - DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A.
> +	 *
> +	 * - DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort.
> +	 *
> +	 * - DRM_MODE_ENCODER_LVDS for display panels, or in general any panel
> +	 *   with a proprietary parallel connector.
> +	 *
> +	 * - DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
> +	 *   Component, SCART).
> +	 *
> +	 * - DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
> +	 *
> +	 * - DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus.
> +	 *
> +	 * - DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel bus.

The line above exceeds 80 chars, should be easy to remove this warning.
> +	 *
> +	 * - DRM_MODE_ENCODER_DPMST for special fake encoders used to allow
> +	 *   mutliple DP MST streams to share one physical encoder.
> +	 */
>   	int encoder_type;
>
>   	/**
> @@ -109,7 +131,34 @@ struct drm_encoder {
>   	 */
>   	unsigned index;
>
> +	/**
> +	 * @possible_crtcs: Bitmask of potential CRTC bindings, using
> +	 * drm_crtc_index() as the index into the bitfield. The driver must set
> +	 * the bits for all &drm_crtc objects this encoder can be connected to
> +	 * before calling drm_encoder_init().
> +	 *
> +	 * In reality almost every driver gets this wrong.
> +	 *
> +	 * Note that since CRTC objects can't be hotplugged the assigned indices
> +	 * are stable and hence known before registering all objects.
> +	 */

Same here.

Archit

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 2/9] drm/doc: Polish kerneldoc for encoders
  2016-08-17 20:55 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
@ 2016-08-17 20:55 ` Daniel Vetter
  2016-08-25 12:24   ` Archit Taneja
  0 siblings, 1 reply; 18+ messages in thread
From: Daniel Vetter @ 2016-08-17 20:55 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

- Move missing bits into struct drm_encoder docs.
- Explain that encoders are 95% internal and only 5% uapi, and that in
  general the uapi part is broken.
- Remove verbose comments for functions not exposed to drivers.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst | 46 ++++--------------------------
 drivers/gpu/drm/drm_encoder.c | 41 +++++++++++++++++----------
 include/drm/drm_encoder.h     | 65 ++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 93 insertions(+), 59 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 7f788caebea3..47c2835b7c2d 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -128,6 +128,12 @@ Connector Functions Reference
 Encoder Abstraction
 ===================
 
+.. kernel-doc:: drivers/gpu/drm/drm_encoder.c
+   :doc: overview
+
+Encoder Functions Reference
+---------------------------
+
 .. kernel-doc:: include/drm/drm_encoder.h
    :internal:
 
@@ -207,46 +213,6 @@ future); drivers that do not wish to provide special handling for
 primary planes may make use of the helper functions described in ? to
 create and register a primary plane with standard capabilities.
 
-Encoders (:c:type:`struct drm_encoder <drm_encoder>`)
------------------------------------------------------
-
-An encoder takes pixel data from a CRTC and converts it to a format
-suitable for any attached connectors. On some devices, it may be
-possible to have a CRTC send data to more than one encoder. In that
-case, both encoders would receive data from the same scanout buffer,
-resulting in a "cloned" display configuration across the connectors
-attached to each encoder.
-
-Encoder Initialization
-~~~~~~~~~~~~~~~~~~~~~~
-
-As for CRTCs, a KMS driver must create, initialize and register at least
-one :c:type:`struct drm_encoder <drm_encoder>` instance. The
-instance is allocated and zeroed by the driver, possibly as part of a
-larger structure.
-
-Drivers must initialize the :c:type:`struct drm_encoder
-<drm_encoder>` possible_crtcs and possible_clones fields before
-registering the encoder. Both fields are bitmasks of respectively the
-CRTCs that the encoder can be connected to, and sibling encoders
-candidate for cloning.
-
-After being initialized, the encoder must be registered with a call to
-:c:func:`drm_encoder_init()`. The function takes a pointer to the
-encoder functions and an encoder type. Supported types are
-
--  DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
--  DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
--  DRM_MODE_ENCODER_LVDS for display panels
--  DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
-   Component, SCART)
--  DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
-
-Encoders must be attached to a CRTC to be used. DRM drivers leave
-encoders unattached at initialization time. Applications (or the fbdev
-compatibility layer when implemented) are responsible for attaching the
-encoders they want to use to a CRTC.
-
 Cleanup
 -------
 
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index bce781b7bb5f..977d8cad9321 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -26,6 +26,29 @@
 
 #include "drm_crtc_internal.h"
 
+/**
+ * DOC: overview
+ *
+ * Encoders represent the connecting element between the CRTC (as the overall
+ * pixel pipeline, represented by struct &drm_crtc) and the connectors (as the
+ * generic sink entity, represented by struct &drm_connector). Encoders are
+ * objects exposed to userspace, originally to allow userspace to infer cloning
+ * and connector/CRTC restrictions. Unfortunately almost all drivers get this
+ * wrong, making the uabi pretty much useless. On top of that the exposed
+ * restrictions are too simple for todays hardware, and the recommend way to
+ * infer restrictions is by using the DRM_MODE_ATOMIC_TEST_ONLY flag for the
+ * atomic IOCTL.
+ *
+ * Otherwise encoders aren't used in the uapi at all (any modeset request from
+ * userspace directly connects a connector with a CRTC), drivers are therefore
+ * free to use them however they wish. Modeset helper libraries make strong use
+ * of encoders to facilitate code sharing. But for more complex settings it is
+ * usually better to move shared code into a separate &drm_bridge, which also
+ * doesn't have any issues with being exposed to userspace.
+ *
+ * Encoders are initialized with drm_encoder_init() and cleaned up using
+ * drm_encoder_cleanup().
+ */
 static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
 	{ DRM_MODE_ENCODER_NONE, "None" },
 	{ DRM_MODE_ENCODER_DAC, "DAC" },
@@ -71,8 +94,9 @@ void drm_encoder_unregister_all(struct drm_device *dev)
  * @encoder_type: user visible type of the encoder
  * @name: printf style format string for the encoder name, or NULL for default name
  *
- * Initialises a preallocated encoder. Encoder should be
- * subclassed as part of driver encoder objects.
+ * Initialises a preallocated encoder. Encoder should be subclassed as part of
+ * driver encoder objects. At driver unload time drm_encoder_cleanup() should be
+ * called from the driver's destroy hook in &drm_encoder_funcs.
  *
  * Returns:
  * Zero on success, error code on failure.
@@ -176,19 +200,6 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
 	return encoder->crtc;
 }
 
-/**
- * drm_mode_getencoder - get encoder configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Construct a encoder configuration structure to return to the user.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
 int drm_mode_getencoder(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 2712fd1a686b..b049748b2514 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -84,9 +84,6 @@ struct drm_encoder_funcs {
  * @head: list management
  * @base: base KMS object
  * @name: human readable name, can be overwritten by the driver
- * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
- * @possible_crtcs: bitmask of potential CRTC bindings
- * @possible_clones: bitmask of potential sibling encoders for cloning
  * @crtc: currently bound CRTC
  * @bridge: bridge associated to the encoder
  * @funcs: control functions
@@ -101,6 +98,31 @@ struct drm_encoder {
 
 	struct drm_mode_object base;
 	char *name;
+	/**
+	 * @encoder_type:
+	 *
+	 * One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following
+	 * encoder types are defined thus far:
+	 *
+	 * - DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A.
+	 *
+	 * - DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort.
+	 *
+	 * - DRM_MODE_ENCODER_LVDS for display panels, or in general any panel
+	 *   with a proprietary parallel connector.
+	 *
+	 * - DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video,
+	 *   Component, SCART).
+	 *
+	 * - DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
+	 *
+	 * - DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus.
+	 *
+	 * - DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel bus.
+	 *
+	 * - DRM_MODE_ENCODER_DPMST for special fake encoders used to allow
+	 *   mutliple DP MST streams to share one physical encoder.
+	 */
 	int encoder_type;
 
 	/**
@@ -109,7 +131,34 @@ struct drm_encoder {
 	 */
 	unsigned index;
 
+	/**
+	 * @possible_crtcs: Bitmask of potential CRTC bindings, using
+	 * drm_crtc_index() as the index into the bitfield. The driver must set
+	 * the bits for all &drm_crtc objects this encoder can be connected to
+	 * before calling drm_encoder_init().
+	 *
+	 * In reality almost every driver gets this wrong.
+	 *
+	 * Note that since CRTC objects can't be hotplugged the assigned indices
+	 * are stable and hence known before registering all objects.
+	 */
 	uint32_t possible_crtcs;
+
+	/**
+	 * @possible_clones: Bitmask of potential sibling encoders for cloning,
+	 * using drm_encoder_index() as the index into the bitfield. The driver
+	 * must set the bits for all &drm_encoder objects which can clone a
+	 * &drm_crtc together with this encoder before calling
+	 * drm_encoder_init(). Drivers should set the bit representing the
+	 * encoder itself, too. Cloning bits should be set such that when two
+	 * encoders can be used in a cloned configuration, they both should have
+	 * each another bits set.
+	 *
+	 * In reality almost every driver gets this wrong.
+	 *
+	 * Note that since encoder objects can't be hotplugged the assigned indices
+	 * are stable and hence known before registering all objects.
+	 */
 	uint32_t possible_clones;
 
 	struct drm_crtc *crtc;
@@ -146,7 +195,7 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc);
  * @encoder: encoder to test
  * @crtc: crtc to test
  *
- * Return false if @encoder can't be driven by @crtc, true otherwise.
+ * Returns false if @encoder can't be driven by @crtc, true otherwise.
  */
 static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 				       struct drm_crtc *crtc)
@@ -154,6 +203,14 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
 }
 
+/**
+ * drm_encoder_find - find a &drm_encoder
+ * @dev: DRM device
+ * @id: encoder id
+ *
+ * Returns the encoder with @id, NULL if it doesn't exist. Simple wrapper around
+ * drm_mode_object_find().
+ */
 static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
 	uint32_t id)
 {
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-09-15  4:47 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-29  8:27 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
2016-08-29  8:27 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
2016-09-15  4:47   ` [2/9] " Pandiyan, Dhinakaran
2016-08-29  8:27 ` [PATCH 3/9] drm: Extract drm_mode_object.[hc] Daniel Vetter
2016-08-29  8:27 ` [PATCH 4/9] drm: Remove drm_mode_object->atomic_count Daniel Vetter
2016-08-29  8:27 ` [PATCH 5/9] drm/doc: Polish docs for drm_mode_object Daniel Vetter
2016-08-29  8:27 ` [PATCH 6/9] drm: move drm_mode_legacy_fb_format to drm_fourcc.c Daniel Vetter
2016-08-29  8:27 ` [PATCH 7/9] drm: Extract drm_property.[hc] Daniel Vetter
2016-08-29  8:27 ` [PATCH 8/9] drm: Unify handling of blob and object properties Daniel Vetter
2016-09-06  9:22   ` Ying Liu
2016-09-07  9:52     ` [PATCH] Revert "drm: Unify handling of blob and object properties" Maarten Lankhorst
2016-09-07  9:56       ` Ying Liu
2016-09-07 11:25         ` Jani Nikula
2016-08-29  8:27 ` [PATCH 9/9] drm/doc: Polish docs for drm_property&drm_property_blob Daniel Vetter
2016-08-29 13:14   ` Archit Taneja
2016-08-29 14:04     ` Daniel Vetter
  -- strict thread matches above, loose matches on Subject: below --
2016-08-17 20:55 [PATCH 1/9] drm: Extract drm_encoder.[hc] Daniel Vetter
2016-08-17 20:55 ` [PATCH 2/9] drm/doc: Polish kerneldoc for encoders Daniel Vetter
2016-08-25 12:24   ` Archit Taneja

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.