diff options
author | Liu Ying <victor.liu@nxp.com> | 2019-09-17 09:44:58 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-11-25 15:58:31 +0800 |
commit | 68e0ff911ab63494bb2cb1a0365c20309c951f8e (patch) | |
tree | 2be43ddeac9fe125cf413515410bf3eda5bd06fa | |
parent | b85579f65349758e6a16a22f5365abd935b7734a (diff) |
drm/imx: dpu: plane: Support multiple pixel blend modes
This patch adds mulitple pixel blend modes for DPU plane.
The modes are "None", "Pre-multiplied" and "Coverage".
Signed-off-by: Liu Ying <victor.liu@nxp.com>
-rw-r--r-- | drivers/gpu/drm/imx/dpu/dpu-plane.c | 23 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-fetchdecode.c | 30 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-fetchunit.c | 30 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-layerblend.c | 38 | ||||
-rw-r--r-- | include/video/dpu.h | 11 |
5 files changed, 93 insertions, 39 deletions
diff --git a/drivers/gpu/drm/imx/dpu/dpu-plane.c b/drivers/gpu/drm/imx/dpu/dpu-plane.c index 016089511ed4..8f2d21fe932e 100644 --- a/drivers/gpu/drm/imx/dpu/dpu-plane.c +++ b/drivers/gpu/drm/imx/dpu/dpu-plane.c @@ -15,6 +15,7 @@ #include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> @@ -84,9 +85,8 @@ static void dpu_plane_reset(struct drm_plane *plane) if (!state) return; - plane->state = &state->base; - plane->state->plane = plane; - plane->state->rotation = DRM_MODE_ROTATE_0; + __drm_atomic_helper_plane_reset(plane, &state->base); + plane->state->zpos = dpu_plane_get_default_zpos(plane->type); } @@ -747,7 +747,8 @@ again: fu->ops->set_src_stride(fu, src_w, src_w, 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_pixel_blend_mode(fu, state->pixel_blend_mode, + state->alpha, 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); @@ -892,7 +893,8 @@ again: layerblend_pixengcfg_dynamic_prim_sel(lb, stage); layerblend_pixengcfg_dynamic_sec_sel(lb, source); layerblend_control(lb, LB_BLEND); - layerblend_blendcontrol(lb, state->normalized_zpos); + layerblend_blendcontrol(lb, state->normalized_zpos, + state->pixel_blend_mode, state->alpha); layerblend_pixengcfg_clken(lb, CLKEN__AUTOMATIC); layerblend_position(lb, crtc_x, state->crtc_y); @@ -964,6 +966,17 @@ struct dpu_plane *dpu_plane_create(struct drm_device *drm, if (ret) goto err; + ret = drm_plane_create_alpha_property(plane); + if (ret) + goto err; + + ret = drm_plane_create_blend_mode_property(plane, + BIT(DRM_MODE_BLEND_PIXEL_NONE) | + BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE)); + if (ret) + goto err; + return dpu_plane; err: diff --git a/drivers/gpu/imx/dpu/dpu-fetchdecode.c b/drivers/gpu/imx/dpu/dpu-fetchdecode.c index b1490ec23cbf..e1582a3a7bd0 100644 --- a/drivers/gpu/imx/dpu/dpu-fetchdecode.c +++ b/drivers/gpu/imx/dpu/dpu-fetchdecode.c @@ -13,6 +13,7 @@ * for more details. */ +#include <drm/drm_blend.h> #include <linux/io.h> #include <linux/module.h> #include <linux/mutex.h> @@ -303,17 +304,24 @@ 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) +fetchdecode_set_pixel_blend_mode(struct dpu_fetchunit *fu, + unsigned int pixel_blend_mode, u16 alpha, + 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; + u32 mode = 0, val; + + if (pixel_blend_mode == DRM_MODE_BLEND_PREMULTI || + pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) { + 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); @@ -324,7 +332,7 @@ fetchdecode_set_pixel_blend_mode(struct dpu_fetchunit *fu, u32 fb_format) val = dpu_fu_read(fu, CONSTANTCOLOR0); val &= ~CONSTANTALPHA_MASK; - val |= CONSTANTALPHA(0xff); + val |= CONSTANTALPHA(alpha >> 8); dpu_fu_write(fu, CONSTANTCOLOR0, val); mutex_unlock(&fu->mutex); } diff --git a/drivers/gpu/imx/dpu/dpu-fetchunit.c b/drivers/gpu/imx/dpu/dpu-fetchunit.c index 89c73b4fc564..343d2ab781a4 100644 --- a/drivers/gpu/imx/dpu/dpu-fetchunit.c +++ b/drivers/gpu/imx/dpu/dpu-fetchunit.c @@ -12,6 +12,7 @@ * for more details. */ +#include <drm/drm_blend.h> #include <video/dpu.h> #include "dpu-prv.h" @@ -212,17 +213,24 @@ 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) +void fetchunit_set_pixel_blend_mode(struct dpu_fetchunit *fu, + unsigned int pixel_blend_mode, u16 alpha, + 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; + u32 mode = 0, val; + + if (pixel_blend_mode == DRM_MODE_BLEND_PREMULTI || + pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) { + 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); @@ -233,7 +241,7 @@ void fetchunit_set_pixel_blend_mode(struct dpu_fetchunit *fu, u32 fb_format) val = dpu_fu_read(fu, CONSTANTCOLOR(fu->sub_id)); val &= ~CONSTANTALPHA_MASK; - val |= CONSTANTALPHA(0xff); + val |= CONSTANTALPHA(alpha >> 8); dpu_fu_write(fu, CONSTANTCOLOR(fu->sub_id), val); mutex_unlock(&fu->mutex); } diff --git a/drivers/gpu/imx/dpu/dpu-layerblend.c b/drivers/gpu/imx/dpu/dpu-layerblend.c index c1dae9a868ce..c19fcbdb169b 100644 --- a/drivers/gpu/imx/dpu/dpu-layerblend.c +++ b/drivers/gpu/imx/dpu/dpu-layerblend.c @@ -13,6 +13,7 @@ * for more details. */ +#include <drm/drm_blend.h> #include <linux/io.h> #include <linux/mutex.h> #include <linux/platform_device.h> @@ -53,9 +54,11 @@ static const lb_prim_sel_t prim_sels[] = { #define OPERATION_MODE_MASK BIT(0) #define BLENDCONTROL 0x10 #define ALPHA(a) (((a) & 0xFF) << 16) +#define PRIM_C_BLD_FUNC__ONE_MINUS_CONST_ALPHA 0x7 #define PRIM_C_BLD_FUNC__ONE_MINUS_SEC_ALPHA 0x5 #define PRIM_C_BLD_FUNC__ZERO 0x0 #define SEC_C_BLD_FUNC__CONST_ALPHA (0x6 << 4) +#define SEC_C_BLD_FUNC__SEC_ALPHA (0x4 << 4) #define PRIM_A_BLD_FUNC__ZERO (0x0 << 8) #define SEC_A_BLD_FUNC__ZERO (0x0 << 12) #define POSITION 0x14 @@ -205,17 +208,34 @@ void layerblend_control(struct dpu_layerblend *lb, lb_mode_t mode) } EXPORT_SYMBOL_GPL(layerblend_control); -void layerblend_blendcontrol(struct dpu_layerblend *lb, unsigned int zpos) +void layerblend_blendcontrol(struct dpu_layerblend *lb, unsigned int zpos, + unsigned int pixel_blend_mode, u16 alpha) { - u32 val; - - val = ALPHA(0xff) | PRIM_A_BLD_FUNC__ZERO | SEC_A_BLD_FUNC__ZERO | - SEC_C_BLD_FUNC__CONST_ALPHA; + u32 val = PRIM_A_BLD_FUNC__ZERO | SEC_A_BLD_FUNC__ZERO; + + if (zpos == 0) { + val |= PRIM_C_BLD_FUNC__ZERO | SEC_C_BLD_FUNC__CONST_ALPHA; + alpha = DRM_BLEND_ALPHA_OPAQUE; + } else { + switch (pixel_blend_mode) { + case DRM_MODE_BLEND_PIXEL_NONE: + val |= PRIM_C_BLD_FUNC__ONE_MINUS_CONST_ALPHA | + SEC_C_BLD_FUNC__CONST_ALPHA; + break; + case DRM_MODE_BLEND_PREMULTI: + val |= PRIM_C_BLD_FUNC__ONE_MINUS_SEC_ALPHA | + SEC_C_BLD_FUNC__CONST_ALPHA; + break; + case DRM_MODE_BLEND_COVERAGE: + val |= PRIM_C_BLD_FUNC__ONE_MINUS_SEC_ALPHA | + SEC_C_BLD_FUNC__SEC_ALPHA; + break; + default: + break; + } + } - if (zpos == 0) - val |= PRIM_C_BLD_FUNC__ZERO; - else - val |= PRIM_C_BLD_FUNC__ONE_MINUS_SEC_ALPHA; + val |= ALPHA(alpha >> 8); mutex_lock(&lb->mutex); dpu_lb_write(lb, BLENDCONTROL, val); diff --git a/include/video/dpu.h b/include/video/dpu.h index 45eac1bab0ff..745676efe21a 100644 --- a/include/video/dpu.h +++ b/include/video/dpu.h @@ -350,7 +350,9 @@ 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 (*set_pixel_blend_mode)(struct dpu_fetchunit *fu, + unsigned int pixel_blend_mode, u16 alpha, + u32 fb_format); void (*enable_src_buf)(struct dpu_fetchunit *fu); void (*disable_src_buf)(struct dpu_fetchunit *fu); @@ -548,7 +550,8 @@ 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, unsigned int zpos); +void layerblend_blendcontrol(struct dpu_layerblend *lb, unsigned int zpos, + unsigned int pixel_blend_mode, u16 alpha); 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); @@ -633,7 +636,9 @@ 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_set_pixel_blend_mode(struct dpu_fetchunit *fu, + unsigned int pixel_blend_mode, u16 alpha, + 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); |