diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2017-06-26 16:51:15 -0400 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2018-01-29 08:02:42 -0500 |
commit | 65f7fa3a3fcbdb67940a58ce24516d62aaec12b7 (patch) | |
tree | 8f3cf4a62a4c44b8731b13e5a045fb0f043f3ffe /drivers/gpu/drm/sun4i/sun4i_backend.c | |
parent | 47a05f4a68f91c09d89d2a0231b7b8c7ebb808ca (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.c | 51 |
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 | ||