Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at beda2c7ea2c15ed01eef00a997d2b0496c3a502d 1099 lines 30 kB view raw
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 "drmP.h" 33#include "drm_crtc.h" 34#include "drm_crtc_helper.h" 35 36/* 37 * Detailed mode info for 800x600@60Hz 38 */ 39static struct drm_display_mode std_modes[] = { 40 { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840, 41 968, 1056, 0, 600, 601, 605, 628, 0, 42 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 43}; 44 45static void drm_mode_validate_flag(struct drm_connector *connector, 46 int flags) 47{ 48 struct drm_display_mode *mode, *t; 49 50 if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) 51 return; 52 53 list_for_each_entry_safe(mode, t, &connector->modes, head) { 54 if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && 55 !(flags & DRM_MODE_FLAG_INTERLACE)) 56 mode->status = MODE_NO_INTERLACE; 57 if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && 58 !(flags & DRM_MODE_FLAG_DBLSCAN)) 59 mode->status = MODE_NO_DBLESCAN; 60 } 61 62 return; 63} 64 65/** 66 * drm_helper_probe_connector_modes - get complete set of display modes 67 * @dev: DRM device 68 * @maxX: max width for modes 69 * @maxY: max height for modes 70 * 71 * LOCKING: 72 * Caller must hold mode config lock. 73 * 74 * Based on @dev's mode_config layout, scan all the connectors and try to detect 75 * modes on them. Modes will first be added to the connector's probed_modes 76 * list, then culled (based on validity and the @maxX, @maxY parameters) and 77 * put into the normal modes list. 78 * 79 * Intended to be used either at bootup time or when major configuration 80 * changes have occurred. 81 * 82 * FIXME: take into account monitor limits 83 * 84 * RETURNS: 85 * Number of modes found on @connector. 86 */ 87int drm_helper_probe_single_connector_modes(struct drm_connector *connector, 88 uint32_t maxX, uint32_t maxY) 89{ 90 struct drm_device *dev = connector->dev; 91 struct drm_display_mode *mode, *t; 92 struct drm_connector_helper_funcs *connector_funcs = 93 connector->helper_private; 94 int count = 0; 95 int mode_flags = 0; 96 97 DRM_DEBUG("%s\n", drm_get_connector_name(connector)); 98 /* set all modes to the unverified state */ 99 list_for_each_entry_safe(mode, t, &connector->modes, head) 100 mode->status = MODE_UNVERIFIED; 101 102 connector->status = connector->funcs->detect(connector); 103 104 if (connector->status == connector_status_disconnected) { 105 DRM_DEBUG("%s is disconnected\n", 106 drm_get_connector_name(connector)); 107 /* TODO set EDID to NULL */ 108 return 0; 109 } 110 111 count = (*connector_funcs->get_modes)(connector); 112 if (!count) 113 return 0; 114 115 drm_mode_connector_list_update(connector); 116 117 if (maxX && maxY) 118 drm_mode_validate_size(dev, &connector->modes, maxX, 119 maxY, 0); 120 121 if (connector->interlace_allowed) 122 mode_flags |= DRM_MODE_FLAG_INTERLACE; 123 if (connector->doublescan_allowed) 124 mode_flags |= DRM_MODE_FLAG_DBLSCAN; 125 drm_mode_validate_flag(connector, mode_flags); 126 127 list_for_each_entry_safe(mode, t, &connector->modes, head) { 128 if (mode->status == MODE_OK) 129 mode->status = connector_funcs->mode_valid(connector, 130 mode); 131 } 132 133 134 drm_mode_prune_invalid(dev, &connector->modes, true); 135 136 if (list_empty(&connector->modes)) 137 return 0; 138 139 drm_mode_sort(&connector->modes); 140 141 DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector)); 142 list_for_each_entry_safe(mode, t, &connector->modes, head) { 143 mode->vrefresh = drm_mode_vrefresh(mode); 144 145 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 146 drm_mode_debug_printmodeline(mode); 147 } 148 149 return count; 150} 151EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); 152 153int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, 154 uint32_t maxY) 155{ 156 struct drm_connector *connector; 157 int count = 0; 158 159 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 160 count += drm_helper_probe_single_connector_modes(connector, 161 maxX, maxY); 162 } 163 164 return count; 165} 166EXPORT_SYMBOL(drm_helper_probe_connector_modes); 167 168static void drm_helper_add_std_modes(struct drm_device *dev, 169 struct drm_connector *connector) 170{ 171 struct drm_display_mode *mode, *t; 172 int i; 173 174 for (i = 0; i < ARRAY_SIZE(std_modes); i++) { 175 struct drm_display_mode *stdmode; 176 177 /* 178 * When no valid EDID modes are available we end up 179 * here and bailed in the past, now we add some standard 180 * modes and move on. 181 */ 182 stdmode = drm_mode_duplicate(dev, &std_modes[i]); 183 drm_mode_probed_add(connector, stdmode); 184 drm_mode_list_concat(&connector->probed_modes, 185 &connector->modes); 186 187 DRM_DEBUG("Adding mode %s to %s\n", stdmode->name, 188 drm_get_connector_name(connector)); 189 } 190 drm_mode_sort(&connector->modes); 191 192 DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector)); 193 list_for_each_entry_safe(mode, t, &connector->modes, head) { 194 mode->vrefresh = drm_mode_vrefresh(mode); 195 196 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 197 drm_mode_debug_printmodeline(mode); 198 } 199} 200 201/** 202 * drm_helper_encoder_in_use - check if a given encoder is in use 203 * @encoder: encoder to check 204 * 205 * LOCKING: 206 * Caller must hold mode config lock. 207 * 208 * Walk @encoders's DRM device's mode_config and see if it's in use. 209 * 210 * RETURNS: 211 * True if @encoder is part of the mode_config, false otherwise. 212 */ 213bool drm_helper_encoder_in_use(struct drm_encoder *encoder) 214{ 215 struct drm_connector *connector; 216 struct drm_device *dev = encoder->dev; 217 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 218 if (connector->encoder == encoder) 219 return true; 220 return false; 221} 222EXPORT_SYMBOL(drm_helper_encoder_in_use); 223 224/** 225 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config 226 * @crtc: CRTC to check 227 * 228 * LOCKING: 229 * Caller must hold mode config lock. 230 * 231 * Walk @crtc's DRM device's mode_config and see if it's in use. 232 * 233 * RETURNS: 234 * True if @crtc is part of the mode_config, false otherwise. 235 */ 236bool drm_helper_crtc_in_use(struct drm_crtc *crtc) 237{ 238 struct drm_encoder *encoder; 239 struct drm_device *dev = crtc->dev; 240 /* FIXME: Locking around list access? */ 241 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 242 if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) 243 return true; 244 return false; 245} 246EXPORT_SYMBOL(drm_helper_crtc_in_use); 247 248/** 249 * drm_disable_unused_functions - disable unused objects 250 * @dev: DRM device 251 * 252 * LOCKING: 253 * Caller must hold mode config lock. 254 * 255 * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled 256 * by calling its dpms function, which should power it off. 257 */ 258void drm_helper_disable_unused_functions(struct drm_device *dev) 259{ 260 struct drm_encoder *encoder; 261 struct drm_encoder_helper_funcs *encoder_funcs; 262 struct drm_crtc *crtc; 263 264 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 265 encoder_funcs = encoder->helper_private; 266 if (!drm_helper_encoder_in_use(encoder)) 267 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); 268 } 269 270 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 271 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 272 crtc->enabled = drm_helper_crtc_in_use(crtc); 273 if (!crtc->enabled) { 274 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 275 crtc->fb = NULL; 276 } 277 } 278} 279EXPORT_SYMBOL(drm_helper_disable_unused_functions); 280 281static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) 282{ 283 struct drm_display_mode *mode; 284 285 list_for_each_entry(mode, &connector->modes, head) { 286 if (drm_mode_width(mode) > width || 287 drm_mode_height(mode) > height) 288 continue; 289 if (mode->type & DRM_MODE_TYPE_PREFERRED) 290 return mode; 291 } 292 return NULL; 293} 294 295static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 296{ 297 bool enable; 298 299 if (strict) { 300 enable = connector->status == connector_status_connected; 301 } else { 302 enable = connector->status != connector_status_disconnected; 303 } 304 return enable; 305} 306 307static void drm_enable_connectors(struct drm_device *dev, bool *enabled) 308{ 309 bool any_enabled = false; 310 struct drm_connector *connector; 311 int i = 0; 312 313 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 314 enabled[i] = drm_connector_enabled(connector, true); 315 DRM_DEBUG("connector %d enabled? %s\n", connector->base.id, 316 enabled[i] ? "yes" : "no"); 317 any_enabled |= enabled[i]; 318 i++; 319 } 320 321 if (any_enabled) 322 return; 323 324 i = 0; 325 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 326 enabled[i] = drm_connector_enabled(connector, false); 327 i++; 328 } 329} 330 331static bool drm_target_preferred(struct drm_device *dev, 332 struct drm_display_mode **modes, 333 bool *enabled, int width, int height) 334{ 335 struct drm_connector *connector; 336 int i = 0; 337 338 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 339 340 if (enabled[i] == false) { 341 i++; 342 continue; 343 } 344 345 DRM_DEBUG("looking for preferred mode on connector %d\n", 346 connector->base.id); 347 348 modes[i] = drm_has_preferred_mode(connector, width, height); 349 /* No preferred modes, pick one off the list */ 350 if (!modes[i] && !list_empty(&connector->modes)) { 351 list_for_each_entry(modes[i], &connector->modes, head) 352 break; 353 } 354 DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name : 355 "none"); 356 i++; 357 } 358 return true; 359} 360 361static int drm_pick_crtcs(struct drm_device *dev, 362 struct drm_crtc **best_crtcs, 363 struct drm_display_mode **modes, 364 int n, int width, int height) 365{ 366 int c, o; 367 struct drm_connector *connector; 368 struct drm_connector_helper_funcs *connector_funcs; 369 struct drm_encoder *encoder; 370 struct drm_crtc *best_crtc; 371 int my_score, best_score, score; 372 struct drm_crtc **crtcs, *crtc; 373 374 if (n == dev->mode_config.num_connector) 375 return 0; 376 c = 0; 377 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 378 if (c == n) 379 break; 380 c++; 381 } 382 383 best_crtcs[n] = NULL; 384 best_crtc = NULL; 385 best_score = drm_pick_crtcs(dev, best_crtcs, modes, n+1, width, height); 386 if (modes[n] == NULL) 387 return best_score; 388 389 crtcs = kmalloc(dev->mode_config.num_connector * 390 sizeof(struct drm_crtc *), GFP_KERNEL); 391 if (!crtcs) 392 return best_score; 393 394 my_score = 1; 395 if (connector->status == connector_status_connected) 396 my_score++; 397 if (drm_has_preferred_mode(connector, width, height)) 398 my_score++; 399 400 connector_funcs = connector->helper_private; 401 encoder = connector_funcs->best_encoder(connector); 402 if (!encoder) 403 goto out; 404 405 connector->encoder = encoder; 406 407 /* select a crtc for this connector and then attempt to configure 408 remaining connectors */ 409 c = 0; 410 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 411 412 if ((connector->encoder->possible_crtcs & (1 << c)) == 0) { 413 c++; 414 continue; 415 } 416 417 for (o = 0; o < n; o++) 418 if (best_crtcs[o] == crtc) 419 break; 420 421 if (o < n) { 422 /* ignore cloning for now */ 423 c++; 424 continue; 425 } 426 427 crtcs[n] = crtc; 428 memcpy(crtcs, best_crtcs, n * sizeof(struct drm_crtc *)); 429 score = my_score + drm_pick_crtcs(dev, crtcs, modes, n + 1, 430 width, height); 431 if (score > best_score) { 432 best_crtc = crtc; 433 best_score = score; 434 memcpy(best_crtcs, crtcs, 435 dev->mode_config.num_connector * 436 sizeof(struct drm_crtc *)); 437 } 438 c++; 439 } 440out: 441 kfree(crtcs); 442 return best_score; 443} 444 445static void drm_setup_crtcs(struct drm_device *dev) 446{ 447 struct drm_crtc **crtcs; 448 struct drm_display_mode **modes; 449 struct drm_encoder *encoder; 450 struct drm_connector *connector; 451 bool *enabled; 452 int width, height; 453 int i, ret; 454 455 DRM_DEBUG("\n"); 456 457 width = dev->mode_config.max_width; 458 height = dev->mode_config.max_height; 459 460 /* clean out all the encoder/crtc combos */ 461 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 462 encoder->crtc = NULL; 463 } 464 465 crtcs = kcalloc(dev->mode_config.num_connector, 466 sizeof(struct drm_crtc *), GFP_KERNEL); 467 modes = kcalloc(dev->mode_config.num_connector, 468 sizeof(struct drm_display_mode *), GFP_KERNEL); 469 enabled = kcalloc(dev->mode_config.num_connector, 470 sizeof(bool), GFP_KERNEL); 471 472 drm_enable_connectors(dev, enabled); 473 474 ret = drm_target_preferred(dev, modes, enabled, width, height); 475 if (!ret) 476 DRM_ERROR("Unable to find initial modes\n"); 477 478 DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height); 479 480 drm_pick_crtcs(dev, crtcs, modes, 0, width, height); 481 482 i = 0; 483 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 484 struct drm_display_mode *mode = modes[i]; 485 struct drm_crtc *crtc = crtcs[i]; 486 487 if (connector->encoder == NULL) { 488 i++; 489 continue; 490 } 491 492 if (mode && crtc) { 493 DRM_DEBUG("desired mode %s set on crtc %d\n", 494 mode->name, crtc->base.id); 495 crtc->desired_mode = mode; 496 connector->encoder->crtc = crtc; 497 } else 498 connector->encoder->crtc = NULL; 499 i++; 500 } 501 502 kfree(crtcs); 503 kfree(modes); 504 kfree(enabled); 505} 506 507/** 508 * drm_encoder_crtc_ok - can a given crtc drive a given encoder? 509 * @encoder: encoder to test 510 * @crtc: crtc to test 511 * 512 * Return false if @encoder can't be driven by @crtc, true otherwise. 513 */ 514static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, 515 struct drm_crtc *crtc) 516{ 517 struct drm_device *dev; 518 struct drm_crtc *tmp; 519 int crtc_mask = 1; 520 521 WARN(!crtc, "checking null crtc?"); 522 523 dev = crtc->dev; 524 525 list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { 526 if (tmp == crtc) 527 break; 528 crtc_mask <<= 1; 529 } 530 531 if (encoder->possible_crtcs & crtc_mask) 532 return true; 533 return false; 534} 535 536/* 537 * Check the CRTC we're going to map each output to vs. its current 538 * CRTC. If they don't match, we have to disable the output and the CRTC 539 * since the driver will have to re-route things. 540 */ 541static void 542drm_crtc_prepare_encoders(struct drm_device *dev) 543{ 544 struct drm_encoder_helper_funcs *encoder_funcs; 545 struct drm_encoder *encoder; 546 547 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 548 encoder_funcs = encoder->helper_private; 549 /* Disable unused encoders */ 550 if (encoder->crtc == NULL) 551 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); 552 /* Disable encoders whose CRTC is about to change */ 553 if (encoder_funcs->get_crtc && 554 encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) 555 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); 556 } 557} 558 559/** 560 * drm_crtc_set_mode - set a mode 561 * @crtc: CRTC to program 562 * @mode: mode to use 563 * @x: width of mode 564 * @y: height of mode 565 * 566 * LOCKING: 567 * Caller must hold mode config lock. 568 * 569 * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance 570 * to fixup or reject the mode prior to trying to set it. 571 * 572 * RETURNS: 573 * True if the mode was set successfully, or false otherwise. 574 */ 575bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 576 struct drm_display_mode *mode, 577 int x, int y, 578 struct drm_framebuffer *old_fb) 579{ 580 struct drm_device *dev = crtc->dev; 581 struct drm_display_mode *adjusted_mode, saved_mode; 582 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 583 struct drm_encoder_helper_funcs *encoder_funcs; 584 int saved_x, saved_y; 585 struct drm_encoder *encoder; 586 bool ret = true; 587 588 adjusted_mode = drm_mode_duplicate(dev, mode); 589 590 crtc->enabled = drm_helper_crtc_in_use(crtc); 591 592 if (!crtc->enabled) 593 return true; 594 595 saved_mode = crtc->mode; 596 saved_x = crtc->x; 597 saved_y = crtc->y; 598 599 /* Update crtc values up front so the driver can rely on them for mode 600 * setting. 601 */ 602 crtc->mode = *mode; 603 crtc->x = x; 604 crtc->y = y; 605 606 /* Pass our mode to the connectors and the CRTC to give them a chance to 607 * adjust it according to limitations or connector properties, and also 608 * a chance to reject the mode entirely. 609 */ 610 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 611 612 if (encoder->crtc != crtc) 613 continue; 614 encoder_funcs = encoder->helper_private; 615 if (!(ret = encoder_funcs->mode_fixup(encoder, mode, 616 adjusted_mode))) { 617 goto done; 618 } 619 } 620 621 if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { 622 goto done; 623 } 624 625 /* Prepare the encoders and CRTCs before setting the mode. */ 626 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 627 628 if (encoder->crtc != crtc) 629 continue; 630 encoder_funcs = encoder->helper_private; 631 /* Disable the encoders as the first thing we do. */ 632 encoder_funcs->prepare(encoder); 633 } 634 635 drm_crtc_prepare_encoders(dev); 636 637 crtc_funcs->prepare(crtc); 638 639 /* Set up the DPLL and any encoders state that needs to adjust or depend 640 * on the DPLL. 641 */ 642 ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); 643 if (!ret) 644 goto done; 645 646 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 647 648 if (encoder->crtc != crtc) 649 continue; 650 651 DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), 652 mode->name, mode->base.id); 653 encoder_funcs = encoder->helper_private; 654 encoder_funcs->mode_set(encoder, mode, adjusted_mode); 655 } 656 657 /* Now enable the clocks, plane, pipe, and connectors that we set up. */ 658 crtc_funcs->commit(crtc); 659 660 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 661 662 if (encoder->crtc != crtc) 663 continue; 664 665 encoder_funcs = encoder->helper_private; 666 encoder_funcs->commit(encoder); 667 668 } 669 670 /* XXX free adjustedmode */ 671 drm_mode_destroy(dev, adjusted_mode); 672 /* FIXME: add subpixel order */ 673done: 674 if (!ret) { 675 crtc->mode = saved_mode; 676 crtc->x = saved_x; 677 crtc->y = saved_y; 678 } 679 680 return ret; 681} 682EXPORT_SYMBOL(drm_crtc_helper_set_mode); 683 684 685/** 686 * drm_crtc_helper_set_config - set a new config from userspace 687 * @crtc: CRTC to setup 688 * @crtc_info: user provided configuration 689 * @new_mode: new mode to set 690 * @connector_set: set of connectors for the new config 691 * @fb: new framebuffer 692 * 693 * LOCKING: 694 * Caller must hold mode config lock. 695 * 696 * Setup a new configuration, provided by the user in @crtc_info, and enable 697 * it. 698 * 699 * RETURNS: 700 * Zero. (FIXME) 701 */ 702int drm_crtc_helper_set_config(struct drm_mode_set *set) 703{ 704 struct drm_device *dev; 705 struct drm_crtc **save_crtcs, *new_crtc; 706 struct drm_encoder **save_encoders, *new_encoder; 707 struct drm_framebuffer *old_fb = NULL; 708 bool save_enabled; 709 bool mode_changed = false; /* if true do a full mode set */ 710 bool fb_changed = false; /* if true and !mode_changed just do a flip */ 711 struct drm_connector *connector; 712 int count = 0, ro, fail = 0; 713 struct drm_crtc_helper_funcs *crtc_funcs; 714 int ret = 0; 715 716 DRM_DEBUG("\n"); 717 718 if (!set) 719 return -EINVAL; 720 721 if (!set->crtc) 722 return -EINVAL; 723 724 if (!set->crtc->helper_private) 725 return -EINVAL; 726 727 crtc_funcs = set->crtc->helper_private; 728 729 DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n", 730 set->crtc, set->crtc->base.id, set->fb, set->connectors, 731 (int)set->num_connectors, set->x, set->y); 732 733 dev = set->crtc->dev; 734 735 /* save previous config */ 736 save_enabled = set->crtc->enabled; 737 738 /* 739 * We do mode_config.num_connectors here since we'll look at the 740 * CRTC and encoder associated with each connector later. 741 */ 742 save_crtcs = kzalloc(dev->mode_config.num_connector * 743 sizeof(struct drm_crtc *), GFP_KERNEL); 744 if (!save_crtcs) 745 return -ENOMEM; 746 747 save_encoders = kzalloc(dev->mode_config.num_connector * 748 sizeof(struct drm_encoders *), GFP_KERNEL); 749 if (!save_encoders) { 750 kfree(save_crtcs); 751 return -ENOMEM; 752 } 753 754 /* We should be able to check here if the fb has the same properties 755 * and then just flip_or_move it */ 756 if (set->crtc->fb != set->fb) { 757 /* If we have no fb then treat it as a full mode set */ 758 if (set->crtc->fb == NULL) { 759 DRM_DEBUG("crtc has no fb, full mode set\n"); 760 mode_changed = true; 761 } else if (set->fb == NULL) { 762 mode_changed = true; 763 } else if ((set->fb->bits_per_pixel != 764 set->crtc->fb->bits_per_pixel) || 765 set->fb->depth != set->crtc->fb->depth) 766 fb_changed = true; 767 else 768 fb_changed = true; 769 } 770 771 if (set->x != set->crtc->x || set->y != set->crtc->y) 772 fb_changed = true; 773 774 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { 775 DRM_DEBUG("modes are different, full mode set\n"); 776 drm_mode_debug_printmodeline(&set->crtc->mode); 777 drm_mode_debug_printmodeline(set->mode); 778 mode_changed = true; 779 } 780 781 /* a) traverse passed in connector list and get encoders for them */ 782 count = 0; 783 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 784 struct drm_connector_helper_funcs *connector_funcs = 785 connector->helper_private; 786 save_encoders[count++] = connector->encoder; 787 new_encoder = connector->encoder; 788 for (ro = 0; ro < set->num_connectors; ro++) { 789 if (set->connectors[ro] == connector) { 790 new_encoder = connector_funcs->best_encoder(connector); 791 /* if we can't get an encoder for a connector 792 we are setting now - then fail */ 793 if (new_encoder == NULL) 794 /* don't break so fail path works correct */ 795 fail = 1; 796 break; 797 } 798 } 799 800 if (new_encoder != connector->encoder) { 801 DRM_DEBUG("encoder changed, full mode switch\n"); 802 mode_changed = true; 803 connector->encoder = new_encoder; 804 } 805 } 806 807 if (fail) { 808 ret = -EINVAL; 809 goto fail_no_encoder; 810 } 811 812 count = 0; 813 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 814 if (!connector->encoder) 815 continue; 816 817 save_crtcs[count++] = connector->encoder->crtc; 818 819 if (connector->encoder->crtc == set->crtc) 820 new_crtc = NULL; 821 else 822 new_crtc = connector->encoder->crtc; 823 824 for (ro = 0; ro < set->num_connectors; ro++) { 825 if (set->connectors[ro] == connector) 826 new_crtc = set->crtc; 827 } 828 829 /* Make sure the new CRTC will work with the encoder */ 830 if (new_crtc && 831 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { 832 ret = -EINVAL; 833 goto fail_set_mode; 834 } 835 if (new_crtc != connector->encoder->crtc) { 836 DRM_DEBUG("crtc changed, full mode switch\n"); 837 mode_changed = true; 838 connector->encoder->crtc = new_crtc; 839 } 840 DRM_DEBUG("setting connector %d crtc to %p\n", 841 connector->base.id, new_crtc); 842 } 843 844 /* mode_set_base is not a required function */ 845 if (fb_changed && !crtc_funcs->mode_set_base) 846 mode_changed = true; 847 848 if (mode_changed) { 849 old_fb = set->crtc->fb; 850 set->crtc->fb = set->fb; 851 set->crtc->enabled = (set->mode != NULL); 852 if (set->mode != NULL) { 853 DRM_DEBUG("attempting to set mode from userspace\n"); 854 drm_mode_debug_printmodeline(set->mode); 855 if (!drm_crtc_helper_set_mode(set->crtc, set->mode, 856 set->x, set->y, 857 old_fb)) { 858 DRM_ERROR("failed to set mode on crtc %p\n", 859 set->crtc); 860 ret = -EINVAL; 861 goto fail_set_mode; 862 } 863 /* TODO are these needed? */ 864 set->crtc->desired_x = set->x; 865 set->crtc->desired_y = set->y; 866 set->crtc->desired_mode = set->mode; 867 } 868 drm_helper_disable_unused_functions(dev); 869 } else if (fb_changed) { 870 old_fb = set->crtc->fb; 871 if (set->crtc->fb != set->fb) 872 set->crtc->fb = set->fb; 873 ret = crtc_funcs->mode_set_base(set->crtc, 874 set->x, set->y, old_fb); 875 if (ret != 0) 876 goto fail_set_mode; 877 } 878 879 kfree(save_encoders); 880 kfree(save_crtcs); 881 return 0; 882 883fail_set_mode: 884 set->crtc->enabled = save_enabled; 885 set->crtc->fb = old_fb; 886 count = 0; 887 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 888 if (!connector->encoder) 889 continue; 890 891 connector->encoder->crtc = save_crtcs[count++]; 892 } 893fail_no_encoder: 894 kfree(save_crtcs); 895 count = 0; 896 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 897 connector->encoder = save_encoders[count++]; 898 } 899 kfree(save_encoders); 900 return ret; 901} 902EXPORT_SYMBOL(drm_crtc_helper_set_config); 903 904bool drm_helper_plugged_event(struct drm_device *dev) 905{ 906 DRM_DEBUG("\n"); 907 908 drm_helper_probe_connector_modes(dev, dev->mode_config.max_width, 909 dev->mode_config.max_height); 910 911 drm_setup_crtcs(dev); 912 913 /* alert the driver fb layer */ 914 dev->mode_config.funcs->fb_changed(dev); 915 916 /* FIXME: send hotplug event */ 917 return true; 918} 919/** 920 * drm_initial_config - setup a sane initial connector configuration 921 * @dev: DRM device 922 * 923 * LOCKING: 924 * Called at init time, must take mode config lock. 925 * 926 * Scan the CRTCs and connectors and try to put together an initial setup. 927 * At the moment, this is a cloned configuration across all heads with 928 * a new framebuffer object as the backing store. 929 * 930 * RETURNS: 931 * Zero if everything went ok, nonzero otherwise. 932 */ 933bool drm_helper_initial_config(struct drm_device *dev) 934{ 935 struct drm_connector *connector; 936 int count = 0; 937 938 count = drm_helper_probe_connector_modes(dev, 939 dev->mode_config.max_width, 940 dev->mode_config.max_height); 941 942 /* 943 * None of the available connectors had any modes, so add some 944 * and try to light them up anyway 945 */ 946 if (!count) { 947 DRM_ERROR("connectors have no modes, using standard modes\n"); 948 list_for_each_entry(connector, 949 &dev->mode_config.connector_list, 950 head) 951 drm_helper_add_std_modes(dev, connector); 952 } 953 954 drm_setup_crtcs(dev); 955 956 /* alert the driver fb layer */ 957 dev->mode_config.funcs->fb_changed(dev); 958 959 return 0; 960} 961EXPORT_SYMBOL(drm_helper_initial_config); 962 963static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) 964{ 965 int dpms = DRM_MODE_DPMS_OFF; 966 struct drm_connector *connector; 967 struct drm_device *dev = encoder->dev; 968 969 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 970 if (connector->encoder == encoder) 971 if (connector->dpms < dpms) 972 dpms = connector->dpms; 973 return dpms; 974} 975 976static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) 977{ 978 int dpms = DRM_MODE_DPMS_OFF; 979 struct drm_connector *connector; 980 struct drm_device *dev = crtc->dev; 981 982 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 983 if (connector->encoder && connector->encoder->crtc == crtc) 984 if (connector->dpms < dpms) 985 dpms = connector->dpms; 986 return dpms; 987} 988 989/** 990 * drm_helper_connector_dpms 991 * @connector affected connector 992 * @mode DPMS mode 993 * 994 * Calls the low-level connector DPMS function, then 995 * calls appropriate encoder and crtc DPMS functions as well 996 */ 997void drm_helper_connector_dpms(struct drm_connector *connector, int mode) 998{ 999 struct drm_encoder *encoder = connector->encoder; 1000 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; 1001 int old_dpms; 1002 1003 if (mode == connector->dpms) 1004 return; 1005 1006 old_dpms = connector->dpms; 1007 connector->dpms = mode; 1008 1009 /* from off to on, do crtc then encoder */ 1010 if (mode < old_dpms) { 1011 if (crtc) { 1012 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 1013 if (crtc_funcs->dpms) 1014 (*crtc_funcs->dpms) (crtc, 1015 drm_helper_choose_crtc_dpms(crtc)); 1016 } 1017 if (encoder) { 1018 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; 1019 if (encoder_funcs->dpms) 1020 (*encoder_funcs->dpms) (encoder, 1021 drm_helper_choose_encoder_dpms(encoder)); 1022 } 1023 } 1024 1025 /* from on to off, do encoder then crtc */ 1026 if (mode > old_dpms) { 1027 if (encoder) { 1028 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; 1029 if (encoder_funcs->dpms) 1030 (*encoder_funcs->dpms) (encoder, 1031 drm_helper_choose_encoder_dpms(encoder)); 1032 } 1033 if (crtc) { 1034 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 1035 if (crtc_funcs->dpms) 1036 (*crtc_funcs->dpms) (crtc, 1037 drm_helper_choose_crtc_dpms(crtc)); 1038 } 1039 } 1040 1041 return; 1042} 1043EXPORT_SYMBOL(drm_helper_connector_dpms); 1044 1045/** 1046 * drm_hotplug_stage_two 1047 * @dev DRM device 1048 * @connector hotpluged connector 1049 * 1050 * LOCKING. 1051 * Caller must hold mode config lock, function might grab struct lock. 1052 * 1053 * Stage two of a hotplug. 1054 * 1055 * RETURNS: 1056 * Zero on success, errno on failure. 1057 */ 1058int drm_helper_hotplug_stage_two(struct drm_device *dev) 1059{ 1060 drm_helper_plugged_event(dev); 1061 1062 return 0; 1063} 1064EXPORT_SYMBOL(drm_helper_hotplug_stage_two); 1065 1066int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, 1067 struct drm_mode_fb_cmd *mode_cmd) 1068{ 1069 fb->width = mode_cmd->width; 1070 fb->height = mode_cmd->height; 1071 fb->pitch = mode_cmd->pitch; 1072 fb->bits_per_pixel = mode_cmd->bpp; 1073 fb->depth = mode_cmd->depth; 1074 1075 return 0; 1076} 1077EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); 1078 1079int drm_helper_resume_force_mode(struct drm_device *dev) 1080{ 1081 struct drm_crtc *crtc; 1082 int ret; 1083 1084 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1085 1086 if (!crtc->enabled) 1087 continue; 1088 1089 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, 1090 crtc->x, crtc->y, crtc->fb); 1091 1092 if (ret == false) 1093 DRM_ERROR("failed to set mode on crtc %p\n", crtc); 1094 } 1095 /* disable the unused connectors while restoring the modesetting */ 1096 drm_helper_disable_unused_functions(dev); 1097 return 0; 1098} 1099EXPORT_SYMBOL(drm_helper_resume_force_mode);