diff mbox series

[v2,09/15] drm/mediatek: Refine OVL format convert API and export to public

Message ID 20250321093435.94835-10-paul-pl.chen@mediatek.com (mailing list archive)
State New
Headers show
Series Add MediaTek SoC DRM support for MT8196 | expand

Commit Message

paul-pl.chen March 21, 2025, 9:33 a.m. UTC
From: Nancy Lin <nancy.lin@mediatek.com>

Refine OVL format convert API and export to public.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 158 ++++++++++++++++--------
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  16 +++
 2 files changed, 122 insertions(+), 52 deletions(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h

Comments

CK Hu (胡俊光) March 25, 2025, 2:57 a.m. UTC | #1
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
> 
> Refine OVL format convert API and export to public.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 158 ++++++++++++++++--------
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  16 +++
>  2 files changed, 122 insertions(+), 52 deletions(-)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index d0581c4e3c99..e2b125a717c6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -18,6 +18,7 @@
>  #include "mtk_crtc.h"
>  #include "mtk_ddp_comp.h"
>  #include "mtk_disp_drv.h"
> +#include "mtk_disp_ovl.h"
>  #include "mtk_drm_drv.h"
>  
>  #define DISP_REG_OVL_INTEN			0x0004
> @@ -62,22 +63,15 @@
>  /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
>  #define OVL_CON_RGB_SWAP	BIT(25)
>  
> -#define OVL_CON_CLRFMT_RGB	(1 << 12)
> -#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
> -#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
> -#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_UYVY	(4 << 12)
> -#define OVL_CON_CLRFMT_YUYV	(5 << 12)
> -#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
> -#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
> -#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
> -#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
> -					0 : OVL_CON_CLRFMT_RGB)
> -#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
> -					OVL_CON_CLRFMT_RGB : 0)
> +#define OVL_CON_CLRFMT_RGB565(shift)	(0 << (shift))
> +#define OVL_CON_CLRFMT_RGB888(shift)	(1 << (shift))
> +#define OVL_CON_CLRFMT_ARGB8888(shift)	(2 << (shift))
> +#define OVL_CON_CLRFMT_RGBA8888(shift)	(3 << (shift))
> +#define OVL_CON_CLRFMT_UYVY(shift)	(4 << (shift))
> +#define OVL_CON_CLRFMT_YUYV(shift)	(5 << (shift))
> +#define OVL_CON_MTX_YUV_TO_RGB		(6 << 16)
> +#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
> +
>  #define	OVL_CON_AEN		BIT(8)
>  #define	OVL_CON_ALPHA		0xff
>  #define	OVL_CON_VIRT_FLIP	BIT(9)
> @@ -85,7 +79,7 @@
>  
>  #define OVL_COLOR_ALPHA		GENMASK(31, 24)
>  
> -static inline bool is_10bit_rgb(u32 fmt)
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
>  {
>  	switch (fmt) {
>  	case DRM_FORMAT_XRGB2101010:
> @@ -295,7 +289,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
>  	if (!ovl->data->supports_clrfmt_ext)
>  		return;
>  
> -	if (is_10bit_rgb(format))
> +	if (mtk_ovl_is_10bit_rgb(format))
>  		bit_depth = OVL_CON_CLRFMT_10_BIT;
>  
>  	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
> @@ -394,10 +388,26 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
>  		      DISP_REG_OVL_RDMA_CTRL(idx));
>  }
>  
> -static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> -					struct mtk_plane_state *state)
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
> +{

This modification is not related to the title, so separate to another patch.

> +	if (!state->base.fb)
> +		return false;
> +
> +	/*
> +	 * Although the alpha channel can be ignored, CONST_BLD must be enabled
> +	 * for XRGB format, otherwise OVL will still read the value from memory.
> +	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
> +	 * affect the result. Therefore we use !has_alpha as the condition.
> +	 */
> +
> +	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
> +		return true;
> +
> +	return false;
> +}
> +
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
>  {
> -	unsigned int fmt = state->pending.format;
>  	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
>  
>  	/*
> @@ -412,52 +422,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
>  	 * will get an error return from drm_plane_create_blend_mode_property() and
>  	 * state->base.pixel_blend_mode should not be used.
>  	 */
> -	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> +	if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
>  		blend_mode = state->base.pixel_blend_mode;
>  
> +	return blend_mode;
> +}
> +
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> +				 bool fmt_rgb565_is_0, bool color_convert,
> +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
> +{
> +	unsigned int con = 0;
> +	bool need_byte_swap = false, need_rgb_swap = false;
> +
>  	switch (fmt) {
>  	default:
>  	case DRM_FORMAT_RGB565:
> -		return OVL_CON_CLRFMT_RGB565(ovl);
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_BGR565:
> -		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> +		need_byte_swap = true;	/* RGB565 -> BGR565 */
> +	break;
>  	case DRM_FORMAT_RGB888:
> -		return OVL_CON_CLRFMT_RGB888(ovl);
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_BGR888:
> -		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> +		need_byte_swap = true;	/* RGB888 -> BGR888 */
> +	break;
>  	case DRM_FORMAT_RGBX8888:
>  	case DRM_FORMAT_RGBA8888:
>  	case DRM_FORMAT_RGBX1010102:
>  	case DRM_FORMAT_RGBA1010102:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_RGBA8888 :
> -		       OVL_CON_CLRFMT_PRGBA8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
> +			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_BGRX8888:
>  	case DRM_FORMAT_BGRA8888:
>  	case DRM_FORMAT_BGRX1010102:
>  	case DRM_FORMAT_BGRA1010102:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_BGRA8888 :
> -		       OVL_CON_CLRFMT_PBGRA8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> +			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_XRGB8888:
>  	case DRM_FORMAT_ARGB8888:
>  	case DRM_FORMAT_XRGB2101010:
>  	case DRM_FORMAT_ARGB2101010:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_ARGB8888 :
> -		       OVL_CON_CLRFMT_PARGB8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
> +			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> +		else
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +	break;
>  	case DRM_FORMAT_XBGR8888:
>  	case DRM_FORMAT_ABGR8888:
>  	case DRM_FORMAT_XBGR2101010:
>  	case DRM_FORMAT_ABGR2101010:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_ABGR8888 :
> -		       OVL_CON_CLRFMT_PABGR8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> +			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_UYVY:
> -		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
> +		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_YUYV:
> -		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
> +		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
> +	break;
>  	}
> +
> +	if (color_convert)
> +		con |= OVL_CON_MTX_YUV_TO_RGB;

Only YUV need this. RGB do not need this.

> +
> +	if (need_byte_swap)
> +		con |= byte_swap;
> +
> +	if (need_rgb_swap)
> +		con |= rgb_swap;
> +
> +	return con;
>  }
>  
>  static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
> @@ -495,7 +555,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  	unsigned int rotation = pending->rotation;
>  	unsigned int offset = (pending->y << 16) | pending->x;
>  	unsigned int src_size = (pending->height << 16) | pending->width;
> -	unsigned int blend_mode = state->base.pixel_blend_mode;
> +	unsigned int blend_mode = mtk_ovl_get_blend_mode(state, ovl->data->blend_modes);

This modification is not related to the title, so separate to another patch.

>  	unsigned int ignore_pixel_alpha = 0;
>  	unsigned int con;
>  
> @@ -504,7 +564,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		return;
>  	}
>  
> -	con = mtk_ovl_fmt_convert(ovl, state);
> +	con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
> +				  12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
>  	if (state->base.fb) {
>  		con |= state->base.alpha & OVL_CON_ALPHA;
>  
> @@ -512,17 +573,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		 * For blend_modes supported SoCs, always enable alpha blending.
>  		 * For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set.
>  		 */
> -		if (blend_mode || state->base.fb->format->has_alpha)
> +		if (state->base.pixel_blend_mode || state->base.fb->format->has_alpha)

This modification is not related to the title, so separate to another patch.

>  			con |= OVL_CON_AEN;
> -
> -		/*
> -		 * Although the alpha channel can be ignored, CONST_BLD must be enabled
> -		 * for XRGB format, otherwise OVL will still read the value from memory.
> -		 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
> -		 * affect the result. Therefore we use !has_alpha as the condition.
> -		 */
> -		if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
> -			ignore_pixel_alpha = OVL_CONST_BLEND;
>  	}
>  
>  	/*
> @@ -548,6 +600,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  
>  	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
>  			      DISP_REG_OVL_CON(idx));
> +
> +	ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state, blend_mode) ? OVL_CONST_BLEND : 0;
>  	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
>  			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
>  	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> new file mode 100644
> index 000000000000..9bd5dc62d626
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#ifndef __MTK_DISP_OVL_H__
> +#define __MTK_DISP_OVL_H__
> +
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode);
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> +				 bool fmt_rgb565_is_0, bool color_convert,
> +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
> +
> +#endif
diff mbox series

Patch

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index d0581c4e3c99..e2b125a717c6 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -18,6 +18,7 @@ 
 #include "mtk_crtc.h"
 #include "mtk_ddp_comp.h"
 #include "mtk_disp_drv.h"
+#include "mtk_disp_ovl.h"
 #include "mtk_drm_drv.h"
 
 #define DISP_REG_OVL_INTEN			0x0004
@@ -62,22 +63,15 @@ 
 /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
 #define OVL_CON_RGB_SWAP	BIT(25)
 
-#define OVL_CON_CLRFMT_RGB	(1 << 12)
-#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
-#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
-#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_UYVY	(4 << 12)
-#define OVL_CON_CLRFMT_YUYV	(5 << 12)
-#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
-#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
-#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
-#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					0 : OVL_CON_CLRFMT_RGB)
-#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					OVL_CON_CLRFMT_RGB : 0)
+#define OVL_CON_CLRFMT_RGB565(shift)	(0 << (shift))
+#define OVL_CON_CLRFMT_RGB888(shift)	(1 << (shift))
+#define OVL_CON_CLRFMT_ARGB8888(shift)	(2 << (shift))
+#define OVL_CON_CLRFMT_RGBA8888(shift)	(3 << (shift))
+#define OVL_CON_CLRFMT_UYVY(shift)	(4 << (shift))
+#define OVL_CON_CLRFMT_YUYV(shift)	(5 << (shift))
+#define OVL_CON_MTX_YUV_TO_RGB		(6 << 16)
+#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
+
 #define	OVL_CON_AEN		BIT(8)
 #define	OVL_CON_ALPHA		0xff
 #define	OVL_CON_VIRT_FLIP	BIT(9)
@@ -85,7 +79,7 @@ 
 
 #define OVL_COLOR_ALPHA		GENMASK(31, 24)
 
-static inline bool is_10bit_rgb(u32 fmt)
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
 {
 	switch (fmt) {
 	case DRM_FORMAT_XRGB2101010:
@@ -295,7 +289,7 @@  static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
 	if (!ovl->data->supports_clrfmt_ext)
 		return;
 
-	if (is_10bit_rgb(format))
+	if (mtk_ovl_is_10bit_rgb(format))
 		bit_depth = OVL_CON_CLRFMT_10_BIT;
 
 	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
@@ -394,10 +388,26 @@  void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
 		      DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
-					struct mtk_plane_state *state)
+bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
+{
+	if (!state->base.fb)
+		return false;
+
+	/*
+	 * Although the alpha channel can be ignored, CONST_BLD must be enabled
+	 * for XRGB format, otherwise OVL will still read the value from memory.
+	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
+	 * affect the result. Therefore we use !has_alpha as the condition.
+	 */
+
+	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
+		return true;
+
+	return false;
+}
+
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
 {
-	unsigned int fmt = state->pending.format;
 	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
 
 	/*
@@ -412,52 +422,102 @@  static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
 	 * will get an error return from drm_plane_create_blend_mode_property() and
 	 * state->base.pixel_blend_mode should not be used.
 	 */
-	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+	if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
 		blend_mode = state->base.pixel_blend_mode;
 
+	return blend_mode;
+}
+
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
+{
+	unsigned int con = 0;
+	bool need_byte_swap = false, need_rgb_swap = false;
+
 	switch (fmt) {
 	default:
 	case DRM_FORMAT_RGB565:
-		return OVL_CON_CLRFMT_RGB565(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR565:
-		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+		need_byte_swap = true;	/* RGB565 -> BGR565 */
+	break;
 	case DRM_FORMAT_RGB888:
-		return OVL_CON_CLRFMT_RGB888(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR888:
-		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+		need_byte_swap = true;	/* RGB888 -> BGR888 */
+	break;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
 	case DRM_FORMAT_RGBX1010102:
 	case DRM_FORMAT_RGBA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_RGBA8888 :
-		       OVL_CON_CLRFMT_PRGBA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
+		}
+	break;
 	case DRM_FORMAT_BGRX8888:
 	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_BGRX1010102:
 	case DRM_FORMAT_BGRA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_BGRA8888 :
-		       OVL_CON_CLRFMT_PBGRA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+		}
+	break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ARGB8888 :
-		       OVL_CON_CLRFMT_PARGB8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+		else
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+	break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ABGR8888 :
-		       OVL_CON_CLRFMT_PABGR8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
+		}
+	break;
 	case DRM_FORMAT_UYVY:
-		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
+	break;
 	case DRM_FORMAT_YUYV:
-		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
+	break;
 	}
+
+	if (color_convert)
+		con |= OVL_CON_MTX_YUV_TO_RGB;
+
+	if (need_byte_swap)
+		con |= byte_swap;
+
+	if (need_rgb_swap)
+		con |= rgb_swap;
+
+	return con;
 }
 
 static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
@@ -495,7 +555,7 @@  void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 	unsigned int rotation = pending->rotation;
 	unsigned int offset = (pending->y << 16) | pending->x;
 	unsigned int src_size = (pending->height << 16) | pending->width;
-	unsigned int blend_mode = state->base.pixel_blend_mode;
+	unsigned int blend_mode = mtk_ovl_get_blend_mode(state, ovl->data->blend_modes);
 	unsigned int ignore_pixel_alpha = 0;
 	unsigned int con;
 
@@ -504,7 +564,8 @@  void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	con = mtk_ovl_fmt_convert(ovl, state);
+	con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
+				  12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
 	if (state->base.fb) {
 		con |= state->base.alpha & OVL_CON_ALPHA;
 
@@ -512,17 +573,8 @@  void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		 * For blend_modes supported SoCs, always enable alpha blending.
 		 * For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set.
 		 */
-		if (blend_mode || state->base.fb->format->has_alpha)
+		if (state->base.pixel_blend_mode || state->base.fb->format->has_alpha)
 			con |= OVL_CON_AEN;
-
-		/*
-		 * Although the alpha channel can be ignored, CONST_BLD must be enabled
-		 * for XRGB format, otherwise OVL will still read the value from memory.
-		 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
-		 * affect the result. Therefore we use !has_alpha as the condition.
-		 */
-		if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
-			ignore_pixel_alpha = OVL_CONST_BLEND;
 	}
 
 	/*
@@ -548,6 +600,8 @@  void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 
 	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
 			      DISP_REG_OVL_CON(idx));
+
+	ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state, blend_mode) ? OVL_CONST_BLEND : 0;
 	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
 			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
 	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
new file mode 100644
index 000000000000..9bd5dc62d626
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -0,0 +1,16 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OVL_H__
+#define __MTK_DISP_OVL_H__
+
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
+bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode);
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
+
+#endif