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 fb->funcs->create_handle(fb, file_priv, &r->handle); 2321 2322 out: 2323 sx_xunlock(&dev->mode_config.mutex); 2324 return ret; 2325 } 2326 2327 int drm_mode_dirtyfb_ioctl(struct drm_device *dev, 2328 void *data, struct drm_file *file_priv) 2329 { 2330 struct drm_clip_rect __user *clips_ptr; 2331 struct drm_clip_rect *clips = NULL; 2332 struct drm_mode_fb_dirty_cmd *r = data; 2333 struct drm_mode_object *obj; 2334 struct drm_framebuffer *fb; 2335 unsigned flags; 2336 int num_clips; 2337 int ret = 0; 2338 2339 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2340 return (EINVAL); 2341 2342 sx_xlock(&dev->mode_config.mutex); 2343 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2344 if (!obj) { 2345 ret = EINVAL; 2346 goto out_err1; 2347 } 2348 fb = obj_to_fb(obj); 2349 2350 num_clips = r->num_clips; 2351 clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; 2352 2353 if (!num_clips != !clips_ptr) { 2354 ret = EINVAL; 2355 goto out_err1; 2356 } 2357 2358 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; 2359 2360 /* If userspace annotates copy, clips must come in pairs */ 2361 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { 2362 ret = EINVAL; 2363 goto out_err1; 2364 } 2365 2366 if (num_clips && clips_ptr) { 2367 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { 2368 ret = EINVAL; 2369 goto out_err1; 2370 } 2371 clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS, 2372 M_WAITOK | M_ZERO); 2373 2374 ret = copyin(clips_ptr, clips, num_clips * sizeof(*clips)); 2375 if (ret) 2376 goto out_err2; 2377 } 2378 2379 if (fb->funcs->dirty) { 2380 ret = -fb->funcs->dirty(fb, file_priv, flags, r->color, 2381 clips, num_clips); 2382 } else { 2383 ret = ENOSYS; 2384 goto out_err2; 2385 } 2386 2387 out_err2: 2388 free(clips, DRM_MEM_KMS); 2389 out_err1: 2390 sx_xunlock(&dev->mode_config.mutex); 2391 return ret; 2392 } 2393 2394 2395 /** 2396 * drm_fb_release - remove and free the FBs on this file 2397 * @filp: file * from the ioctl 2398 * 2399 * LOCKING: 2400 * Takes mode config lock. 2401 * 2402 * Destroy all the FBs associated with @filp. 2403 * 2404 * Called by the user via ioctl. 2405 * 2406 * RETURNS: 2407 * Zero on success, errno on failure. 2408 */ 2409 void drm_fb_release(struct drm_file *priv) 2410 { 2411 #if 1 2412 struct drm_device *dev = priv->dev; 2413 #else 2414 struct drm_device *dev = priv->minor->dev; 2415 #endif 2416 struct drm_framebuffer *fb, *tfb; 2417 2418 sx_xlock(&dev->mode_config.mutex); 2419 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 2420 list_del(&fb->filp_head); 2421 fb->funcs->destroy(fb); 2422 } 2423 sx_xunlock(&dev->mode_config.mutex); 2424 } 2425 2426 /** 2427 * drm_mode_attachmode - add a mode to the user mode list 2428 * @dev: DRM device 2429 * @connector: connector to add the mode to 2430 * @mode: mode to add 2431 * 2432 * Add @mode to @connector's user mode list. 2433 */ 2434 static void drm_mode_attachmode(struct drm_device *dev, 2435 struct drm_connector *connector, 2436 struct drm_display_mode *mode) 2437 { 2438 list_add_tail(&mode->head, &connector->user_modes); 2439 } 2440 2441 int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, 2442 const struct drm_display_mode *mode) 2443 { 2444 struct drm_connector *connector; 2445 int ret = 0; 2446 struct drm_display_mode *dup_mode, *next; 2447 DRM_LIST_HEAD(list); 2448 2449 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2450 if (!connector->encoder) 2451 continue; 2452 if (connector->encoder->crtc == crtc) { 2453 dup_mode = drm_mode_duplicate(dev, mode); 2454 if (!dup_mode) { 2455 ret = ENOMEM; 2456 goto out; 2457 } 2458 list_add_tail(&dup_mode->head, &list); 2459 } 2460 } 2461 2462 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2463 if (!connector->encoder) 2464 continue; 2465 if (connector->encoder->crtc == crtc) 2466 list_move_tail(list.next, &connector->user_modes); 2467 } 2468 2469 MPASS(!list_empty(&list)); 2470 2471 out: 2472 list_for_each_entry_safe(dup_mode, next, &list, head) 2473 drm_mode_destroy(dev, dup_mode); 2474 2475 return ret; 2476 } 2477 2478 static int drm_mode_detachmode(struct drm_device *dev, 2479 struct drm_connector *connector, 2480 struct drm_display_mode *mode) 2481 { 2482 int found = 0; 2483 int ret = 0; 2484 struct drm_display_mode *match_mode, *t; 2485 2486 list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) { 2487 if (drm_mode_equal(match_mode, mode)) { 2488 list_del(&match_mode->head); 2489 drm_mode_destroy(dev, match_mode); 2490 found = 1; 2491 break; 2492 } 2493 } 2494 2495 if (!found) 2496 ret = -EINVAL; 2497 2498 return ret; 2499 } 2500 2501 int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) 2502 { 2503 struct drm_connector *connector; 2504 2505 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2506 drm_mode_detachmode(dev, connector, mode); 2507 } 2508 return 0; 2509 } 2510 2511 /** 2512 * drm_fb_attachmode - Attach a user mode to an connector 2513 * @inode: inode from the ioctl 2514 * @filp: file * from the ioctl 2515 * @cmd: cmd from ioctl 2516 * @arg: arg from ioctl 2517 * 2518 * This attaches a user specified mode to an connector. 2519 * Called by the user via ioctl. 2520 * 2521 * RETURNS: 2522 * Zero on success, errno on failure. 2523 */ 2524 int drm_mode_attachmode_ioctl(struct drm_device *dev, 2525 void *data, struct drm_file *file_priv) 2526 { 2527 struct drm_mode_mode_cmd *mode_cmd = data; 2528 struct drm_connector *connector; 2529 struct drm_display_mode *mode; 2530 struct drm_mode_object *obj; 2531 struct drm_mode_modeinfo *umode = &mode_cmd->mode; 2532 int ret = 0; 2533 2534 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2535 return -EINVAL; 2536 2537 sx_xlock(&dev->mode_config.mutex); 2538 2539 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2540 if (!obj) { 2541 ret = -EINVAL; 2542 goto out; 2543 } 2544 connector = obj_to_connector(obj); 2545 2546 mode = drm_mode_create(dev); 2547 if (!mode) { 2548 ret = -ENOMEM; 2549 goto out; 2550 } 2551 2552 ret = drm_crtc_convert_umode(mode, umode); 2553 if (ret) { 2554 DRM_DEBUG_KMS("Invalid mode\n"); 2555 drm_mode_destroy(dev, mode); 2556 goto out; 2557 } 2558 2559 drm_mode_attachmode(dev, connector, mode); 2560 out: 2561 sx_xunlock(&dev->mode_config.mutex); 2562 return ret; 2563 } 2564 2565 2566 /** 2567 * drm_fb_detachmode - Detach a user specified mode from an connector 2568 * @inode: inode from the ioctl 2569 * @filp: file * from the ioctl 2570 * @cmd: cmd from ioctl 2571 * @arg: arg from ioctl 2572 * 2573 * Called by the user via ioctl. 2574 * 2575 * RETURNS: 2576 * Zero on success, errno on failure. 2577 */ 2578 int drm_mode_detachmode_ioctl(struct drm_device *dev, 2579 void *data, struct drm_file *file_priv) 2580 { 2581 struct drm_mode_object *obj; 2582 struct drm_mode_mode_cmd *mode_cmd = data; 2583 struct drm_connector *connector; 2584 struct drm_display_mode mode; 2585 struct drm_mode_modeinfo *umode = &mode_cmd->mode; 2586 int ret = 0; 2587 2588 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2589 return -EINVAL; 2590 2591 sx_xlock(&dev->mode_config.mutex); 2592 2593 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); 2594 if (!obj) { 2595 ret = -EINVAL; 2596 goto out; 2597 } 2598 connector = obj_to_connector(obj); 2599 2600 ret = drm_crtc_convert_umode(&mode, umode); 2601 if (ret) { 2602 DRM_DEBUG_KMS("Invalid mode\n"); 2603 goto out; 2604 } 2605 2606 ret = drm_mode_detachmode(dev, connector, &mode); 2607 out: 2608 sx_xunlock(&dev->mode_config.mutex); 2609 return ret; 2610 } 2611 2612 struct drm_property *drm_property_create(struct drm_device *dev, int flags, 2613 const char *name, int num_values) 2614 { 2615 struct drm_property *property = NULL; 2616 int ret; 2617 2618 property = malloc(sizeof(struct drm_property), DRM_MEM_KMS, 2619 M_WAITOK | M_ZERO); 2620 2621 if (num_values) { 2622 property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS, 2623 M_WAITOK | M_ZERO); 2624 } 2625 2626 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); 2627 if (ret) 2628 goto fail; 2629 property->flags = flags; 2630 property->num_values = num_values; 2631 INIT_LIST_HEAD(&property->enum_blob_list); 2632 2633 if (name) { 2634 strncpy(property->name, name, DRM_PROP_NAME_LEN); 2635 property->name[DRM_PROP_NAME_LEN-1] = '\0'; 2636 } 2637 2638 list_add_tail(&property->head, &dev->mode_config.property_list); 2639 return property; 2640 2641 fail: 2642 free(property->values, DRM_MEM_KMS); 2643 free(property, DRM_MEM_KMS); 2644 return (NULL); 2645 } 2646 2647 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, 2648 const char *name, 2649 const struct drm_prop_enum_list *props, 2650 int num_values) 2651 { 2652 struct drm_property *property; 2653 int i, ret; 2654 2655 flags |= DRM_MODE_PROP_ENUM; 2656 2657 property = drm_property_create(dev, flags, name, num_values); 2658 if (!property) 2659 return NULL; 2660 2661 for (i = 0; i < num_values; i++) { 2662 ret = drm_property_add_enum(property, i, 2663 props[i].type, 2664 props[i].name); 2665 if (ret) { 2666 drm_property_destroy(dev, property); 2667 return NULL; 2668 } 2669 } 2670 2671 return property; 2672 } 2673 2674 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, 2675 const char *name, 2676 uint64_t min, uint64_t max) 2677 { 2678 struct drm_property *property; 2679 2680 flags |= DRM_MODE_PROP_RANGE; 2681 2682 property = drm_property_create(dev, flags, name, 2); 2683 if (!property) 2684 return NULL; 2685 2686 property->values[0] = min; 2687 property->values[1] = max; 2688 2689 return property; 2690 } 2691 2692 int drm_property_add_enum(struct drm_property *property, int index, 2693 uint64_t value, const char *name) 2694 { 2695 struct drm_property_enum *prop_enum; 2696 2697 if (!(property->flags & DRM_MODE_PROP_ENUM)) 2698 return -EINVAL; 2699 2700 if (!list_empty(&property->enum_blob_list)) { 2701 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2702 if (prop_enum->value == value) { 2703 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2704 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2705 return 0; 2706 } 2707 } 2708 } 2709 2710 prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS, 2711 M_WAITOK | M_ZERO); 2712 2713 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2714 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2715 prop_enum->value = value; 2716 2717 property->values[index] = value; 2718 list_add_tail(&prop_enum->head, &property->enum_blob_list); 2719 return 0; 2720 } 2721 2722 void drm_property_destroy(struct drm_device *dev, struct drm_property *property) 2723 { 2724 struct drm_property_enum *prop_enum, *pt; 2725 2726 list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { 2727 list_del(&prop_enum->head); 2728 free(prop_enum, DRM_MEM_KMS); 2729 } 2730 2731 if (property->num_values) 2732 free(property->values, DRM_MEM_KMS); 2733 drm_mode_object_put(dev, &property->base); 2734 list_del(&property->head); 2735 free(property, DRM_MEM_KMS); 2736 } 2737 2738 int drm_connector_attach_property(struct drm_connector *connector, 2739 struct drm_property *property, uint64_t init_val) 2740 { 2741 int i; 2742 2743 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2744 if (connector->property_ids[i] == 0) { 2745 connector->property_ids[i] = property->base.id; 2746 connector->property_values[i] = init_val; 2747 break; 2748 } 2749 } 2750 2751 if (i == DRM_CONNECTOR_MAX_PROPERTY) 2752 return -EINVAL; 2753 return 0; 2754 } 2755 2756 int drm_connector_property_set_value(struct drm_connector *connector, 2757 struct drm_property *property, uint64_t value) 2758 { 2759 int i; 2760 2761 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2762 if (connector->property_ids[i] == property->base.id) { 2763 connector->property_values[i] = value; 2764 break; 2765 } 2766 } 2767 2768 if (i == DRM_CONNECTOR_MAX_PROPERTY) 2769 return -EINVAL; 2770 return 0; 2771 } 2772 2773 int drm_connector_property_get_value(struct drm_connector *connector, 2774 struct drm_property *property, uint64_t *val) 2775 { 2776 int i; 2777 2778 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 2779 if (connector->property_ids[i] == property->base.id) { 2780 *val = connector->property_values[i]; 2781 break; 2782 } 2783 } 2784 2785 if (i == DRM_CONNECTOR_MAX_PROPERTY) 2786 return -EINVAL; 2787 return 0; 2788 } 2789 2790 int drm_mode_getproperty_ioctl(struct drm_device *dev, 2791 void *data, struct drm_file *file_priv) 2792 { 2793 struct drm_mode_object *obj; 2794 struct drm_mode_get_property *out_resp = data; 2795 struct drm_property *property; 2796 int enum_count = 0; 2797 int blob_count = 0; 2798 int value_count = 0; 2799 int ret = 0, i; 2800 int copied; 2801 struct drm_property_enum *prop_enum; 2802 struct drm_mode_property_enum __user *enum_ptr; 2803 struct drm_property_blob *prop_blob; 2804 uint32_t *blob_id_ptr; 2805 uint64_t *values_ptr; 2806 uint32_t *blob_length_ptr; 2807 2808 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2809 return -EINVAL; 2810 2811 sx_xlock(&dev->mode_config.mutex); 2812 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 2813 if (!obj) { 2814 ret = -EINVAL; 2815 goto done; 2816 } 2817 property = obj_to_property(obj); 2818 2819 if (property->flags & DRM_MODE_PROP_ENUM) { 2820 list_for_each_entry(prop_enum, &property->enum_blob_list, head) 2821 enum_count++; 2822 } else if (property->flags & DRM_MODE_PROP_BLOB) { 2823 list_for_each_entry(prop_blob, &property->enum_blob_list, head) 2824 blob_count++; 2825 } 2826 2827 value_count = property->num_values; 2828 2829 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); 2830 out_resp->name[DRM_PROP_NAME_LEN-1] = 0; 2831 out_resp->flags = property->flags; 2832 2833 if ((out_resp->count_values >= value_count) && value_count) { 2834 values_ptr = (uint64_t *)(uintptr_t)out_resp->values_ptr; 2835 for (i = 0; i < value_count; i++) { 2836 if (copyout(&property->values[i], values_ptr + i, sizeof(uint64_t))) { 2837 ret = -EFAULT; 2838 goto done; 2839 } 2840 } 2841 } 2842 out_resp->count_values = value_count; 2843 2844 if (property->flags & DRM_MODE_PROP_ENUM) { 2845 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { 2846 copied = 0; 2847 enum_ptr = (struct drm_mode_property_enum *)(uintptr_t)out_resp->enum_blob_ptr; 2848 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2849 2850 if (copyout(&prop_enum->value, &enum_ptr[copied].value, sizeof(uint64_t))) { 2851 ret = -EFAULT; 2852 goto done; 2853 } 2854 2855 if (copyout(&prop_enum->name, 2856 &enum_ptr[copied].name,DRM_PROP_NAME_LEN)) { 2857 ret = -EFAULT; 2858 goto done; 2859 } 2860 copied++; 2861 } 2862 } 2863 out_resp->count_enum_blobs = enum_count; 2864 } 2865 2866 if (property->flags & DRM_MODE_PROP_BLOB) { 2867 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { 2868 copied = 0; 2869 blob_id_ptr = (uint32_t *)(uintptr_t)out_resp->enum_blob_ptr; 2870 blob_length_ptr = (uint32_t *)(uintptr_t)out_resp->values_ptr; 2871 2872 list_for_each_entry(prop_blob, &property->enum_blob_list, head) { 2873 if (copyout(&prop_blob->base.id, 2874 blob_id_ptr + copied, sizeof(uint32_t))) { 2875 ret = -EFAULT; 2876 goto done; 2877 } 2878 2879 if (copyout(&prop_blob->length, 2880 blob_length_ptr + copied, sizeof(uint32_t))) { 2881 ret = -EFAULT; 2882 goto done; 2883 } 2884 2885 copied++; 2886 } 2887 } 2888 out_resp->count_enum_blobs = blob_count; 2889 } 2890 done: 2891 sx_xunlock(&dev->mode_config.mutex); 2892 return ret; 2893 } 2894 2895 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, 2896 void *data) 2897 { 2898 struct drm_property_blob *blob; 2899 int ret; 2900 2901 if (!length || !data) 2902 return NULL; 2903 2904 blob = malloc(sizeof(struct drm_property_blob) + length, DRM_MEM_KMS, 2905 M_WAITOK | M_ZERO); 2906 2907 ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); 2908 if (ret) { 2909 free(blob, DRM_MEM_KMS); 2910 return (NULL); 2911 } 2912 2913 blob->length = length; 2914 2915 memcpy(blob->data, data, length); 2916 2917 list_add_tail(&blob->head, &dev->mode_config.property_blob_list); 2918 return blob; 2919 } 2920 2921 static void drm_property_destroy_blob(struct drm_device *dev, 2922 struct drm_property_blob *blob) 2923 { 2924 drm_mode_object_put(dev, &blob->base); 2925 list_del(&blob->head); 2926 free(blob, DRM_MEM_KMS); 2927 } 2928 2929 int drm_mode_getblob_ioctl(struct drm_device *dev, 2930 void *data, struct drm_file *file_priv) 2931 { 2932 struct drm_mode_object *obj; 2933 struct drm_mode_get_blob *out_resp = data; 2934 struct drm_property_blob *blob; 2935 int ret = 0; 2936 void *blob_ptr; 2937 2938 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2939 return -EINVAL; 2940 2941 sx_xlock(&dev->mode_config.mutex); 2942 obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); 2943 if (!obj) { 2944 ret = -EINVAL; 2945 goto done; 2946 } 2947 blob = obj_to_blob(obj); 2948 2949 if (out_resp->length == blob->length) { 2950 blob_ptr = (void *)(unsigned long)out_resp->data; 2951 if (copyout(blob->data, blob_ptr, blob->length)){ 2952 ret = -EFAULT; 2953 goto done; 2954 } 2955 } 2956 out_resp->length = blob->length; 2957 2958 done: 2959 sx_xunlock(&dev->mode_config.mutex); 2960 return ret; 2961 } 2962 2963 int drm_mode_connector_update_edid_property(struct drm_connector *connector, 2964 struct edid *edid) 2965 { 2966 struct drm_device *dev = connector->dev; 2967 int ret = 0, size; 2968 2969 if (connector->edid_blob_ptr) 2970 drm_property_destroy_blob(dev, connector->edid_blob_ptr); 2971 2972 /* Delete edid, when there is none. */ 2973 if (!edid) { 2974 connector->edid_blob_ptr = NULL; 2975 ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); 2976 return ret; 2977 } 2978 2979 size = EDID_LENGTH * (1 + edid->extensions); 2980 connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 2981 size, edid); 2982 2983 ret = drm_connector_property_set_value(connector, 2984 dev->mode_config.edid_property, 2985 connector->edid_blob_ptr->base.id); 2986 2987 return ret; 2988 } 2989 2990 int drm_mode_connector_property_set_ioctl(struct drm_device *dev, 2991 void *data, struct drm_file *file_priv) 2992 { 2993 struct drm_mode_connector_set_property *out_resp = data; 2994 struct drm_mode_object *obj; 2995 struct drm_property *property; 2996 struct drm_connector *connector; 2997 int ret = -EINVAL; 2998 int i; 2999 3000 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3001 return -EINVAL; 3002 3003 sx_xlock(&dev->mode_config.mutex); 3004 3005 obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); 3006 if (!obj) { 3007 goto out; 3008 } 3009 connector = obj_to_connector(obj); 3010 3011 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { 3012 if (connector->property_ids[i] == out_resp->prop_id) 3013 break; 3014 } 3015 3016 if (i == DRM_CONNECTOR_MAX_PROPERTY) { 3017 goto out; 3018 } 3019 3020 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 3021 if (!obj) { 3022 goto out; 3023 } 3024 property = obj_to_property(obj); 3025 3026 if (property->flags & DRM_MODE_PROP_IMMUTABLE) 3027 goto out; 3028 3029 if (property->flags & DRM_MODE_PROP_RANGE) { 3030 if (out_resp->value < property->values[0]) 3031 goto out; 3032 3033 if (out_resp->value > property->values[1]) 3034 goto out; 3035 } else { 3036 int found = 0; 3037 for (i = 0; i < property->num_values; i++) { 3038 if (property->values[i] == out_resp->value) { 3039 found = 1; 3040 break; 3041 } 3042 } 3043 if (!found) { 3044 goto out; 3045 } 3046 } 3047 3048 /* Do DPMS ourselves */ 3049 if (property == connector->dev->mode_config.dpms_property) { 3050 if (connector->funcs->dpms) 3051 (*connector->funcs->dpms)(connector, (int) out_resp->value); 3052 ret = 0; 3053 } else if (connector->funcs->set_property) 3054 ret = connector->funcs->set_property(connector, property, out_resp->value); 3055 3056 /* store the property value if successful */ 3057 if (!ret) 3058 drm_connector_property_set_value(connector, property, out_resp->value); 3059 out: 3060 sx_xunlock(&dev->mode_config.mutex); 3061 return ret; 3062 } 3063 3064 int drm_mode_connector_attach_encoder(struct drm_connector *connector, 3065 struct drm_encoder *encoder) 3066 { 3067 int i; 3068 3069 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3070 if (connector->encoder_ids[i] == 0) { 3071 connector->encoder_ids[i] = encoder->base.id; 3072 return 0; 3073 } 3074 } 3075 return -ENOMEM; 3076 } 3077 3078 void drm_mode_connector_detach_encoder(struct drm_connector *connector, 3079 struct drm_encoder *encoder) 3080 { 3081 int i; 3082 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3083 if (connector->encoder_ids[i] == encoder->base.id) { 3084 connector->encoder_ids[i] = 0; 3085 if (connector->encoder == encoder) 3086 connector->encoder = NULL; 3087 break; 3088 } 3089 } 3090 } 3091 3092 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 3093 int gamma_size) 3094 { 3095 crtc->gamma_size = gamma_size; 3096 3097 crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3, 3098 DRM_MEM_KMS, M_WAITOK | M_ZERO); 3099 3100 return 0; 3101 } 3102 3103 int drm_mode_gamma_set_ioctl(struct drm_device *dev, 3104 void *data, struct drm_file *file_priv) 3105 { 3106 struct drm_mode_crtc_lut *crtc_lut = data; 3107 struct drm_mode_object *obj; 3108 struct drm_crtc *crtc; 3109 void *r_base, *g_base, *b_base; 3110 int size; 3111 int ret = 0; 3112 3113 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3114 return -EINVAL; 3115 3116 sx_xlock(&dev->mode_config.mutex); 3117 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3118 if (!obj) { 3119 ret = -EINVAL; 3120 goto out; 3121 } 3122 crtc = obj_to_crtc(obj); 3123 3124 /* memcpy into gamma store */ 3125 if (crtc_lut->gamma_size != crtc->gamma_size) { 3126 ret = -EINVAL; 3127 goto out; 3128 } 3129 3130 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3131 r_base = crtc->gamma_store; 3132 if (copyin((void *)(uintptr_t)crtc_lut->red, r_base, size)) { 3133 ret = -EFAULT; 3134 goto out; 3135 } 3136 3137 g_base = (char *)r_base + size; 3138 if (copyin((void *)(uintptr_t)crtc_lut->green, g_base, size)) { 3139 ret = -EFAULT; 3140 goto out; 3141 } 3142 3143 b_base = (char *)g_base + size; 3144 if (copyin((void *)(uintptr_t)crtc_lut->blue, b_base, size)) { 3145 ret = -EFAULT; 3146 goto out; 3147 } 3148 3149 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); 3150 3151 out: 3152 sx_xunlock(&dev->mode_config.mutex); 3153 return ret; 3154 3155 } 3156 3157 int drm_mode_gamma_get_ioctl(struct drm_device *dev, 3158 void *data, struct drm_file *file_priv) 3159 { 3160 struct drm_mode_crtc_lut *crtc_lut = data; 3161 struct drm_mode_object *obj; 3162 struct drm_crtc *crtc; 3163 void *r_base, *g_base, *b_base; 3164 int size; 3165 int ret = 0; 3166 3167 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3168 return -EINVAL; 3169 3170 sx_xlock(&dev->mode_config.mutex); 3171 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3172 if (!obj) { 3173 ret = -EINVAL; 3174 goto out; 3175 } 3176 crtc = obj_to_crtc(obj); 3177 3178 /* memcpy into gamma store */ 3179 if (crtc_lut->gamma_size != crtc->gamma_size) { 3180 ret = -EINVAL; 3181 goto out; 3182 } 3183 3184 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3185 r_base = crtc->gamma_store; 3186 if (copyout(r_base, (void *)(uintptr_t)crtc_lut->red, size)) { 3187 ret = -EFAULT; 3188 goto out; 3189 } 3190 3191 g_base = (char *)r_base + size; 3192 if (copyout(g_base, (void *)(uintptr_t)crtc_lut->green, size)) { 3193 ret = -EFAULT; 3194 goto out; 3195 } 3196 3197 b_base = (char *)g_base + size; 3198 if (copyout(b_base, (void *)(uintptr_t)crtc_lut->blue, size)) { 3199 ret = -EFAULT; 3200 goto out; 3201 } 3202 out: 3203 sx_xunlock(&dev->mode_config.mutex); 3204 return ret; 3205 } 3206 3207 static void 3208 drm_kms_free(void *arg) 3209 { 3210 3211 free(arg, DRM_MEM_KMS); 3212 } 3213 3214 int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, 3215 struct drm_file *file_priv) 3216 { 3217 struct drm_mode_crtc_page_flip *page_flip = data; 3218 struct drm_mode_object *obj; 3219 struct drm_crtc *crtc; 3220 struct drm_framebuffer *fb; 3221 struct drm_pending_vblank_event *e = NULL; 3222 int ret = EINVAL; 3223 3224 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || 3225 page_flip->reserved != 0) 3226 return (EINVAL); 3227 3228 sx_xlock(&dev->mode_config.mutex); 3229 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); 3230 if (!obj) 3231 goto out; 3232 crtc = obj_to_crtc(obj); 3233 3234 if (crtc->fb == NULL) { 3235 /* The framebuffer is currently unbound, presumably 3236 * due to a hotplug event, that userspace has not 3237 * yet discovered. 3238 */ 3239 ret = EBUSY; 3240 goto out; 3241 } 3242 3243 if (crtc->funcs->page_flip == NULL) 3244 goto out; 3245 3246 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); 3247 if (!obj) 3248 goto out; 3249 fb = obj_to_fb(obj); 3250 3251 if (crtc->mode.hdisplay > fb->width || 3252 crtc->mode.vdisplay > fb->height || 3253 crtc->x > fb->width - crtc->mode.hdisplay || 3254 crtc->y > fb->height - crtc->mode.vdisplay) { 3255 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", 3256 fb->width, fb->height, 3257 crtc->mode.hdisplay, crtc->mode.vdisplay, 3258 crtc->x, crtc->y); 3259 ret = ENOSPC; 3260 goto out; 3261 } 3262 3263 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3264 ret = ENOMEM; 3265 mtx_lock(&dev->event_lock); 3266 if (file_priv->event_space < sizeof e->event) { 3267 mtx_unlock(&dev->event_lock); 3268 goto out; 3269 } 3270 file_priv->event_space -= sizeof e->event; 3271 mtx_unlock(&dev->event_lock); 3272 3273 e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO); 3274 3275 e->event.base.type = DRM_EVENT_FLIP_COMPLETE; 3276 e->event.base.length = sizeof e->event; 3277 e->event.user_data = page_flip->user_data; 3278 e->base.event = &e->event.base; 3279 e->base.file_priv = file_priv; 3280 e->base.destroy = 3281 (void (*) (struct drm_pending_event *))drm_kms_free; 3282 } 3283 3284 ret = -crtc->funcs->page_flip(crtc, fb, e); 3285 if (ret != 0) { 3286 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3287 mtx_lock(&dev->event_lock); 3288 file_priv->event_space += sizeof e->event; 3289 mtx_unlock(&dev->event_lock); 3290 free(e, DRM_MEM_KMS); 3291 } 3292 } 3293 3294 out: 3295 sx_xunlock(&dev->mode_config.mutex); 3296 CTR3(KTR_DRM, "page_flip_ioctl %d %d %d", curproc->p_pid, 3297 page_flip->crtc_id, ret); 3298 return (ret); 3299 } 3300 3301 void drm_mode_config_reset(struct drm_device *dev) 3302 { 3303 struct drm_crtc *crtc; 3304 struct drm_encoder *encoder; 3305 struct drm_connector *connector; 3306 3307 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 3308 if (crtc->funcs->reset) 3309 crtc->funcs->reset(crtc); 3310 3311 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 3312 if (encoder->funcs->reset) 3313 encoder->funcs->reset(encoder); 3314 3315 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 3316 if (connector->funcs->reset) 3317 connector->funcs->reset(connector); 3318 } 3319 3320 int drm_mode_create_dumb_ioctl(struct drm_device *dev, 3321 void *data, struct drm_file *file_priv) 3322 { 3323 struct drm_mode_create_dumb *args = data; 3324 3325 if (!dev->driver->dumb_create) 3326 return -ENOTSUP; 3327 return dev->driver->dumb_create(file_priv, dev, args); 3328 } 3329 3330 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, 3331 void *data, struct drm_file *file_priv) 3332 { 3333 struct drm_mode_map_dumb *args = data; 3334 3335 /* call driver ioctl to get mmap offset */ 3336 if (!dev->driver->dumb_map_offset) 3337 return -ENOTSUP; 3338 3339 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset); 3340 } 3341 3342 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, 3343 void *data, struct drm_file *file_priv) 3344 { 3345 struct drm_mode_destroy_dumb *args = data; 3346 3347 if (!dev->driver->dumb_destroy) 3348 return -ENOTSUP; 3349 3350 return dev->driver->dumb_destroy(file_priv, dev, args->handle); 3351 } 3352 3353 /* 3354 * Just need to support RGB formats here for compat with code that doesn't 3355 * use pixel formats directly yet. 3356 */ 3357 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, 3358 int *bpp) 3359 { 3360 switch (format) { 3361 case DRM_FORMAT_RGB332: 3362 case DRM_FORMAT_BGR233: 3363 *depth = 8; 3364 *bpp = 8; 3365 break; 3366 case DRM_FORMAT_XRGB1555: 3367 case DRM_FORMAT_XBGR1555: 3368 case DRM_FORMAT_RGBX5551: 3369 case DRM_FORMAT_BGRX5551: 3370 case DRM_FORMAT_ARGB1555: 3371 case DRM_FORMAT_ABGR1555: 3372 case DRM_FORMAT_RGBA5551: 3373 case DRM_FORMAT_BGRA5551: 3374 *depth = 15; 3375 *bpp = 16; 3376 break; 3377 case DRM_FORMAT_RGB565: 3378 case DRM_FORMAT_BGR565: 3379 *depth = 16; 3380 *bpp = 16; 3381 break; 3382 case DRM_FORMAT_RGB888: 3383 case DRM_FORMAT_BGR888: 3384 *depth = 24; 3385 *bpp = 24; 3386 break; 3387 case DRM_FORMAT_XRGB8888: 3388 case DRM_FORMAT_XBGR8888: 3389 case DRM_FORMAT_RGBX8888: 3390 case DRM_FORMAT_BGRX8888: 3391 *depth = 24; 3392 *bpp = 32; 3393 break; 3394 case DRM_FORMAT_XRGB2101010: 3395 case DRM_FORMAT_XBGR2101010: 3396 case DRM_FORMAT_RGBX1010102: 3397 case DRM_FORMAT_BGRX1010102: 3398 case DRM_FORMAT_ARGB2101010: 3399 case DRM_FORMAT_ABGR2101010: 3400 case DRM_FORMAT_RGBA1010102: 3401 case DRM_FORMAT_BGRA1010102: 3402 *depth = 30; 3403 *bpp = 32; 3404 break; 3405 case DRM_FORMAT_ARGB8888: 3406 case DRM_FORMAT_ABGR8888: 3407 case DRM_FORMAT_RGBA8888: 3408 case DRM_FORMAT_BGRA8888: 3409 *depth = 32; 3410 *bpp = 32; 3411 break; 3412 default: 3413 DRM_DEBUG_KMS("unsupported pixel format\n"); 3414 *depth = 0; 3415 *bpp = 0; 3416 break; 3417 } 3418 } 3419