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