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