/* * 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.
*/
/* * Internal function to assign a slot in the object idr and optionally * register the object into the idr.
*/ int __drm_mode_object_add(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.object_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_add - 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. * * Returns: * Zero on success, error code on failure.
*/ int drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj, uint32_t obj_type)
{ return __drm_mode_object_add(dev, obj, obj_type, true, NULL);
}
EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_mode_object_add);
/** * drm_mode_object_unregister - free a modeset identifier * @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)
{
WARN_ON(!dev->driver->load && dev->registered && !object->free_cb);
/** * drm_mode_object_lease_required - check types which must be leased to be used * @type: type of object * * Returns whether the provided type of drm_mode_object must * be owned or leased to be used by a process.
*/ bool drm_mode_object_lease_required(uint32_t type)
{ switch(type) { case DRM_MODE_OBJECT_CRTC: case DRM_MODE_OBJECT_CONNECTOR: case DRM_MODE_OBJECT_PLANE: returntrue; default: returnfalse;
}
}
mutex_lock(&dev->mode_config.idr_mutex);
obj = idr_find(&dev->mode_config.object_idr, id); if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
obj = NULL; if (obj && obj->id != id)
obj = NULL;
if (obj && drm_mode_object_lease_required(obj->type) &&
!_drm_lease_held(file_priv, obj->id)) {
drm_dbg_kms(dev, "[OBJECT:%d] not included in lease", 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 * @file_priv: drm file * @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_put().
*/ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, struct drm_file *file_priv,
uint32_t id, uint32_t type)
{ struct drm_mode_object *obj = NULL;
/** * drm_mode_object_put - release a mode object reference * @obj: DRM mode object * * 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_get().
*/ void drm_mode_object_put(struct drm_mode_object *obj)
{ if (obj->free_cb) {
DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
kref_put(&obj->refcount, obj->free_cb);
}
}
EXPORT_SYMBOL(drm_mode_object_put);
/** * drm_mode_object_get - acquire a mode object reference * @obj: DRM mode object * * 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_put().
*/ void drm_mode_object_get(struct drm_mode_object *obj)
{ if (obj->free_cb) {
DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
kref_get(&obj->refcount);
}
}
EXPORT_SYMBOL(drm_mode_object_get);
/** * 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. * * Note that all properties must be attached before the object itself is * registered and accessible from userspace.
*/ void drm_object_attach_property(struct drm_mode_object *obj, struct drm_property *property,
uint64_t init_val)
{ int count = obj->properties->count; struct drm_device *dev = property->dev;
if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { struct drm_connector *connector = obj_to_connector(obj);
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;
}
/** * 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 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.
*/ int drm_object_property_set_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_drv_uses_atomic_modeset(property->dev) &&
!(property->flags & DRM_MODE_PROP_IMMUTABLE)) return drm_atomic_get_property(obj, property, val);
/** * 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. * * 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.
*/ int drm_object_property_get_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val)
{
WARN_ON(drm_drv_uses_atomic_modeset(property->dev));
/** * drm_object_property_get_default_value - retrieve the default value of a * property when in atomic mode. * @obj: drm mode object to get property value from * @property: property to retrieve * @val: storage for the property value * * This function retrieves the default state of the given property as passed in * to drm_object_attach_property * * Only atomic drivers should call this function directly, as for non-atomic * drivers it will return the current value. * * Returns: * Zero on success, error code on failure.
*/ int drm_object_property_get_default_value(struct drm_mode_object *obj, struct drm_property *property,
uint64_t *val)
{
WARN_ON(!drm_drv_uses_atomic_modeset(property->dev));
/* 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 i, ret, count;
for (i = 0, count = 0; i < obj->properties->count; i++) { struct drm_property *prop = obj->properties->properties[i];
uint64_t val;
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 + count)) return -EFAULT;
if (put_user(val, prop_values + count)) return -EFAULT;
}
count++;
}
*arg_count_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; struct drm_modeset_acquire_ctx ctx; int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP;
DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); if (!obj) {
ret = -ENOENT; goto out;
} if (!obj->properties) {
ret = -EINVAL; goto out_unref;
}
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_property *property; int ret = -EINVAL;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP;
arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); if (!arg_obj) return -ENOENT;
if (!arg_obj->properties) goto out_unref;
property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id); if (!property) goto out_unref;
if (drm_drv_uses_atomic_modeset(property->dev))
ret = set_property_atomic(arg_obj, file_priv, property, arg->value); else
ret = set_property_legacy(arg_obj, property, arg->value);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.