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