From 5ab3112a8d806d8676e40ec3bdca84b1738e27e2 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Tue, 3 Sep 2019 15:16:54 -0400 Subject: [PATCH] MLK-22600-1 drm/imx: dpu: kms: Support proper default blend mode Without the new blend modes("None", "Pre-multiplied" and "Coverage") introduced in the below commit, the old userspace assumes alpha in pixel is per-premultiplied by default. So, let's support the default blend mode properly. commit 468dba6432ca ("drm: Add per-plane pixel blend mode property") Signed-off-by: Liu Ying (cherry picked from commit ebb7b4874493a8fb42de636e9421877a54399177) --- drivers/gpu/drm/imx/dpu/dpu-plane.c | 3 ++- drivers/gpu/imx/dpu/dpu-fetchdecode.c | 28 +++++++++++++++++++++++++++ drivers/gpu/imx/dpu/dpu-fetchlayer.c | 1 + drivers/gpu/imx/dpu/dpu-fetchunit.c | 27 ++++++++++++++++++++++++++ drivers/gpu/imx/dpu/dpu-fetchwarp.c | 1 + drivers/gpu/imx/dpu/dpu-layerblend.c | 18 ++++++++--------- drivers/gpu/imx/dpu/dpu-prv.h | 8 ++++++++ include/video/dpu.h | 5 ++++- 8 files changed, 79 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/imx/dpu/dpu-plane.c b/drivers/gpu/drm/imx/dpu/dpu-plane.c index 19d63919f424..e26b8bc65a97 100644 --- a/drivers/gpu/drm/imx/dpu/dpu-plane.c +++ b/drivers/gpu/drm/imx/dpu/dpu-plane.c @@ -664,6 +664,7 @@ again: fu->ops->set_src_stride(fu, src_w, src_x, mt_w, bpp, fb->pitches[0], baseaddr, use_prefetch); fu->ops->set_src_buf_dimensions(fu, src_w, src_h, 0, fb_is_interlaced); + fu->ops->set_pixel_blend_mode(fu, fb->format->format); fu->ops->set_fmt(fu, fb->format->format, fb_is_interlaced); fu->ops->enable_src_buf(fu); fu->ops->set_framedimensions(fu, src_w, src_h, fb_is_interlaced); @@ -808,7 +809,7 @@ again: layerblend_pixengcfg_dynamic_prim_sel(lb, stage); layerblend_pixengcfg_dynamic_sec_sel(lb, source); layerblend_control(lb, LB_BLEND); - layerblend_blendcontrol(lb, need_hscaler || need_vscaler); + layerblend_blendcontrol(lb, state->normalized_zpos); layerblend_pixengcfg_clken(lb, CLKEN__AUTOMATIC); layerblend_position(lb, crtc_x, state->crtc_y); diff --git a/drivers/gpu/imx/dpu/dpu-fetchdecode.c b/drivers/gpu/imx/dpu/dpu-fetchdecode.c index cf385a711038..97685daabb7a 100644 --- a/drivers/gpu/imx/dpu/dpu-fetchdecode.c +++ b/drivers/gpu/imx/dpu/dpu-fetchdecode.c @@ -378,6 +378,33 @@ void fetchdecode_clipoffset(struct dpu_fetchunit *fu, unsigned int x, } EXPORT_SYMBOL_GPL(fetchdecode_clipoffset); +static void +fetchdecode_set_pixel_blend_mode(struct dpu_fetchunit *fu, u32 fb_format) +{ + u32 val, mode = ALPHACONSTENABLE; + + switch (fb_format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + mode |= ALPHASRCENABLE; + break; + } + + mutex_lock(&fu->mutex); + val = dpu_fu_read(fu, LAYERPROPERTY0); + val &= ~(PREMULCONSTRGB | ALPHA_ENABLE_MASK | RGB_ENABLE_MASK); + val |= mode; + dpu_fu_write(fu, val, LAYERPROPERTY0); + + val = dpu_fu_read(fu, CONSTANTCOLOR0); + val &= ~CONSTANTALPHA_MASK; + val |= CONSTANTALPHA(0xff); + dpu_fu_write(fu, val, CONSTANTCOLOR0); + mutex_unlock(&fu->mutex); +} + static void fetchdecode_enable_src_buf(struct dpu_fetchunit *fu) { u32 val; @@ -693,6 +720,7 @@ static const struct dpu_fetchunit_ops fd_ops = { .set_src_stride = fetchdecode_set_src_stride, .set_src_buf_dimensions = fetchdecode_set_src_buf_dimensions, .set_fmt = fetchdecode_set_fmt, + .set_pixel_blend_mode = fetchdecode_set_pixel_blend_mode, .enable_src_buf = fetchdecode_enable_src_buf, .disable_src_buf = fetchdecode_disable_src_buf, .is_enabled = fetchdecode_is_enabled, diff --git a/drivers/gpu/imx/dpu/dpu-fetchlayer.c b/drivers/gpu/imx/dpu/dpu-fetchlayer.c index aedbab16212c..b6e64a7c12ed 100644 --- a/drivers/gpu/imx/dpu/dpu-fetchlayer.c +++ b/drivers/gpu/imx/dpu/dpu-fetchlayer.c @@ -247,6 +247,7 @@ static const struct dpu_fetchunit_ops fl_ops = { .set_src_stride = fetchunit_set_src_stride, .set_src_buf_dimensions = fetchlayer_set_src_buf_dimensions, .set_fmt = fetchlayer_set_fmt, + .set_pixel_blend_mode = fetchunit_set_pixel_blend_mode, .enable_src_buf = fetchunit_enable_src_buf, .disable_src_buf = fetchunit_disable_src_buf, .is_enabled = fetchunit_is_enabled, diff --git a/drivers/gpu/imx/dpu/dpu-fetchunit.c b/drivers/gpu/imx/dpu/dpu-fetchunit.c index cae8ff05e43d..7c5590963133 100644 --- a/drivers/gpu/imx/dpu/dpu-fetchunit.c +++ b/drivers/gpu/imx/dpu/dpu-fetchunit.c @@ -213,6 +213,33 @@ void fetchunit_set_src_stride(struct dpu_fetchunit *fu, } EXPORT_SYMBOL_GPL(fetchunit_set_src_stride); +void fetchunit_set_pixel_blend_mode(struct dpu_fetchunit *fu, u32 fb_format) +{ + u32 val, mode = ALPHACONSTENABLE; + + switch (fb_format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + mode |= ALPHASRCENABLE; + break; + } + + mutex_lock(&fu->mutex); + val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id)); + val &= ~(PREMULCONSTRGB | ALPHA_ENABLE_MASK | RGB_ENABLE_MASK); + val |= mode; + dpu_fu_write(fu, val, LAYERPROPERTY(fu->sub_id)); + + val = dpu_fu_read(fu, CONSTANTCOLOR(fu->sub_id)); + val &= ~CONSTANTALPHA_MASK; + val |= CONSTANTALPHA(0xff); + dpu_fu_write(fu, val, CONSTANTCOLOR(fu->sub_id)); + mutex_unlock(&fu->mutex); +} +EXPORT_SYMBOL_GPL(fetchunit_set_pixel_blend_mode); + void fetchunit_enable_src_buf(struct dpu_fetchunit *fu) { u32 val; diff --git a/drivers/gpu/imx/dpu/dpu-fetchwarp.c b/drivers/gpu/imx/dpu/dpu-fetchwarp.c index fc9eb7047aa6..ff0f318b60da 100644 --- a/drivers/gpu/imx/dpu/dpu-fetchwarp.c +++ b/drivers/gpu/imx/dpu/dpu-fetchwarp.c @@ -247,6 +247,7 @@ static const struct dpu_fetchunit_ops fw_ops = { .set_src_stride = fetchunit_set_src_stride, .set_src_buf_dimensions = fetchwarp_set_src_buf_dimensions, .set_fmt = fetchwarp_set_fmt, + .set_pixel_blend_mode = fetchunit_set_pixel_blend_mode, .enable_src_buf = fetchunit_enable_src_buf, .disable_src_buf = fetchunit_disable_src_buf, .is_enabled = fetchunit_is_enabled, diff --git a/drivers/gpu/imx/dpu/dpu-layerblend.c b/drivers/gpu/imx/dpu/dpu-layerblend.c index e0245998a96b..66d081615cf1 100644 --- a/drivers/gpu/imx/dpu/dpu-layerblend.c +++ b/drivers/gpu/imx/dpu/dpu-layerblend.c @@ -58,12 +58,9 @@ static const lb_prim_sel_t prim_sels[] = { #define BLENDCONTROL 0x10 #define ALPHA(a) (((a) & 0xFF) << 16) #define PRIM_C_BLD_FUNC__ONE_MINUS_SEC_ALPHA 0x5 -#define PRIM_C_BLD_FUNC__PRIM_ALPHA 0x2 +#define PRIM_C_BLD_FUNC__ZERO 0x0 #define SEC_C_BLD_FUNC__CONST_ALPHA (0x6 << 4) -#define SEC_C_BLD_FUNC__ONE_MINUS_PRIM_ALPHA (0x3 << 4) -#define PRIM_A_BLD_FUNC__ONE_MINUS_SEC_ALPHA (0x5 << 8) #define PRIM_A_BLD_FUNC__ZERO (0x0 << 8) -#define SEC_A_BLD_FUNC__ONE (0x1 << 12) #define SEC_A_BLD_FUNC__ZERO (0x0 << 12) #define POSITION 0x14 #define XPOS(x) ((x) & 0x7FFF) @@ -223,16 +220,17 @@ void layerblend_control(struct dpu_layerblend *lb, lb_mode_t mode) } EXPORT_SYMBOL_GPL(layerblend_control); -void layerblend_blendcontrol(struct dpu_layerblend *lb, bool sec_from_scaler) +void layerblend_blendcontrol(struct dpu_layerblend *lb, unsigned int zpos) { u32 val; - val = ALPHA(0xff) | - PRIM_C_BLD_FUNC__PRIM_ALPHA | - SEC_C_BLD_FUNC__ONE_MINUS_PRIM_ALPHA | - PRIM_A_BLD_FUNC__ZERO; + val = ALPHA(0xff) | PRIM_A_BLD_FUNC__ZERO | SEC_A_BLD_FUNC__ZERO | + SEC_C_BLD_FUNC__CONST_ALPHA; - val |= sec_from_scaler ? SEC_A_BLD_FUNC__ZERO : SEC_A_BLD_FUNC__ONE; + if (zpos == 0) + val |= PRIM_C_BLD_FUNC__ZERO; + else + val |= PRIM_C_BLD_FUNC__ONE_MINUS_SEC_ALPHA; mutex_lock(&lb->mutex); dpu_lb_write(lb, val, BLENDCONTROL); diff --git a/drivers/gpu/imx/dpu/dpu-prv.h b/drivers/gpu/imx/dpu/dpu-prv.h index 42cf8a4495dc..3ac6c34e966a 100644 --- a/drivers/gpu/imx/dpu/dpu-prv.h +++ b/drivers/gpu/imx/dpu/dpu-prv.h @@ -73,6 +73,8 @@ enum linemode { #define CLIPWINDOWYOFFSET(y) (((y) & 0x7FFF) << 16) #define CLIPWINDOWWIDTH(w) (((w) - 1) & 0x3FFF) #define CLIPWINDOWHEIGHT(h) ((((h) - 1) & 0x3FFF) << 16) +#define CONSTANTALPHA_MASK 0xFF +#define CONSTANTALPHA(n) ((n) & CONSTANTALPHA_MASK) #define PALETTEENABLE BIT(0) typedef enum { TILE_FILL_ZERO, @@ -84,10 +86,16 @@ typedef enum { #define ALPHACONSTENABLE BIT(9) #define ALPHAMASKENABLE BIT(10) #define ALPHATRANSENABLE BIT(11) +#define ALPHA_ENABLE_MASK (ALPHASRCENABLE | ALPHACONSTENABLE | \ + ALPHAMASKENABLE | ALPHATRANSENABLE) #define RGBALPHASRCENABLE BIT(12) #define RGBALPHACONSTENABLE BIT(13) #define RGBALPHAMASKENABLE BIT(14) #define RGBALPHATRANSENABLE BIT(15) +#define RGB_ENABLE_MASK (RGBALPHASRCENABLE | \ + RGBALPHACONSTENABLE | \ + RGBALPHAMASKENABLE | \ + RGBALPHATRANSENABLE) #define PREMULCONSTRGB BIT(16) typedef enum { YUVCONVERSIONMODE__OFF, diff --git a/include/video/dpu.h b/include/video/dpu.h index a5ad5000dd50..1fc5b2c200dd 100644 --- a/include/video/dpu.h +++ b/include/video/dpu.h @@ -477,6 +477,8 @@ struct dpu_fetchunit_ops { void (*set_fmt)(struct dpu_fetchunit *fu, u32 fmt, bool deinterlace); + void (*set_pixel_blend_mode)(struct dpu_fetchunit *fu, u32 fb_format); + void (*enable_src_buf)(struct dpu_fetchunit *fu); void (*disable_src_buf)(struct dpu_fetchunit *fu); bool (*is_enabled)(struct dpu_fetchunit *fu); @@ -678,7 +680,7 @@ void layerblend_shden(struct dpu_layerblend *lb, bool enable); void layerblend_shdtoksel(struct dpu_layerblend *lb, lb_shadow_sel_t sel); void layerblend_shdldsel(struct dpu_layerblend *lb, lb_shadow_sel_t sel); void layerblend_control(struct dpu_layerblend *lb, lb_mode_t mode); -void layerblend_blendcontrol(struct dpu_layerblend *lb, bool sec_from_scaler); +void layerblend_blendcontrol(struct dpu_layerblend *lb, unsigned int zpos); void layerblend_position(struct dpu_layerblend *lb, int x, int y); struct dpu_layerblend *dpu_lb_get(struct dpu_soc *dpu, int id); void dpu_lb_put(struct dpu_layerblend *lb); @@ -790,6 +792,7 @@ void fetchunit_set_src_stride(struct dpu_fetchunit *fu, unsigned int width, unsigned int x_offset, unsigned int mt_w, int bpp, unsigned int stride, dma_addr_t baddr, bool use_prefetch); +void fetchunit_set_pixel_blend_mode(struct dpu_fetchunit *fu, u32 fb_format); void fetchunit_enable_src_buf(struct dpu_fetchunit *fu); void fetchunit_disable_src_buf(struct dpu_fetchunit *fu); bool fetchunit_is_enabled(struct dpu_fetchunit *fu); -- 2.17.1