1 /* 2 * Copyright (c) 2006-2008 Intel Corporation 3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 4 * Copyright (c) 2008 Red Hat Inc. 5 * 6 * DRM core CRTC related functions 7 * 8 * Permission to use, copy, modify, distribute, and sell this software and its 9 * documentation for any purpose is hereby granted without fee, provided that 10 * the above copyright notice appear in all copies and that both that copyright 11 * notice and this permission notice appear in supporting documentation, and 12 * that the name of the copyright holders not be used in advertising or 13 * publicity pertaining to distribution of the software without specific, 14 * written prior permission. The copyright holders make no representations 15 * about the suitability of this software for any purpose. It is provided "as 16 * is" without express or implied warranty. 17 * 18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 * 26 * Authors: 27 * Keith Packard 28 * Eric Anholt <eric@anholt.net> 29 * Dave Airlie <airlied@linux.ie> 30 * Jesse Barnes <jesse.barnes@intel.com> 31 */ 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <dev/drm2/drm.h> 36 #include <dev/drm2/drmP.h> 37 #include <dev/drm2/drm_crtc.h> 38 #include <dev/drm2/drm_edid.h> 39 #include <dev/drm2/drm_fourcc.h> 40 #include <sys/limits.h> 41 42 /* Avoid boilerplate. I'm tired of typing. */ 43 #define DRM_ENUM_NAME_FN(fnname, list) \ 44 char *fnname(int val) \ 45 { \ 46 int i; \ 47 for (i = 0; i < DRM_ARRAY_SIZE(list); i++) { \ 48 if (list[i].type == val) \ 49 return list[i].name; \ 50 } \ 51 return "(unknown)"; \ 52 } 53 54 /* 55 * Global properties 56 */ 57 static struct drm_prop_enum_list drm_dpms_enum_list[] = 58 { { DRM_MODE_DPMS_ON, "On" }, 59 { DRM_MODE_DPMS_STANDBY, "Standby" }, 60 { DRM_MODE_DPMS_SUSPEND, "Suspend" }, 61 { DRM_MODE_DPMS_OFF, "Off" } 62 }; 63 64 DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) 65 66 /* 67 * Optional properties 68 */ 69 static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = 70 { 71 { DRM_MODE_SCALE_NONE, "None" }, 72 { DRM_MODE_SCALE_FULLSCREEN, "Full" }, 73 { DRM_MODE_SCALE_CENTER, "Center" }, 74 { DRM_MODE_SCALE_ASPECT, "Full aspect" }, 75 }; 76 77 static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = 78 { 79 { DRM_MODE_DITHERING_OFF, "Off" }, 80 { DRM_MODE_DITHERING_ON, "On" }, 81 { DRM_MODE_DITHERING_AUTO, "Automatic" }, 82 }; 83 84 /* 85 * Non-global properties, but "required" for certain connectors. 86 */ 87 static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = 88 { 89 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ 90 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ 91 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ 92 }; 93 94 DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) 95 96 static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = 97 { 98 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ 99 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ 100 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ 101 }; 102 103 DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, 104 drm_dvi_i_subconnector_enum_list) 105 106 static struct drm_prop_enum_list drm_tv_select_enum_list[] = 107 { 108 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ 109 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ 110 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ 111 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ 112 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ 113 }; 114 115 DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) 116 117 static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = 118 { 119 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ 120 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ 121 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ 122 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ 123 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ 124 }; 125 126 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, 127 drm_tv_subconnector_enum_list) 128 129 static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { 130 { DRM_MODE_DIRTY_OFF, "Off" }, 131 { DRM_MODE_DIRTY_ON, "On" }, 132 { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, 133 }; 134 135 DRM_ENUM_NAME_FN(drm_get_dirty_info_name, 136 drm_dirty_info_enum_list) 137 138 struct drm_conn_prop_enum_list { 139 int type; 140 char *name; 141 int count; 142 }; 143 144 /* 145 * Connector and encoder types. 146 */ 147 static struct drm_conn_prop_enum_list drm_connector_enum_list[] = 148 { { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 }, 149 { DRM_MODE_CONNECTOR_VGA, "VGA", 0 }, 150 { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 }, 151 { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 }, 152 { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 }, 153 { DRM_MODE_CONNECTOR_Composite, "Composite", 0 }, 154 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, 155 { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, 156 { DRM_MODE_CONNECTOR_Component, "Component", 0 }, 157 { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 }, 158 { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 }, 159 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 }, 160 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, 161 { DRM_MODE_CONNECTOR_TV, "TV", 0 }, 162 { DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, 163 }; 164 165 static struct drm_prop_enum_list drm_encoder_enum_list[] = 166 { { DRM_MODE_ENCODER_NONE, "None" }, 167 { DRM_MODE_ENCODER_DAC, "DAC" }, 168 { DRM_MODE_ENCODER_TMDS, "TMDS" }, 169 { DRM_MODE_ENCODER_LVDS, "LVDS" }, 170 { DRM_MODE_ENCODER_TVDAC, "TV" }, 171 }; 172 173 static void drm_property_destroy_blob(struct drm_device *dev, 174 struct drm_property_blob *blob); 175 176 char *drm_get_encoder_name(struct drm_encoder *encoder) 177 { 178 static char buf[32]; 179 180 snprintf(buf, 32, "%s-%d", 181 drm_encoder_enum_list[encoder->encoder_type].name, 182 encoder->base.id); 183 return buf; 184 } 185 186 char *drm_get_connector_name(struct drm_connector *connector) 187 { 188 static char buf[32]; 189 190 snprintf(buf, 32, "%s-%d", 191 drm_connector_enum_list[connector->connector_type].name, 192 connector->connector_type_id); 193 return buf; 194 } 195 196 char *drm_get_connector_status_name(enum drm_connector_status status) 197 { 198 if (status == connector_status_connected) 199 return "connected"; 200 else if (status == connector_status_disconnected) 201 return "disconnected"; 202 else 203 return "unknown"; 204 } 205 206 /** 207 * drm_mode_object_get - allocate a new identifier 208 * @dev: DRM device 209 * @ptr: object pointer, used to generate unique ID 210 * @type: object type 211 * 212 * LOCKING: 213 * 214 * Create a unique identifier based on @ptr in @dev's identifier space. Used 215 * for tracking modes, CRTCs and connectors. 216 * 217 * RETURNS: 218 * New unique (relative to other objects in @dev) integer identifier for the 219 * object. 220 */ 221 static int drm_mode_object_get(struct drm_device *dev, 222 struct drm_mode_object *obj, uint32_t obj_type) 223 { 224 int new_id; 225 int ret; 226 227 new_id = 0; 228 ret = drm_gem_name_create(&dev->mode_config.crtc_names, obj, &new_id); 229 if (ret != 0) 230 return (ret); 231 232 obj->id = new_id; 233 obj->type = obj_type; 234 return 0; 235 } 236 237 /** 238 * drm_mode_object_put - free an identifer 239 * @dev: DRM device 240 * @id: ID to free 241 * 242 * LOCKING: 243 * Caller must hold DRM mode_config lock. 244 * 245 * Free @id from @dev's unique identifier pool. 246 */ 247 static void drm_mode_object_put(struct drm_device *dev, 248 struct drm_mode_object *object) 249 { 250 251 drm_gem_names_remove(&dev->mode_config.crtc_names, object->id); 252 } 253 254 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 255 uint32_t id, uint32_t type) 256 { 257 struct drm_mode_object *obj; 258 259 obj = drm_gem_name_ref(&dev->mode_config.crtc_names, id, NULL); 260 if (!obj || (obj->type != type) || (obj->id != id)) 261 obj = NULL; 262 263 return obj; 264 } 265 266 /** 267 * drm_framebuffer_init - initialize a framebuffer 268 * @dev: DRM device 269 * 270 * LOCKING: 271 * Caller must hold mode config lock. 272 * 273 * Allocates an ID for the framebuffer's parent mode object, sets its mode 274 * functions & device file and adds it to the master fd list. 275 * 276 * RETURNS: 277 * Zero on success, error code on failure. 278 */ 279 int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, 280 const struct drm_framebuffer_funcs *funcs) 281 { 282 int ret; 283 284 DRM_MODE_CONFIG_ASSERT_LOCKED(dev); 285 286 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); 287 if (ret) 288 return ret; 289 290 fb->dev = dev; 291 fb->funcs = funcs; 292 dev->mode_config.num_fb++; 293 list_add(&fb->head, &dev->mode_config.fb_list); 294 295 return 0; 296 } 297 298 /** 299 * drm_framebuffer_cleanup - remove a framebuffer object 300 * @fb: framebuffer to remove 301 * 302 * LOCKING: 303 * Caller must hold mode config lock. 304 * 305 * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes 306 * it, setting it to NULL. 307 */ 308 void drm_framebuffer_cleanup(struct drm_framebuffer *fb) 309 { 310 struct drm_device *dev = fb->dev; 311 struct drm_crtc *crtc; 312 struct drm_plane *plane; 313 struct drm_mode_set set; 314 int ret; 315 316 DRM_MODE_CONFIG_ASSERT_LOCKED(dev); 317 318 /* remove from any CRTC */ 319 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 320 if (crtc->fb == fb) { 321 /* should turn off the crtc */ 322 memset(&set, 0, sizeof(struct drm_mode_set)); 323 set.crtc = crtc; 324 set.fb = NULL; 325 ret = crtc->funcs->set_config(&set); 326 if (ret) 327 DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); 328 } 329 } 330 331 list_for_each_entry(plane, &dev->mode_config.plane_list, head) { 332 if (plane->fb == fb) { 333 /* should turn off the crtc */ 334 ret = plane->funcs->disable_plane(plane); 335 if (ret) 336 DRM_ERROR("failed to disable plane with busy fb\n"); 337 /* disconnect the plane from the fb and crtc: */ 338 plane->fb = NULL; 339 plane->crtc = NULL; 340 } 341 } 342 343 drm_mode_object_put(dev, &fb->base); 344 list_del(&fb->head); 345 dev->mode_config.num_fb--; 346 } 347 348 /** 349 * drm_crtc_init - Initialise a new CRTC object 350 * @dev: DRM device 351 * @crtc: CRTC object to init 352 * @funcs: callbacks for the new CRTC 353 * 354 * LOCKING: 355 * Takes mode_config lock. 356 * 357 * Inits a new object created as base part of an driver crtc object. 358 * 359 * RETURNS: 360 * Zero on success, error code on failure. 361 */ 362 int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 363 const struct drm_crtc_funcs *funcs) 364 { 365 int ret; 366 367 crtc->dev = dev; 368 crtc->funcs = funcs; 369 370 sx_xlock(&dev->mode_config.mutex); 371 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 372 if (ret) 373 goto out; 374 375 crtc->base.properties = &crtc->properties; 376 377 list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 378 dev->mode_config.num_crtc++; 379 380 out: 381 sx_xunlock(&dev->mode_config.mutex); 382 383 return ret; 384 } 385 386 /** 387 * drm_crtc_cleanup - Cleans up the core crtc usage. 388 * @crtc: CRTC to cleanup 389 * 390 * LOCKING: 391 * Caller must hold mode config lock. 392 * 393 * Cleanup @crtc. Removes from drm modesetting space 394 * does NOT free object, caller does that. 395 */ 396 void drm_crtc_cleanup(struct drm_crtc *crtc) 397 { 398 struct drm_device *dev = crtc->dev; 399 400 DRM_MODE_CONFIG_ASSERT_LOCKED(dev); 401 402 if (crtc->gamma_store) { 403 free(crtc->gamma_store, DRM_MEM_KMS); 404 crtc->gamma_store = NULL; 405 } 406 407 drm_mode_object_put(dev, &crtc->base); 408 list_del(&crtc->head); 409 dev->mode_config.num_crtc--; 410 } 411 412 /** 413 * drm_mode_probed_add - add a mode to a connector's probed mode list 414 * @connector: connector the new mode 415 * @mode: mode data 416 * 417 * LOCKING: 418 * Caller must hold mode config lock. 419 * 420 * Add @mode to @connector's mode list for later use. 421 */ 422 void drm_mode_probed_add(struct drm_connector *connector, 423 struct drm_display_mode *mode) 424 { 425 426 DRM_MODE_CONFIG_ASSERT_LOCKED(connector->dev); 427 428 list_add(&mode->head, &connector->probed_modes); 429 } 430 431 /** 432 * drm_mode_remove - remove and free a mode 433 * @connector: connector list to modify 434 * @mode: mode to remove 435 * 436 * LOCKING: 437 * Caller must hold mode config lock. 438 * 439 * Remove @mode from @connector's mode list, then free it. 440 */ 441 void drm_mode_remove(struct drm_connector *connector, 442 struct drm_display_mode *mode) 443 { 444 445 DRM_MODE_CONFIG_ASSERT_LOCKED(connector->dev); 446 447 list_del(&mode->head); 448 drm_mode_destroy(connector->dev, mode); 449 } 450 451 /** 452 * drm_connector_init - Init a preallocated connector 453 * @dev: DRM device 454 * @connector: the connector to init 455 * @funcs: callbacks for this connector 456 * @name: user visible name of the connector 457 * 458 * LOCKING: 459 * Takes mode config lock. 460 * 461 * Initialises a preallocated connector. Connectors should be 462 * subclassed as part of driver connector objects. 463 * 464 * RETURNS: 465 * Zero on success, error code on failure. 466 */ 467 int drm_connector_init(struct drm_device *dev, 468 struct drm_connector *connector, 469 const struct drm_connector_funcs *funcs, 470 int connector_type) 471 { 472 int ret; 473 474 sx_xlock(&dev->mode_config.mutex); 475 476 ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); 477 if (ret) 478 goto out; 479 480 connector->base.properties = &connector->properties; 481 connector->dev = dev; 482 connector->funcs = funcs; 483 connector->connector_type = connector_type; 484 connector->connector_type_id = 485 ++drm_connector_enum_list[connector_type].count; /* TODO */ 486 INIT_LIST_HEAD(&connector->user_modes); 487 INIT_LIST_HEAD(&connector->probed_modes); 488 INIT_LIST_HEAD(&connector->modes); 489 connector->edid_blob_ptr = NULL; 490 491 list_add_tail(&connector->head, &dev->mode_config.connector_list); 492 dev->mode_config.num_connector++; 493 494 drm_connector_attach_property(connector, 495 dev->mode_config.edid_property, 0); 496 497 drm_connector_attach_property(connector, 498 dev->mode_config.dpms_property, 0); 499 500 out: 501 sx_xunlock(&dev->mode_config.mutex); 502 503 return ret; 504 } 505 506 /** 507 * drm_connector_cleanup - cleans up an initialised connector 508 * @connector: connector to cleanup 509 * 510 * LOCKING: 511 * Takes mode config lock. 512 * 513 * Cleans up the connector but doesn't free the object. 514 */ 515 void drm_connector_cleanup(struct drm_connector *connector) 516 { 517 struct drm_device *dev = connector->dev; 518 struct drm_display_mode *mode, *t; 519 520 list_for_each_entry_safe(mode, t, &connector->probed_modes, head) 521 drm_mode_remove(connector, mode); 522 523 list_for_each_entry_safe(mode, t, &connector->modes, head) 524 drm_mode_remove(connector, mode); 525 526 list_for_each_entry_safe(mode, t, &connector->user_modes, head) 527 drm_mode_remove(connector, mode); 528 529 sx_xlock(&dev->mode_config.mutex); 530 if (connector->edid_blob_ptr) 531 drm_property_destroy_blob(dev, connector->edid_blob_ptr); 532 drm_mode_object_put(dev, &connector->base); 533 list_del(&connector->head); 534 dev->mode_config.num_connector--; 535 sx_xunlock(&dev->mode_config.mutex); 536 } 537 538 int drm_encoder_init(struct drm_device *dev, 539 struct drm_encoder *encoder, 540 const struct drm_encoder_funcs *funcs, 541 int encoder_type) 542 { 543 int ret; 544 545 sx_xlock(&dev->mode_config.mutex); 546 547 ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); 548 if (ret) 549 goto out; 550 551 encoder->dev = dev; 552 encoder->encoder_type = encoder_type; 553 encoder->funcs = funcs; 554 555 list_add_tail(&encoder->head, &dev->mode_config.encoder_list); 556 dev->mode_config.num_encoder++; 557 558 out: 559 sx_xunlock(&dev->mode_config.mutex); 560 561 return ret; 562 } 563 564 void drm_encoder_cleanup(struct drm_encoder *encoder) 565 { 566 struct drm_device *dev = encoder->dev; 567 568 sx_xlock(&dev->mode_config.mutex); 569 drm_mode_object_put(dev, &encoder->base); 570 list_del(&encoder->head); 571 dev->mode_config.num_encoder--; 572 sx_xunlock(&dev->mode_config.mutex); 573 } 574 575 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 576 unsigned long possible_crtcs, 577 const struct drm_plane_funcs *funcs, 578 const uint32_t *formats, uint32_t format_count, 579 bool priv) 580 { 581 int ret; 582 583 sx_xlock(&dev->mode_config.mutex); 584 585 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 586 if (ret) 587 goto out; 588 589 plane->base.properties = &plane->properties; 590 plane->dev = dev; 591 plane->funcs = funcs; 592 plane->format_types = malloc(sizeof(uint32_t) * format_count, 593 DRM_MEM_KMS, M_WAITOK); 594 595 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); 596 plane->format_count = format_count; 597 plane->possible_crtcs = possible_crtcs; 598 599 /* private planes are not exposed to userspace, but depending on 600 * display hardware, might be convenient to allow sharing programming 601 * for the scanout engine with the crtc implementation. 602 */ 603 if (!priv) { 604 list_add_tail(&plane->head, &dev->mode_config.plane_list); 605 dev->mode_config.num_plane++; 606 } else { 607 INIT_LIST_HEAD(&plane->head); 608 } 609 610 out: 611 sx_xunlock(&dev->mode_config.mutex); 612 613 return ret; 614 } 615 616 void drm_plane_cleanup(struct drm_plane *plane) 617 { 618 struct drm_device *dev = plane->dev; 619 620 sx_xlock(&dev->mode_config.mutex); 621 free(plane->format_types, DRM_MEM_KMS); 622 drm_mode_object_put(dev, &plane->base); 623 /* if not added to a list, it must be a private plane */ 624 if (!list_empty(&plane->head)) { 625 list_del(&plane->head); 626 dev->mode_config.num_plane--; 627 } 628 sx_xunlock(&dev->mode_config.mutex); 629 } 630 631 /** 632 * drm_mode_create - create a new display mode 633 * @dev: DRM device 634 * 635 * LOCKING: 636 * Caller must hold DRM mode_config lock. 637 * 638 * Create a new drm_display_mode, give it an ID, and return it. 639 * 640 * RETURNS: 641 * Pointer to new mode on success, NULL on error. 642 */ 643 struct drm_display_mode *drm_mode_create(struct drm_device *dev) 644 { 645 struct drm_display_mode *nmode; 646 647 nmode = malloc(sizeof(struct drm_display_mode), DRM_MEM_KMS, 648 M_WAITOK | M_ZERO); 649 650 if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) { 651 free(nmode, DRM_MEM_KMS); 652 return (NULL); 653 } 654 return nmode; 655 } 656 657 /** 658 * drm_mode_destroy - remove a mode 659 * @dev: DRM device 660 * @mode: mode to remove 661 * 662 * LOCKING: 663 * Caller must hold mode config lock. 664 * 665 * Free @mode's unique identifier, then free it. 666 */ 667 void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) 668 { 669 if (!mode) 670 return; 671 672 drm_mode_object_put(dev, &mode->base); 673 674 free(mode, DRM_MEM_KMS); 675 } 676 677 static int drm_mode_create_standard_connector_properties(struct drm_device *dev) 678 { 679 struct drm_property *edid; 680 struct drm_property *dpms; 681 682 /* 683 * Standard properties (apply to all connectors) 684 */ 685 edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | 686 DRM_MODE_PROP_IMMUTABLE, 687 "EDID", 0); 688 dev->mode_config.edid_property = edid; 689 690 dpms = drm_property_create_enum(dev, 0, 691 "DPMS", drm_dpms_enum_list, 692 DRM_ARRAY_SIZE(drm_dpms_enum_list)); 693 dev->mode_config.dpms_property = dpms; 694 695 return 0; 696 } 697 698 /** 699 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties 700 * @dev: DRM device 701 * 702 * Called by a driver the first time a DVI-I connector is made. 703 */ 704 int drm_mode_create_dvi_i_properties(struct drm_device *dev) 705 { 706 struct drm_property *dvi_i_selector; 707 struct drm_property *dvi_i_subconnector; 708 709 if (dev->mode_config.dvi_i_select_subconnector_property) 710 return 0; 711 712 dvi_i_selector = 713 drm_property_create_enum(dev, 0, 714 "select subconnector", 715 drm_dvi_i_select_enum_list, 716 DRM_ARRAY_SIZE(drm_dvi_i_select_enum_list)); 717 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; 718 719 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 720 "subconnector", 721 drm_dvi_i_subconnector_enum_list, 722 DRM_ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); 723 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; 724 725 return 0; 726 } 727 728 /** 729 * drm_create_tv_properties - create TV specific connector properties 730 * @dev: DRM device 731 * @num_modes: number of different TV formats (modes) supported 732 * @modes: array of pointers to strings containing name of each format 733 * 734 * Called by a driver's TV initialization routine, this function creates 735 * the TV specific connector properties for a given device. Caller is 736 * responsible for allocating a list of format names and passing them to 737 * this routine. 738 */ 739 int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, 740 char *modes[]) 741 { 742 struct drm_property *tv_selector; 743 struct drm_property *tv_subconnector; 744 int i; 745 746 if (dev->mode_config.tv_select_subconnector_property) 747 return 0; 748 749 /* 750 * Basic connector properties 751 */ 752 tv_selector = drm_property_create_enum(dev, 0, 753 "select subconnector", 754 drm_tv_select_enum_list, 755 DRM_ARRAY_SIZE(drm_tv_select_enum_list)); 756 dev->mode_config.tv_select_subconnector_property = tv_selector; 757 758 tv_subconnector = 759 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 760 "subconnector", 761 drm_tv_subconnector_enum_list, 762 DRM_ARRAY_SIZE(drm_tv_subconnector_enum_list)); 763 dev->mode_config.tv_subconnector_property = tv_subconnector; 764 765 /* 766 * Other, TV specific properties: margins & TV modes. 767 */ 768 dev->mode_config.tv_left_margin_property = 769 drm_property_create_range(dev, 0, "left margin", 0, 100); 770 771 dev->mode_config.tv_right_margin_property = 772 drm_property_create_range(dev, 0, "right margin", 0, 100); 773 774 dev->mode_config.tv_top_margin_property = 775 drm_property_create_range(dev, 0, "top margin", 0, 100); 776 777 dev->mode_config.tv_bottom_margin_property = 778 drm_property_create_range(dev, 0, "bottom margin", 0, 100); 779 780 dev->mode_config.tv_mode_property = 781 drm_property_create(dev, DRM_MODE_PROP_ENUM, 782 "mode", num_modes); 783 for (i = 0; i < num_modes; i++) 784 drm_property_add_enum(dev->mode_config.tv_mode_property, i, 785 i, modes[i]); 786 787 dev->mode_config.tv_brightness_property = 788 drm_property_create_range(dev, 0, "brightness", 0, 100); 789 790 dev->mode_config.tv_contrast_property = 791 drm_property_create_range(dev, 0, "contrast", 0, 100); 792 793 dev->mode_config.tv_flicker_reduction_property = 794 drm_property_create_range(dev, 0, "flicker reduction", 0, 100); 795 796 dev->mode_config.tv_overscan_property = 797 drm_property_create_range(dev, 0, "overscan", 0, 100); 798 799 dev->mode_config.tv_saturation_property = 800 drm_property_create_range(dev, 0, "saturation", 0, 100); 801 802 dev->mode_config.tv_hue_property = 803 drm_property_create_range(dev, 0, "hue", 0, 100); 804 805 return 0; 806 } 807 808 /** 809 * drm_mode_create_scaling_mode_property - create scaling mode property 810 * @dev: DRM device 811 * 812 * Called by a driver the first time it's needed, must be attached to desired 813 * connectors. 814 */ 815 int drm_mode_create_scaling_mode_property(struct drm_device *dev) 816 { 817 struct drm_property *scaling_mode; 818 819 if (dev->mode_config.scaling_mode_property) 820 return 0; 821 822 scaling_mode = 823 drm_property_create_enum(dev, 0, "scaling mode", 824 drm_scaling_mode_enum_list, 825 DRM_ARRAY_SIZE(drm_scaling_mode_enum_list)); 826 827 dev->mode_config.scaling_mode_property = scaling_mode; 828 829 return 0; 830 } 831 832 /** 833 * drm_mode_create_dithering_property - create dithering property 834 * @dev: DRM device 835 * 836 * Called by a driver the first time it's needed, must be attached to desired 837 * connectors. 838 */ 839 int drm_mode_create_dithering_property(struct drm_device *dev) 840 { 841 struct drm_property *dithering_mode; 842 843 if (dev->mode_config.dithering_mode_property) 844 return 0; 845 846 dithering_mode = 847 drm_property_create_enum(dev, 0, "dithering", 848 drm_dithering_mode_enum_list, 849 DRM_ARRAY_SIZE(drm_dithering_mode_enum_list)); 850 dev->mode_config.dithering_mode_property = dithering_mode; 851 852 return 0; 853 } 854 855 /** 856 * drm_mode_create_dirty_property - create dirty property 857 * @dev: DRM device 858 * 859 * Called by a driver the first time it's needed, must be attached to desired 860 * connectors. 861 */ 862 int drm_mode_create_dirty_info_property(struct drm_device *dev) 863 { 864 struct drm_property *dirty_info; 865 866 if (dev->mode_config.dirty_info_property) 867 return 0; 868 869 dirty_info = 870 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 871 "dirty", 872 drm_dirty_info_enum_list, 873 DRM_ARRAY_SIZE(drm_dirty_info_enum_list)); 874 dev->mode_config.dirty_info_property = dirty_info; 875 876 return 0; 877 } 878 879 /** 880 * drm_mode_config_init - initialize DRM mode_configuration structure 881 * @dev: DRM device 882 * 883 * LOCKING: 884 * None, should happen single threaded at init time. 885 * 886 * Initialize @dev's mode_config structure, used for tracking the graphics 887 * configuration of @dev. 888 */ 889 void drm_mode_config_init(struct drm_device *dev) 890 { 891 sx_init(&dev->mode_config.mutex, "kmslk"); 892 INIT_LIST_HEAD(&dev->mode_config.fb_list); 893 INIT_LIST_HEAD(&dev->mode_config.crtc_list); 894 INIT_LIST_HEAD(&dev->mode_config.connector_list); 895 INIT_LIST_HEAD(&dev->mode_config.encoder_list); 896 INIT_LIST_HEAD(&dev->mode_config.property_list); 897 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 898 INIT_LIST_HEAD(&dev->mode_config.plane_list); 899 drm_gem_names_init(&dev->mode_config.crtc_names); 900 901 sx_xlock(&dev->mode_config.mutex); 902 drm_mode_create_standard_connector_properties(dev); 903 sx_xunlock(&dev->mode_config.mutex); 904 905 /* Just to be sure */ 906 dev->mode_config.num_fb = 0; 907 dev->mode_config.num_connector = 0; 908 dev->mode_config.num_crtc = 0; 909 dev->mode_config.num_encoder = 0; 910 } 911 912 static int 913 drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) 914 { 915 uint32_t total_objects = 0; 916 917 total_objects += dev->mode_config.num_crtc; 918 total_objects += dev->mode_config.num_connector; 919 total_objects += dev->mode_config.num_encoder; 920 921 group->id_list = malloc(total_objects * sizeof(uint32_t), 922 DRM_MEM_KMS, M_WAITOK | M_ZERO); 923 924 group->num_crtcs = 0; 925 group->num_connectors = 0; 926 group->num_encoders = 0; 927 return 0; 928 } 929 930 int drm_mode_group_init_legacy_group(struct drm_device *dev, 931 struct drm_mode_group *group) 932 { 933 struct drm_crtc *crtc; 934 struct drm_encoder *encoder; 935 struct drm_connector *connector; 936 int ret; 937 938 if ((ret = drm_mode_group_init(dev, group))) 939 return ret; 940 941 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 942 group->id_list[group->num_crtcs++] = crtc->base.id; 943 944 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 945 group->id_list[group->num_crtcs + group->num_encoders++] = 946 encoder->base.id; 947 948 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 949 group->id_list[group->num_crtcs + group->num_encoders + 950 group->num_connectors++] = connector->base.id; 951 952 return 0; 953 } 954 955 /** 956 * drm_mode_config_cleanup - free up DRM mode_config info 957 * @dev: DRM device 958 * 959 * LOCKING: 960 * Caller must hold mode config lock. 961 * 962 * Free up all the connectors and CRTCs associated with this DRM device, then 963 * free up the framebuffers and associated buffer objects. 964 * 965 * FIXME: cleanup any dangling user buffer objects too 966 */ 967 void drm_mode_config_cleanup(struct drm_device *dev) 968 { 969 struct drm_connector *connector, *ot; 970 struct drm_crtc *crtc, *ct; 971 struct drm_encoder *encoder, *enct; 972 struct drm_framebuffer *fb, *fbt; 973 struct drm_property *property, *pt; 974 struct drm_plane *plane, *plt; 975 976 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, 977 head) { 978 encoder->funcs->destroy(encoder); 979 } 980 981 list_for_each_entry_safe(connector, ot, 982 &dev->mode_config.connector_list, head) { 983 connector->funcs->destroy(connector); 984 } 985 986 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, 987 head) { 988 drm_property_destroy(dev, property); 989 } 990 991 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { 992 fb->funcs->destroy(fb); 993 } 994 995 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { 996 crtc->funcs->destroy(crtc); 997 } 998 999 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, 1000 head) { 1001 plane->funcs->destroy(plane); 1002 } 1003 drm_gem_names_fini(&dev->mode_config.crtc_names); 1004 } 1005 1006 /** 1007 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo 1008 * @out: drm_mode_modeinfo struct to return to the user 1009 * @in: drm_display_mode to use 1010 * 1011 * LOCKING: 1012 * None. 1013 * 1014 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to 1015 * the user. 1016 */ 1017 static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, 1018 const struct drm_display_mode *in) 1019 { 1020 if (in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || 1021 in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || 1022 in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || 1023 in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || 1024 in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX) 1025 printf("timing values too large for mode info\n"); 1026 1027 out->clock = in->clock; 1028 out->hdisplay = in->hdisplay; 1029 out->hsync_start = in->hsync_start; 1030 out->hsync_end = in->hsync_end; 1031 out->htotal = in->htotal; 1032 out->hskew = in->hskew; 1033 out->vdisplay = in->vdisplay; 1034 out->vsync_start = in->vsync_start; 1035 out->vsync_end = in->vsync_end; 1036 out->vtotal = in->vtotal; 1037 out->vscan = in->vscan; 1038 out->vrefresh = in->vrefresh; 1039 out->flags = in->flags; 1040 out->type = in->type; 1041 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1042 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1043 } 1044 1045 /** 1046 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode 1047 * @out: drm_display_mode to return to the user 1048 * @in: drm_mode_modeinfo to use 1049 * 1050 * LOCKING: 1051 * None. 1052 * 1053 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to 1054 * the caller. 1055 * 1056 * RETURNS: 1057 * Zero on success, errno on failure. 1058 */ 1059 static int drm_crtc_convert_umode(struct drm_display_mode *out, 1060 const struct drm_mode_modeinfo *in) 1061 { 1062 if (in->clock > INT_MAX || in->vrefresh > INT_MAX) 1063 return ERANGE; 1064 1065 out->clock = in->clock; 1066 out->hdisplay = in->hdisplay; 1067 out->hsync_start = in->hsync_start; 1068 out->hsync_end = in->hsync_end; 1069 out->htotal = in->htotal; 1070 out->hskew = in->hskew; 1071 out->vdisplay = in->vdisplay; 1072 out->vsync_start = in->vsync_start; 1073 out->vsync_end = in->vsync_end; 1074 out->vtotal = in->vtotal; 1075 out->vscan = in->vscan; 1076 out->vrefresh = in->vrefresh; 1077 out->flags = in->flags; 1078 out->type = in->type; 1079 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1080 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1081 1082 return 0; 1083 } 1084 1085 /** 1086 * drm_mode_getresources - get graphics configuration 1087 * @inode: inode from the ioctl 1088 * @filp: file * from the ioctl 1089 * @cmd: cmd from ioctl 1090 * @arg: arg from ioctl 1091 * 1092 * LOCKING: 1093 * Takes mode config lock. 1094 * 1095 * Construct a set of configuration description structures and return 1096 * them to the user, including CRTC, connector and framebuffer configuration. 1097 * 1098 * Called by the user via ioctl. 1099 * 1100 * RETURNS: 1101 * Zero on success, errno on failure. 1102 */ 1103 int drm_mode_getresources(struct drm_device *dev, void *data, 1104 struct drm_file *file_priv) 1105 { 1106 struct drm_mode_card_res *card_res = data; 1107 struct list_head *lh; 1108 struct drm_framebuffer *fb; 1109 struct drm_connector *connector; 1110 struct drm_crtc *crtc; 1111 struct drm_encoder *encoder; 1112 int ret = 0; 1113 int connector_count = 0; 1114 int crtc_count = 0; 1115 int fb_count = 0; 1116 int encoder_count = 0; 1117 int copied = 0, i; 1118 uint32_t __user *fb_id; 1119 uint32_t __user *crtc_id; 1120 uint32_t __user *connector_id; 1121 uint32_t __user *encoder_id; 1122 struct drm_mode_group *mode_group; 1123 1124 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1125 return (EINVAL); 1126 1127 sx_xlock(&dev->mode_config.mutex); 1128 1129 /* 1130 * For the non-control nodes we need to limit the list of resources 1131 * by IDs in the group list for this node 1132 */ 1133 list_for_each(lh, &file_priv->fbs) 1134 fb_count++; 1135 1136 #if 1 1137 mode_group = NULL; /* XXXKIB */ 1138 if (1 || file_priv->master) { 1139 #else 1140 mode_group = &file_priv->masterp->minor->mode_group; 1141 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1142 #endif 1143 1144 list_for_each(lh, &dev->mode_config.crtc_list) 1145 crtc_count++; 1146 1147 list_for_each(lh, &dev->mode_config.connector_list) 1148 connector_count++; 1149 1150 list_for_each(lh, &dev->mode_config.encoder_list) 1151 encoder_count++; 1152 } else { 1153 1154 crtc_count = mode_group->num_crtcs; 1155 connector_count = mode_group->num_connectors; 1156 encoder_count = mode_group->num_encoders; 1157 } 1158 1159 card_res->max_height = dev->mode_config.max_height; 1160 card_res->min_height = dev->mode_config.min_height; 1161 card_res->max_width = dev->mode_config.max_width; 1162 card_res->min_width = dev->mode_config.min_width; 1163 1164 /* handle this in 4 parts */ 1165 /* FBs */ 1166 if (card_res->count_fbs >= fb_count) { 1167 copied = 0; 1168 fb_id = (uint32_t *)(uintptr_t)card_res->fb_id_ptr; 1169 list_for_each_entry(fb, &file_priv->fbs, filp_head) { 1170 if (copyout(&fb->base.id, fb_id + copied, 1171 sizeof(uint32_t))) { 1172 ret = EFAULT; 1173 goto out; 1174 } 1175 copied++; 1176 } 1177 } 1178 card_res->count_fbs = fb_count; 1179 1180 /* CRTCs */ 1181 if (card_res->count_crtcs >= crtc_count) { 1182 copied = 0; 1183 crtc_id = (uint32_t *)(uintptr_t)card_res->crtc_id_ptr; 1184 #if 1 1185 if (1 || file_priv->master) { 1186 #else 1187 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1188 #endif 1189 list_for_each_entry(crtc, &dev->mode_config.crtc_list, 1190 head) { 1191 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1192 if (copyout(&crtc->base.id, crtc_id + 1193 copied, sizeof(uint32_t))) { 1194 ret = EFAULT; 1195 goto out; 1196 } 1197 copied++; 1198 } 1199 } else { 1200 for (i = 0; i < mode_group->num_crtcs; i++) { 1201 if (copyout(&mode_group->id_list[i], 1202 crtc_id + copied, sizeof(uint32_t))) { 1203 ret = EFAULT; 1204 goto out; 1205 } 1206 copied++; 1207 } 1208 } 1209 } 1210 card_res->count_crtcs = crtc_count; 1211 1212 /* Encoders */ 1213 if (card_res->count_encoders >= encoder_count) { 1214 copied = 0; 1215 encoder_id = (uint32_t *)(uintptr_t)card_res->encoder_id_ptr; 1216 #if 1 1217 if (file_priv->master) { 1218 #else 1219 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1220 #endif 1221 list_for_each_entry(encoder, 1222 &dev->mode_config.encoder_list, 1223 head) { 1224 DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, 1225 drm_get_encoder_name(encoder)); 1226 if (copyout(&encoder->base.id, encoder_id + 1227 copied, sizeof(uint32_t))) { 1228 ret = EFAULT; 1229 goto out; 1230 } 1231 copied++; 1232 } 1233 } else { 1234 for (i = mode_group->num_crtcs; 1235 i < mode_group->num_crtcs + mode_group->num_encoders; 1236 i++) { 1237 if (copyout(&mode_group->id_list[i], 1238 encoder_id + copied, sizeof(uint32_t))) { 1239 ret = EFAULT; 1240 goto out; 1241 } 1242 copied++; 1243 } 1244 1245 } 1246 } 1247 card_res->count_encoders = encoder_count; 1248 1249 /* Connectors */ 1250 if (card_res->count_connectors >= connector_count) { 1251 copied = 0; 1252 connector_id = (uint32_t *)(uintptr_t)card_res->connector_id_ptr; 1253 #if 1 1254 if (file_priv->master) { 1255 #else 1256 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1257 #endif 1258 list_for_each_entry(connector, 1259 &dev->mode_config.connector_list, 1260 head) { 1261 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 1262 connector->base.id, 1263 drm_get_connector_name(connector)); 1264 if (copyout(&connector->base.id, 1265 connector_id + copied, sizeof(uint32_t))) { 1266 ret = EFAULT; 1267 goto out; 1268 } 1269 copied++; 1270 } 1271 } else { 1272 int start = mode_group->num_crtcs + 1273 mode_group->num_encoders; 1274 for (i = start; i < start + mode_group->num_connectors; i++) { 1275 if (copyout(&mode_group->id_list[i], 1276 connector_id + copied, sizeof(uint32_t))) { 1277 ret = EFAULT; 1278 goto out; 1279 } 1280 copied++; 1281 } 1282 } 1283 } 1284 card_res->count_connectors = connector_count; 1285 1286 DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs, 1287 card_res->count_connectors, card_res->count_encoders); 1288 1289 out: 1290 sx_xunlock(&dev->mode_config.mutex); 1291 return ret; 1292 } 1293 1294 /** 1295 * drm_mode_getcrtc - get CRTC configuration 1296 * @inode: inode from the ioctl 1297 * @filp: file * from the ioctl 1298 * @cmd: cmd from ioctl 1299 * @arg: arg from ioctl 1300 * 1301 * LOCKING: 1302 * Takes mode config lock. 1303 * 1304 * Construct a CRTC configuration structure to return to the user. 1305 * 1306 * Called by the user via ioctl. 1307 * 1308 * RETURNS: 1309 * Zero on success, errno on failure. 1310 */ 1311 int drm_mode_getcrtc(struct drm_device *dev, 1312 void *data, struct drm_file *file_priv) 1313 { 1314 struct drm_mode_crtc *crtc_resp = data; 1315 struct drm_crtc *crtc; 1316 struct drm_mode_object *obj; 1317 int ret = 0; 1318 1319 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1320 return (EINVAL); 1321 1322 sx_xlock(&dev->mode_config.mutex); 1323 1324 obj = drm_mode_object_find(dev, crtc_resp->crtc_id, 1325 DRM_MODE_OBJECT_CRTC); 1326 if (!obj) { 1327 ret = (EINVAL); 1328 goto out; 1329 } 1330 crtc = obj_to_crtc(obj); 1331 1332 crtc_resp->x = crtc->x; 1333 crtc_resp->y = crtc->y; 1334 crtc_resp->gamma_size = crtc->gamma_size; 1335 if (crtc->fb) 1336 crtc_resp->fb_id = crtc->fb->base.id; 1337 else 1338 crtc_resp->fb_id = 0; 1339 1340 if (crtc->enabled) { 1341 1342 drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); 1343 crtc_resp->mode_valid = 1; 1344 1345 } else { 1346 crtc_resp->mode_valid = 0; 1347 } 1348 1349 out: 1350 sx_xunlock(&dev->mode_config.mutex); 1351 return ret; 1352 } 1353 1354 /** 1355 * drm_mode_getconnector - get connector configuration 1356 * @inode: inode from the ioctl 1357 * @filp: file * from the ioctl 1358 * @cmd: cmd from ioctl 1359 * @arg: arg from ioctl 1360 * 1361 * LOCKING: 1362 * Takes mode config lock. 1363 * 1364 * Construct a connector configuration structure to return to the user. 1365 * 1366 * Called by the user via ioctl. 1367 * 1368 * RETURNS: 1369 * Zero on success, errno on failure. 1370 */ 1371 int drm_mode_getconnector(struct drm_device *dev, void *data, 1372 struct drm_file *file_priv) 1373 { 1374 struct drm_mode_get_connector *out_resp = data; 1375 struct drm_mode_object *obj; 1376 struct drm_connector *connector; 1377 struct drm_display_mode *mode; 1378 int mode_count = 0; 1379 int props_count = 0; 1380 int encoders_count = 0; 1381 int ret = 0; 1382 int copied = 0; 1383 int i; 1384 struct drm_mode_modeinfo u_mode; 1385 struct drm_mode_modeinfo __user *mode_ptr; 1386 uint32_t *prop_ptr; 1387 uint64_t *prop_values; 1388 uint32_t *encoder_ptr; 1389 1390 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1391 return (EINVAL); 1392 1393 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); 1394 1395 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); 1396 1397 sx_xlock(&dev->mode_config.mutex); 1398 1399 obj = drm_mode_object_find(dev, out_resp->connector_id, 1400 DRM_MODE_OBJECT_CONNECTOR); 1401 if (!obj) { 1402 ret = EINVAL; 1403 goto out; 1404 } 1405 connector = obj_to_connector(obj); 1406 1407 props_count = connector->properties.count; 1408 1409 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1410 if (connector->encoder_ids[i] != 0) { 1411 encoders_count++; 1412 } 1413 } 1414 1415 if (out_resp->count_modes == 0) { 1416 connector->funcs->fill_modes(connector, 1417 dev->mode_config.max_width, 1418 dev->mode_config.max_height); 1419 } 1420 1421 /* delayed so we get modes regardless of pre-fill_modes state */ 1422 list_for_each_entry(mode, &connector->modes, head) 1423 mode_count++; 1424 1425 out_resp->connector_id = connector->base.id; 1426 out_resp->connector_type = connector->connector_type; 1427 out_resp->connector_type_id = connector->connector_type_id; 1428 out_resp->mm_width = connector->display_info.width_mm; 1429 out_resp->mm_height = connector->display_info.height_mm; 1430 out_resp->subpixel = connector->display_info.subpixel_order; 1431 out_resp->connection = connector->status; 1432 if (connector->encoder) 1433 out_resp->encoder_id = connector->encoder->base.id; 1434 else 1435 out_resp->encoder_id = 0; 1436 1437 /* 1438 * This ioctl is called twice, once to determine how much space is 1439 * needed, and the 2nd time to fill it. 1440 */ 1441 if ((out_resp->count_modes >= mode_count) && mode_count) { 1442 copied = 0; 1443 mode_ptr = (struct drm_mode_modeinfo *)(uintptr_t)out_resp->modes_ptr; 1444 list_for_each_entry(mode, &connector->modes, head) { 1445 drm_crtc_convert_to_umode(&u_mode, mode); 1446 if (copyout(&u_mode, mode_ptr + copied, 1447 sizeof(u_mode))) { 1448 ret = EFAULT; 1449 goto out; 1450 } 1451 copied++; 1452 } 1453 } 1454 out_resp->count_modes = mode_count; 1455 1456 if ((out_resp->count_props >= props_count) && props_count) { 1457 copied = 0; 1458 prop_ptr = (uint32_t *)(uintptr_t)(out_resp->props_ptr); 1459 prop_values = (uint64_t *)(uintptr_t)(out_resp->prop_values_ptr); 1460 for (i = 0; i < connector->properties.count; i++) { 1461 if (copyout(&connector->properties.ids[i], 1462 prop_ptr + copied, sizeof(uint32_t))) { 1463 ret = EFAULT; 1464 goto out; 1465 } 1466 1467 if (copyout(&connector->properties.values[i], 1468 prop_values + copied, sizeof(uint64_t))) { 1469 ret = EFAULT; 1470 goto out; 1471 } 1472 copied++; 1473 } 1474 } 1475 out_resp->count_props = props_count; 1476 1477 if ((out_resp->count_encoders >= encoders_count) && encoders_count) { 1478 copied = 0; 1479 encoder_ptr = (uint32_t *)(uintptr_t)(out_resp->encoders_ptr); 1480 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1481 if (connector->encoder_ids[i] != 0) { 1482 if (copyout(&connector->encoder_ids[i], 1483 encoder_ptr + copied, sizeof(uint32_t))) { 1484 ret = EFAULT; 1485 goto out; 1486 } 1487 copied++; 1488 } 1489 } 1490 } 1491 out_resp->count_encoders = encoders_count; 1492 1493 out: 1494 sx_xunlock(&dev->mode_config.mutex); 1495 return ret; 1496 } 1497 1498 int drm_mode_getencoder(struct drm_device *dev, void *data, 1499 struct drm_file *file_priv) 1500 { 1501 struct drm_mode_get_encoder *enc_resp = data; 1502 struct drm_mode_object *obj; 1503 struct drm_encoder *encoder; 1504 int ret = 0; 1505 1506 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1507 return (EINVAL); 1508 1509 sx_xlock(&dev->mode_config.mutex); 1510 obj = drm_mode_object_find(dev, enc_resp->encoder_id, 1511 DRM_MODE_OBJECT_ENCODER); 1512 if (!obj) { 1513 ret = EINVAL; 1514 goto out; 1515 } 1516 encoder = obj_to_encoder(obj); 1517 1518 if (encoder->crtc) 1519 enc_resp->crtc_id = encoder->crtc->base.id; 1520 else 1521 enc_resp->crtc_id = 0; 1522 enc_resp->encoder_type = encoder->encoder_type; 1523 enc_resp->encoder_id = encoder->base.id; 1524 enc_resp->possible_crtcs = encoder->possible_crtcs; 1525 enc_resp->possible_clones = encoder->possible_clones; 1526 1527 out: 1528 sx_xunlock(&dev->mode_config.mutex); 1529 return ret; 1530 } 1531 1532 /** 1533 * drm_mode_getplane_res - get plane info 1534 * @dev: DRM device 1535 * @data: ioctl data 1536 * @file_priv: DRM file info 1537 * 1538 * LOCKING: 1539 * Takes mode config lock. 1540 * 1541 * Return an plane count and set of IDs. 1542 */ 1543 int drm_mode_getplane_res(struct drm_device *dev, void *data, 1544 struct drm_file *file_priv) 1545 { 1546 struct drm_mode_get_plane_res *plane_resp = data; 1547 struct drm_mode_config *config; 1548 struct drm_plane *plane; 1549 uint32_t *plane_ptr; 1550 int copied = 0, ret = 0; 1551 1552 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1553 return (EINVAL); 1554 1555 sx_xlock(&dev->mode_config.mutex); 1556 config = &dev->mode_config; 1557 1558 /* 1559 * This ioctl is called twice, once to determine how much space is 1560 * needed, and the 2nd time to fill it. 1561 */ 1562 if (config->num_plane && 1563 (plane_resp->count_planes >= config->num_plane)) { 1564 plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr; 1565 1566 list_for_each_entry(plane, &config->plane_list, head) { 1567 if (copyout(&plane->base.id, plane_ptr + copied, 1568 sizeof(uint32_t))) { 1569 ret = EFAULT; 1570 goto out; 1571 } 1572 copied++; 1573 } 1574 } 1575 plane_resp->count_planes = config->num_plane; 1576 1577 out: 1578 sx_xunlock(&dev->mode_config.mutex); 1579 return ret; 1580 } 1581 1582 /** 1583 * drm_mode_getplane - get plane info 1584 * @dev: DRM device 1585 * @data: ioctl data 1586 * @file_priv: DRM file info 1587 * 1588 * LOCKING: 1589 * Takes mode config lock. 1590 * 1591 * Return plane info, including formats supported, gamma size, any 1592 * current fb, etc. 1593 */ 1594 int drm_mode_getplane(struct drm_device *dev, void *data, 1595 struct drm_file *file_priv) 1596 { 1597 struct drm_mode_get_plane *plane_resp = data; 1598 struct drm_mode_object *obj; 1599 struct drm_plane *plane; 1600 uint32_t *format_ptr; 1601 int ret = 0; 1602 1603 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1604 return (EINVAL); 1605 1606 sx_xlock(&dev->mode_config.mutex); 1607 obj = drm_mode_object_find(dev, plane_resp->plane_id, 1608 DRM_MODE_OBJECT_PLANE); 1609 if (!obj) { 1610 ret = ENOENT; 1611 goto out; 1612 } 1613 plane = obj_to_plane(obj); 1614 1615 if (plane->crtc) 1616 plane_resp->crtc_id = plane->crtc->base.id; 1617 else 1618 plane_resp->crtc_id = 0; 1619 1620 if (plane->fb) 1621 plane_resp->fb_id = plane->fb->base.id; 1622 else 1623 plane_resp->fb_id = 0; 1624 1625 plane_resp->plane_id = plane->base.id; 1626 plane_resp->possible_crtcs = plane->possible_crtcs; 1627 plane_resp->gamma_size = plane->gamma_size; 1628 1629 /* 1630 * This ioctl is called twice, once to determine how much space is 1631 * needed, and the 2nd time to fill it. 1632 */ 1633 if (plane->format_count && 1634 (plane_resp->count_format_types >= plane->format_count)) { 1635 format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr; 1636 if (copyout(format_ptr, 1637 plane->format_types, 1638 sizeof(uint32_t) * plane->format_count)) { 1639 ret = EFAULT; 1640 goto out; 1641 } 1642 } 1643 plane_resp->count_format_types = plane->format_count; 1644 1645 out: 1646 sx_xunlock(&dev->mode_config.mutex); 1647 return ret; 1648 } 1649 1650 /** 1651 * drm_mode_setplane - set up or tear down an plane 1652 * @dev: DRM device 1653 * @data: ioctl data* 1654 * @file_prive: DRM file info 1655 * 1656 * LOCKING: 1657 * Takes mode config lock. 1658 * 1659 * Set plane info, including placement, fb, scaling, and other factors. 1660 * Or pass a NULL fb to disable. 1661 */ 1662 int drm_mode_setplane(struct drm_device *dev, void *data, 1663 struct drm_file *file_priv) 1664 { 1665 struct drm_mode_set_plane *plane_req = data; 1666 struct drm_mode_object *obj; 1667 struct drm_plane *plane; 1668 struct drm_crtc *crtc; 1669 struct drm_framebuffer *fb; 1670 int ret = 0; 1671 unsigned int fb_width, fb_height; 1672 int i; 1673 1674 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1675 return (EINVAL); 1676 1677 sx_xlock(&dev->mode_config.mutex); 1678 1679 /* 1680 * First, find the plane, crtc, and fb objects. If not available, 1681 * we don't bother to call the driver. 1682 */ 1683 obj = drm_mode_object_find(dev, plane_req->plane_id, 1684 DRM_MODE_OBJECT_PLANE); 1685 if (!obj) { 1686 DRM_DEBUG_KMS("Unknown plane ID %d\n", 1687 plane_req->plane_id); 1688 ret = ENOENT; 1689 goto out; 1690 } 1691 plane = obj_to_plane(obj); 1692 1693 /* No fb means shut it down */ 1694 if (!plane_req->fb_id) { 1695 plane->funcs->disable_plane(plane); 1696 plane->crtc = NULL; 1697 plane->fb = NULL; 1698 goto out; 1699 } 1700 1701 obj = drm_mode_object_find(dev, plane_req->crtc_id, 1702 DRM_MODE_OBJECT_CRTC); 1703 if (!obj) { 1704 DRM_DEBUG_KMS("Unknown crtc ID %d\n", 1705 plane_req->crtc_id); 1706 ret = ENOENT; 1707 goto out; 1708 } 1709 crtc = obj_to_crtc(obj); 1710 1711 obj = drm_mode_object_find(dev, plane_req->fb_id, 1712 DRM_MODE_OBJECT_FB); 1713 if (!obj) { 1714 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", 1715 plane_req->fb_id); 1716 ret = ENOENT; 1717 goto out; 1718 } 1719 fb = obj_to_fb(obj); 1720 1721 /* Check whether this plane supports the fb pixel format. */ 1722 for (i = 0; i < plane->format_count; i++) 1723 if (fb->pixel_format == plane->format_types[i]) 1724 break; 1725 if (i == plane->format_count) { 1726 DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); 1727 ret = EINVAL; 1728 goto out; 1729 } 1730 1731 fb_width = fb->width << 16; 1732 fb_height = fb->height << 16; 1733 1734 /* Make sure source coordinates are inside the fb. */ 1735 if (plane_req->src_w > fb_width || 1736 plane_req->src_x > fb_width - plane_req->src_w || 1737 plane_req->src_h > fb_height || 1738 plane_req->src_y > fb_height - plane_req->src_h) { 1739 DRM_DEBUG_KMS("Invalid source coordinates " 1740 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", 1741 plane_req->src_w >> 16, 1742 ((plane_req->src_w & 0xffff) * 15625) >> 10, 1743 plane_req->src_h >> 16, 1744 ((plane_req->src_h & 0xffff) * 15625) >> 10, 1745 plane_req->src_x >> 16, 1746 ((plane_req->src_x & 0xffff) * 15625) >> 10, 1747 plane_req->src_y >> 16, 1748 ((plane_req->src_y & 0xffff) * 15625) >> 10); 1749 ret = ENOSPC; 1750 goto out; 1751 } 1752 1753 /* Give drivers some help against integer overflows */ 1754 if (plane_req->crtc_w > INT_MAX || 1755 plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || 1756 plane_req->crtc_h > INT_MAX || 1757 plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { 1758 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", 1759 plane_req->crtc_w, plane_req->crtc_h, 1760 plane_req->crtc_x, plane_req->crtc_y); 1761 ret = ERANGE; 1762 goto out; 1763 } 1764 1765 ret = -plane->funcs->update_plane(plane, crtc, fb, 1766 plane_req->crtc_x, plane_req->crtc_y, 1767 plane_req->crtc_w, plane_req->crtc_h, 1768 plane_req->src_x, plane_req->src_y, 1769 plane_req->src_w, plane_req->src_h); 1770 if (!ret) { 1771 plane->crtc = crtc; 1772 plane->fb = fb; 1773 } 1774 1775 out: 1776 sx_xunlock(&dev->mode_config.mutex); 1777 1778 return ret; 1779 } 1780 1781 /** 1782 * drm_mode_setcrtc - set CRTC configuration 1783 * @inode: inode from the ioctl 1784 * @filp: file * from the ioctl 1785 * @cmd: cmd from ioctl 1786 * @arg: arg from ioctl 1787 * 1788 * LOCKING: 1789 * Takes mode config lock. 1790 * 1791 * Build a new CRTC configuration based on user request. 1792 * 1793 * Called by the user via ioctl. 1794 * 1795 * RETURNS: 1796 * Zero on success, errno on failure. 1797 */ 1798 int drm_mode_setcrtc(struct drm_device *dev, void *data, 1799 struct drm_file *file_priv) 1800 { 1801 struct drm_mode_config *config = &dev->mode_config; 1802 struct drm_mode_crtc *crtc_req = data; 1803 struct drm_mode_object *obj; 1804 struct drm_crtc *crtc; 1805 struct drm_connector **connector_set = NULL, *connector; 1806 struct drm_framebuffer *fb = NULL; 1807 struct drm_display_mode *mode = NULL; 1808 struct drm_mode_set set; 1809 uint32_t *set_connectors_ptr; 1810 int ret; 1811 int i; 1812 1813 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1814 return (EINVAL); 1815 1816 /* For some reason crtc x/y offsets are signed internally. */ 1817 if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) 1818 return (ERANGE); 1819 1820 sx_xlock(&dev->mode_config.mutex); 1821 obj = drm_mode_object_find(dev, crtc_req->crtc_id, 1822 DRM_MODE_OBJECT_CRTC); 1823 if (!obj) { 1824 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); 1825 ret = EINVAL; 1826 goto out; 1827 } 1828 crtc = obj_to_crtc(obj); 1829 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1830 1831 if (crtc_req->mode_valid) { 1832 /* If we have a mode we need a framebuffer. */ 1833 /* If we pass -1, set the mode with the currently bound fb */ 1834 if (crtc_req->fb_id == -1) { 1835 if (!crtc->fb) { 1836 DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); 1837 ret = -EINVAL; 1838 goto out; 1839 } 1840 fb = crtc->fb; 1841 } else { 1842 obj = drm_mode_object_find(dev, crtc_req->fb_id, 1843 DRM_MODE_OBJECT_FB); 1844 if (!obj) { 1845 DRM_DEBUG_KMS("Unknown FB ID%d\n", 1846 crtc_req->fb_id); 1847 ret = EINVAL; 1848 goto out; 1849 } 1850 fb = obj_to_fb(obj); 1851 } 1852 1853 mode = drm_mode_create(dev); 1854 if (!mode) { 1855 ret = ENOMEM; 1856 goto out; 1857 } 1858 1859 ret = drm_crtc_convert_umode(mode, &crtc_req->mode); 1860 if (ret) { 1861 DRM_DEBUG_KMS("Invalid mode\n"); 1862 goto out; 1863 } 1864 1865 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1866 1867 if (mode->hdisplay > fb->width || 1868 mode->vdisplay > fb->height || 1869 crtc_req->x > fb->width - mode->hdisplay || 1870 crtc_req->y > fb->height - mode->vdisplay) { 1871 DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n", 1872 mode->hdisplay, mode->vdisplay, 1873 crtc_req->x, crtc_req->y, 1874 fb->width, fb->height); 1875 ret = ENOSPC; 1876 goto out; 1877 } 1878 } 1879 1880 if (crtc_req->count_connectors == 0 && mode) { 1881 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n"); 1882 ret = EINVAL; 1883 goto out; 1884 } 1885 1886 if (crtc_req->count_connectors > 0 && (!mode || !fb)) { 1887 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n", 1888 crtc_req->count_connectors); 1889 ret = EINVAL; 1890 goto out; 1891 } 1892 1893 if (crtc_req->count_connectors > 0) { 1894 u32 out_id; 1895 1896 /* Avoid unbounded kernel memory allocation */ 1897 if (crtc_req->count_connectors > config->num_connector) { 1898 ret = EINVAL; 1899 goto out; 1900 } 1901 1902 connector_set = malloc(crtc_req->count_connectors * 1903 sizeof(struct drm_connector *), DRM_MEM_KMS, M_WAITOK); 1904 1905 for (i = 0; i < crtc_req->count_connectors; i++) { 1906 set_connectors_ptr = (uint32_t *)(uintptr_t)crtc_req->set_connectors_ptr; 1907 if (copyin(&set_connectors_ptr[i], &out_id, sizeof(uint32_t))) { 1908 ret = EFAULT; 1909 goto out; 1910 } 1911 1912 obj = drm_mode_object_find(dev, out_id, 1913 DRM_MODE_OBJECT_CONNECTOR); 1914 if (!obj) { 1915 DRM_DEBUG_KMS("Connector id %d unknown\n", 1916 out_id); 1917 ret = EINVAL; 1918 goto out; 1919 } 1920 connector = obj_to_connector(obj); 1921 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 1922 connector->base.id, 1923 drm_get_connector_name(connector)); 1924 1925 connector_set[i] = connector; 1926 } 1927 } 1928 1929 set.crtc = crtc; 1930 set.x = crtc_req->x; 1931 set.y = crtc_req->y; 1932 set.mode = mode; 1933 set.connectors = connector_set; 1934 set.num_connectors = crtc_req->count_connectors; 1935 set.fb = fb; 1936 ret = crtc->funcs->set_config(&set); 1937 1938 out: 1939 free(connector_set, DRM_MEM_KMS); 1940 drm_mode_destroy(dev, mode); 1941 sx_xunlock(&dev->mode_config.mutex); 1942 return ret; 1943 } 1944 1945 int drm_mode_cursor_ioctl(struct drm_device *dev, 1946 void *data, struct drm_file *file_priv) 1947 { 1948 struct drm_mode_cursor *req = data; 1949 struct drm_mode_object *obj; 1950 struct drm_crtc *crtc; 1951 int ret = 0; 1952 1953 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1954 return (EINVAL); 1955 1956 if (!req->flags) 1957 return (EINVAL); 1958 1959 sx_xlock(&dev->mode_config.mutex); 1960 obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); 1961 if (!obj) { 1962 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); 1963 ret = EINVAL; 1964 goto out; 1965 } 1966 crtc = obj_to_crtc(obj); 1967 1968 if (req->flags & DRM_MODE_CURSOR_BO) { 1969 if (!crtc->funcs->cursor_set) { 1970 ret = ENXIO; 1971 goto out; 1972 } 1973 /* Turns off the cursor if handle is 0 */ 1974 ret = -crtc->funcs->cursor_set(crtc, file_priv, req->handle, 1975 req->width, req->height); 1976 } 1977 1978 if (req->flags & DRM_MODE_CURSOR_MOVE) { 1979 if (crtc->funcs->cursor_move) { 1980 ret = crtc->funcs->cursor_move(crtc, req->x, req->y); 1981 } else { 1982 ret = EFAULT; 1983 goto out; 1984 } 1985 } 1986 out: 1987 sx_xunlock(&dev->mode_config.mutex); 1988 return ret; 1989 } 1990 1991 /* Original addfb only supported RGB formats, so figure out which one */ 1992 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) 1993 { 1994 uint32_t fmt; 1995 1996 switch (bpp) { 1997 case 8: 1998 fmt = DRM_FORMAT_RGB332; 1999 break; 2000 case 16: 2001 if (depth == 15) 2002 fmt = DRM_FORMAT_XRGB1555; 2003 else 2004 fmt = DRM_FORMAT_RGB565; 2005 break; 2006 case 24: 2007 fmt = DRM_FORMAT_RGB888; 2008 break; 2009 case 32: 2010 if (depth == 24) 2011 fmt = DRM_FORMAT_XRGB8888; 2012 else if (depth == 30) 2013 fmt = DRM_FORMAT_XRGB2101010; 2014 else 2015 fmt = DRM_FORMAT_ARGB8888; 2016 break; 2017 default: 2018 DRM_ERROR("bad bpp, assuming RGB24 pixel format\n"); 2019 fmt = DRM_FORMAT_XRGB8888; 2020 break; 2021 } 2022 2023 return fmt; 2024 } 2025 2026 /** 2027 * drm_mode_addfb - add an FB to the graphics configuration 2028 * @inode: inode from the ioctl 2029 * @filp: file * from the ioctl 2030 * @cmd: cmd from ioctl 2031 * @arg: arg from ioctl 2032 * 2033 * LOCKING: 2034 * Takes mode config lock. 2035 * 2036 * Add a new FB to the specified CRTC, given a user request. 2037 * 2038 * Called by the user via ioctl. 2039 * 2040 * RETURNS: 2041 * Zero on success, errno on failure. 2042 */ 2043 int drm_mode_addfb(struct drm_device *dev, 2044 void *data, struct drm_file *file_priv) 2045 { 2046 struct drm_mode_fb_cmd *or = data; 2047 struct drm_mode_fb_cmd2 r = {}; 2048 struct drm_mode_config *config = &dev->mode_config; 2049 struct drm_framebuffer *fb; 2050 int ret = 0; 2051 2052 /* Use new struct with format internally */ 2053 r.fb_id = or->fb_id; 2054 r.width = or->width; 2055 r.height = or->height; 2056 r.pitches[0] = or->pitch; 2057 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); 2058 r.handles[0] = or->handle; 2059 2060 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2061 return (EINVAL); 2062 2063 if ((config->min_width > r.width) || (r.width > config->max_width)) 2064 return (EINVAL); 2065 if ((config->min_height > r.height) || (r.height > config->max_height)) 2066 return (EINVAL); 2067 2068 sx_xlock(&dev->mode_config.mutex); 2069 2070 ret = -dev->mode_config.funcs->fb_create(dev, file_priv, &r, &fb); 2071 if (ret != 0) { 2072 DRM_DEBUG_KMS("could not create framebuffer, error %d\n", ret); 2073 goto out; 2074 } 2075 2076 or->fb_id = fb->base.id; 2077 list_add(&fb->filp_head, &file_priv->fbs); 2078 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); 2079 2080 out: 2081 sx_xunlock(&dev->mode_config.mutex); 2082 return ret; 2083 } 2084 2085 static int format_check(struct drm_mode_fb_cmd2 *r) 2086 { 2087 uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; 2088 2089 switch (format) { 2090 case DRM_FORMAT_C8: 2091 case DRM_FORMAT_RGB332: 2092 case DRM_FORMAT_BGR233: 2093 case DRM_FORMAT_XRGB4444: 2094 case DRM_FORMAT_XBGR4444: 2095 case DRM_FORMAT_RGBX4444: 2096 case DRM_FORMAT_BGRX4444: 2097 case DRM_FORMAT_ARGB4444: 2098 case DRM_FORMAT_ABGR4444: 2099 case DRM_FORMAT_RGBA4444: 2100 case DRM_FORMAT_BGRA4444: 2101 case DRM_FORMAT_XRGB1555: 2102 case DRM_FORMAT_XBGR1555: 2103 case DRM_FORMAT_RGBX5551: 2104 case DRM_FORMAT_BGRX5551: 2105 case DRM_FORMAT_ARGB1555: 2106 case DRM_FORMAT_ABGR1555: 2107 case DRM_FORMAT_RGBA5551: 2108 case DRM_FORMAT_BGRA5551: 2109 case DRM_FORMAT_RGB565: 2110 case DRM_FORMAT_BGR565: 2111 case DRM_FORMAT_RGB888: 2112 case DRM_FORMAT_BGR888: 2113 case DRM_FORMAT_XRGB8888: 2114 case DRM_FORMAT_XBGR8888: 2115 case DRM_FORMAT_RGBX8888: 2116 case DRM_FORMAT_BGRX8888: 2117 case DRM_FORMAT_ARGB8888: 2118 case DRM_FORMAT_ABGR8888: 2119 case DRM_FORMAT_RGBA8888: 2120 case DRM_FORMAT_BGRA8888: 2121 case DRM_FORMAT_XRGB2101010: 2122 case DRM_FORMAT_XBGR2101010: 2123 case DRM_FORMAT_RGBX1010102: 2124 case DRM_FORMAT_BGRX1010102: 2125 case DRM_FORMAT_ARGB2101010: 2126 case DRM_FORMAT_ABGR2101010: 2127 case DRM_FORMAT_RGBA1010102: 2128 case DRM_FORMAT_BGRA1010102: 2129 case DRM_FORMAT_YUYV: 2130 case DRM_FORMAT_YVYU: 2131 case DRM_FORMAT_UYVY: 2132 case DRM_FORMAT_VYUY: 2133 case DRM_FORMAT_AYUV: 2134 case DRM_FORMAT_NV12: 2135 case DRM_FORMAT_NV21: 2136 case DRM_FORMAT_NV16: 2137 case DRM_FORMAT_NV61: 2138 case DRM_FORMAT_YUV410: 2139 case DRM_FORMAT_YVU410: 2140 case DRM_FORMAT_YUV411: 2141 case DRM_FORMAT_YVU411: 2142 case DRM_FORMAT_YUV420: 2143 case DRM_FORMAT_YVU420: 2144 case DRM_FORMAT_YUV422: 2145 case DRM_FORMAT_YVU422: 2146 case DRM_FORMAT_YUV444: 2147 case DRM_FORMAT_YVU444: 2148 return 0; 2149 default: 2150 return (EINVAL); 2151 } 2152 } 2153 2154 static int framebuffer_check(struct drm_mode_fb_cmd2 *r) 2155 { 2156 int ret, hsub, vsub, num_planes, i; 2157 2158 ret = format_check(r); 2159 if (ret) { 2160 DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format); 2161 return ret; 2162 } 2163 2164 hsub = drm_format_horz_chroma_subsampling(r->pixel_format); 2165 vsub = drm_format_vert_chroma_subsampling(r->pixel_format); 2166 num_planes = drm_format_num_planes(r->pixel_format); 2167 2168 if (r->width == 0 || r->width % hsub) { 2169 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); 2170 return -EINVAL; 2171 } 2172 2173 if (r->height == 0 || r->height % vsub) { 2174 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); 2175 return -EINVAL; 2176 } 2177 2178 for (i = 0; i < num_planes; i++) { 2179 unsigned int width = r->width / (i != 0 ? hsub : 1); 2180 2181 if (!r->handles[i]) { 2182 DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); 2183 return -EINVAL; 2184 } 2185 2186 if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) { 2187 DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); 2188 return -EINVAL; 2189 } 2190 } 2191 2192 return 0; 2193 } 2194 2195 /** 2196 * drm_mode_addfb2 - add an FB to the graphics configuration 2197 * @inode: inode from the ioctl 2198 * @filp: file * from the ioctl 2199 * @cmd: cmd from ioctl 2200 * @arg: arg from ioctl 2201 * 2202 * LOCKING: 2203 * Takes mode config lock. 2204 * 2205 * Add a new FB to the specified CRTC, given a user request with format. 2206 * 2207 * Called by the user via ioctl. 2208 * 2209 * RETURNS: 2210 * Zero on success, errno on failure. 2211 */ 2212 int drm_mode_addfb2(struct drm_device *dev, 2213 void *data, struct drm_file *file_priv) 2214 { 2215 struct drm_mode_fb_cmd2 *r = data; 2216 struct drm_mode_config *config = &dev->mode_config; 2217 struct drm_framebuffer *fb; 2218 int ret = 0; 2219 2220 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2221 return (EINVAL); 2222 2223 if ((config->min_width > r->width) || (r->width > config->max_width)) { 2224 DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", 2225 r->width, config->min_width, config->max_width); 2226 return (EINVAL); 2227 } 2228 if ((config->min_height > r->height) || (r->height > config->max_height)) { 2229 DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", 2230 r->height, config->min_height, config->max_height); 2231 return (EINVAL); 2232 } 2233 2234 ret = framebuffer_check(r); 2235 if (ret) 2236 return -ret; 2237 2238 sx_xlock(&dev->mode_config.mutex); 2239 2240 /* TODO check buffer is sufficiently large */ 2241 /* TODO setup destructor callback */ 2242 2243 ret = -dev->mode_config.funcs->fb_create(dev, file_priv, r, &fb); 2244 if (ret != 0) { 2245 DRM_DEBUG_KMS("could not create framebuffer, error %d\n", ret); 2246 goto out; 2247 } 2248 2249 r->fb_id = fb->base.id; 2250 list_add(&fb->filp_head, &file_priv->fbs); 2251 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); 2252 2253 out: 2254 sx_xunlock(&dev->mode_config.mutex); 2255 return (ret); 2256 } 2257 2258 /** 2259 * drm_mode_rmfb - remove an FB from the configuration 2260 * @inode: inode from the ioctl 2261 * @filp: file * from the ioctl 2262 * @cmd: cmd from ioctl 2263 * @arg: arg from ioctl 2264 * 2265 * LOCKING: 2266 * Takes mode config lock. 2267 * 2268 * Remove the FB specified by the user. 2269 * 2270 * Called by the user via ioctl. 2271 * 2272 * RETURNS: 2273 * Zero on success, errno on failure. 2274 */ 2275 int drm_mode_rmfb(struct drm_device *dev, 2276 void *data, struct drm_file *file_priv) 2277 { 2278 struct drm_mode_object *obj; 2279 struct drm_framebuffer *fb = NULL; 2280 struct drm_framebuffer *fbl = NULL; 2281 uint32_t *id = data; 2282 int ret = 0; 2283 int found = 0; 2284 2285 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2286 return (EINVAL); 2287 2288 sx_xlock(&dev->mode_config.mutex); 2289 obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); 2290 /* TODO check that we really get a framebuffer back. */ 2291 if (!obj) { 2292 ret = EINVAL; 2293 goto out; 2294 } 2295 fb = obj_to_fb(obj); 2296 2297 list_for_each_entry(fbl, &file_priv->fbs, filp_head) 2298 if (fb == fbl) 2299 found = 1; 2300 2301 if (!found) { 2302 ret = EINVAL; 2303 goto out; 2304 } 2305 2306 /* TODO release all crtc connected to the framebuffer */ 2307 /* TODO unhock the destructor from the buffer object */ 2308 2309 list_del(&fb->filp_head); 2310 fb->funcs->destroy(fb); 2311 2312 out: 2313 sx_xunlock(&dev->mode_config.mutex); 2314 return ret; 2315 } 2316 2317 /** 2318 * drm_mode_getfb - get FB info 2319 * @inode: inode from the ioctl 2320 * @filp: file * from the ioctl 2321 * @cmd: cmd from ioctl 2322 * @arg: arg from ioctl 2323 * 2324 * LOCKING: 2325 * Takes mode config lock. 2326 * 2327 * Lookup the FB given its ID and return info about it. 2328 * 2329 * Called by the user via ioctl. 2330 * 2331 * RETURNS: 2332 * Zero on success, errno on failure. 2333 */ 2334 int drm_mode_getfb(struct drm_device *dev, 2335 void *data, struct drm_file *file_priv) 2336 { 2337 struct drm_mode_fb_cmd *r = data; 2338 struct drm_mode_object *obj; 2339 struct drm_framebuffer *fb; 2340 int ret = 0; 2341 2342 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2343 return (EINVAL); 2344 2345 sx_xlock(&dev->mode_config.mutex); 2346 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2347 if (!obj) { 2348 ret = EINVAL; 2349 goto out; 2350 } 2351 fb = obj_to_fb(obj); 2352 2353 r->height = fb->height; 2354 r->width = fb->width; 2355 r->depth = fb->depth; 2356 r->bpp = fb->bits_per_pixel; 2357 r->pitch = fb->pitches[0]; 2358 r->handle = 0; 2359 fb->funcs->create_handle(fb, file_priv, &r->handle); 2360 2361 out: 2362 sx_xunlock(&dev->mode_config.mutex); 2363 return ret; 2364 } 2365 2366 int drm_mode_dirtyfb_ioctl(struct drm_device *dev, 2367 void *data, struct drm_file *file_priv) 2368 { 2369 struct drm_clip_rect __user *clips_ptr; 2370 struct drm_clip_rect *clips = NULL; 2371 struct drm_mode_fb_dirty_cmd *r = data; 2372 struct drm_mode_object *obj; 2373 struct drm_framebuffer *fb; 2374 unsigned flags; 2375 int num_clips; 2376 int ret; 2377 2378 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2379 return (EINVAL); 2380 2381 sx_xlock(&dev->mode_config.mutex); 2382 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2383 if (!obj) { 2384 ret = EINVAL; 2385 goto out_err1; 2386 } 2387 fb = obj_to_fb(obj); 2388 2389 num_clips = r->num_clips; 2390 clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; 2391 2392 if (!num_clips != !clips_ptr) { 2393 ret = EINVAL; 2394 goto out_err1; 2395 } 2396 2397 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; 2398 2399 /* If userspace annotates copy, clips must come in pairs */ 2400 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { 2401 ret = EINVAL; 2402 goto out_err1; 2403 } 2404 2405 if (num_clips && clips_ptr) { 2406 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { 2407 ret = EINVAL; 2408 goto out_err1; 2409 } 2410 clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS, 2411 M_WAITOK | M_ZERO); 2412 2413 ret = copyin(clips_ptr, clips, num_clips * sizeof(*clips)); 2414 if (ret) 2415 goto out_err2; 2416 } 2417 2418 if (fb->funcs->dirty) { 2419 ret = -fb->funcs->dirty(fb, file_priv, flags, r->color, 2420 clips, num_clips); 2421 } else { 2422 ret = ENOSYS; 2423 goto out_err2; 2424 } 2425 2426 out_err2: 2427 free(clips, DRM_MEM_KMS); 2428 out_err1: 2429 sx_xunlock(&dev->mode_config.mutex); 2430 return ret; 2431 } 2432 2433 2434 /** 2435 * drm_fb_release - remove and free the FBs on this file 2436 * @filp: file * from the ioctl 2437 * 2438 * LOCKING: 2439 * Takes mode config lock. 2440 * 2441 * Destroy all the FBs associated with @filp. 2442 * 2443 * Called by the user via ioctl. 2444 * 2445 * RETURNS: 2446 * Zero on success, errno on failure. 2447 */ 2448 void drm_fb_release(struct drm_file *priv) 2449 { 2450 #if 1 2451 struct drm_device *dev = priv->dev; 2452 #else 2453 struct drm_device *dev = priv->minor->dev; 2454 #endif 2455 struct drm_framebuffer *fb, *tfb; 2456 2457 sx_xlock(&dev->mode_config.mutex); 2458 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 2459 list_del(&fb->filp_head); 2460 fb->funcs->destroy(fb); 2461 } 2462 sx_xunlock(&dev->mode_config.mutex); 2463 } 2464 2465 /** 2466 * drm_mode_attachmode - add a mode to the user mode list 2467 * @dev: DRM device 2468 * @connector: connector to add the mode to 2469 * @mode: mode to add 2470 * 2471 * Add @mode to @connector's user mode list. 2472 */ 2473 static void drm_mode_attachmode(struct drm_device *dev, 2474 struct drm_connector *connector, 2475 struct drm_display_mode *mode) 2476 { 2477 list_add_tail(&mode->head, &connector->user_modes); 2478 } 2479 2480 int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, 2481 const struct drm_display_mode *mode) 2482 { 2483 struct drm_connector *connector; 2484 int ret = 0; 2485 struct drm_display_mode *dup_mode, *next; 2486 DRM_LIST_HEAD(list); 2487 2488 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2489 if (!connector->encoder) 2490 continue; 2491 if (connector->encoder->crtc == crtc) { 2492 dup_mode = drm_mode_duplicate(dev, mode); 2493 if (!dup_mode) { 2494 ret = ENOMEM; 2495 goto out; 2496 } 2497 list_add_tail(&dup_mode->head, &list); 2498 } 2499 } 2500 2501 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2502 if (!connector->encoder) 2503 continue; 2504 if (connector->encoder->crtc == crtc) 2505 list_move_tail(list.next, &connector->user_modes); 2506 } 2507 2508 MPASS(!list_empty(&list)); 2509 2510 out: 2511 list_for_each_entry_safe(dup_mode, next, &list, head) 2512 drm_mode_destroy(dev, dup_mode); 2513 2514 return ret; 2515 } 2516 2517 static int drm_mode_detachmode(struct drm_device *dev, 2518 struct drm_connector *connector, 2519 struct drm_display_mode *mode) 2520 { 2521 int found = 0; 2522 int ret = 0; 2523 struct drm_display_mode *match_mode, *t; 2524 2525 list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) { 2526 if (drm_mode_equal(match_mode, mode)) { 2527 list_del(&match_mode->head); 2528 drm_mode_destroy(dev, match_mode); 2529 found = 1; 2530 break; 2531 } 2532 } 2533 2534 if (!found) 2535 ret = -EINVAL; 2536 2537 return ret; 2538 } 2539 2540 int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) 2541 { 2542 struct drm_connector *connector; 2543 2544 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2545 drm_mode_detachmode(dev, connector, mode); 2546 } 2547 return 0; 2548 } 2549 2550 /** 2551 * drm_fb_attachmode - Attach a user mode to an connector 2552 * @inode: inode from the ioctl 2553 * @filp: file * from the ioctl 2554 * @cmd: cmd from ioctl 2555 * @arg: arg from ioctl 2556 * 2557 * This attaches a user specified mode to an connector. 2558 * Called by the user via ioctl. 2559 * 2560 * RETURNS: 2561 * Zero on success, errno on failure. 2562 */ 2563 int drm_mode_attachmode_ioctl(struct drm_device *dev, 2564 void *data, struct drm_file *file_priv) 2565 { 2566 struct drm_mode_mode_cmd *mode_cmd = data; 2567 struct drm_connector *connector; 2568 struct drm_display_mode *mode; 2569 struct drm_mode_object *obj; 2570 struct drm_mode_modeinfo *umode = &mode_cmd->mode; 2571 int ret; 2572 2573 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2574 return -EINVAL; 2575 2576 sx_xlock(&dev->mode_config.mutex); 2577 2578 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2579 if (!obj) { 2580 ret = -EINVAL; 2581 goto out; 2582 } 2583 connector = obj_to_connector(obj); 2584 2585 mode = drm_mode_create(dev); 2586 if (!mode) { 2587 ret = -ENOMEM; 2588 goto out; 2589 } 2590 2591 ret = drm_crtc_convert_umode(mode, umode); 2592 if (ret) { 2593 DRM_DEBUG_KMS("Invalid mode\n"); 2594 drm_mode_destroy(dev, mode); 2595 goto out; 2596 } 2597 2598 drm_mode_attachmode(dev, connector, mode); 2599 out: 2600 sx_xunlock(&dev->mode_config.mutex); 2601 return ret; 2602 } 2603 2604 2605 /** 2606 * drm_fb_detachmode - Detach a user specified mode from an connector 2607 * @inode: inode from the ioctl 2608 * @filp: file * from the ioctl 2609 * @cmd: cmd from ioctl 2610 * @arg: arg from ioctl 2611 * 2612 * Called by the user via ioctl. 2613 * 2614 * RETURNS: 2615 * Zero on success, errno on failure. 2616 */ 2617 int drm_mode_detachmode_ioctl(struct drm_device *dev, 2618 void *data, struct drm_file *file_priv) 2619 { 2620 struct drm_mode_object *obj; 2621 struct drm_mode_mode_cmd *mode_cmd = data; 2622 struct drm_connector *connector; 2623 struct drm_display_mode mode; 2624 struct drm_mode_modeinfo *umode = &mode_cmd->mode; 2625 int ret; 2626 2627 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2628 return -EINVAL; 2629 2630 sx_xlock(&dev->mode_config.mutex); 2631 2632 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2633 if (!obj) { 2634 ret = -EINVAL; 2635 goto out; 2636 } 2637 connector = obj_to_connector(obj); 2638 2639 ret = drm_crtc_convert_umode(&mode, umode); 2640 if (ret) { 2641 DRM_DEBUG_KMS("Invalid mode\n"); 2642 goto out; 2643 } 2644 2645 ret = drm_mode_detachmode(dev, connector, &mode); 2646 out: 2647 sx_xunlock(&dev->mode_config.mutex); 2648 return ret; 2649 } 2650 2651 struct drm_property *drm_property_create(struct drm_device *dev, int flags, 2652 const char *name, int num_values) 2653 { 2654 struct drm_property *property = NULL; 2655 int ret; 2656 2657 property = malloc(sizeof(struct drm_property), DRM_MEM_KMS, 2658 M_WAITOK | M_ZERO); 2659 2660 if (num_values) { 2661 property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS, 2662 M_WAITOK | M_ZERO); 2663 } 2664 2665 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); 2666 if (ret) 2667 goto fail; 2668 property->flags = flags; 2669 property->num_values = num_values; 2670 INIT_LIST_HEAD(&property->enum_blob_list); 2671 2672 if (name) { 2673 strncpy(property->name, name, DRM_PROP_NAME_LEN); 2674 property->name[DRM_PROP_NAME_LEN-1] = '\0'; 2675 } 2676 2677 list_add_tail(&property->head, &dev->mode_config.property_list); 2678 return property; 2679 2680 fail: 2681 free(property->values, DRM_MEM_KMS); 2682 free(property, DRM_MEM_KMS); 2683 return (NULL); 2684 } 2685 2686 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, 2687 const char *name, 2688 const struct drm_prop_enum_list *props, 2689 int num_values) 2690 { 2691 struct drm_property *property; 2692 int i, ret; 2693 2694 flags |= DRM_MODE_PROP_ENUM; 2695 2696 property = drm_property_create(dev, flags, name, num_values); 2697 if (!property) 2698 return NULL; 2699 2700 for (i = 0; i < num_values; i++) { 2701 ret = drm_property_add_enum(property, i, 2702 props[i].type, 2703 props[i].name); 2704 if (ret) { 2705 drm_property_destroy(dev, property); 2706 return NULL; 2707 } 2708 } 2709 2710 return property; 2711 } 2712 2713 struct drm_property *drm_property_create_bitmask(struct drm_device *dev, 2714 int flags, const char *name, 2715 const struct drm_prop_enum_list *props, 2716 int num_values) 2717 { 2718 struct drm_property *property; 2719 int i, ret; 2720 2721 flags |= DRM_MODE_PROP_BITMASK; 2722 2723 property = drm_property_create(dev, flags, name, num_values); 2724 if (!property) 2725 return NULL; 2726 2727 for (i = 0; i < num_values; i++) { 2728 ret = drm_property_add_enum(property, i, 2729 props[i].type, 2730 props[i].name); 2731 if (ret) { 2732 drm_property_destroy(dev, property); 2733 return NULL; 2734 } 2735 } 2736 2737 return property; 2738 } 2739 2740 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, 2741 const char *name, 2742 uint64_t min, uint64_t max) 2743 { 2744 struct drm_property *property; 2745 2746 flags |= DRM_MODE_PROP_RANGE; 2747 2748 property = drm_property_create(dev, flags, name, 2); 2749 if (!property) 2750 return NULL; 2751 2752 property->values[0] = min; 2753 property->values[1] = max; 2754 2755 return property; 2756 } 2757 2758 int drm_property_add_enum(struct drm_property *property, int index, 2759 uint64_t value, const char *name) 2760 { 2761 struct drm_property_enum *prop_enum; 2762 2763 if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) 2764 return -EINVAL; 2765 2766 /* 2767 * Bitmask enum properties have the additional constraint of values 2768 * from 0 to 63 2769 */ 2770 if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63)) 2771 return -EINVAL; 2772 2773 if (!list_empty(&property->enum_blob_list)) { 2774 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2775 if (prop_enum->value == value) { 2776 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2777 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2778 return 0; 2779 } 2780 } 2781 } 2782 2783 prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS, 2784 M_WAITOK | M_ZERO); 2785 2786 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2787 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2788 prop_enum->value = value; 2789 2790 property->values[index] = value; 2791 list_add_tail(&prop_enum->head, &property->enum_blob_list); 2792 return 0; 2793 } 2794 2795 void drm_property_destroy(struct drm_device *dev, struct drm_property *property) 2796 { 2797 struct drm_property_enum *prop_enum, *pt; 2798 2799 list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { 2800 list_del(&prop_enum->head); 2801 free(prop_enum, DRM_MEM_KMS); 2802 } 2803 2804 if (property->num_values) 2805 free(property->values, DRM_MEM_KMS); 2806 drm_mode_object_put(dev, &property->base); 2807 list_del(&property->head); 2808 free(property, DRM_MEM_KMS); 2809 } 2810 2811 void drm_connector_attach_property(struct drm_connector *connector, 2812 struct drm_property *property, uint64_t init_val) 2813 { 2814 drm_object_attach_property(&connector->base, property, init_val); 2815 } 2816 2817 int drm_connector_property_set_value(struct drm_connector *connector, 2818 struct drm_property *property, uint64_t value) 2819 { 2820 return drm_object_property_set_value(&connector->base, property, value); 2821 } 2822 2823 int drm_connector_property_get_value(struct drm_connector *connector, 2824 struct drm_property *property, uint64_t *val) 2825 { 2826 return drm_object_property_get_value(&connector->base, property, val); 2827 } 2828 2829 void drm_object_attach_property(struct drm_mode_object *obj, 2830 struct drm_property *property, 2831 uint64_t init_val) 2832 { 2833 int count = obj->properties->count; 2834 2835 if (count == DRM_OBJECT_MAX_PROPERTY) { 2836 printf("Failed to attach object property (type: 0x%x). Please " 2837 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 2838 "you see this message on the same object type.\n", 2839 obj->type); 2840 return; 2841 } 2842 2843 obj->properties->ids[count] = property->base.id; 2844 obj->properties->values[count] = init_val; 2845 obj->properties->count++; 2846 } 2847 2848 int drm_object_property_set_value(struct drm_mode_object *obj, 2849 struct drm_property *property, uint64_t val) 2850 { 2851 int i; 2852 2853 for (i = 0; i < obj->properties->count; i++) { 2854 if (obj->properties->ids[i] == property->base.id) { 2855 obj->properties->values[i] = val; 2856 return 0; 2857 } 2858 } 2859 2860 return -EINVAL; 2861 } 2862 2863 int drm_object_property_get_value(struct drm_mode_object *obj, 2864 struct drm_property *property, uint64_t *val) 2865 { 2866 int i; 2867 2868 for (i = 0; i < obj->properties->count; i++) { 2869 if (obj->properties->ids[i] == property->base.id) { 2870 *val = obj->properties->values[i]; 2871 return 0; 2872 } 2873 } 2874 2875 return -EINVAL; 2876 } 2877 2878 int drm_mode_getproperty_ioctl(struct drm_device *dev, 2879 void *data, struct drm_file *file_priv) 2880 { 2881 struct drm_mode_object *obj; 2882 struct drm_mode_get_property *out_resp = data; 2883 struct drm_property *property; 2884 int enum_count = 0; 2885 int blob_count = 0; 2886 int value_count = 0; 2887 int ret = 0, i; 2888 int copied; 2889 struct drm_property_enum *prop_enum; 2890 struct drm_mode_property_enum __user *enum_ptr; 2891 struct drm_property_blob *prop_blob; 2892 uint32_t *blob_id_ptr; 2893 uint64_t *values_ptr; 2894 uint32_t *blob_length_ptr; 2895 2896 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2897 return -EINVAL; 2898 2899 sx_xlock(&dev->mode_config.mutex); 2900 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 2901 if (!obj) { 2902 ret = -EINVAL; 2903 goto done; 2904 } 2905 property = obj_to_property(obj); 2906 2907 if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 2908 list_for_each_entry(prop_enum, &property->enum_blob_list, head) 2909 enum_count++; 2910 } else if (property->flags & DRM_MODE_PROP_BLOB) { 2911 list_for_each_entry(prop_blob, &property->enum_blob_list, head) 2912 blob_count++; 2913 } 2914 2915 value_count = property->num_values; 2916 2917 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); 2918 out_resp->name[DRM_PROP_NAME_LEN-1] = 0; 2919 out_resp->flags = property->flags; 2920 2921 if ((out_resp->count_values >= value_count) && value_count) { 2922 values_ptr = (uint64_t *)(uintptr_t)out_resp->values_ptr; 2923 for (i = 0; i < value_count; i++) { 2924 if (copyout(&property->values[i], values_ptr + i, sizeof(uint64_t))) { 2925 ret = -EFAULT; 2926 goto done; 2927 } 2928 } 2929 } 2930 out_resp->count_values = value_count; 2931 2932 if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 2933 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { 2934 copied = 0; 2935 enum_ptr = (struct drm_mode_property_enum *)(uintptr_t)out_resp->enum_blob_ptr; 2936 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2937 2938 if (copyout(&prop_enum->value, &enum_ptr[copied].value, sizeof(uint64_t))) { 2939 ret = -EFAULT; 2940 goto done; 2941 } 2942 2943 if (copyout(&prop_enum->name, 2944 &enum_ptr[copied].name,DRM_PROP_NAME_LEN)) { 2945 ret = -EFAULT; 2946 goto done; 2947 } 2948 copied++; 2949 } 2950 } 2951 out_resp->count_enum_blobs = enum_count; 2952 } 2953 2954 if (property->flags & DRM_MODE_PROP_BLOB) { 2955 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { 2956 copied = 0; 2957 blob_id_ptr = (uint32_t *)(uintptr_t)out_resp->enum_blob_ptr; 2958 blob_length_ptr = (uint32_t *)(uintptr_t)out_resp->values_ptr; 2959 2960 list_for_each_entry(prop_blob, &property->enum_blob_list, head) { 2961 if (copyout(&prop_blob->base.id, 2962 blob_id_ptr + copied, sizeof(uint32_t))) { 2963 ret = -EFAULT; 2964 goto done; 2965 } 2966 2967 if (copyout(&prop_blob->length, 2968 blob_length_ptr + copied, sizeof(uint32_t))) { 2969 ret = -EFAULT; 2970 goto done; 2971 } 2972 2973 copied++; 2974 } 2975 } 2976 out_resp->count_enum_blobs = blob_count; 2977 } 2978 done: 2979 sx_xunlock(&dev->mode_config.mutex); 2980 return ret; 2981 } 2982 2983 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, 2984 void *data) 2985 { 2986 struct drm_property_blob *blob; 2987 int ret; 2988 2989 if (!length || !data) 2990 return NULL; 2991 2992 blob = malloc(sizeof(struct drm_property_blob) + length, DRM_MEM_KMS, 2993 M_WAITOK | M_ZERO); 2994 2995 ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); 2996 if (ret) { 2997 free(blob, DRM_MEM_KMS); 2998 return (NULL); 2999 } 3000 3001 blob->length = length; 3002 3003 memcpy(blob->data, data, length); 3004 3005 list_add_tail(&blob->head, &dev->mode_config.property_blob_list); 3006 return blob; 3007 } 3008 3009 static void drm_property_destroy_blob(struct drm_device *dev, 3010 struct drm_property_blob *blob) 3011 { 3012 drm_mode_object_put(dev, &blob->base); 3013 list_del(&blob->head); 3014 free(blob, DRM_MEM_KMS); 3015 } 3016 3017 int drm_mode_getblob_ioctl(struct drm_device *dev, 3018 void *data, struct drm_file *file_priv) 3019 { 3020 struct drm_mode_object *obj; 3021 struct drm_mode_get_blob *out_resp = data; 3022 struct drm_property_blob *blob; 3023 int ret = 0; 3024 void *blob_ptr; 3025 3026 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3027 return -EINVAL; 3028 3029 sx_xlock(&dev->mode_config.mutex); 3030 obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); 3031 if (!obj) { 3032 ret = -EINVAL; 3033 goto done; 3034 } 3035 blob = obj_to_blob(obj); 3036 3037 if (out_resp->length == blob->length) { 3038 blob_ptr = (void *)(unsigned long)out_resp->data; 3039 if (copyout(blob->data, blob_ptr, blob->length)){ 3040 ret = -EFAULT; 3041 goto done; 3042 } 3043 } 3044 out_resp->length = blob->length; 3045 3046 done: 3047 sx_xunlock(&dev->mode_config.mutex); 3048 return ret; 3049 } 3050 3051 int drm_mode_connector_update_edid_property(struct drm_connector *connector, 3052 struct edid *edid) 3053 { 3054 struct drm_device *dev = connector->dev; 3055 int ret, size; 3056 3057 if (connector->edid_blob_ptr) 3058 drm_property_destroy_blob(dev, connector->edid_blob_ptr); 3059 3060 /* Delete edid, when there is none. */ 3061 if (!edid) { 3062 connector->edid_blob_ptr = NULL; 3063 ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); 3064 return ret; 3065 } 3066 3067 size = EDID_LENGTH * (1 + edid->extensions); 3068 connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 3069 size, edid); 3070 3071 ret = drm_connector_property_set_value(connector, 3072 dev->mode_config.edid_property, 3073 connector->edid_blob_ptr->base.id); 3074 3075 return ret; 3076 } 3077 3078 static bool drm_property_change_is_valid(struct drm_property *property, 3079 u64 value) 3080 { 3081 if (property->flags & DRM_MODE_PROP_IMMUTABLE) 3082 return false; 3083 if (property->flags & DRM_MODE_PROP_RANGE) { 3084 if (value < property->values[0] || value > property->values[1]) 3085 return false; 3086 return true; 3087 } else if (property->flags & DRM_MODE_PROP_BITMASK) { 3088 int i; 3089 u64 valid_mask = 0; 3090 for (i = 0; i < property->num_values; i++) 3091 valid_mask |= (1ULL << property->values[i]); 3092 return !(value & ~valid_mask); 3093 } else { 3094 int i; 3095 for (i = 0; i < property->num_values; i++) 3096 if (property->values[i] == value) 3097 return true; 3098 return false; 3099 } 3100 } 3101 3102 int drm_mode_connector_property_set_ioctl(struct drm_device *dev, 3103 void *data, struct drm_file *file_priv) 3104 { 3105 struct drm_mode_connector_set_property *conn_set_prop = data; 3106 struct drm_mode_obj_set_property obj_set_prop = { 3107 .value = conn_set_prop->value, 3108 .prop_id = conn_set_prop->prop_id, 3109 .obj_id = conn_set_prop->connector_id, 3110 .obj_type = DRM_MODE_OBJECT_CONNECTOR 3111 }; 3112 3113 /* It does all the locking and checking we need */ 3114 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv); 3115 } 3116 3117 static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, 3118 struct drm_property *property, 3119 uint64_t value) 3120 { 3121 int ret = -EINVAL; 3122 struct drm_connector *connector = obj_to_connector(obj); 3123 3124 /* Do DPMS ourselves */ 3125 if (property == connector->dev->mode_config.dpms_property) { 3126 if (connector->funcs->dpms) 3127 (*connector->funcs->dpms)(connector, (int)value); 3128 ret = 0; 3129 } else if (connector->funcs->set_property) 3130 ret = connector->funcs->set_property(connector, property, value); 3131 3132 /* store the property value if successful */ 3133 if (!ret) 3134 drm_connector_property_set_value(connector, property, value); 3135 return ret; 3136 } 3137 3138 static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, 3139 struct drm_property *property, 3140 uint64_t value) 3141 { 3142 int ret = -EINVAL; 3143 struct drm_crtc *crtc = obj_to_crtc(obj); 3144 3145 if (crtc->funcs->set_property) 3146 ret = crtc->funcs->set_property(crtc, property, value); 3147 if (!ret) 3148 drm_object_property_set_value(obj, property, value); 3149 3150 return ret; 3151 } 3152 3153 static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj, 3154 struct drm_property *property, 3155 uint64_t value) 3156 { 3157 int ret = -EINVAL; 3158 struct drm_plane *plane = obj_to_plane(obj); 3159 3160 if (plane->funcs->set_property) 3161 ret = plane->funcs->set_property(plane, property, value); 3162 if (!ret) 3163 drm_object_property_set_value(obj, property, value); 3164 3165 return ret; 3166 } 3167 3168 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 3169 struct drm_file *file_priv) 3170 { 3171 struct drm_mode_obj_get_properties *arg = data; 3172 struct drm_mode_object *obj; 3173 int ret = 0; 3174 int i; 3175 int copied = 0; 3176 int props_count = 0; 3177 uint32_t __user *props_ptr; 3178 uint64_t __user *prop_values_ptr; 3179 3180 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3181 return -EINVAL; 3182 3183 sx_xlock(&dev->mode_config.mutex); 3184 3185 obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 3186 if (!obj) { 3187 ret = -EINVAL; 3188 goto out; 3189 } 3190 if (!obj->properties) { 3191 ret = -EINVAL; 3192 goto out; 3193 } 3194 3195 props_count = obj->properties->count; 3196 3197 /* This ioctl is called twice, once to determine how much space is 3198 * needed, and the 2nd time to fill it. */ 3199 if ((arg->count_props >= props_count) && props_count) { 3200 copied = 0; 3201 props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); 3202 prop_values_ptr = (uint64_t __user *)(unsigned long) 3203 (arg->prop_values_ptr); 3204 for (i = 0; i < props_count; i++) { 3205 if (copyout(props_ptr + copied, 3206 &obj->properties->ids[i], sizeof(uint32_t))) { 3207 ret = -EFAULT; 3208 goto out; 3209 } 3210 if (copyout(prop_values_ptr + copied, 3211 &obj->properties->values[i], sizeof(uint64_t))) { 3212 ret = -EFAULT; 3213 goto out; 3214 } 3215 copied++; 3216 } 3217 } 3218 arg->count_props = props_count; 3219 out: 3220 sx_xunlock(&dev->mode_config.mutex); 3221 return ret; 3222 } 3223 3224 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 3225 struct drm_file *file_priv) 3226 { 3227 struct drm_mode_obj_set_property *arg = data; 3228 struct drm_mode_object *arg_obj; 3229 struct drm_mode_object *prop_obj; 3230 struct drm_property *property; 3231 int ret = -EINVAL; 3232 int i; 3233 3234 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3235 return -EINVAL; 3236 3237 sx_xlock(&dev->mode_config.mutex); 3238 3239 arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 3240 if (!arg_obj) 3241 goto out; 3242 if (!arg_obj->properties) 3243 goto out; 3244 3245 for (i = 0; i < arg_obj->properties->count; i++) 3246 if (arg_obj->properties->ids[i] == arg->prop_id) 3247 break; 3248 3249 if (i == arg_obj->properties->count) 3250 goto out; 3251 3252 prop_obj = drm_mode_object_find(dev, arg->prop_id, 3253 DRM_MODE_OBJECT_PROPERTY); 3254 if (!prop_obj) 3255 goto out; 3256 property = obj_to_property(prop_obj); 3257 3258 if (!drm_property_change_is_valid(property, arg->value)) 3259 goto out; 3260 3261 switch (arg_obj->type) { 3262 case DRM_MODE_OBJECT_CONNECTOR: 3263 ret = drm_mode_connector_set_obj_prop(arg_obj, property, 3264 arg->value); 3265 break; 3266 case DRM_MODE_OBJECT_CRTC: 3267 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); 3268 break; 3269 case DRM_MODE_OBJECT_PLANE: 3270 ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value); 3271 break; 3272 } 3273 3274 out: 3275 sx_xunlock(&dev->mode_config.mutex); 3276 return ret; 3277 } 3278 3279 int drm_mode_connector_attach_encoder(struct drm_connector *connector, 3280 struct drm_encoder *encoder) 3281 { 3282 int i; 3283 3284 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3285 if (connector->encoder_ids[i] == 0) { 3286 connector->encoder_ids[i] = encoder->base.id; 3287 return 0; 3288 } 3289 } 3290 return -ENOMEM; 3291 } 3292 3293 void drm_mode_connector_detach_encoder(struct drm_connector *connector, 3294 struct drm_encoder *encoder) 3295 { 3296 int i; 3297 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3298 if (connector->encoder_ids[i] == encoder->base.id) { 3299 connector->encoder_ids[i] = 0; 3300 if (connector->encoder == encoder) 3301 connector->encoder = NULL; 3302 break; 3303 } 3304 } 3305 } 3306 3307 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 3308 int gamma_size) 3309 { 3310 crtc->gamma_size = gamma_size; 3311 3312 crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3, 3313 DRM_MEM_KMS, M_WAITOK | M_ZERO); 3314 3315 return 0; 3316 } 3317 3318 int drm_mode_gamma_set_ioctl(struct drm_device *dev, 3319 void *data, struct drm_file *file_priv) 3320 { 3321 struct drm_mode_crtc_lut *crtc_lut = data; 3322 struct drm_mode_object *obj; 3323 struct drm_crtc *crtc; 3324 void *r_base, *g_base, *b_base; 3325 int size; 3326 int ret = 0; 3327 3328 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3329 return -EINVAL; 3330 3331 sx_xlock(&dev->mode_config.mutex); 3332 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3333 if (!obj) { 3334 ret = -EINVAL; 3335 goto out; 3336 } 3337 crtc = obj_to_crtc(obj); 3338 3339 /* memcpy into gamma store */ 3340 if (crtc_lut->gamma_size != crtc->gamma_size) { 3341 ret = -EINVAL; 3342 goto out; 3343 } 3344 3345 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3346 r_base = crtc->gamma_store; 3347 if (copyin((void *)(uintptr_t)crtc_lut->red, r_base, size)) { 3348 ret = -EFAULT; 3349 goto out; 3350 } 3351 3352 g_base = (char *)r_base + size; 3353 if (copyin((void *)(uintptr_t)crtc_lut->green, g_base, size)) { 3354 ret = -EFAULT; 3355 goto out; 3356 } 3357 3358 b_base = (char *)g_base + size; 3359 if (copyin((void *)(uintptr_t)crtc_lut->blue, b_base, size)) { 3360 ret = -EFAULT; 3361 goto out; 3362 } 3363 3364 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); 3365 3366 out: 3367 sx_xunlock(&dev->mode_config.mutex); 3368 return ret; 3369 3370 } 3371 3372 int drm_mode_gamma_get_ioctl(struct drm_device *dev, 3373 void *data, struct drm_file *file_priv) 3374 { 3375 struct drm_mode_crtc_lut *crtc_lut = data; 3376 struct drm_mode_object *obj; 3377 struct drm_crtc *crtc; 3378 void *r_base, *g_base, *b_base; 3379 int size; 3380 int ret = 0; 3381 3382 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3383 return -EINVAL; 3384 3385 sx_xlock(&dev->mode_config.mutex); 3386 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3387 if (!obj) { 3388 ret = -EINVAL; 3389 goto out; 3390 } 3391 crtc = obj_to_crtc(obj); 3392 3393 if (crtc->funcs->gamma_set == NULL) { 3394 ret = -ENOSYS; 3395 goto out; 3396 } 3397 3398 /* memcpy into gamma store */ 3399 if (crtc_lut->gamma_size != crtc->gamma_size) { 3400 ret = -EINVAL; 3401 goto out; 3402 } 3403 3404 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3405 r_base = crtc->gamma_store; 3406 if (copyout(r_base, (void *)(uintptr_t)crtc_lut->red, size)) { 3407 ret = -EFAULT; 3408 goto out; 3409 } 3410 3411 g_base = (char *)r_base + size; 3412 if (copyout(g_base, (void *)(uintptr_t)crtc_lut->green, size)) { 3413 ret = -EFAULT; 3414 goto out; 3415 } 3416 3417 b_base = (char *)g_base + size; 3418 if (copyout(b_base, (void *)(uintptr_t)crtc_lut->blue, size)) { 3419 ret = -EFAULT; 3420 goto out; 3421 } 3422 out: 3423 sx_xunlock(&dev->mode_config.mutex); 3424 return ret; 3425 } 3426 3427 static void 3428 drm_kms_free(void *arg) 3429 { 3430 3431 free(arg, DRM_MEM_KMS); 3432 } 3433 3434 int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, 3435 struct drm_file *file_priv) 3436 { 3437 struct drm_mode_crtc_page_flip *page_flip = data; 3438 struct drm_mode_object *obj; 3439 struct drm_crtc *crtc; 3440 struct drm_framebuffer *fb; 3441 struct drm_pending_vblank_event *e = NULL; 3442 int ret = EINVAL; 3443 3444 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || 3445 page_flip->reserved != 0) 3446 return (EINVAL); 3447 3448 sx_xlock(&dev->mode_config.mutex); 3449 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); 3450 if (!obj) 3451 goto out; 3452 crtc = obj_to_crtc(obj); 3453 3454 if (crtc->fb == NULL) { 3455 /* The framebuffer is currently unbound, presumably 3456 * due to a hotplug event, that userspace has not 3457 * yet discovered. 3458 */ 3459 ret = EBUSY; 3460 goto out; 3461 } 3462 3463 if (crtc->funcs->page_flip == NULL) 3464 goto out; 3465 3466 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); 3467 if (!obj) 3468 goto out; 3469 fb = obj_to_fb(obj); 3470 3471 if (crtc->mode.hdisplay > fb->width || 3472 crtc->mode.vdisplay > fb->height || 3473 crtc->x > fb->width - crtc->mode.hdisplay || 3474 crtc->y > fb->height - crtc->mode.vdisplay) { 3475 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", 3476 fb->width, fb->height, 3477 crtc->mode.hdisplay, crtc->mode.vdisplay, 3478 crtc->x, crtc->y); 3479 ret = ENOSPC; 3480 goto out; 3481 } 3482 3483 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3484 ret = ENOMEM; 3485 mtx_lock(&dev->event_lock); 3486 if (file_priv->event_space < sizeof e->event) { 3487 mtx_unlock(&dev->event_lock); 3488 goto out; 3489 } 3490 file_priv->event_space -= sizeof e->event; 3491 mtx_unlock(&dev->event_lock); 3492 3493 e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO); 3494 3495 e->event.base.type = DRM_EVENT_FLIP_COMPLETE; 3496 e->event.base.length = sizeof e->event; 3497 e->event.user_data = page_flip->user_data; 3498 e->base.event = &e->event.base; 3499 e->base.file_priv = file_priv; 3500 e->base.destroy = 3501 (void (*) (struct drm_pending_event *))drm_kms_free; 3502 } 3503 3504 ret = -crtc->funcs->page_flip(crtc, fb, e); 3505 if (ret != 0) { 3506 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3507 mtx_lock(&dev->event_lock); 3508 file_priv->event_space += sizeof e->event; 3509 mtx_unlock(&dev->event_lock); 3510 free(e, DRM_MEM_KMS); 3511 } 3512 } 3513 3514 out: 3515 sx_xunlock(&dev->mode_config.mutex); 3516 CTR3(KTR_DRM, "page_flip_ioctl %d %d %d", curproc->p_pid, 3517 page_flip->crtc_id, ret); 3518 return (ret); 3519 } 3520 3521 void drm_mode_config_reset(struct drm_device *dev) 3522 { 3523 struct drm_crtc *crtc; 3524 struct drm_encoder *encoder; 3525 struct drm_connector *connector; 3526 3527 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 3528 if (crtc->funcs->reset) 3529 crtc->funcs->reset(crtc); 3530 3531 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 3532 if (encoder->funcs->reset) 3533 encoder->funcs->reset(encoder); 3534 3535 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 3536 if (connector->funcs->reset) 3537 connector->funcs->reset(connector); 3538 } 3539 3540 int drm_mode_create_dumb_ioctl(struct drm_device *dev, 3541 void *data, struct drm_file *file_priv) 3542 { 3543 struct drm_mode_create_dumb *args = data; 3544 3545 if (!dev->driver->dumb_create) 3546 return -ENOTSUP; 3547 return dev->driver->dumb_create(file_priv, dev, args); 3548 } 3549 3550 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, 3551 void *data, struct drm_file *file_priv) 3552 { 3553 struct drm_mode_map_dumb *args = data; 3554 3555 /* call driver ioctl to get mmap offset */ 3556 if (!dev->driver->dumb_map_offset) 3557 return -ENOTSUP; 3558 3559 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset); 3560 } 3561 3562 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, 3563 void *data, struct drm_file *file_priv) 3564 { 3565 struct drm_mode_destroy_dumb *args = data; 3566 3567 if (!dev->driver->dumb_destroy) 3568 return -ENOTSUP; 3569 3570 return dev->driver->dumb_destroy(file_priv, dev, args->handle); 3571 } 3572 3573 /* 3574 * Just need to support RGB formats here for compat with code that doesn't 3575 * use pixel formats directly yet. 3576 */ 3577 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, 3578 int *bpp) 3579 { 3580 switch (format) { 3581 case DRM_FORMAT_RGB332: 3582 case DRM_FORMAT_BGR233: 3583 *depth = 8; 3584 *bpp = 8; 3585 break; 3586 case DRM_FORMAT_XRGB1555: 3587 case DRM_FORMAT_XBGR1555: 3588 case DRM_FORMAT_RGBX5551: 3589 case DRM_FORMAT_BGRX5551: 3590 case DRM_FORMAT_ARGB1555: 3591 case DRM_FORMAT_ABGR1555: 3592 case DRM_FORMAT_RGBA5551: 3593 case DRM_FORMAT_BGRA5551: 3594 *depth = 15; 3595 *bpp = 16; 3596 break; 3597 case DRM_FORMAT_RGB565: 3598 case DRM_FORMAT_BGR565: 3599 *depth = 16; 3600 *bpp = 16; 3601 break; 3602 case DRM_FORMAT_RGB888: 3603 case DRM_FORMAT_BGR888: 3604 *depth = 24; 3605 *bpp = 24; 3606 break; 3607 case DRM_FORMAT_XRGB8888: 3608 case DRM_FORMAT_XBGR8888: 3609 case DRM_FORMAT_RGBX8888: 3610 case DRM_FORMAT_BGRX8888: 3611 *depth = 24; 3612 *bpp = 32; 3613 break; 3614 case DRM_FORMAT_XRGB2101010: 3615 case DRM_FORMAT_XBGR2101010: 3616 case DRM_FORMAT_RGBX1010102: 3617 case DRM_FORMAT_BGRX1010102: 3618 case DRM_FORMAT_ARGB2101010: 3619 case DRM_FORMAT_ABGR2101010: 3620 case DRM_FORMAT_RGBA1010102: 3621 case DRM_FORMAT_BGRA1010102: 3622 *depth = 30; 3623 *bpp = 32; 3624 break; 3625 case DRM_FORMAT_ARGB8888: 3626 case DRM_FORMAT_ABGR8888: 3627 case DRM_FORMAT_RGBA8888: 3628 case DRM_FORMAT_BGRA8888: 3629 *depth = 32; 3630 *bpp = 32; 3631 break; 3632 default: 3633 DRM_DEBUG_KMS("unsupported pixel format\n"); 3634 *depth = 0; 3635 *bpp = 0; 3636 break; 3637 } 3638 } 3639 3640 /** 3641 * drm_format_num_planes - get the number of planes for format 3642 * @format: pixel format (DRM_FORMAT_*) 3643 * 3644 * RETURNS: 3645 * The number of planes used by the specified pixel format. 3646 */ 3647 int drm_format_num_planes(uint32_t format) 3648 { 3649 switch (format) { 3650 case DRM_FORMAT_YUV410: 3651 case DRM_FORMAT_YVU410: 3652 case DRM_FORMAT_YUV411: 3653 case DRM_FORMAT_YVU411: 3654 case DRM_FORMAT_YUV420: 3655 case DRM_FORMAT_YVU420: 3656 case DRM_FORMAT_YUV422: 3657 case DRM_FORMAT_YVU422: 3658 case DRM_FORMAT_YUV444: 3659 case DRM_FORMAT_YVU444: 3660 return 3; 3661 case DRM_FORMAT_NV12: 3662 case DRM_FORMAT_NV21: 3663 case DRM_FORMAT_NV16: 3664 case DRM_FORMAT_NV61: 3665 return 2; 3666 default: 3667 return 1; 3668 } 3669 } 3670 3671 /** 3672 * drm_format_plane_cpp - determine the bytes per pixel value 3673 * @format: pixel format (DRM_FORMAT_*) 3674 * @plane: plane index 3675 * 3676 * RETURNS: 3677 * The bytes per pixel value for the specified plane. 3678 */ 3679 int drm_format_plane_cpp(uint32_t format, int plane) 3680 { 3681 unsigned int depth; 3682 int bpp; 3683 3684 if (plane >= drm_format_num_planes(format)) 3685 return 0; 3686 3687 switch (format) { 3688 case DRM_FORMAT_YUYV: 3689 case DRM_FORMAT_YVYU: 3690 case DRM_FORMAT_UYVY: 3691 case DRM_FORMAT_VYUY: 3692 return 2; 3693 case DRM_FORMAT_NV12: 3694 case DRM_FORMAT_NV21: 3695 case DRM_FORMAT_NV16: 3696 case DRM_FORMAT_NV61: 3697 return plane ? 2 : 1; 3698 case DRM_FORMAT_YUV410: 3699 case DRM_FORMAT_YVU410: 3700 case DRM_FORMAT_YUV411: 3701 case DRM_FORMAT_YVU411: 3702 case DRM_FORMAT_YUV420: 3703 case DRM_FORMAT_YVU420: 3704 case DRM_FORMAT_YUV422: 3705 case DRM_FORMAT_YVU422: 3706 case DRM_FORMAT_YUV444: 3707 case DRM_FORMAT_YVU444: 3708 return 1; 3709 default: 3710 drm_fb_get_bpp_depth(format, &depth, &bpp); 3711 return bpp >> 3; 3712 } 3713 } 3714 3715 /** 3716 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor 3717 * @format: pixel format (DRM_FORMAT_*) 3718 * 3719 * RETURNS: 3720 * The horizontal chroma subsampling factor for the 3721 * specified pixel format. 3722 */ 3723 int drm_format_horz_chroma_subsampling(uint32_t format) 3724 { 3725 switch (format) { 3726 case DRM_FORMAT_YUV411: 3727 case DRM_FORMAT_YVU411: 3728 case DRM_FORMAT_YUV410: 3729 case DRM_FORMAT_YVU410: 3730 return 4; 3731 case DRM_FORMAT_YUYV: 3732 case DRM_FORMAT_YVYU: 3733 case DRM_FORMAT_UYVY: 3734 case DRM_FORMAT_VYUY: 3735 case DRM_FORMAT_NV12: 3736 case DRM_FORMAT_NV21: 3737 case DRM_FORMAT_NV16: 3738 case DRM_FORMAT_NV61: 3739 case DRM_FORMAT_YUV422: 3740 case DRM_FORMAT_YVU422: 3741 case DRM_FORMAT_YUV420: 3742 case DRM_FORMAT_YVU420: 3743 return 2; 3744 default: 3745 return 1; 3746 } 3747 } 3748 3749 /** 3750 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor 3751 * @format: pixel format (DRM_FORMAT_*) 3752 * 3753 * RETURNS: 3754 * The vertical chroma subsampling factor for the 3755 * specified pixel format. 3756 */ 3757 int drm_format_vert_chroma_subsampling(uint32_t format) 3758 { 3759 switch (format) { 3760 case DRM_FORMAT_YUV410: 3761 case DRM_FORMAT_YVU410: 3762 return 4; 3763 case DRM_FORMAT_YUV420: 3764 case DRM_FORMAT_YVU420: 3765 case DRM_FORMAT_NV12: 3766 case DRM_FORMAT_NV21: 3767 return 2; 3768 default: 3769 return 1; 3770 } 3771 } 3772