Initial implementation of DE2 planes only supported fixed zpos.

Expand implementation with configurable zpos property.

Signed-off-by: Jernej Skrabec <jernej.skra...@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c    | 15 +++++++--
 drivers/gpu/drm/sun4i/sun8i_mixer.h    |  4 +++
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 45 ++++++++++++++++----------
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 45 ++++++++++++++++----------
 4 files changed, 72 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index ee8febb25903..0747a9a69654 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -260,6 +260,17 @@ const struct de2_fmt_info *sun8i_mixer_format_info(u32 
format)
        return NULL;
 }
 
+static void sun8i_mixer_atomic_begin(struct sunxi_engine *engine,
+                                    struct drm_crtc_state *old_state)
+{
+       /*
+        * Disable all pipes at the beginning. They will be enabled
+        * again if needed in plane update callback.
+        */
+       regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_PIPE_CTL,
+                          SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
+}
+
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
 {
        DRM_DEBUG_DRIVER("Committing changes\n");
@@ -311,6 +322,7 @@ static struct drm_plane **sun8i_layers_init(struct 
drm_device *drm,
 }
 
 static const struct sunxi_engine_ops sun8i_engine_ops = {
+       .atomic_begin   = sun8i_mixer_atomic_begin,
        .commit         = sun8i_mixer_commit,
        .layers_init    = sun8i_layers_init,
 };
@@ -432,9 +444,6 @@ static int sun8i_mixer_bind(struct device *dev, struct 
device *master,
        regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
                     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
-       /* Fixed zpos for now */
-       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 0x43210);
-
        plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
        for (i = 0; i < plane_cnt; i++)
                regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(i),
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index f34e70c42adf..406c42e752d7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -44,6 +44,7 @@
 #define SUN8I_MIXER_BLEND_CK_MIN(x)            (0x10e0 + 0x04 * (x))
 #define SUN8I_MIXER_BLEND_OUTCTL               0x10fc
 
+#define SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK      GENMASK(12, 8)
 #define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe)    BIT(8 + pipe)
 #define SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(pipe) BIT(pipe)
 /* colors are always in AARRGGBB format */
@@ -51,6 +52,9 @@
 /* The following numbers are some still unknown magic numbers */
 #define SUN8I_MIXER_BLEND_MODE_DEF             0x03010301
 
+#define SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(n)    (0xf << ((n) << 2))
+#define SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(n)  ((n) << 2)
+
 #define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED    BIT(1)
 
 #define SUN8I_MIXER_FBFMT_ARGB8888     0
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 9a540330cb79..518e1921f47e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -27,7 +27,7 @@
 #include "sun8i_ui_scaler.h"
 
 static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
-                                 int overlay, bool enable)
+                                 int overlay, bool enable, unsigned int zpos)
 {
        u32 val;
 
@@ -43,18 +43,24 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer 
*mixer, int channel,
                           SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
                           SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
-       if (enable)
-               val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
-       else
-               val = 0;
+       if (enable) {
+               val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
 
-       regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_BLEND_PIPE_CTL,
-                          SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+               regmap_update_bits(mixer->engine.regs,
+                                  SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
+
+               val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
+
+               regmap_update_bits(mixer->engine.regs,
+                                  SUN8I_MIXER_BLEND_ROUTE,
+                                  SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
+                                  val);
+       }
 }
 
 static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
-                                      int overlay, struct drm_plane *plane)
+                                      int overlay, struct drm_plane *plane,
+                                      unsigned int zpos)
 {
        struct drm_plane_state *state = plane->state;
        u32 src_w, src_h, dst_w, dst_h;
@@ -137,10 +143,10 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
                         state->dst.x1, state->dst.y1);
        DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+                    SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
                     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+                    SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
                     outsize);
 
        return 0;
@@ -238,28 +244,30 @@ static void sun8i_ui_layer_atomic_disable(struct 
drm_plane *plane,
        struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
        struct sun8i_mixer *mixer = layer->mixer;
 
-       sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false);
+       sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0);
 }
 
 static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
                                         struct drm_plane_state *old_state)
 {
        struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+       unsigned int zpos = plane->state->normalized_zpos;
        struct sun8i_mixer *mixer = layer->mixer;
 
        if (!plane->state->visible) {
                sun8i_ui_layer_enable(mixer, layer->channel,
-                                     layer->overlay, false);
+                                     layer->overlay, false, 0);
                return;
        }
 
        sun8i_ui_layer_update_coord(mixer, layer->channel,
-                                   layer->overlay, plane);
+                                   layer->overlay, plane, zpos);
        sun8i_ui_layer_update_formats(mixer, layer->channel,
                                      layer->overlay, plane);
        sun8i_ui_layer_update_buffer(mixer, layer->channel,
                                     layer->overlay, plane);
-       sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, true);
+       sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
+                             true, zpos);
 }
 
 static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
@@ -307,6 +315,7 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct 
drm_device *drm,
        enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
        int channel = mixer->cfg->vi_num + index;
        struct sun8i_ui_layer *layer;
+       unsigned int plane_cnt;
        int ret;
 
        layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
@@ -327,8 +336,10 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct 
drm_device *drm,
                return ERR_PTR(ret);
        }
 
-       /* fixed zpos for now */
-       ret = drm_plane_create_zpos_immutable_property(&layer->plane, channel);
+       plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
+
+       ret = drm_plane_create_zpos_property(&layer->plane, channel,
+                                            0, plane_cnt - 1);
        if (ret) {
                dev_err(drm->dev, "Couldn't add zpos property\n");
                return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 5877f8ef5895..17e0d00cfd8a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -21,7 +21,7 @@
 #include "sun8i_vi_scaler.h"
 
 static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
-                                 int overlay, bool enable)
+                                 int overlay, bool enable, unsigned int zpos)
 {
        u32 val;
 
@@ -37,18 +37,24 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer 
*mixer, int channel,
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
 
-       if (enable)
-               val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
-       else
-               val = 0;
+       if (enable) {
+               val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
 
-       regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_BLEND_PIPE_CTL,
-                          SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+               regmap_update_bits(mixer->engine.regs,
+                                  SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
+
+               val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
+
+               regmap_update_bits(mixer->engine.regs,
+                                  SUN8I_MIXER_BLEND_ROUTE,
+                                  SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
+                                  val);
+       }
 }
 
 static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
-                                      int overlay, struct drm_plane *plane)
+                                      int overlay, struct drm_plane *plane,
+                                      unsigned int zpos)
 {
        struct drm_plane_state *state = plane->state;
        const struct drm_format_info *format = state->fb->format;
@@ -130,10 +136,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
                         state->dst.x1, state->dst.y1);
        DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+                    SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
                     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+                    SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
                     outsize);
 
        return 0;
@@ -266,28 +272,30 @@ static void sun8i_vi_layer_atomic_disable(struct 
drm_plane *plane,
        struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
        struct sun8i_mixer *mixer = layer->mixer;
 
-       sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false);
+       sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0);
 }
 
 static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
                                         struct drm_plane_state *old_state)
 {
        struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+       unsigned int zpos = plane->state->normalized_zpos;
        struct sun8i_mixer *mixer = layer->mixer;
 
        if (!plane->state->visible) {
                sun8i_vi_layer_enable(mixer, layer->channel,
-                                     layer->overlay, false);
+                                     layer->overlay, false, 0);
                return;
        }
 
        sun8i_vi_layer_update_coord(mixer, layer->channel,
-                                   layer->overlay, plane);
+                                   layer->overlay, plane, zpos);
        sun8i_vi_layer_update_formats(mixer, layer->channel,
                                      layer->overlay, plane);
        sun8i_vi_layer_update_buffer(mixer, layer->channel,
                                     layer->overlay, plane);
-       sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, true);
+       sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
+                             true, zpos);
 }
 
 static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
@@ -351,6 +359,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
                                               int index)
 {
        struct sun8i_vi_layer *layer;
+       unsigned int plane_cnt;
        int ret;
 
        layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
@@ -368,8 +377,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
                return ERR_PTR(ret);
        }
 
-       /* fixed zpos for now */
-       ret = drm_plane_create_zpos_immutable_property(&layer->plane, index);
+       plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
+
+       ret = drm_plane_create_zpos_property(&layer->plane, index,
+                                            0, plane_cnt - 1);
        if (ret) {
                dev_err(drm->dev, "Couldn't add zpos property\n");
                return ERR_PTR(ret);
-- 
2.18.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to