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 * Caller must hold 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 list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 376 dev->mode_config.num_crtc++; 377 out: 378 sx_xunlock(&dev->mode_config.mutex); 379 380 return ret; 381 } 382 383 /** 384 * drm_crtc_cleanup - Cleans up the core crtc usage. 385 * @crtc: CRTC to cleanup 386 * 387 * LOCKING: 388 * Caller must hold mode config lock. 389 * 390 * Cleanup @crtc. Removes from drm modesetting space 391 * does NOT free object, caller does that. 392 */ 393 void drm_crtc_cleanup(struct drm_crtc *crtc) 394 { 395 struct drm_device *dev = crtc->dev; 396 397 DRM_MODE_CONFIG_ASSERT_LOCKED(dev); 398 399 if (crtc->gamma_store) { 400 free(crtc->gamma_store, DRM_MEM_KMS); 401 crtc->gamma_store = NULL; 402 } 403 404 drm_mode_object_put(dev, &crtc->base); 405 list_del(&crtc->head); 406 dev->mode_config.num_crtc--; 407 } 408 409 /** 410 * drm_mode_probed_add - add a mode to a connector's probed mode list 411 * @connector: connector the new mode 412 * @mode: mode data 413 * 414 * LOCKING: 415 * Caller must hold mode config lock. 416 * 417 * Add @mode to @connector's mode list for later use. 418 */ 419 void drm_mode_probed_add(struct drm_connector *connector, 420 struct drm_display_mode *mode) 421 { 422 423 DRM_MODE_CONFIG_ASSERT_LOCKED(connector->dev); 424 425 list_add(&mode->head, &connector->probed_modes); 426 } 427 428 /** 429 * drm_mode_remove - remove and free a mode 430 * @connector: connector list to modify 431 * @mode: mode to remove 432 * 433 * LOCKING: 434 * Caller must hold mode config lock. 435 * 436 * Remove @mode from @connector's mode list, then free it. 437 */ 438 void drm_mode_remove(struct drm_connector *connector, 439 struct drm_display_mode *mode) 440 { 441 442 DRM_MODE_CONFIG_ASSERT_LOCKED(connector->dev); 443 444 list_del(&mode->head); 445 drm_mode_destroy(connector->dev, mode); 446 } 447 448 /** 449 * drm_connector_init - Init a preallocated connector 450 * @dev: DRM device 451 * @connector: the connector to init 452 * @funcs: callbacks for this connector 453 * @name: user visible name of the connector 454 * 455 * LOCKING: 456 * Takes mode config lock. 457 * 458 * Initialises a preallocated connector. Connectors should be 459 * subclassed as part of driver connector objects. 460 * 461 * RETURNS: 462 * Zero on success, error code on failure. 463 */ 464 int drm_connector_init(struct drm_device *dev, 465 struct drm_connector *connector, 466 const struct drm_connector_funcs *funcs, 467 int connector_type) 468 { 469 int ret; 470 471 sx_xlock(&dev->mode_config.mutex); 472 473 ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); 474 if (ret) 475 goto out; 476 477 connector->dev = dev; 478 connector->funcs = funcs; 479 connector->connector_type = connector_type; 480 connector->connector_type_id = 481 ++drm_connector_enum_list[connector_type].count; /* TODO */ 482 INIT_LIST_HEAD(&connector->user_modes); 483 INIT_LIST_HEAD(&connector->probed_modes); 484 INIT_LIST_HEAD(&connector->modes); 485 connector->edid_blob_ptr = NULL; 486 487 list_add_tail(&connector->head, &dev->mode_config.connector_list); 488 dev->mode_config.num_connector++; 489 490 drm_connector_attach_property(connector, 491 dev->mode_config.edid_property, 0); 492 493 drm_connector_attach_property(connector, 494 dev->mode_config.dpms_property, 0); 495 496 out: 497 sx_xunlock(&dev->mode_config.mutex); 498 499 return ret; 500 } 501 502 /** 503 * drm_connector_cleanup - cleans up an initialised connector 504 * @connector: connector to cleanup 505 * 506 * LOCKING: 507 * Takes mode config lock. 508 * 509 * Cleans up the connector but doesn't free the object. 510 */ 511 void drm_connector_cleanup(struct drm_connector *connector) 512 { 513 struct drm_device *dev = connector->dev; 514 struct drm_display_mode *mode, *t; 515 516 list_for_each_entry_safe(mode, t, &connector->probed_modes, head) 517 drm_mode_remove(connector, mode); 518 519 list_for_each_entry_safe(mode, t, &connector->modes, head) 520 drm_mode_remove(connector, mode); 521 522 list_for_each_entry_safe(mode, t, &connector->user_modes, head) 523 drm_mode_remove(connector, mode); 524 525 sx_xlock(&dev->mode_config.mutex); 526 if (connector->edid_blob_ptr) 527 drm_property_destroy_blob(dev, connector->edid_blob_ptr); 528 drm_mode_object_put(dev, &connector->base); 529 list_del(&connector->head); 530 dev->mode_config.num_connector--; 531 sx_xunlock(&dev->mode_config.mutex); 532 } 533 534 int drm_encoder_init(struct drm_device *dev, 535 struct drm_encoder *encoder, 536 const struct drm_encoder_funcs *funcs, 537 int encoder_type) 538 { 539 int ret; 540 541 sx_xlock(&dev->mode_config.mutex); 542 543 ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); 544 if (ret) 545 goto out; 546 547 encoder->dev = dev; 548 encoder->encoder_type = encoder_type; 549 encoder->funcs = funcs; 550 551 list_add_tail(&encoder->head, &dev->mode_config.encoder_list); 552 dev->mode_config.num_encoder++; 553 554 out: 555 sx_xunlock(&dev->mode_config.mutex); 556 557 return ret; 558 } 559 560 void drm_encoder_cleanup(struct drm_encoder *encoder) 561 { 562 struct drm_device *dev = encoder->dev; 563 564 sx_xlock(&dev->mode_config.mutex); 565 drm_mode_object_put(dev, &encoder->base); 566 list_del(&encoder->head); 567 dev->mode_config.num_encoder--; 568 sx_xunlock(&dev->mode_config.mutex); 569 } 570 571 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 572 unsigned long possible_crtcs, 573 const struct drm_plane_funcs *funcs, 574 const uint32_t *formats, uint32_t format_count, 575 bool priv) 576 { 577 int ret; 578 579 sx_xlock(&dev->mode_config.mutex); 580 581 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 582 if (ret) 583 goto out; 584 585 plane->dev = dev; 586 plane->funcs = funcs; 587 plane->format_types = malloc(sizeof(uint32_t) * format_count, 588 DRM_MEM_KMS, M_WAITOK); 589 590 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); 591 plane->format_count = format_count; 592 plane->possible_crtcs = possible_crtcs; 593 594 /* private planes are not exposed to userspace, but depending on 595 * display hardware, might be convenient to allow sharing programming 596 * for the scanout engine with the crtc implementation. 597 */ 598 if (!priv) { 599 list_add_tail(&plane->head, &dev->mode_config.plane_list); 600 dev->mode_config.num_plane++; 601 } else { 602 INIT_LIST_HEAD(&plane->head); 603 } 604 605 out: 606 sx_xunlock(&dev->mode_config.mutex); 607 608 return ret; 609 } 610 611 void drm_plane_cleanup(struct drm_plane *plane) 612 { 613 struct drm_device *dev = plane->dev; 614 615 sx_xlock(&dev->mode_config.mutex); 616 free(plane->format_types, DRM_MEM_KMS); 617 drm_mode_object_put(dev, &plane->base); 618 /* if not added to a list, it must be a private plane */ 619 if (!list_empty(&plane->head)) { 620 list_del(&plane->head); 621 dev->mode_config.num_plane--; 622 } 623 sx_xunlock(&dev->mode_config.mutex); 624 } 625 626 /** 627 * drm_mode_create - create a new display mode 628 * @dev: DRM device 629 * 630 * LOCKING: 631 * Caller must hold DRM mode_config lock. 632 * 633 * Create a new drm_display_mode, give it an ID, and return it. 634 * 635 * RETURNS: 636 * Pointer to new mode on success, NULL on error. 637 */ 638 struct drm_display_mode *drm_mode_create(struct drm_device *dev) 639 { 640 struct drm_display_mode *nmode; 641 642 nmode = malloc(sizeof(struct drm_display_mode), DRM_MEM_KMS, 643 M_WAITOK | M_ZERO); 644 645 if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) { 646 free(nmode, DRM_MEM_KMS); 647 return (NULL); 648 } 649 return nmode; 650 } 651 652 /** 653 * drm_mode_destroy - remove a mode 654 * @dev: DRM device 655 * @mode: mode to remove 656 * 657 * LOCKING: 658 * Caller must hold mode config lock. 659 * 660 * Free @mode's unique identifier, then free it. 661 */ 662 void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) 663 { 664 if (!mode) 665 return; 666 667 drm_mode_object_put(dev, &mode->base); 668 669 free(mode, DRM_MEM_KMS); 670 } 671 672 static int drm_mode_create_standard_connector_properties(struct drm_device *dev) 673 { 674 struct drm_property *edid; 675 struct drm_property *dpms; 676 677 /* 678 * Standard properties (apply to all connectors) 679 */ 680 edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | 681 DRM_MODE_PROP_IMMUTABLE, 682 "EDID", 0); 683 dev->mode_config.edid_property = edid; 684 685 dpms = drm_property_create_enum(dev, 0, 686 "DPMS", drm_dpms_enum_list, 687 DRM_ARRAY_SIZE(drm_dpms_enum_list)); 688 dev->mode_config.dpms_property = dpms; 689 690 return 0; 691 } 692 693 /** 694 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties 695 * @dev: DRM device 696 * 697 * Called by a driver the first time a DVI-I connector is made. 698 */ 699 int drm_mode_create_dvi_i_properties(struct drm_device *dev) 700 { 701 struct drm_property *dvi_i_selector; 702 struct drm_property *dvi_i_subconnector; 703 704 if (dev->mode_config.dvi_i_select_subconnector_property) 705 return 0; 706 707 dvi_i_selector = 708 drm_property_create_enum(dev, 0, 709 "select subconnector", 710 drm_dvi_i_select_enum_list, 711 DRM_ARRAY_SIZE(drm_dvi_i_select_enum_list)); 712 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; 713 714 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 715 "subconnector", 716 drm_dvi_i_subconnector_enum_list, 717 DRM_ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); 718 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; 719 720 return 0; 721 } 722 723 /** 724 * drm_create_tv_properties - create TV specific connector properties 725 * @dev: DRM device 726 * @num_modes: number of different TV formats (modes) supported 727 * @modes: array of pointers to strings containing name of each format 728 * 729 * Called by a driver's TV initialization routine, this function creates 730 * the TV specific connector properties for a given device. Caller is 731 * responsible for allocating a list of format names and passing them to 732 * this routine. 733 */ 734 int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, 735 char *modes[]) 736 { 737 struct drm_property *tv_selector; 738 struct drm_property *tv_subconnector; 739 int i; 740 741 if (dev->mode_config.tv_select_subconnector_property) 742 return 0; 743 744 /* 745 * Basic connector properties 746 */ 747 tv_selector = drm_property_create_enum(dev, 0, 748 "select subconnector", 749 drm_tv_select_enum_list, 750 DRM_ARRAY_SIZE(drm_tv_select_enum_list)); 751 dev->mode_config.tv_select_subconnector_property = tv_selector; 752 753 tv_subconnector = 754 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 755 "subconnector", 756 drm_tv_subconnector_enum_list, 757 DRM_ARRAY_SIZE(drm_tv_subconnector_enum_list)); 758 dev->mode_config.tv_subconnector_property = tv_subconnector; 759 760 /* 761 * Other, TV specific properties: margins & TV modes. 762 */ 763 dev->mode_config.tv_left_margin_property = 764 drm_property_create_range(dev, 0, "left margin", 0, 100); 765 766 dev->mode_config.tv_right_margin_property = 767 drm_property_create_range(dev, 0, "right margin", 0, 100); 768 769 dev->mode_config.tv_top_margin_property = 770 drm_property_create_range(dev, 0, "top margin", 0, 100); 771 772 dev->mode_config.tv_bottom_margin_property = 773 drm_property_create_range(dev, 0, "bottom margin", 0, 100); 774 775 dev->mode_config.tv_mode_property = 776 drm_property_create(dev, DRM_MODE_PROP_ENUM, 777 "mode", num_modes); 778 for (i = 0; i < num_modes; i++) 779 drm_property_add_enum(dev->mode_config.tv_mode_property, i, 780 i, modes[i]); 781 782 dev->mode_config.tv_brightness_property = 783 drm_property_create_range(dev, 0, "brightness", 0, 100); 784 785 dev->mode_config.tv_contrast_property = 786 drm_property_create_range(dev, 0, "contrast", 0, 100); 787 788 dev->mode_config.tv_flicker_reduction_property = 789 drm_property_create_range(dev, 0, "flicker reduction", 0, 100); 790 791 dev->mode_config.tv_overscan_property = 792 drm_property_create_range(dev, 0, "overscan", 0, 100); 793 794 dev->mode_config.tv_saturation_property = 795 drm_property_create_range(dev, 0, "saturation", 0, 100); 796 797 dev->mode_config.tv_hue_property = 798 drm_property_create_range(dev, 0, "hue", 0, 100); 799 800 return 0; 801 } 802 803 /** 804 * drm_mode_create_scaling_mode_property - create scaling mode property 805 * @dev: DRM device 806 * 807 * Called by a driver the first time it's needed, must be attached to desired 808 * connectors. 809 */ 810 int drm_mode_create_scaling_mode_property(struct drm_device *dev) 811 { 812 struct drm_property *scaling_mode; 813 814 if (dev->mode_config.scaling_mode_property) 815 return 0; 816 817 scaling_mode = 818 drm_property_create_enum(dev, 0, "scaling mode", 819 drm_scaling_mode_enum_list, 820 DRM_ARRAY_SIZE(drm_scaling_mode_enum_list)); 821 822 dev->mode_config.scaling_mode_property = scaling_mode; 823 824 return 0; 825 } 826 827 /** 828 * drm_mode_create_dithering_property - create dithering property 829 * @dev: DRM device 830 * 831 * Called by a driver the first time it's needed, must be attached to desired 832 * connectors. 833 */ 834 int drm_mode_create_dithering_property(struct drm_device *dev) 835 { 836 struct drm_property *dithering_mode; 837 838 if (dev->mode_config.dithering_mode_property) 839 return 0; 840 841 dithering_mode = 842 drm_property_create_enum(dev, 0, "dithering", 843 drm_dithering_mode_enum_list, 844 DRM_ARRAY_SIZE(drm_dithering_mode_enum_list)); 845 dev->mode_config.dithering_mode_property = dithering_mode; 846 847 return 0; 848 } 849 850 /** 851 * drm_mode_create_dirty_property - create dirty property 852 * @dev: DRM device 853 * 854 * Called by a driver the first time it's needed, must be attached to desired 855 * connectors. 856 */ 857 int drm_mode_create_dirty_info_property(struct drm_device *dev) 858 { 859 struct drm_property *dirty_info; 860 861 if (dev->mode_config.dirty_info_property) 862 return 0; 863 864 dirty_info = 865 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 866 "dirty", 867 drm_dirty_info_enum_list, 868 DRM_ARRAY_SIZE(drm_dirty_info_enum_list)); 869 dev->mode_config.dirty_info_property = dirty_info; 870 871 return 0; 872 } 873 874 /** 875 * drm_mode_config_init - initialize DRM mode_configuration structure 876 * @dev: DRM device 877 * 878 * LOCKING: 879 * None, should happen single threaded at init time. 880 * 881 * Initialize @dev's mode_config structure, used for tracking the graphics 882 * configuration of @dev. 883 */ 884 void drm_mode_config_init(struct drm_device *dev) 885 { 886 sx_init(&dev->mode_config.mutex, "kmslk"); 887 INIT_LIST_HEAD(&dev->mode_config.fb_list); 888 INIT_LIST_HEAD(&dev->mode_config.crtc_list); 889 INIT_LIST_HEAD(&dev->mode_config.connector_list); 890 INIT_LIST_HEAD(&dev->mode_config.encoder_list); 891 INIT_LIST_HEAD(&dev->mode_config.property_list); 892 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 893 INIT_LIST_HEAD(&dev->mode_config.plane_list); 894 drm_gem_names_init(&dev->mode_config.crtc_names); 895 896 sx_xlock(&dev->mode_config.mutex); 897 drm_mode_create_standard_connector_properties(dev); 898 sx_xunlock(&dev->mode_config.mutex); 899 900 /* Just to be sure */ 901 dev->mode_config.num_fb = 0; 902 dev->mode_config.num_connector = 0; 903 dev->mode_config.num_crtc = 0; 904 dev->mode_config.num_encoder = 0; 905 } 906 907 static int 908 drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) 909 { 910 uint32_t total_objects = 0; 911 912 total_objects += dev->mode_config.num_crtc; 913 total_objects += dev->mode_config.num_connector; 914 total_objects += dev->mode_config.num_encoder; 915 916 group->id_list = malloc(total_objects * sizeof(uint32_t), 917 DRM_MEM_KMS, M_WAITOK | M_ZERO); 918 919 group->num_crtcs = 0; 920 group->num_connectors = 0; 921 group->num_encoders = 0; 922 return 0; 923 } 924 925 int drm_mode_group_init_legacy_group(struct drm_device *dev, 926 struct drm_mode_group *group) 927 { 928 struct drm_crtc *crtc; 929 struct drm_encoder *encoder; 930 struct drm_connector *connector; 931 int ret; 932 933 if ((ret = drm_mode_group_init(dev, group))) 934 return ret; 935 936 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 937 group->id_list[group->num_crtcs++] = crtc->base.id; 938 939 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 940 group->id_list[group->num_crtcs + group->num_encoders++] = 941 encoder->base.id; 942 943 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 944 group->id_list[group->num_crtcs + group->num_encoders + 945 group->num_connectors++] = connector->base.id; 946 947 return 0; 948 } 949 950 /** 951 * drm_mode_config_cleanup - free up DRM mode_config info 952 * @dev: DRM device 953 * 954 * LOCKING: 955 * Caller must hold mode config lock. 956 * 957 * Free up all the connectors and CRTCs associated with this DRM device, then 958 * free up the framebuffers and associated buffer objects. 959 * 960 * FIXME: cleanup any dangling user buffer objects too 961 */ 962 void drm_mode_config_cleanup(struct drm_device *dev) 963 { 964 struct drm_connector *connector, *ot; 965 struct drm_crtc *crtc, *ct; 966 struct drm_encoder *encoder, *enct; 967 struct drm_framebuffer *fb, *fbt; 968 struct drm_property *property, *pt; 969 struct drm_plane *plane, *plt; 970 971 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, 972 head) { 973 encoder->funcs->destroy(encoder); 974 } 975 976 list_for_each_entry_safe(connector, ot, 977 &dev->mode_config.connector_list, head) { 978 connector->funcs->destroy(connector); 979 } 980 981 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, 982 head) { 983 drm_property_destroy(dev, property); 984 } 985 986 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { 987 fb->funcs->destroy(fb); 988 } 989 990 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { 991 crtc->funcs->destroy(crtc); 992 } 993 994 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, 995 head) { 996 plane->funcs->destroy(plane); 997 } 998 drm_gem_names_fini(&dev->mode_config.crtc_names); 999 } 1000 1001 /** 1002 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo 1003 * @out: drm_mode_modeinfo struct to return to the user 1004 * @in: drm_display_mode to use 1005 * 1006 * LOCKING: 1007 * None. 1008 * 1009 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to 1010 * the user. 1011 */ 1012 static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, 1013 const struct drm_display_mode *in) 1014 { 1015 if (in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || 1016 in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || 1017 in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || 1018 in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || 1019 in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX) 1020 printf("timing values too large for mode info\n"); 1021 1022 out->clock = in->clock; 1023 out->hdisplay = in->hdisplay; 1024 out->hsync_start = in->hsync_start; 1025 out->hsync_end = in->hsync_end; 1026 out->htotal = in->htotal; 1027 out->hskew = in->hskew; 1028 out->vdisplay = in->vdisplay; 1029 out->vsync_start = in->vsync_start; 1030 out->vsync_end = in->vsync_end; 1031 out->vtotal = in->vtotal; 1032 out->vscan = in->vscan; 1033 out->vrefresh = in->vrefresh; 1034 out->flags = in->flags; 1035 out->type = in->type; 1036 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1037 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1038 } 1039 1040 /** 1041 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode 1042 * @out: drm_display_mode to return to the user 1043 * @in: drm_mode_modeinfo to use 1044 * 1045 * LOCKING: 1046 * None. 1047 * 1048 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to 1049 * the caller. 1050 * 1051 * RETURNS: 1052 * Zero on success, errno on failure. 1053 */ 1054 static int drm_crtc_convert_umode(struct drm_display_mode *out, 1055 const struct drm_mode_modeinfo *in) 1056 { 1057 if (in->clock > INT_MAX || in->vrefresh > INT_MAX) 1058 return ERANGE; 1059 1060 out->clock = in->clock; 1061 out->hdisplay = in->hdisplay; 1062 out->hsync_start = in->hsync_start; 1063 out->hsync_end = in->hsync_end; 1064 out->htotal = in->htotal; 1065 out->hskew = in->hskew; 1066 out->vdisplay = in->vdisplay; 1067 out->vsync_start = in->vsync_start; 1068 out->vsync_end = in->vsync_end; 1069 out->vtotal = in->vtotal; 1070 out->vscan = in->vscan; 1071 out->vrefresh = in->vrefresh; 1072 out->flags = in->flags; 1073 out->type = in->type; 1074 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1075 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1076 1077 return 0; 1078 } 1079 1080 /** 1081 * drm_mode_getresources - get graphics configuration 1082 * @inode: inode from the ioctl 1083 * @filp: file * from the ioctl 1084 * @cmd: cmd from ioctl 1085 * @arg: arg from ioctl 1086 * 1087 * LOCKING: 1088 * Takes mode config lock. 1089 * 1090 * Construct a set of configuration description structures and return 1091 * them to the user, including CRTC, connector and framebuffer configuration. 1092 * 1093 * Called by the user via ioctl. 1094 * 1095 * RETURNS: 1096 * Zero on success, errno on failure. 1097 */ 1098 int drm_mode_getresources(struct drm_device *dev, void *data, 1099 struct drm_file *file_priv) 1100 { 1101 struct drm_mode_card_res *card_res = data; 1102 struct list_head *lh; 1103 struct drm_framebuffer *fb; 1104 struct drm_connector *connector; 1105 struct drm_crtc *crtc; 1106 struct drm_encoder *encoder; 1107 int ret = 0; 1108 int connector_count = 0; 1109 int crtc_count = 0; 1110 int fb_count = 0; 1111 int encoder_count = 0; 1112 int copied = 0, i; 1113 uint32_t __user *fb_id; 1114 uint32_t __user *crtc_id; 1115 uint32_t __user *connector_id; 1116 uint32_t __user *encoder_id; 1117 struct drm_mode_group *mode_group; 1118 1119 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1120 return (EINVAL); 1121 1122 sx_xlock(&dev->mode_config.mutex); 1123 1124 /* 1125 * For the non-control nodes we need to limit the list of resources 1126 * by IDs in the group list for this node 1127 */ 1128 list_for_each(lh, &file_priv->fbs) 1129 fb_count++; 1130 1131 #if 1 1132 mode_group = NULL; /* XXXKIB */ 1133 if (1 || file_priv->master) { 1134 #else 1135 mode_group = &file_priv->masterp->minor->mode_group; 1136 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1137 #endif 1138 1139 list_for_each(lh, &dev->mode_config.crtc_list) 1140 crtc_count++; 1141 1142 list_for_each(lh, &dev->mode_config.connector_list) 1143 connector_count++; 1144 1145 list_for_each(lh, &dev->mode_config.encoder_list) 1146 encoder_count++; 1147 } else { 1148 1149 crtc_count = mode_group->num_crtcs; 1150 connector_count = mode_group->num_connectors; 1151 encoder_count = mode_group->num_encoders; 1152 } 1153 1154 card_res->max_height = dev->mode_config.max_height; 1155 card_res->min_height = dev->mode_config.min_height; 1156 card_res->max_width = dev->mode_config.max_width; 1157 card_res->min_width = dev->mode_config.min_width; 1158 1159 /* handle this in 4 parts */ 1160 /* FBs */ 1161 if (card_res->count_fbs >= fb_count) { 1162 copied = 0; 1163 fb_id = (uint32_t *)(uintptr_t)card_res->fb_id_ptr; 1164 list_for_each_entry(fb, &file_priv->fbs, filp_head) { 1165 if (copyout(&fb->base.id, fb_id + copied, 1166 sizeof(uint32_t))) { 1167 ret = EFAULT; 1168 goto out; 1169 } 1170 copied++; 1171 } 1172 } 1173 card_res->count_fbs = fb_count; 1174 1175 /* CRTCs */ 1176 if (card_res->count_crtcs >= crtc_count) { 1177 copied = 0; 1178 crtc_id = (uint32_t *)(uintptr_t)card_res->crtc_id_ptr; 1179 #if 1 1180 if (1 || file_priv->master) { 1181 #else 1182 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1183 #endif 1184 list_for_each_entry(crtc, &dev->mode_config.crtc_list, 1185 head) { 1186 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1187 if (copyout(&crtc->base.id, crtc_id + 1188 copied, sizeof(uint32_t))) { 1189 ret = EFAULT; 1190 goto out; 1191 } 1192 copied++; 1193 } 1194 } else { 1195 for (i = 0; i < mode_group->num_crtcs; i++) { 1196 if (copyout(&mode_group->id_list[i], 1197 crtc_id + copied, sizeof(uint32_t))) { 1198 ret = EFAULT; 1199 goto out; 1200 } 1201 copied++; 1202 } 1203 } 1204 } 1205 card_res->count_crtcs = crtc_count; 1206 1207 /* Encoders */ 1208 if (card_res->count_encoders >= encoder_count) { 1209 copied = 0; 1210 encoder_id = (uint32_t *)(uintptr_t)card_res->encoder_id_ptr; 1211 #if 1 1212 if (file_priv->master) { 1213 #else 1214 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1215 #endif 1216 list_for_each_entry(encoder, 1217 &dev->mode_config.encoder_list, 1218 head) { 1219 DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, 1220 drm_get_encoder_name(encoder)); 1221 if (copyout(&encoder->base.id, encoder_id + 1222 copied, sizeof(uint32_t))) { 1223 ret = EFAULT; 1224 goto out; 1225 } 1226 copied++; 1227 } 1228 } else { 1229 for (i = mode_group->num_crtcs; 1230 i < mode_group->num_crtcs + mode_group->num_encoders; 1231 i++) { 1232 if (copyout(&mode_group->id_list[i], 1233 encoder_id + copied, sizeof(uint32_t))) { 1234 ret = EFAULT; 1235 goto out; 1236 } 1237 copied++; 1238 } 1239 1240 } 1241 } 1242 card_res->count_encoders = encoder_count; 1243 1244 /* Connectors */ 1245 if (card_res->count_connectors >= connector_count) { 1246 copied = 0; 1247 connector_id = (uint32_t *)(uintptr_t)card_res->connector_id_ptr; 1248 #if 1 1249 if (file_priv->master) { 1250 #else 1251 if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) { 1252 #endif 1253 list_for_each_entry(connector, 1254 &dev->mode_config.connector_list, 1255 head) { 1256 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 1257 connector->base.id, 1258 drm_get_connector_name(connector)); 1259 if (copyout(&connector->base.id, 1260 connector_id + copied, sizeof(uint32_t))) { 1261 ret = EFAULT; 1262 goto out; 1263 } 1264 copied++; 1265 } 1266 } else { 1267 int start = mode_group->num_crtcs + 1268 mode_group->num_encoders; 1269 for (i = start; i < start + mode_group->num_connectors; i++) { 1270 if (copyout(&mode_group->id_list[i], 1271 connector_id + copied, sizeof(uint32_t))) { 1272 ret = EFAULT; 1273 goto out; 1274 } 1275 copied++; 1276 } 1277 } 1278 } 1279 card_res->count_connectors = connector_count; 1280 1281 DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs, 1282 card_res->count_connectors, card_res->count_encoders); 1283 1284 out: 1285 sx_xunlock(&dev->mode_config.mutex); 1286 return ret; 1287 } 1288 1289 /** 1290 * drm_mode_getcrtc - get CRTC configuration 1291 * @inode: inode from the ioctl 1292 * @filp: file * from the ioctl 1293 * @cmd: cmd from ioctl 1294 * @arg: arg from ioctl 1295 * 1296 * LOCKING: 1297 * Takes mode config lock. 1298 * 1299 * Construct a CRTC configuration structure to return to the user. 1300 * 1301 * Called by the user via ioctl. 1302 * 1303 * RETURNS: 1304 * Zero on success, errno on failure. 1305 */ 1306 int drm_mode_getcrtc(struct drm_device *dev, 1307 void *data, struct drm_file *file_priv) 1308 { 1309 struct drm_mode_crtc *crtc_resp = data; 1310 struct drm_crtc *crtc; 1311 struct drm_mode_object *obj; 1312 int ret = 0; 1313 1314 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1315 return (EINVAL); 1316 1317 sx_xlock(&dev->mode_config.mutex); 1318 1319 obj = drm_mode_object_find(dev, crtc_resp->crtc_id, 1320 DRM_MODE_OBJECT_CRTC); 1321 if (!obj) { 1322 ret = (EINVAL); 1323 goto out; 1324 } 1325 crtc = obj_to_crtc(obj); 1326 1327 crtc_resp->x = crtc->x; 1328 crtc_resp->y = crtc->y; 1329 crtc_resp->gamma_size = crtc->gamma_size; 1330 if (crtc->fb) 1331 crtc_resp->fb_id = crtc->fb->base.id; 1332 else 1333 crtc_resp->fb_id = 0; 1334 1335 if (crtc->enabled) { 1336 1337 drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); 1338 crtc_resp->mode_valid = 1; 1339 1340 } else { 1341 crtc_resp->mode_valid = 0; 1342 } 1343 1344 out: 1345 sx_xunlock(&dev->mode_config.mutex); 1346 return ret; 1347 } 1348 1349 /** 1350 * drm_mode_getconnector - get connector configuration 1351 * @inode: inode from the ioctl 1352 * @filp: file * from the ioctl 1353 * @cmd: cmd from ioctl 1354 * @arg: arg from ioctl 1355 * 1356 * LOCKING: 1357 * Takes mode config lock. 1358 * 1359 * Construct a connector configuration structure to return to the user. 1360 * 1361 * Called by the user via ioctl. 1362 * 1363 * RETURNS: 1364 * Zero on success, errno on failure. 1365 */ 1366 int drm_mode_getconnector(struct drm_device *dev, void *data, 1367 struct drm_file *file_priv) 1368 { 1369 struct drm_mode_get_connector *out_resp = data; 1370 struct drm_mode_object *obj; 1371 struct drm_connector *connector; 1372 struct drm_display_mode *mode; 1373 int mode_count = 0; 1374 int props_count = 0; 1375 int encoders_count = 0; 1376 int ret = 0; 1377 int copied = 0; 1378 int i; 1379 struct drm_mode_modeinfo u_mode; 1380 struct drm_mode_modeinfo __user *mode_ptr; 1381 uint32_t *prop_ptr; 1382 uint64_t *prop_values; 1383 uint32_t *encoder_ptr; 1384 1385 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1386 return (EINVAL); 1387 1388 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); 1389 1390 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); 1391 1392 sx_xlock(&dev->mode_config.mutex); 1393 1394 obj = drm_mode_object_find(dev, out_resp->connector_id, 1395 DRM_MODE_OBJECT_CONNECTOR); 1396 if (!obj) { 1397 ret = EINVAL; 1398 goto out; 1399 } 1400 connector = obj_to_connector(obj); 1401 1402 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 1403 if (connector->property_ids[i] != 0) { 1404 props_count++; 1405 } 1406 } 1407 1408 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1409 if (connector->encoder_ids[i] != 0) { 1410 encoders_count++; 1411 } 1412 } 1413 1414 if (out_resp->count_modes == 0) { 1415 connector->funcs->fill_modes(connector, 1416 dev->mode_config.max_width, 1417 dev->mode_config.max_height); 1418 } 1419 1420 /* delayed so we get modes regardless of pre-fill_modes state */ 1421 list_for_each_entry(mode, &connector->modes, head) 1422 mode_count++; 1423 1424 out_resp->connector_id = connector->base.id; 1425 out_resp->connector_type = connector->connector_type; 1426 out_resp->connector_type_id = connector->connector_type_id; 1427 out_resp->mm_width = connector->display_info.width_mm; 1428 out_resp->mm_height = connector->display_info.height_mm; 1429 out_resp->subpixel = connector->display_info.subpixel_order; 1430 out_resp->connection = connector->status; 1431 if (connector->encoder) 1432 out_resp->encoder_id = connector->encoder->base.id; 1433 else 1434 out_resp->encoder_id = 0; 1435 1436 /* 1437 * This ioctl is called twice, once to determine how much space is 1438 * needed, and the 2nd time to fill it. 1439 */ 1440 if ((out_resp->count_modes >= mode_count) && mode_count) { 1441 copied = 0; 1442 mode_ptr = (struct drm_mode_modeinfo *)(uintptr_t)out_resp->modes_ptr; 1443 list_for_each_entry(mode, &connector->modes, head) { 1444 drm_crtc_convert_to_umode(&u_mode, mode); 1445 if (copyout(&u_mode, mode_ptr + copied, 1446 sizeof(u_mode))) { 1447 ret = EFAULT; 1448 goto out; 1449 } 1450 copied++; 1451 } 1452 } 1453 out_resp->count_modes = mode_count; 1454 1455 if ((out_resp->count_props >= props_count) && props_count) { 1456 copied = 0; 1457 prop_ptr = (uint32_t *)(uintptr_t)(out_resp->props_ptr); 1458 prop_values = (uint64_t *)(uintptr_t)(out_resp->prop_values_ptr); 1459 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 1460 if (connector->property_ids[i] != 0) { 1461 if (copyout(&connector->property_ids[i], 1462 prop_ptr + copied, sizeof(uint32_t))) { 1463 ret = EFAULT; 1464 goto out; 1465 } 1466 1467 if (copyout(&connector->property_values[i], 1468 prop_values + copied, sizeof(uint64_t))) { 1469 ret = EFAULT; 1470 goto out; 1471 } 1472 copied++; 1473 } 1474 } 1475 } 1476 out_resp->count_props = props_count; 1477 1478 if ((out_resp->count_encoders >= encoders_count) && encoders_count) { 1479 copied = 0; 1480 encoder_ptr = (uint32_t *)(uintptr_t)(out_resp->encoders_ptr); 1481 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1482 if (connector->encoder_ids[i] != 0) { 1483 if (copyout(&connector->encoder_ids[i], 1484 encoder_ptr + copied, sizeof(uint32_t))) { 1485 ret = EFAULT; 1486 goto out; 1487 } 1488 copied++; 1489 } 1490 } 1491 } 1492 out_resp->count_encoders = encoders_count; 1493 1494 out: 1495 sx_xunlock(&dev->mode_config.mutex); 1496 return ret; 1497 } 1498 1499 int drm_mode_getencoder(struct drm_device *dev, void *data, 1500 struct drm_file *file_priv) 1501 { 1502 struct drm_mode_get_encoder *enc_resp = data; 1503 struct drm_mode_object *obj; 1504 struct drm_encoder *encoder; 1505 int ret = 0; 1506 1507 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1508 return (EINVAL); 1509 1510 sx_xlock(&dev->mode_config.mutex); 1511 obj = drm_mode_object_find(dev, enc_resp->encoder_id, 1512 DRM_MODE_OBJECT_ENCODER); 1513 if (!obj) { 1514 ret = EINVAL; 1515 goto out; 1516 } 1517 encoder = obj_to_encoder(obj); 1518 1519 if (encoder->crtc) 1520 enc_resp->crtc_id = encoder->crtc->base.id; 1521 else 1522 enc_resp->crtc_id = 0; 1523 enc_resp->encoder_type = encoder->encoder_type; 1524 enc_resp->encoder_id = encoder->base.id; 1525 enc_resp->possible_crtcs = encoder->possible_crtcs; 1526 enc_resp->possible_clones = encoder->possible_clones; 1527 1528 out: 1529 sx_xunlock(&dev->mode_config.mutex); 1530 return ret; 1531 } 1532 1533 /** 1534 * drm_mode_getplane_res - get plane info 1535 * @dev: DRM device 1536 * @data: ioctl data 1537 * @file_priv: DRM file info 1538 * 1539 * LOCKING: 1540 * Takes mode config lock. 1541 * 1542 * Return an plane count and set of IDs. 1543 */ 1544 int drm_mode_getplane_res(struct drm_device *dev, void *data, 1545 struct drm_file *file_priv) 1546 { 1547 struct drm_mode_get_plane_res *plane_resp = data; 1548 struct drm_mode_config *config; 1549 struct drm_plane *plane; 1550 uint32_t *plane_ptr; 1551 int copied = 0, ret = 0; 1552 1553 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1554 return (EINVAL); 1555 1556 sx_xlock(&dev->mode_config.mutex); 1557 config = &dev->mode_config; 1558 1559 /* 1560 * This ioctl is called twice, once to determine how much space is 1561 * needed, and the 2nd time to fill it. 1562 */ 1563 if (config->num_plane && 1564 (plane_resp->count_planes >= config->num_plane)) { 1565 plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr; 1566 1567 list_for_each_entry(plane, &config->plane_list, head) { 1568 if (copyout(&plane->base.id, plane_ptr + copied, 1569 sizeof(uint32_t))) { 1570 ret = EFAULT; 1571 goto out; 1572 } 1573 copied++; 1574 } 1575 } 1576 plane_resp->count_planes = config->num_plane; 1577 1578 out: 1579 sx_xunlock(&dev->mode_config.mutex); 1580 return ret; 1581 } 1582 1583 /** 1584 * drm_mode_getplane - get plane info 1585 * @dev: DRM device 1586 * @data: ioctl data 1587 * @file_priv: DRM file info 1588 * 1589 * LOCKING: 1590 * Takes mode config lock. 1591 * 1592 * Return plane info, including formats supported, gamma size, any 1593 * current fb, etc. 1594 */ 1595 int drm_mode_getplane(struct drm_device *dev, void *data, 1596 struct drm_file *file_priv) 1597 { 1598 struct drm_mode_get_plane *plane_resp = data; 1599 struct drm_mode_object *obj; 1600 struct drm_plane *plane; 1601 uint32_t *format_ptr; 1602 int ret = 0; 1603 1604 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1605 return (EINVAL); 1606 1607 sx_xlock(&dev->mode_config.mutex); 1608 obj = drm_mode_object_find(dev, plane_resp->plane_id, 1609 DRM_MODE_OBJECT_PLANE); 1610 if (!obj) { 1611 ret = ENOENT; 1612 goto out; 1613 } 1614 plane = obj_to_plane(obj); 1615 1616 if (plane->crtc) 1617 plane_resp->crtc_id = plane->crtc->base.id; 1618 else 1619 plane_resp->crtc_id = 0; 1620 1621 if (plane->fb) 1622 plane_resp->fb_id = plane->fb->base.id; 1623 else 1624 plane_resp->fb_id = 0; 1625 1626 plane_resp->plane_id = plane->base.id; 1627 plane_resp->possible_crtcs = plane->possible_crtcs; 1628 plane_resp->gamma_size = plane->gamma_size; 1629 1630 /* 1631 * This ioctl is called twice, once to determine how much space is 1632 * needed, and the 2nd time to fill it. 1633 */ 1634 if (plane->format_count && 1635 (plane_resp->count_format_types >= plane->format_count)) { 1636 format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr; 1637 if (copyout(format_ptr, 1638 plane->format_types, 1639 sizeof(uint32_t) * plane->format_count)) { 1640 ret = EFAULT; 1641 goto out; 1642 } 1643 } 1644 plane_resp->count_format_types = plane->format_count; 1645 1646 out: 1647 sx_xunlock(&dev->mode_config.mutex); 1648 return ret; 1649 } 1650 1651 /** 1652 * drm_mode_setplane - set up or tear down an plane 1653 * @dev: DRM device 1654 * @data: ioctl data* 1655 * @file_prive: DRM file info 1656 * 1657 * LOCKING: 1658 * Takes mode config lock. 1659 * 1660 * Set plane info, including placement, fb, scaling, and other factors. 1661 * Or pass a NULL fb to disable. 1662 */ 1663 int drm_mode_setplane(struct drm_device *dev, void *data, 1664 struct drm_file *file_priv) 1665 { 1666 struct drm_mode_set_plane *plane_req = data; 1667 struct drm_mode_object *obj; 1668 struct drm_plane *plane; 1669 struct drm_crtc *crtc; 1670 struct drm_framebuffer *fb; 1671 int ret = 0; 1672 unsigned int fb_width, fb_height; 1673 int i; 1674 1675 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1676 return (EINVAL); 1677 1678 sx_xlock(&dev->mode_config.mutex); 1679 1680 /* 1681 * First, find the plane, crtc, and fb objects. If not available, 1682 * we don't bother to call the driver. 1683 */ 1684 obj = drm_mode_object_find(dev, plane_req->plane_id, 1685 DRM_MODE_OBJECT_PLANE); 1686 if (!obj) { 1687 DRM_DEBUG_KMS("Unknown plane ID %d\n", 1688 plane_req->plane_id); 1689 ret = ENOENT; 1690 goto out; 1691 } 1692 plane = obj_to_plane(obj); 1693 1694 /* No fb means shut it down */ 1695 if (!plane_req->fb_id) { 1696 plane->funcs->disable_plane(plane); 1697 plane->crtc = NULL; 1698 plane->fb = NULL; 1699 goto out; 1700 } 1701 1702 obj = drm_mode_object_find(dev, plane_req->crtc_id, 1703 DRM_MODE_OBJECT_CRTC); 1704 if (!obj) { 1705 DRM_DEBUG_KMS("Unknown crtc ID %d\n", 1706 plane_req->crtc_id); 1707 ret = ENOENT; 1708 goto out; 1709 } 1710 crtc = obj_to_crtc(obj); 1711 1712 obj = drm_mode_object_find(dev, plane_req->fb_id, 1713 DRM_MODE_OBJECT_FB); 1714 if (!obj) { 1715 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", 1716 plane_req->fb_id); 1717 ret = ENOENT; 1718 goto out; 1719 } 1720 fb = obj_to_fb(obj); 1721 1722 /* Check whether this plane supports the fb pixel format. */ 1723 for (i = 0; i < plane->format_count; i++) 1724 if (fb->pixel_format == plane->format_types[i]) 1725 break; 1726 if (i == plane->format_count) { 1727 DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); 1728 ret = EINVAL; 1729 goto out; 1730 } 1731 1732 fb_width = fb->width << 16; 1733 fb_height = fb->height << 16; 1734 1735 /* Make sure source coordinates are inside the fb. */ 1736 if (plane_req->src_w > fb_width || 1737 plane_req->src_x > fb_width - plane_req->src_w || 1738 plane_req->src_h > fb_height || 1739 plane_req->src_y > fb_height - plane_req->src_h) { 1740 DRM_DEBUG_KMS("Invalid source coordinates " 1741 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", 1742 plane_req->src_w >> 16, 1743 ((plane_req->src_w & 0xffff) * 15625) >> 10, 1744 plane_req->src_h >> 16, 1745 ((plane_req->src_h & 0xffff) * 15625) >> 10, 1746 plane_req->src_x >> 16, 1747 ((plane_req->src_x & 0xffff) * 15625) >> 10, 1748 plane_req->src_y >> 16, 1749 ((plane_req->src_y & 0xffff) * 15625) >> 10); 1750 ret = ENOSPC; 1751 goto out; 1752 } 1753 1754 /* Give drivers some help against integer overflows */ 1755 if (plane_req->crtc_w > INT_MAX || 1756 plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || 1757 plane_req->crtc_h > INT_MAX || 1758 plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { 1759 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", 1760 plane_req->crtc_w, plane_req->crtc_h, 1761 plane_req->crtc_x, plane_req->crtc_y); 1762 ret = ERANGE; 1763 goto out; 1764 } 1765 1766 ret = -plane->funcs->update_plane(plane, crtc, fb, 1767 plane_req->crtc_x, plane_req->crtc_y, 1768 plane_req->crtc_w, plane_req->crtc_h, 1769 plane_req->src_x, plane_req->src_y, 1770 plane_req->src_w, plane_req->src_h); 1771 if (!ret) { 1772 plane->crtc = crtc; 1773 plane->fb = fb; 1774 } 1775 1776 out: 1777 sx_xunlock(&dev->mode_config.mutex); 1778 1779 return ret; 1780 } 1781 1782 /** 1783 * drm_mode_setcrtc - set CRTC configuration 1784 * @inode: inode from the ioctl 1785 * @filp: file * from the ioctl 1786 * @cmd: cmd from ioctl 1787 * @arg: arg from ioctl 1788 * 1789 * LOCKING: 1790 * Takes mode config lock. 1791 * 1792 * Build a new CRTC configuration based on user request. 1793 * 1794 * Called by the user via ioctl. 1795 * 1796 * RETURNS: 1797 * Zero on success, errno on failure. 1798 */ 1799 int drm_mode_setcrtc(struct drm_device *dev, void *data, 1800 struct drm_file *file_priv) 1801 { 1802 struct drm_mode_config *config = &dev->mode_config; 1803 struct drm_mode_crtc *crtc_req = data; 1804 struct drm_mode_object *obj; 1805 struct drm_crtc *crtc; 1806 struct drm_connector **connector_set = NULL, *connector; 1807 struct drm_framebuffer *fb = NULL; 1808 struct drm_display_mode *mode = NULL; 1809 struct drm_mode_set set; 1810 uint32_t *set_connectors_ptr; 1811 int ret = 0; 1812 int i; 1813 1814 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1815 return (EINVAL); 1816 1817 /* For some reason crtc x/y offsets are signed internally. */ 1818 if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) 1819 return (ERANGE); 1820 1821 sx_xlock(&dev->mode_config.mutex); 1822 obj = drm_mode_object_find(dev, crtc_req->crtc_id, 1823 DRM_MODE_OBJECT_CRTC); 1824 if (!obj) { 1825 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); 1826 ret = EINVAL; 1827 goto out; 1828 } 1829 crtc = obj_to_crtc(obj); 1830 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1831 1832 if (crtc_req->mode_valid) { 1833 /* If we have a mode we need a framebuffer. */ 1834 /* If we pass -1, set the mode with the currently bound fb */ 1835 if (crtc_req->fb_id == -1) { 1836 if (!crtc->fb) { 1837 DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); 1838 ret = -EINVAL; 1839 goto out; 1840 } 1841 fb = crtc->fb; 1842 } else { 1843 obj = drm_mode_object_find(dev, crtc_req->fb_id, 1844 DRM_MODE_OBJECT_FB); 1845 if (!obj) { 1846 DRM_DEBUG_KMS("Unknown FB ID%d\n", 1847 crtc_req->fb_id); 1848 ret = EINVAL; 1849 goto out; 1850 } 1851 fb = obj_to_fb(obj); 1852 } 1853 1854 mode = drm_mode_create(dev); 1855 if (!mode) { 1856 ret = ENOMEM; 1857 goto out; 1858 } 1859 1860 ret = drm_crtc_convert_umode(mode, &crtc_req->mode); 1861 if (ret) { 1862 DRM_DEBUG_KMS("Invalid mode\n"); 1863 goto out; 1864 } 1865 1866 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1867 1868 if (mode->hdisplay > fb->width || 1869 mode->vdisplay > fb->height || 1870 crtc_req->x > fb->width - mode->hdisplay || 1871 crtc_req->y > fb->height - mode->vdisplay) { 1872 DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n", 1873 mode->hdisplay, mode->vdisplay, 1874 crtc_req->x, crtc_req->y, 1875 fb->width, fb->height); 1876 ret = ENOSPC; 1877 goto out; 1878 } 1879 } 1880 1881 if (crtc_req->count_connectors == 0 && mode) { 1882 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n"); 1883 ret = EINVAL; 1884 goto out; 1885 } 1886 1887 if (crtc_req->count_connectors > 0 && (!mode || !fb)) { 1888 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n", 1889 crtc_req->count_connectors); 1890 ret = EINVAL; 1891 goto out; 1892 } 1893 1894 if (crtc_req->count_connectors > 0) { 1895 u32 out_id; 1896 1897 /* Avoid unbounded kernel memory allocation */ 1898 if (crtc_req->count_connectors > config->num_connector) { 1899 ret = EINVAL; 1900 goto out; 1901 } 1902 1903 connector_set = malloc(crtc_req->count_connectors * 1904 sizeof(struct drm_connector *), DRM_MEM_KMS, M_WAITOK); 1905 1906 for (i = 0; i < crtc_req->count_connectors; i++) { 1907 set_connectors_ptr = (uint32_t *)(uintptr_t)crtc_req->set_connectors_ptr; 1908 if (copyin(&set_connectors_ptr[i], &out_id, sizeof(uint32_t))) { 1909 ret = EFAULT; 1910 goto out; 1911 } 1912 1913 obj = drm_mode_object_find(dev, out_id, 1914 DRM_MODE_OBJECT_CONNECTOR); 1915 if (!obj) { 1916 DRM_DEBUG_KMS("Connector id %d unknown\n", 1917 out_id); 1918 ret = EINVAL; 1919 goto out; 1920 } 1921 connector = obj_to_connector(obj); 1922 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 1923 connector->base.id, 1924 drm_get_connector_name(connector)); 1925 1926 connector_set[i] = connector; 1927 } 1928 } 1929 1930 set.crtc = crtc; 1931 set.x = crtc_req->x; 1932 set.y = crtc_req->y; 1933 set.mode = mode; 1934 set.connectors = connector_set; 1935 set.num_connectors = crtc_req->count_connectors; 1936 set.fb = fb; 1937 ret = crtc->funcs->set_config(&set); 1938 1939 out: 1940 free(connector_set, DRM_MEM_KMS); 1941 drm_mode_destroy(dev, mode); 1942 sx_xunlock(&dev->mode_config.mutex); 1943 return ret; 1944 } 1945 1946 int drm_mode_cursor_ioctl(struct drm_device *dev, 1947 void *data, struct drm_file *file_priv) 1948 { 1949 struct drm_mode_cursor *req = data; 1950 struct drm_mode_object *obj; 1951 struct drm_crtc *crtc; 1952 int ret = 0; 1953 1954 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1955 return (EINVAL); 1956 1957 if (!req->flags) 1958 return (EINVAL); 1959 1960 sx_xlock(&dev->mode_config.mutex); 1961 obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); 1962 if (!obj) { 1963 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); 1964 ret = EINVAL; 1965 goto out; 1966 } 1967 crtc = obj_to_crtc(obj); 1968 1969 if (req->flags & DRM_MODE_CURSOR_BO) { 1970 if (!crtc->funcs->cursor_set) { 1971 ret = ENXIO; 1972 goto out; 1973 } 1974 /* Turns off the cursor if handle is 0 */ 1975 ret = -crtc->funcs->cursor_set(crtc, file_priv, req->handle, 1976 req->width, req->height); 1977 } 1978 1979 if (req->flags & DRM_MODE_CURSOR_MOVE) { 1980 if (crtc->funcs->cursor_move) { 1981 ret = crtc->funcs->cursor_move(crtc, req->x, req->y); 1982 } else { 1983 ret = EFAULT; 1984 goto out; 1985 } 1986 } 1987 out: 1988 sx_xunlock(&dev->mode_config.mutex); 1989 return ret; 1990 } 1991 1992 /* Original addfb only supported RGB formats, so figure out which one */ 1993 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) 1994 { 1995 uint32_t fmt; 1996 1997 switch (bpp) { 1998 case 8: 1999 fmt = DRM_FORMAT_RGB332; 2000 break; 2001 case 16: 2002 if (depth == 15) 2003 fmt = DRM_FORMAT_XRGB1555; 2004 else 2005 fmt = DRM_FORMAT_RGB565; 2006 break; 2007 case 24: 2008 fmt = DRM_FORMAT_RGB888; 2009 break; 2010 case 32: 2011 if (depth == 24) 2012 fmt = DRM_FORMAT_XRGB8888; 2013 else if (depth == 30) 2014 fmt = DRM_FORMAT_XRGB2101010; 2015 else 2016 fmt = DRM_FORMAT_ARGB8888; 2017 break; 2018 default: 2019 DRM_ERROR("bad bpp, assuming RGB24 pixel format\n"); 2020 fmt = DRM_FORMAT_XRGB8888; 2021 break; 2022 } 2023 2024 return fmt; 2025 } 2026 2027 /** 2028 * drm_mode_addfb - add an FB to the graphics configuration 2029 * @inode: inode from the ioctl 2030 * @filp: file * from the ioctl 2031 * @cmd: cmd from ioctl 2032 * @arg: arg from ioctl 2033 * 2034 * LOCKING: 2035 * Takes mode config lock. 2036 * 2037 * Add a new FB to the specified CRTC, given a user request. 2038 * 2039 * Called by the user via ioctl. 2040 * 2041 * RETURNS: 2042 * Zero on success, errno on failure. 2043 */ 2044 int drm_mode_addfb(struct drm_device *dev, 2045 void *data, struct drm_file *file_priv) 2046 { 2047 struct drm_mode_fb_cmd *or = data; 2048 struct drm_mode_fb_cmd2 r = {}; 2049 struct drm_mode_config *config = &dev->mode_config; 2050 struct drm_framebuffer *fb; 2051 int ret = 0; 2052 2053 /* Use new struct with format internally */ 2054 r.fb_id = or->fb_id; 2055 r.width = or->width; 2056 r.height = or->height; 2057 r.pitches[0] = or->pitch; 2058 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); 2059 r.handles[0] = or->handle; 2060 2061 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2062 return (EINVAL); 2063 2064 if ((config->min_width > r.width) || (r.width > config->max_width)) 2065 return (EINVAL); 2066 if ((config->min_height > r.height) || (r.height > config->max_height)) 2067 return (EINVAL); 2068 2069 sx_xlock(&dev->mode_config.mutex); 2070 2071 ret = -dev->mode_config.funcs->fb_create(dev, file_priv, &r, &fb); 2072 if (ret != 0) { 2073 DRM_ERROR("could not create framebuffer, error %d\n", ret); 2074 goto out; 2075 } 2076 2077 or->fb_id = fb->base.id; 2078 list_add(&fb->filp_head, &file_priv->fbs); 2079 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); 2080 2081 out: 2082 sx_xunlock(&dev->mode_config.mutex); 2083 return ret; 2084 } 2085 2086 static int format_check(struct drm_mode_fb_cmd2 *r) 2087 { 2088 uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; 2089 2090 switch (format) { 2091 case DRM_FORMAT_C8: 2092 case DRM_FORMAT_RGB332: 2093 case DRM_FORMAT_BGR233: 2094 case DRM_FORMAT_XRGB4444: 2095 case DRM_FORMAT_XBGR4444: 2096 case DRM_FORMAT_RGBX4444: 2097 case DRM_FORMAT_BGRX4444: 2098 case DRM_FORMAT_ARGB4444: 2099 case DRM_FORMAT_ABGR4444: 2100 case DRM_FORMAT_RGBA4444: 2101 case DRM_FORMAT_BGRA4444: 2102 case DRM_FORMAT_XRGB1555: 2103 case DRM_FORMAT_XBGR1555: 2104 case DRM_FORMAT_RGBX5551: 2105 case DRM_FORMAT_BGRX5551: 2106 case DRM_FORMAT_ARGB1555: 2107 case DRM_FORMAT_ABGR1555: 2108 case DRM_FORMAT_RGBA5551: 2109 case DRM_FORMAT_BGRA5551: 2110 case DRM_FORMAT_RGB565: 2111 case DRM_FORMAT_BGR565: 2112 case DRM_FORMAT_RGB888: 2113 case DRM_FORMAT_BGR888: 2114 case DRM_FORMAT_XRGB8888: 2115 case DRM_FORMAT_XBGR8888: 2116 case DRM_FORMAT_RGBX8888: 2117 case DRM_FORMAT_BGRX8888: 2118 case DRM_FORMAT_ARGB8888: 2119 case DRM_FORMAT_ABGR8888: 2120 case DRM_FORMAT_RGBA8888: 2121 case DRM_FORMAT_BGRA8888: 2122 case DRM_FORMAT_XRGB2101010: 2123 case DRM_FORMAT_XBGR2101010: 2124 case DRM_FORMAT_RGBX1010102: 2125 case DRM_FORMAT_BGRX1010102: 2126 case DRM_FORMAT_ARGB2101010: 2127 case DRM_FORMAT_ABGR2101010: 2128 case DRM_FORMAT_RGBA1010102: 2129 case DRM_FORMAT_BGRA1010102: 2130 case DRM_FORMAT_YUYV: 2131 case DRM_FORMAT_YVYU: 2132 case DRM_FORMAT_UYVY: 2133 case DRM_FORMAT_VYUY: 2134 case DRM_FORMAT_AYUV: 2135 case DRM_FORMAT_NV12: 2136 case DRM_FORMAT_NV21: 2137 case DRM_FORMAT_NV16: 2138 case DRM_FORMAT_NV61: 2139 case DRM_FORMAT_YUV410: 2140 case DRM_FORMAT_YVU410: 2141 case DRM_FORMAT_YUV411: 2142 case DRM_FORMAT_YVU411: 2143 case DRM_FORMAT_YUV420: 2144 case DRM_FORMAT_YVU420: 2145 case DRM_FORMAT_YUV422: 2146 case DRM_FORMAT_YVU422: 2147 case DRM_FORMAT_YUV444: 2148 case DRM_FORMAT_YVU444: 2149 return 0; 2150 default: 2151 return (EINVAL); 2152 } 2153 } 2154 2155 /** 2156 * drm_mode_addfb2 - add an FB to the graphics configuration 2157 * @inode: inode from the ioctl 2158 * @filp: file * from the ioctl 2159 * @cmd: cmd from ioctl 2160 * @arg: arg from ioctl 2161 * 2162 * LOCKING: 2163 * Takes mode config lock. 2164 * 2165 * Add a new FB to the specified CRTC, given a user request with format. 2166 * 2167 * Called by the user via ioctl. 2168 * 2169 * RETURNS: 2170 * Zero on success, errno on failure. 2171 */ 2172 int drm_mode_addfb2(struct drm_device *dev, 2173 void *data, struct drm_file *file_priv) 2174 { 2175 struct drm_mode_fb_cmd2 *r = data; 2176 struct drm_mode_config *config = &dev->mode_config; 2177 struct drm_framebuffer *fb; 2178 int ret = 0; 2179 2180 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2181 return (EINVAL); 2182 2183 if ((config->min_width > r->width) || (r->width > config->max_width)) { 2184 DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n", 2185 r->width, config->min_width, config->max_width); 2186 return (EINVAL); 2187 } 2188 if ((config->min_height > r->height) || (r->height > config->max_height)) { 2189 DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n", 2190 r->height, config->min_height, config->max_height); 2191 return (EINVAL); 2192 } 2193 2194 ret = format_check(r); 2195 if (ret) { 2196 DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format); 2197 return ret; 2198 } 2199 2200 sx_xlock(&dev->mode_config.mutex); 2201 2202 /* TODO check buffer is sufficiently large */ 2203 /* TODO setup destructor callback */ 2204 2205 ret = -dev->mode_config.funcs->fb_create(dev, file_priv, r, &fb); 2206 if (ret != 0) { 2207 DRM_ERROR("could not create framebuffer, error %d\n", ret); 2208 goto out; 2209 } 2210 2211 r->fb_id = fb->base.id; 2212 list_add(&fb->filp_head, &file_priv->fbs); 2213 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); 2214 2215 out: 2216 sx_xunlock(&dev->mode_config.mutex); 2217 return (ret); 2218 } 2219 2220 /** 2221 * drm_mode_rmfb - remove an FB from the configuration 2222 * @inode: inode from the ioctl 2223 * @filp: file * from the ioctl 2224 * @cmd: cmd from ioctl 2225 * @arg: arg from ioctl 2226 * 2227 * LOCKING: 2228 * Takes mode config lock. 2229 * 2230 * Remove the FB specified by the user. 2231 * 2232 * Called by the user via ioctl. 2233 * 2234 * RETURNS: 2235 * Zero on success, errno on failure. 2236 */ 2237 int drm_mode_rmfb(struct drm_device *dev, 2238 void *data, struct drm_file *file_priv) 2239 { 2240 struct drm_mode_object *obj; 2241 struct drm_framebuffer *fb = NULL; 2242 struct drm_framebuffer *fbl = NULL; 2243 uint32_t *id = data; 2244 int ret = 0; 2245 int found = 0; 2246 2247 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2248 return (EINVAL); 2249 2250 sx_xlock(&dev->mode_config.mutex); 2251 obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); 2252 /* TODO check that we really get a framebuffer back. */ 2253 if (!obj) { 2254 ret = EINVAL; 2255 goto out; 2256 } 2257 fb = obj_to_fb(obj); 2258 2259 list_for_each_entry(fbl, &file_priv->fbs, filp_head) 2260 if (fb == fbl) 2261 found = 1; 2262 2263 if (!found) { 2264 ret = EINVAL; 2265 goto out; 2266 } 2267 2268 /* TODO release all crtc connected to the framebuffer */ 2269 /* TODO unhock the destructor from the buffer object */ 2270 2271 list_del(&fb->filp_head); 2272 fb->funcs->destroy(fb); 2273 2274 out: 2275 sx_xunlock(&dev->mode_config.mutex); 2276 return ret; 2277 } 2278 2279 /** 2280 * drm_mode_getfb - get FB info 2281 * @inode: inode from the ioctl 2282 * @filp: file * from the ioctl 2283 * @cmd: cmd from ioctl 2284 * @arg: arg from ioctl 2285 * 2286 * LOCKING: 2287 * Takes mode config lock. 2288 * 2289 * Lookup the FB given its ID and return info about it. 2290 * 2291 * Called by the user via ioctl. 2292 * 2293 * RETURNS: 2294 * Zero on success, errno on failure. 2295 */ 2296 int drm_mode_getfb(struct drm_device *dev, 2297 void *data, struct drm_file *file_priv) 2298 { 2299 struct drm_mode_fb_cmd *r = data; 2300 struct drm_mode_object *obj; 2301 struct drm_framebuffer *fb; 2302 int ret = 0; 2303 2304 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2305 return (EINVAL); 2306 2307 sx_xlock(&dev->mode_config.mutex); 2308 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2309 if (!obj) { 2310 ret = EINVAL; 2311 goto out; 2312 } 2313 fb = obj_to_fb(obj); 2314 2315 r->height = fb->height; 2316 r->width = fb->width; 2317 r->depth = fb->depth; 2318 r->bpp = fb->bits_per_pixel; 2319 r->pitch = fb->pitches[0]; 2320 r->handle = 0; 2321 fb->funcs->create_handle(fb, file_priv, &r->handle); 2322 2323 out: 2324 sx_xunlock(&dev->mode_config.mutex); 2325 return ret; 2326 } 2327 2328 int drm_mode_dirtyfb_ioctl(struct drm_device *dev, 2329 void *data, struct drm_file *file_priv) 2330 { 2331 struct drm_clip_rect __user *clips_ptr; 2332 struct drm_clip_rect *clips = NULL; 2333 struct drm_mode_fb_dirty_cmd *r = data; 2334 struct drm_mode_object *obj; 2335 struct drm_framebuffer *fb; 2336 unsigned flags; 2337 int num_clips; 2338 int ret = 0; 2339 2340 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2341 return (EINVAL); 2342 2343 sx_xlock(&dev->mode_config.mutex); 2344 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2345 if (!obj) { 2346 ret = EINVAL; 2347 goto out_err1; 2348 } 2349 fb = obj_to_fb(obj); 2350 2351 num_clips = r->num_clips; 2352 clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; 2353 2354 if (!num_clips != !clips_ptr) { 2355 ret = EINVAL; 2356 goto out_err1; 2357 } 2358 2359 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; 2360 2361 /* If userspace annotates copy, clips must come in pairs */ 2362 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { 2363 ret = EINVAL; 2364 goto out_err1; 2365 } 2366 2367 if (num_clips && clips_ptr) { 2368 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { 2369 ret = EINVAL; 2370 goto out_err1; 2371 } 2372 clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS, 2373 M_WAITOK | M_ZERO); 2374 2375 ret = copyin(clips_ptr, clips, num_clips * sizeof(*clips)); 2376 if (ret) 2377 goto out_err2; 2378 } 2379 2380 if (fb->funcs->dirty) { 2381 ret = -fb->funcs->dirty(fb, file_priv, flags, r->color, 2382 clips, num_clips); 2383 } else { 2384 ret = ENOSYS; 2385 goto out_err2; 2386 } 2387 2388 out_err2: 2389 free(clips, DRM_MEM_KMS); 2390 out_err1: 2391 sx_xunlock(&dev->mode_config.mutex); 2392 return ret; 2393 } 2394 2395 2396 /** 2397 * drm_fb_release - remove and free the FBs on this file 2398 * @filp: file * from the ioctl 2399 * 2400 * LOCKING: 2401 * Takes mode config lock. 2402 * 2403 * Destroy all the FBs associated with @filp. 2404 * 2405 * Called by the user via ioctl. 2406 * 2407 * RETURNS: 2408 * Zero on success, errno on failure. 2409 */ 2410 void drm_fb_release(struct drm_file *priv) 2411 { 2412 #if 1 2413 struct drm_device *dev = priv->dev; 2414 #else 2415 struct drm_device *dev = priv->minor->dev; 2416 #endif 2417 struct drm_framebuffer *fb, *tfb; 2418 2419 sx_xlock(&dev->mode_config.mutex); 2420 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 2421 list_del(&fb->filp_head); 2422 fb->funcs->destroy(fb); 2423 } 2424 sx_xunlock(&dev->mode_config.mutex); 2425 } 2426 2427 /** 2428 * drm_mode_attachmode - add a mode to the user mode list 2429 * @dev: DRM device 2430 * @connector: connector to add the mode to 2431 * @mode: mode to add 2432 * 2433 * Add @mode to @connector's user mode list. 2434 */ 2435 static void drm_mode_attachmode(struct drm_device *dev, 2436 struct drm_connector *connector, 2437 struct drm_display_mode *mode) 2438 { 2439 list_add_tail(&mode->head, &connector->user_modes); 2440 } 2441 2442 int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, 2443 const struct drm_display_mode *mode) 2444 { 2445 struct drm_connector *connector; 2446 int ret = 0; 2447 struct drm_display_mode *dup_mode, *next; 2448 DRM_LIST_HEAD(list); 2449 2450 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2451 if (!connector->encoder) 2452 continue; 2453 if (connector->encoder->crtc == crtc) { 2454 dup_mode = drm_mode_duplicate(dev, mode); 2455 if (!dup_mode) { 2456 ret = ENOMEM; 2457 goto out; 2458 } 2459 list_add_tail(&dup_mode->head, &list); 2460 } 2461 } 2462 2463 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2464 if (!connector->encoder) 2465 continue; 2466 if (connector->encoder->crtc == crtc) 2467 list_move_tail(list.next, &connector->user_modes); 2468 } 2469 2470 MPASS(!list_empty(&list)); 2471 2472 out: 2473 list_for_each_entry_safe(dup_mode, next, &list, head) 2474 drm_mode_destroy(dev, dup_mode); 2475 2476 return ret; 2477 } 2478 2479 static int drm_mode_detachmode(struct drm_device *dev, 2480 struct drm_connector *connector, 2481 struct drm_display_mode *mode) 2482 { 2483 int found = 0; 2484 int ret = 0; 2485 struct drm_display_mode *match_mode, *t; 2486 2487 list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) { 2488 if (drm_mode_equal(match_mode, mode)) { 2489 list_del(&match_mode->head); 2490 drm_mode_destroy(dev, match_mode); 2491 found = 1; 2492 break; 2493 } 2494 } 2495 2496 if (!found) 2497 ret = -EINVAL; 2498 2499 return ret; 2500 } 2501 2502 int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) 2503 { 2504 struct drm_connector *connector; 2505 2506 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2507 drm_mode_detachmode(dev, connector, mode); 2508 } 2509 return 0; 2510 } 2511 2512 /** 2513 * drm_fb_attachmode - Attach a user mode to an connector 2514 * @inode: inode from the ioctl 2515 * @filp: file * from the ioctl 2516 * @cmd: cmd from ioctl 2517 * @arg: arg from ioctl 2518 * 2519 * This attaches a user specified mode to an connector. 2520 * Called by the user via ioctl. 2521 * 2522 * RETURNS: 2523 * Zero on success, errno on failure. 2524 */ 2525 int drm_mode_attachmode_ioctl(struct drm_device *dev, 2526 void *data, struct drm_file *file_priv) 2527 { 2528 struct drm_mode_mode_cmd *mode_cmd = data; 2529 struct drm_connector *connector; 2530 struct drm_display_mode *mode; 2531 struct drm_mode_object *obj; 2532 struct drm_mode_modeinfo *umode = &mode_cmd->mode; 2533 int ret = 0; 2534 2535 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2536 return -EINVAL; 2537 2538 sx_xlock(&dev->mode_config.mutex); 2539 2540 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2541 if (!obj) { 2542 ret = -EINVAL; 2543 goto out; 2544 } 2545 connector = obj_to_connector(obj); 2546 2547 mode = drm_mode_create(dev); 2548 if (!mode) { 2549 ret = -ENOMEM; 2550 goto out; 2551 } 2552 2553 ret = drm_crtc_convert_umode(mode, umode); 2554 if (ret) { 2555 DRM_DEBUG_KMS("Invalid mode\n"); 2556 drm_mode_destroy(dev, mode); 2557 goto out; 2558 } 2559 2560 drm_mode_attachmode(dev, connector, mode); 2561 out: 2562 sx_xunlock(&dev->mode_config.mutex); 2563 return ret; 2564 } 2565 2566 2567 /** 2568 * drm_fb_detachmode - Detach a user specified mode from an connector 2569 * @inode: inode from the ioctl 2570 * @filp: file * from the ioctl 2571 * @cmd: cmd from ioctl 2572 * @arg: arg from ioctl 2573 * 2574 * Called by the user via ioctl. 2575 * 2576 * RETURNS: 2577 * Zero on success, errno on failure. 2578 */ 2579 int drm_mode_detachmode_ioctl(struct drm_device *dev, 2580 void *data, struct drm_file *file_priv) 2581 { 2582 struct drm_mode_object *obj; 2583 struct drm_mode_mode_cmd *mode_cmd = data; 2584 struct drm_connector *connector; 2585 struct drm_display_mode mode; 2586 struct drm_mode_modeinfo *umode = &mode_cmd->mode; 2587 int ret = 0; 2588 2589 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2590 return -EINVAL; 2591 2592 sx_xlock(&dev->mode_config.mutex); 2593 2594 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2595 if (!obj) { 2596 ret = -EINVAL; 2597 goto out; 2598 } 2599 connector = obj_to_connector(obj); 2600 2601 ret = drm_crtc_convert_umode(&mode, umode); 2602 if (ret) { 2603 DRM_DEBUG_KMS("Invalid mode\n"); 2604 goto out; 2605 } 2606 2607 ret = drm_mode_detachmode(dev, connector, &mode); 2608 out: 2609 sx_xunlock(&dev->mode_config.mutex); 2610 return ret; 2611 } 2612 2613 struct drm_property *drm_property_create(struct drm_device *dev, int flags, 2614 const char *name, int num_values) 2615 { 2616 struct drm_property *property = NULL; 2617 int ret; 2618 2619 property = malloc(sizeof(struct drm_property), DRM_MEM_KMS, 2620 M_WAITOK | M_ZERO); 2621 2622 if (num_values) { 2623 property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS, 2624 M_WAITOK | M_ZERO); 2625 } 2626 2627 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); 2628 if (ret) 2629 goto fail; 2630 property->flags = flags; 2631 property->num_values = num_values; 2632 INIT_LIST_HEAD(&property->enum_blob_list); 2633 2634 if (name) { 2635 strncpy(property->name, name, DRM_PROP_NAME_LEN); 2636 property->name[DRM_PROP_NAME_LEN-1] = '\0'; 2637 } 2638 2639 list_add_tail(&property->head, &dev->mode_config.property_list); 2640 return property; 2641 2642 fail: 2643 free(property->values, DRM_MEM_KMS); 2644 free(property, DRM_MEM_KMS); 2645 return (NULL); 2646 } 2647 2648 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, 2649 const char *name, 2650 const struct drm_prop_enum_list *props, 2651 int num_values) 2652 { 2653 struct drm_property *property; 2654 int i, ret; 2655 2656 flags |= DRM_MODE_PROP_ENUM; 2657 2658 property = drm_property_create(dev, flags, name, num_values); 2659 if (!property) 2660 return NULL; 2661 2662 for (i = 0; i < num_values; i++) { 2663 ret = drm_property_add_enum(property, i, 2664 props[i].type, 2665 props[i].name); 2666 if (ret) { 2667 drm_property_destroy(dev, property); 2668 return NULL; 2669 } 2670 } 2671 2672 return property; 2673 } 2674 2675 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, 2676 const char *name, 2677 uint64_t min, uint64_t max) 2678 { 2679 struct drm_property *property; 2680 2681 flags |= DRM_MODE_PROP_RANGE; 2682 2683 property = drm_property_create(dev, flags, name, 2); 2684 if (!property) 2685 return NULL; 2686 2687 property->values[0] = min; 2688 property->values[1] = max; 2689 2690 return property; 2691 } 2692 2693 int drm_property_add_enum(struct drm_property *property, int index, 2694 uint64_t value, const char *name) 2695 { 2696 struct drm_property_enum *prop_enum; 2697 2698 if (!(property->flags & DRM_MODE_PROP_ENUM)) 2699 return -EINVAL; 2700 2701 if (!list_empty(&property->enum_blob_list)) { 2702 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2703 if (prop_enum->value == value) { 2704 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2705 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2706 return 0; 2707 } 2708 } 2709 } 2710 2711 prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS, 2712 M_WAITOK | M_ZERO); 2713 2714 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2715 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2716 prop_enum->value = value; 2717 2718 property->values[index] = value; 2719 list_add_tail(&prop_enum->head, &property->enum_blob_list); 2720 return 0; 2721 } 2722 2723 void drm_property_destroy(struct drm_device *dev, struct drm_property *property) 2724 { 2725 struct drm_property_enum *prop_enum, *pt; 2726 2727 list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { 2728 list_del(&prop_enum->head); 2729 free(prop_enum, DRM_MEM_KMS); 2730 } 2731 2732 if (property->num_values) 2733 free(property->values, DRM_MEM_KMS); 2734 drm_mode_object_put(dev, &property->base); 2735 list_del(&property->head); 2736 free(property, DRM_MEM_KMS); 2737 } 2738 2739 int drm_connector_attach_property(struct drm_connector *connector, 2740 struct drm_property *property, uint64_t init_val) 2741 { 2742 int i; 2743 2744 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2745 if (connector->property_ids[i] == 0) { 2746 connector->property_ids[i] = property->base.id; 2747 connector->property_values[i] = init_val; 2748 break; 2749 } 2750 } 2751 2752 if (i == DRM_CONNECTOR_MAX_PROPERTY) 2753 return -EINVAL; 2754 return 0; 2755 } 2756 2757 int drm_connector_property_set_value(struct drm_connector *connector, 2758 struct drm_property *property, uint64_t value) 2759 { 2760 int i; 2761 2762 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2763 if (connector->property_ids[i] == property->base.id) { 2764 connector->property_values[i] = value; 2765 break; 2766 } 2767 } 2768 2769 if (i == DRM_CONNECTOR_MAX_PROPERTY) 2770 return -EINVAL; 2771 return 0; 2772 } 2773 2774 int drm_connector_property_get_value(struct drm_connector *connector, 2775 struct drm_property *property, uint64_t *val) 2776 { 2777 int i; 2778 2779 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2780 if (connector->property_ids[i] == property->base.id) { 2781 *val = connector->property_values[i]; 2782 break; 2783 } 2784 } 2785 2786 if (i == DRM_CONNECTOR_MAX_PROPERTY) 2787 return -EINVAL; 2788 return 0; 2789 } 2790 2791 int drm_mode_getproperty_ioctl(struct drm_device *dev, 2792 void *data, struct drm_file *file_priv) 2793 { 2794 struct drm_mode_object *obj; 2795 struct drm_mode_get_property *out_resp = data; 2796 struct drm_property *property; 2797 int enum_count = 0; 2798 int blob_count = 0; 2799 int value_count = 0; 2800 int ret = 0, i; 2801 int copied; 2802 struct drm_property_enum *prop_enum; 2803 struct drm_mode_property_enum __user *enum_ptr; 2804 struct drm_property_blob *prop_blob; 2805 uint32_t *blob_id_ptr; 2806 uint64_t *values_ptr; 2807 uint32_t *blob_length_ptr; 2808 2809 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2810 return -EINVAL; 2811 2812 sx_xlock(&dev->mode_config.mutex); 2813 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 2814 if (!obj) { 2815 ret = -EINVAL; 2816 goto done; 2817 } 2818 property = obj_to_property(obj); 2819 2820 if (property->flags & DRM_MODE_PROP_ENUM) { 2821 list_for_each_entry(prop_enum, &property->enum_blob_list, head) 2822 enum_count++; 2823 } else if (property->flags & DRM_MODE_PROP_BLOB) { 2824 list_for_each_entry(prop_blob, &property->enum_blob_list, head) 2825 blob_count++; 2826 } 2827 2828 value_count = property->num_values; 2829 2830 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); 2831 out_resp->name[DRM_PROP_NAME_LEN-1] = 0; 2832 out_resp->flags = property->flags; 2833 2834 if ((out_resp->count_values >= value_count) && value_count) { 2835 values_ptr = (uint64_t *)(uintptr_t)out_resp->values_ptr; 2836 for (i = 0; i < value_count; i++) { 2837 if (copyout(&property->values[i], values_ptr + i, sizeof(uint64_t))) { 2838 ret = -EFAULT; 2839 goto done; 2840 } 2841 } 2842 } 2843 out_resp->count_values = value_count; 2844 2845 if (property->flags & DRM_MODE_PROP_ENUM) { 2846 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { 2847 copied = 0; 2848 enum_ptr = (struct drm_mode_property_enum *)(uintptr_t)out_resp->enum_blob_ptr; 2849 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2850 2851 if (copyout(&prop_enum->value, &enum_ptr[copied].value, sizeof(uint64_t))) { 2852 ret = -EFAULT; 2853 goto done; 2854 } 2855 2856 if (copyout(&prop_enum->name, 2857 &enum_ptr[copied].name,DRM_PROP_NAME_LEN)) { 2858 ret = -EFAULT; 2859 goto done; 2860 } 2861 copied++; 2862 } 2863 } 2864 out_resp->count_enum_blobs = enum_count; 2865 } 2866 2867 if (property->flags & DRM_MODE_PROP_BLOB) { 2868 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { 2869 copied = 0; 2870 blob_id_ptr = (uint32_t *)(uintptr_t)out_resp->enum_blob_ptr; 2871 blob_length_ptr = (uint32_t *)(uintptr_t)out_resp->values_ptr; 2872 2873 list_for_each_entry(prop_blob, &property->enum_blob_list, head) { 2874 if (copyout(&prop_blob->base.id, 2875 blob_id_ptr + copied, sizeof(uint32_t))) { 2876 ret = -EFAULT; 2877 goto done; 2878 } 2879 2880 if (copyout(&prop_blob->length, 2881 blob_length_ptr + copied, sizeof(uint32_t))) { 2882 ret = -EFAULT; 2883 goto done; 2884 } 2885 2886 copied++; 2887 } 2888 } 2889 out_resp->count_enum_blobs = blob_count; 2890 } 2891 done: 2892 sx_xunlock(&dev->mode_config.mutex); 2893 return ret; 2894 } 2895 2896 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, 2897 void *data) 2898 { 2899 struct drm_property_blob *blob; 2900 int ret; 2901 2902 if (!length || !data) 2903 return NULL; 2904 2905 blob = malloc(sizeof(struct drm_property_blob) + length, DRM_MEM_KMS, 2906 M_WAITOK | M_ZERO); 2907 2908 ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); 2909 if (ret) { 2910 free(blob, DRM_MEM_KMS); 2911 return (NULL); 2912 } 2913 2914 blob->length = length; 2915 2916 memcpy(blob->data, data, length); 2917 2918 list_add_tail(&blob->head, &dev->mode_config.property_blob_list); 2919 return blob; 2920 } 2921 2922 static void drm_property_destroy_blob(struct drm_device *dev, 2923 struct drm_property_blob *blob) 2924 { 2925 drm_mode_object_put(dev, &blob->base); 2926 list_del(&blob->head); 2927 free(blob, DRM_MEM_KMS); 2928 } 2929 2930 int drm_mode_getblob_ioctl(struct drm_device *dev, 2931 void *data, struct drm_file *file_priv) 2932 { 2933 struct drm_mode_object *obj; 2934 struct drm_mode_get_blob *out_resp = data; 2935 struct drm_property_blob *blob; 2936 int ret = 0; 2937 void *blob_ptr; 2938 2939 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2940 return -EINVAL; 2941 2942 sx_xlock(&dev->mode_config.mutex); 2943 obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); 2944 if (!obj) { 2945 ret = -EINVAL; 2946 goto done; 2947 } 2948 blob = obj_to_blob(obj); 2949 2950 if (out_resp->length == blob->length) { 2951 blob_ptr = (void *)(unsigned long)out_resp->data; 2952 if (copyout(blob->data, blob_ptr, blob->length)){ 2953 ret = -EFAULT; 2954 goto done; 2955 } 2956 } 2957 out_resp->length = blob->length; 2958 2959 done: 2960 sx_xunlock(&dev->mode_config.mutex); 2961 return ret; 2962 } 2963 2964 int drm_mode_connector_update_edid_property(struct drm_connector *connector, 2965 struct edid *edid) 2966 { 2967 struct drm_device *dev = connector->dev; 2968 int ret = 0, size; 2969 2970 if (connector->edid_blob_ptr) 2971 drm_property_destroy_blob(dev, connector->edid_blob_ptr); 2972 2973 /* Delete edid, when there is none. */ 2974 if (!edid) { 2975 connector->edid_blob_ptr = NULL; 2976 ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); 2977 return ret; 2978 } 2979 2980 size = EDID_LENGTH * (1 + edid->extensions); 2981 connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 2982 size, edid); 2983 2984 ret = drm_connector_property_set_value(connector, 2985 dev->mode_config.edid_property, 2986 connector->edid_blob_ptr->base.id); 2987 2988 return ret; 2989 } 2990 2991 int drm_mode_connector_property_set_ioctl(struct drm_device *dev, 2992 void *data, struct drm_file *file_priv) 2993 { 2994 struct drm_mode_connector_set_property *out_resp = data; 2995 struct drm_mode_object *obj; 2996 struct drm_property *property; 2997 struct drm_connector *connector; 2998 int ret = -EINVAL; 2999 int i; 3000 3001 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3002 return -EINVAL; 3003 3004 sx_xlock(&dev->mode_config.mutex); 3005 3006 obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); 3007 if (!obj) { 3008 goto out; 3009 } 3010 connector = obj_to_connector(obj); 3011 3012 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 3013 if (connector->property_ids[i] == out_resp->prop_id) 3014 break; 3015 } 3016 3017 if (i == DRM_CONNECTOR_MAX_PROPERTY) { 3018 goto out; 3019 } 3020 3021 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 3022 if (!obj) { 3023 goto out; 3024 } 3025 property = obj_to_property(obj); 3026 3027 if (property->flags & DRM_MODE_PROP_IMMUTABLE) 3028 goto out; 3029 3030 if (property->flags & DRM_MODE_PROP_RANGE) { 3031 if (out_resp->value < property->values[0]) 3032 goto out; 3033 3034 if (out_resp->value > property->values[1]) 3035 goto out; 3036 } else { 3037 int found = 0; 3038 for (i = 0; i < property->num_values; i++) { 3039 if (property->values[i] == out_resp->value) { 3040 found = 1; 3041 break; 3042 } 3043 } 3044 if (!found) { 3045 goto out; 3046 } 3047 } 3048 3049 /* Do DPMS ourselves */ 3050 if (property == connector->dev->mode_config.dpms_property) { 3051 if (connector->funcs->dpms) 3052 (*connector->funcs->dpms)(connector, (int) out_resp->value); 3053 ret = 0; 3054 } else if (connector->funcs->set_property) 3055 ret = connector->funcs->set_property(connector, property, out_resp->value); 3056 3057 /* store the property value if successful */ 3058 if (!ret) 3059 drm_connector_property_set_value(connector, property, out_resp->value); 3060 out: 3061 sx_xunlock(&dev->mode_config.mutex); 3062 return ret; 3063 } 3064 3065 int drm_mode_connector_attach_encoder(struct drm_connector *connector, 3066 struct drm_encoder *encoder) 3067 { 3068 int i; 3069 3070 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3071 if (connector->encoder_ids[i] == 0) { 3072 connector->encoder_ids[i] = encoder->base.id; 3073 return 0; 3074 } 3075 } 3076 return -ENOMEM; 3077 } 3078 3079 void drm_mode_connector_detach_encoder(struct drm_connector *connector, 3080 struct drm_encoder *encoder) 3081 { 3082 int i; 3083 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3084 if (connector->encoder_ids[i] == encoder->base.id) { 3085 connector->encoder_ids[i] = 0; 3086 if (connector->encoder == encoder) 3087 connector->encoder = NULL; 3088 break; 3089 } 3090 } 3091 } 3092 3093 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 3094 int gamma_size) 3095 { 3096 crtc->gamma_size = gamma_size; 3097 3098 crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3, 3099 DRM_MEM_KMS, M_WAITOK | M_ZERO); 3100 3101 return 0; 3102 } 3103 3104 int drm_mode_gamma_set_ioctl(struct drm_device *dev, 3105 void *data, struct drm_file *file_priv) 3106 { 3107 struct drm_mode_crtc_lut *crtc_lut = data; 3108 struct drm_mode_object *obj; 3109 struct drm_crtc *crtc; 3110 void *r_base, *g_base, *b_base; 3111 int size; 3112 int ret = 0; 3113 3114 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3115 return -EINVAL; 3116 3117 sx_xlock(&dev->mode_config.mutex); 3118 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3119 if (!obj) { 3120 ret = -EINVAL; 3121 goto out; 3122 } 3123 crtc = obj_to_crtc(obj); 3124 3125 /* memcpy into gamma store */ 3126 if (crtc_lut->gamma_size != crtc->gamma_size) { 3127 ret = -EINVAL; 3128 goto out; 3129 } 3130 3131 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3132 r_base = crtc->gamma_store; 3133 if (copyin((void *)(uintptr_t)crtc_lut->red, r_base, size)) { 3134 ret = -EFAULT; 3135 goto out; 3136 } 3137 3138 g_base = (char *)r_base + size; 3139 if (copyin((void *)(uintptr_t)crtc_lut->green, g_base, size)) { 3140 ret = -EFAULT; 3141 goto out; 3142 } 3143 3144 b_base = (char *)g_base + size; 3145 if (copyin((void *)(uintptr_t)crtc_lut->blue, b_base, size)) { 3146 ret = -EFAULT; 3147 goto out; 3148 } 3149 3150 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); 3151 3152 out: 3153 sx_xunlock(&dev->mode_config.mutex); 3154 return ret; 3155 3156 } 3157 3158 int drm_mode_gamma_get_ioctl(struct drm_device *dev, 3159 void *data, struct drm_file *file_priv) 3160 { 3161 struct drm_mode_crtc_lut *crtc_lut = data; 3162 struct drm_mode_object *obj; 3163 struct drm_crtc *crtc; 3164 void *r_base, *g_base, *b_base; 3165 int size; 3166 int ret = 0; 3167 3168 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3169 return -EINVAL; 3170 3171 sx_xlock(&dev->mode_config.mutex); 3172 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3173 if (!obj) { 3174 ret = -EINVAL; 3175 goto out; 3176 } 3177 crtc = obj_to_crtc(obj); 3178 3179 /* memcpy into gamma store */ 3180 if (crtc_lut->gamma_size != crtc->gamma_size) { 3181 ret = -EINVAL; 3182 goto out; 3183 } 3184 3185 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3186 r_base = crtc->gamma_store; 3187 if (copyout(r_base, (void *)(uintptr_t)crtc_lut->red, size)) { 3188 ret = -EFAULT; 3189 goto out; 3190 } 3191 3192 g_base = (char *)r_base + size; 3193 if (copyout(g_base, (void *)(uintptr_t)crtc_lut->green, size)) { 3194 ret = -EFAULT; 3195 goto out; 3196 } 3197 3198 b_base = (char *)g_base + size; 3199 if (copyout(b_base, (void *)(uintptr_t)crtc_lut->blue, size)) { 3200 ret = -EFAULT; 3201 goto out; 3202 } 3203 out: 3204 sx_xunlock(&dev->mode_config.mutex); 3205 return ret; 3206 } 3207 3208 static void 3209 drm_kms_free(void *arg) 3210 { 3211 3212 free(arg, DRM_MEM_KMS); 3213 } 3214 3215 int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, 3216 struct drm_file *file_priv) 3217 { 3218 struct drm_mode_crtc_page_flip *page_flip = data; 3219 struct drm_mode_object *obj; 3220 struct drm_crtc *crtc; 3221 struct drm_framebuffer *fb; 3222 struct drm_pending_vblank_event *e = NULL; 3223 int ret = EINVAL; 3224 3225 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || 3226 page_flip->reserved != 0) 3227 return (EINVAL); 3228 3229 sx_xlock(&dev->mode_config.mutex); 3230 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); 3231 if (!obj) 3232 goto out; 3233 crtc = obj_to_crtc(obj); 3234 3235 if (crtc->fb == NULL) { 3236 /* The framebuffer is currently unbound, presumably 3237 * due to a hotplug event, that userspace has not 3238 * yet discovered. 3239 */ 3240 ret = EBUSY; 3241 goto out; 3242 } 3243 3244 if (crtc->funcs->page_flip == NULL) 3245 goto out; 3246 3247 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); 3248 if (!obj) 3249 goto out; 3250 fb = obj_to_fb(obj); 3251 3252 if (crtc->mode.hdisplay > fb->width || 3253 crtc->mode.vdisplay > fb->height || 3254 crtc->x > fb->width - crtc->mode.hdisplay || 3255 crtc->y > fb->height - crtc->mode.vdisplay) { 3256 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", 3257 fb->width, fb->height, 3258 crtc->mode.hdisplay, crtc->mode.vdisplay, 3259 crtc->x, crtc->y); 3260 ret = ENOSPC; 3261 goto out; 3262 } 3263 3264 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3265 ret = ENOMEM; 3266 mtx_lock(&dev->event_lock); 3267 if (file_priv->event_space < sizeof e->event) { 3268 mtx_unlock(&dev->event_lock); 3269 goto out; 3270 } 3271 file_priv->event_space -= sizeof e->event; 3272 mtx_unlock(&dev->event_lock); 3273 3274 e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO); 3275 3276 e->event.base.type = DRM_EVENT_FLIP_COMPLETE; 3277 e->event.base.length = sizeof e->event; 3278 e->event.user_data = page_flip->user_data; 3279 e->base.event = &e->event.base; 3280 e->base.file_priv = file_priv; 3281 e->base.destroy = 3282 (void (*) (struct drm_pending_event *))drm_kms_free; 3283 } 3284 3285 ret = -crtc->funcs->page_flip(crtc, fb, e); 3286 if (ret != 0) { 3287 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3288 mtx_lock(&dev->event_lock); 3289 file_priv->event_space += sizeof e->event; 3290 mtx_unlock(&dev->event_lock); 3291 free(e, DRM_MEM_KMS); 3292 } 3293 } 3294 3295 out: 3296 sx_xunlock(&dev->mode_config.mutex); 3297 CTR3(KTR_DRM, "page_flip_ioctl %d %d %d", curproc->p_pid, 3298 page_flip->crtc_id, ret); 3299 return (ret); 3300 } 3301 3302 void drm_mode_config_reset(struct drm_device *dev) 3303 { 3304 struct drm_crtc *crtc; 3305 struct drm_encoder *encoder; 3306 struct drm_connector *connector; 3307 3308 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 3309 if (crtc->funcs->reset) 3310 crtc->funcs->reset(crtc); 3311 3312 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 3313 if (encoder->funcs->reset) 3314 encoder->funcs->reset(encoder); 3315 3316 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 3317 if (connector->funcs->reset) 3318 connector->funcs->reset(connector); 3319 } 3320 3321 int drm_mode_create_dumb_ioctl(struct drm_device *dev, 3322 void *data, struct drm_file *file_priv) 3323 { 3324 struct drm_mode_create_dumb *args = data; 3325 3326 if (!dev->driver->dumb_create) 3327 return -ENOTSUP; 3328 return dev->driver->dumb_create(file_priv, dev, args); 3329 } 3330 3331 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, 3332 void *data, struct drm_file *file_priv) 3333 { 3334 struct drm_mode_map_dumb *args = data; 3335 3336 /* call driver ioctl to get mmap offset */ 3337 if (!dev->driver->dumb_map_offset) 3338 return -ENOTSUP; 3339 3340 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset); 3341 } 3342 3343 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, 3344 void *data, struct drm_file *file_priv) 3345 { 3346 struct drm_mode_destroy_dumb *args = data; 3347 3348 if (!dev->driver->dumb_destroy) 3349 return -ENOTSUP; 3350 3351 return dev->driver->dumb_destroy(file_priv, dev, args->handle); 3352 } 3353 3354 /* 3355 * Just need to support RGB formats here for compat with code that doesn't 3356 * use pixel formats directly yet. 3357 */ 3358 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, 3359 int *bpp) 3360 { 3361 switch (format) { 3362 case DRM_FORMAT_RGB332: 3363 case DRM_FORMAT_BGR233: 3364 *depth = 8; 3365 *bpp = 8; 3366 break; 3367 case DRM_FORMAT_XRGB1555: 3368 case DRM_FORMAT_XBGR1555: 3369 case DRM_FORMAT_RGBX5551: 3370 case DRM_FORMAT_BGRX5551: 3371 case DRM_FORMAT_ARGB1555: 3372 case DRM_FORMAT_ABGR1555: 3373 case DRM_FORMAT_RGBA5551: 3374 case DRM_FORMAT_BGRA5551: 3375 *depth = 15; 3376 *bpp = 16; 3377 break; 3378 case DRM_FORMAT_RGB565: 3379 case DRM_FORMAT_BGR565: 3380 *depth = 16; 3381 *bpp = 16; 3382 break; 3383 case DRM_FORMAT_RGB888: 3384 case DRM_FORMAT_BGR888: 3385 *depth = 24; 3386 *bpp = 24; 3387 break; 3388 case DRM_FORMAT_XRGB8888: 3389 case DRM_FORMAT_XBGR8888: 3390 case DRM_FORMAT_RGBX8888: 3391 case DRM_FORMAT_BGRX8888: 3392 *depth = 24; 3393 *bpp = 32; 3394 break; 3395 case DRM_FORMAT_XRGB2101010: 3396 case DRM_FORMAT_XBGR2101010: 3397 case DRM_FORMAT_RGBX1010102: 3398 case DRM_FORMAT_BGRX1010102: 3399 case DRM_FORMAT_ARGB2101010: 3400 case DRM_FORMAT_ABGR2101010: 3401 case DRM_FORMAT_RGBA1010102: 3402 case DRM_FORMAT_BGRA1010102: 3403 *depth = 30; 3404 *bpp = 32; 3405 break; 3406 case DRM_FORMAT_ARGB8888: 3407 case DRM_FORMAT_ABGR8888: 3408 case DRM_FORMAT_RGBA8888: 3409 case DRM_FORMAT_BGRA8888: 3410 *depth = 32; 3411 *bpp = 32; 3412 break; 3413 default: 3414 DRM_DEBUG_KMS("unsupported pixel format\n"); 3415 *depth = 0; 3416 *bpp = 0; 3417 break; 3418 } 3419 } 3420