summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
};