Skip to content

Commit 96180dd

Browse files
committed
drm/sun4i: backend: Add a custom atomic_check for the frontend
Now that we have everything in place, we can start enabling the frontend. This is more difficult than one would assume since there can only be one plane using the frontend per-backend. We therefore need to make sure that the userspace will not try to setup multiple planes using it, since that would be impossible. In order to prevent that, we can create an atomic_check callback that will check that only one plane will effectively make use of the frontend in a given configuration, and will toggle the switch in that plane state so that the proper setup function can do their role. Reviewed-by: Chen-Yu Tsai <[email protected]> Reviewed-by: Neil Armstrong <[email protected]> Signed-off-by: Maxime Ripard <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/278e6c514a8311750fe627c7f28d58b3e2cbd825.1516613040.git-series.maxime.ripard@free-electrons.com
1 parent ca07b21 commit 96180dd

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

drivers/gpu/drm/sun4i/sun4i_backend.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
*/
1212

1313
#include <drm/drmP.h>
14+
#include <drm/drm_atomic.h>
1415
#include <drm/drm_atomic_helper.h>
1516
#include <drm/drm_crtc.h>
1617
#include <drm/drm_crtc_helper.h>
@@ -270,6 +271,69 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
270271
return 0;
271272
}
272273

274+
static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
275+
{
276+
u16 src_h = state->src_h >> 16;
277+
u16 src_w = state->src_w >> 16;
278+
279+
DRM_DEBUG_DRIVER("Input size %dx%d, output size %dx%d\n",
280+
src_w, src_h, state->crtc_w, state->crtc_h);
281+
282+
if ((state->crtc_h != src_h) || (state->crtc_w != src_w))
283+
return true;
284+
285+
return false;
286+
}
287+
288+
static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state)
289+
{
290+
struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
291+
struct sun4i_backend *backend = layer->backend;
292+
293+
if (IS_ERR(backend->frontend))
294+
return false;
295+
296+
return sun4i_backend_plane_uses_scaler(state);
297+
}
298+
299+
static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
300+
struct drm_crtc_state *crtc_state)
301+
{
302+
struct drm_atomic_state *state = crtc_state->state;
303+
struct drm_device *drm = state->dev;
304+
struct drm_plane *plane;
305+
unsigned int num_frontend_planes = 0;
306+
307+
DRM_DEBUG_DRIVER("Starting checking our planes\n");
308+
309+
if (!crtc_state->planes_changed)
310+
return 0;
311+
312+
drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
313+
struct drm_plane_state *plane_state =
314+
drm_atomic_get_plane_state(state, plane);
315+
struct sun4i_layer_state *layer_state =
316+
state_to_sun4i_layer_state(plane_state);
317+
318+
if (sun4i_backend_plane_uses_frontend(plane_state)) {
319+
DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
320+
plane->index);
321+
322+
layer_state->uses_frontend = true;
323+
num_frontend_planes++;
324+
} else {
325+
layer_state->uses_frontend = false;
326+
}
327+
}
328+
329+
if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) {
330+
DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n");
331+
return -EINVAL;
332+
}
333+
334+
return 0;
335+
}
336+
273337
static void sun4i_backend_vblank_quirk(struct sunxi_engine *engine)
274338
{
275339
struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
@@ -414,6 +478,7 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
414478
}
415479

416480
static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
481+
.atomic_check = sun4i_backend_atomic_check,
417482
.commit = sun4i_backend_commit,
418483
.layers_init = sun4i_layers_init,
419484
.apply_color_correction = sun4i_backend_apply_color_correction,

drivers/gpu/drm/sun4i/sun4i_backend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@
144144
#define SUN4I_BACKEND_HWCCOLORTAB_OFF 0x4c00
145145
#define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p)))
146146

147+
#define SUN4I_BACKEND_NUM_FRONTEND_LAYERS 1
148+
147149
struct sun4i_backend {
148150
struct sunxi_engine engine;
149151
struct sun4i_frontend *frontend;

0 commit comments

Comments
 (0)