1 /* 2 * Copyright (c) 2006-2008 Intel Corporation 3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 4 * 5 * DRM core CRTC related functions 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that copyright 10 * notice and this permission notice appear in supporting documentation, and 11 * that the name of the copyright holders not be used in advertising or 12 * publicity pertaining to distribution of the software without specific, 13 * written prior permission. The copyright holders make no representations 14 * about the suitability of this software for any purpose. It is provided "as 15 * is" without express or implied warranty. 16 * 17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 23 * OF THIS SOFTWARE. 24 * 25 * Authors: 26 * Keith Packard 27 * Eric Anholt <eric@anholt.net> 28 * Dave Airlie <airlied@linux.ie> 29 * Jesse Barnes <jesse.barnes@intel.com> 30 */ 31 32 #include <linux/kernel.h> 33 #include <linux/export.h> 34 #include <linux/moduleparam.h> 35 36 #include <drm/drmP.h> 37 #include <drm/drm_crtc.h> 38 #include <drm/drm_fourcc.h> 39 #include <drm/drm_crtc_helper.h> 40 #include <drm/drm_fb_helper.h> 41 #include <drm/drm_edid.h> 42 43 MODULE_AUTHOR("David Airlie, Jesse Barnes"); 44 MODULE_DESCRIPTION("DRM KMS helper"); 45 MODULE_LICENSE("GPL and additional rights"); 46 47 /** 48 * drm_helper_move_panel_connectors_to_head() - move panels to the front in the 49 * connector list 50 * @dev: drm device to operate on 51 * 52 * Some userspace presumes that the first connected connector is the main 53 * display, where it's supposed to display e.g. the login screen. For 54 * laptops, this should be the main panel. Use this function to sort all 55 * (eDP/LVDS) panels to the front of the connector list, instead of 56 * painstakingly trying to initialize them in the right order. 57 */ 58 void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) 59 { 60 struct drm_connector *connector, *tmp; 61 struct list_head panel_list; 62 63 INIT_LIST_HEAD(&panel_list); 64 65 list_for_each_entry_safe(connector, tmp, 66 &dev->mode_config.connector_list, head) { 67 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || 68 connector->connector_type == DRM_MODE_CONNECTOR_eDP) 69 list_move_tail(&connector->head, &panel_list); 70 } 71 72 list_splice(&panel_list, &dev->mode_config.connector_list); 73 } 74 EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); 75 76 /** 77 * drm_helper_encoder_in_use - check if a given encoder is in use 78 * @encoder: encoder to check 79 * 80 * Checks whether @encoder is with the current mode setting output configuration 81 * in use by any connector. This doesn't mean that it is actually enabled since 82 * the DPMS state is tracked separately. 83 * 84 * Returns: 85 * True if @encoder is used, false otherwise. 86 */ 87 bool drm_helper_encoder_in_use(struct drm_encoder *encoder) 88 { 89 struct drm_connector *connector; 90 struct drm_device *dev = encoder->dev; 91 92 /* 93 * We can expect this mutex to be locked if we are not panicking. 94 * Locking is currently fubar in the panic handler. 95 */ 96 if (!oops_in_progress) { 97 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 98 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); 99 } 100 101 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 102 if (connector->encoder == encoder) 103 return true; 104 return false; 105 } 106 EXPORT_SYMBOL(drm_helper_encoder_in_use); 107 108 /** 109 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config 110 * @crtc: CRTC to check 111 * 112 * Checks whether @crtc is with the current mode setting output configuration 113 * in use by any connector. This doesn't mean that it is actually enabled since 114 * the DPMS state is tracked separately. 115 * 116 * Returns: 117 * True if @crtc is used, false otherwise. 118 */ 119 bool drm_helper_crtc_in_use(struct drm_crtc *crtc) 120 { 121 struct drm_encoder *encoder; 122 struct drm_device *dev = crtc->dev; 123 124 /* 125 * We can expect this mutex to be locked if we are not panicking. 126 * Locking is currently fubar in the panic handler. 127 */ 128 if (!oops_in_progress) 129 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 130 131 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 132 if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) 133 return true; 134 return false; 135 } 136 EXPORT_SYMBOL(drm_helper_crtc_in_use); 137 138 static void 139 drm_encoder_disable(struct drm_encoder *encoder) 140 { 141 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; 142 143 if (encoder->bridge) 144 encoder->bridge->funcs->disable(encoder->bridge); 145 146 if (encoder_funcs->disable) 147 (*encoder_funcs->disable)(encoder); 148 else 149 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); 150 151 if (encoder->bridge) 152 encoder->bridge->funcs->post_disable(encoder->bridge); 153 } 154 155 static void __drm_helper_disable_unused_functions(struct drm_device *dev) 156 { 157 struct drm_encoder *encoder; 158 struct drm_crtc *crtc; 159 160 drm_warn_on_modeset_not_all_locked(dev); 161 162 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 163 if (!drm_helper_encoder_in_use(encoder)) { 164 drm_encoder_disable(encoder); 165 /* disconnect encoder from any connector */ 166 encoder->crtc = NULL; 167 } 168 } 169 170 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 171 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 172 crtc->enabled = drm_helper_crtc_in_use(crtc); 173 if (!crtc->enabled) { 174 if (crtc_funcs->disable) 175 (*crtc_funcs->disable)(crtc); 176 else 177 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); 178 crtc->primary->fb = NULL; 179 } 180 } 181 } 182 183 /** 184 * drm_helper_disable_unused_functions - disable unused objects 185 * @dev: DRM device 186 * 187 * This function walks through the entire mode setting configuration of @dev. It 188 * will remove any crtc links of unused encoders and encoder links of 189 * disconnected connectors. Then it will disable all unused encoders and crtcs 190 * either by calling their disable callback if available or by calling their 191 * dpms callback with DRM_MODE_DPMS_OFF. 192 */ 193 void drm_helper_disable_unused_functions(struct drm_device *dev) 194 { 195 drm_modeset_lock_all(dev); 196 __drm_helper_disable_unused_functions(dev); 197 drm_modeset_unlock_all(dev); 198 } 199 EXPORT_SYMBOL(drm_helper_disable_unused_functions); 200 201 /* 202 * Check the CRTC we're going to map each output to vs. its current 203 * CRTC. If they don't match, we have to disable the output and the CRTC 204 * since the driver will have to re-route things. 205 */ 206 static void 207 drm_crtc_prepare_encoders(struct drm_device *dev) 208 { 209 struct drm_encoder_helper_funcs *encoder_funcs; 210 struct drm_encoder *encoder; 211 212 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 213 encoder_funcs = encoder->helper_private; 214 /* Disable unused encoders */ 215 if (encoder->crtc == NULL) 216 drm_encoder_disable(encoder); 217 /* Disable encoders whose CRTC is about to change */ 218 if (encoder_funcs->get_crtc && 219 encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) 220 drm_encoder_disable(encoder); 221 } 222 } 223 224 /** 225 * drm_crtc_helper_set_mode - internal helper to set a mode 226 * @crtc: CRTC to program 227 * @mode: mode to use 228 * @x: horizontal offset into the surface 229 * @y: vertical offset into the surface 230 * @old_fb: old framebuffer, for cleanup 231 * 232 * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance 233 * to fixup or reject the mode prior to trying to set it. This is an internal 234 * helper that drivers could e.g. use to update properties that require the 235 * entire output pipe to be disabled and re-enabled in a new configuration. For 236 * example for changing whether audio is enabled on a hdmi link or for changing 237 * panel fitter or dither attributes. It is also called by the 238 * drm_crtc_helper_set_config() helper function to drive the mode setting 239 * sequence. 240 * 241 * Returns: 242 * True if the mode was set successfully, false otherwise. 243 */ 244 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 245 struct drm_display_mode *mode, 246 int x, int y, 247 struct drm_framebuffer *old_fb) 248 { 249 struct drm_device *dev = crtc->dev; 250 struct drm_display_mode *adjusted_mode, saved_mode; 251 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 252 struct drm_encoder_helper_funcs *encoder_funcs; 253 int saved_x, saved_y; 254 bool saved_enabled; 255 struct drm_encoder *encoder; 256 bool ret = true; 257 258 drm_warn_on_modeset_not_all_locked(dev); 259 260 saved_enabled = crtc->enabled; 261 crtc->enabled = drm_helper_crtc_in_use(crtc); 262 if (!crtc->enabled) 263 return true; 264 265 adjusted_mode = drm_mode_duplicate(dev, mode); 266 if (!adjusted_mode) { 267 crtc->enabled = saved_enabled; 268 return false; 269 } 270 271 saved_mode = crtc->mode; 272 saved_x = crtc->x; 273 saved_y = crtc->y; 274 275 /* Update crtc values up front so the driver can rely on them for mode 276 * setting. 277 */ 278 crtc->mode = *mode; 279 crtc->x = x; 280 crtc->y = y; 281 282 /* Pass our mode to the connectors and the CRTC to give them a chance to 283 * adjust it according to limitations or connector properties, and also 284 * a chance to reject the mode entirely. 285 */ 286 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 287 288 if (encoder->crtc != crtc) 289 continue; 290 291 if (encoder->bridge && encoder->bridge->funcs->mode_fixup) { 292 ret = encoder->bridge->funcs->mode_fixup( 293 encoder->bridge, mode, adjusted_mode); 294 if (!ret) { 295 DRM_DEBUG_KMS("Bridge fixup failed\n"); 296 goto done; 297 } 298 } 299 300 encoder_funcs = encoder->helper_private; 301 if (!(ret = encoder_funcs->mode_fixup(encoder, mode, 302 adjusted_mode))) { 303 DRM_DEBUG_KMS("Encoder fixup failed\n"); 304 goto done; 305 } 306 } 307 308 if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { 309 DRM_DEBUG_KMS("CRTC fixup failed\n"); 310 goto done; 311 } 312 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 313 314 /* Prepare the encoders and CRTCs before setting the mode. */ 315 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 316 317 if (encoder->crtc != crtc) 318 continue; 319 320 if (encoder->bridge) 321 encoder->bridge->funcs->disable(encoder->bridge); 322 323 encoder_funcs = encoder->helper_private; 324 /* Disable the encoders as the first thing we do. */ 325 encoder_funcs->prepare(encoder); 326 327 if (encoder->bridge) 328 encoder->bridge->funcs->post_disable(encoder->bridge); 329 } 330 331 drm_crtc_prepare_encoders(dev); 332 333 crtc_funcs->prepare(crtc); 334 335 /* Set up the DPLL and any encoders state that needs to adjust or depend 336 * on the DPLL. 337 */ 338 ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); 339 if (!ret) 340 goto done; 341 342 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 343 344 if (encoder->crtc != crtc) 345 continue; 346 347 DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", 348 encoder->base.id, encoder->name, 349 mode->base.id, mode->name); 350 encoder_funcs = encoder->helper_private; 351 encoder_funcs->mode_set(encoder, mode, adjusted_mode); 352 353 if (encoder->bridge && encoder->bridge->funcs->mode_set) 354 encoder->bridge->funcs->mode_set(encoder->bridge, mode, 355 adjusted_mode); 356 } 357 358 /* Now enable the clocks, plane, pipe, and connectors that we set up. */ 359 crtc_funcs->commit(crtc); 360 361 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 362 363 if (encoder->crtc != crtc) 364 continue; 365 366 if (encoder->bridge) 367 encoder->bridge->funcs->pre_enable(encoder->bridge); 368 369 encoder_funcs = encoder->helper_private; 370 encoder_funcs->commit(encoder); 371 372 if (encoder->bridge) 373 encoder->bridge->funcs->enable(encoder->bridge); 374 } 375 376 /* Store real post-adjustment hardware mode. */ 377 crtc->hwmode = *adjusted_mode; 378 379 /* Calculate and store various constants which 380 * are later needed by vblank and swap-completion 381 * timestamping. They are derived from true hwmode. 382 */ 383 drm_calc_timestamping_constants(crtc, &crtc->hwmode); 384 385 /* FIXME: add subpixel order */ 386 done: 387 drm_mode_destroy(dev, adjusted_mode); 388 if (!ret) { 389 crtc->enabled = saved_enabled; 390 crtc->mode = saved_mode; 391 crtc->x = saved_x; 392 crtc->y = saved_y; 393 } 394 395 return ret; 396 } 397 EXPORT_SYMBOL(drm_crtc_helper_set_mode); 398 399 static void 400 drm_crtc_helper_disable(struct drm_crtc *crtc) 401 { 402 struct drm_device *dev = crtc->dev; 403 struct drm_connector *connector; 404 struct drm_encoder *encoder; 405 406 /* Decouple all encoders and their attached connectors from this crtc */ 407 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 408 if (encoder->crtc != crtc) 409 continue; 410 411 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 412 if (connector->encoder != encoder) 413 continue; 414 415 connector->encoder = NULL; 416 417 /* 418 * drm_helper_disable_unused_functions() ought to be 419 * doing this, but since we've decoupled the encoder 420 * from the connector above, the required connection 421 * between them is henceforth no longer available. 422 */ 423 connector->dpms = DRM_MODE_DPMS_OFF; 424 } 425 } 426 427 __drm_helper_disable_unused_functions(dev); 428 } 429 430 /** 431 * drm_crtc_helper_set_config - set a new config from userspace 432 * @set: mode set configuration 433 * 434 * Setup a new configuration, provided by the upper layers (either an ioctl call 435 * from userspace or internally e.g. from the fbdev support code) in @set, and 436 * enable it. This is the main helper functions for drivers that implement 437 * kernel mode setting with the crtc helper functions and the assorted 438 * ->prepare(), ->modeset() and ->commit() helper callbacks. 439 * 440 * Returns: 441 * Returns 0 on success, negative errno numbers on failure. 442 */ 443 int drm_crtc_helper_set_config(struct drm_mode_set *set) 444 { 445 struct drm_device *dev; 446 struct drm_crtc *new_crtc; 447 struct drm_encoder *save_encoders, *new_encoder, *encoder; 448 bool mode_changed = false; /* if true do a full mode set */ 449 bool fb_changed = false; /* if true and !mode_changed just do a flip */ 450 struct drm_connector *save_connectors, *connector; 451 int count = 0, ro, fail = 0; 452 struct drm_crtc_helper_funcs *crtc_funcs; 453 struct drm_mode_set save_set; 454 int ret; 455 int i; 456 457 DRM_DEBUG_KMS("\n"); 458 459 BUG_ON(!set); 460 BUG_ON(!set->crtc); 461 BUG_ON(!set->crtc->helper_private); 462 463 /* Enforce sane interface api - has been abused by the fb helper. */ 464 BUG_ON(!set->mode && set->fb); 465 BUG_ON(set->fb && set->num_connectors == 0); 466 467 crtc_funcs = set->crtc->helper_private; 468 469 if (!set->mode) 470 set->fb = NULL; 471 472 if (set->fb) { 473 DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", 474 set->crtc->base.id, set->fb->base.id, 475 (int)set->num_connectors, set->x, set->y); 476 } else { 477 DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); 478 drm_crtc_helper_disable(set->crtc); 479 return 0; 480 } 481 482 dev = set->crtc->dev; 483 484 drm_warn_on_modeset_not_all_locked(dev); 485 486 /* 487 * Allocate space for the backup of all (non-pointer) encoder and 488 * connector data. 489 */ 490 save_encoders = kzalloc(dev->mode_config.num_encoder * 491 sizeof(struct drm_encoder), GFP_KERNEL); 492 if (!save_encoders) 493 return -ENOMEM; 494 495 save_connectors = kzalloc(dev->mode_config.num_connector * 496 sizeof(struct drm_connector), GFP_KERNEL); 497 if (!save_connectors) { 498 kfree(save_encoders); 499 return -ENOMEM; 500 } 501 502 /* 503 * Copy data. Note that driver private data is not affected. 504 * Should anything bad happen only the expected state is 505 * restored, not the drivers personal bookkeeping. 506 */ 507 count = 0; 508 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 509 save_encoders[count++] = *encoder; 510 } 511 512 count = 0; 513 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 514 save_connectors[count++] = *connector; 515 } 516 517 save_set.crtc = set->crtc; 518 save_set.mode = &set->crtc->mode; 519 save_set.x = set->crtc->x; 520 save_set.y = set->crtc->y; 521 save_set.fb = set->crtc->primary->fb; 522 523 /* We should be able to check here if the fb has the same properties 524 * and then just flip_or_move it */ 525 if (set->crtc->primary->fb != set->fb) { 526 /* If we have no fb then treat it as a full mode set */ 527 if (set->crtc->primary->fb == NULL) { 528 DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); 529 mode_changed = true; 530 } else if (set->fb == NULL) { 531 mode_changed = true; 532 } else if (set->fb->pixel_format != 533 set->crtc->primary->fb->pixel_format) { 534 mode_changed = true; 535 } else 536 fb_changed = true; 537 } 538 539 if (set->x != set->crtc->x || set->y != set->crtc->y) 540 fb_changed = true; 541 542 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { 543 DRM_DEBUG_KMS("modes are different, full mode set\n"); 544 drm_mode_debug_printmodeline(&set->crtc->mode); 545 drm_mode_debug_printmodeline(set->mode); 546 mode_changed = true; 547 } 548 549 /* a) traverse passed in connector list and get encoders for them */ 550 count = 0; 551 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 552 struct drm_connector_helper_funcs *connector_funcs = 553 connector->helper_private; 554 new_encoder = connector->encoder; 555 for (ro = 0; ro < set->num_connectors; ro++) { 556 if (set->connectors[ro] == connector) { 557 new_encoder = connector_funcs->best_encoder(connector); 558 /* if we can't get an encoder for a connector 559 we are setting now - then fail */ 560 if (new_encoder == NULL) 561 /* don't break so fail path works correct */ 562 fail = 1; 563 564 if (connector->dpms != DRM_MODE_DPMS_ON) { 565 DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); 566 mode_changed = true; 567 } 568 569 break; 570 } 571 } 572 573 if (new_encoder != connector->encoder) { 574 DRM_DEBUG_KMS("encoder changed, full mode switch\n"); 575 mode_changed = true; 576 /* If the encoder is reused for another connector, then 577 * the appropriate crtc will be set later. 578 */ 579 if (connector->encoder) 580 connector->encoder->crtc = NULL; 581 connector->encoder = new_encoder; 582 } 583 } 584 585 if (fail) { 586 ret = -EINVAL; 587 goto fail; 588 } 589 590 count = 0; 591 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 592 if (!connector->encoder) 593 continue; 594 595 if (connector->encoder->crtc == set->crtc) 596 new_crtc = NULL; 597 else 598 new_crtc = connector->encoder->crtc; 599 600 for (ro = 0; ro < set->num_connectors; ro++) { 601 if (set->connectors[ro] == connector) 602 new_crtc = set->crtc; 603 } 604 605 /* Make sure the new CRTC will work with the encoder */ 606 if (new_crtc && 607 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { 608 ret = -EINVAL; 609 goto fail; 610 } 611 if (new_crtc != connector->encoder->crtc) { 612 DRM_DEBUG_KMS("crtc changed, full mode switch\n"); 613 mode_changed = true; 614 connector->encoder->crtc = new_crtc; 615 } 616 if (new_crtc) { 617 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n", 618 connector->base.id, connector->name, 619 new_crtc->base.id); 620 } else { 621 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n", 622 connector->base.id, connector->name); 623 } 624 } 625 626 /* mode_set_base is not a required function */ 627 if (fb_changed && !crtc_funcs->mode_set_base) 628 mode_changed = true; 629 630 if (mode_changed) { 631 if (drm_helper_crtc_in_use(set->crtc)) { 632 DRM_DEBUG_KMS("attempting to set mode from" 633 " userspace\n"); 634 drm_mode_debug_printmodeline(set->mode); 635 set->crtc->primary->fb = set->fb; 636 if (!drm_crtc_helper_set_mode(set->crtc, set->mode, 637 set->x, set->y, 638 save_set.fb)) { 639 DRM_ERROR("failed to set mode on [CRTC:%d]\n", 640 set->crtc->base.id); 641 set->crtc->primary->fb = save_set.fb; 642 ret = -EINVAL; 643 goto fail; 644 } 645 DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); 646 for (i = 0; i < set->num_connectors; i++) { 647 DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, 648 set->connectors[i]->name); 649 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); 650 } 651 } 652 __drm_helper_disable_unused_functions(dev); 653 } else if (fb_changed) { 654 set->crtc->x = set->x; 655 set->crtc->y = set->y; 656 set->crtc->primary->fb = set->fb; 657 ret = crtc_funcs->mode_set_base(set->crtc, 658 set->x, set->y, save_set.fb); 659 if (ret != 0) { 660 set->crtc->x = save_set.x; 661 set->crtc->y = save_set.y; 662 set->crtc->primary->fb = save_set.fb; 663 goto fail; 664 } 665 } 666 667 kfree(save_connectors); 668 kfree(save_encoders); 669 return 0; 670 671 fail: 672 /* Restore all previous data. */ 673 count = 0; 674 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 675 *encoder = save_encoders[count++]; 676 } 677 678 count = 0; 679 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 680 *connector = save_connectors[count++]; 681 } 682 683 /* Try to restore the config */ 684 if (mode_changed && 685 !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x, 686 save_set.y, save_set.fb)) 687 DRM_ERROR("failed to restore config after modeset failure\n"); 688 689 kfree(save_connectors); 690 kfree(save_encoders); 691 return ret; 692 } 693 EXPORT_SYMBOL(drm_crtc_helper_set_config); 694 695 static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) 696 { 697 int dpms = DRM_MODE_DPMS_OFF; 698 struct drm_connector *connector; 699 struct drm_device *dev = encoder->dev; 700 701 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 702 if (connector->encoder == encoder) 703 if (connector->dpms < dpms) 704 dpms = connector->dpms; 705 return dpms; 706 } 707 708 /* Helper which handles bridge ordering around encoder dpms */ 709 static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) 710 { 711 struct drm_bridge *bridge = encoder->bridge; 712 struct drm_encoder_helper_funcs *encoder_funcs; 713 714 if (bridge) { 715 if (mode == DRM_MODE_DPMS_ON) 716 bridge->funcs->pre_enable(bridge); 717 else 718 bridge->funcs->disable(bridge); 719 } 720 721 encoder_funcs = encoder->helper_private; 722 if (encoder_funcs->dpms) 723 encoder_funcs->dpms(encoder, mode); 724 725 if (bridge) { 726 if (mode == DRM_MODE_DPMS_ON) 727 bridge->funcs->enable(bridge); 728 else 729 bridge->funcs->post_disable(bridge); 730 } 731 } 732 733 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) 734 { 735 int dpms = DRM_MODE_DPMS_OFF; 736 struct drm_connector *connector; 737 struct drm_device *dev = crtc->dev; 738 739 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 740 if (connector->encoder && connector->encoder->crtc == crtc) 741 if (connector->dpms < dpms) 742 dpms = connector->dpms; 743 return dpms; 744 } 745 746 /** 747 * drm_helper_connector_dpms() - connector dpms helper implementation 748 * @connector: affected connector 749 * @mode: DPMS mode 750 * 751 * This is the main helper function provided by the crtc helper framework for 752 * implementing the DPMS connector attribute. It computes the new desired DPMS 753 * state for all encoders and crtcs in the output mesh and calls the ->dpms() 754 * callback provided by the driver appropriately. 755 */ 756 void drm_helper_connector_dpms(struct drm_connector *connector, int mode) 757 { 758 struct drm_encoder *encoder = connector->encoder; 759 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; 760 int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; 761 762 if (mode == connector->dpms) 763 return; 764 765 old_dpms = connector->dpms; 766 connector->dpms = mode; 767 768 if (encoder) 769 encoder_dpms = drm_helper_choose_encoder_dpms(encoder); 770 771 /* from off to on, do crtc then encoder */ 772 if (mode < old_dpms) { 773 if (crtc) { 774 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 775 if (crtc_funcs->dpms) 776 (*crtc_funcs->dpms) (crtc, 777 drm_helper_choose_crtc_dpms(crtc)); 778 } 779 if (encoder) 780 drm_helper_encoder_dpms(encoder, encoder_dpms); 781 } 782 783 /* from on to off, do encoder then crtc */ 784 if (mode > old_dpms) { 785 if (encoder) 786 drm_helper_encoder_dpms(encoder, encoder_dpms); 787 if (crtc) { 788 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 789 if (crtc_funcs->dpms) 790 (*crtc_funcs->dpms) (crtc, 791 drm_helper_choose_crtc_dpms(crtc)); 792 } 793 } 794 795 return; 796 } 797 EXPORT_SYMBOL(drm_helper_connector_dpms); 798 799 /** 800 * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata 801 * @fb: drm_framebuffer object to fill out 802 * @mode_cmd: metadata from the userspace fb creation request 803 * 804 * This helper can be used in a drivers fb_create callback to pre-fill the fb's 805 * metadata fields. 806 */ 807 void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, 808 struct drm_mode_fb_cmd2 *mode_cmd) 809 { 810 int i; 811 812 fb->width = mode_cmd->width; 813 fb->height = mode_cmd->height; 814 for (i = 0; i < 4; i++) { 815 fb->pitches[i] = mode_cmd->pitches[i]; 816 fb->offsets[i] = mode_cmd->offsets[i]; 817 } 818 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, 819 &fb->bits_per_pixel); 820 fb->pixel_format = mode_cmd->pixel_format; 821 } 822 EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); 823 824 /** 825 * drm_helper_resume_force_mode - force-restore mode setting configuration 826 * @dev: drm_device which should be restored 827 * 828 * Drivers which use the mode setting helpers can use this function to 829 * force-restore the mode setting configuration e.g. on resume or when something 830 * else might have trampled over the hw state (like some overzealous old BIOSen 831 * tended to do). 832 * 833 * This helper doesn't provide a error return value since restoring the old 834 * config should never fail due to resource allocation issues since the driver 835 * has successfully set the restored configuration already. Hence this should 836 * boil down to the equivalent of a few dpms on calls, which also don't provide 837 * an error code. 838 * 839 * Drivers where simply restoring an old configuration again might fail (e.g. 840 * due to slight differences in allocating shared resources when the 841 * configuration is restored in a different order than when userspace set it up) 842 * need to use their own restore logic. 843 */ 844 void drm_helper_resume_force_mode(struct drm_device *dev) 845 { 846 struct drm_crtc *crtc; 847 struct drm_encoder *encoder; 848 struct drm_crtc_helper_funcs *crtc_funcs; 849 int encoder_dpms; 850 bool ret; 851 852 drm_modeset_lock_all(dev); 853 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 854 855 if (!crtc->enabled) 856 continue; 857 858 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, 859 crtc->x, crtc->y, crtc->primary->fb); 860 861 /* Restoring the old config should never fail! */ 862 if (ret == false) 863 DRM_ERROR("failed to set mode on crtc %p\n", crtc); 864 865 /* Turn off outputs that were already powered off */ 866 if (drm_helper_choose_crtc_dpms(crtc)) { 867 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 868 869 if(encoder->crtc != crtc) 870 continue; 871 872 encoder_dpms = drm_helper_choose_encoder_dpms( 873 encoder); 874 875 drm_helper_encoder_dpms(encoder, encoder_dpms); 876 } 877 878 crtc_funcs = crtc->helper_private; 879 if (crtc_funcs->dpms) 880 (*crtc_funcs->dpms) (crtc, 881 drm_helper_choose_crtc_dpms(crtc)); 882 } 883 } 884 885 /* disable the unused connectors while restoring the modesetting */ 886 __drm_helper_disable_unused_functions(dev); 887 drm_modeset_unlock_all(dev); 888 } 889 EXPORT_SYMBOL(drm_helper_resume_force_mode); 890