LKML Archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/14] Support IGT in display driver
@ 2024-03-22  5:28 Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 01/14] soc: mediatek: Disable 9-bit alpha in ETHDR Shawn Sung
                   ` (13 more replies)
  0 siblings, 14 replies; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

This series is based on 20240322012808.26234-1-shawn.sung@mediatek.com.

This series adds support for running IGT (Intel GPU Tool) tests
with MediaTek display driver. The following changes will be
applied:

1. Add a new API for creating GCE thread loop to retrieve CRCs
   from the hardware component
2. Support hardware CRC calculation in both VDOSYS0 and VDOSYS1
3. Support alpha blending in both VDOSYS0 and VDOSYS1

Changes in v6:
- Use drm_vblank_work to deffer the CRC work into bottom halves
- Separate the patches for "Premultiplied" and "None" alpha blending

Changes in v5:
- Add more descriptions to the codes
- Add DRM mode configs to the driver data
- Squash and rearrange the commits

Changes in v4:
- Separate the patch into smaller ones
- Change the title of some patches
- Revert the changes that are not related to the series

Changes in v3:
- Modify the dt-binding document of Mediatek OVL
- Set DRM mode configs accroding to the hardware capabilities
- Replace cmdq_pkt_jump_absolute() with cmdq_pkt_jump()

Changes in v2:
- Simplify CMDQ by adding commands that are currently used only
- Integrate CRC related codes into new APIs for Mixer and OVL to reuse
- Add CPU version CRC retrieval when CMDQ is disabled

Hsiao Chien Sung (14):
  soc: mediatek: Disable 9-bit alpha in ETHDR
  drm/mediatek: Add OVL compatible name for MT8195
  drm/mediatek: Add missing plane settings when async update
  drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property
  drm/mediatek: Set DRM mode configs accordingly
  drm/mediatek: Turn off the layers with zero width or height
  drm/mediatek: Support alpha blending in display driver
  drm/mediatek: Support "Pre-multiplied" alpha blending in OVL
  drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer
  drm/mediatek: Support "None" alpha blending in OVL
  drm/mediatek: Support "None" alpha blending in Mixer
  drm/mediatek: Support CRC in display driver
  drm/mediatek: Support CRC in OVL
  drm/mediatek: Support CRC in OVL adaptor

 drivers/gpu/drm/mediatek/mtk_crtc.c           | 260 +++++++++++++++
 drivers/gpu/drm/mediatek/mtk_crtc.h           |  38 +++
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c       |   6 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h       |   9 +-
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |   6 +
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c       | 304 ++++++++++++++++--
 .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c   |  23 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        |  24 ++
 drivers/gpu/drm/mediatek/mtk_drm_drv.h        |   3 +
 drivers/gpu/drm/mediatek/mtk_ethdr.c          |  94 +++++-
 drivers/gpu/drm/mediatek/mtk_ethdr.h          |   5 +
 drivers/gpu/drm/mediatek/mtk_plane.c          |  15 +-
 drivers/soc/mediatek/mtk-mmsys.c              |   1 +
 13 files changed, 744 insertions(+), 44 deletions(-)

--
2.18.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v6 01/14] soc: mediatek: Disable 9-bit alpha in ETHDR
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 02/14] drm/mediatek: Add OVL compatible name for MT8195 Shawn Sung
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

ETHDR 9-bit alpha should be disabled by default,
otherwise alpha blending will not work.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/soc/mediatek/mtk-mmsys.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index afb2c40c85c15..00eff18a3bcea 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -236,6 +236,7 @@ void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16
 
 	mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_ALPHA + (idx - 1) * 4, ~0,
 			      alpha << 16 | alpha, cmdq_pkt);
+	mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(15 + idx), 0, cmdq_pkt);
 	mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(19 + idx),
 			      alpha_sel << (19 + idx), cmdq_pkt);
 	mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_PAD + (idx - 1) * 4,
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 02/14] drm/mediatek: Add OVL compatible name for MT8195
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 01/14] soc: mediatek: Disable 9-bit alpha in ETHDR Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 03/14] drm/mediatek: Add missing plane settings when async update Shawn Sung
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Add OVL compatible name for MT8195.
Without this commit, DRM won't work after modifying the device tree.

Reviewed-by: CK Hu <ck.hu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 4710cd8b7288b..621015b64674d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -761,6 +761,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
 	  .data = (void *)MTK_DISP_OVL },
 	{ .compatible = "mediatek,mt8192-disp-ovl",
 	  .data = (void *)MTK_DISP_OVL },
+	{ .compatible = "mediatek,mt8195-disp-ovl",
+	  .data = (void *)MTK_DISP_OVL },
 	{ .compatible = "mediatek,mt8183-disp-ovl-2l",
 	  .data = (void *)MTK_DISP_OVL_2L },
 	{ .compatible = "mediatek,mt8192-disp-ovl-2l",
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 03/14] drm/mediatek: Add missing plane settings when async update
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 01/14] soc: mediatek: Disable 9-bit alpha in ETHDR Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 02/14] drm/mediatek: Add OVL compatible name for MT8195 Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property Shawn Sung
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Fix an issue that plane coordinate was not saved when
calling async update.

Fixes: 920fffcc8912 ("drm/mediatek: update cursors by using async atomic update")

Reviewed-by: CK Hu <ck.hu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_plane.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c
index 4625deb21d406..a74b26d359857 100644
--- a/drivers/gpu/drm/mediatek/mtk_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_plane.c
@@ -227,6 +227,8 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane,
 	plane->state->src_y = new_state->src_y;
 	plane->state->src_h = new_state->src_h;
 	plane->state->src_w = new_state->src_w;
+	plane->state->dst.x1 = new_state->dst.x1;
+	plane->state->dst.y1 = new_state->dst.y1;
 
 	mtk_plane_update_new_state(new_state, new_plane_state);
 	swap(plane->state->fb, new_state->fb);
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (2 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 03/14] drm/mediatek: Add missing plane settings when async update Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  9:02   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 05/14] drm/mediatek: Set DRM mode configs accordingly Shawn Sung
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Always add DRM_MODE_ROTATE_0 to rotation property to meet
IGT's (Intel GPU Tools) requirement.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h |  6 +++++-
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 21 +++++++++------------
 drivers/gpu/drm/mediatek/mtk_plane.c    |  2 +-
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 26236691ce4c2..f7fe2e08dc8e2 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -192,7 +192,11 @@ unsigned int mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
 	if (comp->funcs && comp->funcs->supported_rotations)
 		return comp->funcs->supported_rotations(comp->dev);
 
-	return 0;
+	/*
+	 * In order to pass IGT tests, DRM_MODE_ROTATE_0 is required when
+	 * rotation is not supported.
+	 */
+	return DRM_MODE_ROTATE_0;
 }
 
 static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 0ebeaf9830d83..2a767a823c83a 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -288,6 +288,10 @@ unsigned int mtk_ovl_layer_nr(struct device *dev)
 
 unsigned int mtk_ovl_supported_rotations(struct device *dev)
 {
+	/*
+	 * although currently OVL can only do reflection,
+	 * reflect x + reflect y = rotate 180
+	 */
 	return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
 	       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
 }
@@ -296,27 +300,20 @@ int mtk_ovl_layer_check(struct device *dev, unsigned int idx,
 			struct mtk_plane_state *mtk_state)
 {
 	struct drm_plane_state *state = &mtk_state->base;
-	unsigned int rotation = 0;
 
-	rotation = drm_rotation_simplify(state->rotation,
-					 DRM_MODE_ROTATE_0 |
-					 DRM_MODE_REFLECT_X |
-					 DRM_MODE_REFLECT_Y);
-	rotation &= ~DRM_MODE_ROTATE_0;
-
-	/* We can only do reflection, not rotation */
-	if ((rotation & DRM_MODE_ROTATE_MASK) != 0)
+	/* check if any unsupported rotation is set */
+	if (state->rotation & ~mtk_ovl_supported_rotations(dev))
 		return -EINVAL;
 
 	/*
 	 * TODO: Rotating/reflecting YUV buffers is not supported at this time.
 	 *	 Only RGB[AX] variants are supported.
+	 *	 Since DRM_MODE_ROTATE_0 means "no rotation", we should not
+	 *	 reject layers with this property.
 	 */
-	if (state->fb->format->is_yuv && rotation != 0)
+	if (state->fb->format->is_yuv && (state->rotation & ~DRM_MODE_ROTATE_0))
 		return -EINVAL;
 
-	state->rotation = rotation;
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c
index a74b26d359857..1723d4333f371 100644
--- a/drivers/gpu/drm/mediatek/mtk_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_plane.c
@@ -338,7 +338,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
 		return err;
 	}
 
-	if (supported_rotations & ~DRM_MODE_ROTATE_0) {
+	if (supported_rotations) {
 		err = drm_plane_create_rotation_property(plane,
 							 DRM_MODE_ROTATE_0,
 							 supported_rotations);
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 05/14] drm/mediatek: Set DRM mode configs accordingly
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (3 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-04-25  6:54   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 06/14] drm/mediatek: Turn off the layers with zero width or height Shawn Sung
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Set DRM mode configs limitation according to the hardware capabilities
and pass the IGT checks as below:

- The test "graphics.IgtKms.kms_plane" requires a frame buffer with
  width of 4512 pixels (> 4096).
- The test "graphics.IgtKms.kms_cursor_crc" checks if the cursor size is
  defined, and run the test with cursor size from 1x1 to 512x512.

Please notice that the test conditions may change as IGT is updated.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 22 ++++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.h |  3 +++
 2 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 621015b64674d..8e04e9576f7f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -296,6 +296,9 @@ static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = {
 	.conn_routes = mt8188_mtk_ddp_main_routes,
 	.num_conn_routes = ARRAY_SIZE(mt8188_mtk_ddp_main_routes),
 	.mmsys_dev_num = 2,
+	.max_width = 8191,
+	.min_width = 1,
+	.min_height = 1,
 };
 
 static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
@@ -310,6 +313,9 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
 	.main_path = mt8195_mtk_ddp_main,
 	.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
 	.mmsys_dev_num = 2,
+	.max_width = 8191,
+	.min_width = 1,
+	.min_height = 1,
 };
 
 static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
@@ -317,6 +323,9 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
 	.ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
 	.mmsys_id = 1,
 	.mmsys_dev_num = 2,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
 };
 
 static const struct of_device_id mtk_drm_of_ids[] = {
@@ -495,6 +504,15 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 		for (j = 0; j < private->data->mmsys_dev_num; j++) {
 			priv_n = private->all_drm_private[j];
 
+			if (priv_n->data->max_width)
+				drm->mode_config.max_width  = priv_n->data->max_width;
+
+			if (priv_n->data->min_width)
+				drm->mode_config.min_width = priv_n->data->min_width;
+
+			if (priv_n->data->min_height)
+				drm->mode_config.min_height = priv_n->data->min_height;
+
 			if (i == CRTC_MAIN && priv_n->data->main_len) {
 				ret = mtk_crtc_create(drm, priv_n->data->main_path,
 						      priv_n->data->main_len, j,
@@ -522,6 +540,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 		}
 	}
 
+	/* IGT will check if the cursor size is configured */
+	drm->mode_config.cursor_width = drm->mode_config.max_width;
+	drm->mode_config.cursor_height = drm->mode_config.max_height;
+
 	/* Use OVL device for all DMA memory allocations */
 	crtc = drm_crtc_from_index(drm, 0);
 	if (crtc)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 78d698ede1bf8..8917a14d7c0f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -46,6 +46,9 @@ struct mtk_mmsys_driver_data {
 	bool shadow_register;
 	unsigned int mmsys_id;
 	unsigned int mmsys_dev_num;
+
+	int max_width;
+	int min_width, min_height;
 };
 
 struct mtk_drm_private {
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 06/14] drm/mediatek: Turn off the layers with zero width or height
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (4 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 05/14] drm/mediatek: Set DRM mode configs accordingly Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver Shawn Sung
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

We found that IGT (Intel GPU Tool) will try to commit layers with
zero width or height and lead to undefined behaviors in hardware.
Disable the layers in such a situation.

Fixes: 777b7bc86a0a ("UPSTREAM: drm/mediatek: Add ovl_adaptor support for MT8195")
Fixes: fa97fe71f6f9 ("UPSTREAM: drm/mediatek: Add ETHDR support for MT8195")

Reviewed-by: CK Hu <ck.hu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 2 +-
 drivers/gpu/drm/mediatek/mtk_ethdr.c            | 7 ++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 4fbf61c6b5423..494f7bf4a7881 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -158,7 +158,7 @@ void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
 	merge = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MERGE0 + idx];
 	ethdr = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0];

-	if (!pending->enable) {
+	if (!pending->enable || !pending->width || !pending->height) {
 		mtk_merge_stop_cmdq(merge, cmdq_pkt);
 		mtk_mdp_rdma_stop(rdma_l, cmdq_pkt);
 		mtk_mdp_rdma_stop(rdma_r, cmdq_pkt);
diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c
index ac4132210585e..6bf398850e85f 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -160,7 +160,12 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
 	if (idx >= 4)
 		return;

-	if (!pending->enable) {
+	if (!pending->enable || !pending->width || !pending->height) {
+		/*
+		 * instead of disabling layer with MIX_SRC_CON directly
+		 * set the size to 0 to avoid screen shift due to mixer
+		 * mode switch (hardware behavior)
+		 */
 		mtk_ddp_write(cmdq_pkt, 0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(idx));
 		return;
 	}
--
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (5 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 06/14] drm/mediatek: Turn off the layers with zero width or height Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  9:37   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 08/14] drm/mediatek: Support "Pre-multiplied" alpha blending in OVL Shawn Sung
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Support "Pre-multiplied" and "None" blend mode on MediaTek's chips by
adding correct blend mode property when the planes init.
Before this patch, only the "Coverage" mode (default) is supported.

For more information, there are three pixel blend modes in DRM driver:
"None", "Pre-multiplied", and "Coverage".

To understand the difference between these modes, let's take a look at
the following two approaches to do alpha blending:

1. Straight:
dst.RGB = src.RGB * src.A + dst.RGB * (1 - src.A)
This is straightforward and easy to understand, when the source layer is
compositing with the destination layer, it's alpha will affect the
result. This is also known as "post-multiplied", or "Coverage" mode.

2. Pre-multiplied:
dst.RGB = src.RGB + dst.RGB * (1 - src.A)
Since the source RGB have already multiplied its alpha, only destination
RGB need to multiply it. This is the "Pre-multiplied" mode in DRM.

For the "None" blend mode in DRM, it means the pixel alpha is ignored
when compositing the layers, only the constant alpha for the composited
layer will take effects.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_plane.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c
index 1723d4333f371..5bf757a3ef202 100644
--- a/drivers/gpu/drm/mediatek/mtk_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_plane.c
@@ -346,6 +346,17 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
 			DRM_INFO("Create rotation property failed\n");
 	}
 
+	err = drm_plane_create_alpha_property(plane);
+	if (err)
+		DRM_ERROR("failed to create property: alpha\n");
+
+	err = drm_plane_create_blend_mode_property(plane,
+						   BIT(DRM_MODE_BLEND_PREMULTI) |
+						   BIT(DRM_MODE_BLEND_COVERAGE) |
+						   BIT(DRM_MODE_BLEND_PIXEL_NONE));
+	if (err)
+		DRM_ERROR("failed to create property: blend_mode\n");
+
 	drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
 
 	return 0;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 08/14] drm/mediatek: Support "Pre-multiplied" alpha blending in OVL
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (6 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  6:43   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 09/14] drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer Shawn Sung
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Support "Pre-multiplied" blend mode on MediaTek's chips.
Before this patch, only the "coverage" mode is supported.

Please refer to the description of the commit
"drm/mediatek: Support alpha blending in display driver"
for more information.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 84 +++++++++++++++++++++----
 1 file changed, 73 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 2a767a823c83a..b1e5d453316cc 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -38,6 +38,7 @@
 #define DISP_REG_OVL_PITCH_MSB(n)		(0x0040 + 0x20 * (n))
 #define OVL_PITCH_MSB_2ND_SUBBUF			BIT(16)
 #define DISP_REG_OVL_PITCH(n)			(0x0044 + 0x20 * (n))
+#define OVL_CONST_BLEND					BIT(28)
 #define DISP_REG_OVL_RDMA_CTRL(n)		(0x00c0 + 0x20 * (n))
 #define DISP_REG_OVL_RDMA_GMC(n)		(0x00c8 + 0x20 * (n))
 #define DISP_REG_OVL_ADDR_MT2701		0x0040
@@ -51,13 +52,16 @@
 #define GMC_THRESHOLD_HIGH	((1 << GMC_THRESHOLD_BITS) / 4)
 #define GMC_THRESHOLD_LOW	((1 << GMC_THRESHOLD_BITS) / 8)
 
+#define OVL_CON_CLRFMT_MAN	BIT(23)
 #define OVL_CON_BYTE_SWAP	BIT(24)
-#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
+#define OVL_CON_RGB_SWAP	BIT(25)
 #define OVL_CON_CLRFMT_RGB	(1 << 12)
 #define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
 #define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
 #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	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_CLRFMT_MAN)
 #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 ? \
@@ -71,6 +75,24 @@
 #define	OVL_CON_VIRT_FLIP	BIT(9)
 #define	OVL_CON_HORZ_FLIP	BIT(10)
 
+#define OVL_COLOR_ALPHA		GENMASK(31, 24)
+
+static inline bool is_10bit_rgb(u32 fmt)
+{
+	switch (fmt) {
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_BGRA1010102:
+		return true;
+	}
+	return false;
+}
+
 static const u32 mt8173_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
@@ -88,12 +110,20 @@ static const u32 mt8173_formats[] = {
 static const u32 mt8195_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB2101010,
 	DRM_FORMAT_ARGB2101010,
 	DRM_FORMAT_BGRX8888,
 	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_BGRX1010102,
 	DRM_FORMAT_BGRA1010102,
 	DRM_FORMAT_ABGR8888,
 	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_RGBX8888,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_RGBX1010102,
+	DRM_FORMAT_RGBA1010102,
 	DRM_FORMAT_RGB888,
 	DRM_FORMAT_BGR888,
 	DRM_FORMAT_RGB565,
@@ -253,9 +283,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
 	reg = readl(ovl->regs + DISP_REG_OVL_CLRFMT_EXT);
 	reg &= ~OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx);
 
-	if (format == DRM_FORMAT_RGBA1010102 ||
-	    format == DRM_FORMAT_BGRA1010102 ||
-	    format == DRM_FORMAT_ARGB2101010)
+	if (is_10bit_rgb(format))
 		bit_depth = OVL_CON_CLRFMT_10_BIT;
 
 	reg |= OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx);
@@ -273,7 +301,13 @@ void mtk_ovl_config(struct device *dev, unsigned int w,
 	if (w != 0 && h != 0)
 		mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, &ovl->cmdq_reg, ovl->regs,
 				      DISP_REG_OVL_ROI_SIZE);
-	mtk_ddp_write_relaxed(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_ROI_BGCLR);
+
+	/*
+	 * The background color should be opaque black (ARGB),
+	 * otherwise there will be no effect with alpha blend
+	 */
+	mtk_ddp_write_relaxed(cmdq_pkt, OVL_COLOR_ALPHA, &ovl->cmdq_reg,
+			      ovl->regs, DISP_REG_OVL_ROI_BGCLR);
 
 	mtk_ddp_write(cmdq_pkt, 0x1, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RST);
 	mtk_ddp_write(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RST);
@@ -353,7 +387,8 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
 		      DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
+static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt,
+				    unsigned int blend_mode)
 {
 	/* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
 	 * is defined in mediatek HW data sheet.
@@ -372,17 +407,37 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
 		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
+		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
+		       OVL_CON_CLRFMT_ARGB8888 :
+		       OVL_CON_CLRFMT_PARGB8888;
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_RGBA1010102:
 		return OVL_CON_CLRFMT_ARGB8888;
 	case DRM_FORMAT_BGRX8888:
 	case DRM_FORMAT_BGRA8888:
+		return OVL_CON_BYTE_SWAP |
+		       (blend_mode == DRM_MODE_BLEND_COVERAGE ?
+		       OVL_CON_CLRFMT_ARGB8888 :
+		       OVL_CON_CLRFMT_PARGB8888);
+	case DRM_FORMAT_BGRX1010102:
 	case DRM_FORMAT_BGRA1010102:
 		return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
+		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
+		       OVL_CON_CLRFMT_RGBA8888 :
+		       OVL_CON_CLRFMT_PARGB8888;
+	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
 		return OVL_CON_CLRFMT_RGBA8888;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
+		return OVL_CON_RGB_SWAP |
+		       (blend_mode == DRM_MODE_BLEND_COVERAGE ?
+		       OVL_CON_CLRFMT_RGBA8888 :
+		       OVL_CON_CLRFMT_PARGB8888);
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
 		return OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_UYVY:
 		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
@@ -404,6 +459,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 	unsigned int fmt = pending->format;
 	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 ignore_pixel_alpha = 0;
 	unsigned int con;
 	bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
 	union overlay_pitch {
@@ -421,9 +478,14 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	con = ovl_fmt_convert(ovl, fmt);
-	if (state->base.fb && state->base.fb->format->has_alpha)
-		con |= OVL_CON_AEN | OVL_CON_ALPHA;
+	con = ovl_fmt_convert(ovl, fmt, blend_mode);
+	if (state->base.fb) {
+		con |= OVL_CON_AEN;
+		con |= state->base.alpha & OVL_CON_ALPHA;
+	}
+
+	if (state->base.fb && !state->base.fb->format->has_alpha)
+		ignore_pixel_alpha = OVL_CONST_BLEND;
 
 	if (pending->rotation & DRM_MODE_REFLECT_Y) {
 		con |= OVL_CON_VIRT_FLIP;
@@ -440,8 +502,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));
-	mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb, &ovl->cmdq_reg, ovl->regs,
-			      DISP_REG_OVL_PITCH(idx));
+	mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_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,
 			      DISP_REG_OVL_SRC_SIZE(idx));
 	mtk_ddp_write_relaxed(cmdq_pkt, offset, &ovl->cmdq_reg, ovl->regs,
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 09/14] drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (7 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 08/14] drm/mediatek: Support "Pre-multiplied" alpha blending in OVL Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  9:26   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 10/14] drm/mediatek: Support "None" alpha blending in OVL Shawn Sung
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Support "Pre-multiplied" blend mode on MediaTek's chips.
Before this patch, only the "Coverage" mode is supported.

Please refer to the description of the commit
"drm/mediatek: Support alpha blending in display driver"
for more information.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_ethdr.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c
index 6bf398850e85f..4b12ca285e84b 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -5,6 +5,7 @@
 
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
+#include <drm/drm_blend.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/of.h>
@@ -35,6 +36,7 @@
 #define MIX_SRC_L0_EN				BIT(0)
 #define MIX_L_SRC_CON(n)		(0x28 + 0x18 * (n))
 #define NON_PREMULTI_SOURCE			(2 << 12)
+#define PREMULTI_SOURCE				(3 << 12)
 #define MIX_L_SRC_SIZE(n)		(0x30 + 0x18 * (n))
 #define MIX_L_SRC_OFFSET(n)		(0x34 + 0x18 * (n))
 #define MIX_FUNC_DCM0			0x120
@@ -153,7 +155,8 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
 	struct mtk_plane_pending_state *pending = &state->pending;
 	unsigned int offset = (pending->x & 1) << 31 | pending->y << 16 | pending->x;
 	unsigned int align_width = ALIGN_DOWN(pending->width, 2);
-	unsigned int alpha_con = 0;
+	unsigned int mix_con = NON_PREMULTI_SOURCE;
+	bool replace_src_a = false;
 
 	dev_dbg(dev, "%s+ idx:%d", __func__, idx);
 
@@ -170,19 +173,27 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	if (state->base.fb && state->base.fb->format->has_alpha)
-		alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA;
+	mix_con |= MIXER_ALPHA_AEN | (state->base.alpha & MIXER_ALPHA);
 
-	mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1, alpha_con ? false : true,
-				  DEFAULT_9BIT_ALPHA,
+	if (state->base.pixel_blend_mode != DRM_MODE_BLEND_COVERAGE)
+		mix_con |= PREMULTI_SOURCE;
+
+	if (state->base.fb && !state->base.fb->format->has_alpha) {
+		/*
+		 * Mixer doesn't support CONST_BLD mode,
+		 * use a trick to make the output equivalent
+		 */
+		replace_src_a = true;
+	}
+
+	mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1, replace_src_a, MIXER_ALPHA,
 				  pending->x & 1 ? MIXER_INX_MODE_EVEN_EXTEND :
 				  MIXER_INX_MODE_BYPASS, align_width / 2 - 1, cmdq_pkt);
 
 	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &mixer->cmdq_base,
 		      mixer->regs, MIX_L_SRC_SIZE(idx));
 	mtk_ddp_write(cmdq_pkt, offset, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_OFFSET(idx));
-	mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx),
-			   0x1ff);
+	mtk_ddp_write(cmdq_pkt, mix_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx));
 	mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON,
 			   BIT(idx));
 }
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 10/14] drm/mediatek: Support "None" alpha blending in OVL
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (8 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 09/14] drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-22  9:32   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer Shawn Sung
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Support "None" blend mode on MediaTek's chips.

Please refer to the description of the commit
"drm/mediatek: Support alpha blending in display driver"
for more information.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index b1e5d453316cc..a936f338ab79d 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -484,7 +484,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		con |= state->base.alpha & OVL_CON_ALPHA;
 	}
 
-	if (state->base.fb && !state->base.fb->format->has_alpha)
+	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
+	    (state->base.fb && !state->base.fb->format->has_alpha))
 		ignore_pixel_alpha = OVL_CONST_BLEND;
 
 	if (pending->rotation & DRM_MODE_REFLECT_Y) {
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (9 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 10/14] drm/mediatek: Support "None" alpha blending in OVL Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-25  2:03   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 12/14] drm/mediatek: Support CRC in display driver Shawn Sung
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Support "None" blend mode on MediaTek's chips.

Please refer to the description of the commit
"drm/mediatek: Support alpha blending in display driver"
for more information.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_ethdr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c
index 4b12ca285e84b..951e3e82a6a1a 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -178,7 +178,8 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
 	if (state->base.pixel_blend_mode != DRM_MODE_BLEND_COVERAGE)
 		mix_con |= PREMULTI_SOURCE;
 
-	if (state->base.fb && !state->base.fb->format->has_alpha) {
+	if (state->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
+	    (state->base.fb && !state->base.fb->format->has_alpha)) {
 		/*
 		 * Mixer doesn't support CONST_BLD mode,
 		 * use a trick to make the output equivalent
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 12/14] drm/mediatek: Support CRC in display driver
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (10 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-04-01  5:31   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 13/14] drm/mediatek: Support CRC in OVL Shawn Sung
  2024-03-22  5:28 ` [PATCH v6 14/14] drm/mediatek: Support CRC in OVL adaptor Shawn Sung
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

Register CRC related function pointers to support
CRC retrieval.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_crtc.c     | 260 ++++++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_crtc.h     |  38 ++++
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   3 +
 3 files changed, 301 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index d811e4e73a36c..6440c5fb336d7 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
@@ -18,6 +18,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
+#include <drm/drm_vblank_work.h>
 
 #include "mtk_crtc.h"
 #include "mtk_ddp_comp.h"
@@ -69,6 +70,9 @@ struct mtk_crtc {
 	/* lock for display hardware access */
 	struct mutex			hw_lock;
 	bool				config_updating;
+
+	struct mtk_ddp_comp		*crc_provider;
+	struct drm_vblank_work		crc_work;
 };
 
 struct mtk_crtc_state {
@@ -703,6 +707,71 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 	}
 }
 
+static void mtk_crtc_crc_work(struct kthread_work *base)
+{
+	struct drm_vblank_work *work = to_drm_vblank_work(base);
+	struct mtk_crtc *mtk_crtc =
+		container_of(work, typeof(*mtk_crtc), crc_work);
+
+	if (mtk_crtc->base.crc.opened) {
+		struct mtk_ddp_comp *comp = mtk_crtc->crc_provider;
+		u64 vblank = drm_crtc_vblank_count(&mtk_crtc->base);
+
+		comp->funcs->crc_read(comp->dev);
+
+		/* could take more than 50ms to finish */
+		drm_crtc_add_crc_entry(&mtk_crtc->base, true, vblank,
+				       comp->funcs->crc_entry(comp->dev));
+
+		drm_vblank_work_schedule(&mtk_crtc->crc_work, vblank + 1, true);
+	}
+}
+
+static int mtk_crtc_set_crc_source(struct drm_crtc *crtc, const char *src)
+{
+	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
+
+	if (!src)
+		return -EINVAL;
+
+	if (strcmp(src, "auto") != 0) {
+		DRM_ERROR("%s(crtc-%d): unknown source '%s'\n",
+			  __func__, drm_crtc_index(crtc), src);
+		return -EINVAL;
+	}
+
+	/*
+	 * skip the first crc because the first frame (vblank + 1) is configured
+	 * by mtk_crtc_ddp_hw_init() when atomic enable
+	 */
+	drm_vblank_work_schedule(&mtk_crtc->crc_work,
+				 drm_crtc_vblank_count(crtc) + 2, false);
+	return 0;
+}
+
+static int mtk_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src,
+				      size_t *cnt)
+{
+	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_ddp_comp *comp = mtk_crtc->crc_provider;
+
+	if (!comp) {
+		DRM_ERROR("%s(crtc-%d): no crc provider\n",
+			  __func__, drm_crtc_index(crtc));
+		return -ENOENT;
+	}
+
+	if (src && strcmp(src, "auto") != 0) {
+		DRM_ERROR("%s(crtc-%d): unknown source '%s'\n",
+			  __func__, drm_crtc_index(crtc), src);
+		return -EINVAL;
+	}
+
+	*cnt = comp->funcs->crc_cnt(comp->dev);
+
+	return 0;
+}
+
 int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
 			 struct mtk_plane_state *state)
 {
@@ -751,6 +820,8 @@ static void mtk_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	drm_crtc_vblank_on(crtc);
 	mtk_crtc->enabled = true;
+
+	drm_vblank_work_init(&mtk_crtc->crc_work, crtc, mtk_crtc_crc_work);
 }
 
 static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -840,6 +911,8 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
 	.atomic_destroy_state	= mtk_crtc_destroy_state,
 	.enable_vblank		= mtk_crtc_enable_vblank,
 	.disable_vblank		= mtk_crtc_disable_vblank,
+	.set_crc_source		= mtk_crtc_set_crc_source,
+	.verify_crc_source	= mtk_crtc_verify_crc_source,
 };
 
 static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
@@ -1033,6 +1106,11 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 
 			if (comp->funcs->ctm_set)
 				has_ctm = true;
+
+			if (comp->funcs->crc_cnt &&
+			    comp->funcs->crc_entry &&
+			    comp->funcs->crc_read)
+				mtk_crtc->crc_provider = comp;
 		}
 
 		mtk_ddp_comp_register_vblank_cb(comp, mtk_crtc_ddp_irq,
@@ -1136,3 +1214,185 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 
 	return 0;
 }
+
+void mtk_crtc_init_crc(struct mtk_crtc_crc *crc, const u32 *crc_offset_table,
+		       size_t crc_count, u32 reset_offset, u32 reset_mask)
+{
+	crc->ofs = crc_offset_table;
+	crc->cnt = crc_count;
+	crc->rst_ofs = reset_offset;
+	crc->rst_msk = reset_mask;
+	crc->va = kcalloc(crc->cnt, sizeof(*crc->va), GFP_KERNEL);
+	if (!crc->va) {
+		DRM_ERROR("failed to allocate memory for crc\n");
+		crc->cnt = 0;
+	}
+}
+
+void mtk_crtc_read_crc(struct mtk_crtc_crc *crc, void __iomem *reg)
+{
+	if (!crc->cnt || !crc->ofs || !crc->va)
+		return;
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	/* sync to see the most up-to-date copy of the DMA buffer */
+	dma_sync_single_for_cpu(crc->cmdq_client.chan->mbox->dev,
+				crc->pa, crc->cnt * sizeof(*crc->va),
+				DMA_FROM_DEVICE);
+#endif
+}
+
+void mtk_crtc_destroy_crc(struct mtk_crtc_crc *crc)
+{
+	if (!crc->cnt)
+		return;
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	if (crc->pa) {
+		dma_unmap_single(crc->cmdq_client.chan->mbox->dev,
+				 crc->pa, crc->cnt * sizeof(*crc->va),
+				 DMA_TO_DEVICE);
+		crc->pa = 0;
+	}
+	if (crc->cmdq_client.chan) {
+		mtk_drm_cmdq_pkt_destroy(&crc->cmdq_handle);
+		mbox_free_channel(crc->cmdq_client.chan);
+		crc->cmdq_client.chan = NULL;
+	}
+#endif
+	kfree(crc->va);
+	crc->va = NULL;
+	crc->cnt = 0;
+}
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+/**
+ * mtk_crtc_create_crc_cmdq - Create a CMDQ thread for syncing the CRCs
+ * @dev: Kernel device node of the CRC provider
+ * @crc: Pointer of the CRC to init
+ *
+ * This function will create a looping thread on GCE (Global Command Engine) to
+ * keep the CRC up to date by monitoring the assigned event (usually the frame
+ * done event) of the CRC provider, and read the CRCs from the registers to a
+ * shared memory for the workqueue to read. To start/stop the looping thread,
+ * please call `mtk_crtc_start_crc_cmdq()` and `mtk_crtc_stop_crc_cmdq()`
+ * defined blow.
+ *
+ * The reason why we don't update the CRCs with CPU is that the front porch of
+ * 4K60 timing in CEA-861 is less than 60us, and register read/write speed is
+ * relatively unreliable comparing to GCE due to the bus design.
+ *
+ * We must create a new thread instead of using the original one for plane
+ * update is because:
+ * 1. We cannot add another wait-for-event command at the end of cmdq packet, or
+ *    the cmdq callback will delay for too long
+ * 2. Will get the CRC of the previous frame if using the existed wait-for-event
+ *    command which is at the beginning of the packet
+ */
+void mtk_crtc_create_crc_cmdq(struct device *dev, struct mtk_crtc_crc *crc)
+{
+	int i;
+
+	if (!crc->cnt) {
+		dev_warn(dev, "%s: not support\n", __func__);
+		goto cleanup;
+	}
+
+	if (!crc->ofs) {
+		dev_warn(dev, "%s: not defined\n", __func__);
+		goto cleanup;
+	}
+
+	crc->cmdq_client.client.dev = dev;
+	crc->cmdq_client.client.tx_block = false;
+	crc->cmdq_client.client.knows_txdone = true;
+	crc->cmdq_client.client.rx_callback = NULL;
+	crc->cmdq_client.chan = mbox_request_channel(&crc->cmdq_client.client, 0);
+	if (IS_ERR(crc->cmdq_client.chan)) {
+		dev_warn(dev, "%s: failed to create mailbox client\n", __func__);
+		crc->cmdq_client.chan = NULL;
+		goto cleanup;
+	}
+
+	if (mtk_drm_cmdq_pkt_create(&crc->cmdq_client, &crc->cmdq_handle, PAGE_SIZE)) {
+		dev_warn(dev, "%s: failed to create cmdq packet\n", __func__);
+		goto cleanup;
+	}
+
+	if (!crc->va) {
+		dev_warn(dev, "%s: no memory\n", __func__);
+		goto cleanup;
+	}
+
+	/* map the entry to get a dma address for cmdq to store the crc */
+	crc->pa = dma_map_single(crc->cmdq_client.chan->mbox->dev,
+				 crc->va, crc->cnt * sizeof(*crc->va),
+				 DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(crc->cmdq_client.chan->mbox->dev, crc->pa)) {
+		dev_err(dev, "%s: failed to map dma\n", __func__);
+		goto cleanup;
+	}
+
+	if (crc->cmdq_event)
+		cmdq_pkt_wfe(&crc->cmdq_handle, crc->cmdq_event, true);
+
+	for (i = 0; i < crc->cnt; i++) {
+		/* put crc to spr1 register */
+		cmdq_pkt_read_s(&crc->cmdq_handle, crc->cmdq_reg->subsys,
+				crc->cmdq_reg->offset + crc->ofs[i],
+				CMDQ_THR_SPR_IDX1);
+
+		/* copy spr1 register to physical address of the crc */
+		cmdq_pkt_assign(&crc->cmdq_handle, CMDQ_THR_SPR_IDX0,
+				CMDQ_ADDR_HIGH(crc->pa + i * sizeof(*crc->va)));
+		cmdq_pkt_write_s(&crc->cmdq_handle, CMDQ_THR_SPR_IDX0,
+				 CMDQ_ADDR_LOW(crc->pa + i * sizeof(*crc->va)),
+				 CMDQ_THR_SPR_IDX1);
+	}
+	/* reset crc */
+	mtk_ddp_write_mask(&crc->cmdq_handle, ~0, crc->cmdq_reg, 0,
+			   crc->rst_ofs, crc->rst_msk);
+
+	/* clear reset bit */
+	mtk_ddp_write_mask(&crc->cmdq_handle, 0, crc->cmdq_reg, 0,
+			   crc->rst_ofs, crc->rst_msk);
+
+	/* jump to head of the cmdq packet */
+	cmdq_pkt_jump(&crc->cmdq_handle, crc->cmdq_handle.pa_base);
+
+	return;
+cleanup:
+	mtk_crtc_destroy_crc(crc);
+}
+
+/**
+ * mtk_crtc_start_crc_cmdq - Start the GCE looping thread for CRC update
+ * @crc: Pointer of the CRC information
+ */
+void mtk_crtc_start_crc_cmdq(struct mtk_crtc_crc *crc)
+{
+	if (!crc->cmdq_client.chan)
+		return;
+
+	dma_sync_single_for_device(crc->cmdq_client.chan->mbox->dev,
+				   crc->cmdq_handle.pa_base,
+				   crc->cmdq_handle.cmd_buf_size,
+				   DMA_TO_DEVICE);
+	mbox_send_message(crc->cmdq_client.chan, &crc->cmdq_handle);
+	mbox_client_txdone(crc->cmdq_client.chan, 0);
+}
+
+/**
+ * mtk_crtc_stop_crc_cmdq - Stop the GCE looping thread for CRC update
+ * @crc: Pointer of the CRC information
+ */
+void mtk_crtc_stop_crc_cmdq(struct mtk_crtc_crc *crc)
+{
+	if (!crc->cmdq_client.chan)
+		return;
+
+	/* remove all the commands from the cmdq packet */
+	mbox_flush(crc->cmdq_client.chan, 2000);
+}
+#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h b/drivers/gpu/drm/mediatek/mtk_crtc.h
index 388e900b6f4de..a79c4611754e4 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
@@ -14,6 +14,34 @@
 #define MTK_MAX_BPC	10
 #define MTK_MIN_BPC	3
 
+/**
+ * struct mtk_crtc_crc - crc related information
+ * @ofs: register offset of crc
+ * @rst_ofs: register offset of crc reset
+ * @rst_msk: register mask of crc reset
+ * @cnt: count of crc
+ * @va: pointer to the start of crc array
+ * @pa: physical address of the crc for gce to access
+ * @cmdq_event: the event to trigger the cmdq
+ * @cmdq_reg: address of the register that cmdq is going to access
+ * @cmdq_client: handler to control cmdq (mbox channel, thread ...etc.)
+ * @cmdq_handle: cmdq packet to store the commands
+ */
+struct mtk_crtc_crc {
+	const u32 *ofs;
+	u32 rst_ofs;
+	u32 rst_msk;
+	size_t cnt;
+	u32 *va;
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	dma_addr_t pa;
+	u32 cmdq_event;
+	struct cmdq_client_reg *cmdq_reg;
+	struct cmdq_client cmdq_client;
+	struct cmdq_pkt cmdq_handle;
+#endif
+};
+
 void mtk_crtc_commit(struct drm_crtc *crtc);
 int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 		    unsigned int path_len, int priv_data_index,
@@ -25,4 +53,14 @@ void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
 			   struct drm_atomic_state *plane_state);
 struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc);
 
+void mtk_crtc_init_crc(struct mtk_crtc_crc *crc, const u32 *crc_offset_table,
+		       size_t crc_count, u32 reset_offset, u32 reset_mask);
+void mtk_crtc_read_crc(struct mtk_crtc_crc *crc, void __iomem *reg);
+void mtk_crtc_destroy_crc(struct mtk_crtc_crc *crc);
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+void mtk_crtc_create_crc_cmdq(struct device *dev, struct mtk_crtc_crc *crc);
+void mtk_crtc_start_crc_cmdq(struct mtk_crtc_crc *crc);
+void mtk_crtc_stop_crc_cmdq(struct mtk_crtc_crc *crc);
+#endif
+
 #endif /* MTK_CRTC_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index f7fe2e08dc8e2..b9c79e740abe0 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -88,6 +88,9 @@ struct mtk_ddp_comp_funcs {
 	void (*remove)(struct device *dev, struct mtk_mutex *mutex);
 	unsigned int (*encoder_index)(struct device *dev);
 	enum drm_mode_status (*mode_valid)(struct device *dev, const struct drm_display_mode *mode);
+	size_t (*crc_cnt)(struct device *dev);
+	u32 *(*crc_entry)(struct device *dev);
+	void (*crc_read)(struct device *dev);
 };
 
 struct mtk_ddp_comp {
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 13/14] drm/mediatek: Support CRC in OVL
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (11 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 12/14] drm/mediatek: Support CRC in display driver Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  2024-03-26  6:11   ` CK Hu (胡俊光)
  2024-03-22  5:28 ` [PATCH v6 14/14] drm/mediatek: Support CRC in OVL adaptor Shawn Sung
  13 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

We choose OVL as the CRC generator from other hardware
components that are also capable of calculating CRCs,
since its frame done event triggers vblanks, it can be
used as a signal to know when is safe to retrieve CRC of
the frame.

Please note that position of the hardware component
that is chosen as CRC generator in the display path is
significant. For example, while OVL is the first module
in VDOSYS0, its CRC won't be affected by the modules
after it, which means effects applied by PQ, Gamma,
Dither or any other components after OVL won't be
calculated in CRC generation.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c |   3 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h |   3 +
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 198 ++++++++++++++++++++++--
 3 files changed, 194 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 17b0364112922..cb71effda9c2a 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -351,6 +351,9 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
 	.clk_enable = mtk_ovl_clk_enable,
 	.clk_disable = mtk_ovl_clk_disable,
 	.config = mtk_ovl_config,
+	.crc_cnt = mtk_ovl_crc_cnt,
+	.crc_entry = mtk_ovl_crc_entry,
+	.crc_read = mtk_ovl_crc_read,
 	.start = mtk_ovl_start,
 	.stop = mtk_ovl_stop,
 	.register_vblank_cb = mtk_ovl_register_vblank_cb,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 082ac18fe04aa..c476056a5cbb5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -105,6 +105,9 @@ void mtk_ovl_enable_vblank(struct device *dev);
 void mtk_ovl_disable_vblank(struct device *dev);
 const u32 *mtk_ovl_get_formats(struct device *dev);
 size_t mtk_ovl_get_num_formats(struct device *dev);
+size_t mtk_ovl_crc_cnt(struct device *dev);
+u32 *mtk_ovl_crc_entry(struct device *dev);
+void mtk_ovl_crc_read(struct device *dev);
 
 void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
 void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index a936f338ab79d..279e6193e7975 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -24,12 +24,20 @@
 #define OVL_FME_CPL_INT					BIT(1)
 #define DISP_REG_OVL_INTSTA			0x0008
 #define DISP_REG_OVL_EN				0x000c
+#define OVL_EN						BIT(0)
+#define OVL_OP_8BIT_MODE				BIT(4)
+#define OVL_HG_FOVL_CK_ON				BIT(8)
+#define OVL_HF_FOVL_CK_ON				BIT(10)
+#define DISP_REG_OVL_TRIG			0x0010
+#define OVL_CRC_EN					BIT(8)
+#define OVL_CRC_CLR					BIT(9)
 #define DISP_REG_OVL_RST			0x0014
 #define DISP_REG_OVL_ROI_SIZE			0x0020
 #define DISP_REG_OVL_DATAPATH_CON		0x0024
 #define OVL_LAYER_SMI_ID_EN				BIT(0)
 #define OVL_BGCLR_SEL_IN				BIT(2)
 #define OVL_LAYER_AFBC_EN(n)				BIT(4+n)
+#define OVL_OUTPUT_CLAMP				BIT(26)
 #define DISP_REG_OVL_ROI_BGCLR			0x0028
 #define DISP_REG_OVL_SRC_CON			0x002c
 #define DISP_REG_OVL_CON(n)			(0x0030 + 0x20 * (n))
@@ -42,7 +50,26 @@
 #define DISP_REG_OVL_RDMA_CTRL(n)		(0x00c0 + 0x20 * (n))
 #define DISP_REG_OVL_RDMA_GMC(n)		(0x00c8 + 0x20 * (n))
 #define DISP_REG_OVL_ADDR_MT2701		0x0040
+#define DISP_REG_OVL_CRC			0x0270
+#define OVL_CRC_OUT_MASK				GENMASK(30, 0)
 #define DISP_REG_OVL_CLRFMT_EXT			0x02D0
+#define DISP_REG_OVL_CLRFMT_EXT1		0x02D8
+#define OVL_CLRFMT_EXT1_CSC_EN(n)			(1 << (((n) * 4) + 1))
+#define DISP_REG_OVL_Y2R_PARA_R0(n)		(0x0134 + 0x28 * (n))
+#define OVL_Y2R_PARA_C_CF_RMY				(GENMASK(14, 0))
+#define DISP_REG_OVL_Y2R_PARA_G0(n)		(0x013c + 0x28 * (n))
+#define OVL_Y2R_PARA_C_CF_GMU				(GENMASK(30, 16))
+#define DISP_REG_OVL_Y2R_PARA_B1(n)		(0x0148 + 0x28 * (n))
+#define OVL_Y2R_PARA_C_CF_BMV				(GENMASK(14, 0))
+#define DISP_REG_OVL_Y2R_PARA_YUV_A_0(n)	(0x014c + 0x28 * (n))
+#define OVL_Y2R_PARA_C_CF_YA				(GENMASK(10, 0))
+#define OVL_Y2R_PARA_C_CF_UA				(GENMASK(26, 16))
+#define DISP_REG_OVL_Y2R_PARA_YUV_A_1(n)	(0x0150 + 0x28 * (n))
+#define OVL_Y2R_PARA_C_CF_VA				(GENMASK(10, 0))
+#define DISP_REG_OVL_Y2R_PRE_ADD2(n)		(0x0154 + 0x28 * (n))
+#define DISP_REG_OVL_R2R_R0(n)			(0x0500 + 0x40 * (n))
+#define DISP_REG_OVL_R2R_G1(n)			(0x0510 + 0x40 * (n))
+#define DISP_REG_OVL_R2R_B2(n)			(0x0520 + 0x40 * (n))
 #define DISP_REG_OVL_ADDR_MT8173		0x0f40
 #define DISP_REG_OVL_ADDR(ovl, n)		((ovl)->data->addr + 0x20 * (n))
 #define DISP_REG_OVL_HDR_ADDR(ovl, n)		((ovl)->data->addr + 0x20 * (n) + 0x04)
@@ -55,6 +82,8 @@
 #define OVL_CON_CLRFMT_MAN	BIT(23)
 #define OVL_CON_BYTE_SWAP	BIT(24)
 #define OVL_CON_RGB_SWAP	BIT(25)
+#define OVL_CON_MTX_AUTO_DIS	BIT(26)
+#define OVL_CON_MTX_EN		BIT(27)
 #define OVL_CON_CLRFMT_RGB	(1 << 12)
 #define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
 #define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
@@ -62,6 +91,7 @@
 #define OVL_CON_CLRFMT_YUYV	(5 << 12)
 #define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
 #define OVL_CON_CLRFMT_PARGB8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_CLRFMT_MAN)
+#define OVL_CON_MTX_PROGRAMMABLE	(8 << 16)
 #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 ? \
@@ -131,6 +161,10 @@ static const u32 mt8195_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
+static const u32 mt8195_ovl_crc_ofs[] = {
+	DISP_REG_OVL_CRC,
+};
+
 struct mtk_disp_ovl_data {
 	unsigned int addr;
 	unsigned int gmc_bits;
@@ -141,12 +175,15 @@ struct mtk_disp_ovl_data {
 	const u32 *formats;
 	size_t num_formats;
 	bool supports_clrfmt_ext;
+	const u32 *crc_ofs;
+	size_t crc_cnt;
 };
 
 /*
  * struct mtk_disp_ovl - DISP_OVL driver structure
  * @crtc: associated crtc to report vblank events to
  * @data: platform data
+ * @crc: crc related information
  */
 struct mtk_disp_ovl {
 	struct drm_crtc			*crtc;
@@ -156,8 +193,31 @@ struct mtk_disp_ovl {
 	const struct mtk_disp_ovl_data	*data;
 	void				(*vblank_cb)(void *data);
 	void				*vblank_cb_data;
+	resource_size_t			regs_pa;
+	struct mtk_crtc_crc		crc;
 };
 
+size_t mtk_ovl_crc_cnt(struct device *dev)
+{
+	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+	return ovl->crc.cnt;
+}
+
+u32 *mtk_ovl_crc_entry(struct device *dev)
+{
+	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+	return ovl->crc.va;
+}
+
+void mtk_ovl_crc_read(struct device *dev)
+{
+	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+	mtk_crtc_read_crc(&ovl->crc, ovl->regs);
+}
+
 static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
 {
 	struct mtk_disp_ovl *priv = dev_id;
@@ -237,21 +297,40 @@ void mtk_ovl_clk_disable(struct device *dev)
 void mtk_ovl_start(struct device *dev)
 {
 	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+	unsigned int reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
 
-	if (ovl->data->smi_id_en) {
-		unsigned int reg;
+	if (ovl->data->smi_id_en)
+		reg |= OVL_LAYER_SMI_ID_EN;
 
-		reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
-		reg = reg | OVL_LAYER_SMI_ID_EN;
-		writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
+	/*
+	 * When doing Y2R conversion, it's common to get an output
+	 * that is larger than 10 bits (negative numbers).
+	 * Enable this bit to clamp the output to 10 bits per channel
+	 * (should always be enabled)
+	 */
+	reg |= OVL_OUTPUT_CLAMP;
+	writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
+
+	reg = OVL_EN;
+	if (ovl->data->crc_cnt) {
+		/* enable crc  and its related clocks */
+		writel_relaxed(OVL_CRC_EN, ovl->regs + DISP_REG_OVL_TRIG);
+		reg |= OVL_OP_8BIT_MODE | OVL_HG_FOVL_CK_ON | OVL_HF_FOVL_CK_ON;
 	}
-	writel_relaxed(0x1, ovl->regs + DISP_REG_OVL_EN);
+	writel_relaxed(reg, ovl->regs + DISP_REG_OVL_EN);
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	mtk_crtc_start_crc_cmdq(&ovl->crc);
+#endif
 }
 
 void mtk_ovl_stop(struct device *dev)
 {
 	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
 
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	mtk_crtc_stop_crc_cmdq(&ovl->crc);
+#endif
 	writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_EN);
 	if (ovl->data->smi_id_en) {
 		unsigned int reg;
@@ -488,6 +567,83 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 	    (state->base.fb && !state->base.fb->format->has_alpha))
 		ignore_pixel_alpha = OVL_CONST_BLEND;
 
+	/*
+	 * OVL only supports 8 bits data in CRC calculation, transform 10-bit
+	 * RGB to 8-bit RGB by leveraging the ability of the Y2R (YUV-to-RGB)
+	 * hardware to multiply coefficients, although there is nothing to do
+	 * with the YUV format.
+	 */
+	if (ovl->data->supports_clrfmt_ext) {
+		u32 y2r_coef = 0, y2r_offset = 0, r2r_coef = 0, csc_en = 0;
+
+		if (is_10bit_rgb(fmt)) {
+			con |= OVL_CON_MTX_AUTO_DIS | OVL_CON_MTX_EN | OVL_CON_MTX_PROGRAMMABLE;
+
+			/*
+			 * Y2R coefficient setting
+			 * bit 13 is 2^1, bit 12 is 2^0, bit 11 is 2^-1,
+			 * bit 10 is 2^-2 = 0.25
+			 */
+			y2r_coef = BIT(10);
+
+			/* -1 in 10bit */
+			y2r_offset = GENMASK(10, 0) - 1;
+
+			/*
+			 * R2R coefficient setting
+			 * bit 19 is 2^1, bit 18 is 2^0, bit 17 is 2^-1,
+			 * bit 20 is 2^2 = 4
+			 */
+			r2r_coef = BIT(20);
+
+			/* CSC_EN is for R2R */
+			csc_en = OVL_CLRFMT_EXT1_CSC_EN(idx);
+
+			/*
+			 * 1. YUV input data - 1 and shift right for 2 bits to remove it
+			 * [R']   [0.25    0    0]   [Y in - 1]
+			 * [G'] = [   0 0.25    0] * [U in - 1]
+			 * [B']   [   0    0 0.25]   [V in - 1]
+			 *
+			 * 2. shift left for 2 bit letting the last 2 bits become 0
+			 * [R out]   [ 4  0  0]   [R']
+			 * [G out] = [ 0  4  0] * [G']
+			 * [B out]   [ 0  0  4]   [B']
+			 */
+		}
+
+		mtk_ddp_write_mask(cmdq_pkt, y2r_coef,
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_Y2R_PARA_R0(idx),
+				   OVL_Y2R_PARA_C_CF_RMY);
+		mtk_ddp_write_mask(cmdq_pkt, (y2r_coef << 16),
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_Y2R_PARA_G0(idx),
+				   OVL_Y2R_PARA_C_CF_GMU);
+		mtk_ddp_write_mask(cmdq_pkt, y2r_coef,
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_Y2R_PARA_B1(idx),
+				   OVL_Y2R_PARA_C_CF_BMV);
+
+		mtk_ddp_write_mask(cmdq_pkt, y2r_offset,
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_Y2R_PARA_YUV_A_0(idx),
+				   OVL_Y2R_PARA_C_CF_YA);
+		mtk_ddp_write_mask(cmdq_pkt, (y2r_offset << 16),
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_Y2R_PARA_YUV_A_0(idx),
+				   OVL_Y2R_PARA_C_CF_UA);
+		mtk_ddp_write_mask(cmdq_pkt, y2r_offset,
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_Y2R_PARA_YUV_A_1(idx),
+				   OVL_Y2R_PARA_C_CF_VA);
+
+		mtk_ddp_write_relaxed(cmdq_pkt, r2r_coef,
+				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_R2R_R0(idx));
+		mtk_ddp_write_relaxed(cmdq_pkt, r2r_coef,
+				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_R2R_G1(idx));
+		mtk_ddp_write_relaxed(cmdq_pkt, r2r_coef,
+				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_R2R_B2(idx));
+
+		mtk_ddp_write_mask(cmdq_pkt, csc_en,
+				   &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_CLRFMT_EXT1,
+				   OVL_CLRFMT_EXT1_CSC_EN(idx));
+	}
+
 	if (pending->rotation & DRM_MODE_REFLECT_Y) {
 		con |= OVL_CON_VIRT_FLIP;
 		addr += (pending->height - 1) * pending->pitch;
@@ -594,15 +750,31 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 		dev_err(dev, "failed to ioremap ovl\n");
 		return PTR_ERR(priv->regs);
 	}
+
+	priv->data = of_device_get_match_data(dev);
+	platform_set_drvdata(pdev, priv);
+
+	if (priv->data->crc_cnt) {
+		mtk_crtc_init_crc(&priv->crc,
+				  priv->data->crc_ofs, priv->data->crc_cnt,
+				  DISP_REG_OVL_TRIG, OVL_CRC_CLR);
+	}
+
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
 	if (ret)
 		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
-#endif
-
-	priv->data = of_device_get_match_data(dev);
-	platform_set_drvdata(pdev, priv);
 
+	if (priv->data->crc_cnt) {
+		if (of_property_read_u32_index(dev->of_node,
+					       "mediatek,gce-events", 0,
+					       &priv->crc.cmdq_event)) {
+			dev_warn(dev, "failed to get gce-events for crc\n");
+		}
+		priv->crc.cmdq_reg = &priv->cmdq_reg;
+		mtk_crtc_create_crc_cmdq(dev, &priv->crc);
+	}
+#endif
 	ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
 			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
 	if (ret < 0) {
@@ -623,6 +795,10 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 
 static void mtk_disp_ovl_remove(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+	mtk_crtc_destroy_crc(&ovl->crc);
 	component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
 	pm_runtime_disable(&pdev->dev);
 }
@@ -693,6 +869,8 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
 	.formats = mt8195_formats,
 	.num_formats = ARRAY_SIZE(mt8195_formats),
 	.supports_clrfmt_ext = true,
+	.crc_ofs = mt8195_ovl_crc_ofs,
+	.crc_cnt = ARRAY_SIZE(mt8195_ovl_crc_ofs),
 };
 
 static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v6 14/14] drm/mediatek: Support CRC in OVL adaptor
  2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
                   ` (12 preceding siblings ...)
  2024-03-22  5:28 ` [PATCH v6 13/14] drm/mediatek: Support CRC in OVL Shawn Sung
@ 2024-03-22  5:28 ` Shawn Sung
  13 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung @ 2024-03-22  5:28 UTC (permalink / raw
  To: Chun-Kuang Hu, AngeloGioacchino Del Regno
  Cc: Philipp Zabel, David Airlie, Daniel Vetter, Matthias Brugger,
	Bibby Hsieh, CK Hu, Nancy . Lin, Fei Shao, Sean Paul, Jason Chen,
	dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	Hsiao Chien Sung

From: Hsiao Chien Sung <shawn.sung@mediatek.com>

We choose Mixer as CRC generator in OVL adaptor since
its frame done event will trigger vblanks, we can know
when is safe to retrieve CRC of the frame.

In OVL adaptor, there's no image procession after Mixer,
unlike the OVL in VDOSYS0, Mixer's CRC will include all
the effects that are applied to the frame.

Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c       |  3 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |  3 +
 .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c   | 21 +++++++
 drivers/gpu/drm/mediatek/mtk_ethdr.c          | 61 +++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_ethdr.h          |  5 ++
 5 files changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index cb71effda9c2a..8aab373ce67c9 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -406,6 +406,9 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
 	.clk_enable = mtk_ovl_adaptor_clk_enable,
 	.clk_disable = mtk_ovl_adaptor_clk_disable,
 	.config = mtk_ovl_adaptor_config,
+	.crc_cnt = mtk_ovl_adaptor_crc_cnt,
+	.crc_entry = mtk_ovl_adaptor_crc_entry,
+	.crc_read = mtk_ovl_adaptor_crc_read,
 	.start = mtk_ovl_adaptor_start,
 	.stop = mtk_ovl_adaptor_stop,
 	.layer_nr = mtk_ovl_adaptor_layer_nr,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index c476056a5cbb5..24af08b1c86d6 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -138,6 +138,9 @@ const u32 *mtk_ovl_adaptor_get_formats(struct device *dev);
 size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
 enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
 						const struct drm_display_mode *mode);
+size_t mtk_ovl_adaptor_crc_cnt(struct device *dev);
+u32 *mtk_ovl_adaptor_crc_entry(struct device *dev);
+void mtk_ovl_adaptor_crc_read(struct device *dev);
 
 void mtk_rdma_bypass_shadow(struct device *dev);
 int mtk_rdma_clk_enable(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 494f7bf4a7881..9c5e565e6ef92 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -207,6 +207,27 @@ void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
 	mtk_ethdr_layer_config(ethdr, idx, state, cmdq_pkt);
 }
 
+size_t mtk_ovl_adaptor_crc_cnt(struct device *dev)
+{
+	struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+
+	return mtk_ethdr_crc_cnt(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
+}
+
+u32 *mtk_ovl_adaptor_crc_entry(struct device *dev)
+{
+	struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+
+	return mtk_ethdr_crc_entry(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
+}
+
+void mtk_ovl_adaptor_crc_read(struct device *dev)
+{
+	struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
+
+	mtk_ethdr_crc_read(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
+}
+
 void mtk_ovl_adaptor_config(struct device *dev, unsigned int w,
 			    unsigned int h, unsigned int vrefresh,
 			    unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c
index 951e3e82a6a1a..52caf75052d98 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -24,6 +24,9 @@
 #define MIX_FME_CPL_INTEN			BIT(1)
 #define MIX_INTSTA			0x8
 #define MIX_EN				0xc
+#define MIX_TRIG			0x10
+#define MIX_TRIG_CRC_EN				BIT(8)
+#define MIX_TRIG_CRC_RST			BIT(9)
 #define MIX_RST				0x14
 #define MIX_ROI_SIZE			0x18
 #define MIX_DATAPATH_CON		0x1c
@@ -39,6 +42,11 @@
 #define PREMULTI_SOURCE				(3 << 12)
 #define MIX_L_SRC_SIZE(n)		(0x30 + 0x18 * (n))
 #define MIX_L_SRC_OFFSET(n)		(0x34 + 0x18 * (n))
+
+/* CRC register offsets for odd and even lines */
+#define MIX_CRC_ODD			0x110
+#define MIX_CRC_EVEN			0x114
+
 #define MIX_FUNC_DCM0			0x120
 #define MIX_FUNC_DCM1			0x124
 #define MIX_FUNC_DCM_ENABLE			0xffffffff
@@ -82,6 +90,7 @@ struct mtk_ethdr {
 	void			*vblank_cb_data;
 	int			irq;
 	struct reset_control	*reset_ctl;
+	struct mtk_crtc_crc	crc;
 };
 
 static const char * const ethdr_clk_str[] = {
@@ -100,6 +109,32 @@ static const char * const ethdr_clk_str[] = {
 	"vdo_be_async",
 };
 
+static const u32 ethdr_crc_ofs[] = {
+	MIX_CRC_ODD,
+	MIX_CRC_EVEN,
+};
+
+size_t mtk_ethdr_crc_cnt(struct device *dev)
+{
+	struct mtk_ethdr *priv = dev_get_drvdata(dev);
+
+	return priv->crc.cnt;
+}
+
+u32 *mtk_ethdr_crc_entry(struct device *dev)
+{
+	struct mtk_ethdr *priv = dev_get_drvdata(dev);
+
+	return priv->crc.va;
+}
+
+void mtk_ethdr_crc_read(struct device *dev)
+{
+	struct mtk_ethdr *priv = dev_get_drvdata(dev);
+
+	mtk_crtc_read_crc(&priv->crc, priv->ethdr_comp[ETHDR_MIXER].regs);
+}
+
 void mtk_ethdr_register_vblank_cb(struct device *dev,
 				  void (*vblank_cb)(void *),
 				  void *vblank_cb_data)
@@ -256,6 +291,13 @@ void mtk_ethdr_start(struct device *dev)
 	struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER];
 
 	writel(1, mixer->regs + MIX_EN);
+
+	if (priv->crc.cnt) {
+		writel(MIX_TRIG_CRC_EN, mixer->regs + MIX_TRIG);
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+		mtk_crtc_start_crc_cmdq(&priv->crc);
+#endif
+	}
 }
 
 void mtk_ethdr_stop(struct device *dev)
@@ -263,6 +305,9 @@ void mtk_ethdr_stop(struct device *dev)
 	struct mtk_ethdr *priv = dev_get_drvdata(dev);
 	struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER];
 
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	mtk_crtc_stop_crc_cmdq(&priv->crc);
+#endif
 	writel(0, mixer->regs + MIX_EN);
 	writel(1, mixer->regs + MIX_RST);
 	reset_control_reset(priv->reset_ctl);
@@ -317,6 +362,9 @@ static int mtk_ethdr_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
+	mtk_crtc_init_crc(&priv->crc, ethdr_crc_ofs, ARRAY_SIZE(ethdr_crc_ofs),
+			  MIX_TRIG, MIX_TRIG_CRC_RST);
+
 	for (i = 0; i < ETHDR_ID_MAX; i++) {
 		priv->ethdr_comp[i].dev = dev;
 		priv->ethdr_comp[i].regs = of_iomap(dev->of_node, i);
@@ -325,6 +373,16 @@ static int mtk_ethdr_probe(struct platform_device *pdev)
 					      &priv->ethdr_comp[i].cmdq_base, i);
 		if (ret)
 			dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
+
+		if (i == ETHDR_MIXER) {
+			if (of_property_read_u32_index(dev->of_node,
+						       "mediatek,gce-events", i,
+						       &priv->crc.cmdq_event)) {
+				dev_warn(dev, "failed to get gce-events for crc\n");
+			}
+			priv->crc.cmdq_reg = &priv->ethdr_comp[i].cmdq_base;
+			mtk_crtc_create_crc_cmdq(dev, &priv->crc);
+		}
 #endif
 		dev_dbg(dev, "[DRM]regs:0x%p, node:%d\n", priv->ethdr_comp[i].regs, i);
 	}
@@ -365,6 +423,9 @@ static int mtk_ethdr_probe(struct platform_device *pdev)
 
 static int mtk_ethdr_remove(struct platform_device *pdev)
 {
+	struct mtk_ethdr *priv = dev_get_drvdata(&pdev->dev);
+
+	mtk_crtc_destroy_crc(&priv->crc);
 	component_del(&pdev->dev, &mtk_ethdr_component_ops);
 	return 0;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.h b/drivers/gpu/drm/mediatek/mtk_ethdr.h
index 81af9edea3f74..d17d7256bd120 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.h
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.h
@@ -22,4 +22,9 @@ void mtk_ethdr_register_vblank_cb(struct device *dev,
 void mtk_ethdr_unregister_vblank_cb(struct device *dev);
 void mtk_ethdr_enable_vblank(struct device *dev);
 void mtk_ethdr_disable_vblank(struct device *dev);
+
+size_t mtk_ethdr_crc_cnt(struct device *dev);
+u32 *mtk_ethdr_crc_entry(struct device *dev);
+void mtk_ethdr_crc_read(struct device *dev);
+
 #endif
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 08/14] drm/mediatek: Support "Pre-multiplied" alpha blending in OVL
  2024-03-22  5:28 ` [PATCH v6 08/14] drm/mediatek: Support "Pre-multiplied" alpha blending in OVL Shawn Sung
@ 2024-03-22  6:43   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-22  6:43 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Support "Pre-multiplied" blend mode on MediaTek's chips.
> Before this patch, only the "coverage" mode is supported.
> 
> Please refer to the description of the commit
> "drm/mediatek: Support alpha blending in display driver"
> for more information.
> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 84 +++++++++++++++++++++
> ----
>  1 file changed, 73 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index 2a767a823c83a..b1e5d453316cc 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -38,6 +38,7 @@
>  #define DISP_REG_OVL_PITCH_MSB(n)		(0x0040 + 0x20 * (n))
>  #define OVL_PITCH_MSB_2ND_SUBBUF			BIT(16)
>  #define DISP_REG_OVL_PITCH(n)			(0x0044 + 0x20
> * (n))
> +#define OVL_CONST_BLEND					BIT(28)
>  #define DISP_REG_OVL_RDMA_CTRL(n)		(0x00c0 + 0x20 * (n))
>  #define DISP_REG_OVL_RDMA_GMC(n)		(0x00c8 + 0x20 * (n))
>  #define DISP_REG_OVL_ADDR_MT2701		0x0040
> @@ -51,13 +52,16 @@
>  #define GMC_THRESHOLD_HIGH	((1 << GMC_THRESHOLD_BITS) / 4)
>  #define GMC_THRESHOLD_LOW	((1 << GMC_THRESHOLD_BITS) / 8)
>  
> +#define OVL_CON_CLRFMT_MAN	BIT(23)
>  #define OVL_CON_BYTE_SWAP	BIT(24)
> -#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
> +#define OVL_CON_RGB_SWAP	BIT(25)
>  #define OVL_CON_CLRFMT_RGB	(1 << 12)
>  #define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
>  #define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
>  #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	(OVL_CON_CLRFMT_ARGB8888 |
> OVL_CON_CLRFMT_MAN)
>  #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 ?
> \
> @@ -71,6 +75,24 @@
>  #define	OVL_CON_VIRT_FLIP	BIT(9)
>  #define	OVL_CON_HORZ_FLIP	BIT(10)
>  
> +#define OVL_COLOR_ALPHA		GENMASK(31, 24)
> +
> +static inline bool is_10bit_rgb(u32 fmt)
> +{
> +	switch (fmt) {
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_ARGB2101010:
> +	case DRM_FORMAT_RGBX1010102:
> +	case DRM_FORMAT_RGBA1010102:
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_ABGR2101010:
> +	case DRM_FORMAT_BGRX1010102:
> +	case DRM_FORMAT_BGRA1010102:
> +		return true;
> +	}
> +	return false;
> +}
> +
>  static const u32 mt8173_formats[] = {
>  	DRM_FORMAT_XRGB8888,
>  	DRM_FORMAT_ARGB8888,
> @@ -88,12 +110,20 @@ static const u32 mt8173_formats[] = {
>  static const u32 mt8195_formats[] = {
>  	DRM_FORMAT_XRGB8888,
>  	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_XRGB2101010,

As I know, the 'X' in XRGB means garbage data. It's not alpha. And pre-
multiplied alpha formula is:

result = source RGB + (destination RGB * (1 - source alpha))

So pre-multiplied alpha need source alpha. I think XRGB is not related
to pre-multiplied alpha. So separate X-related format to another patch.

>  	DRM_FORMAT_ARGB2101010,
>  	DRM_FORMAT_BGRX8888,
>  	DRM_FORMAT_BGRA8888,
> +	DRM_FORMAT_BGRX1010102,
>  	DRM_FORMAT_BGRA1010102,
>  	DRM_FORMAT_ABGR8888,
>  	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_XBGR2101010,
> +	DRM_FORMAT_ABGR2101010,

It seems 10 bits format has no pre-multiplied alpha function. So
separate 10 bits format modification to another patch.

> +	DRM_FORMAT_RGBX8888,
> +	DRM_FORMAT_RGBA8888,

For RGBA8888, it both has coverage mode and pre-multiplied mode, so
it's not strongly related to pre-multiplied alpha. Separate this to
another patch which add support this new format.

> +	DRM_FORMAT_RGBX1010102,
> +	DRM_FORMAT_RGBA1010102,
>  	DRM_FORMAT_RGB888,
>  	DRM_FORMAT_BGR888,
>  	DRM_FORMAT_RGB565,
> @@ -253,9 +283,7 @@ static void mtk_ovl_set_bit_depth(struct device
> *dev, int idx, u32 format,
>  	reg = readl(ovl->regs + DISP_REG_OVL_CLRFMT_EXT);
>  	reg &= ~OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx);
>  
> -	if (format == DRM_FORMAT_RGBA1010102 ||
> -	    format == DRM_FORMAT_BGRA1010102 ||
> -	    format == DRM_FORMAT_ARGB2101010)
> +	if (is_10bit_rgb(format))
>  		bit_depth = OVL_CON_CLRFMT_10_BIT;
>  
>  	reg |= OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx);
> @@ -273,7 +301,13 @@ void mtk_ovl_config(struct device *dev, unsigned
> int w,
>  	if (w != 0 && h != 0)
>  		mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, &ovl-
> >cmdq_reg, ovl->regs,
>  				      DISP_REG_OVL_ROI_SIZE);
> -	mtk_ddp_write_relaxed(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, 
> DISP_REG_OVL_ROI_BGCLR);
> +
> +	/*
> +	 * The background color should be opaque black (ARGB),
> +	 * otherwise there will be no effect with alpha blend
> +	 */
> +	mtk_ddp_write_relaxed(cmdq_pkt, OVL_COLOR_ALPHA, &ovl-
> >cmdq_reg,
> +			      ovl->regs, DISP_REG_OVL_ROI_BGCLR);

The pre-multiplied alpha formula is:

result = source RGB + (destination RGB * (1 - source alpha))

It does not care destination alpha. Background color is the
destination, so describe more detail why need this modification. For
example, how does hardware calculate with back ground color?

>  
>  	mtk_ddp_write(cmdq_pkt, 0x1, &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_RST);
>  	mtk_ddp_write(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_RST);
> @@ -353,7 +387,8 @@ void mtk_ovl_layer_off(struct device *dev,
> unsigned int idx,
>  		      DISP_REG_OVL_RDMA_CTRL(idx));
>  }
>  
> -static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> unsigned int fmt)
> +static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> unsigned int fmt,
> +				    unsigned int blend_mode)
>  {
>  	/* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
>  	 * is defined in mediatek HW data sheet.
> @@ -372,17 +407,37 @@ static unsigned int ovl_fmt_convert(struct
> mtk_disp_ovl *ovl, unsigned int fmt)
>  		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
>  	case DRM_FORMAT_RGBX8888:
>  	case DRM_FORMAT_RGBA8888:
> +		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> +		       OVL_CON_CLRFMT_ARGB8888 :
> +		       OVL_CON_CLRFMT_PARGB8888;
> +	case DRM_FORMAT_RGBX1010102:
> +	case DRM_FORMAT_RGBA1010102:
>  		return OVL_CON_CLRFMT_ARGB8888;
>  	case DRM_FORMAT_BGRX8888:
>  	case DRM_FORMAT_BGRA8888:
> +		return OVL_CON_BYTE_SWAP |
> +		       (blend_mode == DRM_MODE_BLEND_COVERAGE ?
> +		       OVL_CON_CLRFMT_ARGB8888 :
> +		       OVL_CON_CLRFMT_PARGB8888);
> +	case DRM_FORMAT_BGRX1010102:
>  	case DRM_FORMAT_BGRA1010102:
>  		return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP;
>  	case DRM_FORMAT_XRGB8888:
>  	case DRM_FORMAT_ARGB8888:
> +		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> +		       OVL_CON_CLRFMT_RGBA8888 :
> +		       OVL_CON_CLRFMT_PARGB8888;
> +	case DRM_FORMAT_XRGB2101010:
>  	case DRM_FORMAT_ARGB2101010:
>  		return OVL_CON_CLRFMT_RGBA8888;
>  	case DRM_FORMAT_XBGR8888:
>  	case DRM_FORMAT_ABGR8888:
> +		return OVL_CON_RGB_SWAP |
> +		       (blend_mode == DRM_MODE_BLEND_COVERAGE ?
> +		       OVL_CON_CLRFMT_RGBA8888 :
> +		       OVL_CON_CLRFMT_PARGB8888);
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_ABGR2101010:
>  		return OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP;
>  	case DRM_FORMAT_UYVY:
>  		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
> @@ -404,6 +459,8 @@ void mtk_ovl_layer_config(struct device *dev,
> unsigned int idx,
>  	unsigned int fmt = pending->format;
>  	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 ignore_pixel_alpha = 0;
>  	unsigned int con;
>  	bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
>  	union overlay_pitch {
> @@ -421,9 +478,14 @@ void mtk_ovl_layer_config(struct device *dev,
> unsigned int idx,
>  		return;
>  	}
>  
> -	con = ovl_fmt_convert(ovl, fmt);
> -	if (state->base.fb && state->base.fb->format->has_alpha)
> -		con |= OVL_CON_AEN | OVL_CON_ALPHA;
> +	con = ovl_fmt_convert(ovl, fmt, blend_mode);
> +	if (state->base.fb) {
> +		con |= OVL_CON_AEN;
> +		con |= state->base.alpha & OVL_CON_ALPHA;

Now support pixel alpha, and this seems to support plane alpha. So
separate this to another patch. If possible, describe how plane alpha
calculate with pixel alpha.

> +	}
> +
> +	if (state->base.fb && !state->base.fb->format->has_alpha)
> +		ignore_pixel_alpha = OVL_CONST_BLEND;

Ditto.

Regards,
CK

>  
>  	if (pending->rotation & DRM_MODE_REFLECT_Y) {
>  		con |= OVL_CON_VIRT_FLIP;
> @@ -440,8 +502,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));
> -	mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb,
> &ovl->cmdq_reg, ovl->regs,
> -			      DISP_REG_OVL_PITCH(idx));
> +	mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_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,
>  			      DISP_REG_OVL_SRC_SIZE(idx));
>  	mtk_ddp_write_relaxed(cmdq_pkt, offset, &ovl->cmdq_reg, ovl-
> >regs,

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property
  2024-03-22  5:28 ` [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property Shawn Sung
@ 2024-03-22  9:02   ` CK Hu (胡俊光)
  2024-03-25  1:52     ` CK Hu (胡俊光)
  0 siblings, 1 reply; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-22  9:02 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Always add DRM_MODE_ROTATE_0 to rotation property to meet
> IGT's (Intel GPU Tools) requirement.

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> 
> Reviewed-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.h |  6 +++++-
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 21 +++++++++------------
>  drivers/gpu/drm/mediatek/mtk_plane.c    |  2 +-
>  3 files changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 26236691ce4c2..f7fe2e08dc8e2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -192,7 +192,11 @@ unsigned int
> mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
>  	if (comp->funcs && comp->funcs->supported_rotations)
>  		return comp->funcs->supported_rotations(comp->dev);
>  
> -	return 0;
> +	/*
> +	 * In order to pass IGT tests, DRM_MODE_ROTATE_0 is required
> when
> +	 * rotation is not supported.
> +	 */
> +	return DRM_MODE_ROTATE_0;
>  }
>  
>  static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp
> *comp)
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index 0ebeaf9830d83..2a767a823c83a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -288,6 +288,10 @@ unsigned int mtk_ovl_layer_nr(struct device
> *dev)
>  
>  unsigned int mtk_ovl_supported_rotations(struct device *dev)
>  {
> +	/*
> +	 * although currently OVL can only do reflection,
> +	 * reflect x + reflect y = rotate 180
> +	 */
>  	return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
>  	       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
>  }
> @@ -296,27 +300,20 @@ int mtk_ovl_layer_check(struct device *dev,
> unsigned int idx,
>  			struct mtk_plane_state *mtk_state)
>  {
>  	struct drm_plane_state *state = &mtk_state->base;
> -	unsigned int rotation = 0;
>  
> -	rotation = drm_rotation_simplify(state->rotation,
> -					 DRM_MODE_ROTATE_0 |
> -					 DRM_MODE_REFLECT_X |
> -					 DRM_MODE_REFLECT_Y);
> -	rotation &= ~DRM_MODE_ROTATE_0;
> -
> -	/* We can only do reflection, not rotation */
> -	if ((rotation & DRM_MODE_ROTATE_MASK) != 0)
> +	/* check if any unsupported rotation is set */
> +	if (state->rotation & ~mtk_ovl_supported_rotations(dev))
>  		return -EINVAL;
>  
>  	/*
>  	 * TODO: Rotating/reflecting YUV buffers is not supported at
> this time.
>  	 *	 Only RGB[AX] variants are supported.
> +	 *	 Since DRM_MODE_ROTATE_0 means "no rotation", we
> should not
> +	 *	 reject layers with this property.
>  	 */
> -	if (state->fb->format->is_yuv && rotation != 0)
> +	if (state->fb->format->is_yuv && (state->rotation &
> ~DRM_MODE_ROTATE_0))
>  		return -EINVAL;
>  
> -	state->rotation = rotation;
> -
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c
> b/drivers/gpu/drm/mediatek/mtk_plane.c
> index a74b26d359857..1723d4333f371 100644
> --- a/drivers/gpu/drm/mediatek/mtk_plane.c
> +++ b/drivers/gpu/drm/mediatek/mtk_plane.c
> @@ -338,7 +338,7 @@ int mtk_plane_init(struct drm_device *dev, struct
> drm_plane *plane,
>  		return err;
>  	}
>  
> -	if (supported_rotations & ~DRM_MODE_ROTATE_0) {
> +	if (supported_rotations) {
>  		err = drm_plane_create_rotation_property(plane,
>  							 DRM_MODE_ROTAT
> E_0,
>  							 supported_rota
> tions);

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 09/14] drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer
  2024-03-22  5:28 ` [PATCH v6 09/14] drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer Shawn Sung
@ 2024-03-22  9:26   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-22  9:26 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Support "Pre-multiplied" blend mode on MediaTek's chips.
> Before this patch, only the "Coverage" mode is supported.
> 
> Please refer to the description of the commit
> "drm/mediatek: Support alpha blending in display driver"
> for more information.
> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_ethdr.c | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c
> b/drivers/gpu/drm/mediatek/mtk_ethdr.c
> index 6bf398850e85f..4b12ca285e84b 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
> @@ -5,6 +5,7 @@
>  
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_framebuffer.h>
> +#include <drm/drm_blend.h>
>  #include <linux/clk.h>
>  #include <linux/component.h>
>  #include <linux/of.h>
> @@ -35,6 +36,7 @@
>  #define MIX_SRC_L0_EN				BIT(0)
>  #define MIX_L_SRC_CON(n)		(0x28 + 0x18 * (n))
>  #define NON_PREMULTI_SOURCE			(2 << 12)
> +#define PREMULTI_SOURCE				(3 << 12)
>  #define MIX_L_SRC_SIZE(n)		(0x30 + 0x18 * (n))
>  #define MIX_L_SRC_OFFSET(n)		(0x34 + 0x18 * (n))
>  #define MIX_FUNC_DCM0			0x120
> @@ -153,7 +155,8 @@ void mtk_ethdr_layer_config(struct device *dev,
> unsigned int idx,
>  	struct mtk_plane_pending_state *pending = &state->pending;
>  	unsigned int offset = (pending->x & 1) << 31 | pending->y << 16
> | pending->x;
>  	unsigned int align_width = ALIGN_DOWN(pending->width, 2);
> -	unsigned int alpha_con = 0;
> +	unsigned int mix_con = NON_PREMULTI_SOURCE;

I think you should not assign here. You should choose one of
PREMULTI_SOURCE or NON_PREMULTI_SOURCE later.

> +	bool replace_src_a = false;
>  
>  	dev_dbg(dev, "%s+ idx:%d", __func__, idx);
>  
> @@ -170,19 +173,27 @@ void mtk_ethdr_layer_config(struct device *dev,
> unsigned int idx,
>  		return;
>  	}
>  
> -	if (state->base.fb && state->base.fb->format->has_alpha)
> -		alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA;
> +	mix_con |= MIXER_ALPHA_AEN | (state->base.alpha & MIXER_ALPHA);

Now support pixel alpha, and this seems to support plane alpha.
Separate this to another patch.

>  
> -	mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1, alpha_con ?
> false : true,
> -				  DEFAULT_9BIT_ALPHA,
> +	if (state->base.pixel_blend_mode != DRM_MODE_BLEND_COVERAGE)
> +		mix_con |= PREMULTI_SOURCE;
> +
> +	if (state->base.fb && !state->base.fb->format->has_alpha) {
> +		/*
> +		 * Mixer doesn't support CONST_BLD mode,
> +		 * use a trick to make the output equivalent
> +		 */
> +		replace_src_a = true;

Ditto.

Regards,
CK

> +	}
> +
> +	mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1,
> replace_src_a, MIXER_ALPHA,
>  				  pending->x & 1 ?
> MIXER_INX_MODE_EVEN_EXTEND :
>  				  MIXER_INX_MODE_BYPASS, align_width /
> 2 - 1, cmdq_pkt);
>  
>  	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width,
> &mixer->cmdq_base,
>  		      mixer->regs, MIX_L_SRC_SIZE(idx));
>  	mtk_ddp_write(cmdq_pkt, offset, &mixer->cmdq_base, mixer->regs, 
> MIX_L_SRC_OFFSET(idx));
> -	mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base,
> mixer->regs, MIX_L_SRC_CON(idx),
> -			   0x1ff);
> +	mtk_ddp_write(cmdq_pkt, mix_con, &mixer->cmdq_base, mixer-
> >regs, MIX_L_SRC_CON(idx));
>  	mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base,
> mixer->regs, MIX_SRC_CON,
>  			   BIT(idx));
>  }

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 10/14] drm/mediatek: Support "None" alpha blending in OVL
  2024-03-22  5:28 ` [PATCH v6 10/14] drm/mediatek: Support "None" alpha blending in OVL Shawn Sung
@ 2024-03-22  9:32   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-22  9:32 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Support "None" blend mode on MediaTek's chips.
> 
> Please refer to the description of the commit
> "drm/mediatek: Support alpha blending in display driver"
> for more information.

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index b1e5d453316cc..a936f338ab79d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -484,7 +484,8 @@ void mtk_ovl_layer_config(struct device *dev,
> unsigned int idx,
>  		con |= state->base.alpha & OVL_CON_ALPHA;
>  	}
>  
> -	if (state->base.fb && !state->base.fb->format->has_alpha)
> +	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
> +	    (state->base.fb && !state->base.fb->format->has_alpha))
>  		ignore_pixel_alpha = OVL_CONST_BLEND;
>  
>  	if (pending->rotation & DRM_MODE_REFLECT_Y) {

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver
  2024-03-22  5:28 ` [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver Shawn Sung
@ 2024-03-22  9:37   ` CK Hu (胡俊光)
  2024-03-28  2:52     ` Shawn Sung (宋孝謙)
  0 siblings, 1 reply; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-22  9:37 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Support "Pre-multiplied" and "None" blend mode on MediaTek's chips by
> adding correct blend mode property when the planes init.
> Before this patch, only the "Coverage" mode (default) is supported.
> 
> For more information, there are three pixel blend modes in DRM
> driver:
> "None", "Pre-multiplied", and "Coverage".
> 
> To understand the difference between these modes, let's take a look
> at
> the following two approaches to do alpha blending:
> 
> 1. Straight:
> dst.RGB = src.RGB * src.A + dst.RGB * (1 - src.A)
> This is straightforward and easy to understand, when the source layer
> is
> compositing with the destination layer, it's alpha will affect the
> result. This is also known as "post-multiplied", or "Coverage" mode.
> 
> 2. Pre-multiplied:
> dst.RGB = src.RGB + dst.RGB * (1 - src.A)
> Since the source RGB have already multiplied its alpha, only
> destination
> RGB need to multiply it. This is the "Pre-multiplied" mode in DRM.
> 
> For the "None" blend mode in DRM, it means the pixel alpha is ignored
> when compositing the layers, only the constant alpha for the
> composited
> layer will take effects.
> 
> Reviewed-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_plane.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c
> b/drivers/gpu/drm/mediatek/mtk_plane.c
> index 1723d4333f371..5bf757a3ef202 100644
> --- a/drivers/gpu/drm/mediatek/mtk_plane.c
> +++ b/drivers/gpu/drm/mediatek/mtk_plane.c
> @@ -346,6 +346,17 @@ int mtk_plane_init(struct drm_device *dev,
> struct drm_plane *plane,
>  			DRM_INFO("Create rotation property failed\n");
>  	}
>  
> +	err = drm_plane_create_alpha_property(plane);
> +	if (err)
> +		DRM_ERROR("failed to create property: alpha\n");
> +
> +	err = drm_plane_create_blend_mode_property(plane,
> +						   BIT(DRM_MODE_BLEND_P
> REMULTI) |
> +						   BIT(DRM_MODE_BLEND_C
> OVERAGE) |
> +						   BIT(DRM_MODE_BLEND_P
> IXEL_NONE));

After all sub driver support these function, then create blend
property. So move this patch after all sub driver support these blend
mode.

Regards,
CK

> +	if (err)
> +		DRM_ERROR("failed to create property: blend_mode\n");
> +
>  	drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
>  
>  	return 0;

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property
  2024-03-22  9:02   ` CK Hu (胡俊光)
@ 2024-03-25  1:52     ` CK Hu (胡俊光)
  2024-03-28  2:50       ` Shawn Sung (宋孝謙)
  0 siblings, 1 reply; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-25  1:52 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 17:02 +0800, CK Hu wrote:
> Hi, Shawn:
> 
> On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> > From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> > 
> > Always add DRM_MODE_ROTATE_0 to rotation property to meet
> > IGT's (Intel GPU Tools) requirement.
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 
> > 
> > Reviewed-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@collabora.com>
> > Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> > ---
> >  drivers/gpu/drm/mediatek/mtk_ddp_comp.h |  6 +++++-
> >  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 21 +++++++++------------
> >  drivers/gpu/drm/mediatek/mtk_plane.c    |  2 +-
> >  3 files changed, 15 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index 26236691ce4c2..f7fe2e08dc8e2 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -192,7 +192,11 @@ unsigned int
> > mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
> >  	if (comp->funcs && comp->funcs->supported_rotations)
> >  		return comp->funcs->supported_rotations(comp->dev);
> >  
> > -	return 0;
> > +	/*
> > +	 * In order to pass IGT tests, DRM_MODE_ROTATE_0 is required
> > when
> > +	 * rotation is not supported.
> > +	 */
> > +	return DRM_MODE_ROTATE_0;
> >  }
> >  
> >  static inline unsigned int mtk_ddp_comp_layer_nr(struct
> > mtk_ddp_comp
> > *comp)
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > index 0ebeaf9830d83..2a767a823c83a 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > @@ -288,6 +288,10 @@ unsigned int mtk_ovl_layer_nr(struct device
> > *dev)
> >  
> >  unsigned int mtk_ovl_supported_rotations(struct device *dev)
> >  {
> > +	/*
> > +	 * although currently OVL can only do reflection,
> > +	 * reflect x + reflect y = rotate 180
> > +	 */

Sorry, this comment is not related to DRM_MODE_ROTATE_0, so after
removing this comment,

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> >  	return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
> >  	       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
> >  }
> > @@ -296,27 +300,20 @@ int mtk_ovl_layer_check(struct device *dev,
> > unsigned int idx,
> >  			struct mtk_plane_state *mtk_state)
> >  {
> >  	struct drm_plane_state *state = &mtk_state->base;
> > -	unsigned int rotation = 0;
> >  
> > -	rotation = drm_rotation_simplify(state->rotation,
> > -					 DRM_MODE_ROTATE_0 |
> > -					 DRM_MODE_REFLECT_X |
> > -					 DRM_MODE_REFLECT_Y);
> > -	rotation &= ~DRM_MODE_ROTATE_0;
> > -
> > -	/* We can only do reflection, not rotation */
> > -	if ((rotation & DRM_MODE_ROTATE_MASK) != 0)
> > +	/* check if any unsupported rotation is set */
> > +	if (state->rotation & ~mtk_ovl_supported_rotations(dev))
> >  		return -EINVAL;
> >  
> >  	/*
> >  	 * TODO: Rotating/reflecting YUV buffers is not supported at
> > this time.
> >  	 *	 Only RGB[AX] variants are supported.
> > +	 *	 Since DRM_MODE_ROTATE_0 means "no rotation", we
> > should not
> > +	 *	 reject layers with this property.
> >  	 */
> > -	if (state->fb->format->is_yuv && rotation != 0)
> > +	if (state->fb->format->is_yuv && (state->rotation &
> > ~DRM_MODE_ROTATE_0))
> >  		return -EINVAL;
> >  
> > -	state->rotation = rotation;
> > -
> >  	return 0;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c
> > b/drivers/gpu/drm/mediatek/mtk_plane.c
> > index a74b26d359857..1723d4333f371 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_plane.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_plane.c
> > @@ -338,7 +338,7 @@ int mtk_plane_init(struct drm_device *dev,
> > struct
> > drm_plane *plane,
> >  		return err;
> >  	}
> >  
> > -	if (supported_rotations & ~DRM_MODE_ROTATE_0) {
> > +	if (supported_rotations) {
> >  		err = drm_plane_create_rotation_property(plane,
> >  							 DRM_MODE_ROTAT
> > E_0,
> >  							 supported_rota
> > tions);

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer
  2024-03-22  5:28 ` [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer Shawn Sung
@ 2024-03-25  2:03   ` CK Hu (胡俊光)
  2024-03-28  2:56     ` Shawn Sung (宋孝謙)
  0 siblings, 1 reply; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-25  2:03 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Support "None" blend mode on MediaTek's chips.
> 
> Please refer to the description of the commit
> "drm/mediatek: Support alpha blending in display driver"
> for more information.

But I would like you to describe the information in this patch instead
of referring to another patch. This patch could describe more detail,
and the integration patch could describe more brief.

Regards,
CK

> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_ethdr.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c
> b/drivers/gpu/drm/mediatek/mtk_ethdr.c
> index 4b12ca285e84b..951e3e82a6a1a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
> @@ -178,7 +178,8 @@ void mtk_ethdr_layer_config(struct device *dev,
> unsigned int idx,
>  	if (state->base.pixel_blend_mode != DRM_MODE_BLEND_COVERAGE)
>  		mix_con |= PREMULTI_SOURCE;
>  
> -	if (state->base.fb && !state->base.fb->format->has_alpha) {
> +	if (state->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE
> ||
> +	    (state->base.fb && !state->base.fb->format->has_alpha)) {
>  		/*
>  		 * Mixer doesn't support CONST_BLD mode,
>  		 * use a trick to make the output equivalent

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 13/14] drm/mediatek: Support CRC in OVL
  2024-03-22  5:28 ` [PATCH v6 13/14] drm/mediatek: Support CRC in OVL Shawn Sung
@ 2024-03-26  6:11   ` CK Hu (胡俊光)
  2024-03-28  3:22     ` Shawn Sung (宋孝謙)
  0 siblings, 1 reply; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-26  6:11 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> We choose OVL as the CRC generator from other hardware
> components that are also capable of calculating CRCs,
> since its frame done event triggers vblanks, it can be
> used as a signal to know when is safe to retrieve CRC of
> the frame.
> 
> Please note that position of the hardware component
> that is chosen as CRC generator in the display path is
> significant. For example, while OVL is the first module
> in VDOSYS0, its CRC won't be affected by the modules
> after it, which means effects applied by PQ, Gamma,
> Dither or any other components after OVL won't be
> calculated in CRC generation.
> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.c |   3 +
>  drivers/gpu/drm/mediatek/mtk_disp_drv.h |   3 +
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 198
> ++++++++++++++++++++++--
>  3 files changed, 194 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index 17b0364112922..cb71effda9c2a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -351,6 +351,9 @@ static const struct mtk_ddp_comp_funcs ddp_ovl =
> {
>  	.clk_enable = mtk_ovl_clk_enable,
>  	.clk_disable = mtk_ovl_clk_disable,
>  	.config = mtk_ovl_config,
> +	.crc_cnt = mtk_ovl_crc_cnt,
> +	.crc_entry = mtk_ovl_crc_entry,
> +	.crc_read = mtk_ovl_crc_read,
>  	.start = mtk_ovl_start,
>  	.stop = mtk_ovl_stop,
>  	.register_vblank_cb = mtk_ovl_register_vblank_cb,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 082ac18fe04aa..c476056a5cbb5 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -105,6 +105,9 @@ void mtk_ovl_enable_vblank(struct device *dev);
>  void mtk_ovl_disable_vblank(struct device *dev);
>  const u32 *mtk_ovl_get_formats(struct device *dev);
>  size_t mtk_ovl_get_num_formats(struct device *dev);
> +size_t mtk_ovl_crc_cnt(struct device *dev);
> +u32 *mtk_ovl_crc_entry(struct device *dev);
> +void mtk_ovl_crc_read(struct device *dev);
>  
>  void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex
> *mutex);
>  void mtk_ovl_adaptor_remove_comp(struct device *dev, struct
> mtk_mutex *mutex);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index a936f338ab79d..279e6193e7975 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -24,12 +24,20 @@
>  #define OVL_FME_CPL_INT					BIT(1)
>  #define DISP_REG_OVL_INTSTA			0x0008
>  #define DISP_REG_OVL_EN				0x000c
> +#define OVL_EN						BIT(0)
> +#define OVL_OP_8BIT_MODE				BIT(4)
> +#define OVL_HG_FOVL_CK_ON				BIT(8)
> +#define OVL_HF_FOVL_CK_ON				BIT(10)
> +#define DISP_REG_OVL_TRIG			0x0010
> +#define OVL_CRC_EN					BIT(8)
> +#define OVL_CRC_CLR					BIT(9)
>  #define DISP_REG_OVL_RST			0x0014
>  #define DISP_REG_OVL_ROI_SIZE			0x0020
>  #define DISP_REG_OVL_DATAPATH_CON		0x0024
>  #define OVL_LAYER_SMI_ID_EN				BIT(0)
>  #define OVL_BGCLR_SEL_IN				BIT(2)
>  #define OVL_LAYER_AFBC_EN(n)				BIT(4+n)
> +#define OVL_OUTPUT_CLAMP				BIT(26)
>  #define DISP_REG_OVL_ROI_BGCLR			0x0028
>  #define DISP_REG_OVL_SRC_CON			0x002c
>  #define DISP_REG_OVL_CON(n)			(0x0030 + 0x20 * (n))
> @@ -42,7 +50,26 @@
>  #define DISP_REG_OVL_RDMA_CTRL(n)		(0x00c0 + 0x20 * (n))
>  #define DISP_REG_OVL_RDMA_GMC(n)		(0x00c8 + 0x20 * (n))
>  #define DISP_REG_OVL_ADDR_MT2701		0x0040
> +#define DISP_REG_OVL_CRC			0x0270
> +#define OVL_CRC_OUT_MASK				GENMASK(30, 0)
>  #define DISP_REG_OVL_CLRFMT_EXT			0x02D0
> +#define DISP_REG_OVL_CLRFMT_EXT1		0x02D8
> +#define OVL_CLRFMT_EXT1_CSC_EN(n)			(1 << (((n) *
> 4) + 1))
> +#define DISP_REG_OVL_Y2R_PARA_R0(n)		(0x0134 + 0x28 * (n))
> +#define OVL_Y2R_PARA_C_CF_RMY				(GENMAS
> K(14, 0))
> +#define DISP_REG_OVL_Y2R_PARA_G0(n)		(0x013c + 0x28 * (n))
> +#define OVL_Y2R_PARA_C_CF_GMU				(GENMAS
> K(30, 16))
> +#define DISP_REG_OVL_Y2R_PARA_B1(n)		(0x0148 + 0x28 * (n))
> +#define OVL_Y2R_PARA_C_CF_BMV				(GENMAS
> K(14, 0))
> +#define DISP_REG_OVL_Y2R_PARA_YUV_A_0(n)	(0x014c + 0x28 * (n))
> +#define OVL_Y2R_PARA_C_CF_YA				(GENMASK(10,
> 0))
> +#define OVL_Y2R_PARA_C_CF_UA				(GENMASK(26,
> 16))
> +#define DISP_REG_OVL_Y2R_PARA_YUV_A_1(n)	(0x0150 + 0x28 * (n))
> +#define OVL_Y2R_PARA_C_CF_VA				(GENMASK(10,
> 0))
> +#define DISP_REG_OVL_Y2R_PRE_ADD2(n)		(0x0154 + 0x28 * (n))
> +#define DISP_REG_OVL_R2R_R0(n)			(0x0500 + 0x40
> * (n))
> +#define DISP_REG_OVL_R2R_G1(n)			(0x0510 + 0x40
> * (n))
> +#define DISP_REG_OVL_R2R_B2(n)			(0x0520 + 0x40
> * (n))
>  #define DISP_REG_OVL_ADDR_MT8173		0x0f40
>  #define DISP_REG_OVL_ADDR(ovl, n)		((ovl)->data->addr +
> 0x20 * (n))
>  #define DISP_REG_OVL_HDR_ADDR(ovl, n)		((ovl)->data-
> >addr + 0x20 * (n) + 0x04)
> @@ -55,6 +82,8 @@
>  #define OVL_CON_CLRFMT_MAN	BIT(23)
>  #define OVL_CON_BYTE_SWAP	BIT(24)
>  #define OVL_CON_RGB_SWAP	BIT(25)
> +#define OVL_CON_MTX_AUTO_DIS	BIT(26)
> +#define OVL_CON_MTX_EN		BIT(27)
>  #define OVL_CON_CLRFMT_RGB	(1 << 12)
>  #define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
>  #define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
> @@ -62,6 +91,7 @@
>  #define OVL_CON_CLRFMT_YUYV	(5 << 12)
>  #define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
>  #define OVL_CON_CLRFMT_PARGB8888	(OVL_CON_CLRFMT_ARGB8888 |
> OVL_CON_CLRFMT_MAN)
> +#define OVL_CON_MTX_PROGRAMMABLE	(8 << 16)
>  #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 ?
> \
> @@ -131,6 +161,10 @@ static const u32 mt8195_formats[] = {
>  	DRM_FORMAT_YUYV,
>  };
>  
> +static const u32 mt8195_ovl_crc_ofs[] = {
> +	DISP_REG_OVL_CRC,
> +};
> +
>  struct mtk_disp_ovl_data {
>  	unsigned int addr;
>  	unsigned int gmc_bits;
> @@ -141,12 +175,15 @@ struct mtk_disp_ovl_data {
>  	const u32 *formats;
>  	size_t num_formats;
>  	bool supports_clrfmt_ext;
> +	const u32 *crc_ofs;
> +	size_t crc_cnt;
>  };
>  
>  /*
>   * struct mtk_disp_ovl - DISP_OVL driver structure
>   * @crtc: associated crtc to report vblank events to
>   * @data: platform data
> + * @crc: crc related information
>   */
>  struct mtk_disp_ovl {
>  	struct drm_crtc			*crtc;
> @@ -156,8 +193,31 @@ struct mtk_disp_ovl {
>  	const struct mtk_disp_ovl_data	*data;
>  	void				(*vblank_cb)(void *data);
>  	void				*vblank_cb_data;
> +	resource_size_t			regs_pa;
> +	struct mtk_crtc_crc		crc;
>  };
>  
> +size_t mtk_ovl_crc_cnt(struct device *dev)
> +{
> +	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
> +
> +	return ovl->crc.cnt;
> +}
> +
> +u32 *mtk_ovl_crc_entry(struct device *dev)
> +{
> +	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
> +
> +	return ovl->crc.va;
> +}
> +
> +void mtk_ovl_crc_read(struct device *dev)
> +{
> +	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
> +
> +	mtk_crtc_read_crc(&ovl->crc, ovl->regs);
> +}
> +
>  static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
>  {
>  	struct mtk_disp_ovl *priv = dev_id;
> @@ -237,21 +297,40 @@ void mtk_ovl_clk_disable(struct device *dev)
>  void mtk_ovl_start(struct device *dev)
>  {
>  	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
> +	unsigned int reg = readl(ovl->regs +
> DISP_REG_OVL_DATAPATH_CON);
>  
> -	if (ovl->data->smi_id_en) {
> -		unsigned int reg;
> +	if (ovl->data->smi_id_en)
> +		reg |= OVL_LAYER_SMI_ID_EN;
>  
> -		reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
> -		reg = reg | OVL_LAYER_SMI_ID_EN;
> -		writel_relaxed(reg, ovl->regs +
> DISP_REG_OVL_DATAPATH_CON);
> +	/*
> +	 * When doing Y2R conversion, it's common to get an output
> +	 * that is larger than 10 bits (negative numbers).
> +	 * Enable this bit to clamp the output to 10 bits per channel
> +	 * (should always be enabled)
> +	 */
> +	reg |= OVL_OUTPUT_CLAMP;
> +	writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
> +
> +	reg = OVL_EN;
> +	if (ovl->data->crc_cnt) {
> +		/* enable crc  and its related clocks */
> +		writel_relaxed(OVL_CRC_EN, ovl->regs +
> DISP_REG_OVL_TRIG);
> +		reg |= OVL_OP_8BIT_MODE | OVL_HG_FOVL_CK_ON |
> OVL_HF_FOVL_CK_ON;
>  	}
> -	writel_relaxed(0x1, ovl->regs + DISP_REG_OVL_EN);
> +	writel_relaxed(reg, ovl->regs + DISP_REG_OVL_EN);
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +	mtk_crtc_start_crc_cmdq(&ovl->crc);
> +#endif
>  }
>  
>  void mtk_ovl_stop(struct device *dev)
>  {
>  	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
>  
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +	mtk_crtc_stop_crc_cmdq(&ovl->crc);
> +#endif
>  	writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_EN);
>  	if (ovl->data->smi_id_en) {
>  		unsigned int reg;
> @@ -488,6 +567,83 @@ void mtk_ovl_layer_config(struct device *dev,
> unsigned int idx,
>  	    (state->base.fb && !state->base.fb->format->has_alpha))
>  		ignore_pixel_alpha = OVL_CONST_BLEND;
>  
> +	/*
> +	 * OVL only supports 8 bits data in CRC calculation, transform
> 10-bit
> +	 * RGB to 8-bit RGB by leveraging the ability of the Y2R (YUV-
> to-RGB)
> +	 * hardware to multiply coefficients, although there is nothing
> to do
> +	 * with the YUV format.
> +	 */
> +	if (ovl->data->supports_clrfmt_ext) {
> +		u32 y2r_coef = 0, y2r_offset = 0, r2r_coef = 0, csc_en
> = 0;
> +
> +		if (is_10bit_rgb(fmt)) {
> +			con |= OVL_CON_MTX_AUTO_DIS | OVL_CON_MTX_EN |
> OVL_CON_MTX_PROGRAMMABLE;
> +
> +			/*
> +			 * Y2R coefficient setting
> +			 * bit 13 is 2^1, bit 12 is 2^0, bit 11 is 2^-
> 1,
> +			 * bit 10 is 2^-2 = 0.25
> +			 */
> +			y2r_coef = BIT(10);
> +
> +			/* -1 in 10bit */
> +			y2r_offset = GENMASK(10, 0) - 1;

I don't know why do this? If an input value is 0x100, then

0x100 right shit 2 bit become 0x40.
0x40 - 1 = 0x3f.
0x3f left shift 2 bit become 0xfc.

So input 0x100 and output 0xfc. Why?

> +
> +			/*
> +			 * R2R coefficient setting
> +			 * bit 19 is 2^1, bit 18 is 2^0, bit 17 is 2^-
> 1,
> +			 * bit 20 is 2^2 = 4
> +			 */
> +			r2r_coef = BIT(20);
> +
> +			/* CSC_EN is for R2R */
> +			csc_en = OVL_CLRFMT_EXT1_CSC_EN(idx);
> +
> +			/*
> +			 * 1. YUV input data - 1 and shift right for 2
> bits to remove it
> +			 * [R']   [0.25    0    0]   [Y in - 1]
> +			 * [G'] = [   0 0.25    0] * [U in - 1]
> +			 * [B']   [   0    0 0.25]   [V in - 1]
> +			 *
> +			 * 2. shift left for 2 bit letting the last 2
> bits become 0

You truncate the last two bit, so some quality lost. I think the
quality is main function and CRC is just for debug. So it's better that
in normal case we keep quality and only for debug to lost the quality.

I have another question. You just truncate the last two bit but it is
still 10 bit value, so CRC could calculate this 10 bit value? I don't
know why you say CRC just for 8 bit?

Regards,
CK

> +			 * [R out]   [ 4  0  0]   [R']
> +			 * [G out] = [ 0  4  0] * [G']
> +			 * [B out]   [ 0  0  4]   [B']
> +			 */
> +		}
> +
> +		mtk_ddp_write_mask(cmdq_pkt, y2r_coef,
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_Y2R_PARA_R0(idx),
> +				   OVL_Y2R_PARA_C_CF_RMY);
> +		mtk_ddp_write_mask(cmdq_pkt, (y2r_coef << 16),
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_Y2R_PARA_G0(idx),
> +				   OVL_Y2R_PARA_C_CF_GMU);
> +		mtk_ddp_write_mask(cmdq_pkt, y2r_coef,
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_Y2R_PARA_B1(idx),
> +				   OVL_Y2R_PARA_C_CF_BMV);
> +
> +		mtk_ddp_write_mask(cmdq_pkt, y2r_offset,
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_Y2R_PARA_YUV_A_0(idx),
> +				   OVL_Y2R_PARA_C_CF_YA);
> +		mtk_ddp_write_mask(cmdq_pkt, (y2r_offset << 16),
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_Y2R_PARA_YUV_A_0(idx),
> +				   OVL_Y2R_PARA_C_CF_UA);
> +		mtk_ddp_write_mask(cmdq_pkt, y2r_offset,
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_Y2R_PARA_YUV_A_1(idx),
> +				   OVL_Y2R_PARA_C_CF_VA);
> +
> +		mtk_ddp_write_relaxed(cmdq_pkt, r2r_coef,
> +				      &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_R2R_R0(idx));
> +		mtk_ddp_write_relaxed(cmdq_pkt, r2r_coef,
> +				      &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_R2R_G1(idx));
> +		mtk_ddp_write_relaxed(cmdq_pkt, r2r_coef,
> +				      &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_R2R_B2(idx));
> +
> +		mtk_ddp_write_mask(cmdq_pkt, csc_en,
> +				   &ovl->cmdq_reg, ovl->regs,
> DISP_REG_OVL_CLRFMT_EXT1,
> +				   OVL_CLRFMT_EXT1_CSC_EN(idx));
> +	}
> +
>  	if (pending->rotation & DRM_MODE_REFLECT_Y) {
>  		con |= OVL_CON_VIRT_FLIP;
>  		addr += (pending->height - 1) * pending->pitch;
> @@ -594,15 +750,31 @@ static int mtk_disp_ovl_probe(struct
> platform_device *pdev)
>  		dev_err(dev, "failed to ioremap ovl\n");
>  		return PTR_ERR(priv->regs);
>  	}
> +
> +	priv->data = of_device_get_match_data(dev);
> +	platform_set_drvdata(pdev, priv);
> +
> +	if (priv->data->crc_cnt) {
> +		mtk_crtc_init_crc(&priv->crc,
> +				  priv->data->crc_ofs, priv->data-
> >crc_cnt,
> +				  DISP_REG_OVL_TRIG, OVL_CRC_CLR);
> +	}
> +
>  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
>  	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
>  	if (ret)
>  		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
> -#endif
> -
> -	priv->data = of_device_get_match_data(dev);
> -	platform_set_drvdata(pdev, priv);
>  
> +	if (priv->data->crc_cnt) {
> +		if (of_property_read_u32_index(dev->of_node,
> +					       "mediatek,gce-events",
> 0,
> +					       &priv->crc.cmdq_event))
> {
> +			dev_warn(dev, "failed to get gce-events for
> crc\n");
> +		}
> +		priv->crc.cmdq_reg = &priv->cmdq_reg;
> +		mtk_crtc_create_crc_cmdq(dev, &priv->crc);
> +	}
> +#endif
>  	ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
>  			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
>  	if (ret < 0) {
> @@ -623,6 +795,10 @@ static int mtk_disp_ovl_probe(struct
> platform_device *pdev)
>  
>  static void mtk_disp_ovl_remove(struct platform_device *pdev)
>  {
> +	struct device *dev = &pdev->dev;
> +	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
> +
> +	mtk_crtc_destroy_crc(&ovl->crc);
>  	component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
>  	pm_runtime_disable(&pdev->dev);
>  }
> @@ -693,6 +869,8 @@ static const struct mtk_disp_ovl_data
> mt8195_ovl_driver_data = {
>  	.formats = mt8195_formats,
>  	.num_formats = ARRAY_SIZE(mt8195_formats),
>  	.supports_clrfmt_ext = true,
> +	.crc_ofs = mt8195_ovl_crc_ofs,
> +	.crc_cnt = ARRAY_SIZE(mt8195_ovl_crc_ofs),
>  };
>  
>  static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property
  2024-03-25  1:52     ` CK Hu (胡俊光)
@ 2024-03-28  2:50       ` Shawn Sung (宋孝謙)
  0 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung (宋孝謙) @ 2024-03-28  2:50 UTC (permalink / raw
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi CK,

On Mon, 2024-03-25 at 01:52 +0000, CK Hu (胡俊光) wrote:
> 
> > > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > index 0ebeaf9830d83..2a767a823c83a 100644
> > > --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > @@ -288,6 +288,10 @@ unsigned int mtk_ovl_layer_nr(struct device
> > > *dev)
> > >  
> > >  unsigned int mtk_ovl_supported_rotations(struct device *dev)
> > >  {
> > > +	/*
> > > +	 * although currently OVL can only do reflection,
> > > +	 * reflect x + reflect y = rotate 180
> > > +	 */
> 
> Sorry, this comment is not related to DRM_MODE_ROTATE_0, so after
> removing this comment,
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 

Got it. No problem. Will remove it from this series.

Thanks,
Shawn

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver
  2024-03-22  9:37   ` CK Hu (胡俊光)
@ 2024-03-28  2:52     ` Shawn Sung (宋孝謙)
  0 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung (宋孝謙) @ 2024-03-28  2:52 UTC (permalink / raw
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi CK,

On Fri, 2024-03-22 at 09:37 +0000, CK Hu (胡俊光) wrote:
> > diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c
> > b/drivers/gpu/drm/mediatek/mtk_plane.c
> > index 1723d4333f371..5bf757a3ef202 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_plane.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_plane.c
> > @@ -346,6 +346,17 @@ int mtk_plane_init(struct drm_device *dev,
> > struct drm_plane *plane,
> >  			DRM_INFO("Create rotation property failed\n");
> >  	}
> >  
> > +	err = drm_plane_create_alpha_property(plane);
> > +	if (err)
> > +		DRM_ERROR("failed to create property: alpha\n");
> > +
> > +	err = drm_plane_create_blend_mode_property(plane,
> > +						   BIT(DRM_MODE_BLEND_P
> > REMULTI) |
> > +						   BIT(DRM_MODE_BLEND_C
> > OVERAGE) |
> > +						   BIT(DRM_MODE_BLEND_P
> > IXEL_NONE));
> 
> After all sub driver support these function, then create blend
> property. So move this patch after all sub driver support these blend
> mode.
> 

Got it. Will rearrange the patches in the next version

Thanks,
Shawn

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer
  2024-03-25  2:03   ` CK Hu (胡俊光)
@ 2024-03-28  2:56     ` Shawn Sung (宋孝謙)
  0 siblings, 0 replies; 30+ messages in thread
From: Shawn Sung (宋孝謙) @ 2024-03-28  2:56 UTC (permalink / raw
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	linux-arm-kernel@lists.infradead.org

Hi CK,

On Mon, 2024-03-25 at 02:03 +0000, CK Hu (胡俊光) wrote:
> Hi, Shawn:
> 
> On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> > From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> > 
> > Support "None" blend mode on MediaTek's chips.
> > 
> > Please refer to the description of the commit
> > "drm/mediatek: Support alpha blending in display driver"
> > for more information.
> 
> But I would like you to describe the information in this patch
> instead
> of referring to another patch. This patch could describe more detail,
> and the integration patch could describe more brief.
> 

Got it. Will try to add more information to all the related patches.

Thanks,
Shawn

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 13/14] drm/mediatek: Support CRC in OVL
  2024-03-26  6:11   ` CK Hu (胡俊光)
@ 2024-03-28  3:22     ` Shawn Sung (宋孝謙)
  2024-03-28  5:21       ` CK Hu (胡俊光)
  0 siblings, 1 reply; 30+ messages in thread
From: Shawn Sung (宋孝謙) @ 2024-03-28  3:22 UTC (permalink / raw
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi CK,

On Tue, 2024-03-26 at 06:11 +0000, CK Hu (胡俊光) wrote:
> > @@ -488,6 +567,83 @@ void mtk_ovl_layer_config(struct device *dev,
> > unsigned int idx,
> >  	    (state->base.fb && !state->base.fb->format->has_alpha))
> >  		ignore_pixel_alpha = OVL_CONST_BLEND;
> >  
> > +	/*
> > +	 * OVL only supports 8 bits data in CRC calculation, transform
> > 10-bit
> > +	 * RGB to 8-bit RGB by leveraging the ability of the Y2R (YUV-
> > to-RGB)
> > +	 * hardware to multiply coefficients, although there is nothing
> > to do
> > +	 * with the YUV format.
> > +	 */
> > +	if (ovl->data->supports_clrfmt_ext) {
> > +		u32 y2r_coef = 0, y2r_offset = 0, r2r_coef = 0, csc_en
> > = 0;
> > +
> > +		if (is_10bit_rgb(fmt)) {
> > +			con |= OVL_CON_MTX_AUTO_DIS | OVL_CON_MTX_EN |
> > OVL_CON_MTX_PROGRAMMABLE;
> > +
> > +			/*
> > +			 * Y2R coefficient setting
> > +			 * bit 13 is 2^1, bit 12 is 2^0, bit 11 is 2^-
> > 1,
> > +			 * bit 10 is 2^-2 = 0.25
> > +			 */
> > +			y2r_coef = BIT(10);
> > +
> > +			/* -1 in 10bit */
> > +			y2r_offset = GENMASK(10, 0) - 1;
> 
> I don't know why do this? If an input value is 0x100, then
> 
> 0x100 right shit 2 bit become 0x40.
> 0x40 - 1 = 0x3f.
> 0x3f left shift 2 bit become 0xfc.
> 
> So input 0x100 and output 0xfc. Why?
> 

There is no input here, all the settings are direct bit assignment, and
all the values are calculated by the designer. The main purpose of it
is to configure the Y2R module to be able to transform 10bit RGB format
into 8bit RGB, while this is not Y2R module is originally designed for.

> > +
> > +			/*
> > +			 * R2R coefficient setting
> > +			 * bit 19 is 2^1, bit 18 is 2^0, bit 17 is 2^-
> > 1,
> > +			 * bit 20 is 2^2 = 4
> > +			 */
> > +			r2r_coef = BIT(20);
> > +
> > +			/* CSC_EN is for R2R */
> > +			csc_en = OVL_CLRFMT_EXT1_CSC_EN(idx);
> > +
> > +			/*
> > +			 * 1. YUV input data - 1 and shift right for 2
> > bits to remove it
> > +			 * [R']   [0.25    0    0]   [Y in - 1]
> > +			 * [G'] = [   0 0.25    0] * [U in - 1]
> > +			 * [B']   [   0    0 0.25]   [V in - 1]
> > +			 *
> > +			 * 2. shift left for 2 bit letting the last 2
> > bits become 0
> 
> You truncate the last two bit, so some quality lost. I think the
> quality is main function and CRC is just for debug. So it's better
> that
> in normal case we keep quality and only for debug to lost the
> quality.

Got it. Will modify in the next version to enter this section only if
we need to calculate the CRC.

> I have another question. You just truncate the last two bit but it is
> still 10 bit value, so CRC could calculate this 10 bit value? I don't
> know why you say CRC just for 8 bit?
> 

Yes, for RGB format, OVL can only handle 8bit per channel for CRC
calculation, so I assume there may be similar issue handling 10bit YUV
formats (P010) in the future.

Thanks,
Shawn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 13/14] drm/mediatek: Support CRC in OVL
  2024-03-28  3:22     ` Shawn Sung (宋孝謙)
@ 2024-03-28  5:21       ` CK Hu (胡俊光)
  0 siblings, 0 replies; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-03-28  5:21 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Thu, 2024-03-28 at 03:22 +0000, Shawn Sung (宋孝謙) wrote:
> Hi CK,
> 
> On Tue, 2024-03-26 at 06:11 +0000, CK Hu (胡俊光) wrote:
> > > @@ -488,6 +567,83 @@ void mtk_ovl_layer_config(struct device
> > > *dev,
> > > unsigned int idx,
> > >  	    (state->base.fb && !state->base.fb->format->has_alpha))
> > >  		ignore_pixel_alpha = OVL_CONST_BLEND;
> > >  
> > > +	/*
> > > +	 * OVL only supports 8 bits data in CRC calculation, transform
> > > 10-bit
> > > +	 * RGB to 8-bit RGB by leveraging the ability of the Y2R (YUV-
> > > to-RGB)
> > > +	 * hardware to multiply coefficients, although there is nothing
> > > to do
> > > +	 * with the YUV format.
> > > +	 */
> > > +	if (ovl->data->supports_clrfmt_ext) {
> > > +		u32 y2r_coef = 0, y2r_offset = 0, r2r_coef = 0, csc_en
> > > = 0;
> > > +
> > > +		if (is_10bit_rgb(fmt)) {
> > > +			con |= OVL_CON_MTX_AUTO_DIS | OVL_CON_MTX_EN |
> > > OVL_CON_MTX_PROGRAMMABLE;
> > > +
> > > +			/*
> > > +			 * Y2R coefficient setting
> > > +			 * bit 13 is 2^1, bit 12 is 2^0, bit 11 is 2^-
> > > 1,
> > > +			 * bit 10 is 2^-2 = 0.25
> > > +			 */
> > > +			y2r_coef = BIT(10);
> > > +
> > > +			/* -1 in 10bit */
> > > +			y2r_offset = GENMASK(10, 0) - 1;
> > 
> > I don't know why do this? If an input value is 0x100, then
> > 
> > 0x100 right shit 2 bit become 0x40.
> > 0x40 - 1 = 0x3f.
> > 0x3f left shift 2 bit become 0xfc.
> > 
> > So input 0x100 and output 0xfc. Why?
> > 
> 
> There is no input here, all the settings are direct bit assignment,
> and
> all the values are calculated by the designer. The main purpose of it
> is to configure the Y2R module to be able to transform 10bit RGB
> format
> into 8bit RGB, while this is not Y2R module is originally designed
> for.

The input I mean is the input of Y2R, the pixel value. If input a pixel
value 0x100 into Y2R, then Y2R output pixel value 0xfc, why do this? I
think it should not be minus 1. If remove the minus 1, then input 0x100
and output 0x100.

> 
> > > +
> > > +			/*
> > > +			 * R2R coefficient setting
> > > +			 * bit 19 is 2^1, bit 18 is 2^0, bit 17 is 2^-
> > > 1,
> > > +			 * bit 20 is 2^2 = 4
> > > +			 */
> > > +			r2r_coef = BIT(20);
> > > +
> > > +			/* CSC_EN is for R2R */
> > > +			csc_en = OVL_CLRFMT_EXT1_CSC_EN(idx);
> > > +
> > > +			/*
> > > +			 * 1. YUV input data - 1 and shift right for 2
> > > bits to remove it
> > > +			 * [R']   [0.25    0    0]   [Y in - 1]
> > > +			 * [G'] = [   0 0.25    0] * [U in - 1]
> > > +			 * [B']   [   0    0 0.25]   [V in - 1]
> > > +			 *
> > > +			 * 2. shift left for 2 bit letting the last 2
> > > bits become 0
> > 
> > You truncate the last two bit, so some quality lost. I think the
> > quality is main function and CRC is just for debug. So it's better
> > that
> > in normal case we keep quality and only for debug to lost the
> > quality.
> 
> Got it. Will modify in the next version to enter this section only if
> we need to calculate the CRC.
> 
> > I have another question. You just truncate the last two bit but it
> > is
> > still 10 bit value, so CRC could calculate this 10 bit value? I
> > don't
> > know why you say CRC just for 8 bit?
> > 
> 
> Yes, for RGB format, OVL can only handle 8bit per channel for CRC
> calculation, so I assume there may be similar issue handling 10bit
> YUV
> formats (P010) in the future.

I think this truncation is not necessary. No matter you truncate in
Y2R, OVL would finally truncate pixel value last 2 two bit when
calculate CRC. So this truncation is not necessary.

Regards,
CK


> 
> Thanks,
> Shawn
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 12/14] drm/mediatek: Support CRC in display driver
  2024-03-22  5:28 ` [PATCH v6 12/14] drm/mediatek: Support CRC in display driver Shawn Sung
@ 2024-04-01  5:31   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-04-01  5:31 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Shawn:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Register CRC related function pointers to support
> CRC retrieval.
> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_crtc.c     | 260
> ++++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_crtc.h     |  38 ++++
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   3 +
>  3 files changed, 301 insertions(+)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c
> b/drivers/gpu/drm/mediatek/mtk_crtc.c
> index d811e4e73a36c..6440c5fb336d7 100644
> --- a/drivers/gpu/drm/mediatek/mtk_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
> @@ -18,6 +18,7 @@
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_vblank.h>
> +#include <drm/drm_vblank_work.h>
>  
>  #include "mtk_crtc.h"
>  #include "mtk_ddp_comp.h"
> @@ -69,6 +70,9 @@ struct mtk_crtc {
>  	/* lock for display hardware access */
>  	struct mutex			hw_lock;
>  	bool				config_updating;
> +
> +	struct mtk_ddp_comp		*crc_provider;
> +	struct drm_vblank_work		crc_work;
>  };
>  
>  struct mtk_crtc_state {
> @@ -703,6 +707,71 @@ static void mtk_crtc_update_output(struct
> drm_crtc *crtc,
>  	}
>  }
>  
> +static void mtk_crtc_crc_work(struct kthread_work *base)
> +{
> +	struct drm_vblank_work *work = to_drm_vblank_work(base);
> +	struct mtk_crtc *mtk_crtc =
> +		container_of(work, typeof(*mtk_crtc), crc_work);
> +
> +	if (mtk_crtc->base.crc.opened) {
> +		struct mtk_ddp_comp *comp = mtk_crtc->crc_provider;
> +		u64 vblank = drm_crtc_vblank_count(&mtk_crtc->base);
> +
> +		comp->funcs->crc_read(comp->dev);
> +
> +		/* could take more than 50ms to finish */
> +		drm_crtc_add_crc_entry(&mtk_crtc->base, true, vblank,
> +				       comp->funcs->crc_entry(comp-
> >dev));

It seems that you could regenerate cmdq packet for crc here. So crtc
atomic flush and crc could use the same mailbox channel.

Regards,
CK

> +
> +		drm_vblank_work_schedule(&mtk_crtc->crc_work, vblank +
> 1, true);
> +	}
> +}
> +
> +static int mtk_crtc_set_crc_source(struct drm_crtc *crtc, const char
> *src)
> +{
> +	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> +
> +	if (!src)
> +		return -EINVAL;
> +
> +	if (strcmp(src, "auto") != 0) {
> +		DRM_ERROR("%s(crtc-%d): unknown source '%s'\n",
> +			  __func__, drm_crtc_index(crtc), src);
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * skip the first crc because the first frame (vblank + 1) is
> configured
> +	 * by mtk_crtc_ddp_hw_init() when atomic enable
> +	 */
> +	drm_vblank_work_schedule(&mtk_crtc->crc_work,
> +				 drm_crtc_vblank_count(crtc) + 2,
> false);
> +	return 0;
> +}
> +
> +static int mtk_crtc_verify_crc_source(struct drm_crtc *crtc, const
> char *src,
> +				      size_t *cnt)
> +{
> +	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> +	struct mtk_ddp_comp *comp = mtk_crtc->crc_provider;
> +
> +	if (!comp) {
> +		DRM_ERROR("%s(crtc-%d): no crc provider\n",
> +			  __func__, drm_crtc_index(crtc));
> +		return -ENOENT;
> +	}
> +
> +	if (src && strcmp(src, "auto") != 0) {
> +		DRM_ERROR("%s(crtc-%d): unknown source '%s'\n",
> +			  __func__, drm_crtc_index(crtc), src);
> +		return -EINVAL;
> +	}
> +
> +	*cnt = comp->funcs->crc_cnt(comp->dev);
> +
> +	return 0;
> +}
> +
>  int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane
> *plane,
>  			 struct mtk_plane_state *state)
>  {
> @@ -751,6 +820,8 @@ static void mtk_crtc_atomic_enable(struct
> drm_crtc *crtc,
>  
>  	drm_crtc_vblank_on(crtc);
>  	mtk_crtc->enabled = true;
> +
> +	drm_vblank_work_init(&mtk_crtc->crc_work, crtc,
> mtk_crtc_crc_work);
>  }
>  
>  static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
> @@ -840,6 +911,8 @@ static const struct drm_crtc_funcs mtk_crtc_funcs
> = {
>  	.atomic_destroy_state	= mtk_crtc_destroy_state,
>  	.enable_vblank		= mtk_crtc_enable_vblank,
>  	.disable_vblank		= mtk_crtc_disable_vblank,
> +	.set_crc_source		= mtk_crtc_set_crc_source,
> +	.verify_crc_source	= mtk_crtc_verify_crc_source,
>  };
>  
>  static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
> @@ -1033,6 +1106,11 @@ int mtk_crtc_create(struct drm_device
> *drm_dev, const unsigned int *path,
>  
>  			if (comp->funcs->ctm_set)
>  				has_ctm = true;
> +
> +			if (comp->funcs->crc_cnt &&
> +			    comp->funcs->crc_entry &&
> +			    comp->funcs->crc_read)
> +				mtk_crtc->crc_provider = comp;
>  		}
>  
>  		mtk_ddp_comp_register_vblank_cb(comp, mtk_crtc_ddp_irq,
> @@ -1136,3 +1214,185 @@ int mtk_crtc_create(struct drm_device
> *drm_dev, const unsigned int *path,
>  
>  	return 0;
>  }
> +
> +void mtk_crtc_init_crc(struct mtk_crtc_crc *crc, const u32
> *crc_offset_table,
> +		       size_t crc_count, u32 reset_offset, u32
> reset_mask)
> +{
> +	crc->ofs = crc_offset_table;
> +	crc->cnt = crc_count;
> +	crc->rst_ofs = reset_offset;
> +	crc->rst_msk = reset_mask;
> +	crc->va = kcalloc(crc->cnt, sizeof(*crc->va), GFP_KERNEL);
> +	if (!crc->va) {
> +		DRM_ERROR("failed to allocate memory for crc\n");
> +		crc->cnt = 0;
> +	}
> +}
> +
> +void mtk_crtc_read_crc(struct mtk_crtc_crc *crc, void __iomem *reg)
> +{
> +	if (!crc->cnt || !crc->ofs || !crc->va)
> +		return;
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +	/* sync to see the most up-to-date copy of the DMA buffer */
> +	dma_sync_single_for_cpu(crc->cmdq_client.chan->mbox->dev,
> +				crc->pa, crc->cnt * sizeof(*crc->va),
> +				DMA_FROM_DEVICE);
> +#endif
> +}
> +
> +void mtk_crtc_destroy_crc(struct mtk_crtc_crc *crc)
> +{
> +	if (!crc->cnt)
> +		return;
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +	if (crc->pa) {
> +		dma_unmap_single(crc->cmdq_client.chan->mbox->dev,
> +				 crc->pa, crc->cnt * sizeof(*crc->va),
> +				 DMA_TO_DEVICE);
> +		crc->pa = 0;
> +	}
> +	if (crc->cmdq_client.chan) {
> +		mtk_drm_cmdq_pkt_destroy(&crc->cmdq_handle);
> +		mbox_free_channel(crc->cmdq_client.chan);
> +		crc->cmdq_client.chan = NULL;
> +	}
> +#endif
> +	kfree(crc->va);
> +	crc->va = NULL;
> +	crc->cnt = 0;
> +}
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +/**
> + * mtk_crtc_create_crc_cmdq - Create a CMDQ thread for syncing the
> CRCs
> + * @dev: Kernel device node of the CRC provider
> + * @crc: Pointer of the CRC to init
> + *
> + * This function will create a looping thread on GCE (Global Command
> Engine) to
> + * keep the CRC up to date by monitoring the assigned event (usually
> the frame
> + * done event) of the CRC provider, and read the CRCs from the
> registers to a
> + * shared memory for the workqueue to read. To start/stop the
> looping thread,
> + * please call `mtk_crtc_start_crc_cmdq()` and
> `mtk_crtc_stop_crc_cmdq()`
> + * defined blow.
> + *
> + * The reason why we don't update the CRCs with CPU is that the
> front porch of
> + * 4K60 timing in CEA-861 is less than 60us, and register read/write
> speed is
> + * relatively unreliable comparing to GCE due to the bus design.
> + *
> + * We must create a new thread instead of using the original one for
> plane
> + * update is because:
> + * 1. We cannot add another wait-for-event command at the end of
> cmdq packet, or
> + *    the cmdq callback will delay for too long
> + * 2. Will get the CRC of the previous frame if using the existed
> wait-for-event
> + *    command which is at the beginning of the packet
> + */
> +void mtk_crtc_create_crc_cmdq(struct device *dev, struct
> mtk_crtc_crc *crc)
> +{
> +	int i;
> +
> +	if (!crc->cnt) {
> +		dev_warn(dev, "%s: not support\n", __func__);
> +		goto cleanup;
> +	}
> +
> +	if (!crc->ofs) {
> +		dev_warn(dev, "%s: not defined\n", __func__);
> +		goto cleanup;
> +	}
> +
> +	crc->cmdq_client.client.dev = dev;
> +	crc->cmdq_client.client.tx_block = false;
> +	crc->cmdq_client.client.knows_txdone = true;
> +	crc->cmdq_client.client.rx_callback = NULL;
> +	crc->cmdq_client.chan = mbox_request_channel(&crc-
> >cmdq_client.client, 0);
> +	if (IS_ERR(crc->cmdq_client.chan)) {
> +		dev_warn(dev, "%s: failed to create mailbox client\n",
> __func__);
> +		crc->cmdq_client.chan = NULL;
> +		goto cleanup;
> +	}
> +
> +	if (mtk_drm_cmdq_pkt_create(&crc->cmdq_client, &crc-
> >cmdq_handle, PAGE_SIZE)) {
> +		dev_warn(dev, "%s: failed to create cmdq packet\n",
> __func__);
> +		goto cleanup;
> +	}
> +
> +	if (!crc->va) {
> +		dev_warn(dev, "%s: no memory\n", __func__);
> +		goto cleanup;
> +	}
> +
> +	/* map the entry to get a dma address for cmdq to store the crc
> */
> +	crc->pa = dma_map_single(crc->cmdq_client.chan->mbox->dev,
> +				 crc->va, crc->cnt * sizeof(*crc->va),
> +				 DMA_FROM_DEVICE);
> +
> +	if (dma_mapping_error(crc->cmdq_client.chan->mbox->dev, crc-
> >pa)) {
> +		dev_err(dev, "%s: failed to map dma\n", __func__);
> +		goto cleanup;
> +	}
> +
> +	if (crc->cmdq_event)
> +		cmdq_pkt_wfe(&crc->cmdq_handle, crc->cmdq_event, true);
> +
> +	for (i = 0; i < crc->cnt; i++) {
> +		/* put crc to spr1 register */
> +		cmdq_pkt_read_s(&crc->cmdq_handle, crc->cmdq_reg-
> >subsys,
> +				crc->cmdq_reg->offset + crc->ofs[i],
> +				CMDQ_THR_SPR_IDX1);
> +
> +		/* copy spr1 register to physical address of the crc */
> +		cmdq_pkt_assign(&crc->cmdq_handle, CMDQ_THR_SPR_IDX0,
> +				CMDQ_ADDR_HIGH(crc->pa + i *
> sizeof(*crc->va)));
> +		cmdq_pkt_write_s(&crc->cmdq_handle, CMDQ_THR_SPR_IDX0,
> +				 CMDQ_ADDR_LOW(crc->pa + i *
> sizeof(*crc->va)),
> +				 CMDQ_THR_SPR_IDX1);
> +	}
> +	/* reset crc */
> +	mtk_ddp_write_mask(&crc->cmdq_handle, ~0, crc->cmdq_reg, 0,
> +			   crc->rst_ofs, crc->rst_msk);
> +
> +	/* clear reset bit */
> +	mtk_ddp_write_mask(&crc->cmdq_handle, 0, crc->cmdq_reg, 0,
> +			   crc->rst_ofs, crc->rst_msk);
> +
> +	/* jump to head of the cmdq packet */
> +	cmdq_pkt_jump(&crc->cmdq_handle, crc->cmdq_handle.pa_base);
> +
> +	return;
> +cleanup:
> +	mtk_crtc_destroy_crc(crc);
> +}
> +
> +/**
> + * mtk_crtc_start_crc_cmdq - Start the GCE looping thread for CRC
> update
> + * @crc: Pointer of the CRC information
> + */
> +void mtk_crtc_start_crc_cmdq(struct mtk_crtc_crc *crc)
> +{
> +	if (!crc->cmdq_client.chan)
> +		return;
> +
> +	dma_sync_single_for_device(crc->cmdq_client.chan->mbox->dev,
> +				   crc->cmdq_handle.pa_base,
> +				   crc->cmdq_handle.cmd_buf_size,
> +				   DMA_TO_DEVICE);
> +	mbox_send_message(crc->cmdq_client.chan, &crc->cmdq_handle);
> +	mbox_client_txdone(crc->cmdq_client.chan, 0);
> +}
> +
> +/**
> + * mtk_crtc_stop_crc_cmdq - Stop the GCE looping thread for CRC
> update
> + * @crc: Pointer of the CRC information
> + */
> +void mtk_crtc_stop_crc_cmdq(struct mtk_crtc_crc *crc)
> +{
> +	if (!crc->cmdq_client.chan)
> +		return;
> +
> +	/* remove all the commands from the cmdq packet */
> +	mbox_flush(crc->cmdq_client.chan, 2000);
> +}
> +#endif
> diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h
> b/drivers/gpu/drm/mediatek/mtk_crtc.h
> index 388e900b6f4de..a79c4611754e4 100644
> --- a/drivers/gpu/drm/mediatek/mtk_crtc.h
> +++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
> @@ -14,6 +14,34 @@
>  #define MTK_MAX_BPC	10
>  #define MTK_MIN_BPC	3
>  
> +/**
> + * struct mtk_crtc_crc - crc related information
> + * @ofs: register offset of crc
> + * @rst_ofs: register offset of crc reset
> + * @rst_msk: register mask of crc reset
> + * @cnt: count of crc
> + * @va: pointer to the start of crc array
> + * @pa: physical address of the crc for gce to access
> + * @cmdq_event: the event to trigger the cmdq
> + * @cmdq_reg: address of the register that cmdq is going to access
> + * @cmdq_client: handler to control cmdq (mbox channel, thread
> ...etc.)
> + * @cmdq_handle: cmdq packet to store the commands
> + */
> +struct mtk_crtc_crc {
> +	const u32 *ofs;
> +	u32 rst_ofs;
> +	u32 rst_msk;
> +	size_t cnt;
> +	u32 *va;
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +	dma_addr_t pa;
> +	u32 cmdq_event;
> +	struct cmdq_client_reg *cmdq_reg;
> +	struct cmdq_client cmdq_client;
> +	struct cmdq_pkt cmdq_handle;
> +#endif
> +};
> +
>  void mtk_crtc_commit(struct drm_crtc *crtc);
>  int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int
> *path,
>  		    unsigned int path_len, int priv_data_index,
> @@ -25,4 +53,14 @@ void mtk_crtc_async_update(struct drm_crtc *crtc,
> struct drm_plane *plane,
>  			   struct drm_atomic_state *plane_state);
>  struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc);
>  
> +void mtk_crtc_init_crc(struct mtk_crtc_crc *crc, const u32
> *crc_offset_table,
> +		       size_t crc_count, u32 reset_offset, u32
> reset_mask);
> +void mtk_crtc_read_crc(struct mtk_crtc_crc *crc, void __iomem *reg);
> +void mtk_crtc_destroy_crc(struct mtk_crtc_crc *crc);
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +void mtk_crtc_create_crc_cmdq(struct device *dev, struct
> mtk_crtc_crc *crc);
> +void mtk_crtc_start_crc_cmdq(struct mtk_crtc_crc *crc);
> +void mtk_crtc_stop_crc_cmdq(struct mtk_crtc_crc *crc);
> +#endif
> +
>  #endif /* MTK_CRTC_H */
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index f7fe2e08dc8e2..b9c79e740abe0 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -88,6 +88,9 @@ struct mtk_ddp_comp_funcs {
>  	void (*remove)(struct device *dev, struct mtk_mutex *mutex);
>  	unsigned int (*encoder_index)(struct device *dev);
>  	enum drm_mode_status (*mode_valid)(struct device *dev, const
> struct drm_display_mode *mode);
> +	size_t (*crc_cnt)(struct device *dev);
> +	u32 *(*crc_entry)(struct device *dev);
> +	void (*crc_read)(struct device *dev);
>  };
>  
>  struct mtk_ddp_comp {

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v6 05/14] drm/mediatek: Set DRM mode configs accordingly
  2024-03-22  5:28 ` [PATCH v6 05/14] drm/mediatek: Set DRM mode configs accordingly Shawn Sung
@ 2024-04-25  6:54   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 30+ messages in thread
From: CK Hu (胡俊光) @ 2024-04-25  6:54 UTC (permalink / raw
  To: Shawn Sung (宋孝謙), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org

Hi, Hsiao-chien:

On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> 
> Set DRM mode configs limitation according to the hardware
> capabilities
> and pass the IGT checks as below:
> 
> - The test "graphics.IgtKms.kms_plane" requires a frame buffer with
>   width of 4512 pixels (> 4096).
> - The test "graphics.IgtKms.kms_cursor_crc" checks if the cursor size
> is
>   defined, and run the test with cursor size from 1x1 to 512x512.
> 
> Please notice that the test conditions may change as IGT is updated.
> 
> Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c | 22 ++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h |  3 +++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 621015b64674d..8e04e9576f7f2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -296,6 +296,9 @@ static const struct mtk_mmsys_driver_data
> mt8188_vdosys0_driver_data = {
>  	.conn_routes = mt8188_mtk_ddp_main_routes,
>  	.num_conn_routes = ARRAY_SIZE(mt8188_mtk_ddp_main_routes),
>  	.mmsys_dev_num = 2,
> +	.max_width = 8191,
> +	.min_width = 1,
> +	.min_height = 1,
>  };
>  
>  static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data =
> {
> @@ -310,6 +313,9 @@ static const struct mtk_mmsys_driver_data
> mt8195_vdosys0_driver_data = {
>  	.main_path = mt8195_mtk_ddp_main,
>  	.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
>  	.mmsys_dev_num = 2,
> +	.max_width = 8191,
> +	.min_width = 1,
> +	.min_height = 1,
>  };
>  
>  static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data
> = {
> @@ -317,6 +323,9 @@ static const struct mtk_mmsys_driver_data
> mt8195_vdosys1_driver_data = {
>  	.ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
>  	.mmsys_id = 1,
>  	.mmsys_dev_num = 2,
> +	.max_width = 8191,
> +	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
> +	.min_height = 1,
>  };
>  
>  static const struct of_device_id mtk_drm_of_ids[] = {
> @@ -495,6 +504,15 @@ static int mtk_drm_kms_init(struct drm_device
> *drm)
>  		for (j = 0; j < private->data->mmsys_dev_num; j++) {
>  			priv_n = private->all_drm_private[j];
>  
> +			if (priv_n->data->max_width)
> +				drm->mode_config.max_width  = priv_n-
> >data->max_width;

Remove one extra space before '='.

> +
> +			if (priv_n->data->min_width)
> +				drm->mode_config.min_width = priv_n-
> >data->min_width;
> +
> +			if (priv_n->data->min_height)
> +				drm->mode_config.min_height = priv_n-
> >data->min_height;
> +
>  			if (i == CRTC_MAIN && priv_n->data->main_len) {
>  				ret = mtk_crtc_create(drm, priv_n-
> >data->main_path,
>  						      priv_n->data-
> >main_len, j,
> @@ -522,6 +540,10 @@ static int mtk_drm_kms_init(struct drm_device
> *drm)
>  		}
>  	}
>  
> +	/* IGT will check if the cursor size is configured */
> +	drm->mode_config.cursor_width = drm->mode_config.max_width;
> +	drm->mode_config.cursor_height = drm->mode_config.max_height;
> +
>  	/* Use OVL device for all DMA memory allocations */
>  	crtc = drm_crtc_from_index(drm, 0);
>  	if (crtc)
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index 78d698ede1bf8..8917a14d7c0f2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -46,6 +46,9 @@ struct mtk_mmsys_driver_data {
>  	bool shadow_register;
>  	unsigned int mmsys_id;
>  	unsigned int mmsys_dev_num;
> +
> +	int max_width;
> +	int min_width, min_height;

I would like to be different line:

int min_width;
int min_height;

Regards,
CK

>  };
>  
>  struct mtk_drm_private {

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2024-04-25  6:54 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-22  5:28 [PATCH v6 00/14] Support IGT in display driver Shawn Sung
2024-03-22  5:28 ` [PATCH v6 01/14] soc: mediatek: Disable 9-bit alpha in ETHDR Shawn Sung
2024-03-22  5:28 ` [PATCH v6 02/14] drm/mediatek: Add OVL compatible name for MT8195 Shawn Sung
2024-03-22  5:28 ` [PATCH v6 03/14] drm/mediatek: Add missing plane settings when async update Shawn Sung
2024-03-22  5:28 ` [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property Shawn Sung
2024-03-22  9:02   ` CK Hu (胡俊光)
2024-03-25  1:52     ` CK Hu (胡俊光)
2024-03-28  2:50       ` Shawn Sung (宋孝謙)
2024-03-22  5:28 ` [PATCH v6 05/14] drm/mediatek: Set DRM mode configs accordingly Shawn Sung
2024-04-25  6:54   ` CK Hu (胡俊光)
2024-03-22  5:28 ` [PATCH v6 06/14] drm/mediatek: Turn off the layers with zero width or height Shawn Sung
2024-03-22  5:28 ` [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver Shawn Sung
2024-03-22  9:37   ` CK Hu (胡俊光)
2024-03-28  2:52     ` Shawn Sung (宋孝謙)
2024-03-22  5:28 ` [PATCH v6 08/14] drm/mediatek: Support "Pre-multiplied" alpha blending in OVL Shawn Sung
2024-03-22  6:43   ` CK Hu (胡俊光)
2024-03-22  5:28 ` [PATCH v6 09/14] drm/mediatek: Support "Pre-multiplied" alpha blending in Mixer Shawn Sung
2024-03-22  9:26   ` CK Hu (胡俊光)
2024-03-22  5:28 ` [PATCH v6 10/14] drm/mediatek: Support "None" alpha blending in OVL Shawn Sung
2024-03-22  9:32   ` CK Hu (胡俊光)
2024-03-22  5:28 ` [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer Shawn Sung
2024-03-25  2:03   ` CK Hu (胡俊光)
2024-03-28  2:56     ` Shawn Sung (宋孝謙)
2024-03-22  5:28 ` [PATCH v6 12/14] drm/mediatek: Support CRC in display driver Shawn Sung
2024-04-01  5:31   ` CK Hu (胡俊光)
2024-03-22  5:28 ` [PATCH v6 13/14] drm/mediatek: Support CRC in OVL Shawn Sung
2024-03-26  6:11   ` CK Hu (胡俊光)
2024-03-28  3:22     ` Shawn Sung (宋孝謙)
2024-03-28  5:21       ` CK Hu (胡俊光)
2024-03-22  5:28 ` [PATCH v6 14/14] drm/mediatek: Support CRC in OVL adaptor Shawn Sung

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).