2 * Copyright (C) 2015 Broadcom
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
12 * This is the general code for implementing KMS mode setting that
13 * doesn't clearly associate with any of the other objects (plane,
14 * crtc, HDMI encoder).
18 #include "drm_atomic.h"
19 #include "drm_atomic_helper.h"
20 #include "drm_crtc_helper.h"
21 #include "drm_plane_helper.h"
22 #include "drm_fb_cma_helper.h"
25 static void vc4_output_poll_changed(struct drm_device
*dev
)
27 struct vc4_dev
*vc4
= to_vc4_dev(dev
);
30 drm_fbdev_cma_hotplug_event(vc4
->fbdev
);
34 struct drm_device
*dev
;
35 struct drm_atomic_state
*state
;
36 struct vc4_seqno_cb cb
;
40 vc4_atomic_complete_commit(struct vc4_commit
*c
)
42 struct drm_atomic_state
*state
= c
->state
;
43 struct drm_device
*dev
= state
->dev
;
44 struct vc4_dev
*vc4
= to_vc4_dev(dev
);
46 drm_atomic_helper_commit_modeset_disables(dev
, state
);
48 drm_atomic_helper_commit_planes(dev
, state
, false);
50 drm_atomic_helper_commit_modeset_enables(dev
, state
);
52 /* Make sure that drm_atomic_helper_wait_for_vblanks()
53 * actually waits for vblank. If we're doing a full atomic
54 * modeset (as opposed to a vc4_update_plane() short circuit),
55 * then we need to wait for scanout to be done with our
56 * display lists before we free it and potentially reallocate
57 * and overwrite the dlist memory with a new modeset.
59 state
->legacy_cursor_update
= false;
61 drm_atomic_helper_wait_for_vblanks(dev
, state
);
63 drm_atomic_helper_cleanup_planes(dev
, state
);
65 drm_atomic_state_free(state
);
67 up(&vc4
->async_modeset
);
73 vc4_atomic_complete_commit_seqno_cb(struct vc4_seqno_cb
*cb
)
75 struct vc4_commit
*c
= container_of(cb
, struct vc4_commit
, cb
);
77 vc4_atomic_complete_commit(c
);
80 static struct vc4_commit
*commit_init(struct drm_atomic_state
*state
)
82 struct vc4_commit
*c
= kzalloc(sizeof(*c
), GFP_KERNEL
);
93 * vc4_atomic_commit - commit validated state object
95 * @state: the driver state object
96 * @async: asynchronous commit
98 * This function commits a with drm_atomic_helper_check() pre-validated state
99 * object. This can still fail when e.g. the framebuffer reservation fails. For
100 * now this doesn't implement asynchronous commits.
103 * Zero for success or -errno.
105 static int vc4_atomic_commit(struct drm_device
*dev
,
106 struct drm_atomic_state
*state
,
109 struct vc4_dev
*vc4
= to_vc4_dev(dev
);
112 uint64_t wait_seqno
= 0;
113 struct vc4_commit
*c
;
115 c
= commit_init(state
);
119 /* Make sure that any outstanding modesets have finished. */
120 ret
= down_interruptible(&vc4
->async_modeset
);
126 ret
= drm_atomic_helper_prepare_planes(dev
, state
);
129 up(&vc4
->async_modeset
);
133 for (i
= 0; i
< dev
->mode_config
.num_total_plane
; i
++) {
134 struct drm_plane
*plane
= state
->planes
[i
];
135 struct drm_plane_state
*new_state
= state
->plane_states
[i
];
140 if ((plane
->state
->fb
!= new_state
->fb
) && new_state
->fb
) {
141 struct drm_gem_cma_object
*cma_bo
=
142 drm_fb_cma_get_gem_obj(new_state
->fb
, 0);
143 struct vc4_bo
*bo
= to_vc4_bo(&cma_bo
->base
);
145 wait_seqno
= max(bo
->seqno
, wait_seqno
);
150 * This is the point of no return - everything below never fails except
151 * when the hw goes bonghits. Which means we can commit the new state on
152 * the software side now.
155 drm_atomic_helper_swap_state(dev
, state
);
158 * Everything below can be run asynchronously without the need to grab
159 * any modeset locks at all under one condition: It must be guaranteed
160 * that the asynchronous work has either been cancelled (if the driver
161 * supports it, which at least requires that the framebuffers get
162 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
163 * before the new state gets committed on the software side with
164 * drm_atomic_helper_swap_state().
166 * This scheme allows new atomic state updates to be prepared and
167 * checked in parallel to the asynchronous completion of the previous
168 * update. Which is important since compositors need to figure out the
169 * composition of the next frame right after having submitted the
174 vc4_queue_seqno_cb(dev
, &c
->cb
, wait_seqno
,
175 vc4_atomic_complete_commit_seqno_cb
);
177 vc4_wait_for_seqno(dev
, wait_seqno
, ~0ull, false);
178 vc4_atomic_complete_commit(c
);
184 static const struct drm_mode_config_funcs vc4_mode_funcs
= {
185 .output_poll_changed
= vc4_output_poll_changed
,
186 .atomic_check
= drm_atomic_helper_check
,
187 .atomic_commit
= vc4_atomic_commit
,
188 .fb_create
= drm_fb_cma_create
,
191 int vc4_kms_load(struct drm_device
*dev
)
193 struct vc4_dev
*vc4
= to_vc4_dev(dev
);
196 sema_init(&vc4
->async_modeset
, 1);
198 ret
= drm_vblank_init(dev
, dev
->mode_config
.num_crtc
);
200 dev_err(dev
->dev
, "failed to initialize vblank\n");
204 dev
->mode_config
.max_width
= 2048;
205 dev
->mode_config
.max_height
= 2048;
206 dev
->mode_config
.funcs
= &vc4_mode_funcs
;
207 dev
->mode_config
.preferred_depth
= 24;
208 dev
->mode_config
.async_page_flip
= true;
210 dev
->vblank_disable_allowed
= true;
212 drm_mode_config_reset(dev
);
214 vc4
->fbdev
= drm_fbdev_cma_init(dev
, 32,
215 dev
->mode_config
.num_crtc
,
216 dev
->mode_config
.num_connector
);
217 if (IS_ERR(vc4
->fbdev
))
220 drm_kms_helper_poll_init(dev
);