1 /* 2 * Copyright (c) 2016 Intel Corporation 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23 #include <linux/export.h> 24 #include <linux/uaccess.h> 25 #include <linux/backlight.h> 26 27 #include <drm/drm_atomic.h> 28 #include <drm/drm_drv.h> 29 #include <drm/drm_device.h> 30 #include <drm/drm_file.h> 31 #include <drm/drm_mode_object.h> 32 #include <drm/drm_print.h> 33 34 #include "drm_crtc_internal.h" 35 36 /* 37 * Internal function to assign a slot in the object idr and optionally 38 * register the object into the idr. 39 */ 40 int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj, 41 uint32_t obj_type, bool register_obj, 42 void (*obj_free_cb)(struct kref *kref)) 43 { 44 int ret; 45 46 WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb); 47 48 mutex_lock(&dev->mode_config.idr_mutex); 49 ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL, 50 1, 0, GFP_KERNEL); 51 if (ret >= 0) { 52 /* 53 * Set up the object linking under the protection of the idr 54 * lock so that other users can't see inconsistent state. 55 */ 56 obj->id = ret; 57 obj->type = obj_type; 58 if (obj_free_cb) { 59 obj->free_cb = obj_free_cb; 60 kref_init(&obj->refcount); 61 } 62 } 63 mutex_unlock(&dev->mode_config.idr_mutex); 64 65 return ret < 0 ? ret : 0; 66 } 67 68 /** 69 * drm_mode_object_add - allocate a new modeset identifier 70 * @dev: DRM device 71 * @obj: object pointer, used to generate unique ID 72 * @obj_type: object type 73 * 74 * Create a unique identifier based on @ptr in @dev's identifier space. Used 75 * for tracking modes, CRTCs and connectors. 76 * 77 * Returns: 78 * Zero on success, error code on failure. 79 */ 80 int drm_mode_object_add(struct drm_device *dev, 81 struct drm_mode_object *obj, uint32_t obj_type) 82 { 83 return __drm_mode_object_add(dev, obj, obj_type, true, NULL); 84 } 85 86 void drm_mode_object_register(struct drm_device *dev, 87 struct drm_mode_object *obj) 88 { 89 mutex_lock(&dev->mode_config.idr_mutex); 90 idr_replace(&dev->mode_config.object_idr, obj, obj->id); 91 mutex_unlock(&dev->mode_config.idr_mutex); 92 } 93 94 /** 95 * drm_mode_object_unregister - free a modeset identifier 96 * @dev: DRM device 97 * @object: object to free 98 * 99 * Free @id from @dev's unique identifier pool. 100 * This function can be called multiple times, and guards against 101 * multiple removals. 102 * These modeset identifiers are _not_ reference counted. Hence don't use this 103 * for reference counted modeset objects like framebuffers. 104 */ 105 void drm_mode_object_unregister(struct drm_device *dev, 106 struct drm_mode_object *object) 107 { 108 WARN_ON(!dev->driver->load && dev->registered && !object->free_cb); 109 110 mutex_lock(&dev->mode_config.idr_mutex); 111 if (object->id) { 112 idr_remove(&dev->mode_config.object_idr, object->id); 113 object->id = 0; 114 } 115 mutex_unlock(&dev->mode_config.idr_mutex); 116 } 117 118 /** 119 * drm_mode_object_lease_required - check types which must be leased to be used 120 * @type: type of object 121 * 122 * Returns whether the provided type of drm_mode_object must 123 * be owned or leased to be used by a process. 124 */ 125 bool drm_mode_object_lease_required(uint32_t type) 126 { 127 switch(type) { 128 case DRM_MODE_OBJECT_CRTC: 129 case DRM_MODE_OBJECT_CONNECTOR: 130 case DRM_MODE_OBJECT_PLANE: 131 return true; 132 default: 133 return false; 134 } 135 } 136 137 struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, 138 struct drm_file *file_priv, 139 uint32_t id, uint32_t type) 140 { 141 struct drm_mode_object *obj = NULL; 142 143 mutex_lock(&dev->mode_config.idr_mutex); 144 obj = idr_find(&dev->mode_config.object_idr, id); 145 if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) 146 obj = NULL; 147 if (obj && obj->id != id) 148 obj = NULL; 149 150 #ifdef notyet 151 if (obj && drm_mode_object_lease_required(obj->type) && 152 !_drm_lease_held(file_priv, obj->id)) 153 obj = NULL; 154 #endif 155 156 if (obj && obj->free_cb) { 157 if (!kref_get_unless_zero(&obj->refcount)) 158 obj = NULL; 159 } 160 mutex_unlock(&dev->mode_config.idr_mutex); 161 162 return obj; 163 } 164 165 /** 166 * drm_mode_object_find - look up a drm object with static lifetime 167 * @dev: drm device 168 * @file_priv: drm file 169 * @id: id of the mode object 170 * @type: type of the mode object 171 * 172 * This function is used to look up a modeset object. It will acquire a 173 * reference for reference counted objects. This reference must be dropped again 174 * by callind drm_mode_object_put(). 175 */ 176 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 177 struct drm_file *file_priv, 178 uint32_t id, uint32_t type) 179 { 180 struct drm_mode_object *obj = NULL; 181 182 obj = __drm_mode_object_find(dev, file_priv, id, type); 183 return obj; 184 } 185 EXPORT_SYMBOL(drm_mode_object_find); 186 187 /** 188 * drm_mode_object_put - release a mode object reference 189 * @obj: DRM mode object 190 * 191 * This function decrements the object's refcount if it is a refcounted modeset 192 * object. It is a no-op on any other object. This is used to drop references 193 * acquired with drm_mode_object_get(). 194 */ 195 void drm_mode_object_put(struct drm_mode_object *obj) 196 { 197 if (obj->free_cb) { 198 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 199 kref_put(&obj->refcount, obj->free_cb); 200 } 201 } 202 EXPORT_SYMBOL(drm_mode_object_put); 203 204 /** 205 * drm_mode_object_get - acquire a mode object reference 206 * @obj: DRM mode object 207 * 208 * This function increments the object's refcount if it is a refcounted modeset 209 * object. It is a no-op on any other object. References should be dropped again 210 * by calling drm_mode_object_put(). 211 */ 212 void drm_mode_object_get(struct drm_mode_object *obj) 213 { 214 if (obj->free_cb) { 215 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 216 kref_get(&obj->refcount); 217 } 218 } 219 EXPORT_SYMBOL(drm_mode_object_get); 220 221 /** 222 * drm_object_attach_property - attach a property to a modeset object 223 * @obj: drm modeset object 224 * @property: property to attach 225 * @init_val: initial value of the property 226 * 227 * This attaches the given property to the modeset object with the given initial 228 * value. Currently this function cannot fail since the properties are stored in 229 * a statically sized array. 230 * 231 * Note that all properties must be attached before the object itself is 232 * registered and accessible from userspace. 233 */ 234 void drm_object_attach_property(struct drm_mode_object *obj, 235 struct drm_property *property, 236 uint64_t init_val) 237 { 238 int count = obj->properties->count; 239 struct drm_device *dev = property->dev; 240 241 242 if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { 243 struct drm_connector *connector = obj_to_connector(obj); 244 245 WARN_ON(!dev->driver->load && 246 connector->registration_state == DRM_CONNECTOR_REGISTERED); 247 } else { 248 WARN_ON(!dev->driver->load && dev->registered); 249 } 250 251 if (count == DRM_OBJECT_MAX_PROPERTY) { 252 WARN(1, "Failed to attach object property (type: 0x%x). Please " 253 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 254 "you see this message on the same object type.\n", 255 obj->type); 256 return; 257 } 258 259 obj->properties->properties[count] = property; 260 obj->properties->values[count] = init_val; 261 obj->properties->count++; 262 } 263 EXPORT_SYMBOL(drm_object_attach_property); 264 265 /** 266 * drm_object_property_set_value - set the value of a property 267 * @obj: drm mode object to set property value for 268 * @property: property to set 269 * @val: value the property should be set to 270 * 271 * This function sets a given property on a given object. This function only 272 * changes the software state of the property, it does not call into the 273 * driver's ->set_property callback. 274 * 275 * Note that atomic drivers should not have any need to call this, the core will 276 * ensure consistency of values reported back to userspace through the 277 * appropriate ->atomic_get_property callback. Only legacy drivers should call 278 * this function to update the tracked value (after clamping and other 279 * restrictions have been applied). 280 * 281 * Returns: 282 * Zero on success, error code on failure. 283 */ 284 int drm_object_property_set_value(struct drm_mode_object *obj, 285 struct drm_property *property, uint64_t val) 286 { 287 int i; 288 289 WARN_ON(drm_drv_uses_atomic_modeset(property->dev) && 290 !(property->flags & DRM_MODE_PROP_IMMUTABLE)); 291 292 for (i = 0; i < obj->properties->count; i++) { 293 if (obj->properties->properties[i] == property) { 294 obj->properties->values[i] = val; 295 return 0; 296 } 297 } 298 299 return -EINVAL; 300 } 301 EXPORT_SYMBOL(drm_object_property_set_value); 302 303 static int __drm_object_property_get_prop_value(struct drm_mode_object *obj, 304 struct drm_property *property, 305 uint64_t *val) 306 { 307 int i; 308 309 for (i = 0; i < obj->properties->count; i++) { 310 if (obj->properties->properties[i] == property) { 311 *val = obj->properties->values[i]; 312 return 0; 313 } 314 } 315 316 return -EINVAL; 317 } 318 319 static int __drm_object_property_get_value(struct drm_mode_object *obj, 320 struct drm_property *property, 321 uint64_t *val) 322 { 323 324 #ifdef __OpenBSD__ 325 if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { 326 struct drm_connector *connector = obj_to_connector(obj); 327 328 if (property == connector->backlight_property) { 329 struct backlight_device *bd = 330 connector->backlight_device; 331 332 if (bd->props.type == BACKLIGHT_FIRMWARE) 333 *val = bd->ops->get_brightness(bd); 334 else 335 *val = bd->props.brightness; 336 return 0; 337 } 338 } 339 #endif 340 341 /* read-only properties bypass atomic mechanism and still store 342 * their value in obj->properties->values[].. mostly to avoid 343 * having to deal w/ EDID and similar props in atomic paths: 344 */ 345 if (drm_drv_uses_atomic_modeset(property->dev) && 346 !(property->flags & DRM_MODE_PROP_IMMUTABLE)) 347 return drm_atomic_get_property(obj, property, val); 348 349 return __drm_object_property_get_prop_value(obj, property, val); 350 } 351 352 /** 353 * drm_object_property_get_value - retrieve the value of a property 354 * @obj: drm mode object to get property value from 355 * @property: property to retrieve 356 * @val: storage for the property value 357 * 358 * This function retrieves the softare state of the given property for the given 359 * property. Since there is no driver callback to retrieve the current property 360 * value this might be out of sync with the hardware, depending upon the driver 361 * and property. 362 * 363 * Atomic drivers should never call this function directly, the core will read 364 * out property values through the various ->atomic_get_property callbacks. 365 * 366 * Returns: 367 * Zero on success, error code on failure. 368 */ 369 int drm_object_property_get_value(struct drm_mode_object *obj, 370 struct drm_property *property, uint64_t *val) 371 { 372 WARN_ON(drm_drv_uses_atomic_modeset(property->dev)); 373 374 return __drm_object_property_get_value(obj, property, val); 375 } 376 EXPORT_SYMBOL(drm_object_property_get_value); 377 378 /** 379 * drm_object_property_get_default_value - retrieve the default value of a 380 * property when in atomic mode. 381 * @obj: drm mode object to get property value from 382 * @property: property to retrieve 383 * @val: storage for the property value 384 * 385 * This function retrieves the default state of the given property as passed in 386 * to drm_object_attach_property 387 * 388 * Only atomic drivers should call this function directly, as for non-atomic 389 * drivers it will return the current value. 390 * 391 * Returns: 392 * Zero on success, error code on failure. 393 */ 394 int drm_object_property_get_default_value(struct drm_mode_object *obj, 395 struct drm_property *property, 396 uint64_t *val) 397 { 398 WARN_ON(!drm_drv_uses_atomic_modeset(property->dev)); 399 400 return __drm_object_property_get_prop_value(obj, property, val); 401 } 402 EXPORT_SYMBOL(drm_object_property_get_default_value); 403 404 /* helper for getconnector and getproperties ioctls */ 405 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, 406 uint32_t __user *prop_ptr, 407 uint64_t __user *prop_values, 408 uint32_t *arg_count_props) 409 { 410 int i, ret, count; 411 412 for (i = 0, count = 0; i < obj->properties->count; i++) { 413 struct drm_property *prop = obj->properties->properties[i]; 414 uint64_t val; 415 416 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) 417 continue; 418 419 if (*arg_count_props > count) { 420 ret = __drm_object_property_get_value(obj, prop, &val); 421 if (ret) 422 return ret; 423 424 if (put_user(prop->base.id, prop_ptr + count)) 425 return -EFAULT; 426 427 if (put_user(val, prop_values + count)) 428 return -EFAULT; 429 } 430 431 count++; 432 } 433 *arg_count_props = count; 434 435 return 0; 436 } 437 438 /** 439 * drm_mode_obj_get_properties_ioctl - get the current value of a object's property 440 * @dev: DRM device 441 * @data: ioctl data 442 * @file_priv: DRM file info 443 * 444 * This function retrieves the current value for an object's property. Compared 445 * to the connector specific ioctl this one is extended to also work on crtc and 446 * plane objects. 447 * 448 * Called by the user via ioctl. 449 * 450 * Returns: 451 * Zero on success, negative errno on failure. 452 */ 453 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 454 struct drm_file *file_priv) 455 { 456 struct drm_mode_obj_get_properties *arg = data; 457 struct drm_mode_object *obj; 458 struct drm_modeset_acquire_ctx ctx; 459 int ret = 0; 460 461 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 462 return -EOPNOTSUPP; 463 464 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 465 466 obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 467 if (!obj) { 468 ret = -ENOENT; 469 goto out; 470 } 471 if (!obj->properties) { 472 ret = -EINVAL; 473 goto out_unref; 474 } 475 476 ret = drm_mode_object_get_properties(obj, file_priv->atomic, 477 (uint32_t __user *)(unsigned long)(arg->props_ptr), 478 (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), 479 &arg->count_props); 480 481 out_unref: 482 drm_mode_object_put(obj); 483 out: 484 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 485 return ret; 486 } 487 488 struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, 489 uint32_t prop_id) 490 { 491 int i; 492 493 for (i = 0; i < obj->properties->count; i++) 494 if (obj->properties->properties[i]->base.id == prop_id) 495 return obj->properties->properties[i]; 496 497 return NULL; 498 } 499 500 static int set_property_legacy(struct drm_mode_object *obj, 501 struct drm_property *prop, 502 uint64_t prop_value) 503 { 504 struct drm_device *dev = prop->dev; 505 struct drm_mode_object *ref; 506 struct drm_modeset_acquire_ctx ctx; 507 int ret = -EINVAL; 508 509 if (!drm_property_change_valid_get(prop, prop_value, &ref)) 510 return -EINVAL; 511 512 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 513 switch (obj->type) { 514 case DRM_MODE_OBJECT_CONNECTOR: 515 ret = drm_connector_set_obj_prop(obj, prop, prop_value); 516 break; 517 case DRM_MODE_OBJECT_CRTC: 518 ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value); 519 break; 520 case DRM_MODE_OBJECT_PLANE: 521 ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj), 522 prop, prop_value); 523 break; 524 } 525 drm_property_change_valid_put(prop, ref); 526 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 527 528 return ret; 529 } 530 531 static int set_property_atomic(struct drm_mode_object *obj, 532 struct drm_file *file_priv, 533 struct drm_property *prop, 534 uint64_t prop_value) 535 { 536 struct drm_device *dev = prop->dev; 537 struct drm_atomic_state *state; 538 struct drm_modeset_acquire_ctx ctx; 539 int ret; 540 541 state = drm_atomic_state_alloc(dev); 542 if (!state) 543 return -ENOMEM; 544 545 drm_modeset_acquire_init(&ctx, 0); 546 state->acquire_ctx = &ctx; 547 548 retry: 549 if (prop == state->dev->mode_config.dpms_property) { 550 if (obj->type != DRM_MODE_OBJECT_CONNECTOR) { 551 ret = -EINVAL; 552 goto out; 553 } 554 555 ret = drm_atomic_connector_commit_dpms(state, 556 obj_to_connector(obj), 557 prop_value); 558 #ifdef __OpenBSD__ 559 } else if (obj->type == DRM_MODE_OBJECT_CONNECTOR && 560 prop == (obj_to_connector(obj))->backlight_property) { 561 struct drm_connector *connector = obj_to_connector(obj); 562 connector->backlight_device->props.brightness = prop_value; 563 backlight_schedule_update_status(connector->backlight_device); 564 knote_locked(&connector->dev->note, NOTE_CHANGE); 565 ret = 0; 566 #endif 567 } else { 568 ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value); 569 if (ret) 570 goto out; 571 ret = drm_atomic_commit(state); 572 } 573 out: 574 if (ret == -EDEADLK) { 575 drm_atomic_state_clear(state); 576 drm_modeset_backoff(&ctx); 577 goto retry; 578 } 579 580 drm_atomic_state_put(state); 581 582 drm_modeset_drop_locks(&ctx); 583 drm_modeset_acquire_fini(&ctx); 584 585 return ret; 586 } 587 588 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 589 struct drm_file *file_priv) 590 { 591 struct drm_mode_obj_set_property *arg = data; 592 struct drm_mode_object *arg_obj; 593 struct drm_property *property; 594 int ret = -EINVAL; 595 596 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 597 return -EOPNOTSUPP; 598 599 arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 600 if (!arg_obj) 601 return -ENOENT; 602 603 if (!arg_obj->properties) 604 goto out_unref; 605 606 property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id); 607 if (!property) 608 goto out_unref; 609 610 if (drm_drv_uses_atomic_modeset(property->dev)) 611 ret = set_property_atomic(arg_obj, file_priv, property, arg->value); 612 else 613 ret = set_property_legacy(arg_obj, property, arg->value); 614 615 out_unref: 616 drm_mode_object_put(arg_obj); 617 return ret; 618 } 619