MLK-22600-5 drm/imx: dpu: plane: Support multiple pixel blend modes
authorLiu Ying <victor.liu@nxp.com>
Tue, 17 Sep 2019 01:44:58 +0000 (09:44 +0800)
committerLiu Ying <victor.liu@nxp.com>
Fri, 20 Sep 2019 02:01:35 +0000 (10:01 +0800)
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>
(cherry picked from commit 1259fedbcf2a54f58b47e8531a09b35cc60a43f7)

drivers/gpu/drm/imx/dpu/dpu-plane.c
drivers/gpu/imx/dpu/dpu-fetchdecode.c
drivers/gpu/imx/dpu/dpu-fetchunit.c
drivers/gpu/imx/dpu/dpu-layerblend.c
include/video/dpu.h

index 0292f25..18e97f1 100644 (file)
@@ -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_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
@@ -81,9 +82,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);
 }
 
@@ -655,7 +655,8 @@ 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_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);
@@ -800,7 +801,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);
 
@@ -873,6 +875,17 @@ struct dpu_plane *dpu_plane_init(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:
index 97685da..84b9f69 100644 (file)
@@ -13,6 +13,7 @@
  * for more details.
  */
 
+#include <drm/drm_blend.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -379,17 +380,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);
@@ -400,7 +408,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, val, CONSTANTCOLOR0);
        mutex_unlock(&fu->mutex);
 }
index 7c55909..4f939f3 100644 (file)
@@ -12,6 +12,7 @@
  * for more details.
  */
 
+#include <drm/drm_blend.h>
 #include <video/dpu.h>
 #include "dpu-prv.h"
 
@@ -213,17 +214,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);
@@ -234,7 +242,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, val, CONSTANTCOLOR(fu->sub_id));
        mutex_unlock(&fu->mutex);
 }
index 66d0816..a7018ae 100644 (file)
@@ -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>
@@ -57,9 +58,11 @@ static const lb_prim_sel_t prim_sels[] = {
 #define 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
@@ -220,17 +223,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, val, BLENDCONTROL);
index 1fc5b2c..a1bd1f2 100644 (file)
@@ -477,7 +477,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);
@@ -680,7 +682,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);
@@ -792,7 +795,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);