hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/gpu/drm/drm_atomic.c
....@@ -26,12 +26,19 @@
2626 */
2727
2828
29
-#include <drm/drmP.h>
29
+#include <linux/sync_file.h>
30
+
3031 #include <drm/drm_atomic.h>
32
+#include <drm/drm_atomic_uapi.h>
33
+#include <drm/drm_bridge.h>
34
+#include <drm/drm_debugfs.h>
35
+#include <drm/drm_device.h>
36
+#include <drm/drm_drv.h>
37
+#include <drm/drm_file.h>
38
+#include <drm/drm_fourcc.h>
3139 #include <drm/drm_mode.h>
3240 #include <drm/drm_print.h>
3341 #include <drm/drm_writeback.h>
34
-#include <linux/sync_file.h>
3542
3643 #include "drm_crtc_internal.h"
3744 #include "drm_internal.h"
....@@ -91,6 +98,12 @@
9198 if (!state->planes)
9299 goto fail;
93100
101
+ /*
102
+ * Because drm_atomic_state can be committed asynchronously we need our
103
+ * own reference and cannot rely on the on implied by drm_file in the
104
+ * ioctl call.
105
+ */
106
+ drm_dev_get(dev);
94107 state->dev = dev;
95108
96109 DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state);
....@@ -245,12 +258,13 @@
245258 * @ref: This atomic state to deallocate
246259 *
247260 * This frees all memory associated with an atomic state, including all the
248
- * per-object state for planes, crtcs and connectors.
261
+ * per-object state for planes, CRTCs and connectors.
249262 */
250263 void __drm_atomic_state_free(struct kref *ref)
251264 {
252265 struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
253
- struct drm_mode_config *config = &state->dev->mode_config;
266
+ struct drm_device *dev = state->dev;
267
+ struct drm_mode_config *config = &dev->mode_config;
254268
255269 drm_atomic_state_clear(state);
256270
....@@ -262,16 +276,18 @@
262276 drm_atomic_state_default_release(state);
263277 kfree(state);
264278 }
279
+
280
+ drm_dev_put(dev);
265281 }
266282 EXPORT_SYMBOL(__drm_atomic_state_free);
267283
268284 /**
269
- * drm_atomic_get_crtc_state - get crtc state
285
+ * drm_atomic_get_crtc_state - get CRTC state
270286 * @state: global atomic state object
271
- * @crtc: crtc to get state object for
287
+ * @crtc: CRTC to get state object for
272288 *
273
- * This function returns the crtc state for the given crtc, allocating it if
274
- * needed. It will also grab the relevant crtc lock to make sure that the state
289
+ * This function returns the CRTC state for the given CRTC, allocating it if
290
+ * needed. It will also grab the relevant CRTC lock to make sure that the state
275291 * is consistent.
276292 *
277293 * Returns:
....@@ -314,363 +330,11 @@
314330 }
315331 EXPORT_SYMBOL(drm_atomic_get_crtc_state);
316332
317
-static void set_out_fence_for_crtc(struct drm_atomic_state *state,
318
- struct drm_crtc *crtc, s32 __user *fence_ptr)
333
+static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state,
334
+ const struct drm_crtc_state *new_crtc_state)
319335 {
320
- state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
321
-}
336
+ struct drm_crtc *crtc = new_crtc_state->crtc;
322337
323
-static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
324
- struct drm_crtc *crtc)
325
-{
326
- s32 __user *fence_ptr;
327
-
328
- fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
329
- state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
330
-
331
- return fence_ptr;
332
-}
333
-
334
-static int set_out_fence_for_connector(struct drm_atomic_state *state,
335
- struct drm_connector *connector,
336
- s32 __user *fence_ptr)
337
-{
338
- unsigned int index = drm_connector_index(connector);
339
-
340
- if (!fence_ptr)
341
- return 0;
342
-
343
- if (put_user(-1, fence_ptr))
344
- return -EFAULT;
345
-
346
- state->connectors[index].out_fence_ptr = fence_ptr;
347
-
348
- return 0;
349
-}
350
-
351
-static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
352
- struct drm_connector *connector)
353
-{
354
- unsigned int index = drm_connector_index(connector);
355
- s32 __user *fence_ptr;
356
-
357
- fence_ptr = state->connectors[index].out_fence_ptr;
358
- state->connectors[index].out_fence_ptr = NULL;
359
-
360
- return fence_ptr;
361
-}
362
-
363
-/**
364
- * drm_atomic_set_mode_for_crtc - set mode for CRTC
365
- * @state: the CRTC whose incoming state to update
366
- * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
367
- *
368
- * Set a mode (originating from the kernel) on the desired CRTC state and update
369
- * the enable property.
370
- *
371
- * RETURNS:
372
- * Zero on success, error code on failure. Cannot return -EDEADLK.
373
- */
374
-int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
375
- const struct drm_display_mode *mode)
376
-{
377
- struct drm_crtc *crtc = state->crtc;
378
- struct drm_mode_modeinfo umode;
379
-
380
- /* Early return for no change. */
381
- if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
382
- return 0;
383
-
384
- drm_property_blob_put(state->mode_blob);
385
- state->mode_blob = NULL;
386
-
387
- if (mode) {
388
- drm_mode_convert_to_umode(&umode, mode);
389
- state->mode_blob =
390
- drm_property_create_blob(state->crtc->dev,
391
- sizeof(umode),
392
- &umode);
393
- if (IS_ERR(state->mode_blob))
394
- return PTR_ERR(state->mode_blob);
395
-
396
- drm_mode_copy(&state->mode, mode);
397
- state->enable = true;
398
- DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
399
- mode->name, crtc->base.id, crtc->name, state);
400
- } else {
401
- memset(&state->mode, 0, sizeof(state->mode));
402
- state->enable = false;
403
- DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
404
- crtc->base.id, crtc->name, state);
405
- }
406
-
407
- return 0;
408
-}
409
-EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
410
-
411
-/**
412
- * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
413
- * @state: the CRTC whose incoming state to update
414
- * @blob: pointer to blob property to use for mode
415
- *
416
- * Set a mode (originating from a blob property) on the desired CRTC state.
417
- * This function will take a reference on the blob property for the CRTC state,
418
- * and release the reference held on the state's existing mode property, if any
419
- * was set.
420
- *
421
- * RETURNS:
422
- * Zero on success, error code on failure. Cannot return -EDEADLK.
423
- */
424
-int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
425
- struct drm_property_blob *blob)
426
-{
427
- struct drm_crtc *crtc = state->crtc;
428
-
429
- if (blob == state->mode_blob)
430
- return 0;
431
-
432
- drm_property_blob_put(state->mode_blob);
433
- state->mode_blob = NULL;
434
-
435
- memset(&state->mode, 0, sizeof(state->mode));
436
-
437
- if (blob) {
438
- int ret;
439
-
440
- if (blob->length != sizeof(struct drm_mode_modeinfo)) {
441
- DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
442
- crtc->base.id, crtc->name,
443
- blob->length);
444
- return -EINVAL;
445
- }
446
-
447
- ret = drm_mode_convert_umode(crtc->dev,
448
- &state->mode, blob->data);
449
- if (ret) {
450
- DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
451
- crtc->base.id, crtc->name,
452
- ret, drm_get_mode_status_name(state->mode.status));
453
- drm_mode_debug_printmodeline(&state->mode);
454
- return -EINVAL;
455
- }
456
-
457
- state->mode_blob = drm_property_blob_get(blob);
458
- state->enable = true;
459
- DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
460
- state->mode.name, crtc->base.id, crtc->name,
461
- state);
462
- } else {
463
- state->enable = false;
464
- DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
465
- crtc->base.id, crtc->name, state);
466
- }
467
-
468
- return 0;
469
-}
470
-EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
471
-
472
-/**
473
- * drm_atomic_replace_property_blob_from_id - lookup the new blob and replace the old one with it
474
- * @dev: DRM device
475
- * @blob: a pointer to the member blob to be replaced
476
- * @blob_id: ID of the new blob
477
- * @expected_size: total expected size of the blob data (in bytes)
478
- * @expected_elem_size: expected element size of the blob data (in bytes)
479
- * @replaced: did the blob get replaced?
480
- *
481
- * Replace @blob with another blob with the ID @blob_id. If @blob_id is zero
482
- * @blob becomes NULL.
483
- *
484
- * If @expected_size is positive the new blob length is expected to be equal
485
- * to @expected_size bytes. If @expected_elem_size is positive the new blob
486
- * length is expected to be a multiple of @expected_elem_size bytes. Otherwise
487
- * an error is returned.
488
- *
489
- * @replaced will indicate to the caller whether the blob was replaced or not.
490
- * If the old and new blobs were in fact the same blob @replaced will be false
491
- * otherwise it will be true.
492
- *
493
- * RETURNS:
494
- * Zero on success, error code on failure.
495
- */
496
-static int
497
-drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
498
- struct drm_property_blob **blob,
499
- uint64_t blob_id,
500
- ssize_t expected_size,
501
- ssize_t expected_elem_size,
502
- bool *replaced)
503
-{
504
- struct drm_property_blob *new_blob = NULL;
505
-
506
- if (blob_id != 0) {
507
- new_blob = drm_property_lookup_blob(dev, blob_id);
508
- if (new_blob == NULL)
509
- return -EINVAL;
510
-
511
- if (expected_size > 0 &&
512
- new_blob->length != expected_size) {
513
- drm_property_blob_put(new_blob);
514
- return -EINVAL;
515
- }
516
- if (expected_elem_size > 0 &&
517
- new_blob->length % expected_elem_size != 0) {
518
- drm_property_blob_put(new_blob);
519
- return -EINVAL;
520
- }
521
- }
522
-
523
- *replaced |= drm_property_replace_blob(blob, new_blob);
524
- drm_property_blob_put(new_blob);
525
-
526
- return 0;
527
-}
528
-
529
-/**
530
- * drm_atomic_crtc_set_property - set property on CRTC
531
- * @crtc: the drm CRTC to set a property on
532
- * @state: the state object to update with the new property value
533
- * @property: the property to set
534
- * @val: the new property value
535
- *
536
- * This function handles generic/core properties and calls out to driver's
537
- * &drm_crtc_funcs.atomic_set_property for driver properties. To ensure
538
- * consistent behavior you must call this function rather than the driver hook
539
- * directly.
540
- *
541
- * RETURNS:
542
- * Zero on success, error code on failure
543
- */
544
-int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
545
- struct drm_crtc_state *state, struct drm_property *property,
546
- uint64_t val)
547
-{
548
- struct drm_device *dev = crtc->dev;
549
- struct drm_mode_config *config = &dev->mode_config;
550
- bool replaced = false;
551
- int ret;
552
-
553
- if (property == config->prop_active)
554
- state->active = val;
555
- else if (property == config->prop_mode_id) {
556
- struct drm_property_blob *mode =
557
- drm_property_lookup_blob(dev, val);
558
- ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
559
- drm_property_blob_put(mode);
560
- return ret;
561
- } else if (property == config->degamma_lut_property) {
562
- ret = drm_atomic_replace_property_blob_from_id(dev,
563
- &state->degamma_lut,
564
- val,
565
- -1, sizeof(struct drm_color_lut),
566
- &replaced);
567
- state->color_mgmt_changed |= replaced;
568
- return ret;
569
- } else if (property == config->ctm_property) {
570
- ret = drm_atomic_replace_property_blob_from_id(dev,
571
- &state->ctm,
572
- val,
573
- sizeof(struct drm_color_ctm), -1,
574
- &replaced);
575
- state->color_mgmt_changed |= replaced;
576
- return ret;
577
- } else if (property == config->gamma_lut_property) {
578
- ret = drm_atomic_replace_property_blob_from_id(dev,
579
- &state->gamma_lut,
580
- val,
581
- -1, sizeof(struct drm_color_lut),
582
- &replaced);
583
- state->color_mgmt_changed |= replaced;
584
- return ret;
585
- } else if (property == config->cubic_lut_property) {
586
- ret = drm_atomic_replace_property_blob_from_id(dev,
587
- &state->cubic_lut,
588
- val,
589
- -1, sizeof(struct drm_color_lut),
590
- &replaced);
591
- state->color_mgmt_changed |= replaced;
592
- return ret;
593
- } else if (property == config->prop_out_fence_ptr) {
594
- s32 __user *fence_ptr = u64_to_user_ptr(val);
595
-
596
- if (!fence_ptr)
597
- return 0;
598
-
599
- if (put_user(-1, fence_ptr))
600
- return -EFAULT;
601
-
602
- set_out_fence_for_crtc(state->state, crtc, fence_ptr);
603
- } else if (crtc->funcs->atomic_set_property) {
604
- return crtc->funcs->atomic_set_property(crtc, state, property, val);
605
- } else {
606
- DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
607
- crtc->base.id, crtc->name,
608
- property->base.id, property->name);
609
- return -EINVAL;
610
- }
611
-
612
- return 0;
613
-}
614
-EXPORT_SYMBOL(drm_atomic_crtc_set_property);
615
-
616
-/**
617
- * drm_atomic_crtc_get_property - get property value from CRTC state
618
- * @crtc: the drm CRTC to set a property on
619
- * @state: the state object to get the property value from
620
- * @property: the property to set
621
- * @val: return location for the property value
622
- *
623
- * This function handles generic/core properties and calls out to driver's
624
- * &drm_crtc_funcs.atomic_get_property for driver properties. To ensure
625
- * consistent behavior you must call this function rather than the driver hook
626
- * directly.
627
- *
628
- * RETURNS:
629
- * Zero on success, error code on failure
630
- */
631
-static int
632
-drm_atomic_crtc_get_property(struct drm_crtc *crtc,
633
- const struct drm_crtc_state *state,
634
- struct drm_property *property, uint64_t *val)
635
-{
636
- struct drm_device *dev = crtc->dev;
637
- struct drm_mode_config *config = &dev->mode_config;
638
-
639
- if (property == config->prop_active)
640
- *val = state->active;
641
- else if (property == config->prop_mode_id)
642
- *val = (state->mode_blob) ? state->mode_blob->base.id : 0;
643
- else if (property == config->degamma_lut_property)
644
- *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
645
- else if (property == config->ctm_property)
646
- *val = (state->ctm) ? state->ctm->base.id : 0;
647
- else if (property == config->gamma_lut_property)
648
- *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
649
- else if (property == config->cubic_lut_property)
650
- *val = (state->cubic_lut) ? state->cubic_lut->base.id : 0;
651
- else if (property == config->prop_out_fence_ptr)
652
- *val = 0;
653
- else if (crtc->funcs->atomic_get_property)
654
- return crtc->funcs->atomic_get_property(crtc, state, property, val);
655
- else
656
- return -EINVAL;
657
-
658
- return 0;
659
-}
660
-
661
-/**
662
- * drm_atomic_crtc_check - check crtc state
663
- * @crtc: crtc to check
664
- * @state: crtc state to check
665
- *
666
- * Provides core sanity checks for crtc state.
667
- *
668
- * RETURNS:
669
- * Zero on success, error code on failure
670
- */
671
-static int drm_atomic_crtc_check(struct drm_crtc *crtc,
672
- struct drm_crtc_state *state)
673
-{
674338 /* NOTE: we explicitly don't enforce constraints such as primary
675339 * layer covering entire screen, since that is something we want
676340 * to allow (on hw that supports it). For hw that does not, it
....@@ -679,7 +343,7 @@
679343 * TODO: Add generic modeset state checks once we support those.
680344 */
681345
682
- if (state->active && !state->enable) {
346
+ if (new_crtc_state->active && !new_crtc_state->enable) {
683347 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active without enabled\n",
684348 crtc->base.id, crtc->name);
685349 return -EINVAL;
....@@ -689,14 +353,14 @@
689353 * as this is a kernel-internal detail that userspace should never
690354 * be able to trigger. */
691355 if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
692
- WARN_ON(state->enable && !state->mode_blob)) {
356
+ WARN_ON(new_crtc_state->enable && !new_crtc_state->mode_blob)) {
693357 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled without mode blob\n",
694358 crtc->base.id, crtc->name);
695359 return -EINVAL;
696360 }
697361
698362 if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
699
- WARN_ON(!state->enable && state->mode_blob)) {
363
+ WARN_ON(!new_crtc_state->enable && new_crtc_state->mode_blob)) {
700364 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled with mode blob\n",
701365 crtc->base.id, crtc->name);
702366 return -EINVAL;
....@@ -712,7 +376,8 @@
712376 * and legacy page_flip IOCTL which also reject service on a disabled
713377 * pipe.
714378 */
715
- if (state->event && !state->active && !crtc->state->active) {
379
+ if (new_crtc_state->event &&
380
+ !new_crtc_state->active && !old_crtc_state->active) {
716381 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n",
717382 crtc->base.id, crtc->name);
718383 return -EINVAL;
....@@ -729,6 +394,7 @@
729394 drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name);
730395 drm_printf(p, "\tenable=%d\n", state->enable);
731396 drm_printf(p, "\tactive=%d\n", state->active);
397
+ drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active);
732398 drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed);
733399 drm_printf(p, "\tmode_changed=%d\n", state->mode_changed);
734400 drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
....@@ -743,21 +409,16 @@
743409 crtc->funcs->atomic_print_state(p, state);
744410 }
745411
746
-/**
747
- * drm_atomic_connector_check - check connector state
748
- * @connector: connector to check
749
- * @state: connector state to check
750
- *
751
- * Provides core sanity checks for connector state.
752
- *
753
- * RETURNS:
754
- * Zero on success, error code on failure
755
- */
756412 static int drm_atomic_connector_check(struct drm_connector *connector,
757413 struct drm_connector_state *state)
758414 {
759415 struct drm_crtc_state *crtc_state;
760416 struct drm_writeback_job *writeback_job = state->writeback_job;
417
+ const struct drm_display_info *info = &connector->display_info;
418
+
419
+ state->max_bpc = info->bpc ? info->bpc : 8;
420
+ if (connector->max_bpc_property)
421
+ state->max_bpc = min(state->max_bpc, state->max_requested_bpc);
761422
762423 if ((connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) || !writeback_job)
763424 return 0;
....@@ -779,10 +440,15 @@
779440 return -EINVAL;
780441 }
781442
782
- if (writeback_job->out_fence && !writeback_job->fb) {
783
- DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n",
784
- connector->base.id, connector->name);
785
- return -EINVAL;
443
+ if (!writeback_job->fb) {
444
+ if (writeback_job->out_fence) {
445
+ DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n",
446
+ connector->base.id, connector->name);
447
+ return -EINVAL;
448
+ }
449
+
450
+ drm_writeback_cleanup_job(writeback_job);
451
+ state->writeback_job = NULL;
786452 }
787453
788454 return 0;
....@@ -851,168 +517,14 @@
851517 }
852518 EXPORT_SYMBOL(drm_atomic_get_plane_state);
853519
854
-/**
855
- * drm_atomic_plane_set_property - set property on plane
856
- * @plane: the drm plane to set a property on
857
- * @state: the state object to update with the new property value
858
- * @property: the property to set
859
- * @val: the new property value
860
- *
861
- * This function handles generic/core properties and calls out to driver's
862
- * &drm_plane_funcs.atomic_set_property for driver properties. To ensure
863
- * consistent behavior you must call this function rather than the driver hook
864
- * directly.
865
- *
866
- * RETURNS:
867
- * Zero on success, error code on failure
868
- */
869
-static int drm_atomic_plane_set_property(struct drm_plane *plane,
870
- struct drm_plane_state *state, struct drm_property *property,
871
- uint64_t val)
872
-{
873
- struct drm_device *dev = plane->dev;
874
- struct drm_mode_config *config = &dev->mode_config;
875
-
876
- if (property == config->prop_fb_id) {
877
- struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
878
- drm_atomic_set_fb_for_plane(state, fb);
879
- if (fb)
880
- drm_framebuffer_put(fb);
881
- } else if (property == config->prop_in_fence_fd) {
882
- if (state->fence)
883
- return -EINVAL;
884
-
885
- if (U642I64(val) == -1)
886
- return 0;
887
-
888
- state->fence = sync_file_get_fence(val);
889
- if (!state->fence)
890
- return -EINVAL;
891
-
892
- } else if (property == config->prop_crtc_id) {
893
- struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
894
- return drm_atomic_set_crtc_for_plane(state, crtc);
895
- } else if (property == config->prop_crtc_x) {
896
- state->crtc_x = U642I64(val);
897
- } else if (property == config->prop_crtc_y) {
898
- state->crtc_y = U642I64(val);
899
- } else if (property == config->prop_crtc_w) {
900
- state->crtc_w = val;
901
- } else if (property == config->prop_crtc_h) {
902
- state->crtc_h = val;
903
- } else if (property == config->prop_src_x) {
904
- state->src_x = val;
905
- } else if (property == config->prop_src_y) {
906
- state->src_y = val;
907
- } else if (property == config->prop_src_w) {
908
- state->src_w = val;
909
- } else if (property == config->prop_src_h) {
910
- state->src_h = val;
911
- } else if (property == plane->alpha_property) {
912
- state->alpha = val;
913
- } else if (property == plane->blend_mode_property) {
914
- state->pixel_blend_mode = val;
915
- } else if (property == plane->rotation_property) {
916
- if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
917
- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
918
- plane->base.id, plane->name, val);
919
- return -EINVAL;
920
- }
921
- state->rotation = val;
922
- } else if (property == plane->zpos_property) {
923
- state->zpos = val;
924
- } else if (property == plane->color_encoding_property) {
925
- state->color_encoding = val;
926
- } else if (property == plane->color_range_property) {
927
- state->color_range = val;
928
- } else if (plane->funcs->atomic_set_property) {
929
- return plane->funcs->atomic_set_property(plane, state,
930
- property, val);
931
- } else {
932
- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
933
- plane->base.id, plane->name,
934
- property->base.id, property->name);
935
- return -EINVAL;
936
- }
937
-
938
- return 0;
939
-}
940
-
941
-/**
942
- * drm_atomic_plane_get_property - get property value from plane state
943
- * @plane: the drm plane to set a property on
944
- * @state: the state object to get the property value from
945
- * @property: the property to set
946
- * @val: return location for the property value
947
- *
948
- * This function handles generic/core properties and calls out to driver's
949
- * &drm_plane_funcs.atomic_get_property for driver properties. To ensure
950
- * consistent behavior you must call this function rather than the driver hook
951
- * directly.
952
- *
953
- * RETURNS:
954
- * Zero on success, error code on failure
955
- */
956
-static int
957
-drm_atomic_plane_get_property(struct drm_plane *plane,
958
- const struct drm_plane_state *state,
959
- struct drm_property *property, uint64_t *val)
960
-{
961
- struct drm_device *dev = plane->dev;
962
- struct drm_mode_config *config = &dev->mode_config;
963
-
964
- if (property == config->prop_fb_id) {
965
- *val = (state->fb) ? state->fb->base.id : 0;
966
- } else if (property == config->prop_in_fence_fd) {
967
- *val = -1;
968
- } else if (property == config->prop_crtc_id) {
969
- *val = (state->crtc) ? state->crtc->base.id : 0;
970
- } else if (property == config->prop_crtc_x) {
971
- *val = I642U64(state->crtc_x);
972
- } else if (property == config->prop_crtc_y) {
973
- *val = I642U64(state->crtc_y);
974
- } else if (property == config->prop_crtc_w) {
975
- *val = state->crtc_w;
976
- } else if (property == config->prop_crtc_h) {
977
- *val = state->crtc_h;
978
- } else if (property == config->prop_src_x) {
979
- *val = state->src_x;
980
- } else if (property == config->prop_src_y) {
981
- *val = state->src_y;
982
- } else if (property == config->prop_src_w) {
983
- *val = state->src_w;
984
- } else if (property == config->prop_src_h) {
985
- *val = state->src_h;
986
- } else if (property == plane->alpha_property) {
987
- *val = state->alpha;
988
- } else if (property == plane->blend_mode_property) {
989
- *val = state->pixel_blend_mode;
990
- } else if (property == plane->rotation_property) {
991
- *val = state->rotation;
992
- } else if (property == plane->zpos_property) {
993
- *val = state->zpos;
994
- } else if (property == plane->color_encoding_property) {
995
- *val = state->color_encoding;
996
- } else if (property == plane->color_range_property) {
997
- *val = state->color_range;
998
- } else if (plane->funcs->atomic_get_property) {
999
- return plane->funcs->atomic_get_property(plane, state, property, val);
1000
- } else {
1001
- return -EINVAL;
1002
- }
1003
-
1004
- return 0;
1005
-}
1006
-
1007520 static bool
1008
-plane_switching_crtc(struct drm_atomic_state *state,
1009
- struct drm_plane *plane,
1010
- struct drm_plane_state *plane_state)
521
+plane_switching_crtc(const struct drm_plane_state *old_plane_state,
522
+ const struct drm_plane_state *new_plane_state)
1011523 {
1012
- if (!plane->state->crtc || !plane_state->crtc)
524
+ if (!old_plane_state->crtc || !new_plane_state->crtc)
1013525 return false;
1014526
1015
- if (plane->state->crtc == plane_state->crtc)
527
+ if (old_plane_state->crtc == new_plane_state->crtc)
1016528 return false;
1017529
1018530 /* This could be refined, but currently there's no helper or driver code
....@@ -1025,88 +537,118 @@
1025537
1026538 /**
1027539 * drm_atomic_plane_check - check plane state
1028
- * @plane: plane to check
1029
- * @state: plane state to check
540
+ * @old_plane_state: old plane state to check
541
+ * @new_plane_state: new plane state to check
1030542 *
1031543 * Provides core sanity checks for plane state.
1032544 *
1033545 * RETURNS:
1034546 * Zero on success, error code on failure
1035547 */
1036
-static int drm_atomic_plane_check(struct drm_plane *plane,
1037
- struct drm_plane_state *state)
548
+static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
549
+ const struct drm_plane_state *new_plane_state)
1038550 {
551
+ struct drm_plane *plane = new_plane_state->plane;
552
+ struct drm_crtc *crtc = new_plane_state->crtc;
553
+ const struct drm_framebuffer *fb = new_plane_state->fb;
1039554 unsigned int fb_width, fb_height;
555
+ struct drm_mode_rect *clips;
556
+ uint32_t num_clips;
1040557 int ret;
1041558
1042559 /* either *both* CRTC and FB must be set, or neither */
1043
- if (state->crtc && !state->fb) {
560
+ if (crtc && !fb) {
1044561 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] CRTC set but no FB\n",
1045562 plane->base.id, plane->name);
1046563 return -EINVAL;
1047
- } else if (state->fb && !state->crtc) {
564
+ } else if (fb && !crtc) {
1048565 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] FB set but no CRTC\n",
1049566 plane->base.id, plane->name);
1050567 return -EINVAL;
1051568 }
1052569
1053570 /* if disabled, we don't care about the rest of the state: */
1054
- if (!state->crtc)
571
+ if (!crtc)
1055572 return 0;
1056573
1057574 /* Check whether this plane is usable on this CRTC */
1058
- if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) {
575
+ if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
1059576 DRM_DEBUG_ATOMIC("Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n",
1060
- state->crtc->base.id, state->crtc->name,
577
+ crtc->base.id, crtc->name,
1061578 plane->base.id, plane->name);
1062579 return -EINVAL;
1063580 }
1064581
1065582 /* Check whether this plane supports the fb pixel format. */
1066
- ret = drm_plane_check_pixel_format(plane, state->fb->format->format,
1067
- state->fb->modifier);
583
+ ret = drm_plane_check_pixel_format(plane, fb->format->format,
584
+ fb->modifier);
1068585 if (ret) {
1069586 struct drm_format_name_buf format_name;
587
+
1070588 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid pixel format %s, modifier 0x%llx\n",
1071589 plane->base.id, plane->name,
1072
- drm_get_format_name(state->fb->format->format,
590
+ drm_get_format_name(fb->format->format,
1073591 &format_name),
1074
- state->fb->modifier);
592
+ fb->modifier);
1075593 return ret;
1076594 }
1077595
1078596 /* Give drivers some help against integer overflows */
1079
- if (state->crtc_w > INT_MAX ||
1080
- state->crtc_x > INT_MAX - (int32_t) state->crtc_w ||
1081
- state->crtc_h > INT_MAX ||
1082
- state->crtc_y > INT_MAX - (int32_t) state->crtc_h) {
597
+ if (new_plane_state->crtc_w > INT_MAX ||
598
+ new_plane_state->crtc_x > INT_MAX - (int32_t) new_plane_state->crtc_w ||
599
+ new_plane_state->crtc_h > INT_MAX ||
600
+ new_plane_state->crtc_y > INT_MAX - (int32_t) new_plane_state->crtc_h) {
1083601 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n",
1084602 plane->base.id, plane->name,
1085
- state->crtc_w, state->crtc_h,
1086
- state->crtc_x, state->crtc_y);
603
+ new_plane_state->crtc_w, new_plane_state->crtc_h,
604
+ new_plane_state->crtc_x, new_plane_state->crtc_y);
1087605 return -ERANGE;
1088606 }
1089607
1090
- fb_width = state->fb->width << 16;
1091
- fb_height = state->fb->height << 16;
608
+ fb_width = fb->width << 16;
609
+ fb_height = fb->height << 16;
1092610
1093611 /* Make sure source coordinates are inside the fb. */
1094
- if (state->src_w > fb_width ||
1095
- state->src_x > fb_width - state->src_w ||
1096
- state->src_h > fb_height ||
1097
- state->src_y > fb_height - state->src_h) {
612
+ if (new_plane_state->src_w > fb_width ||
613
+ new_plane_state->src_x > fb_width - new_plane_state->src_w ||
614
+ new_plane_state->src_h > fb_height ||
615
+ new_plane_state->src_y > fb_height - new_plane_state->src_h) {
1098616 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid source coordinates "
1099617 "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
1100618 plane->base.id, plane->name,
1101
- state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
1102
- state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,
1103
- state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,
1104
- state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10,
1105
- state->fb->width, state->fb->height);
619
+ new_plane_state->src_w >> 16,
620
+ ((new_plane_state->src_w & 0xffff) * 15625) >> 10,
621
+ new_plane_state->src_h >> 16,
622
+ ((new_plane_state->src_h & 0xffff) * 15625) >> 10,
623
+ new_plane_state->src_x >> 16,
624
+ ((new_plane_state->src_x & 0xffff) * 15625) >> 10,
625
+ new_plane_state->src_y >> 16,
626
+ ((new_plane_state->src_y & 0xffff) * 15625) >> 10,
627
+ fb->width, fb->height);
1106628 return -ENOSPC;
1107629 }
1108630
1109
- if (plane_switching_crtc(state->state, plane, state)) {
631
+ clips = drm_plane_get_damage_clips(new_plane_state);
632
+ num_clips = drm_plane_get_damage_clips_count(new_plane_state);
633
+
634
+ /* Make sure damage clips are valid and inside the fb. */
635
+ while (num_clips > 0) {
636
+ if (clips->x1 >= clips->x2 ||
637
+ clips->y1 >= clips->y2 ||
638
+ clips->x1 < 0 ||
639
+ clips->y1 < 0 ||
640
+ clips->x2 > fb_width ||
641
+ clips->y2 > fb_height) {
642
+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid damage clip %d %d %d %d\n",
643
+ plane->base.id, plane->name, clips->x1,
644
+ clips->y1, clips->x2, clips->y2);
645
+ return -EINVAL;
646
+ }
647
+ clips++;
648
+ num_clips--;
649
+ }
650
+
651
+ if (plane_switching_crtc(old_plane_state, new_plane_state)) {
1110652 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] switching CRTC directly\n",
1111653 plane->base.id, plane->name);
1112654 return -EINVAL;
....@@ -1157,10 +699,12 @@
1157699 * associated state struct &drm_private_state.
1158700 *
1159701 * Similar to userspace-exposed objects, private state structures can be
1160
- * acquired by calling drm_atomic_get_private_obj_state(). Since this function
1161
- * does not take care of locking, drivers should wrap it for each type of
1162
- * private state object they have with the required call to drm_modeset_lock()
1163
- * for the corresponding &drm_modeset_lock.
702
+ * acquired by calling drm_atomic_get_private_obj_state(). This also takes care
703
+ * of locking, hence drivers should not have a need to call drm_modeset_lock()
704
+ * directly. Sequence of the actual hardware state commit is not handled,
705
+ * drivers might need to keep track of struct drm_crtc_commit within subclassed
706
+ * structure of &drm_private_state as necessary, e.g. similar to
707
+ * &drm_plane_state.commit. See also &drm_atomic_state.fake_commit.
1164708 *
1165709 * All private state structures contained in a &drm_atomic_state update can be
1166710 * iterated using for_each_oldnew_private_obj_in_state(),
....@@ -1178,6 +722,7 @@
1178722
1179723 /**
1180724 * drm_atomic_private_obj_init - initialize private object
725
+ * @dev: DRM device this object will be attached to
1181726 * @obj: private object
1182727 * @state: initial private object state
1183728 * @funcs: pointer to the struct of function pointers that identify the object
....@@ -1187,14 +732,18 @@
1187732 * driver private object that needs its own atomic state.
1188733 */
1189734 void
1190
-drm_atomic_private_obj_init(struct drm_private_obj *obj,
735
+drm_atomic_private_obj_init(struct drm_device *dev,
736
+ struct drm_private_obj *obj,
1191737 struct drm_private_state *state,
1192738 const struct drm_private_state_funcs *funcs)
1193739 {
1194740 memset(obj, 0, sizeof(*obj));
1195741
742
+ drm_modeset_lock_init(&obj->lock);
743
+
1196744 obj->state = state;
1197745 obj->funcs = funcs;
746
+ list_add_tail(&obj->head, &dev->mode_config.privobj_list);
1198747 }
1199748 EXPORT_SYMBOL(drm_atomic_private_obj_init);
1200749
....@@ -1207,7 +756,9 @@
1207756 void
1208757 drm_atomic_private_obj_fini(struct drm_private_obj *obj)
1209758 {
759
+ list_del(&obj->head);
1210760 obj->funcs->atomic_destroy_state(obj, obj->state);
761
+ drm_modeset_lock_fini(&obj->lock);
1211762 }
1212763 EXPORT_SYMBOL(drm_atomic_private_obj_fini);
1213764
....@@ -1217,8 +768,8 @@
1217768 * @obj: private object to get the state for
1218769 *
1219770 * This function returns the private object state for the given private object,
1220
- * allocating the state if needed. It does not grab any locks as the caller is
1221
- * expected to care of any required locking.
771
+ * allocating the state if needed. It will also grab the relevant private
772
+ * object lock to make sure that the state is consistent.
1222773 *
1223774 * RETURNS:
1224775 *
....@@ -1228,7 +779,7 @@
1228779 drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
1229780 struct drm_private_obj *obj)
1230781 {
1231
- int index, num_objs, i;
782
+ int index, num_objs, i, ret;
1232783 size_t size;
1233784 struct __drm_private_objs_state *arr;
1234785 struct drm_private_state *obj_state;
....@@ -1236,6 +787,10 @@
1236787 for (i = 0; i < state->num_private_objs; i++)
1237788 if (obj == state->private_objs[i].ptr)
1238789 return state->private_objs[i].state;
790
+
791
+ ret = drm_modeset_lock(&obj->lock, state->acquire_ctx);
792
+ if (ret)
793
+ return ERR_PTR(ret);
1239794
1240795 num_objs = state->num_private_objs + 1;
1241796 size = sizeof(*state->private_objs) * num_objs;
....@@ -1265,6 +820,119 @@
1265820 return obj_state;
1266821 }
1267822 EXPORT_SYMBOL(drm_atomic_get_private_obj_state);
823
+
824
+/**
825
+ * drm_atomic_get_old_private_obj_state
826
+ * @state: global atomic state object
827
+ * @obj: private_obj to grab
828
+ *
829
+ * This function returns the old private object state for the given private_obj,
830
+ * or NULL if the private_obj is not part of the global atomic state.
831
+ */
832
+struct drm_private_state *
833
+drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state,
834
+ struct drm_private_obj *obj)
835
+{
836
+ int i;
837
+
838
+ for (i = 0; i < state->num_private_objs; i++)
839
+ if (obj == state->private_objs[i].ptr)
840
+ return state->private_objs[i].old_state;
841
+
842
+ return NULL;
843
+}
844
+EXPORT_SYMBOL(drm_atomic_get_old_private_obj_state);
845
+
846
+/**
847
+ * drm_atomic_get_new_private_obj_state
848
+ * @state: global atomic state object
849
+ * @obj: private_obj to grab
850
+ *
851
+ * This function returns the new private object state for the given private_obj,
852
+ * or NULL if the private_obj is not part of the global atomic state.
853
+ */
854
+struct drm_private_state *
855
+drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state,
856
+ struct drm_private_obj *obj)
857
+{
858
+ int i;
859
+
860
+ for (i = 0; i < state->num_private_objs; i++)
861
+ if (obj == state->private_objs[i].ptr)
862
+ return state->private_objs[i].new_state;
863
+
864
+ return NULL;
865
+}
866
+EXPORT_SYMBOL(drm_atomic_get_new_private_obj_state);
867
+
868
+/**
869
+ * drm_atomic_get_old_connector_for_encoder - Get old connector for an encoder
870
+ * @state: Atomic state
871
+ * @encoder: The encoder to fetch the connector state for
872
+ *
873
+ * This function finds and returns the connector that was connected to @encoder
874
+ * as specified by the @state.
875
+ *
876
+ * If there is no connector in @state which previously had @encoder connected to
877
+ * it, this function will return NULL. While this may seem like an invalid use
878
+ * case, it is sometimes useful to differentiate commits which had no prior
879
+ * connectors attached to @encoder vs ones that did (and to inspect their
880
+ * state). This is especially true in enable hooks because the pipeline has
881
+ * changed.
882
+ *
883
+ * Returns: The old connector connected to @encoder, or NULL if the encoder is
884
+ * not connected.
885
+ */
886
+struct drm_connector *
887
+drm_atomic_get_old_connector_for_encoder(struct drm_atomic_state *state,
888
+ struct drm_encoder *encoder)
889
+{
890
+ struct drm_connector_state *conn_state;
891
+ struct drm_connector *connector;
892
+ unsigned int i;
893
+
894
+ for_each_old_connector_in_state(state, connector, conn_state, i) {
895
+ if (conn_state->best_encoder == encoder)
896
+ return connector;
897
+ }
898
+
899
+ return NULL;
900
+}
901
+EXPORT_SYMBOL(drm_atomic_get_old_connector_for_encoder);
902
+
903
+/**
904
+ * drm_atomic_get_new_connector_for_encoder - Get new connector for an encoder
905
+ * @state: Atomic state
906
+ * @encoder: The encoder to fetch the connector state for
907
+ *
908
+ * This function finds and returns the connector that will be connected to
909
+ * @encoder as specified by the @state.
910
+ *
911
+ * If there is no connector in @state which will have @encoder connected to it,
912
+ * this function will return NULL. While this may seem like an invalid use case,
913
+ * it is sometimes useful to differentiate commits which have no connectors
914
+ * attached to @encoder vs ones that do (and to inspect their state). This is
915
+ * especially true in disable hooks because the pipeline will change.
916
+ *
917
+ * Returns: The new connector connected to @encoder, or NULL if the encoder is
918
+ * not connected.
919
+ */
920
+struct drm_connector *
921
+drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state,
922
+ struct drm_encoder *encoder)
923
+{
924
+ struct drm_connector_state *conn_state;
925
+ struct drm_connector *connector;
926
+ unsigned int i;
927
+
928
+ for_each_new_connector_in_state(state, connector, conn_state, i) {
929
+ if (conn_state->best_encoder == encoder)
930
+ return connector;
931
+ }
932
+
933
+ return NULL;
934
+}
935
+EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder);
1268936
1269937 /**
1270938 * drm_atomic_get_connector_state - get connector state
....@@ -1343,122 +1011,6 @@
13431011 }
13441012 EXPORT_SYMBOL(drm_atomic_get_connector_state);
13451013
1346
-/**
1347
- * drm_atomic_connector_set_property - set property on connector.
1348
- * @connector: the drm connector to set a property on
1349
- * @state: the state object to update with the new property value
1350
- * @property: the property to set
1351
- * @val: the new property value
1352
- *
1353
- * This function handles generic/core properties and calls out to driver's
1354
- * &drm_connector_funcs.atomic_set_property for driver properties. To ensure
1355
- * consistent behavior you must call this function rather than the driver hook
1356
- * directly.
1357
- *
1358
- * RETURNS:
1359
- * Zero on success, error code on failure
1360
- */
1361
-static int drm_atomic_connector_set_property(struct drm_connector *connector,
1362
- struct drm_connector_state *state, struct drm_property *property,
1363
- uint64_t val)
1364
-{
1365
- struct drm_device *dev = connector->dev;
1366
- struct drm_mode_config *config = &dev->mode_config;
1367
- bool replaced = false;
1368
- int ret;
1369
-
1370
- if (property == config->prop_crtc_id) {
1371
- struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
1372
- return drm_atomic_set_crtc_for_connector(state, crtc);
1373
- } else if (property == config->dpms_property) {
1374
- /* setting DPMS property requires special handling, which
1375
- * is done in legacy setprop path for us. Disallow (for
1376
- * now?) atomic writes to DPMS property:
1377
- */
1378
- return -EINVAL;
1379
- } else if (property == config->tv_select_subconnector_property) {
1380
- state->tv.subconnector = val;
1381
- } else if (property == config->tv_left_margin_property) {
1382
- state->tv.margins.left = val;
1383
- } else if (property == config->tv_right_margin_property) {
1384
- state->tv.margins.right = val;
1385
- } else if (property == config->tv_top_margin_property) {
1386
- state->tv.margins.top = val;
1387
- } else if (property == config->tv_bottom_margin_property) {
1388
- state->tv.margins.bottom = val;
1389
- } else if (property == config->tv_mode_property) {
1390
- state->tv.mode = val;
1391
- } else if (property == config->tv_brightness_property) {
1392
- state->tv.brightness = val;
1393
- } else if (property == config->tv_contrast_property) {
1394
- state->tv.contrast = val;
1395
- } else if (property == config->tv_flicker_reduction_property) {
1396
- state->tv.flicker_reduction = val;
1397
- } else if (property == config->tv_overscan_property) {
1398
- state->tv.overscan = val;
1399
- } else if (property == config->tv_saturation_property) {
1400
- state->tv.saturation = val;
1401
- } else if (property == config->tv_hue_property) {
1402
- state->tv.hue = val;
1403
- } else if (property == config->link_status_property) {
1404
- /* Never downgrade from GOOD to BAD on userspace's request here,
1405
- * only hw issues can do that.
1406
- *
1407
- * For an atomic property the userspace doesn't need to be able
1408
- * to understand all the properties, but needs to be able to
1409
- * restore the state it wants on VT switch. So if the userspace
1410
- * tries to change the link_status from GOOD to BAD, driver
1411
- * silently rejects it and returns a 0. This prevents userspace
1412
- * from accidently breaking the display when it restores the
1413
- * state.
1414
- */
1415
- if (state->link_status != DRM_LINK_STATUS_GOOD)
1416
- state->link_status = val;
1417
- } else if (property == config->hdr_output_metadata_property) {
1418
- ret = drm_atomic_replace_property_blob_from_id(dev,
1419
- &state->hdr_output_metadata,
1420
- val,
1421
- sizeof(struct hdr_output_metadata), -1,
1422
- &replaced);
1423
- return ret;
1424
- } else if (property == config->aspect_ratio_property) {
1425
- state->picture_aspect_ratio = val;
1426
- } else if (property == config->content_type_property) {
1427
- state->content_type = val;
1428
- } else if (property == connector->scaling_mode_property) {
1429
- state->scaling_mode = val;
1430
- } else if (property == connector->content_protection_property) {
1431
- if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
1432
- DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
1433
- return -EINVAL;
1434
- }
1435
- state->content_protection = val;
1436
- } else if (property == connector->colorspace_property) {
1437
- state->colorspace = val;
1438
- } else if (property == config->writeback_fb_id_property) {
1439
- struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
1440
- int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
1441
- if (fb)
1442
- drm_framebuffer_put(fb);
1443
- return ret;
1444
- } else if (property == config->writeback_out_fence_ptr_property) {
1445
- s32 __user *fence_ptr = u64_to_user_ptr(val);
1446
-
1447
- return set_out_fence_for_connector(state->state, connector,
1448
- fence_ptr);
1449
- } else if (connector->funcs->atomic_set_property) {
1450
- return connector->funcs->atomic_set_property(connector,
1451
- state, property, val);
1452
- } else {
1453
- DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
1454
- connector->base.id, connector->name,
1455
- property->base.id, property->name);
1456
- return -EINVAL;
1457
- }
1458
-
1459
- return 0;
1460
-}
1461
-
14621014 static void drm_atomic_connector_print_state(struct drm_printer *p,
14631015 const struct drm_connector_state *state)
14641016 {
....@@ -1466,6 +1018,8 @@
14661018
14671019 drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
14681020 drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
1021
+ drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
1022
+ drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
14691023
14701024 if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
14711025 if (state->writeback_job && state->writeback_job->fb)
....@@ -1476,373 +1030,130 @@
14761030 }
14771031
14781032 /**
1479
- * drm_atomic_connector_get_property - get property value from connector state
1480
- * @connector: the drm connector to set a property on
1481
- * @state: the state object to get the property value from
1482
- * @property: the property to set
1483
- * @val: return location for the property value
1033
+ * drm_atomic_get_bridge_state - get bridge state
1034
+ * @state: global atomic state object
1035
+ * @bridge: bridge to get state object for
14841036 *
1485
- * This function handles generic/core properties and calls out to driver's
1486
- * &drm_connector_funcs.atomic_get_property for driver properties. To ensure
1487
- * consistent behavior you must call this function rather than the driver hook
1488
- * directly.
1489
- *
1490
- * RETURNS:
1491
- * Zero on success, error code on failure
1492
- */
1493
-static int
1494
-drm_atomic_connector_get_property(struct drm_connector *connector,
1495
- const struct drm_connector_state *state,
1496
- struct drm_property *property, uint64_t *val)
1497
-{
1498
- struct drm_device *dev = connector->dev;
1499
- struct drm_mode_config *config = &dev->mode_config;
1500
-
1501
- if (property == config->prop_crtc_id) {
1502
- *val = (state->crtc) ? state->crtc->base.id : 0;
1503
- } else if (property == config->dpms_property) {
1504
- *val = connector->dpms;
1505
- } else if (property == config->tv_select_subconnector_property) {
1506
- *val = state->tv.subconnector;
1507
- } else if (property == config->tv_left_margin_property) {
1508
- *val = state->tv.margins.left;
1509
- } else if (property == config->tv_right_margin_property) {
1510
- *val = state->tv.margins.right;
1511
- } else if (property == config->tv_top_margin_property) {
1512
- *val = state->tv.margins.top;
1513
- } else if (property == config->tv_bottom_margin_property) {
1514
- *val = state->tv.margins.bottom;
1515
- } else if (property == config->tv_mode_property) {
1516
- *val = state->tv.mode;
1517
- } else if (property == config->tv_brightness_property) {
1518
- *val = state->tv.brightness;
1519
- } else if (property == config->tv_contrast_property) {
1520
- *val = state->tv.contrast;
1521
- } else if (property == config->tv_flicker_reduction_property) {
1522
- *val = state->tv.flicker_reduction;
1523
- } else if (property == config->tv_overscan_property) {
1524
- *val = state->tv.overscan;
1525
- } else if (property == config->tv_saturation_property) {
1526
- *val = state->tv.saturation;
1527
- } else if (property == config->tv_hue_property) {
1528
- *val = state->tv.hue;
1529
- } else if (property == config->link_status_property) {
1530
- *val = state->link_status;
1531
- } else if (property == config->aspect_ratio_property) {
1532
- *val = state->picture_aspect_ratio;
1533
- } else if (property == config->content_type_property) {
1534
- *val = state->content_type;
1535
- } else if (property == connector->colorspace_property) {
1536
- *val = state->colorspace;
1537
- } else if (property == connector->scaling_mode_property) {
1538
- *val = state->scaling_mode;
1539
- } else if (property == config->hdr_output_metadata_property) {
1540
- *val = state->hdr_output_metadata ?
1541
- state->hdr_output_metadata->base.id : 0;
1542
- } else if (property == connector->content_protection_property) {
1543
- *val = state->content_protection;
1544
- } else if (property == config->writeback_fb_id_property) {
1545
- /* Writeback framebuffer is one-shot, write and forget */
1546
- *val = 0;
1547
- } else if (property == config->writeback_out_fence_ptr_property) {
1548
- *val = 0;
1549
- } else if (connector->funcs->atomic_get_property) {
1550
- return connector->funcs->atomic_get_property(connector,
1551
- state, property, val);
1552
- } else {
1553
- return -EINVAL;
1554
- }
1555
-
1556
- return 0;
1557
-}
1558
-
1559
-int drm_atomic_get_property(struct drm_mode_object *obj,
1560
- struct drm_property *property, uint64_t *val)
1561
-{
1562
- struct drm_device *dev = property->dev;
1563
- int ret;
1564
-
1565
- switch (obj->type) {
1566
- case DRM_MODE_OBJECT_CONNECTOR: {
1567
- struct drm_connector *connector = obj_to_connector(obj);
1568
- WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
1569
- ret = drm_atomic_connector_get_property(connector,
1570
- connector->state, property, val);
1571
- break;
1572
- }
1573
- case DRM_MODE_OBJECT_CRTC: {
1574
- struct drm_crtc *crtc = obj_to_crtc(obj);
1575
- WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
1576
- ret = drm_atomic_crtc_get_property(crtc,
1577
- crtc->state, property, val);
1578
- break;
1579
- }
1580
- case DRM_MODE_OBJECT_PLANE: {
1581
- struct drm_plane *plane = obj_to_plane(obj);
1582
- WARN_ON(!drm_modeset_is_locked(&plane->mutex));
1583
- ret = drm_atomic_plane_get_property(plane,
1584
- plane->state, property, val);
1585
- break;
1586
- }
1587
- default:
1588
- ret = -EINVAL;
1589
- break;
1590
- }
1591
-
1592
- return ret;
1593
-}
1594
-
1595
-/**
1596
- * drm_atomic_set_crtc_for_plane - set crtc for plane
1597
- * @plane_state: the plane whose incoming state to update
1598
- * @crtc: crtc to use for the plane
1599
- *
1600
- * Changing the assigned crtc for a plane requires us to grab the lock and state
1601
- * for the new crtc, as needed. This function takes care of all these details
1602
- * besides updating the pointer in the state object itself.
1037
+ * This function returns the bridge state for the given bridge, allocating it
1038
+ * if needed. It will also grab the relevant bridge lock to make sure that the
1039
+ * state is consistent.
16031040 *
16041041 * Returns:
1605
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
1606
- * then the w/w mutex code has detected a deadlock and the entire atomic
1607
- * sequence must be restarted. All other errors are fatal.
1042
+ *
1043
+ * Either the allocated state or the error code encoded into the pointer. When
1044
+ * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
1045
+ * entire atomic sequence must be restarted.
16081046 */
1609
-int
1610
-drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
1611
- struct drm_crtc *crtc)
1047
+struct drm_bridge_state *
1048
+drm_atomic_get_bridge_state(struct drm_atomic_state *state,
1049
+ struct drm_bridge *bridge)
16121050 {
1613
- struct drm_plane *plane = plane_state->plane;
1614
- struct drm_crtc_state *crtc_state;
1615
- /* Nothing to do for same crtc*/
1616
- if (plane_state->crtc == crtc)
1617
- return 0;
1618
- if (plane_state->crtc) {
1619
- crtc_state = drm_atomic_get_crtc_state(plane_state->state,
1620
- plane_state->crtc);
1621
- if (WARN_ON(IS_ERR(crtc_state)))
1622
- return PTR_ERR(crtc_state);
1051
+ struct drm_private_state *obj_state;
16231052
1624
- crtc_state->plane_mask &= ~drm_plane_mask(plane);
1625
- }
1053
+ obj_state = drm_atomic_get_private_obj_state(state, &bridge->base);
1054
+ if (IS_ERR(obj_state))
1055
+ return ERR_CAST(obj_state);
16261056
1627
- plane_state->crtc = crtc;
1628
-
1629
- if (crtc) {
1630
- crtc_state = drm_atomic_get_crtc_state(plane_state->state,
1631
- crtc);
1632
- if (IS_ERR(crtc_state))
1633
- return PTR_ERR(crtc_state);
1634
- crtc_state->plane_mask |= drm_plane_mask(plane);
1635
- }
1636
-
1637
- if (crtc)
1638
- DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
1639
- plane->base.id, plane->name, plane_state,
1640
- crtc->base.id, crtc->name);
1641
- else
1642
- DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
1643
- plane->base.id, plane->name, plane_state);
1644
-
1645
- return 0;
1057
+ return drm_priv_to_bridge_state(obj_state);
16461058 }
1647
-EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
1059
+EXPORT_SYMBOL(drm_atomic_get_bridge_state);
16481060
16491061 /**
1650
- * drm_atomic_set_fb_for_plane - set framebuffer for plane
1651
- * @plane_state: atomic state object for the plane
1652
- * @fb: fb to use for the plane
1062
+ * drm_atomic_get_old_bridge_state - get old bridge state, if it exists
1063
+ * @state: global atomic state object
1064
+ * @bridge: bridge to grab
16531065 *
1654
- * Changing the assigned framebuffer for a plane requires us to grab a reference
1655
- * to the new fb and drop the reference to the old fb, if there is one. This
1656
- * function takes care of all these details besides updating the pointer in the
1657
- * state object itself.
1066
+ * This function returns the old bridge state for the given bridge, or NULL if
1067
+ * the bridge is not part of the global atomic state.
16581068 */
1659
-void
1660
-drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
1661
- struct drm_framebuffer *fb)
1069
+struct drm_bridge_state *
1070
+drm_atomic_get_old_bridge_state(struct drm_atomic_state *state,
1071
+ struct drm_bridge *bridge)
16621072 {
1663
- struct drm_plane *plane = plane_state->plane;
1073
+ struct drm_private_state *obj_state;
16641074
1665
- if (fb)
1666
- DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
1667
- fb->base.id, plane->base.id, plane->name,
1668
- plane_state);
1669
- else
1670
- DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
1671
- plane->base.id, plane->name, plane_state);
1075
+ obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base);
1076
+ if (!obj_state)
1077
+ return NULL;
16721078
1673
- drm_framebuffer_assign(&plane_state->fb, fb);
1079
+ return drm_priv_to_bridge_state(obj_state);
16741080 }
1675
-EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
1081
+EXPORT_SYMBOL(drm_atomic_get_old_bridge_state);
16761082
16771083 /**
1678
- * drm_atomic_set_fence_for_plane - set fence for plane
1679
- * @plane_state: atomic state object for the plane
1680
- * @fence: dma_fence to use for the plane
1084
+ * drm_atomic_get_new_bridge_state - get new bridge state, if it exists
1085
+ * @state: global atomic state object
1086
+ * @bridge: bridge to grab
16811087 *
1682
- * Helper to setup the plane_state fence in case it is not set yet.
1683
- * By using this drivers doesn't need to worry if the user choose
1684
- * implicit or explicit fencing.
1685
- *
1686
- * This function will not set the fence to the state if it was set
1687
- * via explicit fencing interfaces on the atomic ioctl. In that case it will
1688
- * drop the reference to the fence as we are not storing it anywhere.
1689
- * Otherwise, if &drm_plane_state.fence is not set this function we just set it
1690
- * with the received implicit fence. In both cases this function consumes a
1691
- * reference for @fence.
1692
- *
1693
- * This way explicit fencing can be used to overrule implicit fencing, which is
1694
- * important to make explicit fencing use-cases work: One example is using one
1695
- * buffer for 2 screens with different refresh rates. Implicit fencing will
1696
- * clamp rendering to the refresh rate of the slower screen, whereas explicit
1697
- * fence allows 2 independent render and display loops on a single buffer. If a
1698
- * driver allows obeys both implicit and explicit fences for plane updates, then
1699
- * it will break all the benefits of explicit fencing.
1088
+ * This function returns the new bridge state for the given bridge, or NULL if
1089
+ * the bridge is not part of the global atomic state.
17001090 */
1701
-void
1702
-drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
1703
- struct dma_fence *fence)
1091
+struct drm_bridge_state *
1092
+drm_atomic_get_new_bridge_state(struct drm_atomic_state *state,
1093
+ struct drm_bridge *bridge)
17041094 {
1705
- if (plane_state->fence) {
1706
- dma_fence_put(fence);
1707
- return;
1708
- }
1095
+ struct drm_private_state *obj_state;
17091096
1710
- plane_state->fence = fence;
1097
+ obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base);
1098
+ if (!obj_state)
1099
+ return NULL;
1100
+
1101
+ return drm_priv_to_bridge_state(obj_state);
17111102 }
1712
-EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
1103
+EXPORT_SYMBOL(drm_atomic_get_new_bridge_state);
17131104
17141105 /**
1715
- * drm_atomic_set_crtc_for_connector - set crtc for connector
1716
- * @conn_state: atomic state object for the connector
1717
- * @crtc: crtc to use for the connector
1718
- *
1719
- * Changing the assigned crtc for a connector requires us to grab the lock and
1720
- * state for the new crtc, as needed. This function takes care of all these
1721
- * details besides updating the pointer in the state object itself.
1722
- *
1723
- * Returns:
1724
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
1725
- * then the w/w mutex code has detected a deadlock and the entire atomic
1726
- * sequence must be restarted. All other errors are fatal.
1727
- */
1728
-int
1729
-drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
1730
- struct drm_crtc *crtc)
1731
-{
1732
- struct drm_connector *connector = conn_state->connector;
1733
- struct drm_crtc_state *crtc_state;
1734
-
1735
- if (conn_state->crtc == crtc)
1736
- return 0;
1737
-
1738
- if (conn_state->crtc) {
1739
- crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
1740
- conn_state->crtc);
1741
-
1742
- crtc_state->connector_mask &=
1743
- ~drm_connector_mask(conn_state->connector);
1744
-
1745
- drm_connector_put(conn_state->connector);
1746
- conn_state->crtc = NULL;
1747
- }
1748
-
1749
- if (crtc) {
1750
- crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
1751
- if (IS_ERR(crtc_state))
1752
- return PTR_ERR(crtc_state);
1753
-
1754
- crtc_state->connector_mask |=
1755
- drm_connector_mask(conn_state->connector);
1756
-
1757
- drm_connector_get(conn_state->connector);
1758
- conn_state->crtc = crtc;
1759
-
1760
- DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
1761
- connector->base.id, connector->name,
1762
- conn_state, crtc->base.id, crtc->name);
1763
- } else {
1764
- DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
1765
- connector->base.id, connector->name,
1766
- conn_state);
1767
- }
1768
-
1769
- return 0;
1770
-}
1771
-EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
1772
-
1773
-/*
1774
- * drm_atomic_get_writeback_job - return or allocate a writeback job
1775
- * @conn_state: Connector state to get the job for
1776
- *
1777
- * Writeback jobs have a different lifetime to the atomic state they are
1778
- * associated with. This convenience function takes care of allocating a job
1779
- * if there isn't yet one associated with the connector state, otherwise
1780
- * it just returns the existing job.
1781
- *
1782
- * Returns: The writeback job for the given connector state
1783
- */
1784
-static struct drm_writeback_job *
1785
-drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
1786
-{
1787
- WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
1788
-
1789
- if (!conn_state->writeback_job)
1790
- conn_state->writeback_job =
1791
- kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
1792
-
1793
- return conn_state->writeback_job;
1794
-}
1795
-
1796
-/**
1797
- * drm_atomic_set_writeback_fb_for_connector - set writeback framebuffer
1798
- * @conn_state: atomic state object for the connector
1799
- * @fb: fb to use for the connector
1800
- *
1801
- * This is used to set the framebuffer for a writeback connector, which outputs
1802
- * to a buffer instead of an actual physical connector.
1803
- * Changing the assigned framebuffer requires us to grab a reference to the new
1804
- * fb and drop the reference to the old fb, if there is one. This function
1805
- * takes care of all these details besides updating the pointer in the
1806
- * state object itself.
1807
- *
1808
- * Note: The only way conn_state can already have an fb set is if the commit
1809
- * sets the property more than once.
1810
- *
1811
- * See also: drm_writeback_connector_init()
1812
- *
1813
- * Returns: 0 on success
1814
- */
1815
-int drm_atomic_set_writeback_fb_for_connector(
1816
- struct drm_connector_state *conn_state,
1817
- struct drm_framebuffer *fb)
1818
-{
1819
- struct drm_writeback_job *job =
1820
- drm_atomic_get_writeback_job(conn_state);
1821
- if (!job)
1822
- return -ENOMEM;
1823
-
1824
- drm_framebuffer_assign(&job->fb, fb);
1825
-
1826
- if (fb)
1827
- DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
1828
- fb->base.id, conn_state);
1829
- else
1830
- DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
1831
- conn_state);
1832
-
1833
- return 0;
1834
-}
1835
-EXPORT_SYMBOL(drm_atomic_set_writeback_fb_for_connector);
1836
-
1837
-/**
1838
- * drm_atomic_add_affected_connectors - add connectors for crtc
1106
+ * drm_atomic_add_encoder_bridges - add bridges attached to an encoder
18391107 * @state: atomic state
1840
- * @crtc: DRM crtc
1108
+ * @encoder: DRM encoder
1109
+ *
1110
+ * This function adds all bridges attached to @encoder. This is needed to add
1111
+ * bridge states to @state and make them available when
1112
+ * &drm_bridge_funcs.atomic_check(), &drm_bridge_funcs.atomic_pre_enable(),
1113
+ * &drm_bridge_funcs.atomic_enable(),
1114
+ * &drm_bridge_funcs.atomic_disable_post_disable() are called.
1115
+ *
1116
+ * Returns:
1117
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
1118
+ * then the w/w mutex code has detected a deadlock and the entire atomic
1119
+ * sequence must be restarted. All other errors are fatal.
1120
+ */
1121
+int
1122
+drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
1123
+ struct drm_encoder *encoder)
1124
+{
1125
+ struct drm_bridge_state *bridge_state;
1126
+ struct drm_bridge *bridge;
1127
+
1128
+ if (!encoder)
1129
+ return 0;
1130
+
1131
+ DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n",
1132
+ encoder->base.id, encoder->name, state);
1133
+
1134
+ drm_for_each_bridge_in_chain(encoder, bridge) {
1135
+ /* Skip bridges that don't implement the atomic state hooks. */
1136
+ if (!bridge->funcs->atomic_duplicate_state)
1137
+ continue;
1138
+
1139
+ bridge_state = drm_atomic_get_bridge_state(state, bridge);
1140
+ if (IS_ERR(bridge_state))
1141
+ return PTR_ERR(bridge_state);
1142
+ }
1143
+
1144
+ return 0;
1145
+}
1146
+EXPORT_SYMBOL(drm_atomic_add_encoder_bridges);
1147
+
1148
+/**
1149
+ * drm_atomic_add_affected_connectors - add connectors for CRTC
1150
+ * @state: atomic state
1151
+ * @crtc: DRM CRTC
18411152 *
18421153 * This function walks the current configuration and adds all connectors
18431154 * currently using @crtc to the atomic configuration @state. Note that this
18441155 * function must acquire the connection mutex. This can potentially cause
1845
- * unneeded seralization if the update is just for the planes on one crtc. Hence
1156
+ * unneeded seralization if the update is just for the planes on one CRTC. Hence
18461157 * drivers and helpers should only call this when really needed (e.g. when a
18471158 * full modeset needs to happen due to some change).
18481159 *
....@@ -1895,9 +1206,9 @@
18951206 EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
18961207
18971208 /**
1898
- * drm_atomic_add_affected_planes - add planes for crtc
1209
+ * drm_atomic_add_affected_planes - add planes for CRTC
18991210 * @state: atomic state
1900
- * @crtc: DRM crtc
1211
+ * @crtc: DRM CRTC
19011212 *
19021213 * This function walks the current configuration and adds all planes
19031214 * currently used by @crtc to the atomic configuration @state. This is useful
....@@ -1918,6 +1229,8 @@
19181229 drm_atomic_add_affected_planes(struct drm_atomic_state *state,
19191230 struct drm_crtc *crtc)
19201231 {
1232
+ const struct drm_crtc_state *old_crtc_state =
1233
+ drm_atomic_get_old_crtc_state(state, crtc);
19211234 struct drm_plane *plane;
19221235
19231236 WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
....@@ -1925,7 +1238,7 @@
19251238 DRM_DEBUG_ATOMIC("Adding all current planes for [CRTC:%d:%s] to %p\n",
19261239 crtc->base.id, crtc->name, state);
19271240
1928
- drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
1241
+ drm_for_each_plane_mask(plane, state->dev, old_crtc_state->plane_mask) {
19291242 struct drm_plane_state *plane_state =
19301243 drm_atomic_get_plane_state(state, plane);
19311244
....@@ -1952,17 +1265,19 @@
19521265 struct drm_device *dev = state->dev;
19531266 struct drm_mode_config *config = &dev->mode_config;
19541267 struct drm_plane *plane;
1955
- struct drm_plane_state *plane_state;
1268
+ struct drm_plane_state *old_plane_state;
1269
+ struct drm_plane_state *new_plane_state;
19561270 struct drm_crtc *crtc;
1957
- struct drm_crtc_state *crtc_state;
1271
+ struct drm_crtc_state *old_crtc_state;
1272
+ struct drm_crtc_state *new_crtc_state;
19581273 struct drm_connector *conn;
19591274 struct drm_connector_state *conn_state;
19601275 int i, ret = 0;
19611276
19621277 DRM_DEBUG_ATOMIC("checking %p\n", state);
19631278
1964
- for_each_new_plane_in_state(state, plane, plane_state, i) {
1965
- ret = drm_atomic_plane_check(plane, plane_state);
1279
+ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
1280
+ ret = drm_atomic_plane_check(old_plane_state, new_plane_state);
19661281 if (ret) {
19671282 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n",
19681283 plane->base.id, plane->name);
....@@ -1970,8 +1285,8 @@
19701285 }
19711286 }
19721287
1973
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
1974
- ret = drm_atomic_crtc_check(crtc, crtc_state);
1288
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
1289
+ ret = drm_atomic_crtc_check(old_crtc_state, new_crtc_state);
19751290 if (ret) {
19761291 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n",
19771292 crtc->base.id, crtc->name);
....@@ -1999,8 +1314,8 @@
19991314 }
20001315
20011316 if (!state->allow_modeset) {
2002
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
2003
- if (drm_atomic_crtc_needs_modeset(crtc_state)) {
1317
+ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
1318
+ if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
20041319 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n",
20051320 crtc->base.id, crtc->name);
20061321 return -EINVAL;
....@@ -2070,7 +1385,175 @@
20701385 }
20711386 EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
20721387
2073
-static void drm_atomic_print_state(const struct drm_atomic_state *state)
1388
+/* just used from drm-client and atomic-helper: */
1389
+int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
1390
+ struct drm_plane_state *plane_state)
1391
+{
1392
+ int ret;
1393
+
1394
+ ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1395
+ if (ret != 0)
1396
+ return ret;
1397
+
1398
+ drm_atomic_set_fb_for_plane(plane_state, NULL);
1399
+ plane_state->crtc_x = 0;
1400
+ plane_state->crtc_y = 0;
1401
+ plane_state->crtc_w = 0;
1402
+ plane_state->crtc_h = 0;
1403
+ plane_state->src_x = 0;
1404
+ plane_state->src_y = 0;
1405
+ plane_state->src_w = 0;
1406
+ plane_state->src_h = 0;
1407
+
1408
+ return 0;
1409
+}
1410
+EXPORT_SYMBOL(__drm_atomic_helper_disable_plane);
1411
+
1412
+static int update_output_state(struct drm_atomic_state *state,
1413
+ struct drm_mode_set *set)
1414
+{
1415
+ struct drm_device *dev = set->crtc->dev;
1416
+ struct drm_crtc *crtc;
1417
+ struct drm_crtc_state *new_crtc_state;
1418
+ struct drm_connector *connector;
1419
+ struct drm_connector_state *new_conn_state;
1420
+ int ret, i;
1421
+
1422
+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
1423
+ state->acquire_ctx);
1424
+ if (ret)
1425
+ return ret;
1426
+
1427
+ /* First disable all connectors on the target crtc. */
1428
+ ret = drm_atomic_add_affected_connectors(state, set->crtc);
1429
+ if (ret)
1430
+ return ret;
1431
+
1432
+ for_each_new_connector_in_state(state, connector, new_conn_state, i) {
1433
+ if (new_conn_state->crtc == set->crtc) {
1434
+ ret = drm_atomic_set_crtc_for_connector(new_conn_state,
1435
+ NULL);
1436
+ if (ret)
1437
+ return ret;
1438
+
1439
+ /* Make sure legacy setCrtc always re-trains */
1440
+ new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
1441
+ }
1442
+ }
1443
+
1444
+ /* Then set all connectors from set->connectors on the target crtc */
1445
+ for (i = 0; i < set->num_connectors; i++) {
1446
+ new_conn_state = drm_atomic_get_connector_state(state,
1447
+ set->connectors[i]);
1448
+ if (IS_ERR(new_conn_state))
1449
+ return PTR_ERR(new_conn_state);
1450
+
1451
+ ret = drm_atomic_set_crtc_for_connector(new_conn_state,
1452
+ set->crtc);
1453
+ if (ret)
1454
+ return ret;
1455
+ }
1456
+
1457
+ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
1458
+ /*
1459
+ * Don't update ->enable for the CRTC in the set_config request,
1460
+ * since a mismatch would indicate a bug in the upper layers.
1461
+ * The actual modeset code later on will catch any
1462
+ * inconsistencies here.
1463
+ */
1464
+ if (crtc == set->crtc)
1465
+ continue;
1466
+
1467
+ if (!new_crtc_state->connector_mask) {
1468
+ ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
1469
+ NULL);
1470
+ if (ret < 0)
1471
+ return ret;
1472
+
1473
+ new_crtc_state->active = false;
1474
+ }
1475
+ }
1476
+
1477
+ return 0;
1478
+}
1479
+
1480
+/* just used from drm-client and atomic-helper: */
1481
+int __drm_atomic_helper_set_config(struct drm_mode_set *set,
1482
+ struct drm_atomic_state *state)
1483
+{
1484
+ struct drm_crtc_state *crtc_state;
1485
+ struct drm_plane_state *primary_state;
1486
+ struct drm_crtc *crtc = set->crtc;
1487
+ int hdisplay, vdisplay;
1488
+ int ret;
1489
+
1490
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
1491
+ if (IS_ERR(crtc_state))
1492
+ return PTR_ERR(crtc_state);
1493
+
1494
+ primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1495
+ if (IS_ERR(primary_state))
1496
+ return PTR_ERR(primary_state);
1497
+
1498
+ if (!set->mode) {
1499
+ WARN_ON(set->fb);
1500
+ WARN_ON(set->num_connectors);
1501
+
1502
+ ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
1503
+ if (ret != 0)
1504
+ return ret;
1505
+
1506
+ crtc_state->active = false;
1507
+
1508
+ ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1509
+ if (ret != 0)
1510
+ return ret;
1511
+
1512
+ drm_atomic_set_fb_for_plane(primary_state, NULL);
1513
+
1514
+ goto commit;
1515
+ }
1516
+
1517
+ WARN_ON(!set->fb);
1518
+ WARN_ON(!set->num_connectors);
1519
+
1520
+ ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
1521
+ if (ret != 0)
1522
+ return ret;
1523
+
1524
+ crtc_state->active = true;
1525
+
1526
+ ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1527
+ if (ret != 0)
1528
+ return ret;
1529
+
1530
+ drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay);
1531
+
1532
+ drm_atomic_set_fb_for_plane(primary_state, set->fb);
1533
+ primary_state->crtc_x = 0;
1534
+ primary_state->crtc_y = 0;
1535
+ primary_state->crtc_w = hdisplay;
1536
+ primary_state->crtc_h = vdisplay;
1537
+ primary_state->src_x = set->x << 16;
1538
+ primary_state->src_y = set->y << 16;
1539
+ if (drm_rotation_90_or_270(primary_state->rotation)) {
1540
+ primary_state->src_w = vdisplay << 16;
1541
+ primary_state->src_h = hdisplay << 16;
1542
+ } else {
1543
+ primary_state->src_w = hdisplay << 16;
1544
+ primary_state->src_h = vdisplay << 16;
1545
+ }
1546
+
1547
+commit:
1548
+ ret = update_output_state(state, set);
1549
+ if (ret)
1550
+ return ret;
1551
+
1552
+ return 0;
1553
+}
1554
+EXPORT_SYMBOL(__drm_atomic_helper_set_config);
1555
+
1556
+void drm_atomic_print_state(const struct drm_atomic_state *state)
20741557 {
20751558 struct drm_printer p = drm_info_printer(state->dev->dev);
20761559 struct drm_plane *plane;
....@@ -2169,552 +1652,10 @@
21691652 {"state", drm_state_info, 0},
21701653 };
21711654
2172
-int drm_atomic_debugfs_init(struct drm_minor *minor)
1655
+void drm_atomic_debugfs_init(struct drm_minor *minor)
21731656 {
2174
- return drm_debugfs_create_files(drm_atomic_debugfs_list,
2175
- ARRAY_SIZE(drm_atomic_debugfs_list),
2176
- minor->debugfs_root, minor);
1657
+ drm_debugfs_create_files(drm_atomic_debugfs_list,
1658
+ ARRAY_SIZE(drm_atomic_debugfs_list),
1659
+ minor->debugfs_root, minor);
21771660 }
21781661 #endif
2179
-
2180
-/*
2181
- * The big monster ioctl
2182
- */
2183
-
2184
-static struct drm_pending_vblank_event *create_vblank_event(
2185
- struct drm_crtc *crtc, uint64_t user_data)
2186
-{
2187
- struct drm_pending_vblank_event *e = NULL;
2188
-
2189
- e = kzalloc(sizeof *e, GFP_KERNEL);
2190
- if (!e)
2191
- return NULL;
2192
-
2193
- e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
2194
- e->event.base.length = sizeof(e->event);
2195
- e->event.vbl.crtc_id = crtc->base.id;
2196
- e->event.vbl.user_data = user_data;
2197
-
2198
- return e;
2199
-}
2200
-
2201
-int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
2202
- struct drm_connector *connector,
2203
- int mode)
2204
-{
2205
- struct drm_connector *tmp_connector;
2206
- struct drm_connector_state *new_conn_state;
2207
- struct drm_crtc *crtc;
2208
- struct drm_crtc_state *crtc_state;
2209
- int i, ret, old_mode = connector->dpms;
2210
- bool active = false;
2211
-
2212
- ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
2213
- state->acquire_ctx);
2214
- if (ret)
2215
- return ret;
2216
-
2217
- if (mode != DRM_MODE_DPMS_ON)
2218
- mode = DRM_MODE_DPMS_OFF;
2219
- connector->dpms = mode;
2220
-
2221
- crtc = connector->state->crtc;
2222
- if (!crtc)
2223
- goto out;
2224
- ret = drm_atomic_add_affected_connectors(state, crtc);
2225
- if (ret)
2226
- goto out;
2227
-
2228
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
2229
- if (IS_ERR(crtc_state)) {
2230
- ret = PTR_ERR(crtc_state);
2231
- goto out;
2232
- }
2233
-
2234
- for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
2235
- if (new_conn_state->crtc != crtc)
2236
- continue;
2237
- if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
2238
- active = true;
2239
- break;
2240
- }
2241
- }
2242
-
2243
- crtc_state->active = active;
2244
- ret = drm_atomic_commit(state);
2245
-out:
2246
- if (ret != 0)
2247
- connector->dpms = old_mode;
2248
- return ret;
2249
-}
2250
-
2251
-int drm_atomic_set_property(struct drm_atomic_state *state,
2252
- struct drm_mode_object *obj,
2253
- struct drm_property *prop,
2254
- uint64_t prop_value)
2255
-{
2256
- struct drm_mode_object *ref;
2257
- int ret;
2258
-
2259
- if (!drm_property_change_valid_get(prop, prop_value, &ref))
2260
- return -EINVAL;
2261
-
2262
- switch (obj->type) {
2263
- case DRM_MODE_OBJECT_CONNECTOR: {
2264
- struct drm_connector *connector = obj_to_connector(obj);
2265
- struct drm_connector_state *connector_state;
2266
-
2267
- connector_state = drm_atomic_get_connector_state(state, connector);
2268
- if (IS_ERR(connector_state)) {
2269
- ret = PTR_ERR(connector_state);
2270
- break;
2271
- }
2272
-
2273
- ret = drm_atomic_connector_set_property(connector,
2274
- connector_state, prop, prop_value);
2275
- break;
2276
- }
2277
- case DRM_MODE_OBJECT_CRTC: {
2278
- struct drm_crtc *crtc = obj_to_crtc(obj);
2279
- struct drm_crtc_state *crtc_state;
2280
-
2281
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
2282
- if (IS_ERR(crtc_state)) {
2283
- ret = PTR_ERR(crtc_state);
2284
- break;
2285
- }
2286
-
2287
- ret = drm_atomic_crtc_set_property(crtc,
2288
- crtc_state, prop, prop_value);
2289
- break;
2290
- }
2291
- case DRM_MODE_OBJECT_PLANE: {
2292
- struct drm_plane *plane = obj_to_plane(obj);
2293
- struct drm_plane_state *plane_state;
2294
-
2295
- plane_state = drm_atomic_get_plane_state(state, plane);
2296
- if (IS_ERR(plane_state)) {
2297
- ret = PTR_ERR(plane_state);
2298
- break;
2299
- }
2300
-
2301
- ret = drm_atomic_plane_set_property(plane,
2302
- plane_state, prop, prop_value);
2303
- break;
2304
- }
2305
- default:
2306
- ret = -EINVAL;
2307
- break;
2308
- }
2309
-
2310
- drm_property_change_valid_put(prop, ref);
2311
- return ret;
2312
-}
2313
-
2314
-/**
2315
- * DOC: explicit fencing properties
2316
- *
2317
- * Explicit fencing allows userspace to control the buffer synchronization
2318
- * between devices. A Fence or a group of fences are transfered to/from
2319
- * userspace using Sync File fds and there are two DRM properties for that.
2320
- * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
2321
- * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
2322
- *
2323
- * As a contrast, with implicit fencing the kernel keeps track of any
2324
- * ongoing rendering, and automatically ensures that the atomic update waits
2325
- * for any pending rendering to complete. For shared buffers represented with
2326
- * a &struct dma_buf this is tracked in &struct reservation_object.
2327
- * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
2328
- * whereas explicit fencing is what Android wants.
2329
- *
2330
- * "IN_FENCE_FD”:
2331
- * Use this property to pass a fence that DRM should wait on before
2332
- * proceeding with the Atomic Commit request and show the framebuffer for
2333
- * the plane on the screen. The fence can be either a normal fence or a
2334
- * merged one, the sync_file framework will handle both cases and use a
2335
- * fence_array if a merged fence is received. Passing -1 here means no
2336
- * fences to wait on.
2337
- *
2338
- * If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
2339
- * it will only check if the Sync File is a valid one.
2340
- *
2341
- * On the driver side the fence is stored on the @fence parameter of
2342
- * &struct drm_plane_state. Drivers which also support implicit fencing
2343
- * should set the implicit fence using drm_atomic_set_fence_for_plane(),
2344
- * to make sure there's consistent behaviour between drivers in precedence
2345
- * of implicit vs. explicit fencing.
2346
- *
2347
- * "OUT_FENCE_PTR”:
2348
- * Use this property to pass a file descriptor pointer to DRM. Once the
2349
- * Atomic Commit request call returns OUT_FENCE_PTR will be filled with
2350
- * the file descriptor number of a Sync File. This Sync File contains the
2351
- * CRTC fence that will be signaled when all framebuffers present on the
2352
- * Atomic Commit * request for that given CRTC are scanned out on the
2353
- * screen.
2354
- *
2355
- * The Atomic Commit request fails if a invalid pointer is passed. If the
2356
- * Atomic Commit request fails for any other reason the out fence fd
2357
- * returned will be -1. On a Atomic Commit with the
2358
- * DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
2359
- *
2360
- * Note that out-fences don't have a special interface to drivers and are
2361
- * internally represented by a &struct drm_pending_vblank_event in struct
2362
- * &drm_crtc_state, which is also used by the nonblocking atomic commit
2363
- * helpers and for the DRM event handling for existing userspace.
2364
- */
2365
-
2366
-struct drm_out_fence_state {
2367
- s32 __user *out_fence_ptr;
2368
- struct sync_file *sync_file;
2369
- int fd;
2370
-};
2371
-
2372
-static int setup_out_fence(struct drm_out_fence_state *fence_state,
2373
- struct dma_fence *fence)
2374
-{
2375
- fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
2376
- if (fence_state->fd < 0)
2377
- return fence_state->fd;
2378
-
2379
- if (put_user(fence_state->fd, fence_state->out_fence_ptr))
2380
- return -EFAULT;
2381
-
2382
- fence_state->sync_file = sync_file_create(fence);
2383
- if (!fence_state->sync_file)
2384
- return -ENOMEM;
2385
-
2386
- return 0;
2387
-}
2388
-
2389
-static int prepare_signaling(struct drm_device *dev,
2390
- struct drm_atomic_state *state,
2391
- struct drm_mode_atomic *arg,
2392
- struct drm_file *file_priv,
2393
- struct drm_out_fence_state **fence_state,
2394
- unsigned int *num_fences)
2395
-{
2396
- struct drm_crtc *crtc;
2397
- struct drm_crtc_state *crtc_state;
2398
- struct drm_connector *conn;
2399
- struct drm_connector_state *conn_state;
2400
- int i, c = 0, ret;
2401
-
2402
- if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
2403
- return 0;
2404
-
2405
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
2406
- s32 __user *fence_ptr;
2407
-
2408
- fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
2409
-
2410
- if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
2411
- struct drm_pending_vblank_event *e;
2412
-
2413
- e = create_vblank_event(crtc, arg->user_data);
2414
- if (!e)
2415
- return -ENOMEM;
2416
-
2417
- crtc_state->event = e;
2418
- }
2419
-
2420
- if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
2421
- struct drm_pending_vblank_event *e = crtc_state->event;
2422
-
2423
- if (!file_priv)
2424
- continue;
2425
-
2426
- ret = drm_event_reserve_init(dev, file_priv, &e->base,
2427
- &e->event.base);
2428
- if (ret) {
2429
- kfree(e);
2430
- crtc_state->event = NULL;
2431
- return ret;
2432
- }
2433
- }
2434
-
2435
- if (fence_ptr) {
2436
- struct dma_fence *fence;
2437
- struct drm_out_fence_state *f;
2438
-
2439
- f = krealloc(*fence_state, sizeof(**fence_state) *
2440
- (*num_fences + 1), GFP_KERNEL);
2441
- if (!f)
2442
- return -ENOMEM;
2443
-
2444
- memset(&f[*num_fences], 0, sizeof(*f));
2445
-
2446
- f[*num_fences].out_fence_ptr = fence_ptr;
2447
- *fence_state = f;
2448
-
2449
- fence = drm_crtc_create_fence(crtc);
2450
- if (!fence)
2451
- return -ENOMEM;
2452
-
2453
- ret = setup_out_fence(&f[(*num_fences)++], fence);
2454
- if (ret) {
2455
- dma_fence_put(fence);
2456
- return ret;
2457
- }
2458
-
2459
- crtc_state->event->base.fence = fence;
2460
- }
2461
-
2462
- c++;
2463
- }
2464
-
2465
- for_each_new_connector_in_state(state, conn, conn_state, i) {
2466
- struct drm_writeback_connector *wb_conn;
2467
- struct drm_writeback_job *job;
2468
- struct drm_out_fence_state *f;
2469
- struct dma_fence *fence;
2470
- s32 __user *fence_ptr;
2471
-
2472
- fence_ptr = get_out_fence_for_connector(state, conn);
2473
- if (!fence_ptr)
2474
- continue;
2475
-
2476
- job = drm_atomic_get_writeback_job(conn_state);
2477
- if (!job)
2478
- return -ENOMEM;
2479
-
2480
- f = krealloc(*fence_state, sizeof(**fence_state) *
2481
- (*num_fences + 1), GFP_KERNEL);
2482
- if (!f)
2483
- return -ENOMEM;
2484
-
2485
- memset(&f[*num_fences], 0, sizeof(*f));
2486
-
2487
- f[*num_fences].out_fence_ptr = fence_ptr;
2488
- *fence_state = f;
2489
-
2490
- wb_conn = drm_connector_to_writeback(conn);
2491
- fence = drm_writeback_get_out_fence(wb_conn);
2492
- if (!fence)
2493
- return -ENOMEM;
2494
-
2495
- ret = setup_out_fence(&f[(*num_fences)++], fence);
2496
- if (ret) {
2497
- dma_fence_put(fence);
2498
- return ret;
2499
- }
2500
-
2501
- job->out_fence = fence;
2502
- }
2503
-
2504
- /*
2505
- * Having this flag means user mode pends on event which will never
2506
- * reach due to lack of at least one CRTC for signaling
2507
- */
2508
- if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
2509
- return -EINVAL;
2510
-
2511
- return 0;
2512
-}
2513
-
2514
-static void complete_signaling(struct drm_device *dev,
2515
- struct drm_atomic_state *state,
2516
- struct drm_out_fence_state *fence_state,
2517
- unsigned int num_fences,
2518
- bool install_fds)
2519
-{
2520
- struct drm_crtc *crtc;
2521
- struct drm_crtc_state *crtc_state;
2522
- int i;
2523
-
2524
- if (install_fds) {
2525
- for (i = 0; i < num_fences; i++)
2526
- fd_install(fence_state[i].fd,
2527
- fence_state[i].sync_file->file);
2528
-
2529
- kfree(fence_state);
2530
- return;
2531
- }
2532
-
2533
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
2534
- struct drm_pending_vblank_event *event = crtc_state->event;
2535
- /*
2536
- * Free the allocated event. drm_atomic_helper_setup_commit
2537
- * can allocate an event too, so only free it if it's ours
2538
- * to prevent a double free in drm_atomic_state_clear.
2539
- */
2540
- if (event && (event->base.fence || event->base.file_priv)) {
2541
- drm_event_cancel_free(dev, &event->base);
2542
- crtc_state->event = NULL;
2543
- }
2544
- }
2545
-
2546
- if (!fence_state)
2547
- return;
2548
-
2549
- for (i = 0; i < num_fences; i++) {
2550
- if (fence_state[i].sync_file)
2551
- fput(fence_state[i].sync_file->file);
2552
- if (fence_state[i].fd >= 0)
2553
- put_unused_fd(fence_state[i].fd);
2554
-
2555
- /* If this fails log error to the user */
2556
- if (fence_state[i].out_fence_ptr &&
2557
- put_user(-1, fence_state[i].out_fence_ptr))
2558
- DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
2559
- }
2560
-
2561
- kfree(fence_state);
2562
-}
2563
-
2564
-int drm_mode_atomic_ioctl(struct drm_device *dev,
2565
- void *data, struct drm_file *file_priv)
2566
-{
2567
- struct drm_mode_atomic *arg = data;
2568
- uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
2569
- uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
2570
- uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
2571
- uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
2572
- unsigned int copied_objs, copied_props;
2573
- struct drm_atomic_state *state;
2574
- struct drm_modeset_acquire_ctx ctx;
2575
- struct drm_out_fence_state *fence_state;
2576
- int ret = 0;
2577
- unsigned int i, j, num_fences;
2578
-
2579
- /* disallow for drivers not supporting atomic: */
2580
- if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
2581
- return -EINVAL;
2582
-
2583
- /* disallow for userspace that has not enabled atomic cap (even
2584
- * though this may be a bit overkill, since legacy userspace
2585
- * wouldn't know how to call this ioctl)
2586
- */
2587
- if (!file_priv->atomic)
2588
- return -EINVAL;
2589
-
2590
- if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
2591
- return -EINVAL;
2592
-
2593
- if (arg->reserved)
2594
- return -EINVAL;
2595
-
2596
- if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
2597
- !dev->mode_config.async_page_flip)
2598
- return -EINVAL;
2599
-
2600
- /* can't test and expect an event at the same time. */
2601
- if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
2602
- (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
2603
- return -EINVAL;
2604
-
2605
- drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
2606
-
2607
- state = drm_atomic_state_alloc(dev);
2608
- if (!state)
2609
- return -ENOMEM;
2610
-
2611
- state->acquire_ctx = &ctx;
2612
- state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
2613
-
2614
-retry:
2615
- copied_objs = 0;
2616
- copied_props = 0;
2617
- fence_state = NULL;
2618
- num_fences = 0;
2619
-
2620
- for (i = 0; i < arg->count_objs; i++) {
2621
- uint32_t obj_id, count_props;
2622
- struct drm_mode_object *obj;
2623
-
2624
- if (get_user(obj_id, objs_ptr + copied_objs)) {
2625
- ret = -EFAULT;
2626
- goto out;
2627
- }
2628
-
2629
- obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
2630
- if (!obj) {
2631
- ret = -ENOENT;
2632
- goto out;
2633
- }
2634
-
2635
- if (!obj->properties) {
2636
- drm_mode_object_put(obj);
2637
- ret = -ENOENT;
2638
- goto out;
2639
- }
2640
-
2641
- if (get_user(count_props, count_props_ptr + copied_objs)) {
2642
- drm_mode_object_put(obj);
2643
- ret = -EFAULT;
2644
- goto out;
2645
- }
2646
-
2647
- copied_objs++;
2648
-
2649
- for (j = 0; j < count_props; j++) {
2650
- uint32_t prop_id;
2651
- uint64_t prop_value;
2652
- struct drm_property *prop;
2653
-
2654
- if (get_user(prop_id, props_ptr + copied_props)) {
2655
- drm_mode_object_put(obj);
2656
- ret = -EFAULT;
2657
- goto out;
2658
- }
2659
-
2660
- prop = drm_mode_obj_find_prop_id(obj, prop_id);
2661
- if (!prop) {
2662
- drm_mode_object_put(obj);
2663
- ret = -ENOENT;
2664
- goto out;
2665
- }
2666
-
2667
- if (copy_from_user(&prop_value,
2668
- prop_values_ptr + copied_props,
2669
- sizeof(prop_value))) {
2670
- drm_mode_object_put(obj);
2671
- ret = -EFAULT;
2672
- goto out;
2673
- }
2674
-
2675
- ret = drm_atomic_set_property(state, obj, prop,
2676
- prop_value);
2677
- if (ret) {
2678
- drm_mode_object_put(obj);
2679
- goto out;
2680
- }
2681
-
2682
- copied_props++;
2683
- }
2684
-
2685
- drm_mode_object_put(obj);
2686
- }
2687
-
2688
- ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
2689
- &num_fences);
2690
- if (ret)
2691
- goto out;
2692
-
2693
- if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
2694
- ret = drm_atomic_check_only(state);
2695
- } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
2696
- ret = drm_atomic_nonblocking_commit(state);
2697
- } else {
2698
- if (unlikely(drm_debug & DRM_UT_STATE))
2699
- drm_atomic_print_state(state);
2700
-
2701
- ret = drm_atomic_commit(state);
2702
- }
2703
-
2704
-out:
2705
- complete_signaling(dev, state, fence_state, num_fences, !ret);
2706
-
2707
- if (ret == -EDEADLK) {
2708
- drm_atomic_state_clear(state);
2709
- ret = drm_modeset_backoff(&ctx);
2710
- if (!ret)
2711
- goto retry;
2712
- }
2713
-
2714
- drm_atomic_state_put(state);
2715
-
2716
- drm_modeset_drop_locks(&ctx);
2717
- drm_modeset_acquire_fini(&ctx);
2718
-
2719
- return ret;
2720
-}