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 */ 40int __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 */ 80int 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 86void 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 */ 105void 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 */ 125bool 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 137struct 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 drm_dbg_kms(dev, "[OBJECT:%d] not included in lease", id); 154 obj = NULL; 155 } 156#endif 157 158 if (obj && obj->free_cb) { 159 if (!kref_get_unless_zero(&obj->refcount)) 160 obj = NULL; 161 } 162 mutex_unlock(&dev->mode_config.idr_mutex); 163 164 return obj; 165} 166 167/** 168 * drm_mode_object_find - look up a drm object with static lifetime 169 * @dev: drm device 170 * @file_priv: drm file 171 * @id: id of the mode object 172 * @type: type of the mode object 173 * 174 * This function is used to look up a modeset object. It will acquire a 175 * reference for reference counted objects. This reference must be dropped again 176 * by callind drm_mode_object_put(). 177 */ 178struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 179 struct drm_file *file_priv, 180 uint32_t id, uint32_t type) 181{ 182 struct drm_mode_object *obj = NULL; 183 184 obj = __drm_mode_object_find(dev, file_priv, id, type); 185 return obj; 186} 187EXPORT_SYMBOL(drm_mode_object_find); 188 189/** 190 * drm_mode_object_put - release a mode object reference 191 * @obj: DRM mode object 192 * 193 * This function decrements the object's refcount if it is a refcounted modeset 194 * object. It is a no-op on any other object. This is used to drop references 195 * acquired with drm_mode_object_get(). 196 */ 197void drm_mode_object_put(struct drm_mode_object *obj) 198{ 199 if (obj->free_cb) { 200 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 201 kref_put(&obj->refcount, obj->free_cb); 202 } 203} 204EXPORT_SYMBOL(drm_mode_object_put); 205 206/** 207 * drm_mode_object_get - acquire a mode object reference 208 * @obj: DRM mode object 209 * 210 * This function increments the object's refcount if it is a refcounted modeset 211 * object. It is a no-op on any other object. References should be dropped again 212 * by calling drm_mode_object_put(). 213 */ 214void drm_mode_object_get(struct drm_mode_object *obj) 215{ 216 if (obj->free_cb) { 217 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 218 kref_get(&obj->refcount); 219 } 220} 221EXPORT_SYMBOL(drm_mode_object_get); 222 223/** 224 * drm_object_attach_property - attach a property to a modeset object 225 * @obj: drm modeset object 226 * @property: property to attach 227 * @init_val: initial value of the property 228 * 229 * This attaches the given property to the modeset object with the given initial 230 * value. Currently this function cannot fail since the properties are stored in 231 * a statically sized array. 232 * 233 * Note that all properties must be attached before the object itself is 234 * registered and accessible from userspace. 235 */ 236void drm_object_attach_property(struct drm_mode_object *obj, 237 struct drm_property *property, 238 uint64_t init_val) 239{ 240 int count = obj->properties->count; 241 struct drm_device *dev = property->dev; 242 243 244 if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { 245 struct drm_connector *connector = obj_to_connector(obj); 246 247 WARN_ON(!dev->driver->load && 248 connector->registration_state == DRM_CONNECTOR_REGISTERED); 249 } else { 250 WARN_ON(!dev->driver->load && dev->registered); 251 } 252 253 if (count == DRM_OBJECT_MAX_PROPERTY) { 254 WARN(1, "Failed to attach object property (type: 0x%x). Please " 255 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 256 "you see this message on the same object type.\n", 257 obj->type); 258 return; 259 } 260 261 obj->properties->properties[count] = property; 262 obj->properties->values[count] = init_val; 263 obj->properties->count++; 264} 265EXPORT_SYMBOL(drm_object_attach_property); 266 267/** 268 * drm_object_property_set_value - set the value of a property 269 * @obj: drm mode object to set property value for 270 * @property: property to set 271 * @val: value the property should be set to 272 * 273 * This function sets a given property on a given object. This function only 274 * changes the software state of the property, it does not call into the 275 * driver's ->set_property callback. 276 * 277 * Note that atomic drivers should not have any need to call this, the core will 278 * ensure consistency of values reported back to userspace through the 279 * appropriate ->atomic_get_property callback. Only legacy drivers should call 280 * this function to update the tracked value (after clamping and other 281 * restrictions have been applied). 282 * 283 * Returns: 284 * Zero on success, error code on failure. 285 */ 286int drm_object_property_set_value(struct drm_mode_object *obj, 287 struct drm_property *property, uint64_t val) 288{ 289 int i; 290 291 WARN_ON(drm_drv_uses_atomic_modeset(property->dev) && 292 !(property->flags & DRM_MODE_PROP_IMMUTABLE)); 293 294 for (i = 0; i < obj->properties->count; i++) { 295 if (obj->properties->properties[i] == property) { 296 obj->properties->values[i] = val; 297 return 0; 298 } 299 } 300 301 return -EINVAL; 302} 303EXPORT_SYMBOL(drm_object_property_set_value); 304 305static int __drm_object_property_get_prop_value(struct drm_mode_object *obj, 306 struct drm_property *property, 307 uint64_t *val) 308{ 309 int i; 310 311 for (i = 0; i < obj->properties->count; i++) { 312 if (obj->properties->properties[i] == property) { 313 *val = obj->properties->values[i]; 314 return 0; 315 } 316 } 317 318 return -EINVAL; 319} 320 321static int __drm_object_property_get_value(struct drm_mode_object *obj, 322 struct drm_property *property, 323 uint64_t *val) 324{ 325 326#ifdef __OpenBSD__ 327 if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { 328 struct drm_connector *connector = obj_to_connector(obj); 329 330 if (property == connector->backlight_property) { 331 struct backlight_device *bd = 332 connector->backlight_device; 333 334 if (bd->props.type == BACKLIGHT_FIRMWARE) 335 *val = bd->ops->get_brightness(bd); 336 else 337 *val = bd->props.brightness; 338 return 0; 339 } 340 } 341#endif 342 343 /* read-only properties bypass atomic mechanism and still store 344 * their value in obj->properties->values[].. mostly to avoid 345 * having to deal w/ EDID and similar props in atomic paths: 346 */ 347 if (drm_drv_uses_atomic_modeset(property->dev) && 348 !(property->flags & DRM_MODE_PROP_IMMUTABLE)) 349 return drm_atomic_get_property(obj, property, val); 350 351 return __drm_object_property_get_prop_value(obj, property, val); 352} 353 354/** 355 * drm_object_property_get_value - retrieve the value of a property 356 * @obj: drm mode object to get property value from 357 * @property: property to retrieve 358 * @val: storage for the property value 359 * 360 * This function retrieves the softare state of the given property for the given 361 * property. Since there is no driver callback to retrieve the current property 362 * value this might be out of sync with the hardware, depending upon the driver 363 * and property. 364 * 365 * Atomic drivers should never call this function directly, the core will read 366 * out property values through the various ->atomic_get_property callbacks. 367 * 368 * Returns: 369 * Zero on success, error code on failure. 370 */ 371int drm_object_property_get_value(struct drm_mode_object *obj, 372 struct drm_property *property, uint64_t *val) 373{ 374 WARN_ON(drm_drv_uses_atomic_modeset(property->dev)); 375 376 return __drm_object_property_get_value(obj, property, val); 377} 378EXPORT_SYMBOL(drm_object_property_get_value); 379 380/** 381 * drm_object_property_get_default_value - retrieve the default value of a 382 * property when in atomic mode. 383 * @obj: drm mode object to get property value from 384 * @property: property to retrieve 385 * @val: storage for the property value 386 * 387 * This function retrieves the default state of the given property as passed in 388 * to drm_object_attach_property 389 * 390 * Only atomic drivers should call this function directly, as for non-atomic 391 * drivers it will return the current value. 392 * 393 * Returns: 394 * Zero on success, error code on failure. 395 */ 396int drm_object_property_get_default_value(struct drm_mode_object *obj, 397 struct drm_property *property, 398 uint64_t *val) 399{ 400 WARN_ON(!drm_drv_uses_atomic_modeset(property->dev)); 401 402 return __drm_object_property_get_prop_value(obj, property, val); 403} 404EXPORT_SYMBOL(drm_object_property_get_default_value); 405 406/* helper for getconnector and getproperties ioctls */ 407int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, 408 uint32_t __user *prop_ptr, 409 uint64_t __user *prop_values, 410 uint32_t *arg_count_props) 411{ 412 int i, ret, count; 413 414 for (i = 0, count = 0; i < obj->properties->count; i++) { 415 struct drm_property *prop = obj->properties->properties[i]; 416 uint64_t val; 417 418 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) 419 continue; 420 421 if (*arg_count_props > count) { 422 ret = __drm_object_property_get_value(obj, prop, &val); 423 if (ret) 424 return ret; 425 426 if (put_user(prop->base.id, prop_ptr + count)) 427 return -EFAULT; 428 429 if (put_user(val, prop_values + count)) 430 return -EFAULT; 431 } 432 433 count++; 434 } 435 *arg_count_props = count; 436 437 return 0; 438} 439 440/** 441 * drm_mode_obj_get_properties_ioctl - get the current value of a object's property 442 * @dev: DRM device 443 * @data: ioctl data 444 * @file_priv: DRM file info 445 * 446 * This function retrieves the current value for an object's property. Compared 447 * to the connector specific ioctl this one is extended to also work on crtc and 448 * plane objects. 449 * 450 * Called by the user via ioctl. 451 * 452 * Returns: 453 * Zero on success, negative errno on failure. 454 */ 455int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 456 struct drm_file *file_priv) 457{ 458 struct drm_mode_obj_get_properties *arg = data; 459 struct drm_mode_object *obj; 460 struct drm_modeset_acquire_ctx ctx; 461 int ret = 0; 462 463 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 464 return -EOPNOTSUPP; 465 466 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 467 468 obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 469 if (!obj) { 470 ret = -ENOENT; 471 goto out; 472 } 473 if (!obj->properties) { 474 ret = -EINVAL; 475 goto out_unref; 476 } 477 478 ret = drm_mode_object_get_properties(obj, file_priv->atomic, 479 (uint32_t __user *)(unsigned long)(arg->props_ptr), 480 (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), 481 &arg->count_props); 482 483out_unref: 484 drm_mode_object_put(obj); 485out: 486 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 487 return ret; 488} 489 490struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, 491 uint32_t prop_id) 492{ 493 int i; 494 495 for (i = 0; i < obj->properties->count; i++) 496 if (obj->properties->properties[i]->base.id == prop_id) 497 return obj->properties->properties[i]; 498 499 return NULL; 500} 501 502static int set_property_legacy(struct drm_mode_object *obj, 503 struct drm_property *prop, 504 uint64_t prop_value) 505{ 506 struct drm_device *dev = prop->dev; 507 struct drm_mode_object *ref; 508 struct drm_modeset_acquire_ctx ctx; 509 int ret = -EINVAL; 510 511 if (!drm_property_change_valid_get(prop, prop_value, &ref)) 512 return -EINVAL; 513 514 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 515 switch (obj->type) { 516 case DRM_MODE_OBJECT_CONNECTOR: 517 ret = drm_connector_set_obj_prop(obj, prop, prop_value); 518 break; 519 case DRM_MODE_OBJECT_CRTC: 520 ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value); 521 break; 522 case DRM_MODE_OBJECT_PLANE: 523 ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj), 524 prop, prop_value); 525 break; 526 } 527 drm_property_change_valid_put(prop, ref); 528 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 529 530 return ret; 531} 532 533static int set_property_atomic(struct drm_mode_object *obj, 534 struct drm_file *file_priv, 535 struct drm_property *prop, 536 uint64_t prop_value) 537{ 538 struct drm_device *dev = prop->dev; 539 struct drm_atomic_state *state; 540 struct drm_modeset_acquire_ctx ctx; 541 int ret; 542 543 state = drm_atomic_state_alloc(dev); 544 if (!state) 545 return -ENOMEM; 546 547 drm_modeset_acquire_init(&ctx, 0); 548 state->acquire_ctx = &ctx; 549 550retry: 551 if (prop == state->dev->mode_config.dpms_property) { 552 if (obj->type != DRM_MODE_OBJECT_CONNECTOR) { 553 ret = -EINVAL; 554 goto out; 555 } 556 557 ret = drm_atomic_connector_commit_dpms(state, 558 obj_to_connector(obj), 559 prop_value); 560#ifdef __OpenBSD__ 561 } else if (obj->type == DRM_MODE_OBJECT_CONNECTOR && 562 prop == (obj_to_connector(obj))->backlight_property) { 563 struct drm_connector *connector = obj_to_connector(obj); 564 connector->backlight_device->props.brightness = prop_value; 565 backlight_schedule_update_status(connector->backlight_device); 566 knote_locked(&connector->dev->note, NOTE_CHANGE); 567 ret = 0; 568#endif 569 } else { 570 ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value); 571 if (ret) 572 goto out; 573 ret = drm_atomic_commit(state); 574 } 575out: 576 if (ret == -EDEADLK) { 577 drm_atomic_state_clear(state); 578 drm_modeset_backoff(&ctx); 579 goto retry; 580 } 581 582 drm_atomic_state_put(state); 583 584 drm_modeset_drop_locks(&ctx); 585 drm_modeset_acquire_fini(&ctx); 586 587 return ret; 588} 589 590int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 591 struct drm_file *file_priv) 592{ 593 struct drm_mode_obj_set_property *arg = data; 594 struct drm_mode_object *arg_obj; 595 struct drm_property *property; 596 int ret = -EINVAL; 597 598 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 599 return -EOPNOTSUPP; 600 601 arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 602 if (!arg_obj) 603 return -ENOENT; 604 605 if (!arg_obj->properties) 606 goto out_unref; 607 608 property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id); 609 if (!property) 610 goto out_unref; 611 612 if (drm_drv_uses_atomic_modeset(property->dev)) 613 ret = set_property_atomic(arg_obj, file_priv, property, arg->value); 614 else 615 ret = set_property_legacy(arg_obj, property, arg->value); 616 617out_unref: 618 drm_mode_object_put(arg_obj); 619 return ret; 620} 621