summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@bootlin.com>2018-02-16 18:39:32 +0100
committerMaxime Ripard <maxime.ripard@bootlin.com>2018-02-22 16:19:52 +0100
commit8f1f25534fff09f54d75ea8fac4ea8f35fb385d6 (patch)
treed1e5a19d80d6ca7e6c02285aa2278da622600330
parent8a1949455aaa22b3ff581766a640ed7f92cf8cef (diff)
drm/sun4i: backend: Assign the pipes automatically
Since we now have a way to enforce the zpos, check for the number of alpha planes, the only missing part is to assign our pipe automatically instead of hardcoding it. The algorithm is quite simple, but requires two iterations over the list of planes. In the first one (which is the same one that we've had to check for alpha, the frontend usage, and so on), we order the planes by their zpos. We can then do a second iteration over that array by ascending zpos starting with the pipe 0. When and if we encounter our alpha plane, we put it and all the other subsequent planes in the second pipe. Reviewed-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Link: https://patchwork.freedesktop.org/patch/msgid/e9caf21d831438d36a3ccc7cef229c9a7ea7f69f.1518802627.git-series.maxime.ripard@bootlin.com
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c40
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c6
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.h1
3 files changed, 39 insertions, 8 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 245b189fc4d8..f387420bda8d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -275,12 +275,16 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
struct drm_plane *plane)
{
struct drm_plane_state *state = plane->state;
+ struct sun4i_layer_state *p_state = state_to_sun4i_layer_state(state);
unsigned int priority = state->normalized_zpos;
+ unsigned int pipe = p_state->pipe;
- DRM_DEBUG_DRIVER("Setting layer %d's priority to %d\n", layer, priority);
-
+ DRM_DEBUG_DRIVER("Setting layer %d's priority to %d and pipe %d\n",
+ layer, priority, pipe);
regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer),
+ SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK |
SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK,
+ SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(p_state->pipe) |
SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(priority));
return 0;
@@ -325,12 +329,15 @@ static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
struct drm_crtc_state *crtc_state)
{
+ struct drm_plane_state *plane_states[SUN4I_BACKEND_NUM_LAYERS] = { 0 };
struct drm_atomic_state *state = crtc_state->state;
struct drm_device *drm = state->dev;
struct drm_plane *plane;
unsigned int num_planes = 0;
unsigned int num_alpha_planes = 0;
unsigned int num_frontend_planes = 0;
+ unsigned int current_pipe = 0;
+ unsigned int i;
DRM_DEBUG_DRIVER("Starting checking our planes\n");
@@ -361,9 +368,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
if (fb->format->has_alpha)
num_alpha_planes++;
+ DRM_DEBUG_DRIVER("Plane zpos is %d\n",
+ plane_state->normalized_zpos);
+
+ /* Sort our planes by Zpos */
+ plane_states[plane_state->normalized_zpos] = plane_state;
+
num_planes++;
}
+ /* All our planes were disabled, bail out */
+ if (!num_planes)
+ return 0;
+
/*
* The hardware is a bit unusual here.
*
@@ -400,6 +417,25 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
return -EINVAL;
}
+ /* We can't have an alpha plane at the lowest position */
+ if (plane_states[0]->fb->format->has_alpha)
+ return -EINVAL;
+
+ for (i = 1; i < num_planes; i++) {
+ struct drm_plane_state *p_state = plane_states[i];
+ struct drm_framebuffer *fb = p_state->fb;
+ struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(p_state);
+
+ /*
+ * The only alpha position is the lowest plane of the
+ * second pipe.
+ */
+ if (fb->format->has_alpha)
+ current_pipe++;
+
+ s_state->pipe = current_pipe;
+ }
+
if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) {
DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n");
return -EINVAL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 19be798e4fac..3e3d554713cb 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -220,12 +220,6 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm,
drm_plane_create_zpos_immutable_property(&layer->plane, i);
- DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
- i ? "overlay" : "primary", plane->pipe);
- regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
- SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
- SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
-
layer->id = i;
planes[i] = &layer->plane;
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 75b4868ba87c..36b20265bd31 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -24,6 +24,7 @@ struct sun4i_layer {
struct sun4i_layer_state {
struct drm_plane_state state;
+ unsigned int pipe;
bool uses_frontend;
};