0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "drm/drm_modeset_lock.h"
0011 #include <linux/module.h>
0012 #include <linux/mutex.h>
0013 #include <linux/slab.h>
0014 #include <linux/string_helpers.h>
0015
0016 #include <drm/drm_atomic.h>
0017 #include <drm/drm_client.h>
0018 #include <drm/drm_connector.h>
0019 #include <drm/drm_crtc.h>
0020 #include <drm/drm_device.h>
0021 #include <drm/drm_drv.h>
0022 #include <drm/drm_edid.h>
0023 #include <drm/drm_encoder.h>
0024 #include <drm/drm_print.h>
0025
0026 #include "drm_crtc_internal.h"
0027 #include "drm_internal.h"
0028
0029 #define DRM_CLIENT_MAX_CLONED_CONNECTORS 8
0030
0031 struct drm_client_offset {
0032 int x, y;
0033 };
0034
0035 int drm_client_modeset_create(struct drm_client_dev *client)
0036 {
0037 struct drm_device *dev = client->dev;
0038 unsigned int num_crtc = dev->mode_config.num_crtc;
0039 unsigned int max_connector_count = 1;
0040 struct drm_mode_set *modeset;
0041 struct drm_crtc *crtc;
0042 unsigned int i = 0;
0043
0044
0045 client->modesets = kcalloc(num_crtc + 1, sizeof(*client->modesets), GFP_KERNEL);
0046 if (!client->modesets)
0047 return -ENOMEM;
0048
0049 mutex_init(&client->modeset_mutex);
0050
0051 drm_for_each_crtc(crtc, dev)
0052 client->modesets[i++].crtc = crtc;
0053
0054
0055 if (num_crtc == 1)
0056 max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS;
0057
0058 for (modeset = client->modesets; modeset->crtc; modeset++) {
0059 modeset->connectors = kcalloc(max_connector_count,
0060 sizeof(*modeset->connectors), GFP_KERNEL);
0061 if (!modeset->connectors)
0062 goto err_free;
0063 }
0064
0065 return 0;
0066
0067 err_free:
0068 drm_client_modeset_free(client);
0069
0070 return -ENOMEM;
0071 }
0072
0073 static void drm_client_modeset_release(struct drm_client_dev *client)
0074 {
0075 struct drm_mode_set *modeset;
0076 unsigned int i;
0077
0078 drm_client_for_each_modeset(modeset, client) {
0079 drm_mode_destroy(client->dev, modeset->mode);
0080 modeset->mode = NULL;
0081 modeset->fb = NULL;
0082
0083 for (i = 0; i < modeset->num_connectors; i++) {
0084 drm_connector_put(modeset->connectors[i]);
0085 modeset->connectors[i] = NULL;
0086 }
0087 modeset->num_connectors = 0;
0088 }
0089 }
0090
0091 void drm_client_modeset_free(struct drm_client_dev *client)
0092 {
0093 struct drm_mode_set *modeset;
0094
0095 mutex_lock(&client->modeset_mutex);
0096
0097 drm_client_modeset_release(client);
0098
0099 drm_client_for_each_modeset(modeset, client)
0100 kfree(modeset->connectors);
0101
0102 mutex_unlock(&client->modeset_mutex);
0103
0104 mutex_destroy(&client->modeset_mutex);
0105 kfree(client->modesets);
0106 }
0107
0108 static struct drm_mode_set *
0109 drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
0110 {
0111 struct drm_mode_set *modeset;
0112
0113 drm_client_for_each_modeset(modeset, client)
0114 if (modeset->crtc == crtc)
0115 return modeset;
0116
0117 return NULL;
0118 }
0119
0120 static struct drm_display_mode *
0121 drm_connector_get_tiled_mode(struct drm_connector *connector)
0122 {
0123 struct drm_display_mode *mode;
0124
0125 list_for_each_entry(mode, &connector->modes, head) {
0126 if (mode->hdisplay == connector->tile_h_size &&
0127 mode->vdisplay == connector->tile_v_size)
0128 return mode;
0129 }
0130 return NULL;
0131 }
0132
0133 static struct drm_display_mode *
0134 drm_connector_fallback_non_tiled_mode(struct drm_connector *connector)
0135 {
0136 struct drm_display_mode *mode;
0137
0138 list_for_each_entry(mode, &connector->modes, head) {
0139 if (mode->hdisplay == connector->tile_h_size &&
0140 mode->vdisplay == connector->tile_v_size)
0141 continue;
0142 return mode;
0143 }
0144 return NULL;
0145 }
0146
0147 static struct drm_display_mode *
0148 drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height)
0149 {
0150 struct drm_display_mode *mode;
0151
0152 list_for_each_entry(mode, &connector->modes, head) {
0153 if (mode->hdisplay > width ||
0154 mode->vdisplay > height)
0155 continue;
0156 if (mode->type & DRM_MODE_TYPE_PREFERRED)
0157 return mode;
0158 }
0159 return NULL;
0160 }
0161
0162 static struct drm_display_mode *drm_connector_pick_cmdline_mode(struct drm_connector *connector)
0163 {
0164 struct drm_cmdline_mode *cmdline_mode;
0165 struct drm_display_mode *mode;
0166 bool prefer_non_interlace;
0167
0168
0169
0170
0171
0172
0173
0174 list_for_each_entry(mode, &connector->modes, head) {
0175 if (mode->type & DRM_MODE_TYPE_USERDEF)
0176 return mode;
0177 }
0178
0179 cmdline_mode = &connector->cmdline_mode;
0180 if (cmdline_mode->specified == false)
0181 return NULL;
0182
0183
0184
0185
0186
0187
0188 prefer_non_interlace = !cmdline_mode->interlace;
0189 again:
0190 list_for_each_entry(mode, &connector->modes, head) {
0191
0192 if (!strcmp(mode->name, cmdline_mode->name))
0193 return mode;
0194
0195
0196 if (mode->hdisplay != cmdline_mode->xres ||
0197 mode->vdisplay != cmdline_mode->yres)
0198 continue;
0199
0200 if (cmdline_mode->refresh_specified) {
0201 if (drm_mode_vrefresh(mode) != cmdline_mode->refresh)
0202 continue;
0203 }
0204
0205 if (cmdline_mode->interlace) {
0206 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
0207 continue;
0208 } else if (prefer_non_interlace) {
0209 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
0210 continue;
0211 }
0212 return mode;
0213 }
0214
0215 if (prefer_non_interlace) {
0216 prefer_non_interlace = false;
0217 goto again;
0218 }
0219
0220 return NULL;
0221 }
0222
0223 static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
0224 {
0225 bool enable;
0226
0227 if (connector->display_info.non_desktop)
0228 return false;
0229
0230 if (strict)
0231 enable = connector->status == connector_status_connected;
0232 else
0233 enable = connector->status != connector_status_disconnected;
0234
0235 return enable;
0236 }
0237
0238 static void drm_client_connectors_enabled(struct drm_connector **connectors,
0239 unsigned int connector_count,
0240 bool *enabled)
0241 {
0242 bool any_enabled = false;
0243 struct drm_connector *connector;
0244 int i = 0;
0245
0246 for (i = 0; i < connector_count; i++) {
0247 connector = connectors[i];
0248 enabled[i] = drm_connector_enabled(connector, true);
0249 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
0250 connector->display_info.non_desktop ? "non desktop" : str_yes_no(enabled[i]));
0251
0252 any_enabled |= enabled[i];
0253 }
0254
0255 if (any_enabled)
0256 return;
0257
0258 for (i = 0; i < connector_count; i++)
0259 enabled[i] = drm_connector_enabled(connectors[i], false);
0260 }
0261
0262 static bool drm_client_target_cloned(struct drm_device *dev,
0263 struct drm_connector **connectors,
0264 unsigned int connector_count,
0265 struct drm_display_mode **modes,
0266 struct drm_client_offset *offsets,
0267 bool *enabled, int width, int height)
0268 {
0269 int count, i, j;
0270 bool can_clone = false;
0271 struct drm_display_mode *dmt_mode, *mode;
0272
0273
0274 if (dev->mode_config.num_crtc > 1)
0275 return false;
0276
0277 count = 0;
0278 for (i = 0; i < connector_count; i++) {
0279 if (enabled[i])
0280 count++;
0281 }
0282
0283
0284 if (count <= 1)
0285 return false;
0286
0287
0288 can_clone = true;
0289 for (i = 0; i < connector_count; i++) {
0290 if (!enabled[i])
0291 continue;
0292 modes[i] = drm_connector_pick_cmdline_mode(connectors[i]);
0293 if (!modes[i]) {
0294 can_clone = false;
0295 break;
0296 }
0297 for (j = 0; j < i; j++) {
0298 if (!enabled[j])
0299 continue;
0300 if (!drm_mode_match(modes[j], modes[i],
0301 DRM_MODE_MATCH_TIMINGS |
0302 DRM_MODE_MATCH_CLOCK |
0303 DRM_MODE_MATCH_FLAGS |
0304 DRM_MODE_MATCH_3D_FLAGS))
0305 can_clone = false;
0306 }
0307 }
0308
0309 if (can_clone) {
0310 DRM_DEBUG_KMS("can clone using command line\n");
0311 return true;
0312 }
0313
0314
0315 can_clone = true;
0316 dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
0317
0318 for (i = 0; i < connector_count; i++) {
0319 if (!enabled[i])
0320 continue;
0321
0322 list_for_each_entry(mode, &connectors[i]->modes, head) {
0323 if (drm_mode_match(mode, dmt_mode,
0324 DRM_MODE_MATCH_TIMINGS |
0325 DRM_MODE_MATCH_CLOCK |
0326 DRM_MODE_MATCH_FLAGS |
0327 DRM_MODE_MATCH_3D_FLAGS))
0328 modes[i] = mode;
0329 }
0330 if (!modes[i])
0331 can_clone = false;
0332 }
0333
0334 if (can_clone) {
0335 DRM_DEBUG_KMS("can clone using 1024x768\n");
0336 return true;
0337 }
0338 DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
0339 return false;
0340 }
0341
0342 static int drm_client_get_tile_offsets(struct drm_connector **connectors,
0343 unsigned int connector_count,
0344 struct drm_display_mode **modes,
0345 struct drm_client_offset *offsets,
0346 int idx,
0347 int h_idx, int v_idx)
0348 {
0349 struct drm_connector *connector;
0350 int i;
0351 int hoffset = 0, voffset = 0;
0352
0353 for (i = 0; i < connector_count; i++) {
0354 connector = connectors[i];
0355 if (!connector->has_tile)
0356 continue;
0357
0358 if (!modes[i] && (h_idx || v_idx)) {
0359 DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
0360 connector->base.id);
0361 continue;
0362 }
0363 if (connector->tile_h_loc < h_idx)
0364 hoffset += modes[i]->hdisplay;
0365
0366 if (connector->tile_v_loc < v_idx)
0367 voffset += modes[i]->vdisplay;
0368 }
0369 offsets[idx].x = hoffset;
0370 offsets[idx].y = voffset;
0371 DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx);
0372 return 0;
0373 }
0374
0375 static bool drm_client_target_preferred(struct drm_connector **connectors,
0376 unsigned int connector_count,
0377 struct drm_display_mode **modes,
0378 struct drm_client_offset *offsets,
0379 bool *enabled, int width, int height)
0380 {
0381 const u64 mask = BIT_ULL(connector_count) - 1;
0382 struct drm_connector *connector;
0383 u64 conn_configured = 0;
0384 int tile_pass = 0;
0385 int num_tiled_conns = 0;
0386 int i;
0387
0388 for (i = 0; i < connector_count; i++) {
0389 if (connectors[i]->has_tile &&
0390 connectors[i]->status == connector_status_connected)
0391 num_tiled_conns++;
0392 }
0393
0394 retry:
0395 for (i = 0; i < connector_count; i++) {
0396 connector = connectors[i];
0397
0398 if (conn_configured & BIT_ULL(i))
0399 continue;
0400
0401 if (enabled[i] == false) {
0402 conn_configured |= BIT_ULL(i);
0403 continue;
0404 }
0405
0406
0407 if (tile_pass == 0 && connector->has_tile)
0408 continue;
0409
0410 if (tile_pass == 1) {
0411 if (connector->tile_h_loc != 0 ||
0412 connector->tile_v_loc != 0)
0413 continue;
0414
0415 } else {
0416 if (connector->tile_h_loc != tile_pass - 1 &&
0417 connector->tile_v_loc != tile_pass - 1)
0418
0419 continue;
0420
0421
0422
0423
0424
0425 drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i,
0426 connector->tile_h_loc, connector->tile_v_loc);
0427 }
0428 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
0429 connector->base.id);
0430
0431
0432 modes[i] = drm_connector_pick_cmdline_mode(connector);
0433 if (!modes[i]) {
0434 DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
0435 connector->base.id, connector->tile_group ? connector->tile_group->id : 0);
0436 modes[i] = drm_connector_has_preferred_mode(connector, width, height);
0437 }
0438
0439 if (!modes[i] && !list_empty(&connector->modes)) {
0440 list_for_each_entry(modes[i], &connector->modes, head)
0441 break;
0442 }
0443
0444
0445
0446
0447
0448
0449
0450
0451 if (connector->has_tile) {
0452 if (num_tiled_conns <
0453 connector->num_h_tile * connector->num_v_tile ||
0454 (connector->tile_h_loc == 0 &&
0455 connector->tile_v_loc == 0 &&
0456 !drm_connector_get_tiled_mode(connector))) {
0457 DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n",
0458 connector->base.id);
0459 modes[i] = drm_connector_fallback_non_tiled_mode(connector);
0460 } else {
0461 modes[i] = drm_connector_get_tiled_mode(connector);
0462 }
0463 }
0464
0465 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
0466 "none");
0467 conn_configured |= BIT_ULL(i);
0468 }
0469
0470 if ((conn_configured & mask) != mask) {
0471 tile_pass++;
0472 goto retry;
0473 }
0474 return true;
0475 }
0476
0477 static bool connector_has_possible_crtc(struct drm_connector *connector,
0478 struct drm_crtc *crtc)
0479 {
0480 struct drm_encoder *encoder;
0481
0482 drm_connector_for_each_possible_encoder(connector, encoder) {
0483 if (encoder->possible_crtcs & drm_crtc_mask(crtc))
0484 return true;
0485 }
0486
0487 return false;
0488 }
0489
0490 static int drm_client_pick_crtcs(struct drm_client_dev *client,
0491 struct drm_connector **connectors,
0492 unsigned int connector_count,
0493 struct drm_crtc **best_crtcs,
0494 struct drm_display_mode **modes,
0495 int n, int width, int height)
0496 {
0497 struct drm_device *dev = client->dev;
0498 struct drm_connector *connector;
0499 int my_score, best_score, score;
0500 struct drm_crtc **crtcs, *crtc;
0501 struct drm_mode_set *modeset;
0502 int o;
0503
0504 if (n == connector_count)
0505 return 0;
0506
0507 connector = connectors[n];
0508
0509 best_crtcs[n] = NULL;
0510 best_score = drm_client_pick_crtcs(client, connectors, connector_count,
0511 best_crtcs, modes, n + 1, width, height);
0512 if (modes[n] == NULL)
0513 return best_score;
0514
0515 crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
0516 if (!crtcs)
0517 return best_score;
0518
0519 my_score = 1;
0520 if (connector->status == connector_status_connected)
0521 my_score++;
0522 if (connector->cmdline_mode.specified)
0523 my_score++;
0524 if (drm_connector_has_preferred_mode(connector, width, height))
0525 my_score++;
0526
0527
0528
0529
0530
0531 drm_client_for_each_modeset(modeset, client) {
0532 crtc = modeset->crtc;
0533
0534 if (!connector_has_possible_crtc(connector, crtc))
0535 continue;
0536
0537 for (o = 0; o < n; o++)
0538 if (best_crtcs[o] == crtc)
0539 break;
0540
0541 if (o < n) {
0542
0543 if (dev->mode_config.num_crtc > 1)
0544 continue;
0545
0546 if (!drm_mode_equal(modes[o], modes[n]))
0547 continue;
0548 }
0549
0550 crtcs[n] = crtc;
0551 memcpy(crtcs, best_crtcs, n * sizeof(*crtcs));
0552 score = my_score + drm_client_pick_crtcs(client, connectors, connector_count,
0553 crtcs, modes, n + 1, width, height);
0554 if (score > best_score) {
0555 best_score = score;
0556 memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs));
0557 }
0558 }
0559
0560 kfree(crtcs);
0561 return best_score;
0562 }
0563
0564
0565 static bool drm_client_firmware_config(struct drm_client_dev *client,
0566 struct drm_connector **connectors,
0567 unsigned int connector_count,
0568 struct drm_crtc **crtcs,
0569 struct drm_display_mode **modes,
0570 struct drm_client_offset *offsets,
0571 bool *enabled, int width, int height)
0572 {
0573 const int count = min_t(unsigned int, connector_count, BITS_PER_LONG);
0574 unsigned long conn_configured, conn_seq, mask;
0575 struct drm_device *dev = client->dev;
0576 int i, j;
0577 bool *save_enabled;
0578 bool fallback = true, ret = true;
0579 int num_connectors_enabled = 0;
0580 int num_connectors_detected = 0;
0581 int num_tiled_conns = 0;
0582 struct drm_modeset_acquire_ctx ctx;
0583
0584 if (!drm_drv_uses_atomic_modeset(dev))
0585 return false;
0586
0587 if (WARN_ON(count <= 0))
0588 return false;
0589
0590 save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
0591 if (!save_enabled)
0592 return false;
0593
0594 drm_modeset_acquire_init(&ctx, 0);
0595
0596 while (drm_modeset_lock_all_ctx(dev, &ctx) != 0)
0597 drm_modeset_backoff(&ctx);
0598
0599 memcpy(save_enabled, enabled, count);
0600 mask = GENMASK(count - 1, 0);
0601 conn_configured = 0;
0602 for (i = 0; i < count; i++) {
0603 if (connectors[i]->has_tile &&
0604 connectors[i]->status == connector_status_connected)
0605 num_tiled_conns++;
0606 }
0607 retry:
0608 conn_seq = conn_configured;
0609 for (i = 0; i < count; i++) {
0610 struct drm_connector *connector;
0611 struct drm_encoder *encoder;
0612 struct drm_crtc *new_crtc;
0613
0614 connector = connectors[i];
0615
0616 if (conn_configured & BIT(i))
0617 continue;
0618
0619 if (conn_seq == 0 && !connector->has_tile)
0620 continue;
0621
0622 if (connector->status == connector_status_connected)
0623 num_connectors_detected++;
0624
0625 if (!enabled[i]) {
0626 DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
0627 connector->name);
0628 conn_configured |= BIT(i);
0629 continue;
0630 }
0631
0632 if (connector->force == DRM_FORCE_OFF) {
0633 DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
0634 connector->name);
0635 enabled[i] = false;
0636 continue;
0637 }
0638
0639 encoder = connector->state->best_encoder;
0640 if (!encoder || WARN_ON(!connector->state->crtc)) {
0641 if (connector->force > DRM_FORCE_OFF)
0642 goto bail;
0643
0644 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
0645 connector->name);
0646 enabled[i] = false;
0647 conn_configured |= BIT(i);
0648 continue;
0649 }
0650
0651 num_connectors_enabled++;
0652
0653 new_crtc = connector->state->crtc;
0654
0655
0656
0657
0658
0659
0660 for (j = 0; j < count; j++) {
0661 if (crtcs[j] == new_crtc) {
0662 DRM_DEBUG_KMS("fallback: cloned configuration\n");
0663 goto bail;
0664 }
0665 }
0666
0667 DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
0668 connector->name);
0669
0670
0671 modes[i] = drm_connector_pick_cmdline_mode(connector);
0672
0673
0674 if (!modes[i]) {
0675 DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
0676 connector->name, connector->has_tile);
0677 modes[i] = drm_connector_has_preferred_mode(connector, width, height);
0678 }
0679
0680
0681 if (!modes[i] && !list_empty(&connector->modes)) {
0682 DRM_DEBUG_KMS("using first mode listed on connector %s\n",
0683 connector->name);
0684 modes[i] = list_first_entry(&connector->modes,
0685 struct drm_display_mode,
0686 head);
0687 }
0688
0689
0690 if (!modes[i]) {
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702 DRM_DEBUG_KMS("looking for current mode on connector %s\n",
0703 connector->name);
0704 modes[i] = &connector->state->crtc->mode;
0705 }
0706
0707
0708
0709
0710 if (connector->has_tile &&
0711 num_tiled_conns < connector->num_h_tile * connector->num_v_tile) {
0712 DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n",
0713 connector->base.id);
0714 modes[i] = drm_connector_fallback_non_tiled_mode(connector);
0715 }
0716 crtcs[i] = new_crtc;
0717
0718 DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n",
0719 connector->name,
0720 connector->state->crtc->base.id,
0721 connector->state->crtc->name,
0722 modes[i]->hdisplay, modes[i]->vdisplay,
0723 modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "");
0724
0725 fallback = false;
0726 conn_configured |= BIT(i);
0727 }
0728
0729 if ((conn_configured & mask) != mask && conn_configured != conn_seq)
0730 goto retry;
0731
0732
0733
0734
0735
0736
0737 if (num_connectors_enabled != num_connectors_detected &&
0738 num_connectors_enabled < dev->mode_config.num_crtc) {
0739 DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
0740 DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
0741 num_connectors_detected);
0742 fallback = true;
0743 }
0744
0745 if (fallback) {
0746 bail:
0747 DRM_DEBUG_KMS("Not using firmware configuration\n");
0748 memcpy(enabled, save_enabled, count);
0749 ret = false;
0750 }
0751
0752 drm_modeset_drop_locks(&ctx);
0753 drm_modeset_acquire_fini(&ctx);
0754
0755 kfree(save_enabled);
0756 return ret;
0757 }
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771 int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height)
0772 {
0773 struct drm_connector *connector, **connectors = NULL;
0774 struct drm_connector_list_iter conn_iter;
0775 struct drm_device *dev = client->dev;
0776 unsigned int total_modes_count = 0;
0777 struct drm_client_offset *offsets;
0778 unsigned int connector_count = 0;
0779 struct drm_display_mode **modes;
0780 struct drm_crtc **crtcs;
0781 int i, ret = 0;
0782 bool *enabled;
0783
0784 DRM_DEBUG_KMS("\n");
0785
0786 if (!width)
0787 width = dev->mode_config.max_width;
0788 if (!height)
0789 height = dev->mode_config.max_height;
0790
0791 drm_connector_list_iter_begin(dev, &conn_iter);
0792 drm_client_for_each_connector_iter(connector, &conn_iter) {
0793 struct drm_connector **tmp;
0794
0795 tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL);
0796 if (!tmp) {
0797 ret = -ENOMEM;
0798 goto free_connectors;
0799 }
0800
0801 connectors = tmp;
0802 drm_connector_get(connector);
0803 connectors[connector_count++] = connector;
0804 }
0805 drm_connector_list_iter_end(&conn_iter);
0806
0807 if (!connector_count)
0808 return 0;
0809
0810 crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
0811 modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL);
0812 offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL);
0813 enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL);
0814 if (!crtcs || !modes || !enabled || !offsets) {
0815 DRM_ERROR("Memory allocation failed\n");
0816 ret = -ENOMEM;
0817 goto out;
0818 }
0819
0820 mutex_lock(&client->modeset_mutex);
0821
0822 mutex_lock(&dev->mode_config.mutex);
0823 for (i = 0; i < connector_count; i++)
0824 total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height);
0825 if (!total_modes_count)
0826 DRM_DEBUG_KMS("No connectors reported connected with modes\n");
0827 drm_client_connectors_enabled(connectors, connector_count, enabled);
0828
0829 if (!drm_client_firmware_config(client, connectors, connector_count, crtcs,
0830 modes, offsets, enabled, width, height)) {
0831 memset(modes, 0, connector_count * sizeof(*modes));
0832 memset(crtcs, 0, connector_count * sizeof(*crtcs));
0833 memset(offsets, 0, connector_count * sizeof(*offsets));
0834
0835 if (!drm_client_target_cloned(dev, connectors, connector_count, modes,
0836 offsets, enabled, width, height) &&
0837 !drm_client_target_preferred(connectors, connector_count, modes,
0838 offsets, enabled, width, height))
0839 DRM_ERROR("Unable to find initial modes\n");
0840
0841 DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
0842 width, height);
0843
0844 drm_client_pick_crtcs(client, connectors, connector_count,
0845 crtcs, modes, 0, width, height);
0846 }
0847 mutex_unlock(&dev->mode_config.mutex);
0848
0849 drm_client_modeset_release(client);
0850
0851 for (i = 0; i < connector_count; i++) {
0852 struct drm_display_mode *mode = modes[i];
0853 struct drm_crtc *crtc = crtcs[i];
0854 struct drm_client_offset *offset = &offsets[i];
0855
0856 if (mode && crtc) {
0857 struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc);
0858 struct drm_connector *connector = connectors[i];
0859
0860 DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
0861 mode->name, crtc->base.id, offset->x, offset->y);
0862
0863 if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS ||
0864 (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) {
0865 ret = -EINVAL;
0866 break;
0867 }
0868
0869 modeset->mode = drm_mode_duplicate(dev, mode);
0870 drm_connector_get(connector);
0871 modeset->connectors[modeset->num_connectors++] = connector;
0872 modeset->x = offset->x;
0873 modeset->y = offset->y;
0874 }
0875 }
0876
0877 mutex_unlock(&client->modeset_mutex);
0878 out:
0879 kfree(crtcs);
0880 kfree(modes);
0881 kfree(offsets);
0882 kfree(enabled);
0883 free_connectors:
0884 for (i = 0; i < connector_count; i++)
0885 drm_connector_put(connectors[i]);
0886 kfree(connectors);
0887
0888 return ret;
0889 }
0890 EXPORT_SYMBOL(drm_client_modeset_probe);
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905 bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
0906 {
0907 struct drm_connector *connector = modeset->connectors[0];
0908 struct drm_plane *plane = modeset->crtc->primary;
0909 struct drm_cmdline_mode *cmdline;
0910 u64 valid_mask = 0;
0911 unsigned int i;
0912
0913 if (!modeset->num_connectors)
0914 return false;
0915
0916 switch (connector->display_info.panel_orientation) {
0917 case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
0918 *rotation = DRM_MODE_ROTATE_180;
0919 break;
0920 case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
0921 *rotation = DRM_MODE_ROTATE_90;
0922 break;
0923 case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
0924 *rotation = DRM_MODE_ROTATE_270;
0925 break;
0926 default:
0927 *rotation = DRM_MODE_ROTATE_0;
0928 }
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942 cmdline = &connector->cmdline_mode;
0943 if (cmdline->specified && cmdline->rotation_reflection) {
0944 unsigned int cmdline_rest, panel_rest;
0945 unsigned int cmdline_rot, panel_rot;
0946 unsigned int sum_rot, sum_rest;
0947
0948 panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
0949 cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
0950 sum_rot = (panel_rot + cmdline_rot) % 4;
0951
0952 panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
0953 cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK;
0954 sum_rest = panel_rest ^ cmdline_rest;
0955
0956 *rotation = (1 << sum_rot) | sum_rest;
0957 }
0958
0959
0960
0961
0962
0963
0964 if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
0965 (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
0966 !plane->rotation_property)
0967 return false;
0968
0969 for (i = 0; i < plane->rotation_property->num_values; i++)
0970 valid_mask |= (1ULL << plane->rotation_property->values[i]);
0971
0972 if (!(*rotation & valid_mask))
0973 return false;
0974
0975 return true;
0976 }
0977 EXPORT_SYMBOL(drm_client_rotation);
0978
0979 static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active, bool check)
0980 {
0981 struct drm_device *dev = client->dev;
0982 struct drm_plane *plane;
0983 struct drm_atomic_state *state;
0984 struct drm_modeset_acquire_ctx ctx;
0985 struct drm_mode_set *mode_set;
0986 int ret;
0987
0988 drm_modeset_acquire_init(&ctx, 0);
0989
0990 state = drm_atomic_state_alloc(dev);
0991 if (!state) {
0992 ret = -ENOMEM;
0993 goto out_ctx;
0994 }
0995
0996 state->acquire_ctx = &ctx;
0997 retry:
0998 drm_for_each_plane(plane, dev) {
0999 struct drm_plane_state *plane_state;
1000
1001 plane_state = drm_atomic_get_plane_state(state, plane);
1002 if (IS_ERR(plane_state)) {
1003 ret = PTR_ERR(plane_state);
1004 goto out_state;
1005 }
1006
1007 plane_state->rotation = DRM_MODE_ROTATE_0;
1008
1009
1010 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
1011 continue;
1012
1013 ret = __drm_atomic_helper_disable_plane(plane, plane_state);
1014 if (ret != 0)
1015 goto out_state;
1016 }
1017
1018 drm_client_for_each_modeset(mode_set, client) {
1019 struct drm_plane *primary = mode_set->crtc->primary;
1020 unsigned int rotation;
1021
1022 if (drm_client_rotation(mode_set, &rotation)) {
1023 struct drm_plane_state *plane_state;
1024
1025
1026 plane_state = drm_atomic_get_new_plane_state(state, primary);
1027 plane_state->rotation = rotation;
1028 }
1029
1030 ret = __drm_atomic_helper_set_config(mode_set, state);
1031 if (ret != 0)
1032 goto out_state;
1033
1034
1035
1036
1037
1038 if (!active) {
1039 struct drm_crtc *crtc = mode_set->crtc;
1040 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1041
1042 crtc_state->active = false;
1043 }
1044 }
1045
1046 if (check)
1047 ret = drm_atomic_check_only(state);
1048 else
1049 ret = drm_atomic_commit(state);
1050
1051 out_state:
1052 if (ret == -EDEADLK)
1053 goto backoff;
1054
1055 drm_atomic_state_put(state);
1056 out_ctx:
1057 drm_modeset_drop_locks(&ctx);
1058 drm_modeset_acquire_fini(&ctx);
1059
1060 return ret;
1061
1062 backoff:
1063 drm_atomic_state_clear(state);
1064 drm_modeset_backoff(&ctx);
1065
1066 goto retry;
1067 }
1068
1069 static int drm_client_modeset_commit_legacy(struct drm_client_dev *client)
1070 {
1071 struct drm_device *dev = client->dev;
1072 struct drm_mode_set *mode_set;
1073 struct drm_plane *plane;
1074 int ret = 0;
1075
1076 drm_modeset_lock_all(dev);
1077 drm_for_each_plane(plane, dev) {
1078 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
1079 drm_plane_force_disable(plane);
1080
1081 if (plane->rotation_property)
1082 drm_mode_plane_set_obj_prop(plane,
1083 plane->rotation_property,
1084 DRM_MODE_ROTATE_0);
1085 }
1086
1087 drm_client_for_each_modeset(mode_set, client) {
1088 struct drm_crtc *crtc = mode_set->crtc;
1089
1090 if (crtc->funcs->cursor_set2) {
1091 ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
1092 if (ret)
1093 goto out;
1094 } else if (crtc->funcs->cursor_set) {
1095 ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
1096 if (ret)
1097 goto out;
1098 }
1099
1100 ret = drm_mode_set_config_internal(mode_set);
1101 if (ret)
1102 goto out;
1103 }
1104 out:
1105 drm_modeset_unlock_all(dev);
1106
1107 return ret;
1108 }
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 int drm_client_modeset_check(struct drm_client_dev *client)
1120 {
1121 int ret;
1122
1123 if (!drm_drv_uses_atomic_modeset(client->dev))
1124 return 0;
1125
1126 mutex_lock(&client->modeset_mutex);
1127 ret = drm_client_modeset_commit_atomic(client, true, true);
1128 mutex_unlock(&client->modeset_mutex);
1129
1130 return ret;
1131 }
1132 EXPORT_SYMBOL(drm_client_modeset_check);
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145 int drm_client_modeset_commit_locked(struct drm_client_dev *client)
1146 {
1147 struct drm_device *dev = client->dev;
1148 int ret;
1149
1150 mutex_lock(&client->modeset_mutex);
1151 if (drm_drv_uses_atomic_modeset(dev))
1152 ret = drm_client_modeset_commit_atomic(client, true, false);
1153 else
1154 ret = drm_client_modeset_commit_legacy(client);
1155 mutex_unlock(&client->modeset_mutex);
1156
1157 return ret;
1158 }
1159 EXPORT_SYMBOL(drm_client_modeset_commit_locked);
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170 int drm_client_modeset_commit(struct drm_client_dev *client)
1171 {
1172 struct drm_device *dev = client->dev;
1173 int ret;
1174
1175 if (!drm_master_internal_acquire(dev))
1176 return -EBUSY;
1177
1178 ret = drm_client_modeset_commit_locked(client);
1179
1180 drm_master_internal_release(dev);
1181
1182 return ret;
1183 }
1184 EXPORT_SYMBOL(drm_client_modeset_commit);
1185
1186 static void drm_client_modeset_dpms_legacy(struct drm_client_dev *client, int dpms_mode)
1187 {
1188 struct drm_device *dev = client->dev;
1189 struct drm_connector *connector;
1190 struct drm_mode_set *modeset;
1191 struct drm_modeset_acquire_ctx ctx;
1192 int j;
1193 int ret;
1194
1195 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
1196 drm_client_for_each_modeset(modeset, client) {
1197 if (!modeset->crtc->enabled)
1198 continue;
1199
1200 for (j = 0; j < modeset->num_connectors; j++) {
1201 connector = modeset->connectors[j];
1202 connector->funcs->dpms(connector, dpms_mode);
1203 drm_object_property_set_value(&connector->base,
1204 dev->mode_config.dpms_property, dpms_mode);
1205 }
1206 }
1207 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
1208 }
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220 int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
1221 {
1222 struct drm_device *dev = client->dev;
1223 int ret = 0;
1224
1225 if (!drm_master_internal_acquire(dev))
1226 return -EBUSY;
1227
1228 mutex_lock(&client->modeset_mutex);
1229 if (drm_drv_uses_atomic_modeset(dev))
1230 ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON, false);
1231 else
1232 drm_client_modeset_dpms_legacy(client, mode);
1233 mutex_unlock(&client->modeset_mutex);
1234
1235 drm_master_internal_release(dev);
1236
1237 return ret;
1238 }
1239 EXPORT_SYMBOL(drm_client_modeset_dpms);