Currently blend mode is set accordingly to pixel format.
Add pixel blend mode property and make it configurable,
by modifying the blend equation.
Tested on TM2 with Exynos 5433 CPU, on top of exynos-drm-next,
commit: c530174b90fa
Signed-off-by: Christoph Manszewski <[email protected]>
---
After further studying the documentation, it turned out that decon
supports premultiplied pixel blend mode by using blend equation,
make use of this.
v2 changes:
- add premultiplied mode by setting blending equation accordingly,
- remove no longer used blend mode settings from decon_win_set_pixfmt,
drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 64 +++++++++++++++++++++++----
drivers/gpu/drm/exynos/regs-decon5433.h | 15 +++++++
2 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 2578db16750d..bc1339d63aed 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -86,10 +86,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,
@@ -267,13 +267,53 @@ 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:
+ break;
+ case DRM_MODE_BLEND_COVERAGE:
+ val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA_A);
+ val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+ decon_set_bits(ctx, DECON_BLENDERQx(win), mask, val);
+ 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);
+ }
+ decon_set_bits(ctx, DECON_BLENDERQx(win), mask, val);
+ break;
+ }
+}
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) |
@@ -293,6 +333,11 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
unsigned int alpha = state->base.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;
@@ -315,9 +360,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;
}
@@ -335,10 +379,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)
+ if (win > 0) {
decon_win_set_bldmod(ctx, win, alpha);
+ decon_win_set_bldeq(ctx, win, alpha, pixel_alpha);
+ }
}
static void decon_shadow_protect(struct decon_context *ctx, bool protect)
diff --git a/drivers/gpu/drm/exynos/regs-decon5433.h b/drivers/gpu/drm/exynos/regs-decon5433.h
index 72648bda3142..63db6974bf14 100644
--- a/drivers/gpu/drm/exynos/regs-decon5433.h
+++ b/drivers/gpu/drm/exynos/regs-decon5433.h
@@ -117,6 +117,7 @@
#define WINCONx_BPPMODE_16BPP_A4444 (0xe << 2)
#define WINCONx_ALPHA_SEL_F (1 << 1)
#define WINCONx_ENWIN_F (1 << 0)
+#define WINCONx_BLEND_MODE_MASK (0xc2)
/* SHADOWCON */
#define SHADOWCON_PROTECT_MASK GENMASK(14, 10)
@@ -213,4 +214,18 @@
/* BLENDCON */
#define BLEND_NEW (1 << 0)
+/* BLENDERQx */
+#define BLENDERQ_ZERO 0x0
+#define BLENDERQ_ONE 0x1
+#define BLENDERQ_ALPHA_A 0x2
+#define BLENDERQ_ONE_MINUS_ALPHA_A 0x3
+#define BLENDERQ_ALPHA0 0x6
+#define BLENDERQ_Q_FUNC_F(n) (n << 18)
+#define BLENDERQ_P_FUNC_F(n) (n << 12)
+#define BLENDERQ_B_FUNC_F(n) (n << 6)
+#define BLENDERQ_A_FUNC_F(n) (n << 0)
+
+/* BLENDCON */
+#define BLEND_NEW (1 << 0)
+
#endif /* EXYNOS_REGS_DECON5433_H */
--
2.7.4
Hi Christoph,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on drm-exynos/exynos-drm-next]
[also build test ERROR on v4.19-rc8 next-20181019]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Christoph-Manszewski/drm-exynos-decon-Make-plane-alpha-configurable/20181019-053544
base: https://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git exynos-drm-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=arm64
All errors (new ones prefixed by >>):
drivers/gpu/drm/exynos/exynos5433_drm_decon.c: In function 'decon_win_set_pixfmt':
>> drivers/gpu/drm/exynos/exynos5433_drm_decon.c:337:3: error: 'pixel_alpha' undeclared (first use in this function); did you mean 'isalpha'?
pixel_alpha = state->base.pixel_blend_mode;
^~~~~~~~~~~
isalpha
drivers/gpu/drm/exynos/exynos5433_drm_decon.c:337:3: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/gpu/drm/exynos/exynos5433_drm_decon.c:385:3: error: too few arguments to function 'decon_win_set_bldmod'
decon_win_set_bldmod(ctx, win, alpha);
^~~~~~~~~~~~~~~~~~~~
drivers/gpu/drm/exynos/exynos5433_drm_decon.c:298:13: note: declared here
static void decon_win_set_bldmod(struct decon_context *ctx, unsigned int win,
^~~~~~~~~~~~~~~~~~~~
vim +337 drivers/gpu/drm/exynos/exynos5433_drm_decon.c
326
327 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
328 struct drm_framebuffer *fb)
329 {
330 struct exynos_drm_plane plane = ctx->planes[win];
331 struct exynos_drm_plane_state *state =
332 to_exynos_plane_state(plane.base.state);
333 unsigned int alpha = state->base.alpha;
334 unsigned long val;
335
336 if (fb->format->has_alpha)
> 337 pixel_alpha = state->base.pixel_blend_mode;
338 else
339 pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
340
341 val = readl(ctx->addr + DECON_WINCONx(win));
342 val &= WINCONx_ENWIN_F;
343
344 switch (fb->format->format) {
345 case DRM_FORMAT_XRGB1555:
346 val |= WINCONx_BPPMODE_16BPP_I1555;
347 val |= WINCONx_HAWSWP_F;
348 val |= WINCONx_BURSTLEN_16WORD;
349 break;
350 case DRM_FORMAT_RGB565:
351 val |= WINCONx_BPPMODE_16BPP_565;
352 val |= WINCONx_HAWSWP_F;
353 val |= WINCONx_BURSTLEN_16WORD;
354 break;
355 case DRM_FORMAT_XRGB8888:
356 val |= WINCONx_BPPMODE_24BPP_888;
357 val |= WINCONx_WSWP_F;
358 val |= WINCONx_BURSTLEN_16WORD;
359 break;
360 case DRM_FORMAT_ARGB8888:
361 default:
362 val |= WINCONx_BPPMODE_32BPP_A8888;
363 val |= WINCONx_WSWP_F;
364 val |= WINCONx_BURSTLEN_16WORD;
365 break;
366 }
367
368 DRM_DEBUG_KMS("cpp = %u\n", fb->format->cpp[0]);
369
370 /*
371 * In case of exynos, setting dma-burst to 16Word causes permanent
372 * tearing for very small buffers, e.g. cursor buffer. Burst Mode
373 * switching which is based on plane size is not recommended as
374 * plane size varies a lot towards the end of the screen and rapid
375 * movement causes unstable DMA which results into iommu crash/tear.
376 */
377
378 if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
379 val &= ~WINCONx_BURSTLEN_MASK;
380 val |= WINCONx_BURSTLEN_8WORD;
381 }
382 decon_set_bits(ctx, DECON_WINCONx(win), ~WINCONx_BLEND_MODE_MASK, val);
383
384 if (win > 0) {
> 385 decon_win_set_bldmod(ctx, win, alpha);
386 decon_win_set_bldeq(ctx, win, alpha, pixel_alpha);
387 }
388 }
389
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation