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:
#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)
*
* 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.
*
* 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.
*
* 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
*
* 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.
*
* 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.
*
* 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.
* 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;
*
* 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.
*
* 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);
}
}
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)
{
/**
* 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.
/**
* 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)
{
}
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)
{
/**
* 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)
{
* 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)
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
* @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.
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,
}
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)
{
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)
{
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)
{
* 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;
#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;
#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)
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);