Merge tag 'for-5.13/io_uring-2021-04-27' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / gpu / drm / sun4i / sun8i_vi_layer.c
index 8cc294a..4642078 100644 (file)
@@ -7,8 +7,8 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 
@@ -66,6 +66,36 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
        }
 }
 
+static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
+                                       int overlay, struct drm_plane *plane)
+{
+       u32 mask, val, ch_base;
+
+       ch_base = sun8i_channel_base(mixer, channel);
+
+       if (mixer->cfg->is_de3) {
+               mask = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK |
+                      SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK;
+               val = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA
+                       (plane->state->alpha >> 8);
+
+               val |= (plane->state->alpha == DRM_BLEND_ALPHA_OPAQUE) ?
+                       SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_PIXEL :
+                       SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_COMBINED;
+
+               regmap_update_bits(mixer->engine.regs,
+                                  SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base,
+                                                                 overlay),
+                                  mask, val);
+       } else if (mixer->cfg->vi_num == 1) {
+               regmap_update_bits(mixer->engine.regs,
+                                  SUN8I_MIXER_FCC_GLOBAL_ALPHA_REG,
+                                  SUN8I_MIXER_FCC_GLOBAL_ALPHA_MASK,
+                                  SUN8I_MIXER_FCC_GLOBAL_ALPHA
+                                       (plane->state->alpha >> 8));
+       }
+}
+
 static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
                                       int overlay, struct drm_plane *plane,
                                       unsigned int zpos)
@@ -268,14 +298,6 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val);
 
-       /* It seems that YUV formats use global alpha setting. */
-       if (mixer->cfg->is_de3)
-               regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base,
-                                                                 overlay),
-                                  SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK,
-                                  SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(0xff));
-
        return 0;
 }
 
@@ -339,17 +361,20 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
 }
 
 static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
-                                      struct drm_plane_state *state)
+                                      struct drm_atomic_state *state)
 {
+       struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
+                                                                                plane);
        struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
-       struct drm_crtc *crtc = state->crtc;
+       struct drm_crtc *crtc = new_plane_state->crtc;
        struct drm_crtc_state *crtc_state;
        int min_scale, max_scale;
 
        if (!crtc)
                return 0;
 
-       crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+       crtc_state = drm_atomic_get_existing_crtc_state(state,
+                                                       crtc);
        if (WARN_ON(!crtc_state))
                return -EINVAL;
 
@@ -361,14 +386,17 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
                max_scale = SUN8I_VI_SCALER_SCALE_MAX;
        }
 
-       return drm_atomic_helper_check_plane_state(state, crtc_state,
+       return drm_atomic_helper_check_plane_state(new_plane_state,
+                                                  crtc_state,
                                                   min_scale, max_scale,
                                                   true, true);
 }
 
 static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
-                                         struct drm_plane_state *old_state)
+                                         struct drm_atomic_state *state)
 {
+       struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
+                                                                          plane);
        struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
        unsigned int old_zpos = old_state->normalized_zpos;
        struct sun8i_mixer *mixer = layer->mixer;
@@ -378,14 +406,18 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
 }
 
 static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
-                                        struct drm_plane_state *old_state)
+                                        struct drm_atomic_state *state)
 {
+       struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
+                                                                          plane);
+       struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
+                                                                          plane);
        struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
-       unsigned int zpos = plane->state->normalized_zpos;
+       unsigned int zpos = new_state->normalized_zpos;
        unsigned int old_zpos = old_state->normalized_zpos;
        struct sun8i_mixer *mixer = layer->mixer;
 
-       if (!plane->state->visible) {
+       if (!new_state->visible) {
                sun8i_vi_layer_enable(mixer, layer->channel,
                                      layer->overlay, false, 0, old_zpos);
                return;
@@ -393,6 +425,8 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
 
        sun8i_vi_layer_update_coord(mixer, layer->channel,
                                    layer->overlay, plane, zpos);
+       sun8i_vi_layer_update_alpha(mixer, layer->channel,
+                                   layer->overlay, plane);
        sun8i_vi_layer_update_formats(mixer, layer->channel,
                                      layer->overlay, plane);
        sun8i_vi_layer_update_buffer(mixer, layer->channel,
@@ -402,7 +436,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
 }
 
 static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
-       .prepare_fb     = drm_gem_fb_prepare_fb,
+       .prepare_fb     = drm_gem_plane_helper_prepare_fb,
        .atomic_check   = sun8i_vi_layer_atomic_check,
        .atomic_disable = sun8i_vi_layer_atomic_disable,
        .atomic_update  = sun8i_vi_layer_atomic_update,
@@ -534,6 +568,14 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 
        plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
 
+       if (mixer->cfg->vi_num == 1 || mixer->cfg->is_de3) {
+               ret = drm_plane_create_alpha_property(&layer->plane);
+               if (ret) {
+                       dev_err(drm->dev, "Couldn't add alpha property\n");
+                       return ERR_PTR(ret);
+               }
+       }
+
        ret = drm_plane_create_zpos_property(&layer->plane, index,
                                             0, plane_cnt - 1);
        if (ret) {