[PATCH v1 08/10] media: mediatek: isp: Add SCP support for ImgSys driver

Olivia Wen olivia.wen at mediatek.com
Sat May 24 04:50:00 PDT 2025


The ImgSys driver is implemented as a series of patches, with this patch
focusing on the SCP support for ImgSys driver. It covers the memory
allocation and transmission interfaces required by SCP. Frame-related
information is transmitted to SCP, where it is packaged into commands
and the necessary hardware information. These commands are then sent to
the kernel for further processing.

Signed-off-by: Olivia Wen <olivia.wen at mediatek.com>
---
 .../mediatek/isp/isp_7x/imgsys/Makefile       |   1 +
 .../mediatek/isp/isp_7x/imgsys/mtk-img-ipi.h  | 143 +++++++
 .../isp/isp_7x/imgsys/mtk_imgsys-scp.c        | 349 ++++++++++++++++++
 .../isp/isp_7x/imgsys/mtk_imgsys-scp.h        | 194 ++++++++++
 4 files changed, 687 insertions(+)
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk-img-ipi.h
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.c
 create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.h

diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile
index c0f0f3a0c38a..29c18c773fdc 100644
--- a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile
@@ -3,6 +3,7 @@
 
 mtk_imgsys_util-objs := \
 mtk_imgsys-cmdq.o \
+mtk_imgsys-scp.o \
 mtk_imgsys-module_main.o \
 mtk_imgsys-of.o \
 mtk_imgsys-formats.o \
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk-img-ipi.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk-img-ipi.h
new file mode 100644
index 000000000000..850f6ec99a96
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk-img-ipi.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MTK_IMG_IPI_H__
+#define __MTK_IMG_IPI_H__
+
+#include <linux/types.h>
+#include "mtk_header_desc.h"
+
+#define HEADER_VER 19481
+#define IMG_MAX_HW_DMAS 72
+#define IMG_MAX_HW 12
+#define WPE_ENG_NUM 3
+#define TMAX 16
+
+/**
+ * enum img_module_id - Enumeration of image processing module IDs
+ * @IMG_MODULE_WPE: ID for the WPE (Warp Engine) module
+ * @IMG_MODULE_TRAW: ID for the TRAW (Tile Raw) module
+ * @IMG_MODULE_DIP: ID for the DIP (Digital Image Processing) module
+ * @IMG_MODULE_PQDIP: ID for the PQDIP (Picture Quality Digital Image Processing) module
+ * @IMG_MODULE_MAX: Maximum ID value, used for boundary checking
+ */
+enum img_module_id {
+	IMG_MODULE_WPE = 0,
+	IMG_MODULE_TRAW = 1,
+	IMG_MODULE_DIP = 2,
+	IMG_MODULE_PQDIP = 3,
+	IMG_MODULE_MAX = 4,
+};
+
+/**
+ * struct module_init_info - Information about module initialization
+ * @c_wbuf: Command queue (CQ) working buffer address
+ * @c_wbuf_dma: DMA address of the CQ working buffer
+ * @c_wbuf_sz: Size of the CQ working buffer
+ * @t_wbuf: Tile dirvier (TDR) working buffer address
+ * @t_wbuf_dma: DMA address of the TDR working buffer
+ * @t_wbuf_sz: Size of the TDR working buffer
+ */
+struct module_init_info {
+	u64 c_wbuf;         /* CQ working buffer address */
+	u64 c_wbuf_dma;     /* DMA address of the CQ working buffer */
+	u32 c_wbuf_sz;      /* Size of the CQ working buffer */
+	u64 t_wbuf;         /* TDR working buffer address */
+	u64 t_wbuf_dma;     /* DMA address of the TDR working buffer */
+	u32 t_wbuf_sz;      /* Size of the TDR working buffer */
+} __packed;
+
+/**
+ * struct img_init_info - Information about image initialization
+ * @header_version: Version of the header
+ * @isp_version: ISP version
+ * @frameparam_size: Size of the frame parameters
+ * @module_info: Array of module working buffer information
+ * @g_wbuf: Global Command Engine (GCE) working buffer address
+ * @g_wbuf_sz: Size of the GCE working buffer
+ *
+ * This structure is used as the parameter for IPI_IMGSYS_INIT_ID and
+ * IPI_IMGSYS_DEINIT_ID. It contains information necessary for initializing and
+ * deinitializing the image system.
+ */
+struct img_init_info {
+	u32	header_version;
+	u32	isp_version;
+	u32	frameparam_size;
+	struct module_init_info module_info[IMG_MODULE_MAX];
+	u64	g_wbuf;
+	u32	g_wbuf_sz;
+} __packed;
+
+/**
+ * struct img_swfrm_info - Software frame information structure for image system
+ * @hw_comb: Hardware combination, which used to store the combination of
+ * enum mtk_imgsys_engine_bitmask
+ * @sw_ridx: Software read index, provided to SCP upon notification to access
+ * GCE buffer location
+ * @is_time_shared: Indicates if the frame is time-shared
+ * @is_earlycb: Indicates if early callback is enabled
+ * @sw_goft: offset of GCE buffer
+ * @g_swbuf: virtual address of GCE buffer
+ *
+ * These fields are primarily set by SCP (System Control Processor) and used by
+ * the kernel for processing and verifing data.
+ */
+struct img_swfrm_info {
+	u32 hw_comb;
+	int sw_ridx;
+	u8 is_time_shared;
+	u8 is_earlycb;
+	u64 sw_goft;
+	void *g_swbuf;
+} __packed;
+
+/**
+ * struct img_ipi_frameparam - Frame parameters for IMGSYS IPI
+ * @dmas_enable: Array indicating enabled DMAs for each hardware unit
+ * @dmas: Array of DMA descriptors for each hardware unit
+ * @tuning_meta: Descriptor for tuning metadata
+ * @ctrl_meta: Descriptor for control metadata
+ *
+ * This structure defines the frame parameters used in the IMGSYS IPI
+ * (Inter-Processor Interface). It includes arrays to indicate enabled DMAs and
+ * their descriptors, as well as descriptors for tuning and control metadata.
+ */
+struct img_ipi_frameparam {
+	u8 dmas_enable[IMG_MAX_HW_DMAS];
+	struct header_desc_norm	dmas[IMG_MAX_HW_DMAS];
+	struct header_desc_norm	tuning_meta;
+	struct header_desc_norm	ctrl_meta;
+};
+
+/**
+ * struct img_sw_buffer - Software buffer address information
+ * @scp_addr: Physical address accessed by SCP
+ * @offset: Address offset
+ *
+ * This structure defines the address information of a software buffer used in
+ * the SCP.
+ */
+struct img_sw_buffer {
+	u32	scp_addr;
+	u32	offset;
+} __packed;
+
+/**
+ * struct img_ipi_param - Parameters for IMGSYS IPI
+ * @frm_param: Software buffer adreess for frame parameters
+ * @req_addr_va: Virtual address for the request
+ *
+ * This structure defines the parameters used in the IMGSYS IPI, including a
+ * software buffer physical address for frame parameters and a virtual address
+ * for the request.
+ */
+struct img_ipi_param {
+	struct img_sw_buffer frm_param;
+	u64	req_addr_va;
+} __packed;
+
+#endif  /* __MTK_IMG_IPI_H__ */
+
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.c
new file mode 100644
index 000000000000..4e6126d9f28c
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.c
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#include <linux/slab.h>
+#include <linux/remoteproc.h>
+#include <linux/dma-direction.h>
+#include "mtk_imgsys-cmdq.h"
+#include "mtk_imgsys-scp.h"
+
+#define SCP_TIMEOUT_MS          4000U
+
+/**
+ * struct mtk_scp_reserve_memblock - Represents a memory block reserved by the
+ * kernel for usage by the SCP (System Control Processor).
+ *
+ * @id:         Unique identifier for the memory block. This ID is used to
+ *              reference and manage the memory block within the system.
+ * @start_phys: Physical address the starting point of the buffer.
+ * @start_virt: Kernel virtual address of the starting point of the buffer.
+ * @start_dma:  DMA (Direct Memory Access) address of the starting point of the
+ *              buffer.
+ * @size:       Size of the allocated buffer, in bytes.
+ * @dma_dir:	Direction of DMA data transfer, indicating whether the data is
+ *				being transferred to the device, from the device, or
+ *				bidirectionally.
+ */
+struct mtk_scp_reserve_memblock {
+	unsigned int id;
+	phys_addr_t start_phys;
+	void *start_virt;
+	phys_addr_t start_dma;
+	unsigned int size;
+	enum dma_data_direction dma_dir;
+};
+
+/* Array of reserved memory blocks for various hardware components */
+static struct mtk_scp_reserve_memblock reserve_memblock[] = {
+	{
+		/*WPE CQ buffer for WPE HW usage*/
+		.id = WPE_MEM_C_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0xE1000,   /*900KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*WPE TDR buffer for tile driver usage*/
+		.id = WPE_MEM_T_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x196000,   /*1MB + 600KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*TRAW CQ buffer for TRAW driver usage*/
+		.id = TRAW_MEM_C_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x4C8000,   /*4MB + 800KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*TRAW TDR buffer for tile driver usage*/
+		.id = TRAW_MEM_T_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x1AC8000,   /*26MB + 800KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*DIP CQ buffer for TRAW HW usage*/
+		.id = DIP_MEM_C_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x5C8000,   /*5MB + 800KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*DIP TDR buffer for tile driver usage*/
+		.id = DIP_MEM_T_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x1FAF000,   /*31MB + 700KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*PQDIP CQ buffer for TRAW HW usage*/
+		.id = PQDIP_MEM_C_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x100000,   /*1MB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*PQDIP TDR buffer for tile driver usage*/
+		.id = PQDIP_MEM_T_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x170000,   /*1MB + 500KB*/
+		.dma_dir = DMA_TO_DEVICE,
+	},
+	{
+		/*GCE command buffer for GCE HW usage*/
+		.id = IMG_MEM_G_ID,
+		.start_phys = 0x0,
+		.start_virt = NULL,
+		.start_dma  = 0x0,
+		.size = 0x1800000,
+		.dma_dir = DMA_BIDIRECTIONAL,
+	},
+};
+
+static phys_addr_t imgsys_scp_get_reserve_mem_phys(enum img_mem_id id)
+{
+	if (id >= IMG_MEM_ID_COUNT) {
+		pr_err("[SCP] no reserve memory for %d", id);
+		return 0;
+	}
+	return reserve_memblock[id].start_phys;
+}
+
+static phys_addr_t imgsys_scp_get_reserve_mem_dma(enum img_mem_id id)
+{
+	if (id >= IMG_MEM_ID_COUNT) {
+		pr_err("[SCP] no reserve memory for %d", id);
+		return 0;
+	}
+	return reserve_memblock[id].start_dma;
+}
+
+void *imgsys_scp_get_reserve_mem_virt(enum img_mem_id id)
+{
+	if (id >= IMG_MEM_ID_COUNT)
+		return NULL;
+	else
+		return reserve_memblock[id].start_virt;
+}
+EXPORT_SYMBOL(imgsys_scp_get_reserve_mem_virt);
+
+unsigned int imgsys_scp_get_reserve_mem_size(enum img_mem_id id)
+{
+	if (id >= IMG_MEM_ID_COUNT) {
+		pr_err("[SCP] no reserve memory for %d", id);
+		return 0;
+	}
+	return reserve_memblock[id].size;
+}
+
+int imgsys_scp_alloc_reserve_mem(struct mtk_imgsys_dev *imgsys_dev)
+{
+	enum img_mem_id id;
+	unsigned int block_num;
+	void *ptr;
+	dma_addr_t addr;
+
+	block_num = ARRAY_SIZE(reserve_memblock);
+	for (id = 0; id < block_num; id++) {
+		ptr = dma_alloc_coherent(imgsys_dev->smem_dev,
+					 reserve_memblock[id].size,
+					 &addr, GFP_KERNEL);
+		if (!ptr)
+			return -ENOMEM;
+
+		reserve_memblock[id].start_virt = ptr;
+		reserve_memblock[id].start_phys = addr;
+		reserve_memblock[id].start_dma =
+			dma_map_resource(imgsys_dev->dev, addr,
+					 reserve_memblock[id].size,
+					 reserve_memblock[id].dma_dir,
+					 DMA_ATTR_SKIP_CPU_SYNC);
+		if (dma_mapping_error(imgsys_dev->dev,
+				      reserve_memblock[id].start_dma)) {
+			dev_err(imgsys_dev->dev, "failed to map scp iova\n");
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+int imgsys_scp_free_reserve_mem(struct mtk_imgsys_dev *imgsys_dev)
+{
+	enum img_mem_id id;
+
+	/* release reserved memory */
+	for (id = 0; id < IMG_MEM_ID_COUNT; id++) {
+		dma_unmap_resource(imgsys_dev->dev,
+				   reserve_memblock[id].start_dma,
+				   reserve_memblock[id].size,
+				   reserve_memblock[id].dma_dir,
+				   DMA_ATTR_SKIP_CPU_SYNC);
+		dma_free_coherent(imgsys_dev->smem_dev,
+				  reserve_memblock[id].size,
+				  reserve_memblock[id].start_virt,
+				  reserve_memblock[id].start_phys);
+
+		reserve_memblock[id].start_dma = 0x0;
+		reserve_memblock[id].start_virt = NULL;
+		reserve_memblock[id].start_phys = 0x0;
+	}
+
+	return 0;
+}
+
+int imgsys_scp_get_reserve_mem_info(struct img_init_info *info)
+{
+	if (!info) {
+		pr_err("%s:NULL info\n", __func__);
+		return -EINVAL;
+	}
+
+	/* WPE */
+	info->module_info[IMG_MODULE_WPE].c_wbuf =
+				imgsys_scp_get_reserve_mem_phys(WPE_MEM_C_ID);
+	info->module_info[IMG_MODULE_WPE].c_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(WPE_MEM_C_ID);
+	info->module_info[IMG_MODULE_WPE].c_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(WPE_MEM_C_ID);
+	info->module_info[IMG_MODULE_WPE].t_wbuf =
+				imgsys_scp_get_reserve_mem_phys(WPE_MEM_T_ID);
+	info->module_info[IMG_MODULE_WPE].t_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(WPE_MEM_T_ID);
+	info->module_info[IMG_MODULE_WPE].t_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(WPE_MEM_T_ID);
+
+	/* TRAW */
+	info->module_info[IMG_MODULE_TRAW].c_wbuf =
+				imgsys_scp_get_reserve_mem_phys(TRAW_MEM_C_ID);
+	info->module_info[IMG_MODULE_TRAW].c_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(TRAW_MEM_C_ID);
+	info->module_info[IMG_MODULE_TRAW].c_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(TRAW_MEM_C_ID);
+	info->module_info[IMG_MODULE_TRAW].t_wbuf =
+				imgsys_scp_get_reserve_mem_phys(TRAW_MEM_T_ID);
+	info->module_info[IMG_MODULE_TRAW].t_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(TRAW_MEM_T_ID);
+	info->module_info[IMG_MODULE_TRAW].t_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(TRAW_MEM_T_ID);
+
+	/* DIP */
+	info->module_info[IMG_MODULE_DIP].c_wbuf =
+				imgsys_scp_get_reserve_mem_phys(DIP_MEM_C_ID);
+	info->module_info[IMG_MODULE_DIP].c_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(DIP_MEM_C_ID);
+	info->module_info[IMG_MODULE_DIP].c_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(DIP_MEM_C_ID);
+	info->module_info[IMG_MODULE_DIP].t_wbuf =
+				imgsys_scp_get_reserve_mem_phys(DIP_MEM_T_ID);
+	info->module_info[IMG_MODULE_DIP].t_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(DIP_MEM_T_ID);
+	info->module_info[IMG_MODULE_DIP].t_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(DIP_MEM_T_ID);
+
+	/* PQDIP */
+	info->module_info[IMG_MODULE_PQDIP].c_wbuf =
+				imgsys_scp_get_reserve_mem_phys(PQDIP_MEM_C_ID);
+	info->module_info[IMG_MODULE_PQDIP].c_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(PQDIP_MEM_C_ID);
+	info->module_info[IMG_MODULE_PQDIP].c_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(PQDIP_MEM_C_ID);
+	info->module_info[IMG_MODULE_PQDIP].t_wbuf =
+				imgsys_scp_get_reserve_mem_phys(PQDIP_MEM_T_ID);
+	info->module_info[IMG_MODULE_PQDIP].t_wbuf_dma =
+				imgsys_scp_get_reserve_mem_dma(PQDIP_MEM_T_ID);
+	info->module_info[IMG_MODULE_PQDIP].t_wbuf_sz =
+				imgsys_scp_get_reserve_mem_size(PQDIP_MEM_T_ID);
+
+	/* GCE command */
+	info->g_wbuf = imgsys_scp_get_reserve_mem_phys(IMG_MEM_G_ID);
+	info->g_wbuf_sz = imgsys_scp_get_reserve_mem_size(IMG_MEM_G_ID);
+
+	return 0;
+}
+
+int imgsys_scp_init(struct mtk_imgsys_dev *imgsys_dev,
+		    scp_ipi_handler_t imgsys_scp_handler)
+{
+	int ret = 0;
+
+	ret = rproc_boot(imgsys_dev->rproc_handle);
+	if (ret) {
+		dev_err(imgsys_dev->dev,
+			"%s failed to rproc_boot\n", __func__);
+		return ret;
+	}
+
+	ret = scp_ipi_register(imgsys_dev->scp, SCP_IPI_IMGSYS_CMD,
+			       imgsys_scp_handler, imgsys_dev);
+	if (ret) {
+		dev_err(imgsys_dev->dev,
+			"%s failed to register IPI cmd\n", __func__);
+		return ret;
+	}
+
+	return ret;
+}
+
+void imgsys_scp_deinit(struct mtk_imgsys_dev *imgsys_dev)
+{
+	rproc_shutdown(imgsys_dev->rproc_handle);
+}
+
+int imgsys_scp_send(struct mtk_imgsys_dev *imgsys_dev,
+		    enum imgsys_ipi_id id, void *buf,
+		    unsigned int len, int req_fd,
+		    unsigned int wait)
+{
+	struct share_buf send_obj = { 0 };
+	int ret = 0;
+
+	dev_dbg(imgsys_dev->dev, "%s id:%d len %d\n",
+		__func__, id, len);
+
+	if (id < IPI_IMGSYS_INIT_ID || id >= IPI_MAX_ID ||
+	    len > sizeof(send_obj.share_data) || !buf) {
+		dev_info(imgsys_dev->dev,
+			 "%s failed to send scp message (len/sz(%d/%zu)\n",
+			 __func__, len, sizeof(send_obj.share_data));
+		return -EINVAL;
+	}
+
+	send_obj.len = len;
+	send_obj.id = id;
+	memcpy((void *)send_obj.share_data, buf, len);
+
+	send_obj.info.send.ipi = id;
+	send_obj.info.send.req = req_fd;
+	send_obj.info.send.ack = (wait ? 1 : 0);
+	send_obj.info.send.seq = 0;
+
+	ret = scp_ipi_send(imgsys_dev->scp, SCP_IPI_IMGSYS_CMD,
+			   (void *)&send_obj, sizeof(send_obj),
+			   wait ? msecs_to_jiffies(SCP_TIMEOUT_MS) : 0);
+	if (ret)
+		dev_err(imgsys_dev->dev,
+			"%s: send SCP(%d) failed %d\n", __func__, id, ret);
+
+	return 0;
+}
+
diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.h
new file mode 100644
index 000000000000..2082c4bdf96f
--- /dev/null
+++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-scp.h
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef MTK_IMGSYS_SCP_H
+#define MTK_IMGSYS_SCP_H
+
+#include <linux/remoteproc/mtk_scp.h>
+#include "mtk-img-ipi.h"
+#include "mtk_imgsys-dev.h"
+
+/* the size of share buffer between the kernel and SCP */
+#define SCP_SHARE_BUF_SIZE      576
+
+/**
+ * struct object_info - Represents information associated with a object,
+ * particularly in the context of inter-processor communication and media
+ * processing.
+ *
+ * @ipi: Specifies the IPI (Inter-Processor Interrupt) ID, using 5 bits.
+ * @ack: Indicates whether an acknowledgment is required, using 1 bit.
+ * @req: Holds the media request ID, using 10 bits.
+ * @seq: A sequence number, using 16 bits, for tracking the order of
+ *       objects or messages.
+ * @cmd: Combined command representation.
+ */
+struct object_info {
+	union {
+		struct send {
+			u32 ipi: 5;  /* IPI ID */
+			u32 ack: 1;  /* Acknowledgment flag */
+			u32 req: 10; /* Media request ID */
+			u32 seq: 16; /* Sequence number */
+		} __packed send;
+		u32 cmd; /* Combined command representation */
+	};
+} __packed;
+
+/**
+ * struct share_buf - DTCM (Data Tightly-Coupled Memory) buffer shared with
+ *                    AP and hardware components of IMGSYS
+ *
+ * @id:               IPI (Inter-Processor Interrupt) ID
+ * @len:              Length of the shared buffer
+ * @share_data:       Data contained in the shared buffer
+ * @info:             Information associated with the object
+ *
+ * This structure represents a DTCM buffer that is shared between the AP and
+ * the hardware components of the MediaTek Image System (IMGSYS). It includes
+ * the IPI ID, the length of the shared buffer, the actual buffer data, and
+ * additional object information.
+ */
+struct share_buf {
+	u32 id;                            /* IPI (Inter-Processor Interrupt) ID */
+	u32 len;                           /* Length of the shared buffer */
+	u8 share_data[SCP_SHARE_BUF_SIZE]; /* Data contained in the shared buffer */
+	struct object_info info;           /* Information object */
+};
+
+/**
+ * enum img_mem_id - Enumeration of image memory IDs
+ *
+ * @WPE_MEM_C_ID: Warping Engine (WPE) module command queue (CQ) buffer
+ * @WPE_MEM_T_ID: WPE module tile driver (TDR) buffer
+ * @TRAW_MEM_C_ID: Tile-Raw (TRAW) module CQ buffer
+ * @TRAW_MEM_T_ID: TRAW module TDR buffer
+ * @DIP_MEM_C_ID: Digital Image Processing (DIP) module CQ buffer
+ * @DIP_MEM_T_ID: DIP module TDR buffer
+ * @PQDIP_MEM_C_ID: Picture Quality image processing (PQDIP) CQ buffer
+ * @PQDIP_MEM_T_ID: PQDIP TDR buffer
+ * @IMG_MEM_G_ID: GCE command buffer
+ * @IMG_MEM_ID_COUNT: Total number of memory IDs
+ *
+ * This enumeration defines the various memory IDs used in the MediaTek
+ * image system. Each memory ID corresponds to a specific buffer used
+ * by different modules within the image system.
+ */
+enum img_mem_id {
+	WPE_MEM_C_ID,       /* WPE module CQ buffer */
+	WPE_MEM_T_ID,       /* WPE module TDR buffer */
+	TRAW_MEM_C_ID,      /* TRAW module CQ buffer */
+	TRAW_MEM_T_ID,      /* TRAW module TDR buffer */
+	DIP_MEM_C_ID,       /* DIP module CQ buffer */
+	DIP_MEM_T_ID,       /* DIP module TDR buffer */
+	PQDIP_MEM_C_ID,     /* PQDIP CQ buffer */
+	PQDIP_MEM_T_ID,     /* PQDIP TDR buffer */
+	IMG_MEM_G_ID,       /* GCE command buffer */
+	IMG_MEM_ID_COUNT,   /* Total number of memory IDs */
+};
+
+/**
+ * enum imgsys_ipi_id - Enumeration of IPI (Inter-Processor Interrupt) IDs
+ * @IPI_IMGSYS_INIT_ID: ID for initializing the image system
+ * @IPI_IMGSYS_FRAME_ID: ID for processing a frame
+ * @IPI_IMGSYS_DEQUE_DONE_ID: ID for indicating frame dequeuing is done
+ * @IPI_IMGSYS_DEINIT_ID: ID for deinitializing the image system
+ * @IPI_MAX_ID: Maximum ID value, used for boundary checking
+ */
+enum imgsys_ipi_id {
+	IPI_IMGSYS_INIT_ID = 0,	/* ID for initializing the image system */
+	IPI_IMGSYS_FRAME_ID,	/* ID for processing a frame */
+	IPI_IMGSYS_DEQUE_DONE_ID,	/* ID for dequeuing frame is done */
+	IPI_IMGSYS_DEINIT_ID,	/* ID for deinitializing the image system */
+	IPI_MAX_ID,	/* Maximum ID value*/
+};
+
+/**
+ * imgsys_scp_alloc_reserve_mem - allocate reserved memory for use by the
+ * kernel and the SCP (System Control Processor)
+ *
+ * @imgsys_dev:	Pointer to the imgsys platform device structure
+ *
+ **/
+int imgsys_scp_alloc_reserve_mem(struct mtk_imgsys_dev *imgsys_dev);
+
+/**
+ * imgsys_scp_free_reserve_mem - free reserved memory for use by the kernel and
+ * SCP
+ *
+ * @imgsys_dev:	Pointer to the imgsys platform device structure
+ *
+ **/
+int imgsys_scp_free_reserve_mem(struct mtk_imgsys_dev *imgsys_dev);
+
+/**
+ * imgsys_scp_get_reserve_mem_info - get the information about reserved memory
+ *
+ * @info: A pointer to an already allocated structure of type img_init_info,
+ * where this function will populate the reserved memory details.
+ *
+ **/
+int imgsys_scp_get_reserve_mem_info(struct img_init_info *info);
+
+/**
+ * imgsys_scp_get_reserve_mem_virt - get the virtual address of reserved memory
+ * by a particular memory ID
+ *
+ * @id:	The identifier of the reserved memory block
+ *
+ **/
+void *imgsys_scp_get_reserve_mem_virt(enum img_mem_id id);
+
+/**
+ * imgsys_scp_get_reserve_mem_size - get the size of reserved memory by a
+ * particular memory ID
+ *
+ * @id:	The identifier of the reserved memory block
+ *
+ **/
+unsigned int imgsys_scp_get_reserve_mem_size(enum img_mem_id id);
+
+/**
+ * imgsys_scp_init - start the SCP
+ *
+ * @imgsys_dev:	Pointer to the imgsys platform device structure
+ * @imgsys_scp_handler: Handler for SCP IPI
+ **/
+int imgsys_scp_init(struct mtk_imgsys_dev *imgsys_dev,
+		    scp_ipi_handler_t imgsys_scp_handler);
+
+/**
+ * imgsys_scp_deinit - stop the SCP
+ *
+ * @imgsys_dev:	Pointer to the imgsys platform device structure
+ *
+ **/
+void imgsys_scp_deinit(struct mtk_imgsys_dev *imgsys_dev);
+
+/**
+ * imgsys_scp_send - send data from AP to SCP
+ *
+ * @imgsys_dev:	Pointer to the imgsys platform device structure
+ * @id:	IPI ID
+ * @buf:the data buffer
+ * @len: the data buffer length
+ * @req_fd: the file descriptor of media request
+ * @wait: wait until ipi done or not
+ *
+ * This function is thread-safe. When this function returns,
+ * SCP has received the data and starts the processing.
+ * When the processing completes, IPI handler registered
+ * by scp_ipi_register will be called in interrupt context.
+ *
+ **/
+int imgsys_scp_send(struct mtk_imgsys_dev *imgsys_dev,
+		    enum imgsys_ipi_id id,
+		    void *buf,
+		    unsigned int len,
+		    int req_fd,
+		    unsigned int wait);
+
+#endif /* MTK_IMGSYS_SCP_H */
+
-- 
2.45.2




More information about the Linux-mediatek mailing list