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