From patchwork Sat May 24 11:49:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivia Wen X-Patchwork-Id: 892330 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7F811E2823; Sat, 24 May 2025 11:52:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087529; cv=none; b=Qqa+bNxj8OKuIu+gFqMi9Av6T3CsICriQ4HKrhrwuK4SZSWp8nCskuv0EvDySZnrZ4wMpMqDft2M3qbdNecMtNlRsQhfPqJl0PhFegMz4bXzrqPaHWtXh1fwjsPBF5WVj1G2PKF741aGd5Fr3Z+CWDRj38TGcVwkIlELJ/aTdQQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087529; c=relaxed/simple; bh=GEZhTsGk3ZVSazcgFBI82QwzzCMtVU89vuijeUdVM8Q=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lDLB8BjYvHBRJ/PtPEOIGJWzucpsJnbiSbUab0vLuESpJZbvSt+vR3IXEYCdE5WlWdWLBsiH37ksHrwt4wnfG8U83+dREnRJl47BDfvNwKU1vH/KlHWac/mW1CG4msVvzkIInZIvs1NF9KpSV9YyeOxIb52AaAB0PrPXmpDwtZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=tmW8rKlX; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="tmW8rKlX" X-UUID: 7a7ccd30389511f0813e4fe1310efc19-20250524 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=kq/RIYP37aN0j/sweXWMRbMR+f6iN6gPQkEajgOKD/s=; b=tmW8rKlXb2I/Q2tSIkY1dvhRbQFLqzS2L3f59H7gPZdl65InkE6WmCj4TvIj129K05nqIkWZ++a43uSS2ElUags+adp42XQgYy5A25+qtDKNjPXtyO9XAhDXo1ADVjVDMuLObwNjxU7wgi5e1F/T/YMsQFozXMr9PKBBlbfyal0=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:41116408-5831-4d70-bc34-cb7218a21f2d, IP:0, UR L:25,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION: release,TS:25 X-CID-META: VersionHash:0ef645f, CLOUDID:edfaad47-ee4f-4716-aedb-66601021a588, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:11|97|99|83|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OS I:0,OSA:0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 7a7ccd30389511f0813e4fe1310efc19-20250524 Received: from mtkmbs11n2.mediatek.inc [(172.21.101.187)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 541028794; Sat, 24 May 2025 19:51:50 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by MTKMBS09N2.mediatek.inc (172.21.101.94) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Sat, 24 May 2025 19:51:48 +0800 Received: from mtksitap99.mediatek.inc (10.233.130.16) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Sat, 24 May 2025 19:51:48 +0800 From: Olivia Wen To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , AngeloGioacchino Del Regno CC: Krzysztof Kozlowski , Conor Dooley , Olivia Wen , , , , , , , , Subject: [PATCH v1 02/10] dt-bindings: media: Add MT8188 ImgSys's LARB Date: Sat, 24 May 2025 19:49:54 +0800 Message-ID: <20250524115144.3832748-3-olivia.wen@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250524115144.3832748-1-olivia.wen@mediatek.com> References: <20250524115144.3832748-1-olivia.wen@mediatek.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N This patch adds support for the MT8188 Image System's Local Arbiter (LARB) in the device tree bindings. The LARB is a crucial component in MediaTek's ImgSys architecture, responsible for managing memory access and arbitration between various hardware modules. Signed-off-by: Olivia Wen --- .../bindings/media/mediatek,imgsys-larbs.yaml | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/mediatek,imgsys-larbs.yaml diff --git a/Documentation/devicetree/bindings/media/mediatek,imgsys-larbs.yaml b/Documentation/devicetree/bindings/media/mediatek,imgsys-larbs.yaml new file mode 100644 index 000000000000..d2966c64ddb6 --- /dev/null +++ b/Documentation/devicetree/bindings/media/mediatek,imgsys-larbs.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/mediatek,imgsys-larbs.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LARB Information for MediaTek Camera Image System Hardware + +maintainers: + - Olivia Wen + +description: + Detailed configuration for MediaTek Camera Image System's Local Arbiter + (LARB) hardware integration. + +properties: + compatible: + enum: + - mediatek,mt8188-imgsys-larbs + + iommus: + minItems: 1 + maxItems: 30 + + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + +required: + - compatible + - iommus + +additionalProperties: false + +examples: + - | + #include + + imgsys-l11b { + compatible = "mediatek,mt8188-imgsys-larb"; + #address-cells = <2>; + #size-cells = <2>; + iommus = <&vpp_iommu M4U_PORT_L11B_WPE_RDMA_0>, + <&vpp_iommu M4U_PORT_L11B_WPE_RDMA_1>, + <&vpp_iommu M4U_PORT_L11B_WPE_RDMA_4P_0>, + <&vpp_iommu M4U_PORT_L11B_WPE_RDMA_4P_1>, + <&vpp_iommu M4U_PORT_L11B_WPE_CQ0>, + <&vpp_iommu M4U_PORT_L11B_WPE_CQ1>, + <&vpp_iommu M4U_PORT_L11B_PIMGI_P1>, + <&vpp_iommu M4U_PORT_L11B_PIMGBI_P1>, + <&vpp_iommu M4U_PORT_L11B_PIMGCI_P1>, + <&vpp_iommu M4U_PORT_L11B_IMGI_T1_C>, + <&vpp_iommu M4U_PORT_L11B_IMGBI_T1_C>, + <&vpp_iommu M4U_PORT_L11B_IMGCI_T1_C>, + <&vpp_iommu M4U_PORT_L11B_SMTI_T1_C>, + <&vpp_iommu M4U_PORT_L11B_SMTI_T4_C>, + <&vpp_iommu M4U_PORT_L11B_SMTI_T6_C>, + <&vpp_iommu M4U_PORT_L11B_YUVO_T1_C>, + <&vpp_iommu M4U_PORT_L11B_YUVBO_T1_C>, + <&vpp_iommu M4U_PORT_L11B_YUVCO_T1_C>, + <&vpp_iommu M4U_PORT_L11B_WPE_WDMA_0>, + <&vpp_iommu M4U_PORT_L11B_WPE_WDMA_4P_0>, + <&vpp_iommu M4U_PORT_L11B_WROT_P1>, + <&vpp_iommu M4U_PORT_L11B_TCCSO_P1>, + <&vpp_iommu M4U_PORT_L11B_TCCSI_P1>, + <&vpp_iommu M4U_PORT_L11B_TIMGO_T1_C>, + <&vpp_iommu M4U_PORT_L11B_YUVO_T2_C>, + <&vpp_iommu M4U_PORT_L11B_YUVO_T5_C>, + <&vpp_iommu M4U_PORT_L11B_SMTO_T1_C>, + <&vpp_iommu M4U_PORT_L11B_SMTO_T4_C>, + <&vpp_iommu M4U_PORT_L11B_SMTO_T6_C>, + <&vpp_iommu M4U_PORT_L11B_DBGO_T1_C>; + }; From patchwork Sat May 24 11:49:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivia Wen X-Patchwork-Id: 892327 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 365471E1DEC; Sat, 24 May 2025 11:52:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087535; cv=none; b=nw4TL1OCzzimEIg/6TPGZPHHZRPiKGTYCG2OLYoCyrsIoeEo+Kb+9DKmq10uH+c2RdZsXoX1qDA0TG1/uY/R7BOmkgdOCMtTvY3nsUe9zwnpenhdUw6vlbvz1WL7C9xfnlTMjzdvpRYeWXll9ic/oBUFekhYc0HIWXh+9TyqV6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087535; c=relaxed/simple; bh=rT7+t36FaU43VaYYp1bRRg0M/8RgU1q0kiaV7Kg9TW4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=T0Qt9zPPYPoN2cKdFxofigsOuFCQIorwYBiAXOqunldCp8GquXegP6Nt6fvCxYuecZOtiQda0ty2n4SVboy1a0xQDjTbpRUKHTwCZLoNnE97u5rFKv4o4lbVVvq+K5MQatycZuSjz+Jy7TuYZ2NAIv7nimW/myDa3lh6Xt+FU0U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=tc62H3NB; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="tc62H3NB" X-UUID: 7afa9a08389511f0813e4fe1310efc19-20250524 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=Fi3ah/DIL0rzNwXJvtJxpsHjd15GLkx21LToIH9QqfM=; b=tc62H3NBUsWxtWVSq2LJRJCnrJO5rKEPhAdGERHGKmg5kqkSdoXDwygd3vs+LH8kmQaZJ0P011qhMV+S6tZB3jCG8We9IxSGU3aC3Vsg9ejDGgfgOH2ph3Em3M5k+N1j0b1nKRzR8aypcZb7fwi7rw0eRZqMIVIS4GoksI5wjqA=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:3b67a9ac-42a1-4352-ad71-e29c7557bbbc, IP:0, UR L:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:-25 X-CID-META: VersionHash:0ef645f, CLOUDID:52bb3bf1-2ded-45ed-94e2-b3e9fa87100d, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:1,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 2,OSH X-CID-BAS: 2,OSH,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 7afa9a08389511f0813e4fe1310efc19-20250524 Received: from mtkmbs14n1.mediatek.inc [(172.21.101.75)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1959910938; Sat, 24 May 2025 19:51:51 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs11n2.mediatek.inc (172.21.101.187) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Sat, 24 May 2025 19:51:48 +0800 Received: from mtksitap99.mediatek.inc (10.233.130.16) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Sat, 24 May 2025 19:51:48 +0800 From: Olivia Wen To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , AngeloGioacchino Del Regno CC: Krzysztof Kozlowski , Conor Dooley , Olivia Wen , , , , , , , , Subject: [PATCH v1 04/10] media: mediatek: isp: Add V4L2 flow support for ImgSys driver Date: Sat, 24 May 2025 19:49:56 +0800 Message-ID: <20250524115144.3832748-5-olivia.wen@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250524115144.3832748-1-olivia.wen@mediatek.com> References: <20250524115144.3832748-1-olivia.wen@mediatek.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N 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 --- 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 --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 + * + */ + +#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 + * + */ + +#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 + * + */ + +#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 + * + */ + +#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 + * + */ + +#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 + +/** + * 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 + * + */ + +#include "linux/list.h" +#include +#include +#include +#include +#include +#include +#include +#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 + * + */ + +#ifndef _MTK_IMGSYS_DEV_H_ +#define _MTK_IMGSYS_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#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 + * + */ + +#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 + * Holmes Chiou + * + */ + +#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 + * Holmes Chiou + * + */ + +#ifndef _MTK_IMGSYS_OF_H_ +#define _MTK_IMGSYS_OF_H_ + +#include +#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 + * + */ + +#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 + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 "); +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 + * + */ +#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 + * + */ +#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 From patchwork Sat May 24 11:49:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivia Wen X-Patchwork-Id: 892332 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34E4719CC0E; Sat, 24 May 2025 11:52:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087527; cv=none; b=Xxx9jXmYcoZUAPpJmLCp/BboE86w5/5PEezpehiO2lQYNTPWCPMUcrHoxM+wSzoDCwjSTF1aZyGCmwnPo4XmTCdkvRvXEJxHyVYEZ5X681pWjAl6hbSgtvwLdO5DPIOyiuTfONxXFcHIk1hvJmMKPfh3BkZDDnKIXEz35B+nJqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087527; c=relaxed/simple; bh=+DMSQKQzbZb6DFTAwlhUcTjDRVlDQ+q1ruffAhWOvvg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=M3r/UQLlNZP8MFWldPhaKKQwXr8hf0RlxIvWIme9haqf1xsg6q1OklkNTSJjjA27dCLkjgDY/8C+ilK6spxjF3wHek44BANJD7gFVf2/P0M6/fwcDy8/YY5gdOs6YAJ7pVMN2l/WsDfqH/7AMtg55HCHryPvQvSO0xutGoYEPqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=cgk6C7dl; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="cgk6C7dl" X-UUID: 7acc551c389511f0813e4fe1310efc19-20250524 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=5HWVT/dTylYSt+t4LkzZWm+16LjaTBYm2xU/nM2FdEE=; b=cgk6C7dlTjJbdR4T/KZticOcXQBdfGTMNS+HAlTPb8HcA8YSODNByU0lazA/fi0SsTK1R+sJFKHSuvFWTjSGnK5Xz4C/jbmf5jAYqEwciXI/V6r27Gk4N2HvdTkwcl/TMZXbgfQGnOwYqR01DbI8dOE5A0QwXtJwbcQqAQSHyBI=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:c2f17fa4-96b2-44c0-b784-6991b35ea173, IP:0, UR L:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:-25 X-CID-META: VersionHash:0ef645f, CLOUDID:27b91059-eac4-4b21-88a4-d582445d304a, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 7acc551c389511f0813e4fe1310efc19-20250524 Received: from mtkmbs09n2.mediatek.inc [(172.21.101.94)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1131495485; Sat, 24 May 2025 19:51:50 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs10n2.mediatek.inc (172.21.101.183) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Sat, 24 May 2025 19:51:49 +0800 Received: from mtksitap99.mediatek.inc (10.233.130.16) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Sat, 24 May 2025 19:51:48 +0800 From: Olivia Wen To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , AngeloGioacchino Del Regno CC: Krzysztof Kozlowski , Conor Dooley , Olivia Wen , , , , , , , , Subject: [PATCH v1 05/10] media: mediatek: isp: Add the Imgsys LARBs device Date: Sat, 24 May 2025 19:49:57 +0800 Message-ID: <20250524115144.3832748-6-olivia.wen@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250524115144.3832748-1-olivia.wen@mediatek.com> References: <20250524115144.3832748-1-olivia.wen@mediatek.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N The ImgSys driver is implemented as a series of patches, with this patch focusing on the Imgsys LARBs device. This patch adds an independent device driver for the ImgSys Local Arbiter (LARB) devices. The addition is necessary because the IOMMU (Input/Output Memory Management Unit) cannot support multiple LARBs within a single device node. Signed-off-by: Olivia Wen --- .../isp/isp_7x/imgsys/mtk_imgsys-v4l2.c | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) 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 index cfd65858c751..919c69493bbc 100644 --- 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 @@ -28,6 +28,58 @@ #define IMGSYS_MAX_BUFFERS 256 #define IMGSYS_SUSPEND_TIME 3000 /* ms */ +struct mtk_imgsys_larb_device { + struct device *dev; + struct mtk_imgsys_dev *imgsys_dev; +}; + +static int mtk_imgsys_larb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mtk_imgsys_larb_device *larb_dev; + + larb_dev = devm_kzalloc(dev, sizeof(*dev), GFP_KERNEL); + if (!larb_dev) + return -ENOMEM; + + if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34))) + dev_err(dev, "No suitable DMA available\n"); + + if (!dev->dma_parms) { + dev->dma_parms = + devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL); + if (!dev->dma_parms) + return -ENOMEM; + } + if (pdev->dev.dma_parms) + dma_set_max_seg_size(dev, UINT_MAX); + + pm_runtime_enable(dev); + + return 0; +} + +static void mtk_imgsys_larb_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + pm_runtime_disable(dev); +} + +static const struct of_device_id mtk_imgsys_larb_match[] = { + {.compatible = "mediatek,mt8188-imgsys-larb",}, + {}, +}; + +static struct platform_driver mtk_imgsys_larb_driver = { + .probe = mtk_imgsys_larb_probe, + .remove = mtk_imgsys_larb_remove, + .driver = { + .name = "mtk-imgsys-larb", + .of_match_table = of_match_ptr(mtk_imgsys_larb_match), + }, +}; + static int mtk_imgsys_sd_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, struct v4l2_event_subscription *sub) @@ -1537,8 +1589,16 @@ static int mtk_imgsys_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); + ret = platform_driver_register(&mtk_imgsys_larb_driver); + if (ret) { + dev_info(imgsys_dev->dev, "register mtk_imgsys_larb_driver fail\n"); + goto err_release_deinit_v4l2; + } + return 0; +err_release_deinit_v4l2: + mtk_imgsys_dev_v4l2_release(imgsys_dev); err_free_larb_alloc: devm_kfree(&pdev->dev, imgsys_dev->larbs); err_free_dev_alloc: @@ -1551,6 +1611,7 @@ 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); + platform_driver_unregister(&mtk_imgsys_larb_driver); mtk_imgsys_dev_v4l2_release(imgsys_dev); devm_kfree(&pdev->dev, imgsys_dev->larbs); devm_kfree(&pdev->dev, imgsys_dev); From patchwork Sat May 24 11:49:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivia Wen X-Patchwork-Id: 892328 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E6F81E492D; Sat, 24 May 2025 11:52:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087532; cv=none; b=ni6wjXQh9YOOpaqFDrpSQI8uGWY2f3OPHS0JF+Ft9tSjzB4Mq7QH7MEBBDs/R9iIBfydnHEYqpRQYSESUzjz41EIOYOaXfjDevbMeFmHV5ZZNWHlpnw3AYjZNPpgABiWv8Xh2VdOjcSc4hS7rb3YRtmGiIeTMVf4fl5nmEJu5UA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087532; c=relaxed/simple; bh=PZz9yJZAtNqsvo24fcm8RlWB0NCSzRoZfGdd3VJGndI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aUVIeYxxkP+LMW+aUdWlCD2qTFrdD6U2IFbPDZpz0SZew9u6nBBqMwIrAt4rO5tUk1xhocZvb5QtBnlylGmL9jQmOBUwlkyZ1+KT+LC2PfQ0hin+IBjzWQbhSTIatfm2Xy/EP3CflZyhmCqmXQl4rE5gfaeE+JNgUou6DIuhwAg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=ldwSNUZm; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="ldwSNUZm" X-UUID: 7af00a98389511f082f7f7ac98dee637-20250524 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=CqekI3T4vQaqvZMK31hDFZQdEJvFlZRiVAD4u8JmKVI=; b=ldwSNUZmf7YrI3sCS6zbyb8lvzR9ADCpDyP1yAE9XU903iWLipKXW1XyZHaziFqUG0v+p+D08dcVvjy+TsvY7u6qqNx5fJybrDnw/CBzn+m4jpnmhpT2BDzCPLtArnG5mRRE3F2LRMKNZ4FHu94q0n+xUWQkUcLOcXyyMzKF4rA=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:d37ce0b4-a2b1-4f7d-858a-97188a67faf2, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:5dbb3bf1-2ded-45ed-94e2-b3e9fa87100d, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULS X-UUID: 7af00a98389511f082f7f7ac98dee637-20250524 Received: from mtkmbs09n1.mediatek.inc [(172.21.101.35)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 305957609; Sat, 24 May 2025 19:51:51 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Sat, 24 May 2025 19:51:48 +0800 Received: from mtksitap99.mediatek.inc (10.233.130.16) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Sat, 24 May 2025 19:51:48 +0800 From: Olivia Wen To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , AngeloGioacchino Del Regno CC: Krzysztof Kozlowski , Conor Dooley , Olivia Wen , , , , , , , , Subject: [PATCH v1 06/10] media: mediatek: isp: Add module operations structure for ImgSys Date: Sat, 24 May 2025 19:49:58 +0800 Message-ID: <20250524115144.3832748-7-olivia.wen@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250524115144.3832748-1-olivia.wen@mediatek.com> References: <20250524115144.3832748-1-olivia.wen@mediatek.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N The ImgSys driver is implemented as a series of patches, with this patch focusing on a set of operations for specific modules. The ImgSys architecture includes various modules such as WPE (Warping Engine), TRAW (Tile-Raw), DIP (Digital Image Processing), PQDIP (Picture Quality Digital Image Processing), and ME (Motion Estimation). Each module requires specific operations for initialization and deinitialization to ensure proper setup and cleanup. Signed-off-by: Olivia Wen --- .../mediatek/isp/isp_7x/imgsys/Makefile | 8 + .../isp_7x/imgsys/modules/mtk_imgsys-dip.c | 115 +++++++++++ .../isp_7x/imgsys/modules/mtk_imgsys-dip.h | 18 ++ .../isp_7x/imgsys/modules/mtk_imgsys-pqdip.c | 113 +++++++++++ .../isp_7x/imgsys/modules/mtk_imgsys-pqdip.h | 17 ++ .../isp_7x/imgsys/modules/mtk_imgsys-traw.c | 65 +++++++ .../isp_7x/imgsys/modules/mtk_imgsys-traw.h | 17 ++ .../isp_7x/imgsys/modules/mtk_imgsys-wpe.c | 116 +++++++++++ .../isp_7x/imgsys/modules/mtk_imgsys-wpe.h | 17 ++ .../isp/isp_7x/imgsys/mtk_imgsys-dev.h | 12 +- .../isp_7x/imgsys/mtk_imgsys-module_common.h | 82 ++++++++ .../isp_7x/imgsys/mtk_imgsys-module_main.c | 183 ++++++++++++++++++ .../isp_7x/imgsys/mtk_imgsys-module_main.h | 17 ++ .../isp/isp_7x/imgsys/mtk_imgsys-module_ops.h | 26 +++ .../isp/isp_7x/imgsys/mtk_imgsys-of.h | 3 + .../isp/isp_7x/imgsys/mtk_imgsys-sys.c | 73 ++++++- .../isp/isp_7x/imgsys/mtk_imgsys-v4l2.c | 45 ++++- 17 files changed, 923 insertions(+), 4 deletions(-) create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.c create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.h create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.c create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.h create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.c create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.h create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.c create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.h create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.c create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.h diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile index 571d0ae000eb..26c8c1d39750 100644 --- a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile @@ -2,10 +2,18 @@ # mtk_imgsys_util-objs := \ +mtk_imgsys-module_main.o \ mtk_imgsys-of.o \ mtk_imgsys-formats.o \ mtk_imgsys-dev.o \ mtk_imgsys-sys.o \ mtk_imgsys-v4l2.o +mtk_imgsys_hw_isp-objs := \ +modules/mtk_imgsys-dip.o \ +modules/mtk_imgsys-traw.o \ +modules/mtk_imgsys-pqdip.o \ +modules/mtk_imgsys-wpe.o + obj-$(CONFIG_VIDEO_MTK_ISP_71_IMGSYS) += mtk_imgsys_util.o +obj-$(CONFIG_VIDEO_MTK_ISP_71_IMGSYS) += mtk_imgsys_hw_isp.o diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.c new file mode 100644 index 000000000000..1cc1f3e87e8b --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Frederic Chen + * Holmes Chiou + * + */ + +#include +#include +#include "../mtk_imgsys-module_common.h" +#include "mtk_imgsys-dip.h" + +/******************************************************************** + * Global Define + ********************************************************************/ +#define DIPCTL_D1A_DIPCTL_INT1_EN 0x094 +#define DIPCTL_D1A_DIPCTL_INT2_EN 0x0A0 +#define DIPCTL_D1A_DIPCTL_INT3_EN 0x0AC +#define DIPCTL_D1A_DIPCTL_CQ_INT1_EN 0x0C4 +#define DIPCTL_D1A_DIPCTL_CQ_INT2_EN 0x0D0 +#define DIPCTL_D1A_DIPCTL_CQ_INT3_EN 0x0DC + +#define DIPCQ_D1A_DIPCQ_CQ_THR0_CTL 0x208 +#define DIPCQ_D1A_DIPCQ_CQ_THR1_CTL 0x218 +#define DIPCQ_D1A_DIPCQ_CQ_THR2_CTL 0x228 +#define DIPCQ_D1A_DIPCQ_CQ_THR3_CTL 0x238 +#define DIPCQ_D1A_DIPCQ_CQ_THR4_CTL 0x248 +#define DIPCQ_D1A_DIPCQ_CQ_THR5_CTL 0x258 +#define DIPCQ_D1A_DIPCQ_CQ_THR6_CTL 0x268 +#define DIPCQ_D1A_DIPCQ_CQ_THR7_CTL 0x278 +#define DIPCQ_D1A_DIPCQ_CQ_THR8_CTL 0x288 +#define DIPCQ_D1A_DIPCQ_CQ_THR9_CTL 0x298 +#define DIPCQ_D1A_DIPCQ_CQ_THR10_CTL 0x2A8 +#define DIPCQ_D1A_DIPCQ_CQ_THR11_CTL 0x2B8 +#define DIPCQ_D1A_DIPCQ_CQ_THR12_CTL 0x2C8 +#define DIPCQ_D1A_DIPCQ_CQ_THR13_CTL 0x2D8 +#define DIPCQ_D1A_DIPCQ_CQ_THR14_CTL 0x2E8 +#define DIPCQ_D1A_DIPCQ_CQ_THR15_CTL 0x2F8 +#define DIPCQ_D1A_DIPCQ_CQ_THR16_CTL 0x308 +#define DIPCQ_D1A_DIPCQ_CQ_THR17_CTL 0x318 +#define DIPCQ_D1A_DIPCQ_CQ_THR18_CTL 0x328 + +#define DIP_INIT_ARRAY_COUNT ARRAY_SIZE(mtk_imgsys_dip_init_ary) + +/******************************************************************** + * Global Variable + ********************************************************************/ +static const struct mtk_imgsys_init_array mtk_imgsys_dip_init_ary[] = { + { DIPCTL_D1A_DIPCTL_INT1_EN, 0x80000000 }, + { DIPCTL_D1A_DIPCTL_INT2_EN, 0x0 }, + { DIPCTL_D1A_DIPCTL_INT3_EN, 0x0 }, + { DIPCTL_D1A_DIPCTL_CQ_INT1_EN, 0x0 }, + { DIPCTL_D1A_DIPCTL_CQ_INT2_EN, 0x0 }, + { DIPCTL_D1A_DIPCTL_CQ_INT3_EN, 0x0 }, + { DIPCQ_D1A_DIPCQ_CQ_THR0_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR1_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR2_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR3_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR4_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR5_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR6_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR7_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR8_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR9_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR10_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR11_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR12_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR13_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR14_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR15_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR16_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR17_CTL, CQ_THRX_CTL }, + { DIPCQ_D1A_DIPCQ_CQ_THR18_CTL, CQ_THRX_CTL }, +}; + +static void __iomem *dip_reg_base[MTK_IMGSYS_DIP_HW_SET]; + +/******************************************************************** + * Functions + ********************************************************************/ +void imgsys_dip_init(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int i, hw_id, hw_idx; + void __iomem *offset = NULL; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_DIP_HW_SET; hw_idx++) { + hw_id = IMGSYS_REG_DIP1 + hw_idx; + dip_reg_base[hw_idx] = of_iomap(imgsys_dev->dev->of_node, hw_id); + if (!dip_reg_base[hw_idx]) { + dev_info(imgsys_dev->dev, + "%s: error: unable to iomap dip_%d registers, devnode(%s).\n", + __func__, hw_id, imgsys_dev->dev->of_node->name); + continue; + } + + for (i = 0 ; i < DIP_INIT_ARRAY_COUNT; i++) { + offset = dip_reg_base[hw_idx] + mtk_imgsys_dip_init_ary[i].offset; + writel(mtk_imgsys_dip_init_ary[i].value, offset); + } + } +} +EXPORT_SYMBOL_GPL(imgsys_dip_init); + +void imgsys_dip_uninit(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int hw_idx; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_DIP_HW_SET; hw_idx++) { + iounmap(dip_reg_base[hw_idx]); + dip_reg_base[hw_idx] = NULL; + } +} +EXPORT_SYMBOL_GPL(imgsys_dip_uninit); diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.h new file mode 100644 index 000000000000..22b4a7c3616d --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-dip.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Frederic Chen + * + */ + +#ifndef _MTK_DIP_DIP_H_ +#define _MTK_DIP_DIP_H_ + +#include "../mtk_imgsys-dev.h" + +void imgsys_dip_init(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_dip_uninit(struct mtk_imgsys_dev *imgsys_dev); + +#endif /* _MTK_DIP_DIP_H_ */ + diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.c new file mode 100644 index 000000000000..d1d3507555d9 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * + * Author: Daniel Huang + * + */ + +#include +#include +#include "../mtk_imgsys-module_common.h" +#include "mtk_imgsys-pqdip.h" + +/******************************************************************** + * Global Define + ********************************************************************/ +#define PQDIPCTL_P1A_REG_PQDIPCTL_INT1_EN 0x0050 +#define PQDIPCTL_P1A_REG_PQDIPCTL_INT2_EN 0x0060 +#define PQDIPCTL_P1A_REG_PQDIPCTL_CQ_INT1_EN 0x0070 +#define PQDIPCTL_P1A_REG_PQDIPCTL_CQ_INT2_EN 0x0080 +#define PQDIPCTL_P1A_REG_PQDIPCTL_CQ_INT3_EN 0x0090 + +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR0_CTL 0x0208 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR1_CTL 0x0218 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR2_CTL 0x0228 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR3_CTL 0x0238 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR4_CTL 0x0248 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR5_CTL 0x0258 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR6_CTL 0x0268 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR7_CTL 0x0278 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR8_CTL 0x0288 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR9_CTL 0x0298 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR10_CTL 0x02A8 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR11_CTL 0x02B8 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR12_CTL 0x02C8 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR13_CTL 0x02D8 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR14_CTL 0x02E8 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR15_CTL 0x02F8 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR16_CTL 0x0308 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR17_CTL 0x0318 +#define DIPCQ_P1A_REG_DIPCQ_CQ_THR18_CTL 0x0328 + +#define PQDIP_INIT_ARRAY_COUNT ARRAY_SIZE(mtk_imgsys_pqdip_init_ary) + +/******************************************************************** + * Global Variable + ********************************************************************/ +static const struct mtk_imgsys_init_array mtk_imgsys_pqdip_init_ary[] = { + { PQDIPCTL_P1A_REG_PQDIPCTL_INT1_EN, 0x80000000 }, + { PQDIPCTL_P1A_REG_PQDIPCTL_INT2_EN, 0x0 }, + { PQDIPCTL_P1A_REG_PQDIPCTL_CQ_INT1_EN, 0x0 }, + { PQDIPCTL_P1A_REG_PQDIPCTL_CQ_INT2_EN, 0x0 }, + { PQDIPCTL_P1A_REG_PQDIPCTL_CQ_INT3_EN, 0x0 }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR0_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR1_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR2_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR3_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR4_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR5_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR6_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR7_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR8_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR9_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR10_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR11_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR12_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR13_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR14_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR15_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR16_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR17_CTL, CQ_THRX_CTL }, + { DIPCQ_P1A_REG_DIPCQ_CQ_THR18_CTL, CQ_THRX_CTL }, +}; + +static void __iomem *pqdip_reg_base[MTK_IMGSYS_PQDIP_HW_SET]; + +/******************************************************************** + * Functions + ********************************************************************/ +void imgsys_pqdip_init(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int i, hw_id, hw_idx; + void __iomem *offset = NULL; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_PQDIP_HW_SET; hw_idx++) { + hw_id = IMGSYS_REG_PQDIP1 + hw_idx; + pqdip_reg_base[hw_idx] = of_iomap(imgsys_dev->dev->of_node, hw_id); + if (!pqdip_reg_base[hw_idx]) { + dev_info(imgsys_dev->dev, + "%s: error: unable to iomap pqdip_%d registers, devnode(%s).\n", + __func__, hw_id, imgsys_dev->dev->of_node->name); + continue; + } + + for (i = 0 ; i < PQDIP_INIT_ARRAY_COUNT; i++) { + offset = pqdip_reg_base[hw_idx] + mtk_imgsys_pqdip_init_ary[i].offset; + writel(mtk_imgsys_pqdip_init_ary[i].value, offset); + } + } +} +EXPORT_SYMBOL_GPL(imgsys_pqdip_init); + +void imgsys_pqdip_uninit(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int hw_idx; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_PQDIP_HW_SET; hw_idx++) { + iounmap(pqdip_reg_base[hw_idx]); + pqdip_reg_base[hw_idx] = NULL; + } +} +EXPORT_SYMBOL_GPL(imgsys_pqdip_uninit); + diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.h new file mode 100644 index 000000000000..00f93d536181 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-pqdip.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + * + * Author: Daniel Huang + * + */ + +#ifndef _MTK_IMGSYS_PQDIP_H_ +#define _MTK_IMGSYS_PQDIP_H_ + +#include "../mtk_imgsys-dev.h" + +void imgsys_pqdip_init(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_pqdip_uninit(struct mtk_imgsys_dev *imgsys_dev); + +#endif /* _MTK_IMGSYS_PQDIP_H_ */ diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.c new file mode 100644 index 000000000000..292f0ad09c46 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * + * Author: Shih-Fang Chuang + * + */ + +#include +#include +#include "../mtk_imgsys-module_common.h" +#include "mtk_imgsys-traw.h" + +/******************************************************************** + * Global Define + ********************************************************************/ +#define TRAWCTL_INT1_EN 0x00A0 + +#define TRAW_INIT_ARRAY_COUNT ARRAY_SIZE(mtk_imgsys_traw_init_ary) + +/******************************************************************** + * Global Variable + ********************************************************************/ +static const struct mtk_imgsys_init_array mtk_imgsys_traw_init_ary[] = { + { TRAWCTL_INT1_EN, 0x80000000 }, +}; + +static void __iomem *traw_reg_base[MTK_IMGSYS_TRAW_HW_SET]; + +/******************************************************************** + * Functions + ********************************************************************/ +void imgsys_traw_init(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int i, hw_id, hw_idx; + void __iomem *offset = NULL; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_TRAW_HW_SET; hw_idx++) { + hw_id = IMGSYS_REG_TRAW1 + hw_idx; + traw_reg_base[hw_idx] = of_iomap(imgsys_dev->dev->of_node, hw_id); + if (!traw_reg_base[hw_idx]) { + dev_info(imgsys_dev->dev, + "%s: error: unable to iomap traw_%d registers, devnode(%s).\n", + __func__, hw_id, imgsys_dev->dev->of_node->name); + continue; + } + + for (i = 0 ; i < TRAW_INIT_ARRAY_COUNT; i++) { + offset = traw_reg_base[hw_idx] + mtk_imgsys_traw_init_ary[i].offset; + writel(mtk_imgsys_traw_init_ary[i].value, offset); + } + } +} +EXPORT_SYMBOL_GPL(imgsys_traw_init); + +void imgsys_traw_uninit(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int hw_idx; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_TRAW_HW_SET; hw_idx++) { + iounmap(traw_reg_base[hw_idx]); + traw_reg_base[hw_idx] = NULL; + } +} +EXPORT_SYMBOL_GPL(imgsys_traw_uninit); diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.h new file mode 100644 index 000000000000..f3727216b58c --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-traw.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + * + * Author: Shih-fang Chuang + * + */ + +#ifndef _MTK_IMGSYS_TRAW_H_ +#define _MTK_IMGSYS_TRAW_H_ + +#include "../mtk_imgsys-dev.h" + +void imgsys_traw_init(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_traw_uninit(struct mtk_imgsys_dev *imgsys_dev); + +#endif /* _MTK_IMGSYS_TRAW_H_ */ diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.c new file mode 100644 index 000000000000..b19d61529b80 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * + * Author: Floria Huang + * + */ + +#include +#include +#include "../mtk_imgsys-module_common.h" +#include "mtk_imgsys-wpe.h" + +/******************************************************************** + * Global Define + ********************************************************************/ +/* Define register offsets */ +#define WPE_TOP_CTL_INT_EN_OFFSET 0x0018 +#define WPE_TOP_CTL_INT_STATUSX_OFFSET 0x0024 +#define WPE_TOP_CQ_IRQ_EN_OFFSET 0x00D4 +#define WPE_TOP_CQ_IRQ_STX_OFFSET 0x00DC +#define WPE_TOP_CQ_IRQ_EN2_OFFSET 0x00E0 +#define WPE_TOP_CQ_IRQ_STX2_OFFSET 0x00E8 +#define WPE_TOP_CQ_IRQ_EN3_OFFSET 0x00EC +#define WPE_TOP_CQ_IRQ_STX3_OFFSET 0x00F4 +#define WPE_CACHE_RWCTL_CTL_OFFSET 0x0204 +#define WPE_DMA_DMA_ERR_CTRL_OFFSET 0x03D4 +#define DIPCQ_W1A_DIPCQ_CQ_THR0_CTL_OFFSET 0x0B08 +#define DIPCQ_W1A_DIPCQ_CQ_THR1_CTL_OFFSET 0x0B18 +#define DIPCQ_W1A_DIPCQ_CQ_THR2_CTL_OFFSET 0x0B28 +#define DIPCQ_W1A_DIPCQ_CQ_THR3_CTL_OFFSET 0x0B38 +#define DIPCQ_W1A_DIPCQ_CQ_THR4_CTL_OFFSET 0x0B48 +#define DIPCQ_W1A_DIPCQ_CQ_THR5_CTL_OFFSET 0x0B58 +#define DIPCQ_W1A_DIPCQ_CQ_THR6_CTL_OFFSET 0x0B68 +#define DIPCQ_W1A_DIPCQ_CQ_THR7_CTL_OFFSET 0x0B78 +#define DIPCQ_W1A_DIPCQ_CQ_THR8_CTL_OFFSET 0x0B88 +#define DIPCQ_W1A_DIPCQ_CQ_THR9_CTL_OFFSET 0x0B98 +#define DIPCQ_W1A_DIPCQ_CQ_THR10_CTL_OFFSET 0x0BA8 +#define DIPCQ_W1A_DIPCQ_CQ_THR11_CTL_OFFSET 0x0BB8 +#define DIPCQ_W1A_DIPCQ_CQ_THR12_CTL_OFFSET 0x0BC8 +#define DIPCQ_W1A_DIPCQ_CQ_THR13_CTL_OFFSET 0x0BD8 +#define DIPCQ_W1A_DIPCQ_CQ_THR14_CTL_OFFSET 0x0BE8 + +#define WPE_INIT_ARRAY_COUNT ARRAY_SIZE(mtk_imgsys_wpe_init_ary) +/******************************************************************** + * Global Variable + ********************************************************************/ +static const struct mtk_imgsys_init_array mtk_imgsys_wpe_init_ary[] = { + { WPE_TOP_CTL_INT_EN_OFFSET, 0x80000000 }, + { WPE_TOP_CTL_INT_STATUSX_OFFSET, 0xFFFFFFFF }, + { WPE_TOP_CQ_IRQ_EN_OFFSET, 0x80000000 }, + { WPE_TOP_CQ_IRQ_STX_OFFSET, 0xFFFFFFFF }, + { WPE_TOP_CQ_IRQ_EN2_OFFSET, 0x80000000 }, + { WPE_TOP_CQ_IRQ_STX2_OFFSET, 0xFFFFFFFF }, + { WPE_TOP_CQ_IRQ_EN3_OFFSET, 0x80000000 }, + { WPE_TOP_CQ_IRQ_STX3_OFFSET, 0xFFFFFFFF }, + { WPE_CACHE_RWCTL_CTL_OFFSET, 0x00000002 }, + { WPE_DMA_DMA_ERR_CTRL_OFFSET, 0x80000000 }, + { DIPCQ_W1A_DIPCQ_CQ_THR0_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR1_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR2_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR3_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR4_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR5_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR6_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR7_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR8_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR9_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR10_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR11_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR12_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR13_CTL_OFFSET, CQ_THRX_CTL }, + { DIPCQ_W1A_DIPCQ_CQ_THR14_CTL_OFFSET, CQ_THRX_CTL }, +}; + +static void __iomem *wpe_reg_base[MTK_IMGSYS_WPE_HW_SET]; + +/******************************************************************** + * Functions + ********************************************************************/ +void imgsys_wpe_init(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int i, hw_id, hw_idx; + void __iomem *offset = NULL; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_WPE_HW_SET; hw_idx++) { + hw_id = IMGSYS_REG_WPE1 + hw_idx; + wpe_reg_base[hw_idx] = of_iomap(imgsys_dev->dev->of_node, hw_id); + if (!wpe_reg_base[hw_idx]) { + dev_info(imgsys_dev->dev, + "%s: error: unable to iomap wpe_%d registers, devnode(%s).\n", + __func__, hw_id, imgsys_dev->dev->of_node->name); + continue; + } + + for (i = 0 ; i < WPE_INIT_ARRAY_COUNT; i++) { + offset = wpe_reg_base[hw_idx] + mtk_imgsys_wpe_init_ary[i].offset; + writel(mtk_imgsys_wpe_init_ary[i].value, offset); + } + } +} +EXPORT_SYMBOL_GPL(imgsys_wpe_init); + +void imgsys_wpe_uninit(struct mtk_imgsys_dev *imgsys_dev) +{ + unsigned int hw_idx; + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_WPE_HW_SET; hw_idx++) { + iounmap(wpe_reg_base[hw_idx]); + wpe_reg_base[hw_idx] = NULL; + } +} +EXPORT_SYMBOL_GPL(imgsys_wpe_uninit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek IMGSYS Modules"); diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.h new file mode 100644 index 000000000000..6001575265e6 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/modules/mtk_imgsys-wpe.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + * + * Author: Floria Huang + * + */ + +#ifndef _MTK_IMGSYS_WPE_H_ +#define _MTK_IMGSYS_WPE_H_ + +#include "../mtk_imgsys-dev.h" + +void imgsys_wpe_init(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_wpe_uninit(struct mtk_imgsys_dev *imgsys_dev); + +#endif /* _MTK_IMGSYS_WPE_H_ */ 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 index b69cfd0043d3..b8c30cb32b97 100644 --- 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 @@ -23,7 +23,7 @@ #include #include #include - +#include "mtk_imgsys-module_ops.h" #include "mtk_header_desc.h" #define MTK_IMGSYS_MEDIA_MODEL_NAME "MTK-ISP-DIP-V4L2" @@ -273,6 +273,7 @@ struct mtk_imgsys_pipe { * @v4l2_dev: V4L2 device structure for video device operations. * @imgsys_pipe: Image system pipeline configuration structure. * @cust_pipes: Pointer to custom pipeline descriptors. + * @modules: Pointer to image system module operations. * @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). @@ -281,6 +282,9 @@ struct mtk_imgsys_pipe { * @rproc_handle: Handle for remote processor interface. * @smem_dev: Device structure for shared memory operations. * @num_mods: Number of modules in the image system. + * @init_kref: Reference counter for initialization tracking. + * @hw_op_lock: Mutex for serializing hardware operations. + * @stream_cnt: Counter for active streams, increased on stream on. */ struct mtk_imgsys_dev { /* Device and Resource Information */ @@ -292,6 +296,8 @@ struct mtk_imgsys_dev { struct mtk_imgsys_pipe imgsys_pipe; /* Imgsys Pipeline Information */ const struct mtk_imgsys_pipe_desc *cust_pipes; + /* Imgsys Moudles Information */ + const struct module_ops *modules; /* Clock Information */ struct clk_bulk_data *clks; int num_clks; @@ -304,6 +310,10 @@ struct mtk_imgsys_dev { struct device *smem_dev; /* Number of modules */ int num_mods; + /* Synchronization and Flow Control */ + struct kref init_kref; + struct mutex hw_op_lock; /* Protect HW operations */ + int stream_cnt; }; /** diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h new file mode 100644 index 000000000000..dd02a8fa28d4 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Christopher Chen + * + */ + +#ifndef _MTK_IMGSYS_CORE_REG_H_ +#define _MTK_IMGSYS_CORE_REG_H_ + +/** + * Define the minimum and maximum hardware IDs + * for different MediaTek Image System components + */ +#define WPE_HW_MIN_ID IMGSYS_REG_WPE1 +#define WPE_HW_MAX_ID IMGSYS_REG_WPE3 +#define TRAW_HW_MIN_ID IMGSYS_REG_TRAW1 +#define TRAW_HW_MAX_ID IMGSYS_REG_TRAW3 +#define DIP_HW_MIN_ID IMGSYS_REG_DIP1 +#define DIP_HW_MAX_ID IMGSYS_REG_DIP2 +#define PQDIP_HW_MIN_ID IMGSYS_REG_PQDIP1 +#define PQDIP_HW_MAX_ID IMGSYS_REG_PQDIP2 +#define ME_HW_MIN_ID IMGSYS_REG_ME +#define ME_HW_MAX_ID IMGSYS_REG_ME + +/* Macro to calculate the size of a hardware set */ +#define HW_SET_SIZE(min_id, max_id) ((max_id) - (min_id) + 1) + +/* Define the hardware set sizes */ +#define MTK_IMGSYS_WPE_HW_SET HW_SET_SIZE(WPE_HW_MIN_ID, WPE_HW_MAX_ID) +#define MTK_IMGSYS_TRAW_HW_SET HW_SET_SIZE(TRAW_HW_MIN_ID, TRAW_HW_MAX_ID) +#define MTK_IMGSYS_DIP_HW_SET HW_SET_SIZE(DIP_HW_MIN_ID, DIP_HW_MAX_ID) +#define MTK_IMGSYS_PQDIP_HW_SET HW_SET_SIZE(PQDIP_HW_MIN_ID, PQDIP_HW_MAX_ID) +#define MTK_IMGSYS_ME_HW_SET HW_SET_SIZE(ME_HW_MIN_ID, ME_HW_MAX_ID) + +/* Define the CQ's control register bits */ +#define CQ_THRX_CTL_EN BIT(0) +#define CQ_THRX_CTL_MODE BIT(4) +#define CQ_THRX_CTL (CQ_THRX_CTL_EN | CQ_THRX_CTL_MODE) + +/** + * enum mtk_imgsys_reg_id + * + * Definition about hw register map id + * The engine order should be the same as register order in dts + */ +enum mtk_imgsys_reg_id { + IMGSYS_REG_TOP = 0, + IMGSYS_REG_TRAW1, + IMGSYS_REG_TRAW2, + IMGSYS_REG_TRAW3, + IMGSYS_REG_DIP1, + IMGSYS_REG_DIP2, + IMGSYS_REG_PQDIP1, + IMGSYS_REG_PQDIP2, + IMGSYS_REG_WPE1, + IMGSYS_REG_WPE2, + IMGSYS_REG_WPE3, + IMGSYS_REG_WPE1_DIP1, + IMGSYS_REG_ME, + IMGSYS_REG_WPE2_DIP1, + IMGSYS_REG_WPE3_DIP1, + IMGSYS_REG_DIP1_TOP, + IMGSYS_REG_DIP2_TOP +}; + +/** + * struct mtk_imgsys_init_array - Array structure for initializing registers + * @offset: Offset of the register + * @val: Value to be written to the register + * + * This structure represents an array element used for initializing registers + * in the MediaTek Image System. Each element contains the offset of the register + * and the value to be written to that register. + */ +struct mtk_imgsys_init_array { + unsigned int offset; + unsigned int value; +}; +#endif /* _MTK_IMGSYS_CORE_REG_H_ */ + diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.c new file mode 100644 index 000000000000..5daa8f863bd2 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Christopher Chen + * + */ + +#include +#include +#include "mtk_imgsys-module_common.h" +#include "mtk_imgsys-module_main.h" + +/******************************************************************** + * Global Define + ********************************************************************/ +/* Define the reset register bits */ +#define SW_RST (0x000C) + +/******************************************************************** + * Global Variable + ********************************************************************/ +static void __iomem *imgsys_main_reg_base; +static void __iomem *wpe_dip1_reg_base; +static void __iomem *wpe_dip2_reg_base; +static void __iomem *wpe_dip3_reg_base; +static void __iomem *dip1_reg_base; +static void __iomem *dip2_reg_base; + +/******************************************************************** + * Functions + ********************************************************************/ +static void imgsys_main_hw_init(struct mtk_imgsys_dev *imgsys_dev) +{ + void __iomem *wpe_reg_base = NULL; + void __iomem *wpe_ctrl = NULL; + unsigned int hw_idx = 0; + + /* Enable all LARBs of ImgSys */ + /** + * The flow will be updated based on the patch series 958467 from + * the Linux MediaTek project. For more details, refer to the following link: + * https://patchwork.kernel.org/project/linux-mediatek/list/?series=958467 + */ + + /* Reset ImgSys hardware */ + iowrite32(0xFFFFFFFF, dip1_reg_base + SW_RST); + iowrite32(0xFFFFFFFF, dip2_reg_base + SW_RST); + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_WPE_HW_SET; hw_idx++) { + if (hw_idx == 0) + wpe_reg_base = wpe_dip1_reg_base; + else if (hw_idx == 1) + wpe_reg_base = wpe_dip2_reg_base; + else + wpe_reg_base = wpe_dip3_reg_base; + + wpe_ctrl = wpe_reg_base + SW_RST; + iowrite32(0xFFFFFFFF, wpe_ctrl); + iowrite32(0x0, wpe_ctrl); + } + + iowrite32(0x00CF00FF, imgsys_main_reg_base + SW_RST); + iowrite32(0x0, imgsys_main_reg_base + SW_RST); + + iowrite32(0x0, dip1_reg_base + SW_RST); + iowrite32(0x0, dip2_reg_base + SW_RST); + + for (hw_idx = 0; hw_idx < MTK_IMGSYS_WPE_HW_SET; hw_idx++) { + if (hw_idx == 0) + wpe_reg_base = wpe_dip1_reg_base; + else if (hw_idx == 1) + wpe_reg_base = wpe_dip2_reg_base; + else + wpe_reg_base = wpe_dip3_reg_base; + + wpe_ctrl = wpe_reg_base + SW_RST; + iowrite32(0xFFFFFFFF, wpe_ctrl); + iowrite32(0x0, wpe_ctrl); + } + + iowrite32(0x00CF00FF, imgsys_main_reg_base + SW_RST); + iowrite32(0x0, imgsys_main_reg_base + SW_RST); + + /* Disable all LARBs of ImgSys*/ + /** + * The flow will be updated based on the patch series 958467 from + * the Linux MediaTek project. For more details, refer to the following link: + * https://patchwork.kernel.org/project/linux-mediatek/list/?series=958467 + */ +} + +void imgsys_main_init(struct mtk_imgsys_dev *imgsys_dev) +{ + imgsys_main_reg_base = of_iomap(imgsys_dev->dev->of_node, IMGSYS_REG_TOP); + if (!imgsys_main_reg_base) { + dev_info(imgsys_dev->dev, "%s Unable to ioremap imgsys_top registers\n", + __func__); + dev_info(imgsys_dev->dev, "%s of_iomap fail, devnode(%s).\n", + __func__, imgsys_dev->dev->of_node->name); + return; + } + + wpe_dip1_reg_base = of_iomap(imgsys_dev->dev->of_node, IMGSYS_REG_WPE1_DIP1); + if (!wpe_dip1_reg_base) { + dev_info(imgsys_dev->dev, "%s Unable to ioremap wpe_dip1 registers\n", + __func__); + dev_info(imgsys_dev->dev, "%s of_iomap fail, devnode(%s).\n", + __func__, imgsys_dev->dev->of_node->name); + return; + } + + wpe_dip2_reg_base = of_iomap(imgsys_dev->dev->of_node, IMGSYS_REG_WPE2_DIP1); + if (!wpe_dip2_reg_base) { + dev_info(imgsys_dev->dev, "%s Unable to ioremap wpe_dip2 registers\n", + __func__); + dev_info(imgsys_dev->dev, "%s of_iomap fail, devnode(%s).\n", + __func__, imgsys_dev->dev->of_node->name); + return; + } + + wpe_dip3_reg_base = of_iomap(imgsys_dev->dev->of_node, IMGSYS_REG_WPE3_DIP1); + if (!wpe_dip3_reg_base) { + dev_info(imgsys_dev->dev, "%s Unable to ioremap wpe_dip3 registers\n", + __func__); + dev_info(imgsys_dev->dev, "%s of_iomap fail, devnode(%s).\n", + __func__, imgsys_dev->dev->of_node->name); + return; + } + + dip1_reg_base = of_iomap(imgsys_dev->dev->of_node, IMGSYS_REG_DIP1_TOP); + if (!dip1_reg_base) { + dev_info(imgsys_dev->dev, "%s Unable to ioremap dip_top registers\n", + __func__); + dev_info(imgsys_dev->dev, "%s of_iomap fail, devnode(%s).\n", + __func__, imgsys_dev->dev->of_node->name); + return; + } + + dip2_reg_base = of_iomap(imgsys_dev->dev->of_node, IMGSYS_REG_DIP2_TOP); + if (!dip2_reg_base) { + dev_info(imgsys_dev->dev, "%s Unable to ioremap dip_top_nr registers\n", + __func__); + dev_info(imgsys_dev->dev, "%s of_iomap fail, devnode(%s).\n", + __func__, imgsys_dev->dev->of_node->name); + return; + } + + imgsys_main_hw_init(imgsys_dev); +} + +void imgsys_main_uninit(struct mtk_imgsys_dev *imgsys_dev) +{ + if (imgsys_main_reg_base) { + iounmap(imgsys_main_reg_base); + imgsys_main_reg_base = NULL; + } + + if (wpe_dip1_reg_base) { + iounmap(wpe_dip1_reg_base); + wpe_dip1_reg_base = NULL; + } + + if (wpe_dip2_reg_base) { + iounmap(wpe_dip2_reg_base); + wpe_dip2_reg_base = NULL; + } + + if (wpe_dip3_reg_base) { + iounmap(wpe_dip3_reg_base); + wpe_dip3_reg_base = NULL; + } + + if (dip1_reg_base) { + iounmap(dip1_reg_base); + dip1_reg_base = NULL; + } + + if (dip2_reg_base) { + iounmap(dip2_reg_base); + dip2_reg_base = NULL; + } +} diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.h new file mode 100644 index 000000000000..2a3fbd08d128 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_main.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Christopher Chen + * + */ + +#ifndef _MTK_IMGSYS_DEBUG_H_ +#define _MTK_IMGSYS_DEBUG_H_ + +#include "mtk_imgsys-dev.h" + +void imgsys_main_init(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_main_uninit(struct mtk_imgsys_dev *imgsys_dev); + +#endif /* _MTK_IMGSYS_DEBUG_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 index 6dc4b7b60832..a2eea8f4fb3c 100644 --- 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 @@ -24,4 +24,30 @@ enum mtk_imgsys_module { IMGSYS_MOD_MAX, }; +struct mtk_imgsys_dev; + +/** + * struct module_ops - Operations for a specific module in the MediaTek Image System + * @module_id: Identifier for the module. + * @init: Function pointer to initialize the module. + * This function sets the default values for various software-related + * parameters and ensures that the module is ready for operation. + * Example function: imgsys_dip_init + * @uninit: Function pointer to uninitialize the module. + * This function resets various software-related parameters to ensure + * the module is properly cleaned up and ready for shutdown. + * Example function: imgsys_dip_uninit + * + * This structure defines a set of operations for specific modules within the + * MediaTek Image System, such as WPE (Warping Engine), TRAW (Tile-Raw), + * DIP (Digital Image Processing), PQDIP (Picture Quality Digital Image + * Processing), and ME (Motion Estimation). Each module is identified by + * a unique identifier and includes function pointers for operations like + * initialization and deinitialization. + */ +struct module_ops { + int module_id; + void (*init)(struct mtk_imgsys_dev *imgsys_dev); + void (*uninit)(struct mtk_imgsys_dev *imgsys_dev); +}; #endif /* _MTK_IMGSYS_MODULES_H_ */ 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 index 5088c9df704c..f34ea9465745 100644 --- 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 @@ -12,6 +12,7 @@ #include #include "mtk_imgsys-dev.h" +#include "mtk_imgsys-module_ops.h" /** * struct mtk_imgsys_mod_pipe_desc - Description of a module's pipeline @@ -31,6 +32,7 @@ struct mtk_imgsys_mod_pipe_desc { * @mod_num: Number of modules in the pipeline. * @pipe_settings: Pointer to pipeline settings for the module. * @pipe_num: Number of pipeline settings. + * @imgsys_modules: Pointer to module operations for image system modules. */ struct cust_data { struct clk_bulk_data *clks; @@ -39,6 +41,7 @@ struct cust_data { unsigned int mod_num; const struct mtk_imgsys_pipe_desc *pipe_settings; unsigned int pipe_num; + const struct module_ops *imgsys_modules; }; /** 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 index 9cdcdb0a0200..9f118491b37d 100644 --- 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 @@ -6,7 +6,45 @@ * */ +#include #include "mtk_imgsys-sys.h" +#include "mtk_imgsys-dev.h" + +static int mtk_imgsys_hw_connect(struct mtk_imgsys_dev *imgsys_dev) +{ + int ret, i; + + ret = pm_runtime_get_sync(imgsys_dev->dev); + if (ret < 0) { + dev_err(imgsys_dev->dev, "Failed to sync runtime PM: %d\n", ret); + return ret; + } + + /* Set default value for hardware modules */ + for (i = 0; i < (imgsys_dev->num_mods); i++) + imgsys_dev->modules[i].init(imgsys_dev); + + kref_init(&imgsys_dev->init_kref); + + return 0; +} + +static void module_uninit(struct kref *kref) +{ + struct mtk_imgsys_dev *imgsys_dev; + int i; + + imgsys_dev = container_of(kref, struct mtk_imgsys_dev, init_kref); + + for (i = 0; i < (imgsys_dev->num_mods); i++) + if (imgsys_dev->modules[i].uninit) + imgsys_dev->modules[i].uninit(imgsys_dev); +} + +static void mtk_imgsys_hw_disconnect(struct mtk_imgsys_dev *imgsys_dev) +{ + kref_put(&imgsys_dev->init_kref, module_uninit); +} void mtk_imgsys_hw_enqueue(struct mtk_imgsys_dev *imgsys_dev, struct mtk_imgsys_request *req) @@ -16,12 +54,43 @@ void mtk_imgsys_hw_enqueue(struct mtk_imgsys_dev *imgsys_dev, int mtk_imgsys_hw_streamon(struct mtk_imgsys_pipe *pipe) { - /* Function implementation will be provided in subsequent patches */ + struct mtk_imgsys_dev *imgsys_dev = pipe->imgsys_dev; + int ret; + + mutex_lock(&imgsys_dev->hw_op_lock); + if (!imgsys_dev->stream_cnt) { + ret = mtk_imgsys_hw_connect(pipe->imgsys_dev); + if (ret) { + dev_info(pipe->imgsys_dev->dev, + "%s:%s: pipe(%d) connect to dip_hw failed\n", + __func__, pipe->desc->name, pipe->desc->id); + mutex_unlock(&imgsys_dev->hw_op_lock); + return ret; + } + } + imgsys_dev->stream_cnt++; + mutex_unlock(&imgsys_dev->hw_op_lock); + + dev_dbg(pipe->imgsys_dev->dev, + "%s:%s: stream on, id(%d), stream cnt(%d)\n", + __func__, pipe->desc->name, pipe->desc->id, imgsys_dev->stream_cnt); + return 0; } int mtk_imgsys_hw_streamoff(struct mtk_imgsys_pipe *pipe) { - /* Function implementation will be provided in subsequent patches */ + struct mtk_imgsys_dev *imgsys_dev = pipe->imgsys_dev; + + dev_dbg(pipe->imgsys_dev->dev, + "%s:%s: stream off, id(%d), stream cnt(%d)\n", + __func__, pipe->desc->name, pipe->desc->id, imgsys_dev->stream_cnt); + + mutex_lock(&imgsys_dev->hw_op_lock); + imgsys_dev->stream_cnt--; + if (!imgsys_dev->stream_cnt) + mtk_imgsys_hw_disconnect(imgsys_dev); + mutex_unlock(&imgsys_dev->hw_op_lock); + return 0; } 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 index 919c69493bbc..e25f17b98649 100644 --- 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 @@ -18,8 +18,13 @@ #include #include #include "linux/mtkisp_imgsys.h" -#include "mtk_imgsys-of.h" #include "mtk_imgsys-module_ops.h" +#include "mtk_imgsys-module_main.h" +#include "modules/mtk_imgsys-dip.h" +#include "modules/mtk_imgsys-traw.h" +#include "modules/mtk_imgsys-pqdip.h" +#include "modules/mtk_imgsys-wpe.h" +#include "mtk_imgsys-of.h" #include "mtk_imgsys-vnode_id.h" #include "mtk_imgsys_v4l2_vnode.h" #include "mtk_imgsys-dev.h" @@ -1499,6 +1504,7 @@ static int mtk_imgsys_probe(struct platform_device *pdev) init_imgsys_pipeline(data); imgsys_dev->cust_pipes = data->pipe_settings; + imgsys_dev->modules = data->imgsys_modules; imgsys_dev->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1511,6 +1517,8 @@ static int mtk_imgsys_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, imgsys_dev); imgsys_dev->num_mods = data->mod_num; + imgsys_dev->stream_cnt = 0; + mutex_init(&imgsys_dev->hw_op_lock); /* Get Clocks */ imgsys_dev->clks = data->clks; @@ -1613,6 +1621,7 @@ static void mtk_imgsys_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); platform_driver_unregister(&mtk_imgsys_larb_driver); mtk_imgsys_dev_v4l2_release(imgsys_dev); + mutex_destroy(&imgsys_dev->hw_op_lock); devm_kfree(&pdev->dev, imgsys_dev->larbs); devm_kfree(&pdev->dev, imgsys_dev); } @@ -1709,6 +1718,39 @@ static struct clk_bulk_data imgsys_isp7_clks[] = { { .id = "ME_CG_LARB12" }, }; +static const struct module_ops imgsys_isp7_modules[] = { + [IMGSYS_MOD_IMGMAIN] = { + .module_id = IMGSYS_MOD_IMGMAIN, + .init = imgsys_main_init, + .uninit = imgsys_main_uninit, + }, + [IMGSYS_MOD_WPE] = { + .module_id = IMGSYS_MOD_WPE, + .init = imgsys_wpe_init, + .uninit = imgsys_wpe_uninit, + }, + [IMGSYS_MOD_TRAW] = { + .module_id = IMGSYS_MOD_TRAW, + .init = imgsys_traw_init, + .uninit = imgsys_traw_uninit, + }, + [IMGSYS_MOD_DIP] = { + .module_id = IMGSYS_MOD_DIP, + .init = imgsys_dip_init, + .uninit = imgsys_dip_uninit, + }, + [IMGSYS_MOD_PQDIP] = { + .module_id = IMGSYS_MOD_PQDIP, + .init = imgsys_pqdip_init, + .uninit = imgsys_pqdip_uninit, + }, + [IMGSYS_MOD_ME] = { + .module_id = IMGSYS_MOD_ME, + .init = NULL, + .uninit = NULL, + }, +}; + static const struct cust_data imgsys_data[] = { [0] = { .clks = imgsys_isp7_clks, @@ -1717,6 +1759,7 @@ static const struct cust_data imgsys_data[] = { .mod_num = ARRAY_SIZE(module_pipe_isp7), .pipe_settings = pipe_settings_isp7, .pipe_num = ARRAY_SIZE(pipe_settings_isp7), + .imgsys_modules = imgsys_isp7_modules, }, }; From patchwork Sat May 24 11:49:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivia Wen X-Patchwork-Id: 892331 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13CD72628D; Sat, 24 May 2025 11:52:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087528; cv=none; b=t3Skkn+o93J6DhW3OUlOAmZBqvcyMnH6LG1mMlnmB0UHygTVwa+81KqPuCNCamTCq5YP/CcZulMEqzMJQPjt3BACG9R4FGDqa0ZPPS62K9l/r6iLq/CEcjuKuXP23yas7ptetrco71/e7l6aoBdNBAm1VjLDR4JghqRrZPUWVPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748087528; c=relaxed/simple; bh=sKxvTiAI2I+14IHRf/brUv2jEtyU6dy4HJeHzviC2L4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DJuZdYUcQk7VMPL9WHGHfz+vvzr5YOKefsV543+grb8/sl/PIogrUmciagMnyp1io3zMldj+/UHUqm8Ej6IapvYjr1dY+r2bnpUvUPlvUynbBhuvhr81qBcuEInEQ6RP7X/LgGYpr73UdJ2WGkrHUxYBhlpmKa+jibX+erjelO4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=e4/Sbafw; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="e4/Sbafw" X-UUID: 7b046d26389511f0813e4fe1310efc19-20250524 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=/z+bsZKsBfIBHHVZrtMwqYH16nsQ/48zaWhfdDZkJ0Y=; b=e4/SbafwCFVwwv/QD+EED7S2eB17rsQtJZIMY/UhyBRPiybtlLxAHLZAqc3yr1ubpG2UE+iIsUfbJ00UJRBEtijWPBSgVCIR9EuHI+KjuXzXI7U3vImh74XTs7DWx4iaMayumPCfDTnnTVo3Y0L0jhoBROPRhcl4AELkKTMIOYk=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:17ce16b5-a09f-4555-918f-edc04f1b2d64, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:738ded57-abad-4ac2-9923-3af0a8a9a079, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 7b046d26389511f0813e4fe1310efc19-20250524 Received: from mtkmbs09n2.mediatek.inc [(172.21.101.94)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1362999662; Sat, 24 May 2025 19:51:51 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs13n1.mediatek.inc (172.21.101.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Sat, 24 May 2025 19:51:49 +0800 Received: from mtksitap99.mediatek.inc (10.233.130.16) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Sat, 24 May 2025 19:51:49 +0800 From: Olivia Wen To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , AngeloGioacchino Del Regno CC: Krzysztof Kozlowski , Conor Dooley , Olivia Wen , , , , , , , , Subject: [PATCH v1 07/10] media: mediatek: isp: Add CMDQ support for ImgSys driver Date: Sat, 24 May 2025 19:49:59 +0800 Message-ID: <20250524115144.3832748-8-olivia.wen@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250524115144.3832748-1-olivia.wen@mediatek.com> References: <20250524115144.3832748-1-olivia.wen@mediatek.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N The ImgSys driver is implemented as a series of patches, with this patch focusing on CMDQ (Command Queue) support for the MediaTek Image System driver. CMDQ is essential for managing and executing hardware commands efficiently, ensuring smooth operation of image processing tasks within the ImgSys architecture. Signed-off-by: Olivia Wen --- .../mediatek/isp/isp_7x/imgsys/Makefile | 1 + .../isp/isp_7x/imgsys/mtk_imgsys-cmdq-plat.h | 502 +++++++++++++ .../isp/isp_7x/imgsys/mtk_imgsys-cmdq.c | 690 ++++++++++++++++++ .../isp/isp_7x/imgsys/mtk_imgsys-cmdq.h | 29 + .../isp_7x/imgsys/mtk_imgsys-module_common.h | 20 + .../isp/isp_7x/imgsys/mtk_imgsys-sys.c | 5 + 6 files changed, 1247 insertions(+) create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq-plat.h create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.c create mode 100644 drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.h diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile index 26c8c1d39750..c0f0f3a0c38a 100644 --- a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/Makefile @@ -2,6 +2,7 @@ # mtk_imgsys_util-objs := \ +mtk_imgsys-cmdq.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_imgsys-cmdq-plat.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq-plat.h new file mode 100644 index 000000000000..801a12e70bac --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq-plat.h @@ -0,0 +1,502 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Daniel Huang + * + */ + +#ifndef _MTK_IMGSYS_CMDQ_PLAT_H_ +#define _MTK_IMGSYS_CMDQ_PLAT_H_ + +#include "mtk_imgsys-cmdq.h" + +/* Maximum number of frame blocks for GCE recording */ +#define GCE_REC_MAX_FRAME_BLOCK 40 + +/* Maximum number of tile blocks for GCE recording */ +#define GCE_REC_MAX_TILE_BLOCK 40 + +/* Maximum number of label counts for GCE recording */ +#define GCE_REC_MAX_LABEL_COUNT 2048 + +/* Maximum number of image system engines */ +#define IMGSYS_ENG_MAX 10 + +/* Start address of the image system register */ +#define IMGSYS_REG_START 0x15000000 + +/* End address of the image system register */ +#define IMGSYS_REG_END 0x1570FFFF + +/* Number of normal camera's thread */ +#define IMGSYS_NOR_THD 10 + +/* Define the constants for buffer validation */ +#define HEADER_CODE 0x5A5A5A5A +#define CHECK_PRE 0x55AA55AA +#define CHECK_POST 0xAA55AA55 +#define FOOTER_CODE 0xA5A5A5A5 + +/* Enumeration for Image System (IMGSYS) events */ +enum mtk_imgsys_event { + /* HW event */ + /* TRAW frame done events */ + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_0 = 0, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_1, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_2, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_3, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_4, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_5, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_6, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_7, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_8, + IMGSYS_EVENT_TRAW0_CQ_THR_DONE_9, + /* LTRAW frame done events */ + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_0, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_1, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_2, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_3, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_4, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_5, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_6, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_7, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_8, + IMGSYS_EVENT_TRAW1_CQ_THR_DONE_9, + /* XTRAW frame done events */ + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_0, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_1, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_2, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_3, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_4, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_5, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_6, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_7, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_8, + IMGSYS_EVENT_XTRAW_CQ_THR_DONE_9, + /* DIP frame done events */ + IMGSYS_EVENT_DIP_CQ_THR_DONE_0, + IMGSYS_EVENT_DIP_CQ_THR_DONE_1, + IMGSYS_EVENT_DIP_CQ_THR_DONE_2, + IMGSYS_EVENT_DIP_CQ_THR_DONE_3, + IMGSYS_EVENT_DIP_CQ_THR_DONE_4, + IMGSYS_EVENT_DIP_CQ_THR_DONE_5, + IMGSYS_EVENT_DIP_CQ_THR_DONE_6, + IMGSYS_EVENT_DIP_CQ_THR_DONE_7, + IMGSYS_EVENT_DIP_CQ_THR_DONE_8, + IMGSYS_EVENT_DIP_CQ_THR_DONE_9, + /* PQ_DIP_A frame done events */ + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_0, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_1, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_2, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_3, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_4, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_5, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_6, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_7, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_8, + IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_9, + /* PQ_DIP_B frame done events */ + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_0, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_1, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_2, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_3, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_4, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_5, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_6, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_7, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_8, + IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_9, + /* WPE_EIS frame done events */ + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_0, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_1, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_2, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_3, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_4, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_5, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_6, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_7, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_8, + IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_9, + /* WPE_TNR frame done events */ + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_0, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_1, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_2, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_3, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_4, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_5, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_6, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_7, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_8, + IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_9, + /* WPE_LITE frame done events */ + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_0, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_1, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_2, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_3, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_4, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_5, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_6, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_7, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_8, + IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_9, + /* ME done events */ + IMGSYS_EVENT_IMGSYS_IPE_ME_DONE, + /* SW events */ + IMGSYS_EVENT_SYNC_TOKEN_START, + IMGSYS_EVENT_SYNC_TOKEN_WPE_EIS = IMGSYS_EVENT_SYNC_TOKEN_START, + IMGSYS_EVENT_SYNC_TOKEN_WPE_TNR, + IMGSYS_EVENT_SYNC_TOKEN_WPE_LITE, + IMGSYS_EVENT_SYNC_TOKEN_TRAW, + IMGSYS_EVENT_SYNC_TOKEN_LTRAW, + IMGSYS_EVENT_SYNC_TOKEN_XTRAW, + IMGSYS_EVENT_SYNC_TOKEN_DIP, + IMGSYS_EVENT_SYNC_TOKEN_PQDIP_A, + IMGSYS_EVENT_SYNC_TOKEN_PQDIP_B, + IMGSYS_EVENT_SYNC_TOKEN_IPESYS_ME, + IMGSYS_EVENT_SYNC_TOKEN_APUSYS_APU, + IMGSYS_EVENT_SYNC_TOKEN_VSS_TRAW, + IMGSYS_EVENT_SYNC_TOKEN_VSS_LTRAW, + IMGSYS_EVENT_SYNC_TOKEN_VSS_XTRAW, + IMGSYS_EVENT_SYNC_TOKEN_VSS_DIP, + IMGSYS_EVENT_SYNC_TOKEN_POOL_START, + IMGSYS_EVENT_SYNC_TOKEN_POOL_1 = IMGSYS_EVENT_SYNC_TOKEN_POOL_START, + IMGSYS_EVENT_SYNC_TOKEN_POOL_2, + IMGSYS_EVENT_SYNC_TOKEN_POOL_3, + IMGSYS_EVENT_SYNC_TOKEN_POOL_4, + IMGSYS_EVENT_SYNC_TOKEN_POOL_5, + IMGSYS_EVENT_SYNC_TOKEN_POOL_6, + IMGSYS_EVENT_SYNC_TOKEN_POOL_7, + IMGSYS_EVENT_SYNC_TOKEN_POOL_8, + IMGSYS_EVENT_SYNC_TOKEN_POOL_9, + IMGSYS_EVENT_SYNC_TOKEN_POOL_10, + IMGSYS_EVENT_SYNC_TOKEN_POOL_11, + IMGSYS_EVENT_SYNC_TOKEN_POOL_12, + IMGSYS_EVENT_SYNC_TOKEN_POOL_13, + IMGSYS_EVENT_SYNC_TOKEN_POOL_14, + IMGSYS_EVENT_SYNC_TOKEN_POOL_15, + IMGSYS_EVENT_SYNC_TOKEN_POOL_16, + IMGSYS_EVENT_SYNC_TOKEN_POOL_17, + IMGSYS_EVENT_SYNC_TOKEN_POOL_18, + IMGSYS_EVENT_SYNC_TOKEN_POOL_19, + IMGSYS_EVENT_SYNC_TOKEN_POOL_20, + IMGSYS_EVENT_SYNC_TOKEN_POOL_21, + IMGSYS_EVENT_SYNC_TOKEN_POOL_22, + IMGSYS_EVENT_SYNC_TOKEN_POOL_23, + IMGSYS_EVENT_SYNC_TOKEN_POOL_24, + IMGSYS_EVENT_SYNC_TOKEN_POOL_25, + IMGSYS_EVENT_SYNC_TOKEN_POOL_26, + IMGSYS_EVENT_SYNC_TOKEN_POOL_27, + IMGSYS_EVENT_SYNC_TOKEN_POOL_28, + IMGSYS_EVENT_SYNC_TOKEN_POOL_29, + IMGSYS_EVENT_SYNC_TOKEN_POOL_30, + IMGSYS_EVENT_SYNC_TOKEN_POOL_31, + IMGSYS_EVENT_SYNC_TOKEN_POOL_32, + IMGSYS_EVENT_SYNC_TOKEN_POOL_33, + IMGSYS_EVENT_SYNC_TOKEN_POOL_34, + IMGSYS_EVENT_SYNC_TOKEN_POOL_35, + IMGSYS_EVENT_SYNC_TOKEN_POOL_36, + IMGSYS_EVENT_SYNC_TOKEN_POOL_37, + IMGSYS_EVENT_SYNC_TOKEN_POOL_38, + IMGSYS_EVENT_SYNC_TOKEN_POOL_39, + IMGSYS_EVENT_SYNC_TOKEN_POOL_40, + IMGSYS_EVENT_SYNC_TOKEN_POOL_41, + IMGSYS_EVENT_SYNC_TOKEN_POOL_42, + IMGSYS_EVENT_SYNC_TOKEN_POOL_43, + IMGSYS_EVENT_SYNC_TOKEN_POOL_44, + IMGSYS_EVENT_SYNC_TOKEN_POOL_45, + IMGSYS_EVENT_SYNC_TOKEN_POOL_46, + IMGSYS_EVENT_SYNC_TOKEN_POOL_47, + IMGSYS_EVENT_SYNC_TOKEN_POOL_48, + IMGSYS_EVENT_SYNC_TOKEN_POOL_49, + IMGSYS_EVENT_SYNC_TOKEN_POOL_50, + IMGSYS_EVENT_SYNC_TOKEN_POOL_51, + IMGSYS_EVENT_SYNC_TOKEN_POOL_52, + IMGSYS_EVENT_SYNC_TOKEN_POOL_53, + IMGSYS_EVENT_SYNC_TOKEN_POOL_54, + IMGSYS_EVENT_SYNC_TOKEN_POOL_55, + IMGSYS_EVENT_SYNC_TOKEN_POOL_56, + IMGSYS_EVENT_SYNC_TOKEN_POOL_57, + IMGSYS_EVENT_SYNC_TOKEN_POOL_58, + IMGSYS_EVENT_SYNC_TOKEN_POOL_59, + IMGSYS_EVENT_SYNC_TOKEN_POOL_60, + IMGSYS_EVENT_SYNC_TOKEN_END = IMGSYS_EVENT_SYNC_TOKEN_POOL_60, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_1, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_2, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_3, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_4, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_5, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_6, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_7, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_8, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_9, + IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_10, + IMGSYS_EVENT_SYNC_TOKEN_TZMP_ISP_WAIT, + IMGSYS_EVENT_SYNC_TOKEN_TZMP_ISP_SET, + IMGSYS_EVENT_MAX +}; + +/* Structure to represent an IMGSYS event */ +struct imgsys_event_table { + u16 event; + char dts_name[256]; +}; + +/* Event table for Image System (IMGSYS) */ +static struct imgsys_event_table imgsys_event[] = { + /* TRAW frame done events */ + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_0, "traw_cq_thread0_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_1, "traw_cq_thread1_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_2, "traw_cq_thread2_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_3, "traw_cq_thread3_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_4, "traw_cq_thread4_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_5, "traw_cq_thread5_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_6, "traw_cq_thread6_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_7, "traw_cq_thread7_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_8, "traw_cq_thread8_frame_done"}, + { IMGSYS_EVENT_TRAW0_CQ_THR_DONE_9, "traw_cq_thread9_frame_done"}, + /* LTRAW frame done events */ + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_0, "ltraw_cq_thread0_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_1, "ltraw_cq_thread1_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_2, "ltraw_cq_thread2_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_3, "ltraw_cq_thread3_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_4, "ltraw_cq_thread4_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_5, "ltraw_cq_thread5_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_6, "ltraw_cq_thread6_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_7, "ltraw_cq_thread7_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_8, "ltraw_cq_thread8_frame_done"}, + { IMGSYS_EVENT_TRAW1_CQ_THR_DONE_9, "ltraw_cq_thread9_frame_done"}, + /* XTRAW frame done events */ + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_0, "xtraw_cq_thread0_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_1, "xtraw_cq_thread1_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_2, "xtraw_cq_thread2_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_3, "xtraw_cq_thread3_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_4, "xtraw_cq_thread4_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_5, "xtraw_cq_thread5_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_6, "xtraw_cq_thread6_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_7, "xtraw_cq_thread7_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_8, "xtraw_cq_thread8_frame_done"}, + { IMGSYS_EVENT_XTRAW_CQ_THR_DONE_9, "xtraw_cq_thread9_frame_done"}, + /* DIP frame done events */ + { IMGSYS_EVENT_DIP_CQ_THR_DONE_0, "dip_cq_thread0_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_1, "dip_cq_thread1_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_2, "dip_cq_thread2_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_3, "dip_cq_thread3_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_4, "dip_cq_thread4_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_5, "dip_cq_thread5_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_6, "dip_cq_thread6_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_7, "dip_cq_thread7_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_8, "dip_cq_thread8_frame_done"}, + { IMGSYS_EVENT_DIP_CQ_THR_DONE_9, "dip_cq_thread9_frame_done"}, + /* PQ_DIP_A frame done events */ + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_0, "pqa_cq_thread0_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_1, "pqa_cq_thread1_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_2, "pqa_cq_thread2_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_3, "pqa_cq_thread3_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_4, "pqa_cq_thread4_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_5, "pqa_cq_thread5_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_6, "pqa_cq_thread6_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_7, "pqa_cq_thread7_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_8, "pqa_cq_thread8_frame_done"}, + { IMGSYS_EVENT_PQDIP_A_CQ_THR_DONE_9, "pqa_cq_thread9_frame_done"}, + /* PQ_DIP_B frame done events */ + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_0, "pqb_cq_thread0_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_1, "pqb_cq_thread1_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_2, "pqb_cq_thread2_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_3, "pqb_cq_thread3_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_4, "pqb_cq_thread4_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_5, "pqb_cq_thread5_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_6, "pqb_cq_thread6_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_7, "pqb_cq_thread7_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_8, "pqb_cq_thread8_frame_done"}, + { IMGSYS_EVENT_PQDIP_B_CQ_THR_DONE_9, "pqb_cq_thread9_frame_done"}, + /* WPE_EIS frame done events */ + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_0, "wpe_eis_cq_thread0_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_1, "wpe_eis_cq_thread1_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_2, "wpe_eis_cq_thread2_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_3, "wpe_eis_cq_thread3_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_4, "wpe_eis_cq_thread4_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_5, "wpe_eis_cq_thread5_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_6, "wpe_eis_cq_thread6_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_7, "wpe_eis_cq_thread7_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_8, "wpe_eis_cq_thread8_frame_done"}, + { IMGSYS_EVENT_WPE_EIS_CQ_THR_DONE_9, "wpe_eis_cq_thread9_frame_done"}, + /* WPE_TNR frame done events */ + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_0, "wpe_tnr_cq_thread0_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_1, "wpe_tnr_cq_thread1_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_2, "wpe_tnr_cq_thread2_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_3, "wpe_tnr_cq_thread3_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_4, "wpe_tnr_cq_thread4_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_5, "wpe_tnr_cq_thread5_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_6, "wpe_tnr_cq_thread6_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_7, "wpe_tnr_cq_thread7_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_8, "wpe_tnr_cq_thread8_frame_done"}, + { IMGSYS_EVENT_WPE_TNR_CQ_THR_DONE_9, "wpe_tnr_cq_thread9_frame_done"}, + /* WPE_LITE frame done events */ + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_0, "wpe_lite_cq_thread0_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_1, "wpe_lite_cq_thread1_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_2, "wpe_lite_cq_thread2_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_3, "wpe_lite_cq_thread3_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_4, "wpe_lite_cq_thread4_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_5, "wpe_lite_cq_thread5_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_6, "wpe_lite_cq_thread6_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_7, "wpe_lite_cq_thread7_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_8, "wpe_lite_cq_thread8_frame_done"}, + { IMGSYS_EVENT_WPE_LITE_CQ_THR_DONE_9, "wpe_lite_cq_thread9_frame_done"}, + /* ME done events */ + { IMGSYS_EVENT_IMGSYS_IPE_ME_DONE, "me_done"}, + /* SW events */ + { IMGSYS_EVENT_SYNC_TOKEN_WPE_EIS, "wpe_eis_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_WPE_TNR, "wpe_tnr_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_WPE_LITE, "wpe_lite_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_TRAW, "traw_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_LTRAW, "ltraw_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_XTRAW, "xtraw_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_DIP, "dip_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_PQDIP_A, "pqdip_a_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_PQDIP_B, "pqdip_b_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_IPESYS_ME, "me_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_APUSYS_APU, "apu_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_VSS_TRAW, "vss_traw_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_VSS_LTRAW, "vss_ltraw_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_VSS_XTRAW, "vss_xtraw_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_VSS_DIP, "vss_dip_sync_token"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_1, "sw_sync_token_pool_1"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_2, "sw_sync_token_pool_2"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_3, "sw_sync_token_pool_3"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_4, "sw_sync_token_pool_4"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_5, "sw_sync_token_pool_5"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_6, "sw_sync_token_pool_6"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_7, "sw_sync_token_pool_7"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_8, "sw_sync_token_pool_8"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_9, "sw_sync_token_pool_9"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_10, "sw_sync_token_pool_10"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_11, "sw_sync_token_pool_11"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_12, "sw_sync_token_pool_12"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_13, "sw_sync_token_pool_13"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_14, "sw_sync_token_pool_14"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_15, "sw_sync_token_pool_15"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_16, "sw_sync_token_pool_16"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_17, "sw_sync_token_pool_17"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_18, "sw_sync_token_pool_18"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_19, "sw_sync_token_pool_19"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_20, "sw_sync_token_pool_20"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_21, "sw_sync_token_pool_21"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_22, "sw_sync_token_pool_22"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_23, "sw_sync_token_pool_23"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_24, "sw_sync_token_pool_24"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_25, "sw_sync_token_pool_25"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_26, "sw_sync_token_pool_26"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_27, "sw_sync_token_pool_27"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_28, "sw_sync_token_pool_28"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_29, "sw_sync_token_pool_29"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_30, "sw_sync_token_pool_30"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_31, "sw_sync_token_pool_31"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_32, "sw_sync_token_pool_32"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_33, "sw_sync_token_pool_33"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_34, "sw_sync_token_pool_34"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_35, "sw_sync_token_pool_35"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_36, "sw_sync_token_pool_36"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_37, "sw_sync_token_pool_37"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_38, "sw_sync_token_pool_38"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_39, "sw_sync_token_pool_39"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_40, "sw_sync_token_pool_40"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_41, "sw_sync_token_pool_41"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_42, "sw_sync_token_pool_42"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_43, "sw_sync_token_pool_43"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_44, "sw_sync_token_pool_44"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_45, "sw_sync_token_pool_45"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_46, "sw_sync_token_pool_46"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_47, "sw_sync_token_pool_47"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_48, "sw_sync_token_pool_48"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_49, "sw_sync_token_pool_49"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_50, "sw_sync_token_pool_50"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_51, "sw_sync_token_pool_51"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_52, "sw_sync_token_pool_52"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_53, "sw_sync_token_pool_53"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_54, "sw_sync_token_pool_54"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_55, "sw_sync_token_pool_55"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_56, "sw_sync_token_pool_56"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_57, "sw_sync_token_pool_57"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_58, "sw_sync_token_pool_58"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_59, "sw_sync_token_pool_59"}, + { IMGSYS_EVENT_SYNC_TOKEN_POOL_60, "sw_sync_token_pool_60"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_1, "sw_sync_token_camsys_pool_1"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_2, "sw_sync_token_camsys_pool_2"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_3, "sw_sync_token_camsys_pool_3"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_4, "sw_sync_token_camsys_pool_4"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_5, "sw_sync_token_camsys_pool_5"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_6, "sw_sync_token_camsys_pool_6"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_7, "sw_sync_token_camsys_pool_7"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_8, "sw_sync_token_camsys_pool_8"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_9, "sw_sync_token_camsys_pool_9"}, + { IMGSYS_EVENT_SYNC_TOKEN_CAMSYS_POOL_10, "sw_sync_token_camsys_pool_10"}, + { IMGSYS_EVENT_SYNC_TOKEN_TZMP_ISP_WAIT, "sw_sync_token_tzmp_isp_wait"}, + { IMGSYS_EVENT_SYNC_TOKEN_TZMP_ISP_SET, "sw_sync_token_tzmp_isp_set"}, + { IMGSYS_EVENT_MAX, "imgsys_event_max"}, +}; + +/* Structure to record block information */ +struct block_record { + u32 label_min; /* Minimum label value */ + u32 label_max; /* Maximum label value */ + u32 label_count; /* Count of labels */ + u32 cmd_offset; /* Offset of the command */ + u32 cmd_length; /* Length of the command */ +}; + +/* Enumeration for GCE recording block types */ +enum gce_rec_block_enum { + GCE_REC_NONE_BLOCK = -1, /* No block */ + GCE_REC_FRAME_BLOCK = 0, /* Frame block */ + GCE_REC_TILE_BLOCK /* Tile block */ +}; + +/* Enumeration for GCE recording modes */ +enum gce_rec_mode_enum { + GCE_REC_APPEND_MODE = 0, /* Append mode */ + GCE_REC_REPLACE_MODE /* Replace mode */ +}; + +/** + *This structure is utilized by the SCP (Secondary Control Processor), + * which is another CPU in the system. It contains necessary information + * for managing software frames across different processing units. + */ +struct gce_recorder { + u32 header_code; /* Header guard word */ + u32 cmd_offset; /* Command offset */ + u32 check_pre; /* Pre-check guard word */ + u32 *p_output; /* Output buffer pointer */ + u32 check_post; /* Post-check guard word */ + u32 *p_buffer; /* Buffer pointer */ + u32 max_length; /* Maximum length of the buffer */ + u32 curr_length; /* Current length of the buffer */ + + struct block_record frame_record[GCE_REC_MAX_FRAME_BLOCK]; /* Frame block records */ + u32 frame_block; /* Number of frame blocks */ + u32 curr_frame; /* Current frame block index */ + + struct block_record tile_record[GCE_REC_MAX_TILE_BLOCK]; /* Tile block records */ + u32 tile_block; /* Number of tile blocks */ + u32 curr_tile; /* Current tile block index */ + + enum gce_rec_block_enum curr_block; /* Current block type */ + enum gce_rec_mode_enum curr_mode; /* Current recording mode */ + + u32 orig_index; /* Original index */ + u32 *p_orig_out; /* Original output buffer pointer */ + u32 curr_label; /* Current label index */ + + enum gce_rec_block_enum label_block; /* Current label block type */ + + u32 frame_label[GCE_REC_MAX_LABEL_COUNT]; /* Frame labels */ + u32 frame_count; /* Number of frame labels */ + + u32 tile_label[GCE_REC_MAX_LABEL_COUNT]; /* Tile labels */ + u32 tile_count; /* Number of tile labels */ + + u32 footer_code; /* Footer guard word */ +}; +#endif /* _MTK_IMGSYS_CMDQ_PLAT_H_ */ + diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.c b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.c new file mode 100644 index 000000000000..7628ade90b6b --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + * Author: Daniel Huang + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtk_imgsys-cmdq.h" +#include "mtk_imgsys-cmdq-plat.h" +#include "mtk_imgsys-module_common.h" + +#define MAX_FRAME_IN_TASK 64 +#define CMDQ_BUF_SIZE 0x4000 + +static struct workqueue_struct *imgsys_cmdq_wq; +static u32 is_stream_off; + +/** + * enum mtk_imgsys_cmd - Commands for image system operations + * @IMGSYS_CMD_WRITE: Write operation + * @IMGSYS_CMD_POLL: Poll operation + * @IMGSYS_CMD_WAIT: Wait operation + * @IMGSYS_CMD_UPDATE: Update operation + * @IMGSYS_CMD_ACQUIRE: Acquire operation + * @IMGSYS_CMD_STOP: Stop operation + * + * This enumeration defines the various commands that determine how to use the + * cmdq API for image system operations. + */ +enum mtk_imgsys_cmd { + IMGSYS_CMD_WRITE, + IMGSYS_CMD_POLL, + IMGSYS_CMD_WAIT, + IMGSYS_CMD_UPDATE, + IMGSYS_CMD_ACQUIRE, + IMGSYS_CMD_STOP +}; + +/** + * struct access - Access parameters for image system commands + * @address: Memory address to access + * @value: Value to write to the memory address + * @mask: Mask for the value + * + * This structure defines the parameters for memory access operations used by + * IMGSYS_CMD_WRITE and IMGSYS_CMD_POLL commands. + */ +struct access { + u64 address; + u32 value; + u32 mask; +} __packed; + +/** + * struct event - Event parameters for image system commands + * @event: Event identifier + * @action: Action to perform for the event + * + * This structure defines the parameters for event-based operations used by + * IMGSYS_CMD_WAIT, IMGSYS_CMD_UPDATE and IMGSYS_CMD_ACQUIRE commands. + */ +struct event { + u32 event; + u32 action; +} __packed; + +/** + * struct command - Command structure for image system operations + * @opcode: Operation code (command) + * @param: Union of parameters for different commands + * @write: Parameters for write command + * @poll: Parameters for poll command + * @wait: Parameters for wait command + * @update: Parameters for update command + * @acquire: Parameters for acquire command + * + * This structure is used to store the instructions and parameters for how to + * use the cmdq driver. + */ +struct command { + enum mtk_imgsys_cmd opcode; + union { + struct access write; + struct access poll; + struct event wait; + struct event update; + struct event acquire; + } param; +} __packed; + +/** + * struct mtk_imgsys_cb_param - Callback parameters for image system commands + * @cmdq_cb_work: Work structure for command queue callback + * @pkt: Command packet + * @frm_info: Pointer to frame information + * @imgsys_dev: Pointer to image system device + * @clt: Pointer to command queue client + * @user_cmdq_cb: User-defined command queue callback function + * @err: Error code + * @frm_idx: Frame index + * @frm_num: Number of frames + * @blk_idx: Block index + * @blk_num: Number of blocks + * @is_earlycb: Indicates if it is an early callback + * @group_id: Group identifier + * @thd_idx: Thread index + * @task_id: Task identifier + * @task_num: Number of tasks + * @task_cnt: Task count + * @pkt_ofst: Array of packet offsets for frames in task + * @is_blk_last: Indicates if it is the last block + * @is_frm_last: Indicates if it is the last frame + * @is_task_last: Indicates if it is the last task + * + * This structure defines the parameters for callbacks related to + * image system commands. + */ +struct mtk_imgsys_cb_param { + struct work_struct cmdq_cb_work; + struct cmdq_pkt pkt; + struct swfrm_info *frm_info; + struct mtk_imgsys_dev *imgsys_dev; + struct cmdq_client *clt; + void (*user_cmdq_cb)(struct imgsys_cmdq_cb_data data); + s32 err; + u32 frm_idx; + u32 frm_num; + u32 blk_idx; + u32 blk_num; + u32 is_earlycb; + s32 group_id; + u32 thd_idx; + u32 task_id; + u32 task_num; + u32 task_cnt; + size_t pkt_ofst[MAX_FRAME_IN_TASK]; + bool is_blk_last; + bool is_frm_last; + bool is_task_last; +}; + +static void imgsys_cmdq_task_cb(struct mbox_client *cl, void *mssg); +static struct cmdq_client *imgsys_clt[IMGSYS_ENG_MAX]; + +void imgsys_cmdq_init(struct mtk_imgsys_dev *imgsys_dev) +{ + struct device *dev = imgsys_dev->dev; + u32 idx = 0; + + /* Only first user has to allocate the work queue */ + if (!imgsys_cmdq_wq) { + imgsys_cmdq_wq = + alloc_ordered_workqueue("%s", __WQ_LEGACY | + WQ_MEM_RECLAIM | + WQ_FREEZABLE, + "imgsys_cmdq_cb_wq"); + if (!imgsys_cmdq_wq) { + dev_dbg(imgsys_dev->dev, + "%s:allcate cmdq callback work queue fail!\n", + __func__); + return; + } + } + + /* Request mailbox channels for each IMGSYS engine */ + for (idx = 0; idx < IMGSYS_ENG_MAX; idx++) { + imgsys_clt[idx] = kzalloc(sizeof(*imgsys_clt[idx]), GFP_KERNEL); + if (!imgsys_clt[idx]) + return; + + imgsys_clt[idx]->client.dev = dev; + imgsys_clt[idx]->client.tx_block = false; + imgsys_clt[idx]->client.knows_txdone = true; + imgsys_clt[idx]->client.rx_callback = imgsys_cmdq_task_cb; + imgsys_clt[idx]->chan = + mbox_request_channel(&imgsys_clt[idx]->client, idx); + } + + /* Parse events from dts */ + for (idx = 0; idx < IMGSYS_EVENT_MAX; idx++) + of_property_read_u16(dev->of_node, + imgsys_event[idx].dts_name, + &imgsys_event[idx].event); +} + +void imgsys_cmdq_release(struct mtk_imgsys_dev *imgsys_dev) +{ + u32 idx = 0; + + /* Destroy cmdq client */ + for (idx = 0; idx < IMGSYS_ENG_MAX; idx++) { + cmdq_mbox_destroy(imgsys_clt[idx]); + imgsys_clt[idx] = NULL; + } + + /* Release work_quque */ + flush_workqueue(imgsys_cmdq_wq); + destroy_workqueue(imgsys_cmdq_wq); + imgsys_cmdq_wq = NULL; +} + +void imgsys_cmdq_streamon(struct mtk_imgsys_dev *imgsys_dev) +{ + dev_info(imgsys_dev->dev, "%s: cmdq stream on (%d)\n", __func__, is_stream_off); + is_stream_off = 0; +} + +void imgsys_cmdq_streamoff(struct mtk_imgsys_dev *imgsys_dev) +{ + dev_info(imgsys_dev->dev, "%s: cmdq stream off (%d)\n", __func__, is_stream_off); + is_stream_off = 1; +} + +static void imgsys_cmdq_cmd_dump(struct swfrm_info *frm_info, u32 frm_idx) +{ + struct gce_recorder *cmd_buf = NULL; + struct command *cmd = NULL; + u32 cmd_num = 0; + u32 cmd_idx = 0; + + cmd_buf = (struct gce_recorder *)frm_info->user_info[frm_idx].g_swbuf; + cmd_num = cmd_buf->curr_length / sizeof(struct command); + + if (sizeof(struct gce_recorder) != (u64)cmd_buf->cmd_offset) { + pr_info("%s: [ERROR] cmd offset is not match (0x%x/0x%zx)!\n", + __func__, cmd_buf->cmd_offset, + sizeof(struct gce_recorder)); + return; + } + + cmd = (struct command *)((char *)(frm_info->user_info[frm_idx].g_swbuf) + + (unsigned long)(cmd_buf->cmd_offset)); + + for (cmd_idx = 0; cmd_idx < cmd_num; cmd_idx++) { + switch (cmd[cmd_idx].opcode) { + case IMGSYS_CMD_WRITE: + pr_info("WRITE with addr(0x%08llx) value(0x%08x) mask(0x%08x)\n", + cmd[cmd_idx].param.write.address, + cmd[cmd_idx].param.write.value, + cmd[cmd_idx].param.write.mask); + break; + case IMGSYS_CMD_POLL: + pr_info("POLL with addr(0x%08llx) value(0x%08x) mask(0x%08x)\n", + cmd[cmd_idx].param.poll.address, + cmd[cmd_idx].param.poll.value, + cmd[cmd_idx].param.poll.mask); + break; + case IMGSYS_CMD_WAIT: + pr_info("WAIT event(%d/%d) action(%d)\n", + cmd[cmd_idx].param.wait.event, + imgsys_event[cmd[cmd_idx].param.wait.event].event, + cmd[cmd_idx].param.wait.action); + break; + case IMGSYS_CMD_UPDATE: + pr_info("UPDATE event(%d/%d) action(%d)\n", + cmd[cmd_idx].param.update.event, + imgsys_event[cmd[cmd_idx].param.update.event].event, + cmd[cmd_idx].param.update.action); + break; + case IMGSYS_CMD_ACQUIRE: + pr_info("ACQUIRE event(%d/%d) action(%d)\n", + cmd[cmd_idx].param.acquire.event, + imgsys_event[cmd[cmd_idx].param.acquire.event].event, + cmd[cmd_idx].param.acquire.action); + break; + case IMGSYS_CMD_STOP: + pr_info("%s: End Of Cmd!\n", __func__); + break; + default: + pr_info("%s: [ERROR]Not Support Cmd(%d)!\n", + __func__, cmd[cmd_idx].opcode); + break; + } + } +} + +static void imgsys_cmdq_cb_work(struct work_struct *work) +{ + struct mtk_imgsys_cb_param *cb_param = NULL; + struct mtk_imgsys_dev *imgsys_dev = NULL; + u32 cb_frm_cnt; + + cb_param = container_of(work, struct mtk_imgsys_cb_param, cmdq_cb_work); + imgsys_dev = cb_param->imgsys_dev; + + if (cb_param->err != 0) { + pr_info("%s: [ERROR] cb(%p) cb_cnt(%d) req fd/no(%d/%d) error(%d).\n", + __func__, cb_param, + cb_param->frm_info->cb_frmcnt, + cb_param->frm_info->request_fd, + cb_param->frm_info->request_no, + cb_param->err); + + pr_info("%s: Frame Info: frm(%d/%d) blk(%d/%d) earlycb(%d) lst(%d/%d/%d).\n", + __func__, cb_param->frm_idx, cb_param->frm_num, + cb_param->blk_idx, cb_param->blk_num, cb_param->is_earlycb, + cb_param->is_blk_last, cb_param->is_frm_last, cb_param->is_task_last); + + pr_info("%s: CMDQ Info: task(%d/%d/%d) ofst(%zx/%zx/%zx/%zx/%zx).\n", + __func__, cb_param->task_id, cb_param->task_num, cb_param->task_cnt, + cb_param->pkt_ofst[0], cb_param->pkt_ofst[1], cb_param->pkt_ofst[2], + cb_param->pkt_ofst[3], cb_param->pkt_ofst[4]); + } + + if (is_stream_off == 1) + pr_info("%s: [ERROR] cb(%p) pipe already streamoff(%d)!\n", + __func__, cb_param, is_stream_off); + + cb_param->frm_info->cb_frmcnt++; + cb_frm_cnt = cb_param->frm_info->cb_frmcnt; + + if (cb_param->is_blk_last && cb_param->user_cmdq_cb && + (cb_param->frm_info->total_taskcnt == cb_frm_cnt || + cb_param->is_earlycb)) { + struct imgsys_cmdq_cb_data user_cb_data; + + user_cb_data.cmdq_data.sta = cb_param->err; + user_cb_data.cmdq_data.pkt = NULL; + user_cb_data.data = (void *)cb_param->frm_info; + cb_param->user_cmdq_cb(user_cb_data); + } + + cmdq_pkt_destroy(cb_param->clt, &cb_param->pkt); + vfree(cb_param); +} + +static void imgsys_cmdq_task_cb(struct mbox_client *cl, void *mssg) +{ + struct cmdq_cb_data *data = mssg; + struct mtk_imgsys_cb_param *cb_param = + container_of(data->pkt, struct mtk_imgsys_cb_param, pkt); + + struct mtk_imgsys_pipe *pipe; + u32 frm_idx = 0; + + cb_param->err = data->sta; + + pr_debug("%s: Receive cb(%p) with sta(%d) for frm(%d/%d)\n", + __func__, cb_param, data->sta, cb_param->frm_idx, + cb_param->frm_num); + + if (cb_param->err != 0) { + frm_idx = cb_param->frm_idx; + pr_info("%s: [ERROR] cb(%p) error info(%d).\n", + __func__, cb_param, cb_param->err); + + pr_info("%s: Frame Info: frm(%d/%d) blk(%d/%d) earlycb(%d) lst(%d/%d/%d).\n", + __func__, cb_param->frm_idx, cb_param->frm_num, + cb_param->blk_idx, cb_param->blk_num, cb_param->is_earlycb, + cb_param->is_blk_last, cb_param->is_frm_last, cb_param->is_task_last); + + pr_info("%s: CMDQ Info: task(%d/%d/%d) ofst(%zx/%zx/%zx/%zx/%zx).\n", + __func__, cb_param->task_id, cb_param->task_num, cb_param->task_cnt, + cb_param->pkt_ofst[0], cb_param->pkt_ofst[1], cb_param->pkt_ofst[2], + cb_param->pkt_ofst[3], cb_param->pkt_ofst[4]); + + if (is_stream_off == 1) + pr_info("%s: [ERROR] cb(%p) pipe had been turned off(%d)!\n", + __func__, cb_param, is_stream_off); + + pipe = (struct mtk_imgsys_pipe *)cb_param->frm_info->pipe; + if (!pipe->streaming) { + pr_info("%s: [ERROR] cb(%p): pipe already streamoff\n", + __func__, cb_param); + } + + imgsys_cmdq_cmd_dump(cb_param->frm_info, frm_idx); + } + + INIT_WORK(&cb_param->cmdq_cb_work, imgsys_cmdq_cb_work); + queue_work(imgsys_cmdq_wq, &cb_param->cmdq_cb_work); +} + +static int imgsys_cmdq_parser(struct cmdq_pkt *pkt, + struct command *cmd, u32 cmd_num) +{ + bool stop = false; + int count = 0; + u32 event_id; + + do { + switch (cmd->opcode) { + case IMGSYS_CMD_WRITE: + if (cmd->param.write.address < IMGSYS_REG_START || + cmd->param.write.address > IMGSYS_REG_END) { + pr_info("%s: [ERROR] WRITE: wrong address(0x%08llx)!\n", + __func__, cmd->param.poll.address); + return -1; + } + pr_debug("%s: WRITE with addr(0x%08llx) value(0x%08x) mask(0x%08x)\n", + __func__, cmd->param.write.address, + cmd->param.write.value, + cmd->param.write.mask); + + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX0, + CMDQ_ADDR_HIGH(cmd->param.write.address)); + if (cmd->param.write.mask != GENMASK(31, 0)) + cmdq_pkt_write_s_mask_value(pkt, CMDQ_THR_SPR_IDX0, + CMDQ_ADDR_LOW(cmd->param.write.address), + cmd->param.write.value, + cmd->param.write.mask); + else + cmdq_pkt_write_s_value(pkt, CMDQ_THR_SPR_IDX0, + CMDQ_ADDR_LOW(cmd->param.write.address), + cmd->param.write.value); + break; + case IMGSYS_CMD_POLL: + if (cmd->param.poll.address < IMGSYS_REG_START || + cmd->param.poll.address > IMGSYS_REG_END) { + pr_info("%s: [ERROR] POLL: wrong address(0x%08llx)!\n", + __func__, cmd->param.poll.address); + return -1; + } + pr_debug("%s: POLL with addr(0x%08llx) value(0x%08x) mask(0x%08x)\n", + __func__, cmd->param.poll.address, + cmd->param.poll.value, cmd->param.poll.mask); + + cmdq_pkt_poll_addr(pkt, cmd->param.poll.address, + cmd->param.poll.value, + cmd->param.poll.mask); + break; + case IMGSYS_CMD_WAIT: + event_id = cmd->param.wait.event; + if (event_id >= IMGSYS_EVENT_MAX) { + pr_info("%s: [ERROR] WAIT: wrong event(%d)!\n", + __func__, event_id); + return -1; + } + pr_debug("%s: WAIT event(%d/%d) action(%d)\n", + __func__, event_id, + imgsys_event[event_id].event, + cmd->param.wait.action); + + if (cmd->param.wait.action == 1) + cmdq_pkt_wfe(pkt, imgsys_event[event_id].event, true); + else if (cmd->param.wait.action == 0) + cmdq_pkt_wfe(pkt, imgsys_event[event_id].event, false); + + break; + case IMGSYS_CMD_UPDATE: + event_id = cmd->param.update.event; + if (event_id >= IMGSYS_EVENT_MAX) { + pr_info("%s: [ERROR] UPDATE: wrong event(%d)!\n", + __func__, event_id); + return -1; + } + + pr_debug("%s: UPDATE event(%d/%d) action(%d)\n", + __func__, event_id, + imgsys_event[event_id].event, + cmd->param.update.action); + + if (cmd->param.update.action == 1) + cmdq_pkt_set_event(pkt, imgsys_event[event_id].event); + else if (cmd->param.update.action == 0) + cmdq_pkt_clear_event(pkt, imgsys_event[event_id].event); + + break; + case IMGSYS_CMD_ACQUIRE: + event_id = cmd->param.acquire.event; + if (event_id >= IMGSYS_EVENT_MAX) { + pr_info("%s: [ERROR] ACQUIRE: wrong event(%d)!\n", + __func__, event_id); + return -1; + } + + pr_debug("%s: ACQUIRE event(%d/%d) action(%d)\n", + __func__, event_id, + imgsys_event[event_id].event, + cmd->param.acquire.action); + + cmdq_pkt_acquire_event(pkt, imgsys_event[event_id].event); + break; + case IMGSYS_CMD_STOP: + pr_debug("%s: End Of Cmd!\n", __func__); + stop = true; + break; + default: + pr_info("%s: [ERROR] Not Support Cmd(%d)!\n", __func__, cmd->opcode); + return -1; + } + cmd++; + count++; + } while ((!stop) && (count < cmd_num)); + + return count; +} + +int imgsys_cmdq_sendtask(struct mtk_imgsys_dev *imgsys_dev, + struct swfrm_info *frm_info, + void (*cmdq_cb)(struct imgsys_cmdq_cb_data data)) +{ + struct cmdq_client *clt = NULL; + struct gce_recorder *cmd_buf = NULL; + struct command *cmd = NULL; + struct mtk_imgsys_cb_param *cb_param = NULL; + u32 cmd_num = 0; + u32 cmd_idx = 0; + u32 blk_idx = 0; /* For Vss block cnt */ + u32 thd_idx = 0; + u32 hw_comb = 0; + int ret = 0, ret_flush = 0; + u32 frm_num = 0, frm_idx = 0; + bool is_pack = 0; + u32 task_idx = 0; + u32 task_id = 0; + u32 task_num = 0; + u32 task_cnt = 0; + size_t pkt_ofst[MAX_FRAME_IN_TASK] = {0}; + + frm_num = frm_info->total_frmnum; + frm_info->cb_frmcnt = 0; + frm_info->total_taskcnt = 0; + + for (frm_idx = 0; frm_idx < frm_num; frm_idx++) { + cmd_buf = (struct gce_recorder *)frm_info->user_info[frm_idx].g_swbuf; + + /* Validate the GCE recorder structure */ + if (cmd_buf->header_code != HEADER_CODE || + cmd_buf->check_pre != CHECK_PRE || + cmd_buf->check_post != CHECK_POST || + cmd_buf->footer_code != FOOTER_CODE) { + pr_info("%s: Incorrect guard word: %08x/%08x/%08x/%08x", + __func__, cmd_buf->header_code, cmd_buf->check_pre, + cmd_buf->check_post, cmd_buf->footer_code); + return -1; + } + + cmd_num = cmd_buf->curr_length / sizeof(struct command); + cmd = (struct command *)((char *)frm_info->user_info[frm_idx].g_swbuf + + (unsigned long)cmd_buf->cmd_offset); + + hw_comb = frm_info->user_info[frm_idx].hw_comb; + + if (is_pack == 0) { + if (frm_info->group_id == -1) { + /* Choose cmdq_client base on hw scenario */ + for (thd_idx = 0; thd_idx < IMGSYS_ENG_MAX; thd_idx++) { + if (hw_comb & 0x1) { + clt = imgsys_clt[thd_idx]; + pr_debug("%s: mbox thread (%d, %p)\n", + __func__, thd_idx, clt); + pr_debug("%s: frm(%d/%d)\n", + __func__, frm_idx, frm_num); + break; + } + hw_comb = hw_comb >> 1; + } + /* This segment can be removed since user had set dependency */ + if (frm_info->user_info[frm_idx].hw_comb & IMGSYS_ENG_DIP) { + thd_idx = 4; + clt = imgsys_clt[thd_idx]; + } + } else { + if (frm_info->group_id >= 0 && + frm_info->group_id < IMGSYS_NOR_THD) { + thd_idx = frm_info->group_id; + clt = imgsys_clt[thd_idx]; + } else { + pr_info("%s: [ERROR] Group id(%d) is not in range(%d).\n", + __func__, frm_info->group_id, IMGSYS_NOR_THD); + pr_info("%s: [ERROR] Frame Info: frm(%d/%d) hw_comb(%d).\n", + __func__, frm_idx, frm_num, + frm_info->user_info[frm_idx].hw_comb); + return -1; + } + } + + /* This is work around for low latency flow. */ + /* If we change to request base, */ + /* we don't have to take this condition into account. */ + if (frm_info->sync_id != -1) { + thd_idx = 0; + clt = imgsys_clt[thd_idx]; + } + + if (!clt) { + pr_info("%s: [ERROR] No HW Found (0x%x) for frm(%d/%d)!\n", + __func__, frm_info->user_info[frm_idx].hw_comb, + frm_idx, frm_num); + return -1; + } + } + + cmd_idx = 0; + + for (blk_idx = 0; blk_idx < cmd_buf->frame_block; blk_idx++) { + if (is_pack == 0) { + /* Prepare cb param */ + cb_param = vzalloc(sizeof(*cb_param)); + if (!cb_param) + return -1; + + /* create pkt and hook clt as pkt's private data */ + if (cmdq_pkt_create(clt, &cb_param->pkt, CMDQ_BUF_SIZE)) { + vfree(cb_param); + pr_info("%s: [ERROR] Id %d imgsys_create_pkt fail!\n", + __func__, blk_idx); + return -1; + } + } + + ret = imgsys_cmdq_parser(&cb_param->pkt, &cmd[cmd_idx], cmd_num); + + if (ret < 0) { + pr_info("%s: [ERROR] Parsing fail. cmd(%d/%d) frm(%d/%d/%d)\n", + __func__, cmd_idx, cmd[cmd_idx].opcode, + blk_idx, frm_idx, frm_num); + + cmdq_pkt_destroy(clt, &cb_param->pkt); + vfree(cb_param); + goto sendtask_done; + } + cmd_idx += ret; + + /* Check for packing gce task */ + pkt_ofst[task_cnt] = cb_param->pkt.cmd_buf_size - CMDQ_INST_SIZE; + task_cnt++; + if (frm_info->user_info[frm_idx].is_time_shared || + frm_info->user_info[frm_idx].is_earlycb || + frm_idx + 1 == frm_num) { + task_num++; + cb_param->frm_info = frm_info; + cb_param->frm_idx = frm_idx; + cb_param->frm_num = frm_num; + cb_param->user_cmdq_cb = cmdq_cb; + if ((blk_idx + 1) == cmd_buf->frame_block) + cb_param->is_blk_last = 1; + else + cb_param->is_blk_last = 0; + if ((frm_idx + 1) == frm_num) + cb_param->is_frm_last = 1; + else + cb_param->is_frm_last = 0; + cb_param->blk_idx = blk_idx; + cb_param->blk_num = cmd_buf->frame_block; + cb_param->is_earlycb = frm_info->user_info[frm_idx].is_earlycb; + cb_param->group_id = frm_info->group_id; + cb_param->imgsys_dev = imgsys_dev; + cb_param->thd_idx = thd_idx; + cb_param->clt = clt; + cb_param->task_cnt = task_cnt; + for (task_idx = 0; task_idx < task_cnt; task_idx++) + cb_param->pkt_ofst[task_idx] = pkt_ofst[task_idx]; + task_cnt = 0; + cb_param->task_id = task_id; + task_id++; + if (cb_param->is_blk_last && cb_param->is_frm_last) { + cb_param->is_task_last = 1; + cb_param->task_num = task_num; + frm_info->total_taskcnt = task_num; + } else { + cb_param->is_task_last = 0; + cb_param->task_num = 0; + } + + /* flush synchronized, block API */ + cmdq_pkt_eoc(&cb_param->pkt); + cmdq_pkt_jump_rel(&cb_param->pkt, CMDQ_INST_SIZE, + cmdq_get_shift_pa(clt->chan)); + dma_sync_single_for_device(clt->chan->mbox->dev, + cb_param->pkt.pa_base, + cb_param->pkt.cmd_buf_size, + DMA_TO_DEVICE); + + mbox_send_message(clt->chan, &cb_param->pkt); + mbox_client_txdone(clt->chan, 0); + if (ret_flush < 0) + pr_info("%s: [ERROR] Frame(%d/%d) flushing fail(%d).\n", + __func__, ret_flush, frm_idx, frm_num); + is_pack = 0; + } else { + dev_info(imgsys_dev->dev, "%s:is_pack = 1", __func__); + is_pack = 1; + } + } + } + +sendtask_done: + return 0; +} diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.h new file mode 100644 index 000000000000..47bbd6735d0b --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-cmdq.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 MediaTek Inc. + * + * Author: Daniel Huang + * + */ +#ifndef _MTK_IMGSYS_CMDQ_H_ +#define _MTK_IMGSYS_CMDQ_H_ + +#include +#include +#include "mtk_imgsys-dev.h" + +/* Structure to hold command queue callback data */ +struct imgsys_cmdq_cb_data { + struct cmdq_cb_data cmdq_data; /* Command queue data */ + void *data; /* Additional data */ +}; + +void imgsys_cmdq_streamon(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_cmdq_streamoff(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_cmdq_init(struct mtk_imgsys_dev *imgsys_dev); +void imgsys_cmdq_release(struct mtk_imgsys_dev *imgsys_dev); +int imgsys_cmdq_sendtask(struct mtk_imgsys_dev *imgsys_dev, + struct swfrm_info *frm_info, + void (*cmdq_cb)(struct imgsys_cmdq_cb_data data)); + +#endif /* _MTK_IMGSYS_CMDQ_H_ */ diff --git a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h index dd02a8fa28d4..3918e360a5a0 100644 --- a/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h +++ b/drivers/media/platform/mediatek/isp/isp_7x/imgsys/mtk_imgsys-module_common.h @@ -39,6 +39,26 @@ #define CQ_THRX_CTL_MODE BIT(4) #define CQ_THRX_CTL (CQ_THRX_CTL_EN | CQ_THRX_CTL_MODE) +/** + * enum mtk_imgsys_engine_bitmask - Bitmasks for supported hardware engines + * + * This enumeration defines the bitmasks for the supported hardware engines in + * the image system. + */ +enum mtk_imgsys_engine_bitmask { + IMGSYS_ENG_WPE_EIS = 0x00000001, /* Bitmask for WPE EIS engine */ + IMGSYS_ENG_WPE_TNR = 0x00000002, /* Bitmask for WPE TNR engine */ + IMGSYS_ENG_WPE_LITE = 0x00000004, /* Bitmask for WPE Lite engine */ + IMGSYS_ENG_TRAW = 0x00000020, /* Bitmask for TRAW engine */ + IMGSYS_ENG_LTR = 0x00000040, /* Bitmask for LTR engine */ + IMGSYS_ENG_XTR = 0x00000080, /* Bitmask for XTR engine */ + IMGSYS_ENG_DIP = 0x00000100, /* Bitmask for DIP engine */ + IMGSYS_ENG_PQDIP_A = 0x00000200, /* Bitmask for PQDIP A engine */ + IMGSYS_ENG_PQDIP_B = 0x00000400, /* Bitmask for PQDIP B engine */ + IMGSYS_ENG_ME = 0x00000800, /* Bitmask for ME engine */ + IMGSYS_ENG_MAX_NUM = 0x00001000 /* Maximum bitmask value */ +}; + /** * enum mtk_imgsys_reg_id * 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 index 9f118491b37d..184f0e3a4d3b 100644 --- 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 @@ -9,6 +9,7 @@ #include #include "mtk_imgsys-sys.h" #include "mtk_imgsys-dev.h" +#include "mtk_imgsys-cmdq.h" static int mtk_imgsys_hw_connect(struct mtk_imgsys_dev *imgsys_dev) { @@ -26,6 +27,8 @@ static int mtk_imgsys_hw_connect(struct mtk_imgsys_dev *imgsys_dev) kref_init(&imgsys_dev->init_kref); + /* calling cmdq stream on */ + imgsys_cmdq_streamon(imgsys_dev); return 0; } @@ -43,6 +46,8 @@ static void module_uninit(struct kref *kref) static void mtk_imgsys_hw_disconnect(struct mtk_imgsys_dev *imgsys_dev) { + /* calling cmdq stream off */ + imgsys_cmdq_streamoff(imgsys_dev); kref_put(&imgsys_dev->init_kref, module_uninit); }