aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
diff options
context:
space:
mode:
authorChristoph Manszewski <c.manszewski@samsung.com>2018-10-25 18:21:53 +0200
committerInki Dae <inki.dae@samsung.com>2018-12-05 17:26:16 +0900
commitaf130280c613218a37675c6442650ca809f274c2 (patch)
tree6f113962aa4ae2ab4b8482916b9a31fd7c864ccf /drivers/gpu/drm/exynos/exynos5433_drm_decon.c
parentdrm/exynos: decon: Make plane alpha configurable (diff)
downloadlinux-dev-af130280c613218a37675c6442650ca809f274c2.tar.xz
linux-dev-af130280c613218a37675c6442650ca809f274c2.zip
drm/exynos: decon: Make pixel blend mode configurable
The decon hardware supports different blend modes. Add pixel blend mode property and make it configurable, by modifying the blend equation. Tested on TM2 with Exynos 5433 CPU, on top of linux-next-20181019. Signed-off-by: Christoph Manszewski <c.manszewski@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos5433_drm_decon.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 83a578c0dfa8..5b4e0e8b23bc 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -85,10 +85,10 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
static const unsigned int capabilities[WINDOWS_NR] = {
0,
- EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
- EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
- EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
- EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
};
static inline void decon_set_bits(struct decon_context *ctx, u32 reg, u32 mask,
@@ -259,13 +259,51 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
}
+static void decon_win_set_bldeq(struct decon_context *ctx, unsigned int win,
+ unsigned int alpha, unsigned int pixel_alpha)
+{
+ u32 mask = BLENDERQ_A_FUNC_F(0xf) | BLENDERQ_B_FUNC_F(0xf);
+ u32 val = 0;
+
+ switch (pixel_alpha) {
+ case DRM_MODE_BLEND_PIXEL_NONE:
+ case DRM_MODE_BLEND_COVERAGE:
+ val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA_A);
+ val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+ break;
+ case DRM_MODE_BLEND_PREMULTI:
+ default:
+ if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
+ val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA0);
+ val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+ } else {
+ val |= BLENDERQ_A_FUNC_F(BLENDERQ_ONE);
+ val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+ }
+ break;
+ }
+ decon_set_bits(ctx, DECON_BLENDERQx(win), mask, val);
+}
static void decon_win_set_bldmod(struct decon_context *ctx, unsigned int win,
- unsigned int alpha)
+ unsigned int alpha, unsigned int pixel_alpha)
{
u32 win_alpha = alpha >> 8;
u32 val = 0;
+ switch (pixel_alpha) {
+ case DRM_MODE_BLEND_PIXEL_NONE:
+ break;
+ case DRM_MODE_BLEND_COVERAGE:
+ case DRM_MODE_BLEND_PREMULTI:
+ default:
+ val |= WINCONx_ALPHA_SEL_F;
+ val |= WINCONx_BLD_PIX_F;
+ val |= WINCONx_ALPHA_MUL_F;
+ break;
+ }
+ decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_BLEND_MODE_MASK, val);
+
if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
val = VIDOSD_Wx_ALPHA_R_F(win_alpha) |
VIDOSD_Wx_ALPHA_G_F(win_alpha) |
@@ -283,8 +321,14 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
struct exynos_drm_plane_state *state =
to_exynos_plane_state(plane.base.state);
unsigned int alpha = state->base.alpha;
+ unsigned int pixel_alpha;
unsigned long val;
+ if (fb->format->has_alpha)
+ pixel_alpha = state->base.pixel_blend_mode;
+ else
+ pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
+
val = readl(ctx->addr + DECON_WINCONx(win));
val &= WINCONx_ENWIN_F;
@@ -307,9 +351,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
case DRM_FORMAT_ARGB8888:
default:
val |= WINCONx_BPPMODE_32BPP_A8888;
- val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F;
+ val |= WINCONx_WSWP_F;
val |= WINCONx_BURSTLEN_16WORD;
- val |= WINCONx_ALPHA_MUL_F;
break;
}
@@ -327,10 +370,12 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
val &= ~WINCONx_BURSTLEN_MASK;
val |= WINCONx_BURSTLEN_8WORD;
}
+ decon_set_bits(ctx, DECON_WINCONx(win), ~WINCONx_BLEND_MODE_MASK, val);
- writel(val, ctx->addr + DECON_WINCONx(win));
- if (win > 0)
- decon_win_set_bldmod(ctx, win, alpha);
+ if (win > 0) {
+ decon_win_set_bldmod(ctx, win, alpha, pixel_alpha);
+ decon_win_set_bldeq(ctx, win, alpha, pixel_alpha);
+ }
}
static void decon_shadow_protect(struct decon_context *ctx, bool protect)