diff mbox

[v2,2/2] drm/mali-dp: Implement plane alpha and pixel blend on malidp

Message ID 1527679434-13228-3-git-send-email-lowry.li@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lowry Li (Arm Technology China) May 30, 2018, 11:23 a.m. UTC
Check the pixel blending mode and plane alpha value when
do the plane_check. Mali DP supports blending the current plane
with the background either based on the pixel alpha blending
mode or by using the layer's alpha value, but not both at the
same time. If both case, plane_check will return failed.

Set the HW when doing plane_update accordingly. If plane alpha
is the 0xffff, set the PREM bit accordingly. If not we'd set
ALPHA bit as zero and layer alpha value.

Signed-off-by: Lowry Li <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/malidp_planes.c | 76 +++++++++++++++++++++----------------
 1 file changed, 44 insertions(+), 32 deletions(-)

Comments

Brian Starkey May 30, 2018, 1:34 p.m. UTC | #1
Hi Lowry,

On Wed, May 30, 2018 at 07:23:54PM +0800, Lowry Li wrote:
>Check the pixel blending mode and plane alpha value when
>do the plane_check. Mali DP supports blending the current plane
>with the background either based on the pixel alpha blending
>mode or by using the layer's alpha value, but not both at the
>same time. If both case, plane_check will return failed.
>
>Set the HW when doing plane_update accordingly. If plane alpha
>is the 0xffff, set the PREM bit accordingly. If not we'd set
>ALPHA bit as zero and layer alpha value.

The code looks correct - but the description of the PREM bit seems
wrong here. Did you mean "set the pixel blending bits accordingly"?

With that fixed:

Reviewed-by: Brian Starkey <brian.starkey@arm.com>

>
>Signed-off-by: Lowry Li <lowry.li@arm.com>
>---
> drivers/gpu/drm/arm/malidp_planes.c | 76 +++++++++++++++++++++----------------
> 1 file changed, 44 insertions(+), 32 deletions(-)
>
>diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
>index 7a44897..daa3f4f 100644
>--- a/drivers/gpu/drm/arm/malidp_planes.c
>+++ b/drivers/gpu/drm/arm/malidp_planes.c
>@@ -35,6 +35,7 @@
> #define   LAYER_COMP_MASK		(0x3 << 12)
> #define   LAYER_COMP_PIXEL		(0x3 << 12)
> #define   LAYER_COMP_PLANE		(0x2 << 12)
>+#define   LAYER_PMUL_ENABLE		(0x1 << 14)
> #define   LAYER_ALPHA_OFFSET		(16)
> #define   LAYER_ALPHA_MASK		(0xff)
> #define   LAYER_ALPHA(x)		(((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
>@@ -182,6 +183,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> 	struct malidp_plane_state *ms = to_malidp_plane_state(state);
> 	bool rotated = state->rotation & MALIDP_ROTATED_MASK;
> 	struct drm_framebuffer *fb;
>+	u16 pixel_alpha = state->pixel_blend_mode;
> 	int i, ret;
>
> 	if (!state->crtc || !state->fb)
>@@ -244,6 +246,11 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> 		ms->rotmem_size = val;
> 	}
>
>+	/* HW can't support plane + pixel blending */
>+	if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
>+	    (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE))
>+		return -EINVAL;
>+
> 	return 0;
> }
>
>@@ -325,31 +332,33 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> {
> 	struct malidp_plane *mp;
> 	struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
>+	struct drm_plane_state *state = plane->state;
>+	u16 pixel_alpha = state->pixel_blend_mode;
>+	u8 plane_alpha = state->alpha >> 8;
> 	u32 src_w, src_h, dest_w, dest_h, val;
> 	int i;
>-	bool format_has_alpha = plane->state->fb->format->has_alpha;
>
> 	mp = to_malidp_plane(plane);
>
> 	/* convert src values from Q16 fixed point to integer */
>-	src_w = plane->state->src_w >> 16;
>-	src_h = plane->state->src_h >> 16;
>-	dest_w = plane->state->crtc_w;
>-	dest_h = plane->state->crtc_h;
>+	src_w = state->src_w >> 16;
>+	src_h = state->src_h >> 16;
>+	dest_w = state->crtc_w;
>+	dest_h = state->crtc_h;
>
> 	malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
>
> 	for (i = 0; i < ms->n_planes; i++) {
> 		/* calculate the offset for the layer's plane registers */
> 		u16 ptr = mp->layer->ptr + (i << 4);
>-		dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb,
>-							     plane->state, i);
>+		dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
>+							     state, i);
>
> 		malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
> 		malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
> 	}
> 	malidp_de_set_plane_pitches(mp, ms->n_planes,
>-				    plane->state->fb->pitches);
>+				    state->fb->pitches);
>
> 	if ((plane->state->color_encoding != old_state->color_encoding) ||
> 	    (plane->state->color_range != old_state->color_range))
>@@ -362,8 +371,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> 	malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
> 			mp->layer->base + MALIDP_LAYER_COMP_SIZE);
>
>-	malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) |
>-			LAYER_V_VAL(plane->state->crtc_y),
>+	malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
>+			LAYER_V_VAL(state->crtc_y),
> 			mp->layer->base + MALIDP_LAYER_OFFSET);
>
> 	if (mp->layer->id == DE_SMART)
>@@ -376,38 +385,35 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> 	val &= ~LAYER_ROT_MASK;
>
> 	/* setup the rotation and axis flip bits */
>-	if (plane->state->rotation & DRM_MODE_ROTATE_MASK)
>+	if (state->rotation & DRM_MODE_ROTATE_MASK)
> 		val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
> 		       LAYER_ROT_OFFSET;
>-	if (plane->state->rotation & DRM_MODE_REFLECT_X)
>+	if (state->rotation & DRM_MODE_REFLECT_X)
> 		val |= LAYER_H_FLIP;
>-	if (plane->state->rotation & DRM_MODE_REFLECT_Y)
>+	if (state->rotation & DRM_MODE_REFLECT_Y)
> 		val |= LAYER_V_FLIP;
>
>-	val &= ~LAYER_COMP_MASK;
>-	if (format_has_alpha) {
>-
>-		/*
>-		 * always enable pixel alpha blending until we have a way
>-		 * to change blend modes
>-		 */
>-		val |= LAYER_COMP_PIXEL;
>-	} else {
>-
>-		/*
>-		 * do not enable pixel alpha blending as the color channel
>-		 * does not have any alpha information
>-		 */
>-		val |= LAYER_COMP_PLANE;
>-
>-		/* Set layer alpha coefficient to 0xff ie fully opaque */
>+	val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE);
>+
>+	if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
>+		val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha);
>+	} else if (state->fb->format->has_alpha) {
>+		/* We only care about blend mode if the format has alpha */
>+		switch (pixel_alpha) {
>+		case DRM_MODE_BLEND_PREMULTI:
>+			val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
>+			break;
>+		case DRM_MODE_BLEND_COVERAGE:
>+			val |= LAYER_COMP_PIXEL;
>+			break;
>+		}
> 		val |= LAYER_ALPHA(0xff);
> 	}
>
> 	val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
>-	if (plane->state->crtc) {
>+	if (state->crtc) {
> 		struct malidp_crtc_state *m =
>-			to_malidp_crtc_state(plane->state->crtc->state);
>+			to_malidp_crtc_state(state->crtc->state);
>
> 		if (m->scaler_config.scale_enable &&
> 		    m->scaler_config.plane_src_id == mp->layer->id)
>@@ -446,6 +452,9 @@ int malidp_de_planes_init(struct drm_device *drm)
> 	unsigned long crtcs = 1 << drm->mode_config.num_crtc;
> 	unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
> 			      DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
>+	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
>+				  BIT(DRM_MODE_BLEND_PREMULTI)   |
>+				  BIT(DRM_MODE_BLEND_COVERAGE);
> 	u32 *formats;
> 	int ret, i, j, n;
>
>@@ -498,6 +507,9 @@ int malidp_de_planes_init(struct drm_device *drm)
> 		malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
> 				plane->layer->base + MALIDP_LAYER_COMPOSE);
>
>+		drm_plane_create_alpha_property(&plane->base);
>+		drm_plane_create_blend_mode_property(&plane->base, blend_caps);
>+
> 		/* Attach the YUV->RGB property only to video layers */
> 		if (id & (DE_VIDEO1 | DE_VIDEO2)) {
> 			/* default encoding for YUV->RGB is BT601 NARROW */
>-- 
>1.9.1
>
Lowry Li (Arm Technology China) May 31, 2018, 10:19 a.m. UTC | #2
On Wed, May 30, 2018 at 02:34:33PM +0100, Brian Starkey wrote:
> Hi Lowry,
> 
> On Wed, May 30, 2018 at 07:23:54PM +0800, Lowry Li wrote:
> >Check the pixel blending mode and plane alpha value when
> >do the plane_check. Mali DP supports blending the current plane
> >with the background either based on the pixel alpha blending
> >mode or by using the layer's alpha value, but not both at the
> >same time. If both case, plane_check will return failed.
> >
> >Set the HW when doing plane_update accordingly. If plane alpha
> >is the 0xffff, set the PREM bit accordingly. If not we'd set
> >ALPHA bit as zero and layer alpha value.
> 
> The code looks correct - but the description of the PREM bit seems
> wrong here. Did you mean "set the pixel blending bits accordingly"?
> 
> With that fixed:
> 
> Reviewed-by: Brian Starkey <brian.starkey@arm.com>
> 
Hi Brian,

PREM bit is PREMULTI bit to be set premulti or coverage bit
accordingly. But yes, I think I'd change to use "set pixel blending
bits accordingly" to make it entirety :)
Thanks for the review.

> >
> >Signed-off-by: Lowry Li <lowry.li@arm.com>
> >---
> >drivers/gpu/drm/arm/malidp_planes.c | 76 +++++++++++++++++++++----------------
> >1 file changed, 44 insertions(+), 32 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
> >index 7a44897..daa3f4f 100644
> >--- a/drivers/gpu/drm/arm/malidp_planes.c

> >+++ b/drivers/gpu/drm/arm/malidp_planes.c
> >@@ -35,6 +35,7 @@
> >#define   LAYER_COMP_MASK		(0x3 << 12)
> >#define   LAYER_COMP_PIXEL		(0x3 << 12)
> >#define   LAYER_COMP_PLANE		(0x2 << 12)
> >+#define   LAYER_PMUL_ENABLE		(0x1 << 14)
> >#define   LAYER_ALPHA_OFFSET		(16)
> >#define   LAYER_ALPHA_MASK		(0xff)
> >#define   LAYER_ALPHA(x)		(((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
> >@@ -182,6 +183,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> >	struct malidp_plane_state *ms = to_malidp_plane_state(state);
> >	bool rotated = state->rotation & MALIDP_ROTATED_MASK;
> >	struct drm_framebuffer *fb;
> >+	u16 pixel_alpha = state->pixel_blend_mode;
> >	int i, ret;
> >
> >	if (!state->crtc || !state->fb)
> >@@ -244,6 +246,11 @@ static int malidp_de_plane_check(struct drm_plane *plane,
> >		ms->rotmem_size = val;
> >	}
> >
> >+	/* HW can't support plane + pixel blending */
> >+	if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
> >+	    (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE))
> >+		return -EINVAL;
> >+
> >	return 0;
> >}
> >
> >@@ -325,31 +332,33 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> >{
> >	struct malidp_plane *mp;
> >	struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
> >+	struct drm_plane_state *state = plane->state;
> >+	u16 pixel_alpha = state->pixel_blend_mode;
> >+	u8 plane_alpha = state->alpha >> 8;
> >	u32 src_w, src_h, dest_w, dest_h, val;
> >	int i;
> >-	bool format_has_alpha = plane->state->fb->format->has_alpha;
> >
> >	mp = to_malidp_plane(plane);
> >
> >	/* convert src values from Q16 fixed point to integer */
> >-	src_w = plane->state->src_w >> 16;
> >-	src_h = plane->state->src_h >> 16;
> >-	dest_w = plane->state->crtc_w;
> >-	dest_h = plane->state->crtc_h;
> >+	src_w = state->src_w >> 16;
> >+	src_h = state->src_h >> 16;
> >+	dest_w = state->crtc_w;
> >+	dest_h = state->crtc_h;
> >
> >	malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
> >
> >	for (i = 0; i < ms->n_planes; i++) {
> >		/* calculate the offset for the layer's plane registers */
> >		u16 ptr = mp->layer->ptr + (i << 4);
> >-		dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb,
> >-							     plane->state, i);
> >+		dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
> >+							     state, i);
> >
> >		malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
> >		malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
> >	}
> >	malidp_de_set_plane_pitches(mp, ms->n_planes,
> >-				    plane->state->fb->pitches);
> >+				    state->fb->pitches);
> >
> >	if ((plane->state->color_encoding != old_state->color_encoding) ||
> >	    (plane->state->color_range != old_state->color_range))
> >@@ -362,8 +371,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> >	malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
> >			mp->layer->base + MALIDP_LAYER_COMP_SIZE);
> >
> >-	malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) |
> >-			LAYER_V_VAL(plane->state->crtc_y),
> >+	malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
> >+			LAYER_V_VAL(state->crtc_y),
> >			mp->layer->base + MALIDP_LAYER_OFFSET);
> >
> >	if (mp->layer->id == DE_SMART)
> >@@ -376,38 +385,35 @@ static void malidp_de_plane_update(struct drm_plane *plane,
> >	val &= ~LAYER_ROT_MASK;
> >
> >	/* setup the rotation and axis flip bits */
> >-	if (plane->state->rotation & DRM_MODE_ROTATE_MASK)
> >+	if (state->rotation & DRM_MODE_ROTATE_MASK)
> >		val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
> >		       LAYER_ROT_OFFSET;
> >-	if (plane->state->rotation & DRM_MODE_REFLECT_X)
> >+	if (state->rotation & DRM_MODE_REFLECT_X)
> >		val |= LAYER_H_FLIP;
> >-	if (plane->state->rotation & DRM_MODE_REFLECT_Y)
> >+	if (state->rotation & DRM_MODE_REFLECT_Y)
> >		val |= LAYER_V_FLIP;
> >
> >-	val &= ~LAYER_COMP_MASK;
> >-	if (format_has_alpha) {
> >-
> >-		/*
> >-		 * always enable pixel alpha blending until we have a way
> >-		 * to change blend modes
> >-		 */
> >-		val |= LAYER_COMP_PIXEL;
> >-	} else {
> >-
> >-		/*
> >-		 * do not enable pixel alpha blending as the color channel
> >-		 * does not have any alpha information
> >-		 */
> >-		val |= LAYER_COMP_PLANE;
> >-
> >-		/* Set layer alpha coefficient to 0xff ie fully opaque */
> >+	val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE);
> >+
> >+	if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
> >+		val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha);
> >+	} else if (state->fb->format->has_alpha) {
> >+		/* We only care about blend mode if the format has alpha */
> >+		switch (pixel_alpha) {
> >+		case DRM_MODE_BLEND_PREMULTI:
> >+			val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
> >+			break;
> >+		case DRM_MODE_BLEND_COVERAGE:
> >+			val |= LAYER_COMP_PIXEL;
> >+			break;
> >+		}
> >		val |= LAYER_ALPHA(0xff);
> >	}
> >
> >	val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
> >-	if (plane->state->crtc) {
> >+	if (state->crtc) {
> >		struct malidp_crtc_state *m =
> >-			to_malidp_crtc_state(plane->state->crtc->state);
> >+			to_malidp_crtc_state(state->crtc->state);
> >
> >		if (m->scaler_config.scale_enable &&
> >		    m->scaler_config.plane_src_id == mp->layer->id)
> >@@ -446,6 +452,9 @@ int malidp_de_planes_init(struct drm_device *drm)
> >	unsigned long crtcs = 1 << drm->mode_config.num_crtc;
> >	unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
> >			      DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
> >+	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
> >+				  BIT(DRM_MODE_BLEND_PREMULTI)   |
> >+				  BIT(DRM_MODE_BLEND_COVERAGE);
> >	u32 *formats;
> >	int ret, i, j, n;
> >
> >@@ -498,6 +507,9 @@ int malidp_de_planes_init(struct drm_device *drm)
> >		malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
> >				plane->layer->base + MALIDP_LAYER_COMPOSE);
> >
> >+		drm_plane_create_alpha_property(&plane->base);
> >+		drm_plane_create_blend_mode_property(&plane->base, blend_caps);
> >+
> >		/* Attach the YUV->RGB property only to video layers */
> >		if (id & (DE_VIDEO1 | DE_VIDEO2)) {
> >			/* default encoding for YUV->RGB is BT601 NARROW */
> >-- 
> >1.9.1
> >
kernel test robot June 1, 2018, 11:22 a.m. UTC | #3
Hi Lowry,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.17-rc7]
[cannot apply to next-20180531]
[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/Lowry-Li/drm-blend-Add-per-plane-pixel-blend-mode-property/20180601-180033
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: arm64-allmodconfig (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
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/arm/malidp_planes.c: In function 'malidp_de_plane_check':
>> drivers/gpu/drm/arm/malidp_planes.c:250:12: error: 'struct drm_plane_state' has no member named 'alpha'
     if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
               ^~
>> drivers/gpu/drm/arm/malidp_planes.c:250:23: error: 'DRM_BLEND_ALPHA_OPAQUE' undeclared (first use in this function)
     if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
                          ^~~~~~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/arm/malidp_planes.c:250:23: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpu/drm/arm/malidp_planes.c: In function 'malidp_de_plane_update':
   drivers/gpu/drm/arm/malidp_planes.c:337:24: error: 'struct drm_plane_state' has no member named 'alpha'
     u8 plane_alpha = state->alpha >> 8;
                           ^~
   drivers/gpu/drm/arm/malidp_planes.c:398:11: error: 'struct drm_plane_state' has no member named 'alpha'
     if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
              ^~
   drivers/gpu/drm/arm/malidp_planes.c:398:22: error: 'DRM_BLEND_ALPHA_OPAQUE' undeclared (first use in this function)
     if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
                         ^~~~~~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/arm/malidp_planes.c: In function 'malidp_de_planes_init':
>> drivers/gpu/drm/arm/malidp_planes.c:510:3: error: implicit declaration of function 'drm_plane_create_alpha_property'; did you mean 'drm_plane_create_zpos_property'? [-Werror=implicit-function-declaration]
      drm_plane_create_alpha_property(&plane->base);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      drm_plane_create_zpos_property
   cc1: some warnings being treated as errors

vim +250 drivers/gpu/drm/arm/malidp_planes.c

   178	
   179	static int malidp_de_plane_check(struct drm_plane *plane,
   180					 struct drm_plane_state *state)
   181	{
   182		struct malidp_plane *mp = to_malidp_plane(plane);
   183		struct malidp_plane_state *ms = to_malidp_plane_state(state);
   184		bool rotated = state->rotation & MALIDP_ROTATED_MASK;
   185		struct drm_framebuffer *fb;
   186		u16 pixel_alpha = state->pixel_blend_mode;
   187		int i, ret;
   188	
   189		if (!state->crtc || !state->fb)
   190			return 0;
   191	
   192		fb = state->fb;
   193	
   194		ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
   195						     mp->layer->id,
   196						     fb->format->format);
   197		if (ms->format == MALIDP_INVALID_FORMAT_ID)
   198			return -EINVAL;
   199	
   200		ms->n_planes = fb->format->num_planes;
   201		for (i = 0; i < ms->n_planes; i++) {
   202			u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
   203			if (fb->pitches[i] & (alignment - 1)) {
   204				DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
   205					      fb->pitches[i], i);
   206				return -EINVAL;
   207			}
   208		}
   209	
   210		if ((state->crtc_w > mp->hwdev->max_line_size) ||
   211		    (state->crtc_h > mp->hwdev->max_line_size) ||
   212		    (state->crtc_w < mp->hwdev->min_line_size) ||
   213		    (state->crtc_h < mp->hwdev->min_line_size))
   214			return -EINVAL;
   215	
   216		/*
   217		 * DP550/650 video layers can accept 3 plane formats only if
   218		 * fb->pitches[1] == fb->pitches[2] since they don't have a
   219		 * third plane stride register.
   220		 */
   221		if (ms->n_planes == 3 &&
   222		    !(mp->hwdev->hw->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
   223		    (state->fb->pitches[1] != state->fb->pitches[2]))
   224			return -EINVAL;
   225	
   226		ret = malidp_se_check_scaling(mp, state);
   227		if (ret)
   228			return ret;
   229	
   230		/* packed RGB888 / BGR888 can't be rotated or flipped */
   231		if (state->rotation != DRM_MODE_ROTATE_0 &&
   232		    (fb->format->format == DRM_FORMAT_RGB888 ||
   233		     fb->format->format == DRM_FORMAT_BGR888))
   234			return -EINVAL;
   235	
   236		ms->rotmem_size = 0;
   237		if (state->rotation & MALIDP_ROTATED_MASK) {
   238			int val;
   239	
   240			val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_h,
   241							     state->crtc_w,
   242							     fb->format->format);
   243			if (val < 0)
   244				return val;
   245	
   246			ms->rotmem_size = val;
   247		}
   248	
   249		/* HW can't support plane + pixel blending */
 > 250		if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
   251		    (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE))
   252			return -EINVAL;
   253	
   254		return 0;
   255	}
   256	
   257	static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
   258						int num_planes, unsigned int pitches[3])
   259	{
   260		int i;
   261		int num_strides = num_planes;
   262	
   263		if (!mp->layer->stride_offset)
   264			return;
   265	
   266		if (num_planes == 3)
   267			num_strides = (mp->hwdev->hw->features &
   268				       MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
   269	
   270		for (i = 0; i < num_strides; ++i)
   271			malidp_hw_write(mp->hwdev, pitches[i],
   272					mp->layer->base +
   273					mp->layer->stride_offset + i * 4);
   274	}
   275	
   276	static const s16
   277	malidp_yuv2rgb_coeffs[][DRM_COLOR_RANGE_MAX][MALIDP_COLORADJ_NUM_COEFFS] = {
   278		[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
   279			1192,    0, 1634,
   280			1192, -401, -832,
   281			1192, 2066,    0,
   282			  64,  512,  512
   283		},
   284		[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
   285			1024,    0, 1436,
   286			1024, -352, -731,
   287			1024, 1815,    0,
   288			   0,  512,  512
   289		},
   290		[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
   291			1192,    0, 1836,
   292			1192, -218, -546,
   293			1192, 2163,    0,
   294			  64,  512,  512
   295		},
   296		[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
   297			1024,    0, 1613,
   298			1024, -192, -479,
   299			1024, 1900,    0,
   300			   0,  512,  512
   301		},
   302		[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
   303			1024,    0, 1476,
   304			1024, -165, -572,
   305			1024, 1884,    0,
   306			   0,  512,  512
   307		},
   308		[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = {
   309			1024,    0, 1510,
   310			1024, -168, -585,
   311			1024, 1927,    0,
   312			   0,  512,  512
   313		}
   314	};
   315	
   316	static void malidp_de_set_color_encoding(struct malidp_plane *plane,
   317						 enum drm_color_encoding enc,
   318						 enum drm_color_range range)
   319	{
   320		unsigned int i;
   321	
   322		for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
   323			/* coefficients are signed, two's complement values */
   324			malidp_hw_write(plane->hwdev, malidp_yuv2rgb_coeffs[enc][range][i],
   325					plane->layer->base + plane->layer->yuv2rgb_offset +
   326					i * 4);
   327		}
   328	}
   329	
   330	static void malidp_de_plane_update(struct drm_plane *plane,
   331					   struct drm_plane_state *old_state)
   332	{
   333		struct malidp_plane *mp;
   334		struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
   335		struct drm_plane_state *state = plane->state;
   336		u16 pixel_alpha = state->pixel_blend_mode;
   337		u8 plane_alpha = state->alpha >> 8;
   338		u32 src_w, src_h, dest_w, dest_h, val;
   339		int i;
   340	
   341		mp = to_malidp_plane(plane);
   342	
   343		/* convert src values from Q16 fixed point to integer */
   344		src_w = state->src_w >> 16;
   345		src_h = state->src_h >> 16;
   346		dest_w = state->crtc_w;
   347		dest_h = state->crtc_h;
   348	
   349		malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
   350	
   351		for (i = 0; i < ms->n_planes; i++) {
   352			/* calculate the offset for the layer's plane registers */
   353			u16 ptr = mp->layer->ptr + (i << 4);
   354			dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
   355								     state, i);
   356	
   357			malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
   358			malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
   359		}
   360		malidp_de_set_plane_pitches(mp, ms->n_planes,
   361					    state->fb->pitches);
   362	
   363		if ((plane->state->color_encoding != old_state->color_encoding) ||
   364		    (plane->state->color_range != old_state->color_range))
   365			malidp_de_set_color_encoding(mp, plane->state->color_encoding,
   366						     plane->state->color_range);
   367	
   368		malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
   369				mp->layer->base + MALIDP_LAYER_SIZE);
   370	
   371		malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
   372				mp->layer->base + MALIDP_LAYER_COMP_SIZE);
   373	
   374		malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
   375				LAYER_V_VAL(state->crtc_y),
   376				mp->layer->base + MALIDP_LAYER_OFFSET);
   377	
   378		if (mp->layer->id == DE_SMART)
   379			malidp_hw_write(mp->hwdev,
   380					LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
   381					mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
   382	
   383		/* first clear the rotation bits */
   384		val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
   385		val &= ~LAYER_ROT_MASK;
   386	
   387		/* setup the rotation and axis flip bits */
   388		if (state->rotation & DRM_MODE_ROTATE_MASK)
   389			val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
   390			       LAYER_ROT_OFFSET;
   391		if (state->rotation & DRM_MODE_REFLECT_X)
   392			val |= LAYER_H_FLIP;
   393		if (state->rotation & DRM_MODE_REFLECT_Y)
   394			val |= LAYER_V_FLIP;
   395	
   396		val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE);
   397	
 > 398		if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
   399			val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha);
   400		} else if (state->fb->format->has_alpha) {
   401			/* We only care about blend mode if the format has alpha */
   402			switch (pixel_alpha) {
   403			case DRM_MODE_BLEND_PREMULTI:
   404				val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
   405				break;
   406			case DRM_MODE_BLEND_COVERAGE:
   407				val |= LAYER_COMP_PIXEL;
   408				break;
   409			}
   410			val |= LAYER_ALPHA(0xff);
   411		}
   412	
   413		val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
   414		if (state->crtc) {
   415			struct malidp_crtc_state *m =
   416				to_malidp_crtc_state(state->crtc->state);
   417	
   418			if (m->scaler_config.scale_enable &&
   419			    m->scaler_config.plane_src_id == mp->layer->id)
   420				val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE);
   421		}
   422	
   423		/* set the 'enable layer' bit */
   424		val |= LAYER_ENABLE;
   425	
   426		malidp_hw_write(mp->hwdev, val,
   427				mp->layer->base + MALIDP_LAYER_CONTROL);
   428	}
   429	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 7a44897..daa3f4f 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -35,6 +35,7 @@ 
 #define   LAYER_COMP_MASK		(0x3 << 12)
 #define   LAYER_COMP_PIXEL		(0x3 << 12)
 #define   LAYER_COMP_PLANE		(0x2 << 12)
+#define   LAYER_PMUL_ENABLE		(0x1 << 14)
 #define   LAYER_ALPHA_OFFSET		(16)
 #define   LAYER_ALPHA_MASK		(0xff)
 #define   LAYER_ALPHA(x)		(((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
@@ -182,6 +183,7 @@  static int malidp_de_plane_check(struct drm_plane *plane,
 	struct malidp_plane_state *ms = to_malidp_plane_state(state);
 	bool rotated = state->rotation & MALIDP_ROTATED_MASK;
 	struct drm_framebuffer *fb;
+	u16 pixel_alpha = state->pixel_blend_mode;
 	int i, ret;
 
 	if (!state->crtc || !state->fb)
@@ -244,6 +246,11 @@  static int malidp_de_plane_check(struct drm_plane *plane,
 		ms->rotmem_size = val;
 	}
 
+	/* HW can't support plane + pixel blending */
+	if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
+	    (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -325,31 +332,33 @@  static void malidp_de_plane_update(struct drm_plane *plane,
 {
 	struct malidp_plane *mp;
 	struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
+	struct drm_plane_state *state = plane->state;
+	u16 pixel_alpha = state->pixel_blend_mode;
+	u8 plane_alpha = state->alpha >> 8;
 	u32 src_w, src_h, dest_w, dest_h, val;
 	int i;
-	bool format_has_alpha = plane->state->fb->format->has_alpha;
 
 	mp = to_malidp_plane(plane);
 
 	/* convert src values from Q16 fixed point to integer */
-	src_w = plane->state->src_w >> 16;
-	src_h = plane->state->src_h >> 16;
-	dest_w = plane->state->crtc_w;
-	dest_h = plane->state->crtc_h;
+	src_w = state->src_w >> 16;
+	src_h = state->src_h >> 16;
+	dest_w = state->crtc_w;
+	dest_h = state->crtc_h;
 
 	malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
 
 	for (i = 0; i < ms->n_planes; i++) {
 		/* calculate the offset for the layer's plane registers */
 		u16 ptr = mp->layer->ptr + (i << 4);
-		dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb,
-							     plane->state, i);
+		dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
+							     state, i);
 
 		malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
 		malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
 	}
 	malidp_de_set_plane_pitches(mp, ms->n_planes,
-				    plane->state->fb->pitches);
+				    state->fb->pitches);
 
 	if ((plane->state->color_encoding != old_state->color_encoding) ||
 	    (plane->state->color_range != old_state->color_range))
@@ -362,8 +371,8 @@  static void malidp_de_plane_update(struct drm_plane *plane,
 	malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
 			mp->layer->base + MALIDP_LAYER_COMP_SIZE);
 
-	malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) |
-			LAYER_V_VAL(plane->state->crtc_y),
+	malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
+			LAYER_V_VAL(state->crtc_y),
 			mp->layer->base + MALIDP_LAYER_OFFSET);
 
 	if (mp->layer->id == DE_SMART)
@@ -376,38 +385,35 @@  static void malidp_de_plane_update(struct drm_plane *plane,
 	val &= ~LAYER_ROT_MASK;
 
 	/* setup the rotation and axis flip bits */
-	if (plane->state->rotation & DRM_MODE_ROTATE_MASK)
+	if (state->rotation & DRM_MODE_ROTATE_MASK)
 		val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
 		       LAYER_ROT_OFFSET;
-	if (plane->state->rotation & DRM_MODE_REFLECT_X)
+	if (state->rotation & DRM_MODE_REFLECT_X)
 		val |= LAYER_H_FLIP;
-	if (plane->state->rotation & DRM_MODE_REFLECT_Y)
+	if (state->rotation & DRM_MODE_REFLECT_Y)
 		val |= LAYER_V_FLIP;
 
-	val &= ~LAYER_COMP_MASK;
-	if (format_has_alpha) {
-
-		/*
-		 * always enable pixel alpha blending until we have a way
-		 * to change blend modes
-		 */
-		val |= LAYER_COMP_PIXEL;
-	} else {
-
-		/*
-		 * do not enable pixel alpha blending as the color channel
-		 * does not have any alpha information
-		 */
-		val |= LAYER_COMP_PLANE;
-
-		/* Set layer alpha coefficient to 0xff ie fully opaque */
+	val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE);
+
+	if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
+		val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha);
+	} else if (state->fb->format->has_alpha) {
+		/* We only care about blend mode if the format has alpha */
+		switch (pixel_alpha) {
+		case DRM_MODE_BLEND_PREMULTI:
+			val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
+			break;
+		case DRM_MODE_BLEND_COVERAGE:
+			val |= LAYER_COMP_PIXEL;
+			break;
+		}
 		val |= LAYER_ALPHA(0xff);
 	}
 
 	val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
-	if (plane->state->crtc) {
+	if (state->crtc) {
 		struct malidp_crtc_state *m =
-			to_malidp_crtc_state(plane->state->crtc->state);
+			to_malidp_crtc_state(state->crtc->state);
 
 		if (m->scaler_config.scale_enable &&
 		    m->scaler_config.plane_src_id == mp->layer->id)
@@ -446,6 +452,9 @@  int malidp_de_planes_init(struct drm_device *drm)
 	unsigned long crtcs = 1 << drm->mode_config.num_crtc;
 	unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
 			      DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
+	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
+				  BIT(DRM_MODE_BLEND_PREMULTI)   |
+				  BIT(DRM_MODE_BLEND_COVERAGE);
 	u32 *formats;
 	int ret, i, j, n;
 
@@ -498,6 +507,9 @@  int malidp_de_planes_init(struct drm_device *drm)
 		malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
 				plane->layer->base + MALIDP_LAYER_COMPOSE);
 
+		drm_plane_create_alpha_property(&plane->base);
+		drm_plane_create_blend_mode_property(&plane->base, blend_caps);
+
 		/* Attach the YUV->RGB property only to video layers */
 		if (id & (DE_VIDEO1 | DE_VIDEO2)) {
 			/* default encoding for YUV->RGB is BT601 NARROW */