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