summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2019-09-17 09:44:58 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:58:31 +0800
commit68e0ff911ab63494bb2cb1a0365c20309c951f8e (patch)
tree2be43ddeac9fe125cf413515410bf3eda5bd06fa
parentb85579f65349758e6a16a22f5365abd935b7734a (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.c23
-rw-r--r--drivers/gpu/imx/dpu/dpu-fetchdecode.c30
-rw-r--r--drivers/gpu/imx/dpu/dpu-fetchunit.c30
-rw-r--r--drivers/gpu/imx/dpu/dpu-layerblend.c38
-rw-r--r--include/video/dpu.h11
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);