aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c81
1 files changed, 55 insertions, 26 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 523e0e8c6962..50b34f5fc97b 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -11,6 +11,7 @@
11#include <linux/of_device.h> 11#include <linux/of_device.h>
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <drm/drmP.h> 13#include <drm/drmP.h>
14#include <drm/drm_atomic.h>
14#include <drm/drm_crtc_helper.h> 15#include <drm/drm_crtc_helper.h>
15#include <drm/drm_plane_helper.h> 16#include <drm/drm_plane_helper.h>
16#include <drm/drm_atomic_helper.h> 17#include <drm/drm_atomic_helper.h>
@@ -939,53 +940,81 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
939 * and a mode_set. 940 * and a mode_set.
940 */ 941 */
941static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, 942static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
942 struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, 943 struct drm_framebuffer *fb, struct drm_pending_vblank_event *event,
943 struct drm_modeset_acquire_ctx *ctx) 944 uint32_t page_flip_flags, struct drm_modeset_acquire_ctx *ctx)
944{ 945{
945 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 946 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
947 struct drm_plane *plane = crtc->primary;
948 const struct drm_plane_helper_funcs *plane_funcs;
949 struct drm_plane_state *state;
946 struct armada_plane_work *work; 950 struct armada_plane_work *work;
947 unsigned i;
948 int ret; 951 int ret;
949 952
950 work = armada_drm_crtc_alloc_plane_work(dcrtc->crtc.primary); 953 /* Construct new state for the primary plane */
951 if (!work) 954 state = drm_atomic_helper_plane_duplicate_state(plane);
955 if (!state)
952 return -ENOMEM; 956 return -ENOMEM;
953 957
954 work->event = event; 958 drm_atomic_set_fb_for_plane(state, fb);
955 work->old_fb = dcrtc->crtc.primary->fb;
956 959
957 i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs, 960 work = armada_drm_crtc_alloc_plane_work(plane);
958 dcrtc->interlaced); 961 if (!work) {
959 armada_reg_queue_end(work->regs, i); 962 ret = -ENOMEM;
963 goto put_state;
964 }
965
966 /* Make sure we can get vblank interrupts */
967 ret = drm_crtc_vblank_get(crtc);
968 if (ret)
969 goto put_work;
960 970
961 /* 971 /*
962 * Ensure that we hold a reference on the new framebuffer. 972 * If we have another work pending, we can't process this flip.
963 * This has to match the behaviour in mode_set. 973 * The modeset locks protect us from another user queuing a work
974 * while we're setting up.
964 */ 975 */
965 drm_framebuffer_get(fb); 976 if (drm_to_armada_plane(plane)->work) {
966 977 ret = -EBUSY;
967 ret = armada_drm_plane_work_queue(dcrtc, work); 978 goto put_vblank;
968 if (ret) {
969 /* Undo our reference above */
970 drm_framebuffer_put(fb);
971 kfree(work);
972 return ret;
973 } 979 }
974 980
981 work->event = event;
982 work->old_fb = plane->state->fb;
983
975 /* 984 /*
976 * We are in transition to atomic modeset: update the atomic modeset 985 * Hold a ref on the new fb while it's being displayed by the
977 * state with the new framebuffer to keep the state consistent. 986 * hardware. The old fb refcount will be released in the worker.
978 */ 987 */
979 drm_framebuffer_assign(&dcrtc->crtc.primary->state->fb, fb); 988 drm_framebuffer_get(state->fb);
989
990 /* Point of no return */
991 swap(plane->state, state);
992
993 dcrtc->regs_idx = 0;
994 dcrtc->regs = work->regs;
995
996 plane_funcs = plane->helper_private;
997 plane_funcs->atomic_update(plane, state);
998 armada_reg_queue_end(dcrtc->regs, dcrtc->regs_idx);
999
1000 /* Queue the work - this should never fail */
1001 WARN_ON(armada_drm_plane_work_queue(dcrtc, work));
1002 work = NULL;
980 1003
981 /* 1004 /*
982 * Finally, if the display is blanked, we won't receive an 1005 * Finally, if the display is blanked, we won't receive an
983 * interrupt, so complete it now. 1006 * interrupt, so complete it now.
984 */ 1007 */
985 if (dpms_blanked(dcrtc->dpms)) 1008 if (dpms_blanked(dcrtc->dpms))
986 armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary); 1009 armada_drm_plane_work_run(dcrtc, plane);
987 1010
988 return 0; 1011put_vblank:
1012 drm_crtc_vblank_put(crtc);
1013put_work:
1014 kfree(work);
1015put_state:
1016 drm_atomic_helper_plane_destroy_state(plane, state);
1017 return ret;
989} 1018}
990 1019
991static int 1020static int