Commit 187f7f21 authored by Lowry Li's avatar Lowry Li Committed by Liviu Dudau

drm/mali-dp: Implement plane alpha and pixel blend on malidp

Checks the pixel blending mode and plane alpha value when
do the plane_check. Mali DP supports blending the current plane
with the background either based on the pixel alpha blending
mode or by using the layer's alpha value, but not both at the
same time. If both case, plane_check will return failed.

Sets the HW when doing plane_update accordingly. If plane alpha
is the 0xffff, set the pixel blending bits accordingly. If not
we'd set ALPHA bit as zero and layer alpha value.

Changes since v1:
 - Introduces to use it in the malidp driver, which depends on
   the plane alpha patch
Changes since v2:
 - Refines the comments of drm/mali-dp patchset
Changes since v3:
 - Adds hardware limitation check
Changes since v4:
 - Updates on drm/malidp, hardware limitation check only when
   the format has alpha pixel.
 - Rebases on drm-misc-next.
Signed-off-by: default avatarLowry Li <lowry.li@arm.com>
Acked-by: default avatarLiviu Dudau <liviu.dudau@arm.com>
Signed-off-by: default avatarLiviu Dudau <liviu.dudau@arm.com>
parent 791d54fa
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#define LAYER_COMP_MASK (0x3 << 12) #define LAYER_COMP_MASK (0x3 << 12)
#define LAYER_COMP_PIXEL (0x3 << 12) #define LAYER_COMP_PIXEL (0x3 << 12)
#define LAYER_COMP_PLANE (0x2 << 12) #define LAYER_COMP_PLANE (0x2 << 12)
#define LAYER_PMUL_ENABLE (0x1 << 14)
#define LAYER_ALPHA_OFFSET (16) #define LAYER_ALPHA_OFFSET (16)
#define LAYER_ALPHA_MASK (0xff) #define LAYER_ALPHA_MASK (0xff)
#define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
...@@ -180,6 +181,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, ...@@ -180,6 +181,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
struct malidp_plane_state *ms = to_malidp_plane_state(state); struct malidp_plane_state *ms = to_malidp_plane_state(state);
bool rotated = state->rotation & MALIDP_ROTATED_MASK; bool rotated = state->rotation & MALIDP_ROTATED_MASK;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
u16 pixel_alpha = state->pixel_blend_mode;
int i, ret; int i, ret;
if (!state->crtc || !state->fb) if (!state->crtc || !state->fb)
...@@ -242,6 +244,12 @@ static int malidp_de_plane_check(struct drm_plane *plane, ...@@ -242,6 +244,12 @@ static int malidp_de_plane_check(struct drm_plane *plane,
ms->rotmem_size = val; ms->rotmem_size = val;
} }
/* HW can't support plane + pixel blending */
if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
(pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) &&
fb->format->has_alpha)
return -EINVAL;
return 0; return 0;
} }
...@@ -323,17 +331,19 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -323,17 +331,19 @@ static void malidp_de_plane_update(struct drm_plane *plane,
{ {
struct malidp_plane *mp; struct malidp_plane *mp;
struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
struct drm_plane_state *state = plane->state;
u16 pixel_alpha = state->pixel_blend_mode;
u8 plane_alpha = state->alpha >> 8;
u32 src_w, src_h, dest_w, dest_h, val; u32 src_w, src_h, dest_w, dest_h, val;
int i; int i;
bool format_has_alpha = plane->state->fb->format->has_alpha;
mp = to_malidp_plane(plane); mp = to_malidp_plane(plane);
/* convert src values from Q16 fixed point to integer */ /* convert src values from Q16 fixed point to integer */
src_w = plane->state->src_w >> 16; src_w = state->src_w >> 16;
src_h = plane->state->src_h >> 16; src_h = state->src_h >> 16;
dest_w = plane->state->crtc_w; dest_w = state->crtc_w;
dest_h = plane->state->crtc_h; dest_h = state->crtc_h;
val = malidp_hw_read(mp->hwdev, mp->layer->base); val = malidp_hw_read(mp->hwdev, mp->layer->base);
val = (val & ~LAYER_FORMAT_MASK) | ms->format; val = (val & ~LAYER_FORMAT_MASK) | ms->format;
...@@ -342,14 +352,14 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -342,14 +352,14 @@ static void malidp_de_plane_update(struct drm_plane *plane,
for (i = 0; i < ms->n_planes; i++) { for (i = 0; i < ms->n_planes; i++) {
/* calculate the offset for the layer's plane registers */ /* calculate the offset for the layer's plane registers */
u16 ptr = mp->layer->ptr + (i << 4); u16 ptr = mp->layer->ptr + (i << 4);
dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
plane->state, i); state, i);
malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
} }
malidp_de_set_plane_pitches(mp, ms->n_planes, malidp_de_set_plane_pitches(mp, ms->n_planes,
plane->state->fb->pitches); state->fb->pitches);
if ((plane->state->color_encoding != old_state->color_encoding) || if ((plane->state->color_encoding != old_state->color_encoding) ||
(plane->state->color_range != old_state->color_range)) (plane->state->color_range != old_state->color_range))
...@@ -362,8 +372,8 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -362,8 +372,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
mp->layer->base + MALIDP_LAYER_COMP_SIZE); mp->layer->base + MALIDP_LAYER_COMP_SIZE);
malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
LAYER_V_VAL(plane->state->crtc_y), LAYER_V_VAL(state->crtc_y),
mp->layer->base + MALIDP_LAYER_OFFSET); mp->layer->base + MALIDP_LAYER_OFFSET);
if (mp->layer->id == DE_SMART) { if (mp->layer->id == DE_SMART) {
...@@ -383,38 +393,35 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -383,38 +393,35 @@ static void malidp_de_plane_update(struct drm_plane *plane,
val &= ~LAYER_ROT_MASK; val &= ~LAYER_ROT_MASK;
/* setup the rotation and axis flip bits */ /* setup the rotation and axis flip bits */
if (plane->state->rotation & DRM_MODE_ROTATE_MASK) if (state->rotation & DRM_MODE_ROTATE_MASK)
val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
LAYER_ROT_OFFSET; LAYER_ROT_OFFSET;
if (plane->state->rotation & DRM_MODE_REFLECT_X) if (state->rotation & DRM_MODE_REFLECT_X)
val |= LAYER_H_FLIP; val |= LAYER_H_FLIP;
if (plane->state->rotation & DRM_MODE_REFLECT_Y) if (state->rotation & DRM_MODE_REFLECT_Y)
val |= LAYER_V_FLIP; val |= LAYER_V_FLIP;
val &= ~LAYER_COMP_MASK; val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff));
if (format_has_alpha) {
/*
* always enable pixel alpha blending until we have a way
* to change blend modes
*/
val |= LAYER_COMP_PIXEL;
} else {
/* if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
* do not enable pixel alpha blending as the color channel
* does not have any alpha information
*/
val |= LAYER_COMP_PLANE; val |= LAYER_COMP_PLANE;
} else if (state->fb->format->has_alpha) {
/* Set layer alpha coefficient to 0xff ie fully opaque */ /* We only care about blend mode if the format has alpha */
val |= LAYER_ALPHA(0xff); switch (pixel_alpha) {
case DRM_MODE_BLEND_PREMULTI:
val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
break;
case DRM_MODE_BLEND_COVERAGE:
val |= LAYER_COMP_PIXEL;
break;
}
} }
val |= LAYER_ALPHA(plane_alpha);
val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
if (plane->state->crtc) { if (state->crtc) {
struct malidp_crtc_state *m = struct malidp_crtc_state *m =
to_malidp_crtc_state(plane->state->crtc->state); to_malidp_crtc_state(state->crtc->state);
if (m->scaler_config.scale_enable && if (m->scaler_config.scale_enable &&
m->scaler_config.plane_src_id == mp->layer->id) m->scaler_config.plane_src_id == mp->layer->id)
...@@ -453,6 +460,9 @@ int malidp_de_planes_init(struct drm_device *drm) ...@@ -453,6 +460,9 @@ int malidp_de_planes_init(struct drm_device *drm)
unsigned long crtcs = 1 << drm->mode_config.num_crtc; unsigned long crtcs = 1 << drm->mode_config.num_crtc;
unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE);
u32 *formats; u32 *formats;
int ret, i, j, n; int ret, i, j, n;
...@@ -490,6 +500,9 @@ int malidp_de_planes_init(struct drm_device *drm) ...@@ -490,6 +500,9 @@ int malidp_de_planes_init(struct drm_device *drm)
plane->hwdev = malidp->dev; plane->hwdev = malidp->dev;
plane->layer = &map->layers[i]; plane->layer = &map->layers[i];
drm_plane_create_alpha_property(&plane->base);
drm_plane_create_blend_mode_property(&plane->base, blend_caps);
if (id == DE_SMART) { if (id == DE_SMART) {
/* Skip the features which the SMART layer doesn't have. */ /* Skip the features which the SMART layer doesn't have. */
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment