Rev 6935 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6935 | Rev 6937 | ||
---|---|---|---|
Line 50... | Line 50... | ||
50 | * This library also provides implementations for all the legacy driver |
50 | * This library also provides implementations for all the legacy driver |
51 | * interfaces on top of the atomic interface. See drm_atomic_helper_set_config(), |
51 | * interfaces on top of the atomic interface. See drm_atomic_helper_set_config(), |
52 | * drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the |
52 | * drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the |
53 | * various functions to implement set_property callbacks. New drivers must not |
53 | * various functions to implement set_property callbacks. New drivers must not |
54 | * implement these functions themselves but must use the provided helpers. |
54 | * implement these functions themselves but must use the provided helpers. |
- | 55 | * |
|
- | 56 | * The atomic helper uses the same function table structures as all other |
|
- | 57 | * modesetting helpers. See the documentation for struct &drm_crtc_helper_funcs, |
|
- | 58 | * struct &drm_encoder_helper_funcs and struct &drm_connector_helper_funcs. It |
|
- | 59 | * also shares the struct &drm_plane_helper_funcs function table with the plane |
|
- | 60 | * helpers. |
|
55 | */ |
61 | */ |
56 | static void |
62 | static void |
57 | drm_atomic_helper_plane_changed(struct drm_atomic_state *state, |
63 | drm_atomic_helper_plane_changed(struct drm_atomic_state *state, |
58 | struct drm_plane_state *plane_state, |
64 | struct drm_plane_state *plane_state, |
59 | struct drm_plane *plane) |
65 | struct drm_plane *plane) |
Line 78... | Line 84... | ||
78 | 84 | ||
79 | crtc_state->planes_changed = true; |
85 | crtc_state->planes_changed = true; |
80 | } |
86 | } |
Line -... | Line 87... | ||
- | 87 | } |
|
- | 88 | ||
- | 89 | static bool |
|
- | 90 | check_pending_encoder_assignment(struct drm_atomic_state *state, |
|
- | 91 | struct drm_encoder *new_encoder) |
|
- | 92 | { |
|
- | 93 | struct drm_connector *connector; |
|
- | 94 | struct drm_connector_state *conn_state; |
|
- | 95 | int i; |
|
- | 96 | ||
- | 97 | for_each_connector_in_state(state, connector, conn_state, i) { |
|
- | 98 | if (conn_state->best_encoder != new_encoder) |
|
- | 99 | continue; |
|
- | 100 | ||
- | 101 | /* encoder already assigned and we're trying to re-steal it! */ |
|
- | 102 | if (connector->state->best_encoder != conn_state->best_encoder) |
|
- | 103 | return false; |
|
- | 104 | } |
|
- | 105 | ||
- | 106 | return true; |
|
81 | } |
107 | } |
82 | 108 | ||
83 | static struct drm_crtc * |
109 | static struct drm_crtc * |
84 | get_current_crtc_for_encoder(struct drm_device *dev, |
110 | get_current_crtc_for_encoder(struct drm_device *dev, |
85 | struct drm_encoder *encoder) |
111 | struct drm_encoder *encoder) |
Line 106... | Line 132... | ||
106 | { |
132 | { |
107 | struct drm_mode_config *config = &state->dev->mode_config; |
133 | struct drm_mode_config *config = &state->dev->mode_config; |
108 | struct drm_crtc_state *crtc_state; |
134 | struct drm_crtc_state *crtc_state; |
109 | struct drm_connector *connector; |
135 | struct drm_connector *connector; |
110 | struct drm_connector_state *connector_state; |
136 | struct drm_connector_state *connector_state; |
- | 137 | int ret; |
|
Line 111... | Line 138... | ||
111 | 138 | ||
112 | /* |
139 | /* |
113 | * We can only steal an encoder coming from a connector, which means we |
140 | * We can only steal an encoder coming from a connector, which means we |
114 | * must already hold the connection_mutex. |
141 | * must already hold the connection_mutex. |
115 | */ |
142 | */ |
Line 116... | Line 143... | ||
116 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); |
143 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); |
117 | 144 | ||
118 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d], stealing it\n", |
145 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", |
Line 119... | Line 146... | ||
119 | encoder->base.id, encoder->name, |
146 | encoder->base.id, encoder->name, |
120 | encoder_crtc->base.id); |
147 | encoder_crtc->base.id, encoder_crtc->name); |
121 | 148 | ||
Line 136... | Line 163... | ||
136 | connector_state = drm_atomic_get_connector_state(state, |
163 | connector_state = drm_atomic_get_connector_state(state, |
137 | connector); |
164 | connector); |
138 | if (IS_ERR(connector_state)) |
165 | if (IS_ERR(connector_state)) |
139 | return PTR_ERR(connector_state); |
166 | return PTR_ERR(connector_state); |
Line -... | Line 167... | ||
- | 167 | ||
- | 168 | ret = drm_atomic_set_crtc_for_connector(connector_state, NULL); |
|
- | 169 | if (ret) |
|
140 | 170 | return ret; |
|
141 | connector_state->best_encoder = NULL; |
171 | connector_state->best_encoder = NULL; |
Line 142... | Line 172... | ||
142 | } |
172 | } |
143 | 173 | ||
Line 213... | Line 243... | ||
213 | connector_state->crtc->base.id); |
243 | connector_state->crtc->base.id); |
214 | return -EINVAL; |
244 | return -EINVAL; |
215 | } |
245 | } |
Line 216... | Line 246... | ||
216 | 246 | ||
217 | if (new_encoder == connector_state->best_encoder) { |
247 | if (new_encoder == connector_state->best_encoder) { |
218 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n", |
248 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n", |
219 | connector->base.id, |
249 | connector->base.id, |
220 | connector->name, |
250 | connector->name, |
221 | new_encoder->base.id, |
251 | new_encoder->base.id, |
222 | new_encoder->name, |
252 | new_encoder->name, |
- | 253 | connector_state->crtc->base.id, |
|
Line 223... | Line 254... | ||
223 | connector_state->crtc->base.id); |
254 | connector_state->crtc->name); |
224 | 255 | ||
Line -... | Line 256... | ||
- | 256 | return 0; |
|
- | 257 | } |
|
- | 258 | ||
- | 259 | if (!check_pending_encoder_assignment(state, new_encoder)) { |
|
- | 260 | DRM_DEBUG_ATOMIC("Encoder for [CONNECTOR:%d:%s] already assigned\n", |
|
- | 261 | connector->base.id, |
|
- | 262 | connector->name); |
|
225 | return 0; |
263 | return -EINVAL; |
226 | } |
264 | } |
Line 227... | Line 265... | ||
227 | 265 | ||
228 | encoder_crtc = get_current_crtc_for_encoder(state->dev, |
266 | encoder_crtc = get_current_crtc_for_encoder(state->dev, |
Line 245... | Line 283... | ||
245 | idx = drm_crtc_index(connector_state->crtc); |
283 | idx = drm_crtc_index(connector_state->crtc); |
Line 246... | Line 284... | ||
246 | 284 | ||
247 | crtc_state = state->crtc_states[idx]; |
285 | crtc_state = state->crtc_states[idx]; |
Line 248... | Line 286... | ||
248 | crtc_state->connectors_changed = true; |
286 | crtc_state->connectors_changed = true; |
249 | 287 | ||
250 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n", |
288 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", |
251 | connector->base.id, |
289 | connector->base.id, |
252 | connector->name, |
290 | connector->name, |
253 | new_encoder->base.id, |
291 | new_encoder->base.id, |
- | 292 | new_encoder->name, |
|
Line 254... | Line 293... | ||
254 | new_encoder->name, |
293 | connector_state->crtc->base.id, |
255 | connector_state->crtc->base.id); |
294 | connector_state->crtc->name); |
Line 256... | Line 295... | ||
256 | 295 | ||
Line 263... | Line 302... | ||
263 | struct drm_crtc *crtc; |
302 | struct drm_crtc *crtc; |
264 | struct drm_crtc_state *crtc_state; |
303 | struct drm_crtc_state *crtc_state; |
265 | struct drm_connector *connector; |
304 | struct drm_connector *connector; |
266 | struct drm_connector_state *conn_state; |
305 | struct drm_connector_state *conn_state; |
267 | int i; |
306 | int i; |
268 | int ret; |
307 | bool ret; |
Line 269... | Line 308... | ||
269 | 308 | ||
270 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
309 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
271 | if (!crtc_state->mode_changed && |
310 | if (!crtc_state->mode_changed && |
272 | !crtc_state->connectors_changed) |
311 | !crtc_state->connectors_changed) |
Line 334... | Line 373... | ||
334 | continue; |
373 | continue; |
Line 335... | Line 374... | ||
335 | 374 | ||
336 | ret = funcs->mode_fixup(crtc, &crtc_state->mode, |
375 | ret = funcs->mode_fixup(crtc, &crtc_state->mode, |
337 | &crtc_state->adjusted_mode); |
376 | &crtc_state->adjusted_mode); |
338 | if (!ret) { |
377 | if (!ret) { |
339 | DRM_DEBUG_ATOMIC("[CRTC:%d] fixup failed\n", |
378 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] fixup failed\n", |
340 | crtc->base.id); |
379 | crtc->base.id, crtc->name); |
341 | return -EINVAL; |
380 | return -EINVAL; |
342 | } |
381 | } |
Line 343... | Line 382... | ||
343 | } |
382 | } |
Line 382... | Line 421... | ||
382 | struct drm_connector_state *connector_state; |
421 | struct drm_connector_state *connector_state; |
383 | int i, ret; |
422 | int i, ret; |
Line 384... | Line 423... | ||
384 | 423 | ||
385 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
424 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
386 | if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { |
425 | if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { |
387 | DRM_DEBUG_ATOMIC("[CRTC:%d] mode changed\n", |
426 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n", |
388 | crtc->base.id); |
427 | crtc->base.id, crtc->name); |
389 | crtc_state->mode_changed = true; |
428 | crtc_state->mode_changed = true; |
Line 390... | Line 429... | ||
390 | } |
429 | } |
391 | 430 | ||
392 | if (crtc->state->enable != crtc_state->enable) { |
431 | if (crtc->state->enable != crtc_state->enable) { |
Line 393... | Line 432... | ||
393 | DRM_DEBUG_ATOMIC("[CRTC:%d] enable changed\n", |
432 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enable changed\n", |
394 | crtc->base.id); |
433 | crtc->base.id, crtc->name); |
395 | 434 | ||
396 | /* |
435 | /* |
Line 422... | Line 461... | ||
422 | * connector which is itself unchanged, but who's crtc changes it's |
461 | * connector which is itself unchanged, but who's crtc changes it's |
423 | * configuration. This must be done before calling mode_fixup in case a |
462 | * configuration. This must be done before calling mode_fixup in case a |
424 | * crtc only changed its mode but has the same set of connectors. |
463 | * crtc only changed its mode but has the same set of connectors. |
425 | */ |
464 | */ |
426 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
465 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
427 | int num_connectors; |
466 | bool has_connectors = |
- | 467 | !!crtc_state->connector_mask; |
|
Line 428... | Line 468... | ||
428 | 468 | ||
429 | /* |
469 | /* |
430 | * We must set ->active_changed after walking connectors for |
470 | * We must set ->active_changed after walking connectors for |
431 | * otherwise an update that only changes active would result in |
471 | * otherwise an update that only changes active would result in |
432 | * a full modeset because update_connector_routing force that. |
472 | * a full modeset because update_connector_routing force that. |
433 | */ |
473 | */ |
434 | if (crtc->state->active != crtc_state->active) { |
474 | if (crtc->state->active != crtc_state->active) { |
435 | DRM_DEBUG_ATOMIC("[CRTC:%d] active changed\n", |
475 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n", |
436 | crtc->base.id); |
476 | crtc->base.id, crtc->name); |
437 | crtc_state->active_changed = true; |
477 | crtc_state->active_changed = true; |
Line 438... | Line 478... | ||
438 | } |
478 | } |
439 | 479 | ||
Line 440... | Line 480... | ||
440 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) |
480 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) |
441 | continue; |
481 | continue; |
442 | 482 | ||
443 | DRM_DEBUG_ATOMIC("[CRTC:%d] needs all connectors, enable: %c, active: %c\n", |
483 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] needs all connectors, enable: %c, active: %c\n", |
Line 444... | Line 484... | ||
444 | crtc->base.id, |
484 | crtc->base.id, crtc->name, |
445 | crtc_state->enable ? 'y' : 'n', |
485 | crtc_state->enable ? 'y' : 'n', |
Line 451... | Line 491... | ||
451 | 491 | ||
452 | ret = drm_atomic_add_affected_planes(state, crtc); |
492 | ret = drm_atomic_add_affected_planes(state, crtc); |
453 | if (ret != 0) |
493 | if (ret != 0) |
Line 454... | Line -... | ||
454 | return ret; |
- | |
455 | - | ||
456 | num_connectors = drm_atomic_connectors_for_crtc(state, |
- | |
457 | crtc); |
494 | return ret; |
458 | 495 | ||
459 | if (crtc_state->enable != !!num_connectors) { |
496 | if (crtc_state->enable != has_connectors) { |
Line 460... | Line 497... | ||
460 | DRM_DEBUG_ATOMIC("[CRTC:%d] enabled/connectors mismatch\n", |
497 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n", |
461 | crtc->base.id); |
498 | crtc->base.id, crtc->name); |
462 | 499 | ||
Line 503... | Line 540... | ||
503 | if (!funcs || !funcs->atomic_check) |
540 | if (!funcs || !funcs->atomic_check) |
504 | continue; |
541 | continue; |
Line 505... | Line 542... | ||
505 | 542 | ||
506 | ret = funcs->atomic_check(plane, plane_state); |
543 | ret = funcs->atomic_check(plane, plane_state); |
507 | if (ret) { |
544 | if (ret) { |
508 | DRM_DEBUG_ATOMIC("[PLANE:%d] atomic driver check failed\n", |
545 | DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic driver check failed\n", |
509 | plane->base.id); |
546 | plane->base.id, plane->name); |
510 | return ret; |
547 | return ret; |
511 | } |
548 | } |
Line 512... | Line 549... | ||
512 | } |
549 | } |
Line 519... | Line 556... | ||
519 | if (!funcs || !funcs->atomic_check) |
556 | if (!funcs || !funcs->atomic_check) |
520 | continue; |
557 | continue; |
Line 521... | Line 558... | ||
521 | 558 | ||
522 | ret = funcs->atomic_check(crtc, state->crtc_states[i]); |
559 | ret = funcs->atomic_check(crtc, state->crtc_states[i]); |
523 | if (ret) { |
560 | if (ret) { |
524 | DRM_DEBUG_ATOMIC("[CRTC:%d] atomic driver check failed\n", |
561 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n", |
525 | crtc->base.id); |
562 | crtc->base.id, crtc->name); |
526 | return ret; |
563 | return ret; |
527 | } |
564 | } |
Line 528... | Line 565... | ||
528 | } |
565 | } |
Line 633... | Line 670... | ||
633 | if (!old_crtc_state->active) |
670 | if (!old_crtc_state->active) |
634 | continue; |
671 | continue; |
Line 635... | Line 672... | ||
635 | 672 | ||
Line 636... | Line 673... | ||
636 | funcs = crtc->helper_private; |
673 | funcs = crtc->helper_private; |
637 | 674 | ||
Line 638... | Line 675... | ||
638 | DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n", |
675 | DRM_DEBUG_ATOMIC("disabling [CRTC:%d:%s]\n", |
639 | crtc->base.id); |
676 | crtc->base.id, crtc->name); |
640 | 677 | ||
Line 745... | Line 782... | ||
745 | continue; |
782 | continue; |
Line 746... | Line 783... | ||
746 | 783 | ||
Line 747... | Line 784... | ||
747 | funcs = crtc->helper_private; |
784 | funcs = crtc->helper_private; |
748 | 785 | ||
749 | if (crtc->state->enable && funcs->mode_set_nofb) { |
786 | if (crtc->state->enable && funcs->mode_set_nofb) { |
Line 750... | Line 787... | ||
750 | DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n", |
787 | DRM_DEBUG_ATOMIC("modeset on [CRTC:%d:%s]\n", |
751 | crtc->base.id); |
788 | crtc->base.id, crtc->name); |
752 | 789 | ||
Line 845... | Line 882... | ||
845 | continue; |
882 | continue; |
Line 846... | Line 883... | ||
846 | 883 | ||
Line 847... | Line 884... | ||
847 | funcs = crtc->helper_private; |
884 | funcs = crtc->helper_private; |
848 | 885 | ||
849 | if (crtc->state->enable) { |
886 | if (crtc->state->enable) { |
Line 850... | Line 887... | ||
850 | DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n", |
887 | DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n", |
851 | crtc->base.id); |
888 | crtc->base.id, crtc->name); |
852 | 889 | ||
853 | if (funcs->enable) |
890 | if (funcs->enable) |
Line 907... | Line 944... | ||
907 | fence_put(plane->state->fence); |
944 | fence_put(plane->state->fence); |
908 | plane->state->fence = NULL; |
945 | plane->state->fence = NULL; |
909 | } |
946 | } |
910 | } |
947 | } |
Line -... | Line 948... | ||
- | 948 | ||
- | 949 | /** |
|
- | 950 | * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed |
|
- | 951 | * @dev: DRM device |
|
- | 952 | * @old_state: atomic state object with old state structures |
|
- | 953 | * @crtc: DRM crtc |
|
- | 954 | * |
|
- | 955 | * Checks whether the framebuffer used for this CRTC changes as a result of |
|
- | 956 | * the atomic update. This is useful for drivers which cannot use |
|
- | 957 | * drm_atomic_helper_wait_for_vblanks() and need to reimplement its |
|
- | 958 | * functionality. |
|
- | 959 | * |
|
- | 960 | * Returns: |
|
- | 961 | * true if the framebuffer changed. |
|
911 | 962 | */ |
|
912 | static bool framebuffer_changed(struct drm_device *dev, |
963 | bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, |
913 | struct drm_atomic_state *old_state, |
964 | struct drm_atomic_state *old_state, |
914 | struct drm_crtc *crtc) |
965 | struct drm_crtc *crtc) |
915 | { |
966 | { |
916 | struct drm_plane *plane; |
967 | struct drm_plane *plane; |
Line 926... | Line 977... | ||
926 | return true; |
977 | return true; |
927 | } |
978 | } |
Line 928... | Line 979... | ||
928 | 979 | ||
929 | return false; |
980 | return false; |
- | 981 | } |
|
Line 930... | Line 982... | ||
930 | } |
982 | EXPORT_SYMBOL(drm_atomic_helper_framebuffer_changed); |
931 | 983 | ||
932 | /** |
984 | /** |
933 | * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs |
985 | * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs |
Line 960... | Line 1012... | ||
960 | /* Legacy cursor ioctls are completely unsynced, and userspace |
1012 | /* Legacy cursor ioctls are completely unsynced, and userspace |
961 | * relies on that (by doing tons of cursor updates). */ |
1013 | * relies on that (by doing tons of cursor updates). */ |
962 | if (old_state->legacy_cursor_update) |
1014 | if (old_state->legacy_cursor_update) |
963 | continue; |
1015 | continue; |
Line 964... | Line 1016... | ||
964 | 1016 | ||
- | 1017 | if (!drm_atomic_helper_framebuffer_changed(dev, |
|
965 | if (!framebuffer_changed(dev, old_state, crtc)) |
1018 | old_state, crtc)) |
Line 966... | Line 1019... | ||
966 | continue; |
1019 | continue; |
967 | 1020 | ||
968 | ret = drm_crtc_vblank_get(crtc); |
1021 | ret = drm_crtc_vblank_get(crtc); |
Line 1336... | Line 1389... | ||
1336 | crtc_funcs->atomic_flush(crtc, old_crtc_state); |
1389 | crtc_funcs->atomic_flush(crtc, old_crtc_state); |
1337 | } |
1390 | } |
1338 | EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc); |
1391 | EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc); |
Line 1339... | Line 1392... | ||
1339 | 1392 | ||
- | 1393 | /** |
|
- | 1394 | * drm_atomic_helper_disable_planes_on_crtc - helper to disable CRTC's planes |
|
- | 1395 | * @crtc: CRTC |
|
- | 1396 | * @atomic: if set, synchronize with CRTC's atomic_begin/flush hooks |
|
- | 1397 | * |
|
- | 1398 | * Disables all planes associated with the given CRTC. This can be |
|
- | 1399 | * used for instance in the CRTC helper disable callback to disable |
|
- | 1400 | * all planes before shutting down the display pipeline. |
|
- | 1401 | * |
|
- | 1402 | * If the atomic-parameter is set the function calls the CRTC's |
|
- | 1403 | * atomic_begin hook before and atomic_flush hook after disabling the |
|
- | 1404 | * planes. |
|
- | 1405 | * |
|
- | 1406 | * It is a bug to call this function without having implemented the |
|
- | 1407 | * ->atomic_disable() plane hook. |
|
- | 1408 | */ |
|
- | 1409 | void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc *crtc, |
|
- | 1410 | bool atomic) |
|
- | 1411 | { |
|
- | 1412 | const struct drm_crtc_helper_funcs *crtc_funcs = |
|
- | 1413 | crtc->helper_private; |
|
- | 1414 | struct drm_plane *plane; |
|
- | 1415 | ||
- | 1416 | if (atomic && crtc_funcs && crtc_funcs->atomic_begin) |
|
- | 1417 | crtc_funcs->atomic_begin(crtc, NULL); |
|
- | 1418 | ||
- | 1419 | drm_for_each_plane(plane, crtc->dev) { |
|
- | 1420 | const struct drm_plane_helper_funcs *plane_funcs = |
|
- | 1421 | plane->helper_private; |
|
- | 1422 | ||
- | 1423 | if (plane->state->crtc != crtc || !plane_funcs) |
|
- | 1424 | continue; |
|
- | 1425 | ||
- | 1426 | WARN_ON(!plane_funcs->atomic_disable); |
|
- | 1427 | if (plane_funcs->atomic_disable) |
|
- | 1428 | plane_funcs->atomic_disable(plane, NULL); |
|
- | 1429 | } |
|
- | 1430 | ||
- | 1431 | if (atomic && crtc_funcs && crtc_funcs->atomic_flush) |
|
- | 1432 | crtc_funcs->atomic_flush(crtc, NULL); |
|
- | 1433 | } |
|
- | 1434 | EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc); |
|
- | 1435 | ||
1340 | /** |
1436 | /** |
1341 | * drm_atomic_helper_cleanup_planes - cleanup plane resources after commit |
1437 | * drm_atomic_helper_cleanup_planes - cleanup plane resources after commit |
1342 | * @dev: DRM device |
1438 | * @dev: DRM device |
1343 | * @old_state: atomic state object with old state structures |
1439 | * @old_state: atomic state object with old state structures |
1344 | * |
1440 | * |
Line 1395... | Line 1491... | ||
1395 | void drm_atomic_helper_swap_state(struct drm_device *dev, |
1491 | void drm_atomic_helper_swap_state(struct drm_device *dev, |
1396 | struct drm_atomic_state *state) |
1492 | struct drm_atomic_state *state) |
1397 | { |
1493 | { |
1398 | int i; |
1494 | int i; |
Line 1399... | Line 1495... | ||
1399 | 1495 | ||
1400 | for (i = 0; i < dev->mode_config.num_connector; i++) { |
1496 | for (i = 0; i < state->num_connector; i++) { |
Line 1401... | Line 1497... | ||
1401 | struct drm_connector *connector = state->connectors[i]; |
1497 | struct drm_connector *connector = state->connectors[i]; |
1402 | 1498 | ||
Line 1479... | Line 1575... | ||
1479 | if (ret != 0) |
1575 | if (ret != 0) |
1480 | goto fail; |
1576 | goto fail; |
1481 | drm_atomic_set_fb_for_plane(plane_state, fb); |
1577 | drm_atomic_set_fb_for_plane(plane_state, fb); |
1482 | plane_state->crtc_x = crtc_x; |
1578 | plane_state->crtc_x = crtc_x; |
1483 | plane_state->crtc_y = crtc_y; |
1579 | plane_state->crtc_y = crtc_y; |
1484 | plane_state->crtc_h = crtc_h; |
- | |
1485 | plane_state->crtc_w = crtc_w; |
1580 | plane_state->crtc_w = crtc_w; |
- | 1581 | plane_state->crtc_h = crtc_h; |
|
1486 | plane_state->src_x = src_x; |
1582 | plane_state->src_x = src_x; |
1487 | plane_state->src_y = src_y; |
1583 | plane_state->src_y = src_y; |
1488 | plane_state->src_h = src_h; |
- | |
1489 | plane_state->src_w = src_w; |
1584 | plane_state->src_w = src_w; |
- | 1585 | plane_state->src_h = src_h; |
|
Line 1490... | Line 1586... | ||
1490 | 1586 | ||
1491 | if (plane == crtc->cursor) |
1587 | if (plane == crtc->cursor) |
Line 1492... | Line 1588... | ||
1492 | state->legacy_cursor_update = true; |
1588 | state->legacy_cursor_update = true; |
Line 1603... | Line 1699... | ||
1603 | return ret; |
1699 | return ret; |
Line 1604... | Line 1700... | ||
1604 | 1700 | ||
1605 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
1701 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
1606 | plane_state->crtc_x = 0; |
1702 | plane_state->crtc_x = 0; |
1607 | plane_state->crtc_y = 0; |
- | |
1608 | plane_state->crtc_h = 0; |
1703 | plane_state->crtc_y = 0; |
- | 1704 | plane_state->crtc_w = 0; |
|
1609 | plane_state->crtc_w = 0; |
1705 | plane_state->crtc_h = 0; |
1610 | plane_state->src_x = 0; |
1706 | plane_state->src_x = 0; |
1611 | plane_state->src_y = 0; |
- | |
1612 | plane_state->src_h = 0; |
1707 | plane_state->src_y = 0; |
- | 1708 | plane_state->src_w = 0; |
|
Line 1613... | Line 1709... | ||
1613 | plane_state->src_w = 0; |
1709 | plane_state->src_h = 0; |
1614 | 1710 | ||
Line 1615... | Line 1711... | ||
1615 | return 0; |
1711 | return 0; |
Line 1670... | Line 1766... | ||
1670 | * The actual modeset code later on will catch any |
1766 | * The actual modeset code later on will catch any |
1671 | * inconsistencies here. */ |
1767 | * inconsistencies here. */ |
1672 | if (crtc == set->crtc) |
1768 | if (crtc == set->crtc) |
1673 | continue; |
1769 | continue; |
Line 1674... | Line 1770... | ||
1674 | 1770 | ||
1675 | if (!drm_atomic_connectors_for_crtc(state, crtc)) { |
1771 | if (!crtc_state->connector_mask) { |
1676 | ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, |
1772 | ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, |
1677 | NULL); |
1773 | NULL); |
1678 | if (ret < 0) |
1774 | if (ret < 0) |
Line 1791... | Line 1887... | ||
1791 | drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); |
1887 | drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); |
Line 1792... | Line 1888... | ||
1792 | 1888 | ||
1793 | drm_atomic_set_fb_for_plane(primary_state, set->fb); |
1889 | drm_atomic_set_fb_for_plane(primary_state, set->fb); |
1794 | primary_state->crtc_x = 0; |
1890 | primary_state->crtc_x = 0; |
1795 | primary_state->crtc_y = 0; |
- | |
1796 | primary_state->crtc_h = vdisplay; |
1891 | primary_state->crtc_y = 0; |
- | 1892 | primary_state->crtc_w = hdisplay; |
|
1797 | primary_state->crtc_w = hdisplay; |
1893 | primary_state->crtc_h = vdisplay; |
1798 | primary_state->src_x = set->x << 16; |
1894 | primary_state->src_x = set->x << 16; |
1799 | primary_state->src_y = set->y << 16; |
1895 | primary_state->src_y = set->y << 16; |
1800 | if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) { |
- | |
1801 | primary_state->src_h = hdisplay << 16; |
1896 | if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) { |
- | 1897 | primary_state->src_w = vdisplay << 16; |
|
1802 | primary_state->src_w = vdisplay << 16; |
1898 | primary_state->src_h = hdisplay << 16; |
1803 | } else { |
- | |
1804 | primary_state->src_h = vdisplay << 16; |
1899 | } else { |
- | 1900 | primary_state->src_w = hdisplay << 16; |
|
1805 | primary_state->src_w = hdisplay << 16; |
1901 | primary_state->src_h = vdisplay << 16; |
Line 1806... | Line 1902... | ||
1806 | } |
1902 | } |
1807 | 1903 | ||
1808 | commit: |
1904 | commit: |
Line 1812... | Line 1908... | ||
1812 | 1908 | ||
1813 | return 0; |
1909 | return 0; |
Line 1814... | Line 1910... | ||
1814 | } |
1910 | } |
- | 1911 | ||
- | 1912 | /** |
|
- | 1913 | * drm_atomic_helper_disable_all - disable all currently active outputs |
|
- | 1914 | * @dev: DRM device |
|
- | 1915 | * @ctx: lock acquisition context |
|
- | 1916 | * |
|
- | 1917 | * Loops through all connectors, finding those that aren't turned off and then |
|
- | 1918 | * turns them off by setting their DPMS mode to OFF and deactivating the CRTC |
|
- | 1919 | * that they are connected to. |
|
- | 1920 | * |
|
- | 1921 | * This is used for example in suspend/resume to disable all currently active |
|
- | 1922 | * functions when suspending. |
|
- | 1923 | * |
|
- | 1924 | * Note that if callers haven't already acquired all modeset locks this might |
|
- | 1925 | * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). |
|
- | 1926 | * |
|
- | 1927 | * Returns: |
|
- | 1928 | * 0 on success or a negative error code on failure. |
|
- | 1929 | * |
|
- | 1930 | * See also: |
|
- | 1931 | * drm_atomic_helper_suspend(), drm_atomic_helper_resume() |
|
- | 1932 | */ |
|
- | 1933 | int drm_atomic_helper_disable_all(struct drm_device *dev, |
|
- | 1934 | struct drm_modeset_acquire_ctx *ctx) |
|
- | 1935 | { |
|
- | 1936 | struct drm_atomic_state *state; |
|
- | 1937 | struct drm_connector *conn; |
|
- | 1938 | int err; |
|
- | 1939 | ||
- | 1940 | state = drm_atomic_state_alloc(dev); |
|
- | 1941 | if (!state) |
|
- | 1942 | return -ENOMEM; |
|
- | 1943 | ||
- | 1944 | state->acquire_ctx = ctx; |
|
- | 1945 | ||
- | 1946 | drm_for_each_connector(conn, dev) { |
|
- | 1947 | struct drm_crtc *crtc = conn->state->crtc; |
|
- | 1948 | struct drm_crtc_state *crtc_state; |
|
- | 1949 | ||
- | 1950 | if (!crtc || conn->dpms != DRM_MODE_DPMS_ON) |
|
- | 1951 | continue; |
|
- | 1952 | ||
- | 1953 | crtc_state = drm_atomic_get_crtc_state(state, crtc); |
|
- | 1954 | if (IS_ERR(crtc_state)) { |
|
- | 1955 | err = PTR_ERR(crtc_state); |
|
- | 1956 | goto free; |
|
- | 1957 | } |
|
- | 1958 | ||
- | 1959 | crtc_state->active = false; |
|
- | 1960 | } |
|
- | 1961 | ||
- | 1962 | err = drm_atomic_commit(state); |
|
- | 1963 | ||
- | 1964 | free: |
|
- | 1965 | if (err < 0) |
|
- | 1966 | drm_atomic_state_free(state); |
|
- | 1967 | ||
- | 1968 | return err; |
|
- | 1969 | } |
|
- | 1970 | EXPORT_SYMBOL(drm_atomic_helper_disable_all); |
|
- | 1971 | ||
- | 1972 | /** |
|
- | 1973 | * drm_atomic_helper_suspend - subsystem-level suspend helper |
|
- | 1974 | * @dev: DRM device |
|
- | 1975 | * |
|
- | 1976 | * Duplicates the current atomic state, disables all active outputs and then |
|
- | 1977 | * returns a pointer to the original atomic state to the caller. Drivers can |
|
- | 1978 | * pass this pointer to the drm_atomic_helper_resume() helper upon resume to |
|
- | 1979 | * restore the output configuration that was active at the time the system |
|
- | 1980 | * entered suspend. |
|
- | 1981 | * |
|
- | 1982 | * Note that it is potentially unsafe to use this. The atomic state object |
|
- | 1983 | * returned by this function is assumed to be persistent. Drivers must ensure |
|
- | 1984 | * that this holds true. Before calling this function, drivers must make sure |
|
- | 1985 | * to suspend fbdev emulation so that nothing can be using the device. |
|
- | 1986 | * |
|
- | 1987 | * Returns: |
|
- | 1988 | * A pointer to a copy of the state before suspend on success or an ERR_PTR()- |
|
- | 1989 | * encoded error code on failure. Drivers should store the returned atomic |
|
- | 1990 | * state object and pass it to the drm_atomic_helper_resume() helper upon |
|
- | 1991 | * resume. |
|
- | 1992 | * |
|
- | 1993 | * See also: |
|
- | 1994 | * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(), |
|
- | 1995 | * drm_atomic_helper_resume() |
|
- | 1996 | */ |
|
- | 1997 | struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev) |
|
- | 1998 | { |
|
- | 1999 | struct drm_modeset_acquire_ctx ctx; |
|
- | 2000 | struct drm_atomic_state *state; |
|
- | 2001 | int err; |
|
- | 2002 | ||
- | 2003 | drm_modeset_acquire_init(&ctx, 0); |
|
- | 2004 | ||
- | 2005 | retry: |
|
- | 2006 | err = drm_modeset_lock_all_ctx(dev, &ctx); |
|
- | 2007 | if (err < 0) { |
|
- | 2008 | state = ERR_PTR(err); |
|
- | 2009 | goto unlock; |
|
- | 2010 | } |
|
- | 2011 | ||
- | 2012 | state = drm_atomic_helper_duplicate_state(dev, &ctx); |
|
- | 2013 | if (IS_ERR(state)) |
|
- | 2014 | goto unlock; |
|
- | 2015 | ||
- | 2016 | err = drm_atomic_helper_disable_all(dev, &ctx); |
|
- | 2017 | if (err < 0) { |
|
- | 2018 | drm_atomic_state_free(state); |
|
- | 2019 | state = ERR_PTR(err); |
|
- | 2020 | goto unlock; |
|
- | 2021 | } |
|
- | 2022 | ||
- | 2023 | unlock: |
|
- | 2024 | if (PTR_ERR(state) == -EDEADLK) { |
|
- | 2025 | drm_modeset_backoff(&ctx); |
|
- | 2026 | goto retry; |
|
- | 2027 | } |
|
- | 2028 | ||
- | 2029 | drm_modeset_drop_locks(&ctx); |
|
- | 2030 | drm_modeset_acquire_fini(&ctx); |
|
- | 2031 | return state; |
|
- | 2032 | } |
|
- | 2033 | EXPORT_SYMBOL(drm_atomic_helper_suspend); |
|
- | 2034 | ||
- | 2035 | /** |
|
- | 2036 | * drm_atomic_helper_resume - subsystem-level resume helper |
|
- | 2037 | * @dev: DRM device |
|
- | 2038 | * @state: atomic state to resume to |
|
- | 2039 | * |
|
- | 2040 | * Calls drm_mode_config_reset() to synchronize hardware and software states, |
|
- | 2041 | * grabs all modeset locks and commits the atomic state object. This can be |
|
- | 2042 | * used in conjunction with the drm_atomic_helper_suspend() helper to |
|
- | 2043 | * implement suspend/resume for drivers that support atomic mode-setting. |
|
- | 2044 | * |
|
- | 2045 | * Returns: |
|
- | 2046 | * 0 on success or a negative error code on failure. |
|
- | 2047 | * |
|
- | 2048 | * See also: |
|
- | 2049 | * drm_atomic_helper_suspend() |
|
- | 2050 | */ |
|
- | 2051 | int drm_atomic_helper_resume(struct drm_device *dev, |
|
- | 2052 | struct drm_atomic_state *state) |
|
- | 2053 | { |
|
- | 2054 | struct drm_mode_config *config = &dev->mode_config; |
|
- | 2055 | int err; |
|
- | 2056 | ||
- | 2057 | drm_mode_config_reset(dev); |
|
- | 2058 | drm_modeset_lock_all(dev); |
|
- | 2059 | state->acquire_ctx = config->acquire_ctx; |
|
- | 2060 | err = drm_atomic_commit(state); |
|
- | 2061 | drm_modeset_unlock_all(dev); |
|
- | 2062 | ||
- | 2063 | return err; |
|
- | 2064 | } |
|
- | 2065 | EXPORT_SYMBOL(drm_atomic_helper_resume); |
|
1815 | 2066 | ||
1816 | /** |
2067 | /** |
1817 | * drm_atomic_helper_crtc_set_property - helper for crtc properties |
2068 | * drm_atomic_helper_crtc_set_property - helper for crtc properties |
1818 | * @crtc: DRM crtc |
2069 | * @crtc: DRM crtc |
1819 | * @property: DRM property |
2070 | * @property: DRM property |
Line 2045... | Line 2296... | ||
2045 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
2296 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
2046 | if (ret != 0) |
2297 | if (ret != 0) |
2047 | goto fail; |
2298 | goto fail; |
2048 | drm_atomic_set_fb_for_plane(plane_state, fb); |
2299 | drm_atomic_set_fb_for_plane(plane_state, fb); |
Line -... | Line 2300... | ||
- | 2300 | ||
- | 2301 | /* Make sure we don't accidentally do a full modeset. */ |
|
- | 2302 | state->allow_modeset = false; |
|
- | 2303 | if (!crtc_state->active) { |
|
- | 2304 | DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n", |
|
- | 2305 | crtc->base.id); |
|
- | 2306 | ret = -EINVAL; |
|
- | 2307 | goto fail; |
|
- | 2308 | } |
|
2049 | 2309 | ||
2050 | ret = drm_atomic_async_commit(state); |
2310 | ret = drm_atomic_async_commit(state); |
2051 | if (ret != 0) |
2311 | if (ret != 0) |
Line 2052... | Line 2312... | ||
2052 | goto fail; |
2312 | goto fail; |
Line 2167... | Line 2427... | ||
2167 | * driver). |
2427 | * driver). |
2168 | * |
2428 | * |
2169 | * The simpler solution is to just reset the software state to everything off, |
2429 | * The simpler solution is to just reset the software state to everything off, |
2170 | * which is easiest to do by calling drm_mode_config_reset(). To facilitate this |
2430 | * which is easiest to do by calling drm_mode_config_reset(). To facilitate this |
2171 | * the atomic helpers provide default reset implementations for all hooks. |
2431 | * the atomic helpers provide default reset implementations for all hooks. |
- | 2432 | * |
|
- | 2433 | * On the upside the precise state tracking of atomic simplifies system suspend |
|
- | 2434 | * and resume a lot. For drivers using drm_mode_config_reset() a complete recipe |
|
- | 2435 | * is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume(). |
|
- | 2436 | * For other drivers the building blocks are split out, see the documentation |
|
- | 2437 | * for these functions. |
|
2172 | */ |
2438 | */ |
Line 2173... | Line 2439... | ||
2173 | 2439 | ||
2174 | /** |
2440 | /** |
2175 | * drm_atomic_helper_crtc_reset - default ->reset hook for CRTCs |
2441 | * drm_atomic_helper_crtc_reset - default ->reset hook for CRTCs |
Line 2178... | Line 2444... | ||
2178 | * Resets the atomic state for @crtc by freeing the state pointer (which might |
2444 | * Resets the atomic state for @crtc by freeing the state pointer (which might |
2179 | * be NULL, e.g. at driver load time) and allocating a new empty state object. |
2445 | * be NULL, e.g. at driver load time) and allocating a new empty state object. |
2180 | */ |
2446 | */ |
2181 | void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) |
2447 | void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) |
2182 | { |
2448 | { |
2183 | if (crtc->state && crtc->state->mode_blob) |
2449 | if (crtc->state) |
2184 | drm_property_unreference_blob(crtc->state->mode_blob); |
2450 | drm_property_unreference_blob(crtc->state->mode_blob); |
2185 | kfree(crtc->state); |
2451 | kfree(crtc->state); |
2186 | crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); |
2452 | crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); |
Line 2187... | Line 2453... | ||
2187 | 2453 | ||
Line 2246... | Line 2512... | ||
2246 | * CRTC state. |
2512 | * CRTC state. |
2247 | */ |
2513 | */ |
2248 | void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, |
2514 | void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, |
2249 | struct drm_crtc_state *state) |
2515 | struct drm_crtc_state *state) |
2250 | { |
2516 | { |
2251 | if (state->mode_blob) |
- | |
2252 | drm_property_unreference_blob(state->mode_blob); |
2517 | drm_property_unreference_blob(state->mode_blob); |
2253 | } |
2518 | } |
2254 | EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); |
2519 | EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); |
Line 2255... | Line 2520... | ||
2255 | 2520 | ||
Line 2362... | Line 2627... | ||
2362 | kfree(state); |
2627 | kfree(state); |
2363 | } |
2628 | } |
2364 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); |
2629 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); |
Line 2365... | Line 2630... | ||
2365 | 2630 | ||
- | 2631 | /** |
|
- | 2632 | * __drm_atomic_helper_connector_reset - reset state on connector |
|
- | 2633 | * @connector: drm connector |
|
- | 2634 | * @conn_state: connector state to assign |
|
- | 2635 | * |
|
- | 2636 | * Initializes the newly allocated @conn_state and assigns it to |
|
- | 2637 | * #connector ->state, usually required when initializing the drivers |
|
- | 2638 | * or when called from the ->reset hook. |
|
- | 2639 | * |
|
- | 2640 | * This is useful for drivers that subclass the connector state. |
|
- | 2641 | */ |
|
- | 2642 | void |
|
- | 2643 | __drm_atomic_helper_connector_reset(struct drm_connector *connector, |
|
- | 2644 | struct drm_connector_state *conn_state) |
|
- | 2645 | { |
|
- | 2646 | if (conn_state) |
|
- | 2647 | conn_state->connector = connector; |
|
- | 2648 | ||
- | 2649 | connector->state = conn_state; |
|
- | 2650 | } |
|
- | 2651 | EXPORT_SYMBOL(__drm_atomic_helper_connector_reset); |
|
- | 2652 | ||
2366 | /** |
2653 | /** |
2367 | * drm_atomic_helper_connector_reset - default ->reset hook for connectors |
2654 | * drm_atomic_helper_connector_reset - default ->reset hook for connectors |
2368 | * @connector: drm connector |
2655 | * @connector: drm connector |
2369 | * |
2656 | * |
2370 | * Resets the atomic state for @connector by freeing the state pointer (which |
2657 | * Resets the atomic state for @connector by freeing the state pointer (which |
2371 | * might be NULL, e.g. at driver load time) and allocating a new empty state |
2658 | * might be NULL, e.g. at driver load time) and allocating a new empty state |
2372 | * object. |
2659 | * object. |
2373 | */ |
2660 | */ |
2374 | void drm_atomic_helper_connector_reset(struct drm_connector *connector) |
2661 | void drm_atomic_helper_connector_reset(struct drm_connector *connector) |
2375 | { |
2662 | { |
2376 | kfree(connector->state); |
2663 | struct drm_connector_state *conn_state = |
Line 2377... | Line 2664... | ||
2377 | connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL); |
2664 | kzalloc(sizeof(*conn_state), GFP_KERNEL); |
2378 | 2665 | ||
2379 | if (connector->state) |
2666 | kfree(connector->state); |
2380 | connector->state->connector = connector; |
2667 | __drm_atomic_helper_connector_reset(connector, conn_state); |
Line 2381... | Line 2668... | ||
2381 | } |
2668 | } |
2382 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); |
2669 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); |
Line 2424... | Line 2711... | ||
2424 | * drm_atomic_helper_duplicate_state - duplicate an atomic state object |
2711 | * drm_atomic_helper_duplicate_state - duplicate an atomic state object |
2425 | * @dev: DRM device |
2712 | * @dev: DRM device |
2426 | * @ctx: lock acquisition context |
2713 | * @ctx: lock acquisition context |
2427 | * |
2714 | * |
2428 | * Makes a copy of the current atomic state by looping over all objects and |
2715 | * Makes a copy of the current atomic state by looping over all objects and |
2429 | * duplicating their respective states. |
2716 | * duplicating their respective states. This is used for example by suspend/ |
- | 2717 | * resume support code to save the state prior to suspend such that it can |
|
- | 2718 | * be restored upon resume. |
|
2430 | * |
2719 | * |
2431 | * Note that this treats atomic state as persistent between save and restore. |
2720 | * Note that this treats atomic state as persistent between save and restore. |
2432 | * Drivers must make sure that this is possible and won't result in confusion |
2721 | * Drivers must make sure that this is possible and won't result in confusion |
2433 | * or erroneous behaviour. |
2722 | * or erroneous behaviour. |
2434 | * |
2723 | * |
Line 2436... | Line 2725... | ||
2436 | * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). |
2725 | * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). |
2437 | * |
2726 | * |
2438 | * Returns: |
2727 | * Returns: |
2439 | * A pointer to the copy of the atomic state object on success or an |
2728 | * A pointer to the copy of the atomic state object on success or an |
2440 | * ERR_PTR()-encoded error code on failure. |
2729 | * ERR_PTR()-encoded error code on failure. |
- | 2730 | * |
|
- | 2731 | * See also: |
|
- | 2732 | * drm_atomic_helper_suspend(), drm_atomic_helper_resume() |
|
2441 | */ |
2733 | */ |
2442 | struct drm_atomic_state * |
2734 | struct drm_atomic_state * |
2443 | drm_atomic_helper_duplicate_state(struct drm_device *dev, |
2735 | drm_atomic_helper_duplicate_state(struct drm_device *dev, |
2444 | struct drm_modeset_acquire_ctx *ctx) |
2736 | struct drm_modeset_acquire_ctx *ctx) |
2445 | { |
2737 | { |