diff mbox series

[v1,04/10] media: mediatek: isp: Add V4L2 flow support for ImgSys driver

Message ID 20250524115144.3832748-5-olivia.wen@mediatek.com
State New
Headers show
Series Add MediaTek ISP7 Image Syatem driver | expand

Commit Message

Olivia Wen May 24, 2025, 11:49 a.m. UTC
The ImgSys driver is implemented as a series of patches, with this patch
focusing on the V4L2 flow. The MediaTek's Image System (ImgSys), also
known as ISP Pass2. ImgSys is a memory-to-memory hardware device
designed for advanced image processing tasks. It is composed of multiple
hardware components, including TRAW, DIP, PQDIP, ME, and WPE.

TRAW (Tile RAW):
- Provides multiple downscaled resizers to support multi-scale noise
  reduction.
- Supports RAW/RGB format conversion.

DIP (Digital Image Processing) and PQDIP (Picture Quality DIP):
- Supports such as temporal and spatial noise reduction (TNR/SNR),
  edge enhancement (EE), and sharpness (SHP).
- PQDIP also supports image scaling and rotation.

ME (Motion Estimation):
- Supports motion estimation between two consecutive frames.

WPE (Warping Engine):
- Handles image warping and de-warping processes.

The ImgSys driver, primarily utilized for Google Chromebook products,
uses Multi-Frame Combined Noise Reduction technology to enhance image
quality.

Below is a simplified architecture of the ImgSys driver:
User -> V4L2 Framework -> ImgSys Driver
     -> SCP (It packages the hardware settings into commands)
     -> ImgSys Driver
     -> CMDQ (The packaged commands are sent to the hardware via GCE)
     -> Hardware

Signed-off-by: Olivia Wen <olivia.wen@mediatek.com>
---
 drivers/media/platform/mediatek/Kconfig       |    1 +
 drivers/media/platform/mediatek/Makefile      |    1 +
 drivers/media/platform/mediatek/isp/Kconfig   |   23 +
 .../platform/mediatek/isp/isp_7x/Makefile     |    6 +
 .../mediatek/isp/isp_7x/imgsys/Makefile       |   11 +
 .../imgsys/modules/mtk_dip_v4l2_vnode.h       |  594 ++++++
 .../isp_7x/imgsys/modules/mtk_me_v4l2_vnode.h |  386 ++++
 .../imgsys/modules/mtk_pqdip_v4l2_vnode.h     |  149 ++
 .../imgsys/modules/mtk_traw_v4l2_vnode.h      |  371 ++++
 .../imgsys/modules/mtk_wpe_v4l2_vnode.h       |  317 ++++
 .../isp/isp_7x/imgsys/mtk_header_desc.h       |   28 +
 .../isp/isp_7x/imgsys/mtk_imgsys-dev.c        |  238 +++
 .../isp/isp_7x/imgsys/mtk_imgsys-dev.h        |  427 +++++
 .../isp/isp_7x/imgsys/mtk_imgsys-formats.c    |  139 ++
 .../isp/isp_7x/imgsys/mtk_imgsys-formats.h    |   72 +
 .../isp/isp_7x/imgsys/mtk_imgsys-module_ops.h |   27 +
 .../isp/isp_7x/imgsys/mtk_imgsys-of.c         |   39 +
 .../isp/isp_7x/imgsys/mtk_imgsys-of.h         |   55 +
 .../isp/isp_7x/imgsys/mtk_imgsys-sys.c        |   27 +
 .../isp/isp_7x/imgsys/mtk_imgsys-sys.h        |   50 +
 .../isp/isp_7x/imgsys/mtk_imgsys-v4l2.c       | 1684 +++++++++++++++++
 .../isp/isp_7x/imgsys/mtk_imgsys-vnode_id.h   |  100 +
 .../isp/isp_7x/imgsys/mtk_imgsys_v4l2_vnode.h |  135 ++
 23 files changed, 4880 insertions(+)
 create mode 100644 drivers/media/platform/mediatek/isp/Kconfig
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/Makefile
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_dip_v4l2_vnode.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_me_v4l2_vnode.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_pqdip_v4l2_vnode.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_traw_v4l2_vnode.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_wpe_v4l2_vnode.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_header_desc.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.c
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.c
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_ops.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.c
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.c
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-v4l2.c
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-vnode_id.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys_v4l2_vnode.h
diff mbox series

Patch

diff --git a/drivers/media/platform/mediatek/Kconfig b/drivers/media/platform/mediatek/Kconfig
index 84104e2cd024..4e0a5a43f35e 100644
--- a/drivers/media/platform/mediatek/Kconfig
+++ b/drivers/media/platform/mediatek/Kconfig
@@ -7,3 +7,4 @@  source "drivers/media/platform/mediatek/mdp/Kconfig"
 source "drivers/media/platform/mediatek/vcodec/Kconfig"
 source "drivers/media/platform/mediatek/vpu/Kconfig"
 source "drivers/media/platform/mediatek/mdp3/Kconfig"
+source "drivers/media/platform/mediatek/isp/Kconfig"
diff --git a/drivers/media/platform/mediatek/Makefile b/drivers/media/platform/mediatek/Makefile
index 38e6ba917fe5..611fa95416bc 100644
--- a/drivers/media/platform/mediatek/Makefile
+++ b/drivers/media/platform/mediatek/Makefile
@@ -4,3 +4,4 @@  obj-y += mdp/
 obj-y += vcodec/
 obj-y += vpu/
 obj-y += mdp3/
+obj-y += isp/isp_7x/
diff --git a/drivers/media/platform/mediatek/isp/Kconfig b/drivers/media/platform/mediatek/isp/Kconfig
new file mode 100644
index 000000000000..df92ac67574d
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/Kconfig
@@ -0,0 +1,23 @@ 
+# SPDX-License-Identifier: GPL-2.0-only
+
+config VIDEO_MTK_ISP_71_IMGSYS
+	tristate "MediaTek ISP71 image processing system function"
+	depends on MTK_CMDQ
+	depends on REMOTEPROC
+	depends on MTK_SCP
+	select VIDEO_V4L2_SUBDEV_API
+	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_CORE
+	select VIDEOBUF2_V4L2
+	select VIDEOBUF2_MEMOPS
+	select MEDIA_CONTROLLER
+
+	default n
+	help
+	    Support the basic Image processing system driver.
+
+	    IMGSYS driver provides image format conversion, resizing,
+	    and rotation function through the low power hardware.
+	    IMGSYS also supports multiple output feature. It can
+	    generate two or more output image with different effect
+	    based on a single input image at the same time.
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/Makefile b/drivers/media/platform/mediatek/isp/isp_7x/Makefile
new file mode 100644
index 000000000000..11d2aee9a3dc
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/Makefile
@@ -0,0 +1,6 @@ 
+# SPDX-License-Identifier: GPL-2.0
+
+subdir-ccflags-y += -Werror
+
+obj-$(CONFIG_VIDEO_MTK_ISP_71_IMGSYS) += imgsys/
+
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile
new file mode 100644
index 000000000000..571d0ae000eb
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile
@@ -0,0 +1,11 @@ 
+# SPDX-License-Identifier: GPL-2.0
+#
+
+mtk_imgsys_util-objs := \
+mtk_imgsys-of.o \
+mtk_imgsys-formats.o \
+mtk_imgsys-dev.o \
+mtk_imgsys-sys.o \
+mtk_imgsys-v4l2.o
+
+obj-$(CONFIG_VIDEO_MTK_ISP_71_IMGSYS) += mtk_imgsys_util.o
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_dip_v4l2_vnode.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_dip_v4l2_vnode.h
new file mode 100644
index 000000000000..1b5c8b738a54
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_dip_v4l2_vnode.h
@@ -0,0 +1,594 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_DIP_V4L2_VNODE_H_
+#define _MTK_DIP_V4L2_VNODE_H_
+
+#include "../mtk_imgsys-dev.h"
+#include "../mtk_imgsys-formats.h"
+#include "../mtk_imgsys-vnode_id.h"
+
+static const struct mtk_imgsys_dev_format dip_imgi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_vipi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_rec_dsi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_rec_dpi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y32,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_meta_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_y32,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_tnrw_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 192,
+		.scan_align = 192,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_tnrci_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 144,
+		.scan_align = 108,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_tnrli_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_img2o_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_img3o_fmts[] = {
+	/* YUV422, 3 plane 8 bit */
+	/* YUV420, 2 plane 8 bit */
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	/* Y8 bit */
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format dip_img4o_fmts[] = {
+	/* YUV420, 2 plane 8 bit */
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	/* Y8 bit */
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct v4l2_frmsizeenum dip_in_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+	.stepwise.min_width = MTK_IMGSYS_CAPTURE_MIN_WIDTH,
+	.stepwise.max_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+	.stepwise.min_height = MTK_IMGSYS_CAPTURE_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct v4l2_frmsizeenum dip_out_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+	.stepwise.min_width = MTK_IMGSYS_OUTPUT_MIN_WIDTH,
+	.stepwise.max_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+	.stepwise.min_height = MTK_IMGSYS_OUTPUT_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct mtk_imgsys_video_device_desc dip_setting[] = {
+	/* Input Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_IMGI_OUT,
+		.name = "Imgi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_imgi_fmts,
+		.num_fmts = ARRAY_SIZE(dip_imgi_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Main image source",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_VIPI_OUT,
+		.name = "Vipi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_vipi_fmts,
+		.num_fmts = ARRAY_SIZE(dip_vipi_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Vipi image source",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_REC_DSI_OUT,
+		.name = "Rec_Dsi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_rec_dsi_fmts,
+		.num_fmts = ARRAY_SIZE(dip_rec_dsi_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Down Source Image",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_REC_DPI_OUT,
+		.name = "Rec_Dpi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_rec_dpi_fmts,
+		.num_fmts = ARRAY_SIZE(dip_rec_dpi_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Down Processed Image",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_CNR_BLURMAPI_OUT,
+		.name = "Bokeh Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Bokehi data",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_LFEI_OUT,
+		.name = "Dmgi_FM Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Dmgi_FM data",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_RFEI_OUT,
+		.name = "Depi_FM Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Depi_FM data",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRSI_OUT,
+		.name = "Tnrsi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Statistics input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRWI_OUT,
+		.name = "Tnrwi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_tnrw_fmts,
+		.num_fmts = ARRAY_SIZE(dip_tnrw_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Weighting input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRMI_OUT,
+		.name = "Tnrmi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Motion Map input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRCI_OUT,
+		.name = "Tnrci Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_tnrci_fmts,
+		.num_fmts = ARRAY_SIZE(dip_tnrci_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Confidence Map input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRLI_OUT,
+		.name = "Tnrli Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_tnrli_fmts,
+		.num_fmts = ARRAY_SIZE(dip_tnrli_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Low Frequency Diff input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRVBI_OUT,
+		.name = "Tnrvbi Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Valid Bit Map input",
+	},
+	/* Output Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_IMG2O_CAPTURE,
+		.name = "Img2o Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_img2o_fmts,
+		.num_fmts = ARRAY_SIZE(dip_img2o_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "Resized output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_IMG3O_CAPTURE,
+		.name = "Img3o Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_img3o_fmts,
+		.num_fmts = ARRAY_SIZE(dip_img3o_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "Dip output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_IMG4O_CAPTURE,
+		.name = "Img4o Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_img4o_fmts,
+		.num_fmts = ARRAY_SIZE(dip_img4o_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "Nr3d output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_FMO_CAPTURE,
+		.name = "FM Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "FM output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRSO_CAPTURE,
+		.name = "Tnrso Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "statistics output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRWO_CAPTURE,
+		.name = "Tnrwo Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_tnrw_fmts,
+		.num_fmts = ARRAY_SIZE(dip_tnrw_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "Weighting output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TNRMO_CAPTURE,
+		.name = "Tnrmo Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = dip_meta_fmts,
+		.num_fmts = ARRAY_SIZE(dip_meta_fmts),
+		.default_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &dip_out_frmsizeenum,
+		.description = "Motion Map output",
+	},
+};
+
+#endif // _MTK_IMGSYS_V4L2_VNODE_H_
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_me_v4l2_vnode.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_me_v4l2_vnode.h
new file mode 100644
index 000000000000..d33f8847731f
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_me_v4l2_vnode.h
@@ -0,0 +1,386 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_ME_V4L2_VNODE_H_
+#define _MTK_ME_V4L2_VNODE_H_
+
+#include "../mtk_imgsys-dev.h"
+#include "../mtk_imgsys-formats.h"
+#include "../mtk_imgsys-vnode_id.h"
+
+static const struct mtk_imgsys_dev_format me_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_y32,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y16,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format mewmap_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_warp2p,
+		.align = 8,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format melmi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_y16,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format mel1i_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_aply8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct v4l2_frmsizeenum in_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_IMGSYS_CAPTURE_MAX_WIDTH,
+	.stepwise.min_width = MTK_IMGSYS_CAPTURE_MIN_WIDTH,
+	.stepwise.max_height = MTK_IMGSYS_CAPTURE_MAX_HEIGHT,
+	.stepwise.min_height = MTK_IMGSYS_CAPTURE_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct v4l2_frmsizeenum out_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+	.stepwise.min_width = MTK_IMGSYS_OUTPUT_MIN_WIDTH,
+	.stepwise.max_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+	.stepwise.min_height = MTK_IMGSYS_OUTPUT_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct mtk_imgsys_video_device_desc me_setting[] = {
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL0IMG0_OUT,
+		.name = "L0I0I Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME Input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL0IMG1_OUT,
+		.name = "L0I1I Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME Input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL1IMG0_OUT,
+		.name = "L1I0I Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = mel1i_fmts,
+		.num_fmts = ARRAY_SIZE(mel1i_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME L1 Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL1IMG1_OUT,
+		.name = "L1I1I Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = mel1i_fmts,
+		.num_fmts = ARRAY_SIZE(mel1i_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME L1 Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEIMGSTATS_OUT,
+		.name = "STATI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME IMGSTATS Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL0RMV_OUT,
+		.name = "L0RMVI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME L0RMV Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL1RMV_OUT,
+		.name = "L1RMVI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME L1RMV Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL0FMB_OUT,
+		.name = "L0FMBI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME L0FMB Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL1FMB_OUT,
+		.name = "L1FMBI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME L1FMB Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEMIL_OUT,
+		.name = "MEMILI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &in_frmsizeenum,
+		.description = "ME MIL Input ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEMMGMIL_CAPTURE,
+		.name = "MILO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME MMGMIL Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL0WMV_CAPTURE,
+		.name = "L0WMVO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME L0WMV Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL1WMV_CAPTURE,
+		.name = "L1WMVO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME L1WMV Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MECONF_CAPTURE,
+		.name = "CONFO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME CONF Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEWMAP_CAPTURE,
+		.name = "WMAPO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = mewmap_fmts,
+		.num_fmts = ARRAY_SIZE(mewmap_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME WMAP Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEFMV_CAPTURE,
+		.name = "FMVO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME OTHERS Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEFST_CAPTURE,
+		.name = "FSTO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME FST Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MELMI_CAPTURE,
+		.name = "LMIO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = melmi_fmts,
+		.num_fmts = ARRAY_SIZE(melmi_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME LMI Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL0WFMB_CAPTURE,
+		.name = "L0FMBO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME L0FMB Output ",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_MEL1WFMB_CAPTURE,
+		.name = "L1FMBO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = me_fmts,
+		.num_fmts = ARRAY_SIZE(me_fmts),
+		.default_width = MTK_IMGSYS_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_IMGSYS_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &out_frmsizeenum,
+		.description = "ME L1FMB Output ",
+	},
+};
+
+#endif /* _MTK_ME_V4L2_VNODE_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_pqdip_v4l2_vnode.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_pqdip_v4l2_vnode.h
new file mode 100644
index 000000000000..23c8db3b30f3
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_pqdip_v4l2_vnode.h
@@ -0,0 +1,149 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Daniel Huang <daniel.huang@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_PQDIP_V4L2_VNODE_H_
+#define _MTK_PQDIP_V4L2_VNODE_H_
+
+#include "../mtk_imgsys-dev.h"
+#include "../mtk_imgsys-formats.h"
+#include "../mtk_imgsys-vnode_id.h"
+
+#define MTK_PQDIP_OUTPUT_MIN_WIDTH		2U
+#define MTK_PQDIP_OUTPUT_MIN_HEIGHT		2U
+#define MTK_PQDIP_OUTPUT_MAX_WIDTH		5376U
+#define MTK_PQDIP_OUTPUT_MAX_HEIGHT		4032U
+#define MTK_PQDIP_CAPTURE_MIN_WIDTH		2U
+#define MTK_PQDIP_CAPTURE_MIN_HEIGHT		2U
+#define MTK_PQDIP_CAPTURE_MAX_WIDTH		5376U
+#define MTK_PQDIP_CAPTURE_MAX_HEIGHT		4032U
+
+static const struct mtk_imgsys_dev_format pqdip_pimgi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format pqdip_wroto_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format pqdip_tccso_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+};
+
+static const struct v4l2_frmsizeenum pqdip_in_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+	.stepwise.min_width = MTK_PQDIP_CAPTURE_MIN_WIDTH,
+	.stepwise.max_height = MTK_PQDIP_CAPTURE_MAX_HEIGHT,
+	.stepwise.min_height = MTK_PQDIP_CAPTURE_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct v4l2_frmsizeenum pqdip_out_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_PQDIP_OUTPUT_MAX_WIDTH,
+	.stepwise.min_width = MTK_PQDIP_OUTPUT_MIN_WIDTH,
+	.stepwise.max_height = MTK_PQDIP_OUTPUT_MAX_HEIGHT,
+	.stepwise.min_height = MTK_PQDIP_OUTPUT_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct mtk_imgsys_video_device_desc pqdip_setting[] = {
+	/* Input Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_PIMGI_OUT,
+		.name = "PIMGI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = pqdip_pimgi_fmts,
+		.num_fmts = ARRAY_SIZE(pqdip_pimgi_fmts),
+		.default_width = MTK_PQDIP_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_PQDIP_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &pqdip_in_frmsizeenum,
+		.description = "Imgi image source",
+	},
+	/* Output Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WROT_A_CAPTURE,
+		.name = "WROTO A Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = pqdip_wroto_fmts,
+		.num_fmts = ARRAY_SIZE(pqdip_wroto_fmts),
+		.default_width = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &pqdip_out_frmsizeenum,
+		.description = "Output quality enhanced image",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WROT_B_CAPTURE,
+		.name = "WROTO B Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = pqdip_wroto_fmts,
+		.num_fmts = ARRAY_SIZE(pqdip_wroto_fmts),
+		.default_width = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &pqdip_out_frmsizeenum,
+		.description = "Output quality enhanced image",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TCCSO_A_CAPTURE,
+		.name = "TCCSO A Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = pqdip_tccso_fmts,
+		.num_fmts = ARRAY_SIZE(pqdip_tccso_fmts),
+		.default_width = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &pqdip_out_frmsizeenum,
+		.description = "Output tone curve statistics",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TCCSO_B_CAPTURE,
+		.name = "TCCSO B Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = pqdip_tccso_fmts,
+		.num_fmts = ARRAY_SIZE(pqdip_tccso_fmts),
+		.default_width = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_PQDIP_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &pqdip_out_frmsizeenum,
+		.description = "Output tone curve statistics",
+	},
+};
+
+#endif /* _MTK_PQDIP_V4L2_VNODE_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_traw_v4l2_vnode.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_traw_v4l2_vnode.h
new file mode 100644
index 000000000000..ec03f7a59be8
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_traw_v4l2_vnode.h
@@ -0,0 +1,371 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Shih-Fang chuang <shih-fang.chuang@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_TRAW_V4L2_VNODE_H_
+#define _MTK_TRAW_V4L2_VNODE_H_
+
+#include "../mtk_imgsys-dev.h"
+#include "../mtk_imgsys-formats.h"
+#include "../mtk_imgsys-vnode_id.h"
+
+#define MTK_TRAW_OUTPUT_MIN_WIDTH		2U
+#define MTK_TRAW_OUTPUT_MIN_HEIGHT		2U
+#define MTK_TRAW_OUTPUT_MAX_WIDTH		5376U
+#define MTK_TRAW_OUTPUT_MAX_HEIGHT		4032U
+#define MTK_TRAW_CAPTURE_MIN_WIDTH		2U
+#define MTK_TRAW_CAPTURE_MIN_HEIGHT		2U
+#define MTK_TRAW_CAPTURE_MAX_WIDTH		5376U
+#define MTK_TRAW_CAPTURE_MAX_HEIGHT		4032U
+
+static const struct mtk_imgsys_dev_format traw_imgi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_sgbrg10,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_warp2p,
+		.align = 8,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_srggb10,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_sgrbg10,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format traw_metai_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_metai,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format traw_stato_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_stt,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format traw_yuvo_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_warp2p,
+		.align = 8,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y8,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_aply8,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format traw_pdc_fmts[] = {
+	/* Y8 bit */
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+};
+
+static const struct v4l2_frmsizeenum traw_in_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+	.stepwise.min_width = MTK_TRAW_CAPTURE_MIN_WIDTH,
+	.stepwise.max_height = MTK_TRAW_CAPTURE_MAX_HEIGHT,
+	.stepwise.min_height = MTK_TRAW_CAPTURE_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct v4l2_frmsizeenum traw_out_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_TRAW_OUTPUT_MAX_WIDTH,
+	.stepwise.min_width = MTK_TRAW_OUTPUT_MIN_WIDTH,
+	.stepwise.max_height = MTK_TRAW_OUTPUT_MAX_HEIGHT,
+	.stepwise.min_height = MTK_TRAW_OUTPUT_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct mtk_imgsys_video_device_desc traw_setting[] = {
+	/* Input Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TIMGI_OUT,
+		.name = "TIMGI Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_imgi_fmts,
+		.num_fmts = ARRAY_SIZE(traw_imgi_fmts),
+		.default_width = MTK_TRAW_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_TRAW_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &traw_in_frmsizeenum,
+		.description = "Imgi image source",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_METAI_OUT,
+		.name = "METAI Input",
+		.cap = V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_META_OUTPUT,
+		.smem_alloc = 1,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_metai_fmts,
+		.num_fmts = ARRAY_SIZE(traw_metai_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &traw_in_frmsizeenum,
+		.description = "METAI image source",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_PDC_OUT,
+		.name = "PDC Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_pdc_fmts,
+		.num_fmts = ARRAY_SIZE(traw_pdc_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &traw_in_frmsizeenum,
+		.description = "PDC image source",
+	},
+	/* Output Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TYUVO_CAPTURE,
+		.name = "TYUVO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_yuvo_fmts,
+		.num_fmts = ARRAY_SIZE(traw_yuvo_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "YUVO output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TYUV2O_CAPTURE,
+		.name = "TYUV2O Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_yuvo_fmts,
+		.num_fmts = ARRAY_SIZE(traw_yuvo_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "YUV2O output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TYUV3O_CAPTURE,
+		.name = "TYUV3O Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_yuvo_fmts,
+		.num_fmts = ARRAY_SIZE(traw_yuvo_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "YUV3O output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TYUV4O_CAPTURE,
+		.name = "TYUV4O Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_yuvo_fmts,
+		.num_fmts = ARRAY_SIZE(traw_yuvo_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "YUV4O output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TYUV5O_CAPTURE,
+		.name = "TYUV5O Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_yuvo_fmts,
+		.num_fmts = ARRAY_SIZE(traw_yuvo_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "YUV5O output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_FEO_CAPTURE,
+		.name = "FEO Output",
+		.cap = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_META_CAPTURE,
+		.smem_alloc = 1,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_metai_fmts,
+		.num_fmts = ARRAY_SIZE(traw_metai_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "FEO output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TIMGO_CAPTURE,
+		.name = "TIMGO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_imgi_fmts,
+		.num_fmts = ARRAY_SIZE(traw_imgi_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "TIMGO output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_IMGSTATO_CAPTURE,
+		.name = "IMGSTATO Output",
+		.cap = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_META_CAPTURE,
+		.smem_alloc = 1,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_stato_fmts,
+		.num_fmts = ARRAY_SIZE(traw_stato_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "IMGSTATO output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_XTMEO_CAPTURE,
+		.name = "XTMEO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_pdc_fmts,
+		.num_fmts = ARRAY_SIZE(traw_pdc_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "XTMEO output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_XTFDO_CAPTURE,
+		.name = "XTFDO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_yuvo_fmts,
+		.num_fmts = ARRAY_SIZE(traw_yuvo_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "XTFDO output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_XTADLDBGO_CAPTURE,
+		.name = "XTDBGO Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = traw_imgi_fmts,
+		.num_fmts = ARRAY_SIZE(traw_imgi_fmts),
+		.default_width = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_TRAW_CAPTURE_MAX_WIDTH,
+		.frmsizeenum = &traw_out_frmsizeenum,
+		.description = "XTDBGO output",
+	},
+};
+
+#endif /* _MTK_TRAW_V4L2_VNODE_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_wpe_v4l2_vnode.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_wpe_v4l2_vnode.h
new file mode 100644
index 000000000000..3e378d54b900
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_wpe_v4l2_vnode.h
@@ -0,0 +1,317 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Floria Huang <floria.huang@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_WPE_V4L2_VNODE_H_
+#define _MTK_WPE_V4L2_VNODE_H_
+
+#include "../mtk_imgsys-dev.h"
+#include "../mtk_imgsys-formats.h"
+#include "../mtk_imgsys-vnode_id.h"
+
+#define MTK_WPE_OUTPUT_MIN_WIDTH	2U
+#define MTK_WPE_OUTPUT_MIN_HEIGHT	2U
+#define MTK_WPE_OUTPUT_MAX_WIDTH	18472U
+#define MTK_WPE_OUTPUT_MAX_HEIGHT	13856U
+
+#define MTK_WPE_MAP_OUTPUT_MIN_WIDTH	2U
+#define MTK_WPE_MAP_OUTPUT_MIN_HEIGHT	2U
+#define MTK_WPE_MAP_OUTPUT_MAX_WIDTH	640U
+#define MTK_WPE_MAP_OUTPUT_MAX_HEIGHT	480U
+
+#define MTK_WPE_PSP_OUTPUT_WIDTH	8U
+#define MTK_WPE_PSP_OUTPUT_HEIGHT	33U
+
+#define MTK_WPE_CAPTURE_MIN_WIDTH	2U
+#define MTK_WPE_CAPTURE_MIN_HEIGHT	2U
+#define MTK_WPE_CAPTURE_MAX_WIDTH	18472U
+#define MTK_WPE_CAPTURE_MAX_HEIGHT	13856U
+
+static const struct mtk_imgsys_dev_format wpe_wpei_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	/* Y8 bit */
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 192,
+		.scan_align = 192,
+	},
+	/* Bayer 10 bit */
+	{
+		.fmt = &mtk_imgsys_format_sgbrg10,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format wpe_veci_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_warp2p,
+		.align = 8,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format wpe_pspi_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_y32,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format wpe_wpeo_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_nv12,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_nv21,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 192,
+		.scan_align = 192,
+	},
+	{
+		.fmt = &mtk_imgsys_format_sgbrg10,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p010p,
+		.align = 1,
+		.scan_align = 1,
+	},
+	{
+		.fmt = &mtk_imgsys_format_2p012p,
+		.align = 1,
+		.scan_align = 1,
+	},
+};
+
+static const struct mtk_imgsys_dev_format wpe_msko_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_grey,
+		.align = 16,
+		.scan_align = 1,
+	},
+};
+
+static const struct v4l2_frmsizeenum wpe_in_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+	.stepwise.min_width = MTK_WPE_CAPTURE_MIN_WIDTH,
+	.stepwise.max_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+	.stepwise.min_height = MTK_WPE_CAPTURE_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct v4l2_frmsizeenum wpe_in_map_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_WPE_MAP_OUTPUT_MAX_WIDTH,
+	.stepwise.min_width = MTK_WPE_MAP_OUTPUT_MIN_WIDTH,
+	.stepwise.max_height = MTK_WPE_MAP_OUTPUT_MAX_HEIGHT,
+	.stepwise.min_height = MTK_WPE_MAP_OUTPUT_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct v4l2_frmsizeenum wpe_out_frmsizeenum = {
+	.type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+	.stepwise.max_width = MTK_WPE_OUTPUT_MAX_WIDTH,
+	.stepwise.min_width = MTK_WPE_OUTPUT_MIN_WIDTH,
+	.stepwise.max_height = MTK_WPE_OUTPUT_MAX_HEIGHT,
+	.stepwise.min_height = MTK_WPE_OUTPUT_MIN_HEIGHT,
+	.stepwise.step_height = 1,
+	.stepwise.step_width = 1,
+};
+
+static const struct mtk_imgsys_video_device_desc wpe_setting[] = {
+	/* Input Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WWPEI_OUT,
+		.name = "WPEI_E Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_wpei_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_wpei_fmts),
+		.default_width = MTK_WPE_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_WPE_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &wpe_in_frmsizeenum,
+		.description = "WPE main image input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WVECI_OUT,
+		.name = "VECI_E Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_veci_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_veci_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_in_map_frmsizeenum,
+		.description = "WarpMap input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WPSP_COEFI_OUT,
+		.name = "PSPI_E Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_pspi_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_pspi_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_in_frmsizeenum,
+		.description = "PSP coef. table input",
+	},
+	/* WPE_EIS Output Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WWPEO_CAPTURE,
+		.name = "WPEO_E Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_wpeo_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_wpeo_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_out_frmsizeenum,
+		.description = "WPE image output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WMSKO_CAPTURE,
+		.name = "MSKO_E Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_msko_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_msko_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_out_frmsizeenum,
+		.description = "WPE valid map output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WTWPEI_OUT,
+		.name = "WPEI_T Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_wpei_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_wpei_fmts),
+		.default_width = MTK_WPE_OUTPUT_MAX_WIDTH,
+		.default_height = MTK_WPE_OUTPUT_MAX_HEIGHT,
+		.frmsizeenum = &wpe_in_frmsizeenum,
+		.description = "WPE main image input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WTVECI_OUT,
+		.name = "VECI_T Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_veci_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_veci_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_in_map_frmsizeenum,
+		.description = "WarpMap input",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WTPSP_COEFI_OUT,
+		.name = "PSPI_T Input",
+		.cap = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_pspi_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_pspi_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_in_frmsizeenum,
+		.description = "PSP coef. table input",
+	},
+	/* WPE_TNR Output Video Node */
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WTWPEO_CAPTURE,
+		.name = "WPEO_T Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_wpeo_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_wpeo_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_out_frmsizeenum,
+		.description = "WPE image output",
+	},
+	{
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_WTMSKO_CAPTURE,
+		.name = "MSKO_T Output",
+		.cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.smem_alloc = 0,
+		.supports_ctrls = true,
+		.flags = MEDIA_LNK_FL_DYNAMIC,
+		.fmts = wpe_msko_fmts,
+		.num_fmts = ARRAY_SIZE(wpe_msko_fmts),
+		.default_width = MTK_WPE_CAPTURE_MAX_WIDTH,
+		.default_height = MTK_WPE_CAPTURE_MAX_HEIGHT,
+		.frmsizeenum = &wpe_out_frmsizeenum,
+		.description = "WPE valid map output",
+	},
+};
+
+#endif /* _MTK_WPE_V4L2_VNODE_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_header_desc.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_header_desc.h
new file mode 100644
index 000000000000..50c2e3c3395b
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_header_desc.h
@@ -0,0 +1,28 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ */
+
+#ifndef _HEADER_DESC_
+#define _HEADER_DESC_
+
+#include <linux/videodev2.h>
+
+/**
+ * struct mtk_imgsys_crop - Crop parameters for MediaTek Image System
+ * @c: Rectangle defining the crop area
+ * @left_subpix: Sub-pixel adjustment for the left edge
+ * @top_subpix: Sub-pixel adjustment for the top edge
+ * @width_subpix: Sub-pixel adjustment for the width
+ * @height_subpix: Sub-pixel adjustment for the height
+ */
+struct mtk_imgsys_crop {
+	struct v4l2_rect    c;             /* Rectangle defining the crop area */
+	struct v4l2_fract   left_subpix;   /* Sub-pixel adjustment for the left edge */
+	struct v4l2_fract   top_subpix;    /* Sub-pixel adjustment for the top edge */
+	struct v4l2_fract   width_subpix;  /* Sub-pixel adjustment for the width */
+	struct v4l2_fract   height_subpix; /* Sub-pixel adjustment for the height */
+};
+
+#endif
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.c
new file mode 100644
index 000000000000..28a35a3226a2
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.c
@@ -0,0 +1,238 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+
+#include "linux/list.h"
+#include <linux/dma-buf.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/hashtable.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-event.h>
+#include "mtk_imgsys-formats.h"
+#include "mtk_imgsys-vnode_id.h"
+#include "mtk_imgsys-dev.h"
+#include "mtk_imgsys-sys.h"
+
+int mtk_imgsys_pipe_init(struct mtk_imgsys_dev *imgsys_dev,
+			 struct mtk_imgsys_pipe *pipe,
+			 const struct mtk_imgsys_pipe_desc *setting)
+{
+	u32 i, nodes_num;
+	size_t nodes_size;
+
+	pipe->imgsys_dev = imgsys_dev;
+	pipe->desc = setting;
+	pipe->nodes_enabled = 0ULL;
+	pipe->nodes_streaming = 0ULL;
+
+	atomic_set(&pipe->pipe_job_sequence, 0);
+	INIT_LIST_HEAD(&pipe->pipe_job_running_list);
+	INIT_LIST_HEAD(&pipe->pipe_job_pending_list);
+
+	spin_lock_init(&pipe->pending_job_lock);
+	spin_lock_init(&pipe->running_job_lock);
+	mutex_init(&pipe->lock);
+
+	nodes_num = pipe->desc->total_queues;
+	nodes_size = sizeof(*pipe->nodes) * nodes_num;
+	pipe->nodes = devm_kzalloc(imgsys_dev->dev, nodes_size, GFP_KERNEL);
+	if (!pipe->nodes)
+		return -ENOMEM;
+
+	for (i = 0; i < nodes_num; i++) {
+		pipe->nodes[i].desc = &pipe->desc->queue_descs[i];
+		pipe->nodes[i].flags = pipe->nodes[i].desc->flags;
+		spin_lock_init(&pipe->nodes[i].buf_list_lock);
+		INIT_LIST_HEAD(&pipe->nodes[i].buf_list);
+
+		pipe->nodes[i].crop.left = 0;
+		pipe->nodes[i].crop.top = 0;
+		pipe->nodes[i].crop.width =
+			pipe->nodes[i].desc->frmsizeenum->stepwise.max_width;
+		pipe->nodes[i].crop.height =
+			pipe->nodes[i].desc->frmsizeenum->stepwise.max_height;
+
+		pipe->nodes[i].compose.left = 0;
+		pipe->nodes[i].compose.top = 0;
+		pipe->nodes[i].compose.width =
+			pipe->nodes[i].desc->frmsizeenum->stepwise.max_width;
+		pipe->nodes[i].compose.height =
+			pipe->nodes[i].desc->frmsizeenum->stepwise.max_height;
+	}
+
+	return 0;
+}
+
+int mtk_imgsys_pipe_release(struct mtk_imgsys_pipe *pipe)
+{
+	mutex_destroy(&pipe->lock);
+
+	return 0;
+}
+
+int mtk_imgsys_pipe_next_job_id(struct mtk_imgsys_pipe *pipe)
+{
+	int global_job_id = atomic_inc_return(&pipe->pipe_job_sequence);
+
+	return (global_job_id & 0x0000FFFF) | (pipe->desc->id << 16);
+}
+
+void mtk_imgsys_pipe_debug_job(struct mtk_imgsys_pipe *pipe,
+			       struct mtk_imgsys_request *req)
+{
+	int i;
+
+	dev_dbg(pipe->imgsys_dev->dev, "%s:%s: pipe-job(%p),id(%d)\n",
+		__func__, pipe->desc->name, req, req->id);
+
+	for (i = 0; i < pipe->desc->total_queues ; i++) {
+		if (req->buf_map[i])
+			dev_dbg(pipe->imgsys_dev->dev, "%s:%s:buf(%p)\n",
+				pipe->desc->name, pipe->nodes[i].desc->name,
+				req->buf_map[i]);
+	}
+}
+
+static unsigned int mtk_imgsys_get_stride(unsigned int width,
+					  const struct mtk_imgsys_dev_format *dfmt,
+					  unsigned int plane)
+{
+	unsigned int stride =
+		(width + dfmt->fmt->pixels_per_group - 1) /
+		dfmt->fmt->pixels_per_group * dfmt->fmt->bytes_per_group[plane];
+
+	return (stride + dfmt->align - 1) / dfmt->align * dfmt->align;
+}
+
+static unsigned int mtk_imgsys_get_height(unsigned int height,
+					  const struct mtk_imgsys_dev_format *dfmt,
+					  unsigned int plane)
+{
+	unsigned int plane_height =
+		(height + dfmt->fmt->vertical_sub_sampling[plane] - 1) /
+		dfmt->fmt->vertical_sub_sampling[plane];
+
+	return (plane_height + dfmt->scan_align - 1) / dfmt->scan_align * dfmt->scan_align;
+}
+
+void mtk_imgsys_pipe_try_fmt(struct mtk_imgsys_video_device *node,
+			     struct v4l2_format *fmt,
+			     const struct v4l2_format *ufmt,
+			     const struct mtk_imgsys_dev_format *dfmt)
+{
+	unsigned int i;
+
+	if (!dfmt)
+		return;
+
+	fmt->type = ufmt->type;
+	fmt->fmt.pix_mp.width =
+		clamp_val(ufmt->fmt.pix_mp.width,
+			  node->desc->frmsizeenum->stepwise.min_width,
+			  node->desc->frmsizeenum->stepwise.max_width);
+	fmt->fmt.pix_mp.height =
+		clamp_val(ufmt->fmt.pix_mp.height,
+			  node->desc->frmsizeenum->stepwise.min_height,
+			  node->desc->frmsizeenum->stepwise.max_height);
+	fmt->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
+	fmt->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	fmt->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB;
+	fmt->fmt.pix_mp.field = V4L2_FIELD_NONE;
+
+	fmt->fmt.pix_mp.pixelformat = dfmt->fmt->format;
+	fmt->fmt.pix_mp.num_planes = dfmt->fmt->num_planes;
+
+	for (i = 0; i < fmt->fmt.pix_mp.num_planes; ++i) {
+		struct v4l2_plane_pix_format *plane =
+			&fmt->fmt.pix_mp.plane_fmt[i];
+		const struct v4l2_plane_pix_format *uplane;
+
+		uplane = &ufmt->fmt.pix_mp.plane_fmt[i];
+		plane->bytesperline =
+			mtk_imgsys_get_stride(fmt->fmt.pix_mp.width, dfmt, i);
+		if (plane->bytesperline < uplane->bytesperline)
+			plane->bytesperline = uplane->bytesperline;
+
+		plane->sizeimage = plane->bytesperline *
+			mtk_imgsys_get_height(fmt->fmt.pix_mp.height, dfmt, i);
+
+		plane->sizeimage += dfmt->fmt->ext_data;
+	}
+}
+
+static void set_meta_fmt(struct mtk_imgsys_pipe *pipe,
+			 struct v4l2_meta_format *fmt,
+			 const struct mtk_imgsys_dev_format *dev_fmt)
+{
+	fmt->dataformat = dev_fmt->fmt->format;
+	fmt->buffersize = dev_fmt->fmt->buffer_size;
+}
+
+void mtk_imgsys_pipe_load_default_fmt(struct mtk_imgsys_pipe *pipe,
+				      struct mtk_imgsys_video_device *node,
+				      struct v4l2_format *fmt)
+{
+	fmt->type = node->desc->buf_type;
+	if (mtk_imgsys_buf_is_meta(node->desc->buf_type)) {
+		set_meta_fmt(pipe, &fmt->fmt.meta,
+			     &node->desc->fmts[0]);
+	} else {
+		fmt->fmt.pix_mp.width = node->desc->default_width;
+		fmt->fmt.pix_mp.height = node->desc->default_height;
+		mtk_imgsys_pipe_try_fmt(node, fmt, fmt,
+					&node->desc->fmts[0]);
+	}
+}
+
+const struct mtk_imgsys_dev_format*
+mtk_imgsys_pipe_find_fmt(struct mtk_imgsys_pipe *pipe,
+			 struct mtk_imgsys_video_device *node,
+			 u32 format)
+{
+	int i;
+
+	for (i = 0; i < node->desc->num_fmts; i++) {
+		if (node->desc->fmts[i].fmt->format == format)
+			return &node->desc->fmts[i];
+	}
+
+	return NULL;
+}
+
+void mtk_imgsys_pipe_try_enqueue(struct mtk_imgsys_pipe *pipe)
+{
+	struct mtk_imgsys_request *req = NULL;
+	unsigned long flag;
+
+	if (!pipe->streaming)
+		return;
+
+	spin_lock_irqsave(&pipe->pending_job_lock, flag);
+	if (list_empty(&pipe->pipe_job_pending_list)) {
+		spin_unlock_irqrestore(&pipe->pending_job_lock, flag);
+		return;
+	}
+
+	req = list_first_entry(&pipe->pipe_job_pending_list, struct mtk_imgsys_request, list);
+	list_del(&req->list);
+	pipe->num_pending_jobs--;
+	spin_unlock_irqrestore(&pipe->pending_job_lock, flag);
+
+	spin_lock_irqsave(&pipe->running_job_lock, flag);
+	list_add_tail(&req->list,
+		      &pipe->pipe_job_running_list);
+	pipe->num_jobs++;
+	spin_unlock_irqrestore(&pipe->running_job_lock, flag);
+
+	mtk_imgsys_hw_enqueue(pipe->imgsys_dev, req);
+	dev_dbg(pipe->imgsys_dev->dev,
+		"%s:%s: pending jobs(%d), running jobs(%d)\n",
+		__func__, pipe->desc->name, pipe->num_pending_jobs,
+		pipe->num_jobs);
+}
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.h
new file mode 100644
index 000000000000..b69cfd0043d3
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-dev.h
@@ -0,0 +1,427 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_IMGSYS_DEV_H_
+#define _MTK_IMGSYS_DEV_H_
+
+#include <linux/completion.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
+#include <linux/videodev2.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "mtk_header_desc.h"
+
+#define MTK_IMGSYS_MEDIA_MODEL_NAME	"MTK-ISP-DIP-V4L2"
+
+#define MTK_IMGSYS_OUTPUT_MIN_WIDTH		1U
+#define MTK_IMGSYS_OUTPUT_MIN_HEIGHT		1U
+#define MTK_IMGSYS_OUTPUT_MAX_WIDTH		5376U
+#define MTK_IMGSYS_OUTPUT_MAX_HEIGHT		4032U
+
+#define MTK_IMGSYS_CAPTURE_MIN_WIDTH		1U
+#define MTK_IMGSYS_CAPTURE_MIN_HEIGHT		1U
+#define MTK_IMGSYS_CAPTURE_MAX_WIDTH		5376U
+#define MTK_IMGSYS_CAPTURE_MAX_HEIGHT		4032U
+
+/**
+ * struct mtk_imgsys_dev_format - Device format for MediaTek Image System
+ * @fmt: Pointer to the Image System format structure
+ * @align: Alignment requirement
+ * @scan_align: Scan alignment requirement
+ *
+ * This structure defines the format used by the MediaTek Image System device.
+ * It includes a pointer to the format structure, and alignment and scan
+ * alignment requirements.
+ */
+struct mtk_imgsys_dev_format {
+	const struct mtk_imgsys_format *fmt;
+	u32 align;
+	u32 scan_align;
+};
+
+/**
+ * struct mtk_imgsys_dev_buffer - Device buffer for MediaTek Image System
+ * @vbb: Video buffer structure for V4L2
+ * @fmt: Format of the video buffer
+ * @dev_fmt: Pointer to the device-specific format structure
+ * @isp_daddr: DMA addresses for ISP processing, indexed by plane
+ * @scp_daddr: DMA addresses for SCP processing, indexed by plane
+ * @crop: Crop information for image processing
+ * @compose: Composition rectangle for output
+ * @rotation: Rotation angle for the image
+ * @hflip: Horizontal flip flag
+ * @vflip: Vertical flip flag
+ * @resize_ratio: Ratio for resizing the image
+ * @dataofst: Offset for the data buffer
+ * @list: List head for buffer management
+ *
+ * This structure represents the buffer used by the MediaTek ImgSys device.
+ * It includes various parameters for buffer management and image processing,
+ * such as format, DMA addresses, cropping, composition, rotation, flipping,
+ * resizing, and list management. This buffer is essential for handling
+ * image data in the device's processing pipeline.
+ */
+struct mtk_imgsys_dev_buffer {
+	struct vb2_v4l2_buffer vbb;
+	struct v4l2_format fmt;
+	const struct mtk_imgsys_dev_format *dev_fmt;
+	dma_addr_t isp_daddr[VB2_MAX_PLANES];
+	dma_addr_t scp_daddr[VB2_MAX_PLANES];
+	struct mtk_imgsys_crop crop;
+	struct v4l2_rect compose;
+	__u32 rotation;
+	__u32 hflip;
+	__u32 vflip;
+	__u32 resize_ratio;
+	__u32 dataofst;
+	struct list_head list;
+};
+
+/**
+ * struct mtk_imgsys_pipe_desc - Description of an image processing pipeline
+ * @name: Name of the pipeline
+ * @id: Identifier for the pipeline
+ * @queue_descs: Pointer to an array of video device descriptors
+ * @total_queues: Total number of queues in the pipeline
+ *
+ * This structure describes an image processing pipeline within the MediaTek
+ * image system. It includes the name and identifier of the pipeline, and
+ * an array of video device descriptors along with the total number of queues.
+ */
+struct mtk_imgsys_pipe_desc {
+	char *name;
+	int id;
+	struct mtk_imgsys_video_device_desc *queue_descs;
+	int total_queues;
+};
+
+/**
+ * struct mtk_imgsys_video_device_desc - Description of a video device
+ * @id: Identifier for the video device
+ * @name: Name of the video device
+ * @buf_type: Buffer type used by the video device
+ * @cap: Capabilities of the video device
+ * @smem_alloc: Using the smem_dev as alloc device or not
+ * @supports_ctrls: Flag indicating if the device supports controls
+ * @fmts: Pointer to an array of supported formats
+ * @num_fmts: Number of supported formats
+ * @description: Description of the video device
+ * @default_width: Default width of the video frames
+ * @default_height: Default height of the video frames
+ * @dma_port: DMA port used by the video device
+ * @frmsizeenum: Pointer to an array of frame size enumerations
+ * @flags: Additional flags for the video device
+ *
+ * This structure describes a video device within the MediaTek image system.
+ * It includes various properties such as the identifier, name, buffer type,
+ * capabilities, supported formats, and other relevant details.
+ */
+struct mtk_imgsys_video_device_desc {
+	int id;
+	char *name;
+	u32 buf_type;
+	u32 cap;
+	int smem_alloc;
+	int supports_ctrls;
+	const struct mtk_imgsys_dev_format *fmts;
+	int num_fmts;
+	char *description;
+	int default_width;
+	int default_height;
+	unsigned int dma_port;
+	const struct v4l2_frmsizeenum *frmsizeenum;
+	u32 flags;
+};
+
+/**
+ * struct mtk_imgsys_dev_queue - Device queue structure for image system
+ * @vbq: VB2 queue structure
+ * @lock: Mutex to serialize vb2 queue and video device operations
+ * @dev_fmt: Pointer to the device format structure
+ *
+ * This structure defines the device queue for the image system, including the
+ * VB2 queue, a mutex for serializing operations, and a pointer to the device
+ * format.
+ */
+struct mtk_imgsys_dev_queue {
+	struct vb2_queue vbq;
+	struct mutex lock; /* Protect the vb2_queue */
+	const struct mtk_imgsys_dev_format *dev_fmt;
+};
+
+/**
+ * struct mtk_imgsys_video_device -
+ * Video device structure for MediaTek Image System
+ *
+ * @vdev: Video device structure
+ * @dev_q: Device queue for buffer management
+ * @vdev_fmt: Format of the video device
+ * @vdev_pad: Media pad for the video device
+ * @pad_fmt: Media bus frame format for the pad
+ * @ctrl_handler: Control handler for V4L2 controls
+ * @resize_ratio_ctrl: Pointer to the resize ratio control
+ * @flags: Link attribute flags (e.g., MEDIA_LNK_FL_ENABLED)
+ * @desc: Pointer to the video device description structure
+ * @buf_list: List head for buffer management
+ * @crop: Crop rectangle for the video device
+ * @compose: Composition rectangle for the video device
+ * @rotation: Rotation angle for the video device
+ * @vflip: Vertical flip flag
+ * @hflip: Horizontal flip flag
+ * @resize_ratio: Resize ratio for the video device
+ * @buf_list_lock: Spinlock to protect the in-device buffer list
+ *
+ * This structure represents the video device used by the MediaTek Image System.
+ * It includes various parameters for managing video buffers, formats, media pads,
+ * controls, cropping, composition, rotation, flipping, resizing, and buffer list
+ * protection. This structure is essential for handling video data and device
+ * configuration in the MediaTek Image System.
+ */
+struct mtk_imgsys_video_device {
+	struct video_device vdev;
+	struct mtk_imgsys_dev_queue dev_q;
+	struct v4l2_format vdev_fmt;
+	struct media_pad vdev_pad;
+	struct v4l2_mbus_framefmt pad_fmt;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_ctrl *resize_ratio_ctrl;
+	u32 flags; /* Link attribute flags, e.g. MEDIA_LNK_FL_ENABLED */
+	const struct mtk_imgsys_video_device_desc *desc;
+	struct list_head buf_list;
+	struct v4l2_rect crop;
+	struct v4l2_rect compose;
+	int rotation;
+	bool vflip;
+	bool hflip;
+	int resize_ratio;
+	/* protect the in-device buffer list */
+	spinlock_t buf_list_lock;
+};
+
+/**
+ * struct mtk_imgsys_pipe - Pipeline structure for MediaTek Image System
+ * @imgsys_dev: Pointer to the image system device
+ * @nodes: Pointer to the video device nodes associated with the pipeline
+ * @nodes_streaming: Bitmap representing streaming status of nodes
+ * @nodes_enabled: Bitmap representing enabled status of nodes
+ * @streaming: Flag indicating if the pipeline is currently streaming
+ * @subdev_pads: Media pads for subdevice connections
+ * @pipeline: Media pipeline structure
+ * @subdev: V4L2 subdevice structure
+ * @fh: File handle for subdevice operations
+ * @pipe_job_sequence: Atomic counter for job sequencing
+ * @pipe_job_pending_list: List head for pending jobs in the pipeline
+ * @num_pending_jobs: Number of pending jobs in the pipeline
+ * @pending_job_lock: To protect pipe_job_pending_list and num_pending_jobs
+ * @pipe_job_running_list: List head for running jobs in the pipeline
+ * @running_job_lock: Spinlock to protect pipe_job_running_list
+ * @num_jobs: Total number of jobs in the pipeline
+ * @lock: Mutex to serialize stream on/off and buffer enqueue operations
+ * @desc: Pointer to the pipeline description structure
+ *
+ * This structure represents a pipeline in the MediaTek Image System. It includes
+ * various components for managing the image processing pipeline, such as device
+ * pointers, video nodes, streaming flags, media pads, pipeline configuration,
+ * subdevice operations, job management, and synchronization mechanisms.
+ * This structure is essential for coordinating the flow of image data through
+ * the processing pipeline.
+ */
+struct mtk_imgsys_pipe {
+	struct mtk_imgsys_dev *imgsys_dev;
+	struct mtk_imgsys_video_device *nodes;
+	unsigned long long nodes_streaming;
+	unsigned long long nodes_enabled;
+	int streaming;
+	struct media_pad *subdev_pads;
+	struct media_pipeline pipeline;
+	struct v4l2_subdev subdev;
+	struct v4l2_subdev_fh *fh;
+	atomic_t pipe_job_sequence;
+	struct list_head pipe_job_pending_list;
+	int num_pending_jobs;
+	/* protect pipe_job_pending_list and num_pending_jobs */
+	spinlock_t pending_job_lock;
+	struct list_head pipe_job_running_list;
+	/* protect pipe_job_running_list */
+	spinlock_t running_job_lock;
+	int num_jobs;
+	/* Serializes pipe's stream on/off and buffers enqueue operations */
+	struct mutex lock;
+	const struct mtk_imgsys_pipe_desc *desc;
+};
+
+/**
+ * struct mtk_imgsys_dev - MediaTek Image System Device Structure
+ * @dev: Pointer to the device structure.
+ * @imgsys_resource: Resource descriptor for image system hardware.
+ * @mdev: Media device structure for media controller framework integration.
+ * @v4l2_dev: V4L2 device structure for video device operations.
+ * @imgsys_pipe: Image system pipeline configuration structure.
+ * @cust_pipes: Pointer to custom pipeline descriptors.
+ * @clks: Array of clock bulk data for managing multiple clocks.
+ * @num_clks: Number of clocks in the clock array.
+ * @larbs: Array of device pointers for managing LARB (local arbiter).
+ * @num_larbs: Number of LARBs in the system.
+ * @scp: Pointer to the SCP (System Control Processor) structure.
+ * @rproc_handle: Handle for remote processor interface.
+ * @smem_dev: Device structure for shared memory operations.
+ * @num_mods: Number of modules in the image system.
+ */
+struct mtk_imgsys_dev {
+	/* Device and Resource Information */
+	struct device *dev;
+	struct resource *imgsys_resource;
+	/* Media and V4L2 Device Management */
+	struct media_device mdev;
+	struct v4l2_device v4l2_dev;
+	struct mtk_imgsys_pipe imgsys_pipe;
+	/* Imgsys Pipeline Information */
+	const struct mtk_imgsys_pipe_desc *cust_pipes;
+	/* Clock Information */
+	struct clk_bulk_data *clks;
+	int num_clks;
+	/* LARB (Local Arbitration) Control */
+	struct device **larbs;
+	unsigned int num_larbs;
+	/* SCP (System Control Processor) Integration */
+	struct mtk_scp *scp;
+	struct rproc *rproc_handle;
+	struct device *smem_dev;
+	/* Number of modules */
+	int num_mods;
+};
+
+/**
+ * struct req_frameparam - Request frame parameters for MediaTek Image System
+ * @frame_no: Frame number identifier
+ * @state: State of the frame (e.g., init, timeout)
+ *
+ * This structure represents the parameters for a request frame in the MediaTek Image System.
+ * It includes various attributes such as the frame index, frame number, timestamp, state,
+ * and the number of input and output buffers. This structure is used to manage and track
+ * the frames within the image processing pipeline.
+ */
+struct req_frameparam {
+	u32		frame_no;
+	u8		state;
+} __packed;
+
+/**
+ * struct mtk_imgsys_request - Request structure for MediaTek Image System
+ * @req: Media request structure
+ * @imgsys_pipe: Pointer to the image system pipeline
+ * @id: Unique identifier for the request
+ * @buf_map: Pointer to an array of device buffers mapped to the request
+ * @list: List head for request management
+ * @img_fparam: Frame parameters associated with the request
+ * @composer_work: Work structure for composer tasks
+ * @runner_work: Work structure for runner tasks
+ * @working_buf: Pointer to the hardware working buffer
+ * @swfrm_info: Pointer to software frame information
+ * @buf_count: Atomic counter for buffer management
+ * @request_fd: File descriptor for the request
+ *
+ * This structure represents a request in the MediaTek Image System. It includes
+ * various parameters for managing media requests, image processing pipeline,
+ * buffer mapping, frame parameters, work tasks, hardware buffers, software frame
+ * information, buffer count, and request file descriptor. This structure is
+ * essential for handling and processing image requests within the MediaTek Image
+ * System.
+ */
+struct mtk_imgsys_request {
+	struct media_request req;
+	struct mtk_imgsys_pipe *imgsys_pipe;
+	int id;
+	struct mtk_imgsys_dev_buffer **buf_map;
+	struct list_head list;
+	struct req_frameparam img_fparam;
+	atomic_t buf_count;
+	int request_fd;
+};
+
+static inline struct mtk_imgsys_video_device*
+mtk_imgsys_file_to_node(struct file *file)
+{
+	return container_of(video_devdata(file),
+			    struct mtk_imgsys_video_device, vdev);
+}
+
+static inline struct mtk_imgsys_pipe*
+mtk_imgsys_subdev_to_pipe(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mtk_imgsys_pipe, subdev);
+}
+
+static inline struct mtk_imgsys_dev*
+mtk_imgsys_mdev_to_dev(struct media_device *mdev)
+{
+	return container_of(mdev, struct mtk_imgsys_dev, mdev);
+}
+
+static inline struct mtk_imgsys_video_device*
+mtk_imgsys_vbq_to_node(struct vb2_queue *vq)
+{
+	return container_of(vq, struct mtk_imgsys_video_device, dev_q.vbq);
+}
+
+static inline struct mtk_imgsys_dev_buffer*
+mtk_imgsys_vb2_buf_to_dev_buf(struct vb2_buffer *vb)
+{
+	return container_of(vb, struct mtk_imgsys_dev_buffer, vbb.vb2_buf);
+}
+
+static inline struct mtk_imgsys_request*
+mtk_imgsys_media_req_to_imgsys_req(struct media_request *req)
+{
+	return container_of(req, struct mtk_imgsys_request, req);
+}
+
+static inline int mtk_imgsys_buf_is_meta(u32 type)
+{
+	return type == V4L2_BUF_TYPE_META_CAPTURE ||
+	       type == V4L2_BUF_TYPE_META_OUTPUT;
+}
+
+int mtk_imgsys_pipe_init(struct mtk_imgsys_dev *imgsys_dev,
+			 struct mtk_imgsys_pipe *pipe,
+			 const struct mtk_imgsys_pipe_desc *setting);
+
+int mtk_imgsys_pipe_release(struct mtk_imgsys_pipe *pipe);
+
+int mtk_imgsys_pipe_next_job_id(struct mtk_imgsys_pipe *pipe);
+
+void mtk_imgsys_pipe_debug_job(struct mtk_imgsys_pipe *pipe,
+			       struct mtk_imgsys_request *req);
+
+const struct mtk_imgsys_dev_format *
+mtk_imgsys_pipe_find_fmt(struct mtk_imgsys_pipe *pipe,
+			 struct mtk_imgsys_video_device *node,
+			 u32 format);
+
+void mtk_imgsys_pipe_try_fmt(struct mtk_imgsys_video_device *node,
+			     struct v4l2_format *fmt,
+			     const struct v4l2_format *ufmt,
+			     const struct mtk_imgsys_dev_format *dfmt);
+
+void mtk_imgsys_pipe_load_default_fmt(struct mtk_imgsys_pipe *pipe,
+				      struct mtk_imgsys_video_device *node,
+				      struct v4l2_format *fmt_to_fill);
+
+void mtk_imgsys_pipe_try_enqueue(struct mtk_imgsys_pipe *pipe);
+
+#endif /* _MTK_IMGSYS_DEV_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.c
new file mode 100644
index 000000000000..6a3a98e9cd42
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.c
@@ -0,0 +1,139 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ISP ImgSys formats
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/mtkisp_imgsys.h>
+#include <linux/videodev2.h>
+#include "mtk_imgsys-formats.h"
+
+const struct mtk_imgsys_format mtk_imgsys_format_nv12 = {
+	.format = V4L2_PIX_FMT_NV12,
+	.num_planes = 2,
+	.pixels_per_group = 2,
+	.bytes_per_group = {2, 2},
+	.vertical_sub_sampling = { 1, 2 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_nv21 = {
+	.format = V4L2_PIX_FMT_NV21,
+	.num_planes = 2,
+	.pixels_per_group = 2,
+	.bytes_per_group = {2, 2},
+	.vertical_sub_sampling = { 1, 2 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_grey = {
+	.format = V4L2_PIX_FMT_GREY,
+	.num_planes = 1,
+	.pixels_per_group = 1,
+	.bytes_per_group = { 1 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_2p012p = {
+	.format = V4L2_PIX_FMT_YUV_2P012P,
+	.num_planes = 2,
+	.pixels_per_group = 64,
+	.bytes_per_group = { 96, 96 },
+	.vertical_sub_sampling = { 1, 2 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_2p010p = {
+	.format = V4L2_PIX_FMT_YUV_2P010P,
+	.num_planes = 2,
+	.pixels_per_group = 64,
+	.bytes_per_group = { 80, 80 },
+	.vertical_sub_sampling = { 1, 2 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_y8 = {
+	.format = V4L2_PIX_FMT_MTISP_Y8,
+	.num_planes = 1,
+	.pixels_per_group = 1,
+	.bytes_per_group = { 1 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_y16 = {
+	.format = V4L2_PIX_FMT_MTISP_Y16,
+	.num_planes = 1,
+	.buffer_size = 0,
+	.pixels_per_group = 1,
+	.bytes_per_group = { 2 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_y32 = {
+	.format = V4L2_PIX_FMT_MTISP_Y32,
+	.num_planes = 1,
+	.buffer_size = 0,
+	.pixels_per_group = 1,
+	.bytes_per_group = { 4 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_warp2p = {
+	.format = V4L2_PIX_FMT_WARP2P,
+	.num_planes = 2,
+	.buffer_size = 0,
+	.pixels_per_group = 4,
+	.bytes_per_group = { 8, 8 },
+	.vertical_sub_sampling = { 1, 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_sgbrg10 = {
+	.format = V4L2_PIX_FMT_MTISP_SGBRG10,
+	.num_planes = 1,
+	.buffer_size = 0,
+	.pixels_per_group = 64,
+	.bytes_per_group = { 80 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_srggb10 = {
+	.format = V4L2_PIX_FMT_MTISP_SRGGB10,
+	.num_planes = 1,
+	.buffer_size = 0,
+	.pixels_per_group = 64,
+	.bytes_per_group = { 80 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_sgrbg10 = {
+	.format = V4L2_PIX_FMT_MTISP_SGRBG10,
+	.num_planes = 1,
+	.buffer_size = 0,
+	.pixels_per_group = 64,
+	.bytes_per_group = { 80 },
+	.vertical_sub_sampling = { 1 },
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_aply8 = {
+	.format = V4L2_PIX_FMT_MTISP_APLY8,
+	.num_planes = 1,
+	.pixels_per_group = 1,
+	.bytes_per_group = { 1 },
+	.vertical_sub_sampling = { 1 },
+	.ext_data = SIZE_OF_APL_DATA,
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_metai = {
+	.format = V4L2_META_FMT_MTISP_TUN_PARAMS,
+	.num_planes = 1,
+	.buffer_size = SIZE_OF_TUNING_META,
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_stt = {
+	.format = V4L2_META_FMT_MTISP_STAT_PARAMS,
+	.num_planes = 1,
+	.buffer_size = SIZE_OF_STATISTICS_META,
+};
+
+const struct mtk_imgsys_format mtk_imgsys_format_ctrlmeta = {
+	.format = V4L2_META_FMT_MTISP_CTL_PARAMS,
+	.num_planes = 1,
+	.buffer_size = SIZE_OF_CTRL_META,
+};
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.h
new file mode 100644
index 000000000000..cbf8b2b414f8
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-formats.h
@@ -0,0 +1,72 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * MediaTek ISP ImgSys formats
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef _MTK_IMGSYS_FORMATS_H_
+#define _MTK_IMGSYS_FORMATS_H_
+
+/**
+ * struct mtk_imgsys_format - MediaTek Image System format description
+ * @format: Pixel format identifier (e.g., V4L2_PIX_FMT_*).
+ * @num_planes: Number of planes in the image format. For example, 1 for
+ * single-plane formats, 2 or 3 for multi-plane formats like YUV420.
+ * @buffer_size: Total buffer size in bytes required to store the image data.
+ * @pixels_per_group: Number of pixels per group, which s defined as the
+ * minimum number of pixels (including padding) necessary in a row when the
+ * image has only one column of effective pixels.
+ * @bytes_per_group: Array specifying the number of bytes per group for each
+ * plane. The array size is 3 to support up to 3 planes.
+ * @vertical_sub_sampling: Array specifying the vertical subsampling factor for
+ * each plane. The array size is 3 to support up to 3 planes.
+ * @ext_data: Additional data or flags related to the image format.
+ *
+ * This structure is used to describe the format of images processed by the
+ * MediaTek Image System. It includes information about the pixel format,
+ * number of planes, buffer size, and other relevant details.
+ */
+struct mtk_imgsys_format {
+	u32 format;
+	u8 num_planes;
+	u32 buffer_size;
+	u32 pixels_per_group;
+	u32 bytes_per_group[3];
+	u32 vertical_sub_sampling[3];
+	u32 ext_data;
+};
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_nv12;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_nv21;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_grey;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_2p012p;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_2p010p;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_y8;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_y16;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_y32;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_warp2p;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_sgbrg10;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_srggb10;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_sgrbg10;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_aply8;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_metai;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_stt;
+
+extern const struct mtk_imgsys_format mtk_imgsys_format_ctrlmeta;
+
+#endif /* _MTK_IMGSYS_FORMATS_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_ops.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_ops.h
new file mode 100644
index 000000000000..6dc4b7b60832
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_ops.h
@@ -0,0 +1,27 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_IMGSYS_MODULES_H_
+#define _MTK_IMGSYS_MODULES_H_
+
+/**
+ * enum mtk_imgsys_module
+ *
+ * Definition about supported hw modules
+ */
+enum mtk_imgsys_module {
+	IMGSYS_MOD_IMGMAIN = 0,
+	IMGSYS_MOD_WPE,
+	IMGSYS_MOD_TRAW,
+	IMGSYS_MOD_DIP,
+	IMGSYS_MOD_PQDIP,
+	IMGSYS_MOD_ME,
+	IMGSYS_MOD_MAX,
+};
+
+#endif /* _MTK_IMGSYS_MODULES_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.c
new file mode 100644
index 000000000000..94888682a939
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.c
@@ -0,0 +1,39 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *         Holmes Chiou <holmes.chiou@mediatek.com>
+ *
+ */
+
+#include "mtk_imgsys-of.h"
+
+static void merge_module_pipelines(const struct mtk_imgsys_pipe_desc *imgsys_pipe,
+				   const struct cust_data *data)
+{
+	const struct mtk_imgsys_mod_pipe_desc *module_pipe;
+	unsigned int mod_num;
+	unsigned int i, j, k;
+
+	mod_num = data->mod_num;
+	k = 0;
+	for (i = 0; i < mod_num; i++) {
+		module_pipe = &data->module_pipes[i];
+		for (j = 0; j < module_pipe->node_num; j++) {
+			imgsys_pipe->queue_descs[k] = module_pipe->vnode_desc[j];
+			k++;
+		}
+	}
+}
+
+void init_imgsys_pipeline(const struct cust_data *data)
+{
+	const struct mtk_imgsys_pipe_desc *imgsys_pipe;
+	unsigned int i;
+
+	for (i = 0; i < data->pipe_num; i++) {
+		imgsys_pipe = &data->pipe_settings[i];
+		merge_module_pipelines(imgsys_pipe, data);
+	}
+}
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.h
new file mode 100644
index 000000000000..5088c9df704c
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-of.h
@@ -0,0 +1,55 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *         Holmes Chiou <holmes.chiou@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_IMGSYS_OF_H_
+#define _MTK_IMGSYS_OF_H_
+
+#include <linux/clk.h>
+#include "mtk_imgsys-dev.h"
+
+/**
+ * struct mtk_imgsys_mod_pipe_desc - Description of a module's pipeline
+ * @vnode_desc: Pointer to an array of video device descriptors for the module.
+ * @node_num: Number of video nodes associated with this module.
+ */
+struct mtk_imgsys_mod_pipe_desc {
+	const struct mtk_imgsys_video_device_desc *vnode_desc;
+	unsigned int node_num;
+};
+
+/**
+ * struct cust_data - Custom data structure for image system configuration
+ * @clks: Pointer to an array of clock bulk data for the module.
+ * @clk_num: Number of clocks associated with this module.
+ * @module_pipes: Pointer to an array of module pipeline descriptions.
+ * @mod_num: Number of modules in the pipeline.
+ * @pipe_settings: Pointer to pipeline settings for the module.
+ * @pipe_num: Number of pipeline settings.
+ */
+struct cust_data {
+	struct clk_bulk_data *clks;
+	unsigned int clk_num;
+	const struct mtk_imgsys_mod_pipe_desc *module_pipes;
+	unsigned int mod_num;
+	const struct mtk_imgsys_pipe_desc *pipe_settings;
+	unsigned int pipe_num;
+};
+
+/**
+ * init_imgsys_pipeline - Initialize the video nodes in image system pipeline
+ * @data: Pointer to the custom data structure containing configuration
+ *  information.
+ *
+ * This function initializes the image system pipeline based on the provided
+ * custom data. It sets up the necessary modules's video nodes as defined in
+ * the cust_data structure.
+ */
+void init_imgsys_pipeline(const struct cust_data *data);
+
+#endif /* _MTK_IMGSYS_OF_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.c
new file mode 100644
index 000000000000..9cdcdb0a0200
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.c
@@ -0,0 +1,27 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+
+#include "mtk_imgsys-sys.h"
+
+void mtk_imgsys_hw_enqueue(struct mtk_imgsys_dev *imgsys_dev,
+			   struct mtk_imgsys_request *req)
+{
+	/* Function implementation will be provided in subsequent patches */
+}
+
+int mtk_imgsys_hw_streamon(struct mtk_imgsys_pipe *pipe)
+{
+	/* Function implementation will be provided in subsequent patches */
+	return 0;
+}
+
+int mtk_imgsys_hw_streamoff(struct mtk_imgsys_pipe *pipe)
+{
+	/* Function implementation will be provided in subsequent patches */
+	return 0;
+}
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.h
new file mode 100644
index 000000000000..9f9b0b627305
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-sys.h
@@ -0,0 +1,50 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef _MTK_IMGSYS_SYS_H_
+#define _MTK_IMGSYS_SYS_H_
+
+#include "mtk_imgsys-dev.h"
+
+/*
+ * mtk_imgsys_hw_streamon - Start streaming on the ImgSys pipeline
+ * @pipe: Pointer to the ImgSys pipeline structure
+ *
+ * This function starts streaming on the specified ImgSys pipeline. It ensures
+ * that the pipeline is properly initialized and ready to process image data.
+ * This is typically used to begin image processing operations after the pipeline
+ * has been configured.
+ *
+ * Return: 0 on success, a negative error code on failure
+ */
+int mtk_imgsys_hw_streamon(struct mtk_imgsys_pipe *pipe);
+
+/*
+ * mtk_imgsys_hw_streamoff - Stop streaming on the ImgSys pipeline
+ * @pipe: Pointer to the ImgSys pipeline structure
+ *
+ * This function stops streaming on the specified ImgSys pipeline. It ensures
+ * that any ongoing image processing tasks are halted and the pipeline is
+ * properly shut down. This is typically used when the image processing
+ * operations are no longer needed or when the system is being reconfigured.
+ *
+ * Return: 0 on success, a negative error code on failure
+ */
+int mtk_imgsys_hw_streamoff(struct mtk_imgsys_pipe *pipe);
+
+/*
+ * mtk_imgsys_hw_enqueue - Enqueue a request to the ImgSys hardware
+ * @imgsys_dev: Pointer to the ImgSys device structure
+ * @req: Pointer to the ImgSys request structure
+ *
+ * This function enqueues a request to the ImgSys hardware for processing.
+ * The request contains information about the image processing tasks to be
+ * performed by the hardware. The function ensures that the request is properly
+ * queued and ready for execution by the ImgSys hardware.
+ */
+void mtk_imgsys_hw_enqueue(struct mtk_imgsys_dev *imgsys_dev,
+			   struct mtk_imgsys_request *req);
+
+#endif /* _MTK_IMGSYS_SYS_H_ */
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-v4l2.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-v4l2.c
new file mode 100644
index 000000000000..cfd65858c751
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-v4l2.c
@@ -0,0 +1,1684 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev2.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-event.h>
+#include "linux/mtkisp_imgsys.h"
+#include "mtk_imgsys-of.h"
+#include "mtk_imgsys-module_ops.h"
+#include "mtk_imgsys-vnode_id.h"
+#include "mtk_imgsys_v4l2_vnode.h"
+#include "mtk_imgsys-dev.h"
+#include "mtk_imgsys-sys.h"
+
+#define IMGSYS_MAX_BUFFERS	256
+#define IMGSYS_SUSPEND_TIME 3000 /* ms */
+
+static int mtk_imgsys_sd_subscribe_event(struct v4l2_subdev *subdev,
+					 struct v4l2_fh *fh,
+					 struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_FRAME_SYNC:
+		return v4l2_event_subscribe(fh, sub, 64, NULL);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_subdev_core_ops mtk_imgsys_subdev_core_ops = {
+	.subscribe_event = mtk_imgsys_sd_subscribe_event,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static int mtk_imgsys_subdev_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct mtk_imgsys_pipe *pipe = mtk_imgsys_subdev_to_pipe(sd);
+	int ret;
+
+	if (enable) {
+		ret = mtk_imgsys_hw_streamon(pipe);
+		if (ret)
+			dev_err(pipe->imgsys_dev->dev,
+				"%s: pipe(%d) stream on failed\n",
+				pipe->desc->name, pipe->desc->id);
+	} else {
+		ret = mtk_imgsys_hw_streamoff(pipe);
+		if (ret)
+			dev_err(pipe->imgsys_dev->dev,
+				"%s: pipe(%d) stream off failed\n",
+				pipe->desc->name, pipe->desc->id);
+	}
+
+	return ret;
+}
+
+static const struct v4l2_subdev_video_ops mtk_imgsys_subdev_video_ops = {
+	.s_stream = mtk_imgsys_subdev_s_stream,
+};
+
+static const struct v4l2_subdev_ops mtk_imgsys_subdev_ops = {
+	.core = &mtk_imgsys_subdev_core_ops,
+	.video = &mtk_imgsys_subdev_video_ops,
+};
+
+static int mtk_imgsys_link_setup(struct media_entity *entity,
+				 const struct media_pad *local,
+				 const struct media_pad *remote,
+				 u32 flags)
+{
+	struct mtk_imgsys_pipe *pipe =
+		container_of(entity, struct mtk_imgsys_pipe, subdev.entity);
+	u32 pad = local->index;
+
+	WARN_ON(entity->obj_type != MEDIA_ENTITY_TYPE_V4L2_SUBDEV);
+	WARN_ON(pad >= pipe->desc->total_queues);
+
+	mutex_lock(&pipe->lock);
+
+	if (flags & MEDIA_LNK_FL_ENABLED)
+		pipe->nodes_enabled++;
+	else
+		pipe->nodes_enabled--;
+
+	pipe->nodes[pad].flags &= ~MEDIA_LNK_FL_ENABLED;
+	pipe->nodes[pad].flags |= flags & MEDIA_LNK_FL_ENABLED;
+
+	dev_dbg(pipe->imgsys_dev->dev,
+		"%s: link setup, flags(0x%x), (%s)%d -->(%s)%d, nodes_enabled(0x%llx)\n",
+		pipe->desc->name, flags, local->entity->name, local->index,
+		remote->entity->name, remote->index, pipe->nodes_enabled);
+
+	mutex_unlock(&pipe->lock);
+
+	return 0;
+}
+
+static const struct media_entity_operations mtk_imgsys_media_ops = {
+	.link_setup = mtk_imgsys_link_setup,
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int mtk_imgsys_vb2_meta_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_imgsys_pipe *pipe = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_imgsys_video_device *node =
+					mtk_imgsys_vbq_to_node(vb->vb2_queue);
+	struct device *dev = pipe->imgsys_dev->dev;
+	const struct v4l2_format *fmt = &node->vdev_fmt;
+
+	if (vb->planes[0].length < fmt->fmt.meta.buffersize) {
+		dev_err(dev,
+			"%s:%s: size error(user:%d, required:%d)\n",
+			pipe->desc->name, node->desc->name,
+			vb->planes[0].length, fmt->fmt.meta.buffersize);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_imgsys_vb2_video_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_imgsys_pipe *pipe = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_imgsys_video_device *node =
+					mtk_imgsys_vbq_to_node(vb->vb2_queue);
+	struct device *dev = pipe->imgsys_dev->dev;
+	const struct v4l2_format *fmt = &node->vdev_fmt;
+	unsigned int size;
+	int i;
+
+	for (i = 0; i < vb->num_planes; i++) {
+		size = fmt->fmt.pix_mp.plane_fmt[i].sizeimage;
+		if (vb->planes[i].length < size) {
+			dev_err(dev,
+				"%s:%s: size error(user:%d, required:%d)\n",
+				pipe->desc->name, node->desc->name,
+				vb->planes[i].length, size);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int mtk_imgsys_vb2_buf_out_validate(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
+
+	if (v4l2_buf->field == V4L2_FIELD_ANY)
+		v4l2_buf->field = V4L2_FIELD_NONE;
+
+	if (v4l2_buf->field != V4L2_FIELD_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mtk_imgsys_vb2_meta_buf_init(struct vb2_buffer *vb)
+{
+	struct mtk_imgsys_dev_buffer *dev_buf =
+					mtk_imgsys_vb2_buf_to_dev_buf(vb);
+	struct mtk_imgsys_pipe *pipe = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_imgsys_video_device *node =
+					mtk_imgsys_vbq_to_node(vb->vb2_queue);
+
+	/*
+	 * The meta buffers are allocated from the SCP reserved memory.
+	 * Setup the mapping to ImgSys device here.
+	 */
+	dev_buf->scp_daddr[0] = vb2_dma_contig_plane_dma_addr(vb, 0);
+	dev_buf->isp_daddr[0] =
+		dma_map_resource(pipe->imgsys_dev->dev,
+				 dev_buf->scp_daddr[0],
+				 vb->planes[0].length,
+				 DMA_BIDIRECTIONAL,
+				 DMA_ATTR_SKIP_CPU_SYNC);
+	if (dma_mapping_error(pipe->imgsys_dev->dev,
+			      dev_buf->isp_daddr[0])) {
+		dev_err(pipe->imgsys_dev->dev,
+			"%s:%s: failed to map buffer: s_daddr(%pad)\n",
+			pipe->desc->name, node->desc->name,
+			&dev_buf->scp_daddr[0]);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_imgsys_vb2_video_buf_init(struct vb2_buffer *vb)
+{
+	struct mtk_imgsys_dev_buffer *dev_buf =
+					mtk_imgsys_vb2_buf_to_dev_buf(vb);
+	unsigned int plane;
+
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		dev_buf->isp_daddr[plane] = vb2_dma_contig_plane_dma_addr(vb, plane);
+
+	return 0;
+}
+
+static void mtk_imgsys_vb2_queue_meta_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct mtk_imgsys_dev_buffer *dev_buf =
+					mtk_imgsys_vb2_buf_to_dev_buf(vb);
+	struct mtk_imgsys_pipe *pipe = vb2_get_drv_priv(vb->vb2_queue);
+
+	dma_unmap_resource(pipe->imgsys_dev->dev,
+			   dev_buf->isp_daddr[0],
+			   vb->planes[0].length, DMA_BIDIRECTIONAL,
+			   DMA_ATTR_SKIP_CPU_SYNC);
+}
+
+static void mtk_imgsys_vb2_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *b = to_vb2_v4l2_buffer(vb);
+	struct mtk_imgsys_dev_buffer *dev_buf =
+					mtk_imgsys_vb2_buf_to_dev_buf(vb);
+	struct mtk_imgsys_request *req = NULL;
+	struct mtk_imgsys_video_device *node =
+					mtk_imgsys_vbq_to_node(vb->vb2_queue);
+	int buf_count;
+
+	if (!vb->request)
+		return;
+
+	req = mtk_imgsys_media_req_to_imgsys_req(vb->request);
+
+	dev_buf->dev_fmt = node->dev_q.dev_fmt;
+	spin_lock(&node->buf_list_lock);
+	list_add_tail(&dev_buf->list, &node->buf_list);
+	spin_unlock(&node->buf_list_lock);
+
+	buf_count = atomic_dec_return(&req->buf_count);
+	if (!buf_count) {
+		dev_dbg(&node->vdev.dev,
+			"framo_no: (%d), reqfd-%d\n",
+			req->img_fparam.frame_no, b->request_fd);
+		req->request_fd = b->request_fd;
+		mutex_lock(&req->imgsys_pipe->lock);
+		mtk_imgsys_pipe_try_enqueue(req->imgsys_pipe);
+		mutex_unlock(&req->imgsys_pipe->lock);
+	}
+}
+
+static int mtk_imgsys_vb2_meta_queue_setup(struct vb2_queue *vq,
+					   unsigned int *num_buffers,
+					   unsigned int *num_planes,
+					   unsigned int sizes[],
+					   struct device *alloc_devs[])
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_vbq_to_node(vq);
+	const struct v4l2_format *fmt = &node->vdev_fmt;
+
+	if (*num_planes)
+		return 0;
+
+	*num_planes = 1;
+	sizes[0] = fmt->fmt.meta.buffersize;
+
+	return 0;
+}
+
+static int mtk_imgsys_vb2_video_queue_setup(struct vb2_queue *vq,
+					    unsigned int *num_buffers,
+					    unsigned int *num_planes,
+					    unsigned int sizes[],
+					    struct device *alloc_devs[])
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_vbq_to_node(vq);
+	const struct v4l2_format *fmt = &node->vdev_fmt;
+	int i;
+
+	if (*num_planes)
+		return 0;
+
+	*num_planes = fmt->fmt.pix_mp.num_planes;
+
+	for (i = 0; i < *num_planes; i++) {
+		sizes[i] = fmt->fmt.pix_mp.plane_fmt[i].sizeimage;
+		*num_buffers = clamp_val(*num_buffers, 1, IMGSYS_MAX_BUFFERS);
+	}
+	return 0;
+}
+
+static void mtk_imgsys_return_all_buffers(struct mtk_imgsys_pipe *pipe,
+					  struct mtk_imgsys_video_device *node,
+					  enum vb2_buffer_state state)
+{
+	struct mtk_imgsys_dev_buffer *b, *b0;
+
+	spin_lock(&node->buf_list_lock);
+	list_for_each_entry_safe(b, b0, &node->buf_list, list) {
+		list_del(&b->list);
+		vb2_buffer_done(&b->vbb.vb2_buf, state);
+	}
+	spin_unlock(&node->buf_list_lock);
+}
+
+static int mtk_imgsys_vb2_start_streaming(struct vb2_queue *vq,
+					  unsigned int count)
+{
+	struct mtk_imgsys_pipe *pipe = vb2_get_drv_priv(vq);
+	struct mtk_imgsys_video_device *node = mtk_imgsys_vbq_to_node(vq);
+	int ret;
+
+	if (!pipe->nodes_streaming) {
+		ret = media_pipeline_start(&node->vdev.entity.pads[0], &pipe->pipeline);
+		if (ret < 0) {
+			dev_info(pipe->imgsys_dev->dev,
+				 "%s:%s: media_pipeline_start failed(%d)\n",
+				 pipe->desc->name, node->desc->name, ret);
+			goto fail_return_bufs;
+		}
+	}
+
+	mutex_lock(&pipe->lock);
+	if (!(node->flags & MEDIA_LNK_FL_ENABLED)) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "%s:%s: stream on failed, node is not enabled\n",
+			 pipe->desc->name, node->desc->name);
+
+		ret = -ENOLINK;
+		goto fail_stop_pipeline;
+	}
+
+	pipe->nodes_streaming++;
+	if (pipe->nodes_streaming == pipe->nodes_enabled) {
+		/* Start streaming of the whole pipeline */
+		ret = v4l2_subdev_call(&pipe->subdev, video, s_stream, 1);
+		if (ret < 0) {
+			dev_info(pipe->imgsys_dev->dev,
+				 "%s:%s: sub dev s_stream(1) failed(%d)\n",
+				 pipe->desc->name, node->desc->name, ret);
+
+			goto fail_stop_pipeline;
+		}
+	}
+
+	dev_dbg(pipe->imgsys_dev->dev,
+		"%s:%s:%s nodes_streaming(0x%llx), nodes_enable(0x%llx)\n",
+		__func__, pipe->desc->name, node->desc->name,
+		pipe->nodes_streaming, pipe->nodes_enabled);
+
+	mutex_unlock(&pipe->lock);
+
+	return 0;
+
+fail_stop_pipeline:
+	mutex_unlock(&pipe->lock);
+	media_pipeline_stop(&node->vdev.entity.pads[0]);
+
+fail_return_bufs:
+	mtk_imgsys_return_all_buffers(pipe, node, VB2_BUF_STATE_QUEUED);
+
+	return ret;
+}
+
+static void mtk_imgsys_vb2_stop_streaming(struct vb2_queue *vq)
+{
+	struct mtk_imgsys_pipe *pipe = vb2_get_drv_priv(vq);
+	struct mtk_imgsys_video_device *node = mtk_imgsys_vbq_to_node(vq);
+	int ret;
+
+	mutex_lock(&pipe->lock);
+
+	if (pipe->streaming) {
+		ret = v4l2_subdev_call(&pipe->subdev, video, s_stream, 0);
+		if (ret)
+			dev_info(pipe->imgsys_dev->dev,
+				 "%s:%s: sub dev s_stream(0) failed(%d)\n",
+				 pipe->desc->name, node->desc->name, ret);
+	}
+
+	pipe->nodes_streaming--;
+
+	if (!pipe->nodes_streaming)
+		media_pipeline_stop(&node->vdev.entity.pads[0]);
+
+	mtk_imgsys_return_all_buffers(pipe, node, VB2_BUF_STATE_ERROR);
+
+	mutex_unlock(&pipe->lock);
+}
+
+static void mtk_imgsys_vb2_request_complete(struct vb2_buffer *vb)
+{
+	struct mtk_imgsys_video_device *node =
+					mtk_imgsys_vbq_to_node(vb->vb2_queue);
+
+	v4l2_ctrl_request_complete(vb->req_obj.req,
+				   &node->ctrl_handler);
+}
+
+static const struct vb2_ops mtk_imgsys_vb2_meta_ops = {
+	.buf_queue = mtk_imgsys_vb2_buf_queue,
+	.queue_setup = mtk_imgsys_vb2_meta_queue_setup,
+	.buf_init = mtk_imgsys_vb2_meta_buf_init,
+	.buf_prepare  = mtk_imgsys_vb2_meta_buf_prepare,
+	.buf_out_validate = mtk_imgsys_vb2_buf_out_validate,
+	.buf_cleanup = mtk_imgsys_vb2_queue_meta_buf_cleanup,
+	.start_streaming = mtk_imgsys_vb2_start_streaming,
+	.stop_streaming = mtk_imgsys_vb2_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.buf_request_complete = mtk_imgsys_vb2_request_complete,
+};
+
+static const struct vb2_ops mtk_imgsys_vb2_video_ops = {
+	.buf_queue = mtk_imgsys_vb2_buf_queue,
+	.queue_setup = mtk_imgsys_vb2_video_queue_setup,
+	.buf_init = mtk_imgsys_vb2_video_buf_init,
+	.buf_prepare  = mtk_imgsys_vb2_video_buf_prepare,
+	.buf_out_validate = mtk_imgsys_vb2_buf_out_validate,
+	.start_streaming = mtk_imgsys_vb2_start_streaming,
+	.stop_streaming = mtk_imgsys_vb2_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.buf_request_complete = mtk_imgsys_vb2_request_complete,
+};
+
+static int mtk_imgsys_video_device_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mtk_imgsys_video_device *node =
+		container_of(ctrl->handler,
+			     struct mtk_imgsys_video_device, ctrl_handler);
+
+	switch (ctrl->id) {
+	case V4L2_CID_ROTATE:
+		node->rotation = ctrl->val;
+		break;
+	case V4L2_CID_VFLIP:
+		node->vflip = ctrl->val;
+		break;
+	case V4L2_CID_HFLIP:
+		node->hflip = ctrl->val;
+		break;
+	case V4L2_CID_MTK_IMG_RESIZE_RATIO:
+		node->resize_ratio = ctrl->val;
+		break;
+	default:
+		dev_dbg(&node->vdev.dev, "[%s] doesn't support ctrl(%d)\n",
+			node->desc->name, ctrl->id);
+		return -EINVAL;
+	}
+
+	node->rotation = ctrl->val;
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops mtk_imgsys_video_device_ctrl_ops = {
+	.s_ctrl = mtk_imgsys_video_device_s_ctrl,
+};
+
+static int mtk_imgsys_vidioc_qbuf(struct file *file, void *priv,
+				  struct v4l2_buffer *buf)
+{
+	struct mtk_imgsys_pipe *pipe = video_drvdata(file);
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+	struct vb2_buffer *vb = node->dev_q.vbq.bufs[buf->index];
+	struct mtk_imgsys_dev_buffer *dev_buf =
+					mtk_imgsys_vb2_buf_to_dev_buf(vb);
+
+	if (!dev_buf)
+		return -EFAULT;
+
+	dev_buf->fmt = node->vdev_fmt;
+	dev_buf->rotation = node->rotation;
+	dev_buf->crop.c = node->crop;
+	dev_buf->compose = node->compose;
+	dev_buf->hflip = node->hflip;
+	dev_buf->vflip = node->vflip;
+	dev_buf->resize_ratio = node->resize_ratio;
+
+	return vb2_qbuf(node->vdev.queue, &pipe->imgsys_dev->mdev, buf);
+}
+
+static int mtk_imgsys_videoc_querycap(struct file *file, void *fh,
+				      struct v4l2_capability *cap)
+{
+	struct mtk_imgsys_pipe *pipe = video_drvdata(file);
+
+	strscpy(cap->driver, pipe->desc->name, sizeof(cap->driver));
+	strscpy(cap->card, pipe->desc->name, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", dev_name(pipe->imgsys_dev->mdev.dev));
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_try_fmt(struct file *file, void *fh,
+				     struct v4l2_format *f)
+{
+	struct mtk_imgsys_pipe *pipe = video_drvdata(file);
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+	const struct mtk_imgsys_dev_format *dev_fmt;
+	struct v4l2_format try_fmt;
+
+	memset(&try_fmt, 0, sizeof(try_fmt));
+
+	dev_fmt = mtk_imgsys_pipe_find_fmt(pipe, node,
+					   f->fmt.pix_mp.pixelformat);
+	if (!dev_fmt) {
+		dev_fmt = &node->desc->fmts[0];
+		dev_dbg(pipe->imgsys_dev->dev,
+			"%s:%s:%s: dev_fmt(%d) not found, use default(%d)\n",
+			__func__, pipe->desc->name, node->desc->name,
+			f->fmt.pix_mp.pixelformat, dev_fmt->fmt->format);
+	}
+
+	mtk_imgsys_pipe_try_fmt(node, &try_fmt, f, dev_fmt);
+	*f = try_fmt;
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_g_fmt(struct file *file, void *fh,
+				   struct v4l2_format *f)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+
+	*f = node->vdev_fmt;
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_s_fmt(struct file *file, void *fh,
+				   struct v4l2_format *f)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+	struct mtk_imgsys_pipe *pipe = video_drvdata(file);
+	const struct mtk_imgsys_dev_format *dev_fmt;
+
+	dev_fmt = mtk_imgsys_pipe_find_fmt(pipe, node,
+					   f->fmt.pix_mp.pixelformat);
+	if (!dev_fmt) {
+		dev_fmt = &node->desc->fmts[0];
+		dev_info(pipe->imgsys_dev->dev,
+			 "%s:%s:%s: dev_fmt(%d) not found, use default(%d)\n",
+			 __func__, pipe->desc->name, node->desc->name,
+			 f->fmt.pix_mp.pixelformat, dev_fmt->fmt->format);
+	}
+
+	memset(&node->vdev_fmt, 0, sizeof(node->vdev_fmt));
+
+	mtk_imgsys_pipe_try_fmt(node, &node->vdev_fmt, f, dev_fmt);
+	*f = node->vdev_fmt;
+
+	node->dev_q.dev_fmt = dev_fmt;
+	node->crop.left = 0; /* reset crop setting of nodes */
+	node->crop.top = 0;
+	node->crop.width = f->fmt.pix_mp.width;
+	node->crop.height = f->fmt.pix_mp.height;
+	node->compose.left = 0;
+	node->compose.top = 0;
+	node->compose.width = f->fmt.pix_mp.width;
+	node->compose.height = f->fmt.pix_mp.height;
+	if (node->resize_ratio_ctrl)
+		v4l2_ctrl_s_ctrl(node->resize_ratio_ctrl, 0);
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_enum_framesizes(struct file *file, void *priv,
+					     struct v4l2_frmsizeenum *sizes)
+{
+	struct mtk_imgsys_pipe *pipe = video_drvdata(file);
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+	const struct mtk_imgsys_dev_format *dev_fmt;
+
+	dev_fmt = mtk_imgsys_pipe_find_fmt(pipe, node, sizes->pixel_format);
+
+	if (!dev_fmt || sizes->index)
+		return -EINVAL;
+
+	sizes->type = node->desc->frmsizeenum->type;
+	sizes->stepwise.max_width =
+		node->desc->frmsizeenum->stepwise.max_width;
+	sizes->stepwise.min_width =
+		node->desc->frmsizeenum->stepwise.min_width;
+	sizes->stepwise.max_height =
+		node->desc->frmsizeenum->stepwise.max_height;
+	sizes->stepwise.min_height =
+		node->desc->frmsizeenum->stepwise.min_height;
+	sizes->stepwise.step_height =
+		node->desc->frmsizeenum->stepwise.step_height;
+	sizes->stepwise.step_width =
+		node->desc->frmsizeenum->stepwise.step_width;
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_enum_fmt(struct file *file, void *fh,
+				      struct v4l2_fmtdesc *f)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+
+	if (f->index >= node->desc->num_fmts)
+		return -EINVAL;
+
+	strscpy(f->description, node->desc->description, sizeof(f->description));
+	f->pixelformat = node->desc->fmts[f->index].fmt->format;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int mtk_imgsys_meta_enum_format(struct file *file, void *fh,
+				       struct v4l2_fmtdesc *f)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+
+	if (f->index > 0)
+		return -EINVAL;
+
+	strscpy(f->description, node->desc->description, sizeof(f->description));
+
+	f->pixelformat = node->vdev_fmt.fmt.meta.dataformat;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_g_meta_fmt(struct file *file, void *fh,
+					struct v4l2_format *f)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+	*f = node->vdev_fmt;
+
+	return 0;
+}
+
+static int mtk_imgsys_videoc_s_meta_fmt(struct file *file, void *fh,
+					struct v4l2_format *f)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+	struct mtk_imgsys_pipe *pipe = video_drvdata(file);
+	const struct mtk_imgsys_dev_format *dev_fmt;
+
+	if (pipe->streaming || vb2_is_busy(&node->dev_q.vbq))
+		return -EBUSY;
+
+	dev_fmt = mtk_imgsys_pipe_find_fmt(pipe, node,
+					   f->fmt.meta.dataformat);
+	if (!dev_fmt) {
+		dev_fmt = &node->desc->fmts[0];
+		dev_info(pipe->imgsys_dev->dev,
+			 "%s:%s:%s: dev_fmt(%d) not found, use default(%d)\n",
+			 __func__, pipe->desc->name, node->desc->name,
+			 f->fmt.meta.dataformat, dev_fmt->fmt->format);
+	}
+
+	memset(&node->vdev_fmt, 0, sizeof(node->vdev_fmt));
+
+	f->fmt.meta.dataformat = dev_fmt->fmt->format;
+	f->fmt.meta.buffersize = dev_fmt->fmt->buffer_size;
+
+	node->dev_q.dev_fmt = dev_fmt;
+	node->vdev_fmt = *f;
+
+	return 0;
+}
+
+static int mtk_imgsys_g_selection(struct file *file, void *priv,
+				  struct v4l2_selection *s)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+
+	if (!node)
+		return -EINVAL;
+
+	if ((node->desc->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+	     s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
+	    (node->desc->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+	     s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP:
+		s->r = node->crop;
+		break;
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		s->r.width = node->desc->default_width;
+		s->r.height = node->desc->default_width;
+		s->r.left = 0;
+		s->r.top = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int mtk_imgsys_s_selection(struct file *file, void *priv,
+				  struct v4l2_selection *s)
+{
+	struct mtk_imgsys_video_device *node = mtk_imgsys_file_to_node(file);
+
+	if (!node)
+		return -EINVAL;
+
+	if ((node->desc->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+	     s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
+	    (node->desc->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+	     s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP:
+		node->crop = s->r;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops mtk_imgsys_v4l2_video_out_ioctl_ops = {
+	.vidioc_querycap = mtk_imgsys_videoc_querycap,
+
+	.vidioc_enum_framesizes = mtk_imgsys_videoc_enum_framesizes,
+	.vidioc_enum_fmt_vid_out = mtk_imgsys_videoc_enum_fmt,
+	.vidioc_g_fmt_vid_out_mplane = mtk_imgsys_videoc_g_fmt,
+	.vidioc_s_fmt_vid_out_mplane = mtk_imgsys_videoc_s_fmt,
+	.vidioc_try_fmt_vid_out_mplane = mtk_imgsys_videoc_try_fmt,
+
+	.vidioc_g_selection = mtk_imgsys_g_selection,
+	.vidioc_s_selection = mtk_imgsys_s_selection,
+
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_remove_bufs = vb2_ioctl_remove_bufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_qbuf = mtk_imgsys_vidioc_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ioctl_ops mtk_imgsys_v4l2_video_cap_ioctl_ops = {
+	.vidioc_querycap = mtk_imgsys_videoc_querycap,
+
+	.vidioc_enum_framesizes = mtk_imgsys_videoc_enum_framesizes,
+	.vidioc_enum_fmt_vid_cap = mtk_imgsys_videoc_enum_fmt,
+	.vidioc_g_fmt_vid_cap_mplane = mtk_imgsys_videoc_g_fmt,
+	.vidioc_s_fmt_vid_cap_mplane = mtk_imgsys_videoc_s_fmt,
+	.vidioc_try_fmt_vid_cap_mplane = mtk_imgsys_videoc_try_fmt,
+
+	.vidioc_g_selection = mtk_imgsys_g_selection,
+	.vidioc_s_selection = mtk_imgsys_s_selection,
+
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_remove_bufs = vb2_ioctl_remove_bufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_qbuf = mtk_imgsys_vidioc_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ioctl_ops mtk_imgsys_v4l2_meta_out_ioctl_ops = {
+	.vidioc_querycap = mtk_imgsys_videoc_querycap,
+
+	.vidioc_enum_fmt_meta_out = mtk_imgsys_meta_enum_format,
+	.vidioc_g_fmt_meta_out = mtk_imgsys_videoc_g_meta_fmt,
+	.vidioc_s_fmt_meta_out = mtk_imgsys_videoc_s_meta_fmt,
+	.vidioc_try_fmt_meta_out = mtk_imgsys_videoc_g_meta_fmt,
+
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_remove_bufs = vb2_ioctl_remove_bufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_qbuf = mtk_imgsys_vidioc_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+};
+
+static const struct v4l2_ioctl_ops mtk_imgsys_v4l2_meta_cap_ioctl_ops = {
+	.vidioc_querycap = mtk_imgsys_videoc_querycap,
+
+	.vidioc_enum_fmt_meta_cap = mtk_imgsys_meta_enum_format,
+	.vidioc_g_fmt_meta_cap = mtk_imgsys_videoc_g_meta_fmt,
+	.vidioc_s_fmt_meta_cap = mtk_imgsys_videoc_s_meta_fmt,
+	.vidioc_try_fmt_meta_cap = mtk_imgsys_videoc_g_meta_fmt,
+
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_remove_bufs = vb2_ioctl_remove_bufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_qbuf = mtk_imgsys_vidioc_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+};
+
+static struct media_request *mtk_imgsys_request_alloc(struct media_device *mdev)
+{
+	struct mtk_imgsys_request *req;
+	struct mtk_imgsys_pipe *pipe;
+
+	pipe = &mtk_imgsys_mdev_to_dev(mdev)->imgsys_pipe;
+	req = vzalloc(sizeof(*req));
+	if (!req)
+		return NULL;
+
+	req->buf_map = vzalloc(pipe->desc->total_queues *
+			       sizeof(struct mtk_imgsys_dev_buffer *));
+	if (!req->buf_map)
+		goto error;
+
+	return &req->req;
+
+error:
+	vfree(req);
+	return NULL;
+}
+
+static void mtk_imgsys_request_free(struct media_request *req)
+{
+	struct mtk_imgsys_request *imgsys_req =
+					mtk_imgsys_media_req_to_imgsys_req(req);
+
+	vfree(imgsys_req->buf_map);
+	vfree(imgsys_req);
+}
+
+static int mtk_imgsys_vb2_request_validate(struct media_request *req)
+{
+	struct media_request_object *obj;
+	struct mtk_imgsys_dev *imgsys_dev = mtk_imgsys_mdev_to_dev(req->mdev);
+	struct mtk_imgsys_request *imgsys_req =
+					mtk_imgsys_media_req_to_imgsys_req(req);
+	struct mtk_imgsys_pipe *pipe = NULL;
+	struct mtk_imgsys_pipe *pipe_prev = NULL;
+	struct mtk_imgsys_dev_buffer **buf_map = imgsys_req->buf_map;
+	int buf_count = 0;
+	int i;
+
+	for (i = 0; i < imgsys_dev->imgsys_pipe.desc->total_queues; i++)
+		buf_map[i] = NULL;
+
+	list_for_each_entry(obj, &req->objects, list) {
+		struct vb2_buffer *vb;
+		struct mtk_imgsys_dev_buffer *dev_buf;
+		struct mtk_imgsys_video_device *node;
+
+		if (!vb2_request_object_is_buffer(obj))
+			continue;
+
+		vb = container_of(obj, struct vb2_buffer, req_obj);
+		node = mtk_imgsys_vbq_to_node(vb->vb2_queue);
+		pipe = vb2_get_drv_priv(vb->vb2_queue);
+		if (pipe_prev && pipe != pipe_prev) {
+			dev_dbg(imgsys_dev->dev,
+				"%s:%s:%s:found buf of different pipes(%p,%p)\n",
+				__func__, node->desc->name,
+				req->debug_str, pipe, pipe_prev);
+			return -EINVAL;
+		}
+
+		pipe_prev = pipe;
+		dev_buf = mtk_imgsys_vb2_buf_to_dev_buf(vb);
+		imgsys_req->buf_map[node->desc->id] = dev_buf;
+		buf_count++;
+
+		dev_dbg(pipe->imgsys_dev->dev,
+			"%s:%s: added buf(%p) to pipe-job(%p), buf_count(%d)\n",
+			pipe->desc->name, node->desc->name, dev_buf,
+			imgsys_req, buf_count);
+	}
+
+	if (!pipe) {
+		dev_dbg(imgsys_dev->dev,
+			"%s: no buffer in the request(%p)\n",
+			req->debug_str, req);
+
+		return -ENOENT;
+	}
+
+	atomic_set(&imgsys_req->buf_count, buf_count);
+	imgsys_req->id = mtk_imgsys_pipe_next_job_id(pipe);
+	imgsys_req->imgsys_pipe = pipe;
+	mtk_imgsys_pipe_debug_job(pipe, imgsys_req);
+
+	return vb2_request_validate(req);
+}
+
+static void mtk_imgsys_vb2_request_queue(struct media_request *req)
+{
+	struct mtk_imgsys_request *imgsys_req =
+					mtk_imgsys_media_req_to_imgsys_req(req);
+	struct mtk_imgsys_pipe *pipe = imgsys_req->imgsys_pipe;
+	unsigned long flag;
+
+	spin_lock_irqsave(&pipe->pending_job_lock, flag);
+	list_add_tail(&imgsys_req->list, &pipe->pipe_job_pending_list);
+	pipe->num_pending_jobs++;
+	dev_dbg(req->mdev->dev,
+		"%s:%s: current num of pending jobs(%d)\n",
+		__func__, pipe->desc->name, pipe->num_pending_jobs);
+	spin_unlock_irqrestore(&pipe->pending_job_lock, flag);
+	vb2_request_queue(req);
+}
+
+static const struct media_device_ops mtk_imgsys_media_req_ops = {
+	.req_validate = mtk_imgsys_vb2_request_validate,
+	.req_queue = mtk_imgsys_vb2_request_queue,
+	.req_alloc = mtk_imgsys_request_alloc,
+	.req_free = mtk_imgsys_request_free,
+};
+
+static const struct v4l2_file_operations mtk_imgsys_v4l2_fops = {
+	.unlocked_ioctl = video_ioctl2,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.poll = vb2_fop_poll,
+	.mmap = vb2_fop_mmap,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl32 = v4l2_compat_ioctl32,
+#endif
+};
+
+static int mtk_imgsys_dev_media_register(struct device *dev,
+					 struct media_device *media_dev)
+{
+	int ret;
+
+	media_dev->dev = dev;
+	strscpy(media_dev->model, MTK_IMGSYS_MEDIA_MODEL_NAME, sizeof(media_dev->model));
+	snprintf(media_dev->bus_info, sizeof(media_dev->bus_info),
+		 "platform:%s", dev_name(dev));
+	media_dev->hw_revision = 0;
+	media_dev->ops = &mtk_imgsys_media_req_ops;
+	media_device_init(media_dev);
+
+	ret = media_device_register(media_dev);
+	if (ret)
+		media_device_cleanup(media_dev);
+
+	return ret;
+}
+
+static int mtk_imgsys_video_device_v4l2_register(struct mtk_imgsys_pipe *pipe,
+						 struct mtk_imgsys_video_device *node)
+{
+	struct vb2_queue *vbq = &node->dev_q.vbq;
+	struct video_device *vdev = &node->vdev;
+	struct media_link *link;
+	int ret;
+
+	switch (node->desc->buf_type) {
+	case V4L2_BUF_TYPE_META_OUTPUT:
+		vbq->ops = &mtk_imgsys_vb2_meta_ops;
+		vdev->ioctl_ops = &mtk_imgsys_v4l2_meta_out_ioctl_ops;
+		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		vbq->ops = &mtk_imgsys_vb2_meta_ops;
+		vdev->ioctl_ops = &mtk_imgsys_v4l2_meta_cap_ioctl_ops;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		vbq->ops = &mtk_imgsys_vb2_video_ops;
+		vdev->ioctl_ops = &mtk_imgsys_v4l2_video_out_ioctl_ops;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		vbq->ops = &mtk_imgsys_vb2_video_ops;
+		vdev->ioctl_ops = &mtk_imgsys_v4l2_video_cap_ioctl_ops;
+		break;
+	default:
+		dev_info(pipe->imgsys_dev->dev,
+			 "unexpected buf_type %u\n", node->desc->buf_type);
+		return -EFAULT;
+	}
+
+	mutex_init(&node->dev_q.lock);
+	vdev->device_caps = node->desc->cap;
+	node->vdev_fmt.type = node->desc->buf_type;
+	mtk_imgsys_pipe_load_default_fmt(pipe, node, &node->vdev_fmt);
+
+	ret = media_entity_pads_init(&vdev->entity, 1, &node->vdev_pad);
+	if (ret) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "failed initialize media entity (%d)\n", ret);
+		goto err_mutex_destroy;
+	}
+
+	node->vdev_pad.flags = V4L2_TYPE_IS_OUTPUT(node->desc->buf_type) ?
+		MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
+
+	vbq->type = node->vdev_fmt.type;
+	vbq->io_modes = VB2_MMAP | VB2_DMABUF;
+	vbq->mem_ops = &vb2_dma_contig_memops;
+	vbq->supports_requests = true;
+	vbq->requires_requests = true;
+	vbq->buf_struct_size = sizeof(struct mtk_imgsys_dev_buffer);
+	vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	vbq->min_queued_buffers = 0;
+	vbq->drv_priv = pipe;
+	vbq->lock = &node->dev_q.lock;
+	vbq->max_num_buffers = IMGSYS_MAX_BUFFERS;
+
+	ret = vb2_queue_init(vbq);
+	if (ret) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "%s:%s:%s: failed to init vb2 queue(%d)\n",
+			 __func__, pipe->desc->name, node->desc->name,
+			 ret);
+		goto err_media_entity_cleanup;
+	}
+
+	strscpy(vbq->name, node->desc->name, sizeof(vbq->name));
+
+	snprintf(vdev->name, sizeof(vdev->name), "%s %s", pipe->desc->name,
+		 node->desc->name);
+	vdev->entity.name = vdev->name;
+	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+	vdev->entity.ops = NULL;
+	vdev->release = video_device_release_empty;
+	vdev->fops = &mtk_imgsys_v4l2_fops;
+	vdev->lock = &node->dev_q.lock;
+	if (node->desc->supports_ctrls)
+		vdev->ctrl_handler = &node->ctrl_handler;
+	else
+		vdev->ctrl_handler = NULL;
+	vdev->v4l2_dev = &pipe->imgsys_dev->v4l2_dev;
+	vdev->queue = &node->dev_q.vbq;
+	vdev->vfl_dir = V4L2_TYPE_IS_OUTPUT(node->desc->buf_type) ?
+		VFL_DIR_TX : VFL_DIR_RX;
+
+	vdev->queue->dev = pipe->imgsys_dev->dev;
+
+	if (node->desc->smem_alloc) {
+		vdev->queue->dev = pipe->imgsys_dev->smem_dev;
+		dev_dbg(pipe->imgsys_dev->dev,
+			"%s:%s: select smem_vb2_alloc_ctx(%p)\n",
+			pipe->desc->name, node->desc->name,
+			vdev->queue->dev);
+	} else {
+		vdev->queue->dev = pipe->imgsys_dev->dev;
+		dev_dbg(pipe->imgsys_dev->dev,
+			"%s:%s: select default_vb2_alloc_ctx(%p)\n",
+			pipe->desc->name, node->desc->name,
+			pipe->imgsys_dev->dev);
+	}
+
+	video_set_drvdata(vdev, pipe);
+
+	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+	if (ret) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "failed to register video device (%d)\n", ret);
+		goto err_vb2_queue_release;
+	}
+	dev_dbg(pipe->imgsys_dev->dev, "registered vdev: %s\n",
+		vdev->name);
+
+	if (V4L2_TYPE_IS_OUTPUT(node->desc->buf_type))
+		ret = media_create_pad_link(&vdev->entity, 0,
+					    &pipe->subdev.entity,
+					    node->desc->id, node->flags);
+	else
+		ret = media_create_pad_link(&pipe->subdev.entity,
+					    node->desc->id, &vdev->entity,
+					    0, node->flags);
+	if (ret)
+		goto err_video_unregister_device;
+
+	vdev->intf_devnode = media_devnode_create(&pipe->imgsys_dev->mdev,
+						  MEDIA_INTF_T_V4L_VIDEO, 0,
+						  VIDEO_MAJOR, vdev->minor);
+	if (!vdev->intf_devnode) {
+		ret = -ENOMEM;
+		goto err_rm_links;
+	}
+
+	link = media_create_intf_link(&vdev->entity,
+				      &vdev->intf_devnode->intf,
+				      node->flags);
+	if (!link) {
+		ret = -ENOMEM;
+		goto err_rm_devnode;
+	}
+
+	return 0;
+
+err_rm_devnode:
+	media_devnode_remove(vdev->intf_devnode);
+
+err_rm_links:
+	media_entity_remove_links(&vdev->entity);
+
+err_video_unregister_device:
+	video_unregister_device(vdev);
+
+err_vb2_queue_release:
+	vb2_queue_release(&node->dev_q.vbq);
+
+err_media_entity_cleanup:
+	media_entity_cleanup(&node->vdev.entity);
+
+err_mutex_destroy:
+	mutex_destroy(&node->dev_q.lock);
+
+	return ret;
+}
+
+/******************************************************************************
+ * @array img_resize_ratio_menu
+ * @brief IMGSYS hardware supports multiple resizers.
+ *        - Any Ratio: Allows for any resize ratio, including
+ *          down 2, down 4, and down 42.
+ *        - Down 4: Specifically for downscaling by a factor of 4.
+ *        - Down 2: Specifically for downscaling by a factor of 2.
+ *        - Down42: Used for downscaling by a factor of 4 on the
+ *          first use, and by a factor of 2 on subsequent uses.
+ *        - NULL: Indicates the end of the menu options
+ ******************************************************************************/
+static const char * const img_resize_ratio_menu[] = {
+	"Any Ratio",
+	"Down 4",
+	"Down 2",
+	"Down 42",
+	NULL,
+};
+
+static const struct v4l2_ctrl_config cfg_mtk_resize_ratio = {
+	.ops = &mtk_imgsys_video_device_ctrl_ops,
+	.id = V4L2_CID_MTK_IMG_RESIZE_RATIO,
+	.name = "Image resize ratio",
+	.type = V4L2_CTRL_TYPE_MENU,
+	.max = 3,
+	.def = 0,
+	.qmenu = img_resize_ratio_menu,
+};
+
+static int mtk_imgsys_pipe_v4l2_ctrl_init(struct mtk_imgsys_pipe *imgsys_pipe)
+{
+	int i, ret;
+	struct mtk_imgsys_video_device *ctrl_node;
+
+	for (i = 0; i < MTK_IMGSYS_VIDEO_NODE_ID_TOTAL_NUM; i++) {
+		ctrl_node = &imgsys_pipe->nodes[i];
+		if (!ctrl_node->desc->supports_ctrls)
+			continue;
+
+		v4l2_ctrl_handler_init(&ctrl_node->ctrl_handler, 4);
+		v4l2_ctrl_new_std(&ctrl_node->ctrl_handler,
+				  &mtk_imgsys_video_device_ctrl_ops, V4L2_CID_ROTATE,
+				  0, 270, 90, 0);
+		v4l2_ctrl_new_std(&ctrl_node->ctrl_handler,
+				  &mtk_imgsys_video_device_ctrl_ops, V4L2_CID_VFLIP,
+				  0, 1, 1, 0);
+		v4l2_ctrl_new_std(&ctrl_node->ctrl_handler,
+				  &mtk_imgsys_video_device_ctrl_ops, V4L2_CID_HFLIP,
+				  0, 1, 1, 0);
+		ctrl_node->resize_ratio_ctrl =
+			v4l2_ctrl_new_custom(&ctrl_node->ctrl_handler,
+					     &cfg_mtk_resize_ratio, NULL);
+		ret = ctrl_node->ctrl_handler.error;
+		if (ret) {
+			dev_info(imgsys_pipe->imgsys_dev->dev,
+				 "%s create rotate ctrl failed:(%d)",
+				 ctrl_node->desc->name, ret);
+			goto err_free_ctrl_handlers;
+		}
+	}
+
+	return 0;
+
+err_free_ctrl_handlers:
+	for (; i >= 0; i--) {
+		ctrl_node = &imgsys_pipe->nodes[i];
+		if (!ctrl_node->desc->supports_ctrls)
+			continue;
+		v4l2_ctrl_handler_free(&ctrl_node->ctrl_handler);
+	}
+
+	return ret;
+}
+
+static void mtk_imgsys_pipe_v4l2_ctrl_release(struct mtk_imgsys_pipe *imgsys_pipe)
+{
+	struct mtk_imgsys_video_device *vdev;
+	int i;
+
+	for (i = 0; i < imgsys_pipe->desc->total_queues; ++i) {
+		vdev = &imgsys_pipe->nodes[i];
+		if (vdev->desc->supports_ctrls)
+			v4l2_ctrl_handler_free(&vdev->ctrl_handler);
+	}
+}
+
+static int mtk_imgsys_pipe_v4l2_register(struct mtk_imgsys_pipe *pipe,
+					 struct media_device *media_dev,
+					 struct v4l2_device *v4l2_dev)
+{
+	int i, ret;
+
+	ret = mtk_imgsys_pipe_v4l2_ctrl_init(pipe);
+	if (ret) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "%s: failed(%d) to initialize ctrls\n",
+			 pipe->desc->name, ret);
+
+		return ret;
+	}
+
+	pipe->streaming = 0;
+
+	/* Initialize subdev media entity */
+	pipe->subdev_pads = devm_kcalloc(pipe->imgsys_dev->dev,
+					 pipe->desc->total_queues,
+					 sizeof(*pipe->subdev_pads),
+					 GFP_KERNEL);
+	if (!pipe->subdev_pads) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "failed to alloc pipe->subdev_pads (%d)\n", ret);
+		ret = -ENOMEM;
+		goto err_release_ctrl;
+	}
+	ret = media_entity_pads_init(&pipe->subdev.entity,
+				     pipe->desc->total_queues,
+				     pipe->subdev_pads);
+	if (ret) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "failed initialize subdev media entity (%d)\n", ret);
+		goto err_free_subdev_pads;
+	}
+
+	/* Initialize subdev */
+	v4l2_subdev_init(&pipe->subdev, &mtk_imgsys_subdev_ops);
+
+	pipe->subdev.entity.function =
+		MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
+	pipe->subdev.entity.ops = &mtk_imgsys_media_ops;
+	pipe->subdev.flags =
+		V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+	pipe->subdev.ctrl_handler = NULL;
+
+	for (i = 0; i < pipe->desc->total_queues; i++)
+		pipe->subdev_pads[pipe->nodes[i].desc->id].flags =
+			V4L2_TYPE_IS_OUTPUT(pipe->nodes[i].desc->buf_type) ?
+			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+
+	snprintf(pipe->subdev.name, sizeof(pipe->subdev.name),
+		 "%s", pipe->desc->name);
+	v4l2_set_subdevdata(&pipe->subdev, pipe);
+
+	ret = v4l2_device_register_subdev(&pipe->imgsys_dev->v4l2_dev,
+					  &pipe->subdev);
+	if (ret) {
+		dev_info(pipe->imgsys_dev->dev,
+			 "failed initialize subdev (%d)\n", ret);
+		goto err_media_entity_cleanup;
+	}
+
+	dev_dbg(pipe->imgsys_dev->dev,
+		"register subdev: %s, ctrl_handler %p\n",
+		 pipe->subdev.name, pipe->subdev.ctrl_handler);
+
+	/* Create video nodes and links */
+	for (i = 0; i < pipe->desc->total_queues; i++) {
+		ret =
+			mtk_imgsys_video_device_v4l2_register(pipe,
+							      &pipe->nodes[i]);
+		if (ret)
+			goto err_unregister_subdev;
+	}
+
+	return 0;
+
+err_unregister_subdev:
+	v4l2_device_unregister_subdev(&pipe->subdev);
+
+err_media_entity_cleanup:
+	media_entity_cleanup(&pipe->subdev.entity);
+
+err_free_subdev_pads:
+	devm_kfree(pipe->imgsys_dev->dev, pipe->subdev_pads);
+
+err_release_ctrl:
+	mtk_imgsys_pipe_v4l2_ctrl_release(pipe);
+
+	return ret;
+}
+
+static void mtk_imgsys_pipe_v4l2_unregister(struct mtk_imgsys_pipe *pipe)
+{
+	unsigned int i;
+
+	for (i = 0; i < pipe->desc->total_queues; i++) {
+		video_unregister_device(&pipe->nodes[i].vdev);
+		vb2_queue_release(&pipe->nodes[i].dev_q.vbq);
+		media_entity_cleanup(&pipe->nodes[i].vdev.entity);
+		mutex_destroy(&pipe->nodes[i].dev_q.lock);
+	}
+
+	v4l2_device_unregister_subdev(&pipe->subdev);
+	media_entity_cleanup(&pipe->subdev.entity);
+	mtk_imgsys_pipe_v4l2_ctrl_release(pipe);
+}
+
+static void mtk_imgsys_dev_media_unregister(struct mtk_imgsys_dev *imgsys_dev)
+{
+	media_device_unregister(&imgsys_dev->mdev);
+	media_device_cleanup(&imgsys_dev->mdev);
+}
+
+static int mtk_imgsys_dev_v4l2_init(struct mtk_imgsys_dev *imgsys_dev)
+{
+	struct media_device *media_dev = &imgsys_dev->mdev;
+	struct v4l2_device *v4l2_dev = &imgsys_dev->v4l2_dev;
+	int ret;
+
+	ret = mtk_imgsys_dev_media_register(imgsys_dev->dev, media_dev);
+	if (ret) {
+		dev_info(imgsys_dev->dev,
+			 "%s: media device register failed(%d)\n",
+			 __func__, ret);
+		return ret;
+	}
+
+	v4l2_dev->mdev = media_dev;
+	v4l2_dev->ctrl_handler = NULL;
+
+	ret = v4l2_device_register(imgsys_dev->dev, v4l2_dev);
+	if (ret) {
+		dev_info(imgsys_dev->dev,
+			 "%s: v4l2 device register failed(%d)\n",
+			 __func__, ret);
+		goto err_release_media_device;
+	}
+
+	ret = mtk_imgsys_pipe_init(imgsys_dev,
+				   &imgsys_dev->imgsys_pipe,
+				   imgsys_dev->cust_pipes);
+	if (ret) {
+		dev_info(imgsys_dev->dev,
+			 "%s: init failed(%d)\n",
+			 imgsys_dev->imgsys_pipe.desc->name, ret);
+		goto err_release_pipe;
+	}
+
+	ret = mtk_imgsys_pipe_v4l2_register(&imgsys_dev->imgsys_pipe, &imgsys_dev->mdev,
+					    &imgsys_dev->v4l2_dev);
+	if (ret) {
+		dev_info(imgsys_dev->dev,
+			 "%s: failed(%d) to create V4L2 devices\n",
+			 imgsys_dev->imgsys_pipe.desc->name, ret);
+		goto err_register_pipe;
+	}
+
+	ret = v4l2_device_register_subdev_nodes(&imgsys_dev->v4l2_dev);
+	if (ret) {
+		dev_info(imgsys_dev->dev,
+			 "failed to register subdevs (%d)\n", ret);
+		goto err_register_pipe;
+	}
+
+	return 0;
+
+err_register_pipe:
+	mtk_imgsys_pipe_v4l2_unregister(&imgsys_dev->imgsys_pipe);
+err_release_pipe:
+	mtk_imgsys_pipe_release(&imgsys_dev->imgsys_pipe);
+
+	v4l2_device_unregister(v4l2_dev);
+
+err_release_media_device:
+	mtk_imgsys_dev_media_unregister(imgsys_dev);
+
+	return ret;
+}
+
+static void mtk_imgsys_dev_v4l2_release(struct mtk_imgsys_dev *imgsys_dev)
+{
+	mtk_imgsys_pipe_v4l2_unregister(&imgsys_dev->imgsys_pipe);
+	mtk_imgsys_pipe_release(&imgsys_dev->imgsys_pipe);
+	v4l2_device_unregister(&imgsys_dev->v4l2_dev);
+	mtk_imgsys_dev_media_unregister(imgsys_dev);
+}
+
+static int mtk_imgsys_of_rproc(struct mtk_imgsys_dev *imgsys,
+			       struct platform_device *pdev)
+{
+	struct device *dev = imgsys->dev;
+
+	imgsys->scp = scp_get(pdev);
+	if (!imgsys->scp) {
+		dev_err(dev, "failed to get scp device\n");
+		return -ENODEV;
+	}
+
+	imgsys->rproc_handle = scp_get_rproc(imgsys->scp);
+	dev_dbg(dev, "imgsys rproc_phandle: 0x%pK\n", imgsys->rproc_handle);
+	imgsys->smem_dev = scp_get_device(imgsys->scp);
+
+	return 0;
+}
+
+static int mtk_imgsys_probe(struct platform_device *pdev)
+{
+	struct mtk_imgsys_dev *imgsys_dev;
+	struct device **larb_devs;
+	struct device_link *link;
+	const struct cust_data *data;
+	struct resource *res;
+	int larbs_num, i;
+	int ret;
+
+	imgsys_dev = devm_kzalloc(&pdev->dev, sizeof(*imgsys_dev), GFP_KERNEL);
+	if (!imgsys_dev)
+		return -ENOMEM;
+
+	data = of_device_get_match_data(&pdev->dev);
+
+	init_imgsys_pipeline(data);
+
+	imgsys_dev->cust_pipes = data->pipe_settings;
+	imgsys_dev->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get memory resource\n");
+		return -ENODEV;
+	}
+	imgsys_dev->imgsys_resource = res;
+
+	dev_set_drvdata(&pdev->dev, imgsys_dev);
+
+	imgsys_dev->num_mods = data->mod_num;
+
+	/* Get Clocks */
+	imgsys_dev->clks = data->clks;
+	imgsys_dev->num_clks = data->clk_num;
+	ret = devm_clk_bulk_get(&pdev->dev, imgsys_dev->num_clks,
+				imgsys_dev->clks);
+	if (ret)
+		dev_info(&pdev->dev, "Failed to get clks:%d\n", ret);
+
+	/* DMA configuration */
+	if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34)))
+		dev_info(&pdev->dev, "%s:No DMA available\n", __func__);
+
+	if (!pdev->dev.dma_parms) {
+		pdev->dev.dma_parms =
+			devm_kzalloc(imgsys_dev->dev, sizeof(*pdev->dev.dma_parms), GFP_KERNEL);
+	}
+	if (pdev->dev.dma_parms)
+		dma_set_max_seg_size(imgsys_dev->dev, UINT_MAX);
+
+	/* Get LARB Information */
+	larbs_num = of_count_phandle_with_args(pdev->dev.of_node,
+					       "mediatek,larbs", NULL);
+	dev_dbg(imgsys_dev->dev, "%d larbs to be added", larbs_num);
+	larb_devs = devm_kzalloc(&pdev->dev, sizeof(larb_devs) * larbs_num, GFP_KERNEL);
+	if (!larb_devs) {
+		ret = -ENOMEM;
+		goto err_free_dev_alloc;
+	}
+	for (i = 0; i < larbs_num; i++) {
+		struct device_node *larb_node;
+		struct platform_device *larb_pdev;
+
+		larb_node = of_parse_phandle(pdev->dev.of_node, "mediatek,larbs", i);
+		if (!larb_node) {
+			dev_info(imgsys_dev->dev,
+				 "%d larb node not found\n", i);
+			continue;
+		}
+
+		larb_pdev = of_find_device_by_node(larb_node);
+		if (!larb_pdev) {
+			of_node_put(larb_node);
+			dev_info(imgsys_dev->dev,
+				 "%d larb device not found\n", i);
+			continue;
+		}
+		of_node_put(larb_node);
+
+		link = device_link_add(&pdev->dev, &larb_pdev->dev,
+				       DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+		if (!link)
+			dev_info(imgsys_dev->dev, "unable to link SMI LARB idx %d\n", i);
+
+		larb_devs[i] = &larb_pdev->dev;
+	}
+	imgsys_dev->larbs = larb_devs;
+	imgsys_dev->num_larbs = larbs_num;
+
+	/* Register rproc device */
+	if (mtk_imgsys_of_rproc(imgsys_dev, pdev)) {
+		ret = -EFAULT;
+		goto err_free_larb_alloc;
+	}
+
+	/* Imgsys device initialization */
+	ret = mtk_imgsys_dev_v4l2_init(imgsys_dev);
+	if (ret) {
+		dev_info(&pdev->dev, "v4l2 init failed(%d)\n", ret);
+
+		goto err_free_larb_alloc;
+	}
+
+	/* Enable power*/
+	pm_runtime_set_autosuspend_delay(&pdev->dev, IMGSYS_SUSPEND_TIME);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+err_free_larb_alloc:
+	devm_kfree(&pdev->dev, imgsys_dev->larbs);
+err_free_dev_alloc:
+	devm_kfree(&pdev->dev, imgsys_dev);
+	return ret;
+}
+
+static void mtk_imgsys_remove(struct platform_device *pdev)
+{
+	struct mtk_imgsys_dev *imgsys_dev = dev_get_drvdata(&pdev->dev);
+
+	pm_runtime_disable(&pdev->dev);
+	mtk_imgsys_dev_v4l2_release(imgsys_dev);
+	devm_kfree(&pdev->dev, imgsys_dev->larbs);
+	devm_kfree(&pdev->dev, imgsys_dev);
+}
+
+static int __maybe_unused mtk_imgsys_pm_suspend(struct device *dev)
+{
+	int ret;
+
+	if (pm_runtime_suspended(dev)) {
+		dev_info(dev, "%s: pm_runtime_suspended is true, no action\n",
+			 __func__);
+		return 0;
+	}
+
+	ret = pm_runtime_force_suspend(dev);
+	if (ret) {
+		dev_info(dev, "%s: pm_runtime_force_suspend failed:(%d)\n",
+			 __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused mtk_imgsys_pm_resume(struct device *dev)
+{
+	int ret;
+
+	if (pm_runtime_suspended(dev)) {
+		dev_info(dev, "%s: pm_runtime_suspended is true, no action\n",
+			 __func__);
+		return 0;
+	}
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret) {
+		dev_info(dev, "%s: pm_runtime_force_resume failed:(%d)\n",
+			 __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused mtk_imgsys_runtime_suspend(struct device *dev)
+{
+	struct mtk_imgsys_dev *imgsys_dev = dev_get_drvdata(dev);
+
+	clk_bulk_disable_unprepare(imgsys_dev->num_clks,
+				   imgsys_dev->clks);
+
+	return 0;
+}
+
+static int __maybe_unused mtk_imgsys_runtime_resume(struct device *dev)
+{
+	struct mtk_imgsys_dev *imgsys_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_bulk_prepare_enable(imgsys_dev->num_clks,
+				      imgsys_dev->clks);
+	if (ret) {
+		dev_info(imgsys_dev->dev,
+			 "failed to enable dip clks(%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops mtk_imgsys_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mtk_imgsys_pm_suspend, mtk_imgsys_pm_resume)
+	SET_RUNTIME_PM_OPS(mtk_imgsys_runtime_suspend,
+			   mtk_imgsys_runtime_resume, NULL)
+};
+
+static struct clk_bulk_data imgsys_isp7_clks[] = {
+	{ .id = "IMGSYS_CG_IMG_TRAW0" },
+	{ .id = "IMGSYS_CG_IMG_TRAW1" },
+	{ .id = "IMGSYS_CG_IMG_VCORE_GALS" },
+	{ .id = "IMGSYS_CG_IMG_DIP0" },
+	{ .id = "IMGSYS_CG_IMG_WPE0" },
+	{ .id = "IMGSYS_CG_IMG_WPE1" },
+	{ .id = "IMGSYS_CG_IMG_WPE2" },
+	{ .id = "IMGSYS_CG_IMG_GALS" },
+	{ .id = "DIP_TOP_DIP_TOP" },
+	{ .id = "DIP_NR_DIP_NR" },
+	{ .id = "WPE1_CG_DIP1_WPE" },
+	{ .id = "WPE2_CG_DIP1_WPE" },
+	{ .id = "WPE3_CG_DIP1_WPE" },
+	{ .id = "ME_CG_IPE" },
+	{ .id = "ME_CG_IPE_TOP" },
+	{ .id = "ME_CG" },
+	{ .id = "ME_CG_LARB12" },
+};
+
+static const struct cust_data imgsys_data[] = {
+	[0] = {
+		.clks = imgsys_isp7_clks,
+		.clk_num = ARRAY_SIZE(imgsys_isp7_clks),
+		.module_pipes = module_pipe_isp7,
+		.mod_num = ARRAY_SIZE(module_pipe_isp7),
+		.pipe_settings = pipe_settings_isp7,
+		.pipe_num = ARRAY_SIZE(pipe_settings_isp7),
+	},
+};
+
+static const struct of_device_id mtk_imgsys_of_match[] = {
+	{ .compatible = "mediatek,mt8188-isp-imgsys", .data = (void *)&imgsys_data},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_imgsys_of_match);
+
+static struct platform_driver mtk_imgsys_driver = {
+	.probe   = mtk_imgsys_probe,
+	.remove  = mtk_imgsys_remove,
+	.driver  = {
+		.name = "mtk-imgsys",
+		.owner	= THIS_MODULE,
+		.pm = &mtk_imgsys_pm_ops,
+		.of_match_table = of_match_ptr(mtk_imgsys_of_match),
+	}
+};
+
+module_platform_driver(mtk_imgsys_driver);
+
+MODULE_AUTHOR("Frederic Chen <frederic.chen@mediatek.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek IMGSYS driver");
+
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-vnode_id.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-vnode_id.h
new file mode 100644
index 000000000000..4a418099d7c0
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-vnode_id.h
@@ -0,0 +1,100 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+#ifndef _MTK_IMGSYS_VNODE_ID_H_
+#define _MTK_IMGSYS_VNODE_ID_H_
+
+/**
+ * enum imgsys_video_nodes_id - Enumeration of video node IDs for image system
+ *
+ * This enumeration defines the unique identifiers for various video nodes
+ * used in the image processing system. Each ID corresponds to a specific
+ * video node that can be utilized for different functionalities.
+ */
+enum imgsys_video_nodes_id {
+	/* IMGSYS_MODULE_TRAW */
+	MTK_IMGSYS_VIDEO_NODE_ID_TIMGI_OUT = 0,
+	MTK_IMGSYS_VIDEO_NODE_ID_METAI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_PDC_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TYUVO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TYUV2O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TYUV3O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TYUV4O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TYUV5O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_FEO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TIMGO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_IMGSTATO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_XTMEO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_XTFDO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_XTADLDBGO_CAPTURE,
+	/* IMGSYS_MODULE_DIP */
+	MTK_IMGSYS_VIDEO_NODE_ID_IMGI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_VIPI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_REC_DSI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_REC_DPI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_CNR_BLURMAPI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_LFEI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_RFEI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRSI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRWI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRMI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRCI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRLI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRVBI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_IMG2O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_IMG3O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_IMG4O_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_FMO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRSO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRWO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TNRMO_CAPTURE,
+	/* IMGSYS_MODULE_PQDIP */
+	MTK_IMGSYS_VIDEO_NODE_ID_PIMGI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WROT_A_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_WROT_B_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TCCSO_A_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_TCCSO_B_CAPTURE,
+	/* IMGSYS_MODULE_ME */
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL0IMG0_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL0IMG1_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL1IMG0_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL1IMG1_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEIMGSTATS_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL0RMV_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL1RMV_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL0FMB_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL1FMB_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEMIL_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEMMGMIL_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL0WMV_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL1WMV_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MECONF_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEWMAP_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEFMV_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEFST_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MELMI_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL0WFMB_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_MEL1WFMB_CAPTURE,
+	/* IMGSYS_MODULE_WPE */
+	MTK_IMGSYS_VIDEO_NODE_ID_WWPEI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WVECI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WPSP_COEFI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WWPEO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_WMSKO_CAPTURE,
+	/* IMGSYS_MODULE_WPE_TNR */
+	MTK_IMGSYS_VIDEO_NODE_ID_WTWPEI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WTVECI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WTPSP_COEFI_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_WTWPEO_CAPTURE,
+	MTK_IMGSYS_VIDEO_NODE_ID_WTMSKO_CAPTURE,
+	/* other module video nodes to be added */
+	MTK_IMGSYS_VIDEO_NODE_ID_TUNING_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_CTRLMETA_OUT,
+	MTK_IMGSYS_VIDEO_NODE_ID_TOTAL_NUM,
+};
+
+#endif
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys_v4l2_vnode.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys_v4l2_vnode.h
new file mode 100644
index 000000000000..5a6f3220ab6b
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys_v4l2_vnode.h
@@ -0,0 +1,135 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Author: Frederic Chen <frederic.chen@mediatek.com>
+ *
+ */
+#ifndef _MTK_IMGSYS_V4L2_VNODE_H_
+#define _MTK_IMGSYS_V4L2_VNODE_H_
+
+#include "mtk_imgsys-of.h"
+#include "mtk_imgsys-dev.h"
+#include "mtk_imgsys-formats.h"
+#include "modules/mtk_dip_v4l2_vnode.h"
+#include "modules/mtk_traw_v4l2_vnode.h"
+#include "modules/mtk_pqdip_v4l2_vnode.h"
+#include "modules/mtk_wpe_v4l2_vnode.h"
+#include "modules/mtk_me_v4l2_vnode.h"
+
+/**
+ * enum mtk_imgsys_module_id - Enumeration of image system module IDs
+ * @IMGSYS_MODULE_TRAW: Module for TRAW processing.
+ * @IMGSYS_MODULE_DIP: Module for DIP processing.
+ * @IMGSYS_MODULE_PQDIP: Module for PQDIP processing.
+ * @IMGSYS_MODULE_ME: Module for Motion Estimation (ME).
+ * @IMGSYS_MODULE_WPE: Module for WPE processing.
+ * @IMGSYS_MODULE_MAIN: Main module for image system.
+ * @IMGSYS_MODULE_NUM: Total number of image system modules.
+ */
+enum mtk_imgsys_module_id {
+	IMGSYS_MODULE_TRAW = 0,
+	IMGSYS_MODULE_DIP,
+	IMGSYS_MODULE_PQDIP,
+	IMGSYS_MODULE_ME,
+	IMGSYS_MODULE_WPE,
+	IMGSYS_MODULE_MAIN,
+	IMGSYS_MODULE_NUM,
+};
+
+/**
+ * struct mtk_imgsys_mod_pipe_desc - Pipe description for image system modules
+ * @vnode_desc: Pointer to the node descriptor array
+ * @node_num: Number of nodes in the descriptor array
+ *
+ * This structure defines the pipe description for each module in the MediaTek
+ * image system. It includes a pointer to the node descriptor array and the
+ * number of nodes in that array.
+ */
+static const struct mtk_imgsys_mod_pipe_desc module_pipe_isp7[] = {
+	[IMGSYS_MODULE_TRAW] = {
+		.vnode_desc = traw_setting,
+		.node_num = ARRAY_SIZE(traw_setting),
+	},
+	[IMGSYS_MODULE_DIP] = {
+		.vnode_desc = dip_setting,
+		.node_num = ARRAY_SIZE(dip_setting),
+	},
+	[IMGSYS_MODULE_PQDIP] = {
+		.vnode_desc = pqdip_setting,
+		.node_num = ARRAY_SIZE(pqdip_setting),
+	},
+	[IMGSYS_MODULE_ME] = {
+		.vnode_desc = me_setting,
+		.node_num = ARRAY_SIZE(me_setting),
+	},
+	[IMGSYS_MODULE_WPE] = {
+		.vnode_desc = wpe_setting,
+		.node_num = ARRAY_SIZE(wpe_setting),
+	},
+	[IMGSYS_MODULE_MAIN] = {
+		.vnode_desc = NULL,
+		.node_num = 0,
+	}
+};
+
+/* Tuning formats for MediaTek Image System */
+static const struct mtk_imgsys_dev_format tuning_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_metai,
+	},
+};
+
+/* Control metadata formats for MediaTek Image System */
+static const struct mtk_imgsys_dev_format ctrlmeta_fmts[] = {
+	{
+		.fmt = &mtk_imgsys_format_ctrlmeta,
+	},
+};
+
+/**
+ * queues_setting - Array to store video device descriptions for each module
+ * and meta in ImgSys
+ */
+static struct mtk_imgsys_video_device_desc
+queues_setting[MTK_IMGSYS_VIDEO_NODE_ID_TOTAL_NUM] = {
+	[MTK_IMGSYS_VIDEO_NODE_ID_TUNING_OUT] = {
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_TUNING_OUT,
+		.name = "Tuning",
+		.cap = V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_META_OUTPUT,
+		.smem_alloc = 1,
+		.flags = 0,
+		.fmts = tuning_fmts,
+		.num_fmts = ARRAY_SIZE(tuning_fmts),
+		.dma_port = 0,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Tuning data",
+	},
+	[MTK_IMGSYS_VIDEO_NODE_ID_CTRLMETA_OUT] = {
+		.id = MTK_IMGSYS_VIDEO_NODE_ID_CTRLMETA_OUT,
+		.name = "CtrlMeta",
+		.cap = V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING,
+		.buf_type = V4L2_BUF_TYPE_META_OUTPUT,
+		.smem_alloc = 1,
+		.flags = 0,
+		.fmts = ctrlmeta_fmts,
+		.num_fmts = ARRAY_SIZE(ctrlmeta_fmts),
+		.dma_port = 0,
+		.frmsizeenum = &dip_in_frmsizeenum,
+		.description = "Control meta data for flow control",
+	},
+};
+
+/**
+ * pipe_settings_isp7 - Array to store pipeline configurations for ISP7 in ImgSys
+ */
+static const struct mtk_imgsys_pipe_desc pipe_settings_isp7[] = {
+	{
+		.name = MTK_IMGSYS_MEDIA_MODEL_NAME,
+		.id = 0,
+		.queue_descs = queues_setting,
+		.total_queues = ARRAY_SIZE(queues_setting),
+	},
+};
+#endif