aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sun4i/sun4i_backend.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2017-06-26 16:51:15 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2018-01-29 08:02:42 -0500
commit65f7fa3a3fcbdb67940a58ce24516d62aaec12b7 (patch)
tree8f3cf4a62a4c44b8731b13e5a045fb0f043f3ffe /drivers/gpu/drm/sun4i/sun4i_backend.c
parent47a05f4a68f91c09d89d2a0231b7b8c7ebb808ca (diff)
drm/sun4i: backend: Check for the number of alpha planes
Due to the way the composition is done in hardware, we can only have a single alpha-enabled plane active at a time, placed in the second (highest priority) pipe. Make sure of that in our atomic_check to not end up in an impossible scenario. Reviewed-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Link: https://patchwork.freedesktop.org/patch/msgid/7371f62a1385f2cbe3ed75dfca2e746338eb2286.1516617243.git-series.maxime.ripard@free-electrons.com
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 0cbe9f066f0c..245b189fc4d8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -328,6 +328,8 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
328 struct drm_atomic_state *state = crtc_state->state; 328 struct drm_atomic_state *state = crtc_state->state;
329 struct drm_device *drm = state->dev; 329 struct drm_device *drm = state->dev;
330 struct drm_plane *plane; 330 struct drm_plane *plane;
331 unsigned int num_planes = 0;
332 unsigned int num_alpha_planes = 0;
331 unsigned int num_frontend_planes = 0; 333 unsigned int num_frontend_planes = 0;
332 334
333 DRM_DEBUG_DRIVER("Starting checking our planes\n"); 335 DRM_DEBUG_DRIVER("Starting checking our planes\n");
@@ -340,6 +342,8 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
340 drm_atomic_get_plane_state(state, plane); 342 drm_atomic_get_plane_state(state, plane);
341 struct sun4i_layer_state *layer_state = 343 struct sun4i_layer_state *layer_state =
342 state_to_sun4i_layer_state(plane_state); 344 state_to_sun4i_layer_state(plane_state);
345 struct drm_framebuffer *fb = plane_state->fb;
346 struct drm_format_name_buf format_name;
343 347
344 if (sun4i_backend_plane_uses_frontend(plane_state)) { 348 if (sun4i_backend_plane_uses_frontend(plane_state)) {
345 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", 349 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
@@ -350,6 +354,50 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
350 } else { 354 } else {
351 layer_state->uses_frontend = false; 355 layer_state->uses_frontend = false;
352 } 356 }
357
358 DRM_DEBUG_DRIVER("Plane FB format is %s\n",
359 drm_get_format_name(fb->format->format,
360 &format_name));
361 if (fb->format->has_alpha)
362 num_alpha_planes++;
363
364 num_planes++;
365 }
366
367 /*
368 * The hardware is a bit unusual here.
369 *
370 * Even though it supports 4 layers, it does the composition
371 * in two separate steps.
372 *
373 * The first one is assigning a layer to one of its two
374 * pipes. If more that 1 layer is assigned to the same pipe,
375 * and if pixels overlaps, the pipe will take the pixel from
376 * the layer with the highest priority.
377 *
378 * The second step is the actual alpha blending, that takes
379 * the two pipes as input, and uses the eventual alpha
380 * component to do the transparency between the two.
381 *
382 * This two steps scenario makes us unable to guarantee a
383 * robust alpha blending between the 4 layers in all
384 * situations, since this means that we need to have one layer
385 * with alpha at the lowest position of our two pipes.
386 *
387 * However, we cannot even do that, since the hardware has a
388 * bug where the lowest plane of the lowest pipe (pipe 0,
389 * priority 0), if it has any alpha, will discard the pixel
390 * entirely and just display the pixels in the background
391 * color (black by default).
392 *
393 * This means that we effectively have only three valid
394 * configurations with alpha, all of them with the alpha being
395 * on pipe1 with the lowest position, which can be 1, 2 or 3
396 * depending on the number of planes and their zpos.
397 */
398 if (num_alpha_planes > SUN4I_BACKEND_NUM_ALPHA_LAYERS) {
399 DRM_DEBUG_DRIVER("Too many planes with alpha, rejecting...\n");
400 return -EINVAL;
353 } 401 }
354 402
355 if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) { 403 if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) {
@@ -357,6 +405,9 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
357 return -EINVAL; 405 return -EINVAL;
358 } 406 }
359 407
408 DRM_DEBUG_DRIVER("State valid with %u planes, %u alpha, %u video\n",
409 num_planes, num_alpha_planes, num_frontend_planes);
410
360 return 0; 411 return 0;
361} 412}
362 413