From patchwork Wed Jun 23 07:35:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339139 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E968C48BC2 for ; Wed, 23 Jun 2021 07:36:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E99E7611AC for ; Wed, 23 Jun 2021 07:36:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230151AbhFWHiR (ORCPT ); Wed, 23 Jun 2021 03:38:17 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:46935 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S229906AbhFWHiQ (ORCPT ); Wed, 23 Jun 2021 03:38:16 -0400 X-UUID: e54e2cfa3aaf4e9babab47bf2b06f007-20210623 X-UUID: e54e2cfa3aaf4e9babab47bf2b06f007-20210623 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1527834436; Wed, 23 Jun 2021 15:35:53 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n1.mediatek.inc (172.21.101.68) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:51 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:51 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 01/10] media: mtk-mdp3: Add Mediatek MDP Driver Date: Wed, 23 Jun 2021 15:35:40 +0800 Message-ID: <20210623073549.24170-1-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: mtk18742 Add MDP driver for MT8183 Signed-off-by: Moudy Ho --- drivers/media/platform/Kconfig | 17 + drivers/media/platform/Makefile | 2 + drivers/media/platform/mtk-mdp3/Makefile | 9 + drivers/media/platform/mtk-mdp3/isp_reg.h | 37 + .../media/platform/mtk-mdp3/mdp-platform.h | 58 + .../media/platform/mtk-mdp3/mdp_reg_ccorr.h | 75 + .../media/platform/mtk-mdp3/mdp_reg_rdma.h | 206 +++ drivers/media/platform/mtk-mdp3/mdp_reg_rsz.h | 109 ++ .../media/platform/mtk-mdp3/mdp_reg_wdma.h | 125 ++ .../media/platform/mtk-mdp3/mdp_reg_wrot.h | 115 ++ .../media/platform/mtk-mdp3/mmsys_config.h | 188 +++ drivers/media/platform/mtk-mdp3/mmsys_mutex.h | 35 + .../media/platform/mtk-mdp3/mmsys_reg_base.h | 38 + drivers/media/platform/mtk-mdp3/mtk-img-ipi.h | 282 ++++ .../media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 521 +++++++ .../media/platform/mtk-mdp3/mtk-mdp3-cmdq.h | 54 + .../media/platform/mtk-mdp3/mtk-mdp3-comp.c | 1329 +++++++++++++++++ .../media/platform/mtk-mdp3/mtk-mdp3-comp.h | 155 ++ .../media/platform/mtk-mdp3/mtk-mdp3-core.c | 282 ++++ .../media/platform/mtk-mdp3/mtk-mdp3-core.h | 86 ++ .../media/platform/mtk-mdp3/mtk-mdp3-debug.c | 973 ++++++++++++ .../media/platform/mtk-mdp3/mtk-mdp3-debug.h | 39 + .../media/platform/mtk-mdp3/mtk-mdp3-m2m.c | 804 ++++++++++ .../media/platform/mtk-mdp3/mtk-mdp3-m2m.h | 42 + .../media/platform/mtk-mdp3/mtk-mdp3-regs.c | 748 ++++++++++ .../media/platform/mtk-mdp3/mtk-mdp3-regs.h | 373 +++++ .../media/platform/mtk-mdp3/mtk-mdp3-vpu.c | 313 ++++ .../media/platform/mtk-mdp3/mtk-mdp3-vpu.h | 79 + 28 files changed, 7094 insertions(+) create mode 100644 drivers/media/platform/mtk-mdp3/Makefile create mode 100644 drivers/media/platform/mtk-mdp3/isp_reg.h create mode 100644 drivers/media/platform/mtk-mdp3/mdp-platform.h create mode 100644 drivers/media/platform/mtk-mdp3/mdp_reg_ccorr.h create mode 100644 drivers/media/platform/mtk-mdp3/mdp_reg_rdma.h create mode 100644 drivers/media/platform/mtk-mdp3/mdp_reg_rsz.h create mode 100644 drivers/media/platform/mtk-mdp3/mdp_reg_wdma.h create mode 100644 drivers/media/platform/mtk-mdp3/mdp_reg_wrot.h create mode 100644 drivers/media/platform/mtk-mdp3/mmsys_config.h create mode 100644 drivers/media/platform/mtk-mdp3/mmsys_mutex.h create mode 100644 drivers/media/platform/mtk-mdp3/mmsys_reg_base.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-img-ipi.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.c create mode 100644 drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.h diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 157c924686e4..dd2d3f0f732f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -299,6 +299,23 @@ config VIDEO_MEDIATEK_MDP To compile this driver as a module, choose M here: the module will be called mtk-mdp. +config VIDEO_MEDIATEK_MDP3 + tristate "Mediatek MDP3 driver" + depends on MTK_IOMMU || COMPILE_TEST + depends on VIDEO_DEV && VIDEO_V4L2 + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on MTK_SCP && MTK_CMDQ + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + select VIDEO_MEDIATEK_VPU + help + It is a v4l2 driver and present in Mediatek MT8183 SoCs. + The driver supports for scaling and color space conversion. + Supports ISP PASS2(DIP) direct link for yuv image output. + + To compile this driver as a module, choose M here: the + module will be called mtk-mdp3. + config VIDEO_MEDIATEK_VCODEC tristate "Mediatek Video Codec driver" depends on MTK_IOMMU || COMPILE_TEST diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index eedc14aafb32..4d65f8fb75f6 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -76,6 +76,8 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec/ obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp/ +obj-$(CONFIG_VIDEO_MEDIATEK_MDP3) += mtk-mdp3/ + obj-$(CONFIG_VIDEO_MEDIATEK_JPEG) += mtk-jpeg/ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/ diff --git a/drivers/media/platform/mtk-mdp3/Makefile b/drivers/media/platform/mtk-mdp3/Makefile new file mode 100644 index 000000000000..3c1ccb36ea9f --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +mtk-mdp3-y += mtk-mdp3-core.o mtk-mdp3-vpu.o mtk-mdp3-regs.o +mtk-mdp3-y += mtk-mdp3-m2m.o +mtk-mdp3-y += mtk-mdp3-comp.o mtk-mdp3-cmdq.o + +mtk-mdp3-y += mtk-mdp3-debug.o + +obj-$(CONFIG_VIDEO_MEDIATEK_MDP3) += mtk-mdp3.o + diff --git a/drivers/media/platform/mtk-mdp3/isp_reg.h b/drivers/media/platform/mtk-mdp3/isp_reg.h new file mode 100644 index 000000000000..a8b2f22bae8c --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/isp_reg.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __ISP_REG_H__ +#define __ISP_REG_H__ + +enum ISP_DIP_CQ { + ISP_DRV_DIP_CQ_THRE0 = 0, + ISP_DRV_DIP_CQ_THRE1, + ISP_DRV_DIP_CQ_THRE2, + ISP_DRV_DIP_CQ_THRE3, + ISP_DRV_DIP_CQ_THRE4, + ISP_DRV_DIP_CQ_THRE5, + ISP_DRV_DIP_CQ_THRE6, + ISP_DRV_DIP_CQ_THRE7, + ISP_DRV_DIP_CQ_THRE8, + ISP_DRV_DIP_CQ_THRE9, + ISP_DRV_DIP_CQ_THRE10, + ISP_DRV_DIP_CQ_THRE11, + ISP_DRV_DIP_CQ_NUM, + ISP_DRV_DIP_CQ_NONE, + /* we only need 12 CQ threads in this chip, + *so we move the following enum behind ISP_DRV_DIP_CQ_NUM + */ + ISP_DRV_DIP_CQ_THRE12, + ISP_DRV_DIP_CQ_THRE13, + ISP_DRV_DIP_CQ_THRE14, + ISP_DRV_DIP_CQ_THRE15, /* CQ_THREAD15 does not connect to GCE */ + ISP_DRV_DIP_CQ_THRE16, /* CQ_THREAD16 does not connect to GCE */ + ISP_DRV_DIP_CQ_THRE17, /* CQ_THREAD17 does not connect to GCE */ + ISP_DRV_DIP_CQ_THRE18, /* CQ_THREAD18 does not connect to GCE */ +}; + +#endif // __ISP_REG_H__ diff --git a/drivers/media/platform/mtk-mdp3/mdp-platform.h b/drivers/media/platform/mtk-mdp3/mdp-platform.h new file mode 100644 index 000000000000..d474580306b7 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mdp-platform.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MDP_PLATFORM_H__ +#define __MDP_PLATFORM_H__ + +#include "mtk-mdp3-comp.h" + +/* CAM */ +#define MDP_WPEI MDP_COMP_WPEI +#define MDP_WPEO MDP_COMP_WPEO +#define MDP_WPEI2 MDP_COMP_WPEI2 +#define MDP_WPEO2 MDP_COMP_WPEO2 +#define MDP_IMGI MDP_COMP_ISP_IMGI +#define MDP_IMGO MDP_COMP_ISP_IMGO +#define MDP_IMG2O MDP_COMP_ISP_IMG2O + +/* IPU */ +#define MDP_IPUI MDP_COMP_NONE +#define MDP_IPUO MDP_COMP_NONE + +/* MDP */ +#define MDP_CAMIN MDP_COMP_CAMIN +#define MDP_CAMIN2 MDP_COMP_CAMIN2 +#define MDP_RDMA0 MDP_COMP_RDMA0 +#define MDP_RDMA1 MDP_COMP_NONE +#define MDP_AAL0 MDP_COMP_AAL0 +#define MDP_CCORR0 MDP_COMP_CCORR0 +#define MDP_SCL0 MDP_COMP_RSZ0 +#define MDP_SCL1 MDP_COMP_RSZ1 +#define MDP_SCL2 MDP_COMP_NONE +#define MDP_TDSHP0 MDP_COMP_TDSHP0 +#define MDP_COLOR0 MDP_COMP_COLOR0 +#define MDP_WROT0 MDP_COMP_WROT0 +#define MDP_WROT1 MDP_COMP_NONE +#define MDP_WDMA MDP_COMP_WDMA +#define MDP_PATH0_SOUT MDP_COMP_PATH0_SOUT +#define MDP_PATH1_SOUT MDP_COMP_PATH1_SOUT + +#define MDP_TOTAL (MDP_COMP_WDMA + 1) + +/* Platform options */ +#define ESL_SETTING 1 +#define RDMA_SUPPORT_10BIT 1 +#define RDMA0_RSZ1_SRAM_SHARING 1 +#define RDMA_UPSAMPLE_REPEAT_ONLY 1 +#define RSZ_DISABLE_DCM_SMALL_TILE 0 +#define WROT_FILTER_CONSTRAINT 0 +#define WROT0_DISP_SRAM_SHARING 0 + +#define MM_MUTEX_MOD_OFFSET 0x30 +#define MM_MUTEX_SOF_OFFSET 0x2c + +#endif /* __MDP_PLATFORM_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mdp_reg_ccorr.h b/drivers/media/platform/mtk-mdp3/mdp_reg_ccorr.h new file mode 100644 index 000000000000..2e8624446502 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mdp_reg_ccorr.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MDP_REG_CCORR_H__ +#define __MDP_REG_CCORR_H__ + +#include "mmsys_reg_base.h" + +#define MDP_CCORR_EN 0x000 +#define MDP_CCORR_RESET 0x004 +#define MDP_CCORR_INTEN 0x008 +#define MDP_CCORR_INTSTA 0x00c +#define MDP_CCORR_STATUS 0x010 +#define MDP_CCORR_CFG 0x020 +#define MDP_CCORR_INPUT_COUNT 0x024 +#define MDP_CCORR_OUTPUT_COUNT 0x028 +#define MDP_CCORR_CHKSUM 0x02c +#define MDP_CCORR_SIZE 0x030 +#define MDP_CCORR_Y2R_00 0x034 +#define MDP_CCORR_Y2R_01 0x038 +#define MDP_CCORR_Y2R_02 0x03c +#define MDP_CCORR_Y2R_03 0x040 +#define MDP_CCORR_Y2R_04 0x044 +#define MDP_CCORR_Y2R_05 0x048 +#define MDP_CCORR_R2Y_00 0x04c +#define MDP_CCORR_R2Y_01 0x050 +#define MDP_CCORR_R2Y_02 0x054 +#define MDP_CCORR_R2Y_03 0x058 +#define MDP_CCORR_R2Y_04 0x05c +#define MDP_CCORR_R2Y_05 0x060 +#define MDP_CCORR_COEF_0 0x080 +#define MDP_CCORR_COEF_1 0x084 +#define MDP_CCORR_COEF_2 0x088 +#define MDP_CCORR_COEF_3 0x08c +#define MDP_CCORR_COEF_4 0x090 +#define MDP_CCORR_SHADOW 0x0a0 +#define MDP_CCORR_DUMMY_REG 0x0c0 +#define MDP_CCORR_ATPG 0x0fc + +/* MASK */ +#define MDP_CCORR_EN_MASK 0x00000001 +#define MDP_CCORR_RESET_MASK 0x00000001 +#define MDP_CCORR_INTEN_MASK 0x00000003 +#define MDP_CCORR_INTSTA_MASK 0x00000003 +#define MDP_CCORR_STATUS_MASK 0xfffffff3 +#define MDP_CCORR_CFG_MASK 0x70001317 +#define MDP_CCORR_INPUT_COUNT_MASK 0x1fff1fff +#define MDP_CCORR_OUTPUT_COUNT_MASK 0x1fff1fff +#define MDP_CCORR_CHKSUM_MASK 0xffffffff +#define MDP_CCORR_SIZE_MASK 0x1fff1fff +#define MDP_CCORR_Y2R_00_MASK 0x01ff01ff +#define MDP_CCORR_Y2R_01_MASK 0x1fff01ff +#define MDP_CCORR_Y2R_02_MASK 0x1fff1fff +#define MDP_CCORR_Y2R_03_MASK 0x1fff1fff +#define MDP_CCORR_Y2R_04_MASK 0x1fff1fff +#define MDP_CCORR_Y2R_05_MASK 0x1fff1fff +#define MDP_CCORR_R2Y_00_MASK 0x01ff01ff +#define MDP_CCORR_R2Y_01_MASK 0x07ff01ff +#define MDP_CCORR_R2Y_02_MASK 0x07ff07ff +#define MDP_CCORR_R2Y_03_MASK 0x07ff07ff +#define MDP_CCORR_R2Y_04_MASK 0x07ff07ff +#define MDP_CCORR_R2Y_05_MASK 0x07ff07ff +#define MDP_CCORR_COEF_0_MASK 0x1fff1fff +#define MDP_CCORR_COEF_1_MASK 0x1fff1fff +#define MDP_CCORR_COEF_2_MASK 0x1fff1fff +#define MDP_CCORR_COEF_3_MASK 0x1fff1fff +#define MDP_CCORR_COEF_4_MASK 0x1fff1fff +#define MDP_CCORR_SHADOW_MASK 0x00000007 +#define MDP_CCORR_DUMMY_REG_MASK 0xffffffff +#define MDP_CCORR_ATPG_MASK 0x00000003 + +#endif // __MDP_REG_CCORR_H__ diff --git a/drivers/media/platform/mtk-mdp3/mdp_reg_rdma.h b/drivers/media/platform/mtk-mdp3/mdp_reg_rdma.h new file mode 100644 index 000000000000..d7f5d9275d6d --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mdp_reg_rdma.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MDP_REG_RDMA_H__ +#define __MDP_REG_RDMA_H__ + +#include "mmsys_reg_base.h" + +#define MDP_RDMA_EN 0x000 +#define MDP_RDMA_RESET 0x008 +#define MDP_RDMA_INTERRUPT_ENABLE 0x010 +#define MDP_RDMA_INTERRUPT_STATUS 0x018 +#define MDP_RDMA_CON 0x020 +#define MDP_RDMA_GMCIF_CON 0x028 +#define MDP_RDMA_SRC_CON 0x030 +#define MDP_RDMA_SRC_BASE_0 0xf00 +#define MDP_RDMA_SRC_BASE_1 0xf08 +#define MDP_RDMA_SRC_BASE_2 0xf10 +#define MDP_RDMA_UFO_DEC_LENGTH_BASE_Y 0xf20 +#define MDP_RDMA_UFO_DEC_LENGTH_BASE_C 0xf28 +#define MDP_RDMA_MF_BKGD_SIZE_IN_BYTE 0x060 +#define MDP_RDMA_MF_BKGD_SIZE_IN_PXL 0x068 +#define MDP_RDMA_MF_SRC_SIZE 0x070 +#define MDP_RDMA_MF_CLIP_SIZE 0x078 +#define MDP_RDMA_MF_OFFSET_1 0x080 +#define MDP_RDMA_MF_PAR 0x088 +#define MDP_RDMA_SF_BKGD_SIZE_IN_BYTE 0x090 +#define MDP_RDMA_SF_PAR 0x0b8 +#define MDP_RDMA_MB_DEPTH 0x0c0 +#define MDP_RDMA_MB_BASE 0x0c8 +#define MDP_RDMA_MB_CON 0x0d0 +#define MDP_RDMA_SB_DEPTH 0x0d8 +#define MDP_RDMA_SB_BASE 0x0e0 +#define MDP_RDMA_SB_CON 0x0e8 +#define MDP_RDMA_VC1_RANGE 0x0f0 +#define MDP_RDMA_SRC_END_0 0x100 +#define MDP_RDMA_SRC_END_1 0x108 +#define MDP_RDMA_SRC_END_2 0x110 +#define MDP_RDMA_SRC_OFFSET_0 0x118 +#define MDP_RDMA_SRC_OFFSET_1 0x120 +#define MDP_RDMA_SRC_OFFSET_2 0x128 +#define MDP_RDMA_SRC_OFFSET_W_0 0x130 +#define MDP_RDMA_SRC_OFFSET_W_1 0x138 +#define MDP_RDMA_SRC_OFFSET_W_2 0x140 +#define MDP_RDMA_SRC_OFFSET_0_P 0x148 +#define MDP_RDMA_TRANSFORM_0 0x200 +#define MDP_RDMA_TRANSFORM_1 0x208 +#define MDP_RDMA_TRANSFORM_2 0x210 +#define MDP_RDMA_TRANSFORM_3 0x218 +#define MDP_RDMA_TRANSFORM_4 0x220 +#define MDP_RDMA_TRANSFORM_5 0x228 +#define MDP_RDMA_TRANSFORM_6 0x230 +#define MDP_RDMA_TRANSFORM_7 0x238 +#define MDP_RDMA_DMABUF_CON_0 0x240 +#define MDP_RDMA_DMAULTRA_CON_0 0x248 +#define MDP_RDMA_DMABUF_CON_1 0x250 +#define MDP_RDMA_DMAULTRA_CON_1 0x258 +#define MDP_RDMA_DMABUF_CON_2 0x260 +#define MDP_RDMA_DMAULTRA_CON_2 0x268 +#define MDP_RDMA_DITHER_CON 0x288 +#define MDP_RDMA_RESV_DUMMY_0 0x2a0 +#define MDP_RDMA_CHKS_EXTR 0x300 +#define MDP_RDMA_CHKS_INTW 0x308 +#define MDP_RDMA_CHKS_INTR 0x310 +#define MDP_RDMA_CHKS_ROTO 0x318 +#define MDP_RDMA_CHKS_SRIY 0x320 +#define MDP_RDMA_CHKS_SRIU 0x328 +#define MDP_RDMA_CHKS_SRIV 0x330 +#define MDP_RDMA_CHKS_SROY 0x338 +#define MDP_RDMA_CHKS_SROU 0x340 +#define MDP_RDMA_CHKS_SROV 0x348 +#define MDP_RDMA_CHKS_VUPI 0x350 +#define MDP_RDMA_CHKS_VUPO 0x358 +#define MDP_RDMA_DEBUG_CON 0x380 +#define MDP_RDMA_MON_STA_0 0x400 +#define MDP_RDMA_MON_STA_1 0x408 +#define MDP_RDMA_MON_STA_2 0x410 +#define MDP_RDMA_MON_STA_3 0x418 +#define MDP_RDMA_MON_STA_4 0x420 +#define MDP_RDMA_MON_STA_5 0x428 +#define MDP_RDMA_MON_STA_6 0x430 +#define MDP_RDMA_MON_STA_7 0x438 +#define MDP_RDMA_MON_STA_8 0x440 +#define MDP_RDMA_MON_STA_9 0x448 +#define MDP_RDMA_MON_STA_10 0x450 +#define MDP_RDMA_MON_STA_11 0x458 +#define MDP_RDMA_MON_STA_12 0x460 +#define MDP_RDMA_MON_STA_13 0x468 +#define MDP_RDMA_MON_STA_14 0x470 +#define MDP_RDMA_MON_STA_15 0x478 +#define MDP_RDMA_MON_STA_16 0x480 +#define MDP_RDMA_MON_STA_17 0x488 +#define MDP_RDMA_MON_STA_18 0x490 +#define MDP_RDMA_MON_STA_19 0x498 +#define MDP_RDMA_MON_STA_20 0x4a0 +#define MDP_RDMA_MON_STA_21 0x4a8 +#define MDP_RDMA_MON_STA_22 0x4b0 +#define MDP_RDMA_MON_STA_23 0x4b8 +#define MDP_RDMA_MON_STA_24 0x4c0 +#define MDP_RDMA_MON_STA_25 0x4c8 +#define MDP_RDMA_MON_STA_26 0x4d0 +#define MDP_RDMA_MON_STA_27 0x4d8 +#define MDP_RDMA_MON_STA_28 0x4e0 + +/* MASK */ +#define MDP_RDMA_EN_MASK 0x00000001 +#define MDP_RDMA_RESET_MASK 0x00000001 +#define MDP_RDMA_INTERRUPT_ENABLE_MASK 0x00000007 +#define MDP_RDMA_INTERRUPT_STATUS_MASK 0x00000007 +#define MDP_RDMA_CON_MASK 0x00001110 +#define MDP_RDMA_GMCIF_CON_MASK 0xfffb3771 +#define MDP_RDMA_SRC_CON_MASK 0xf3ffffff +#define MDP_RDMA_SRC_BASE_0_MASK 0xffffffff +#define MDP_RDMA_SRC_BASE_1_MASK 0xffffffff +#define MDP_RDMA_SRC_BASE_2_MASK 0xffffffff +#define MDP_RDMA_UFO_DEC_LENGTH_BASE_Y_MASK 0xffffffff +#define MDP_RDMA_UFO_DEC_LENGTH_BASE_C_MASK 0xffffffff +#define MDP_RDMA_MF_BKGD_SIZE_IN_BYTE_MASK 0x001fffff +#define MDP_RDMA_MF_BKGD_SIZE_IN_PXL_MASK 0x001fffff +#define MDP_RDMA_MF_SRC_SIZE_MASK 0x1fff1fff +#define MDP_RDMA_MF_CLIP_SIZE_MASK 0x1fff1fff +#define MDP_RDMA_MF_OFFSET_1_MASK 0x003f001f +#define MDP_RDMA_MF_PAR_MASK 0x1ffff3ff +#define MDP_RDMA_SF_BKGD_SIZE_IN_BYTE_MASK 0x001fffff +#define MDP_RDMA_SF_PAR_MASK 0x1ffff3ff +#define MDP_RDMA_MB_DEPTH_MASK 0x0000007f +#define MDP_RDMA_MB_BASE_MASK 0x0000ffff +#define MDP_RDMA_MB_CON_MASK 0x3fff1fff +#define MDP_RDMA_SB_DEPTH_MASK 0x0000007f +#define MDP_RDMA_SB_BASE_MASK 0x0000ffff +#define MDP_RDMA_SB_CON_MASK 0x3fff1fff +#define MDP_RDMA_VC1_RANGE_MASK 0x001f1f11 +#define MDP_RDMA_SRC_END_0_MASK 0xffffffff +#define MDP_RDMA_SRC_END_1_MASK 0xffffffff +#define MDP_RDMA_SRC_END_2_MASK 0xffffffff +#define MDP_RDMA_SRC_OFFSET_0_MASK 0xffffffff +#define MDP_RDMA_SRC_OFFSET_1_MASK 0xffffffff +#define MDP_RDMA_SRC_OFFSET_2_MASK 0xffffffff +#define MDP_RDMA_SRC_OFFSET_W_0_MASK 0x0000ffff +#define MDP_RDMA_SRC_OFFSET_W_1_MASK 0x0000ffff +#define MDP_RDMA_SRC_OFFSET_W_2_MASK 0x0000ffff +#define MDP_RDMA_SRC_OFFSET_0_P_MASK 0xffffffff +#define MDP_RDMA_TRANSFORM_0_MASK 0xff110777 +#define MDP_RDMA_TRANSFORM_1_MASK 0x1ff7fdff +#define MDP_RDMA_TRANSFORM_2_MASK 0x1ff7fdff +#define MDP_RDMA_TRANSFORM_3_MASK 0x1fff1fff +#define MDP_RDMA_TRANSFORM_4_MASK 0x1fff1fff +#define MDP_RDMA_TRANSFORM_5_MASK 0x1fff1fff +#define MDP_RDMA_TRANSFORM_6_MASK 0x1fff1fff +#define MDP_RDMA_TRANSFORM_7_MASK 0x00001fff +#define MDP_RDMA_DMABUF_CON_0_MASK 0x077f007f +#define MDP_RDMA_DMAULTRA_CON_0_MASK 0x7f7f7f7f +#define MDP_RDMA_DMABUF_CON_1_MASK 0x073f003f +#define MDP_RDMA_DMAULTRA_CON_1_MASK 0x3f3f3f3f +#define MDP_RDMA_DMABUF_CON_2_MASK 0x071f001f +#define MDP_RDMA_DMAULTRA_CON_2_MASK 0x1f1f1f1f + +#define MDP_RDMA_DITHER_CON_MASK 0xffffffff +#define MDP_RDMA_RESV_DUMMY_0_MASK 0xffffffff +#define MDP_RDMA_CHKS_EXTR_MASK 0xffffff01 +#define MDP_RDMA_CHKS_INTW_MASK 0xffffff01 +#define MDP_RDMA_CHKS_INTR_MASK 0xffffff01 +#define MDP_RDMA_CHKS_ROTO_MASK 0xffffff01 +#define MDP_RDMA_CHKS_SRIY_MASK 0xffffff01 +#define MDP_RDMA_CHKS_SRIU_MASK 0xffffff01 +#define MDP_RDMA_CHKS_SRIV_MASK 0xffffff01 +#define MDP_RDMA_CHKS_SROY_MASK 0xffffff01 +#define MDP_RDMA_CHKS_SROU_MASK 0xffffff01 +#define MDP_RDMA_CHKS_SROV_MASK 0xffffff01 +#define MDP_RDMA_CHKS_VUPI_MASK 0xffffff01 +#define MDP_RDMA_CHKS_VUPO_MASK 0xffffff01 +#define MDP_RDMA_DEBUG_CON_MASK 0x00001f11 +#define MDP_RDMA_MON_STA_0_MASK 0xffffffff +#define MDP_RDMA_MON_STA_1_MASK 0xffffffff +#define MDP_RDMA_MON_STA_2_MASK 0xffffffff +#define MDP_RDMA_MON_STA_3_MASK 0xffffffff +#define MDP_RDMA_MON_STA_4_MASK 0xffffffff +#define MDP_RDMA_MON_STA_5_MASK 0xffffffff +#define MDP_RDMA_MON_STA_6_MASK 0xffffffff +#define MDP_RDMA_MON_STA_7_MASK 0xffffffff +#define MDP_RDMA_MON_STA_8_MASK 0xffffffff +#define MDP_RDMA_MON_STA_9_MASK 0xffffffff +#define MDP_RDMA_MON_STA_10_MASK 0xffffffff +#define MDP_RDMA_MON_STA_11_MASK 0xffffffff +#define MDP_RDMA_MON_STA_12_MASK 0xffffffff +#define MDP_RDMA_MON_STA_13_MASK 0xffffffff +#define MDP_RDMA_MON_STA_14_MASK 0xffffffff +#define MDP_RDMA_MON_STA_15_MASK 0xffffffff +#define MDP_RDMA_MON_STA_16_MASK 0xffffffff +#define MDP_RDMA_MON_STA_17_MASK 0xffffffff +#define MDP_RDMA_MON_STA_18_MASK 0xffffffff +#define MDP_RDMA_MON_STA_19_MASK 0xffffffff +#define MDP_RDMA_MON_STA_20_MASK 0xffffffff +#define MDP_RDMA_MON_STA_21_MASK 0xffffffff +#define MDP_RDMA_MON_STA_22_MASK 0xffffffff +#define MDP_RDMA_MON_STA_23_MASK 0xffffffff +#define MDP_RDMA_MON_STA_24_MASK 0xffffffff +#define MDP_RDMA_MON_STA_25_MASK 0xffffffff +#define MDP_RDMA_MON_STA_26_MASK 0xffffffff +#define MDP_RDMA_MON_STA_27_MASK 0xffffffff +#define MDP_RDMA_MON_STA_28_MASK 0xffffffff + +#endif // __MDP_REG_RDMA_H__ diff --git a/drivers/media/platform/mtk-mdp3/mdp_reg_rsz.h b/drivers/media/platform/mtk-mdp3/mdp_reg_rsz.h new file mode 100644 index 000000000000..7f0683f3c60d --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mdp_reg_rsz.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MDP_REG_RSZ_H__ +#define __MDP_REG_RSZ_H__ + +#include "mmsys_reg_base.h" + +#define PRZ_ENABLE 0x000 +#define PRZ_CONTROL_1 0x004 +#define PRZ_CONTROL_2 0x008 +#define PRZ_INT_FLAG 0x00c +#define PRZ_INPUT_IMAGE 0x010 +#define PRZ_OUTPUT_IMAGE 0x014 +#define PRZ_HORIZONTAL_COEFF_STEP 0x018 +#define PRZ_VERTICAL_COEFF_STEP 0x01c +#define PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET 0x020 +#define PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET 0x024 +#define PRZ_LUMA_VERTICAL_INTEGER_OFFSET 0x028 +#define PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET 0x02c +#define PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET 0x030 +#define PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET 0x034 +#define PRZ_RSV 0x040 +#define PRZ_DEBUG_SEL 0x044 +#define PRZ_DEBUG 0x048 +#define PRZ_TAP_ADAPT 0x04c +#define PRZ_IBSE_SOFTCLIP 0x050 +#define PRZ_IBSE_YLEVEL_1 0x054 +#define PRZ_IBSE_YLEVEL_2 0x058 +#define PRZ_IBSE_YLEVEL_3 0x05c +#define PRZ_IBSE_YLEVEL_4 0x060 +#define PRZ_IBSE_YLEVEL_5 0x064 +#define PRZ_IBSE_GAINCONTROL_1 0x068 +#define PRZ_IBSE_GAINCONTROL_2 0x06c +#define PRZ_DEMO_IN_HMASK 0x070 +#define PRZ_DEMO_IN_VMASK 0x074 +#define PRZ_DEMO_OUT_HMASK 0x078 +#define PRZ_DEMO_OUT_VMASK 0x07c +#define PRZ_ATPG 0x0fc +#define PRZ_PAT1_GEN_SET 0x100 +#define PRZ_PAT1_GEN_FRM_SIZE 0x104 +#define PRZ_PAT1_GEN_COLOR0 0x108 +#define PRZ_PAT1_GEN_COLOR1 0x10c +#define PRZ_PAT1_GEN_COLOR2 0x110 +#define PRZ_PAT1_GEN_POS 0x114 +#define PRZ_PAT1_GEN_TILE_POS 0x124 +#define PRZ_PAT1_GEN_TILE_OV 0x128 +#define PRZ_PAT2_GEN_SET 0x200 +#define PRZ_PAT2_GEN_COLOR0 0x208 +#define PRZ_PAT2_GEN_COLOR1 0x20c +#define PRZ_PAT2_GEN_POS 0x214 +#define PRZ_PAT2_GEN_CURSOR_RB0 0x218 +#define PRZ_PAT2_GEN_CURSOR_RB1 0x21c +#define PRZ_PAT2_GEN_TILE_POS 0x224 +#define PRZ_PAT2_GEN_TILE_OV 0x228 + +/* MASK */ +#define PRZ_ENABLE_MASK 0x00010001 +#define PRZ_CONTROL_1_MASK 0xfffffff3 +#define PRZ_CONTROL_2_MASK 0x0ffffaff +#define PRZ_INT_FLAG_MASK 0x00000033 +#define PRZ_INPUT_IMAGE_MASK 0xffffffff +#define PRZ_OUTPUT_IMAGE_MASK 0xffffffff +#define PRZ_HORIZONTAL_COEFF_STEP_MASK 0x007fffff +#define PRZ_VERTICAL_COEFF_STEP_MASK 0x007fffff +#define PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET_MASK 0x0000ffff +#define PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET_MASK 0x001fffff +#define PRZ_LUMA_VERTICAL_INTEGER_OFFSET_MASK 0x0000ffff +#define PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET_MASK 0x001fffff +#define PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET_MASK 0x0000ffff +#define PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET_MASK 0x001fffff +#define PRZ_RSV_MASK 0xffffffff +#define PRZ_DEBUG_SEL_MASK 0x0000000f +#define PRZ_DEBUG_MASK 0xffffffff +#define PRZ_TAP_ADAPT_MASK 0x03ffffff +#define PRZ_IBSE_SOFTCLIP_MASK 0x000fffff +#define PRZ_IBSE_YLEVEL_1_MASK 0xffffffff +#define PRZ_IBSE_YLEVEL_2_MASK 0xffffffff +#define PRZ_IBSE_YLEVEL_3_MASK 0xffffffff +#define PRZ_IBSE_YLEVEL_4_MASK 0xffffffff +#define PRZ_IBSE_YLEVEL_5_MASK 0x0000ff3f +#define PRZ_IBSE_GAINCONTROL_1_MASK 0xffffffff +#define PRZ_IBSE_GAINCONTROL_2_MASK 0x0fffff0f +#define PRZ_DEMO_IN_HMASK_MASK 0xffffffff +#define PRZ_DEMO_IN_VMASK_MASK 0xffffffff +#define PRZ_DEMO_OUT_HMASK_MASK 0xffffffff +#define PRZ_DEMO_OUT_VMASK_MASK 0xffffffff +#define PRZ_ATPG_MASK 0x00000003 +#define PRZ_PAT1_GEN_SET_MASK 0x00ff00fd +#define PRZ_PAT1_GEN_FRM_SIZE_MASK 0x1fff1fff +#define PRZ_PAT1_GEN_COLOR0_MASK 0x00ff00ff +#define PRZ_PAT1_GEN_COLOR1_MASK 0x00ff00ff +#define PRZ_PAT1_GEN_COLOR2_MASK 0x00ff00ff +#define PRZ_PAT1_GEN_POS_MASK 0x1fff1fff +#define PRZ_PAT1_GEN_TILE_POS_MASK 0x1fff1fff +#define PRZ_PAT1_GEN_TILE_OV_MASK 0x0000ffff +#define PRZ_PAT2_GEN_SET_MASK 0x00ff0003 +#define PRZ_PAT2_GEN_COLOR0_MASK 0x00ff00ff +#define PRZ_PAT2_GEN_COLOR1_MASK 0x000000ff +#define PRZ_PAT2_GEN_POS_MASK 0x1fff1fff +#define PRZ_PAT2_GEN_CURSOR_RB0_MASK 0x00ff00ff +#define PRZ_PAT2_GEN_CURSOR_RB1_MASK 0x000000ff +#define PRZ_PAT2_GEN_TILE_POS_MASK 0x1fff1fff +#define PRZ_PAT2_GEN_TILE_OV_MASK 0x0000ffff + +#endif // __MDP_REG_RSZ_H__ diff --git a/drivers/media/platform/mtk-mdp3/mdp_reg_wdma.h b/drivers/media/platform/mtk-mdp3/mdp_reg_wdma.h new file mode 100644 index 000000000000..c274b54c1f18 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mdp_reg_wdma.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MDP_REG_WDMA_H__ +#define __MDP_REG_WDMA_H__ + +#include "mmsys_reg_base.h" + +#define WDMA_INTEN 0x000 +#define WDMA_INTSTA 0x004 +#define WDMA_EN 0x008 +#define WDMA_RST 0x00c +#define WDMA_SMI_CON 0x010 +#define WDMA_CFG 0x014 +#define WDMA_SRC_SIZE 0x018 +#define WDMA_CLIP_SIZE 0x01c +#define WDMA_CLIP_COORD 0x020 +#define WDMA_DST_ADDR 0xf00 +#define WDMA_DST_W_IN_BYTE 0x028 +#define WDMA_ALPHA 0x02c +#define WDMA_BUF_CON1 0x038 +#define WDMA_BUF_CON2 0x03c +#define WDMA_C00 0x040 +#define WDMA_C02 0x044 +#define WDMA_C10 0x048 +#define WDMA_C12 0x04c +#define WDMA_C20 0x050 +#define WDMA_C22 0x054 +#define WDMA_PRE_ADD0 0x058 +#define WDMA_PRE_ADD2 0x05c +#define WDMA_POST_ADD0 0x060 +#define WDMA_POST_ADD2 0x064 +#define WDMA_DST_U_ADDR 0xf04 +#define WDMA_DST_V_ADDR 0xf08 +#define WDMA_DST_UV_PITCH 0x078 +#define WDMA_DST_ADDR_OFFSET 0x080 +#define WDMA_DST_U_ADDR_OFFSET 0x084 +#define WDMA_DST_V_ADDR_OFFSET 0x088 +#define PROC_TRACK_CON_0 0x090 +#define PROC_TRACK_CON_1 0x094 +#define PROC_TRACK_CON_2 0x098 +#define WDMA_FLOW_CTRL_DBG 0x0a0 +#define WDMA_EXEC_DBG 0x0a4 +#define WDMA_CT_DBG 0x0a8 +#define WDMA_SMI_TRAFFIC_DBG 0x0ac +#define WDMA_PROC_TRACK_DBG_0 0x0b0 +#define WDMA_PROC_TRACK_DBG_1 0x0b4 +#define WDMA_DEBUG 0x0b8 +#define WDMA_DUMMY 0x100 +#define WDMA_DITHER_0 0xe00 +#define WDMA_DITHER_5 0xe14 +#define WDMA_DITHER_6 0xe18 +#define WDMA_DITHER_7 0xe1c +#define WDMA_DITHER_8 0xe20 +#define WDMA_DITHER_9 0xe24 +#define WDMA_DITHER_10 0xe28 +#define WDMA_DITHER_11 0xe2c +#define WDMA_DITHER_12 0xe30 +#define WDMA_DITHER_13 0xe34 +#define WDMA_DITHER_14 0xe38 +#define WDMA_DITHER_15 0xe3c +#define WDMA_DITHER_16 0xe40 +#define WDMA_DITHER_17 0xe44 + +/* MASK */ +#define WDMA_INTEN_MASK 0x00000003 +#define WDMA_INTSTA_MASK 0x00000003 +#define WDMA_EN_MASK 0x00000001 +#define WDMA_RST_MASK 0x00000001 +#define WDMA_SMI_CON_MASK 0x0fffffff +#define WDMA_CFG_MASK 0xff03bff0 +#define WDMA_SRC_SIZE_MASK 0x3fff3fff +#define WDMA_CLIP_SIZE_MASK 0x3fff3fff +#define WDMA_CLIP_COORD_MASK 0x3fff3fff +#define WDMA_DST_ADDR_MASK 0xffffffff +#define WDMA_DST_W_IN_BYTE_MASK 0x0000ffff +#define WDMA_ALPHA_MASK 0x800000ff +#define WDMA_BUF_CON1_MASK 0xd1ff01ff +#define WDMA_BUF_CON2_MASK 0xffffffff +#define WDMA_C00_MASK 0x1fff1fff +#define WDMA_C02_MASK 0x00001fff +#define WDMA_C10_MASK 0x1fff1fff +#define WDMA_C12_MASK 0x00001fff +#define WDMA_C20_MASK 0x1fff1fff +#define WDMA_C22_MASK 0x00001fff +#define WDMA_PRE_ADD0_MASK 0x01ff01ff +#define WDMA_PRE_ADD2_MASK 0x000001ff +#define WDMA_POST_ADD0_MASK 0x01ff01ff +#define WDMA_POST_ADD2_MASK 0x000001ff +#define WDMA_DST_U_ADDR_MASK 0xffffffff +#define WDMA_DST_V_ADDR_MASK 0xffffffff +#define WDMA_DST_UV_PITCH_MASK 0x0000ffff +#define WDMA_DST_ADDR_OFFSET_MASK 0x0fffffff +#define WDMA_DST_U_ADDR_OFFSET_MASK 0x0fffffff +#define WDMA_DST_V_ADDR_OFFSET_MASK 0x0fffffff +#define PROC_TRACK_CON_0_MASK 0x70000fff +#define PROC_TRACK_CON_1_MASK 0x00ffffff +#define PROC_TRACK_CON_2_MASK 0x00ffffff +#define WDMA_FLOW_CTRL_DBG_MASK 0x0000f3ff +#define WDMA_EXEC_DBG_MASK 0x003f003f +#define WDMA_CT_DBG_MASK 0x3fff3fff +#define WDMA_SMI_TRAFFIC_DBG_MASK 0xffffffff +#define WDMA_PROC_TRACK_DBG_0_MASK 0xffffffff +#define WDMA_PROC_TRACK_DBG_1_MASK 0xffffffff +#define WDMA_DEBUG_MASK 0xffffffff +#define WDMA_DUMMY_MASK 0xffffffff +#define WDMA_DITHER_0_MASK 0x0111ff11 +#define WDMA_DITHER_5_MASK 0x0000ffff +#define WDMA_DITHER_6_MASK 0x0001f3ff +#define WDMA_DITHER_7_MASK 0x00000333 +#define WDMA_DITHER_8_MASK 0x03ff0001 +#define WDMA_DITHER_9_MASK 0x03ff03ff +#define WDMA_DITHER_10_MASK 0x00000733 +#define WDMA_DITHER_11_MASK 0x00003331 +#define WDMA_DITHER_12_MASK 0xffff0031 +#define WDMA_DITHER_13_MASK 0x00000777 +#define WDMA_DITHER_14_MASK 0x00000371 +#define WDMA_DITHER_15_MASK 0x77770001 +#define WDMA_DITHER_16_MASK 0x77777777 +#define WDMA_DITHER_17_MASK 0x0001ffff + +#endif // __MDP_REG_WDMA_H__ diff --git a/drivers/media/platform/mtk-mdp3/mdp_reg_wrot.h b/drivers/media/platform/mtk-mdp3/mdp_reg_wrot.h new file mode 100644 index 000000000000..b757a288267d --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mdp_reg_wrot.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MDP_REG_WROT_H__ +#define __MDP_REG_WROT_H__ + +#include "mmsys_reg_base.h" + +#define VIDO_CTRL 0x000 +#define VIDO_DMA_PERF 0x004 +#define VIDO_MAIN_BUF_SIZE 0x008 +#define VIDO_SOFT_RST 0x010 +#define VIDO_SOFT_RST_STAT 0x014 +#define VIDO_INT_EN 0x018 +#define VIDO_INT 0x01c +#define VIDO_CROP_OFST 0x020 +#define VIDO_TAR_SIZE 0x024 +#define VIDO_BASE_ADDR 0xf00 +#define VIDO_OFST_ADDR 0x02c +#define VIDO_STRIDE 0x030 +#define VIDO_BASE_ADDR_C 0xf04 +#define VIDO_OFST_ADDR_C 0x038 +#define VIDO_STRIDE_C 0x03c +#define VIDO_DITHER 0x054 +#define VIDO_BASE_ADDR_V 0xf08 +#define VIDO_OFST_ADDR_V 0x068 +#define VIDO_STRIDE_V 0x06c +#define VIDO_RSV_1 0x070 +#define VIDO_DMA_PREULTRA 0x074 +#define VIDO_IN_SIZE 0x078 +#define VIDO_ROT_EN 0x07c +#define VIDO_FIFO_TEST 0x080 +#define VIDO_MAT_CTRL 0x084 +#define VIDO_MAT_RMY 0x088 +#define VIDO_MAT_RMV 0x08c +#define VIDO_MAT_GMY 0x090 +#define VIDO_MAT_BMY 0x094 +#define VIDO_MAT_BMV 0x098 +#define VIDO_MAT_PREADD 0x09c +#define VIDO_MAT_POSTADD 0x0a0 +#define VIDO_DITHER_00 0x0a4 +#define VIDO_DITHER_02 0x0ac +#define VIDO_DITHER_03 0x0b0 +#define VIDO_DITHER_04 0x0b4 +#define VIDO_DITHER_05 0x0b8 +#define VIDO_DITHER_06 0x0bc +#define VIDO_DITHER_07 0x0c0 +#define VIDO_DITHER_08 0x0c4 +#define VIDO_DITHER_09 0x0c8 +#define VIDO_DITHER_10 0x0cc +#define VIDO_DEBUG 0x0d0 +#define VIDO_ARB_SW_CTL 0x0d4 +#define MDP_WROT_TRACK_CTL 0x0e0 +#define MDP_WROT_TRACK_WINDOW 0x0e4 +#define MDP_WROT_TRACK_TARGET 0x0e8 +#define MDP_WROT_TRACK_STOP 0x0ec +#define MDP_WROT_TRACK_PROC_CNT0 0x0f0 +#define MDP_WROT_TRACK_PROC_CNT1 0x0f4 + +/* MASK */ +#define VIDO_CTRL_MASK 0xf530711f +#define VIDO_DMA_PERF_MASK 0x3fffffff +#define VIDO_MAIN_BUF_SIZE_MASK 0x1fff7f77 +#define VIDO_SOFT_RST_MASK 0x00000001 +#define VIDO_SOFT_RST_STAT_MASK 0x00000001 +#define VIDO_INT_EN_MASK 0x00003f07 +#define VIDO_INT_MASK 0x00000007 +#define VIDO_CROP_OFST_MASK 0x1fff1fff +#define VIDO_TAR_SIZE_MASK 0x1fff1fff +#define VIDO_BASE_ADDR_MASK 0xffffffff +#define VIDO_OFST_ADDR_MASK 0x0fffffff +#define VIDO_STRIDE_MASK 0x0000ffff +#define VIDO_BASE_ADDR_C_MASK 0xffffffff +#define VIDO_OFST_ADDR_C_MASK 0x0fffffff +#define VIDO_STRIDE_C_MASK 0x0000ffff +#define VIDO_DITHER_MASK 0xff000001 +#define VIDO_BASE_ADDR_V_MASK 0xffffffff +#define VIDO_OFST_ADDR_V_MASK 0x0fffffff +#define VIDO_STRIDE_V_MASK 0x0000ffff +#define VIDO_RSV_1_MASK 0xffffffff +#define VIDO_DMA_PREULTRA_MASK 0x00ffffff +#define VIDO_IN_SIZE_MASK 0x1fff1fff +#define VIDO_ROT_EN_MASK 0x00000001 +#define VIDO_FIFO_TEST_MASK 0x00000fff +#define VIDO_MAT_CTRL_MASK 0x000000f3 +#define VIDO_MAT_RMY_MASK 0x1fff1fff +#define VIDO_MAT_RMV_MASK 0x1fff1fff +#define VIDO_MAT_GMY_MASK 0x1fff1fff +#define VIDO_MAT_BMY_MASK 0x1fff1fff +#define VIDO_MAT_BMV_MASK 0x00001fff +#define VIDO_MAT_PREADD_MASK 0x1ff7fdff +#define VIDO_MAT_POSTADD_MASK 0x1ff7fdff +#define VIDO_DITHER_00_MASK 0x0000ff3f +#define VIDO_DITHER_02_MASK 0xffff3fff +#define VIDO_DITHER_03_MASK 0x0000003f +#define VIDO_DITHER_04_MASK 0xbfffffff +#define VIDO_DITHER_05_MASK 0xffff7fff +#define VIDO_DITHER_06_MASK 0x003ff773 +#define VIDO_DITHER_07_MASK 0x00007777 +#define VIDO_DITHER_08_MASK 0x00007777 +#define VIDO_DITHER_09_MASK 0x00007777 +#define VIDO_DITHER_10_MASK 0x0001ffff +#define VIDO_DEBUG_MASK 0xffffffff +#define VIDO_ARB_SW_CTL_MASK 0x00000007 +#define MDP_WROT_TRACK_CTL_MASK 0x0000001f +#define MDP_WROT_TRACK_WINDOW_MASK 0x00000fff +#define MDP_WROT_TRACK_TARGET_MASK 0x00ffffff +#define MDP_WROT_TRACK_STOP_MASK 0x00ffffff +#define MDP_WROT_TRACK_PROC_CNT0_MASK 0xffffffff +#define MDP_WROT_TRACK_PROC_CNT1_MASK 0x00000001 + +#endif // __MDP_REG_WROT_H__ diff --git a/drivers/media/platform/mtk-mdp3/mmsys_config.h b/drivers/media/platform/mtk-mdp3/mmsys_config.h new file mode 100644 index 000000000000..5cdfb864dadf --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mmsys_config.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MMSYS_CONFIG_H__ +#define __MMSYS_CONFIG_H__ + +#include "mmsys_reg_base.h" + +#define MMSYS_INTEN 0x000 +#define MMSYS_INTSTA 0x004 +#define MJC_APB_TX_CON 0x00c + +#define ISP_MOUT_EN 0xf80 +#define MDP_RDMA0_MOUT_EN 0xf84 +#define MDP_RDMA1_MOUT_EN 0xf88 +#define MDP_PRZ0_MOUT_EN 0xf8c +#define MDP_PRZ1_MOUT_EN 0xf90 +#define MDP_COLOR_MOUT_EN 0xf94 +#define IPU_MOUT_EN 0xf98 +#define DISP_TO_WROT_SOUT_SEL 0xfa0 +#define MDP_COLOR_IN_SOUT_SEL 0xfa4 +#define MDP_PATH0_SOUT_SEL 0xfa8 +#define MDP_PATH1_SOUT_SEL 0xfac +#define MDP_TDSHP_SOUT_SEL 0xfb0 + +#define DISP_OVL0_MOUT_EN 0xf00 +#define DISP_OVL0_2L_MOUT_EN 0xf04 +#define DISP_OVL1_2L_MOUT_EN 0xf08 +#define DISP_DITHER0_MOUT_EN 0xf0c +#define DISP_RSZ_MOUT_EN 0xf10 + +#define MMSYS_MOUT_RST 0x048 +#define MDP_PRZ0_SEL_IN 0xfc0 +#define MDP_PRZ1_SEL_IN 0xfc4 +#define MDP_TDSHP_SEL_IN 0xfc8 +#define DISP_WDMA0_SEL_IN 0xfcc +#define MDP_WROT0_SEL_IN 0xfd0 +#define MDP_WDMA_SEL_IN 0xfd4 +#define MDP_COLOR_OUT_SEL_IN 0xfd8 +#define MDP_COLOR_SEL_IN 0xfdc +#define MDP_PATH0_SEL_IN 0xfe0 +#define MDP_PATH1_SEL_IN 0xfe4 + +#define DISP_COLOR_OUT_SEL_IN 0xf20 +#define DISP_PATH0_SEL_IN 0xf24 +#define DISP_WDMA0_PRE_SEL_IN 0xf28 +#define DSI0_SEL_IN 0xf2c +#define DSI1_SEL_IN 0xf30 +#define DISP_OVL0_SEL_IN 0xf34 +#define DISP_OVL0_2L_SEL_IN 0xf38 +#define OVL_TO_RSZ_SEL_IN 0xf3c +#define OVL_TO_WDMA_SEL_IN 0xf40 +#define OVL_TO_WROT_SEL_IN 0xf44 +#define DISP_RSZ_SEL_IN 0xf48 +#define DISP_RDMA0_SOUT_SEL_IN 0xf50 +#define DISP_RDMA1_SOUT_SEL_IN 0xf54 +#define MDP_TO_DISP0_SOUT_SEL_IN 0xf58 +#define MDP_TO_DISP1_SOUT_SEL_IN 0xf5c +#define DISP_RDMA0_RSZ_IN_SOUT_SEL_IN 0xf60 +#define DISP_RDMA0_RSZ_OUT_SEL_IN 0xf64 +#define MDP_AAL_MOUT_EN 0xfe8 +#define MDP_AAL_SEL_IN 0xfec +#define MDP_CCORR_SEL_IN 0xff0 +#define MDP_CCORR_SOUT_SEL 0xff4 + +#define MMSYS_MISC 0x0f0 +#define MMSYS_SMI_LARB_SEL 0x0f4 +#define MMSYS_SODI_REQ_MASK 0x0f8 +#define MMSYS_CG_CON0 0x100 +#define MMSYS_CG_SET0 0x104 +#define MMSYS_CG_CLR0 0x108 +#define MMSYS_CG_CON1 0x110 +#define MMSYS_CG_SET1 0x114 +#define MMSYS_CG_CLR1 0x118 +#define MMSYS_HW_DCM_DIS0 0x120 +#define MMSYS_HW_DCM_DIS_SET0 0x124 +#define MMSYS_HW_DCM_DIS_CLR0 0x128 +#define MMSYS_HW_DCM_DIS1 0x130 +#define MMSYS_HW_DCM_DIS_SET1 0x134 +#define MMSYS_HW_DCM_DIS_CLR1 0x138 +#define MMSYS_HW_DCM_EVENT_CTL1 0x13c +#define MMSYS_SW0_RST_B 0x140 +#define MMSYS_SW1_RST_B 0x144 +#define MMSYS_LCM_RST_B 0x150 +#define LARB6_AXI_ASIF_CFG_WD 0x180 +#define LARB6_AXI_ASIF_CFG_RD 0x184 +#define PROC_TRACK_EMI_BUSY_CON 0x190 +#define DISP_FAKE_ENG_EN 0x200 +#define DISP_FAKE_ENG_RST 0x204 +#define DISP_FAKE_ENG_CON0 0x208 +#define DISP_FAKE_ENG_CON1 0x20c +#define DISP_FAKE_ENG_RD_ADDR 0x210 +#define DISP_FAKE_ENG_WR_ADDR 0x214 +#define DISP_FAKE_ENG_STATE 0x218 +#define DISP_FAKE_ENG2_EN 0x220 +#define DISP_FAKE_ENG2_RST 0x224 +#define DISP_FAKE_ENG2_CON0 0x228 +#define DISP_FAKE_ENG2_CON1 0x22c +#define DISP_FAKE_ENG2_RD_ADDR 0x230 +#define DISP_FAKE_ENG2_WR_ADDR 0x234 +#define DISP_FAKE_ENG2_STATE 0x238 +#define MMSYS_MBIST_CON 0x800 +#define MMSYS_MBIST_DONE 0x804 +#define MMSYS_MBIST_HOLDB 0x808 +#define MMSYS_MBIST_MODE 0x80c +#define MMSYS_MBIST_FAIL0 0x810 +#define MMSYS_MBIST_FAIL1 0x814 +#define MMSYS_MBIST_FAIL2 0x818 +#define MMSYS_MBIST_DEBUG 0x820 +#define MMSYS_MBIST_DIAG_SCANOUT 0x824 +#define MMSYS_MBIST_PRE_FUSE 0x828 +#define MMSYS_MBIST_BSEL0 0x82c +#define MMSYS_MBIST_BSEL1 0x830 +#define MMSYS_MBIST_BSEL2 0x834 +#define MMSYS_MBIST_BSEL3 0x838 +#define MMSYS_MBIST_HDEN 0x83c +#define MDP_RDMA0_MEM_DELSEL 0x840 +#define MDP_RDMA1_MEM_DELSEL 0x844 +#define MDP_RSZ_MEM_DELSEL 0x848 +#define MDP_TDSHP_MEM_DELSEL 0x84c +#define MDP_AAL_MEM_DELSEL 0x850 + +#define MDP_WROT0_MEM_DELSEL 0x854 +#define MDP_WDMA_MEM_DELSEL 0x858 +#define DISP_OVL_MEM_DELSEL 0x85c +#define DISP_OVL_2L_MEM_DELSEL 0x860 +#define DISP_RDMA_MEM_DELSEL 0x864 +#define DISP_WDMA0_MEM_DELSEL 0x868 +#define DISP_GAMMA_MEM_DELSEL 0x870 +#define DSI_MEM_DELSEL 0x874 +#define DISP_SPLIT_MEM_DELSEL 0x878 +#define DISP_DSC_MEM_DELSEL 0x87c +#define MMSYS_DEBUG_OUT_SEL 0x88c +#define MMSYS_MBIST_RP_RST_B 0x890 +#define MMSYS_MBIST_RP_FAIL0 0x894 +#define MMSYS_MBIST_RP_FAIL1 0x898 +#define MMSYS_MBIST_RP_OK0 0x89c +#define MMSYS_MBIST_RP_OK1 0x8a0 +#define MMSYS_DUMMY0 0x8a4 +#define MMSYS_DUMMY1 0x8a8 +#define MMSYS_DUMMY2 0x8ac +#define MMSYS_DUMMY3 0x8b0 +#define DISP_DL_VALID_0 0x8b4 +#define DISP_DL_VALID_1 0x8b8 +#define DISP_DL_VALID_2 0x8bc +#define DISP_DL_READY_0 0x8c0 +#define DISP_DL_READY_1 0x8c4 +#define DISP_DL_READY_2 0x8C8 +#define MDP_DL_VALID_0 0x8cc +#define MDP_DL_VALID_1 0x8d0 +#define MDP_DL_READY_0 0x8d4 +#define MDP_DL_READY_1 0x8d8 +#define SMI_LARB0_GREQ 0x8dc +#define DISP_MOUT_MASK 0x8e0 +#define DISP_MOUT_MASK1 0x8e4 +#define MDP_MOUT_MASK 0x8e8 +#define MMSYS_POWER_READ 0x8ec +#define TOP_RELAY_FSM_RD 0x960 +#define MDP_ASYNC_CFG_WD 0x934 +#define MDP_ASYNC_CFG_RD 0x938 +#define MDP_ASYNC_IPU_CFG_WD 0x93C +#define MDP_ASYNC_CFG_IPU_RD 0x940 +#define MDP_ASYNC_CFG_OUT_RD 0x958 +#define MDP_ASYNC_IPU_CFG_OUT_RD 0x95C +#define ISP_RELAY_CFG_WD 0x994 +#define ISP_RELAY_CNT_RD 0x998 +#define ISP_RELAY_CNT_LATCH_RD 0x99c +#define IPU_RELAY_CFG_WD 0x9a0 +#define IPU_RELAY_CNT_RD 0x9a4 +#define IPU_RELAY_CNT_LATCH_RD 0x9a8 + +/* MASK */ +#define MMSYS_SW0_RST_B_MASK 0xffffffff +#define MMSYS_SW1_RST_B_MASK 0xffffffff +#define MDP_COLOR_IN_SOUT_SEL_MASK 0x0000000f +#define DISP_COLOR_OUT_SEL_IN_MASK 0xffffffff +#define MDP_ASYNC_CFG_WD_MASK 0xffffffff +#define MDP_ASYNC_IPU_CFG_WD_MASK 0xffffffff +#define MMSYS_HW_DCM_DIS0_MASK 0xffffffff +#define MMSYS_HW_DCM_DIS1_MASK 0xffffffff +#define MDP_ASYNC_CFG_WD_MASK 0xffffffff +#define ISP_RELAY_CFG_WD_MASK 0xffffffff +#define IPU_RELAY_CFG_WD_MASK 0xffffffff + +#endif // __MMSYS_CONFIG_H__ diff --git a/drivers/media/platform/mtk-mdp3/mmsys_mutex.h b/drivers/media/platform/mtk-mdp3/mmsys_mutex.h new file mode 100644 index 000000000000..fb8c179f11af --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mmsys_mutex.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MMSYS_MUTEX_H__ +#define __MMSYS_MUTEX_H__ + +#include "mmsys_reg_base.h" +#include "mdp-platform.h" + +#define MM_MUTEX_INTEN 0x00 +#define MM_MUTEX_INTSTA 0x04 +#define MM_MUTEX_CFG 0x08 + +#define MM_MUTEX_EN (0x20 + mutex_id * 0x20) +#define MM_MUTEX_GET (0x24 + mutex_id * 0x20) +#define MM_MUTEX_RST (0x28 + mutex_id * 0x20) +#define MM_MUTEX_MOD (MM_MUTEX_MOD_OFFSET + mutex_id * 0x20) +#define MM_MUTEX_SOF (MM_MUTEX_SOF_OFFSET + mutex_id * 0x20) + +// MASK +#define MM_MUTEX_INTEN_MASK 0x0fff +#define MM_MUTEX_INTSTA_MASK 0x0fff +#define MM_MUTEX_DEBUG_OUT_SEL_MASK 0x03 +#define MM_MUTEX_CFG_MASK 0x01 + +#define MM_MUTEX_EN_MASK 0x01 +#define MM_MUTEX_GET_MASK 0x03 +#define MM_MUTEX_RST_MASK 0x01 +#define MM_MUTEX_MOD_MASK 0x07ffffff +#define MM_MUTEX_SOF_MASK 0x0f + +#endif // __MMSYS_MUTEX_H__ diff --git a/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h b/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h new file mode 100644 index 000000000000..d79b82eea61b --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MMSYS_REG_BASE_H__ +#define __MMSYS_REG_BASE_H__ + +#define MM_REG_WRITE_MASK(cmd, id, base, ofst, val, mask, ...) \ + cmdq_pkt_write_mask(cmd->pkt, id, \ + (base) + (ofst), (val), (mask), ##__VA_ARGS__) +#define MM_REG_WRITE(cmd, id, base, ofst, val, mask, ...) \ + MM_REG_WRITE_MASK(cmd, id, base, ofst, val, \ + (((mask) & (ofst##_MASK)) == (ofst##_MASK)) ? \ + (0xffffffff) : (mask), ##__VA_ARGS__) + +#define MM_REG_WAIT(cmd, evt) \ + cmdq_pkt_wfe(cmd->pkt, cmd->event[(evt)]) + +#define MM_REG_WAIT_NO_CLEAR(cmd, evt) \ + cmdq_pkt_wait_no_clear(cmd->pkt, cmd->event[(evt)]) + +#define MM_REG_CLEAR(cmd, evt) \ + cmdq_pkt_clear_event(cmd->pkt, cmd->event[(evt)]) + +#define MM_REG_SET_EVENT(cmd, evt) \ + cmdq_pkt_set_event(cmd->pkt, cmd->event[(evt)]) + +#define MM_REG_POLL_MASK(cmd, id, base, ofst, val, mask, ...) \ + cmdq_pkt_poll_mask(cmd->pkt, id, \ + (base) + (ofst), (val), (mask), ##__VA_ARGS__) +#define MM_REG_POLL(cmd, id, base, ofst, val, mask, ...) \ + MM_REG_POLL_MASK(cmd, id, base, ofst, val, \ + (((mask) & (ofst##_MASK)) == (ofst##_MASK)) ? \ + (0xffffffff) : (mask), ##__VA_ARGS__) + +#endif // __MM_REG_BASE_H__ diff --git a/drivers/media/platform/mtk-mdp3/mtk-img-ipi.h b/drivers/media/platform/mtk-mdp3/mtk-img-ipi.h new file mode 100644 index 000000000000..1c9b0e95658d --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-img-ipi.h @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Holmes Chiou + * Ping-Hsun Wu + */ + +#ifndef __MTK_IMG_IPI_H__ +#define __MTK_IMG_IPI_H__ + +#include + +/* ISP-MDP generic input information */ + +#define IMG_MAX_HW_INPUTS 3 + +#define IMG_MAX_HW_OUTPUTS 4 + +#define IMG_MAX_PLANES 3 + +#define IMG_IPI_INIT 1 +#define IMG_IPI_DEINIT 2 +#define IMG_IPI_FRAME 3 +#define IMG_IPI_DEBUG 4 + +struct img_addr { + u64 va; /* Used by Linux OS access */ + u32 pa; /* Used by CM4 access */ + u32 iova; /* Used by IOMMU HW access */ +} __attribute__ ((__packed__)); + +struct tuning_addr { + u64 present; + u32 pa; /* Used by CM4 access */ + u32 iova; /* Used by IOMMU HW access */ +} __attribute__ ((__packed__)); + + +struct img_sw_addr { + u64 va; /* Used by APMCU access */ + u32 pa; /* Used by CM4 access */ +} __attribute__ ((__packed__)); + +struct img_plane_format { + u32 size; + u16 stride; +} __attribute__ ((__packed__)); + +struct img_pix_format { + u16 width; + u16 height; + u32 colorformat; /* enum mdp_color */ + u16 ycbcr_prof; /* enum mdp_ycbcr_profile */ + struct img_plane_format plane_fmt[IMG_MAX_PLANES]; +} __attribute__ ((__packed__)); + +struct img_image_buffer { + struct img_pix_format format; + u32 iova[IMG_MAX_PLANES]; + /* enum mdp_buffer_usage, FD or advanced ISP usages */ + u32 usage; +} __attribute__ ((__packed__)); + +#define IMG_SUBPIXEL_SHIFT 20 + +struct img_crop { + s16 left; + s16 top; + u16 width; + u16 height; + u32 left_subpix; + u32 top_subpix; + u32 width_subpix; + u32 height_subpix; +} __attribute__ ((__packed__)); + +#define IMG_CTRL_FLAG_HFLIP BIT(0) +#define IMG_CTRL_FLAG_DITHER BIT(1) +#define IMG_CTRL_FLAG_SHARPNESS BIT(4) +#define IMG_CTRL_FLAG_HDR BIT(5) +#define IMG_CTRL_FLAG_DRE BIT(6) + +struct img_input { + struct img_image_buffer buffer; + u16 flags; /* HDR, DRE, dither */ +} __attribute__ ((__packed__)); + +struct img_output { + struct img_image_buffer buffer; + struct img_crop crop; + s16 rotation; + u16 flags; /* H-flip, sharpness, dither */ +} __attribute__ ((__packed__)); + +struct img_ipi_frameparam { + u32 index; + u32 frame_no; + u64 timestamp; + u8 type; /* enum mdp_stream_type */ + u8 state; + u8 num_inputs; + u8 num_outputs; + u64 drv_data; + struct img_input inputs[IMG_MAX_HW_INPUTS]; + struct img_output outputs[IMG_MAX_HW_OUTPUTS]; + struct tuning_addr tuning_data; + struct img_addr subfrm_data; + struct img_sw_addr config_data; + struct img_sw_addr self_data; +} __attribute__ ((__packed__)); + +struct img_sw_buffer { + u64 handle; /* Used by APMCU access */ + u32 scp_addr; /* Used by CM4 access */ +} __attribute__ ((__packed__)); + +struct img_ipi_param { + u8 usage; + struct img_sw_buffer frm_param; +} __attribute__ ((__packed__)); + +struct img_frameparam { + struct list_head list_entry; + struct img_ipi_frameparam frameparam; +}; + +/* ISP-MDP generic output information */ + +struct img_comp_frame { + u32 output_disable:1; + u32 bypass:1; + u16 in_width; + u16 in_height; + u16 out_width; + u16 out_height; + struct img_crop crop; + u16 in_total_width; + u16 out_total_width; +} __attribute__ ((__packed__)); + +struct img_region { + s16 left; + s16 right; + s16 top; + s16 bottom; +} __attribute__ ((__packed__)); + +struct img_offset { + s16 left; + s16 top; + u32 left_subpix; + u32 top_subpix; +} __attribute__ ((__packed__)); + +struct img_comp_subfrm { + u32 tile_disable:1; + struct img_region in; + struct img_region out; + struct img_offset luma; + struct img_offset chroma; + s16 out_vertical; /* Output vertical index */ + s16 out_horizontal; /* Output horizontal index */ +} __attribute__ ((__packed__)); + +#define IMG_MAX_SUBFRAMES 14 + +struct mdp_rdma_subfrm { + u32 offset[IMG_MAX_PLANES]; + u32 offset_0_p; + u32 src; + u32 clip; + u32 clip_ofst; +} __attribute__ ((__packed__)); + +struct mdp_rdma_data { + u32 src_ctrl; + u32 control; + u32 iova[IMG_MAX_PLANES]; + u32 iova_end[IMG_MAX_PLANES]; + u32 mf_bkgd; + u32 mf_bkgd_in_pxl; + u32 sf_bkgd; + u32 ufo_dec_y; + u32 ufo_dec_c; + u32 transform; + struct mdp_rdma_subfrm subfrms[IMG_MAX_SUBFRAMES]; +} __attribute__ ((__packed__)); + +struct mdp_rsz_subfrm { + u32 control2; + u32 src; + u32 clip; +} __attribute__ ((__packed__)); + +struct mdp_rsz_data { + u32 coeff_step_x; + u32 coeff_step_y; + u32 control1; + u32 control2; + struct mdp_rsz_subfrm subfrms[IMG_MAX_SUBFRAMES]; +} __attribute__ ((__packed__)); + +struct mdp_wrot_subfrm { + u32 offset[IMG_MAX_PLANES]; + u32 src; + u32 clip; + u32 clip_ofst; + u32 main_buf; +} __attribute__ ((__packed__)); + +struct mdp_wrot_data { + u32 iova[IMG_MAX_PLANES]; + u32 control; + u32 stride[IMG_MAX_PLANES]; + u32 mat_ctrl; + u32 fifo_test; + u32 filter; + struct mdp_wrot_subfrm subfrms[IMG_MAX_SUBFRAMES]; +} __attribute__ ((__packed__)); + +struct mdp_wdma_subfrm { + u32 offset[IMG_MAX_PLANES]; + u32 src; + u32 clip; + u32 clip_ofst; +} __attribute__ ((__packed__)); + +struct mdp_wdma_data { + u32 wdma_cfg; + u32 iova[IMG_MAX_PLANES]; + u32 w_in_byte; + u32 uv_stride; + struct mdp_wdma_subfrm subfrms[IMG_MAX_SUBFRAMES]; +} __attribute__ ((__packed__)); + +struct isp_data { + u64 dl_flags; /* 1 << (enum mdp_comp_type) */ + u32 smxi_iova[4]; + u32 cq_idx; + u32 cq_iova; + u32 tpipe_iova[IMG_MAX_SUBFRAMES]; +} __attribute__ ((__packed__)); + +struct img_compparam { + u16 type; /* enum mdp_comp_type */ + u16 id; /* enum mdp_comp_id */ + u32 input; + u32 outputs[IMG_MAX_HW_OUTPUTS]; + u32 num_outputs; + struct img_comp_frame frame; + struct img_comp_subfrm subfrms[IMG_MAX_SUBFRAMES]; + u32 num_subfrms; + union { + struct mdp_rdma_data rdma; + struct mdp_rsz_data rsz; + struct mdp_wrot_data wrot; + struct mdp_wdma_data wdma; + struct isp_data isp; + }; +} __attribute__ ((__packed__)); + +#define IMG_MAX_COMPONENTS 20 + +struct img_mux { + u32 reg; + u32 value; +}; + +struct img_mmsys_ctrl { + struct img_mux sets[IMG_MAX_COMPONENTS * 2]; + u32 num_sets; +}; + +struct img_config { + struct img_compparam components[IMG_MAX_COMPONENTS]; + u32 num_components; + struct img_mmsys_ctrl ctrls[IMG_MAX_SUBFRAMES]; + u32 num_subfrms; +} __attribute__ ((__packed__)); + +#endif /* __MTK_IMG_IPI_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c new file mode 100644 index 000000000000..ee81a3387cf9 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -0,0 +1,521 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#include +#include "mtk-mdp3-cmdq.h" +#include "mtk-mdp3-comp.h" +#include "mtk-mdp3-core.h" +#include "mtk-mdp3-debug.h" +#include "mtk-mdp3-m2m.h" + +#include "mdp-platform.h" +#include "mmsys_mutex.h" + +#define DISP_MUTEX_MDP_FIRST (5) +#define DISP_MUTEX_MDP_COUNT (5) + +#define MDP_PATH_MAX_COMPS IMG_MAX_COMPONENTS + +struct mdp_path { + struct mdp_dev *mdp_dev; + struct mdp_comp_ctx comps[MDP_PATH_MAX_COMPS]; + u32 num_comps; + const struct img_config *config; + const struct img_ipi_frameparam *param; + const struct v4l2_rect *composes[IMG_MAX_HW_OUTPUTS]; + struct v4l2_rect bounds[IMG_MAX_HW_OUTPUTS]; +}; + +#define has_op(ctx, op) \ + (ctx->comp->ops && ctx->comp->ops->op) +#define call_op(ctx, op, ...) \ + (has_op(ctx, op) ? ctx->comp->ops->op(ctx, ##__VA_ARGS__) : 0) + +struct mdp_path_subfrm { + s32 mutex_id; + u32 mutex_mod; + s32 sofs[MDP_PATH_MAX_COMPS]; + u32 num_sofs; +}; + +static bool is_output_disable(const struct img_compparam *param, u32 count) +{ + return (count < param->num_subfrms) ? + (param->frame.output_disable || + param->subfrms[count].tile_disable) : + true; +} + +static int mdp_path_subfrm_require(struct mdp_path_subfrm *subfrm, + const struct mdp_path *path, + struct mdp_cmd *cmd, u32 count) +{ + const struct img_config *config = path->config; + const struct mdp_comp_ctx *ctx; + phys_addr_t mm_mutex = path->mdp_dev->mm_mutex.reg_base; + s32 mutex_id = -1; + u32 mutex_sof = 0; + int mdp_color = 0; + int index; + u8 subsys_id = path->mdp_dev->mm_mutex.subsys_id; + + /* Default value */ + memset(subfrm, 0, sizeof(*subfrm)); + + for (index = 0; index < config->num_components; index++) { + ctx = &path->comps[index]; + if (is_output_disable(ctx->param, count)) + continue; + switch (ctx->comp->id) { + /********************************************** + * Name MSB LSB + * DISP_MUTEX_MOD 23 0 + * + * Specifies which modules are in this mutex. + * Every bit denotes a module. Bit definition: + * 2 mdp_rdma0 + * 4 mdp_rsz0 + * 5 mdp_rsz1 + * 6 mdp_tdshp + * 7 mdp_wrot0 + * 8 mdp_wdma + * 13 mdp_color + * 23 mdp_aal + * 24 mdp_ccorr + **********************************************/ + case MDP_AAL0: + subfrm->mutex_mod |= 1 << 23; + break; + case MDP_CCORR0: + subfrm->mutex_mod |= 1 << 24; + break; + case MDP_COLOR0: + if (mdp_color) + subfrm->mutex_mod |= 1 << 13; + break; + case MDP_WDMA: + subfrm->mutex_mod |= 1 << 8; + subfrm->sofs[subfrm->num_sofs++] = MDP_WDMA; + break; + case MDP_WROT0: + subfrm->mutex_mod |= 1 << 7; + subfrm->sofs[subfrm->num_sofs++] = MDP_WROT0; + break; + case MDP_TDSHP0: + subfrm->mutex_mod |= 1 << 6; + subfrm->sofs[subfrm->num_sofs++] = MDP_TDSHP0; + break; + case MDP_SCL1: + subfrm->mutex_mod |= 1 << 5; + subfrm->sofs[subfrm->num_sofs++] = MDP_SCL1; + break; + case MDP_SCL0: + subfrm->mutex_mod |= 1 << 4; + subfrm->sofs[subfrm->num_sofs++] = MDP_SCL0; + break; + case MDP_RDMA0: + mutex_id = DISP_MUTEX_MDP_FIRST + 1; + subfrm->mutex_mod |= 1 << 2; + subfrm->sofs[subfrm->num_sofs++] = MDP_RDMA0; + break; + case MDP_IMGI: + mutex_id = DISP_MUTEX_MDP_FIRST; + break; + case MDP_WPEI: + mutex_id = DISP_MUTEX_MDP_FIRST + 3; + break; + case MDP_WPEI2: + mutex_id = DISP_MUTEX_MDP_FIRST + 4; + break; + default: + break; + } + } + + subfrm->mutex_id = mutex_id; + if (-1 == mutex_id) { + mdp_err("No mutex assigned"); + return -EINVAL; + } + + if (subfrm->mutex_mod) { + /* Set mutex modules */ + MM_REG_WRITE(cmd, subsys_id, mm_mutex, MM_MUTEX_MOD, + subfrm->mutex_mod, 0x07FFFFFF); + MM_REG_WRITE(cmd, subsys_id, mm_mutex, MM_MUTEX_SOF, + mutex_sof, 0x00000007); + } + return 0; +} + +static int mdp_path_subfrm_run(const struct mdp_path_subfrm *subfrm, + const struct mdp_path *path, + struct mdp_cmd *cmd) +{ + phys_addr_t mm_mutex = path->mdp_dev->mm_mutex.reg_base; + s32 mutex_id = subfrm->mutex_id; + u8 subsys_id = path->mdp_dev->mm_mutex.subsys_id; + + if (-1 == mutex_id) { + mdp_err("Incorrect mutex id"); + return -EINVAL; + } + + if (subfrm->mutex_mod) { + int index; + + /* Wait WROT SRAM shared to DISP RDMA */ + /* Clear SOF event for each engine */ + for (index = 0; index < subfrm->num_sofs; index++) { + switch (subfrm->sofs[index]) { + case MDP_RDMA0: + MM_REG_CLEAR(cmd, RDMA0_SOF); + break; + case MDP_TDSHP0: + MM_REG_CLEAR(cmd, TDSHP0_SOF); + break; + case MDP_SCL0: + MM_REG_CLEAR(cmd, RSZ0_SOF); + break; + case MDP_SCL1: + MM_REG_CLEAR(cmd, RSZ1_SOF); + break; + case MDP_WDMA: + MM_REG_CLEAR(cmd, WDMA0_SOF); + break; + case MDP_WROT0: +#if WROT0_DISP_SRAM_SHARING + MM_REG_WAIT_NO_CLEAR(cmd, WROT0_SRAM_READY); +#endif + MM_REG_CLEAR(cmd, WROT0_SOF); + break; + default: + break; + } + } + + /* Enable the mutex */ + MM_REG_WRITE(cmd, subsys_id, mm_mutex, MM_MUTEX_EN, 0x1, + 0x00000001); + + /* Wait SOF events and clear mutex modules (optional) */ + for (index = 0; index < subfrm->num_sofs; index++) { + switch (subfrm->sofs[index]) { + case MDP_RDMA0: + MM_REG_WAIT(cmd, RDMA0_SOF); + break; + case MDP_TDSHP0: + MM_REG_WAIT(cmd, TDSHP0_SOF); + break; + case MDP_SCL0: + MM_REG_WAIT(cmd, RSZ0_SOF); + break; + case MDP_SCL1: + MM_REG_WAIT(cmd, RSZ1_SOF); + break; + case MDP_WDMA: + MM_REG_WAIT(cmd, WDMA0_SOF); + break; + case MDP_WROT0: + MM_REG_WAIT(cmd, WROT0_SOF); + break; + default: + break; + } + } + } + return 0; +} + +static int mdp_path_config_subfrm(struct mdp_cmd *cmd, struct mdp_path *path, + u32 count) +{ + struct mdp_path_subfrm subfrm; + const struct img_config *config = path->config; + const struct img_mmsys_ctrl *ctrl = &config->ctrls[count]; + const struct img_mux *set; + struct mdp_comp_ctx *ctx; + phys_addr_t mmsys = path->mdp_dev->mmsys.reg_base; + int index, ret; + u8 subsys_id = path->mdp_dev->mmsys.subsys_id; + + /* Acquire components */ + ret = mdp_path_subfrm_require(&subfrm, path, cmd, count); + if (ret) + return ret; + /* Enable mux settings */ + for (index = 0; index < ctrl->num_sets; index++) { + set = &ctrl->sets[index]; + MM_REG_WRITE_MASK(cmd, subsys_id, mmsys, set->reg, set->value, + 0xFFFFFFFF); + } + /* Config sub-frame information */ + for (index = (config->num_components - 1); index >= 0; index--) { + ctx = &path->comps[index]; + if (is_output_disable(ctx->param, count)) + continue; + ret = call_op(ctx, config_subfrm, cmd, count); + if (ret) + return ret; + } + /* Run components */ + ret = mdp_path_subfrm_run(&subfrm, path, cmd); + if (ret) + return ret; + /* Wait components done */ + for (index = 0; index < config->num_components; index++) { + ctx = &path->comps[index]; + if (is_output_disable(ctx->param, count)) + continue; + ret = call_op(ctx, wait_comp_event, cmd); + if (ret) + return ret; + } + /* Advance to the next sub-frame */ + for (index = 0; index < config->num_components; index++) { + ctx = &path->comps[index]; + ret = call_op(ctx, advance_subfrm, cmd, count); + if (ret) + return ret; + } + /* Disable mux settings */ + for (index = 0; index < ctrl->num_sets; index++) { + set = &ctrl->sets[index]; + MM_REG_WRITE_MASK(cmd, subsys_id, mmsys, set->reg, 0, + 0xFFFFFFFF); + } + return 0; +} + +static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmd *cmd, + struct mdp_path *path) +{ + const struct img_config *config = path->config; + struct mdp_comp_ctx *ctx; + int index, count, ret; + + for (index = 0; index < config->num_components; index++) { + ret = mdp_comp_ctx_init(mdp, &path->comps[index], + &config->components[index], + path->param); + if (ret) + return ret; + } + + /* Config path frame */ + /* Reset components */ + for (index = 0; index < config->num_components; index++) { + ctx = &path->comps[index]; + ret = call_op(ctx, init_comp, cmd); + if (ret) + return ret; + } + /* Config frame mode */ + for (index = 0; index < config->num_components; index++) { + const struct v4l2_rect *compose = + path->composes[ctx->param->outputs[0]]; + + ctx = &path->comps[index]; + ret = call_op(ctx, config_frame, cmd, compose); + if (ret) + return ret; + } + + /* Config path sub-frames */ + for (count = 0; count < config->num_subfrms; count++) { + ret = mdp_path_config_subfrm(cmd, path, count); + if (ret) + return ret; + } + /* Post processing information */ + for (index = 0; index < config->num_components; index++) { + ctx = &path->comps[index]; + ret = call_op(ctx, post_process, cmd); + if (ret) + return ret; + } + return 0; +} + +static void mdp_auto_release_work(struct work_struct *work) +{ + struct mdp_cmdq_cb_param *cb_param; + struct mdp_dev *mdp; + + cb_param = container_of(work, struct mdp_cmdq_cb_param, + auto_release_work); + mdp = cb_param->mdp; + + if (cb_param->comps && cb_param->num_comps) { + int i; + + for (i = 0; i < cb_param->num_comps; i++) + mdp_comp_clock_off(&mdp->pdev->dev, + &cb_param->comps[i]); + } + + kfree(cb_param->comps); + kfree(cb_param); + + atomic_dec(&mdp->job_count); + wake_up(&mdp->callback_wq); +} + +static void mdp_handle_cmdq_callback(struct cmdq_cb_data data) +{ + struct mdp_cmdq_cb_param *cb_param; + struct mdp_dev *mdp; + + if (!data.data) { + mdp_err("%s:no callback data\n", __func__); + return; + } + + cb_param = (struct mdp_cmdq_cb_param *)data.data; + mdp = cb_param->mdp; + + if (cb_param->mdp_ctx) + mdp_m2m_job_finish(cb_param->mdp_ctx); +#ifdef MDP_DEBUG + if (data.sta == CMDQ_CB_ERROR) { + struct mdp_func_struct *p_func = mdp_get_func(); + + p_func->mdp_dump_mmsys_config(); + mdp_dump_info(~0, 1); + } +#endif + + if (cb_param->user_cmdq_cb) { + struct cmdq_cb_data user_cb_data; + + user_cb_data.sta = data.sta; + user_cb_data.data = cb_param->user_cb_data; + cb_param->user_cmdq_cb(user_cb_data); + } + + cmdq_pkt_destroy(cb_param->pkt); + INIT_WORK(&cb_param->auto_release_work, mdp_auto_release_work); + queue_work(mdp->clock_wq, &cb_param->auto_release_work); +} + +int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) +{ + struct mdp_cmd cmd; + struct mdp_path path; + int i, ret; + + if (atomic_read(&mdp->suspended)) + return -ECANCELED; + + atomic_inc(&mdp->job_count); + + cmd.pkt = cmdq_pkt_create(mdp->cmdq_clt, SZ_16K); + if (IS_ERR(cmd.pkt)) { + atomic_dec(&mdp->job_count); + wake_up(&mdp->callback_wq); + return PTR_ERR(cmd.pkt); + } + cmd.event = &mdp->event[0]; + + path.mdp_dev = mdp; + path.config = param->config; + path.param = param->param; + for (i = 0; i < param->param->num_outputs; i++) { + path.bounds[i].left = 0; + path.bounds[i].top = 0; + path.bounds[i].width = + param->param->outputs[i].buffer.format.width; + path.bounds[i].height = + param->param->outputs[i].buffer.format.height; + path.composes[i] = param->composes[i] ? + param->composes[i] : &path.bounds[i]; + } + ret = mdp_path_config(mdp, &cmd, &path); + if (ret) { + atomic_dec(&mdp->job_count); + wake_up(&mdp->callback_wq); + return ret; + } + + // TODO: engine conflict dispatch + for (i = 0; i < param->config->num_components; i++) + mdp_comp_clock_on(&mdp->pdev->dev, path.comps[i].comp); + + if (param->wait) { + ret = cmdq_pkt_flush(cmd.pkt); +#ifdef MDP_DEBUG + if (ret) { + struct mdp_func_struct *p_func = mdp_get_func(); + + p_func->mdp_dump_mmsys_config(); + mdp_dump_info(~0, 1); + } +#endif + if (param->mdp_ctx) + mdp_m2m_job_finish(param->mdp_ctx); + cmdq_pkt_destroy(cmd.pkt); + for (i = 0; i < param->config->num_components; i++) + mdp_comp_clock_off(&mdp->pdev->dev, path.comps[i].comp); + + atomic_dec(&mdp->job_count); + wake_up(&mdp->callback_wq); + } else { + struct mdp_cmdq_cb_param *cb_param; + struct mdp_comp *comps; + + cb_param = kzalloc(sizeof(*cb_param), GFP_KERNEL); + if (!cb_param) + return -ENOMEM; + comps = kcalloc(param->config->num_components, sizeof(*comps), + GFP_KERNEL); + if (!comps) { + kfree(cb_param); + mdp_err("%s:comps alloc fail!\n", __func__); + return -ENOMEM; + } + + for (i = 0; i < param->config->num_components; i++) + memcpy(&comps[i], path.comps[i].comp, + sizeof(struct mdp_comp)); + cb_param->mdp = mdp; + cb_param->user_cmdq_cb = param->cmdq_cb; + cb_param->user_cb_data = param->cb_data; + cb_param->pkt = cmd.pkt; + cb_param->comps = comps; + cb_param->num_comps = param->config->num_components; + cb_param->mdp_ctx = param->mdp_ctx; + + ret = cmdq_pkt_flush_async(cmd.pkt, + mdp_handle_cmdq_callback, + (void *)cb_param); + if (ret) { + mdp_err("%s:cmdq_pkt_flush_async fail!\n", __func__); + kfree(cb_param); + kfree(comps); + } + } + return ret; +} + +int mdp_cmdq_sendtask(struct platform_device *pdev, struct img_config *config, + struct img_ipi_frameparam *param, + struct v4l2_rect *compose, unsigned int wait, + void (*cmdq_cb)(struct cmdq_cb_data data), void *cb_data) +{ + struct mdp_dev *mdp = platform_get_drvdata(pdev); + struct mdp_cmdq_param task = { + .config = config, + .param = param, + .composes[0] = compose, + .wait = wait, + .cmdq_cb = cmdq_cb, + .cb_data = cb_data, + }; + + return mdp_cmdq_send(mdp, &task); +} +EXPORT_SYMBOL_GPL(mdp_cmdq_sendtask); + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h new file mode 100644 index 000000000000..6b8b0f6b4bb5 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MTK_MDP3_CMDQ_H__ +#define __MTK_MDP3_CMDQ_H__ + +#include +#include +#include +#include "mtk-img-ipi.h" + +struct platform_device *mdp_get_plat_device(struct platform_device *pdev); + +int mdp_cmdq_sendtask(struct platform_device *pdev, struct img_config *config, + struct img_ipi_frameparam *param, + struct v4l2_rect *compose, unsigned int wait, + void (*cmdq_cb)(struct cmdq_cb_data data), void *cb_data); + +struct mdp_cmd { + struct cmdq_pkt *pkt; + s32 *event; +}; + +struct mdp_cmdq_param { + struct img_config *config; + struct img_ipi_frameparam *param; + const struct v4l2_rect *composes[IMG_MAX_HW_OUTPUTS]; + unsigned int wait; + + void (*cmdq_cb)(struct cmdq_cb_data data); + void *cb_data; + void *mdp_ctx; +}; + +struct mdp_cmdq_cb_param { + struct work_struct auto_release_work; + struct mdp_dev *mdp; + void (*user_cmdq_cb)(struct cmdq_cb_data data); + void *user_cb_data; + struct cmdq_pkt *pkt; + struct mdp_comp *comps; + u8 num_comps; + void *mdp_ctx; +}; + +struct mdp_dev; + +int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param); + +#endif /* __MTK_MDP3_CMDQ_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c new file mode 100644 index 000000000000..3033cd32340c --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c @@ -0,0 +1,1329 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#include +#include +#include +#include +#include "mtk-mdp3-comp.h" +#include "mtk-mdp3-core.h" +#include "mtk-mdp3-regs.h" + +#include "mdp-platform.h" +#include "mmsys_config.h" +#include "mdp_reg_rdma.h" +#include "mdp_reg_ccorr.h" +#include "mdp_reg_rsz.h" +#include "mdp_reg_wrot.h" +#include "mdp_reg_wdma.h" +#include "isp_reg.h" + +static s64 get_comp_flag(const struct mdp_comp_ctx *ctx) +{ +#if RDMA0_RSZ1_SRAM_SHARING + if (ctx->comp->id == MDP_RDMA0) + return (1 << MDP_RDMA0) | (1 << MDP_SCL1); +#endif + return 1 << ctx->comp->id; +} + +static int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; +#if RDMA0_RSZ1_SRAM_SHARING + struct mdp_comp *prz1 = ctx->comp->mdp_dev->comp[MDP_SCL1]; + + /* Disable RSZ1 */ + if (ctx->comp->id == MDP_RDMA0 && prz1) + MM_REG_WRITE(cmd, subsys_id, prz1->reg_base, PRZ_ENABLE, + 0x00000000, 0x00000001); +#endif + /* Reset RDMA */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESET, 0x00000001, + 0x00000001); + MM_REG_POLL(cmd, subsys_id, base, MDP_RDMA_MON_STA_1, 0x00000100, + 0x00000100); + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESET, 0x00000000, + 0x00000001); + return 0; +} + +static int config_rdma_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose) +{ + const struct mdp_rdma_data *rdma = &ctx->param->rdma; + u32 colorformat = ctx->input->buffer.format.colorformat; + bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat); + bool en_ufo = MDP_COLOR_IS_UFP(colorformat); + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + +#if RDMA_SUPPORT_10BIT + if (block10bit) + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESV_DUMMY_0, + 0x00000007, 0x00000007); + else + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESV_DUMMY_0, + 0x00000000, 0x00000007); +#endif + + /* Setup smi control */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_GMCIF_CON, + (1 << 0) + + (7 << 4) + //burst type to 8 + (1 << 16), //enable pre-ultra + 0x00030071); + + /* Setup source frame info */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_CON, rdma->src_ctrl, + 0x03C8FE0F); +#if RDMA_SUPPORT_10BIT + if (en_ufo) { + /* Setup source buffer base */ + MM_REG_WRITE(cmd, subsys_id, + base, MDP_RDMA_UFO_DEC_LENGTH_BASE_Y, + rdma->ufo_dec_y, 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, + base, MDP_RDMA_UFO_DEC_LENGTH_BASE_C, + rdma->ufo_dec_c, 0xFFFFFFFF); + /* Set 10bit source frame pitch */ + if (block10bit) + MM_REG_WRITE(cmd, subsys_id, + base, MDP_RDMA_MF_BKGD_SIZE_IN_PXL, + rdma->mf_bkgd_in_pxl, 0x001FFFFF); + } +#endif + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_CON, rdma->control, + 0x00001110); + /* Setup source buffer base */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, rdma->iova[0], + 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, rdma->iova[1], + 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, rdma->iova[2], + 0xFFFFFFFF); + /* Setup source buffer end */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_0, + rdma->iova_end[0], 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_1, + rdma->iova_end[1], 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_2, + rdma->iova_end[2], 0xFFFFFFFF); + /* Setup source frame pitch */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE, + rdma->mf_bkgd, 0x001FFFFF); + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SF_BKGD_SIZE_IN_BYTE, + rdma->sf_bkgd, 0x001FFFFF); + /* Setup color transform */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_TRANSFORM_0, + rdma->transform, 0x0F110000); + + return 0; +} + +static int config_rdma_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + const struct mdp_rdma_subfrm *subfrm = &ctx->param->rdma.subfrms[index]; + const struct img_comp_subfrm *csf = &ctx->param->subfrms[index]; + u32 colorformat = ctx->input->buffer.format.colorformat; + bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat); + bool en_ufo = MDP_COLOR_IS_UFP(colorformat); + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* Enable RDMA */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, 0x00000001, + 0x00000001); + + /* Set Y pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0, + subfrm->offset[0], 0xFFFFFFFF); +#if RDMA_SUPPORT_10BIT + /* Set 10bit UFO mode */ + if (block10bit && en_ufo) + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0_P, + subfrm->offset_0_p, 0xFFFFFFFF); +#endif + /* Set U pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_1, + subfrm->offset[1], 0xFFFFFFFF); + /* Set V pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_2, + subfrm->offset[2], 0xFFFFFFFF); + /* Set source size */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, subfrm->src, + 0x1FFF1FFF); + /* Set target size */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_CLIP_SIZE, + subfrm->clip, 0x1FFF1FFF); + /* Set crop offset */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_OFFSET_1, + subfrm->clip_ofst, 0x003F001F); + +#if RDMA_UPSAMPLE_REPEAT_ONLY + if ((csf->in.right - csf->in.left + 1) > 320) + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESV_DUMMY_0, + 0x00000004, 0x00000004); +#endif + + return 0; +} + +static int wait_rdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + if (ctx->comp->alias_id == 0) + MM_REG_WAIT(cmd, RDMA0_DONE); + else + pr_err("Do not support RDMA1_DONE event\n"); + + /* Disable RDMA */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, 0x00000000, + 0x00000001); + return 0; +} + +static const struct mdp_comp_ops rdma_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = init_rdma, + .config_frame = config_rdma_frame, + .config_subfrm = config_rdma_subfrm, + /* .reconfig_frame = reconfig_rdma_frame, */ + /* .reconfig_subfrms = reconfig_rdma_subfrms, */ + .wait_comp_event = wait_rdma_event, + .advance_subfrm = NULL, + .post_process = NULL, +}; + +static int init_rsz(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* Reset RSZ */ + MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x00010000, + 0x00010000); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x00000000, + 0x00010000); + /* Enable RSZ */ + MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x00000001, + 0x00000001); + return 0; +} + +static int config_rsz_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose) +{ + const struct mdp_rsz_data *rsz = &ctx->param->rsz; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + if (ctx->param->frame.bypass) { + /* Disable RSZ */ + MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x00000000, + 0x00000001); + + return 0; + } + + MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, rsz->control1, + 0x03FFFDF3); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, rsz->control2, + 0x0FFFC290); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_HORIZONTAL_COEFF_STEP, + rsz->coeff_step_x, 0x007FFFFF); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_VERTICAL_COEFF_STEP, + rsz->coeff_step_y, 0x007FFFFF); + return 0; +} + +static int config_rsz_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + const struct mdp_rsz_subfrm *subfrm = &ctx->param->rsz.subfrms[index]; + const struct img_comp_subfrm *csf = &ctx->param->subfrms[index]; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, subfrm->control2, + 0x00003800); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_INPUT_IMAGE, subfrm->src, + 0xFFFFFFFF); +#if RSZ_DISABLE_DCM_SMALL_TILE + if ((csf->in.right - csf->in.left + 1) <= 16) + MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, 1 << 27, + 1 << 27); +#endif + MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET, + csf->luma.left, 0x0000FFFF); + MM_REG_WRITE(cmd, subsys_id, + base, PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET, + csf->luma.left_subpix, 0x001FFFFF); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_INTEGER_OFFSET, + csf->luma.top, 0x0000FFFF); + MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET, + csf->luma.top_subpix, 0x001FFFFF); + MM_REG_WRITE(cmd, subsys_id, + base, PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET, + csf->chroma.left, 0x0000FFFF); + MM_REG_WRITE(cmd, subsys_id, + base, PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET, + csf->chroma.left_subpix, 0x001FFFFF); + + MM_REG_WRITE(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, subfrm->clip, + 0xFFFFFFFF); + + return 0; +} + +static int advance_rsz_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ +#if RSZ_DISABLE_DCM_SMALL_TILE + const struct img_comp_subfrm *csf = &ctx->param->subfrms[index]; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + if ((csf->in.right - csf->in.left + 1) <= 16) + MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, 0, 1 << 27); +#endif + return 0; +} + +static const struct mdp_comp_ops rsz_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = init_rsz, + .config_frame = config_rsz_frame, + .config_subfrm = config_rsz_subfrm, + /* .reconfig_frame = NULL, */ + /* .reconfig_subfrms = NULL, */ + .wait_comp_event = NULL, + .advance_subfrm = advance_rsz_subfrm, + .post_process = NULL, +}; + +static int init_wrot(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + +#if WROT_FILTER_CONSTRAINT + /* Wait WROT SRAM shared to DISP RDMA */ + if (ctx->comp->alias_id == 0) + pr_err("Do not support WROT0_SRAM_READY event\n"); + else + pr_err("Do not support WROT1_SRAM_READY event\n"); +#endif + /* Reset WROT */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_SOFT_RST, 0x01, 0x00000001); + MM_REG_POLL(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x01, + 0x00000001); + MM_REG_WRITE(cmd, subsys_id, base, VIDO_SOFT_RST, 0x00, 0x00000001); + MM_REG_POLL(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x00, + 0x00000001); + return 0; +} + +static int config_wrot_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose) +{ + const struct mdp_wrot_data *wrot = &ctx->param->wrot; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* Write frame base address */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR, wrot->iova[0], + 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_C, wrot->iova[1], + 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_V, wrot->iova[2], + 0xFFFFFFFF); + /* Write frame related registers */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_CTRL, wrot->control, + 0xF131510F); + /* Write frame Y pitch */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE, wrot->stride[0], + 0x0000FFFF); + /* Write frame UV pitch */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_C, wrot->stride[1], + 0x0000FFFF); + MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_V, wrot->stride[2], + 0x0000FFFF); + /* Write matrix control */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAT_CTRL, wrot->mat_ctrl, + 0x000000F3); + + /* Set the fixed ALPHA as 0xFF */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_DITHER, 0xFF000000, + 0xFF000000); + /* Set VIDO_EOL_SEL */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_RSV_1, 0x80000000, + 0x80000000); + /* Set VIDO_FIFO_TEST */ + if (wrot->fifo_test != 0) + MM_REG_WRITE(cmd, subsys_id, base, VIDO_FIFO_TEST, + wrot->fifo_test, 0x00000FFF); + +#if WROT_FILTER_CONSTRAINT + /* Filter enable */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, wrot->filter, + 0x00000077); +#endif + + return 0; +} + +static int config_wrot_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + const struct mdp_wrot_subfrm *subfrm = &ctx->param->wrot.subfrms[index]; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* Write Y pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR, + subfrm->offset[0], 0x0FFFFFFF); + /* Write U pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_C, + subfrm->offset[1], 0x0FFFFFFF); + /* Write V pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_V, + subfrm->offset[2], 0x0FFFFFFF); + /* Write source size */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_IN_SIZE, subfrm->src, + 0x1FFF1FFF); + /* Write target size */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_TAR_SIZE, subfrm->clip, + 0x1FFF1FFF); + MM_REG_WRITE(cmd, subsys_id, base, VIDO_CROP_OFST, subfrm->clip_ofst, + 0x1FFF1FFF); + + MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, + subfrm->main_buf, 0x1FFF7F00); + + /* Enable WROT */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, 0x01, 0x00000001); + + return 0; +} + +static int wait_wrot_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + if (ctx->comp->alias_id == 0) + MM_REG_WAIT(cmd, WROT0_DONE); + else + pr_err("Do not support WROT1_DONE event\n"); +#if WROT_FILTER_CONSTRAINT + /* Filter disable */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, + (0 << 4) + + (0 << 0), + 0x00000077); +#endif + /* Disable WROT */ + MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, 0x00, 0x00000001); + + return 0; +} + +static const struct mdp_comp_ops wrot_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = init_wrot, + .config_frame = config_wrot_frame, + .config_subfrm = config_wrot_subfrm, + /* .reconfig_frame = reconfig_wrot_frame, */ + /* .reconfig_subfrms = reconfig_wrot_subfrms, */ + .wait_comp_event = wait_wrot_event, + .advance_subfrm = NULL, + .post_process = NULL, +}; + +static int init_wdma(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* Reset WDMA */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_RST, 0x1, 0x00000001); + MM_REG_POLL(cmd, subsys_id, base, WDMA_FLOW_CTRL_DBG, 0x01, + 0x00000001); + MM_REG_WRITE(cmd, subsys_id, base, WDMA_RST, 0x0, 0x00000001); + return 0; +} + +static int config_wdma_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose) +{ + const struct mdp_wdma_data *wdma = &ctx->param->wdma; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + MM_REG_WRITE(cmd, subsys_id, base, WDMA_BUF_CON2, 0x10101050, + 0xFFFFFFFF); + + /* Setup frame information */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_CFG, wdma->wdma_cfg, + 0x0F01B8F0); + /* Setup frame base address */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR, wdma->iova[0], + 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR, wdma->iova[1], + 0xFFFFFFFF); + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR, wdma->iova[2], + 0xFFFFFFFF); + /* Setup Y pitch */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_W_IN_BYTE, + wdma->w_in_byte, 0x0000FFFF); + /* Setup UV pitch */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_UV_PITCH, + wdma->uv_stride, 0x0000FFFF); + /* Set the fixed ALPHA as 0xFF */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_ALPHA, 0x800000FF, + 0x800000FF); + + return 0; +} + +static int config_wdma_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + const struct mdp_wdma_subfrm *subfrm = &ctx->param->wdma.subfrms[index]; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* Write Y pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR_OFFSET, + subfrm->offset[0], 0x0FFFFFFF); + /* Write U pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR_OFFSET, + subfrm->offset[1], 0x0FFFFFFF); + /* Write V pixel offset */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR_OFFSET, + subfrm->offset[2], 0x0FFFFFFF); + /* Write source size */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_SRC_SIZE, subfrm->src, + 0x3FFF3FFF); + /* Write target size */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_SIZE, subfrm->clip, + 0x3FFF3FFF); + /* Write clip offset */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_COORD, subfrm->clip_ofst, + 0x3FFF3FFF); + + /* Enable WDMA */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_EN, 0x01, 0x00000001); + + return 0; +} + +static int wait_wdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + MM_REG_WAIT(cmd, WDMA0_DONE); + /* Disable WDMA */ + MM_REG_WRITE(cmd, subsys_id, base, WDMA_EN, 0x00, 0x00000001); + return 0; +} + +static const struct mdp_comp_ops wdma_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = init_wdma, + .config_frame = config_wdma_frame, + .config_subfrm = config_wdma_subfrm, + /* .reconfig_frame = reconfig_wdma_frame, */ + /* .reconfig_subfrms = reconfig_wdma_subfrms, */ + .wait_comp_event = wait_wdma_event, + .advance_subfrm = NULL, + .post_process = NULL, +}; + +static int init_ccorr(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* CCORR enable */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_EN, 0x1, 0x1); + /* Relay mode */ + MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_CFG, 0x1, 0x1); + return 0; +} + +static int config_ccorr_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose) +{ + /* Disabled function */ + return 0; +} + +static int config_ccorr_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + const struct img_comp_subfrm *csf = &ctx->param->subfrms[index]; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + u32 hsize, vsize; + + hsize = csf->in.right - csf->in.left + 1; + vsize = csf->in.bottom - csf->in.top + 1; + MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_SIZE, + (hsize << 16) + (vsize << 0), 0x1FFF1FFF); + return 0; +} + +static const struct mdp_comp_ops ccorr_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = init_ccorr, + .config_frame = config_ccorr_frame, + .config_subfrm = config_ccorr_subfrm, + /* .reconfig_frame = NULL, */ + /* .reconfig_subfrms = NULL, */ + .wait_comp_event = NULL, + .advance_subfrm = NULL, + .post_process = NULL, +}; + +static int init_isp(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + const struct isp_data *isp = &ctx->param->isp; + phys_addr_t mmsys = ctx->comp->mdp_dev->mmsys.reg_base; + u8 subsys_id = ctx->comp->mdp_dev->mmsys.subsys_id; + + /* Direct link */ + if (isp->dl_flags & (1 << MDP_CAMIN)) { + mdp_dbg(2, "SW_RST ASYNC"); + /* Reset MDP_DL_ASYNC_TX */ + /* Bit 3: MDP_DL_ASYNC_TX / MDP_RELAY */ + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 0x0, + 0x00000008); + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 1 << 3, + 0x00000008); + /* Reset MDP_DL_ASYNC_RX */ + /* Bit 10: MDP_DL_ASYNC_RX */ + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 0x0, + 0x00000400); + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 1 << 10, + 0x00000400); + + /* Enable sof mode */ + MM_REG_WRITE(cmd, subsys_id, mmsys, ISP_RELAY_CFG_WD, 0 << 31, + 0x80000000); + } + + if (isp->dl_flags & (1 << MDP_CAMIN2)) { + mdp_dbg(2, "SW_RST ASYNC2"); + /* Reset MDP_DL_ASYNC2_TX */ + /* Bit 4: MDP_DL_ASYNC2_TX / MDP_RELAY2 */ + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 0x0, + 0x00000010); + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW0_RST_B, 1 << 4, + 0x00000010); + /* Reset MDP_DL_ASYNC2_RX */ + /* Bit 11: MDP_DL_ASYNC2_RX */ + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 0x0, + 0x00000800); + MM_REG_WRITE(cmd, subsys_id, mmsys, MMSYS_SW1_RST_B, 1 << 11, + 0x00000800); + + /* Enable sof mode */ + MM_REG_WRITE(cmd, subsys_id, mmsys, IPU_RELAY_CFG_WD, 0 << 31, + 0x80000000); + } + + return 0; +} + +static int config_isp_frame(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose) +{ + const struct isp_data *isp = &ctx->param->isp; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* DIP_X_SMX1I_BASE_ADDR, DIP_X_SMX1O_BASE_ADDR */ + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2890, isp->smxi_iova[0], + 0xFFFFFFFF); + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x27D0, isp->smxi_iova[0], + 0xFFFFFFFF); + /* DIP_X_SMX2I_BASE_ADDR, DIP_X_SMX2O_BASE_ADDR */ + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x28C0, isp->smxi_iova[1], + 0xFFFFFFFF); + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2800, isp->smxi_iova[1], + 0xFFFFFFFF); + /* DIP_X_SMX3I_BASE_ADDR, DIP_X_SMX3O_BASE_ADDR */ + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x28F0, isp->smxi_iova[2], + 0xFFFFFFFF); + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2830, isp->smxi_iova[2], + 0xFFFFFFFF); + /* DIP_X_SMX4I_BASE_ADDR, DIP_X_SMX4O_BASE_ADDR */ + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2920, isp->smxi_iova[3], + 0xFFFFFFFF); + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2860, isp->smxi_iova[3], + 0xFFFFFFFF); + + switch (isp->cq_idx) { + case ISP_DRV_DIP_CQ_THRE0: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2208, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE1: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2214, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE2: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2220, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE3: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x222C, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE4: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2238, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE5: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2244, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE6: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2250, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE7: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x225C, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE8: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2268, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE9: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2274, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE10: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2280, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE11: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x228C, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE12: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2298, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE13: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x22A4, + isp->cq_iova, 0xFFFFFFFF); + break; + case ISP_DRV_DIP_CQ_THRE14: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x22B0, + isp->cq_iova, 0xFFFFFFFF); + break; + /* From CQ15 to CQ18, these do not connect to GCE */ + default: + mdp_err("Do not support this cq (%d)", isp->cq_idx); + return -EINVAL; + } + + return 0; +} + +static int config_isp_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2304, + ctx->param->isp.tpipe_iova[index], 0xFFFFFFFF); + return 0; +} + +static int wait_isp_event(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd) +{ + const struct isp_data *isp = &ctx->param->isp; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + + /* MDP_DL_SEL: select MDP_CROP */ + if (isp->dl_flags & (1 << MDP_CAMIN)) + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x0030, 0x00000000, + 0x00000200); + /* MDP2_DL_SEL: select MDP_CROP2 */ + if (isp->dl_flags & (1 << MDP_CAMIN2)) + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x0030, 0x00000000, + 0x00000C00); + + switch (isp->cq_idx) { + case ISP_DRV_DIP_CQ_THRE0: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0001, + 0x00000001); + MM_REG_WAIT(cmd, ISP_P2_0_DONE); + break; + case ISP_DRV_DIP_CQ_THRE1: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0002, + 0x00000002); + MM_REG_WAIT(cmd, ISP_P2_1_DONE); + break; + case ISP_DRV_DIP_CQ_THRE2: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0004, + 0x00000004); + MM_REG_WAIT(cmd, ISP_P2_2_DONE); + break; + case ISP_DRV_DIP_CQ_THRE3: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0008, + 0x00000008); + MM_REG_WAIT(cmd, ISP_P2_3_DONE); + break; + case ISP_DRV_DIP_CQ_THRE4: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0010, + 0x00000010); + MM_REG_WAIT(cmd, ISP_P2_4_DONE); + break; + case ISP_DRV_DIP_CQ_THRE5: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0020, + 0x00000020); + MM_REG_WAIT(cmd, ISP_P2_5_DONE); + break; + case ISP_DRV_DIP_CQ_THRE6: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0040, + 0x00000040); + MM_REG_WAIT(cmd, ISP_P2_6_DONE); + break; + case ISP_DRV_DIP_CQ_THRE7: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0080, + 0x00000080); + MM_REG_WAIT(cmd, ISP_P2_7_DONE); + break; + case ISP_DRV_DIP_CQ_THRE8: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0100, + 0x00000100); + MM_REG_WAIT(cmd, ISP_P2_8_DONE); + break; + case ISP_DRV_DIP_CQ_THRE9: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0200, + 0x00000200); + MM_REG_WAIT(cmd, ISP_P2_9_DONE); + break; + case ISP_DRV_DIP_CQ_THRE10: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0400, + 0x00000400); + MM_REG_WAIT(cmd, ISP_P2_10_DONE); + break; + case ISP_DRV_DIP_CQ_THRE11: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x0800, + 0x00000800); + MM_REG_WAIT(cmd, ISP_P2_11_DONE); + break; + case ISP_DRV_DIP_CQ_THRE12: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x1000, + 0x00001000); + MM_REG_WAIT(cmd, ISP_P2_12_DONE); + break; + case ISP_DRV_DIP_CQ_THRE13: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x2000, + 0x00002000); + MM_REG_WAIT(cmd, ISP_P2_13_DONE); + break; + case ISP_DRV_DIP_CQ_THRE14: + MM_REG_WRITE_MASK(cmd, subsys_id, base, 0x2000, 0x4000, + 0x00004000); + MM_REG_WAIT(cmd, ISP_P2_14_DONE); + break; + /* From CQ15 to CQ18, these do not connect to GCE */ + default: + mdp_err("Do not support this cq (%d)", isp->cq_idx); + return -EINVAL; + } + + return 0; +} + +static const struct mdp_comp_ops imgi_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = init_isp, + .config_frame = config_isp_frame, + .config_subfrm = config_isp_subfrm, + /* .reconfig_frame = reconfig_isp_frame, */ + /* .reconfig_subfrms = reconfig_isp_subfrms, */ + .wait_comp_event = wait_isp_event, + .advance_subfrm = NULL, + .post_process = NULL, +}; + +static int config_camin_subfrm(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index) +{ + const struct img_comp_subfrm *csf = &ctx->param->subfrms[index]; + phys_addr_t base = ctx->comp->reg_base; + u8 subsys_id = ctx->comp->subsys_id; + u32 isp_dl_w, isp_dl_h; + + isp_dl_w = csf->in.right - csf->in.left + 1; + isp_dl_h = csf->in.bottom - csf->in.top + 1; + + /* Config for direct link */ + if (ctx->comp->alias_id == 0) { +#ifdef MDP_ASYNC_CFG_WD + MM_REG_WRITE(cmd, subsys_id, base, MDP_ASYNC_CFG_WD, + (isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF); +#endif +#ifdef ISP_RELAY_CFG_WD + MM_REG_WRITE(cmd, subsys_id, base, ISP_RELAY_CFG_WD, + (isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF); +#endif + } else { +#ifdef MDP_ASYNC_IPU_CFG_WD + MM_REG_WRITE(cmd, subsys_id, base, MDP_ASYNC_IPU_CFG_WD, + (isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF); +#endif +#ifdef IPU_RELAY_CFG_WD + MM_REG_WRITE(cmd, subsys_id, base, IPU_RELAY_CFG_WD, + (isp_dl_h << 16) + isp_dl_w, 0x3FFF3FFF); +#endif + } + + return 0; +} + +static const struct mdp_comp_ops camin_ops = { + .get_comp_flag = get_comp_flag, + .init_comp = NULL, + .config_frame = NULL, + .config_subfrm = config_camin_subfrm, + /* .reconfig_frame = NULL, */ + /* .reconfig_subfrms = NULL, */ + .wait_comp_event = NULL, + .advance_subfrm = NULL, + .post_process = NULL, +}; + +static const struct mdp_comp_ops *mdp_comp_ops[MDP_COMP_TYPE_COUNT] = { + [MDP_COMP_TYPE_RDMA] = &rdma_ops, + [MDP_COMP_TYPE_RSZ] = &rsz_ops, + [MDP_COMP_TYPE_WROT] = &wrot_ops, + [MDP_COMP_TYPE_WDMA] = &wdma_ops, + [MDP_COMP_TYPE_PATH] = NULL, + + [MDP_COMP_TYPE_CCORR] = &ccorr_ops, + + [MDP_COMP_TYPE_IMGI] = &imgi_ops, + [MDP_COMP_TYPE_EXTO] = NULL, + [MDP_COMP_TYPE_DL_PATH] = &camin_ops, +}; + +struct mdp_comp_match { + enum mdp_comp_type type; + u32 alias_id; +}; + +static const struct mdp_comp_match mdp_comp_matches[MDP_MAX_COMP_COUNT] = { + [MDP_COMP_WPEI] = { MDP_COMP_TYPE_WPEI, 0 }, + [MDP_COMP_WPEO] = { MDP_COMP_TYPE_EXTO, 2 }, + [MDP_COMP_WPEI2] = { MDP_COMP_TYPE_WPEI, 1 }, + [MDP_COMP_WPEO2] = { MDP_COMP_TYPE_EXTO, 3 }, + [MDP_COMP_ISP_IMGI] = { MDP_COMP_TYPE_IMGI, 0 }, + [MDP_COMP_ISP_IMGO] = { MDP_COMP_TYPE_EXTO, 0 }, + [MDP_COMP_ISP_IMG2O] = { MDP_COMP_TYPE_EXTO, 1 }, + + [MDP_COMP_CAMIN] = { MDP_COMP_TYPE_DL_PATH, 0 }, + [MDP_COMP_CAMIN2] = { MDP_COMP_TYPE_DL_PATH, 1 }, + [MDP_COMP_RDMA0] = { MDP_COMP_TYPE_RDMA, 0 }, + [MDP_COMP_CCORR0] = { MDP_COMP_TYPE_CCORR, 0 }, + [MDP_COMP_RSZ0] = { MDP_COMP_TYPE_RSZ, 0 }, + [MDP_COMP_RSZ1] = { MDP_COMP_TYPE_RSZ, 1 }, + [MDP_COMP_PATH0_SOUT] = { MDP_COMP_TYPE_PATH, 0 }, + [MDP_COMP_PATH1_SOUT] = { MDP_COMP_TYPE_PATH, 1 }, + [MDP_COMP_WROT0] = { MDP_COMP_TYPE_WROT, 0 }, + [MDP_COMP_WDMA] = { MDP_COMP_TYPE_WDMA, 0 }, +}; + +static const char * const gce_event_names[MDP_MAX_EVENT_COUNT] = { + [RDMA0_SOF] = "rdma0_sof", + [RDMA0_DONE] = "rdma0_done", + [RSZ0_SOF] = "rsz0_sof", + [RSZ1_SOF] = "rsz1_sof", + [TDSHP0_SOF] = "tdshp0_sof", + [WROT0_SOF] = "wrot0_sof", + [WROT0_DONE] = "wrot0_done", + [WDMA0_SOF] = "wdma0_sof", + [WDMA0_DONE] = "wdma0_done", + + [ISP_P2_0_DONE] = "isp_p2_0_done", + [ISP_P2_1_DONE] = "isp_p2_1_done", + [ISP_P2_2_DONE] = "isp_p2_2_done", + [ISP_P2_3_DONE] = "isp_p2_3_done", + [ISP_P2_4_DONE] = "isp_p2_4_done", + [ISP_P2_5_DONE] = "isp_p2_5_done", + [ISP_P2_6_DONE] = "isp_p2_6_done", + [ISP_P2_7_DONE] = "isp_p2_7_done", + [ISP_P2_8_DONE] = "isp_p2_8_done", + [ISP_P2_9_DONE] = "isp_p2_9_done", + [ISP_P2_10_DONE] = "isp_p2_10_done", + [ISP_P2_11_DONE] = "isp_p2_11_done", + [ISP_P2_12_DONE] = "isp_p2_12_done", + [ISP_P2_13_DONE] = "isp_p2_13_done", + [ISP_P2_14_DONE] = "isp_p2_14_done", + + [WPE_DONE] = "wpe_done", + [WPE_B_DONE] = "wpe_b_done", +}; + +static const struct of_device_id mdp_comp_dt_ids[] = { + { + .compatible = "mediatek,mt8183-mdp-rdma", + .data = (void *)MDP_COMP_TYPE_RDMA, + }, { + .compatible = "mediatek,mt8183-mdp-ccorr", + .data = (void *)MDP_COMP_TYPE_CCORR, + }, { + .compatible = "mediatek,mt8183-mdp-rsz", + .data = (void *)MDP_COMP_TYPE_RSZ, + }, { + .compatible = "mediatek,mt8183-mdp-wrot", + .data = (void *)MDP_COMP_TYPE_WROT, + }, { + .compatible = "mediatek,mt8183-mdp-wdma", + .data = (void *)MDP_COMP_TYPE_WDMA, + }, { + .compatible = "mediatek,mt8183-mdp-path", + .data = (void *)MDP_COMP_TYPE_PATH, + }, { + .compatible = "mediatek,mt8183-mdp-imgi", + .data = (void *)MDP_COMP_TYPE_IMGI, + }, { + .compatible = "mediatek,mt8183-mdp-exto", + .data = (void *)MDP_COMP_TYPE_EXTO, + }, { + .compatible = "mediatek,mt8183-mdp-dl", + .data = (void *)MDP_COMP_TYPE_DL_PATH, + }, + {} +}; + +static int mdp_comp_get_id(struct device *dev, struct device_node *node, + enum mdp_comp_type type) +{ + u32 alias_id; + int i, ret; + + ret = of_property_read_u32(node, "mediatek,mdp-id", &alias_id); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(mdp_comp_matches); i++) + if (mdp_comp_matches[i].type == type && + mdp_comp_matches[i].alias_id == alias_id) + return i; + + dev_err(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id); + return -EINVAL; +} + +void mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp) +{ + int i, err; + + if (comp->larb_dev) { + err = pm_runtime_get_sync(comp->larb_dev); + if (err < 0) + dev_err(dev, + "Failed to get larb, err %d. type:%d id:%d\n", + err, comp->type, comp->id); + } + + for (i = 0; i < ARRAY_SIZE(comp->clks); i++) { + if (IS_ERR(comp->clks[i])) + break; + err = clk_prepare_enable(comp->clks[i]); + if (err) + dev_err(dev, + "Failed to enable clock %d, err %d. type:%d id:%d\n", + i, err, comp->type, comp->id); + } +} + +void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(comp->clks); i++) { + if (IS_ERR(comp->clks[i])) + break; + clk_disable_unprepare(comp->clks[i]); + } + + if (comp->larb_dev) + pm_runtime_put(comp->larb_dev); +} + +static int mdp_get_subsys_id(struct device *dev, struct device_node *node, + struct mdp_comp *comp) +{ + struct platform_device *comp_pdev; + struct cmdq_client_reg *cmdq_reg; + int ret = 0; + + if (!dev || !node || !comp) + return -EINVAL; + + comp_pdev = of_find_device_by_node(node); + + if (!comp_pdev) { + dev_err(dev, "get comp_pdev fail! comp id=%d type=%d\n", + comp->id, comp->type); + return -ENODEV; + } + + cmdq_reg = kzalloc(sizeof(*cmdq_reg), GFP_KERNEL); + if (!cmdq_reg) + return -ENOMEM; + + ret = cmdq_dev_get_client_reg(&comp_pdev->dev, cmdq_reg, 0); + if (ret != 0) { + dev_err(&comp_pdev->dev, + "cmdq_dev_get_subsys fail!\n"); + kfree(cmdq_reg); + return -EINVAL; + } + + comp->subsys_id = cmdq_reg->subsys; + dev_err(&comp_pdev->dev, "subsys id=%d\n", cmdq_reg->subsys); + + kfree(cmdq_reg); + + return 0; +} + +static void __mdp_comp_init(struct mdp_dev *mdp, struct device_node *node, + struct mdp_comp *comp) +{ + struct resource res; + phys_addr_t base; + + if (of_address_to_resource(node, 0, &res) < 0) + base = 0L; + else + base = 0L | res.start; + + comp->mdp_dev = mdp; + /* comp->dev_node = of_node_get(node); */ + comp->regs = of_iomap(node, 0); + comp->reg_base = base; +} + +static int mdp_mm_init(struct mdp_dev *mdp, + struct mdp_comp *comp, const char *ref_name) +{ + struct device_node *node; + struct device *dev = &mdp->pdev->dev; + + node = of_parse_phandle(dev->of_node, ref_name, 0); + if (!node) { + dev_err(dev, "Failed to parse dt %s\n", ref_name); + return -EINVAL; + } + + __mdp_comp_init(mdp, node, comp); + mdp_get_subsys_id(dev, node, comp); + of_node_put(node); + if (!comp->reg_base) { + dev_err(dev, "Failed to init %s base\n", ref_name); + return -EINVAL; + } + return 0; +} + +static int mdp_comp_init(struct device *dev, struct mdp_dev *mdp, + struct device_node *node, struct mdp_comp *comp, + enum mdp_comp_id id) +{ + struct device_node *larb_node; + struct platform_device *larb_pdev; + int i; + + if (id < 0 || id >= MDP_MAX_COMP_COUNT) { + dev_err(dev, "Invalid component id %d\n", id); + return -EINVAL; + } + + __mdp_comp_init(mdp, node, comp); + comp->type = mdp_comp_matches[id].type; + comp->id = id; + comp->alias_id = mdp_comp_matches[id].alias_id; + comp->ops = mdp_comp_ops[comp->type]; + + for (i = 0; i < ARRAY_SIZE(comp->clks); i++) { + comp->clks[i] = of_clk_get(node, i); + if (IS_ERR(comp->clks[i])) + break; + } + + mdp_get_subsys_id(dev, node, comp); + + /* Only DMA capable components need the LARB property */ + comp->larb_dev = NULL; + if (comp->type != MDP_COMP_TYPE_RDMA && + comp->type != MDP_COMP_TYPE_WROT && + comp->type != MDP_COMP_TYPE_WDMA) + return 0; + + larb_node = of_parse_phandle(node, "mediatek,larb", 0); + if (!larb_node) { + dev_err(dev, "Missing mediatek,larb phandle in %pOF node\n", + node); + return -EINVAL; + } + + larb_pdev = of_find_device_by_node(larb_node); + if (!larb_pdev) { + dev_warn(dev, "Waiting for larb device %pOF\n", larb_node); + of_node_put(larb_node); + return -EPROBE_DEFER; + } + of_node_put(larb_node); + + comp->larb_dev = &larb_pdev->dev; + + return 0; +} + +static void mdp_comp_deinit(struct mdp_comp *comp) +{ + iounmap(comp->regs); + /* of_node_put(comp->dev_node); */ +} + +void mdp_component_deinit(struct mdp_dev *mdp) +{ + int i; + + mdp_comp_deinit(&mdp->mmsys); + mdp_comp_deinit(&mdp->mm_mutex); + for (i = 0; i < ARRAY_SIZE(mdp->comp); i++) { + if (mdp->comp[i]) { + mdp_comp_deinit(mdp->comp[i]); + kfree(mdp->comp[i]); + } + } +} + +int mdp_component_init(struct mdp_dev *mdp) +{ + struct device *dev = &mdp->pdev->dev; + struct device_node *node, *parent; + int i, ret; + + for (i = RDMA0_SOF; i < MDP_MAX_EVENT_COUNT; i++) { + s32 event_id; + + if (!dev) + return -EINVAL; + if (of_property_read_u32_index(dev->of_node, + "mediatek,gce-events", + i, &event_id)) { + dev_err(dev, "can't parse gce-events property"); + + return -ENODEV; + } + mdp->event[i] = (event_id < 0) ? -i : event_id; + dev_info(dev, "Get event %s id:%d\n", + gce_event_names[i], mdp->event[i]); + } + + ret = mdp_mm_init(mdp, &mdp->mmsys, "mediatek,mmsys"); + if (ret) + goto err_init_mm; + + ret = mdp_mm_init(mdp, &mdp->mm_mutex, "mediatek,mm-mutex"); + if (ret) + goto err_init_mm; + + parent = dev->of_node->parent; + /* Iterate over sibling MDP function blocks */ + for_each_child_of_node(parent, node) { + const struct of_device_id *of_id; + enum mdp_comp_type type; + int id; + struct mdp_comp *comp; + + of_id = of_match_node(mdp_comp_dt_ids, node); + if (!of_id) + continue; + + if (!of_device_is_available(node)) { + dev_info(dev, "Skipping disabled component %pOF\n", + node); + continue; + } + + type = (enum mdp_comp_type)of_id->data; + id = mdp_comp_get_id(dev, node, type); + if (id < 0) { + dev_warn(dev, "Skipping unknown component %pOF\n", + node); + continue; + } + + comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto err_init_comps; + } + mdp->comp[id] = comp; + + ret = mdp_comp_init(dev, mdp, node, comp, id); + if (ret) + goto err_init_comps; + + dev_info(dev, "%s type:%d alias:%d id:%d base:%#x regs:%p\n", + of_id->compatible, type, comp->alias_id, id, + (u32)comp->reg_base, comp->regs); + } + return 0; + +err_init_comps: + mdp_component_deinit(mdp); +err_init_mm: + return ret; +} + +int mdp_comp_ctx_init(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx, + const struct img_compparam *param, + const struct img_ipi_frameparam *frame) +{ + int i; + + if (param->type < 0 || param->type >= MDP_MAX_COMP_COUNT) { + mdp_err("Invalid component id %d", param->type); + return -EINVAL; + } + + ctx->comp = mdp->comp[param->type]; + if (!ctx->comp) { + mdp_err("Uninit component id %d", param->type); + return -EINVAL; + } + + ctx->param = param; + ctx->input = &frame->inputs[param->input]; + for (i = 0; i < param->num_outputs; i++) + ctx->outputs[i] = &frame->outputs[param->outputs[i]]; + return 0; +} + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h new file mode 100644 index 000000000000..77d2c3e989c4 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MTK_MDP3_COMP_H__ +#define __MTK_MDP3_COMP_H__ + +#include "mtk-mdp3-cmdq.h" + +enum mdp_comp_type { + MDP_COMP_TYPE_INVALID = 0, + + MDP_COMP_TYPE_RDMA, + MDP_COMP_TYPE_RSZ, + MDP_COMP_TYPE_WROT, + MDP_COMP_TYPE_WDMA, + MDP_COMP_TYPE_PATH, + + MDP_COMP_TYPE_TDSHP, + MDP_COMP_TYPE_COLOR, + MDP_COMP_TYPE_DRE, + MDP_COMP_TYPE_CCORR, + MDP_COMP_TYPE_HDR, + + MDP_COMP_TYPE_IMGI, + MDP_COMP_TYPE_WPEI, + MDP_COMP_TYPE_EXTO, /* External path */ + MDP_COMP_TYPE_DL_PATH, /* Direct-link path */ + + MDP_COMP_TYPE_COUNT /* ALWAYS keep at the end */ +}; + +enum mdp_comp_id { + MDP_COMP_NONE = -1, /* Invalid engine */ + + /* ISP */ + MDP_COMP_WPEI = 0, + MDP_COMP_WPEO, /* 1 */ + MDP_COMP_WPEI2, /* 2 */ + MDP_COMP_WPEO2, /* 3 */ + MDP_COMP_ISP_IMGI, /* 4 */ + MDP_COMP_ISP_IMGO, /* 5 */ + MDP_COMP_ISP_IMG2O, /* 6 */ + + /* IPU */ + MDP_COMP_IPUI, /* 7 */ + MDP_COMP_IPUO, /* 8 */ + + /* MDP */ + MDP_COMP_CAMIN, /* 9 */ + MDP_COMP_CAMIN2, /* 10 */ + MDP_COMP_RDMA0, /* 11 */ + MDP_COMP_AAL0, /* 12 */ + MDP_COMP_CCORR0, /* 13 */ + MDP_COMP_RSZ0, /* 14 */ + MDP_COMP_RSZ1, /* 15 */ + MDP_COMP_TDSHP0, /* 16 */ + MDP_COMP_COLOR0, /* 17 */ + MDP_COMP_PATH0_SOUT, /* 18 */ + MDP_COMP_PATH1_SOUT, /* 19 */ + MDP_COMP_WROT0, /* 20 */ + MDP_COMP_WDMA, /* 21 */ + + /* Dummy Engine */ + MDP_COMP_RDMA1, /* 22 */ + MDP_COMP_RSZ2, /* 23 */ + MDP_COMP_TDSHP1, /* 24 */ + MDP_COMP_WROT1, /* 25 */ + + MDP_MAX_COMP_COUNT /* ALWAYS keep at the end */ +}; + +enum mdp_comp_event { + RDMA0_SOF, + RDMA0_DONE, + RSZ0_SOF, + RSZ1_SOF, + TDSHP0_SOF, + WROT0_SOF, + WROT0_DONE, + WDMA0_SOF, + WDMA0_DONE, + + ISP_P2_0_DONE, + ISP_P2_1_DONE, + ISP_P2_2_DONE, + ISP_P2_3_DONE, + ISP_P2_4_DONE, + ISP_P2_5_DONE, + ISP_P2_6_DONE, + ISP_P2_7_DONE, + ISP_P2_8_DONE, + ISP_P2_9_DONE, + ISP_P2_10_DONE, + ISP_P2_11_DONE, + ISP_P2_12_DONE, + ISP_P2_13_DONE, + ISP_P2_14_DONE, + + WPE_DONE, + WPE_B_DONE, + + MDP_MAX_EVENT_COUNT /* ALWAYS keep at the end */ +}; + +struct mdp_comp_ops; + +struct mdp_comp { + struct mdp_dev *mdp_dev; + void __iomem *regs; + phys_addr_t reg_base; + u8 subsys_id; + struct clk *clks[2]; + struct device *larb_dev; + enum mdp_comp_type type; + enum mdp_comp_id id; + u32 alias_id; + const struct mdp_comp_ops *ops; +}; + +struct mdp_comp_ctx { + struct mdp_comp *comp; + const struct img_compparam *param; + const struct img_input *input; + const struct img_output *outputs[IMG_MAX_HW_OUTPUTS]; +}; + +struct mdp_comp_ops { + s64 (*get_comp_flag)(const struct mdp_comp_ctx *ctx); + int (*init_comp)(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd); + int (*config_frame)(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd, + const struct v4l2_rect *compose); + int (*config_subfrm)(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index); + int (*wait_comp_event)(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd); + int (*advance_subfrm)(struct mdp_comp_ctx *ctx, + struct mdp_cmd *cmd, u32 index); + int (*post_process)(struct mdp_comp_ctx *ctx, struct mdp_cmd *cmd); +}; + +struct mdp_dev; + +int mdp_component_init(struct mdp_dev *mdp); +void mdp_component_deinit(struct mdp_dev *mdp); +void mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp); +void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp); +int mdp_comp_ctx_init(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx, + const struct img_compparam *param, + const struct img_ipi_frameparam *frame); + +#endif /* __MTK_MDP3_COMP_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c new file mode 100644 index 000000000000..4a59dec8cfd9 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtk-mdp3-core.h" +#include "mtk-mdp3-debug.h" +#include "mtk-mdp3-m2m.h" + +/* MDP debug log level (0-3). 3 shows all the logs. */ +int mtk_mdp_debug; +EXPORT_SYMBOL(mtk_mdp_debug); +module_param_named(debug, mtk_mdp_debug, int, 0644); + +static const struct of_device_id mdp_of_ids[] = { + { .compatible = "mediatek,mt8183-mdp3", }, + {}, +}; +MODULE_DEVICE_TABLE(of, mdp_of_ids); + +struct platform_device *mdp_get_plat_device(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *mdp_node; + struct platform_device *mdp_pdev; + + mdp_node = of_parse_phandle(dev->of_node, "mediatek,mdp3", 0); + if (!mdp_node) { + dev_err(dev, "can't get mdp node\n"); + return NULL; + } + + mdp_pdev = of_find_device_by_node(mdp_node); + if (WARN_ON(!mdp_pdev)) { + dev_err(dev, "mdp pdev failed\n"); + of_node_put(mdp_node); + return NULL; + } + + return mdp_pdev; +} +EXPORT_SYMBOL_GPL(mdp_get_plat_device); + +int mdp_vpu_get_locked(struct mdp_dev *mdp) +{ + int ret = 0; + + if (mdp->vpu_count++ == 0) { + ret = rproc_boot(mdp->rproc_handle); + if (ret) { + dev_err(&mdp->pdev->dev, + "vpu_load_firmware failed %d\n", ret); + goto err_load_vpu; + } + ret = mdp_vpu_register(mdp); + if (ret) { + dev_err(&mdp->pdev->dev, + "mdp_vpu register failed %d\n", ret); + goto err_reg_vpu; + } + ret = mdp_vpu_dev_init(&mdp->vpu, mdp->scp, &mdp->vpu_lock); + if (ret) { + dev_err(&mdp->pdev->dev, + "mdp_vpu device init failed %d\n", ret); + goto err_init_vpu; + } + } + return 0; + +err_init_vpu: + mdp_vpu_unregister(mdp); +err_reg_vpu: +err_load_vpu: + mdp->vpu_count--; + return ret; +} + +void mdp_vpu_put_locked(struct mdp_dev *mdp) +{ + if (--mdp->vpu_count == 0) { + mdp_vpu_dev_deinit(&mdp->vpu); + mdp_vpu_unregister(mdp); + } +} + +static int mdp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mdp_dev *mdp; + int ret; + + mdp = devm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL); + if (!mdp) + return -ENOMEM; + + mdp->pdev = pdev; + ret = mdp_component_init(mdp); + if (ret) { + dev_err(dev, "Failed to initialize mdp components\n"); + goto err_return; + } + + mdp->job_wq = alloc_workqueue(MDP_MODULE_NAME, WQ_FREEZABLE, 0); + if (!mdp->job_wq) { + dev_err(dev, "Unable to create job workqueue\n"); + ret = -ENOMEM; + goto err_destroy_job_wq; + } + + mdp->clock_wq = alloc_workqueue(MDP_MODULE_NAME "-clock", WQ_FREEZABLE, + 0); + if (!mdp->clock_wq) { + dev_err(dev, "Unable to create clock workqueue\n"); + ret = -ENOMEM; + goto err_destroy_clock_wq; + } + + mdp->scp = scp_get(pdev); + if (!mdp->scp) { + dev_err(&pdev->dev, "Could not get scp device\n"); + ret = -ENODEV; + goto err_destroy_clock_wq; + } + + mdp->rproc_handle = scp_get_rproc(mdp->scp); + dev_info(&pdev->dev, "MDP rproc_handle: %pK", mdp->rproc_handle); + + mutex_init(&mdp->vpu_lock); + mutex_init(&mdp->m2m_lock); + + mdp->cmdq_clt = cmdq_mbox_create(dev, 0, 1200); + if (IS_ERR(mdp->cmdq_clt)) { + ret = PTR_ERR(mdp->cmdq_clt); + goto err_put_scp; + } + + init_waitqueue_head(&mdp->callback_wq); + ida_init(&mdp->mdp_ida); + platform_set_drvdata(pdev, mdp); + +#ifdef MDP_DEBUG + mdp_debug_init(pdev); +#endif + + vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); + pm_runtime_enable(dev); + + ret = v4l2_device_register(dev, &mdp->v4l2_dev); + if (ret) { + dev_err(dev, "Failed to register v4l2 device\n"); + ret = -EINVAL; + goto err_mbox_destroy; + } + + ret = mdp_m2m_device_register(mdp); + if (ret) { + v4l2_err(&mdp->v4l2_dev, "Failed to register m2m device\n"); + goto err_unregister_device; + } + + dev_dbg(dev, "mdp-%d registered successfully\n", pdev->id); + return 0; + +err_unregister_device: + v4l2_device_unregister(&mdp->v4l2_dev); +err_mbox_destroy: + cmdq_mbox_destroy(mdp->cmdq_clt); +err_put_scp: + scp_put(mdp->scp); +err_destroy_clock_wq: + destroy_workqueue(mdp->clock_wq); +err_destroy_job_wq: + destroy_workqueue(mdp->job_wq); +err_return: + dev_dbg(dev, "Errno %d\n", ret); + return ret; +} + +static int mdp_remove(struct platform_device *pdev) +{ + struct mdp_dev *mdp = platform_get_drvdata(pdev); + + mdp_m2m_device_unregister(mdp); + v4l2_device_unregister(&mdp->v4l2_dev); + + scp_put(mdp->scp); + + destroy_workqueue(mdp->job_wq); + destroy_workqueue(mdp->clock_wq); + + pm_runtime_disable(&pdev->dev); + + vb2_dma_contig_clear_max_seg_size(&pdev->dev); + mdp_component_deinit(mdp); + +#ifdef MDP_DEBUG + mdp_debug_deinit(); +#endif + + mdp_vpu_shared_mem_free(&mdp->vpu); + + dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name); + return 0; +} + +static int __maybe_unused mdp_pm_suspend(struct device *dev) +{ + struct mdp_dev *mdp = dev_get_drvdata(dev); + int ret; + + atomic_set(&mdp->suspended, 1); + + if (atomic_read(&mdp->job_count)) { + ret = wait_event_timeout(mdp->callback_wq, + !atomic_read(&mdp->job_count), + HZ); + if (ret == 0) + dev_err(dev, + "%s:flushed cmdq task incomplete\n", + __func__); + else//need to remove + pr_err("%s:ret=%d\n", __func__, ret); + } + + return 0; +} + +static int __maybe_unused mdp_pm_resume(struct device *dev) +{ + struct mdp_dev *mdp = dev_get_drvdata(dev); + + atomic_set(&mdp->suspended, 0); + + return 0; +} + +static int __maybe_unused mdp_suspend(struct device *dev) +{ + if (pm_runtime_suspended(dev)) + return 0; + + return mdp_pm_suspend(dev); +} + +static int __maybe_unused mdp_resume(struct device *dev) +{ + if (pm_runtime_suspended(dev)) + return 0; + + return mdp_pm_resume(dev); +} + +static const struct dev_pm_ops mdp_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mdp_suspend, mdp_resume) + SET_RUNTIME_PM_OPS(mdp_pm_suspend, mdp_pm_resume, NULL) +}; + +static struct platform_driver mdp_driver = { + .probe = mdp_probe, + .remove = mdp_remove, + .driver = { + .name = MDP_MODULE_NAME, + .pm = &mdp_pm_ops, + .of_match_table = of_match_ptr(mdp_of_ids), + }, +}; + +module_platform_driver(mdp_driver); + +MODULE_AUTHOR("Ping-Hsun Wu "); +MODULE_DESCRIPTION("Mediatek image processor 3 driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h new file mode 100644 index 000000000000..98cf54b1d92b --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MTK_MDP3_CORE_H__ +#define __MTK_MDP3_CORE_H__ + +#include +#include +#include "mtk-mdp3-comp.h" +#include "mtk-mdp3-vpu.h" + +#define MDP_MODULE_NAME "mtk-mdp3" + +enum mdp_buffer_usage { + MDP_BUFFER_USAGE_HW_READ, + MDP_BUFFER_USAGE_MDP, + MDP_BUFFER_USAGE_MDP2, + MDP_BUFFER_USAGE_ISP, + MDP_BUFFER_USAGE_WPE, +}; + +struct mdp_dev { + struct platform_device *pdev; + struct mdp_comp mmsys; + struct mdp_comp mm_mutex; + struct mdp_comp *comp[MDP_MAX_COMP_COUNT]; + s32 event[MDP_MAX_EVENT_COUNT]; + + struct workqueue_struct *job_wq; + struct workqueue_struct *clock_wq; + struct mdp_vpu_dev vpu; + struct mtk_scp *scp; + struct rproc *rproc_handle; + /* synchronization protect for accessing vpu working buffer info */ + struct mutex vpu_lock; + s32 vpu_count; + u32 id_count; + struct ida mdp_ida; + struct cmdq_client *cmdq_clt; + wait_queue_head_t callback_wq; + + struct v4l2_device v4l2_dev; + struct video_device *m2m_vdev; + struct v4l2_m2m_dev *m2m_dev; + /* synchronization protect for m2m device operation */ + struct mutex m2m_lock; + atomic_t suspended; + atomic_t job_count; +}; + +int mdp_vpu_get_locked(struct mdp_dev *mdp); +void mdp_vpu_put_locked(struct mdp_dev *mdp); +int mdp_vpu_register(struct mdp_dev *mdp); +void mdp_vpu_unregister(struct mdp_dev *mdp); + +extern int mtk_mdp_debug; + +#define DEBUG +#if defined(DEBUG) + +#define mdp_dbg(level, fmt, ...)\ + do {\ + if (mtk_mdp_debug >= (level))\ + pr_info("[MTK-MDP3] %d %s:%d: " fmt "\n",\ + level, __func__, __LINE__, ##__VA_ARGS__);\ + } while (0) + +#define mdp_err(fmt, ...)\ + pr_err("[MTK-MDP3][ERR] %s:%d: " fmt "\n", __func__, __LINE__,\ + ##__VA_ARGS__) + +#else + +#define mdp_dbg(level, fmt, ...) do {} while (0) +#define mdp_err(fmt, ...) do {} while (0) + +#endif + +#define mdp_dbg_enter() mdp_dbg(3, "+") +#define mdp_dbg_leave() mdp_dbg(3, "-") + +#endif /* __MTK_MDP3_CORE_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.c new file mode 100644 index 000000000000..98f3f77bd591 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.c @@ -0,0 +1,973 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Daoyuan Huang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include "mmsys_reg_base.h" +#include "mtk-mdp3-core.h" +#include "mtk-mdp3-debug.h" +#include "mtk-mdp3-regs.h" + +struct mdp_module_base_va { + void __iomem *MDP_RDMA0; + void __iomem *MDP_RSZ0; + void __iomem *MDP_RSZ1; + void __iomem *MDP_TDSHP; + void __iomem *MDP_COLOR; + void __iomem *MDP_AAL; + void __iomem *MDP_CCORR; + void __iomem *MDP_WROT0; + void __iomem *MDP_WDMA; + void __iomem *SMI_LARB0; +}; + +struct RegDef { + int offset; + const char *name; +}; + +struct mdp_debug_context { + struct platform_device *mdp_device; + struct mdp_func_struct mdp_func_pointer; + struct mdp_module_base_va mdp_mod_base_va; + void __iomem *mdp_mmsys_base_va; +}; + +static struct mdp_debug_context g_mdp_debug; + +#define MMSYS_CONFIG_BASE g_mdp_debug.mdp_mmsys_base_va +#define MDP_RDMA0_BASE g_mdp_debug.mdp_mod_base_va.MDP_RDMA0 +#define MDP_RSZ0_BASE g_mdp_debug.mdp_mod_base_va.MDP_RSZ0 +#define MDP_RSZ1_BASE g_mdp_debug.mdp_mod_base_va.MDP_RSZ1 +#define MDP_TDSHP_BASE g_mdp_debug.mdp_mod_base_va.MDP_TDSHP +#define MDP_COLOR_BASE g_mdp_debug.mdp_mod_base_va.MDP_COLOR +#define MDP_AAL_BASE g_mdp_debug.mdp_mod_base_va.MDP_AAL +#define MDP_CCORR_BASE g_mdp_debug.mdp_mod_base_va.MDP_CCORR +#define MDP_WROT0_BASE g_mdp_debug.mdp_mod_base_va.MDP_WROT0 +#define MDP_WDMA_BASE g_mdp_debug.mdp_mod_base_va.MDP_WDMA + +#define MDP_REG_GET32(addr) (readl((void *)addr) & 0xffffffff) +#define MDP_REG_SET32(addr, val) writel(val, addr) + +static const char *mdp_get_rsz_state(const uint32_t state); + +struct mdp_func_struct *mdp_get_func(void) +{ + return &g_mdp_debug.mdp_func_pointer; +} + +static void __iomem *mdp_alloc_reference_VA_by_name(const char *ref_name) +{ + struct device_node *node; + struct device *dev = &(g_mdp_debug.mdp_device->dev); + void __iomem *VA; + + node = of_parse_phandle(dev->of_node, ref_name, 0); + if (!node) { + mdp_err("DEV: cannot parse node name:%s\n", ref_name); + return 0; + } + + VA = of_iomap(node, 0); + of_node_put(node); + mdp_dbg(2, "DEV: VA ref(%s): 0x%p\n", ref_name, VA); + + return VA; +} + +static void mdp_free_module_base_VA(void __iomem *VA) +{ + iounmap(VA); +} + +static void mdp_init_module_base_VA(void) +{ + struct mdp_module_base_va *mod_base_va = &(g_mdp_debug.mdp_mod_base_va); + struct device_node *rdma_node = g_mdp_debug.mdp_device->dev.of_node; + void __iomem *va; + + if (rdma_node) { + va = of_iomap(rdma_node, 0); + of_node_put(rdma_node); + mod_base_va->MDP_RDMA0 = va; + mdp_dbg(2, "MDP_RDMA va: 0x%p\n", va); + } else + mdp_err("%s:MDP_RDMA node missing!\n", __func__); + + mod_base_va->MDP_RSZ0 = mdp_alloc_reference_VA_by_name("mdp_rsz0"); + mod_base_va->MDP_RSZ1 = mdp_alloc_reference_VA_by_name("mdp_rsz1"); + mod_base_va->MDP_WROT0 = mdp_alloc_reference_VA_by_name("mdp_wrot0"); + mod_base_va->MDP_WDMA = mdp_alloc_reference_VA_by_name("mdp_wdma0"); + mod_base_va->MDP_TDSHP = mdp_alloc_reference_VA_by_name("mdp_tdshp0"); + mod_base_va->MDP_COLOR = mdp_alloc_reference_VA_by_name("mdp_color0"); + mod_base_va->MDP_AAL = mdp_alloc_reference_VA_by_name("mdp_aal0"); + mod_base_va->MDP_CCORR = mdp_alloc_reference_VA_by_name("mdp_ccorr0"); + mod_base_va->SMI_LARB0 = + mdp_alloc_reference_VA_by_name("mediatek,larb"); +} + +static void mdp_deinit_module_base_VA(void) +{ + struct mdp_module_base_va *mod_base_va = &(g_mdp_debug.mdp_mod_base_va); + + mdp_free_module_base_VA(mod_base_va->MDP_RDMA0); + mdp_free_module_base_VA(mod_base_va->MDP_RSZ0); + mdp_free_module_base_VA(mod_base_va->MDP_RSZ1); + mdp_free_module_base_VA(mod_base_va->MDP_WROT0); + mdp_free_module_base_VA(mod_base_va->MDP_WDMA); + mdp_free_module_base_VA(mod_base_va->MDP_TDSHP); + mdp_free_module_base_VA(mod_base_va->MDP_COLOR); + mdp_free_module_base_VA(mod_base_va->MDP_AAL); + mdp_free_module_base_VA(mod_base_va->MDP_CCORR); + mdp_free_module_base_VA(mod_base_va->SMI_LARB0); + memset(mod_base_va, 0, sizeof(struct mdp_module_base_va)); +} + +static void mdp_map_mmsys_VA(void) +{ + g_mdp_debug.mdp_mmsys_base_va = + mdp_alloc_reference_VA_by_name("mediatek,mmsys"); +} + +static void mdp_unmap_mmsys_VA(void) +{ + mdp_free_module_base_VA(g_mdp_debug.mdp_mmsys_base_va); +} + +static uint32_t mdp_rdma_get_reg_offset_src_addr_virtual(void) +{ + return 0; +} + +static uint32_t mdp_wrot_get_reg_offset_dst_addr_virtual(void) +{ + return 0; +} + +static uint32_t mdp_wdma_get_reg_offset_dst_addr_virtual(void) +{ + return 0; +} + +/* MDP engine dump */ +static void mdp_dump_rsz_common(void __iomem *base, const char *label) +{ + uint32_t value[8]; + uint32_t request[8]; + uint32_t state; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x004); + value[1] = MDP_REG_GET32(base + 0x00C); + value[2] = MDP_REG_GET32(base + 0x010); + value[3] = MDP_REG_GET32(base + 0x014); + value[4] = MDP_REG_GET32(base + 0x018); + MDP_REG_SET32(base + 0x040, 0x00000001); + value[5] = MDP_REG_GET32(base + 0x044); + MDP_REG_SET32(base + 0x040, 0x00000002); + value[6] = MDP_REG_GET32(base + 0x044); + MDP_REG_SET32(base + 0x040, 0x00000003); + value[7] = MDP_REG_GET32(base + 0x044); + + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("RSZ_CONTROL: 0x%08x, RSZ_INPUT_IMAGE: 0x%08x\n", + value[0], value[1]); + mdp_err("RSZ_OUTPUT_IMAGE: 0x%08x RSZ_VERTICAL_COEFF_STEP: 0x%08x\n", + value[2], value[3]); + mdp_err("RSZ_HORIZONTAL_COEFF_STEP: 0x%08x, RSZ_DEBUG_1: 0x%08x\n", + value[4], value[5]); + mdp_err(", RSZ_DEBUG_2: 0x%08x, RSZ_DEBUG_3: 0x%08x\n", + value[6], value[7]); + + /* parse state */ + /* .valid=1/request=1: upstream module sends data */ + /* .ready=1: downstream module receives data */ + state = value[6] & 0xF; + request[0] = state & (0x1); /* out valid */ + request[1] = (state & (0x1 << 1)) >> 1; /* out ready */ + request[2] = (state & (0x1 << 2)) >> 2; /* in valid */ + request[3] = (state & (0x1 << 3)) >> 3; /* in ready */ + request[4] = (value[1] & 0x1FFF); /* input_width */ + request[5] = (value[1] >> 16) & 0x1FFF; /* input_height */ + request[6] = (value[2] & 0x1FFF); /* output_width */ + request[7] = (value[2] >> 16) & 0x1FFF; /* output_height */ + + mdp_err("RSZ inRdy,inRsq,outRdy,outRsq: %d,%d,%d,%d (%s)\n", + request[3], request[2], request[1], request[0], + mdp_get_rsz_state(state)); + mdp_err("RSZ input_width,input_height,output_width,output_height:"); + mdp_err("%d,%d,%d,%d\n", + request[4], request[5], request[6], request[7]); +} + +static void mdp_dump_tdshp_common(void __iomem *base, const char *label) +{ + uint32_t value[8]; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x114); + value[1] = MDP_REG_GET32(base + 0x11C); + value[2] = MDP_REG_GET32(base + 0x104); + value[3] = MDP_REG_GET32(base + 0x108); + value[4] = MDP_REG_GET32(base + 0x10C); + value[5] = MDP_REG_GET32(base + 0x120); + value[6] = MDP_REG_GET32(base + 0x128); + value[7] = MDP_REG_GET32(base + 0x110); + + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("TDSHP INPUT_CNT: 0x%08x, OUTPUT_CNT: 0x%08x\n", + value[0], value[1]); + mdp_err("TDSHP INTEN: 0x%08x, INTSTA: 0x%08x, 0x10C: 0x%08x\n", + value[2], value[3], value[4]); + mdp_err("TDSHP CFG: 0x%08x, IN_SIZE: 0x%08x, OUT_SIZE: 0x%08x\n", + value[7], value[5], value[6]); +} + +static void mdp_virtual_function_setting(void) +{ + struct mdp_func_struct *pfunc = mdp_get_func(); + + pfunc->mdp_dump_rsz = mdp_dump_rsz_common; + pfunc->mdp_dump_tdshp = mdp_dump_tdshp_common; + pfunc->mdp_rdma_get_src_base_addr = + mdp_rdma_get_reg_offset_src_addr_virtual; + pfunc->mdp_wrot_get_reg_offset_dst_addr = + mdp_wrot_get_reg_offset_dst_addr_virtual; + pfunc->mdp_wdma_get_reg_offset_dst_addr = + mdp_wdma_get_reg_offset_dst_addr_virtual; +} + +static void mdp_dump_mmsys_config(void) +{ + int i; + uint32_t value; + static const struct RegDef configRegisters[] = { + {0xF80, "ISP_MOUT_EN"}, + {0xF84, "MDP_RDMA0_MOUT_EN"}, + {0xF8C, "MDP_PRZ0_MOUT_EN"}, + {0xF90, "MDP_PRZ1_MOUT_EN"}, + {0xF94, "MDP_COLOR_MOUT_EN"}, + {0xF98, "IPU_MOUT_EN"}, + {0xFE8, "MDP_AAL_MOUT_EN"}, + /* {0x02C, "MDP_TDSHP_MOUT_EN"}, */ + {0xF00, "DISP_OVL0_MOUT_EN"}, + {0xF04, "DISP_OVL0_2L_MOUT_EN"}, + {0xF08, "DISP_OVL1_2L_MOUT_EN"}, + {0xF0C, "DISP_DITHER0_MOUT_EN"}, + {0xF10, "DISP_RSZ_MOUT_EN"}, + /* {0x040, "DISP_UFOE_MOUT_EN"}, */ + /* {0x040, "MMSYS_MOUT_RST"}, */ + {0xFA0, "DISP_TO_WROT_SOUT_SEL"}, + {0xFA4, "MDP_COLOR_IN_SOUT_SEL"}, + {0xFA8, "MDP_PATH0_SOUT_SEL"}, + {0xFAC, "MDP_PATH1_SOUT_SEL"}, + {0xFB0, "MDP_TDSHP_SOUT_SEL"}, + {0xFC0, "MDP_PRZ0_SEL_IN"}, + {0xFC4, "MDP_PRZ1_SEL_IN"}, + {0xFC8, "MDP_TDSHP_SEL_IN"}, + {0xFCC, "DISP_WDMA0_SEL_IN"}, + {0xFDC, "MDP_COLOR_SEL_IN"}, + {0xF20, "DISP_COLOR_OUT_SEL_IN"}, + {0xFD0, "MDP_WROT0_SEL_IN"}, + {0xFD4, "MDP_WDMA_SEL_IN"}, + {0xFD8, "MDP_COLOR_OUT_SEL_IN"}, + {0xFDC, "MDP_COLOR_SEL_IN "}, + /* {0xFDC, "DISP_COLOR_SEL_IN"}, */ + {0xFE0, "MDP_PATH0_SEL_IN"}, + {0xFE4, "MDP_PATH1_SEL_IN"}, + {0xFEC, "MDP_AAL_SEL_IN"}, + {0xFF0, "MDP_CCORR_SEL_IN"}, + {0xFF4, "MDP_CCORR_SOUT_SEL"}, + /* {0x070, "DISP_WDMA1_SEL_IN"}, */ + /* {0x074, "DISP_UFOE_SEL_IN"}, */ + {0xF2C, "DSI0_SEL_IN"}, + {0xF30, "DSI1_SEL_IN"}, + {0xF50, "DISP_RDMA0_SOUT_SEL_IN"}, + {0xF54, "DISP_RDMA1_SOUT_SEL_IN"}, + {0x0F0, "MMSYS_MISC"}, + /* ACK and REQ related */ + {0x8B4, "DISP_DL_VALID_0"}, + {0x8B8, "DISP_DL_VALID_1"}, + {0x8C0, "DISP_DL_READY_0"}, + {0x8C4, "DISP_DL_READY_1"}, + {0x8CC, "MDP_DL_VALID_0"}, + {0x8D0, "MDP_DL_VALID_1"}, + {0x8D4, "MDP_DL_READY_0"}, + {0x8D8, "MDP_DL_READY_1"}, + {0x8E8, "MDP_MOUT_MASK"}, + {0x948, "MDP_DL_VALID_2"}, + {0x94C, "MDP_DL_READY_2"}, + {0x950, "DISP_DL_VALID_2"}, + {0x954, "DISP_DL_READY_2"}, + {0x100, "MMSYS_CG_CON0"}, + {0x110, "MMSYS_CG_CON1"}, + /* Async DL related */ + {0x960, "TOP_RELAY_FSM_RD"}, + {0x934, "MDP_ASYNC_CFG_WD"}, + {0x938, "MDP_ASYNC_CFG_RD"}, + {0x958, "MDP_ASYNC_CFG_OUT_RD"}, + {0x95C, "MDP_ASYNC_IPU_CFG_OUT_RD"}, + {0x994, "ISP_RELAY_CFG_WD"}, + {0x998, "ISP_RELAY_CNT_RD"}, + {0x99C, "ISP_RELAY_CNT_LATCH_RD"}, + {0x9A0, "IPU_RELAY_CFG_WD"}, + {0x9A4, "IPU_RELAY_CNT_RD"}, + {0x9A8, "IPU_RELAY_CNT_LATCH_RD"} + }; + + if (!MMSYS_CONFIG_BASE) { + mdp_err("%s:MMSYS_CONFIG_BASE=0!\n", __func__); + return; + } + + for (i = 0; i < ARRAY_SIZE(configRegisters); i++) { + value = MDP_REG_GET32(MMSYS_CONFIG_BASE + + configRegisters[i].offset); + mdp_err("%s: 0x%08x\n", configRegisters[i].name, value); + } +} + +static const char *mdp_get_rdma_state(uint32_t state) +{ + switch (state) { + case 0x1: + return "idle"; + case 0x2: + return "wait sof"; + case 0x4: + return "reg update"; + case 0x8: + return "clear0"; + case 0x10: + return "clear1"; + case 0x20: + return "int0"; + case 0x40: + return "int1"; + case 0x80: + return "data running"; + case 0x100: + return "wait done"; + case 0x200: + return "warm reset"; + case 0x400: + return "wait reset"; + default: + return ""; + } +} + +static const char *mdp_get_rsz_state(const uint32_t state) +{ + switch (state) { + case 0x5: + return "downstream hang"; /* 0,1,0,1 */ + case 0xa: + return "upstream hang"; /* 1,0,1,0 */ + default: + return ""; + } +} + +static const char *mdp_get_wdma_state(uint32_t state) +{ + switch (state) { + case 0x1: + return "idle"; + case 0x2: + return "clear"; + case 0x4: + return "prepare"; + case 0x8: + return "prepare"; + case 0x10: + return "data running"; + case 0x20: + return "eof wait"; + case 0x40: + return "soft reset wait"; + case 0x80: + return "eof done"; + case 0x100: + return "sof reset done"; + case 0x200: + return "frame complete"; + default: + return ""; + } +} + +static void mdp_dump_rdma_common(void __iomem *base, const char *label) +{ + uint32_t value[17]; + uint32_t state; + uint32_t grep; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x030); + value[1] = MDP_REG_GET32(base + + mdp_get_func()->mdp_rdma_get_src_base_addr()); + value[2] = MDP_REG_GET32(base + 0x060); + value[3] = MDP_REG_GET32(base + 0x070); + value[4] = MDP_REG_GET32(base + 0x078); + value[5] = MDP_REG_GET32(base + 0x080); + value[6] = MDP_REG_GET32(base + 0x100); + value[7] = MDP_REG_GET32(base + 0x118); + value[8] = MDP_REG_GET32(base + 0x130); + value[9] = MDP_REG_GET32(base + 0x400); + value[10] = MDP_REG_GET32(base + 0x408); + value[11] = MDP_REG_GET32(base + 0x410); + value[12] = MDP_REG_GET32(base + 0x420); + value[13] = MDP_REG_GET32(base + 0x430); + value[14] = MDP_REG_GET32(base + 0x440); + value[15] = MDP_REG_GET32(base + 0x4D0); + value[16] = MDP_REG_GET32(base + 0x0); + + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err + ("RDMA_SRC_CON: 0x%08x, RDMA_SRC_BASE_0: 0x%08x\n", + value[0], value[1]); + mdp_err + ("RDMA_MF_BKGD_SIZE_IN_BYTE: 0x%08x RDMA_MF_SRC_SIZE: 0x%08x\n", + value[2], value[3]); + mdp_err("RDMA_MF_CLIP_SIZE: 0x%08x, RDMA_MF_OFFSET_1: 0x%08x\n", + value[4], value[5]); + mdp_err("RDMA_SRC_END_0: 0x%08x, RDMA_SRC_OFFSET_0: 0x%08x\n", + value[6], value[7]); + mdp_err("RDMA_SRC_OFFSET_W_0: 0x%08x, RDMA_MON_STA_0: 0x%08x\n", + value[8], value[9]); + mdp_err("RDMA_MON_STA_1: 0x%08x, RDMA_MON_STA_2: 0x%08x\n", + value[10], value[11]); + mdp_err("RDMA_MON_STA_4: 0x%08x, RDMA_MON_STA_6: 0x%08x\n", + value[12], value[13]); + mdp_err("RDMA_MON_STA_8: 0x%08x, RDMA_MON_STA_26: 0x%08x\n", + value[14], value[15]); + mdp_err("RDMA_EN: 0x%08x\n", + value[16]); + + /* parse state */ + mdp_err("RDMA ack:%d req:%d\n", (value[9] & (1 << 11)) >> 11, + (value[9] & (1 << 10)) >> 10); + state = (value[10] >> 8) & 0x7FF; + grep = (value[10] >> 20) & 0x1; + mdp_err("RDMA state: 0x%x (%s)\n", state, mdp_get_rdma_state(state)); + mdp_err("RDMA horz_cnt: %d vert_cnt:%d\n", + value[15] & 0xFFF, (value[15] >> 16) & 0xFFF); + + mdp_err("RDMA grep:%d => suggest to ask SMI help:%d\n", grep, grep); +} + +static void mdp_dump_rot_common(void __iomem *base, const char *label) +{ + uint32_t value[47]; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x000); + value[1] = MDP_REG_GET32(base + 0x008); + value[2] = MDP_REG_GET32(base + 0x00C); + value[3] = MDP_REG_GET32(base + 0x024); + value[4] = MDP_REG_GET32(base + + mdp_get_func()->mdp_wrot_get_reg_offset_dst_addr()); + value[5] = MDP_REG_GET32(base + 0x02C); + value[6] = MDP_REG_GET32(base + 0x004); + value[7] = MDP_REG_GET32(base + 0x030); + value[8] = MDP_REG_GET32(base + 0x078); + value[9] = MDP_REG_GET32(base + 0x070); + MDP_REG_SET32(base + 0x018, 0x00000100); + value[10] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000200); + value[11] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000300); + value[12] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000400); + value[13] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000500); + value[14] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000600); + value[15] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000700); + value[16] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000800); + value[17] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000900); + value[18] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000A00); + value[19] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000B00); + value[20] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000C00); + value[21] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000D00); + value[22] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000E00); + value[23] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00000F00); + value[24] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001000); + value[25] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001100); + value[26] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001200); + value[27] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001300); + value[28] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001400); + value[29] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001500); + value[30] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001600); + value[31] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001700); + value[32] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001800); + value[33] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001900); + value[34] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001A00); + value[35] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001B00); + value[36] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001C00); + value[37] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001D00); + value[38] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001E00); + value[39] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00001F00); + value[40] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00002000); + value[41] = MDP_REG_GET32(base + 0x0D0); + MDP_REG_SET32(base + 0x018, 0x00002100); + value[42] = MDP_REG_GET32(base + 0x0D0); + value[43] = MDP_REG_GET32(base + 0x01C); + value[44] = MDP_REG_GET32(base + 0x07C); + value[45] = MDP_REG_GET32(base + 0x010); + value[46] = MDP_REG_GET32(base + 0x014); + + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("ROT_CTRL: 0x%08x, ROT_MAIN_BUF_SIZE: 0x%08x\n", + value[0], value[1]); + mdp_err("ROT_SUB_BUF_SIZE: 0x%08x, ROT_TAR_SIZE: 0x%08x\n", + value[2], value[3]); + mdp_err("ROT_BASE_ADDR: 0x%08x, ROT_OFST_ADDR: 0x%08x\n", + value[4], value[5]); + mdp_err("ROT_DMA_PERF: 0x%08x, ROT_STRIDE: 0x%08x\n", + value[6], value[7]); + mdp_err("ROT_IN_SIZE: 0x%08x, ROT_EOL: 0x%08x\n", + value[8], value[9]); + mdp_err("ROT_DBUGG_1: 0x%08x, ROT_DEBUBG_2: 0x%08x\n", + value[10], value[11]); + mdp_err("ROT_DBUGG_3: 0x%08x, ROT_DBUGG_4: 0x%08x\n", + value[12], value[13]); + mdp_err("ROT_DEBUBG_5: 0x%08x, ROT_DBUGG_6: 0x%08x\n", + value[14], value[15]); + mdp_err("ROT_DBUGG_7: 0x%08x, ROT_DEBUBG_8: 0x%08x\n", + value[16], value[17]); + mdp_err("ROT_DBUGG_9: 0x%08x, ROT_DBUGG_A: 0x%08x\n", + value[18], value[19]); + mdp_err("ROT_DEBUBG_B: 0x%08x, ROT_DBUGG_C: 0x%08x\n", + value[20], value[21]); + mdp_err("ROT_DBUGG_D: 0x%08x, ROT_DEBUBG_E: 0x%08x\n", + value[22], value[23]); + mdp_err("ROT_DBUGG_F: 0x%08x, ROT_DBUGG_10: 0x%08x\n", + value[24], value[25]); + mdp_err("ROT_DEBUBG_11: 0x%08x, ROT_DEBUG_12: 0x%08x\n", + value[26], value[27]); + mdp_err("ROT_DBUGG_13: 0x%08x, ROT_DBUGG_14: 0x%08x\n", + value[28], value[29]); + mdp_err("ROT_DEBUG_15: 0x%08x, ROT_DBUGG_16: 0x%08x\n", + value[30], value[31]); + mdp_err("ROT_DBUGG_17: 0x%08x, ROT_DEBUG_18: 0x%08x\n", + value[32], value[33]); + mdp_err("ROT_DBUGG_19: 0x%08x, ROT_DBUGG_1A: 0x%08x\n", + value[34], value[35]); + mdp_err("ROT_DEBUG_1B: 0x%08x, ROT_DBUGG_1C: 0x%08x\n", + value[36], value[37]); + mdp_err("ROT_DBUGG_1D: 0x%08x, ROT_DEBUG_1E: 0x%08x\n", + value[38], value[39]); + mdp_err("ROT_DBUGG_1F: 0x%08x, ROT_DBUGG_20: 0x%08x\n", + value[40], value[41]); + mdp_err("ROT_DEBUG_21: 0x%08x\n", + value[42]); + mdp_err("VIDO_INT: 0x%08x, VIDO_ROT_EN: 0x%08x\n", + value[43], value[44]); + mdp_err("VIDO_SOFT_RST: 0x%08x, VIDO_SOFT_RST_STAT: 0x%08x\n", + value[45], value[46]); +} + +static void mdp_dump_color_common(void __iomem *base, const char *label) +{ + uint32_t value[13]; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x400); + value[1] = MDP_REG_GET32(base + 0x404); + value[2] = MDP_REG_GET32(base + 0x408); + value[3] = MDP_REG_GET32(base + 0x40C); + value[4] = MDP_REG_GET32(base + 0x410); + value[5] = MDP_REG_GET32(base + 0x420); + value[6] = MDP_REG_GET32(base + 0xC00); + value[7] = MDP_REG_GET32(base + 0xC04); + value[8] = MDP_REG_GET32(base + 0xC08); + value[9] = MDP_REG_GET32(base + 0xC0C); + value[10] = MDP_REG_GET32(base + 0xC10); + value[11] = MDP_REG_GET32(base + 0xC50); + value[12] = MDP_REG_GET32(base + 0xC54); + + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("COLOR CFG_MAIN: 0x%08x\n", value[0]); + mdp_err("COLOR PXL_CNT_MAIN: 0x%08x, LINE_CNT_MAIN: 0x%08x\n", + value[1], value[2]); + mdp_err("COLOR WIN_X_MAIN: 0x%08x, WIN_Y_MAIN: 0x%08x\n", + value[3], value[4]); + mdp_err("DBG_CFG_MAIN: 0x%08x, COLOR START: 0x%08x\n", + value[5], value[6]); + mdp_err("INTEN: 0x%08x, INTSTA: 0x%08x\n", + value[7], value[8]); + mdp_err("COLOR OUT_SEL: 0x%08x, FRAME_DONE_DEL: 0x%08x\n", + value[9], value[10]); + mdp_err + ("COLOR INTERNAL_IP_WIDTH: 0x%08x, INTERNAL_IP_HEIGHT: 0x%08x\n", + value[11], value[12]); +} + +static void mdp_dump_wdma_common(void __iomem *base, const char *label) +{ + uint32_t value[56]; + uint32_t state; + /* grep bit = 1, WDMA has sent request to SMI, + *and not receive done yet + */ + uint32_t grep; + uint32_t isFIFOFull; /* 1 for WDMA FIFO full */ + int i; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x014); + value[1] = MDP_REG_GET32(base + 0x018); + value[2] = MDP_REG_GET32(base + 0x028); + value[3] = MDP_REG_GET32(base + + mdp_get_func()->mdp_wdma_get_reg_offset_dst_addr()); + value[4] = MDP_REG_GET32(base + 0x078); + value[5] = MDP_REG_GET32(base + 0x080); + value[6] = MDP_REG_GET32(base + 0x0A0); + value[7] = MDP_REG_GET32(base + 0x0A8); + + for (i = 0; i < 16; i++) { + MDP_REG_SET32(base + 0x014, (0x10000000 * i) | + (value[0] & (0x0FFFFFFF))); + value[8 + (3 * i)] = MDP_REG_GET32(base + 0x014); + value[9 + (3 * i)] = MDP_REG_GET32(base + 0x0AC); + value[10 + (3 * i)] = MDP_REG_GET32(base + 0x0B8); + } + + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("[MDP]WDMA_CFG: 0x%08x, WDMA_SRC_SIZE: 0x%08x\n", + value[0], value[1]); + mdp_err("WDMA_DST_W_IN_BYTE = 0x%08x, [MDP]WDMA_DST_ADDR0: 0x%08x\n", + value[2], value[3]); + mdp_err + ("WDMA_DST_UV_PITCH: 0x%08x, WDMA_DST_ADDR_OFFSET0 = 0x%08x\n", + value[4], value[5]); + mdp_err("[MDP]WDMA_STATUS: 0x%08x, WDMA_INPUT_CNT: 0x%08x\n", + value[6], value[7]); + + /* Dump Addtional WDMA debug info */ + for (i = 0; i < 16; i++) { + mdp_err("WDMA_DEBUG_%x 014:0x%08x, 0ac:0x%08x, 0b8:0x%08x\n", + i, value[8 + (3 * i)], value[9 + (3 * i)], + value[10 + (3 * i)]); + } + + /* parse WDMA state */ + state = value[6] & 0x3FF; + grep = (value[6] >> 13) & 0x1; + isFIFOFull = (value[6] >> 12) & 0x1; + + mdp_err("WDMA state:0x%x (%s)\n", state, mdp_get_wdma_state(state)); + mdp_err("WDMA in_req:%d in_ack:%d\n", (value[6] >> 15) & 0x1, + (value[6] >> 14) & 0x1); + + /* note WDMA send request(i.e command) to SMI first, + * then SMI takes request data from WDMA FIFO + */ + /* if SMI dose not process request and upstream HWs */ + /* such as MDP_RSZ send data to WDMA, WDMA FIFO will full finally */ + mdp_err("WDMA grep:%d, FIFO full:%d\n", grep, isFIFOFull); + mdp_err("WDMA suggest: Need SMI help:%d, Need check WDMA config:%d\n", + (grep), ((grep == 0) && (isFIFOFull == 1))); +} + +static void mdp_dump_rsz(void __iomem *base, const char *label) +{ + uint32_t value[11]; + uint32_t request[4]; + uint32_t state; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x004); + value[1] = MDP_REG_GET32(base + 0x008); + value[2] = MDP_REG_GET32(base + 0x010); + value[3] = MDP_REG_GET32(base + 0x014); + value[4] = MDP_REG_GET32(base + 0x018); + value[5] = MDP_REG_GET32(base + 0x01C); + MDP_REG_SET32(base + 0x044, 0x00000001); + value[6] = MDP_REG_GET32(base + 0x048); + MDP_REG_SET32(base + 0x044, 0x00000002); + value[7] = MDP_REG_GET32(base + 0x048); + MDP_REG_SET32(base + 0x044, 0x00000003); + value[8] = MDP_REG_GET32(base + 0x048); + value[9] = MDP_REG_GET32(base + 0x100); + value[10] = MDP_REG_GET32(base + 0x200); + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("RSZ_CONTROL_1: 0x%08x, RSZ_CONTROL_2: 0x%08x\n", + value[0], value[1]); + mdp_err("RSZ_INPUT_IMAGE: 0x%08x, RSZ_OUTPUT_IMAGE: 0x%08x\n", + value[2], value[3]); + mdp_err("RSZ_HORIZONTAL_COEFF_STEP: 0x%08x\n", value[4]); + mdp_err("RSZ_VERTICAL_COEFF_STEP: 0x%08x\n", value[5]); + mdp_err + ("RSZ_DEBUG_1: 0x%08x, RSZ_DEBUG_2: 0x%08x, RSZ_DEBUG_3: 0x%08x\n", + value[6], value[7], value[8]); + mdp_err("PAT1_GEN_SET: 0x%08x, PAT2_GEN_SET: 0x%08x\n", + value[9], value[10]); + /* parse state */ + /* .valid=1/request=1: upstream module sends data */ + /* .ready=1: downstream module receives data */ + state = value[7] & 0xF; + request[0] = state & (0x1); /* out valid */ + request[1] = (state & (0x1 << 1)) >> 1; /* out ready */ + request[2] = (state & (0x1 << 2)) >> 2; /* in valid */ + request[3] = (state & (0x1 << 3)) >> 3; /* in ready */ + mdp_err("RSZ inRdy,inRsq,outRdy,outRsq: %d,%d,%d,%d (%s)\n", + request[3], request[2], request[1], request[0], + mdp_get_rsz_state(state)); +} + +static void mdp_dump_tdshp(void __iomem *base, const char *label) +{ + uint32_t value[10]; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x114); + value[1] = MDP_REG_GET32(base + 0x11C); + value[2] = MDP_REG_GET32(base + 0x104); + value[3] = MDP_REG_GET32(base + 0x108); + value[4] = MDP_REG_GET32(base + 0x10C); + value[5] = MDP_REG_GET32(base + 0x110); + value[6] = MDP_REG_GET32(base + 0x120); + value[7] = MDP_REG_GET32(base + 0x124); + value[8] = MDP_REG_GET32(base + 0x128); + value[9] = MDP_REG_GET32(base + 0x12C); + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("TDSHP INPUT_CNT: 0x%08x, OUTPUT_CNT: 0x%08x\n", + value[0], value[1]); + mdp_err("TDSHP INTEN: 0x%08x, INTSTA: 0x%08x, STATUS: 0x%08x\n", + value[2], value[3], value[4]); + mdp_err("TDSHP CFG: 0x%08x, IN_SIZE: 0x%08x, OUT_SIZE: 0x%08x\n", + value[5], value[6], value[8]); + mdp_err("TDSHP OUTPUT_OFFSET: 0x%08x, BLANK_WIDTH: 0x%08x\n", + value[7], value[9]); +} + +static void mdp_dump_aal(void __iomem *base, const char *label) +{ + uint32_t value[9]; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x00C); /* MDP_AAL_INTSTA */ + value[1] = MDP_REG_GET32(base + 0x010); /* MDP_AAL_STATUS */ + value[2] = MDP_REG_GET32(base + 0x024); /* MDP_AAL_INPUT_COUNT */ + value[3] = MDP_REG_GET32(base + 0x028); /* MDP_AAL_OUTPUT_COUNT */ + value[4] = MDP_REG_GET32(base + 0x030); /* MDP_AAL_SIZE */ + value[5] = MDP_REG_GET32(base + 0x034); /* MDP_AAL_OUTPUT_SIZE */ + value[6] = MDP_REG_GET32(base + 0x038); /* MDP_AAL_OUTPUT_OFFSET*/ + value[7] = MDP_REG_GET32(base + 0x4EC); /* MDP_AAL_TILE_00 */ + value[8] = MDP_REG_GET32(base + 0x4F0); /* MDP_AAL_TILE_01 */ + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("AAL_INTSTA: 0x%08x, AAL_STATUS: 0x%08x\n", + value[0], value[1]); + mdp_err("AAL_INPUT_COUNT: 0x%08x, AAL_OUTPUT_COUNT: 0x%08x\n", + value[2], value[3]); + mdp_err("AAL_SIZE: 0x%08x\n", value[4]); + mdp_err("AAL_OUTPUT_SIZE: 0x%08x, AAL_OUTPUT_OFFSET: 0x%08x\n", + value[5], value[6]); + mdp_err("AAL_TILE_00: 0x%08x, AAL_TILE_01: 0x%08x\n", + value[7], value[8]); +} + +static void mdp_dump_ccorr(void __iomem *base, const char *label) +{ + uint32_t value[5]; + + if (!base) { + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("%s:base=0!\n", __func__); + return; + } + + value[0] = MDP_REG_GET32(base + 0x00C);/* MDP_CCORR_INTSTA */ + value[1] = MDP_REG_GET32(base + 0x010);/* MDP_CCORR_STATUS */ + value[2] = MDP_REG_GET32(base + 0x024);/* MDP_CCORR_INPUT_COUNT */ + value[3] = MDP_REG_GET32(base + 0x028);/* MDP_CCORR_OUTPUT_COUNT */ + value[4] = MDP_REG_GET32(base + 0x030);/* MDP_CCORR_SIZE */ + mdp_err("=============== [MDP] %s Status ===============\n", + label); + mdp_err("CCORR_INTSTA: 0x%08x, CCORR_STATUS: 0x%08x\n", + value[0], value[1]); + mdp_err("CCORR_INPUT_COUNT: 0x%08x, CCORR_OUTPUT_COUNT: 0x%08x\n", + value[2], value[3]); + mdp_err("CCORR_SIZE: 0x%08x\n", + value[4]); +} + +static uint32_t mdp_rdma_get_reg_offset_src_addr(void) +{ + return 0xF00; +} + +static uint32_t mdp_wrot_get_reg_offset_dst_addr(void) +{ + return 0xF00; +} + +static uint32_t mdp_wdma_get_reg_offset_dst_addr(void) +{ + return 0xF00; +} + +static void mdp_platform_function_setting(void) +{ + struct mdp_func_struct *pFunc = mdp_get_func(); + + pFunc->mdp_dump_mmsys_config = mdp_dump_mmsys_config; + pFunc->mdp_dump_rsz = mdp_dump_rsz; + pFunc->mdp_dump_tdshp = mdp_dump_tdshp; + pFunc->mdp_rdma_get_src_base_addr = mdp_rdma_get_reg_offset_src_addr; + pFunc->mdp_wrot_get_reg_offset_dst_addr = + mdp_wrot_get_reg_offset_dst_addr; + pFunc->mdp_wdma_get_reg_offset_dst_addr = + mdp_wdma_get_reg_offset_dst_addr; +} + +int32_t mdp_dump_info(uint64_t comp_flag, int log_level) +{ + if (comp_flag & (1LL << MDP_COMP_RDMA0)) + mdp_dump_rdma_common(MDP_RDMA0_BASE, "RDMA0"); + if (comp_flag & (1LL << MDP_COMP_AAL0)) + mdp_dump_aal(MDP_AAL_BASE, "AAL0"); + if (comp_flag & (1LL << MDP_COMP_CCORR0)) + mdp_dump_ccorr(MDP_CCORR_BASE, "CCORR0"); + if (comp_flag & (1LL << MDP_COMP_RSZ0)) + mdp_get_func()->mdp_dump_rsz(MDP_RSZ0_BASE, "RSZ0"); + if (comp_flag & (1LL << MDP_COMP_RSZ1)) + mdp_get_func()->mdp_dump_rsz(MDP_RSZ1_BASE, "RSZ1"); + if (comp_flag & (1LL << MDP_COMP_TDSHP0)) + mdp_get_func()->mdp_dump_tdshp(MDP_TDSHP_BASE, "TDSHP"); + if (comp_flag & (1LL << MDP_COMP_COLOR0)) + mdp_dump_color_common(MDP_COLOR_BASE, "COLOR0"); + if (comp_flag & (1LL << MDP_COMP_WROT0)) + mdp_dump_rot_common(MDP_WROT0_BASE, "WROT0"); + if (comp_flag & (1LL << MDP_COMP_WDMA)) + mdp_dump_wdma_common(MDP_WDMA_BASE, "WDMA"); + + return 0; +} + +void mdp_debug_init(struct platform_device *pDevice) +{ + pr_err("%s:start\n", __func__); + g_mdp_debug.mdp_device = pDevice; + + mdp_init_module_base_VA(); + mdp_map_mmsys_VA(); + mdp_virtual_function_setting(); + mdp_platform_function_setting(); + + pr_err("%s:end\n", __func__); +} + +void mdp_debug_deinit(void) +{ + mdp_deinit_module_base_VA(); + mdp_unmap_mmsys_VA(); +} + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.h new file mode 100644 index 000000000000..083f03367809 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-debug.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Daoyuan Huang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MTK_MDP3_DEBUG_H__ +#define __MTK_MDP3_DEBUG_H__ + +#include + +#define MDP_DEBUG + +struct mdp_func_struct { + void (*mdp_dump_mmsys_config)(void); + void (*mdp_dump_rsz)(void __iomem *base, const char *label); + void (*mdp_dump_tdshp)(void __iomem *base, const char *label); + uint32_t (*mdp_rdma_get_src_base_addr)(void); + uint32_t (*mdp_wrot_get_reg_offset_dst_addr)(void); + uint32_t (*mdp_wdma_get_reg_offset_dst_addr)(void); +}; + +void mdp_debug_init(struct platform_device *pDevice); +void mdp_debug_deinit(void); +struct mdp_func_struct *mdp_get_func(void); +int32_t mdp_dump_info(uint64_t comp_flag, int log_level); + + +#endif /* __MTK_MDP3_DEBUG_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c new file mode 100644 index 000000000000..1ae499f6c84b --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c @@ -0,0 +1,804 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#include +#include +#include +#include +#include "mtk-mdp3-m2m.h" + +static inline struct mdp_m2m_ctx *fh_to_ctx(struct v4l2_fh *fh) +{ + return container_of(fh, struct mdp_m2m_ctx, fh); +} + +static inline struct mdp_m2m_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) +{ + return container_of(ctrl->handler, struct mdp_m2m_ctx, ctrl_handler); +} + +static inline struct mdp_frame *ctx_get_frame(struct mdp_m2m_ctx *ctx, + enum v4l2_buf_type type) +{ + if (V4L2_TYPE_IS_OUTPUT(type)) + return &ctx->curr_param.output; + else + return &ctx->curr_param.captures[0]; +} + +static void mdp_m2m_ctx_set_state(struct mdp_m2m_ctx *ctx, u32 state) +{ + mutex_lock(&ctx->curr_param.state_lock); + ctx->curr_param.state |= state; + mutex_unlock(&ctx->curr_param.state_lock); +} + +static bool mdp_m2m_ctx_is_state_set(struct mdp_m2m_ctx *ctx, u32 mask) +{ + bool ret; + + mutex_lock(&ctx->curr_param.state_lock); + ret = (ctx->curr_param.state & mask) == mask; + mutex_unlock(&ctx->curr_param.state_lock); + return ret; +} + +static void mdp_m2m_ctx_lock(struct vb2_queue *q) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); + + mutex_lock(&ctx->mdp_dev->m2m_lock); +} + +static void mdp_m2m_ctx_unlock(struct vb2_queue *q) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); + + mutex_unlock(&ctx->mdp_dev->m2m_lock); +} + +static void mdp_m2m_job_abort(void *priv) +{ +} + +static void mdp_m2m_process_done(void *priv, int vb_state) +{ + struct mdp_m2m_ctx *ctx = priv; + struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf; + u32 valid_output_flags = V4L2_BUF_FLAG_TIMECODE | + V4L2_BUF_FLAG_TSTAMP_SRC_MASK | + V4L2_BUF_FLAG_KEYFRAME | + V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME; + + src_vbuf = (struct vb2_v4l2_buffer *) + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + dst_vbuf = (struct vb2_v4l2_buffer *) + v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + src_vbuf->sequence = ctx->frame_count; + dst_vbuf->sequence = src_vbuf->sequence; + dst_vbuf->timecode = src_vbuf->timecode; + dst_vbuf->flags &= ~valid_output_flags; + dst_vbuf->flags |= src_vbuf->flags & valid_output_flags; + + v4l2_m2m_buf_done(src_vbuf, vb_state); + v4l2_m2m_buf_done(dst_vbuf, vb_state); + v4l2_m2m_job_finish(ctx->mdp_dev->m2m_dev, ctx->m2m_ctx); + + ctx->curr_param.frame_no = ctx->frame_count++; +} + +static void mdp_m2m_worker(struct work_struct *work) +{ + struct mdp_m2m_ctx *ctx = container_of(work, struct mdp_m2m_ctx, work); + struct mdp_frame *frame; + struct vb2_v4l2_buffer *src_vb, *dst_vb; + struct img_ipi_frameparam param = {0}; + struct mdp_cmdq_param task = {0}; + enum vb2_buffer_state vb_state = VB2_BUF_STATE_ERROR; + int ret; + + if (mdp_m2m_ctx_is_state_set(ctx, MDP_M2M_CTX_ERROR)) { + dev_err(&ctx->mdp_dev->pdev->dev, + "mdp_m2m_ctx is in error state\n"); + goto worker_end; + } + + param.frame_no = ctx->curr_param.frame_no; + param.type = ctx->curr_param.type; + param.num_inputs = 1; + param.num_outputs = 1; + + frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + mdp_set_src_config(¶m.inputs[0], frame, &src_vb->vb2_buf); + + frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + mdp_set_dst_config(¶m.outputs[0], frame, &dst_vb->vb2_buf); + + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; + param.timestamp = src_vb->vb2_buf.timestamp; + + ret = mdp_vpu_process(&ctx->vpu, ¶m); + if (ret) { + dev_err(&ctx->mdp_dev->pdev->dev, + "VPU MDP process failed: %d\n", ret); + goto worker_end; + } + + task.config = ctx->vpu.config; + task.param = ¶m; + task.composes[0] = &frame->compose; + task.wait = 1; + task.cmdq_cb = NULL; + task.cb_data = NULL; + task.mdp_ctx = ctx; + + ret = mdp_cmdq_send(ctx->mdp_dev, &task); + if (ret) { + dev_err(&ctx->mdp_dev->pdev->dev, + "CMDQ sendtask failed: %d\n", ret); + goto worker_end; + } + + return; + +worker_end: + mdp_m2m_process_done(ctx, vb_state); +} + +static void mdp_m2m_device_run(void *priv) +{ + struct mdp_m2m_ctx *ctx = priv; + + queue_work(ctx->mdp_dev->job_wq, &ctx->work); +} + +static int mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); + int ret; + + ret = 0;//pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev); + if (ret < 0) + mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d", ctx->id, ret); + + ctx->frame_count = 0; + + return 0; +} + +static struct vb2_v4l2_buffer *mdp_m2m_buf_remove(struct mdp_m2m_ctx *ctx, + unsigned int type) +{ + if (V4L2_TYPE_IS_OUTPUT(type)) + return (struct vb2_v4l2_buffer *) + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + else + return (struct vb2_v4l2_buffer *) + v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); +} + +static void mdp_m2m_stop_streaming(struct vb2_queue *q) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); + struct vb2_v4l2_buffer *vb; + + vb = mdp_m2m_buf_remove(ctx, q->type); + while (vb) { + v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); + vb = mdp_m2m_buf_remove(ctx, q->type); + } + + //pm_runtime_put(&ctx->mdp_dev->pdev->dev); +} + +static int mdp_m2m_queue_setup(struct vb2_queue *q, + unsigned int *num_buffers, + unsigned int *num_planes, unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); + struct v4l2_pix_format_mplane *pix_mp; + u32 i; + + pix_mp = &ctx_get_frame(ctx, q->type)->format.fmt.pix_mp; + + /* from VIDIOC_CREATE_BUFS */ + if (*num_planes) { + if (*num_planes != pix_mp->num_planes) + return -EINVAL; + for (i = 0; i < pix_mp->num_planes; ++i) + if (sizes[i] < pix_mp->plane_fmt[i].sizeimage) + return -EINVAL; + } else {/* from VIDIOC_REQBUFS */ + *num_planes = pix_mp->num_planes; + for (i = 0; i < pix_mp->num_planes; ++i) + sizes[i] = pix_mp->plane_fmt[i].sizeimage; + } + + mdp_dbg(2, "[%d] type:%d, planes:%u, buffers:%u, size:%u,%u,%u", + ctx->id, q->type, *num_planes, *num_buffers, + sizes[0], sizes[1], sizes[2]); + return 0; +} + +static int mdp_m2m_buf_prepare(struct vb2_buffer *vb) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct v4l2_pix_format_mplane *pix_mp; + struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); + u32 i; + + v4l2_buf->field = V4L2_FIELD_NONE; + + if (!V4L2_TYPE_IS_OUTPUT(vb->type)) { + pix_mp = &ctx_get_frame(ctx, vb->type)->format.fmt.pix_mp; + for (i = 0; i < pix_mp->num_planes; ++i) { + vb2_set_plane_payload(vb, i, + pix_mp->plane_fmt[i].sizeimage); + } + } + return 0; +} + +static int mdp_m2m_buf_out_validate(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); + + v4l2_buf->field = V4L2_FIELD_NONE; + + return 0; +} + +static void mdp_m2m_buf_queue(struct vb2_buffer *vb) +{ + struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); + + v4l2_buf->field = V4L2_FIELD_NONE; + + v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); +} + +static const struct vb2_ops mdp_m2m_qops = { + .queue_setup = mdp_m2m_queue_setup, + .wait_prepare = mdp_m2m_ctx_unlock, + .wait_finish = mdp_m2m_ctx_lock, + .buf_prepare = mdp_m2m_buf_prepare, + .start_streaming = mdp_m2m_start_streaming, + .stop_streaming = mdp_m2m_stop_streaming, + .buf_queue = mdp_m2m_buf_queue, + .buf_out_validate = mdp_m2m_buf_out_validate, +}; + +static int mdp_m2m_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + + strlcpy(cap->driver, MDP_MODULE_NAME, sizeof(cap->driver)); + strlcpy(cap->card, ctx->mdp_dev->pdev->name, sizeof(cap->card)); + strlcpy(cap->bus_info, "platform:mt8183", sizeof(cap->bus_info)); + cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING | + V4L2_CAP_DEVICE_CAPS; /* | V4L2_CAP_META_OUTPUT */ + cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + return 0; +} + +static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + return mdp_enum_fmt_mplane(f); +} + +static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_frame *frame; + struct v4l2_pix_format_mplane *pix_mp; + + frame = ctx_get_frame(ctx, f->type); + *f = frame->format; + pix_mp = &f->fmt.pix_mp; + pix_mp->colorspace = ctx->curr_param.colorspace; + pix_mp->xfer_func = ctx->curr_param.xfer_func; + pix_mp->ycbcr_enc = ctx->curr_param.ycbcr_enc; + pix_mp->quantization = ctx->curr_param.quant; + + mdp_dbg(2, "[%d] type:%d, frame:%ux%u colorspace=%d", ctx->id, f->type, + f->fmt.pix_mp.width, f->fmt.pix_mp.height, + f->fmt.pix_mp.colorspace); + return 0; +} + +static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_frame *frame = ctx_get_frame(ctx, f->type); + struct mdp_frame *capture; + const struct mdp_format *fmt; + struct vb2_queue *vq; + + mdp_dbg(2, "[%d] type:%d", ctx->id, f->type); + + fmt = mdp_try_fmt_mplane(f, &ctx->curr_param, ctx->id); + if (!fmt) { + mdp_err("[%d] try_fmt failed, type:%d", ctx->id, f->type); + return -EINVAL; + } + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (vb2_is_streaming(vq)) { + dev_info(&ctx->mdp_dev->pdev->dev, "Queue %d busy\n", f->type); + return -EBUSY; + } + + frame->format = *f; + frame->mdp_fmt = fmt; + frame->ycbcr_prof = mdp_map_ycbcr_prof_mplane(f, fmt->mdp_color); + frame->usage = V4L2_TYPE_IS_OUTPUT(f->type) ? + MDP_BUFFER_USAGE_HW_READ : MDP_BUFFER_USAGE_MDP; + + capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (V4L2_TYPE_IS_OUTPUT(f->type)) { + capture->crop.c.left = 0; + capture->crop.c.top = 0; + capture->crop.c.width = f->fmt.pix_mp.width; + capture->crop.c.height = f->fmt.pix_mp.height; + ctx->curr_param.colorspace = f->fmt.pix_mp.colorspace; + ctx->curr_param.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + ctx->curr_param.quant = f->fmt.pix_mp.quantization; + ctx->curr_param.xfer_func = f->fmt.pix_mp.xfer_func; + } else { + capture->compose.left = 0; + capture->compose.top = 0; + capture->compose.width = f->fmt.pix_mp.width; + capture->compose.height = f->fmt.pix_mp.height; + } + + ctx->frame_count = 0; + + mdp_dbg(2, "[%d] type:%d, frame:%ux%u", ctx->id, f->type, + f->fmt.pix_mp.width, f->fmt.pix_mp.height); + return 0; +} + +static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + + if (!mdp_try_fmt_mplane(f, &ctx->curr_param, ctx->id)) + return -EINVAL; + + return 0; +} + +static int mdp_m2m_reqbufs(struct file *file, void *fh, + struct v4l2_requestbuffers *reqbufs) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); +} + +static int mdp_m2m_streamon(struct file *file, void *fh, + enum v4l2_buf_type type) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_frame *capture; + int ret; + bool out_streaming, cap_streaming; + + capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + out_streaming = ctx->m2m_ctx->out_q_ctx.q.streaming; + cap_streaming = ctx->m2m_ctx->cap_q_ctx.q.streaming; + + /* Check to see if scaling ratio is within supported range */ + if ((V4L2_TYPE_IS_OUTPUT(type) && cap_streaming) || + (!V4L2_TYPE_IS_OUTPUT(type) && out_streaming)) { + ret = mdp_check_scaling_ratio(&capture->crop.c, + &capture->compose, + capture->rotation, + ctx->curr_param.limit); + if (ret) { + dev_info(&ctx->mdp_dev->pdev->dev, + "Out of scaling range\n"); + return ret; + } + } + + if (!mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) { + ret = mdp_vpu_get_locked(ctx->mdp_dev); + if (ret) + return ret; + + ret = mdp_vpu_ctx_init(&ctx->vpu, &ctx->mdp_dev->vpu, + MDP_DEV_M2M); + if (ret) { + dev_err(&ctx->mdp_dev->pdev->dev, + "VPU init failed %d\n", ret); + return -EINVAL; + } + mdp_m2m_ctx_set_state(ctx, MDP_VPU_INIT); + } + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); +} + +static int mdp_m2m_g_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_frame *frame; + bool valid = false; + + if (s->type <= V4L2_BUF_TYPE_META_OUTPUT) { + if (V4L2_TYPE_IS_OUTPUT(s->type)) + valid = mdp_target_is_crop(s->target); + else + valid = mdp_target_is_compose(s->target); + } + + if (!valid) { + mdp_dbg(1, "[%d] invalid type:%u target:%u", ctx->id, s->type, + s->target); + return -EINVAL; + } + + switch (s->target) { + case V4L2_SEL_TGT_CROP: + frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + s->r = frame->crop.c; + return 0; + case V4L2_SEL_TGT_COMPOSE: + frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + s->r = frame->compose; + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + frame = ctx_get_frame(ctx, s->type); + s->r.left = 0; + s->r.top = 0; + s->r.width = frame->format.fmt.pix_mp.width; + s->r.height = frame->format.fmt.pix_mp.height; + return 0; + } + return -EINVAL; +} + +static int mdp_m2m_s_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_frame *frame = ctx_get_frame(ctx, s->type); + struct mdp_frame *capture; + struct v4l2_rect r; + bool valid = false; + int ret; + + if (s->type <= V4L2_BUF_TYPE_META_OUTPUT) { + if (V4L2_TYPE_IS_OUTPUT(s->type)) + valid = (s->target == V4L2_SEL_TGT_CROP); + else + valid = (s->target == V4L2_SEL_TGT_COMPOSE); + } + if (!valid) { + mdp_dbg(1, "[%d] invalid type:%u target:%u", ctx->id, s->type, + s->target); + return -EINVAL; + } + + ret = mdp_try_crop(&r, s, frame, ctx->id); + if (ret) + return ret; + capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + if (mdp_target_is_crop(s->target)) + capture->crop.c = r; + else + capture->compose = r; + + s->r = r; + memset(s->reserved, 0, sizeof(s->reserved)); + + ctx->frame_count = 0; + return 0; +} + +static const struct v4l2_ioctl_ops mdp_m2m_ioctl_ops = { + .vidioc_querycap = mdp_m2m_querycap, + .vidioc_enum_fmt_vid_cap = mdp_m2m_enum_fmt_mplane, + .vidioc_enum_fmt_vid_out = mdp_m2m_enum_fmt_mplane, + .vidioc_g_fmt_vid_cap_mplane = mdp_m2m_g_fmt_mplane, + .vidioc_g_fmt_vid_out_mplane = mdp_m2m_g_fmt_mplane, + .vidioc_s_fmt_vid_cap_mplane = mdp_m2m_s_fmt_mplane, + .vidioc_s_fmt_vid_out_mplane = mdp_m2m_s_fmt_mplane, + .vidioc_try_fmt_vid_cap_mplane = mdp_m2m_try_fmt_mplane, + .vidioc_try_fmt_vid_out_mplane = mdp_m2m_try_fmt_mplane, + .vidioc_reqbufs = mdp_m2m_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_streamon = mdp_m2m_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_g_selection = mdp_m2m_g_selection, + .vidioc_s_selection = mdp_m2m_s_selection, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static int mdp_m2m_queue_init(void *priv, + struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct mdp_m2m_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->ops = &mdp_m2m_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->dev = &ctx->mdp_dev->pdev->dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->ops = &mdp_m2m_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->dev = &ctx->mdp_dev->pdev->dev; + + return vb2_queue_init(dst_vq); +} + +static int mdp_m2m_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct mdp_m2m_ctx *ctx = ctrl_to_ctx(ctrl); + struct mdp_frame *capture; + + if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) + return 0; + + capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + switch (ctrl->id) { + case V4L2_CID_HFLIP: + capture->hflip = ctrl->val; + break; + case V4L2_CID_VFLIP: + capture->vflip = ctrl->val; + break; + case V4L2_CID_ROTATE: + capture->rotation = ctrl->val; + break; + } + + return 0; +} + +static const struct v4l2_ctrl_ops mdp_m2m_ctrl_ops = { + .s_ctrl = mdp_m2m_s_ctrl, +}; + +static int mdp_m2m_ctrls_create(struct mdp_m2m_ctx *ctx) +{ + v4l2_ctrl_handler_init(&ctx->ctrl_handler, MDP_MAX_CTRLS); + ctx->ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &mdp_m2m_ctrl_ops, V4L2_CID_HFLIP, + 0, 1, 1, 0); + ctx->ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &mdp_m2m_ctrl_ops, V4L2_CID_VFLIP, + 0, 1, 1, 0); + ctx->ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &mdp_m2m_ctrl_ops, + V4L2_CID_ROTATE, 0, 270, 90, 0); + + if (ctx->ctrl_handler.error) { + int err = ctx->ctrl_handler.error; + + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + dev_err(&ctx->mdp_dev->pdev->dev, + "Failed to register controls\n"); + return err; + } + return 0; +} + +static int mdp_m2m_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct mdp_dev *mdp = video_get_drvdata(vdev); + struct mdp_m2m_ctx *ctx; + int ret; + struct v4l2_format default_format; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + if (mutex_lock_interruptible(&mdp->m2m_lock)) { + ret = -ERESTARTSYS; + goto err_free_ctx; + } + + ctx->id = ida_alloc(&mdp->mdp_ida, GFP_KERNEL); + ctx->mdp_dev = mdp; + + v4l2_fh_init(&ctx->fh, vdev); + vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + file->private_data = &ctx->fh; + ret = mdp_m2m_ctrls_create(ctx); + if (ret) + goto err_exit_fh; + + /* Use separate control handler per file handle */ + ctx->fh.ctrl_handler = &ctx->ctrl_handler; + v4l2_fh_add(&ctx->fh); + + ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx, mdp_m2m_queue_init); + if (IS_ERR(ctx->m2m_ctx)) { + dev_err(&mdp->pdev->dev, "Failed to initialize m2m context\n"); + ret = PTR_ERR(ctx->m2m_ctx); + goto err_release_handler; + } + ctx->fh.m2m_ctx = ctx->m2m_ctx; + + INIT_WORK(&ctx->work, mdp_m2m_worker); + + ret = mdp_frameparam_init(&ctx->curr_param); + if (ret) { + dev_err(&mdp->pdev->dev, + "Failed to initialize mdp parameter\n"); + goto err_release_m2m_ctx; + } + + mutex_unlock(&mdp->m2m_lock); + + /* Default format */ + memset(&default_format, 0, sizeof(default_format)); + default_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + default_format.fmt.pix_mp.width = 32; + default_format.fmt.pix_mp.height = 32; + default_format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; + mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); + default_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); + + mdp_dbg(1, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id); + + return 0; + +err_release_m2m_ctx: + v4l2_m2m_ctx_release(ctx->m2m_ctx); +err_release_handler: + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_fh_del(&ctx->fh); +err_exit_fh: + v4l2_fh_exit(&ctx->fh); + mutex_unlock(&mdp->m2m_lock); +err_free_ctx: + kfree(ctx); + + return ret; +} + +static int mdp_m2m_release(struct file *file) +{ + struct mdp_m2m_ctx *ctx = fh_to_ctx(file->private_data); + struct mdp_dev *mdp = video_drvdata(file); + + mutex_lock(&mdp->m2m_lock); + v4l2_m2m_ctx_release(ctx->m2m_ctx); + if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) { + mdp_vpu_ctx_deinit(&ctx->vpu); + mdp_vpu_put_locked(mdp); + } + + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + ida_free(&mdp->mdp_ida, ctx->id); + mutex_unlock(&mdp->m2m_lock); + + mdp_dbg(1, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id); + kfree(ctx); + + return 0; +} + +static const struct v4l2_file_operations mdp_m2m_fops = { + .owner = THIS_MODULE, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, + .open = mdp_m2m_open, + .release = mdp_m2m_release, +}; + +static const struct v4l2_m2m_ops mdp_m2m_ops = { + .device_run = mdp_m2m_device_run, + .job_abort = mdp_m2m_job_abort, +}; + +int mdp_m2m_device_register(struct mdp_dev *mdp) +{ + struct device *dev = &mdp->pdev->dev; + int ret = 0; + + mdp->m2m_vdev = video_device_alloc(); + if (!mdp->m2m_vdev) { + dev_err(dev, "Failed to allocate video device\n"); + ret = -ENOMEM; + goto err_video_alloc; + } + //mdp->m2m_vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | + // V4L2_CAP_STREAMING; + mdp->m2m_vdev->fops = &mdp_m2m_fops; + mdp->m2m_vdev->ioctl_ops = &mdp_m2m_ioctl_ops; + mdp->m2m_vdev->release = video_device_release; + mdp->m2m_vdev->lock = &mdp->m2m_lock; + mdp->m2m_vdev->vfl_dir = VFL_DIR_M2M; + mdp->m2m_vdev->v4l2_dev = &mdp->v4l2_dev; + snprintf(mdp->m2m_vdev->name, sizeof(mdp->m2m_vdev->name), "%s:m2m", + MDP_MODULE_NAME); + video_set_drvdata(mdp->m2m_vdev, mdp); + + mdp->m2m_dev = v4l2_m2m_init(&mdp_m2m_ops); + if (IS_ERR(mdp->m2m_dev)) { + dev_err(dev, "Failed to initialize v4l2-m2m device\n"); + ret = PTR_ERR(mdp->m2m_dev); + goto err_m2m_init; + } + + ret = video_register_device(mdp->m2m_vdev, VFL_TYPE_GRABBER, 2); + if (ret) { + dev_err(dev, "Failed to register video device\n"); + goto err_video_register; + } + + v4l2_info(&mdp->v4l2_dev, "Driver registered as /dev/video%d", + mdp->m2m_vdev->num); + return 0; + +err_video_register: + v4l2_m2m_release(mdp->m2m_dev); +err_m2m_init: + video_device_release(mdp->m2m_vdev); +err_video_alloc: + + return ret; +} + +void mdp_m2m_device_unregister(struct mdp_dev *mdp) +{ + video_unregister_device(mdp->m2m_vdev); + video_device_release(mdp->m2m_vdev); + v4l2_m2m_release(mdp->m2m_dev); +} + +void mdp_m2m_job_finish(struct mdp_m2m_ctx *ctx) +{ + enum vb2_buffer_state vb_state = VB2_BUF_STATE_DONE; + + mdp_m2m_process_done(ctx, vb_state); +} + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.h new file mode 100644 index 000000000000..c3f340f7ec49 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MTK_MDP3_M2M_H__ +#define __MTK_MDP3_M2M_H__ + +#include +#include "mtk-mdp3-core.h" +#include "mtk-mdp3-vpu.h" +#include "mtk-mdp3-regs.h" + +#define MDP_MAX_CTRLS 10 + +struct mdp_m2m_ctrls { + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *rotate; +}; + +struct mdp_m2m_ctx { + u32 id; + struct mdp_dev *mdp_dev; + struct v4l2_fh fh; + struct v4l2_ctrl_handler ctrl_handler; + struct mdp_m2m_ctrls ctrls; + struct v4l2_m2m_ctx *m2m_ctx; + struct mdp_vpu_ctx vpu; + struct work_struct work; + u32 frame_count; + + struct mdp_frameparam curr_param; +}; + +int mdp_m2m_device_register(struct mdp_dev *mdp); +void mdp_m2m_device_unregister(struct mdp_dev *mdp); +void mdp_m2m_job_finish(struct mdp_m2m_ctx *ctx); + +#endif /* __MTK_MDP3_M2M_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c new file mode 100644 index 000000000000..5c48a7e75efd --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c @@ -0,0 +1,748 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#include +#include +#include +#include "mtk-mdp3-core.h" +#include "mtk-mdp3-regs.h" + +static const struct mdp_format mdp_formats[] = { + { + .pixelformat = V4L2_PIX_FMT_GREY, + .mdp_color = MDP_COLOR_GREY, + .depth = { 8 }, + .row_depth = { 8 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_RGB565X, + .mdp_color = MDP_COLOR_RGB565, + .depth = { 16 }, + .row_depth = { 16 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_RGB565, + .mdp_color = MDP_COLOR_BGR565, + .depth = { 16 }, + .row_depth = { 16 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_RGB24, + .mdp_color = MDP_COLOR_RGB888, + .depth = { 24 }, + .row_depth = { 24 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_BGR24, + .mdp_color = MDP_COLOR_BGR888, + .depth = { 24 }, + .row_depth = { 24 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_ABGR32, + .mdp_color = MDP_COLOR_BGRA8888, + .depth = { 32 }, + .row_depth = { 32 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_ARGB32, + .mdp_color = MDP_COLOR_ARGB8888, + .depth = { 32 }, + .row_depth = { 32 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_UYVY, + .mdp_color = MDP_COLOR_UYVY, + .depth = { 16 }, + .row_depth = { 16 }, + .num_planes = 1, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_VYUY, + .mdp_color = MDP_COLOR_VYUY, + .depth = { 16 }, + .row_depth = { 16 }, + .num_planes = 1, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_YUYV, + .mdp_color = MDP_COLOR_YUYV, + .depth = { 16 }, + .row_depth = { 16 }, + .num_planes = 1, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_YVYU, + .mdp_color = MDP_COLOR_YVYU, + .depth = { 16 }, + .row_depth = { 16 }, + .num_planes = 1, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_YUV420, + .mdp_color = MDP_COLOR_I420, + .depth = { 12 }, + .row_depth = { 8 }, + .num_planes = 1, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_YVU420, + .mdp_color = MDP_COLOR_YV12, + .depth = { 12 }, + .row_depth = { 8 }, + .num_planes = 1, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_NV12, + .mdp_color = MDP_COLOR_NV12, + .depth = { 12 }, + .row_depth = { 8 }, + .num_planes = 1, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_NV21, + .mdp_color = MDP_COLOR_NV21, + .depth = { 12 }, + .row_depth = { 8 }, + .num_planes = 1, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_NV16, + .mdp_color = MDP_COLOR_NV16, + .depth = { 16 }, + .row_depth = { 8 }, + .num_planes = 1, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_NV61, + .mdp_color = MDP_COLOR_NV61, + .depth = { 16 }, + .row_depth = { 8 }, + .num_planes = 1, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_NV24, + .mdp_color = MDP_COLOR_NV24, + .depth = { 24 }, + .row_depth = { 8 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_NV42, + .mdp_color = MDP_COLOR_NV42, + .depth = { 24 }, + .row_depth = { 8 }, + .num_planes = 1, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_MT21C, + .mdp_color = MDP_COLOR_420_BLK_UFO, + .depth = { 8, 4 }, + .row_depth = { 8, 8 }, + .num_planes = 2, + .walign = 4, + .halign = 5, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_MM21, + .mdp_color = MDP_COLOR_420_BLK, + .depth = { 8, 4 }, + .row_depth = { 8, 8 }, + .num_planes = 2, + .walign = 4, + .halign = 5, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_NV12M, + .mdp_color = MDP_COLOR_NV12, + .depth = { 8, 4 }, + .row_depth = { 8, 8 }, + .num_planes = 2, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_NV21M, + .mdp_color = MDP_COLOR_NV21, + .depth = { 8, 4 }, + .row_depth = { 8, 8 }, + .num_planes = 2, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_NV16M, + .mdp_color = MDP_COLOR_NV16, + .depth = { 8, 8 }, + .row_depth = { 8, 8 }, + .num_planes = 2, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_NV61M, + .mdp_color = MDP_COLOR_NV61, + .depth = { 8, 8 }, + .row_depth = { 8, 8 }, + .num_planes = 2, + .walign = 1, + .flags = MDP_FMT_FLAG_OUTPUT, + }, { + .pixelformat = V4L2_PIX_FMT_YUV420M, + .mdp_color = MDP_COLOR_I420, + .depth = { 8, 2, 2 }, + .row_depth = { 8, 4, 4 }, + .num_planes = 3, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + }, { + .pixelformat = V4L2_PIX_FMT_YVU420M, + .mdp_color = MDP_COLOR_YV12, + .depth = { 8, 2, 2 }, + .row_depth = { 8, 4, 4 }, + .num_planes = 3, + .walign = 1, + .halign = 1, + .flags = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE, + } +}; + +static const struct mdp_limit mdp_def_limit = { + .out_limit = { + .wmin = 16, + .hmin = 16, + .wmax = 8176, + .hmax = 8176, + }, + .cap_limit = { + .wmin = 2, + .hmin = 2, + .wmax = 8176, + .hmax = 8176, + }, + .h_scale_up_max = 32, + .v_scale_up_max = 32, + .h_scale_down_max = 20, + .v_scale_down_max = 128, +}; + +static const struct mdp_format *mdp_find_fmt(u32 pixelformat, u32 type) +{ + u32 i, flag; + + flag = V4L2_TYPE_IS_OUTPUT(type) ? MDP_FMT_FLAG_OUTPUT : + MDP_FMT_FLAG_CAPTURE; + for (i = 0; i < ARRAY_SIZE(mdp_formats); ++i) { + if (!(mdp_formats[i].flags & flag)) + continue; + if (mdp_formats[i].pixelformat == pixelformat) + return &mdp_formats[i]; + } + return NULL; +} + +static const struct mdp_format *mdp_find_fmt_by_index(u32 index, u32 type) +{ + u32 i, flag, num = 0; + + flag = V4L2_TYPE_IS_OUTPUT(type) ? MDP_FMT_FLAG_OUTPUT : + MDP_FMT_FLAG_CAPTURE; + for (i = 0; i < ARRAY_SIZE(mdp_formats); ++i) { + if (!(mdp_formats[i].flags & flag)) + continue; + if (index == num) + return &mdp_formats[i]; + num++; + } + return NULL; +} + +enum mdp_ycbcr_profile mdp_map_ycbcr_prof_mplane(struct v4l2_format *f, + u32 mdp_color) +{ + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + + if (MDP_COLOR_IS_RGB(mdp_color)) + return MDP_YCBCR_PROFILE_FULL_BT601; + + switch (pix_mp->colorspace) { + case V4L2_COLORSPACE_JPEG: + return MDP_YCBCR_PROFILE_JPEG; + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_DCI_P3: + if (pix_mp->quantization == V4L2_QUANTIZATION_FULL_RANGE) + return MDP_YCBCR_PROFILE_FULL_BT709; + return MDP_YCBCR_PROFILE_BT709; + case V4L2_COLORSPACE_BT2020: + if (pix_mp->quantization == V4L2_QUANTIZATION_FULL_RANGE) + return MDP_YCBCR_PROFILE_FULL_BT2020; + return MDP_YCBCR_PROFILE_BT2020; + default: + if (pix_mp->quantization == V4L2_QUANTIZATION_FULL_RANGE) + return MDP_YCBCR_PROFILE_FULL_BT601; + return MDP_YCBCR_PROFILE_BT601; + } +} + +static void mdp_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, + unsigned int walign, + u32 *h, unsigned int hmin, unsigned int hmax, + unsigned int halign, unsigned int salign) +{ + unsigned int org_w, org_h, wstep, hstep; + + org_w = *w; + org_h = *h; + v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, + salign); + + wstep = 1 << walign; + hstep = 1 << halign; + if (*w < org_w && (*w + wstep) <= wmax) + *w += wstep; + if (*h < org_h && (*h + hstep) <= hmax) + *h += hstep; +} + +static int mdp_clamp_align(s32 *x, int min, int max, unsigned int align) +{ + unsigned int mask; + + if (min < 0 || max < 0) + return -ERANGE; + + /* Bits that must be zero to be aligned */ + mask = ~((1 << align) - 1); + + min = 0 ? 0 : ((min + ~mask) & mask); + max = max & mask; + if ((unsigned int)min > (unsigned int)max) + return -ERANGE; + + /* Clamp to aligned min and max */ + *x = clamp(*x, min, max); + + /* Round to nearest aligned value */ + if (align) + *x = (*x + (1 << (align - 1))) & mask; + return 0; +} + +int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f) +{ + const struct mdp_format *fmt; + + if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) + return -EINVAL; + + fmt = mdp_find_fmt_by_index(f->index, f->type); + if (!fmt) + return -EINVAL; + + /* f->description */ + f->pixelformat = fmt->pixelformat; + return 0; +} + +const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f, + struct mdp_frameparam *param, + u32 ctx_id) +{ + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + const struct mdp_format *fmt; + const struct mdp_pix_limit *pix_limit; + u32 wmin, wmax, hmin, hmax, org_w, org_h; + unsigned int i; + + if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) + return NULL; + + fmt = mdp_find_fmt(pix_mp->pixelformat, f->type); + if (!fmt) + fmt = mdp_find_fmt_by_index(0, f->type); + if (!fmt) { + mdp_dbg(0, "[%d] pixelformat %c%c%c%c invalid", ctx_id, + (pix_mp->pixelformat & 0xff), + (pix_mp->pixelformat >> 8) & 0xff, + (pix_mp->pixelformat >> 16) & 0xff, + (pix_mp->pixelformat >> 24) & 0xff); + return NULL; + } + + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->flags = 0; + pix_mp->pixelformat = fmt->pixelformat; + if (!V4L2_TYPE_IS_OUTPUT(f->type)) { + pix_mp->colorspace = param->colorspace; + pix_mp->xfer_func = param->xfer_func; + pix_mp->ycbcr_enc = param->ycbcr_enc; + pix_mp->quantization = param->quant; + } + memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); + + pix_limit = V4L2_TYPE_IS_OUTPUT(f->type) ? ¶m->limit->out_limit : + ¶m->limit->cap_limit; + wmin = pix_limit->wmin; + wmax = pix_limit->wmax; + hmin = pix_limit->hmin; + hmax = pix_limit->hmax; + org_w = pix_mp->width; + org_h = pix_mp->height; + + mdp_bound_align_image(&pix_mp->width, wmin, wmax, fmt->walign, + &pix_mp->height, hmin, hmax, fmt->halign, + fmt->salign); + if (org_w != pix_mp->width || org_h != pix_mp->height) + mdp_dbg(1, "[%d] size change: %ux%u to %ux%u", ctx_id, + org_w, org_h, pix_mp->width, pix_mp->height); + + if (pix_mp->num_planes && pix_mp->num_planes != fmt->num_planes) + mdp_dbg(1, "[%d] num of planes change: %u to %u", ctx_id, + pix_mp->num_planes, fmt->num_planes); + pix_mp->num_planes = fmt->num_planes; + + for (i = 0; i < pix_mp->num_planes; ++i) { + u32 min_bpl = (pix_mp->width * fmt->row_depth[i]) / 8; + u32 bpl = pix_mp->plane_fmt[i].bytesperline; + u32 si; + + if (bpl < min_bpl) + bpl = min_bpl; + si = (bpl * pix_mp->height * fmt->depth[i]) / fmt->row_depth[i]; + + pix_mp->plane_fmt[i].bytesperline = bpl; + if (pix_mp->plane_fmt[i].sizeimage < si) + pix_mp->plane_fmt[i].sizeimage = si; + memset(pix_mp->plane_fmt[i].reserved, 0, + sizeof(pix_mp->plane_fmt[i].reserved)); + mdp_dbg(2, "[%d] p%u, bpl:%u (%u), sizeimage:%u (%u)", ctx_id, + i, bpl, min_bpl, pix_mp->plane_fmt[i].sizeimage, si); + } + + return fmt; +} + +static int mdp_clamp_start(s32 *x, int min, int max, unsigned int align, + u32 flags) +{ + if (flags & V4L2_SEL_FLAG_GE) + max = *x; + if (flags & V4L2_SEL_FLAG_LE) + min = *x; + return mdp_clamp_align(x, min, max, align); +} + +static int mdp_clamp_end(s32 *x, int min, int max, unsigned int align, + u32 flags) +{ + if (flags & V4L2_SEL_FLAG_GE) + min = *x; + if (flags & V4L2_SEL_FLAG_LE) + max = *x; + return mdp_clamp_align(x, min, max, align); +} + +int mdp_try_crop(struct v4l2_rect *r, const struct v4l2_selection *s, + struct mdp_frame *frame, u32 ctx_id) +{ + s32 left, top, right, bottom; + u32 framew, frameh, walign, halign; + int ret; + + mdp_dbg(2, "[%d] target:%d, set:(%d,%d) %ux%u", ctx_id, s->target, + s->r.left, s->r.top, s->r.width, s->r.height); + + left = s->r.left; + top = s->r.top; + right = s->r.left + s->r.width; + bottom = s->r.top + s->r.height; + framew = frame->format.fmt.pix_mp.width; + frameh = frame->format.fmt.pix_mp.height; + + if (mdp_target_is_crop(s->target)) { + walign = 1; + halign = 1; + } else { + walign = frame->mdp_fmt->walign; + halign = frame->mdp_fmt->halign; + } + + mdp_dbg(2, "[%d] align:%u,%u, bound:%ux%u", ctx_id, + walign, halign, framew, frameh); + + ret = mdp_clamp_start(&left, 0, right, walign, s->flags); + if (ret) + return ret; + ret = mdp_clamp_start(&top, 0, bottom, halign, s->flags); + if (ret) + return ret; + ret = mdp_clamp_end(&right, left, framew, walign, s->flags); + if (ret) + return ret; + ret = mdp_clamp_end(&bottom, top, frameh, halign, s->flags); + if (ret) + return ret; + + r->left = left; + r->top = top; + r->width = right - left; + r->height = bottom - top; + + mdp_dbg(2, "[%d] crop:(%d,%d) %ux%u", ctx_id, + r->left, r->top, r->width, r->height); + return 0; +} + +int mdp_check_scaling_ratio(const struct v4l2_rect *crop, + const struct v4l2_rect *compose, s32 rotation, + const struct mdp_limit *limit) +{ + u32 crop_w, crop_h, comp_w, comp_h; + + crop_w = crop->width; + crop_h = crop->height; + if (90 == rotation || 270 == rotation) { + comp_w = compose->height; + comp_h = compose->width; + } else { + comp_w = compose->width; + comp_h = compose->height; + } + + if ((crop_w / comp_w) > limit->h_scale_down_max || + (crop_h / comp_h) > limit->v_scale_down_max || + (comp_w / crop_w) > limit->h_scale_up_max || + (comp_h / crop_h) > limit->v_scale_up_max) + return -ERANGE; + return 0; +} + +/* Stride that is accepted by MDP HW */ +static u32 mdp_fmt_get_stride(const struct mdp_format *fmt, + u32 bytesperline, unsigned int plane) +{ + enum mdp_color c = fmt->mdp_color; + u32 stride; + + stride = (bytesperline * MDP_COLOR_BITS_PER_PIXEL(c)) + / fmt->row_depth[0]; + if (plane == 0) + return stride; + if (plane < MDP_COLOR_GET_PLANE_COUNT(c)) { + if (MDP_COLOR_IS_BLOCK_MODE(c)) + stride = stride / 2; + return stride; + } + return 0; +} + +/* Stride that is accepted by MDP HW of format with contiguous planes */ +static u32 mdp_fmt_get_stride_contig(const struct mdp_format *fmt, + u32 pix_stride, unsigned int plane) +{ + enum mdp_color c = fmt->mdp_color; + u32 stride = pix_stride; + + if (plane == 0) + return stride; + if (plane < MDP_COLOR_GET_PLANE_COUNT(c)) { + stride = stride >> MDP_COLOR_GET_H_SUBSAMPLE(c); + if (MDP_COLOR_IS_UV_COPLANE(c) && !MDP_COLOR_IS_BLOCK_MODE(c)) + stride = stride * 2; + return stride; + } + return 0; +} + +/* Plane size that is accepted by MDP HW */ +static u32 mdp_fmt_get_plane_size(const struct mdp_format *fmt, + u32 stride, u32 height, unsigned int plane) +{ + enum mdp_color c = fmt->mdp_color; + u32 bytesperline; + + bytesperline = (stride * fmt->row_depth[0]) + / MDP_COLOR_BITS_PER_PIXEL(c); + if (plane == 0) + return bytesperline * height; + if (plane < MDP_COLOR_GET_PLANE_COUNT(c)) { + height = height >> MDP_COLOR_GET_V_SUBSAMPLE(c); + if (MDP_COLOR_IS_BLOCK_MODE(c)) + bytesperline = bytesperline * 2; + return bytesperline * height; + } + return 0; +} + +static void mdp_prepare_buffer(struct img_image_buffer *b, + struct mdp_frame *frame, struct vb2_buffer *vb) +{ + struct v4l2_pix_format_mplane *pix_mp = &frame->format.fmt.pix_mp; + unsigned int i; + + b->format.colorformat = frame->mdp_fmt->mdp_color; + b->format.ycbcr_prof = frame->ycbcr_prof; + for (i = 0; i < pix_mp->num_planes; ++i) { + u32 stride = mdp_fmt_get_stride(frame->mdp_fmt, + pix_mp->plane_fmt[i].bytesperline, i); + + b->format.plane_fmt[i].stride = stride; + /* + * TODO(crbug.com/901264): The way to pass an offset within a + * DMA-buf is not defined in V4L2 specification, so we abuse + * data_offset for now. Fix it when we have the right interface, + * including any necessary validation and potential alignment + * issues. + */ + b->format.plane_fmt[i].size = + mdp_fmt_get_plane_size(frame->mdp_fmt, stride, + pix_mp->height, i) - + vb->planes[i].data_offset; + b->iova[i] = vb2_dma_contig_plane_dma_addr(vb, i) + + vb->planes[i].data_offset; + } + for (; i < MDP_COLOR_GET_PLANE_COUNT(b->format.colorformat); ++i) { + u32 stride = mdp_fmt_get_stride_contig(frame->mdp_fmt, + b->format.plane_fmt[0].stride, i); + + b->format.plane_fmt[i].stride = stride; + b->format.plane_fmt[i].size = + mdp_fmt_get_plane_size(frame->mdp_fmt, stride, + pix_mp->height, i); + b->iova[i] = b->iova[i - 1] + b->format.plane_fmt[i - 1].size; + } + b->usage = frame->usage; +} + +void mdp_set_src_config(struct img_input *in, + struct mdp_frame *frame, struct vb2_buffer *vb) +{ + in->buffer.format.width = frame->format.fmt.pix_mp.width; + in->buffer.format.height = frame->format.fmt.pix_mp.height; + mdp_prepare_buffer(&in->buffer, frame, vb); + + /* in->flags |= ; */ /* HDR, DRE, dither */ +} + +static u32 mdp_to_fixed(u32 *r, struct v4l2_fract *f) +{ + u32 q; + + if (f->denominator == 0) { + *r = 0; + return 0; + } + + q = f->numerator / f->denominator; + *r = div_u64(((u64)f->numerator - q * f->denominator) << + IMG_SUBPIXEL_SHIFT, f->denominator); + return q; +} + +static void mdp_set_src_crop(struct img_crop *c, struct mdp_crop *crop) +{ + c->left = crop->c.left + + mdp_to_fixed(&c->left_subpix, &crop->left_subpix); + c->top = crop->c.top + + mdp_to_fixed(&c->top_subpix, &crop->top_subpix); + c->width = crop->c.width + + mdp_to_fixed(&c->width_subpix, &crop->width_subpix); + c->height = crop->c.height + + mdp_to_fixed(&c->height_subpix, &crop->height_subpix); +} + +static void mdp_set_orientation(struct img_output *out, + s32 rotation, bool hflip, bool vflip) +{ + u8 flip = 0; + + if (hflip) + flip ^= 1; + if (vflip) { + /* + * A vertical flip is equivalent to + * a 180-degree rotation with a horizontal flip + */ + rotation += 180; + flip ^= 1; + } + + out->rotation = rotation % 360; + if (flip != 0) + out->flags |= IMG_CTRL_FLAG_HFLIP; + else + out->flags &= ~IMG_CTRL_FLAG_HFLIP; +} + +void mdp_set_dst_config(struct img_output *out, + struct mdp_frame *frame, struct vb2_buffer *vb) +{ + out->buffer.format.width = frame->compose.width; + out->buffer.format.height = frame->compose.height; + mdp_prepare_buffer(&out->buffer, frame, vb); + mdp_set_src_crop(&out->crop, &frame->crop); + mdp_set_orientation(out, frame->rotation, frame->hflip, frame->vflip); + + /* out->flags |= ; */ /* sharpness, dither */ +} + +int mdp_frameparam_init(struct mdp_frameparam *param) +{ + struct mdp_frame *frame; + + if (!param) + return -EINVAL; + + INIT_LIST_HEAD(¶m->list); + mutex_init(¶m->state_lock); + param->limit = &mdp_def_limit; + param->type = MDP_STREAM_TYPE_BITBLT; + + frame = ¶m->output; + frame->format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + frame->mdp_fmt = mdp_try_fmt_mplane(&frame->format, param, 0); + frame->ycbcr_prof = + mdp_map_ycbcr_prof_mplane(&frame->format, + frame->mdp_fmt->mdp_color); + frame->usage = MDP_BUFFER_USAGE_HW_READ; + + param->num_captures = 1; + frame = ¶m->captures[0]; + frame->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + frame->mdp_fmt = mdp_try_fmt_mplane(&frame->format, param, 0); + frame->ycbcr_prof = + mdp_map_ycbcr_prof_mplane(&frame->format, + frame->mdp_fmt->mdp_color); + frame->usage = MDP_BUFFER_USAGE_MDP; + frame->crop.c.width = param->output.format.fmt.pix_mp.width; + frame->crop.c.height = param->output.format.fmt.pix_mp.height; + frame->compose.width = frame->format.fmt.pix_mp.width; + frame->compose.height = frame->format.fmt.pix_mp.height; + + return 0; +} + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h new file mode 100644 index 000000000000..b41c419afb10 --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h @@ -0,0 +1,373 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MTK_MDP3_REGS_H__ +#define __MTK_MDP3_REGS_H__ + +#include +#include +#include "mtk-img-ipi.h" + +/* + * MDP native color code + * Plane count: 1, 2, 3 + * H-subsample: 0, 1, 2 + * V-subsample: 0, 1 + * Color group: 0-RGB, 1-YUV, 2-raw + */ +#define MDP_COLOR(PACKED, LOOSE, VIDEO, PLANE, HF, VF, BITS, GROUP, SWAP, ID)\ + (((PACKED) << 27) | ((LOOSE) << 26) | ((VIDEO) << 23) |\ + ((PLANE) << 21) | ((HF) << 19) | ((VF) << 18) | ((BITS) << 8) |\ + ((GROUP) << 6) | ((SWAP) << 5) | ((ID) << 0)) + +#define MDP_COLOR_IS_10BIT_PACKED(c) ((0x08000000 & (c)) >> 27) +#define MDP_COLOR_IS_10BIT_LOOSE(c) (((0x0c000000 & (c)) >> 26) == 1) +#define MDP_COLOR_IS_10BIT_TILE(c) (((0x0c000000 & (c)) >> 26) == 3) +#define MDP_COLOR_IS_UFP(c) ((0x02000000 & (c)) >> 25) +#define MDP_COLOR_IS_INTERLACED(c) ((0x01000000 & (c)) >> 24) +#define MDP_COLOR_IS_BLOCK_MODE(c) ((0x00800000 & (c)) >> 23) +#define MDP_COLOR_GET_PLANE_COUNT(c) ((0x00600000 & (c)) >> 21) +#define MDP_COLOR_GET_H_SUBSAMPLE(c) ((0x00180000 & (c)) >> 19) +#define MDP_COLOR_GET_V_SUBSAMPLE(c) ((0x00040000 & (c)) >> 18) +#define MDP_COLOR_BITS_PER_PIXEL(c) ((0x0003ff00 & (c)) >> 8) +#define MDP_COLOR_GET_GROUP(c) ((0x000000c0 & (c)) >> 6) +#define MDP_COLOR_IS_SWAPPED(c) ((0x00000020 & (c)) >> 5) +#define MDP_COLOR_GET_UNIQUE_ID(c) ((0x0000001f & (c)) >> 0) +#define MDP_COLOR_GET_HW_FORMAT(c) ((0x0000001f & (c)) >> 0) + +#define MDP_COLOR_IS_RGB(c) (MDP_COLOR_GET_GROUP(c) == 0) +#define MDP_COLOR_IS_YUV(c) (MDP_COLOR_GET_GROUP(c) == 1) +#define MDP_COLOR_IS_UV_COPLANE(c) ((MDP_COLOR_GET_PLANE_COUNT(c) == 2) &&\ + MDP_COLOR_IS_YUV(c)) + +enum mdp_color { + MDP_COLOR_UNKNOWN = 0, + + //MDP_COLOR_FULLG8, + MDP_COLOR_FULLG8_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 8, 2, 0, 21), + MDP_COLOR_FULLG8_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 8, 2, 0, 21), + MDP_COLOR_FULLG8_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 8, 2, 0, 21), + MDP_COLOR_FULLG8_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 8, 2, 0, 21), + MDP_COLOR_FULLG8 = MDP_COLOR_FULLG8_BGGR, + + //MDP_COLOR_FULLG10, + MDP_COLOR_FULLG10_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2, 0, 21), + MDP_COLOR_FULLG10_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 10, 2, 0, 21), + MDP_COLOR_FULLG10_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 10, 2, 0, 21), + MDP_COLOR_FULLG10_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 10, 2, 0, 21), + MDP_COLOR_FULLG10 = MDP_COLOR_FULLG10_BGGR, + + //MDP_COLOR_FULLG12, + MDP_COLOR_FULLG12_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 12, 2, 0, 21), + MDP_COLOR_FULLG12_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 12, 2, 0, 21), + MDP_COLOR_FULLG12_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 12, 2, 0, 21), + MDP_COLOR_FULLG12_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 12, 2, 0, 21), + MDP_COLOR_FULLG12 = MDP_COLOR_FULLG12_BGGR, + + //MDP_COLOR_FULLG14, + MDP_COLOR_FULLG14_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 14, 2, 0, 21), + MDP_COLOR_FULLG14_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 14, 2, 0, 21), + MDP_COLOR_FULLG14_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 14, 2, 0, 21), + MDP_COLOR_FULLG14_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 14, 2, 0, 21), + MDP_COLOR_FULLG14 = MDP_COLOR_FULLG14_BGGR, + + MDP_COLOR_UFO10 = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2, 0, 24), + + //MDP_COLOR_BAYER8, + MDP_COLOR_BAYER8_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 8, 2, 0, 20), + MDP_COLOR_BAYER8_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 8, 2, 0, 20), + MDP_COLOR_BAYER8_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 8, 2, 0, 20), + MDP_COLOR_BAYER8_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 8, 2, 0, 20), + MDP_COLOR_BAYER8 = MDP_COLOR_BAYER8_BGGR, + + //MDP_COLOR_BAYER10, + MDP_COLOR_BAYER10_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2, 0, 20), + MDP_COLOR_BAYER10_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 10, 2, 0, 20), + MDP_COLOR_BAYER10_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 10, 2, 0, 20), + MDP_COLOR_BAYER10_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 10, 2, 0, 20), + MDP_COLOR_BAYER10 = MDP_COLOR_BAYER10_BGGR, + + //MDP_COLOR_BAYER12, + MDP_COLOR_BAYER12_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 12, 2, 0, 20), + MDP_COLOR_BAYER12_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 12, 2, 0, 20), + MDP_COLOR_BAYER12_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 12, 2, 0, 20), + MDP_COLOR_BAYER12_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 12, 2, 0, 20), + MDP_COLOR_BAYER12 = MDP_COLOR_BAYER12_BGGR, + + //MDP_COLOR_BAYER14, + MDP_COLOR_BAYER14_RGGB = MDP_COLOR(0, 0, 0, 1, 0, 0, 14, 2, 0, 20), + MDP_COLOR_BAYER14_GRBG = MDP_COLOR(0, 0, 0, 1, 0, 1, 14, 2, 0, 20), + MDP_COLOR_BAYER14_GBRG = MDP_COLOR(0, 0, 0, 1, 1, 0, 14, 2, 0, 20), + MDP_COLOR_BAYER14_BGGR = MDP_COLOR(0, 0, 0, 1, 1, 1, 14, 2, 0, 20), + MDP_COLOR_BAYER14 = MDP_COLOR_BAYER14_BGGR, + + MDP_COLOR_RGB48 = MDP_COLOR(0, 0, 0, 1, 0, 0, 48, 0, 0, 23), + /* For bayer+mono raw-16 */ + MDP_COLOR_RGB565_RAW = MDP_COLOR(0, 0, 0, 1, 0, 0, 16, 2, 0, 0), + + MDP_COLOR_BAYER8_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 8, 2, 0, 22), + MDP_COLOR_BAYER10_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2, 0, 22), + MDP_COLOR_BAYER12_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 12, 2, 0, 22), + MDP_COLOR_BAYER14_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 14, 2, 0, 22), + + /* Unified formats */ + MDP_COLOR_GREY = MDP_COLOR(0, 0, 0, 1, 0, 0, 8, 1, 0, 7), + + MDP_COLOR_RGB565 = MDP_COLOR(0, 0, 0, 1, 0, 0, 16, 0, 0, 0), + MDP_COLOR_BGR565 = MDP_COLOR(0, 0, 0, 1, 0, 0, 16, 0, 1, 0), + MDP_COLOR_RGB888 = MDP_COLOR(0, 0, 0, 1, 0, 0, 24, 0, 1, 1), + MDP_COLOR_BGR888 = MDP_COLOR(0, 0, 0, 1, 0, 0, 24, 0, 0, 1), + MDP_COLOR_RGBA8888 = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0, 1, 2), + MDP_COLOR_BGRA8888 = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0, 0, 2), + MDP_COLOR_ARGB8888 = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0, 1, 3), + MDP_COLOR_ABGR8888 = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0, 0, 3), + + MDP_COLOR_UYVY = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1, 0, 4), + MDP_COLOR_VYUY = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1, 1, 4), + MDP_COLOR_YUYV = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1, 0, 5), + MDP_COLOR_YVYU = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1, 1, 5), + + MDP_COLOR_I420 = MDP_COLOR(0, 0, 0, 3, 1, 1, 8, 1, 0, 8), + MDP_COLOR_YV12 = MDP_COLOR(0, 0, 0, 3, 1, 1, 8, 1, 1, 8), + MDP_COLOR_I422 = MDP_COLOR(0, 0, 0, 3, 1, 0, 8, 1, 0, 9), + MDP_COLOR_YV16 = MDP_COLOR(0, 0, 0, 3, 1, 0, 8, 1, 1, 9), + MDP_COLOR_I444 = MDP_COLOR(0, 0, 0, 3, 0, 0, 8, 1, 0, 10), + MDP_COLOR_YV24 = MDP_COLOR(0, 0, 0, 3, 0, 0, 8, 1, 1, 10), + + MDP_COLOR_NV12 = MDP_COLOR(0, 0, 0, 2, 1, 1, 8, 1, 0, 12), + MDP_COLOR_NV21 = MDP_COLOR(0, 0, 0, 2, 1, 1, 8, 1, 1, 12), + MDP_COLOR_NV16 = MDP_COLOR(0, 0, 0, 2, 1, 0, 8, 1, 0, 13), + MDP_COLOR_NV61 = MDP_COLOR(0, 0, 0, 2, 1, 0, 8, 1, 1, 13), + MDP_COLOR_NV24 = MDP_COLOR(0, 0, 0, 2, 0, 0, 8, 1, 0, 14), + MDP_COLOR_NV42 = MDP_COLOR(0, 0, 0, 2, 0, 0, 8, 1, 1, 14), + + /* Mediatek proprietary formats */ + /* UFO encoded block mode */ + MDP_COLOR_420_BLK_UFO = MDP_COLOR(0, 0, 5, 2, 1, 1, 256, 1, 0, 12), + /* Block mode */ + MDP_COLOR_420_BLK = MDP_COLOR(0, 0, 1, 2, 1, 1, 256, 1, 0, 12), + /* Block mode + field mode */ + MDP_COLOR_420_BLKI = MDP_COLOR(0, 0, 3, 2, 1, 1, 256, 1, 0, 12), + /* Block mode */ + MDP_COLOR_422_BLK = MDP_COLOR(0, 0, 1, 1, 1, 0, 512, 1, 0, 4), + + MDP_COLOR_IYU2 = MDP_COLOR(0, 0, 0, 1, 0, 0, 24, 1, 0, 25), + MDP_COLOR_YUV444 = MDP_COLOR(0, 0, 0, 1, 0, 0, 24, 1, 0, 30), + + /* Packed 10-bit formats */ + MDP_COLOR_RGBA1010102 = MDP_COLOR(1, 0, 0, 1, 0, 0, 32, 0, 1, 2), + MDP_COLOR_BGRA1010102 = MDP_COLOR(1, 0, 0, 1, 0, 0, 32, 0, 0, 2), + /* Packed 10-bit UYVY */ + MDP_COLOR_UYVY_10P = MDP_COLOR(1, 0, 0, 1, 1, 0, 20, 1, 0, 4), + /* Packed 10-bit NV21 */ + MDP_COLOR_NV21_10P = MDP_COLOR(1, 0, 0, 2, 1, 1, 10, 1, 1, 12), + /* 10-bit block mode */ + MDP_COLOR_420_BLK_10_H = MDP_COLOR(1, 0, 1, 2, 1, 1, 320, 1, 0, 12), + /* 10-bit HEVC tile mode */ + MDP_COLOR_420_BLK_10_V = MDP_COLOR(1, 1, 1, 2, 1, 1, 320, 1, 0, 12), + /* UFO encoded 10-bit block mode */ + MDP_COLOR_420_BLK_U10_H = MDP_COLOR(1, 0, 5, 2, 1, 1, 320, 1, 0, 12), + /* UFO encoded 10-bit HEVC tile mode */ + MDP_COLOR_420_BLK_U10_V = MDP_COLOR(1, 1, 5, 2, 1, 1, 320, 1, 0, 12), + + /* Loose 10-bit formats */ + MDP_COLOR_UYVY_10L = MDP_COLOR(0, 1, 0, 1, 1, 0, 20, 1, 0, 4), + MDP_COLOR_VYUY_10L = MDP_COLOR(0, 1, 0, 1, 1, 0, 20, 1, 1, 4), + MDP_COLOR_YUYV_10L = MDP_COLOR(0, 1, 0, 1, 1, 0, 20, 1, 0, 5), + MDP_COLOR_YVYU_10L = MDP_COLOR(0, 1, 0, 1, 1, 0, 20, 1, 1, 5), + MDP_COLOR_NV12_10L = MDP_COLOR(0, 1, 0, 2, 1, 1, 10, 1, 0, 12), + MDP_COLOR_NV21_10L = MDP_COLOR(0, 1, 0, 2, 1, 1, 10, 1, 1, 12), + MDP_COLOR_NV16_10L = MDP_COLOR(0, 1, 0, 2, 1, 0, 10, 1, 0, 13), + MDP_COLOR_NV61_10L = MDP_COLOR(0, 1, 0, 2, 1, 0, 10, 1, 1, 13), + MDP_COLOR_YV12_10L = MDP_COLOR(0, 1, 0, 3, 1, 1, 10, 1, 1, 8), + MDP_COLOR_I420_10L = MDP_COLOR(0, 1, 0, 3, 1, 1, 10, 1, 0, 8), +}; + +/* Minimum Y stride that is accepted by MDP HW */ +static inline u32 mdp_color_get_min_y_stride(enum mdp_color c, u32 width) +{ + return ((MDP_COLOR_BITS_PER_PIXEL(c) * width) + 4) >> 3; +} + +/* Minimum UV stride that is accepted by MDP HW */ +static inline u32 mdp_color_get_min_uv_stride(enum mdp_color c, u32 width) +{ + u32 min_stride; + + if (MDP_COLOR_GET_PLANE_COUNT(c) == 1) + return 0; + min_stride = mdp_color_get_min_y_stride(c, width) + >> MDP_COLOR_GET_H_SUBSAMPLE(c); + if (MDP_COLOR_IS_UV_COPLANE(c) && !MDP_COLOR_IS_BLOCK_MODE(c)) + min_stride = min_stride * 2; + return min_stride; +} + +/* Minimum Y plane size that is necessary in buffer */ +static inline u32 mdp_color_get_min_y_size(enum mdp_color c, + u32 width, u32 height) +{ + if (MDP_COLOR_IS_BLOCK_MODE(c)) + return ((MDP_COLOR_BITS_PER_PIXEL(c) * width) >> 8) * height; + return mdp_color_get_min_y_stride(c, width) * height; +} + +/* Minimum UV plane size that is necessary in buffer */ +static inline u32 mdp_color_get_min_uv_size(enum mdp_color c, + u32 width, u32 height) +{ + height = height >> MDP_COLOR_GET_V_SUBSAMPLE(c); + if (MDP_COLOR_IS_BLOCK_MODE(c) && (MDP_COLOR_GET_PLANE_COUNT(c) > 1)) + return ((MDP_COLOR_BITS_PER_PIXEL(c) * width) >> 8) * height; + return mdp_color_get_min_uv_stride(c, width) * height; +} + +/* Combine colorspace, xfer_func, ycbcr_encoding, and quantization */ +enum mdp_ycbcr_profile { + /* V4L2_YCBCR_ENC_601 and V4L2_QUANTIZATION_LIM_RANGE */ + MDP_YCBCR_PROFILE_BT601, + /* V4L2_YCBCR_ENC_709 and V4L2_QUANTIZATION_LIM_RANGE */ + MDP_YCBCR_PROFILE_BT709, + /* V4L2_YCBCR_ENC_601 and V4L2_QUANTIZATION_FULL_RANGE */ + MDP_YCBCR_PROFILE_JPEG, + MDP_YCBCR_PROFILE_FULL_BT601 = MDP_YCBCR_PROFILE_JPEG, + + /* Colorspaces not support for capture */ + /* V4L2_YCBCR_ENC_BT2020 and V4L2_QUANTIZATION_LIM_RANGE */ + MDP_YCBCR_PROFILE_BT2020, + /* V4L2_YCBCR_ENC_709 and V4L2_QUANTIZATION_FULL_RANGE */ + MDP_YCBCR_PROFILE_FULL_BT709, + /* V4L2_YCBCR_ENC_BT2020 and V4L2_QUANTIZATION_FULL_RANGE */ + MDP_YCBCR_PROFILE_FULL_BT2020, +}; + +#define MDP_FMT_FLAG_OUTPUT BIT(0) +#define MDP_FMT_FLAG_CAPTURE BIT(1) + +struct mdp_format { + u32 pixelformat; + u32 mdp_color; + u8 depth[VIDEO_MAX_PLANES]; + u8 row_depth[VIDEO_MAX_PLANES]; + u8 num_planes; + u8 walign; + u8 halign; + u8 salign; + u32 flags; +}; + +struct mdp_pix_limit { + u32 wmin; + u32 hmin; + u32 wmax; + u32 hmax; +}; + +struct mdp_limit { + struct mdp_pix_limit out_limit; + struct mdp_pix_limit cap_limit; + u32 h_scale_up_max; + u32 v_scale_up_max; + u32 h_scale_down_max; + u32 v_scale_down_max; +}; + +enum mdp_stream_type { + MDP_STREAM_TYPE_UNKNOWN, + MDP_STREAM_TYPE_BITBLT, + MDP_STREAM_TYPE_GPU_BITBLT, + MDP_STREAM_TYPE_DUAL_BITBLT, + MDP_STREAM_TYPE_2ND_BITBLT, + MDP_STREAM_TYPE_ISP_IC, + MDP_STREAM_TYPE_ISP_VR, + MDP_STREAM_TYPE_ISP_ZSD, + MDP_STREAM_TYPE_ISP_IP, + MDP_STREAM_TYPE_ISP_VSS, + MDP_STREAM_TYPE_ISP_ZSD_SLOW, + MDP_STREAM_TYPE_WPE, + MDP_STREAM_TYPE_WPE2, +}; + +struct mdp_crop { + struct v4l2_rect c; + struct v4l2_fract left_subpix; + struct v4l2_fract top_subpix; + struct v4l2_fract width_subpix; + struct v4l2_fract height_subpix; +}; + +struct mdp_frame { + struct v4l2_format format; + const struct mdp_format *mdp_fmt; + u32 ycbcr_prof; /* enum mdp_ycbcr_profile */ + u32 usage; /* enum mdp_buffer_usage */ + struct mdp_crop crop; + struct v4l2_rect compose; + s32 rotation; + u32 hflip:1; + u32 vflip:1; + u32 hdr:1; + u32 dre:1; + u32 sharpness:1; + u32 dither:1; +}; + +static inline bool mdp_target_is_crop(u32 target) +{ + return (target == V4L2_SEL_TGT_CROP) || + (target == V4L2_SEL_TGT_CROP_DEFAULT) || + (target == V4L2_SEL_TGT_CROP_BOUNDS); +} + +static inline bool mdp_target_is_compose(u32 target) +{ + return (target == V4L2_SEL_TGT_COMPOSE) || + (target == V4L2_SEL_TGT_COMPOSE_DEFAULT) || + (target == V4L2_SEL_TGT_COMPOSE_BOUNDS); +} + +#define MDP_MAX_CAPTURES IMG_MAX_HW_OUTPUTS + +#define MDP_VPU_INIT BIT(0) +#define MDP_M2M_CTX_ERROR BIT(1) + +struct mdp_frameparam { + struct list_head list; + /* synchronization protect for m2m context state */ + struct mutex state_lock; + u32 state; + const struct mdp_limit *limit; + u32 type; /* enum mdp_stream_type */ + u32 frame_no; + struct mdp_frame output; + struct mdp_frame captures[MDP_MAX_CAPTURES]; + u32 num_captures; + enum v4l2_colorspace colorspace; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_xfer_func xfer_func; + enum v4l2_quantization quant; +}; + +int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f); +const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f, + struct mdp_frameparam *param, + u32 ctx_id); +enum mdp_ycbcr_profile mdp_map_ycbcr_prof_mplane(struct v4l2_format *f, + u32 mdp_color); +int mdp_try_crop(struct v4l2_rect *r, const struct v4l2_selection *s, + struct mdp_frame *frame, u32 ctx_id); +int mdp_check_scaling_ratio(const struct v4l2_rect *crop, + const struct v4l2_rect *compose, s32 rotation, + const struct mdp_limit *limit); +void mdp_set_src_config(struct img_input *in, + struct mdp_frame *frame, struct vb2_buffer *vb); +void mdp_set_dst_config(struct img_output *out, + struct mdp_frame *frame, struct vb2_buffer *vb); + +int mdp_frameparam_init(struct mdp_frameparam *param); + +#endif /* __MTK_MDP3_REGS_H__ */ + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.c new file mode 100644 index 000000000000..a1b2065aabbd --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#include +#include +#include "mtk-mdp3-vpu.h" +#include "mtk-mdp3-core.h" + +#define MDP_VPU_MESSAGE_TIMEOUT 500U +#define vpu_alloc_size 0x600000 + +static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu) +{ + return container_of(vpu, struct mdp_dev, vpu); +} + +static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu) +{ + if (vpu->work && vpu->work_addr) + return 0; + + vpu->work = dma_alloc_coherent(scp_get_device(vpu->scp), vpu_alloc_size, + &vpu->work_addr, GFP_KERNEL); + + if (!vpu->work) + return -ENOMEM; + else + return 0; +} + +void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu) +{ + if (vpu->work && vpu->work_addr) + dma_free_coherent(scp_get_device(vpu->scp), vpu_alloc_size, + vpu->work, vpu->work_addr); +} + +static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len, + void *priv) +{ + struct mdp_ipi_init_msg *msg = (struct mdp_ipi_init_msg *)data; + struct mdp_vpu_dev *vpu = + (struct mdp_vpu_dev *)(unsigned long)msg->drv_data; + + if (!vpu->work_size) + vpu->work_size = msg->work_size; + + vpu->status = msg->status; + complete(&vpu->ipi_acked); +} + +static void mdp_vpu_ipi_handle_deinit_ack(void *data, unsigned int len, + void *priv) +{ + struct mdp_ipi_deinit_msg *msg = (struct mdp_ipi_deinit_msg *)data; + struct mdp_vpu_dev *vpu = + (struct mdp_vpu_dev *)(unsigned long)msg->drv_data; + + vpu->status = msg->status; + complete(&vpu->ipi_acked); +} + +static void mdp_vpu_ipi_handle_frame_ack(void *data, unsigned int len, + void *priv) +{ + struct img_sw_addr *addr = (struct img_sw_addr *)data; + struct img_ipi_frameparam *param = + (struct img_ipi_frameparam *)(unsigned long)addr->va; + struct mdp_vpu_ctx *ctx = + (struct mdp_vpu_ctx *)(unsigned long)param->drv_data; + + if (param->state) { + struct mdp_dev *mdp = vpu_to_mdp(ctx->vpu_dev); + + dev_info(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state); + } + complete(&ctx->vpu_dev->ipi_acked); +} + +int mdp_vpu_register(struct mdp_dev *mdp) +{ + int err; + struct mtk_scp *scp = mdp->scp; + struct device *dev = &mdp->pdev->dev; + + err = scp_ipi_register(scp, SCP_IPI_MDP_INIT, + mdp_vpu_ipi_handle_init_ack, NULL); + if (err) { + dev_err(dev, "scp_ipi_register failed %d\n", err); + goto err_ipi_init; + } + err = scp_ipi_register(scp, SCP_IPI_MDP_DEINIT, + mdp_vpu_ipi_handle_deinit_ack, NULL); + if (err) { + dev_err(dev, "scp_ipi_register failed %d\n", err); + goto err_ipi_deinit; + } + err = scp_ipi_register(scp, SCP_IPI_MDP_FRAME, + mdp_vpu_ipi_handle_frame_ack, NULL); + if (err) { + dev_err(dev, "scp_ipi_register failed %d\n", err); + goto err_ipi_frame; + } + return 0; + +err_ipi_frame: + scp_ipi_unregister(scp, SCP_IPI_MDP_DEINIT); +err_ipi_deinit: + scp_ipi_unregister(scp, SCP_IPI_MDP_INIT); +err_ipi_init: + + return err; +} + +void mdp_vpu_unregister(struct mdp_dev *mdp) +{ + scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_INIT); + scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_DEINIT); + scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_FRAME); +} + +static int mdp_vpu_sendmsg(struct mdp_vpu_dev *vpu, enum scp_ipi_id id, + void *buf, unsigned int len) +{ + struct mdp_dev *mdp = vpu_to_mdp(vpu); + int ret; + + if (!vpu->scp) { + dev_dbg(&mdp->pdev->dev, "vpu scp is NULL"); + return -EINVAL; + } + ret = scp_ipi_send(vpu->scp, id, buf, len, 2000); + + if (ret) { + dev_err(&mdp->pdev->dev, "scp_ipi_send failed %d\n", ret); + return -EPERM; + } + ret = wait_for_completion_timeout( + &vpu->ipi_acked, msecs_to_jiffies(MDP_VPU_MESSAGE_TIMEOUT)); + if (!ret) + ret = -ETIME; + else if (vpu->status) + ret = -EINVAL; + else + ret = 0; + return ret; +} + +int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp, + struct mutex *lock) +{ + struct mdp_ipi_init_msg msg = { + .drv_data = (unsigned long)vpu, + }; + size_t mem_size; + phys_addr_t pool; + const size_t pool_size = sizeof(struct mdp_config_pool); + struct mdp_dev *mdp = vpu_to_mdp(vpu); + int err; + + init_completion(&vpu->ipi_acked); + vpu->scp = scp; + vpu->lock = lock; + vpu->work_size = 0; + err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg)); + if (err) + goto err_work_size; + /* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */ + + mem_size = vpu_alloc_size; + if (mdp_vpu_shared_mem_alloc(vpu)) { + dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); + goto err_mem_alloc; + } + + pool = ALIGN((phys_addr_t)vpu->work + vpu->work_size, 8); + if (pool + pool_size - (phys_addr_t)vpu->work > mem_size) { + dev_err(&mdp->pdev->dev, + "VPU memory insufficient: %zx + %zx > %zx", + vpu->work_size, pool_size, mem_size); + err = -ENOMEM; + goto err_mem_size; + } + + dev_dbg(&mdp->pdev->dev, + "VPU work:%pK pa:%pad sz:%zx pool:%pa sz:%zx (mem sz:%zx)", + vpu->work, &vpu->work_addr, vpu->work_size, + &pool, pool_size, mem_size); + vpu->pool = (struct mdp_config_pool *)pool; + msg.work_addr = vpu->work_addr; + msg.work_size = vpu->work_size; + err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg)); + if (err) + goto err_work_size; + + memset(vpu->pool, 0, sizeof(*vpu->pool)); + return 0; + +err_work_size: + switch (vpu->status) { + case -MDP_IPI_EBUSY: + err = -EBUSY; + break; + case -MDP_IPI_ENOMEM: + err = -ENOSPC; /* -ENOMEM */ + break; + } + return err; +err_mem_size: +err_mem_alloc: + return err; +} + +int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu) +{ + struct mdp_ipi_deinit_msg msg = { + .drv_data = (unsigned long)vpu, + .work_addr = vpu->work_addr, + }; + + return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg)); +} + +static struct img_config *mdp_config_get(struct mdp_vpu_dev *vpu, + enum mdp_config_id id, uint32_t *addr) +{ + struct img_config *config; + + if (id < 0 || id >= MDP_CONFIG_POOL_SIZE) + return ERR_PTR(-EINVAL); + + mutex_lock(vpu->lock); + vpu->pool->cfg_count[id]++; + config = &vpu->pool->configs[id]; + *addr = vpu->work_addr + + ((unsigned long)config - (phys_addr_t)vpu->work); + mutex_unlock(vpu->lock); + + return config; +} + +static int mdp_config_put(struct mdp_vpu_dev *vpu, + enum mdp_config_id id, + const struct img_config *config) +{ + int err = 0; + + if (id < 0 || id >= MDP_CONFIG_POOL_SIZE) + return -EINVAL; + if (vpu->lock) + mutex_lock(vpu->lock); + if (!vpu->pool->cfg_count[id] || config != &vpu->pool->configs[id]) + err = -EINVAL; + else + vpu->pool->cfg_count[id]--; + if (vpu->lock) + mutex_unlock(vpu->lock); + return err; +} + +int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu, + enum mdp_config_id id) +{ + ctx->config = mdp_config_get(vpu, id, &ctx->inst_addr); + if (IS_ERR(ctx->config)) { + int err = PTR_ERR(ctx->config); + + ctx->config = NULL; + return err; + } + ctx->config_id = id; + ctx->vpu_dev = vpu; + return 0; +} + +int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx) +{ + int err = mdp_config_put(ctx->vpu_dev, ctx->config_id, ctx->config); + + ctx->config_id = 0; + ctx->config = NULL; + ctx->inst_addr = 0; + return err; +} + +int mdp_vpu_process(struct mdp_vpu_ctx *ctx, struct img_ipi_frameparam *param) +{ + struct mdp_vpu_dev *vpu = ctx->vpu_dev; + struct mdp_dev *mdp = vpu_to_mdp(vpu); + struct img_sw_addr addr; + + if (!ctx->vpu_dev->work || !ctx->vpu_dev->work_addr) { + if (mdp_vpu_shared_mem_alloc(vpu)) { + dev_err(&mdp->pdev->dev, "VPU memory alloc fail!"); + return -ENOMEM; + } + } + memset((void *)ctx->vpu_dev->work, 0, ctx->vpu_dev->work_size); + memset(ctx->config, 0, sizeof(*ctx->config)); + param->config_data.va = (unsigned long)ctx->config; + param->config_data.pa = ctx->inst_addr; + param->drv_data = (unsigned long)ctx; + + memcpy((void *)ctx->vpu_dev->work, param, sizeof(*param)); + addr.pa = ctx->vpu_dev->work_addr; + addr.va = (phys_addr_t)ctx->vpu_dev->work; + return mdp_vpu_sendmsg(ctx->vpu_dev, SCP_IPI_MDP_FRAME, + &addr, sizeof(addr)); +} + diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.h new file mode 100644 index 000000000000..4be8f861a93e --- /dev/null +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-vpu.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ping-Hsun Wu + */ + +#ifndef __MTK_MDP3_VPU_H__ +#define __MTK_MDP3_VPU_H__ + +#include +#include "mtk-img-ipi.h" + +enum mdp_ipi_result { + MDP_IPI_SUCCESS = 0, + MDP_IPI_ENOMEM = 12, + MDP_IPI_EBUSY = 16, + MDP_IPI_EINVAL = 22, + MDP_IPI_EMINST = 24, + MDP_IPI_ERANGE = 34, + MDP_IPI_NR_ERRNO, + + MDP_IPI_EOTHER = MDP_IPI_NR_ERRNO, + MDP_IPI_PATH_CANT_MERGE, + MDP_IPI_OP_FAIL, +}; + +struct mdp_ipi_init_msg { + u32 status; + u64 drv_data; + u32 work_addr; /* [in] working buffer address */ + u32 work_size; /* [in] working buffer size */ +} __attribute__ ((__packed__)); + +struct mdp_ipi_deinit_msg { + u32 status; + u64 drv_data; + u32 work_addr; +} __attribute__ ((__packed__)); + +enum mdp_config_id { + MDP_DEV_M2M = 0, + MDP_CONFIG_POOL_SIZE /* ALWAYS keep at the end */ +}; + +struct mdp_config_pool { + u64 cfg_count[MDP_CONFIG_POOL_SIZE]; + struct img_config configs[MDP_CONFIG_POOL_SIZE]; +}; + +struct mdp_vpu_dev { + /* synchronization protect for accessing vpu working buffer info */ + struct mutex *lock; + struct mtk_scp *scp; + struct completion ipi_acked; + void *work; + dma_addr_t work_addr; + size_t work_size; + struct mdp_config_pool *pool; + u32 status; +}; + +struct mdp_vpu_ctx { + struct mdp_vpu_dev *vpu_dev; + u32 config_id; + struct img_config *config; + u32 inst_addr; +}; + +void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu); +int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp, + struct mutex *lock); +int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu); +int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu, + enum mdp_config_id id); +int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx); +int mdp_vpu_process(struct mdp_vpu_ctx *vpu, struct img_ipi_frameparam *param); + +#endif /* __MTK_MDP3_VPU_H__ */ + From patchwork Wed Jun 23 07:35:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339137 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 296A7C48BE5 for ; Wed, 23 Jun 2021 07:36:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 072B961350 for ; Wed, 23 Jun 2021 07:36:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230123AbhFWHiQ (ORCPT ); Wed, 23 Jun 2021 03:38:16 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:60972 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S229978AbhFWHiQ (ORCPT ); Wed, 23 Jun 2021 03:38:16 -0400 X-UUID: 78d6776bd0214c32b4edbaf1791e1ea0-20210623 X-UUID: 78d6776bd0214c32b4edbaf1791e1ea0-20210623 Received: from mtkexhb02.mediatek.inc [(172.21.101.103)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1932890681; Wed, 23 Jun 2021 15:35:55 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs02n2.mediatek.inc (172.21.101.101) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:53 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:53 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 02/10] media: mtk-mdp3: fix redundant process done caused KE Date: Wed, 23 Jun 2021 15:35:41 +0800 Message-ID: <20210623073549.24170-2-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: daoyuan huang In mdp_m2m_worker, there is m2m process done in error handle, so add statement in mdp_cmdq_send for preventing redundant process done in cmdq_pkt_flush return fail case. Signed-off-by: daoyuan huang --- drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c index ee81a3387cf9..f8bf8fde599c 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -454,8 +454,10 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) mdp_dump_info(~0, 1); } #endif - if (param->mdp_ctx) - mdp_m2m_job_finish(param->mdp_ctx); + if (!ret) { /* error handle in mdp_m2m_worker */ + if (param->mdp_ctx) + mdp_m2m_job_finish(param->mdp_ctx); + } cmdq_pkt_destroy(cmd.pkt); for (i = 0; i < param->config->num_components; i++) mdp_comp_clock_off(&mdp->pdev->dev, path.comps[i].comp); From patchwork Wed Jun 23 07:35:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339141 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0BD6EC49EAB for ; Wed, 23 Jun 2021 07:36:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EC1936128C for ; Wed, 23 Jun 2021 07:36:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230235AbhFWHiW (ORCPT ); Wed, 23 Jun 2021 03:38:22 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32792 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230189AbhFWHiU (ORCPT ); Wed, 23 Jun 2021 03:38:20 -0400 X-UUID: 7ecef9c80dd74b319bfc22e54ffb7d48-20210623 X-UUID: 7ecef9c80dd74b319bfc22e54ffb7d48-20210623 Received: from mtkcas11.mediatek.inc [(172.21.101.40)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 655790490; Wed, 23 Jun 2021 15:35:58 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n1.mediatek.inc (172.21.101.68) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:56 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:56 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 03/10] media: mtk-mdp3: revise suspend strategy Date: Wed, 23 Jun 2021 15:35:42 +0800 Message-ID: <20210623073549.24170-3-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: daoyuan huang 1.The wait queue check for incomplete running task should be put in mdp_suspend instead of mdp_pm_suspend; Due to mdp_suspend could be called while task is running; Add error return value in suspend fail situation. 2.modify dma modules' power control from larb device to modules' device self; For support real mdp_pm_suspend callback. Signed-off-by: daoyuan huang --- .../media/platform/mtk-mdp3/mtk-mdp3-comp.c | 36 ++++++++----------- .../media/platform/mtk-mdp3/mtk-mdp3-comp.h | 2 +- .../media/platform/mtk-mdp3/mtk-mdp3-core.c | 34 +++++------------- 3 files changed, 23 insertions(+), 49 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c index 3033cd32340c..23dd413f3423 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c @@ -1039,8 +1039,8 @@ void mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp) { int i, err; - if (comp->larb_dev) { - err = pm_runtime_get_sync(comp->larb_dev); + if (comp->comp_dev) { + err = pm_runtime_get_sync(comp->comp_dev); if (err < 0) dev_err(dev, "Failed to get larb, err %d. type:%d id:%d\n", @@ -1068,8 +1068,8 @@ void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp) clk_disable_unprepare(comp->clks[i]); } - if (comp->larb_dev) - pm_runtime_put(comp->larb_dev); + if (comp->comp_dev) + pm_runtime_put(comp->comp_dev); } static int mdp_get_subsys_id(struct device *dev, struct device_node *node, @@ -1153,8 +1153,7 @@ static int mdp_comp_init(struct device *dev, struct mdp_dev *mdp, struct device_node *node, struct mdp_comp *comp, enum mdp_comp_id id) { - struct device_node *larb_node; - struct platform_device *larb_pdev; + struct platform_device *pdev; int i; if (id < 0 || id >= MDP_MAX_COMP_COUNT) { @@ -1176,29 +1175,22 @@ static int mdp_comp_init(struct device *dev, struct mdp_dev *mdp, mdp_get_subsys_id(dev, node, comp); - /* Only DMA capable components need the LARB property */ - comp->larb_dev = NULL; + /* Only DMA capable components need the pm control */ + comp->comp_dev = NULL; if (comp->type != MDP_COMP_TYPE_RDMA && comp->type != MDP_COMP_TYPE_WROT && comp->type != MDP_COMP_TYPE_WDMA) return 0; - larb_node = of_parse_phandle(node, "mediatek,larb", 0); - if (!larb_node) { - dev_err(dev, "Missing mediatek,larb phandle in %pOF node\n", - node); - return -EINVAL; - } - - larb_pdev = of_find_device_by_node(larb_node); - if (!larb_pdev) { - dev_warn(dev, "Waiting for larb device %pOF\n", larb_node); - of_node_put(larb_node); - return -EPROBE_DEFER; + pdev = of_find_device_by_node(node); + if (!pdev) { + dev_warn(dev, "can't find platform device of node:%s\n", + node->name); + return -ENODEV; } - of_node_put(larb_node); - comp->larb_dev = &larb_pdev->dev; + comp->comp_dev = &pdev->dev; + pm_runtime_enable(comp->comp_dev); return 0; } diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h index 77d2c3e989c4..27d58dc51dce 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h @@ -113,7 +113,7 @@ struct mdp_comp { phys_addr_t reg_base; u8 subsys_id; struct clk *clks[2]; - struct device *larb_dev; + struct device *comp_dev; enum mdp_comp_type type; enum mdp_comp_id id; u32 alias_id; diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c index 4a59dec8cfd9..eaf5b07e720f 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c @@ -152,7 +152,6 @@ static int mdp_probe(struct platform_device *pdev) #endif vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); - pm_runtime_enable(dev); ret = v4l2_device_register(dev, &mdp->v4l2_dev); if (ret) { @@ -212,7 +211,7 @@ static int mdp_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused mdp_pm_suspend(struct device *dev) +static int __maybe_unused mdp_suspend(struct device *dev) { struct mdp_dev *mdp = dev_get_drvdata(dev); int ret; @@ -222,19 +221,19 @@ static int __maybe_unused mdp_pm_suspend(struct device *dev) if (atomic_read(&mdp->job_count)) { ret = wait_event_timeout(mdp->callback_wq, !atomic_read(&mdp->job_count), - HZ); - if (ret == 0) + 2 * HZ); + if (ret == 0) { dev_err(dev, - "%s:flushed cmdq task incomplete\n", - __func__); - else//need to remove - pr_err("%s:ret=%d\n", __func__, ret); + "%s:flushed cmdq task incomplete, count=%d\n", + __func__, atomic_read(&mdp->job_count)); + return -EBUSY; + } } return 0; } -static int __maybe_unused mdp_pm_resume(struct device *dev) +static int __maybe_unused mdp_resume(struct device *dev) { struct mdp_dev *mdp = dev_get_drvdata(dev); @@ -243,25 +242,8 @@ static int __maybe_unused mdp_pm_resume(struct device *dev) return 0; } -static int __maybe_unused mdp_suspend(struct device *dev) -{ - if (pm_runtime_suspended(dev)) - return 0; - - return mdp_pm_suspend(dev); -} - -static int __maybe_unused mdp_resume(struct device *dev) -{ - if (pm_runtime_suspended(dev)) - return 0; - - return mdp_pm_resume(dev); -} - static const struct dev_pm_ops mdp_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mdp_suspend, mdp_resume) - SET_RUNTIME_PM_OPS(mdp_pm_suspend, mdp_pm_resume, NULL) }; static struct platform_driver mdp_driver = { From patchwork Wed Jun 23 07:35:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339153 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BADCC49EA5 for ; Wed, 23 Jun 2021 07:36:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7D7BC61351 for ; Wed, 23 Jun 2021 07:36:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230357AbhFWHic (ORCPT ); Wed, 23 Jun 2021 03:38:32 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32792 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230222AbhFWHiW (ORCPT ); Wed, 23 Jun 2021 03:38:22 -0400 X-UUID: 4783db3ba090400eb04bc6ddc0d93cf7-20210623 X-UUID: 4783db3ba090400eb04bc6ddc0d93cf7-20210623 Received: from mtkexhb01.mediatek.inc [(172.21.101.102)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 314512722; Wed, 23 Jun 2021 15:35:58 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n2.mediatek.inc (172.21.101.79) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:56 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:56 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 04/10] media: mtk-mdp3: add error handling in error return Date: Wed, 23 Jun 2021 15:35:43 +0800 Message-ID: <20210623073549.24170-4-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: daoyuan huang add error handling in missed places. Signed-off-by: daoyuan huang --- drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 14 +++++++++++++- drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c | 16 ++++++++++++++++ drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h | 2 ++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c index f8bf8fde599c..42a51061677a 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -398,7 +398,17 @@ static void mdp_handle_cmdq_callback(struct cmdq_cb_data data) cmdq_pkt_destroy(cb_param->pkt); INIT_WORK(&cb_param->auto_release_work, mdp_auto_release_work); - queue_work(mdp->clock_wq, &cb_param->auto_release_work); + if (!queue_work(mdp->clock_wq, &cb_param->auto_release_work)) { + mdp_err("%s:queue_work fail!\n", __func__); + mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, + cb_param->num_comps); + + kfree(cb_param->comps); + kfree(cb_param); + + atomic_dec(&mdp->job_count); + wake_up(&mdp->callback_wq); + } } int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) @@ -495,6 +505,8 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) (void *)cb_param); if (ret) { mdp_err("%s:cmdq_pkt_flush_async fail!\n", __func__); + mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, + cb_param->num_comps); kfree(cb_param); kfree(comps); } diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c index 23dd413f3423..157ef9408ed3 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c @@ -1072,6 +1072,22 @@ void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp) pm_runtime_put(comp->comp_dev); } +void mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num) +{ + int i; + + for (i = 0; i < num; i++) + mdp_comp_clock_on(dev, &comps[i]); +} + +void mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num) +{ + int i; + + for (i = 0; i < num; i++) + mdp_comp_clock_off(dev, &comps[i]); +} + static int mdp_get_subsys_id(struct device *dev, struct device_node *node, struct mdp_comp *comp) { diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h index 27d58dc51dce..f201bced3c06 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h @@ -147,6 +147,8 @@ int mdp_component_init(struct mdp_dev *mdp); void mdp_component_deinit(struct mdp_dev *mdp); void mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp); void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp); +void mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num); +void mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num); int mdp_comp_ctx_init(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx, const struct img_compparam *param, const struct img_ipi_frameparam *frame); From patchwork Wed Jun 23 07:35:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339143 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9286AC49EA5 for ; Wed, 23 Jun 2021 07:36:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7D05561361 for ; Wed, 23 Jun 2021 07:36:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230001AbhFWHiU (ORCPT ); Wed, 23 Jun 2021 03:38:20 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32792 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230163AbhFWHiT (ORCPT ); Wed, 23 Jun 2021 03:38:19 -0400 X-UUID: 0d48c2887b92484d8d70713bed3920d9-20210623 X-UUID: 0d48c2887b92484d8d70713bed3920d9-20210623 Received: from mtkcas11.mediatek.inc [(172.21.101.40)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1373349356; Wed, 23 Jun 2021 15:35:58 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n1.mediatek.inc (172.21.101.68) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:56 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:56 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 05/10] media: mtk-mdp3: remove unnecessary Null check Date: Wed, 23 Jun 2021 15:35:44 +0800 Message-ID: <20210623073549.24170-5-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: daoyuan huang Remove logically unnecessary NULL check in call back function. Due to no NULL callback param should occur in normal case; and if we use NULL check to jump over this clock off step, the clock ref. count may go asymmetric. Signed-off-by: daoyuan huang --- drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c index 42a51061677a..df956ca3685c 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -349,13 +349,8 @@ static void mdp_auto_release_work(struct work_struct *work) auto_release_work); mdp = cb_param->mdp; - if (cb_param->comps && cb_param->num_comps) { - int i; - - for (i = 0; i < cb_param->num_comps; i++) - mdp_comp_clock_off(&mdp->pdev->dev, - &cb_param->comps[i]); - } + mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, + cb_param->num_comps); kfree(cb_param->comps); kfree(cb_param); From patchwork Wed Jun 23 07:35:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339151 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57968C49EA4 for ; Wed, 23 Jun 2021 07:36:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3D0FC61351 for ; Wed, 23 Jun 2021 07:36:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230397AbhFWHid (ORCPT ); Wed, 23 Jun 2021 03:38:33 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32841 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230224AbhFWHiW (ORCPT ); Wed, 23 Jun 2021 03:38:22 -0400 X-UUID: b8ebb6a309b0468da29a2edfaf44f64a-20210623 X-UUID: b8ebb6a309b0468da29a2edfaf44f64a-20210623 Received: from mtkexhb01.mediatek.inc [(172.21.101.102)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1649141153; Wed, 23 Jun 2021 15:35:58 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n2.mediatek.inc (172.21.101.79) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:57 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:57 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 06/10] media: mtk-mdp3: move clock on to precise place Date: Wed, 23 Jun 2021 15:35:45 +0800 Message-ID: <20210623073549.24170-6-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: daoyuan huang Move clock on to the previous line of cmdq_pkt_flush. Due to there're two ways(sync/async) to submit CMDQ task, and for async case we need to prepare callback param struct along with error checks and error handlings before submit, if we move clock on after these error check steps, we can save some clock off code in error handling. Signed-off-by: daoyuan huang --- drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c index df956ca3685c..a1bdf92d45f7 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -445,11 +445,9 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) return ret; } - // TODO: engine conflict dispatch - for (i = 0; i < param->config->num_components; i++) - mdp_comp_clock_on(&mdp->pdev->dev, path.comps[i].comp); - if (param->wait) { + for (i = 0; i < param->config->num_components; i++) + mdp_comp_clock_on(&mdp->pdev->dev, path.comps[i].comp); ret = cmdq_pkt_flush(cmd.pkt); #ifdef MDP_DEBUG if (ret) { @@ -495,6 +493,9 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) cb_param->num_comps = param->config->num_components; cb_param->mdp_ctx = param->mdp_ctx; + mdp_comp_clocks_on(&mdp->pdev->dev, cb_param->comps, + cb_param->num_comps); + ret = cmdq_pkt_flush_async(cmd.pkt, mdp_handle_cmdq_callback, (void *)cb_param); From patchwork Wed Jun 23 07:35:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339145 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DF97C49EB7 for ; Wed, 23 Jun 2021 07:36:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6BD1E6128C for ; Wed, 23 Jun 2021 07:36:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230267AbhFWHiX (ORCPT ); Wed, 23 Jun 2021 03:38:23 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32810 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230161AbhFWHiU (ORCPT ); Wed, 23 Jun 2021 03:38:20 -0400 X-UUID: 5cbdb2f31c824079b2ddb69ff0dc0608-20210623 X-UUID: 5cbdb2f31c824079b2ddb69ff0dc0608-20210623 Received: from mtkcas11.mediatek.inc [(172.21.101.40)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 500013350; Wed, 23 Jun 2021 15:35:58 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n1.mediatek.inc (172.21.101.68) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:57 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:57 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 07/10] media: mtk-mdp3: Fix unpaired settings Date: Wed, 23 Jun 2021 15:35:46 +0800 Message-ID: <20210623073549.24170-7-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Fix unpaired settings about: 1. clk on/off. 2. CMDQ packet kzalloc/kfree. 3. MDP job_count increase/decrease. Also revise the redundant log. Signed-off-by: Moudy Ho --- .../media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 97 ++++++++++++------- .../media/platform/mtk-mdp3/mtk-mdp3-core.h | 4 +- .../media/platform/mtk-mdp3/mtk-mdp3-m2m.c | 2 +- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c index a1bdf92d45f7..eac10944283a 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -5,6 +5,7 @@ */ #include +#include #include "mtk-mdp3-cmdq.h" #include "mtk-mdp3-comp.h" #include "mtk-mdp3-core.h" @@ -230,6 +231,25 @@ static int mdp_path_subfrm_run(const struct mdp_path_subfrm *subfrm, return 0; } +static int mdp_path_ctx_init(struct mdp_dev *mdp, struct mdp_path *path) +{ + const struct img_config *config = path->config; + int index, ret; + + if (config->num_components < 1) + return -EINVAL; + + for (index = 0; index < config->num_components; index++) { + ret = mdp_comp_ctx_init(mdp, &path->comps[index], + &config->components[index], + path->param); + if (ret) + return ret; + } + + return 0; +} + static int mdp_path_config_subfrm(struct mdp_cmd *cmd, struct mdp_path *path, u32 count) { @@ -297,14 +317,6 @@ static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmd *cmd, struct mdp_comp_ctx *ctx; int index, count, ret; - for (index = 0; index < config->num_components; index++) { - ret = mdp_comp_ctx_init(mdp, &path->comps[index], - &config->components[index], - path->param); - if (ret) - return ret; - } - /* Config path frame */ /* Reset components */ for (index = 0; index < config->num_components; index++) { @@ -410,6 +422,8 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) { struct mdp_cmd cmd; struct mdp_path path; + struct mdp_cmdq_cb_param *cb_param = NULL; + struct mdp_comp *comps = NULL; int i, ret; if (atomic_read(&mdp->suspended)) @@ -438,16 +452,23 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) path.composes[i] = param->composes[i] ? param->composes[i] : &path.bounds[i]; } + + ret = mdp_path_ctx_init(mdp, &path); + if (ret) { + pr_info("%s mdp_path_ctx_init error\n", __func__); + goto err_destory_pkt; + } + + for (i = 0; i < param->config->num_components; i++) + mdp_comp_clock_on(&mdp->pdev->dev, path.comps[i].comp); + ret = mdp_path_config(mdp, &cmd, &path); if (ret) { - atomic_dec(&mdp->job_count); - wake_up(&mdp->callback_wq); - return ret; + pr_info("%s mdp_path_config error\n", __func__); + goto err_destory_pkt; } if (param->wait) { - for (i = 0; i < param->config->num_components; i++) - mdp_comp_clock_on(&mdp->pdev->dev, path.comps[i].comp); ret = cmdq_pkt_flush(cmd.pkt); #ifdef MDP_DEBUG if (ret) { @@ -461,25 +482,20 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) if (param->mdp_ctx) mdp_m2m_job_finish(param->mdp_ctx); } - cmdq_pkt_destroy(cmd.pkt); - for (i = 0; i < param->config->num_components; i++) - mdp_comp_clock_off(&mdp->pdev->dev, path.comps[i].comp); - - atomic_dec(&mdp->job_count); - wake_up(&mdp->callback_wq); + goto err_clock_off; } else { - struct mdp_cmdq_cb_param *cb_param; - struct mdp_comp *comps; - cb_param = kzalloc(sizeof(*cb_param), GFP_KERNEL); - if (!cb_param) - return -ENOMEM; + if (!cb_param) { + ret = -ENOMEM; + goto err_destory_pkt; + } + comps = kcalloc(param->config->num_components, sizeof(*comps), GFP_KERNEL); if (!comps) { - kfree(cb_param); mdp_err("%s:comps alloc fail!\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto err_destory_pkt; } for (i = 0; i < param->config->num_components; i++) @@ -493,20 +509,35 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) cb_param->num_comps = param->config->num_components; cb_param->mdp_ctx = param->mdp_ctx; - mdp_comp_clocks_on(&mdp->pdev->dev, cb_param->comps, - cb_param->num_comps); - + cmdq_pkt_finalize(cmd.pkt); ret = cmdq_pkt_flush_async(cmd.pkt, mdp_handle_cmdq_callback, (void *)cb_param); if (ret) { mdp_err("%s:cmdq_pkt_flush_async fail!\n", __func__); - mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, - cb_param->num_comps); - kfree(cb_param); - kfree(comps); + goto err_clock_off; } } + return 0; + +err_clock_off: + if (param->wait) { + for (i = 0; i < param->config->num_components; i++) + mdp_comp_clock_off(&mdp->pdev->dev, path.comps[i].comp); + } else { + mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, + cb_param->num_comps); + } +err_destory_pkt: + cmdq_pkt_destroy(cmd.pkt); + atomic_dec(&mdp->job_count); + if (param->wait) + wake_up(&mdp->callback_wq); + if (comps) + kfree(comps); + if (cb_param) + kfree(cb_param); + return ret; } diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h index 98cf54b1d92b..19f46da487aa 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h @@ -64,12 +64,12 @@ extern int mtk_mdp_debug; #define mdp_dbg(level, fmt, ...)\ do {\ if (mtk_mdp_debug >= (level))\ - pr_info("[MTK-MDP3] %d %s:%d: " fmt "\n",\ + pr_info("[MTK-MDP3] %d %s:%d: " fmt,\ level, __func__, __LINE__, ##__VA_ARGS__);\ } while (0) #define mdp_err(fmt, ...)\ - pr_err("[MTK-MDP3][ERR] %s:%d: " fmt "\n", __func__, __LINE__,\ + pr_err("[MTK-MDP3][ERR] %s:%d: " fmt, __func__, __LINE__,\ ##__VA_ARGS__) #else diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c index 1ae499f6c84b..ff80f01be82f 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c @@ -133,7 +133,7 @@ static void mdp_m2m_worker(struct work_struct *work) task.config = ctx->vpu.config; task.param = ¶m; task.composes[0] = &frame->compose; - task.wait = 1; + task.wait = 0; task.cmdq_cb = NULL; task.cb_data = NULL; task.mdp_ctx = ctx; From patchwork Wed Jun 23 07:35:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339155 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21D0BC49EAF for ; Wed, 23 Jun 2021 07:36:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 02FCE6128D for ; Wed, 23 Jun 2021 07:36:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230429AbhFWHie (ORCPT ); Wed, 23 Jun 2021 03:38:34 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32810 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230202AbhFWHiW (ORCPT ); Wed, 23 Jun 2021 03:38:22 -0400 X-UUID: e215b238cadd4e8598a42ad26459be46-20210623 X-UUID: e215b238cadd4e8598a42ad26459be46-20210623 Received: from mtkexhb01.mediatek.inc [(172.21.101.102)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1782219528; Wed, 23 Jun 2021 15:35:58 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs01n2.mediatek.inc (172.21.101.79) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:57 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:57 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 08/10] media: mtk-mdp3: remove illegal device node usage Date: Wed, 23 Jun 2021 15:35:47 +0800 Message-ID: <20210623073549.24170-8-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org This patch is used for review before send upstream patch. From Rob Herring's review comment: device node can't use same register address as other nodes'. Remove illegal device nodes in device tree. MDP's sub component init need to do corresponding modification. Signed-off-by: Moudy Ho --- .../media/platform/mtk-mdp3/mtk-mdp3-comp.c | 224 +++++++++++++----- .../media/platform/mtk-mdp3/mtk-mdp3-comp.h | 2 +- 2 files changed, 163 insertions(+), 63 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c index 157ef9408ed3..e89fd02bb556 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.c @@ -1016,23 +1016,15 @@ static const struct of_device_id mdp_comp_dt_ids[] = { {} }; -static int mdp_comp_get_id(struct device *dev, struct device_node *node, - enum mdp_comp_type type) +static int mdp_comp_get_id(enum mdp_comp_type type, u32 alias_id) { - u32 alias_id; - int i, ret; - - ret = of_property_read_u32(node, "mediatek,mdp-id", &alias_id); - if (ret) - return ret; + int i; for (i = 0; i < ARRAY_SIZE(mdp_comp_matches); i++) if (mdp_comp_matches[i].type == type && mdp_comp_matches[i].alias_id == alias_id) return i; - - dev_err(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id); - return -EINVAL; + return -ENODEV; } void mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp) @@ -1143,33 +1135,10 @@ static void __mdp_comp_init(struct mdp_dev *mdp, struct device_node *node, comp->reg_base = base; } -static int mdp_mm_init(struct mdp_dev *mdp, - struct mdp_comp *comp, const char *ref_name) +static int mdp_comp_init(struct mdp_dev *mdp, struct device_node *node, + struct mdp_comp *comp, enum mdp_comp_id id) { - struct device_node *node; struct device *dev = &mdp->pdev->dev; - - node = of_parse_phandle(dev->of_node, ref_name, 0); - if (!node) { - dev_err(dev, "Failed to parse dt %s\n", ref_name); - return -EINVAL; - } - - __mdp_comp_init(mdp, node, comp); - mdp_get_subsys_id(dev, node, comp); - of_node_put(node); - if (!comp->reg_base) { - dev_err(dev, "Failed to init %s base\n", ref_name); - return -EINVAL; - } - return 0; -} - -static int mdp_comp_init(struct device *dev, struct mdp_dev *mdp, - struct device_node *node, struct mdp_comp *comp, - enum mdp_comp_id id) -{ - struct platform_device *pdev; int i; if (id < 0 || id >= MDP_MAX_COMP_COUNT) { @@ -1191,32 +1160,140 @@ static int mdp_comp_init(struct device *dev, struct mdp_dev *mdp, mdp_get_subsys_id(dev, node, comp); - /* Only DMA capable components need the pm control */ - comp->comp_dev = NULL; - if (comp->type != MDP_COMP_TYPE_RDMA && - comp->type != MDP_COMP_TYPE_WROT && - comp->type != MDP_COMP_TYPE_WDMA) - return 0; + return 0; +} - pdev = of_find_device_by_node(node); - if (!pdev) { - dev_warn(dev, "can't find platform device of node:%s\n", - node->name); - return -ENODEV; +static struct mdp_comp *mdp_comp_create(struct mdp_dev *mdp, + struct device_node *node, + enum mdp_comp_id id) +{ + struct device *dev = &mdp->pdev->dev; + struct mdp_comp *comp; + int ret; + + if (mdp->comp[id]) + return ERR_PTR(-EEXIST); + + comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL); + if (!comp) + return ERR_PTR(-ENOMEM); + + ret = mdp_comp_init(mdp, node, comp, id); + if (ret) { + kfree(comp); + return ERR_PTR(ret); } + mdp->comp[id] = comp; + + dev_info(dev, "%s type:%d alias:%d id:%d base:%#x regs:%p\n", + dev->of_node->name, comp->type, comp->alias_id, id, + (u32)comp->reg_base, comp->regs); + return comp; +} - comp->comp_dev = &pdev->dev; - pm_runtime_enable(comp->comp_dev); +static int mdp_sub_comps_create(struct mdp_dev *mdp, struct device_node *node) +{ + struct device *dev = &mdp->pdev->dev; + struct property *prop; + const char *name; + int index = 0; + + of_property_for_each_string(node, "mdp-comps", prop, name) { + const struct of_device_id *matches = mdp_comp_dt_ids; + enum mdp_comp_type type = MDP_COMP_NONE; + u32 alias_id; + int id, ret; + struct mdp_comp *comp; + for (; matches->compatible[0]; matches++) { + if (of_compat_cmp(name, matches->compatible, + strlen(matches->compatible)) == 0) { + type = (enum mdp_comp_type)matches->data; + break; + } + } + + ret = of_property_read_u32_index(node, "mdp-comp-ids", + index, &alias_id); + if (ret) { + dev_warn(dev, "Skipping unknown component %s\n", name); + return ret; + } + + id = mdp_comp_get_id(type, alias_id); + if (id < 0) { + dev_err(dev, "Failed to get component id: " + "%s type %d, alias %d\n", name, type, alias_id); + return -ENODEV; + } + + comp = mdp_comp_create(mdp, node, id); + if (IS_ERR(comp)) + return PTR_ERR(comp); + + index++; + } return 0; } static void mdp_comp_deinit(struct mdp_comp *comp) { - iounmap(comp->regs); + if (!comp) + return; + + if (comp->regs) + iounmap(comp->regs); /* of_node_put(comp->dev_node); */ } +static int mdp_imgi_init(struct mdp_dev *mdp, const char *ref_name) +{ + struct device_node *node; + struct device *dev = &mdp->pdev->dev; + int ret; + + node = of_parse_phandle(dev->of_node, ref_name, 0); + if (!node) { + dev_err(dev, "Failed to parse dt %s\n", ref_name); + return -EINVAL; + } + + ret = mdp_sub_comps_create(mdp, node); + of_node_put(node); + if (ret) + return ret; + + return 0; +} + +static int mdp_mm_init(struct mdp_dev *mdp, struct mdp_comp *comp, + const char *ref_name) +{ + struct device_node *node; + struct device *dev = &mdp->pdev->dev; + int ret; + + node = of_parse_phandle(dev->of_node, ref_name, 0); + if (!node) { + dev_err(dev, "Failed to parse dt %s\n", ref_name); + return -EINVAL; + } + + __mdp_comp_init(mdp, node, comp); + mdp_get_subsys_id(dev, node, comp); + if (!comp->reg_base) { + dev_err(dev, "Failed to init %s base\n", ref_name); + of_node_put(node); + return -EINVAL; + } + + ret = mdp_sub_comps_create(mdp, node); + of_node_put(node); + if (ret) + return ret; + return 0; +} + void mdp_component_deinit(struct mdp_dev *mdp) { int i; @@ -1235,6 +1312,8 @@ int mdp_component_init(struct mdp_dev *mdp) { struct device *dev = &mdp->pdev->dev; struct device_node *node, *parent; + struct platform_device *pdev; + u32 alias_id; int i, ret; for (i = RDMA0_SOF; i < MDP_MAX_EVENT_COUNT; i++) { @@ -1260,7 +1339,11 @@ int mdp_component_init(struct mdp_dev *mdp) ret = mdp_mm_init(mdp, &mdp->mm_mutex, "mediatek,mm-mutex"); if (ret) - goto err_init_mm; + goto err_init_comps; + + ret = mdp_imgi_init(mdp, "mediatek,imgsys"); + if (ret) + goto err_init_comps; parent = dev->of_node->parent; /* Iterate over sibling MDP function blocks */ @@ -1281,27 +1364,44 @@ int mdp_component_init(struct mdp_dev *mdp) } type = (enum mdp_comp_type)of_id->data; - id = mdp_comp_get_id(dev, node, type); - if (id < 0) { + ret = of_property_read_u32(node, "mediatek,mdp-id", &alias_id); + if (ret) { dev_warn(dev, "Skipping unknown component %pOF\n", node); continue; } + id = mdp_comp_get_id(type, alias_id); + if (id < 0) { + dev_err(dev, + "Fail to get component id: type %d alias %d\n", + type, alias_id); + continue; + } - comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL); - if (!comp) { - ret = -ENOMEM; + comp = mdp_comp_create(mdp, node, id); + if (IS_ERR(comp)) goto err_init_comps; - } - mdp->comp[id] = comp; - ret = mdp_comp_init(dev, mdp, node, comp, id); + ret = mdp_sub_comps_create(mdp, node); if (ret) goto err_init_comps; - dev_info(dev, "%s type:%d alias:%d id:%d base:%#x regs:%p\n", - of_id->compatible, type, comp->alias_id, id, - (u32)comp->reg_base, comp->regs); + /* Only DMA capable components need the pm control */ + comp->comp_dev = NULL; + if (comp->type != MDP_COMP_TYPE_RDMA && + comp->type != MDP_COMP_TYPE_WROT && + comp->type != MDP_COMP_TYPE_WDMA) + continue; + + pdev = of_find_device_by_node(node); + if (!pdev) { + dev_warn(dev, "can't find platform device of node:%s\n", + node->name); + return -ENODEV; + } + + comp->comp_dev = &pdev->dev; + pm_runtime_enable(comp->comp_dev); } return 0; diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h index f201bced3c06..f5d514a51236 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-comp.h @@ -112,7 +112,7 @@ struct mdp_comp { void __iomem *regs; phys_addr_t reg_base; u8 subsys_id; - struct clk *clks[2]; + struct clk *clks[4]; struct device *comp_dev; enum mdp_comp_type type; enum mdp_comp_id id; From patchwork Wed Jun 23 07:35:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339149 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFD2BC49EAB for ; Wed, 23 Jun 2021 07:36:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A707D61360 for ; Wed, 23 Jun 2021 07:36:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230347AbhFWHib (ORCPT ); Wed, 23 Jun 2021 03:38:31 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32824 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S229906AbhFWHiV (ORCPT ); Wed, 23 Jun 2021 03:38:21 -0400 X-UUID: d4ce259365fc4cbea0667d582b7737a2-20210623 X-UUID: d4ce259365fc4cbea0667d582b7737a2-20210623 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1741434742; Wed, 23 Jun 2021 15:35:59 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs02n1.mediatek.inc (172.21.101.77) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:57 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:57 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 09/10] media: mtk-mdp3: revise error handling about get/probe MDP3 Date: Wed, 23 Jun 2021 15:35:48 +0800 Message-ID: <20210623073549.24170-9-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org This patch is used for review before send upstream patch. From Alexandre Courbot's review comment: Independent from the main patch. Revise error handling about get/probe MDP3 driver to make it stable. Signed-off-by: Moudy Ho --- drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c index eaf5b07e720f..207b55ace97b 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c @@ -40,9 +40,9 @@ struct platform_device *mdp_get_plat_device(struct platform_device *pdev) } mdp_pdev = of_find_device_by_node(mdp_node); + of_node_put(mdp_node); if (WARN_ON(!mdp_pdev)) { dev_err(dev, "mdp pdev failed\n"); - of_node_put(mdp_node); return NULL; } @@ -113,7 +113,7 @@ static int mdp_probe(struct platform_device *pdev) if (!mdp->job_wq) { dev_err(dev, "Unable to create job workqueue\n"); ret = -ENOMEM; - goto err_destroy_job_wq; + goto err_deinit_comp; } mdp->clock_wq = alloc_workqueue(MDP_MODULE_NAME "-clock", WQ_FREEZABLE, @@ -121,7 +121,7 @@ static int mdp_probe(struct platform_device *pdev) if (!mdp->clock_wq) { dev_err(dev, "Unable to create clock workqueue\n"); ret = -ENOMEM; - goto err_destroy_clock_wq; + goto err_destroy_job_wq; } mdp->scp = scp_get(pdev); @@ -179,6 +179,8 @@ static int mdp_probe(struct platform_device *pdev) destroy_workqueue(mdp->clock_wq); err_destroy_job_wq: destroy_workqueue(mdp->job_wq); +err_deinit_comp: + mdp_component_deinit(mdp); err_return: dev_dbg(dev, "Errno %d\n", ret); return ret; From patchwork Wed Jun 23 07:35:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moudy Ho X-Patchwork-Id: 12339147 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A9A4C49EBD for ; Wed, 23 Jun 2021 07:36:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 215896128A for ; Wed, 23 Jun 2021 07:36:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230308AbhFWHia (ORCPT ); Wed, 23 Jun 2021 03:38:30 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:47029 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230185AbhFWHiV (ORCPT ); Wed, 23 Jun 2021 03:38:21 -0400 X-UUID: 35c07978e10a4887b812a0db3c03beee-20210623 X-UUID: 35c07978e10a4887b812a0db3c03beee-20210623 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 658592435; Wed, 23 Jun 2021 15:35:59 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs02n2.mediatek.inc (172.21.101.101) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 23 Jun 2021 15:35:57 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 23 Jun 2021 15:35:57 +0800 From: Moudy Ho To: Mauro Carvalho Chehab , Rob Herring , Matthias Brugger , Hans Verkuil , Jernej Skrabec CC: Maoguang Meng , Krzysztof Kozlowski , daoyuan huang , Ping-Hsun Wu , Geert Uytterhoeven , Rob Landley , Laurent Pinchart , , , , , , , , , , , , , , , , Subject: [RFC PATCH V0 10/10] media: mtk-mdp3: Adjust related settings for 5.13-rc1 Date: Wed, 23 Jun 2021 15:35:49 +0800 Message-ID: <20210623073549.24170-10-moudy.ho@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20210623073549.24170-1-moudy.ho@mediatek.com> References: <20210623073549.24170-1-moudy.ho@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: mtk18742 1. remove cmdq_pkt_flush usage. 2. remove VFL_TYPE_GRABBER enum. 3. remove undefined format 4. Adjust CMDQ API param. Signed-off-by: Moudy Ho --- .../media/platform/mtk-mdp3/mmsys_reg_base.h | 2 +- .../media/platform/mtk-mdp3/mtk-mdp3-cmdq.c | 92 +++++++------------ .../media/platform/mtk-mdp3/mtk-mdp3-cmdq.h | 3 +- .../media/platform/mtk-mdp3/mtk-mdp3-core.c | 2 +- .../media/platform/mtk-mdp3/mtk-mdp3-m2m.c | 3 +- .../media/platform/mtk-mdp3/mtk-mdp3-regs.c | 2 +- 6 files changed, 39 insertions(+), 65 deletions(-) diff --git a/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h b/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h index d79b82eea61b..738ecd525474 100644 --- a/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h +++ b/drivers/media/platform/mtk-mdp3/mmsys_reg_base.h @@ -16,7 +16,7 @@ (0xffffffff) : (mask), ##__VA_ARGS__) #define MM_REG_WAIT(cmd, evt) \ - cmdq_pkt_wfe(cmd->pkt, cmd->event[(evt)]) + cmdq_pkt_wfe(cmd->pkt, cmd->event[(evt)], true) #define MM_REG_WAIT_NO_CLEAR(cmd, evt) \ cmdq_pkt_wait_no_clear(cmd->pkt, cmd->event[(evt)]) diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c index eac10944283a..151485933eae 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.c @@ -468,71 +468,48 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) goto err_destory_pkt; } - if (param->wait) { - ret = cmdq_pkt_flush(cmd.pkt); -#ifdef MDP_DEBUG - if (ret) { - struct mdp_func_struct *p_func = mdp_get_func(); - - p_func->mdp_dump_mmsys_config(); - mdp_dump_info(~0, 1); - } -#endif - if (!ret) { /* error handle in mdp_m2m_worker */ - if (param->mdp_ctx) - mdp_m2m_job_finish(param->mdp_ctx); - } - goto err_clock_off; - } else { - cb_param = kzalloc(sizeof(*cb_param), GFP_KERNEL); - if (!cb_param) { - ret = -ENOMEM; - goto err_destory_pkt; - } + cb_param = kzalloc(sizeof(*cb_param), GFP_KERNEL); + if (!cb_param) { + ret = -ENOMEM; + goto err_destory_pkt; + } - comps = kcalloc(param->config->num_components, sizeof(*comps), - GFP_KERNEL); - if (!comps) { - mdp_err("%s:comps alloc fail!\n", __func__); - ret = -ENOMEM; - goto err_destory_pkt; - } + comps = kcalloc(param->config->num_components, sizeof(*comps), + GFP_KERNEL); + if (!comps) { + mdp_err("%s:comps alloc fail!\n", __func__); + ret = -ENOMEM; + goto err_destory_pkt; + } - for (i = 0; i < param->config->num_components; i++) - memcpy(&comps[i], path.comps[i].comp, - sizeof(struct mdp_comp)); - cb_param->mdp = mdp; - cb_param->user_cmdq_cb = param->cmdq_cb; - cb_param->user_cb_data = param->cb_data; - cb_param->pkt = cmd.pkt; - cb_param->comps = comps; - cb_param->num_comps = param->config->num_components; - cb_param->mdp_ctx = param->mdp_ctx; - - cmdq_pkt_finalize(cmd.pkt); - ret = cmdq_pkt_flush_async(cmd.pkt, - mdp_handle_cmdq_callback, - (void *)cb_param); - if (ret) { - mdp_err("%s:cmdq_pkt_flush_async fail!\n", __func__); - goto err_clock_off; - } + for (i = 0; i < param->config->num_components; i++) + memcpy(&comps[i], path.comps[i].comp, + sizeof(struct mdp_comp)); + cb_param->mdp = mdp; + cb_param->user_cmdq_cb = param->cmdq_cb; + cb_param->user_cb_data = param->cb_data; + cb_param->pkt = cmd.pkt; + cb_param->comps = comps; + cb_param->num_comps = param->config->num_components; + cb_param->mdp_ctx = param->mdp_ctx; + + cmdq_pkt_finalize(cmd.pkt); + ret = cmdq_pkt_flush_async(cmd.pkt, + mdp_handle_cmdq_callback, + (void *)cb_param); + if (ret) { + mdp_err("%s:cmdq_pkt_flush_async fail!\n", __func__); + goto err_clock_off; } return 0; err_clock_off: - if (param->wait) { - for (i = 0; i < param->config->num_components; i++) - mdp_comp_clock_off(&mdp->pdev->dev, path.comps[i].comp); - } else { - mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, - cb_param->num_comps); - } + mdp_comp_clocks_off(&mdp->pdev->dev, cb_param->comps, + cb_param->num_comps); err_destory_pkt: cmdq_pkt_destroy(cmd.pkt); atomic_dec(&mdp->job_count); - if (param->wait) - wake_up(&mdp->callback_wq); + wake_up(&mdp->callback_wq); if (comps) kfree(comps); if (cb_param) @@ -543,7 +520,7 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) int mdp_cmdq_sendtask(struct platform_device *pdev, struct img_config *config, struct img_ipi_frameparam *param, - struct v4l2_rect *compose, unsigned int wait, + struct v4l2_rect *compose, void (*cmdq_cb)(struct cmdq_cb_data data), void *cb_data) { struct mdp_dev *mdp = platform_get_drvdata(pdev); @@ -551,7 +528,6 @@ int mdp_cmdq_sendtask(struct platform_device *pdev, struct img_config *config, .config = config, .param = param, .composes[0] = compose, - .wait = wait, .cmdq_cb = cmdq_cb, .cb_data = cb_data, }; diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h index 6b8b0f6b4bb5..f6394d3d0358 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-cmdq.h @@ -16,7 +16,7 @@ struct platform_device *mdp_get_plat_device(struct platform_device *pdev); int mdp_cmdq_sendtask(struct platform_device *pdev, struct img_config *config, struct img_ipi_frameparam *param, - struct v4l2_rect *compose, unsigned int wait, + struct v4l2_rect *compose, void (*cmdq_cb)(struct cmdq_cb_data data), void *cb_data); struct mdp_cmd { @@ -28,7 +28,6 @@ struct mdp_cmdq_param { struct img_config *config; struct img_ipi_frameparam *param; const struct v4l2_rect *composes[IMG_MAX_HW_OUTPUTS]; - unsigned int wait; void (*cmdq_cb)(struct cmdq_cb_data data); void *cb_data; diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c index 207b55ace97b..a42e436d3a8c 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.c @@ -137,7 +137,7 @@ static int mdp_probe(struct platform_device *pdev) mutex_init(&mdp->vpu_lock); mutex_init(&mdp->m2m_lock); - mdp->cmdq_clt = cmdq_mbox_create(dev, 0, 1200); + mdp->cmdq_clt = cmdq_mbox_create(dev, 0); if (IS_ERR(mdp->cmdq_clt)) { ret = PTR_ERR(mdp->cmdq_clt); goto err_put_scp; diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c index ff80f01be82f..536574f6bc32 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c @@ -133,7 +133,6 @@ static void mdp_m2m_worker(struct work_struct *work) task.config = ctx->vpu.config; task.param = ¶m; task.composes[0] = &frame->compose; - task.wait = 0; task.cmdq_cb = NULL; task.cb_data = NULL; task.mdp_ctx = ctx; @@ -769,7 +768,7 @@ int mdp_m2m_device_register(struct mdp_dev *mdp) goto err_m2m_init; } - ret = video_register_device(mdp->m2m_vdev, VFL_TYPE_GRABBER, 2); + ret = video_register_device(mdp->m2m_vdev, VFL_TYPE_VIDEO, 2); if (ret) { dev_err(dev, "Failed to register video device\n"); goto err_video_register; diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c index 5c48a7e75efd..0c4c942b5f9c 100644 --- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c +++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c @@ -168,7 +168,7 @@ static const struct mdp_format mdp_formats[] = { .halign = 5, .flags = MDP_FMT_FLAG_OUTPUT, }, { - .pixelformat = V4L2_PIX_FMT_MM21, + .pixelformat = V4L2_PIX_FMT_NV12MT, .mdp_color = MDP_COLOR_420_BLK, .depth = { 8, 4 }, .row_depth = { 8, 8 },