aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2017-04-06 07:19:03 -0400
committerSean Paul <seanpaul@chromium.org>2017-04-06 17:00:27 -0400
commitce09d7667dd225564df1e20b8185d4ce7be886cc (patch)
treef0ae676586ba349dbb2cd1a3c118ca79210f928d
parent970ece83fdd46cb4fa834a4d5adfdf746e4174b2 (diff)
drm/atomic: Add connector atomic_check function, v2.
The atomic_check function is useful for implementing properties, but it can be used for other connector modeset related checks as well. Similar to plane check functions, on a modeset atomic_check() is always called. Changes since v1: - Make sure atomic_check() is called on any modeset. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491477543-31257-5-git-send-email-maarten.lankhorst@linux.intel.com
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c44
-rw-r--r--include/drm/drm_modeset_helper_vtables.h34
2 files changed, 74 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index ff3c6eb5b6bd..8be9719284b0 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -459,10 +459,20 @@ mode_fixup(struct drm_atomic_state *state)
459 * 459 *
460 * Check the state object to see if the requested state is physically possible. 460 * Check the state object to see if the requested state is physically possible.
461 * This does all the crtc and connector related computations for an atomic 461 * This does all the crtc and connector related computations for an atomic
462 * update and adds any additional connectors needed for full modesets and calls 462 * update and adds any additional connectors needed for full modesets. It calls
463 * down into &drm_crtc_helper_funcs.mode_fixup and 463 * the various per-object callbacks in the follow order:
464 * &drm_encoder_helper_funcs.mode_fixup or 464 *
465 * &drm_encoder_helper_funcs.atomic_check functions of the driver backend. 465 * 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder.
466 * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state.
467 * 3. If it's determined a modeset is needed then all connectors on the affected crtc
468 * crtc are added and &drm_connector_helper_funcs.atomic_check is run on them.
469 * 4. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
470 * 5. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
471 * This function is only called when the encoder will be part of a configured crtc,
472 * it must not be used for implementing connector property validation.
473 * If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called
474 * instead.
475 * 6. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
466 * 476 *
467 * &drm_crtc_state.mode_changed is set when the input mode is changed. 477 * &drm_crtc_state.mode_changed is set when the input mode is changed.
468 * &drm_crtc_state.connectors_changed is set when a connector is added or 478 * &drm_crtc_state.connectors_changed is set when a connector is added or
@@ -492,6 +502,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
492 struct drm_connector *connector; 502 struct drm_connector *connector;
493 struct drm_connector_state *old_connector_state, *new_connector_state; 503 struct drm_connector_state *old_connector_state, *new_connector_state;
494 int i, ret; 504 int i, ret;
505 unsigned connectors_mask = 0;
495 506
496 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 507 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
497 bool has_connectors = 508 bool has_connectors =
@@ -538,6 +549,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
538 return ret; 549 return ret;
539 550
540 for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { 551 for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
552 const struct drm_connector_helper_funcs *funcs = connector->helper_private;
553
541 /* 554 /*
542 * This only sets crtc->connectors_changed for routing changes, 555 * This only sets crtc->connectors_changed for routing changes,
543 * drivers must set crtc->connectors_changed themselves when 556 * drivers must set crtc->connectors_changed themselves when
@@ -555,6 +568,13 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
555 new_connector_state->link_status) 568 new_connector_state->link_status)
556 new_crtc_state->connectors_changed = true; 569 new_crtc_state->connectors_changed = true;
557 } 570 }
571
572 if (funcs->atomic_check)
573 ret = funcs->atomic_check(connector, new_connector_state);
574 if (ret)
575 return ret;
576
577 connectors_mask += BIT(i);
558 } 578 }
559 579
560 /* 580 /*
@@ -581,6 +601,22 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
581 return ret; 601 return ret;
582 } 602 }
583 603
604 /*
605 * Iterate over all connectors again, to make sure atomic_check()
606 * has been called on them when a modeset is forced.
607 */
608 for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
609 const struct drm_connector_helper_funcs *funcs = connector->helper_private;
610
611 if (connectors_mask & BIT(i))
612 continue;
613
614 if (funcs->atomic_check)
615 ret = funcs->atomic_check(connector, new_connector_state);
616 if (ret)
617 return ret;
618 }
619
584 return mode_fixup(state); 620 return mode_fixup(state);
585} 621}
586EXPORT_SYMBOL(drm_atomic_helper_check_modeset); 622EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 7847babd893c..c01c328f6cc8 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -872,6 +872,40 @@ struct drm_connector_helper_funcs {
872 */ 872 */
873 struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, 873 struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector,
874 struct drm_connector_state *connector_state); 874 struct drm_connector_state *connector_state);
875
876 /**
877 * @atomic_check:
878 *
879 * This hook is used to validate connector state. This function is
880 * called from &drm_atomic_helper_check_modeset, and is called when
881 * a connector property is set, or a modeset on the crtc is forced.
882 *
883 * Because &drm_atomic_helper_check_modeset may be called multiple times,
884 * this function should handle being called multiple times as well.
885 *
886 * This function is also allowed to inspect any other object's state and
887 * can add more state objects to the atomic commit if needed. Care must
888 * be taken though to ensure that state check and compute functions for
889 * these added states are all called, and derived state in other objects
890 * all updated. Again the recommendation is to just call check helpers
891 * until a maximal configuration is reached.
892 *
893 * NOTE:
894 *
895 * This function is called in the check phase of an atomic update. The
896 * driver is not allowed to change anything outside of the free-standing
897 * state objects passed-in or assembled in the overall &drm_atomic_state
898 * update tracking structure.
899 *
900 * RETURNS:
901 *
902 * 0 on success, -EINVAL if the state or the transition can't be
903 * supported, -ENOMEM on memory allocation failure and -EDEADLK if an
904 * attempt to obtain another state object ran into a &drm_modeset_lock
905 * deadlock.
906 */
907 int (*atomic_check)(struct drm_connector *connector,
908 struct drm_connector_state *state);
875}; 909};
876 910
877/** 911/**