1 /* $NetBSD: drm_client_modeset.c,v 1.3 2021/12/19 02:00:03 riastradh Exp $ */ 2 3 // SPDX-License-Identifier: MIT 4 /* 5 * Copyright 2018 Noralf Trønnes 6 * Copyright (c) 2006-2009 Red Hat Inc. 7 * Copyright (c) 2006-2008 Intel Corporation 8 * Jesse Barnes <jesse.barnes@intel.com> 9 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 10 */ 11 12 #include <sys/cdefs.h> 13 __KERNEL_RCSID(0, "$NetBSD: drm_client_modeset.c,v 1.3 2021/12/19 02:00:03 riastradh Exp $"); 14 15 #include <linux/module.h> 16 #include <linux/mutex.h> 17 #include <linux/slab.h> 18 19 #include <drm/drm_atomic.h> 20 #include <drm/drm_client.h> 21 #include <drm/drm_connector.h> 22 #include <drm/drm_crtc.h> 23 #include <drm/drm_device.h> 24 #include <drm/drm_drv.h> 25 #include <drm/drm_encoder.h> 26 #include <drm/drm_print.h> 27 28 #include "drm_crtc_internal.h" 29 #include "drm_internal.h" 30 31 #include <linux/nbsd-namespace.h> 32 33 #define DRM_CLIENT_MAX_CLONED_CONNECTORS 8 34 35 struct drm_client_offset { 36 int x, y; 37 }; 38 39 int drm_client_modeset_create(struct drm_client_dev *client) 40 { 41 struct drm_device *dev = client->dev; 42 unsigned int num_crtc = dev->mode_config.num_crtc; 43 unsigned int max_connector_count = 1; 44 struct drm_mode_set *modeset; 45 struct drm_crtc *crtc; 46 unsigned int i = 0; 47 48 /* Add terminating zero entry to enable index less iteration */ 49 client->modesets = kcalloc(num_crtc + 1, sizeof(*client->modesets), GFP_KERNEL); 50 if (!client->modesets) 51 return -ENOMEM; 52 53 mutex_init(&client->modeset_mutex); 54 55 drm_for_each_crtc(crtc, dev) 56 client->modesets[i++].crtc = crtc; 57 58 /* Cloning is only supported in the single crtc case. */ 59 if (num_crtc == 1) 60 max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS; 61 62 for (modeset = client->modesets; modeset->crtc; modeset++) { 63 modeset->connectors = kcalloc(max_connector_count, 64 sizeof(*modeset->connectors), GFP_KERNEL); 65 if (!modeset->connectors) 66 goto err_free; 67 } 68 69 return 0; 70 71 err_free: 72 drm_client_modeset_free(client); 73 74 return -ENOMEM; 75 } 76 77 static void drm_client_modeset_release(struct drm_client_dev *client) 78 { 79 struct drm_mode_set *modeset; 80 unsigned int i; 81 82 drm_client_for_each_modeset(modeset, client) { 83 drm_mode_destroy(client->dev, modeset->mode); 84 modeset->mode = NULL; 85 modeset->fb = NULL; 86 87 for (i = 0; i < modeset->num_connectors; i++) { 88 drm_connector_put(modeset->connectors[i]); 89 modeset->connectors[i] = NULL; 90 } 91 modeset->num_connectors = 0; 92 } 93 } 94 95 void drm_client_modeset_free(struct drm_client_dev *client) 96 { 97 struct drm_mode_set *modeset; 98 99 mutex_lock(&client->modeset_mutex); 100 101 drm_client_modeset_release(client); 102 103 drm_client_for_each_modeset(modeset, client) 104 kfree(modeset->connectors); 105 106 mutex_unlock(&client->modeset_mutex); 107 108 mutex_destroy(&client->modeset_mutex); 109 kfree(client->modesets); 110 } 111 112 static struct drm_mode_set * 113 drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc) 114 { 115 struct drm_mode_set *modeset; 116 117 drm_client_for_each_modeset(modeset, client) 118 if (modeset->crtc == crtc) 119 return modeset; 120 121 return NULL; 122 } 123 124 static struct drm_display_mode * 125 drm_connector_get_tiled_mode(struct drm_connector *connector) 126 { 127 struct drm_display_mode *mode; 128 129 list_for_each_entry(mode, &connector->modes, head) { 130 if (mode->hdisplay == connector->tile_h_size && 131 mode->vdisplay == connector->tile_v_size) 132 return mode; 133 } 134 return NULL; 135 } 136 137 static struct drm_display_mode * 138 drm_connector_fallback_non_tiled_mode(struct drm_connector *connector) 139 { 140 struct drm_display_mode *mode; 141 142 list_for_each_entry(mode, &connector->modes, head) { 143 if (mode->hdisplay == connector->tile_h_size && 144 mode->vdisplay == connector->tile_v_size) 145 continue; 146 return mode; 147 } 148 return NULL; 149 } 150 151 static struct drm_display_mode * 152 drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height) 153 { 154 struct drm_display_mode *mode; 155 156 list_for_each_entry(mode, &connector->modes, head) { 157 if (mode->hdisplay > width || 158 mode->vdisplay > height) 159 continue; 160 if (mode->type & DRM_MODE_TYPE_PREFERRED) 161 return mode; 162 } 163 return NULL; 164 } 165 166 static struct drm_display_mode * 167 drm_connector_pick_cmdline_mode(struct drm_connector *connector) 168 { 169 struct drm_cmdline_mode *cmdline_mode; 170 struct drm_display_mode *mode; 171 bool prefer_non_interlace; 172 173 cmdline_mode = &connector->cmdline_mode; 174 if (cmdline_mode->specified == false) 175 return NULL; 176 177 /* attempt to find a matching mode in the list of modes 178 * we have gotten so far, if not add a CVT mode that conforms 179 */ 180 if (cmdline_mode->rb || cmdline_mode->margins) 181 goto create_mode; 182 183 prefer_non_interlace = !cmdline_mode->interlace; 184 again: 185 list_for_each_entry(mode, &connector->modes, head) { 186 /* Check (optional) mode name first */ 187 if (!strcmp(mode->name, cmdline_mode->name)) 188 return mode; 189 190 /* check width/height */ 191 if (mode->hdisplay != cmdline_mode->xres || 192 mode->vdisplay != cmdline_mode->yres) 193 continue; 194 195 if (cmdline_mode->refresh_specified) { 196 if (mode->vrefresh != cmdline_mode->refresh) 197 continue; 198 } 199 200 if (cmdline_mode->interlace) { 201 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) 202 continue; 203 } else if (prefer_non_interlace) { 204 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 205 continue; 206 } 207 return mode; 208 } 209 210 if (prefer_non_interlace) { 211 prefer_non_interlace = false; 212 goto again; 213 } 214 215 create_mode: 216 mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode); 217 if (mode) 218 list_add(&mode->head, &connector->modes); 219 220 return mode; 221 } 222 223 static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 224 { 225 bool enable; 226 227 if (connector->display_info.non_desktop) 228 return false; 229 230 if (strict) 231 enable = connector->status == connector_status_connected; 232 else 233 enable = connector->status != connector_status_disconnected; 234 235 return enable; 236 } 237 238 static void drm_client_connectors_enabled(struct drm_connector **connectors, 239 unsigned int connector_count, 240 bool *enabled) 241 { 242 bool any_enabled = false; 243 struct drm_connector *connector; 244 int i = 0; 245 246 for (i = 0; i < connector_count; i++) { 247 connector = connectors[i]; 248 enabled[i] = drm_connector_enabled(connector, true); 249 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, 250 connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); 251 252 any_enabled |= enabled[i]; 253 } 254 255 if (any_enabled) 256 return; 257 258 for (i = 0; i < connector_count; i++) 259 enabled[i] = drm_connector_enabled(connectors[i], false); 260 } 261 262 static bool drm_client_target_cloned(struct drm_device *dev, 263 struct drm_connector **connectors, 264 unsigned int connector_count, 265 struct drm_display_mode **modes, 266 struct drm_client_offset *offsets, 267 bool *enabled, int width, int height) 268 { 269 int count, i, j; 270 bool can_clone = false; 271 struct drm_display_mode *dmt_mode, *mode; 272 273 /* only contemplate cloning in the single crtc case */ 274 if (dev->mode_config.num_crtc > 1) 275 return false; 276 277 count = 0; 278 for (i = 0; i < connector_count; i++) { 279 if (enabled[i]) 280 count++; 281 } 282 283 /* only contemplate cloning if more than one connector is enabled */ 284 if (count <= 1) 285 return false; 286 287 /* check the command line or if nothing common pick 1024x768 */ 288 can_clone = true; 289 for (i = 0; i < connector_count; i++) { 290 if (!enabled[i]) 291 continue; 292 modes[i] = drm_connector_pick_cmdline_mode(connectors[i]); 293 if (!modes[i]) { 294 can_clone = false; 295 break; 296 } 297 for (j = 0; j < i; j++) { 298 if (!enabled[j]) 299 continue; 300 if (!drm_mode_match(modes[j], modes[i], 301 DRM_MODE_MATCH_TIMINGS | 302 DRM_MODE_MATCH_CLOCK | 303 DRM_MODE_MATCH_FLAGS | 304 DRM_MODE_MATCH_3D_FLAGS)) 305 can_clone = false; 306 } 307 } 308 309 if (can_clone) { 310 DRM_DEBUG_KMS("can clone using command line\n"); 311 return true; 312 } 313 314 /* try and find a 1024x768 mode on each connector */ 315 can_clone = true; 316 dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false); 317 318 for (i = 0; i < connector_count; i++) { 319 if (!enabled[i]) 320 continue; 321 322 list_for_each_entry(mode, &connectors[i]->modes, head) { 323 if (drm_mode_match(mode, dmt_mode, 324 DRM_MODE_MATCH_TIMINGS | 325 DRM_MODE_MATCH_CLOCK | 326 DRM_MODE_MATCH_FLAGS | 327 DRM_MODE_MATCH_3D_FLAGS)) 328 modes[i] = mode; 329 } 330 if (!modes[i]) 331 can_clone = false; 332 } 333 334 if (can_clone) { 335 DRM_DEBUG_KMS("can clone using 1024x768\n"); 336 return true; 337 } 338 DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); 339 return false; 340 } 341 342 static int drm_client_get_tile_offsets(struct drm_connector **connectors, 343 unsigned int connector_count, 344 struct drm_display_mode **modes, 345 struct drm_client_offset *offsets, 346 int idx, 347 int h_idx, int v_idx) 348 { 349 struct drm_connector *connector; 350 int i; 351 int hoffset = 0, voffset = 0; 352 353 for (i = 0; i < connector_count; i++) { 354 connector = connectors[i]; 355 if (!connector->has_tile) 356 continue; 357 358 if (!modes[i] && (h_idx || v_idx)) { 359 DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, 360 connector->base.id); 361 continue; 362 } 363 if (connector->tile_h_loc < h_idx) 364 hoffset += modes[i]->hdisplay; 365 366 if (connector->tile_v_loc < v_idx) 367 voffset += modes[i]->vdisplay; 368 } 369 offsets[idx].x = hoffset; 370 offsets[idx].y = voffset; 371 DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx); 372 return 0; 373 } 374 375 static bool drm_client_target_preferred(struct drm_connector **connectors, 376 unsigned int connector_count, 377 struct drm_display_mode **modes, 378 struct drm_client_offset *offsets, 379 bool *enabled, int width, int height) 380 { 381 const u64 mask = BIT_ULL(connector_count) - 1; 382 struct drm_connector *connector; 383 u64 conn_configured = 0; 384 int tile_pass = 0; 385 int num_tiled_conns = 0; 386 int i; 387 388 for (i = 0; i < connector_count; i++) { 389 if (connectors[i]->has_tile && 390 connectors[i]->status == connector_status_connected) 391 num_tiled_conns++; 392 } 393 394 retry: 395 for (i = 0; i < connector_count; i++) { 396 connector = connectors[i]; 397 398 if (conn_configured & BIT_ULL(i)) 399 continue; 400 401 if (enabled[i] == false) { 402 conn_configured |= BIT_ULL(i); 403 continue; 404 } 405 406 /* first pass over all the untiled connectors */ 407 if (tile_pass == 0 && connector->has_tile) 408 continue; 409 410 if (tile_pass == 1) { 411 if (connector->tile_h_loc != 0 || 412 connector->tile_v_loc != 0) 413 continue; 414 415 } else { 416 if (connector->tile_h_loc != tile_pass - 1 && 417 connector->tile_v_loc != tile_pass - 1) 418 /* if this tile_pass doesn't cover any of the tiles - keep going */ 419 continue; 420 421 /* 422 * find the tile offsets for this pass - need to find 423 * all tiles left and above 424 */ 425 drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i, 426 connector->tile_h_loc, connector->tile_v_loc); 427 } 428 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", 429 connector->base.id); 430 431 /* got for command line mode first */ 432 modes[i] = drm_connector_pick_cmdline_mode(connector); 433 if (!modes[i]) { 434 DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", 435 connector->base.id, connector->tile_group ? connector->tile_group->id : 0); 436 modes[i] = drm_connector_has_preferred_mode(connector, width, height); 437 } 438 /* No preferred modes, pick one off the list */ 439 if (!modes[i] && !list_empty(&connector->modes)) { 440 list_for_each_entry(modes[i], &connector->modes, head) 441 break; 442 } 443 /* 444 * In case of tiled mode if all tiles not present fallback to 445 * first available non tiled mode. 446 * After all tiles are present, try to find the tiled mode 447 * for all and if tiled mode not present due to fbcon size 448 * limitations, use first non tiled mode only for 449 * tile 0,0 and set to no mode for all other tiles. 450 */ 451 if (connector->has_tile) { 452 if (num_tiled_conns < 453 connector->num_h_tile * connector->num_v_tile || 454 (connector->tile_h_loc == 0 && 455 connector->tile_v_loc == 0 && 456 !drm_connector_get_tiled_mode(connector))) { 457 DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", 458 connector->base.id); 459 modes[i] = drm_connector_fallback_non_tiled_mode(connector); 460 } else { 461 modes[i] = drm_connector_get_tiled_mode(connector); 462 } 463 } 464 465 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : 466 "none"); 467 conn_configured |= BIT_ULL(i); 468 } 469 470 if ((conn_configured & mask) != mask) { 471 tile_pass++; 472 goto retry; 473 } 474 return true; 475 } 476 477 static bool connector_has_possible_crtc(struct drm_connector *connector, 478 struct drm_crtc *crtc) 479 { 480 struct drm_encoder *encoder; 481 482 drm_connector_for_each_possible_encoder(connector, encoder) { 483 if (encoder->possible_crtcs & drm_crtc_mask(crtc)) 484 return true; 485 } 486 487 return false; 488 } 489 490 static int drm_client_pick_crtcs(struct drm_client_dev *client, 491 struct drm_connector **connectors, 492 unsigned int connector_count, 493 struct drm_crtc **best_crtcs, 494 struct drm_display_mode **modes, 495 int n, int width, int height) 496 { 497 struct drm_device *dev = client->dev; 498 struct drm_connector *connector; 499 int my_score, best_score, score; 500 struct drm_crtc **crtcs, *crtc; 501 struct drm_mode_set *modeset; 502 int o; 503 504 if (n == connector_count) 505 return 0; 506 507 connector = connectors[n]; 508 509 best_crtcs[n] = NULL; 510 best_score = drm_client_pick_crtcs(client, connectors, connector_count, 511 best_crtcs, modes, n + 1, width, height); 512 if (modes[n] == NULL) 513 return best_score; 514 515 crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); 516 if (!crtcs) 517 return best_score; 518 519 my_score = 1; 520 if (connector->status == connector_status_connected) 521 my_score++; 522 if (connector->cmdline_mode.specified) 523 my_score++; 524 if (drm_connector_has_preferred_mode(connector, width, height)) 525 my_score++; 526 527 /* 528 * select a crtc for this connector and then attempt to configure 529 * remaining connectors 530 */ 531 drm_client_for_each_modeset(modeset, client) { 532 crtc = modeset->crtc; 533 534 if (!connector_has_possible_crtc(connector, crtc)) 535 continue; 536 537 for (o = 0; o < n; o++) 538 if (best_crtcs[o] == crtc) 539 break; 540 541 if (o < n) { 542 /* ignore cloning unless only a single crtc */ 543 if (dev->mode_config.num_crtc > 1) 544 continue; 545 546 if (!drm_mode_equal(modes[o], modes[n])) 547 continue; 548 } 549 550 crtcs[n] = crtc; 551 memcpy(crtcs, best_crtcs, n * sizeof(*crtcs)); 552 score = my_score + drm_client_pick_crtcs(client, connectors, connector_count, 553 crtcs, modes, n + 1, width, height); 554 if (score > best_score) { 555 best_score = score; 556 memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs)); 557 } 558 } 559 560 kfree(crtcs); 561 return best_score; 562 } 563 564 /* Try to read the BIOS display configuration and use it for the initial config */ 565 static bool drm_client_firmware_config(struct drm_client_dev *client, 566 struct drm_connector **connectors, 567 unsigned int connector_count, 568 struct drm_crtc **crtcs, 569 struct drm_display_mode **modes, 570 struct drm_client_offset *offsets, 571 bool *enabled, int width, int height) 572 { 573 unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG); 574 unsigned long conn_configured, conn_seq, mask; 575 struct drm_device *dev = client->dev; 576 int i, j; 577 bool *save_enabled; 578 bool fallback = true, ret = true; 579 int num_connectors_enabled = 0; 580 int num_connectors_detected = 0; 581 int num_tiled_conns = 0; 582 struct drm_modeset_acquire_ctx ctx; 583 584 if (!drm_drv_uses_atomic_modeset(dev)) 585 return false; 586 587 save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); 588 if (!save_enabled) 589 return false; 590 591 drm_modeset_acquire_init(&ctx, 0); 592 593 while (drm_modeset_lock_all_ctx(dev, &ctx) != 0) 594 drm_modeset_backoff(&ctx); 595 596 memcpy(save_enabled, enabled, count); 597 mask = GENMASK(count - 1, 0); 598 conn_configured = 0; 599 for (i = 0; i < count; i++) { 600 if (connectors[i]->has_tile && 601 connectors[i]->status == connector_status_connected) 602 num_tiled_conns++; 603 } 604 retry: 605 conn_seq = conn_configured; 606 for (i = 0; i < count; i++) { 607 struct drm_connector *connector; 608 struct drm_encoder *encoder; 609 struct drm_crtc *new_crtc; 610 611 connector = connectors[i]; 612 613 if (conn_configured & BIT(i)) 614 continue; 615 616 if (conn_seq == 0 && !connector->has_tile) 617 continue; 618 619 if (connector->status == connector_status_connected) 620 num_connectors_detected++; 621 622 if (!enabled[i]) { 623 DRM_DEBUG_KMS("connector %s not enabled, skipping\n", 624 connector->name); 625 conn_configured |= BIT(i); 626 continue; 627 } 628 629 if (connector->force == DRM_FORCE_OFF) { 630 DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", 631 connector->name); 632 enabled[i] = false; 633 continue; 634 } 635 636 encoder = connector->state->best_encoder; 637 if (!encoder || WARN_ON(!connector->state->crtc)) { 638 if (connector->force > DRM_FORCE_OFF) 639 goto bail; 640 641 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", 642 connector->name); 643 enabled[i] = false; 644 conn_configured |= BIT(i); 645 continue; 646 } 647 648 num_connectors_enabled++; 649 650 new_crtc = connector->state->crtc; 651 652 /* 653 * Make sure we're not trying to drive multiple connectors 654 * with a single CRTC, since our cloning support may not 655 * match the BIOS. 656 */ 657 for (j = 0; j < count; j++) { 658 if (crtcs[j] == new_crtc) { 659 DRM_DEBUG_KMS("fallback: cloned configuration\n"); 660 goto bail; 661 } 662 } 663 664 DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", 665 connector->name); 666 667 /* go for command line mode first */ 668 modes[i] = drm_connector_pick_cmdline_mode(connector); 669 670 /* try for preferred next */ 671 if (!modes[i]) { 672 DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", 673 connector->name, connector->has_tile); 674 modes[i] = drm_connector_has_preferred_mode(connector, width, height); 675 } 676 677 /* No preferred mode marked by the EDID? Are there any modes? */ 678 if (!modes[i] && !list_empty(&connector->modes)) { 679 DRM_DEBUG_KMS("using first mode listed on connector %s\n", 680 connector->name); 681 modes[i] = list_first_entry(&connector->modes, 682 struct drm_display_mode, 683 head); 684 } 685 686 /* last resort: use current mode */ 687 if (!modes[i]) { 688 /* 689 * IMPORTANT: We want to use the adjusted mode (i.e. 690 * after the panel fitter upscaling) as the initial 691 * config, not the input mode, which is what crtc->mode 692 * usually contains. But since our current 693 * code puts a mode derived from the post-pfit timings 694 * into crtc->mode this works out correctly. 695 * 696 * This is crtc->mode and not crtc->state->mode for the 697 * fastboot check to work correctly. 698 */ 699 DRM_DEBUG_KMS("looking for current mode on connector %s\n", 700 connector->name); 701 modes[i] = &connector->state->crtc->mode; 702 } 703 /* 704 * In case of tiled modes, if all tiles are not present 705 * then fallback to a non tiled mode. 706 */ 707 if (connector->has_tile && 708 num_tiled_conns < connector->num_h_tile * connector->num_v_tile) { 709 DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", 710 connector->base.id); 711 modes[i] = drm_connector_fallback_non_tiled_mode(connector); 712 } 713 crtcs[i] = new_crtc; 714 715 DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", 716 connector->name, 717 connector->state->crtc->base.id, 718 connector->state->crtc->name, 719 modes[i]->hdisplay, modes[i]->vdisplay, 720 modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); 721 722 fallback = false; 723 conn_configured |= BIT(i); 724 } 725 726 if ((conn_configured & mask) != mask && conn_configured != conn_seq) 727 goto retry; 728 729 /* 730 * If the BIOS didn't enable everything it could, fall back to have the 731 * same user experiencing of lighting up as much as possible like the 732 * fbdev helper library. 733 */ 734 if (num_connectors_enabled != num_connectors_detected && 735 num_connectors_enabled < dev->mode_config.num_crtc) { 736 DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); 737 DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, 738 num_connectors_detected); 739 fallback = true; 740 } 741 742 if (fallback) { 743 bail: 744 DRM_DEBUG_KMS("Not using firmware configuration\n"); 745 memcpy(enabled, save_enabled, count); 746 ret = false; 747 } 748 749 drm_modeset_drop_locks(&ctx); 750 drm_modeset_acquire_fini(&ctx); 751 752 kfree(save_enabled); 753 return ret; 754 } 755 756 /** 757 * drm_client_modeset_probe() - Probe for displays 758 * @client: DRM client 759 * @width: Maximum display mode width (optional) 760 * @height: Maximum display mode height (optional) 761 * 762 * This function sets up display pipelines for enabled connectors and stores the 763 * config in the client's modeset array. 764 * 765 * Returns: 766 * Zero on success or negative error code on failure. 767 */ 768 int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height) 769 { 770 struct drm_connector *connector, **connectors = NULL; 771 struct drm_connector_list_iter conn_iter; 772 struct drm_device *dev = client->dev; 773 unsigned int total_modes_count = 0; 774 struct drm_client_offset *offsets; 775 unsigned int connector_count = 0; 776 struct drm_display_mode **modes; 777 struct drm_crtc **crtcs; 778 int i, ret = 0; 779 bool *enabled; 780 781 DRM_DEBUG_KMS("\n"); 782 783 if (!width) 784 width = dev->mode_config.max_width; 785 if (!height) 786 height = dev->mode_config.max_height; 787 788 drm_connector_list_iter_begin(dev, &conn_iter); 789 drm_client_for_each_connector_iter(connector, &conn_iter) { 790 struct drm_connector **tmp; 791 792 tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL); 793 if (!tmp) { 794 ret = -ENOMEM; 795 goto free_connectors; 796 } 797 798 connectors = tmp; 799 drm_connector_get(connector); 800 connectors[connector_count++] = connector; 801 } 802 drm_connector_list_iter_end(&conn_iter); 803 804 if (!connector_count) 805 return 0; 806 807 crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL); 808 modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL); 809 offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL); 810 enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL); 811 if (!crtcs || !modes || !enabled || !offsets) { 812 DRM_ERROR("Memory allocation failed\n"); 813 ret = -ENOMEM; 814 goto out; 815 } 816 817 mutex_lock(&client->modeset_mutex); 818 819 mutex_lock(&dev->mode_config.mutex); 820 for (i = 0; i < connector_count; i++) 821 total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height); 822 if (!total_modes_count) 823 DRM_DEBUG_KMS("No connectors reported connected with modes\n"); 824 drm_client_connectors_enabled(connectors, connector_count, enabled); 825 826 if (!drm_client_firmware_config(client, connectors, connector_count, crtcs, 827 modes, offsets, enabled, width, height)) { 828 memset(modes, 0, connector_count * sizeof(*modes)); 829 memset(crtcs, 0, connector_count * sizeof(*crtcs)); 830 memset(offsets, 0, connector_count * sizeof(*offsets)); 831 832 if (!drm_client_target_cloned(dev, connectors, connector_count, modes, 833 offsets, enabled, width, height) && 834 !drm_client_target_preferred(connectors, connector_count, modes, 835 offsets, enabled, width, height)) 836 DRM_ERROR("Unable to find initial modes\n"); 837 838 DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", 839 width, height); 840 841 drm_client_pick_crtcs(client, connectors, connector_count, 842 crtcs, modes, 0, width, height); 843 } 844 mutex_unlock(&dev->mode_config.mutex); 845 846 drm_client_modeset_release(client); 847 848 for (i = 0; i < connector_count; i++) { 849 struct drm_display_mode *mode = modes[i]; 850 struct drm_crtc *crtc = crtcs[i]; 851 struct drm_client_offset *offset = &offsets[i]; 852 853 if (mode && crtc) { 854 struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc); 855 struct drm_connector *connector = connectors[i]; 856 857 DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", 858 mode->name, crtc->base.id, offset->x, offset->y); 859 860 if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS || 861 (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) { 862 ret = -EINVAL; 863 break; 864 } 865 866 modeset->mode = drm_mode_duplicate(dev, mode); 867 drm_connector_get(connector); 868 modeset->connectors[modeset->num_connectors++] = connector; 869 modeset->x = offset->x; 870 modeset->y = offset->y; 871 } 872 } 873 874 mutex_unlock(&client->modeset_mutex); 875 out: 876 kfree(crtcs); 877 kfree(modes); 878 kfree(offsets); 879 kfree(enabled); 880 free_connectors: 881 for (i = 0; i < connector_count; i++) 882 drm_connector_put(connectors[i]); 883 kfree(connectors); 884 885 return ret; 886 } 887 EXPORT_SYMBOL(drm_client_modeset_probe); 888 889 /** 890 * drm_client_rotation() - Check the initial rotation value 891 * @modeset: DRM modeset 892 * @rotation: Returned rotation value 893 * 894 * This function checks if the primary plane in @modeset can hw rotate 895 * to match the rotation needed on its connector. 896 * 897 * Note: Currently only 0 and 180 degrees are supported. 898 * 899 * Return: 900 * True if the plane can do the rotation, false otherwise. 901 */ 902 bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation) 903 { 904 struct drm_connector *connector = modeset->connectors[0]; 905 struct drm_plane *plane = modeset->crtc->primary; 906 struct drm_cmdline_mode *cmdline; 907 u64 valid_mask = 0; 908 unsigned int i; 909 910 if (!modeset->num_connectors) 911 return false; 912 913 switch (connector->display_info.panel_orientation) { 914 case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: 915 *rotation = DRM_MODE_ROTATE_180; 916 break; 917 case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: 918 *rotation = DRM_MODE_ROTATE_90; 919 break; 920 case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: 921 *rotation = DRM_MODE_ROTATE_270; 922 break; 923 default: 924 *rotation = DRM_MODE_ROTATE_0; 925 } 926 927 /** 928 * The panel already defined the default rotation 929 * through its orientation. Whatever has been provided 930 * on the command line needs to be added to that. 931 * 932 * Unfortunately, the rotations are at different bit 933 * indices, so the math to add them up are not as 934 * trivial as they could. 935 * 936 * Reflections on the other hand are pretty trivial to deal with, a 937 * simple XOR between the two handle the addition nicely. 938 */ 939 cmdline = &connector->cmdline_mode; 940 if (cmdline->specified && cmdline->rotation_reflection) { 941 unsigned int cmdline_rest, panel_rest; 942 unsigned int cmdline_rot, panel_rot; 943 unsigned int sum_rot, sum_rest; 944 945 panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK); 946 cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK); 947 sum_rot = (panel_rot + cmdline_rot) % 4; 948 949 panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK; 950 cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK; 951 sum_rest = panel_rest ^ cmdline_rest; 952 953 *rotation = (1 << sum_rot) | sum_rest; 954 } 955 956 /* 957 * TODO: support 90 / 270 degree hardware rotation, 958 * depending on the hardware this may require the framebuffer 959 * to be in a specific tiling format. 960 */ 961 if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 && 962 (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) || 963 !plane->rotation_property) 964 return false; 965 966 for (i = 0; i < plane->rotation_property->num_values; i++) 967 valid_mask |= (1ULL << plane->rotation_property->values[i]); 968 969 if (!(*rotation & valid_mask)) 970 return false; 971 972 return true; 973 } 974 EXPORT_SYMBOL(drm_client_rotation); 975 976 static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active) 977 { 978 struct drm_device *dev = client->dev; 979 struct drm_plane *plane; 980 struct drm_atomic_state *state; 981 struct drm_modeset_acquire_ctx ctx; 982 struct drm_mode_set *mode_set; 983 int ret; 984 985 drm_modeset_acquire_init(&ctx, 0); 986 987 state = drm_atomic_state_alloc(dev); 988 if (!state) { 989 ret = -ENOMEM; 990 goto out_ctx; 991 } 992 993 state->acquire_ctx = &ctx; 994 retry: 995 drm_for_each_plane(plane, dev) { 996 struct drm_plane_state *plane_state; 997 998 plane_state = drm_atomic_get_plane_state(state, plane); 999 if (IS_ERR(plane_state)) { 1000 ret = PTR_ERR(plane_state); 1001 goto out_state; 1002 } 1003 1004 plane_state->rotation = DRM_MODE_ROTATE_0; 1005 1006 /* disable non-primary: */ 1007 if (plane->type == DRM_PLANE_TYPE_PRIMARY) 1008 continue; 1009 1010 ret = __drm_atomic_helper_disable_plane(plane, plane_state); 1011 if (ret != 0) 1012 goto out_state; 1013 } 1014 1015 drm_client_for_each_modeset(mode_set, client) { 1016 struct drm_plane *primary = mode_set->crtc->primary; 1017 unsigned int rotation; 1018 1019 if (drm_client_rotation(mode_set, &rotation)) { 1020 struct drm_plane_state *plane_state; 1021 1022 /* Cannot fail as we've already gotten the plane state above */ 1023 plane_state = drm_atomic_get_new_plane_state(state, primary); 1024 plane_state->rotation = rotation; 1025 } 1026 1027 ret = __drm_atomic_helper_set_config(mode_set, state); 1028 if (ret != 0) 1029 goto out_state; 1030 1031 /* 1032 * __drm_atomic_helper_set_config() sets active when a 1033 * mode is set, unconditionally clear it if we force DPMS off 1034 */ 1035 if (!active) { 1036 struct drm_crtc *crtc = mode_set->crtc; 1037 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 1038 1039 crtc_state->active = false; 1040 } 1041 } 1042 1043 ret = drm_atomic_commit(state); 1044 1045 out_state: 1046 if (ret == -EDEADLK) 1047 goto backoff; 1048 1049 drm_atomic_state_put(state); 1050 out_ctx: 1051 drm_modeset_drop_locks(&ctx); 1052 drm_modeset_acquire_fini(&ctx); 1053 1054 return ret; 1055 1056 backoff: 1057 drm_atomic_state_clear(state); 1058 drm_modeset_backoff(&ctx); 1059 1060 goto retry; 1061 } 1062 1063 static int drm_client_modeset_commit_legacy(struct drm_client_dev *client) 1064 { 1065 struct drm_device *dev = client->dev; 1066 struct drm_mode_set *mode_set; 1067 struct drm_plane *plane; 1068 int ret = 0; 1069 1070 drm_modeset_lock_all(dev); 1071 drm_for_each_plane(plane, dev) { 1072 if (plane->type != DRM_PLANE_TYPE_PRIMARY) 1073 drm_plane_force_disable(plane); 1074 1075 if (plane->rotation_property) 1076 drm_mode_plane_set_obj_prop(plane, 1077 plane->rotation_property, 1078 DRM_MODE_ROTATE_0); 1079 } 1080 1081 drm_client_for_each_modeset(mode_set, client) { 1082 struct drm_crtc *crtc = mode_set->crtc; 1083 1084 if (crtc->funcs->cursor_set2) { 1085 ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); 1086 if (ret) 1087 goto out; 1088 } else if (crtc->funcs->cursor_set) { 1089 ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); 1090 if (ret) 1091 goto out; 1092 } 1093 1094 ret = drm_mode_set_config_internal(mode_set); 1095 if (ret) 1096 goto out; 1097 } 1098 out: 1099 drm_modeset_unlock_all(dev); 1100 1101 return ret; 1102 } 1103 1104 /** 1105 * drm_client_modeset_commit_force() - Force commit CRTC configuration 1106 * @client: DRM client 1107 * 1108 * Commit modeset configuration to crtcs without checking if there is a DRM master. 1109 * 1110 * Returns: 1111 * Zero on success or negative error code on failure. 1112 */ 1113 int drm_client_modeset_commit_force(struct drm_client_dev *client) 1114 { 1115 struct drm_device *dev = client->dev; 1116 int ret; 1117 1118 mutex_lock(&client->modeset_mutex); 1119 if (drm_drv_uses_atomic_modeset(dev)) 1120 ret = drm_client_modeset_commit_atomic(client, true); 1121 else 1122 ret = drm_client_modeset_commit_legacy(client); 1123 mutex_unlock(&client->modeset_mutex); 1124 1125 return ret; 1126 } 1127 EXPORT_SYMBOL(drm_client_modeset_commit_force); 1128 1129 /** 1130 * drm_client_modeset_commit() - Commit CRTC configuration 1131 * @client: DRM client 1132 * 1133 * Commit modeset configuration to crtcs. 1134 * 1135 * Returns: 1136 * Zero on success or negative error code on failure. 1137 */ 1138 int drm_client_modeset_commit(struct drm_client_dev *client) 1139 { 1140 struct drm_device *dev = client->dev; 1141 int ret; 1142 1143 if (!drm_master_internal_acquire(dev)) 1144 return -EBUSY; 1145 1146 ret = drm_client_modeset_commit_force(client); 1147 1148 drm_master_internal_release(dev); 1149 1150 return ret; 1151 } 1152 EXPORT_SYMBOL(drm_client_modeset_commit); 1153 1154 static void drm_client_modeset_dpms_legacy(struct drm_client_dev *client, int dpms_mode) 1155 { 1156 struct drm_device *dev = client->dev; 1157 struct drm_connector *connector; 1158 struct drm_mode_set *modeset; 1159 int j; 1160 1161 drm_modeset_lock_all(dev); 1162 drm_client_for_each_modeset(modeset, client) { 1163 if (!modeset->crtc->enabled) 1164 continue; 1165 1166 for (j = 0; j < modeset->num_connectors; j++) { 1167 connector = modeset->connectors[j]; 1168 connector->funcs->dpms(connector, dpms_mode); 1169 drm_object_property_set_value(&connector->base, 1170 dev->mode_config.dpms_property, dpms_mode); 1171 } 1172 } 1173 drm_modeset_unlock_all(dev); 1174 } 1175 1176 /** 1177 * drm_client_modeset_dpms() - Set DPMS mode 1178 * @client: DRM client 1179 * @mode: DPMS mode 1180 * 1181 * Note: For atomic drivers @mode is reduced to on/off. 1182 * 1183 * Returns: 1184 * Zero on success or negative error code on failure. 1185 */ 1186 int drm_client_modeset_dpms(struct drm_client_dev *client, int mode) 1187 { 1188 struct drm_device *dev = client->dev; 1189 int ret = 0; 1190 1191 if (!drm_master_internal_acquire(dev)) 1192 return -EBUSY; 1193 1194 mutex_lock(&client->modeset_mutex); 1195 if (drm_drv_uses_atomic_modeset(dev)) 1196 ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON); 1197 else 1198 drm_client_modeset_dpms_legacy(client, mode); 1199 mutex_unlock(&client->modeset_mutex); 1200 1201 drm_master_internal_release(dev); 1202 1203 return ret; 1204 } 1205 EXPORT_SYMBOL(drm_client_modeset_dpms); 1206