@@ -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;
}
@@ -393,6 +415,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,
@@ -534,6 +558,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) {
@@ -29,14 +29,25 @@
#define SUN8I_MIXER_CHAN_VI_VDS_UV(base) \
((base) + 0xfc)
+#define SUN8I_MIXER_FCC_GLOBAL_ALPHA_REG \
+ (0xAA000 + 0x90)
+
+#define SUN8I_MIXER_FCC_GLOBAL_ALPHA(x) ((x) << 24)
+#define SUN8I_MIXER_FCC_GLOBAL_ALPHA_MASK GENMASK(31, 24)
+
#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN BIT(0)
/* RGB mode should be set for RGB formats and cleared for YCbCr */
#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE BIT(15)
#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET 8
#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK GENMASK(12, 8)
+#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK GENMASK(2, 1)
#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK GENMASK(31, 24)
#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(x) ((x) << 24)
+#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_PIXEL ((0) << 1)
+#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_LAYER ((1) << 1)
+#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_COMBINED ((2) << 1)
+
#define SUN8I_MIXER_CHAN_VI_DS_N(x) ((x) << 16)
#define SUN8I_MIXER_CHAN_VI_DS_M(x) ((x) << 0)