1949619f3SDaniel Vetter /* 2949619f3SDaniel Vetter * Copyright (c) 2016 Intel Corporation 3949619f3SDaniel Vetter * 4949619f3SDaniel Vetter * Permission to use, copy, modify, distribute, and sell this software and its 5949619f3SDaniel Vetter * documentation for any purpose is hereby granted without fee, provided that 6949619f3SDaniel Vetter * the above copyright notice appear in all copies and that both that copyright 7949619f3SDaniel Vetter * notice and this permission notice appear in supporting documentation, and 8949619f3SDaniel Vetter * that the name of the copyright holders not be used in advertising or 9949619f3SDaniel Vetter * publicity pertaining to distribution of the software without specific, 10949619f3SDaniel Vetter * written prior permission. The copyright holders make no representations 11949619f3SDaniel Vetter * about the suitability of this software for any purpose. It is provided "as 12949619f3SDaniel Vetter * is" without express or implied warranty. 13949619f3SDaniel Vetter * 14949619f3SDaniel Vetter * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15949619f3SDaniel Vetter * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16949619f3SDaniel Vetter * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17949619f3SDaniel Vetter * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18949619f3SDaniel Vetter * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19949619f3SDaniel Vetter * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20949619f3SDaniel Vetter * OF THIS SOFTWARE. 21949619f3SDaniel Vetter */ 22949619f3SDaniel Vetter 23949619f3SDaniel Vetter #include <linux/export.h> 24949619f3SDaniel Vetter #include <drm/drmP.h> 25949619f3SDaniel Vetter #include <drm/drm_mode_object.h> 26949619f3SDaniel Vetter 27949619f3SDaniel Vetter #include "drm_crtc_internal.h" 28949619f3SDaniel Vetter 29949619f3SDaniel Vetter /* 30949619f3SDaniel Vetter * Internal function to assign a slot in the object idr and optionally 31949619f3SDaniel Vetter * register the object into the idr. 32949619f3SDaniel Vetter */ 33949619f3SDaniel Vetter int drm_mode_object_get_reg(struct drm_device *dev, 34949619f3SDaniel Vetter struct drm_mode_object *obj, 35949619f3SDaniel Vetter uint32_t obj_type, 36949619f3SDaniel Vetter bool register_obj, 37949619f3SDaniel Vetter void (*obj_free_cb)(struct kref *kref)) 38949619f3SDaniel Vetter { 39949619f3SDaniel Vetter int ret; 40949619f3SDaniel Vetter 41949619f3SDaniel Vetter mutex_lock(&dev->mode_config.idr_mutex); 42949619f3SDaniel Vetter ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL); 43949619f3SDaniel Vetter if (ret >= 0) { 44949619f3SDaniel Vetter /* 45949619f3SDaniel Vetter * Set up the object linking under the protection of the idr 46949619f3SDaniel Vetter * lock so that other users can't see inconsistent state. 47949619f3SDaniel Vetter */ 48949619f3SDaniel Vetter obj->id = ret; 49949619f3SDaniel Vetter obj->type = obj_type; 50949619f3SDaniel Vetter if (obj_free_cb) { 51949619f3SDaniel Vetter obj->free_cb = obj_free_cb; 52949619f3SDaniel Vetter kref_init(&obj->refcount); 53949619f3SDaniel Vetter } 54949619f3SDaniel Vetter } 55949619f3SDaniel Vetter mutex_unlock(&dev->mode_config.idr_mutex); 56949619f3SDaniel Vetter 57949619f3SDaniel Vetter return ret < 0 ? ret : 0; 58949619f3SDaniel Vetter } 59949619f3SDaniel Vetter 60949619f3SDaniel Vetter /** 61949619f3SDaniel Vetter * drm_mode_object_get - allocate a new modeset identifier 62949619f3SDaniel Vetter * @dev: DRM device 63949619f3SDaniel Vetter * @obj: object pointer, used to generate unique ID 64949619f3SDaniel Vetter * @obj_type: object type 65949619f3SDaniel Vetter * 66949619f3SDaniel Vetter * Create a unique identifier based on @ptr in @dev's identifier space. Used 67949619f3SDaniel Vetter * for tracking modes, CRTCs and connectors. Note that despite the _get postfix 68949619f3SDaniel Vetter * modeset identifiers are _not_ reference counted. Hence don't use this for 69949619f3SDaniel Vetter * reference counted modeset objects like framebuffers. 70949619f3SDaniel Vetter * 71949619f3SDaniel Vetter * Returns: 72949619f3SDaniel Vetter * Zero on success, error code on failure. 73949619f3SDaniel Vetter */ 74949619f3SDaniel Vetter int drm_mode_object_get(struct drm_device *dev, 75949619f3SDaniel Vetter struct drm_mode_object *obj, uint32_t obj_type) 76949619f3SDaniel Vetter { 77949619f3SDaniel Vetter return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL); 78949619f3SDaniel Vetter } 79949619f3SDaniel Vetter 80949619f3SDaniel Vetter void drm_mode_object_register(struct drm_device *dev, 81949619f3SDaniel Vetter struct drm_mode_object *obj) 82949619f3SDaniel Vetter { 83949619f3SDaniel Vetter mutex_lock(&dev->mode_config.idr_mutex); 84949619f3SDaniel Vetter idr_replace(&dev->mode_config.crtc_idr, obj, obj->id); 85949619f3SDaniel Vetter mutex_unlock(&dev->mode_config.idr_mutex); 86949619f3SDaniel Vetter } 87949619f3SDaniel Vetter 88949619f3SDaniel Vetter /** 89949619f3SDaniel Vetter * drm_mode_object_unregister - free a modeset identifer 90949619f3SDaniel Vetter * @dev: DRM device 91949619f3SDaniel Vetter * @object: object to free 92949619f3SDaniel Vetter * 93949619f3SDaniel Vetter * Free @id from @dev's unique identifier pool. 94949619f3SDaniel Vetter * This function can be called multiple times, and guards against 95949619f3SDaniel Vetter * multiple removals. 96949619f3SDaniel Vetter * These modeset identifiers are _not_ reference counted. Hence don't use this 97949619f3SDaniel Vetter * for reference counted modeset objects like framebuffers. 98949619f3SDaniel Vetter */ 99949619f3SDaniel Vetter void drm_mode_object_unregister(struct drm_device *dev, 100949619f3SDaniel Vetter struct drm_mode_object *object) 101949619f3SDaniel Vetter { 102949619f3SDaniel Vetter mutex_lock(&dev->mode_config.idr_mutex); 103949619f3SDaniel Vetter if (object->id) { 104949619f3SDaniel Vetter idr_remove(&dev->mode_config.crtc_idr, object->id); 105949619f3SDaniel Vetter object->id = 0; 106949619f3SDaniel Vetter } 107949619f3SDaniel Vetter mutex_unlock(&dev->mode_config.idr_mutex); 108949619f3SDaniel Vetter } 109949619f3SDaniel Vetter 110949619f3SDaniel Vetter struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, 111949619f3SDaniel Vetter uint32_t id, uint32_t type) 112949619f3SDaniel Vetter { 113949619f3SDaniel Vetter struct drm_mode_object *obj = NULL; 114949619f3SDaniel Vetter 115949619f3SDaniel Vetter mutex_lock(&dev->mode_config.idr_mutex); 116949619f3SDaniel Vetter obj = idr_find(&dev->mode_config.crtc_idr, id); 117949619f3SDaniel Vetter if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) 118949619f3SDaniel Vetter obj = NULL; 119949619f3SDaniel Vetter if (obj && obj->id != id) 120949619f3SDaniel Vetter obj = NULL; 121949619f3SDaniel Vetter 122949619f3SDaniel Vetter if (obj && obj->free_cb) { 123949619f3SDaniel Vetter if (!kref_get_unless_zero(&obj->refcount)) 124949619f3SDaniel Vetter obj = NULL; 125949619f3SDaniel Vetter } 126949619f3SDaniel Vetter mutex_unlock(&dev->mode_config.idr_mutex); 127949619f3SDaniel Vetter 128949619f3SDaniel Vetter return obj; 129949619f3SDaniel Vetter } 130949619f3SDaniel Vetter 131949619f3SDaniel Vetter /** 132949619f3SDaniel Vetter * drm_mode_object_find - look up a drm object with static lifetime 133949619f3SDaniel Vetter * @dev: drm device 134949619f3SDaniel Vetter * @id: id of the mode object 135949619f3SDaniel Vetter * @type: type of the mode object 136949619f3SDaniel Vetter * 137949619f3SDaniel Vetter * This function is used to look up a modeset object. It will acquire a 138949619f3SDaniel Vetter * reference for reference counted objects. This reference must be dropped again 139949619f3SDaniel Vetter * by callind drm_mode_object_unreference(). 140949619f3SDaniel Vetter */ 141949619f3SDaniel Vetter struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 142949619f3SDaniel Vetter uint32_t id, uint32_t type) 143949619f3SDaniel Vetter { 144949619f3SDaniel Vetter struct drm_mode_object *obj = NULL; 145949619f3SDaniel Vetter 146949619f3SDaniel Vetter obj = __drm_mode_object_find(dev, id, type); 147949619f3SDaniel Vetter return obj; 148949619f3SDaniel Vetter } 149949619f3SDaniel Vetter EXPORT_SYMBOL(drm_mode_object_find); 150949619f3SDaniel Vetter 151949619f3SDaniel Vetter /** 152949619f3SDaniel Vetter * drm_mode_object_unreference - decr the object refcnt 153949619f3SDaniel Vetter * @obj: mode_object 154949619f3SDaniel Vetter * 155a2511a55SDaniel Vetter * This function decrements the object's refcount if it is a refcounted modeset 156949619f3SDaniel Vetter * object. It is a no-op on any other object. This is used to drop references 157949619f3SDaniel Vetter * acquired with drm_mode_object_reference(). 158949619f3SDaniel Vetter */ 159949619f3SDaniel Vetter void drm_mode_object_unreference(struct drm_mode_object *obj) 160949619f3SDaniel Vetter { 161949619f3SDaniel Vetter if (obj->free_cb) { 162*2c935bc5SPeter Zijlstra DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 163949619f3SDaniel Vetter kref_put(&obj->refcount, obj->free_cb); 164949619f3SDaniel Vetter } 165949619f3SDaniel Vetter } 166949619f3SDaniel Vetter EXPORT_SYMBOL(drm_mode_object_unreference); 167949619f3SDaniel Vetter 168949619f3SDaniel Vetter /** 169949619f3SDaniel Vetter * drm_mode_object_reference - incr the object refcnt 170949619f3SDaniel Vetter * @obj: mode_object 171949619f3SDaniel Vetter * 172a2511a55SDaniel Vetter * This function increments the object's refcount if it is a refcounted modeset 173949619f3SDaniel Vetter * object. It is a no-op on any other object. References should be dropped again 174949619f3SDaniel Vetter * by calling drm_mode_object_unreference(). 175949619f3SDaniel Vetter */ 176949619f3SDaniel Vetter void drm_mode_object_reference(struct drm_mode_object *obj) 177949619f3SDaniel Vetter { 178949619f3SDaniel Vetter if (obj->free_cb) { 179*2c935bc5SPeter Zijlstra DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 180949619f3SDaniel Vetter kref_get(&obj->refcount); 181949619f3SDaniel Vetter } 182949619f3SDaniel Vetter } 183949619f3SDaniel Vetter EXPORT_SYMBOL(drm_mode_object_reference); 184949619f3SDaniel Vetter 185949619f3SDaniel Vetter /** 186949619f3SDaniel Vetter * drm_object_attach_property - attach a property to a modeset object 187949619f3SDaniel Vetter * @obj: drm modeset object 188949619f3SDaniel Vetter * @property: property to attach 189949619f3SDaniel Vetter * @init_val: initial value of the property 190949619f3SDaniel Vetter * 191949619f3SDaniel Vetter * This attaches the given property to the modeset object with the given initial 192949619f3SDaniel Vetter * value. Currently this function cannot fail since the properties are stored in 193949619f3SDaniel Vetter * a statically sized array. 194949619f3SDaniel Vetter */ 195949619f3SDaniel Vetter void drm_object_attach_property(struct drm_mode_object *obj, 196949619f3SDaniel Vetter struct drm_property *property, 197949619f3SDaniel Vetter uint64_t init_val) 198949619f3SDaniel Vetter { 199949619f3SDaniel Vetter int count = obj->properties->count; 200949619f3SDaniel Vetter 201949619f3SDaniel Vetter if (count == DRM_OBJECT_MAX_PROPERTY) { 202949619f3SDaniel Vetter WARN(1, "Failed to attach object property (type: 0x%x). Please " 203949619f3SDaniel Vetter "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 204949619f3SDaniel Vetter "you see this message on the same object type.\n", 205949619f3SDaniel Vetter obj->type); 206949619f3SDaniel Vetter return; 207949619f3SDaniel Vetter } 208949619f3SDaniel Vetter 209949619f3SDaniel Vetter obj->properties->properties[count] = property; 210949619f3SDaniel Vetter obj->properties->values[count] = init_val; 211949619f3SDaniel Vetter obj->properties->count++; 212949619f3SDaniel Vetter } 213949619f3SDaniel Vetter EXPORT_SYMBOL(drm_object_attach_property); 214949619f3SDaniel Vetter 215949619f3SDaniel Vetter /** 216949619f3SDaniel Vetter * drm_object_property_set_value - set the value of a property 217949619f3SDaniel Vetter * @obj: drm mode object to set property value for 218949619f3SDaniel Vetter * @property: property to set 219949619f3SDaniel Vetter * @val: value the property should be set to 220949619f3SDaniel Vetter * 221a2511a55SDaniel Vetter * This function sets a given property on a given object. This function only 222949619f3SDaniel Vetter * changes the software state of the property, it does not call into the 223949619f3SDaniel Vetter * driver's ->set_property callback. 224949619f3SDaniel Vetter * 225a2511a55SDaniel Vetter * Note that atomic drivers should not have any need to call this, the core will 226a2511a55SDaniel Vetter * ensure consistency of values reported back to userspace through the 227a2511a55SDaniel Vetter * appropriate ->atomic_get_property callback. Only legacy drivers should call 228a2511a55SDaniel Vetter * this function to update the tracked value (after clamping and other 229a2511a55SDaniel Vetter * restrictions have been applied). 230a2511a55SDaniel Vetter * 231949619f3SDaniel Vetter * Returns: 232949619f3SDaniel Vetter * Zero on success, error code on failure. 233949619f3SDaniel Vetter */ 234949619f3SDaniel Vetter int drm_object_property_set_value(struct drm_mode_object *obj, 235949619f3SDaniel Vetter struct drm_property *property, uint64_t val) 236949619f3SDaniel Vetter { 237949619f3SDaniel Vetter int i; 238949619f3SDaniel Vetter 239949619f3SDaniel Vetter for (i = 0; i < obj->properties->count; i++) { 240949619f3SDaniel Vetter if (obj->properties->properties[i] == property) { 241949619f3SDaniel Vetter obj->properties->values[i] = val; 242949619f3SDaniel Vetter return 0; 243949619f3SDaniel Vetter } 244949619f3SDaniel Vetter } 245949619f3SDaniel Vetter 246949619f3SDaniel Vetter return -EINVAL; 247949619f3SDaniel Vetter } 248949619f3SDaniel Vetter EXPORT_SYMBOL(drm_object_property_set_value); 249949619f3SDaniel Vetter 250949619f3SDaniel Vetter /** 251949619f3SDaniel Vetter * drm_object_property_get_value - retrieve the value of a property 252949619f3SDaniel Vetter * @obj: drm mode object to get property value from 253949619f3SDaniel Vetter * @property: property to retrieve 254949619f3SDaniel Vetter * @val: storage for the property value 255949619f3SDaniel Vetter * 256949619f3SDaniel Vetter * This function retrieves the softare state of the given property for the given 257949619f3SDaniel Vetter * property. Since there is no driver callback to retrieve the current property 258949619f3SDaniel Vetter * value this might be out of sync with the hardware, depending upon the driver 259949619f3SDaniel Vetter * and property. 260949619f3SDaniel Vetter * 261a2511a55SDaniel Vetter * Atomic drivers should never call this function directly, the core will read 262a2511a55SDaniel Vetter * out property values through the various ->atomic_get_property callbacks. 263a2511a55SDaniel Vetter * 264949619f3SDaniel Vetter * Returns: 265949619f3SDaniel Vetter * Zero on success, error code on failure. 266949619f3SDaniel Vetter */ 267949619f3SDaniel Vetter int drm_object_property_get_value(struct drm_mode_object *obj, 268949619f3SDaniel Vetter struct drm_property *property, uint64_t *val) 269949619f3SDaniel Vetter { 270949619f3SDaniel Vetter int i; 271949619f3SDaniel Vetter 272949619f3SDaniel Vetter /* read-only properties bypass atomic mechanism and still store 273949619f3SDaniel Vetter * their value in obj->properties->values[].. mostly to avoid 274949619f3SDaniel Vetter * having to deal w/ EDID and similar props in atomic paths: 275949619f3SDaniel Vetter */ 276949619f3SDaniel Vetter if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) && 277949619f3SDaniel Vetter !(property->flags & DRM_MODE_PROP_IMMUTABLE)) 278949619f3SDaniel Vetter return drm_atomic_get_property(obj, property, val); 279949619f3SDaniel Vetter 280949619f3SDaniel Vetter for (i = 0; i < obj->properties->count; i++) { 281949619f3SDaniel Vetter if (obj->properties->properties[i] == property) { 282949619f3SDaniel Vetter *val = obj->properties->values[i]; 283949619f3SDaniel Vetter return 0; 284949619f3SDaniel Vetter } 285949619f3SDaniel Vetter 286949619f3SDaniel Vetter } 287949619f3SDaniel Vetter 288949619f3SDaniel Vetter return -EINVAL; 289949619f3SDaniel Vetter } 290949619f3SDaniel Vetter EXPORT_SYMBOL(drm_object_property_get_value); 291949619f3SDaniel Vetter 292949619f3SDaniel Vetter /* helper for getconnector and getproperties ioctls */ 293949619f3SDaniel Vetter int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, 294949619f3SDaniel Vetter uint32_t __user *prop_ptr, 295949619f3SDaniel Vetter uint64_t __user *prop_values, 296949619f3SDaniel Vetter uint32_t *arg_count_props) 297949619f3SDaniel Vetter { 298f094d881SDaniel Vetter int i, ret, count; 299949619f3SDaniel Vetter 300f094d881SDaniel Vetter for (i = 0, count = 0; i < obj->properties->count; i++) { 301949619f3SDaniel Vetter struct drm_property *prop = obj->properties->properties[i]; 302949619f3SDaniel Vetter uint64_t val; 303949619f3SDaniel Vetter 304949619f3SDaniel Vetter if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) 305949619f3SDaniel Vetter continue; 306949619f3SDaniel Vetter 307f094d881SDaniel Vetter if (*arg_count_props > count) { 308949619f3SDaniel Vetter ret = drm_object_property_get_value(obj, prop, &val); 309949619f3SDaniel Vetter if (ret) 310949619f3SDaniel Vetter return ret; 311949619f3SDaniel Vetter 312f094d881SDaniel Vetter if (put_user(prop->base.id, prop_ptr + count)) 313949619f3SDaniel Vetter return -EFAULT; 314949619f3SDaniel Vetter 315f094d881SDaniel Vetter if (put_user(val, prop_values + count)) 316949619f3SDaniel Vetter return -EFAULT; 317f094d881SDaniel Vetter } 318949619f3SDaniel Vetter 319f094d881SDaniel Vetter count++; 320949619f3SDaniel Vetter } 321f094d881SDaniel Vetter *arg_count_props = count; 322949619f3SDaniel Vetter 323949619f3SDaniel Vetter return 0; 324949619f3SDaniel Vetter } 325949619f3SDaniel Vetter 326949619f3SDaniel Vetter /** 327949619f3SDaniel Vetter * drm_mode_obj_get_properties_ioctl - get the current value of a object's property 328949619f3SDaniel Vetter * @dev: DRM device 329949619f3SDaniel Vetter * @data: ioctl data 330949619f3SDaniel Vetter * @file_priv: DRM file info 331949619f3SDaniel Vetter * 332949619f3SDaniel Vetter * This function retrieves the current value for an object's property. Compared 333949619f3SDaniel Vetter * to the connector specific ioctl this one is extended to also work on crtc and 334949619f3SDaniel Vetter * plane objects. 335949619f3SDaniel Vetter * 336949619f3SDaniel Vetter * Called by the user via ioctl. 337949619f3SDaniel Vetter * 338949619f3SDaniel Vetter * Returns: 339949619f3SDaniel Vetter * Zero on success, negative errno on failure. 340949619f3SDaniel Vetter */ 341949619f3SDaniel Vetter int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 342949619f3SDaniel Vetter struct drm_file *file_priv) 343949619f3SDaniel Vetter { 344949619f3SDaniel Vetter struct drm_mode_obj_get_properties *arg = data; 345949619f3SDaniel Vetter struct drm_mode_object *obj; 346949619f3SDaniel Vetter int ret = 0; 347949619f3SDaniel Vetter 348949619f3SDaniel Vetter if (!drm_core_check_feature(dev, DRIVER_MODESET)) 349949619f3SDaniel Vetter return -EINVAL; 350949619f3SDaniel Vetter 351949619f3SDaniel Vetter drm_modeset_lock_all(dev); 352949619f3SDaniel Vetter 353949619f3SDaniel Vetter obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 354949619f3SDaniel Vetter if (!obj) { 355949619f3SDaniel Vetter ret = -ENOENT; 356949619f3SDaniel Vetter goto out; 357949619f3SDaniel Vetter } 358949619f3SDaniel Vetter if (!obj->properties) { 359949619f3SDaniel Vetter ret = -EINVAL; 360949619f3SDaniel Vetter goto out_unref; 361949619f3SDaniel Vetter } 362949619f3SDaniel Vetter 363949619f3SDaniel Vetter ret = drm_mode_object_get_properties(obj, file_priv->atomic, 364949619f3SDaniel Vetter (uint32_t __user *)(unsigned long)(arg->props_ptr), 365949619f3SDaniel Vetter (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), 366949619f3SDaniel Vetter &arg->count_props); 367949619f3SDaniel Vetter 368949619f3SDaniel Vetter out_unref: 369949619f3SDaniel Vetter drm_mode_object_unreference(obj); 370949619f3SDaniel Vetter out: 371949619f3SDaniel Vetter drm_modeset_unlock_all(dev); 372949619f3SDaniel Vetter return ret; 373949619f3SDaniel Vetter } 374949619f3SDaniel Vetter 375f92f053bSMaarten Lankhorst struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, 376f92f053bSMaarten Lankhorst uint32_t prop_id) 377f92f053bSMaarten Lankhorst { 378f92f053bSMaarten Lankhorst int i; 379f92f053bSMaarten Lankhorst 380f92f053bSMaarten Lankhorst for (i = 0; i < obj->properties->count; i++) 381f92f053bSMaarten Lankhorst if (obj->properties->properties[i]->base.id == prop_id) 382f92f053bSMaarten Lankhorst return obj->properties->properties[i]; 383f92f053bSMaarten Lankhorst 384f92f053bSMaarten Lankhorst return NULL; 385f92f053bSMaarten Lankhorst } 386f92f053bSMaarten Lankhorst 387949619f3SDaniel Vetter int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 388949619f3SDaniel Vetter struct drm_file *file_priv) 389949619f3SDaniel Vetter { 390949619f3SDaniel Vetter struct drm_mode_obj_set_property *arg = data; 391949619f3SDaniel Vetter struct drm_mode_object *arg_obj; 392949619f3SDaniel Vetter struct drm_property *property; 393f92f053bSMaarten Lankhorst int ret = -EINVAL; 394949619f3SDaniel Vetter struct drm_mode_object *ref; 395949619f3SDaniel Vetter 396949619f3SDaniel Vetter if (!drm_core_check_feature(dev, DRIVER_MODESET)) 397949619f3SDaniel Vetter return -EINVAL; 398949619f3SDaniel Vetter 399949619f3SDaniel Vetter drm_modeset_lock_all(dev); 400949619f3SDaniel Vetter 401949619f3SDaniel Vetter arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 402949619f3SDaniel Vetter if (!arg_obj) { 403949619f3SDaniel Vetter ret = -ENOENT; 404949619f3SDaniel Vetter goto out; 405949619f3SDaniel Vetter } 406f92f053bSMaarten Lankhorst 407949619f3SDaniel Vetter if (!arg_obj->properties) 408949619f3SDaniel Vetter goto out_unref; 409949619f3SDaniel Vetter 410f92f053bSMaarten Lankhorst property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id); 411f92f053bSMaarten Lankhorst if (!property) 412949619f3SDaniel Vetter goto out_unref; 413949619f3SDaniel Vetter 414949619f3SDaniel Vetter if (!drm_property_change_valid_get(property, arg->value, &ref)) 415949619f3SDaniel Vetter goto out_unref; 416949619f3SDaniel Vetter 417949619f3SDaniel Vetter switch (arg_obj->type) { 418949619f3SDaniel Vetter case DRM_MODE_OBJECT_CONNECTOR: 419949619f3SDaniel Vetter ret = drm_mode_connector_set_obj_prop(arg_obj, property, 420949619f3SDaniel Vetter arg->value); 421949619f3SDaniel Vetter break; 422949619f3SDaniel Vetter case DRM_MODE_OBJECT_CRTC: 423949619f3SDaniel Vetter ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); 424949619f3SDaniel Vetter break; 425949619f3SDaniel Vetter case DRM_MODE_OBJECT_PLANE: 426949619f3SDaniel Vetter ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj), 427949619f3SDaniel Vetter property, arg->value); 428949619f3SDaniel Vetter break; 429949619f3SDaniel Vetter } 430949619f3SDaniel Vetter 431949619f3SDaniel Vetter drm_property_change_valid_put(property, ref); 432949619f3SDaniel Vetter 433949619f3SDaniel Vetter out_unref: 434949619f3SDaniel Vetter drm_mode_object_unreference(arg_obj); 435949619f3SDaniel Vetter out: 436949619f3SDaniel Vetter drm_modeset_unlock_all(dev); 437949619f3SDaniel Vetter return ret; 438949619f3SDaniel Vetter } 439