diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 99 |
1 files changed, 70 insertions, 29 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 01d936b7be43..9203f3e933f7 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -322,10 +322,11 @@ update_connector_routing(struct drm_atomic_state *state, | |||
322 | } | 322 | } |
323 | 323 | ||
324 | if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) { | 324 | if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) { |
325 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n", | 325 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d:%s]\n", |
326 | new_encoder->base.id, | 326 | new_encoder->base.id, |
327 | new_encoder->name, | 327 | new_encoder->name, |
328 | connector_state->crtc->base.id); | 328 | connector_state->crtc->base.id, |
329 | connector_state->crtc->name); | ||
329 | return -EINVAL; | 330 | return -EINVAL; |
330 | } | 331 | } |
331 | 332 | ||
@@ -1119,7 +1120,8 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, | |||
1119 | drm_crtc_vblank_count(crtc), | 1120 | drm_crtc_vblank_count(crtc), |
1120 | msecs_to_jiffies(50)); | 1121 | msecs_to_jiffies(50)); |
1121 | 1122 | ||
1122 | WARN(!ret, "[CRTC:%d] vblank wait timed out\n", crtc->base.id); | 1123 | WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n", |
1124 | crtc->base.id, crtc->name); | ||
1123 | 1125 | ||
1124 | drm_crtc_vblank_put(crtc); | 1126 | drm_crtc_vblank_put(crtc); |
1125 | } | 1127 | } |
@@ -1170,7 +1172,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_tail); | |||
1170 | static void commit_tail(struct drm_atomic_state *old_state) | 1172 | static void commit_tail(struct drm_atomic_state *old_state) |
1171 | { | 1173 | { |
1172 | struct drm_device *dev = old_state->dev; | 1174 | struct drm_device *dev = old_state->dev; |
1173 | struct drm_mode_config_helper_funcs *funcs; | 1175 | const struct drm_mode_config_helper_funcs *funcs; |
1174 | 1176 | ||
1175 | funcs = dev->mode_config.helper_private; | 1177 | funcs = dev->mode_config.helper_private; |
1176 | 1178 | ||
@@ -1977,11 +1979,11 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, | |||
1977 | int i; | 1979 | int i; |
1978 | long ret; | 1980 | long ret; |
1979 | struct drm_connector *connector; | 1981 | struct drm_connector *connector; |
1980 | struct drm_connector_state *conn_state; | 1982 | struct drm_connector_state *conn_state, *old_conn_state; |
1981 | struct drm_crtc *crtc; | 1983 | struct drm_crtc *crtc; |
1982 | struct drm_crtc_state *crtc_state; | 1984 | struct drm_crtc_state *crtc_state, *old_crtc_state; |
1983 | struct drm_plane *plane; | 1985 | struct drm_plane *plane; |
1984 | struct drm_plane_state *plane_state; | 1986 | struct drm_plane_state *plane_state, *old_plane_state; |
1985 | struct drm_crtc_commit *commit; | 1987 | struct drm_crtc_commit *commit; |
1986 | 1988 | ||
1987 | if (stall) { | 1989 | if (stall) { |
@@ -2005,13 +2007,17 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, | |||
2005 | } | 2007 | } |
2006 | } | 2008 | } |
2007 | 2009 | ||
2008 | for_each_connector_in_state(state, connector, conn_state, i) { | 2010 | for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) { |
2011 | WARN_ON(connector->state != old_conn_state); | ||
2012 | |||
2009 | connector->state->state = state; | 2013 | connector->state->state = state; |
2010 | swap(state->connectors[i].state, connector->state); | 2014 | swap(state->connectors[i].state, connector->state); |
2011 | connector->state->state = NULL; | 2015 | connector->state->state = NULL; |
2012 | } | 2016 | } |
2013 | 2017 | ||
2014 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 2018 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { |
2019 | WARN_ON(crtc->state != old_crtc_state); | ||
2020 | |||
2015 | crtc->state->state = state; | 2021 | crtc->state->state = state; |
2016 | swap(state->crtcs[i].state, crtc->state); | 2022 | swap(state->crtcs[i].state, crtc->state); |
2017 | crtc->state->state = NULL; | 2023 | crtc->state->state = NULL; |
@@ -2026,7 +2032,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, | |||
2026 | } | 2032 | } |
2027 | } | 2033 | } |
2028 | 2034 | ||
2029 | for_each_plane_in_state(state, plane, plane_state, i) { | 2035 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) { |
2036 | WARN_ON(plane->state != old_plane_state); | ||
2037 | |||
2030 | plane->state->state = state; | 2038 | plane->state->state = state; |
2031 | swap(state->planes[i].state, plane->state); | 2039 | swap(state->planes[i].state, plane->state); |
2032 | plane->state->state = NULL; | 2040 | plane->state->state = NULL; |
@@ -2477,7 +2485,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all); | |||
2477 | * | 2485 | * |
2478 | * See also: | 2486 | * See also: |
2479 | * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(), | 2487 | * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(), |
2480 | * drm_atomic_helper_resume() | 2488 | * drm_atomic_helper_resume(), drm_atomic_helper_commit_duplicated_state() |
2481 | */ | 2489 | */ |
2482 | struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev) | 2490 | struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev) |
2483 | { | 2491 | { |
@@ -2518,6 +2526,47 @@ unlock: | |||
2518 | EXPORT_SYMBOL(drm_atomic_helper_suspend); | 2526 | EXPORT_SYMBOL(drm_atomic_helper_suspend); |
2519 | 2527 | ||
2520 | /** | 2528 | /** |
2529 | * drm_atomic_helper_commit_duplicated_state - commit duplicated state | ||
2530 | * @state: duplicated atomic state to commit | ||
2531 | * @ctx: pointer to acquire_ctx to use for commit. | ||
2532 | * | ||
2533 | * The state returned by drm_atomic_helper_duplicate_state() and | ||
2534 | * drm_atomic_helper_suspend() is partially invalid, and needs to | ||
2535 | * be fixed up before commit. | ||
2536 | * | ||
2537 | * Returns: | ||
2538 | * 0 on success or a negative error code on failure. | ||
2539 | * | ||
2540 | * See also: | ||
2541 | * drm_atomic_helper_suspend() | ||
2542 | */ | ||
2543 | int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, | ||
2544 | struct drm_modeset_acquire_ctx *ctx) | ||
2545 | { | ||
2546 | int i; | ||
2547 | struct drm_plane *plane; | ||
2548 | struct drm_plane_state *plane_state; | ||
2549 | struct drm_connector *connector; | ||
2550 | struct drm_connector_state *conn_state; | ||
2551 | struct drm_crtc *crtc; | ||
2552 | struct drm_crtc_state *crtc_state; | ||
2553 | |||
2554 | state->acquire_ctx = ctx; | ||
2555 | |||
2556 | for_each_new_plane_in_state(state, plane, plane_state, i) | ||
2557 | state->planes[i].old_state = plane->state; | ||
2558 | |||
2559 | for_each_new_crtc_in_state(state, crtc, crtc_state, i) | ||
2560 | state->crtcs[i].old_state = crtc->state; | ||
2561 | |||
2562 | for_each_new_connector_in_state(state, connector, conn_state, i) | ||
2563 | state->connectors[i].old_state = connector->state; | ||
2564 | |||
2565 | return drm_atomic_commit(state); | ||
2566 | } | ||
2567 | EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state); | ||
2568 | |||
2569 | /** | ||
2521 | * drm_atomic_helper_resume - subsystem-level resume helper | 2570 | * drm_atomic_helper_resume - subsystem-level resume helper |
2522 | * @dev: DRM device | 2571 | * @dev: DRM device |
2523 | * @state: atomic state to resume to | 2572 | * @state: atomic state to resume to |
@@ -2540,9 +2589,9 @@ int drm_atomic_helper_resume(struct drm_device *dev, | |||
2540 | int err; | 2589 | int err; |
2541 | 2590 | ||
2542 | drm_mode_config_reset(dev); | 2591 | drm_mode_config_reset(dev); |
2592 | |||
2543 | drm_modeset_lock_all(dev); | 2593 | drm_modeset_lock_all(dev); |
2544 | state->acquire_ctx = config->acquire_ctx; | 2594 | err = drm_atomic_helper_commit_duplicated_state(state, config->acquire_ctx); |
2545 | err = drm_atomic_commit(state); | ||
2546 | drm_modeset_unlock_all(dev); | 2595 | drm_modeset_unlock_all(dev); |
2547 | 2596 | ||
2548 | return err; | 2597 | return err; |
@@ -2718,7 +2767,8 @@ static int page_flip_common( | |||
2718 | struct drm_atomic_state *state, | 2767 | struct drm_atomic_state *state, |
2719 | struct drm_crtc *crtc, | 2768 | struct drm_crtc *crtc, |
2720 | struct drm_framebuffer *fb, | 2769 | struct drm_framebuffer *fb, |
2721 | struct drm_pending_vblank_event *event) | 2770 | struct drm_pending_vblank_event *event, |
2771 | uint32_t flags) | ||
2722 | { | 2772 | { |
2723 | struct drm_plane *plane = crtc->primary; | 2773 | struct drm_plane *plane = crtc->primary; |
2724 | struct drm_plane_state *plane_state; | 2774 | struct drm_plane_state *plane_state; |
@@ -2730,12 +2780,12 @@ static int page_flip_common( | |||
2730 | return PTR_ERR(crtc_state); | 2780 | return PTR_ERR(crtc_state); |
2731 | 2781 | ||
2732 | crtc_state->event = event; | 2782 | crtc_state->event = event; |
2783 | crtc_state->pageflip_flags = flags; | ||
2733 | 2784 | ||
2734 | plane_state = drm_atomic_get_plane_state(state, plane); | 2785 | plane_state = drm_atomic_get_plane_state(state, plane); |
2735 | if (IS_ERR(plane_state)) | 2786 | if (IS_ERR(plane_state)) |
2736 | return PTR_ERR(plane_state); | 2787 | return PTR_ERR(plane_state); |
2737 | 2788 | ||
2738 | |||
2739 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | 2789 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
2740 | if (ret != 0) | 2790 | if (ret != 0) |
2741 | return ret; | 2791 | return ret; |
@@ -2744,8 +2794,8 @@ static int page_flip_common( | |||
2744 | /* Make sure we don't accidentally do a full modeset. */ | 2794 | /* Make sure we don't accidentally do a full modeset. */ |
2745 | state->allow_modeset = false; | 2795 | state->allow_modeset = false; |
2746 | if (!crtc_state->active) { | 2796 | if (!crtc_state->active) { |
2747 | DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n", | 2797 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled, rejecting legacy flip\n", |
2748 | crtc->base.id); | 2798 | crtc->base.id, crtc->name); |
2749 | return -EINVAL; | 2799 | return -EINVAL; |
2750 | } | 2800 | } |
2751 | 2801 | ||
@@ -2762,10 +2812,6 @@ static int page_flip_common( | |||
2762 | * Provides a default &drm_crtc_funcs.page_flip implementation | 2812 | * Provides a default &drm_crtc_funcs.page_flip implementation |
2763 | * using the atomic driver interface. | 2813 | * using the atomic driver interface. |
2764 | * | 2814 | * |
2765 | * Note that for now so called async page flips (i.e. updates which are not | ||
2766 | * synchronized to vblank) are not supported, since the atomic interfaces have | ||
2767 | * no provisions for this yet. | ||
2768 | * | ||
2769 | * Returns: | 2815 | * Returns: |
2770 | * Returns 0 on success, negative errno numbers on failure. | 2816 | * Returns 0 on success, negative errno numbers on failure. |
2771 | * | 2817 | * |
@@ -2781,9 +2827,6 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | |||
2781 | struct drm_atomic_state *state; | 2827 | struct drm_atomic_state *state; |
2782 | int ret = 0; | 2828 | int ret = 0; |
2783 | 2829 | ||
2784 | if (flags & DRM_MODE_PAGE_FLIP_ASYNC) | ||
2785 | return -EINVAL; | ||
2786 | |||
2787 | state = drm_atomic_state_alloc(plane->dev); | 2830 | state = drm_atomic_state_alloc(plane->dev); |
2788 | if (!state) | 2831 | if (!state) |
2789 | return -ENOMEM; | 2832 | return -ENOMEM; |
@@ -2791,7 +2834,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | |||
2791 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | 2834 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); |
2792 | 2835 | ||
2793 | retry: | 2836 | retry: |
2794 | ret = page_flip_common(state, crtc, fb, event); | 2837 | ret = page_flip_common(state, crtc, fb, event, flags); |
2795 | if (ret != 0) | 2838 | if (ret != 0) |
2796 | goto fail; | 2839 | goto fail; |
2797 | 2840 | ||
@@ -2846,9 +2889,6 @@ int drm_atomic_helper_page_flip_target( | |||
2846 | struct drm_crtc_state *crtc_state; | 2889 | struct drm_crtc_state *crtc_state; |
2847 | int ret = 0; | 2890 | int ret = 0; |
2848 | 2891 | ||
2849 | if (flags & DRM_MODE_PAGE_FLIP_ASYNC) | ||
2850 | return -EINVAL; | ||
2851 | |||
2852 | state = drm_atomic_state_alloc(plane->dev); | 2892 | state = drm_atomic_state_alloc(plane->dev); |
2853 | if (!state) | 2893 | if (!state) |
2854 | return -ENOMEM; | 2894 | return -ENOMEM; |
@@ -2856,7 +2896,7 @@ int drm_atomic_helper_page_flip_target( | |||
2856 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | 2896 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); |
2857 | 2897 | ||
2858 | retry: | 2898 | retry: |
2859 | ret = page_flip_common(state, crtc, fb, event); | 2899 | ret = page_flip_common(state, crtc, fb, event, flags); |
2860 | if (ret != 0) | 2900 | if (ret != 0) |
2861 | goto fail; | 2901 | goto fail; |
2862 | 2902 | ||
@@ -3056,6 +3096,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, | |||
3056 | state->color_mgmt_changed = false; | 3096 | state->color_mgmt_changed = false; |
3057 | state->zpos_changed = false; | 3097 | state->zpos_changed = false; |
3058 | state->event = NULL; | 3098 | state->event = NULL; |
3099 | state->pageflip_flags = 0; | ||
3059 | } | 3100 | } |
3060 | EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); | 3101 | EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); |
3061 | 3102 | ||