]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/gpu/drm/drm_atomic_helper.c
drm/atomic-helper: implementatations for legacy interfaces
[mirror_ubuntu-zesty-kernel.git] / drivers / gpu / drm / drm_atomic_helper.c
CommitLineData
c2fcd274
DV
1/*
2 * Copyright (C) 2014 Red Hat
3 * Copyright (C) 2014 Intel Corp.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Rob Clark <robdclark@gmail.com>
25 * Daniel Vetter <daniel.vetter@ffwll.ch>
26 */
27
28#include <drm/drmP.h>
29#include <drm/drm_atomic.h>
30#include <drm/drm_plane_helper.h>
31#include <drm/drm_crtc_helper.h>
623369e5 32#include <drm/drm_atomic_helper.h>
c2fcd274
DV
33
34static void
35drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
36 struct drm_plane_state *plane_state,
37 struct drm_plane *plane)
38{
39 struct drm_crtc_state *crtc_state;
40
41 if (plane->state->crtc) {
42 crtc_state = state->crtc_states[drm_crtc_index(plane->crtc)];
43
44 if (WARN_ON(!crtc_state))
45 return;
46
47 crtc_state->planes_changed = true;
48 }
49
50 if (plane_state->crtc) {
51 crtc_state =
52 state->crtc_states[drm_crtc_index(plane_state->crtc)];
53
54 if (WARN_ON(!crtc_state))
55 return;
56
57 crtc_state->planes_changed = true;
58 }
59}
60
623369e5
DV
61static struct drm_crtc *
62get_current_crtc_for_encoder(struct drm_device *dev,
63 struct drm_encoder *encoder)
64{
65 struct drm_mode_config *config = &dev->mode_config;
66 struct drm_connector *connector;
67
68 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
69
70 list_for_each_entry(connector, &config->connector_list, head) {
71 if (connector->state->best_encoder != encoder)
72 continue;
73
74 return connector->state->crtc;
75 }
76
77 return NULL;
78}
79
80static int
81steal_encoder(struct drm_atomic_state *state,
82 struct drm_encoder *encoder,
83 struct drm_crtc *encoder_crtc)
84{
85 struct drm_mode_config *config = &state->dev->mode_config;
86 struct drm_crtc_state *crtc_state;
87 struct drm_connector *connector;
88 struct drm_connector_state *connector_state;
042652ed 89 int ret;
623369e5
DV
90
91 /*
92 * We can only steal an encoder coming from a connector, which means we
93 * must already hold the connection_mutex.
94 */
95 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
96
97 DRM_DEBUG_KMS("[ENCODER:%d:%s] in use on [CRTC:%d], stealing it\n",
98 encoder->base.id, encoder->name,
99 encoder_crtc->base.id);
100
101 crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc);
102 if (IS_ERR(crtc_state))
103 return PTR_ERR(crtc_state);
104
105 crtc_state->mode_changed = true;
106
107 list_for_each_entry(connector, &config->connector_list, head) {
108 if (connector->state->best_encoder != encoder)
109 continue;
110
111 DRM_DEBUG_KMS("Stealing encoder from [CONNECTOR:%d:%s]\n",
112 connector->base.id,
113 connector->name);
114
115 connector_state = drm_atomic_get_connector_state(state,
116 connector);
117 if (IS_ERR(connector_state))
118 return PTR_ERR(connector_state);
119
042652ed
DV
120 ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
121 if (ret)
122 return ret;
623369e5
DV
123 connector_state->best_encoder = NULL;
124 }
125
126 return 0;
127}
128
129static int
130update_connector_routing(struct drm_atomic_state *state, int conn_idx)
131{
132 struct drm_connector_helper_funcs *funcs;
133 struct drm_encoder *new_encoder;
134 struct drm_crtc *encoder_crtc;
135 struct drm_connector *connector;
136 struct drm_connector_state *connector_state;
137 struct drm_crtc_state *crtc_state;
138 int idx, ret;
139
140 connector = state->connectors[conn_idx];
141 connector_state = state->connector_states[conn_idx];
142
143 if (!connector)
144 return 0;
145
146 DRM_DEBUG_KMS("Updating routing for [CONNECTOR:%d:%s]\n",
147 connector->base.id,
148 connector->name);
149
150 if (connector->state->crtc != connector_state->crtc) {
151 if (connector->state->crtc) {
152 idx = drm_crtc_index(connector->state->crtc);
153
154 crtc_state = state->crtc_states[idx];
155 crtc_state->mode_changed = true;
156 }
157
158 if (connector_state->crtc) {
159 idx = drm_crtc_index(connector_state->crtc);
160
161 crtc_state = state->crtc_states[idx];
162 crtc_state->mode_changed = true;
163 }
164 }
165
166 if (!connector_state->crtc) {
167 DRM_DEBUG_KMS("Disabling [CONNECTOR:%d:%s]\n",
168 connector->base.id,
169 connector->name);
170
171 connector_state->best_encoder = NULL;
172
173 return 0;
174 }
175
176 funcs = connector->helper_private;
177 new_encoder = funcs->best_encoder(connector);
178
179 if (!new_encoder) {
180 DRM_DEBUG_KMS("No suitable encoder found for [CONNECTOR:%d:%s]\n",
181 connector->base.id,
182 connector->name);
183 return -EINVAL;
184 }
185
186 if (new_encoder == connector_state->best_encoder) {
187 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
188 connector->base.id,
189 connector->name,
190 new_encoder->base.id,
191 new_encoder->name,
192 connector_state->crtc->base.id);
193
194 return 0;
195 }
196
197 encoder_crtc = get_current_crtc_for_encoder(state->dev,
198 new_encoder);
199
200 if (encoder_crtc) {
201 ret = steal_encoder(state, new_encoder, encoder_crtc);
202 if (ret) {
203 DRM_DEBUG_KMS("Encoder stealing failed for [CONNECTOR:%d:%s]\n",
204 connector->base.id,
205 connector->name);
206 return ret;
207 }
208 }
209
210 connector_state->best_encoder = new_encoder;
211 idx = drm_crtc_index(connector_state->crtc);
212
213 crtc_state = state->crtc_states[idx];
214 crtc_state->mode_changed = true;
215
216 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n",
217 connector->base.id,
218 connector->name,
219 new_encoder->base.id,
220 new_encoder->name,
221 connector_state->crtc->base.id);
222
223 return 0;
224}
225
226static int
227mode_fixup(struct drm_atomic_state *state)
228{
229 int ncrtcs = state->dev->mode_config.num_crtc;
230 int nconnectors = state->dev->mode_config.num_connector;
231 struct drm_crtc_state *crtc_state;
232 struct drm_connector_state *conn_state;
233 int i;
234 bool ret;
235
236 for (i = 0; i < ncrtcs; i++) {
237 crtc_state = state->crtc_states[i];
238
239 if (!crtc_state || !crtc_state->mode_changed)
240 continue;
241
242 drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
243 }
244
245 for (i = 0; i < nconnectors; i++) {
246 struct drm_encoder_helper_funcs *funcs;
247 struct drm_encoder *encoder;
248
249 conn_state = state->connector_states[i];
250
251 if (!conn_state)
252 continue;
253
254 WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc);
255
256 if (!conn_state->crtc || !conn_state->best_encoder)
257 continue;
258
259 crtc_state =
260 state->crtc_states[drm_crtc_index(conn_state->crtc)];
261
262 /*
263 * Each encoder has at most one connector (since we always steal
264 * it away), so we won't call ->mode_fixup twice.
265 */
266 encoder = conn_state->best_encoder;
267 funcs = encoder->helper_private;
268
269 if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
270 ret = encoder->bridge->funcs->mode_fixup(
271 encoder->bridge, &crtc_state->mode,
272 &crtc_state->adjusted_mode);
273 if (!ret) {
274 DRM_DEBUG_KMS("Bridge fixup failed\n");
275 return -EINVAL;
276 }
277 }
278
279
280 ret = funcs->mode_fixup(encoder, &crtc_state->mode,
281 &crtc_state->adjusted_mode);
282 if (!ret) {
283 DRM_DEBUG_KMS("[ENCODER:%d:%s] fixup failed\n",
284 encoder->base.id, encoder->name);
285 return -EINVAL;
286 }
287 }
288
289 for (i = 0; i < ncrtcs; i++) {
290 struct drm_crtc_helper_funcs *funcs;
291 struct drm_crtc *crtc;
292
293 crtc_state = state->crtc_states[i];
294 crtc = state->crtcs[i];
295
296 if (!crtc_state || !crtc_state->mode_changed)
297 continue;
298
299 funcs = crtc->helper_private;
300 ret = funcs->mode_fixup(crtc, &crtc_state->mode,
301 &crtc_state->adjusted_mode);
302 if (!ret) {
303 DRM_DEBUG_KMS("[CRTC:%d] fixup failed\n",
304 crtc->base.id);
305 return -EINVAL;
306 }
307 }
308
309 return 0;
310}
311
312static int
313drm_atomic_helper_check_prepare(struct drm_device *dev,
314 struct drm_atomic_state *state)
315{
316 int ncrtcs = dev->mode_config.num_crtc;
317 int nconnectors = dev->mode_config.num_connector;
318 struct drm_crtc *crtc;
319 struct drm_crtc_state *crtc_state;
320 int i, ret;
321
322 for (i = 0; i < ncrtcs; i++) {
323 crtc = state->crtcs[i];
324 crtc_state = state->crtc_states[i];
325
326 if (!crtc)
327 continue;
328
329 if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) {
330 DRM_DEBUG_KMS("[CRTC:%d] mode changed\n",
331 crtc->base.id);
332 crtc_state->mode_changed = true;
333 }
334
335 if (crtc->state->enable != crtc_state->enable) {
336 DRM_DEBUG_KMS("[CRTC:%d] enable changed\n",
337 crtc->base.id);
338 crtc_state->mode_changed = true;
339 }
340 }
341
342 for (i = 0; i < nconnectors; i++) {
343 /*
344 * This only sets crtc->mode_changed for routing changes,
345 * drivers must set crtc->mode_changed themselves when connector
346 * properties need to be updated.
347 */
348 ret = update_connector_routing(state, i);
349 if (ret)
350 return ret;
351 }
352
353 /*
354 * After all the routing has been prepared we need to add in any
355 * connector which is itself unchanged, but who's crtc changes it's
356 * configuration. This must be done before calling mode_fixup in case a
357 * crtc only changed its mode but has the same set of connectors.
358 */
359 for (i = 0; i < ncrtcs; i++) {
360 int num_connectors;
361
362 crtc = state->crtcs[i];
363 crtc_state = state->crtc_states[i];
364
365 if (!crtc || !crtc_state->mode_changed)
366 continue;
367
368 DRM_DEBUG_KMS("[CRTC:%d] needs full modeset, enable: %c\n",
369 crtc->base.id,
370 crtc_state->enable ? 'y' : 'n');
371
372 ret = drm_atomic_add_affected_connectors(state, crtc);
373 if (ret != 0)
374 return ret;
375
376 num_connectors = drm_atomic_connectors_for_crtc(state,
377 crtc);
378
379 if (crtc_state->enable != !!num_connectors) {
380 DRM_DEBUG_KMS("[CRTC:%d] enabled/connectors mismatch\n",
381 crtc->base.id);
382
383 return -EINVAL;
384 }
385 }
386
387 return mode_fixup(state);
388}
389
c2fcd274
DV
390/**
391 * drm_atomic_helper_check - validate state object
392 * @dev: DRM device
393 * @state: the driver state object
394 *
395 * Check the state object to see if the requested state is physically possible.
396 * Only crtcs and planes have check callbacks, so for any additional (global)
397 * checking that a driver needs it can simply wrap that around this function.
398 * Drivers without such needs can directly use this as their ->atomic_check()
399 * callback.
400 *
401 * RETURNS
402 * Zero for success or -errno
403 */
404int drm_atomic_helper_check(struct drm_device *dev,
405 struct drm_atomic_state *state)
406{
407 int nplanes = dev->mode_config.num_total_plane;
408 int ncrtcs = dev->mode_config.num_crtc;
409 int i, ret = 0;
410
623369e5
DV
411 ret = drm_atomic_helper_check_prepare(dev, state);
412 if (ret)
413 return ret;
414
c2fcd274
DV
415 for (i = 0; i < nplanes; i++) {
416 struct drm_plane_helper_funcs *funcs;
417 struct drm_plane *plane = state->planes[i];
418 struct drm_plane_state *plane_state = state->plane_states[i];
419
420 if (!plane)
421 continue;
422
423 funcs = plane->helper_private;
424
425 drm_atomic_helper_plane_changed(state, plane_state, plane);
426
427 if (!funcs || !funcs->atomic_check)
428 continue;
429
430 ret = funcs->atomic_check(plane, plane_state);
431 if (ret) {
432 DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n",
433 plane->base.id);
434 return ret;
435 }
436 }
437
438 for (i = 0; i < ncrtcs; i++) {
439 struct drm_crtc_helper_funcs *funcs;
440 struct drm_crtc *crtc = state->crtcs[i];
441
442 if (!crtc)
443 continue;
444
445 funcs = crtc->helper_private;
446
447 if (!funcs || !funcs->atomic_check)
448 continue;
449
450 ret = funcs->atomic_check(crtc, state->crtc_states[i]);
451 if (ret) {
452 DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n",
453 crtc->base.id);
454 return ret;
455 }
456 }
457
458 return ret;
459}
460EXPORT_SYMBOL(drm_atomic_helper_check);
461
623369e5
DV
462static void
463disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
464{
465 int ncrtcs = old_state->dev->mode_config.num_crtc;
466 int nconnectors = old_state->dev->mode_config.num_connector;
467 int i;
468
469 for (i = 0; i < nconnectors; i++) {
470 struct drm_connector_state *old_conn_state;
471 struct drm_connector *connector;
472 struct drm_encoder_helper_funcs *funcs;
473 struct drm_encoder *encoder;
474
475 old_conn_state = old_state->connector_states[i];
476 connector = old_state->connectors[i];
477
478 /* Shut down everything that's in the changeset and currently
479 * still on. So need to check the old, saved state. */
480 if (!old_conn_state || !old_conn_state->crtc)
481 continue;
482
483 encoder = connector->state->best_encoder;
484
485 if (!encoder)
486 continue;
487
488 funcs = encoder->helper_private;
489
490 /*
491 * Each encoder has at most one connector (since we always steal
492 * it away), so we won't call call disable hooks twice.
493 */
494 if (encoder->bridge)
495 encoder->bridge->funcs->disable(encoder->bridge);
496
497 /* Right function depends upon target state. */
498 if (connector->state->crtc)
499 funcs->prepare(encoder);
500 else if (funcs->disable)
501 funcs->disable(encoder);
502 else
503 funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
504
505 if (encoder->bridge)
506 encoder->bridge->funcs->post_disable(encoder->bridge);
507 }
508
509 for (i = 0; i < ncrtcs; i++) {
510 struct drm_crtc_helper_funcs *funcs;
511 struct drm_crtc *crtc;
512
513 crtc = old_state->crtcs[i];
514
515 /* Shut down everything that needs a full modeset. */
516 if (!crtc || !crtc->state->mode_changed)
517 continue;
518
519 funcs = crtc->helper_private;
520
521 /* Right function depends upon target state. */
522 if (crtc->state->enable)
523 funcs->prepare(crtc);
524 else if (funcs->disable)
525 funcs->disable(crtc);
526 else
527 funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
528 }
529}
530
531static void
532set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state)
533{
534 int nconnectors = dev->mode_config.num_connector;
535 int ncrtcs = old_state->dev->mode_config.num_crtc;
536 int i;
537
538 /* clear out existing links */
539 for (i = 0; i < nconnectors; i++) {
540 struct drm_connector *connector;
541
542 connector = old_state->connectors[i];
543
544 if (!connector || !connector->encoder)
545 continue;
546
547 WARN_ON(!connector->encoder->crtc);
548
549 connector->encoder->crtc = NULL;
550 connector->encoder = NULL;
551 }
552
553 /* set new links */
554 for (i = 0; i < nconnectors; i++) {
555 struct drm_connector *connector;
556
557 connector = old_state->connectors[i];
558
559 if (!connector || !connector->state->crtc)
560 continue;
561
562 if (WARN_ON(!connector->state->best_encoder))
563 continue;
564
565 connector->encoder = connector->state->best_encoder;
566 connector->encoder->crtc = connector->state->crtc;
567 }
568
569 /* set legacy state in the crtc structure */
570 for (i = 0; i < ncrtcs; i++) {
571 struct drm_crtc *crtc;
572
573 crtc = old_state->crtcs[i];
574
575 if (!crtc)
576 continue;
577
578 crtc->mode = crtc->state->mode;
579 crtc->enabled = crtc->state->enable;
580 crtc->x = crtc->primary->state->src_x >> 16;
581 crtc->y = crtc->primary->state->src_y >> 16;
582 }
583}
584
585static void
586crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
587{
588 int ncrtcs = old_state->dev->mode_config.num_crtc;
589 int nconnectors = old_state->dev->mode_config.num_connector;
590 int i;
591
592 for (i = 0; i < ncrtcs; i++) {
593 struct drm_crtc_helper_funcs *funcs;
594 struct drm_crtc *crtc;
595
596 crtc = old_state->crtcs[i];
597
598 if (!crtc || !crtc->state->mode_changed)
599 continue;
600
601 funcs = crtc->helper_private;
602
603 if (crtc->state->enable)
604 funcs->mode_set_nofb(crtc);
605 }
606
607 for (i = 0; i < nconnectors; i++) {
608 struct drm_connector *connector;
609 struct drm_crtc_state *new_crtc_state;
610 struct drm_encoder_helper_funcs *funcs;
611 struct drm_encoder *encoder;
612 struct drm_display_mode *mode, *adjusted_mode;
613
614 connector = old_state->connectors[i];
615
616 if (!connector || !connector->state->best_encoder)
617 continue;
618
619 encoder = connector->state->best_encoder;
620 funcs = encoder->helper_private;
621 new_crtc_state = connector->state->crtc->state;
622 mode = &new_crtc_state->mode;
623 adjusted_mode = &new_crtc_state->adjusted_mode;
624
625 /*
626 * Each encoder has at most one connector (since we always steal
627 * it away), so we won't call call mode_set hooks twice.
628 */
629 funcs->mode_set(encoder, mode, adjusted_mode);
630
631 if (encoder->bridge && encoder->bridge->funcs->mode_set)
632 encoder->bridge->funcs->mode_set(encoder->bridge,
633 mode, adjusted_mode);
634 }
635}
636
637/**
638 * drm_atomic_helper_commit_pre_planes - modeset commit before plane updates
639 * @dev: DRM device
640 * @state: atomic state
641 *
642 * This function commits the modeset changes that need to be committed before
643 * updating planes. It shuts down all the outputs that need to be shut down and
644 * prepares them (if required) with the new mode.
645 */
646void drm_atomic_helper_commit_pre_planes(struct drm_device *dev,
647 struct drm_atomic_state *state)
648{
649 disable_outputs(dev, state);
650 set_routing_links(dev, state);
651 crtc_set_mode(dev, state);
652}
653EXPORT_SYMBOL(drm_atomic_helper_commit_pre_planes);
654
655/**
656 * drm_atomic_helper_commit_post_planes - modeset commit after plane updates
657 * @dev: DRM device
658 * @old_state: atomic state object with old state structures
659 *
660 * This function commits the modeset changes that need to be committed after
661 * updating planes: It enables all the outputs with the new configuration which
662 * had to be turned off for the update.
663 */
664void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
665 struct drm_atomic_state *old_state)
666{
667 int ncrtcs = old_state->dev->mode_config.num_crtc;
668 int nconnectors = old_state->dev->mode_config.num_connector;
669 int i;
670
671 for (i = 0; i < ncrtcs; i++) {
672 struct drm_crtc_helper_funcs *funcs;
673 struct drm_crtc *crtc;
674
675 crtc = old_state->crtcs[i];
676
677 /* Need to filter out CRTCs where only planes change. */
678 if (!crtc || !crtc->state->mode_changed)
679 continue;
680
681 funcs = crtc->helper_private;
682
683 if (crtc->state->enable)
684 funcs->commit(crtc);
685 }
686
687 for (i = 0; i < nconnectors; i++) {
688 struct drm_connector *connector;
689 struct drm_encoder_helper_funcs *funcs;
690 struct drm_encoder *encoder;
691
692 connector = old_state->connectors[i];
693
694 if (!connector || !connector->state->best_encoder)
695 continue;
696
697 encoder = connector->state->best_encoder;
698 funcs = encoder->helper_private;
699
700 /*
701 * Each encoder has at most one connector (since we always steal
702 * it away), so we won't call call enable hooks twice.
703 */
704 if (encoder->bridge)
705 encoder->bridge->funcs->pre_enable(encoder->bridge);
706
707 funcs->commit(encoder);
708
709 if (encoder->bridge)
710 encoder->bridge->funcs->enable(encoder->bridge);
711 }
712}
713EXPORT_SYMBOL(drm_atomic_helper_commit_post_planes);
714
715static void
716wait_for_vblanks(struct drm_device *dev, struct drm_atomic_state *old_state)
717{
718 struct drm_crtc *crtc;
719 struct drm_crtc_state *old_crtc_state;
720 int ncrtcs = old_state->dev->mode_config.num_crtc;
721 int i, ret;
722
723 for (i = 0; i < ncrtcs; i++) {
724 crtc = old_state->crtcs[i];
725 old_crtc_state = old_state->crtc_states[i];
726
727 if (!crtc)
728 continue;
729
730 /* No one cares about the old state, so abuse it for tracking
731 * and store whether we hold a vblank reference (and should do a
732 * vblank wait) in the ->enable boolean. */
733 old_crtc_state->enable = false;
734
735 if (!crtc->state->enable)
736 continue;
737
738 ret = drm_crtc_vblank_get(crtc);
739 if (ret != 0)
740 continue;
741
742 old_crtc_state->enable = true;
743 old_crtc_state->last_vblank_count = drm_vblank_count(dev, i);
744 }
745
746 for (i = 0; i < ncrtcs; i++) {
747 crtc = old_state->crtcs[i];
748 old_crtc_state = old_state->crtc_states[i];
749
750 if (!crtc || !old_crtc_state->enable)
751 continue;
752
753 ret = wait_event_timeout(dev->vblank[i].queue,
754 old_crtc_state->last_vblank_count !=
755 drm_vblank_count(dev, i),
756 msecs_to_jiffies(50));
757
758 drm_crtc_vblank_put(crtc);
759 }
760}
761
762/**
763 * drm_atomic_helper_commit - commit validated state object
764 * @dev: DRM device
765 * @state: the driver state object
766 * @async: asynchronous commit
767 *
768 * This function commits a with drm_atomic_helper_check() pre-validated state
769 * object. This can still fail when e.g. the framebuffer reservation fails. For
770 * now this doesn't implement asynchronous commits.
771 *
772 * RETURNS
773 * Zero for success or -errno.
774 */
775int drm_atomic_helper_commit(struct drm_device *dev,
776 struct drm_atomic_state *state,
777 bool async)
778{
779 int ret;
780
781 if (async)
782 return -EBUSY;
783
784 ret = drm_atomic_helper_prepare_planes(dev, state);
785 if (ret)
786 return ret;
787
788 /*
789 * This is the point of no return - everything below never fails except
790 * when the hw goes bonghits. Which means we can commit the new state on
791 * the software side now.
792 */
793
794 drm_atomic_helper_swap_state(dev, state);
795
796 /*
797 * Everything below can be run asynchronously without the need to grab
798 * any modeset locks at all under one conditions: It must be guaranteed
799 * that the asynchronous work has either been cancelled (if the driver
800 * supports it, which at least requires that the framebuffers get
801 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
802 * before the new state gets committed on the software side with
803 * drm_atomic_helper_swap_state().
804 *
805 * This scheme allows new atomic state updates to be prepared and
806 * checked in parallel to the asynchronous completion of the previous
807 * update. Which is important since compositors need to figure out the
808 * composition of the next frame right after having submitted the
809 * current layout.
810 */
811
812 drm_atomic_helper_commit_pre_planes(dev, state);
813
814 drm_atomic_helper_commit_planes(dev, state);
815
816 drm_atomic_helper_commit_post_planes(dev, state);
817
818 wait_for_vblanks(dev, state);
819
820 drm_atomic_helper_cleanup_planes(dev, state);
821
822 drm_atomic_state_free(state);
823
824 return 0;
825}
826EXPORT_SYMBOL(drm_atomic_helper_commit);
827
c2fcd274
DV
828/**
829 * drm_atomic_helper_prepare_planes - prepare plane resources after commit
830 * @dev: DRM device
831 * @state: atomic state object with old state structures
832 *
833 * This function prepares plane state, specifically framebuffers, for the new
834 * configuration. If any failure is encountered this function will call
835 * ->cleanup_fb on any already successfully prepared framebuffer.
836 *
837 * Returns:
838 * 0 on success, negative error code on failure.
839 */
840int drm_atomic_helper_prepare_planes(struct drm_device *dev,
841 struct drm_atomic_state *state)
842{
843 int nplanes = dev->mode_config.num_total_plane;
844 int ret, i;
845
846 for (i = 0; i < nplanes; i++) {
847 struct drm_plane_helper_funcs *funcs;
848 struct drm_plane *plane = state->planes[i];
849 struct drm_framebuffer *fb;
850
851 if (!plane)
852 continue;
853
854 funcs = plane->helper_private;
855
856 fb = state->plane_states[i]->fb;
857
858 if (fb && funcs->prepare_fb) {
859 ret = funcs->prepare_fb(plane, fb);
860 if (ret)
861 goto fail;
862 }
863 }
864
865 return 0;
866
867fail:
868 for (i--; i >= 0; i--) {
869 struct drm_plane_helper_funcs *funcs;
870 struct drm_plane *plane = state->planes[i];
871 struct drm_framebuffer *fb;
872
873 if (!plane)
874 continue;
875
876 funcs = plane->helper_private;
877
878 fb = state->plane_states[i]->fb;
879
880 if (fb && funcs->cleanup_fb)
881 funcs->cleanup_fb(plane, fb);
882
883 }
884
885 return ret;
886}
887EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
888
889/**
890 * drm_atomic_helper_commit_planes - commit plane state
891 * @dev: DRM device
892 * @state: atomic state
893 *
894 * This function commits the new plane state using the plane and atomic helper
895 * functions for planes and crtcs. It assumes that the atomic state has already
896 * been pushed into the relevant object state pointers, since this step can no
897 * longer fail.
898 *
899 * It still requires the global state object @state to know which planes and
900 * crtcs need to be updated though.
901 */
902void drm_atomic_helper_commit_planes(struct drm_device *dev,
903 struct drm_atomic_state *state)
904{
905 int nplanes = dev->mode_config.num_total_plane;
906 int ncrtcs = dev->mode_config.num_crtc;
907 int i;
908
909 for (i = 0; i < ncrtcs; i++) {
910 struct drm_crtc_helper_funcs *funcs;
911 struct drm_crtc *crtc = state->crtcs[i];
912
913 if (!crtc)
914 continue;
915
916 funcs = crtc->helper_private;
917
918 if (!funcs || !funcs->atomic_begin)
919 continue;
920
921 funcs->atomic_begin(crtc);
922 }
923
924 for (i = 0; i < nplanes; i++) {
925 struct drm_plane_helper_funcs *funcs;
926 struct drm_plane *plane = state->planes[i];
927
928 if (!plane)
929 continue;
930
931 funcs = plane->helper_private;
932
933 if (!funcs || !funcs->atomic_update)
934 continue;
935
936 funcs->atomic_update(plane);
937 }
938
939 for (i = 0; i < ncrtcs; i++) {
940 struct drm_crtc_helper_funcs *funcs;
941 struct drm_crtc *crtc = state->crtcs[i];
942
943 if (!crtc)
944 continue;
945
946 funcs = crtc->helper_private;
947
948 if (!funcs || !funcs->atomic_flush)
949 continue;
950
951 funcs->atomic_flush(crtc);
952 }
953}
954EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
955
956/**
957 * drm_atomic_helper_cleanup_planes - cleanup plane resources after commit
958 * @dev: DRM device
959 * @old_state: atomic state object with old state structures
960 *
961 * This function cleans up plane state, specifically framebuffers, from the old
962 * configuration. Hence the old configuration must be perserved in @old_state to
963 * be able to call this function.
964 *
965 * This function must also be called on the new state when the atomic update
966 * fails at any point after calling drm_atomic_helper_prepare_planes().
967 */
968void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
969 struct drm_atomic_state *old_state)
970{
971 int nplanes = dev->mode_config.num_total_plane;
972 int i;
973
974 for (i = 0; i < nplanes; i++) {
975 struct drm_plane_helper_funcs *funcs;
976 struct drm_plane *plane = old_state->planes[i];
977 struct drm_framebuffer *old_fb;
978
979 if (!plane)
980 continue;
981
982 funcs = plane->helper_private;
983
984 old_fb = old_state->plane_states[i]->fb;
985
986 if (old_fb && funcs->cleanup_fb)
987 funcs->cleanup_fb(plane, old_fb);
988 }
989}
990EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
991
992/**
993 * drm_atomic_helper_swap_state - store atomic state into current sw state
994 * @dev: DRM device
995 * @state: atomic state
996 *
997 * This function stores the atomic state into the current state pointers in all
998 * driver objects. It should be called after all failing steps have been done
999 * and succeeded, but before the actual hardware state is committed.
1000 *
1001 * For cleanup and error recovery the current state for all changed objects will
1002 * be swaped into @state.
1003 *
1004 * With that sequence it fits perfectly into the plane prepare/cleanup sequence:
1005 *
1006 * 1. Call drm_atomic_helper_prepare_planes() with the staged atomic state.
1007 *
1008 * 2. Do any other steps that might fail.
1009 *
1010 * 3. Put the staged state into the current state pointers with this function.
1011 *
1012 * 4. Actually commit the hardware state.
1013 *
1014 * 5. Call drm_atomic_helper_cleanup_planes with @state, which since step 3
1015 * contains the old state. Also do any other cleanup required with that state.
1016 */
1017void drm_atomic_helper_swap_state(struct drm_device *dev,
1018 struct drm_atomic_state *state)
1019{
1020 int i;
1021
1022 for (i = 0; i < dev->mode_config.num_connector; i++) {
1023 struct drm_connector *connector = state->connectors[i];
1024
1025 if (!connector)
1026 continue;
1027
1028 connector->state->state = state;
1029 swap(state->connector_states[i], connector->state);
1030 connector->state->state = NULL;
1031 }
1032
1033 for (i = 0; i < dev->mode_config.num_crtc; i++) {
1034 struct drm_crtc *crtc = state->crtcs[i];
1035
1036 if (!crtc)
1037 continue;
1038
1039 crtc->state->state = state;
1040 swap(state->crtc_states[i], crtc->state);
1041 crtc->state->state = NULL;
1042 }
1043
1044 for (i = 0; i < dev->mode_config.num_total_plane; i++) {
1045 struct drm_plane *plane = state->planes[i];
1046
1047 if (!plane)
1048 continue;
1049
1050 plane->state->state = state;
1051 swap(state->plane_states[i], plane->state);
1052 plane->state->state = NULL;
1053 }
1054}
1055EXPORT_SYMBOL(drm_atomic_helper_swap_state);
042652ed
DV
1056
1057/**
1058 * drm_atomic_helper_update_plane - Helper for primary plane update using atomic
1059 * @plane: plane object to update
1060 * @crtc: owning CRTC of owning plane
1061 * @fb: framebuffer to flip onto plane
1062 * @crtc_x: x offset of primary plane on crtc
1063 * @crtc_y: y offset of primary plane on crtc
1064 * @crtc_w: width of primary plane rectangle on crtc
1065 * @crtc_h: height of primary plane rectangle on crtc
1066 * @src_x: x offset of @fb for panning
1067 * @src_y: y offset of @fb for panning
1068 * @src_w: width of source rectangle in @fb
1069 * @src_h: height of source rectangle in @fb
1070 *
1071 * Provides a default plane update handler using the atomic driver interface.
1072 *
1073 * RETURNS:
1074 * Zero on success, error code on failure
1075 */
1076int drm_atomic_helper_update_plane(struct drm_plane *plane,
1077 struct drm_crtc *crtc,
1078 struct drm_framebuffer *fb,
1079 int crtc_x, int crtc_y,
1080 unsigned int crtc_w, unsigned int crtc_h,
1081 uint32_t src_x, uint32_t src_y,
1082 uint32_t src_w, uint32_t src_h)
1083{
1084 struct drm_atomic_state *state;
1085 struct drm_plane_state *plane_state;
1086 int ret = 0;
1087
1088 state = drm_atomic_state_alloc(plane->dev);
1089 if (!state)
1090 return -ENOMEM;
1091
1092 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1093retry:
1094 plane_state = drm_atomic_get_plane_state(state, plane);
1095 if (IS_ERR(plane_state)) {
1096 ret = PTR_ERR(plane_state);
1097 goto fail;
1098 }
1099
1100 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
1101 if (ret != 0)
1102 goto fail;
1103 plane_state->fb = fb;
1104 plane_state->crtc_x = crtc_x;
1105 plane_state->crtc_y = crtc_y;
1106 plane_state->crtc_h = crtc_h;
1107 plane_state->crtc_w = crtc_w;
1108 plane_state->src_x = src_x;
1109 plane_state->src_y = src_y;
1110 plane_state->src_h = src_h;
1111 plane_state->src_w = src_w;
1112
1113 ret = drm_atomic_commit(state);
1114 if (ret != 0)
1115 goto fail;
1116
1117 /* Driver takes ownership of state on successful commit. */
1118 return 0;
1119fail:
1120 if (ret == -EDEADLK)
1121 goto backoff;
1122
1123 drm_atomic_state_free(state);
1124
1125 return ret;
1126backoff:
1127 drm_atomic_legacy_backoff(state);
1128 drm_atomic_state_clear(state);
1129
1130 /*
1131 * Someone might have exchanged the framebuffer while we dropped locks
1132 * in the backoff code. We need to fix up the fb refcount tracking the
1133 * core does for us.
1134 */
1135 plane->old_fb = plane->fb;
1136
1137 goto retry;
1138}
1139EXPORT_SYMBOL(drm_atomic_helper_update_plane);
1140
1141/**
1142 * drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic
1143 * @plane: plane to disable
1144 *
1145 * Provides a default plane disable handler using the atomic driver interface.
1146 *
1147 * RETURNS:
1148 * Zero on success, error code on failure
1149 */
1150int drm_atomic_helper_disable_plane(struct drm_plane *plane)
1151{
1152 struct drm_atomic_state *state;
1153 struct drm_plane_state *plane_state;
1154 int ret = 0;
1155
1156 state = drm_atomic_state_alloc(plane->dev);
1157 if (!state)
1158 return -ENOMEM;
1159
1160 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
1161retry:
1162 plane_state = drm_atomic_get_plane_state(state, plane);
1163 if (IS_ERR(plane_state)) {
1164 ret = PTR_ERR(plane_state);
1165 goto fail;
1166 }
1167
1168 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1169 if (ret != 0)
1170 goto fail;
1171 plane_state->fb = NULL;
1172 plane_state->crtc_x = 0;
1173 plane_state->crtc_y = 0;
1174 plane_state->crtc_h = 0;
1175 plane_state->crtc_w = 0;
1176 plane_state->src_x = 0;
1177 plane_state->src_y = 0;
1178 plane_state->src_h = 0;
1179 plane_state->src_w = 0;
1180
1181 ret = drm_atomic_commit(state);
1182 if (ret != 0)
1183 goto fail;
1184
1185 /* Driver takes ownership of state on successful commit. */
1186 return 0;
1187fail:
1188 if (ret == -EDEADLK)
1189 goto backoff;
1190
1191 drm_atomic_state_free(state);
1192
1193 return ret;
1194backoff:
1195 drm_atomic_legacy_backoff(state);
1196 drm_atomic_state_clear(state);
1197
1198 /*
1199 * Someone might have exchanged the framebuffer while we dropped locks
1200 * in the backoff code. We need to fix up the fb refcount tracking the
1201 * core does for us.
1202 */
1203 plane->old_fb = plane->fb;
1204
1205 goto retry;
1206}
1207EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
1208
1209static int update_output_state(struct drm_atomic_state *state,
1210 struct drm_mode_set *set)
1211{
1212 struct drm_device *dev = set->crtc->dev;
1213 struct drm_connector_state *conn_state;
1214 int nconnectors = state->dev->mode_config.num_connector;
1215 int ncrtcs = state->dev->mode_config.num_crtc;
1216 int ret, i, j;
1217
1218 ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
1219 state->acquire_ctx);
1220 if (ret)
1221 return ret;
1222
1223 /* First grab all affected connector/crtc states. */
1224 for (i = 0; i < set->num_connectors; i++) {
1225 conn_state = drm_atomic_get_connector_state(state,
1226 set->connectors[i]);
1227 if (IS_ERR(conn_state))
1228 return PTR_ERR(conn_state);
1229 }
1230
1231 for (i = 0; i < ncrtcs; i++) {
1232 struct drm_crtc *crtc = state->crtcs[i];
1233
1234 if (!crtc)
1235 continue;
1236
1237 ret = drm_atomic_add_affected_connectors(state, crtc);
1238 if (ret)
1239 return ret;
1240 }
1241
1242 /* Then recompute connector->crtc links and crtc enabling state. */
1243 for (i = 0; i < nconnectors; i++) {
1244 struct drm_connector *connector;
1245
1246 connector = state->connectors[i];
1247 conn_state = state->connector_states[i];
1248
1249 if (!connector)
1250 continue;
1251
1252 if (conn_state->crtc == set->crtc) {
1253 ret = drm_atomic_set_crtc_for_connector(conn_state,
1254 NULL);
1255 if (ret)
1256 return ret;
1257 }
1258
1259 for (j = 0; j < set->num_connectors; j++) {
1260 if (set->connectors[j] == connector) {
1261 ret = drm_atomic_set_crtc_for_connector(conn_state,
1262 set->crtc);
1263 if (ret)
1264 return ret;
1265 break;
1266 }
1267 }
1268 }
1269
1270 for (i = 0; i < ncrtcs; i++) {
1271 struct drm_crtc *crtc = state->crtcs[i];
1272 struct drm_crtc_state *crtc_state = state->crtc_states[i];
1273
1274 if (!crtc)
1275 continue;
1276
1277 /* Don't update ->enable for the CRTC in the set_config request,
1278 * since a mismatch would indicate a bug in the upper layers.
1279 * The actual modeset code later on will catch any
1280 * inconsistencies here. */
1281 if (crtc == set->crtc)
1282 continue;
1283
1284 crtc_state->enable =
1285 drm_atomic_connectors_for_crtc(state, crtc);
1286 }
1287
1288 return 0;
1289}
1290
1291/**
1292 * drm_atomic_helper_set_config - set a new config from userspace
1293 * @set: mode set configuration
1294 *
1295 * Provides a default crtc set_config handler using the atomic driver interface.
1296 *
1297 * Returns:
1298 * Returns 0 on success, negative errno numbers on failure.
1299 */
1300int drm_atomic_helper_set_config(struct drm_mode_set *set)
1301{
1302 struct drm_atomic_state *state;
1303 struct drm_crtc *crtc = set->crtc;
1304 struct drm_crtc_state *crtc_state;
1305 struct drm_plane_state *primary_state;
1306 int ret = 0;
1307
1308 state = drm_atomic_state_alloc(crtc->dev);
1309 if (!state)
1310 return -ENOMEM;
1311
1312 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1313retry:
1314 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1315 if (IS_ERR(crtc_state)) {
1316 ret = PTR_ERR(crtc_state);
1317 goto fail;
1318 }
1319
1320 if (!set->mode) {
1321 WARN_ON(set->fb);
1322 WARN_ON(set->num_connectors);
1323
1324 crtc_state->enable = false;
1325 goto commit;
1326 }
1327
1328 WARN_ON(!set->fb);
1329 WARN_ON(!set->num_connectors);
1330
1331 crtc_state->enable = true;
1332 drm_mode_copy(&crtc_state->mode, set->mode);
1333
1334 primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1335 if (IS_ERR(primary_state)) {
1336 ret = PTR_ERR(primary_state);
1337 goto fail;
1338 }
1339
1340 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1341 if (ret != 0)
1342 goto fail;
1343 primary_state->fb = set->fb;
1344 primary_state->crtc_x = 0;
1345 primary_state->crtc_y = 0;
1346 primary_state->crtc_h = set->mode->vdisplay;
1347 primary_state->crtc_w = set->mode->hdisplay;
1348 primary_state->src_x = set->x << 16;
1349 primary_state->src_y = set->y << 16;
1350 primary_state->src_h = set->mode->vdisplay << 16;
1351 primary_state->src_w = set->mode->hdisplay << 16;
1352
1353commit:
1354 ret = update_output_state(state, set);
1355 if (ret)
1356 goto fail;
1357
1358 ret = drm_atomic_commit(state);
1359 if (ret != 0)
1360 goto fail;
1361
1362 /* Driver takes ownership of state on successful commit. */
1363 return 0;
1364fail:
1365 if (ret == -EDEADLK)
1366 goto backoff;
1367
1368 drm_atomic_state_free(state);
1369
1370 return ret;
1371backoff:
1372 drm_atomic_legacy_backoff(state);
1373 drm_atomic_state_clear(state);
1374
1375 /*
1376 * Someone might have exchanged the framebuffer while we dropped locks
1377 * in the backoff code. We need to fix up the fb refcount tracking the
1378 * core does for us.
1379 */
1380 crtc->primary->old_fb = crtc->primary->fb;
1381
1382 goto retry;
1383}
1384EXPORT_SYMBOL(drm_atomic_helper_set_config);
1385
1386/**
1387 * drm_atomic_helper_crtc_set_property - helper for crtc prorties
1388 * @crtc: DRM crtc
1389 * @property: DRM property
1390 * @val: value of property
1391 *
1392 * Provides a default plane disablle handler using the atomic driver interface.
1393 *
1394 * RETURNS:
1395 * Zero on success, error code on failure
1396 */
1397int
1398drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
1399 struct drm_property *property,
1400 uint64_t val)
1401{
1402 struct drm_atomic_state *state;
1403 struct drm_crtc_state *crtc_state;
1404 int ret = 0;
1405
1406 state = drm_atomic_state_alloc(crtc->dev);
1407 if (!state)
1408 return -ENOMEM;
1409
1410 /* ->set_property is always called with all locks held. */
1411 state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
1412retry:
1413 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1414 if (IS_ERR(crtc_state)) {
1415 ret = PTR_ERR(crtc_state);
1416 goto fail;
1417 }
1418
1419 ret = crtc->funcs->atomic_set_property(crtc, crtc_state,
1420 property, val);
1421 if (ret)
1422 goto fail;
1423
1424 ret = drm_atomic_commit(state);
1425 if (ret != 0)
1426 goto fail;
1427
1428 /* Driver takes ownership of state on successful commit. */
1429 return 0;
1430fail:
1431 if (ret == -EDEADLK)
1432 goto backoff;
1433
1434 drm_atomic_state_free(state);
1435
1436 return ret;
1437backoff:
1438 drm_atomic_legacy_backoff(state);
1439 drm_atomic_state_clear(state);
1440
1441 goto retry;
1442}
1443EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property);
1444
1445/**
1446 * drm_atomic_helper_plane_set_property - helper for plane prorties
1447 * @plane: DRM plane
1448 * @property: DRM property
1449 * @val: value of property
1450 *
1451 * Provides a default plane disable handler using the atomic driver interface.
1452 *
1453 * RETURNS:
1454 * Zero on success, error code on failure
1455 */
1456int
1457drm_atomic_helper_plane_set_property(struct drm_plane *plane,
1458 struct drm_property *property,
1459 uint64_t val)
1460{
1461 struct drm_atomic_state *state;
1462 struct drm_plane_state *plane_state;
1463 int ret = 0;
1464
1465 state = drm_atomic_state_alloc(plane->dev);
1466 if (!state)
1467 return -ENOMEM;
1468
1469 /* ->set_property is always called with all locks held. */
1470 state->acquire_ctx = plane->dev->mode_config.acquire_ctx;
1471retry:
1472 plane_state = drm_atomic_get_plane_state(state, plane);
1473 if (IS_ERR(plane_state)) {
1474 ret = PTR_ERR(plane_state);
1475 goto fail;
1476 }
1477
1478 ret = plane->funcs->atomic_set_property(plane, plane_state,
1479 property, val);
1480 if (ret)
1481 goto fail;
1482
1483 ret = drm_atomic_commit(state);
1484 if (ret != 0)
1485 goto fail;
1486
1487 /* Driver takes ownership of state on successful commit. */
1488 return 0;
1489fail:
1490 if (ret == -EDEADLK)
1491 goto backoff;
1492
1493 drm_atomic_state_free(state);
1494
1495 return ret;
1496backoff:
1497 drm_atomic_legacy_backoff(state);
1498 drm_atomic_state_clear(state);
1499
1500 goto retry;
1501}
1502EXPORT_SYMBOL(drm_atomic_helper_plane_set_property);
1503
1504/**
1505 * drm_atomic_helper_connector_set_property - helper for connector prorties
1506 * @connector: DRM connector
1507 * @property: DRM property
1508 * @val: value of property
1509 *
1510 * Provides a default plane disablle handler using the atomic driver interface.
1511 *
1512 * RETURNS:
1513 * Zero on success, error code on failure
1514 */
1515int
1516drm_atomic_helper_connector_set_property(struct drm_connector *connector,
1517 struct drm_property *property,
1518 uint64_t val)
1519{
1520 struct drm_atomic_state *state;
1521 struct drm_connector_state *connector_state;
1522 int ret = 0;
1523
1524 state = drm_atomic_state_alloc(connector->dev);
1525 if (!state)
1526 return -ENOMEM;
1527
1528 /* ->set_property is always called with all locks held. */
1529 state->acquire_ctx = connector->dev->mode_config.acquire_ctx;
1530retry:
1531 connector_state = drm_atomic_get_connector_state(state, connector);
1532 if (IS_ERR(connector_state)) {
1533 ret = PTR_ERR(connector_state);
1534 goto fail;
1535 }
1536
1537 ret = connector->funcs->atomic_set_property(connector, connector_state,
1538 property, val);
1539 if (ret)
1540 goto fail;
1541
1542 ret = drm_atomic_commit(state);
1543 if (ret != 0)
1544 goto fail;
1545
1546 /* Driver takes ownership of state on successful commit. */
1547 return 0;
1548fail:
1549 if (ret == -EDEADLK)
1550 goto backoff;
1551
1552 drm_atomic_state_free(state);
1553
1554 return ret;
1555backoff:
1556 drm_atomic_legacy_backoff(state);
1557 drm_atomic_state_clear(state);
1558
1559 goto retry;
1560}
1561EXPORT_SYMBOL(drm_atomic_helper_connector_set_property);