From: Yelian Wang <yelian.wang@xxxxxxxxxxxx> Add a V4L2 sub-device driver for MT8188 AIE. Signed-off-by: Yelian Wang <yelian.wang@xxxxxxxxxxxx> --- drivers/media/platform/mediatek/Kconfig | 1 + drivers/media/platform/mediatek/Makefile | 1 + drivers/media/platform/mediatek/aie/Kconfig | 13 + drivers/media/platform/mediatek/aie/Makefile | 5 + drivers/media/platform/mediatek/aie/mtk_aie.h | 1012 +++++ .../media/platform/mediatek/aie/mtk_aie_53.c | 2031 +++++++++ .../media/platform/mediatek/aie/mtk_aie_drv.c | 3613 +++++++++++++++++ 7 files changed, 6676 insertions(+) create mode 100644 drivers/media/platform/mediatek/aie/Kconfig create mode 100644 drivers/media/platform/mediatek/aie/Makefile create mode 100644 drivers/media/platform/mediatek/aie/mtk_aie.h create mode 100644 drivers/media/platform/mediatek/aie/mtk_aie_53.c create mode 100644 drivers/media/platform/mediatek/aie/mtk_aie_drv.c diff --git a/drivers/media/platform/mediatek/Kconfig b/drivers/media/platform/mediatek/Kconfig index 84104e2cd024..987c754a76b7 100644 --- a/drivers/media/platform/mediatek/Kconfig +++ b/drivers/media/platform/mediatek/Kconfig @@ -7,3 +7,4 @@ source "drivers/media/platform/mediatek/mdp/Kconfig" source "drivers/media/platform/mediatek/vcodec/Kconfig" source "drivers/media/platform/mediatek/vpu/Kconfig" source "drivers/media/platform/mediatek/mdp3/Kconfig" +source "drivers/media/platform/mediatek/aie/Kconfig" diff --git a/drivers/media/platform/mediatek/Makefile b/drivers/media/platform/mediatek/Makefile index 38e6ba917fe5..db8e6d09de4e 100644 --- a/drivers/media/platform/mediatek/Makefile +++ b/drivers/media/platform/mediatek/Makefile @@ -4,3 +4,4 @@ obj-y += mdp/ obj-y += vcodec/ obj-y += vpu/ obj-y += mdp3/ +obj-y += aie/ diff --git a/drivers/media/platform/mediatek/aie/Kconfig b/drivers/media/platform/mediatek/aie/Kconfig new file mode 100644 index 000000000000..f2fe4bfcdd6a --- /dev/null +++ b/drivers/media/platform/mediatek/aie/Kconfig @@ -0,0 +1,13 @@ +config VIDEO_MTK_AIE + tristate "MediaTek AI engine function" + depends on OF + select V4L2_MEM2MEM_DEV + select VIDEOBUF2_DMA_CONTIG + select MEDIA_CONTROLLER_REQUEST_API + help + Support the AI engine (AIE) feature + + AIE driver is a V4L2 memory-to-memory device driver which + provides hardware accelerated face detection function, + it can detect different sizes of faces in a raw image. + diff --git a/drivers/media/platform/mediatek/aie/Makefile b/drivers/media/platform/mediatek/aie/Makefile new file mode 100644 index 000000000000..615fb8de8f3e --- /dev/null +++ b/drivers/media/platform/mediatek/aie/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +mtk-aie-y += mtk_aie_53.o +mtk-aie-y += mtk_aie_drv.o + +obj-$(CONFIG_VIDEO_MTK_AIE) += mtk-aie.o diff --git a/drivers/media/platform/mediatek/aie/mtk_aie.h b/drivers/media/platform/mediatek/aie/mtk_aie.h new file mode 100644 index 000000000000..0a2af547b56b --- /dev/null +++ b/drivers/media/platform/mediatek/aie/mtk_aie.h @@ -0,0 +1,1012 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + * Author: Fish Wu <fish.wu@xxxxxxxxxxxx> + */ + +#ifndef __MTK_AIE_H__ +#define __MTK_AIE_H__ + +#include <linux/completion.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/pm_opp.h> +#include <linux/regulator/consumer.h> +#include <linux/types.h> +#include <linux/videodev2.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/videobuf2-v4l2.h> + +// AIE 3.X + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION +#include "mtk-interconnect.h" +#endif + +// AIE 3.X +#define MTK_AIE_OPP_SET 1 +#define MTK_AIE_CLK_LEVEL_CNT 4 + +#define FD_VERSION 1946050 +#define ATTR_VERSION 1929401 + +#define Y2R_SRC_DST_FORMAT 0 +#define Y2R_IN_W_H 1 +#define Y2R_OUT_W_H 2 +#define Y2R_RA0_RA1_EN 3 +#define Y2R_IN_X_Y_SIZE0 4 +#define Y2R_IN_STRIDE0_BUS_SIZE0 5 +#define Y2R_IN_X_Y_SIZE1 6 +#define Y2R_IN_STRIDE1_BUS_SIZE1 7 +#define Y2R_OUT_X_Y_SIZE0 8 +#define Y2R_OUT_STRIDE0_BUS_SIZE0 9 +#define Y2R_OUT_X_Y_SIZE1 10 +#define Y2R_OUT_STRIDE1_BUS_SIZE1 11 +#define Y2R_OUT_X_Y_SIZE2 12 +#define Y2R_OUT_STRIDE2_BUS_SIZE2 13 +#define Y2R_IN_0 14 +#define Y2R_IN_1 15 +#define Y2R_OUT_0 16 +#define Y2R_OUT_1 17 +#define Y2R_OUT_2 18 +#define Y2R_RS_SEL_SRZ_EN 19 +#define Y2R_X_Y_MAG 20 +#define Y2R_SRZ_HORI_STEP 22 +#define Y2R_SRZ_VERT_STEP 23 +#define Y2R_PADDING_EN_UP_DOWN 26 +#define Y2R_PADDING_RIGHT_LEFT 27 +#define Y2R_CO2_FMT_MODE_EN 28 /* AIE3.0 new */ +#define Y2R_CO2_CROP_X 29 /* AIE3.0 new */ +#define Y2R_CO2_CROP_Y 30 /* AIE3.0 new */ +#define Y2R_CON_IN_BA_MSB 31 +#define Y2R_CON_OUT_BA_MSB 32 + +#define RS_IN_0 22 +#define RS_IN_1 23 +#define RS_IN_2 24 +#define RS_OUT_0 25 +#define RS_OUT_1 26 +#define RS_OUT_2 27 +#define RS_X_Y_MAG 1 +#define RS_SRZ_HORI_STEP 3 +#define RS_SRZ_VERT_STEP 4 +#define RS_INPUT_W_H 7 +#define RS_OUTPUT_W_H 8 +#define RS_IN_X_Y_SIZE0 10 +#define RS_IN_STRIDE0 11 +#define RS_IN_X_Y_SIZE1 12 +#define RS_IN_STRIDE1 13 +#define RS_IN_X_Y_SIZE2 14 +#define RS_IN_STRIDE2 15 +#define RS_OUT_X_Y_SIZE0 16 +#define RS_OUT_STRIDE0 17 +#define RS_OUT_X_Y_SIZE1 18 +#define RS_OUT_STRIDE1 19 +#define RS_OUT_X_Y_SIZE2 20 +#define RS_OUT_STRIDE2 21 +// AIE 3.X +#define RS_CON_IN_BA_MSB 28 +#define RS_CON_OUT_BA_MSB 29 + +#define FD_INPUT_ROTATE 1 +#define FD_CONV_WIDTH_MOD6 2 +#define FD_CONV_IMG_W_H 4 + +#define FD_IN_IMG_W_H 5 +#define FD_OUT_IMG_W_H 6 + +#define FD_IN_X_Y_SIZE0 9 +#define FD_IN_X_Y_SIZE1 11 +#define FD_IN_X_Y_SIZE2 13 +#define FD_IN_X_Y_SIZE3 15 + +#define FD_IN_STRIDE0_BUS_SIZE0 10 +#define FD_IN_STRIDE1_BUS_SIZE1 12 +#define FD_IN_STRIDE2_BUS_SIZE2 14 +#define FD_IN_STRIDE3_BUS_SIZE3 16 + +#define FD_OUT_X_Y_SIZE0 17 +#define FD_OUT_X_Y_SIZE1 19 +#define FD_OUT_X_Y_SIZE2 21 +#define FD_OUT_X_Y_SIZE3 23 + +#define FD_OUT_STRIDE0_BUS_SIZE0 18 +#define FD_OUT_STRIDE1_BUS_SIZE1 20 +#define FD_OUT_STRIDE2_BUS_SIZE2 22 +#define FD_OUT_STRIDE3_BUS_SIZE3 24 + +#define FD_IN_0 27 +#define FD_IN_1 28 +#define FD_IN_2 29 +#define FD_IN_3 30 + +#define FD_OUT_0 31 +#define FD_OUT_1 32 +#define FD_OUT_2 33 +#define FD_OUT_3 34 + +#define FD_KERNEL_0 35 +#define FD_KERNEL_1 36 + +#define FD_RPN_SET 37 +#define FD_IMAGE_COORD 38 +#define FD_IMAGE_COORD_XY_OFST 39 /* AIE3.0 new */ +#define FD_BIAS_ACCU 47 /* AIE3.0 new */ +#define FD_SRZ_FDRZ_RS 48 /* AIE3.0 new */ +#define FD_SRZ_HORI_STEP 49 /* AIE3.0 new */ +#define FD_SRZ_VERT_STEP 50 /* AIE3.0 new */ +#define FD_SRZ_HORI_SUB_INT_OFST 51 /* AIE3.0 new */ +#define FD_SRZ_VERT_SUB_INT_OFST 52 /* AIE3.0 new */ +// AIE 3.X +#define FD_CON_IN_BA_MSB 53 +#define FD_CON_OUT_BA_MSB 54 +#define FD_CON_KERNEL_BA_MSB 55 + +#define SRZ_BIT (BIT_MASK(16) | BIT_MASK(12) | BIT_MASK(8) | BIT_MASK(0)) + +#define FD_LOOP_NUM 87 +#define RPN0_LOOP_NUM 86 +#define RPN1_LOOP_NUM 57 +#define RPN2_LOOP_NUM 28 + +#define PYM0_START_LOOP 58 +#define PYM1_START_LOOP 29 +#define PYM2_START_LOOP 0 + +#define ATTR_LOOP_NUM 26 +#define AGE_OUT_RGS 17 +#define GENDER_OUT_RGS 20 +#define INDIAN_OUT_RGS 22 +#define RACE_OUT_RGS 25 + +#define INPUT_WDMA_WRA_NUM 4 +#define OUTPUT_WDMA_WRA_NUM 4 +#define KERNEL_RDMA_RA_NUM 2 + +#define MAX_ENQUE_FRAME_NUM 10 +#define PYM_NUM 3 +#define COLOR_NUM 3 + +#define ATTR_MODE_PYRAMID_WIDTH 128 +#define ATTR_OUT_SIZE 32 + +/* AIE 2.0 3.X register offset */ +#define AIE_START_REG 0x000 +#define AIE_ENABLE_REG 0x004 +#define AIE_LOOP_REG 0x008 +#define AIE_YUV2RGB_CON_BASE_ADR_REG 0x00c +#define AIE_RS_CON_BASE_ADR_REG 0x010 +#define AIE_FD_CON_BASE_ADR_REG 0x014 +#define AIE_INT_EN_REG 0x018 +#define AIE_INT_REG 0x01c +#define AIE_RESULT_0_REG 0x08c +#define AIE_RESULT_1_REG 0x090 +#define AIE_DMA_CTL_REG 0x094 + +/* AIE 3.0 register offset */ +#define AIE_YUV2RGB_CON_BASE_ADR_MSB 0x14C +#define AIE_RS_CON_BASE_ADR_MSB 0x150 +#define AIE_FD_CON_BASE_ADR_MSB 0x154 + +/* AIE 3.0 FLD register offset */ +#define FLD_EN 0x400 +#define FLD_BASE_ADDR_FACE_0 0x404 +#define FLD_BASE_ADDR_FACE_1 0x408 +#define FLD_BASE_ADDR_FACE_2 0x40C +#define FLD_BASE_ADDR_FACE_3 0x410 +#define FLD_BASE_ADDR_FACE_4 0x414 +#define FLD_BASE_ADDR_FACE_5 0x418 +#define FLD_BASE_ADDR_FACE_6 0x41C +#define FLD_BASE_ADDR_FACE_7 0x420 +#define FLD_BASE_ADDR_FACE_8 0x424 +#define FLD_BASE_ADDR_FACE_9 0x428 +#define FLD_BASE_ADDR_FACE_10 0x42C +#define FLD_BASE_ADDR_FACE_11 0x430 +#define FLD_BASE_ADDR_FACE_12 0x434 +#define FLD_BASE_ADDR_FACE_13 0x438 +#define FLD_BASE_ADDR_FACE_14 0x43C + +#define FLD_INFO_0_FACE_0 0x440 +#define FLD_INFO_1_FACE_0 0x444 +#define FLD_INFO_2_FACE_0 0x448 +#define FLD_INFO_0_FACE_1 0x44C +#define FLD_INFO_1_FACE_1 0x450 +#define FLD_INFO_2_FACE_1 0x454 +#define FLD_INFO_0_FACE_2 0x458 +#define FLD_INFO_1_FACE_2 0x45C +#define FLD_INFO_2_FACE_2 0x460 +#define FLD_INFO_0_FACE_3 0x464 +#define FLD_INFO_1_FACE_3 0x468 +#define FLD_INFO_2_FACE_3 0x46C +#define FLD_INFO_0_FACE_4 0x470 +#define FLD_INFO_1_FACE_4 0x474 +#define FLD_INFO_2_FACE_4 0x478 +#define FLD_INFO_0_FACE_5 0x47C +#define FLD_INFO_1_FACE_5 0x480 +#define FLD_INFO_2_FACE_5 0x484 +#define FLD_INFO_0_FACE_6 0x488 +#define FLD_INFO_1_FACE_6 0x48C +#define FLD_INFO_2_FACE_6 0x490 +#define FLD_INFO_0_FACE_7 0x494 +#define FLD_INFO_1_FACE_7 0x498 + +#define FLD_INFO_2_FACE_7 0x4A0 +#define FLD_INFO_0_FACE_8 0x4A4 +#define FLD_INFO_1_FACE_8 0x4A8 +#define FLD_INFO_2_FACE_8 0x4AC +#define FLD_INFO_0_FACE_9 0x4B0 +#define FLD_INFO_1_FACE_9 0x4B4 +#define FLD_INFO_2_FACE_9 0x4B8 +#define FLD_INFO_0_FACE_10 0x4BC +#define FLD_INFO_1_FACE_10 0x4C0 +#define FLD_INFO_2_FACE_10 0x4C4 +#define FLD_INFO_0_FACE_11 0x4C8 +#define FLD_INFO_1_FACE_11 0x4CC +#define FLD_INFO_2_FACE_11 0x4D0 +#define FLD_INFO_0_FACE_12 0x4D4 +#define FLD_INFO_1_FACE_12 0x4D8 +#define FLD_INFO_2_FACE_12 0x4DC +#define FLD_INFO_0_FACE_13 0x4E0 +#define FLD_INFO_1_FACE_13 0x4E4 +#define FLD_INFO_2_FACE_13 0x4E8 +#define FLD_INFO_0_FACE_14 0x4EC +#define FLD_INFO_1_FACE_14 0x4F0 +#define FLD_INFO_2_FACE_14 0x4F4 + +#define FLD_MODEL_PARA0 0x4F8 +#define FLD_MODEL_PARA1 0x4FC +#define FLD_MODEL_PARA2 0x500 +#define FLD_MODEL_PARA3 0x504 +#define FLD_MODEL_PARA4 0x508 +#define FLD_MODEL_PARA5 0x50C +#define FLD_MODEL_PARA6 0x510 +#define FLD_MODEL_PARA7 0x514 +#define FLD_MODEL_PARA8 0x518 +#define FLD_MODEL_PARA9 0x51C +#define FLD_MODEL_PARA10 0x520 +#define FLD_MODEL_PARA11 0x524 +#define FLD_MODEL_PARA12 0x528 +#define FLD_MODEL_PARA13 0x52C +#define FLD_MODEL_PARA14 0x530 +#define FLD_MODEL_PARA15 0x534 +#define FLD_MODEL_PARA16 0x538 +#define FLD_DEBUG_INFO0 0x53C +#define FLD_DEBUG_INFO1 0x540 + +#define FLD_BUSY 0x544 +#define FLD_DONE 0x548 +#define FLD_SRC_WD_HT 0x54C + +#define FLD_PL_IN_BASE_ADDR_0_0 0x550 +#define FLD_PL_IN_BASE_ADDR_0_1 0x554 +#define FLD_PL_IN_BASE_ADDR_0_2 0x558 +#define FLD_PL_IN_BASE_ADDR_0_3 0x55C +#define FLD_PL_IN_BASE_ADDR_0_4 0x560 +#define FLD_PL_IN_BASE_ADDR_0_5 0x564 +#define FLD_PL_IN_BASE_ADDR_0_6 0x568 +#define FLD_PL_IN_BASE_ADDR_0_7 0x56C +#define FLD_PL_IN_BASE_ADDR_0_8 0x570 +#define FLD_PL_IN_BASE_ADDR_0_9 0x574 +#define FLD_PL_IN_BASE_ADDR_0_10 0x578 +#define FLD_PL_IN_BASE_ADDR_0_11 0x57C +#define FLD_PL_IN_BASE_ADDR_0_12 0x580 +#define FLD_PL_IN_BASE_ADDR_0_13 0x584 +#define FLD_PL_IN_BASE_ADDR_0_14 0x588 +#define FLD_PL_IN_BASE_ADDR_0_15 0x58C +#define FLD_PL_IN_BASE_ADDR_0_16 0x590 +#define FLD_PL_IN_BASE_ADDR_0_17 0x594 +#define FLD_PL_IN_BASE_ADDR_0_18 0x598 +#define FLD_PL_IN_BASE_ADDR_0_19 0x59C +#define FLD_PL_IN_BASE_ADDR_0_20 0x5A0 +#define FLD_PL_IN_BASE_ADDR_0_21 0x5A4 +#define FLD_PL_IN_BASE_ADDR_0_22 0x5A8 +#define FLD_PL_IN_BASE_ADDR_0_23 0x5AC +#define FLD_PL_IN_BASE_ADDR_0_24 0x5B0 +#define FLD_PL_IN_BASE_ADDR_0_25 0x5B4 +#define FLD_PL_IN_BASE_ADDR_0_26 0x5B8 +#define FLD_PL_IN_BASE_ADDR_0_27 0x5BC +#define FLD_PL_IN_BASE_ADDR_0_28 0x5C0 +#define FLD_PL_IN_BASE_ADDR_0_29 0x5C4 + +#define FLD_PL_IN_BASE_ADDR_1_0 0x5C8 +#define FLD_PL_IN_BASE_ADDR_1_1 0x5CC +#define FLD_PL_IN_BASE_ADDR_1_2 0x5D0 +#define FLD_PL_IN_BASE_ADDR_1_3 0x5D4 +#define FLD_PL_IN_BASE_ADDR_1_4 0x5D8 +#define FLD_PL_IN_BASE_ADDR_1_5 0x5DC +#define FLD_PL_IN_BASE_ADDR_1_6 0x5E0 +#define FLD_PL_IN_BASE_ADDR_1_7 0x5E4 +#define FLD_PL_IN_BASE_ADDR_1_8 0x5E8 +#define FLD_PL_IN_BASE_ADDR_1_9 0x5EC +#define FLD_PL_IN_BASE_ADDR_1_10 0x5F0 +#define FLD_PL_IN_BASE_ADDR_1_11 0x5F4 +#define FLD_PL_IN_BASE_ADDR_1_12 0x5F8 +#define FLD_PL_IN_BASE_ADDR_1_13 0x5FC +#define FLD_PL_IN_BASE_ADDR_1_14 0x600 +#define FLD_PL_IN_BASE_ADDR_1_15 0x604 +#define FLD_PL_IN_BASE_ADDR_1_16 0x608 +#define FLD_PL_IN_BASE_ADDR_1_17 0x60C +#define FLD_PL_IN_BASE_ADDR_1_18 0x610 +#define FLD_PL_IN_BASE_ADDR_1_19 0x614 +#define FLD_PL_IN_BASE_ADDR_1_20 0x618 +#define FLD_PL_IN_BASE_ADDR_1_21 0x61C +#define FLD_PL_IN_BASE_ADDR_1_22 0x620 +#define FLD_PL_IN_BASE_ADDR_1_23 0x624 +#define FLD_PL_IN_BASE_ADDR_1_24 0x628 +#define FLD_PL_IN_BASE_ADDR_1_25 0x62C +#define FLD_PL_IN_BASE_ADDR_1_26 0x630 +#define FLD_PL_IN_BASE_ADDR_1_27 0x634 +#define FLD_PL_IN_BASE_ADDR_1_28 0x638 +#define FLD_PL_IN_BASE_ADDR_1_29 0x63C + +#define FLD_PL_IN_BASE_ADDR_2_0 0x640 +#define FLD_PL_IN_BASE_ADDR_2_1 0x644 +#define FLD_PL_IN_BASE_ADDR_2_2 0x648 +#define FLD_PL_IN_BASE_ADDR_2_3 0x64C +#define FLD_PL_IN_BASE_ADDR_2_4 0x650 +#define FLD_PL_IN_BASE_ADDR_2_5 0x654 +#define FLD_PL_IN_BASE_ADDR_2_6 0x658 +#define FLD_PL_IN_BASE_ADDR_2_7 0x65C +#define FLD_PL_IN_BASE_ADDR_2_8 0x660 +#define FLD_PL_IN_BASE_ADDR_2_9 0x664 +#define FLD_PL_IN_BASE_ADDR_2_10 0x668 +#define FLD_PL_IN_BASE_ADDR_2_11 0x66C +#define FLD_PL_IN_BASE_ADDR_2_12 0x670 +#define FLD_PL_IN_BASE_ADDR_2_13 0x674 +#define FLD_PL_IN_BASE_ADDR_2_14 0x678 +#define FLD_PL_IN_BASE_ADDR_2_15 0x67C +#define FLD_PL_IN_BASE_ADDR_2_16 0x680 +#define FLD_PL_IN_BASE_ADDR_2_17 0x684 +#define FLD_PL_IN_BASE_ADDR_2_18 0x688 +#define FLD_PL_IN_BASE_ADDR_2_19 0x68C +#define FLD_PL_IN_BASE_ADDR_2_20 0x690 +#define FLD_PL_IN_BASE_ADDR_2_21 0x694 +#define FLD_PL_IN_BASE_ADDR_2_22 0x698 +#define FLD_PL_IN_BASE_ADDR_2_23 0x69C +#define FLD_PL_IN_BASE_ADDR_2_24 0x6A0 +#define FLD_PL_IN_BASE_ADDR_2_25 0x6A4 +#define FLD_PL_IN_BASE_ADDR_2_26 0x6A8 +#define FLD_PL_IN_BASE_ADDR_2_27 0x6AC +#define FLD_PL_IN_BASE_ADDR_2_28 0x6B0 +#define FLD_PL_IN_BASE_ADDR_2_29 0x6B4 + +#define FLD_PL_IN_BASE_ADDR_3_0 0x6B8 +#define FLD_PL_IN_BASE_ADDR_3_1 0x6BC +#define FLD_PL_IN_BASE_ADDR_3_2 0x6C0 +#define FLD_PL_IN_BASE_ADDR_3_3 0x6C4 +#define FLD_PL_IN_BASE_ADDR_3_4 0x6C8 +#define FLD_PL_IN_BASE_ADDR_3_5 0x6CC +#define FLD_PL_IN_BASE_ADDR_3_6 0x6D0 +#define FLD_PL_IN_BASE_ADDR_3_7 0x6D4 +#define FLD_PL_IN_BASE_ADDR_3_8 0x6D8 +#define FLD_PL_IN_BASE_ADDR_3_9 0x6DC +#define FLD_PL_IN_BASE_ADDR_3_10 0x6E0 +#define FLD_PL_IN_BASE_ADDR_3_11 0x6E4 +#define FLD_PL_IN_BASE_ADDR_3_12 0x6E8 +#define FLD_PL_IN_BASE_ADDR_3_13 0x6EC +#define FLD_PL_IN_BASE_ADDR_3_14 0x6F0 +#define FLD_PL_IN_BASE_ADDR_3_15 0x6F4 +#define FLD_PL_IN_BASE_ADDR_3_16 0x6F8 +#define FLD_PL_IN_BASE_ADDR_3_17 0x6FC +#define FLD_PL_IN_BASE_ADDR_3_18 0x700 +#define FLD_PL_IN_BASE_ADDR_3_19 0x704 +#define FLD_PL_IN_BASE_ADDR_3_20 0x708 +#define FLD_PL_IN_BASE_ADDR_3_21 0x70C +#define FLD_PL_IN_BASE_ADDR_3_22 0x710 +#define FLD_PL_IN_BASE_ADDR_3_23 0x714 +#define FLD_PL_IN_BASE_ADDR_3_24 0x718 +#define FLD_PL_IN_BASE_ADDR_3_25 0x71C +#define FLD_PL_IN_BASE_ADDR_3_26 0x720 +#define FLD_PL_IN_BASE_ADDR_3_27 0x724 +#define FLD_PL_IN_BASE_ADDR_3_28 0x728 +#define FLD_PL_IN_BASE_ADDR_3_29 0x72C + +#define FLD_PL_IN_SIZE_0 0x730 +#define FLD_PL_IN_STRIDE_0 0x734 +#define FLD_PL_IN_SIZE_1 0x738 +#define FLD_PL_IN_STRIDE_1 0x73C +#define FLD_PL_IN_SIZE_2_0 0x740 +#define FLD_PL_IN_STRIDE_2_0 0x744 +#define FLD_PL_IN_SIZE_2_1 0x748 +#define FLD_PL_IN_STRIDE_2_1 0x74C +#define FLD_PL_IN_SIZE_2_2 0x750 +#define FLD_PL_IN_STRIDE_2_2 0x754 +#define FLD_PL_IN_SIZE_3 0x758 +#define FLD_PL_IN_STRIDE_3 0x75C + +#define FLD_SH_IN_BASE_ADDR_0 0x760 +#define FLD_SH_IN_BASE_ADDR_1 0x764 +#define FLD_SH_IN_BASE_ADDR_2 0x768 +#define FLD_SH_IN_BASE_ADDR_3 0x76C +#define FLD_SH_IN_BASE_ADDR_4 0x770 +#define FLD_SH_IN_BASE_ADDR_5 0x774 +#define FLD_SH_IN_BASE_ADDR_6 0x778 +#define FLD_SH_IN_BASE_ADDR_7 0x77C +#define FLD_SH_IN_BASE_ADDR_8 0x780 +#define FLD_SH_IN_BASE_ADDR_9 0x784 +#define FLD_SH_IN_BASE_ADDR_10 0x788 +#define FLD_SH_IN_BASE_ADDR_11 0x78C +#define FLD_SH_IN_BASE_ADDR_12 0x790 +#define FLD_SH_IN_BASE_ADDR_13 0x794 +#define FLD_SH_IN_BASE_ADDR_14 0x798 +#define FLD_SH_IN_BASE_ADDR_15 0x79C +#define FLD_SH_IN_BASE_ADDR_16 0x7A0 +#define FLD_SH_IN_BASE_ADDR_17 0x7A4 +#define FLD_SH_IN_BASE_ADDR_18 0x7A8 +#define FLD_SH_IN_BASE_ADDR_19 0x7AC +#define FLD_SH_IN_BASE_ADDR_20 0x7B0 +#define FLD_SH_IN_BASE_ADDR_21 0x7B4 +#define FLD_SH_IN_BASE_ADDR_22 0x7B8 +#define FLD_SH_IN_BASE_ADDR_23 0x7BC +#define FLD_SH_IN_BASE_ADDR_24 0x7C0 +#define FLD_SH_IN_BASE_ADDR_25 0x7C4 +#define FLD_SH_IN_BASE_ADDR_26 0x7C8 +#define FLD_SH_IN_BASE_ADDR_27 0x7CC +#define FLD_SH_IN_BASE_ADDR_28 0x7D0 +#define FLD_SH_IN_BASE_ADDR_29 0x7D4 + +#define FLD_SH_IN_SIZE_0 0x7D8 +#define FLD_SH_IN_STRIDE_0 0x7DC +#define FLD_TR_OUT_BASE_ADDR_0 0x7E0 +#define FLD_TR_OUT_SIZE_0 0x7E4 +#define FLD_TR_OUT_STRIDE_0 0x7E8 +#define FLD_PP_OUT_BASE_ADDR_0 0x7EC +#define FLD_PP_OUT_SIZE_0 0x7F0 +#define FLD_PP_OUT_STRIDE_0 0x7F4 +#define FLD_SPARE 0x7F8 + +#define FLD_BASE_ADDR_FACE_0_7_MSB 0x7FC +#define FLD_BASE_ADDR_FACE_8_14_MSB 0x800 + +#define FLD_PL_IN_BASE_ADDR_0_0_7_MSB 0x804 +#define FLD_PL_IN_BASE_ADDR_0_8_15_MSB 0x808 +#define FLD_PL_IN_BASE_ADDR_0_16_23_MSB 0x80C +#define FLD_PL_IN_BASE_ADDR_0_24_29_MSB 0x810 + +#define FLD_PL_IN_BASE_ADDR_1_0_7_MSB 0x814 +#define FLD_PL_IN_BASE_ADDR_1_8_15_MSB 0x818 +#define FLD_PL_IN_BASE_ADDR_1_16_23_MSB 0x81C +#define FLD_PL_IN_BASE_ADDR_1_24_29_MSB 0x820 + +#define FLD_PL_IN_BASE_ADDR_2_0_7_MSB 0x824 +#define FLD_PL_IN_BASE_ADDR_2_8_15_MSB 0x828 +#define FLD_PL_IN_BASE_ADDR_2_16_23_MSB 0x82C +#define FLD_PL_IN_BASE_ADDR_2_24_29_MSB 0x830 + +#define FLD_PL_IN_BASE_ADDR_3_0_7_MSB 0x834 +#define FLD_PL_IN_BASE_ADDR_3_8_15_MSB 0x838 +#define FLD_PL_IN_BASE_ADDR_3_16_23_MSB 0x83C +#define FLD_PL_IN_BASE_ADDR_3_24_29_MSB 0x840 + +#define FLD_SH_IN_BASE_ADDR_0_7_MSB 0x844 +#define FLD_SH_IN_BASE_ADDR_8_15_MSB 0x848 +#define FLD_SH_IN_BASE_ADDR_16_23_MSB 0x84C +#define FLD_SH_IN_BASE_ADDR_24_29_MSB 0x850 + +#define FLD_BS_IN_BASE_ADDR_0_7_MSB 0x8d4 +#define FLD_BS_IN_BASE_ADDR_8_15_MSB 0x8d8 + +#define FLD_TR_OUT_BASE_ADDR_0_MSB 0x854 +#define FLD_PP_OUT_BASE_ADDR_0_MSB 0x858 + +#define FLD_BS_IN_BASE_ADDR_00 0x85C +#define FLD_BS_IN_BASE_ADDR_01 0x860 +#define FLD_BS_IN_BASE_ADDR_02 0x864 +#define FLD_BS_IN_BASE_ADDR_03 0x868 +#define FLD_BS_IN_BASE_ADDR_04 0x86C +#define FLD_BS_IN_BASE_ADDR_05 0x870 +#define FLD_BS_IN_BASE_ADDR_06 0x874 +#define FLD_BS_IN_BASE_ADDR_07 0x878 +#define FLD_BS_IN_BASE_ADDR_08 0x87C +#define FLD_BS_IN_BASE_ADDR_09 0x880 +#define FLD_BS_IN_BASE_ADDR_10 0x884 +#define FLD_BS_IN_BASE_ADDR_11 0x888 +#define FLD_BS_IN_BASE_ADDR_12 0x88C +#define FLD_BS_IN_BASE_ADDR_13 0x890 +#define FLD_BS_IN_BASE_ADDR_14 0x894 +#define FLD_BS_BIAS 0x8E4 +#define FLD_CV_FM_RANGE_0 0x8E8 +#define FLD_CV_FM_RANGE_1 0x8EC +#define FLD_CV_PM_RANGE_0 0x8F0 +#define FLD_CV_PM_RANGE_1 0x8F4 +#define FLD_BS_RANGE_0 0x8F8 +#define FLD_BS_RANGE_1 0x8FC + +#define MTK_FD_OUTPUT_MIN_WIDTH 16U +#define MTK_FD_OUTPUT_MIN_HEIGHT 16U +#define MTK_FD_OUTPUT_MAX_WIDTH 4096U +#define MTK_FD_OUTPUT_MAX_HEIGHT 4096U + +#define MTK_FD_HW_TIMEOUT_IN_MSEC 2000 +#define MAX_FACE_NUM 1024 +#define RLT_NUM 48 +#define GENDER_OUT 32 + +#define RACE_RST_X_NUM 4 +#define RACE_RST_Y_NUM 64 +#define GENDER_RST_X_NUM 2 +#define GENDER_RST_Y_NUM 64 +#define MRACE_RST_NUM 4 +#define MGENDER_RST_NUM 2 +#define MAGE_RST_NUM 2 +#define MINDIAN_RST_NUM 2 + +// AIE 3.X +#define FLD_FOREST 14 +#define FLD_POINT 500 + +#define FLD_STEP_NUM 6 +#define FLD_MAX_FRAME 15 + +#define FLD_STEP_BLINK 0 +#define FLD_STEP_CV 1 +#define FLD_STEP_FP 2 +#define FLD_STEP_LEAF 3 +#define FLD_STEP_KM02 4 +#define FLD_STEP_KM13 5 + +#define FLD_BLINK_WEIGHT_FOREST14_SIZE 6416 +#define FLD_CV_SIZE 19392 +#define FLD_FP_SIZE 80160 +#define FLD_LEAFNODE_SIZE 4608000 +#define FLD_TREE_KM02_SIZE 120000 +#define FLD_TREE_KM13_SIZE 120000 +#define FLD_OUTPUT_SIZE 112 + +#define FLD_CUR_LANDMARK 11 + +#define RESULT_SIZE (RLT_NUM * MAX_FACE_NUM) + +struct aie_static_info_element { + unsigned int fd_wdma_size[OUTPUT_WDMA_WRA_NUM]; + unsigned int out_xsize_plus_1; + unsigned int out_height; + unsigned int out_ysize_plus_1_stride2; + unsigned int out_stride; + unsigned int out_stride_stride2; + unsigned int out_width; + unsigned int img_width; + unsigned int img_height; + unsigned int stride2_out_width; + unsigned int stride2_out_height; + unsigned int out_xsize_plus_1_stride2; + unsigned int input_xsize_plus_1; +}; + +struct aie_static_info { + struct aie_static_info_element inf_elm[FD_LOOP_NUM]; +}; + +enum aie_state { STATE_NA = 0x0, STATE_INIT = 0x1, STATE_OPEN = 0x2 }; + +// AIE 3.1 +enum aie_mode { FDMODE = 0, ATTRIBUTEMODE = 1, FLDMODE = 2}; + +enum aie_format { + FMT_NA = 0, + FMT_YUV_2P = 1, + FMT_YVU_2P = 2, + FMT_YUYV = 3, + FMT_YVYU = 4, + FMT_UYVY = 5, + FMT_VYUY = 6, + FMT_MONO = 7, + // AIE 3.X + FMT_YUV420_2P = 8, + FMT_YUV420_1P = 9 +}; + +enum aie_input_degree { + DEGREE_0 = 0, + DEGREE_90 = 1, + DEGREE_270 = 2, + DEGREE_180 = 3 +}; + +/* align v4l2 user space interface */ +struct FDRESULT { + u16 anchor_x0[MAX_FACE_NUM]; + u16 anchor_x1[MAX_FACE_NUM]; + u16 anchor_y0[MAX_FACE_NUM]; + u16 anchor_y1[MAX_FACE_NUM]; + signed short rop_landmark_score0[MAX_FACE_NUM]; + signed short rop_landmark_score1[MAX_FACE_NUM]; + signed short rop_landmark_score2[MAX_FACE_NUM]; + signed short anchor_score[MAX_FACE_NUM]; + signed short rip_landmark_score0[MAX_FACE_NUM]; + signed short rip_landmark_score1[MAX_FACE_NUM]; + signed short rip_landmark_score2[MAX_FACE_NUM]; + signed short rip_landmark_score3[MAX_FACE_NUM]; + signed short rip_landmark_score4[MAX_FACE_NUM]; + signed short rip_landmark_score5[MAX_FACE_NUM]; + signed short rip_landmark_score6[MAX_FACE_NUM]; + u16 face_result_index[MAX_FACE_NUM]; + u16 anchor_index[MAX_FACE_NUM]; + u32 fd_partial_result; +}; + +struct fd_result { + u16 fd_pyramid0_num; + u16 fd_pyramid1_num; + u16 fd_pyramid2_num; + u16 fd_total_num; + struct FDRESULT PYRAMID0_RESULT; + struct FDRESULT PYRAMID1_RESULT; + struct FDRESULT PYRAMID2_RESULT; +}; + +struct RACERESULT { + signed short RESULT[4][64]; // RESULT[Channel][Feature] +}; + +struct GENDERRESULT { + signed short RESULT[2][64]; // RESULT[Channel][Feature] +}; + +struct MERGED_RACERESULT { + signed short RESULT[4]; // RESULT[Feature] +}; + +struct MERGED_GENDERRESULT { + signed short RESULT[2]; // RESULT[Feature] +}; + +struct MERGED_AGERESULT { + signed short RESULT[2]; // RESULT[Feature] +}; + +struct MERGED_IS_INDIANRESULT { + signed short RESULT[2]; // RESULT[Feature] +}; + +struct attr_result { + struct GENDERRESULT GENDER_RESULT; + struct RACERESULT RACE_RESULT; + struct MERGED_AGERESULT MERGED_AGE_RESULT; + struct MERGED_GENDERRESULT MERGED_GENDER_RESULT; + struct MERGED_IS_INDIANRESULT MERGED_IS_INDIAN_RESULT; + struct MERGED_RACERESULT MERGED_RACE_RESULT; +}; + +// AIE 3.X +struct FLD_LANDMARK { + u16 x; + u16 y; +}; + +struct fld_result { + struct FLD_LANDMARK fld_landmark[FLD_CUR_LANDMARK]; + u16 fld_out_rip; + u16 fld_out_rop; + u16 confidence; + signed short blinkscore; +}; + +struct aie_roi { + u32 x1; + u32 y1; + u32 x2; + u32 y2; +}; + +struct aie_padding { + u32 left; + u32 right; + u32 down; + u32 up; +}; + +// AIE 3.X +struct fld_crop_rip_rop { + unsigned int fld_in_crop_x1; + unsigned int fld_in_crop_y1; + unsigned int fld_in_crop_x2; + unsigned int fld_in_crop_y2; + unsigned int fld_in_rip; + unsigned int fld_in_rop; +}; + +/* align v4l2 user space interface */ +struct aie_enq_info { + unsigned int sel_mode; + unsigned int src_img_fmt; + unsigned int src_img_width; + unsigned int src_img_height; + unsigned int src_img_stride; + unsigned int pyramid_base_width; + unsigned int pyramid_base_height; + unsigned int number_of_pyramid; + unsigned int rotate_degree; + int en_roi; + struct aie_roi src_roi; + int en_padding; + struct aie_padding src_padding; + unsigned int freq_level; + // AIE 3.X + unsigned int fld_face_num; + struct fld_crop_rip_rop fld_input[FLD_MAX_FRAME]; + u32 src_img_addr; + u32 src_img_addr_uv; + u32 fd_version; + u32 attr_version; + u32 pose_version; + struct fd_result fd_out; + struct attr_result attr_out; +// AIE 3.X + struct fld_result fld_out[FLD_MAX_FRAME]; + u32 irq_status; +}; + +struct aie_reg_cfg { + u32 rs_adr; + u32 yuv2rgb_adr; + u32 fd_adr; + u32 fd_pose_adr; + u32 fd_mode; + u32 hw_result; + u32 hw_result1; + u32 reserved; +}; + +struct aie_para { + void *fd_fd_cfg_va; + void *fd_rs_cfg_va; + void *fd_yuv2rgb_cfg_va; + + void *attr_fd_cfg_va[MAX_ENQUE_FRAME_NUM]; + void *attr_yuv2rgb_cfg_va[MAX_ENQUE_FRAME_NUM]; + + void *rs_pym_rst_va[PYM_NUM][COLOR_NUM]; + + dma_addr_t fd_fd_cfg_pa; + dma_addr_t fd_rs_cfg_pa; + dma_addr_t fd_yuv2rgb_cfg_pa; + + dma_addr_t attr_fd_cfg_pa[MAX_ENQUE_FRAME_NUM]; + dma_addr_t attr_yuv2rgb_cfg_pa[MAX_ENQUE_FRAME_NUM]; + + dma_addr_t rs_pym_rst_pa[PYM_NUM][COLOR_NUM]; + + u32 sel_mode; + u16 max_img_width; + u16 max_img_height; + u16 img_width; + u16 img_height; + u16 crop_width; + u16 crop_height; + u32 src_img_fmt; + u32 rotate_degree; + s16 rpn_anchor_thrd; + u16 pyramid_width; + u16 pyramid_height; + u16 max_pyramid_width; + u16 max_pyramid_height; + u16 number_of_pyramid; + u32 src_img_addr; + u32 src_img_addr_uv; +}; + +struct aie_attr_para { + u32 w_idx; + u32 r_idx; + u32 sel_mode[MAX_ENQUE_FRAME_NUM]; + u16 img_width[MAX_ENQUE_FRAME_NUM]; + u16 img_height[MAX_ENQUE_FRAME_NUM]; + u16 crop_width[MAX_ENQUE_FRAME_NUM]; + u16 crop_height[MAX_ENQUE_FRAME_NUM]; + u32 src_img_fmt[MAX_ENQUE_FRAME_NUM]; + u32 rotate_degree[MAX_ENQUE_FRAME_NUM]; + u32 src_img_addr[MAX_ENQUE_FRAME_NUM]; + u32 src_img_addr_uv[MAX_ENQUE_FRAME_NUM]; +}; + +struct aie_fd_dma_para { + void *fd_out_hw_va[FD_LOOP_NUM][OUTPUT_WDMA_WRA_NUM]; + void *fd_kernel_va[FD_LOOP_NUM][KERNEL_RDMA_RA_NUM]; + void *attr_out_hw_va[ATTR_LOOP_NUM][OUTPUT_WDMA_WRA_NUM]; + void *attr_kernel_va[ATTR_LOOP_NUM][KERNEL_RDMA_RA_NUM]; + + void *age_out_hw_va[MAX_ENQUE_FRAME_NUM]; + void *gender_out_hw_va[MAX_ENQUE_FRAME_NUM]; + void *is_indian_out_hw_va[MAX_ENQUE_FRAME_NUM]; + void *race_out_hw_va[MAX_ENQUE_FRAME_NUM]; + + dma_addr_t fd_out_hw_pa[FD_LOOP_NUM][OUTPUT_WDMA_WRA_NUM]; + dma_addr_t fd_kernel_pa[FD_LOOP_NUM][KERNEL_RDMA_RA_NUM]; + dma_addr_t attr_out_hw_pa[ATTR_LOOP_NUM][OUTPUT_WDMA_WRA_NUM]; + dma_addr_t attr_kernel_pa[ATTR_LOOP_NUM][KERNEL_RDMA_RA_NUM]; + + dma_addr_t age_out_hw_pa[MAX_ENQUE_FRAME_NUM]; + dma_addr_t gender_out_hw_pa[MAX_ENQUE_FRAME_NUM]; + dma_addr_t is_indian_out_hw_pa[MAX_ENQUE_FRAME_NUM]; + dma_addr_t race_out_hw_pa[MAX_ENQUE_FRAME_NUM]; +}; + +// AIE 3.X +struct aie_fd_fld_para { + void *fld_step_va[FLD_STEP_NUM][FLD_MAX_FRAME]; + void *fld_output_va[FLD_MAX_FRAME]; + dma_addr_t fld_step_pa[FLD_STEP_NUM][FLD_MAX_FRAME]; + dma_addr_t fld_output_pa[FLD_MAX_FRAME]; +}; + +struct imem_buf_info { + void *va; + dma_addr_t pa; + unsigned int size; + unsigned int reserved; +}; + +struct fd_buffer { + u32 dma_addr; /* used by DMA HW */ +}; + +// AIE 3.X +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION +struct mtk_aie_dvfs { + struct device *dev; + struct regulator *reg; + unsigned int clklv_num[MTK_AIE_OPP_SET]; + unsigned int clklv[MTK_AIE_OPP_SET][MTK_AIE_CLK_LEVEL_CNT]; + unsigned int voltlv[MTK_AIE_OPP_SET][MTK_AIE_CLK_LEVEL_CNT]; + unsigned int clklv_idx[MTK_AIE_OPP_SET]; + unsigned int clklv_target[MTK_AIE_OPP_SET]; + unsigned int cur_volt; +}; + +struct mtk_aie_qos_path { + struct icc_path *path; /* cmdq event enum value */ + char dts_name[256]; + unsigned long long bw; +}; + +struct mtk_aie_qos { + struct device *dev; + struct mtk_aie_qos_path *qos_path; +}; +#endif + +struct aie_clocks { + struct clk_bulk_data *clks; + unsigned int clk_num; +}; + +struct mtk_aie_req_work { + struct work_struct work; + struct mtk_aie_dev *fd_dev; +}; + +#ifdef CONFIG_DEBUG_FS +struct aie_trace_info { + char *dump_buffer; + unsigned int dump_size; + unsigned int dump_offset; + char trigger_dump[3]; + char *srcdata_buf; + unsigned int srcdata_size; + char *dstdata_buf; + unsigned int dstdata_size; +}; +#endif + +struct mtk_aie_variant { + unsigned int hw_version; + unsigned int fld_enable; + unsigned int y2r_cfg_size; + unsigned int rs_cfg_size; + unsigned int fd_cfg_size; +}; + +struct mtk_aie_dev { + struct device *dev; + struct mtk_aie_ctx *ctx; + struct v4l2_m2m_dev *m2m_dev; + struct device *larb; + struct aie_para *base_para; + struct aie_attr_para *attr_para; + struct aie_fd_dma_para *dma_para; + + // AIE 3.X + struct aie_fd_fld_para *fld_para; +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION + struct mtk_aie_dvfs *dvfs_info; + struct mtk_aie_qos *qos_info; +#endif + + struct aie_enq_info *aie_cfg; + struct workqueue_struct *frame_done_wq; + void __iomem *fd_base; + const struct mtk_aie_variant *variant; + + /* Input Buffer Pointer */ + struct imem_buf_info rs_cfg_data; + struct imem_buf_info fd_cfg_data; + struct imem_buf_info yuv2rgb_cfg_data; + /* HW Output Buffer Pointer */ + struct imem_buf_info rs_output_hw; + struct imem_buf_info fd_dma_hw; + struct imem_buf_info fd_dma_result_hw; + struct imem_buf_info fd_kernel_hw; + struct imem_buf_info fd_attr_dma_hw; + struct aie_static_info st_info; + + struct aie_reg_cfg reg_cfg; + + // AIE 3.X + /* fld fw buffer */ + struct media_device mdev; + struct video_device vfd; + struct aie_clocks aie_clk; + struct v4l2_device v4l2_dev; + + /* Lock for V4L2 operations */ + struct mutex vfd_lock; + /* Lock for device operations */ + struct mutex dev_lock; + /* Lock for performance optimization */ + struct mutex fd_lock; + struct imem_buf_info fd_fld_step_data; + struct imem_buf_info fd_fld_out_hw; + + int irq; + struct completion fd_job_finished; + struct delayed_work job_timeout_work; + + /* DRAM Buffer Size */ + unsigned int fd_rs_cfg_size; + unsigned int fd_fd_cfg_size; + unsigned int fd_yuv2rgb_cfg_size; + unsigned int attr_fd_cfg_size; + unsigned int attr_yuv2rgb_cfg_size; + + /* HW Output Buffer Size */ + unsigned int rs_pym_out_size[PYM_NUM]; + unsigned int fd_dma_max_size; + unsigned int fd_dma_rst_max_size; + unsigned int fd_fd_kernel_size; + unsigned int fd_attr_kernel_size; + unsigned int fd_attr_dma_max_size; + unsigned int fd_attr_dma_rst_max_size; + // AIE 3.X + /* fld size */ + unsigned int fld_step_size; + unsigned int fld_out_size; + + wait_queue_head_t flushing_waitq; + atomic_t num_composing; + struct mtk_aie_req_work req_work; + unsigned int fd_state; + unsigned int fd_mem_size; + u32 fd_stream_count; + +#ifdef CONFIG_DEBUG_FS + struct aie_trace_info tr_info; +#endif +}; + +struct mtk_aie_ctx { + struct mtk_aie_dev *fd_dev; + struct device *dev; + struct v4l2_fh fh; + struct v4l2_ctrl_handler hdl; + struct v4l2_pix_format_mplane src_fmt; + struct v4l2_meta_format dst_fmt; + struct v4l2_ctrl_aie_init user_init; + struct v4l2_ctrl_aie_param user_param; +}; + +/**************************************************************************/ +/* C L A S S D E C L A R A T I O N */ +/**************************************************************************/ + +void aie_reset(struct mtk_aie_dev *fd); +int aie_init(struct mtk_aie_dev *fd, struct v4l2_ctrl_aie_init *user_init); +void aie_uninit(struct mtk_aie_dev *fd); +void aie_prepare(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg); +void aie_execute(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg); +void aie_irqhandle(struct mtk_aie_dev *fd); +void aie_get_fd_result(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg); +void aie_get_attr_result(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg); +void aie_get_fld_result(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg); +#endif /*__MTK_AIE_H__*/ diff --git a/drivers/media/platform/mediatek/aie/mtk_aie_53.c b/drivers/media/platform/mediatek/aie/mtk_aie_53.c new file mode 100644 index 000000000000..a976b23c5576 --- /dev/null +++ b/drivers/media/platform/mediatek/aie/mtk_aie_53.c @@ -0,0 +1,2031 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Author: Fish Wu <fish.wu@xxxxxxxxxxxx> + */ + +#include <linux/clk.h> +#include <linux/debugfs.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/iopoll.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/remoteproc.h> +#include <linux/types.h> +#include <linux/version.h> +#include <linux/mtk_aie_v4l2_controls.h> + +#include <media/v4l2-event.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-mem2mem.h> +#include <media/videobuf2-core.h> +#include <media/videobuf2-dma-contig.h> + +#include <soc/mediatek/smi.h> + +#include "mtk_aie.h" + +static const struct mtk_aie_variant *mtk_aie_get_variant(struct device *dev); + +static struct clk_bulk_data aie_clks[] = { + { .id = "IMG_IPE" }, + { .id = "IPE_FDVT" }, + { .id = "IPE_TOP" }, + { .id = "IPE_SMI_LARB12" }, +}; + +#ifdef CONFIG_DEBUG_FS +#define AIE_DUMP_BUFFER_SIZE (1 * 1024 * 1024) +#define AIE_DEBUG_RAW_DATA_SIZE (1 * 640 * 480) +static unsigned char srcrawdata[AIE_DEBUG_RAW_DATA_SIZE]; +static unsigned char dstrawdata[AIE_DEBUG_RAW_DATA_SIZE]; +static struct debugfs_blob_wrapper srcdata, dstdata; +#endif + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION +#define AIE_QOS_MAX 4 +#define AIE_QOS_RA_IDX 0 +#define AIE_QOS_RB_IDX 1 +#define AIE_QOS_WA_IDX 2 +#define AIE_QOS_WB_IDX 3 +#define AIE_READ_AVG_BW 213 +#define AIE_WRITE_AVG_BW 145 +#endif + +#define V4L2_CID_MTK_AIE_MAX 2 + +static const struct v4l2_pix_format_mplane mtk_aie_img_fmts[] = { + { + .pixelformat = V4L2_PIX_FMT_NV16M, + .num_planes = 2, + }, + { + .pixelformat = V4L2_PIX_FMT_NV61M, + .num_planes = 2, + }, + { + .pixelformat = V4L2_PIX_FMT_YUYV, + .num_planes = 1, + }, + { + .pixelformat = V4L2_PIX_FMT_YVYU, + .num_planes = 1, + }, + { + .pixelformat = V4L2_PIX_FMT_UYVY, + .num_planes = 1, + }, + { + .pixelformat = V4L2_PIX_FMT_VYUY, + .num_planes = 1, + }, + { + .pixelformat = V4L2_PIX_FMT_GREY, + .num_planes = 1, + }, + { + .pixelformat = V4L2_PIX_FMT_NV12M, + .num_planes = 2, + }, + { + .pixelformat = V4L2_PIX_FMT_NV12, + .num_planes = 1, + }, +}; + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION +static const struct mtk_aie_qos_path aie_qos_path[AIE_QOS_MAX] = { + { NULL, "l12_fdvt_rda", 0 }, + { NULL, "l12_fdvt_rdb", 0 }, + { NULL, "l12_fdvt_wra", 0 }, + { NULL, "l12_fdvt_wrb", 0 } +}; +#endif + +#define NUM_FORMATS ARRAY_SIZE(mtk_aie_img_fmts) + +static inline struct mtk_aie_ctx *fh_to_ctx(struct v4l2_fh *fh) +{ + return container_of(fh, struct mtk_aie_ctx, fh); +} + +static inline struct mtk_aie_ctx *ctrl_to_ctx(const struct v4l2_ctrl *ctrl) +{ + return container_of(ctrl->handler, struct mtk_aie_ctx, hdl); +} + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION +static int mtk_aie_mmdvfs_init(struct mtk_aie_dev *fd) +{ + u64 freq = 0; + int ret = -ENOMEM; + int opp_num = 0, opp_idx = 0, idx = 0, volt = 0; + struct device_node *np = NULL, *child_np = NULL; + struct of_phandle_iterator it; + + fd->dvfs_info = kzalloc(sizeof(*fd->dvfs_info), GFP_KERNEL); + if (!fd->dvfs_info) + return ret; + + fd->dvfs_info->dev = fd->dev; + ret = dev_pm_opp_of_add_table(fd->dvfs_info->dev); + if (ret < 0) { + dev_err(fd->dvfs_info->dev, "fail to init opp table: %d\n", ret); + return ret; + } + + fd->dvfs_info->reg = + devm_regulator_get(fd->dvfs_info->dev, "dvfsrc-vcore"); + if (IS_ERR(fd->dvfs_info->reg)) { + dev_err(fd->dvfs_info->dev, "can't get dvfsrc-vcore\n"); + ret = PTR_ERR(fd->dvfs_info->reg); + fd->dvfs_info->reg = NULL; + return ret; + } + + opp_num = regulator_count_voltages(fd->dvfs_info->reg); + of_for_each_phandle(&it, ret, fd->dvfs_info->dev->of_node, "operating-points-v2", NULL, 0) { + if (!it.node) { + dev_err(fd->dvfs_info->dev, "of_node_get fail\n"); + return ret; + } + np = of_node_get(it.node); + + do { + child_np = of_get_next_available_child(np, child_np); + if (child_np) { + of_property_read_u64(child_np, "opp-hz", &freq); + of_property_read_u32(child_np, "opp-microvolt", &volt); + if (freq == 0 || volt == 0) { + dev_err(fd->dvfs_info->dev, + "%s: [ERROR] parsing zero freq/volt(%d/%d) at idx(%d)\n", + __func__, + freq, + volt, + idx + ); + continue; + } + fd->dvfs_info->clklv[opp_idx][idx] = freq; + fd->dvfs_info->voltlv[opp_idx][idx] = volt; + dev_dbg(fd->dvfs_info->dev, + "[%s] opp=%d, idx=%d, clk=%d volt=%d\n", + __func__, + opp_idx, + idx, + fd->dvfs_info->clklv[opp_idx][idx], + fd->dvfs_info->voltlv[opp_idx][idx] + ); + idx++; + } + } while (child_np); + fd->dvfs_info->clklv_num[opp_idx] = idx; + fd->dvfs_info->clklv_target[opp_idx] = fd->dvfs_info->clklv[opp_idx][0]; + fd->dvfs_info->clklv_idx[opp_idx] = 0; + idx = 0; + opp_idx++; + of_node_put(np); + } + fd->dvfs_info->cur_volt = 0; + + return 0; +} + +static void mtk_aie_mmdvfs_uninit(struct mtk_aie_dev *fd) +{ + int volt = 0; + + if (fd->dvfs_info) { + fd->dvfs_info->cur_volt = volt; + + regulator_set_voltage(fd->dvfs_info->reg, volt, INT_MAX); + + kfree(fd->dvfs_info); + } +} + +static void mtk_aie_mmdvfs_set(struct mtk_aie_dev *fd, bool is_set, + unsigned int level) +{ + int volt = 0, idx = 0, opp_idx = 0; + + if (is_set) { + if (level < fd->dvfs_info->clklv_num[opp_idx]) + idx = level; + } + volt = fd->dvfs_info->voltlv[opp_idx][idx]; + + if (fd->dvfs_info->cur_volt != volt) { + dev_dbg(fd->dvfs_info->dev, + "[%s] volt change opp=%d, idx=%d, clk=%d volt=%d\n", + __func__, + opp_idx, + idx, + fd->dvfs_info->clklv[opp_idx][idx], + fd->dvfs_info->voltlv[opp_idx][idx] + ); + regulator_set_voltage(fd->dvfs_info->reg, volt, INT_MAX); + fd->dvfs_info->cur_volt = volt; + } +} + +static int mtk_aie_mmqos_init(struct mtk_aie_dev *fd) +{ + int idx = 0; + int ret = -ENOMEM; + + fd->qos_info = kzalloc(sizeof(*fd->qos_info), GFP_KERNEL); + if (!fd->qos_info) + return ret; + + fd->qos_info->dev = fd->dev; + fd->qos_info->qos_path = (struct mtk_aie_qos_path *)aie_qos_path; + + for (idx = 0; idx < AIE_QOS_MAX; idx++) { + fd->qos_info->qos_path[idx].path = + of_mtk_icc_get(fd->qos_info->dev, fd->qos_info->qos_path[idx].dts_name); + fd->qos_info->qos_path[idx].bw = 0; + dev_dbg(fd->qos_info->dev, + "[%s] idx=%d, path=%p, name=%s, bw=%llu\n", + __func__, + idx, + fd->qos_info->qos_path[idx].path, + fd->qos_info->qos_path[idx].dts_name, + fd->qos_info->qos_path[idx].bw + ); + } + return 0; +} + +static void mtk_aie_mmqos_uninit(struct mtk_aie_dev *fd) +{ + int idx = 0; + + if (fd->qos_info) { + for (idx = 0; idx < AIE_QOS_MAX; idx++) { + if (!fd->qos_info->qos_path[idx].path) { + dev_dbg(fd->qos_info->dev, + "[%s] path of idx(%d) is NULL\n", + __func__, + idx + ); + continue; + } + dev_dbg(fd->qos_info->dev, + "[%s] idx=%d, path=%p, bw=%llu\n", + __func__, + idx, + fd->qos_info->qos_path[idx].path, + fd->qos_info->qos_path[idx].bw + ); + fd->qos_info->qos_path[idx].bw = 0; + mtk_icc_set_bw(fd->qos_info->qos_path[idx].path, 0, 0); + } + kfree(fd->qos_info); + } +} + +static void mtk_aie_mmqos_set(struct mtk_aie_dev *fd, bool is_set) +{ + int r_bw = 0; + int w_bw = 0; + int idx = 0; + + if (is_set) { + r_bw = AIE_READ_AVG_BW; + w_bw = AIE_WRITE_AVG_BW; + } + + for (idx = 0; idx < AIE_QOS_MAX; idx++) { + if (!fd->qos_info->qos_path[idx].path) { + dev_dbg(fd->qos_info->dev, + "[%s] path of idx(%d) is NULL\n", + __func__, + idx + ); + continue; + } + + if (idx == AIE_QOS_RA_IDX && + fd->qos_info->qos_path[idx].bw != r_bw) { + dev_dbg(fd->qos_info->dev, + "[%s] idx=%d, path=%p, bw=%llu/%d,\n", + __func__, + idx, + fd->qos_info->qos_path[idx].path, + fd->qos_info->qos_path[idx].bw, + r_bw + ); + fd->qos_info->qos_path[idx].bw = r_bw; + mtk_icc_set_bw(fd->qos_info->qos_path[idx].path, + MBps_to_icc(fd->qos_info->qos_path[idx].bw), + 0 + ); + } + + if (idx == AIE_QOS_WA_IDX && + fd->qos_info->qos_path[idx].bw != w_bw) { + dev_dbg(fd->qos_info->dev, + "[%s] idx=%d, path=%p, bw=%llu/%d,\n", + __func__, + idx, + fd->qos_info->qos_path[idx].path, + fd->qos_info->qos_path[idx].bw, + w_bw + ); + fd->qos_info->qos_path[idx].bw = w_bw; + mtk_icc_set_bw(fd->qos_info->qos_path[idx].path, + MBps_to_icc(fd->qos_info->qos_path[idx].bw), + 0 + ); + } + } +} +#endif + +static int mtk_aie_hw_enable(struct mtk_aie_dev *fd) +{ + struct mtk_aie_ctx *ctx = fd->ctx; + + /* initial value */ + dev_info(fd->dev, "init param : max w:%d, max h:%d", + ctx->user_init.max_img_width, ctx->user_init.max_img_height); + + dev_info(fd->dev, "init param : p_w:%d, p_h:%d, f thread:%d", + ctx->user_init.pyramid_width, + ctx->user_init.pyramid_height, + ctx->user_init.feature_threshold); + + return aie_init(fd, &ctx->user_init); +} + +static void mtk_aie_hw_job_finish(struct mtk_aie_dev *fd, + enum vb2_buffer_state vb_state) +{ + struct mtk_aie_ctx *ctx = NULL; + struct vb2_v4l2_buffer *src_vbuf = NULL, *dst_vbuf = NULL; + + pm_runtime_put(fd->dev); + ctx = v4l2_m2m_get_curr_priv(fd->m2m_dev); + if (!ctx) { + dev_err(fd->dev, "Failed to do v4l2_m2m_get_curr_priv!\n"); + } else { + src_vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + if (src_vbuf && dst_vbuf) + v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, true); + if (src_vbuf) + v4l2_m2m_buf_done(src_vbuf, vb_state); + if (dst_vbuf) + v4l2_m2m_buf_done(dst_vbuf, vb_state); + if (src_vbuf && dst_vbuf) + v4l2_m2m_job_finish(fd->m2m_dev, ctx->fh.m2m_ctx); + } + complete_all(&fd->fd_job_finished); +} + +static int mtk_aie_hw_connect(struct mtk_aie_dev *fd) +{ + if (mtk_aie_hw_enable(fd)) + return -EINVAL; +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION + mtk_aie_mmdvfs_set(fd, 1, 0); + mtk_aie_mmqos_set(fd, 1); +#endif + + return 0; +} + +static void mtk_aie_hw_disconnect(struct mtk_aie_dev *fd) +{ +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION + mtk_aie_mmqos_set(fd, 0); + mtk_aie_mmdvfs_set(fd, 0, 0); +#endif + aie_uninit(fd); +} + +static int mtk_aie_hw_job_exec(struct mtk_aie_dev *fd) +{ + pm_runtime_get_sync(fd->dev); + + reinit_completion(&fd->fd_job_finished); + schedule_delayed_work(&fd->job_timeout_work, + msecs_to_jiffies(MTK_FD_HW_TIMEOUT_IN_MSEC) + ); + + return 0; +} + +static int mtk_aie_vb2_buf_out_validate(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); + + if (v4l2_buf->field == V4L2_FIELD_ANY) + v4l2_buf->field = V4L2_FIELD_NONE; + if (v4l2_buf->field != V4L2_FIELD_NONE) + return -EINVAL; + + return 0; +} + +static int mtk_aie_vb2_buf_prepare(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vb2_queue *vq = vb->vb2_queue; + struct mtk_aie_ctx *ctx = vb2_get_drv_priv(vq); + struct device *dev = ctx->dev; + struct v4l2_pix_format_mplane *pixfmt = NULL; + int ret = 0; + + switch (vq->type) { + case V4L2_BUF_TYPE_META_CAPTURE: + if (vb2_plane_size(vb, 0) < ctx->dst_fmt.buffersize) { + dev_err(dev, "meta size %lu is too small\n", vb2_plane_size(vb, 0)); + ret = -EINVAL; + } else { + vb2_set_plane_payload(vb, 0, ctx->dst_fmt.buffersize); + } + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + pixfmt = &ctx->src_fmt; + + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + + if (vb->num_planes > 2 || vbuf->field != V4L2_FIELD_NONE) { + dev_dbg(dev, + "plane %d or field %d not supported\n", + vb->num_planes, + vbuf->field + ); + ret = -EINVAL; + } + + if (vb2_plane_size(vb, 0) < pixfmt->plane_fmt[0].sizeimage) { + dev_dbg(dev, + "plane 0 %lu is too small than %x\n", + vb2_plane_size(vb, 0), + pixfmt->plane_fmt[0].sizeimage + ); + ret = -EINVAL; + } else { + vb2_set_plane_payload(vb, 0, pixfmt->plane_fmt[0].sizeimage); + } + + if (pixfmt->num_planes == 2 && + vb2_plane_size(vb, 1) < pixfmt->plane_fmt[1].sizeimage) { + dev_dbg(dev, + "plane 1 %lu is too small than %x\n", + vb2_plane_size(vb, 1), + pixfmt->plane_fmt[1].sizeimage + ); + ret = -EINVAL; + } else { + vb2_set_plane_payload(vb, 1, pixfmt->plane_fmt[1].sizeimage); + } + break; + } + + return ret; +} + +static void mtk_aie_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct mtk_aie_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +} + +static int mtk_aie_vb2_queue_setup(struct vb2_queue *vq, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct mtk_aie_ctx *ctx = vb2_get_drv_priv(vq); + struct device *dev = ctx->dev; + unsigned int size[2] = { 0, 0 }; + unsigned int plane = 0; + + switch (vq->type) { + case V4L2_BUF_TYPE_META_CAPTURE: + size[0] = ctx->dst_fmt.buffersize; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + size[0] = ctx->src_fmt.plane_fmt[0].sizeimage; + size[1] = ctx->src_fmt.plane_fmt[1].sizeimage; + break; + } + + dev_info(dev, "vq type =%d, size[0]=%d, size[1]=%d\n", vq->type, size[0], size[1]); + + if (*num_planes > 2) + return -EINVAL; + + *num_buffers = clamp_val(*num_buffers, 1, VB2_MAX_FRAME); + + if (*num_planes == 0) { + if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { + sizes[0] = ctx->dst_fmt.buffersize; + *num_planes = 1; + return 0; + } + + *num_planes = ctx->src_fmt.num_planes; + if (*num_planes > 2) + return -EINVAL; + for (plane = 0; plane < *num_planes; plane++) + sizes[plane] = ctx->src_fmt.plane_fmt[plane].sizeimage; + + return 0; + } + + return 0; +} + +static int mtk_aie_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct mtk_aie_ctx *ctx = vb2_get_drv_priv(vq); + struct mtk_aie_dev *fd = NULL; + + if (!ctx) + return -EINVAL; + + fd = ctx->fd_dev; + + if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + fd->fd_stream_count++; + if (fd->fd_stream_count == 1) + return mtk_aie_hw_connect(ctx->fd_dev); + } + + return 0; +} + +static void aie_dumpinfo(struct mtk_aie_dev *fd) +{ + unsigned int i = 0; + u32 *cfg_value = NULL; + + for (i = 0; i < 0x158; i = i + 4) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "Reg: %x %x\n", + i, + readl(fd->fd_base + i) + ); + } + for (i = 0x200; i < 0x3F8; i = i + 4) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "Dma Reg: %x %x\n", + i, + readl(fd->fd_base + i) + ); + } + if (fd->aie_cfg->sel_mode == FDMODE) { + cfg_value = (u32 *)fd->base_para->fd_yuv2rgb_cfg_va; + for (i = 0; i < fd->fd_yuv2rgb_cfg_size / 4; i++) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "YUV config: %x, %x\n", + i, + cfg_value[i] + ); + } + cfg_value = (u32 *)fd->base_para->fd_rs_cfg_va; + for (i = 0; i < fd->fd_rs_cfg_size / 4; i++) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "RS config: %x, %x\n", + i, + cfg_value[i] + ); + } + cfg_value = (u32 *)fd->base_para->fd_fd_cfg_va; + for (i = 0; i < fd->fd_fd_cfg_size / 4; i++) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "FD config: %x, %x\n", + i, + cfg_value[i] + ); + } + } + + if (fd->aie_cfg->sel_mode == ATTRIBUTEMODE) { + cfg_value = (u32 *)fd->base_para->attr_yuv2rgb_cfg_va; + for (i = 0; i < fd->fd_yuv2rgb_cfg_size / 4; i++) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "YUV config: %x, %x\n", + i, + cfg_value[i] + ); + } + cfg_value = (u32 *)fd->base_para->attr_fd_cfg_va; + for (i = 0; i < fd->fd_fd_cfg_size / 4; i++) { + fd->tr_info.dump_offset += + scnprintf(fd->tr_info.dump_buffer + fd->tr_info.dump_offset, + fd->tr_info.dump_size - fd->tr_info.dump_offset, + "FD config: %x, %x\n", + i, + cfg_value[i] + ); + } + } + + if (fd->tr_info.srcdata_size <= AIE_DEBUG_RAW_DATA_SIZE) + memcpy(srcrawdata, fd->tr_info.srcdata_buf, fd->tr_info.srcdata_size); + + if (fd->tr_info.dstdata_size <= AIE_DEBUG_RAW_DATA_SIZE) + memcpy(dstrawdata, fd->tr_info.dstdata_buf, fd->tr_info.dstdata_size); +} + +static void mtk_aie_job_timeout_work(struct work_struct *work) +{ + struct mtk_aie_dev *fd = + container_of(work, struct mtk_aie_dev, job_timeout_work.work); + + dev_err(fd->dev, "FD Job timeout!"); + + dev_dbg(fd->dev, + "%s result result1: %x, %x, %x", + __func__, + readl(fd->fd_base + AIE_RESULT_0_REG), + readl(fd->fd_base + AIE_RESULT_1_REG), + readl(fd->fd_base + AIE_DMA_CTL_REG) + ); + + fd->aie_cfg->irq_status = readl(fd->fd_base + AIE_INT_EN_REG); + +#ifdef CONFIG_DEBUG_FS + if (fd->aie_cfg->irq_status & 0x00010000 || + fd->aie_cfg->irq_status & 0x00100000 || + fd->aie_cfg->irq_status & 0x01000000) + aie_dumpinfo(fd); +#endif + + if (fd->aie_cfg->sel_mode == ATTRIBUTEMODE) + dev_dbg(fd->dev, + "[ATTRMODE] w_idx = %d, r_idx = %d\n", + fd->attr_para->w_idx, + fd->attr_para->r_idx + ); + + aie_irqhandle(fd); + aie_reset(fd); + atomic_dec(&fd->num_composing); + mtk_aie_hw_job_finish(fd, VB2_BUF_STATE_ERROR); + wake_up(&fd->flushing_waitq); +} + +static int mtk_aie_job_wait_finish(struct mtk_aie_dev *fd) +{ + return wait_for_completion_timeout(&fd->fd_job_finished, msecs_to_jiffies(1000)); +} + +static void mtk_aie_vb2_stop_streaming(struct vb2_queue *vq) +{ + struct mtk_aie_ctx *ctx = vb2_get_drv_priv(vq); + struct mtk_aie_dev *fd = ctx->fd_dev; + struct vb2_v4l2_buffer *vb = NULL; + struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; + struct v4l2_m2m_queue_ctx *queue_ctx; + + if (!mtk_aie_job_wait_finish(fd)) + dev_info(fd->dev, "wait job finish timeout\n"); + + if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + fd->fd_stream_count--; + if (fd->fd_stream_count > 0) + dev_info(fd->dev, "stop: fd_stream_count = %d\n", fd->fd_stream_count); + else + mtk_aie_hw_disconnect(fd); + } + + queue_ctx = V4L2_TYPE_IS_OUTPUT(vq->type) ? &m2m_ctx->out_q_ctx : + &m2m_ctx->cap_q_ctx; + while ((vb = v4l2_m2m_buf_remove(queue_ctx))) + v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); +} + +static void mtk_aie_vb2_request_complete(struct vb2_buffer *vb) +{ + struct mtk_aie_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); +} + +static int mtk_aie_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + struct mtk_aie_dev *fd = video_drvdata(file); + struct device *dev = fd->dev; + + strscpy(cap->driver, dev_driver_string(dev), sizeof(cap->driver)); + strscpy(cap->card, dev_driver_string(dev), sizeof(cap->card)); + + cap->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_STREAMING | V4L2_CAP_META_CAPTURE; + cap->capabilities = V4L2_CAP_DEVICE_CAPS | cap->device_caps; + + return 0; +} + +static int mtk_aie_enum_fmt_out_mp(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + if (f->index >= NUM_FORMATS) + return -EINVAL; + + f->pixelformat = mtk_aie_img_fmts[f->index].pixelformat; + return 0; +} + +static void mtk_aie_fill_pixfmt_mp(struct v4l2_pix_format_mplane *dfmt, + const struct v4l2_pix_format_mplane *sfmt) +{ + dfmt->field = V4L2_FIELD_NONE; + dfmt->colorspace = V4L2_COLORSPACE_BT2020; + dfmt->num_planes = sfmt->num_planes; + dfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + dfmt->quantization = V4L2_QUANTIZATION_DEFAULT; + dfmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(dfmt->colorspace); + dfmt->pixelformat = sfmt->pixelformat; + + /* Keep user setting as possible */ + dfmt->width = clamp(dfmt->width, MTK_FD_OUTPUT_MIN_WIDTH, + MTK_FD_OUTPUT_MAX_WIDTH); + dfmt->height = clamp(dfmt->height, MTK_FD_OUTPUT_MIN_HEIGHT, + MTK_FD_OUTPUT_MAX_HEIGHT); + + dfmt->plane_fmt[0].bytesperline = ALIGN(dfmt->width, 16); + dfmt->plane_fmt[1].bytesperline = ALIGN(dfmt->width, 16); + + if (sfmt->num_planes == 2) { + dfmt->plane_fmt[0].sizeimage = + dfmt->height * dfmt->plane_fmt[0].bytesperline; + if (sfmt->pixelformat == V4L2_PIX_FMT_NV12M) + dfmt->plane_fmt[1].sizeimage = + dfmt->height * dfmt->plane_fmt[1].bytesperline / + 2; + else + dfmt->plane_fmt[1].sizeimage = + dfmt->height * dfmt->plane_fmt[1].bytesperline; + } else { + if (sfmt->pixelformat == V4L2_PIX_FMT_NV12) + dfmt->plane_fmt[0].sizeimage = + dfmt->height * dfmt->plane_fmt[0].bytesperline * + 3 / 2; + else + dfmt->plane_fmt[0].sizeimage = + dfmt->height * dfmt->plane_fmt[0].bytesperline; + } +} + +static const struct v4l2_pix_format_mplane *mtk_aie_find_fmt(u32 format) +{ + unsigned int i = 0; + + for (i = 0; i < NUM_FORMATS; i++) { + if (mtk_aie_img_fmts[i].pixelformat == format) + return &mtk_aie_img_fmts[i]; + } + + return NULL; +} + +static int mtk_aie_try_fmt_out_mp(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + const struct v4l2_pix_format_mplane *fmt = NULL; + + fmt = mtk_aie_find_fmt(pix_mp->pixelformat); + if (!fmt) + fmt = &mtk_aie_img_fmts[0]; /* Get default img fmt */ + + mtk_aie_fill_pixfmt_mp(pix_mp, fmt); + return 0; +} + +static int mtk_aie_g_fmt_out_mp(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct mtk_aie_ctx *ctx = fh_to_ctx(fh); + + f->fmt.pix_mp = ctx->src_fmt; + + return 0; +} + +static int mtk_aie_s_fmt_out_mp(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct mtk_aie_ctx *ctx = fh_to_ctx(fh); + struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + struct mtk_aie_dev *fd = ctx->fd_dev; + const struct v4l2_pix_format_mplane *fmt = NULL; + + if (!vq) { + dev_err(fd->dev, "%s vq is NULL!\n", __func__); + return -EINVAL; + } + + /* Change not allowed if queue is streaming. */ + if (vb2_is_streaming(vq)) + return -EBUSY; + + fmt = mtk_aie_find_fmt(f->fmt.pix_mp.pixelformat); + if (!fmt) + fmt = &mtk_aie_img_fmts[0]; /* Get default img fmt */ + else if (&fd->ctx->fh != file->private_data) + return -EBUSY; + if (fd->ctx != ctx) + fd->ctx = ctx; + + mtk_aie_fill_pixfmt_mp(&f->fmt.pix_mp, fmt); + ctx->src_fmt = f->fmt.pix_mp; + + return 0; +} + +static int mtk_aie_enum_fmt_meta_cap(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + if (f->index) + return -EINVAL; + + strscpy(f->description, "Face detection result", + sizeof(f->description)); + + f->pixelformat = V4L2_META_FMT_MTFD_RESULT; + f->flags = 0; + + return 0; +} + +static int mtk_aie_g_fmt_meta_cap(struct file *file, void *fh, + struct v4l2_format *f) +{ + f->fmt.meta.dataformat = V4L2_META_FMT_MTFD_RESULT; + f->fmt.meta.buffersize = sizeof(struct aie_enq_info); + + return 0; +} + +static const struct vb2_ops mtk_aie_vb2_ops = { + .queue_setup = mtk_aie_vb2_queue_setup, + .buf_out_validate = mtk_aie_vb2_buf_out_validate, + .buf_prepare = mtk_aie_vb2_buf_prepare, + .buf_queue = mtk_aie_vb2_buf_queue, + .start_streaming = mtk_aie_vb2_start_streaming, + .stop_streaming = mtk_aie_vb2_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .buf_request_complete = mtk_aie_vb2_request_complete, +}; + +static const struct v4l2_ioctl_ops mtk_aie_v4l2_video_out_ioctl_ops = { + .vidioc_querycap = mtk_aie_querycap, + .vidioc_enum_fmt_vid_out = mtk_aie_enum_fmt_out_mp, + .vidioc_g_fmt_vid_out_mplane = mtk_aie_g_fmt_out_mp, + .vidioc_s_fmt_vid_out_mplane = mtk_aie_s_fmt_out_mp, + .vidioc_try_fmt_vid_out_mplane = mtk_aie_try_fmt_out_mp, + .vidioc_enum_fmt_meta_cap = mtk_aie_enum_fmt_meta_cap, + .vidioc_g_fmt_meta_cap = mtk_aie_g_fmt_meta_cap, + .vidioc_s_fmt_meta_cap = mtk_aie_g_fmt_meta_cap, + .vidioc_try_fmt_meta_cap = mtk_aie_g_fmt_meta_cap, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static int mtk_aie_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct mtk_aie_ctx *ctx = priv; + int ret = -EINVAL; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->supports_requests = true; + src_vq->drv_priv = ctx; + src_vq->ops = &mtk_aie_vb2_ops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->fd_dev->vfd_lock; + src_vq->dev = ctx->fd_dev->v4l2_dev.dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_META_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->ops = &mtk_aie_vb2_ops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->fd_dev->vfd_lock; + dst_vq->dev = ctx->fd_dev->v4l2_dev.dev; + + return vb2_queue_init(dst_vq); +} + +static int mtk_aie_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct mtk_aie_ctx *ctx = ctrl_to_ctx(ctrl); + struct v4l2_ctrl_aie_init *p_aie_init = NULL; + struct v4l2_ctrl_aie_param *p_aie_param = NULL; + + if (!ctx) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_MTK_AIE_INIT: + p_aie_init = ctrl->p_new.p; + memcpy(&ctx->user_init, p_aie_init, sizeof(struct v4l2_ctrl_aie_init)); + break; + + case V4L2_CID_MTK_AIE_PARAM: + p_aie_param = ctrl->p_new.p; + memcpy(&ctx->user_param, p_aie_param, sizeof(struct v4l2_ctrl_aie_param)); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static const struct v4l2_ctrl_ops aie_ctrl_ops = { + .s_ctrl = mtk_aie_s_ctrl, +}; + +static void mtk_aie_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, + u32 from_idx, union v4l2_ctrl_ptr ptr) +{ + struct v4l2_ctrl_aie_init *p_aie_init = NULL; + struct v4l2_ctrl_aie_param *p_aie_param = NULL; + + switch (ctrl->id) { + case V4L2_CID_MTK_AIE_INIT: + p_aie_init = ptr.p; + memset(p_aie_init, 0, sizeof(struct v4l2_ctrl_aie_init)); + break; + + case V4L2_CID_MTK_AIE_PARAM: + p_aie_param = ptr.p; + memset(p_aie_param, 0, sizeof(struct v4l2_ctrl_aie_param)); + break; + + default: + break; + } +} + +static int mtk_aie_ctrl_type_op_validate(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr) +{ + struct mtk_aie_ctx *ctx = ctrl_to_ctx(ctrl); + struct mtk_aie_dev *fd = NULL; + struct v4l2_ctrl_aie_init *p_aie_init = NULL; + struct v4l2_ctrl_aie_param *p_aie_param = NULL; + + if (!ctx) + return -EINVAL; + + fd = ctx->fd_dev; + + switch (ctrl->id) { + case V4L2_CID_MTK_AIE_PARAM: + p_aie_param = ptr.p; + + switch (p_aie_param->fd_mode) { + case FDMODE: + case ATTRIBUTEMODE: + case FLDMODE: + break; + default: + dev_err(ctx->dev, "AIE err: mode: %d\n", p_aie_param->fd_mode); + return -EINVAL; + } + + switch (p_aie_param->src_img_fmt) { + case FMT_YUV_2P: + case FMT_YVU_2P: + case FMT_YUYV: + case FMT_YVYU: + case FMT_UYVY: + case FMT_VYUY: + case FMT_MONO: + case FMT_YUV420_2P: + case FMT_YUV420_1P: + break; + default: + dev_err(ctx->dev, "AIE err: fmt: %d\n", p_aie_param->src_img_fmt); + return -EINVAL; + } + + if (p_aie_param->src_img_width > + fd->base_para->max_img_width || + p_aie_param->src_img_height > + fd->base_para->max_img_height || + p_aie_param->src_img_width == 0 || + p_aie_param->src_img_height == 0) { + dev_err(fd->dev, "AIE err: Src_WD: %d Src_HT: %d\n", + p_aie_param->src_img_width, + p_aie_param->src_img_height); + + dev_err(fd->dev, + "AIE err: MAX_Src_WD: %d MAX_Src_HT: %d\n", + fd->base_para->max_img_width, + fd->base_para->max_img_height); + + return -EINVAL; + } + + if (p_aie_param->pyramid_base_width + > fd->base_para->max_pyramid_width || + p_aie_param->pyramid_base_height + > fd->base_para->max_pyramid_height || + p_aie_param->number_of_pyramid > 3 || + p_aie_param->number_of_pyramid <= 0) { + dev_err(fd->dev, "AIE err: base w: %d h: %d num: %d\n", + p_aie_param->pyramid_base_width, + p_aie_param->pyramid_base_height, + p_aie_param->number_of_pyramid); + + dev_err(fd->dev, "AIE err: max w: %d h: %d\n", + fd->base_para->max_pyramid_width, + fd->base_para->max_pyramid_height); + + return -EINVAL; + } + + break; + + case V4L2_CID_MTK_AIE_INIT: + p_aie_init = ptr.p; + if (!p_aie_init->max_img_width || !p_aie_init->max_img_height || + !p_aie_init->pyramid_width || !p_aie_init->pyramid_height) { + dev_err(fd->dev, + "AIE INIT err: max_w: %d max_h: %d, p_w: %d p_h: %d\n", + p_aie_init->max_img_width, p_aie_init->max_img_height, + p_aie_init->pyramid_width, p_aie_init->pyramid_height); + + return -EINVAL; + } + + break; + + default: + return -EINVAL; + } + + return 0; +} + +static const struct v4l2_ctrl_type_ops aie_ctrl_type_ops = { + .equal = v4l2_ctrl_type_op_equal, + .init = mtk_aie_ctrl_type_op_init, + .log = v4l2_ctrl_type_op_log, + .validate = mtk_aie_ctrl_type_op_validate, +}; + +static struct v4l2_ctrl_config mtk_aie_controls[] = { + { + .ops = &aie_ctrl_ops, + .type_ops = &aie_ctrl_type_ops, + .id = V4L2_CID_MTK_AIE_INIT, + .name = "FD detection init", + .type = V4L2_CTRL_TYPE_AIE_INIT, + .elem_size = sizeof(struct v4l2_ctrl_aie_init), + }, + { + .ops = &aie_ctrl_ops, + .type_ops = &aie_ctrl_type_ops, + .id = V4L2_CID_MTK_AIE_PARAM, + .name = "FD detection param", + .type = V4L2_CTRL_TYPE_AIE_PARAM, + .elem_size = sizeof(struct v4l2_ctrl_aie_param), + }, +}; + +static int mtk_aie_ctrls_setup(struct mtk_aie_ctx *ctx) +{ + struct v4l2_ctrl_handler *hdl = &ctx->hdl; + int i; + + v4l2_ctrl_handler_init(hdl, V4L2_CID_MTK_AIE_MAX); + if (hdl->error) + return hdl->error; + + for (i = 0; i < ARRAY_SIZE(mtk_aie_controls); i++) { + v4l2_ctrl_new_custom(hdl, &mtk_aie_controls[i], ctx); + if (hdl->error) { + v4l2_ctrl_handler_free(hdl); + dev_err(ctx->dev, "Failed to register controls:%d", i); + return hdl->error; + } + } + + ctx->fh.ctrl_handler = &ctx->hdl; + v4l2_ctrl_handler_setup(hdl); + + return 0; +} + +static void init_ctx_fmt(struct mtk_aie_ctx *ctx) +{ + struct v4l2_pix_format_mplane *src_fmt = &ctx->src_fmt; + struct v4l2_meta_format *dst_fmt = &ctx->dst_fmt; + + /* Initialize M2M source fmt */ + src_fmt->width = MTK_FD_OUTPUT_MAX_WIDTH; + src_fmt->height = MTK_FD_OUTPUT_MAX_HEIGHT; + mtk_aie_fill_pixfmt_mp(src_fmt, &mtk_aie_img_fmts[0]); + + /* Initialize M2M destination fmt */ + dst_fmt->buffersize = sizeof(struct aie_enq_info); + dst_fmt->dataformat = V4L2_META_FMT_MTFD_RESULT; +} + +/* + * V4L2 file operations. + */ +static int mtk_vfd_open(struct file *filp) +{ + struct mtk_aie_dev *fd = video_drvdata(filp); + struct video_device *vdev = video_devdata(filp); + struct mtk_aie_ctx *ctx = NULL; + int ret = -EINVAL; + + mutex_lock(&fd->dev_lock); + + if (fd->fd_state & STATE_OPEN) { + dev_info(fd->dev, "vfd_open again"); + ret = -EBUSY; + goto err_unlock; + } + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + ret = -ENOMEM; + goto err_unlock; + } + + ctx->fd_dev = fd; + ctx->dev = fd->dev; + fd->ctx = ctx; + + v4l2_fh_init(&ctx->fh, vdev); + filp->private_data = &ctx->fh; + + init_ctx_fmt(ctx); + + ret = mtk_aie_ctrls_setup(ctx); + if (ret) { + dev_err(ctx->dev, "Failed to set up controls:%d\n", ret); + goto err_fh_exit; + } + ctx->fh.m2m_ctx = + v4l2_m2m_ctx_init(fd->m2m_dev, ctx, &mtk_aie_queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); + goto err_free_ctrl_handler; + } + v4l2_fh_add(&ctx->fh); + fd->fd_state |= STATE_OPEN; + + mutex_unlock(&fd->dev_lock); + + return 0; +err_free_ctrl_handler: + v4l2_ctrl_handler_free(&ctx->hdl); +err_fh_exit: + v4l2_fh_exit(&ctx->fh); + kfree(ctx); +err_unlock: + mutex_unlock(&fd->dev_lock); + + return ret; +} + +static int mtk_vfd_release(struct file *filp) +{ + struct mtk_aie_ctx *ctx = + container_of(filp->private_data, struct mtk_aie_ctx, fh); + struct mtk_aie_dev *fd = video_drvdata(filp); + + mutex_lock(&fd->dev_lock); + + fd->fd_state &= ~STATE_OPEN; + + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + v4l2_ctrl_handler_free(&ctx->hdl); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + + kfree(ctx); + + mutex_unlock(&fd->dev_lock); + + return 0; +} + +static __poll_t mtk_vfd_fop_poll(struct file *file, poll_table *wait) +{ + struct mtk_aie_ctx *ctx = + container_of(file->private_data, struct mtk_aie_ctx, fh); + + struct mtk_aie_dev *fd = ctx->fd_dev; + + if (fd->fd_state & STATE_INIT) { + if (!mtk_aie_job_wait_finish(ctx->fd_dev)) { + dev_info(ctx->dev, "wait job finish timeout from poll\n"); + return EPOLLERR; + } + } + + return v4l2_m2m_fop_poll(file, wait); +} + +static const struct v4l2_file_operations fd_video_fops = { + .owner = THIS_MODULE, + .open = mtk_vfd_open, + .release = mtk_vfd_release, + .poll = mtk_vfd_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static int mtk_aie_job_ready(void *priv) +{ + struct mtk_aie_ctx *ctx = priv; + struct mtk_aie_dev *fd = ctx->fd_dev; + struct vb2_v4l2_buffer *src_buf = NULL, *dst_buf = NULL; + struct fd_buffer src_img[2] = {}; + void *plane_vaddr = NULL; + int ret = 1; + + if (!ctx->fh.m2m_ctx) { + dev_info(fd->dev, "Memory-to-memory context is NULL\n"); + return 0; + } + + if (!(fd->fd_state & STATE_OPEN)) { + dev_err(fd->dev, "%s fd state fail: %d\n", __func__, fd->fd_state); + return 0; + } + + mutex_lock(&fd->fd_lock); + + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + + if (!src_buf || !dst_buf) { + dev_err(fd->dev, "src or dst buf is NULL\n"); + ret = 0; + goto err_unlock; + } + + if (!(fd->fd_state & STATE_INIT)) { + dev_err(fd->dev, "%s fd state fail: %d\n", __func__, fd->fd_state); + ret = 0; + goto err_unlock; + } + + plane_vaddr = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); + if (!plane_vaddr) { + dev_info(fd->dev, "Failed to get plane virtual address\n"); + ret = 0; + goto err_unlock; + } + +#ifdef CONFIG_DEBUG_FS + fd->tr_info.srcdata_buf = vb2_plane_vaddr(&src_buf->vb2_buf, 0); + fd->tr_info.srcdata_size = vb2_get_plane_payload(&src_buf->vb2_buf, 0); + fd->tr_info.dstdata_buf = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); + fd->tr_info.dstdata_size = vb2_get_plane_payload(&dst_buf->vb2_buf, 0); +#endif + + v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, &ctx->hdl); + + fd->aie_cfg = (struct aie_enq_info *)plane_vaddr; + + memset(fd->aie_cfg, 0, sizeof(struct aie_enq_info)); + + memcpy(fd->aie_cfg, &ctx->user_param, sizeof(struct v4l2_ctrl_aie_param)); + + if (fd->variant->fld_enable) { + fd->aie_cfg->fld_face_num = ctx->user_param.fld_face_num; + memcpy(fd->aie_cfg->fld_input, + ctx->user_param.fld_input, + FLD_MAX_FRAME * sizeof(struct fld_crop_rip_rop) + ); + } + + src_img[0].dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + + if (ctx->src_fmt.num_planes == 2) { + src_img[1].dma_addr = + vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); + } + + if ((fd->aie_cfg->sel_mode == FDMODE || fd->aie_cfg->sel_mode == ATTRIBUTEMODE) && + fd->aie_cfg->src_img_fmt == FMT_YUV420_1P) { + src_img[1].dma_addr = + src_img[0].dma_addr + + ctx->user_param.src_img_stride * + ctx->user_param.src_img_height; + } + + fd->aie_cfg->src_img_addr = src_img[0].dma_addr; + fd->aie_cfg->src_img_addr_uv = src_img[1].dma_addr; + + aie_prepare(fd, fd->aie_cfg); + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION + mtk_aie_mmdvfs_set(fd, 1, fd->aie_cfg->freq_level); +#endif + +err_unlock: + mutex_unlock(&fd->fd_lock); + + if (src_buf) { + /* Complete request controls if any */ + v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->hdl); + } + + return ret; +} + +static void mtk_aie_device_run(void *priv) +{ + struct mtk_aie_ctx *ctx = priv; + struct mtk_aie_dev *fd = ctx->fd_dev; + int ret = 0; + + ret = mtk_aie_job_ready(priv); + if (ret != 1) { + dev_err(fd->dev, "Failed to run job ready\n"); + return; + } + + atomic_inc(&fd->num_composing); + mtk_aie_hw_job_exec(fd); + aie_execute(fd, fd->aie_cfg); +} + +static struct v4l2_m2m_ops fd_m2m_ops = { + .device_run = mtk_aie_device_run, +}; + +static const struct media_device_ops fd_m2m_media_ops = { + .req_validate = vb2_request_validate, + .req_queue = v4l2_m2m_request_queue, +}; + +static int mtk_aie_video_device_register(struct mtk_aie_dev *fd) +{ + struct video_device *vfd = &fd->vfd; + struct v4l2_m2m_dev *m2m_dev = fd->m2m_dev; + struct device *dev = fd->dev; + int ret = -EINVAL; + + vfd->fops = &fd_video_fops; + vfd->release = video_device_release_empty; + vfd->lock = &fd->vfd_lock; + vfd->v4l2_dev = &fd->v4l2_dev; + vfd->vfl_dir = VFL_DIR_M2M; + vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_META_CAPTURE; + vfd->ioctl_ops = &mtk_aie_v4l2_video_out_ioctl_ops; + + strscpy(vfd->name, dev_driver_string(dev), sizeof(vfd->name)); + + video_set_drvdata(vfd, fd); + + ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); + if (ret) { + dev_err(dev, "Failed to register video device\n"); + goto err_free_dev; + } +#ifdef CONFIG_MEDIA_CONTROLLER + ret = v4l2_m2m_register_media_controller(m2m_dev, vfd, MEDIA_ENT_F_PROC_VIDEO_STATISTICS); + if (ret) { + dev_err(dev, "Failed to init mem2mem media controller\n"); + goto err_unreg_video; + } +#endif + return 0; +#ifdef CONFIG_MEDIA_CONTROLLER +err_unreg_video: + video_unregister_device(vfd); +#endif +err_free_dev: + return ret; +} + +static int mtk_aie_dev_v4l2_init(struct mtk_aie_dev *fd) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = &fd->mdev; +#endif + struct device *dev = fd->dev; + int ret = -EINVAL; + + ret = v4l2_device_register(dev, &fd->v4l2_dev); + if (ret) { + dev_err(dev, "Failed to register v4l2 device\n"); + return ret; + } + + fd->m2m_dev = v4l2_m2m_init(&fd_m2m_ops); + if (IS_ERR(fd->m2m_dev)) { + dev_err(dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(fd->m2m_dev); + goto err_unreg_v4l2_dev; + } +#ifdef CONFIG_MEDIA_CONTROLLER + mdev->dev = dev; + strscpy(mdev->model, dev_driver_string(dev), sizeof(mdev->model)); + media_device_init(mdev); + mdev->ops = &fd_m2m_media_ops; + fd->v4l2_dev.mdev = mdev; +#endif + + ret = mtk_aie_video_device_register(fd); + if (ret) + goto err_cleanup_mdev; + +#ifdef CONFIG_MEDIA_CONTROLLER + ret = media_device_register(mdev); + if (ret) { + dev_err(dev, "Failed to register mem2mem media device\n"); + goto err_unreg_vdev; + } +#endif + return 0; + +#ifdef CONFIG_MEDIA_CONTROLLER +err_unreg_vdev: + v4l2_m2m_unregister_media_controller(fd->m2m_dev); + video_unregister_device(&fd->vfd); +#endif +err_cleanup_mdev: +#ifdef CONFIG_MEDIA_CONTROLLER + media_device_cleanup(mdev); +#endif + v4l2_m2m_release(fd->m2m_dev); +err_unreg_v4l2_dev: + v4l2_device_unregister(&fd->v4l2_dev); + return ret; +} + +static void mtk_aie_video_device_unregister(struct mtk_aie_dev *fd) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + v4l2_m2m_unregister_media_controller(fd->m2m_dev); +#endif + video_unregister_device(&fd->vfd); +#ifdef CONFIG_MEDIA_CONTROLLER + media_device_cleanup(&fd->mdev); +#endif + v4l2_m2m_release(fd->m2m_dev); + v4l2_device_unregister(&fd->v4l2_dev); +} + +static void mtk_aie_frame_done_worker(struct work_struct *work) +{ + struct mtk_aie_req_work *req_work = (struct mtk_aie_req_work *)work; + struct mtk_aie_dev *fd = (struct mtk_aie_dev *)req_work->fd_dev; + + if (fd->reg_cfg.fd_mode == FDMODE) { + fd->reg_cfg.hw_result = readl(fd->fd_base + AIE_RESULT_0_REG); + fd->reg_cfg.hw_result1 = readl(fd->fd_base + AIE_RESULT_1_REG); + } + + mutex_lock(&fd->fd_lock); + + switch (fd->aie_cfg->sel_mode) { + case FDMODE: + aie_get_fd_result(fd, fd->aie_cfg); + break; + case ATTRIBUTEMODE: + aie_get_attr_result(fd, fd->aie_cfg); + break; + case FLDMODE: + if (fd->variant->fld_enable) + aie_get_fld_result(fd, fd->aie_cfg); + break; + default: + dev_dbg(fd->dev, "Wrong sel_mode\n"); + break; + } + + mutex_unlock(&fd->fd_lock); + +#ifdef CONFIG_DEBUG_FS + if (fd->tr_info.trigger_dump[0] != '0') { + cancel_delayed_work(&fd->job_timeout_work); + aie_irqhandle(fd); + aie_reset(fd); + atomic_dec(&fd->num_composing); + mtk_aie_hw_job_finish(fd, VB2_BUF_STATE_ERROR); + wake_up(&fd->flushing_waitq); + aie_dumpinfo(fd); + fd->tr_info.trigger_dump[0] = '0'; + return; + } +#endif + if (!cancel_delayed_work(&fd->job_timeout_work)) + return; + + atomic_dec(&fd->num_composing); + mtk_aie_hw_job_finish(fd, VB2_BUF_STATE_DONE); + wake_up(&fd->flushing_waitq); +} + +#ifdef CONFIG_DEBUG_FS +static int aie_dbg_dump_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t aie_dbg_dump_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + struct mtk_aie_dev *fd = file->private_data; + ssize_t ret_size = 0; + + ret_size = simple_read_from_buffer(buf, len, ppos, + fd->tr_info.dump_buffer, + fd->tr_info.dump_offset); + + return ret_size; +} + +static const struct file_operations aie_debug_dump_fops = { + .owner = THIS_MODULE, + .open = aie_dbg_dump_open, + .read = aie_dbg_dump_read, +}; + +static int aie_dbg_trigger_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t aie_dbg_trigger_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct mtk_aie_dev *fd = file->private_data; + size_t ret = -EINVAL; + + if (*ppos > sizeof(fd->tr_info.trigger_dump)) + return -EINVAL; + + ret = simple_write_to_buffer(fd->tr_info.trigger_dump, + sizeof(fd->tr_info.trigger_dump), ppos, + buf, len); + + return ret; +} + +static ssize_t aie_dbg_trigger_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + struct mtk_aie_dev *fd = file->private_data; + + return simple_read_from_buffer(buf, len, ppos, + fd->tr_info.trigger_dump, + sizeof(fd->tr_info.trigger_dump)); +} + +static const struct file_operations aie_debug_trigger_fops = { + .owner = THIS_MODULE, + .open = aie_dbg_trigger_open, + .write = aie_dbg_trigger_write, + .read = aie_dbg_trigger_read, +}; + +static struct dentry *aie_debugfs_dump, *aie_debugfs_trigger, + *aie_debugfs_srcdata, *aie_debugfs_dstdata, *aie_debugfs_root; +#endif + +#ifdef CONFIG_DEBUG_FS +static int mtk_aie_debugfs_init(struct mtk_aie_dev *fd) +{ + aie_debugfs_root = debugfs_create_dir("mtk_aie", NULL); + if (!aie_debugfs_root) + return -ENOMEM; + + aie_debugfs_dump = debugfs_create_file("dumpinfo", + 0444, + aie_debugfs_root, + fd, + &aie_debug_dump_fops + ); + if (!aie_debugfs_dump) + return -ENOMEM; + + aie_debugfs_trigger = debugfs_create_file("trigger_dump", + 0444, + aie_debugfs_root, + fd, + &aie_debug_trigger_fops + ); + if (!aie_debugfs_trigger) + return -ENOMEM; + + srcdata.data = (void *)srcrawdata; + srcdata.size = AIE_DEBUG_RAW_DATA_SIZE; + + aie_debugfs_srcdata = debugfs_create_blob("srcdata.raw", + 0444, + aie_debugfs_root, + &srcdata + ); + if (!aie_debugfs_srcdata) + return -ENOMEM; + + dstdata.data = (void *)dstrawdata; + dstdata.size = AIE_DEBUG_RAW_DATA_SIZE; + + aie_debugfs_dstdata = debugfs_create_blob("dstdata.raw", + 0444, + aie_debugfs_root, + &dstdata + ); + if (!aie_debugfs_dstdata) + return -ENOMEM; + + fd->tr_info.dump_size = AIE_DUMP_BUFFER_SIZE; + fd->tr_info.dump_buffer = + kmalloc(fd->tr_info.dump_size, GFP_KERNEL); + if (!fd->tr_info.dump_buffer) + return -ENOMEM; + + fd->tr_info.trigger_dump[0] = '0'; + fd->tr_info.trigger_dump[1] = '\n'; + fd->tr_info.trigger_dump[2] = '\0'; + + return 0; +} + +static void mtk_aie_debugfs_free(struct platform_device *pdev) +{ + struct mtk_aie_dev *fd = dev_get_drvdata(&pdev->dev); + + kfree(fd->tr_info.dump_buffer); + fd->tr_info.dump_buffer = NULL; + + debugfs_remove_recursive(aie_debugfs_root); + aie_debugfs_root = NULL; +} +#else +static int mtk_aie_debugfs_init(struct mtk_aie_dev *fd) +{ + return 0; +} + +static void mtk_aie_debugfs_free(struct platform_device *pdev) +{ +} +#endif + +static int mtk_aie_resource_init(struct mtk_aie_dev *fd) +{ + int ret = 0; + + mutex_init(&fd->vfd_lock); + mutex_init(&fd->dev_lock); + mutex_init(&fd->fd_lock); + + init_completion(&fd->fd_job_finished); + complete_all(&fd->fd_job_finished); + INIT_DELAYED_WORK(&fd->job_timeout_work, mtk_aie_job_timeout_work); + init_waitqueue_head(&fd->flushing_waitq); + atomic_set(&fd->num_composing, 0); + fd->fd_stream_count = 0; + + fd->frame_done_wq = alloc_ordered_workqueue(dev_name(fd->dev), + WQ_HIGHPRI | WQ_FREEZABLE + ); + if (!fd->frame_done_wq) { + dev_err(fd->dev, "failed to alloc frame_done workqueue\n"); + mutex_destroy(&fd->vfd_lock); + mutex_destroy(&fd->dev_lock); + mutex_destroy(&fd->fd_lock); + return -ENOMEM; + } + + INIT_WORK(&fd->req_work.work, mtk_aie_frame_done_worker); + fd->req_work.fd_dev = fd; + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION + ret = mtk_aie_mmdvfs_init(fd); + if (ret) + return ret; + ret = mtk_aie_mmqos_init(fd); + if (ret) + return ret; + } +#endif + return ret; +} + +static void mtk_aie_resource_free(struct platform_device *pdev) +{ + struct mtk_aie_dev *fd = dev_get_drvdata(&pdev->dev); + +#ifdef CONFIG_INTERCONNECT_MTK_EXTENSION + mtk_aie_mmdvfs_uninit(fd); + mtk_aie_mmqos_uninit(fd); +#endif + if (fd->frame_done_wq) + destroy_workqueue(fd->frame_done_wq); + fd->frame_done_wq = NULL; + mutex_destroy(&fd->vfd_lock); + mutex_destroy(&fd->dev_lock); + mutex_destroy(&fd->fd_lock); +} + +static irqreturn_t mtk_aie_irq(int irq, void *data) +{ + struct mtk_aie_dev *fd = (struct mtk_aie_dev *)data; + + aie_irqhandle(fd); + + queue_work(fd->frame_done_wq, &fd->req_work.work); + + return IRQ_HANDLED; +} + +static int mtk_aie_probe(struct platform_device *pdev) +{ + struct mtk_aie_dev *fd = NULL; + struct device *dev = &pdev->dev; + + int irq = -1; + int ret = -EINVAL; + + fd = devm_kzalloc(&pdev->dev, sizeof(struct mtk_aie_dev), GFP_KERNEL); + if (!fd) + return -ENOMEM; + + fd->variant = mtk_aie_get_variant(dev); + if (!fd->variant) + return -ENODEV; + + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34)); + if (ret) { + dev_err(dev, "%s: No suitable DMA available\n", __func__); + return ret; + } + + dev_set_drvdata(dev, fd); + fd->dev = dev; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "Failed to get irq by platform: %d\n", irq); + return irq; + } + + ret = devm_request_irq(dev, + irq, + mtk_aie_irq, + IRQF_SHARED, + dev_driver_string(dev), + fd + ); + if (ret) { + dev_err(dev, "Failed to request irq\n"); + return ret; + } + fd->irq = irq; + + fd->fd_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(fd->fd_base)) { + dev_err(dev, "Failed to get fd reg base\n"); + return PTR_ERR(fd->fd_base); + } + + fd->aie_clk.clk_num = ARRAY_SIZE(aie_clks); + fd->aie_clk.clks = aie_clks; + ret = devm_clk_bulk_get(&pdev->dev, fd->aie_clk.clk_num, fd->aie_clk.clks); + if (ret) { + dev_err(dev, "failed to get raw clock:%d\n", ret); + return ret; + } + + ret = mtk_aie_debugfs_init(fd); + if (ret) + goto err_free; + + ret = mtk_aie_resource_init(fd); + if (ret) + goto err_free; + pm_runtime_enable(dev); + ret = mtk_aie_dev_v4l2_init(fd); + if (ret) + goto err_free; + dev_info(dev, "AIE : Success to %s\n", __func__); + + return 0; + +err_free: + pm_runtime_disable(&pdev->dev); + mtk_aie_resource_free(pdev); + + return ret; +} + +static void mtk_aie_remove(struct platform_device *pdev) +{ + struct mtk_aie_dev *fd = dev_get_drvdata(&pdev->dev); + + mtk_aie_video_device_unregister(fd); + pm_runtime_disable(&pdev->dev); + mtk_aie_debugfs_free(pdev); + mtk_aie_resource_free(pdev); + +#ifdef CONFIG_DEBUG_FS + kfree(fd->tr_info.dump_buffer); +#endif +} + +static int mtk_aie_suspend(struct device *dev) +{ + struct mtk_aie_dev *fd = dev_get_drvdata(dev); + int ret = -EINVAL, num = 0; + + if (pm_runtime_suspended(dev)) + return 0; + + num = atomic_read(&fd->num_composing); + dev_info(dev, "%s: suspend aie job start, num(%d)\n", __func__, num); + + ret = wait_event_timeout(fd->flushing_waitq, + !(num = atomic_read(&fd->num_composing)), + msecs_to_jiffies(MTK_FD_HW_TIMEOUT_IN_MSEC) + ); + if (!ret && num) { + dev_dbg(dev, + "%s: flushing aie job timeout num %d\n", + __func__, + num + ); + + return -EBUSY; + } + + dev_info(dev, "%s: suspend aie job end num(%d)\n", __func__, num); + + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret; + + return 0; +} + +static int mtk_aie_resume(struct device *dev) +{ + int ret = -EINVAL; + + dev_info(dev, "%s: resume aie job start)\n", __func__); + + if (pm_runtime_suspended(dev)) { + dev_info(dev, + "%s: pm_runtime_suspended is true, no action\n", + __func__ + ); + return 0; + } + + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + + dev_info(dev, "%s: resume aie job end)\n", __func__); + return 0; +} + +static int mtk_aie_runtime_suspend(struct device *dev) +{ + struct mtk_aie_dev *fd = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(fd->aie_clk.clk_num, fd->aie_clk.clks); + + return 0; +} + +static int mtk_aie_runtime_resume(struct device *dev) +{ + struct mtk_aie_dev *fd = dev_get_drvdata(dev); + int ret = -EINVAL; + + ret = clk_bulk_prepare_enable(fd->aie_clk.clk_num, fd->aie_clk.clks); + if (ret) { + dev_err(dev, "failed to enable clock:%d\n", ret); + return ret; + } + + return 0; +} + +static const struct dev_pm_ops mtk_aie_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mtk_aie_suspend, mtk_aie_resume) + SET_RUNTIME_PM_OPS(mtk_aie_runtime_suspend, mtk_aie_runtime_resume, NULL) +}; + +static const struct mtk_aie_variant aie_30_drvdata = { + .hw_version = 30, + .fld_enable = 0, + .y2r_cfg_size = 32, + .rs_cfg_size = 28, + .fd_cfg_size = 54, +}; + +static const struct mtk_aie_variant aie_31_drvdata = { + .hw_version = 31, + .fld_enable = 1, + .y2r_cfg_size = 34, + .rs_cfg_size = 30, + .fd_cfg_size = 56, +}; + +static const struct of_device_id mtk_aie_of_ids[] = { + { + .compatible = "mediatek,aie-hw3.0", + .data = &aie_30_drvdata, + }, + { + .compatible = "mediatek,aie-hw3.1", + .data = &aie_31_drvdata, + }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, mtk_aie_of_ids); + +static const struct mtk_aie_variant *mtk_aie_get_variant(struct device *dev) +{ + const struct mtk_aie_variant *driver_data = NULL; + const struct of_device_id *match = NULL; + + match = of_match_node(mtk_aie_of_ids, dev->of_node); + + if (match) + driver_data = (const struct mtk_aie_variant *)match->data; + else + return &aie_30_drvdata; + + return driver_data; +} + +static struct platform_driver mtk_aie_driver = { + .probe = mtk_aie_probe, + .remove = mtk_aie_remove, + .driver = { + .name = "mtk-aie-5.3", + .of_match_table = of_match_ptr(mtk_aie_of_ids), + .pm = pm_ptr(&mtk_aie_pm_ops), + } +}; + +module_platform_driver(mtk_aie_driver); +MODULE_AUTHOR("Fish Wu <fish.wu@xxxxxxxxxxxx>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek AIE driver"); diff --git a/drivers/media/platform/mediatek/aie/mtk_aie_drv.c b/drivers/media/platform/mediatek/aie/mtk_aie_drv.c new file mode 100644 index 000000000000..2d1fc5760f8d --- /dev/null +++ b/drivers/media/platform/mediatek/aie/mtk_aie_drv.c @@ -0,0 +1,3613 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Author: Fish Wu <fish.wu@xxxxxxxxxxxx> + */ + +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/mtk_aie_v4l2_controls.h> + +#include "mtk_aie.h" + +static const unsigned int fd_wdma_en[FD_LOOP_NUM][OUTPUT_WDMA_WRA_NUM] = { + { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 0, 0 }, + { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, { 1, 1, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, + { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, + { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, + { 1, 1, 1, 1 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, + { 1, 0, 1, 0 }, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, + { 1, 0, 0, 0 }, { 1, 0, 1, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 } +}; + +static const unsigned int out_stride_size[FD_LOOP_NUM][OUTPUT_WDMA_WRA_NUM] = { + { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, { 1, 0, 2, 0 }, { 1, 0, 0, 0 }, + { 1, 1, 2, 2 }, { 1, 1, 2, 2 }, { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, { 1, 1, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, + { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, + { 3, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, { 1, 0, 2, 0 }, + { 1, 0, 0, 0 }, { 1, 1, 2, 2 }, { 1, 1, 2, 2 }, { 1, 0, 0, 0 }, + { 1, 0, 2, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, + { 1, 1, 1, 1 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 0, 0, 0 }, { 3, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, + { 1, 0, 2, 0 }, { 1, 0, 0, 0 }, { 1, 1, 2, 2 }, { 1, 1, 2, 2 }, + { 1, 0, 0, 0 }, { 1, 0, 2, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 2, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 3, 0, 0, 0 } +}; + +static const unsigned int fd_ker_rdma_size[FD_LOOP_NUM][KERNEL_RDMA_RA_NUM] = { + { 240, 240 }, { 1168, 1168 }, { 1168, 1168 }, { 272, 272 }, + { 2320, 2320 }, { 2080, 2080 }, { 1040, 1040 }, { 4624, 4624 }, + { 3104, 3104 }, { 9232, 9232 }, { 4624, 4624 }, { 4128, 4128 }, + { 1040, 1040 }, { 4624, 4624 }, { 4624, 4624 }, { 1552, 1552 }, + { 4624, 4624 }, { 4624, 4624 }, { 4128, 4128 }, { 1040, 1040 }, + { 1040, 1040 }, { 528, 528 }, { 4160, 4160 }, { 4160, 4160 }, + { 2080, 2080 }, { 2080, 2080 }, { 2080, 2080 }, { 1040, 1040 }, + { 0, 0 }, { 240, 240 }, { 1168, 1168 }, { 1168, 1168 }, + { 272, 272 }, { 2320, 2320 }, { 2080, 2080 }, { 1040, 1040 }, + { 4624, 4624 }, { 3104, 3104 }, { 9232, 9232 }, { 4624, 4624 }, + { 4128, 4128 }, { 1040, 1040 }, { 4624, 4624 }, { 4624, 4624 }, + { 1552, 1552 }, { 4624, 4624 }, { 4624, 4624 }, { 4128, 4128 }, + { 1040, 1040 }, { 1040, 1040 }, { 528, 528 }, { 4160, 4160 }, + { 4160, 4160 }, { 2080, 2080 }, { 2080, 2080 }, { 2080, 2080 }, + { 1040, 1040 }, { 0, 0 }, { 240, 240 }, { 1168, 1168 }, + { 1168, 1168 }, { 272, 272 }, { 2320, 2320 }, { 2080, 2080 }, + { 1040, 1040 }, { 4624, 4624 }, { 3104, 3104 }, { 9232, 9232 }, + { 4624, 4624 }, { 4128, 4128 }, { 1040, 1040 }, { 4624, 4624 }, + { 4624, 4624 }, { 1552, 1552 }, { 4624, 4624 }, { 4624, 4624 }, + { 4128, 4128 }, { 1040, 1040 }, { 1040, 1040 }, { 528, 528 }, + { 4160, 4160 }, { 4160, 4160 }, { 2080, 2080 }, { 2080, 2080 }, + { 2080, 2080 }, { 1040, 1040 }, { 0, 0 } +}; + +static const unsigned int fd_out_stride2_in[FD_LOOP_NUM] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const unsigned int fd_stride[FD_LOOP_NUM] = { + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const unsigned int fd_maxpool[FD_LOOP_NUM] = { + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const unsigned int out_2size[FD_LOOP_NUM] = { + 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const unsigned int in_ch_pack[FD_LOOP_NUM] = { + 1, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 1, 16, 16, 16, 16, 16, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 0, 1, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0 +}; + +static const unsigned int outlayer[FD_LOOP_NUM] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 +}; + +static const unsigned int out_ch_pack[FD_LOOP_NUM] = { + 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 16, 16, 16, 32, 32, 32, 32, 32, 32, 0, 16, 16, 16, 16, 16, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 32, 32, 32, + 32, 32, 32, 0, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 16, 16, 16, 32, 32, 32, 32, 32, 32, 0 +}; + +static const unsigned int anchor_en_num[FD_LOOP_NUM] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +/* [loop][ch][output_index] */ +static const signed int fd_rdma_en[FD_LOOP_NUM][INPUT_WDMA_WRA_NUM][2] = { + { { 99, 99 }, { 99, 99 }, { 99, 99 }, { -1, -1 } }, + { { 0, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 1, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 1, 0 }, { 2, 0 }, { -1, -1 }, { -1, -1 } }, + { { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 1, 2 }, { 2, 2 }, { 4, 2 }, { 4, 3 } }, + { { 5, 0 }, { 5, 1 }, { -1, -1 }, { -1, -1 } }, + { { 6, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 5, 0 }, { 5, 1 }, { 7, 0 }, { -1, -1 } }, + { { 8, 0 }, { 8, 1 }, { -1, -1 }, { -1, -1 } }, + { { 9, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 5, 2 }, { 5, 3 }, { 7, 2 }, { 10, 2 } }, + { { 11, 0 }, { 11, 1 }, { -1, -1 }, { -1, -1 } }, + { { 12, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 13, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 11, 0 }, { 11, 1 }, { 14, 0 }, { -1, -1 } }, + { { 15, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 16, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 11, 0 }, { 11, 1 }, { 14, 0 }, { 17, 0 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { 18, 1 }, { -1, -1 }, { -1, -1 } }, + { { 19, 0 }, { 22, 0 }, { 22, 1 }, { 25, 0 } }, + { { 99, 99 }, { 99, 99 }, { 99, 99 }, { -1, -1 } }, + { { 29, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 30, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 30, 0 }, { 31, 0 }, { -1, -1 }, { -1, -1 } }, + { { 32, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 30, 2 }, { 31, 2 }, { 33, 2 }, { 33, 3 } }, + { { 34, 0 }, { 34, 1 }, { -1, -1 }, { -1, -1 } }, + { { 35, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 34, 0 }, { 34, 1 }, { 36, 0 }, { -1, -1 } }, + { { 37, 0 }, { 37, 1 }, { -1, -1 }, { -1, -1 } }, + { { 38, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 34, 2 }, { 34, 3 }, { 36, 2 }, { 39, 2 } }, + { { 40, 0 }, { 40, 1 }, { -1, -1 }, { -1, -1 } }, + { { 41, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 42, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 40, 0 }, { 40, 1 }, { 43, 0 }, { -1, -1 } }, + { { 44, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 45, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 40, 0 }, { 40, 1 }, { 43, 0 }, { 46, 0 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 47, 0 }, { 47, 1 }, { -1, -1 }, { -1, -1 } }, + { { 48, 0 }, { 51, 0 }, { 51, 1 }, { 54, 0 } }, + { { 99, 99 }, { 99, 99 }, { 99, 99 }, { -1, -1 } }, + { { 58, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 59, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 59, 0 }, { 60, 0 }, { -1, -1 }, { -1, -1 } }, + { { 61, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 59, 2 }, { 60, 2 }, { 62, 2 }, { 62, 3 } }, + { { 63, 0 }, { 63, 1 }, { -1, -1 }, { -1, -1 } }, + { { 64, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 63, 0 }, { 63, 1 }, { 65, 0 }, { -1, -1 } }, + { { 66, 0 }, { 66, 1 }, { -1, -1 }, { -1, -1 } }, + { { 67, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 63, 2 }, { 63, 3 }, { 65, 2 }, { 68, 2 } }, + { { 69, 0 }, { 69, 1 }, { -1, -1 }, { -1, -1 } }, + { { 70, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 71, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 69, 0 }, { 69, 1 }, { 72, 0 }, { -1, -1 } }, + { { 73, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 74, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 69, 0 }, { 69, 1 }, { 72, 0 }, { 75, 0 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 76, 0 }, { 76, 1 }, { -1, -1 }, { -1, -1 } }, + { { 77, 0 }, { 80, 0 }, { 80, 1 }, { 83, 0 } } +}; + +static const unsigned int attr_wdma_en[ATTR_LOOP_NUM][OUTPUT_WDMA_WRA_NUM] = { + { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, + { 1, 1, 1, 1 }, { 1, 0, 1, 0 }, { 1, 1, 0, 0 }, { 1, 0, 1, 0 }, + { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, + { 1, 0, 0, 0 }, { 1, 0, 0, 0 } +}; + +static const unsigned int + attr_ker_rdma_size[ATTR_LOOP_NUM][KERNEL_RDMA_RA_NUM] = { + { 240, 240 }, { 1168, 1168 }, { 272, 272 }, { 2320, 2320 }, + { 2080, 2080 }, { 9232, 9232 }, { 3104, 3104 }, { 9232, 9232 }, + { 4128, 4128 }, { 1040, 1040 }, { 4624, 4624 }, { 4624, 4624 }, + { 1552, 1552 }, { 4624, 4624 }, { 4624, 4624 }, { 4128, 4128 }, + { 9232, 9232 }, { 272, 272 }, { 9232, 9232 }, { 2320, 2320 }, + { 144, 144 }, { 9232, 9232 }, { 272, 272 }, { 9232, 9232 }, + { 2320, 2320 }, { 144, 144 } + }; + +static const unsigned int attr_out_stride2_as_in[ATTR_LOOP_NUM] = { + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const unsigned int attr_fd_stride[ATTR_LOOP_NUM] = { /* H */ + 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 +}; + +static const unsigned int attr_fd_maxpool[ATTR_LOOP_NUM] = { /* L */ + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; + +static const unsigned int attr_out_2size[ATTR_LOOP_NUM] = { /* O */ + 1, 1, 0, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 +}; + +/* [loop][ch][output_index] */ +static const signed int attr_rdma_en[ATTR_LOOP_NUM][INPUT_WDMA_WRA_NUM][2] = { + { { 99, 99 }, { 99, 99 }, { 99, 99 }, { -1, -1 } }, + { { 0, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 0, 0 }, { 1, 0 }, { -1, -1 }, { -1, -1 } }, + { { 2, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 0, 2 }, { 1, 2 }, { 3, 2 }, { 3, 3 } }, + { { 4, 0 }, { 4, 1 }, { -1, -1 }, { -1, -1 } }, + { { 4, 0 }, { 4, 1 }, { 5, 0 }, { -1, -1 } }, + { { 6, 0 }, { 6, 1 }, { -1, -1 }, { -1, -1 } }, + { { 4, 2 }, { 4, 3 }, { 5, 2 }, { 7, 2 } }, + { { 8, 0 }, { 8, 1 }, { -1, -1 }, { -1, -1 } }, + { { 9, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 10, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 8, 0 }, { 8, 1 }, { 11, 0 }, { -1, -1 } }, + { { 12, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 13, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 8, 0 }, { 8, 1 }, { 11, 0 }, { 14, 0 } }, + { { 15, 0 }, { 15, 1 }, { -1, -1 }, { -1, -1 } }, + { { 16, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 15, 0 }, { 15, 1 }, { -1, -1 }, { -1, -1 } }, + { { 18, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 19, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 15, 0 }, { 15, 1 }, { -1, -1 }, { -1, -1 } }, + { { 21, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 15, 0 }, { 15, 1 }, { -1, -1 }, { -1, -1 } }, + { { 23, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, + { { 24, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 } } +}; + +static const unsigned int attr_wdma_size[ATTR_LOOP_NUM][OUTPUT_WDMA_WRA_NUM] = { + { 16384, 0, 4096, 0 }, + { 16384, 0, 4096, 0 }, + { 16384, 0, 0, 0 }, + { 16384, 16384, 4096, 4096 }, + { 8192, 8192, 2048, 2048 }, + { 8192, 0, 2048, 0 }, + { 8192, 8192, 0, 0 }, + { 8192, 0, 2048, 0 }, + { 2048, 2048, 0, 0 }, + { 2048, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 2048, 2048, 0, 0 }, + { 2048, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 1024, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 2048, 0, 0, 0 }, + { 1024, 0, 0, 0 }, + { 0, 0, 0, 0 } +}; + +static const unsigned int fld_step_align_size[FLD_STEP_NUM][FLD_MAX_FRAME] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6528 }, + { 1536, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, + 1280, 1280, 1280, 1280 }, + { 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, + 5376, 5376, 5376, 5376 }, + { 307200, 307200, 307200, 307200, 307200, 307200, 307200, 307200, + 307200, 307200, 307200, 307200, 307200, 307200, 307200 }, + { 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, + 8064, 8064, 8064, 8064 }, + { 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, + 8064, 8064, 8064, 8064 } +}; + +static const unsigned int fld_face_info_0[FLD_MAX_FRAME] = { + FLD_INFO_0_FACE_0, FLD_INFO_0_FACE_1, FLD_INFO_0_FACE_2, + FLD_INFO_0_FACE_3, FLD_INFO_0_FACE_4, FLD_INFO_0_FACE_5, + FLD_INFO_0_FACE_6, FLD_INFO_0_FACE_7, FLD_INFO_0_FACE_8, + FLD_INFO_0_FACE_9, FLD_INFO_0_FACE_10, FLD_INFO_0_FACE_11, + FLD_INFO_0_FACE_12, FLD_INFO_0_FACE_13, FLD_INFO_0_FACE_14 +}; + +static const unsigned int fld_face_info_1[FLD_MAX_FRAME] = { + FLD_INFO_1_FACE_0, FLD_INFO_1_FACE_1, FLD_INFO_1_FACE_2, + FLD_INFO_1_FACE_3, FLD_INFO_1_FACE_4, FLD_INFO_1_FACE_5, + FLD_INFO_1_FACE_6, FLD_INFO_1_FACE_7, FLD_INFO_1_FACE_8, + FLD_INFO_1_FACE_9, FLD_INFO_1_FACE_10, FLD_INFO_1_FACE_11, + FLD_INFO_1_FACE_12, FLD_INFO_1_FACE_13, FLD_INFO_1_FACE_14 +}; + +static const unsigned int fld_face_info_2[FLD_MAX_FRAME] = { + FLD_INFO_2_FACE_0, FLD_INFO_2_FACE_1, FLD_INFO_2_FACE_2, + FLD_INFO_2_FACE_3, FLD_INFO_2_FACE_4, FLD_INFO_2_FACE_5, + FLD_INFO_2_FACE_6, FLD_INFO_2_FACE_7, FLD_INFO_2_FACE_8, + FLD_INFO_2_FACE_9, FLD_INFO_2_FACE_10, FLD_INFO_2_FACE_11, + FLD_INFO_2_FACE_12, FLD_INFO_2_FACE_13, FLD_INFO_2_FACE_14 +}; + +static u32 aie_cmb_u16(u16 low, u16 high) +{ + return ((u32)high << 16) | low; +} + +static u32 aie_cmb_stride(u16 low, u16 high) +{ + return ((u32)high << 16) | (low & 0x000F); +} + +static inline u16 dif_x(const struct aie_enq_info *aie_cfg) +{ + return (u16)(aie_cfg->src_roi.x2 - aie_cfg->src_roi.x1); +} + +static inline u16 dif_y(const struct aie_enq_info *aie_cfg) +{ + return (u16)(aie_cfg->src_roi.y2 - aie_cfg->src_roi.y1); +} + +static inline void set_cmb_cfg(u32 *tbl, u16 index, u16 stride) +{ + tbl[index] = aie_cmb_u16(tbl[index], stride); +} + +static inline void set_cmbst_cfg(u32 *tbl, u16 index, u16 stride) +{ + tbl[index] = aie_cmb_stride(tbl[index], stride); +} + +static int aie_imem_alloc(struct mtk_aie_dev *fd, u32 size, + struct imem_buf_info *bufinfo) +{ + struct device *dev = fd->dev; + void *va = NULL; + dma_addr_t dma_handle = 0; + + if (size == 0) { + dev_dbg(fd->dev, "%s: size(%d)\n", __func__, size); + return -EINVAL; + } + + fd->fd_mem_size += size; + + va = dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL); + if (!va || dma_handle == 0) + return -ENOMEM; + + bufinfo->va = va; + bufinfo->pa = dma_handle; + bufinfo->size = size; + + dev_dbg(fd->dev, + "%s: vAddr(0x%p) pAddr(0x%pad) size(%d)\n", + __func__, + va, + &dma_handle, + size + ); + + return 0; +} + +static void aie_imem_free(struct mtk_aie_dev *fd, struct imem_buf_info *bufinfo) +{ + dev_dbg(fd->dev, + "%s: vAddr(0x%p) pAddr(0x%pad) size(%d)\n", + __func__, + bufinfo->va, + &bufinfo->pa, + bufinfo->size + ); + + if (bufinfo->va) + dma_free_coherent(fd->dev, + bufinfo->size, + bufinfo->va, + bufinfo->pa + ); +} + +static void aie_init_table(struct mtk_aie_dev *fd, u16 pym_width, + u16 pym_height) +{ + int i = 0; + struct aie_static_info *pstv = &fd->st_info; + + pstv->inf_elm[PYM2_START_LOOP].img_width = pym_width / 4; + pstv->inf_elm[PYM2_START_LOOP].img_height = pym_height / 4; + + pstv->inf_elm[PYM1_START_LOOP].img_width = pym_width / 2; + pstv->inf_elm[PYM1_START_LOOP].img_height = pym_height / 2; + + pstv->inf_elm[PYM0_START_LOOP].img_width = pym_width; + pstv->inf_elm[PYM0_START_LOOP].img_height = pym_height; + + for (i = 0; i < FD_LOOP_NUM; i++) { + if (i != PYM2_START_LOOP && i != PYM1_START_LOOP && i != PYM0_START_LOOP) { + if (fd_out_stride2_in[i] == 1) { + pstv->inf_elm[i].img_width = + pstv->inf_elm[i - 1].stride2_out_width; + pstv->inf_elm[i].img_height = + pstv->inf_elm[i - 1].stride2_out_height; + } else { + pstv->inf_elm[i].img_width = + pstv->inf_elm[i - 1].out_width; + pstv->inf_elm[i].img_height = + pstv->inf_elm[i - 1].out_height; + } + } + + if (fd_maxpool[i] == 1 && fd_stride[i] == 1) { + pstv->inf_elm[i].out_width = + (pstv->inf_elm[i].img_width - 1) / (2 * fd_maxpool[i]) + 1; + pstv->inf_elm[i].out_height = + (pstv->inf_elm[i].img_height - 1) / (2 * fd_maxpool[i]) + 1; + } else { + pstv->inf_elm[i].out_width = + (pstv->inf_elm[i].img_width - 1) / + (fd_stride[i] + 2 * fd_maxpool[i]) + 1; + pstv->inf_elm[i].out_height = + (pstv->inf_elm[i].img_height - 1) / + (fd_stride[i] + 2 * fd_maxpool[i]) + 1; + } + + pstv->inf_elm[i].stride2_out_width = + ((pstv->inf_elm[i].out_width - 1) / 2 + 1) * out_2size[i]; + pstv->inf_elm[i].stride2_out_height = + ((pstv->inf_elm[i].out_height - 1) / 2 + 1) * out_2size[i]; + + if (outlayer[i] == 1) { + pstv->inf_elm[i].out_xsize_plus_1 = + pstv->inf_elm[i].out_width * out_ch_pack[i] * 2; + pstv->inf_elm[i].out_stride = + round_up(pstv->inf_elm[i].out_xsize_plus_1 * anchor_en_num[i], 16); + pstv->inf_elm[i].out_xsize_plus_1_stride2 = + ((pstv->inf_elm[i].out_width - 1) / 2 + 1) * + out_ch_pack[i] * 2 * out_2size[i]; + } else { + pstv->inf_elm[i].out_xsize_plus_1 = + pstv->inf_elm[i].out_width * out_ch_pack[i]; + pstv->inf_elm[i].out_stride = + round_up(pstv->inf_elm[i].out_xsize_plus_1, 16); + pstv->inf_elm[i].out_xsize_plus_1_stride2 = + ((pstv->inf_elm[i].out_width - 1) / 2 + 1) * + out_ch_pack[i] * out_2size[i]; + } + + pstv->inf_elm[i].out_stride_stride2 = + round_up(pstv->inf_elm[i].out_xsize_plus_1_stride2, 16); + + if (out_2size[i] == 1) + pstv->inf_elm[i].out_ysize_plus_1_stride2 = + (pstv->inf_elm[i].out_height - 1) / 2 + 1; + else + pstv->inf_elm[i].out_ysize_plus_1_stride2 = + pstv->inf_elm[i].out_height; + + if (fd_wdma_en[i][0]) { + if (i == RPN2_LOOP_NUM || i == RPN1_LOOP_NUM || i == RPN0_LOOP_NUM) + pstv->inf_elm[i].fd_wdma_size[0] = + RESULT_SIZE; + else + pstv->inf_elm[i].fd_wdma_size[0] = + pstv->inf_elm[i].out_height * + pstv->inf_elm[i].out_stride; + } + + if (outlayer[i] == 1) { + if (fd_wdma_en[i][1]) + pstv->inf_elm[i].fd_wdma_size[1] = + pstv->inf_elm[i].fd_wdma_size[0]; + if (fd_wdma_en[i][2]) + pstv->inf_elm[i].fd_wdma_size[2] = + pstv->inf_elm[i].fd_wdma_size[0]; + if (fd_wdma_en[i][3]) + pstv->inf_elm[i].fd_wdma_size[3] = + pstv->inf_elm[i].fd_wdma_size[0]; + } else if (i == RPN2_LOOP_NUM || i == RPN1_LOOP_NUM || i == RPN0_LOOP_NUM) { + pstv->inf_elm[i].fd_wdma_size[0] = RESULT_SIZE; + } else { + if (fd_wdma_en[i][1]) + pstv->inf_elm[i].fd_wdma_size[1] = + pstv->inf_elm[i].out_height * + pstv->inf_elm[i].out_stride; + if (fd_wdma_en[i][2]) + pstv->inf_elm[i].fd_wdma_size[2] = + pstv->inf_elm[i].out_ysize_plus_1_stride2 * + pstv->inf_elm[i].out_stride_stride2; + if (fd_wdma_en[i][3]) + pstv->inf_elm[i].fd_wdma_size[3] = + pstv->inf_elm[i].out_ysize_plus_1_stride2 * + pstv->inf_elm[i].out_stride_stride2; + } + + if (in_ch_pack[i] == 1) + pstv->inf_elm[i].input_xsize_plus_1 = + round_up(pstv->inf_elm[i].img_width, 8); + else + pstv->inf_elm[i].input_xsize_plus_1 = + pstv->inf_elm[i].img_width * in_ch_pack[i]; + } +} + +static void aie_update_table(struct mtk_aie_dev *fd, u16 pym_width, + u16 pym_height) +{ + int i = 0; + struct aie_static_info *pstv = &fd->st_info; + + pstv->inf_elm[PYM2_START_LOOP].img_width = pym_width / 4; + pstv->inf_elm[PYM2_START_LOOP].img_height = pym_height / 4; + + pstv->inf_elm[PYM1_START_LOOP].img_width = pym_width / 2; + pstv->inf_elm[PYM1_START_LOOP].img_height = pym_height / 2; + + pstv->inf_elm[PYM0_START_LOOP].img_width = pym_width; + pstv->inf_elm[PYM0_START_LOOP].img_height = pym_height; + + for (i = 0; i < FD_LOOP_NUM; i++) { + if (i != PYM2_START_LOOP && i != PYM1_START_LOOP && + i != PYM0_START_LOOP) { + if (fd_out_stride2_in[i] == 1) { + pstv->inf_elm[i].img_width = + pstv->inf_elm[i - 1].stride2_out_width; + pstv->inf_elm[i].img_height = + pstv->inf_elm[i - 1].stride2_out_height; + } else { + pstv->inf_elm[i].img_width = + pstv->inf_elm[i - 1].out_width; + pstv->inf_elm[i].img_height = + pstv->inf_elm[i - 1].out_height; + } + } + + if (fd_maxpool[i] == 1 && fd_stride[i] == 1) { + pstv->inf_elm[i].out_width = + (pstv->inf_elm[i].img_width - 1) / + (2 * fd_maxpool[i]) + + 1; + pstv->inf_elm[i].out_height = + (pstv->inf_elm[i].img_height - 1) / + (2 * fd_maxpool[i]) + + 1; + } else { + pstv->inf_elm[i].out_width = + (pstv->inf_elm[i].img_width - 1) / + (fd_stride[i] + 2 * fd_maxpool[i]) + + 1; + pstv->inf_elm[i].out_height = + (pstv->inf_elm[i].img_height - 1) / + (fd_stride[i] + 2 * fd_maxpool[i]) + + 1; + } + + pstv->inf_elm[i].stride2_out_width = + ((pstv->inf_elm[i].out_width - 1) / 2 + 1) * + out_2size[i]; + pstv->inf_elm[i].stride2_out_height = + ((pstv->inf_elm[i].out_height - 1) / 2 + 1) * + out_2size[i]; + + if (outlayer[i] == 1) { + pstv->inf_elm[i].out_xsize_plus_1 = + pstv->inf_elm[i].out_width * + out_ch_pack[i] * 2; + pstv->inf_elm[i].out_stride = + round_up(pstv->inf_elm[i].out_xsize_plus_1 * anchor_en_num[i], 16); + pstv->inf_elm[i].out_xsize_plus_1_stride2 = + ((pstv->inf_elm[i].out_width - 1) / 2 + + 1) * + out_ch_pack[i] * 2 * out_2size[i]; + } else { + pstv->inf_elm[i].out_xsize_plus_1 = + pstv->inf_elm[i].out_width * + out_ch_pack[i]; + pstv->inf_elm[i].out_stride = + round_up(pstv->inf_elm[i].out_xsize_plus_1, 16); + pstv->inf_elm[i].out_xsize_plus_1_stride2 = + ((pstv->inf_elm[i].out_width - 1) / 2 + + 1) * + out_ch_pack[i] * out_2size[i]; + } + + pstv->inf_elm[i].out_stride_stride2 = + round_up(pstv->inf_elm[i].out_xsize_plus_1_stride2, 16); + + if (out_2size[i] == 1) + pstv->inf_elm[i].out_ysize_plus_1_stride2 = + (pstv->inf_elm[i].out_height - 1) / 2 + 1; + else + pstv->inf_elm[i].out_ysize_plus_1_stride2 = + pstv->inf_elm[i].out_height; + + if (in_ch_pack[i] == 1) + pstv->inf_elm[i].input_xsize_plus_1 = + round_up(pstv->inf_elm[i].img_width, 8); + else + pstv->inf_elm[i].input_xsize_plus_1 = + pstv->inf_elm[i].img_width * in_ch_pack[i]; + } +} + +static void aie_update_buf_params(struct mtk_aie_dev *fd, u16 max_img_width, + u16 max_img_height) +{ + u8 i = 0, j = 0; + struct aie_static_info *pstv = &fd->st_info; + + fd->base_para->max_img_width = max_img_width; + fd->base_para->max_img_height = max_img_height; + fd->fd_dma_max_size = 0; + fd->fd_dma_rst_max_size = 0; + fd->fd_fd_kernel_size = 0; + fd->fd_attr_kernel_size = 0; + fd->fd_attr_dma_max_size = 0; + fd->fd_attr_dma_rst_max_size = 0; + + /* FDMODE Dram Buffer Size */ + fd->fd_rs_cfg_size = 4 * fd->variant->rs_cfg_size * 2; + fd->fd_fd_cfg_size = 4 * fd->variant->fd_cfg_size * FD_LOOP_NUM; + fd->fd_yuv2rgb_cfg_size = 4 * fd->variant->y2r_cfg_size; + + /* ATTRMODE Dram Buffer Size */ + fd->attr_fd_cfg_size = 4 * fd->variant->fd_cfg_size * ATTR_LOOP_NUM; + fd->attr_yuv2rgb_cfg_size = 4 * fd->variant->y2r_cfg_size; + + /* HW Output Buffer Size */ + fd->rs_pym_out_size[0] = fd->base_para->max_pyramid_width * + fd->base_para->max_pyramid_height; + fd->rs_pym_out_size[1] = fd->rs_pym_out_size[0] / 2; + fd->rs_pym_out_size[2] = fd->rs_pym_out_size[0] / 4; + + /* FDMODE Dram Buffer Size */ + for (i = 0; i < FD_LOOP_NUM; i++) { + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + if (fd_wdma_en[i][j]) { + if ((i == RPN2_LOOP_NUM || i == RPN1_LOOP_NUM || + i == RPN0_LOOP_NUM) && j == 0) { + fd->fd_dma_rst_max_size += + pstv->inf_elm[i] + .fd_wdma_size[j]; + } else { + fd->fd_dma_max_size += + pstv->inf_elm[i] + .fd_wdma_size[j]; + } + } + } + } + + for (i = 0; i < FD_LOOP_NUM; i++) { + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + if (fd_ker_rdma_size[i][j]) + fd->fd_fd_kernel_size += fd_ker_rdma_size[i][j]; + } + } + + /* ATTRMODE Dram Buffer Size */ + for (i = 0; i < ATTR_LOOP_NUM; i++) { + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + if (attr_wdma_en[i][j]) { + if ((i == AGE_OUT_RGS || i == GENDER_OUT_RGS || + i == INDIAN_OUT_RGS || i == RACE_OUT_RGS) && j == 0) { + fd->fd_attr_dma_rst_max_size += + ATTR_OUT_SIZE * + MAX_ENQUE_FRAME_NUM; + } else { + fd->fd_attr_dma_max_size += + attr_wdma_size[i][j]; + } + } + } + } + + for (i = 0; i < ATTR_LOOP_NUM; i++) { + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) + fd->fd_attr_kernel_size += attr_ker_rdma_size[i][j]; + } + + /* FD Pose secure result output buffer: result size * 3 loops */ + fd->fd_dma_rst_max_size += RESULT_SIZE * 3; + + if (fd->variant->fld_enable) { + /* fld size */ + fd->fld_step_size = 0; + for (i = 0; i < FLD_STEP_NUM; i++) + for (j = 0; j < FLD_MAX_FRAME; j++) + fd->fld_step_size += fld_step_align_size[i][j]; + + fd->fld_out_size = FLD_OUTPUT_SIZE * FLD_MAX_FRAME; + } +} + +static int aie_alloc_dram_buf(struct mtk_aie_dev *fd) +{ + int ret = -EINVAL; + u8 i = 0; + u32 alloc_size = 0; + + /* RS DRAM */ + alloc_size = fd->fd_rs_cfg_size; + dev_dbg(fd->dev, "RS CFG:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->rs_cfg_data); + if (ret) + goto dma_alloc_fail; + /* FD MODE */ + fd->base_para->fd_rs_cfg_pa = fd->rs_cfg_data.pa; + fd->base_para->fd_rs_cfg_va = fd->rs_cfg_data.va; + + /* FD DRAM */ + alloc_size = + fd->fd_fd_cfg_size + fd->attr_fd_cfg_size * MAX_ENQUE_FRAME_NUM; + dev_dbg(fd->dev, "FD CFG:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_cfg_data); + if (ret) + goto dma_alloc_fail; + /* FD MODE */ + fd->base_para->fd_fd_cfg_pa = fd->fd_cfg_data.pa; + fd->base_para->fd_fd_cfg_va = fd->fd_cfg_data.va; + /* ATTR MODE */ + fd->base_para->attr_fd_cfg_pa[0] = + fd->base_para->fd_fd_cfg_pa + fd->fd_fd_cfg_size; + fd->base_para->attr_fd_cfg_va[0] = + fd->base_para->fd_fd_cfg_va + fd->fd_fd_cfg_size; + + for (i = 1; i < MAX_ENQUE_FRAME_NUM; i++) { + fd->base_para->attr_fd_cfg_pa[i] = + fd->base_para->attr_fd_cfg_pa[i - 1] + + fd->attr_fd_cfg_size; + fd->base_para->attr_fd_cfg_va[i] = + fd->base_para->attr_fd_cfg_va[i - 1] + + fd->attr_fd_cfg_size; + } + + /* YUV2RGB DRAM */ + alloc_size = fd->fd_yuv2rgb_cfg_size + + fd->attr_yuv2rgb_cfg_size * MAX_ENQUE_FRAME_NUM; + dev_dbg(fd->dev, "YUV2RGB CFG:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->yuv2rgb_cfg_data); + if (ret) + goto dma_alloc_fail; + /* FD MODE */ + fd->base_para->fd_yuv2rgb_cfg_pa = fd->yuv2rgb_cfg_data.pa; + fd->base_para->fd_yuv2rgb_cfg_va = fd->yuv2rgb_cfg_data.va; + + /* ATTR MODE */ + fd->base_para->attr_yuv2rgb_cfg_pa[0] = + fd->base_para->fd_yuv2rgb_cfg_pa + fd->fd_yuv2rgb_cfg_size; + fd->base_para->attr_yuv2rgb_cfg_va[0] = + fd->base_para->fd_yuv2rgb_cfg_va + fd->fd_yuv2rgb_cfg_size; + + for (i = 1; i < MAX_ENQUE_FRAME_NUM; i++) { + fd->base_para->attr_yuv2rgb_cfg_pa[i] = + fd->base_para->attr_yuv2rgb_cfg_pa[i - 1] + + fd->attr_yuv2rgb_cfg_size; + fd->base_para->attr_yuv2rgb_cfg_va[i] = + fd->base_para->attr_yuv2rgb_cfg_va[i - 1] + + fd->attr_yuv2rgb_cfg_size; + } + + return ret; +dma_alloc_fail: + aie_imem_free(fd, &fd->fd_cfg_data); + aie_imem_free(fd, &fd->rs_cfg_data); + + return ret; +} + +static int aie_alloc_output_buf(struct mtk_aie_dev *fd) +{ + int ret = -EINVAL; + u32 alloc_size = 0; + int i, j, pa_off = 0, va_off = 0; + + for (i = 0; i < PYM_NUM; i++) + alloc_size += fd->rs_pym_out_size[i] * 3; + dev_dbg(fd->dev, "RS OUT:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->rs_output_hw); + if (ret) + return ret; + + for (i = 0; i < PYM_NUM; i++) { + for (j = 0; j < COLOR_NUM; j++) { + fd->base_para->rs_pym_rst_pa[i][j] = + fd->rs_output_hw.pa + pa_off; + pa_off += fd->rs_pym_out_size[i]; + + fd->base_para->rs_pym_rst_va[i][j] = + fd->rs_output_hw.va + va_off; + va_off += fd->rs_pym_out_size[i]; + } + } + + return ret; +} + +static void aie_alloc_normal(struct mtk_aie_dev *fd, int start, int end) +{ + int i = 0, j = 0; + int pi = 0, pj = 0; + struct aie_static_info *pstv = &fd->st_info; + + if (start <= 0 || end <= start || end >= FD_LOOP_NUM) { + dev_err(fd->dev, "%s: start = %d, end = %d\n", __func__, start, end); + return; + } + + pi = start - 1; + pj = 0; + for (i = start; i < end + 1; i++) { + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + if (fd_wdma_en[i][j]) { + fd->dma_para->fd_out_hw_pa[i][j] = + fd->dma_para->fd_out_hw_pa[pi][pj] + + pstv->inf_elm[pi].fd_wdma_size[pj]; + pi = i; + pj = j; + } + } + } +} + +static int aie_alloc_fddma_buf(struct mtk_aie_dev *fd) +{ + int ret = -EINVAL; + u32 alloc_size = 0; + + alloc_size = fd->fd_dma_max_size; + dev_dbg(fd->dev, "FD DMA:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_dma_hw); + if (ret) + goto dma_alloc_fail; + alloc_size = fd->fd_fd_kernel_size + fd->fd_attr_kernel_size; + dev_dbg(fd->dev, "FD KERNEL:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_kernel_hw); + if (ret) + goto dma_alloc_fail; + + alloc_size = fd->fd_attr_dma_max_size; + dev_dbg(fd->dev, "ATTR DMA:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_attr_dma_hw); + if (ret) + goto dma_alloc_fail; + + alloc_size = fd->fd_dma_rst_max_size + fd->fd_attr_dma_rst_max_size; + dev_dbg(fd->dev, "RESULT DMA:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_dma_result_hw); + if (ret) + goto dma_alloc_fail; + + return 0; + +dma_alloc_fail: + aie_imem_free(fd, &fd->fd_attr_dma_hw); + aie_imem_free(fd, &fd->fd_kernel_hw); + aie_imem_free(fd, &fd->fd_dma_hw); + + return ret; +} + +static int aie_alloc_fld_buf(struct mtk_aie_dev *fd) +{ + int ret = -EINVAL; + u32 alloc_size = 0; + + alloc_size = fd->fld_step_size; + dev_dbg(fd->dev, "FLD STEP:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_fld_step_data); + if (ret) + return ret; + + alloc_size = fd->fld_out_size; + dev_dbg(fd->dev, "FLD OUT:"); + ret = aie_imem_alloc(fd, alloc_size, &fd->fd_fld_out_hw); + if (ret) + goto fld_step; + + return 0; +fld_step: + aie_imem_free(fd, &fd->fd_fld_step_data); + + return ret; +} + +static void aie_arrange_fddma_buf(struct mtk_aie_dev *fd) +{ + void *current_va = NULL; + dma_addr_t current_pa = 0; + struct aie_static_info *pstv = &fd->st_info; + u8 i = 0, j = 0; + + /* 0~18 */ + fd->dma_para->fd_out_hw_pa[0][0] = fd->fd_dma_hw.pa; + aie_alloc_normal(fd, 1, 18); + + /* 19~27 */ + fd->dma_para->fd_out_hw_pa[19][0] = + fd->dma_para->fd_out_hw_pa[18][1] + + pstv->inf_elm[18].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[19][1] = + fd->dma_para->fd_out_hw_pa[19][0] + + pstv->inf_elm[19].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[20][0] = + fd->dma_para->fd_out_hw_pa[19][0] + + 2 * pstv->inf_elm[20].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[20][1] = + fd->dma_para->fd_out_hw_pa[19][0] + + 3 * pstv->inf_elm[20].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[21][0] = + fd->dma_para->fd_out_hw_pa[19][0] + + 4 * pstv->inf_elm[21].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[22][0] = + fd->dma_para->fd_out_hw_pa[19][0] + + pstv->inf_elm[19].fd_wdma_size[0] + + pstv->inf_elm[19].fd_wdma_size[1] + + pstv->inf_elm[20].fd_wdma_size[0] + + pstv->inf_elm[20].fd_wdma_size[1] + + pstv->inf_elm[21].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[22][1] = + fd->dma_para->fd_out_hw_pa[22][0] + + pstv->inf_elm[22].fd_wdma_size[0] + + pstv->inf_elm[22].fd_wdma_size[2] + + pstv->inf_elm[23].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[22][2] = + fd->dma_para->fd_out_hw_pa[22][0] + + pstv->inf_elm[22].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[22][3] = + fd->dma_para->fd_out_hw_pa[22][1] + + pstv->inf_elm[22].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][0] = + fd->dma_para->fd_out_hw_pa[22][0] + + 2 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][1] = + fd->dma_para->fd_out_hw_pa[22][1] + + 2 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][2] = + fd->dma_para->fd_out_hw_pa[22][0] + + 3 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][3] = + fd->dma_para->fd_out_hw_pa[22][1] + + 3 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[24][0] = + fd->dma_para->fd_out_hw_pa[22][0] + + 4 * pstv->inf_elm[24].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[24][1] = + fd->dma_para->fd_out_hw_pa[22][1] + + 4 * pstv->inf_elm[24].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[25][0] = + fd->dma_para->fd_out_hw_pa[22][1] + + pstv->inf_elm[22].fd_wdma_size[1] + + pstv->inf_elm[22].fd_wdma_size[3] + + pstv->inf_elm[23].fd_wdma_size[1] + + pstv->inf_elm[23].fd_wdma_size[3] + + pstv->inf_elm[24].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[25][1] = + fd->dma_para->fd_out_hw_pa[25][0] + + pstv->inf_elm[25].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[26][0] = + fd->dma_para->fd_out_hw_pa[25][0] + + 2 * pstv->inf_elm[26].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[26][1] = + fd->dma_para->fd_out_hw_pa[25][0] + + 3 * pstv->inf_elm[26].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[27][0] = + fd->dma_para->fd_out_hw_pa[25][0] + + 4 * pstv->inf_elm[27].out_xsize_plus_1; + + /* 29~47 */ + fd->dma_para->fd_out_hw_pa[29][0] = + fd->dma_para->fd_out_hw_pa[25][0] + + pstv->inf_elm[25].fd_wdma_size[0] + + pstv->inf_elm[25].fd_wdma_size[1] + + pstv->inf_elm[26].fd_wdma_size[0] + + pstv->inf_elm[26].fd_wdma_size[1] + + pstv->inf_elm[27].fd_wdma_size[0]; + aie_alloc_normal(fd, 30, 47); + + /* 48~56 */ + fd->dma_para->fd_out_hw_pa[48][0] = + fd->dma_para->fd_out_hw_pa[47][1] + + pstv->inf_elm[47].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[48][1] = + fd->dma_para->fd_out_hw_pa[48][0] + + pstv->inf_elm[48].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[49][0] = + fd->dma_para->fd_out_hw_pa[48][0] + + 2 * pstv->inf_elm[49].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[49][1] = + fd->dma_para->fd_out_hw_pa[48][0] + + 3 * pstv->inf_elm[49].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[50][0] = + fd->dma_para->fd_out_hw_pa[48][0] + + 4 * pstv->inf_elm[50].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[51][0] = + fd->dma_para->fd_out_hw_pa[48][0] + + pstv->inf_elm[48].fd_wdma_size[0] + + pstv->inf_elm[48].fd_wdma_size[1] + + pstv->inf_elm[49].fd_wdma_size[0] + + pstv->inf_elm[49].fd_wdma_size[1] + + pstv->inf_elm[50].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[51][1] = + fd->dma_para->fd_out_hw_pa[51][0] + + pstv->inf_elm[51].fd_wdma_size[0] + + pstv->inf_elm[51].fd_wdma_size[2] + + pstv->inf_elm[52].fd_wdma_size[0] + + pstv->inf_elm[52].fd_wdma_size[2] + + pstv->inf_elm[53].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[51][2] = + fd->dma_para->fd_out_hw_pa[51][0] + + pstv->inf_elm[51].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[51][3] = + fd->dma_para->fd_out_hw_pa[51][1] + + pstv->inf_elm[51].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][0] = + fd->dma_para->fd_out_hw_pa[51][0] + + 2 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][1] = + fd->dma_para->fd_out_hw_pa[51][1] + + 2 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][2] = + fd->dma_para->fd_out_hw_pa[51][0] + + 3 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][3] = + fd->dma_para->fd_out_hw_pa[51][1] + + 3 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[53][0] = + fd->dma_para->fd_out_hw_pa[51][0] + + 4 * pstv->inf_elm[53].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[53][1] = + fd->dma_para->fd_out_hw_pa[51][1] + + 4 * pstv->inf_elm[53].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[54][0] = + fd->dma_para->fd_out_hw_pa[51][1] + + pstv->inf_elm[51].fd_wdma_size[1] + + pstv->inf_elm[51].fd_wdma_size[3] + + pstv->inf_elm[52].fd_wdma_size[1] + + pstv->inf_elm[52].fd_wdma_size[3] + + pstv->inf_elm[53].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[54][1] = + fd->dma_para->fd_out_hw_pa[54][0] + + pstv->inf_elm[54].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[55][0] = + fd->dma_para->fd_out_hw_pa[54][0] + + 2 * pstv->inf_elm[55].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[55][1] = + fd->dma_para->fd_out_hw_pa[54][0] + + 3 * pstv->inf_elm[55].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[56][0] = + fd->dma_para->fd_out_hw_pa[54][0] + + 4 * pstv->inf_elm[56].out_xsize_plus_1; + + /* 58~76 */ + fd->dma_para->fd_out_hw_pa[58][0] = + fd->dma_para->fd_out_hw_pa[54][0] + + pstv->inf_elm[54].fd_wdma_size[0] + + pstv->inf_elm[54].fd_wdma_size[1] + + pstv->inf_elm[55].fd_wdma_size[0] + + pstv->inf_elm[55].fd_wdma_size[1] + + pstv->inf_elm[56].fd_wdma_size[0]; + aie_alloc_normal(fd, 59, 76); + + /* 77~85 */ + fd->dma_para->fd_out_hw_pa[77][0] = + fd->dma_para->fd_out_hw_pa[76][1] + + pstv->inf_elm[76].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[77][1] = + fd->dma_para->fd_out_hw_pa[77][0] + + pstv->inf_elm[77].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[78][0] = + fd->dma_para->fd_out_hw_pa[77][0] + + 2 * pstv->inf_elm[78].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[78][1] = + fd->dma_para->fd_out_hw_pa[77][0] + + 3 * pstv->inf_elm[78].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[79][0] = + fd->dma_para->fd_out_hw_pa[77][0] + + 4 * pstv->inf_elm[79].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[80][0] = + fd->dma_para->fd_out_hw_pa[77][0] + + pstv->inf_elm[77].fd_wdma_size[0] + + pstv->inf_elm[77].fd_wdma_size[1] + + pstv->inf_elm[78].fd_wdma_size[0] + + pstv->inf_elm[78].fd_wdma_size[1] + + pstv->inf_elm[79].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[80][1] = + fd->dma_para->fd_out_hw_pa[80][0] + + pstv->inf_elm[80].fd_wdma_size[0] + + pstv->inf_elm[80].fd_wdma_size[2] + + pstv->inf_elm[81].fd_wdma_size[0] + + pstv->inf_elm[81].fd_wdma_size[2] + + pstv->inf_elm[82].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[80][2] = + fd->dma_para->fd_out_hw_pa[80][0] + + pstv->inf_elm[80].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[80][3] = + fd->dma_para->fd_out_hw_pa[80][1] + + pstv->inf_elm[80].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][0] = + fd->dma_para->fd_out_hw_pa[80][0] + + 2 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][1] = + fd->dma_para->fd_out_hw_pa[80][1] + + 2 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][2] = + fd->dma_para->fd_out_hw_pa[80][0] + + 3 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][3] = + fd->dma_para->fd_out_hw_pa[80][1] + + 3 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[82][0] = + fd->dma_para->fd_out_hw_pa[80][0] + + 4 * pstv->inf_elm[82].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[82][1] = + fd->dma_para->fd_out_hw_pa[80][1] + + 4 * pstv->inf_elm[82].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[83][0] = + fd->dma_para->fd_out_hw_pa[80][1] + + pstv->inf_elm[80].fd_wdma_size[1] + + pstv->inf_elm[80].fd_wdma_size[3] + + pstv->inf_elm[81].fd_wdma_size[1] + + pstv->inf_elm[81].fd_wdma_size[3] + + pstv->inf_elm[82].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[83][1] = + fd->dma_para->fd_out_hw_pa[83][0] + + pstv->inf_elm[83].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[84][0] = + fd->dma_para->fd_out_hw_pa[83][0] + + 2 * pstv->inf_elm[84].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[84][1] = + fd->dma_para->fd_out_hw_pa[83][0] + + 3 * pstv->inf_elm[84].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[85][0] = + fd->dma_para->fd_out_hw_pa[83][0] + + 4 * pstv->inf_elm[85].out_xsize_plus_1; + + /* VA : except 28, 57, 86 */ + /* 0~86 */ + fd->dma_para->fd_out_hw_va[0][0] = fd->fd_dma_hw.va; + for (i = 1; i < FD_LOOP_NUM; i++) { + if (i == RPN2_LOOP_NUM || i == RPN1_LOOP_NUM || + i == RPN0_LOOP_NUM) + continue; + for (j = 0; j < 4; j++) { + if (fd_wdma_en[i][j]) { + fd->dma_para->fd_out_hw_va[i][j] = + fd->fd_dma_hw.va + + fd->dma_para->fd_out_hw_pa[i][j] - + fd->fd_dma_hw.pa; + } + } + } + + current_pa = fd->dma_para->fd_out_hw_pa[83][0] + + pstv->inf_elm[83].fd_wdma_size[0] + + pstv->inf_elm[83].fd_wdma_size[1] + + pstv->inf_elm[84].fd_wdma_size[0] + + pstv->inf_elm[84].fd_wdma_size[1] + + pstv->inf_elm[85].fd_wdma_size[0]; + current_va = fd->dma_para->fd_out_hw_va[83][0] + + pstv->inf_elm[83].fd_wdma_size[0] + + pstv->inf_elm[83].fd_wdma_size[1] + + pstv->inf_elm[84].fd_wdma_size[0] + + pstv->inf_elm[84].fd_wdma_size[1] + + pstv->inf_elm[85].fd_wdma_size[0]; + + dev_dbg(fd->dev, + "%s: current VA = %p PA = 0x%pad\n", + __func__, + current_va, + ¤t_pa + ); +} + +static void aie_arrange_kernel_buf(struct mtk_aie_dev *fd) +{ + void *current_va = NULL; + dma_addr_t current_pa = 0; + u8 i = 0, j = 0; + + current_pa = fd->fd_kernel_hw.pa; + current_va = fd->fd_kernel_hw.va; + + for (i = 0; i < FD_LOOP_NUM; i++) { + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + if (fd_ker_rdma_size[i][j]) { + fd->dma_para->fd_kernel_pa[i][j] = current_pa; + fd->dma_para->fd_kernel_va[i][j] = current_va; + current_pa += fd_ker_rdma_size[i][j]; + current_va += fd_ker_rdma_size[i][j]; + } + } + } + + for (i = 0; i < ATTR_LOOP_NUM; i++) { + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + fd->dma_para->attr_kernel_pa[i][j] = current_pa; + fd->dma_para->attr_kernel_va[i][j] = current_va; + current_pa += attr_ker_rdma_size[i][j]; + current_va += attr_ker_rdma_size[i][j]; + } + } + + dev_dbg(fd->dev, + "%s: current VA = %p PA = 0x%pad\n", + __func__, + current_va, + ¤t_pa + ); +} + +static void aie_arrange_attrdma_buf(struct mtk_aie_dev *fd) +{ + void *current_va = NULL; + dma_addr_t current_pa = 0; + u8 i = 0, j = 0; + + current_pa = fd->fd_attr_dma_hw.pa; + current_va = fd->fd_attr_dma_hw.va; + + /* attribute mode */ + for (i = 0; i < ATTR_LOOP_NUM; i++) { + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + if (attr_wdma_en[i][j]) { + fd->dma_para->attr_out_hw_pa[i][j] = current_pa; + fd->dma_para->attr_out_hw_va[i][j] = current_va; + current_pa += attr_wdma_size[i][j]; + current_va += attr_wdma_size[i][j]; + } + } + } + + dev_dbg(fd->dev, + "%s: current VA = %p PA = 0x%pad\n", + __func__, + current_va, + ¤t_pa + ); +} + +static void aie_arrange_result_dma_buf(struct mtk_aie_dev *fd) +{ + void *currentresult_va = NULL; + dma_addr_t currentresult_pa = 0; + u8 i = 0; + struct aie_static_info *pstv = &fd->st_info; + + currentresult_pa = fd->fd_dma_result_hw.pa; + currentresult_va = fd->fd_dma_result_hw.va; + + fd->dma_para->fd_out_hw_pa[RPN2_LOOP_NUM][0] = currentresult_pa; + fd->dma_para->fd_out_hw_va[RPN2_LOOP_NUM][0] = currentresult_va; + currentresult_pa += pstv->inf_elm[RPN2_LOOP_NUM].fd_wdma_size[0]; + currentresult_va += pstv->inf_elm[RPN2_LOOP_NUM].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[RPN1_LOOP_NUM][0] = currentresult_pa; + fd->dma_para->fd_out_hw_va[RPN1_LOOP_NUM][0] = currentresult_va; + currentresult_pa += pstv->inf_elm[RPN1_LOOP_NUM].fd_wdma_size[0]; + currentresult_va += pstv->inf_elm[RPN1_LOOP_NUM].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[RPN0_LOOP_NUM][0] = currentresult_pa; + fd->dma_para->fd_out_hw_va[RPN0_LOOP_NUM][0] = currentresult_va; + currentresult_pa += pstv->inf_elm[RPN0_LOOP_NUM].fd_wdma_size[0]; + currentresult_va += pstv->inf_elm[RPN0_LOOP_NUM].fd_wdma_size[0]; + + fd->dma_para->attr_out_hw_pa[AGE_OUT_RGS][0] = currentresult_pa; + fd->dma_para->attr_out_hw_va[AGE_OUT_RGS][0] = currentresult_va; + currentresult_pa += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + currentresult_va += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + fd->dma_para->attr_out_hw_pa[GENDER_OUT_RGS][0] = currentresult_pa; + fd->dma_para->attr_out_hw_va[GENDER_OUT_RGS][0] = currentresult_va; + currentresult_pa += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + currentresult_va += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + fd->dma_para->attr_out_hw_pa[INDIAN_OUT_RGS][0] = currentresult_pa; + fd->dma_para->attr_out_hw_va[INDIAN_OUT_RGS][0] = currentresult_va; + currentresult_pa += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + currentresult_va += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + fd->dma_para->attr_out_hw_pa[RACE_OUT_RGS][0] = currentresult_pa; + fd->dma_para->attr_out_hw_va[RACE_OUT_RGS][0] = currentresult_va; + currentresult_pa += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + currentresult_va += ATTR_OUT_SIZE * MAX_ENQUE_FRAME_NUM; + + /* need to prepare 10 buffers to store 10 times result */ + fd->dma_para->age_out_hw_pa[0] = + fd->dma_para->attr_out_hw_pa[AGE_OUT_RGS][0]; + fd->dma_para->age_out_hw_va[0] = + fd->dma_para->attr_out_hw_va[AGE_OUT_RGS][0]; + fd->dma_para->gender_out_hw_pa[0] = + fd->dma_para->attr_out_hw_pa[GENDER_OUT_RGS][0]; + fd->dma_para->gender_out_hw_va[0] = + fd->dma_para->attr_out_hw_va[GENDER_OUT_RGS][0]; + fd->dma_para->is_indian_out_hw_pa[0] = + fd->dma_para->attr_out_hw_pa[INDIAN_OUT_RGS][0]; + fd->dma_para->is_indian_out_hw_va[0] = + fd->dma_para->attr_out_hw_va[INDIAN_OUT_RGS][0]; + fd->dma_para->race_out_hw_pa[0] = + fd->dma_para->attr_out_hw_pa[RACE_OUT_RGS][0]; + fd->dma_para->race_out_hw_va[0] = + fd->dma_para->attr_out_hw_va[RACE_OUT_RGS][0]; + + for (i = 1; i < MAX_ENQUE_FRAME_NUM; i++) { + fd->dma_para->age_out_hw_pa[i] = + fd->dma_para->age_out_hw_pa[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->age_out_hw_va[i] = + fd->dma_para->age_out_hw_va[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->gender_out_hw_pa[i] = + fd->dma_para->gender_out_hw_pa[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->gender_out_hw_va[i] = + fd->dma_para->gender_out_hw_va[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->is_indian_out_hw_pa[i] = + fd->dma_para->is_indian_out_hw_pa[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->is_indian_out_hw_va[i] = + fd->dma_para->is_indian_out_hw_va[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->race_out_hw_pa[i] = + fd->dma_para->race_out_hw_pa[i - 1] + ATTR_OUT_SIZE; + fd->dma_para->race_out_hw_va[i] = + fd->dma_para->race_out_hw_va[i - 1] + ATTR_OUT_SIZE; + } + + memset(fd->fd_dma_result_hw.va, 0, fd->fd_dma_result_hw.size); + + dev_dbg(fd->dev, + "%s: current VA = %p PA = 0x%pad\n", + __func__, + currentresult_va, + ¤tresult_pa + ); +} + +static void aie_arrange_fld_buf(struct mtk_aie_dev *fd) +{ + u8 i = 0, j = 0; + unsigned int offset = 0; + + for (i = 0; i < FLD_STEP_NUM; i++) { + for (j = 0; j < FLD_MAX_FRAME; j++) { + fd->fld_para->fld_step_va[i][j] = + fd->fd_fld_step_data.va + offset; + fd->fld_para->fld_step_pa[i][j] = + fd->fd_fld_step_data.pa + offset; + offset += fld_step_align_size[i][j]; + } + } + + for (i = 0, offset = 0; i < FLD_MAX_FRAME; i++) { + fd->fld_para->fld_output_va[i] = fd->fd_fld_out_hw.va + offset; + fd->fld_para->fld_output_pa[i] = fd->fd_fld_out_hw.pa + offset; + offset += FLD_OUTPUT_SIZE; + } +} + +static void aie_update_fddma_buf(struct mtk_aie_dev *fd) +{ + struct aie_static_info *pstv = &fd->st_info; + u8 i = 0, j = 0; + + /* 19~27 */ + fd->dma_para->fd_out_hw_pa[19][0] = + fd->dma_para->fd_out_hw_pa[18][1] + + pstv->inf_elm[18].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[19][1] = + fd->dma_para->fd_out_hw_pa[19][0] + + pstv->inf_elm[19].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[20][0] = + fd->dma_para->fd_out_hw_pa[19][0] + + 2 * pstv->inf_elm[20].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[20][1] = + fd->dma_para->fd_out_hw_pa[19][0] + + 3 * pstv->inf_elm[20].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[21][0] = + fd->dma_para->fd_out_hw_pa[19][0] + + 4 * pstv->inf_elm[21].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[22][0] = + fd->dma_para->fd_out_hw_pa[19][0] + + pstv->inf_elm[19].fd_wdma_size[0] + + pstv->inf_elm[19].fd_wdma_size[1] + + pstv->inf_elm[20].fd_wdma_size[0] + + pstv->inf_elm[20].fd_wdma_size[1] + + pstv->inf_elm[21].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[22][1] = + fd->dma_para->fd_out_hw_pa[22][0] + + pstv->inf_elm[22].fd_wdma_size[0] + + pstv->inf_elm[22].fd_wdma_size[2] + + pstv->inf_elm[23].fd_wdma_size[0] + + pstv->inf_elm[23].fd_wdma_size[2] + + pstv->inf_elm[24].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[22][2] = + fd->dma_para->fd_out_hw_pa[22][0] + + pstv->inf_elm[22].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[22][3] = + fd->dma_para->fd_out_hw_pa[22][1] + + pstv->inf_elm[22].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][0] = + fd->dma_para->fd_out_hw_pa[22][0] + + 2 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][1] = + fd->dma_para->fd_out_hw_pa[22][1] + + 2 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][2] = + fd->dma_para->fd_out_hw_pa[22][0] + + 3 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[23][3] = + fd->dma_para->fd_out_hw_pa[22][1] + + 3 * pstv->inf_elm[23].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[24][0] = + fd->dma_para->fd_out_hw_pa[22][0] + + 4 * pstv->inf_elm[24].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[24][1] = + fd->dma_para->fd_out_hw_pa[22][1] + + 4 * pstv->inf_elm[24].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[25][0] = + fd->dma_para->fd_out_hw_pa[22][1] + + pstv->inf_elm[22].fd_wdma_size[1] + + pstv->inf_elm[22].fd_wdma_size[3] + + pstv->inf_elm[23].fd_wdma_size[1] + + pstv->inf_elm[23].fd_wdma_size[3] + + pstv->inf_elm[24].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[25][1] = + fd->dma_para->fd_out_hw_pa[25][0] + + pstv->inf_elm[25].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[26][0] = + fd->dma_para->fd_out_hw_pa[25][0] + + 2 * pstv->inf_elm[26].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[26][1] = + fd->dma_para->fd_out_hw_pa[25][0] + + 3 * pstv->inf_elm[26].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[27][0] = + fd->dma_para->fd_out_hw_pa[25][0] + + 4 * pstv->inf_elm[27].out_xsize_plus_1; + + /* 48~56 */ + fd->dma_para->fd_out_hw_pa[48][0] = + fd->dma_para->fd_out_hw_pa[47][1] + + pstv->inf_elm[47].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[48][1] = + fd->dma_para->fd_out_hw_pa[48][0] + + pstv->inf_elm[48].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[49][0] = + fd->dma_para->fd_out_hw_pa[48][0] + + 2 * pstv->inf_elm[49].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[49][1] = + fd->dma_para->fd_out_hw_pa[48][0] + + 3 * pstv->inf_elm[49].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[50][0] = + fd->dma_para->fd_out_hw_pa[48][0] + + 4 * pstv->inf_elm[50].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[51][0] = + fd->dma_para->fd_out_hw_pa[48][0] + + pstv->inf_elm[48].fd_wdma_size[0] + + pstv->inf_elm[48].fd_wdma_size[1] + + pstv->inf_elm[49].fd_wdma_size[0] + + pstv->inf_elm[49].fd_wdma_size[1] + + pstv->inf_elm[50].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[51][1] = + fd->dma_para->fd_out_hw_pa[51][0] + + pstv->inf_elm[51].fd_wdma_size[0] + + pstv->inf_elm[51].fd_wdma_size[2] + + pstv->inf_elm[52].fd_wdma_size[0] + + pstv->inf_elm[52].fd_wdma_size[2] + + pstv->inf_elm[53].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[51][2] = + fd->dma_para->fd_out_hw_pa[51][0] + + pstv->inf_elm[51].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[51][3] = + fd->dma_para->fd_out_hw_pa[51][1] + + pstv->inf_elm[51].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][0] = + fd->dma_para->fd_out_hw_pa[51][0] + + 2 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][1] = + fd->dma_para->fd_out_hw_pa[51][1] + + 2 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][2] = + fd->dma_para->fd_out_hw_pa[51][0] + + 3 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[52][3] = + fd->dma_para->fd_out_hw_pa[51][1] + + 3 * pstv->inf_elm[52].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[53][0] = + fd->dma_para->fd_out_hw_pa[51][0] + + 4 * pstv->inf_elm[53].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[53][1] = + fd->dma_para->fd_out_hw_pa[51][1] + + 4 * pstv->inf_elm[53].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[54][0] = + fd->dma_para->fd_out_hw_pa[51][1] + + pstv->inf_elm[51].fd_wdma_size[1] + + pstv->inf_elm[51].fd_wdma_size[3] + + pstv->inf_elm[52].fd_wdma_size[1] + + pstv->inf_elm[52].fd_wdma_size[3] + + pstv->inf_elm[53].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[54][1] = + fd->dma_para->fd_out_hw_pa[54][0] + + pstv->inf_elm[54].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[55][0] = + fd->dma_para->fd_out_hw_pa[54][0] + + 2 * pstv->inf_elm[55].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[55][1] = + fd->dma_para->fd_out_hw_pa[54][0] + + 3 * pstv->inf_elm[55].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[56][0] = + fd->dma_para->fd_out_hw_pa[54][0] + + 4 * pstv->inf_elm[56].out_xsize_plus_1; + /* 77~85 */ + fd->dma_para->fd_out_hw_pa[77][0] = + fd->dma_para->fd_out_hw_pa[76][1] + + pstv->inf_elm[76].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[77][1] = + fd->dma_para->fd_out_hw_pa[77][0] + + pstv->inf_elm[77].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[78][0] = + fd->dma_para->fd_out_hw_pa[77][0] + + 2 * pstv->inf_elm[78].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[78][1] = + fd->dma_para->fd_out_hw_pa[77][0] + + 3 * pstv->inf_elm[78].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[79][0] = + fd->dma_para->fd_out_hw_pa[77][0] + + 4 * pstv->inf_elm[79].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[80][0] = + fd->dma_para->fd_out_hw_pa[77][0] + + pstv->inf_elm[77].fd_wdma_size[0] + + pstv->inf_elm[77].fd_wdma_size[1] + + pstv->inf_elm[78].fd_wdma_size[0] + + pstv->inf_elm[78].fd_wdma_size[1] + + pstv->inf_elm[79].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[80][1] = + fd->dma_para->fd_out_hw_pa[80][0] + + pstv->inf_elm[80].fd_wdma_size[0] + + pstv->inf_elm[80].fd_wdma_size[2] + + pstv->inf_elm[81].fd_wdma_size[0] + + pstv->inf_elm[81].fd_wdma_size[2] + + pstv->inf_elm[82].fd_wdma_size[0]; + fd->dma_para->fd_out_hw_pa[80][2] = + fd->dma_para->fd_out_hw_pa[80][0] + + pstv->inf_elm[80].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[80][3] = + fd->dma_para->fd_out_hw_pa[80][1] + + pstv->inf_elm[80].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][0] = + fd->dma_para->fd_out_hw_pa[80][0] + + 2 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][1] = + fd->dma_para->fd_out_hw_pa[80][1] + + 2 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][2] = + fd->dma_para->fd_out_hw_pa[80][0] + + 3 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[81][3] = + fd->dma_para->fd_out_hw_pa[80][1] + + 3 * pstv->inf_elm[81].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[82][0] = + fd->dma_para->fd_out_hw_pa[80][0] + + 4 * pstv->inf_elm[82].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[82][1] = + fd->dma_para->fd_out_hw_pa[80][1] + + 4 * pstv->inf_elm[82].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[83][0] = + fd->dma_para->fd_out_hw_pa[80][1] + + pstv->inf_elm[80].fd_wdma_size[1] + + pstv->inf_elm[80].fd_wdma_size[3] + + pstv->inf_elm[81].fd_wdma_size[1] + + pstv->inf_elm[81].fd_wdma_size[3] + + pstv->inf_elm[82].fd_wdma_size[1]; + fd->dma_para->fd_out_hw_pa[83][1] = + fd->dma_para->fd_out_hw_pa[83][0] + + pstv->inf_elm[83].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[84][0] = + fd->dma_para->fd_out_hw_pa[83][0] + + 2 * pstv->inf_elm[84].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[84][1] = + fd->dma_para->fd_out_hw_pa[83][0] + + 3 * pstv->inf_elm[84].out_xsize_plus_1; + fd->dma_para->fd_out_hw_pa[85][0] = + fd->dma_para->fd_out_hw_pa[83][0] + + 4 * pstv->inf_elm[85].out_xsize_plus_1; + + /* VA : except 28, 57, 86 */ + /* 0~86 */ + fd->dma_para->fd_out_hw_va[0][0] = fd->fd_dma_hw.va; + for (i = 1; i < FD_LOOP_NUM; i++) { + if (i == RPN2_LOOP_NUM || i == RPN1_LOOP_NUM || + i == RPN0_LOOP_NUM) + continue; + for (j = 0; j < 4; j++) { + if (fd_wdma_en[i][j]) { + fd->dma_para->fd_out_hw_va[i][j] = + fd->fd_dma_hw.va + + fd->dma_para->fd_out_hw_pa[i][j] - + fd->fd_dma_hw.pa; + } + } + } +} + +static void aie_free_dram_buf(struct mtk_aie_dev *fd) +{ + aie_imem_free(fd, &fd->rs_cfg_data); + aie_imem_free(fd, &fd->fd_cfg_data); + aie_imem_free(fd, &fd->yuv2rgb_cfg_data); +} + +static void aie_free_output_buf(struct mtk_aie_dev *fd) +{ + aie_imem_free(fd, &fd->rs_output_hw); +} + +static void aie_free_fddma_buf(struct mtk_aie_dev *fd) +{ + aie_imem_free(fd, &fd->fd_dma_hw); + aie_imem_free(fd, &fd->fd_kernel_hw); + aie_imem_free(fd, &fd->fd_attr_dma_hw); + aie_imem_free(fd, &fd->fd_dma_result_hw); +} + +static void aie_free_fld_buf(struct mtk_aie_dev *fd) +{ + aie_imem_free(fd, &fd->fd_fld_step_data); + aie_imem_free(fd, &fd->fd_fld_out_hw); +} + +static int aie_copy_fw(struct mtk_aie_dev *fd, const char *name, void *buf, + unsigned int size) +{ + int ret = -EINVAL; + const struct firmware *fw = NULL; + + ret = request_firmware(&fw, name, fd->dev); + if (ret == 0) { + if (size >= fw->size) + memcpy(buf, fw->data, fw->size); + else + ret = -EINVAL; + } + + release_firmware(fw); + + return ret; +} + +static int aie_load_fw(struct mtk_aie_dev *fd) +{ + u8 i = 0, j = 0; + int ret = -EINVAL; + char name[128] = {}; + char *sel_folder = NULL; + char *mp_fw30_folder = "aie_mp_fw"; + char *mp_fw31_folder = "aie_mp_fw31"; + + if (fd->variant->hw_version == 30) + sel_folder = mp_fw30_folder; + else if (fd->variant->hw_version == 31) + sel_folder = mp_fw31_folder; + else + return -EINVAL; + + ret = sprintf(name, "%s/config/aie_fd_fd_config.bin", sel_folder); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->base_para->fd_fd_cfg_va, + fd->fd_fd_cfg_size + ); + if (ret) + return ret; + + ret = sprintf(name, "%s/config/aie_fd_rs_config.bin", sel_folder); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->base_para->fd_rs_cfg_va, + fd->fd_rs_cfg_size + ); + if (ret) + return ret; + + ret = sprintf(name, "%s/config/aie_fd_yuv2rgb_config.bin", sel_folder); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->base_para->fd_yuv2rgb_cfg_va, + fd->fd_yuv2rgb_cfg_size + ); + if (ret) + return ret; + + ret = sprintf(name, "%s/config/aie_attr_fd_config.bin", sel_folder); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->base_para->attr_fd_cfg_va[0], + fd->attr_fd_cfg_size + ); + if (ret) + return ret; + + ret = sprintf(name, "%s/config/aie_attr_yuv2rgb_config.bin", sel_folder); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->base_para->attr_yuv2rgb_cfg_va[0], + fd->attr_yuv2rgb_cfg_size + ); + if (ret) + return ret; + + for (i = 1; i < MAX_ENQUE_FRAME_NUM; i++) { + memcpy(fd->base_para->attr_fd_cfg_va[i], + fd->base_para->attr_fd_cfg_va[0], fd->attr_fd_cfg_size); + memcpy(fd->base_para->attr_yuv2rgb_cfg_va[i], + fd->base_para->attr_yuv2rgb_cfg_va[0], + fd->attr_yuv2rgb_cfg_size); + } + + for (i = 0; i < FD_LOOP_NUM; i++) { + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + if (fd_ker_rdma_size[i][j]) { + ret = sprintf(name, + "%s/kernel/aie_fd_kernel_bias_loop%02d_%d.bin", + sel_folder, + i, + j + ); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->dma_para->fd_kernel_va[i][j], + fd_ker_rdma_size[i][j] + ); + if (ret) + return ret; + } + } + } + + for (i = 0; i < ATTR_LOOP_NUM; i++) { + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + ret = sprintf(name, + "%s/kernel/aie_attr_kernel_bias_loop%02d_%d.bin", + sel_folder, + i, + j + ); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->dma_para->attr_kernel_va[i][j], + attr_ker_rdma_size[i][j] + ); + if (ret) + return ret; + } + } + + if (fd->variant->fld_enable) { + ret = sprintf(name, "%s/config/aie_fld_blink_weight_forest14.bin", sel_folder); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->fld_para->fld_step_va[FLD_STEP_BLINK][14], + fld_step_align_size[FLD_STEP_BLINK][14] + ); + if (ret) + return ret; + + for (j = 0; j < FLD_MAX_FRAME; j++) { + ret = sprintf(name, + "%s/config/aie_fld_cv_forest%02d_iom3.bin", + sel_folder, + j + ); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->fld_para->fld_step_va[FLD_STEP_CV][j], + fld_step_align_size[FLD_STEP_CV][j] + ); + if (ret) + return ret; + } + + for (j = 0; j < FLD_MAX_FRAME; j++) { + ret = sprintf(name, + "%s/config/aie_fld_fp_forest%02d_om45.bin", + sel_folder, + j + ); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->fld_para->fld_step_va[FLD_STEP_FP][j], + fld_step_align_size[FLD_STEP_FP][j] + ); + if (ret) + return ret; + } + + for (j = 0; j < FLD_MAX_FRAME; j++) { + ret = sprintf(name, + "%s/config/aie_fld_leafnode_forest%02d.bin", + sel_folder, + j + ); + if (ret < 0) + return ret; + + ret = aie_copy_fw(fd, + name, + fd->fld_para->fld_step_va[FLD_STEP_LEAF][j], + fld_step_align_size[FLD_STEP_LEAF][j] + ); + if (ret) + return ret; + } + + for (j = 0; j < FLD_MAX_FRAME; j++) { + ret = sprintf(name, + "%s/config/aie_fld_tree_forest%02d_km02.bin", + sel_folder, + j + ); + if (ret < 0) + return ret; + ret = aie_copy_fw(fd, + name, + fd->fld_para->fld_step_va[FLD_STEP_KM02][j], + fld_step_align_size[FLD_STEP_KM02][j] + ); + if (ret) + return ret; + } + + for (j = 0; j < FLD_MAX_FRAME; j++) { + ret = sprintf(name, + "%s/config/aie_fld_tree_forest%02d_km13.bin", + sel_folder, + j + ); + if (ret < 0) + return ret; + ret = aie_copy_fw(fd, + name, + fd->fld_para->fld_step_va[FLD_STEP_KM13][j], + fld_step_align_size[FLD_STEP_KM13][j] + ); + if (ret) + return ret; + } + } + + return ret; +} + +static void aie_reset_output_buf(struct mtk_aie_dev *fd, + struct aie_enq_info *aie_cfg) +{ + if (aie_cfg->sel_mode == FDMODE) { + memset(fd->rs_output_hw.va, 0, fd->rs_output_hw.size); + memset(fd->dma_para->fd_out_hw_va[RPN0_LOOP_NUM][0], 0, + RESULT_SIZE); + memset(fd->dma_para->fd_out_hw_va[RPN1_LOOP_NUM][0], 0, + RESULT_SIZE); + memset(fd->dma_para->fd_out_hw_va[RPN2_LOOP_NUM][0], 0, + RESULT_SIZE); + } else if (aie_cfg->sel_mode == ATTRIBUTEMODE) { + memset(fd->base_para->rs_pym_rst_va[0][0], 0, + fd->rs_pym_out_size[0]); + memset(fd->base_para->rs_pym_rst_va[0][1], 0, + fd->rs_pym_out_size[0]); + memset(fd->base_para->rs_pym_rst_va[0][2], 0, + fd->rs_pym_out_size[0]); + } else if (aie_cfg->sel_mode == FLDMODE) { + if (fd->variant->fld_enable) + memset(fd->fld_para->fld_output_va[0], 0, + FLD_MAX_FRAME * FLD_OUTPUT_SIZE); + } +} + +static int aie_update_cfg(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + int crop_width = 0; + int crop_height = 0; + + crop_width = aie_cfg->src_img_width; + crop_height = aie_cfg->src_img_height; + + if (aie_cfg->en_roi) { + crop_width = dif_x(aie_cfg) + 1; + crop_height = dif_y(aie_cfg) + 1; + } + + if (crop_width == 0 || crop_height == 0) { + dev_err(fd->dev, "AIE error:crop size is wrong"); + return -EINVAL; + } + + if (aie_cfg->en_padding) { + crop_width = crop_width + aie_cfg->src_padding.right + + aie_cfg->src_padding.left; + crop_height = crop_height + aie_cfg->src_padding.up + + aie_cfg->src_padding.down; + } + + if (aie_cfg->sel_mode == FDMODE) { + fd->base_para->sel_mode = aie_cfg->sel_mode; + fd->base_para->crop_width = crop_width; + fd->base_para->crop_height = crop_height; + fd->base_para->src_img_addr = aie_cfg->src_img_addr; + fd->base_para->src_img_addr_uv = aie_cfg->src_img_addr_uv; + fd->base_para->img_width = aie_cfg->src_img_width; + fd->base_para->img_height = aie_cfg->src_img_height; + fd->base_para->src_img_fmt = aie_cfg->src_img_fmt; + fd->base_para->rotate_degree = aie_cfg->rotate_degree; + } else if (aie_cfg->sel_mode == ATTRIBUTEMODE) { + fd->attr_para->sel_mode[fd->attr_para->w_idx] = + aie_cfg->sel_mode; + fd->attr_para->crop_width[fd->attr_para->w_idx] = crop_width; + fd->attr_para->crop_height[fd->attr_para->w_idx] = crop_height; + fd->attr_para->src_img_addr[fd->attr_para->w_idx] = + aie_cfg->src_img_addr; + fd->attr_para->src_img_addr_uv[fd->attr_para->w_idx] = + aie_cfg->src_img_addr_uv; + fd->attr_para->img_width[fd->attr_para->w_idx] = + aie_cfg->src_img_width; + fd->attr_para->img_height[fd->attr_para->w_idx] = + aie_cfg->src_img_height; + fd->attr_para->src_img_fmt[fd->attr_para->w_idx] = + aie_cfg->src_img_fmt; + fd->attr_para->rotate_degree[fd->attr_para->w_idx] = + aie_cfg->rotate_degree; + } + + return 0; +} + +static int aie_config_y2r(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg, + int mode) +{ + u32 img_addr = 0; + u32 img_addr_UV = 0; + u32 img_off = 0; + u32 img_off_uv = 0; + u32 *yuv2rgb_cfg = NULL; + u32 srcbuf, srcbuf_UV = 0; + u16 xmag_0 = 0, ymag_0 = 0; + u16 pym0_out_w = 0; + u16 pym0_out_h = 0; + u16 stride_pym0_out_w = 0; + u16 sr_crp_w = 0; + u16 sr_crp_h = 0; + u16 y1_stride = 0; + + if (!aie_cfg->en_roi) { + img_off = 0; + img_off_uv = 0; + } else { + if (aie_cfg->src_img_fmt == FMT_MONO || + aie_cfg->src_img_fmt == FMT_YUV_2P || + aie_cfg->src_img_fmt == FMT_YVU_2P) { + y1_stride = aie_cfg->src_img_stride * aie_cfg->src_roi.y1; + img_off = y1_stride + aie_cfg->src_roi.x1; + img_off_uv = y1_stride + aie_cfg->src_roi.x1; + } else if (aie_cfg->src_img_fmt == FMT_YUV420_2P || + aie_cfg->src_img_fmt == FMT_YUV420_1P) { + y1_stride = aie_cfg->src_img_stride * aie_cfg->src_roi.y1; + img_off = y1_stride + aie_cfg->src_roi.x1; + img_off_uv = y1_stride / 2 + aie_cfg->src_roi.x1; + } else if (aie_cfg->src_img_fmt == FMT_YUYV || + aie_cfg->src_img_fmt == FMT_YVYU || + aie_cfg->src_img_fmt == FMT_UYVY || + aie_cfg->src_img_fmt == FMT_VYUY) { + y1_stride = aie_cfg->src_img_stride * aie_cfg->src_roi.y1; + img_off = y1_stride + aie_cfg->src_roi.x1 * 2; + img_off_uv = y1_stride + aie_cfg->src_roi.x1 * 2; + } else { + dev_err(fd->dev, + "AIE error: Unsupport input format %d", + aie_cfg->src_img_fmt + ); + return -EINVAL; + } + } + + img_addr = aie_cfg->src_img_addr + img_off; + img_addr_UV = aie_cfg->src_img_addr_uv + img_off_uv; + + srcbuf = img_addr; + if (aie_cfg->src_img_fmt == FMT_YUV420_2P || + aie_cfg->src_img_fmt == FMT_YUV420_1P || + aie_cfg->src_img_fmt == FMT_YUV_2P || + aie_cfg->src_img_fmt == FMT_YVU_2P) + srcbuf_UV = img_addr_UV; + else + srcbuf_UV = 0; + + if (mode == FDMODE) { + sr_crp_w = fd->base_para->crop_width; + sr_crp_h = fd->base_para->crop_height; + yuv2rgb_cfg = (u32 *)fd->base_para->fd_yuv2rgb_cfg_va; + pym0_out_w = fd->base_para->pyramid_width; + } else {/* for ATTRIBUTEMODE mode */ + sr_crp_w = fd->attr_para->crop_width[fd->attr_para->w_idx]; + sr_crp_h = fd->attr_para->crop_height[fd->attr_para->w_idx]; + yuv2rgb_cfg = + (u32 *)fd->base_para + ->attr_yuv2rgb_cfg_va[fd->attr_para->w_idx]; + pym0_out_w = ATTR_MODE_PYRAMID_WIDTH; + } + + pym0_out_h = pym0_out_w * sr_crp_h / sr_crp_w; + + if (pym0_out_w != 0) { + xmag_0 = 512 * sr_crp_w / pym0_out_w; + ymag_0 = xmag_0; + } else { + xmag_0 = 0; + ymag_0 = 0; + } + + yuv2rgb_cfg[Y2R_SRC_DST_FORMAT] = + (yuv2rgb_cfg[Y2R_SRC_DST_FORMAT] & 0xFFFFFFF8) | + ((aie_cfg->src_img_fmt) & 0x7); + if (aie_cfg->src_img_fmt == FMT_YUV420_2P || + aie_cfg->src_img_fmt == FMT_YUV420_1P) { /* for match patten */ + yuv2rgb_cfg[Y2R_SRC_DST_FORMAT] = + (yuv2rgb_cfg[Y2R_SRC_DST_FORMAT] & 0xFFFFFFF8) | + ((0x3) & 0x7); + } + yuv2rgb_cfg[Y2R_IN_W_H] = (yuv2rgb_cfg[Y2R_IN_W_H] & 0xF800F800) | + ((sr_crp_w << 16) & 0x7FF0000) | + (sr_crp_h & 0x7FF); + yuv2rgb_cfg[Y2R_OUT_W_H] = (yuv2rgb_cfg[Y2R_OUT_W_H] & 0xF800F800) | + ((pym0_out_w << 16) & 0x7FF0000) | + (pym0_out_h & 0x7FF); + + if (aie_cfg->src_img_fmt == FMT_YUV_2P || + aie_cfg->src_img_fmt == FMT_YVU_2P) { /* 2 plane */ + yuv2rgb_cfg[Y2R_RA0_RA1_EN] = + (yuv2rgb_cfg[Y2R_RA0_RA1_EN] & 0xFFFFFFEE) | 0x11; + if (aie_cfg->en_roi) { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = aie_cmb_u16(dif_x(aie_cfg), dif_y(aie_cfg)); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = aie_cmb_u16(dif_x(aie_cfg), dif_y(aie_cfg)); + } else { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = + aie_cmb_u16(sr_crp_w - 1, sr_crp_h - 1); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = + aie_cmb_u16(sr_crp_w - 1, sr_crp_h - 1); + } + yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] = + (yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x1; + yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] = + (yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x1; + } else if (aie_cfg->src_img_fmt == FMT_MONO) { + yuv2rgb_cfg[Y2R_RA0_RA1_EN] = + (yuv2rgb_cfg[Y2R_RA0_RA1_EN] & 0xFFFFFFEE) | 0x01; + if (aie_cfg->en_roi) { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = aie_cmb_u16(dif_x(aie_cfg), dif_y(aie_cfg)); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = aie_cmb_u16(dif_x(aie_cfg), dif_y(aie_cfg)); + } else { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = + aie_cmb_u16(sr_crp_w - 1, sr_crp_h - 1); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = + aie_cmb_u16(sr_crp_w - 1, sr_crp_h - 1); + } + yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] = + (yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x0; + yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] = + (yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x0; + } else if (aie_cfg->src_img_fmt == FMT_YUYV || + aie_cfg->src_img_fmt == FMT_YVYU || + aie_cfg->src_img_fmt == FMT_UYVY || + aie_cfg->src_img_fmt == FMT_VYUY) { /* 1 plane */ + yuv2rgb_cfg[Y2R_RA0_RA1_EN] = + (yuv2rgb_cfg[Y2R_RA0_RA1_EN] & 0xFFFFFFEE) | 0x1; + if (aie_cfg->en_roi) { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = aie_cmb_u16(2 * (dif_x(aie_cfg) + 1) - 1, + dif_y(aie_cfg) + ); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = aie_cmb_u16(2 * (dif_x(aie_cfg) + 1) - 1, + dif_y(aie_cfg) + ); + } else { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = aie_cmb_u16(2 * sr_crp_w - 1, sr_crp_h - 1); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = aie_cmb_u16(2 * sr_crp_w - 1, sr_crp_h - 1); + } + yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] = + (yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x3; + yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] = + (yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x3; + } + + /* AIE3.0 */ + if (aie_cfg->src_img_fmt == FMT_YUV420_2P || + aie_cfg->src_img_fmt == FMT_YUV420_1P) { + yuv2rgb_cfg[Y2R_RA0_RA1_EN] = + (yuv2rgb_cfg[Y2R_RA0_RA1_EN] & 0xFFFFFFEE) | 0x11; + if (aie_cfg->en_roi) { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = aie_cmb_u16(dif_x(aie_cfg), dif_y(aie_cfg)); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = aie_cmb_u16(dif_x(aie_cfg), + dif_y(aie_cfg) / 2 + ); + } else { + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE0] = + aie_cmb_u16(sr_crp_w - 1, sr_crp_h - 1); + yuv2rgb_cfg[Y2R_IN_X_Y_SIZE1] = aie_cmb_u16(sr_crp_w - 1, + sr_crp_h / 2 - 1 + ); + } + yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] = + (yuv2rgb_cfg[Y2R_IN_STRIDE0_BUS_SIZE0] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x0; + yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] = + (yuv2rgb_cfg[Y2R_IN_STRIDE1_BUS_SIZE1] & 0xFFF0) | + ((aie_cfg->src_img_stride << 16) & 0xFFFF0000) | 0x0; + + yuv2rgb_cfg[Y2R_CO2_FMT_MODE_EN] = + (yuv2rgb_cfg[Y2R_CO2_FMT_MODE_EN] & 0xFFFFFFFE) | 0x01; + if (aie_cfg->en_roi) { + yuv2rgb_cfg[Y2R_CO2_CROP_X] = aie_cmb_u16(0, dif_x(aie_cfg)); + yuv2rgb_cfg[Y2R_CO2_CROP_Y] = aie_cmb_u16(0, dif_y(aie_cfg)); + } else { + yuv2rgb_cfg[Y2R_CO2_CROP_X] = + aie_cmb_u16(0, sr_crp_w - 1); + yuv2rgb_cfg[Y2R_CO2_CROP_Y] = + aie_cmb_u16(0, sr_crp_h - 1); + } + } else { + yuv2rgb_cfg[Y2R_CO2_FMT_MODE_EN] = + (yuv2rgb_cfg[Y2R_CO2_FMT_MODE_EN] & 0xFFFFFFFE); + + if (aie_cfg->en_roi) { + yuv2rgb_cfg[Y2R_CO2_CROP_X] = aie_cmb_u16(0, dif_x(aie_cfg)); + yuv2rgb_cfg[Y2R_CO2_CROP_Y] = aie_cmb_u16(0, dif_y(aie_cfg)); + } else { + yuv2rgb_cfg[Y2R_CO2_CROP_X] = + aie_cmb_u16(0, sr_crp_w - 1); + yuv2rgb_cfg[Y2R_CO2_CROP_Y] = + aie_cmb_u16(0, sr_crp_h - 1); + } + } + + stride_pym0_out_w = round_up(pym0_out_w, 8); + + yuv2rgb_cfg[Y2R_OUT_X_Y_SIZE0] = + aie_cmb_u16(pym0_out_w - 1, pym0_out_h - 1); + set_cmb_cfg(yuv2rgb_cfg, Y2R_OUT_STRIDE0_BUS_SIZE0, stride_pym0_out_w); + yuv2rgb_cfg[Y2R_OUT_X_Y_SIZE1] = + aie_cmb_u16(pym0_out_w - 1, pym0_out_h - 1); + set_cmb_cfg(yuv2rgb_cfg, Y2R_OUT_STRIDE1_BUS_SIZE1, stride_pym0_out_w); + yuv2rgb_cfg[Y2R_OUT_X_Y_SIZE2] = + aie_cmb_u16(pym0_out_w - 1, pym0_out_h - 1); + set_cmb_cfg(yuv2rgb_cfg, Y2R_OUT_STRIDE2_BUS_SIZE2, stride_pym0_out_w); + + if (aie_cfg->en_padding) { + yuv2rgb_cfg[Y2R_PADDING_EN_UP_DOWN] = + 1 | ((aie_cfg->src_padding.up << 4) & 0x1FF0) | + ((aie_cfg->src_padding.down << 16) & 0x01FF0000); + yuv2rgb_cfg[Y2R_PADDING_RIGHT_LEFT] = + (aie_cfg->src_padding.right & 0x01FF) | + ((aie_cfg->src_padding.left << 16) & 0x01FF0000); + } else { + yuv2rgb_cfg[Y2R_PADDING_EN_UP_DOWN] = 0; + yuv2rgb_cfg[Y2R_PADDING_RIGHT_LEFT] = 0; + } + + yuv2rgb_cfg[Y2R_IN_0] = srcbuf; + yuv2rgb_cfg[Y2R_IN_1] = srcbuf_UV; + + yuv2rgb_cfg[Y2R_OUT_0] = (u32)fd->base_para->rs_pym_rst_pa[0][0]; + yuv2rgb_cfg[Y2R_OUT_1] = (u32)fd->base_para->rs_pym_rst_pa[0][1]; + yuv2rgb_cfg[Y2R_OUT_2] = (u32)fd->base_para->rs_pym_rst_pa[0][2]; + + yuv2rgb_cfg[Y2R_X_Y_MAG] = (xmag_0 & 0x3FFF) | + ((ymag_0 << 16) & 0x3FFF0000); + + if (sr_crp_w >= pym0_out_w) { /* down scale AIE1.0 by FRZ */ + yuv2rgb_cfg[Y2R_RS_SEL_SRZ_EN] = + (yuv2rgb_cfg[Y2R_RS_SEL_SRZ_EN] & 0x00100070); + yuv2rgb_cfg[Y2R_SRZ_HORI_STEP] = 0; + yuv2rgb_cfg[Y2R_SRZ_VERT_STEP] = 0; + } else { /* SRZ */ + /* 0: FDRZ for down scaling */ + /* 1: SRZ for up scaling */ + yuv2rgb_cfg[Y2R_RS_SEL_SRZ_EN] = + (yuv2rgb_cfg[Y2R_RS_SEL_SRZ_EN] & 0x00100070) | SRZ_BIT; + yuv2rgb_cfg[Y2R_SRZ_HORI_STEP] = + ((sr_crp_w - 1) << 15) / (pym0_out_w - 1); + yuv2rgb_cfg[Y2R_SRZ_VERT_STEP] = + ((sr_crp_h - 1) << 15) / (pym0_out_h - 1); + } + + if (fd->variant->hw_version == 31) { + yuv2rgb_cfg[Y2R_CON_IN_BA_MSB] = (u32)0x02020202; + yuv2rgb_cfg[Y2R_CON_OUT_BA_MSB] = (u32)0x02020202; + } + + return 0; +} + +static int aie_config_rs(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + u32 *rs_cfg = NULL; + u32 *rs_tbl[2] = { NULL, NULL }; + u16 xmag_0 = 0, ymag_0 = 0; + u16 pym_out_w[3] = { 0, 0, 0 }; + u16 pym_out_h[3] = { 0, 0, 0 }; + u16 round_w = 0; + u16 sr_crp_w = 0; + u16 sr_crp_h = 0; + int i = 0; + + sr_crp_w = fd->base_para->crop_width; + sr_crp_h = fd->base_para->crop_height; + + rs_cfg = (u32 *)fd->base_para->fd_rs_cfg_va; + + pym_out_w[0] = fd->base_para->pyramid_width; + pym_out_w[1] = pym_out_w[0] >> 1; + pym_out_w[2] = pym_out_w[1] >> 1; + + pym_out_h[0] = pym_out_w[0] * sr_crp_h / sr_crp_w; + pym_out_h[1] = pym_out_h[0] >> 1; + pym_out_h[2] = pym_out_h[1] >> 1; + + for (i = 0; i < 2; i++) { + rs_tbl[i] = rs_cfg + fd->variant->rs_cfg_size * i; + + rs_tbl[i][RS_IN_0] = (u32)fd->base_para->rs_pym_rst_pa[i][0]; + rs_tbl[i][RS_IN_1] = (u32)fd->base_para->rs_pym_rst_pa[i][1]; + rs_tbl[i][RS_IN_2] = (u32)fd->base_para->rs_pym_rst_pa[i][2]; + + rs_tbl[i][RS_OUT_0] = + (u32)fd->base_para->rs_pym_rst_pa[i + 1][0]; + rs_tbl[i][RS_OUT_1] = + (u32)fd->base_para->rs_pym_rst_pa[i + 1][1]; + rs_tbl[i][RS_OUT_2] = + (u32)fd->base_para->rs_pym_rst_pa[i + 1][2]; + + rs_tbl[i][RS_INPUT_W_H] = + (rs_tbl[i][RS_INPUT_W_H] & 0xF800F800) | + (pym_out_h[i] & 0x7FF) | + ((pym_out_w[i] << 16) & 0x7FF0000); + rs_tbl[i][RS_OUTPUT_W_H] = + (rs_tbl[i][RS_OUTPUT_W_H] & 0xF800F800) | + (pym_out_h[i + 1] & 0x7FF) | + ((pym_out_w[i + 1] << 16) & 0x7FF0000); + rs_tbl[i][RS_IN_X_Y_SIZE0] = + aie_cmb_u16(pym_out_w[i] - 1, pym_out_h[i] - 1); + rs_tbl[i][RS_IN_X_Y_SIZE1] = + aie_cmb_u16(pym_out_w[i] - 1, pym_out_h[i] - 1); + rs_tbl[i][RS_IN_X_Y_SIZE2] = + aie_cmb_u16(pym_out_w[i] - 1, pym_out_h[i] - 1); + set_cmb_cfg(rs_tbl[i], RS_IN_STRIDE0, pym_out_w[i]); + set_cmb_cfg(rs_tbl[i], RS_IN_STRIDE1, pym_out_w[i]); + set_cmb_cfg(rs_tbl[i], RS_IN_STRIDE2, pym_out_w[i]); + rs_tbl[i][RS_OUT_X_Y_SIZE0] = aie_cmb_u16(pym_out_w[i + 1] - 1, + pym_out_h[i + 1] - 1 + ); + rs_tbl[i][RS_OUT_X_Y_SIZE1] = aie_cmb_u16(pym_out_w[i + 1] - 1, + pym_out_h[i + 1] - 1 + ); + rs_tbl[i][RS_OUT_X_Y_SIZE2] = aie_cmb_u16(pym_out_w[i + 1] - 1, + pym_out_h[i + 1] - 1 + ); + + if (i == 0) + round_w = pym_out_w[i + 1]; + else + round_w = round_up(pym_out_w[i + 1], 8); + + set_cmb_cfg(rs_tbl[i], RS_OUT_STRIDE0, round_w); + set_cmb_cfg(rs_tbl[i], RS_OUT_STRIDE1, round_w); + set_cmb_cfg(rs_tbl[i], RS_OUT_STRIDE2, round_w); + + xmag_0 = 512 * pym_out_w[i] / pym_out_w[i + 1]; + ymag_0 = xmag_0; + + rs_tbl[i][RS_X_Y_MAG] = (xmag_0 & 0x3FFF) | + ((ymag_0 << 16) & 0x3FFF0000); + + if (fd->variant->hw_version == 31) { + rs_tbl[i][RS_CON_IN_BA_MSB] = (u32)0x02020202; + rs_tbl[i][RS_CON_OUT_BA_MSB] = (u32)0x02020202; + } + } + + return 0; +} + +static int aie_config_network(struct mtk_aie_dev *fd, + struct aie_enq_info *aie_cfg) +{ + u16 conv_width = 0; + u16 conv_height = 0; + u8 i = 0; + u8 j = 0; + u8 uch = 0; + u8 uloop = 0; + u16 fd_xsize[4] = { 0, 0, 0, 0 }; + void *fd_cfg = NULL; + u32 *fd_cur_cfg = NULL; + u32 *fd_cur_set = NULL; + u16 pyramid0_out_w = 0; + u16 pyramid0_out_h = 0; + u16 pyramid1_out_h = 0; + u16 pyramid2_out_h = 0; + u16 input_height = 0; + u16 out_height = 0; + u16 out_ysize_plus_1 = 0; + u16 out_ysize_plus_1_stride2 = 0; + u32 sr_crp_w = 0; + u32 sr_crp_h = 0; + struct aie_static_info *pstv = &fd->st_info; + u32 cal_x = 0; + u32 cal_y = 0; + + sr_crp_w = fd->base_para->crop_width; + sr_crp_h = fd->base_para->crop_height; + + pyramid0_out_w = fd->base_para->pyramid_width; + pyramid0_out_h = pyramid0_out_w * sr_crp_h / sr_crp_w; + + pyramid1_out_h = pyramid0_out_h / 2; + pyramid2_out_h = pyramid1_out_h / 2; + + fd_cfg = fd->base_para->fd_fd_cfg_va; + + for (i = 0; i < FD_LOOP_NUM; i++) { + fd_cur_cfg = (u32 *)fd_cfg + fd->variant->fd_cfg_size * i; + fd_cur_cfg[FD_INPUT_ROTATE] = + (fd_cur_cfg[FD_INPUT_ROTATE] & 0xFFFF0FFF) | + ((aie_cfg->rotate_degree << 12) & 0x3000); + + if (i == 0) + input_height = pyramid2_out_h; + else if (i == (RPN2_LOOP_NUM + 1)) + input_height = pyramid1_out_h; + else if (i == (RPN1_LOOP_NUM + 1)) + input_height = pyramid0_out_h; + else + if (fd_out_stride2_in[i] == 0) + input_height = out_height; + else + input_height = (out_height + 1) / 2; + + if (fd_maxpool[i] == 1 && fd_stride[i] == 1) + out_height = + DIV_ROUND_UP(input_height, 2 * fd_maxpool[i]); + else + out_height = DIV_ROUND_UP(input_height, fd_stride[i] + 2 * fd_maxpool[i]); + + if (i == RPN0_LOOP_NUM || i == RPN1_LOOP_NUM || + i == RPN2_LOOP_NUM) { + conv_width = fd->base_para->img_width; + conv_height = fd->base_para->img_height; + fd_xsize[0] = pstv->inf_elm[i].img_width * 2 * 16 * + anchor_en_num[i] - + 1; + fd_xsize[3] = pstv->inf_elm[i].img_width * 2 * 32 * + anchor_en_num[i] - 1; + fd_xsize[2] = fd_xsize[3]; + fd_xsize[1] = fd_xsize[2]; + } else { + conv_width = DIV_ROUND_UP(pstv->inf_elm[i].img_width, fd_stride[i]); + conv_height = DIV_ROUND_UP(input_height, fd_stride[i]); + + fd_xsize[3] = pstv->inf_elm[i].input_xsize_plus_1 - 1; + fd_xsize[2] = fd_xsize[3]; + fd_xsize[1] = fd_xsize[2]; + fd_xsize[0] = fd_xsize[1]; + } + + fd_cur_cfg[FD_CONV_WIDTH_MOD6] = + (fd_cur_cfg[FD_CONV_WIDTH_MOD6] & 0xFF8FFFFF) | + (((conv_width % 6) << 20) & 0x00700000); + fd_cur_cfg[FD_CONV_IMG_W_H] = + aie_cmb_u16(conv_height, conv_width); + + fd_cur_cfg[FD_IN_IMG_W_H] = aie_cmb_u16(input_height, pstv->inf_elm[i].img_width); + fd_cur_cfg[FD_OUT_IMG_W_H] = aie_cmb_u16(out_height, pstv->inf_elm[i].out_width); + + if (fd_rdma_en[i][0][0] != -1) { + for (j = 0; j < 4; j++) { + fd_cur_cfg[FD_IN_X_Y_SIZE0 + 2 * j] = + aie_cmb_u16(fd_xsize[j], input_height - 1); + set_cmbst_cfg(fd_cur_cfg, + FD_IN_STRIDE0_BUS_SIZE0 + 2 * j, + fd_xsize[j] + 1 + ); + } + } + + out_ysize_plus_1 = out_height - 1; + out_ysize_plus_1_stride2 = (out_height + 1) / 2 - 1; + + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + fd_cur_set = fd_cur_cfg + 2 * j; + if (!fd_wdma_en[i][j]) + continue; + + if (out_stride_size[i][j] == 1) { + fd_cur_set[FD_OUT_X_Y_SIZE0] = + aie_cmb_u16(pstv->inf_elm[i].out_xsize_plus_1 - 1, + out_ysize_plus_1 + ); + set_cmbst_cfg(fd_cur_set, + FD_OUT_STRIDE0_BUS_SIZE0, + pstv->inf_elm[i].out_stride + ); + } else if (out_stride_size[i][j] == 2) { + fd_cur_set[FD_OUT_X_Y_SIZE0] = + aie_cmb_u16(pstv->inf_elm[i].out_xsize_plus_1_stride2 - 1, + out_ysize_plus_1_stride2 + ); + set_cmbst_cfg(fd_cur_set, + FD_OUT_STRIDE0_BUS_SIZE0, + pstv->inf_elm[i].out_stride_stride2 + ); + } + } + + if (i == RPN0_LOOP_NUM || i == RPN1_LOOP_NUM || i == RPN2_LOOP_NUM) + set_cmb_cfg(fd_cur_cfg, FD_RPN_SET, fd->base_para->rpn_anchor_thrd); + + if (i == RPN0_LOOP_NUM) { + cal_x = ((sr_crp_w << 10) * 100 / + (int)fd->base_para->pyramid_width) >> + 10; + cal_y = cal_x * 512 / 100; + fd_cur_cfg[FD_IMAGE_COORD] = + (fd_cur_cfg[FD_IMAGE_COORD] & 0xF) | + ((cal_y << 4) & 0x7FFF0); + fd_cur_cfg[FD_IMAGE_COORD_XY_OFST] = 0; + if (aie_cfg->en_roi) { + fd_cur_cfg[FD_IMAGE_COORD_XY_OFST] = + (aie_cfg->src_roi.x1 - + aie_cfg->src_padding.left) | + (aie_cfg->src_roi.y1 - + aie_cfg->src_padding.up) + << 16; + } + } else if (i == RPN1_LOOP_NUM) { + cal_x = ((sr_crp_w << 10) * 100 / + (int)fd->base_para->pyramid_width) >> + 10; + cal_y = cal_x * 2 * 512 / 100; + fd_cur_cfg[FD_IMAGE_COORD] = + (fd_cur_cfg[FD_IMAGE_COORD] & 0xF) | + ((cal_y << 4) & 0x7FFF0); + fd_cur_cfg[FD_IMAGE_COORD_XY_OFST] = 0; + if (aie_cfg->en_roi) { + fd_cur_cfg[FD_IMAGE_COORD_XY_OFST] = + (aie_cfg->src_roi.x1 - + aie_cfg->src_padding.left) | + (aie_cfg->src_roi.y1 - + aie_cfg->src_padding.up) + << 16; + } + } else if (i == RPN2_LOOP_NUM) { + cal_x = ((sr_crp_w << 10) * 100 / + (int)fd->base_para->pyramid_width) >> + 10; + cal_y = cal_x * 4 * 512 / 100; + fd_cur_cfg[FD_IMAGE_COORD] = + (fd_cur_cfg[FD_IMAGE_COORD] & 0xF) | + ((cal_y << 4) & 0x7FFF0); + fd_cur_cfg[FD_IMAGE_COORD_XY_OFST] = 0; + if (aie_cfg->en_roi) { + fd_cur_cfg[FD_IMAGE_COORD_XY_OFST] = + (aie_cfg->src_roi.x1 - + aie_cfg->src_padding.left) | + (aie_cfg->src_roi.y1 - + aie_cfg->src_padding.up) + << 16; + } + } + + /* IN_FM_BASE_ADR */ + if (i == 0) { + fd_cur_cfg[FD_IN_0] = + (u32)(fd->base_para->rs_pym_rst_pa[2][0]); + fd_cur_cfg[FD_IN_1] = + (u32)(fd->base_para->rs_pym_rst_pa[2][1]); + fd_cur_cfg[FD_IN_2] = + (u32)(fd->base_para->rs_pym_rst_pa[2][2]); + } else if (i == (RPN2_LOOP_NUM + 1)) { + fd_cur_cfg[FD_IN_0] = + (u32)(fd->base_para->rs_pym_rst_pa[1][0]); + fd_cur_cfg[FD_IN_1] = + (u32)(fd->base_para->rs_pym_rst_pa[1][1]); + fd_cur_cfg[FD_IN_2] = + (u32)(fd->base_para->rs_pym_rst_pa[1][2]); + } else if (i == (RPN1_LOOP_NUM + 1)) { + fd_cur_cfg[FD_IN_0] = + (u32)(fd->base_para->rs_pym_rst_pa[0][0]); + fd_cur_cfg[FD_IN_1] = + (u32)(fd->base_para->rs_pym_rst_pa[0][1]); + fd_cur_cfg[FD_IN_2] = + (u32)(fd->base_para->rs_pym_rst_pa[0][2]); + } else { + for (j = 0; j < INPUT_WDMA_WRA_NUM; j++) { + if (fd_rdma_en[i][j][0] != -1) { + uloop = fd_rdma_en[i][j][0]; + uch = fd_rdma_en[i][j][1]; + fd_cur_cfg[FD_IN_0 + j] = + (u32)(fd->dma_para->fd_out_hw_pa + [uloop][uch]); + } + } + } + + /* OUT_FM_BASE_ADR */ + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + if (fd_wdma_en[i][j]) + fd_cur_cfg[FD_OUT_0 + j] = + (u32)(fd->dma_para->fd_out_hw_pa[i][j]); + } + + /* KERNEL_BASE_ADR */ + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + if (fd_ker_rdma_size[i][j]) + fd_cur_cfg[FD_KERNEL_0 + j] = + (u32)(fd->dma_para->fd_kernel_pa[i][j]); + } + + if (fd->variant->hw_version == 31) { + fd_cur_cfg[FD_CON_IN_BA_MSB] = (u32)0x02020202; + fd_cur_cfg[FD_CON_OUT_BA_MSB] = (u32)0x02020202; + fd_cur_cfg[FD_CON_KERNEL_BA_MSB] = (u32)0x00000202; + } + } + + return 0; +} + +static int aie_config_attr_network(struct mtk_aie_dev *fd, + struct aie_enq_info *aie_cfg) +{ + bool is_regression_loop = false; + void *fd_cfg = NULL; + u32 *fd_cur_cfg = NULL; + u16 fd_input_ht = 0, fd_output_ht = 0; + u16 fd_out_y[4] = { 0, 0, 0, 0 }; + u8 i = 0, j = 0; + u8 uloop = 0, uch = 0, uidx = 0; + u16 pyramid0_out_w = 0, pyramid0_out_h = 0; + int fd_conv_ht = 0; + u16 sr_crp_w = 0; + u16 sr_crp_h = 0; + + sr_crp_w = fd->attr_para->crop_width[fd->attr_para->w_idx]; + sr_crp_h = fd->attr_para->crop_height[fd->attr_para->w_idx]; + + pyramid0_out_w = ATTR_MODE_PYRAMID_WIDTH; + pyramid0_out_h = pyramid0_out_w * sr_crp_h / sr_crp_w; + + fd_cfg = fd->base_para->attr_fd_cfg_va[fd->attr_para->w_idx]; + + for (i = 0; i < ATTR_LOOP_NUM; i++) { + fd_cur_cfg = (u32 *)fd_cfg + fd->variant->fd_cfg_size * i; + fd_cur_cfg[FD_INPUT_ROTATE] = + (fd_cur_cfg[FD_INPUT_ROTATE] & 0xFFFF0FFF) | + ((aie_cfg->rotate_degree << 12) & 0x3000); + if (i == 0) + fd_input_ht = pyramid0_out_h; + else + if (attr_out_stride2_as_in[i] == 0) + fd_input_ht = fd_output_ht; + else if (attr_out_stride2_as_in[i] == 1) + fd_input_ht = (fd_output_ht + 1) / 2; + + fd_output_ht = DIV_ROUND_UP(fd_input_ht, + attr_fd_stride[i] + + 2 * attr_fd_maxpool[i] + ); + fd_conv_ht = DIV_ROUND_UP(fd_input_ht, attr_fd_stride[i]); + + fd_cur_cfg[FD_CONV_IMG_W_H] = + (fd_cur_cfg[FD_CONV_IMG_W_H] & 0xFFFF0000) | + (fd_conv_ht & 0xFFFF); + fd_cur_cfg[FD_IN_IMG_W_H] = + (fd_cur_cfg[FD_IN_IMG_W_H] & 0xFFFF0000) | + (fd_input_ht & 0xFFFF); + fd_cur_cfg[FD_OUT_IMG_W_H] = + (fd_cur_cfg[FD_OUT_IMG_W_H] & 0xFFFF0000) | + (fd_output_ht & 0xFFFF); + set_cmb_cfg(fd_cur_cfg, FD_IN_X_Y_SIZE0, fd_input_ht - 1); + set_cmb_cfg(fd_cur_cfg, FD_IN_X_Y_SIZE1, fd_input_ht - 1); + set_cmb_cfg(fd_cur_cfg, FD_IN_X_Y_SIZE2, fd_input_ht - 1); + set_cmb_cfg(fd_cur_cfg, FD_IN_X_Y_SIZE3, fd_input_ht - 1); + + is_regression_loop = (i == AGE_OUT_RGS || i == GENDER_OUT_RGS || + i == INDIAN_OUT_RGS || i == RACE_OUT_RGS); + + if (is_regression_loop) { + fd_out_y[0] = 0; + fd_out_y[1] = 0; + fd_out_y[2] = 0; + fd_out_y[3] = 0; + } else { + fd_out_y[0] = fd_output_ht - 1; + fd_out_y[1] = fd_output_ht - 1; + if (attr_out_2size[i] == 0) { + fd_out_y[2] = fd_output_ht - 1; + fd_out_y[3] = fd_output_ht - 1; + } else { + fd_out_y[2] = (fd_output_ht + 1) / 2 - 1; + fd_out_y[3] = (fd_output_ht + 1) / 2 - 1; + } + } + + for (j = 0; j < 4; j++) + set_cmb_cfg(fd_cur_cfg, FD_OUT_X_Y_SIZE0 + 2 * j, fd_out_y[j]); + + /* IN_FM_BASE_ADR */ + if (i == 0) { + fd_cur_cfg[FD_IN_0] = + (u32)(fd->base_para->rs_pym_rst_pa[0][0]); + fd_cur_cfg[FD_IN_1] = + (u32)(fd->base_para->rs_pym_rst_pa[0][1]); + fd_cur_cfg[FD_IN_2] = + (u32)(fd->base_para->rs_pym_rst_pa[0][2]); + } else { + for (j = 0; j < INPUT_WDMA_WRA_NUM; j++) { + if (attr_rdma_en[i][j][0] != -1) { + uloop = attr_rdma_en[i][j][0]; + uch = attr_rdma_en[i][j][1]; + fd_cur_cfg[FD_IN_0 + j] = + (u32)(fd->dma_para->attr_out_hw_pa + [uloop][uch]); + } + } + } + + /* OUT_FM_BASE_ADR */ + for (j = 0; j < OUTPUT_WDMA_WRA_NUM; j++) { + if (attr_wdma_en[i][j]) { + uidx = fd->attr_para->w_idx; + if (i == AGE_OUT_RGS && j == 0) + fd_cur_cfg[FD_OUT_0 + j] = + (u32)(fd->dma_para->age_out_hw_pa + [uidx]); + else if (i == GENDER_OUT_RGS && j == 0) + fd_cur_cfg[FD_OUT_0 + j] = + (u32)(fd->dma_para + ->gender_out_hw_pa + [uidx]); + else if (i == INDIAN_OUT_RGS && j == 0) + fd_cur_cfg[FD_OUT_0 + j] = + (u32)(fd->dma_para + ->is_indian_out_hw_pa + [uidx]); + else if (i == RACE_OUT_RGS && j == 0) + fd_cur_cfg[FD_OUT_0 + j] = + (u32)(fd->dma_para + ->race_out_hw_pa + [uidx]); + else + fd_cur_cfg[FD_OUT_0 + j] = + (u32)(fd->dma_para + ->attr_out_hw_pa + [i][j]); + } + } + + /* KERNEL_BASE_ADR */ + for (j = 0; j < KERNEL_RDMA_RA_NUM; j++) { + fd_cur_cfg[FD_KERNEL_0 + j] = + (u32)(fd->dma_para->attr_kernel_pa[i][j]); + } + + if (fd->variant->hw_version == 31) { + fd_cur_cfg[FD_CON_IN_BA_MSB] = (u32)0x02020202; + fd_cur_cfg[FD_CON_OUT_BA_MSB] = (u32)0x02020202; + fd_cur_cfg[FD_CON_KERNEL_BA_MSB] = (u32)0x00000202; + } + } + return 0; +} + +static int aie_config_dram(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + int ret = -EINVAL; + + if (aie_cfg->sel_mode == FDMODE) { + ret = aie_config_y2r(fd, aie_cfg, aie_cfg->sel_mode); + if (ret) + return ret; + + ret = aie_config_rs(fd, aie_cfg); + if (ret) + return ret; + + ret = aie_config_network(fd, aie_cfg); + if (ret) + return ret; + + } else if (aie_cfg->sel_mode == ATTRIBUTEMODE) { + ret = aie_config_y2r(fd, aie_cfg, aie_cfg->sel_mode); + if (ret) + return ret; + + ret = aie_config_attr_network(fd, aie_cfg); + if (ret) + return ret; + } + + return ret; +} + +void aie_reset(struct mtk_aie_dev *fd) +{ + writel(0x30000, fd->fd_base + AIE_START_REG); + writel(0x0, fd->fd_base + AIE_START_REG); +} + +int aie_init(struct mtk_aie_dev *fd, struct v4l2_ctrl_aie_init *user_init) +{ + int ret = -ENOMEM; + int i = 0, j = 0; + + if (fd->fd_state & STATE_INIT) { + dev_err(fd->dev, "%s fd state: %d\n", __func__, fd->fd_state); + return -EINVAL; + } + + fd->fd_state &= ~STATE_INIT; + fd->fd_mem_size = 0; + + fd->base_para = kmalloc(sizeof(*fd->base_para), GFP_KERNEL); + if (!fd->base_para) + goto kmalloc_fail; + + fd->attr_para = kmalloc(sizeof(*fd->attr_para), GFP_KERNEL); + if (!fd->attr_para) + goto kmalloc_fail; + + fd->dma_para = kmalloc(sizeof(*fd->dma_para), GFP_KERNEL); + if (!fd->dma_para) + goto kmalloc_fail; + + if (fd->variant->fld_enable) { + fd->fld_para = + kmalloc(sizeof(*fd->fld_para), GFP_KERNEL); + if (!fd->fld_para) + goto kmalloc_fail; + } + + fd->base_para->rpn_anchor_thrd = + (signed short)(user_init->feature_threshold & 0x0000FFFF); + fd->base_para->pyramid_width = user_init->pyramid_width; + fd->base_para->pyramid_height = user_init->pyramid_height; + fd->base_para->max_pyramid_width = user_init->pyramid_width; + fd->base_para->max_pyramid_height = user_init->pyramid_height; + + fd->base_para->fd_fd_cfg_va = NULL; + fd->base_para->fd_rs_cfg_va = NULL; + fd->base_para->fd_yuv2rgb_cfg_va = NULL; + for (i = 0; i < MAX_ENQUE_FRAME_NUM; i++) + fd->base_para->attr_fd_cfg_va[i] = NULL; + for (i = 0; i < MAX_ENQUE_FRAME_NUM; i++) + fd->base_para->attr_yuv2rgb_cfg_va[i] = NULL; + for (i = 0; i < PYM_NUM; i++) + for (j = 0; j < COLOR_NUM; j++) + fd->base_para->rs_pym_rst_va[i][j] = NULL; + + memset(&fd->st_info, 0, sizeof(struct aie_static_info)); + aie_init_table(fd, fd->base_para->max_pyramid_width, + fd->base_para->max_pyramid_height); + aie_update_buf_params(fd, user_init->max_img_width, + user_init->max_img_height); + ret = aie_alloc_dram_buf(fd); + if (ret) + goto free_all; + + ret = aie_alloc_output_buf(fd); + if (ret) + goto free_all; + + ret = aie_alloc_fddma_buf(fd); + if (ret) + goto free_all; + + if (fd->variant->fld_enable) { + ret = aie_alloc_fld_buf(fd); + if (ret) + goto free_all; + } + + aie_arrange_fddma_buf(fd); + aie_arrange_kernel_buf(fd); + aie_arrange_attrdma_buf(fd); + aie_arrange_result_dma_buf(fd); + + if (fd->variant->fld_enable) + aie_arrange_fld_buf(fd); + + ret = aie_load_fw(fd); + if (ret) { + dev_err(fd->dev, "Failed to load aie fw\n"); + goto free_all; + } + + fd->attr_para->r_idx = 0; + fd->attr_para->w_idx = 0; + + fd->fd_state |= STATE_INIT; + + dev_info(fd->dev, "%s: fd_mem_size(%d)\n", __func__, fd->fd_mem_size); + + return ret; + +free_all: + aie_free_dram_buf(fd); + aie_free_output_buf(fd); + aie_free_fddma_buf(fd); + if (fd->variant->fld_enable) + aie_free_fld_buf(fd); + +kmalloc_fail: + kfree(fd->base_para); + kfree(fd->attr_para); + kfree(fd->dma_para); + kfree(fd->fld_para); + + dev_err(fd->dev, "Failed to init aie\n"); + + return ret; +} + +void aie_uninit(struct mtk_aie_dev *fd) +{ + fd->fd_state &= ~STATE_INIT; + + aie_free_dram_buf(fd); + aie_free_output_buf(fd); + aie_free_fddma_buf(fd); + + if (fd->variant->fld_enable) + aie_free_fld_buf(fd); + + kfree(fd->base_para); + kfree(fd->attr_para); + kfree(fd->dma_para); + kfree(fd->fld_para); +} + +void aie_prepare(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + if (fd->variant->fld_enable) { + if (aie_cfg->sel_mode == FLDMODE) { /* FLD don't need to prepare buf */ + dev_dbg(fd->dev, "FLD, Mode: %d", aie_cfg->sel_mode); + return; + } + } + + memset(&fd->reg_cfg, 0, sizeof(struct aie_reg_cfg)); + + if (aie_cfg->pyramid_base_width == 0) { + fd->base_para->pyramid_width = fd->base_para->max_pyramid_width; + fd->base_para->pyramid_height = + fd->base_para->max_pyramid_height; + fd->base_para->number_of_pyramid = 3; + } else { + fd->base_para->pyramid_height = + fd->base_para->max_pyramid_height; + fd->base_para->number_of_pyramid = aie_cfg->number_of_pyramid; + if (aie_cfg->pyramid_base_width != + fd->base_para->pyramid_width) { + dev_dbg(fd->dev, + "pre: %d cur: %d num: %d\n", + fd->base_para->pyramid_width, + aie_cfg->pyramid_base_width, + fd->base_para->number_of_pyramid + ); + fd->base_para->pyramid_width = + aie_cfg->pyramid_base_width; + aie_update_table(fd, fd->base_para->pyramid_width, + fd->base_para->pyramid_height); + aie_update_fddma_buf(fd); + } + } + + aie_reset_output_buf(fd, aie_cfg); + + fd->reg_cfg.fd_mode = aie_cfg->sel_mode; + if (aie_cfg->sel_mode == FDMODE) { + fd->reg_cfg.rs_adr = (u32)fd->base_para->fd_rs_cfg_pa; + fd->reg_cfg.yuv2rgb_adr = (u32)fd->base_para->fd_yuv2rgb_cfg_pa; + fd->reg_cfg.fd_adr = (u32)fd->base_para->fd_fd_cfg_pa + + fd->variant->fd_cfg_size * 4 * + FD_LOOP_NUM / 3 * + (3 - aie_cfg->number_of_pyramid); + + } else if (aie_cfg->sel_mode == ATTRIBUTEMODE) { + fd->reg_cfg.yuv2rgb_adr = + (u32)fd->base_para->attr_yuv2rgb_cfg_pa[fd->attr_para->w_idx]; + fd->reg_cfg.fd_adr = + (u32)fd->base_para->attr_fd_cfg_pa[fd->attr_para->w_idx]; + } else { + dev_err(fd->dev, "AIE error, Mode: %d", aie_cfg->sel_mode); + } + + aie_update_cfg(fd, aie_cfg); + + aie_config_dram(fd, aie_cfg); + + if (aie_cfg->sel_mode == ATTRIBUTEMODE) + fd->attr_para->w_idx = + (fd->attr_para->w_idx + 1) % MAX_ENQUE_FRAME_NUM; +} + +void aie_execute(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + unsigned int loop_num = 0; + unsigned int loop_reg_val = 0; + unsigned int i = 0; + + if (aie_cfg->sel_mode == FDMODE) { + writel(0x0, fd->fd_base + AIE_START_REG); + writel(0x00000111, fd->fd_base + AIE_ENABLE_REG); + loop_num = FD_LOOP_NUM / 3 * (aie_cfg->number_of_pyramid); + loop_reg_val = (loop_num << 8) | + (aie_cfg->number_of_pyramid - 1); + writel(loop_reg_val, fd->fd_base + AIE_LOOP_REG); + writel(0x1, fd->fd_base + AIE_INT_EN_REG); + writel(fd->reg_cfg.rs_adr, + fd->fd_base + AIE_RS_CON_BASE_ADR_REG); + writel(fd->reg_cfg.fd_adr, + fd->fd_base + AIE_FD_CON_BASE_ADR_REG); + writel(fd->reg_cfg.yuv2rgb_adr, + fd->fd_base + AIE_YUV2RGB_CON_BASE_ADR_REG); + + if (fd->variant->hw_version == 31) { + writel(0x00000002, + fd->fd_base + AIE_YUV2RGB_CON_BASE_ADR_MSB); + writel(0x00000002, + fd->fd_base + AIE_RS_CON_BASE_ADR_MSB); + writel(0x00000002, + fd->fd_base + AIE_FD_CON_BASE_ADR_MSB); + } + + writel(0x1, fd->fd_base + AIE_START_REG); + } else if (aie_cfg->sel_mode == ATTRIBUTEMODE) { + writel(0x0, fd->fd_base + AIE_START_REG); + writel(0x00000101, fd->fd_base + AIE_ENABLE_REG); + writel(0x00001A00, fd->fd_base + AIE_LOOP_REG); + writel(0x1, fd->fd_base + AIE_INT_EN_REG); + writel(fd->reg_cfg.rs_adr, + fd->fd_base + AIE_RS_CON_BASE_ADR_REG); + writel(fd->reg_cfg.fd_adr, + fd->fd_base + AIE_FD_CON_BASE_ADR_REG); + writel(fd->reg_cfg.yuv2rgb_adr, + fd->fd_base + AIE_YUV2RGB_CON_BASE_ADR_REG); + + if (fd->variant->hw_version == 31) { + writel(0x00000002, + fd->fd_base + AIE_YUV2RGB_CON_BASE_ADR_MSB); + writel(0x00000002, + fd->fd_base + AIE_RS_CON_BASE_ADR_MSB); + writel(0x00000002, + fd->fd_base + AIE_FD_CON_BASE_ADR_MSB); + } + + writel(0x1, fd->fd_base + AIE_START_REG); + } else if (aie_cfg->sel_mode == FLDMODE) { + if (fd->variant->fld_enable) { + writel(0x10, fd->fd_base + AIE_START_REG); + writel(0x00011111, fd->fd_base + AIE_DMA_CTL_REG); + writel(0x01111111, fd->fd_base + FLD_EN); + writel(0x1, fd->fd_base + AIE_INT_EN_REG); + for (i = 0; i < aie_cfg->fld_face_num; i++) { + writel(aie_cfg->src_img_addr, + fd->fd_base + FLD_BASE_ADDR_FACE_0 + + i * 0x4); + writel(aie_cfg->fld_input[i].fld_in_crop_x1 + << 16 | + aie_cfg->fld_input[i] + .fld_in_crop_y1, + fd->fd_base + fld_face_info_0[i]); + writel(aie_cfg->fld_input[i].fld_in_crop_x2 + << 16 | + aie_cfg->fld_input[i] + .fld_in_crop_y2, + fd->fd_base + fld_face_info_1[i]); + writel(aie_cfg->fld_input[i].fld_in_rip << 4 | + aie_cfg->fld_input[i].fld_in_rop, + fd->fd_base + fld_face_info_2[i]); + } + + writel(aie_cfg->fld_face_num << 28 | FLD_FOREST << 16 | + FLD_POINT, + fd->fd_base + FLD_MODEL_PARA1); + writel(13 << 16 | 0xfe9, + fd->fd_base + FLD_MODEL_PARA14); + + writel(aie_cfg->src_img_width << 16 | + aie_cfg->src_img_height, + fd->fd_base + FLD_SRC_WD_HT); + + /*input settings*/ + writel(0x007c003f, fd->fd_base + FLD_PL_IN_SIZE_0); + writel(0x0040000f, fd->fd_base + FLD_PL_IN_STRIDE_0); + writel(0x007c003f, fd->fd_base + FLD_PL_IN_SIZE_1); + writel(0x0040000f, fd->fd_base + FLD_PL_IN_STRIDE_1); + writel(0x0016003f, fd->fd_base + FLD_PL_IN_SIZE_2_0); + writel(0x0040000f, fd->fd_base + FLD_PL_IN_STRIDE_2_0); + writel(0x0013003f, fd->fd_base + FLD_PL_IN_SIZE_2_1); + writel(0x0040000f, fd->fd_base + FLD_PL_IN_STRIDE_2_1); + writel(0x0013003f, fd->fd_base + FLD_PL_IN_SIZE_2_2); + writel(0x0040000f, fd->fd_base + FLD_PL_IN_STRIDE_2_2); + writel(0x00a6001f, fd->fd_base + FLD_PL_IN_SIZE_3); + writel(0x0020000f, fd->fd_base + FLD_PL_IN_STRIDE_3); + + /*output setting*/ + writel((2400 * aie_cfg->fld_face_num - 1) << 16 | 127, + fd->fd_base + FLD_SH_IN_SIZE_0); + writel(0x0010000f, fd->fd_base + FLD_SH_IN_STRIDE_0); + writel(fd->fld_para->fld_output_pa[0], + fd->fd_base + FLD_TR_OUT_BASE_ADDR_0); + writel((aie_cfg->fld_face_num - 1) << 16 | 0x6f, + fd->fd_base + FLD_TR_OUT_SIZE_0); + writel(0x0070000f, fd->fd_base + FLD_TR_OUT_STRIDE_0); + writel(fd->fld_para->fld_output_pa[0], + fd->fd_base + FLD_PP_OUT_BASE_ADDR_0); + writel((aie_cfg->fld_face_num - 1) << 16 | 0x6f, + fd->fd_base + FLD_PP_OUT_SIZE_0); + writel(0x0070000f, fd->fd_base + FLD_PP_OUT_STRIDE_0); + + /*cv score*/ + writel(0x00000001, fd->fd_base + FLD_BS_BIAS); + writel(0x0000b835, + fd->fd_base + FLD_CV_FM_RANGE_0); // 8E8 + writel(0xffff5cba, + fd->fd_base + FLD_CV_FM_RANGE_1); // 8EC + writel(0x00005ed5, + fd->fd_base + FLD_CV_PM_RANGE_0); // 8F0 + writel(0xffff910d, + fd->fd_base + FLD_CV_PM_RANGE_1); // 8F4 + writel(0x0000031e, fd->fd_base + FLD_BS_RANGE_0); // 8F8 + writel(0xfffffcae, fd->fd_base + FLD_BS_RANGE_1); // 8FC + + /* 6 steps */ + writel(fd->fld_para->fld_step_pa[FLD_STEP_BLINK][14], + fd->fd_base + FLD_BS_IN_BASE_ADDR_14); + + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][0], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_0); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][1], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_1); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][2], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_2); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][3], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_3); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][4], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_4); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][5], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_5); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][6], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_6); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][7], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_7); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][8], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_8); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][9], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_9); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][10], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_10); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][11], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_11); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][12], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_12); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][13], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_13); + writel(fd->fld_para->fld_step_pa[FLD_STEP_CV][14], + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_14); + + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][0], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_0); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][1], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_1); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][2], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_2); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][3], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_3); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][4], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_4); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][5], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_5); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][6], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_6); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][7], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_7); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][8], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_8); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][9], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_9); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][10], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_10); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][11], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_11); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][12], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_12); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][13], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_13); + writel(fd->fld_para->fld_step_pa[FLD_STEP_FP][14], + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_14); + + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][0], + fd->fd_base + FLD_SH_IN_BASE_ADDR_0); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][1], + fd->fd_base + FLD_SH_IN_BASE_ADDR_1); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][2], + fd->fd_base + FLD_SH_IN_BASE_ADDR_2); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][3], + fd->fd_base + FLD_SH_IN_BASE_ADDR_3); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][4], + fd->fd_base + FLD_SH_IN_BASE_ADDR_4); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][5], + fd->fd_base + FLD_SH_IN_BASE_ADDR_5); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][6], + fd->fd_base + FLD_SH_IN_BASE_ADDR_6); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][7], + fd->fd_base + FLD_SH_IN_BASE_ADDR_7); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][8], + fd->fd_base + FLD_SH_IN_BASE_ADDR_8); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][9], + fd->fd_base + FLD_SH_IN_BASE_ADDR_9); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][10], + fd->fd_base + FLD_SH_IN_BASE_ADDR_10); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][11], + fd->fd_base + FLD_SH_IN_BASE_ADDR_11); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][12], + fd->fd_base + FLD_SH_IN_BASE_ADDR_12); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][13], + fd->fd_base + FLD_SH_IN_BASE_ADDR_13); + writel(fd->fld_para->fld_step_pa[FLD_STEP_LEAF][14], + fd->fd_base + FLD_SH_IN_BASE_ADDR_14); + + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][0], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_0); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][1], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_1); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][2], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_2); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][3], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_3); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][4], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_4); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][5], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_5); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][6], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_6); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][7], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_7); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][8], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_8); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][9], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_9); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][10], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_10); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][11], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_11); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][12], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_12); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][13], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_13); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM02][14], + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_14); + + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][0], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_0); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][1], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_1); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][2], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_2); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][3], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_3); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][4], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_4); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][5], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_5); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][6], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_6); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][7], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_7); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][8], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_8); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][9], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_9); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][10], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_10); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][11], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_11); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][12], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_12); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][13], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_13); + writel(fd->fld_para->fld_step_pa[FLD_STEP_KM13][14], + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_14); + + /* */ + writel(0x22222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_0_7_MSB); + writel(0x02222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_0_8_15_MSB); + + writel(0x22222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_0_7_MSB); + writel(0x02222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_1_8_15_MSB); + + writel(0x22222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_0_7_MSB); + writel(0x02222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_2_8_15_MSB); + + writel(0x22222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_0_7_MSB); + writel(0x02222222, + fd->fd_base + FLD_PL_IN_BASE_ADDR_3_8_15_MSB); + + writel(0x22222222, + fd->fd_base + FLD_SH_IN_BASE_ADDR_0_7_MSB); + writel(0x02222222, + fd->fd_base + FLD_SH_IN_BASE_ADDR_8_15_MSB); + + writel(0x02000000, + fd->fd_base + FLD_BS_IN_BASE_ADDR_8_15_MSB); + + writel(0x22222222, + fd->fd_base + FLD_BASE_ADDR_FACE_0_7_MSB); + writel(0x02222222, + fd->fd_base + FLD_BASE_ADDR_FACE_8_14_MSB); + writel(0x00000002, + fd->fd_base + FLD_TR_OUT_BASE_ADDR_0_MSB); + writel(0x00000002, + fd->fd_base + FLD_PP_OUT_BASE_ADDR_0_MSB); + + /*fld mode + trigger start*/ + writel(0x11, fd->fd_base + AIE_START_REG); + } + } +} + +void aie_irqhandle(struct mtk_aie_dev *fd) +{ + writel(0x0, fd->fd_base + AIE_START_REG); + + /* interrupt read clear */ + readl(fd->fd_base + AIE_INT_REG); +} + +static u16 aie_get_hi16(unsigned int value) +{ + return (value & 0xFFFF0000) >> 16; +} + +static u16 aie_get_lo16(unsigned int value) +{ + return value & 0xFFFF; +} + +static signed short aie_refine_s16_value(signed short value) +{ + s16 result = 0; + + if ((value & 0x200) >> 9) + result = (value | 0xFE00); + else + result = value; + + return result; +} + +/* return aie_cfg to user space */ +void aie_get_fd_result(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + void *fd_pym_result[PYM_NUM] = { NULL, NULL, NULL }; + unsigned int *pto12 = NULL; + unsigned int i = 0, j = 0; + struct FDRESULT *prst = NULL; + signed short landmark = 0; + struct aie_enq_info *tmp_aie_cfg = NULL; + u32 fd_result_hw = 0, fd_result_1_hw = 0; + u32 fd_total_num = 0; + u32 fd_pyramid_num[PYM_NUM] = { 0, 0, 0 }; + + aie_cfg->sel_mode = fd->base_para->sel_mode; + aie_cfg->rotate_degree = fd->base_para->rotate_degree; + aie_cfg->src_img_addr = fd->base_para->src_img_addr; + aie_cfg->src_img_addr_uv = fd->base_para->src_img_addr_uv; + aie_cfg->src_img_width = fd->base_para->img_width; + aie_cfg->src_img_height = fd->base_para->img_height; + aie_cfg->src_img_fmt = fd->base_para->src_img_fmt; + aie_cfg->fd_version = FD_VERSION; + aie_cfg->attr_version = ATTR_VERSION; + + aie_cfg->irq_status = readl(fd->fd_base + AIE_INT_EN_REG); + + fd_result_hw = fd->reg_cfg.hw_result; + fd_result_1_hw = fd->reg_cfg.hw_result1; + fd_total_num = fd_result_hw & 0xFFF; + fd_pyramid_num[0] = (fd_result_hw & 0xFFF0000) >> 16; + fd_pyramid_num[1] = fd_result_1_hw & 0xFFF; + fd_pyramid_num[2] = (fd_result_1_hw & 0xFFF0000) >> 16; + + if (fd_total_num == 0) + goto nothing_out; + + tmp_aie_cfg = aie_cfg; + + tmp_aie_cfg->fd_out.fd_total_num = fd_total_num; + tmp_aie_cfg->fd_out.fd_pyramid0_num = fd_pyramid_num[0]; + tmp_aie_cfg->fd_out.fd_pyramid1_num = fd_pyramid_num[1]; + tmp_aie_cfg->fd_out.fd_pyramid2_num = fd_pyramid_num[2]; + + switch (tmp_aie_cfg->number_of_pyramid) { + case 1: + fd_pym_result[2] = fd->dma_para->fd_out_hw_va[RPN0_LOOP_NUM][0]; + break; + case 2: + fd_pym_result[1] = fd->dma_para->fd_out_hw_va[RPN0_LOOP_NUM][0]; + fd_pym_result[2] = fd->dma_para->fd_out_hw_va[RPN1_LOOP_NUM][0]; + break; + case 3: + fd_pym_result[0] = fd->dma_para->fd_out_hw_va[RPN0_LOOP_NUM][0]; + fd_pym_result[1] = fd->dma_para->fd_out_hw_va[RPN1_LOOP_NUM][0]; + fd_pym_result[2] = fd->dma_para->fd_out_hw_va[RPN2_LOOP_NUM][0]; + break; + default: + dev_err(fd->dev, "Wrong number_of_pyramid\n"); + goto nothing_out; + } + + for (i = 0; i < 3; i++) { + for (j = 0; j < fd_pyramid_num[i]; j++) { + if (i == 0) + prst = &tmp_aie_cfg->fd_out.PYRAMID0_RESULT; + else if (i == 1) + prst = &tmp_aie_cfg->fd_out.PYRAMID1_RESULT; + else if (i == 2) + prst = &tmp_aie_cfg->fd_out.PYRAMID2_RESULT; + + pto12 = (unsigned int *)fd_pym_result[i] + 12 * j; + + prst->anchor_x0[j] = aie_get_lo16(*(pto12 + 0)); + prst->anchor_y0[j] = aie_get_hi16(*(pto12 + 0)); + prst->anchor_x1[j] = aie_get_lo16(*(pto12 + 1)); + prst->anchor_y1[j] = aie_get_hi16(*(pto12 + 1)); + + if (prst->anchor_x1[j] == 0 || + prst->anchor_y1[j] == 0) { + dev_err(fd->dev, + "wrong coordinate: i=%d j=%d M:%d %d %d %d\n", + i, + j, + prst->anchor_x0[j], + prst->anchor_x1[j], + prst->anchor_y0[j], + prst->anchor_y1[j] + ); + goto nothing_out; + } + + /* ROP result at 1st run */ + landmark = (*(pto12 + 2) & 0x3FF); + prst->rop_landmark_score0[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 2) & 0xFFC00) >> 10); + prst->rop_landmark_score1[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 2) & 0x3FF00000) >> 20); + prst->rop_landmark_score2[j] = + aie_refine_s16_value(landmark); + + prst->anchor_score[j] = + aie_refine_s16_value(*(pto12 + 9) & 0x3FF); + + /* RIP result at 1st run */ + landmark = ((*(pto12 + 9) & 0xFFC00) >> 10); + prst->rip_landmark_score0[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 9) & 0x3FF00000) >> 20); + prst->rip_landmark_score1[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 9) & 0xC0000000) >> 30) | + ((*(pto12 + 10) & 0xFF) << 2); + prst->rip_landmark_score2[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 10) & 0x3FF00) >> 8); + prst->rip_landmark_score3[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 10) & 0xFFC0000) >> 18); + prst->rip_landmark_score4[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 10) & 0xF0000000) >> 28) | + ((*(pto12 + 11) & 0x3F) << 4); + prst->rip_landmark_score5[j] = + aie_refine_s16_value(landmark); + landmark = ((*(pto12 + 11) & 0xFFC0) >> 6); + prst->rip_landmark_score6[j] = + aie_refine_s16_value(landmark); + prst->face_result_index[j] = + ((*(pto12 + 11) & 0xFFF0000) >> 16); + prst->anchor_index[j] = + ((*(pto12 + 11) & 0x70000000) >> 28); + + prst->fd_partial_result = fd_pyramid_num[i]; + } + } + return; +nothing_out: + // Ensure that user mode does not receive an inappropriate result structure + memset(&aie_cfg->fd_out, 0, sizeof(struct fd_result)); +} + +void aie_get_attr_result(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + u32 *attr_race_result = NULL, *attr_gender_result = NULL; + u32 *attr_age_result = NULL, *attr_is_indian_result = NULL; + + aie_cfg->sel_mode = fd->attr_para->sel_mode[fd->attr_para->r_idx]; + aie_cfg->rotate_degree = + fd->attr_para->rotate_degree[fd->attr_para->r_idx]; + aie_cfg->src_img_addr = + fd->attr_para->src_img_addr[fd->attr_para->r_idx]; + aie_cfg->src_img_addr_uv = + fd->attr_para->src_img_addr_uv[fd->attr_para->r_idx]; + aie_cfg->src_img_width = fd->attr_para->img_width[fd->attr_para->r_idx]; + aie_cfg->src_img_height = + fd->attr_para->img_height[fd->attr_para->r_idx]; + aie_cfg->src_img_fmt = fd->attr_para->src_img_fmt[fd->attr_para->r_idx]; + aie_cfg->fd_version = FD_VERSION; + aie_cfg->attr_version = ATTR_VERSION; + + aie_cfg->irq_status = readl(fd->fd_base + AIE_INT_EN_REG); + + /* 64 feature * 32 bytes */ + attr_age_result = + (u32 *)fd->dma_para->age_out_hw_va[fd->attr_para->r_idx]; + attr_gender_result = + (u32 *)fd->dma_para->gender_out_hw_va[fd->attr_para->r_idx]; + attr_is_indian_result = + (u32 *)fd->dma_para->is_indian_out_hw_va[fd->attr_para->r_idx]; + attr_race_result = + (u32 *)fd->dma_para->race_out_hw_va[fd->attr_para->r_idx]; + + aie_cfg->attr_out.MERGED_AGE_RESULT.RESULT[0] = + aie_get_lo16(*attr_age_result); + aie_cfg->attr_out.MERGED_AGE_RESULT.RESULT[1] = + aie_get_hi16(*attr_age_result); + + aie_cfg->attr_out.MERGED_GENDER_RESULT.RESULT[0] = + aie_get_lo16(*attr_gender_result); + aie_cfg->attr_out.MERGED_GENDER_RESULT.RESULT[1] = + aie_get_hi16(*attr_gender_result); + + aie_cfg->attr_out.MERGED_IS_INDIAN_RESULT.RESULT[0] = + aie_get_lo16(*attr_is_indian_result); + aie_cfg->attr_out.MERGED_IS_INDIAN_RESULT.RESULT[1] = + aie_get_hi16(*attr_is_indian_result); + + aie_cfg->attr_out.MERGED_RACE_RESULT.RESULT[0] = + aie_get_lo16(*attr_race_result); + aie_cfg->attr_out.MERGED_RACE_RESULT.RESULT[1] = + aie_get_hi16(*attr_race_result); + aie_cfg->attr_out.MERGED_RACE_RESULT.RESULT[2] = + aie_get_lo16(*(attr_race_result + 1)); + + fd->attr_para->r_idx = (fd->attr_para->r_idx + 1) % MAX_ENQUE_FRAME_NUM; +} + +void aie_get_fld_result(struct mtk_aie_dev *fd, struct aie_enq_info *aie_cfg) +{ + int i = 0, j = 0; + u16 *out_parsing = NULL; + u8 fld_rlt[FLD_MAX_FRAME][FLD_OUTPUT_SIZE]; + + aie_cfg->irq_status = readl(fd->fd_base + AIE_INT_EN_REG); + + memcpy(fld_rlt, fd->fld_para->fld_output_va[0], sizeof(fld_rlt)); + + for (j = 0; j < aie_cfg->fld_face_num; j++) { + out_parsing = (unsigned short *)&fld_rlt[j][0]; + for (i = 0; i < FLD_CUR_LANDMARK; i++) { + aie_cfg->fld_out[j].fld_landmark[i].x = *out_parsing; + aie_cfg->fld_out[j].fld_landmark[i].y = + *(out_parsing + 1); + + if (i % 2) + out_parsing = out_parsing + 6; + else + out_parsing = out_parsing + 2; + } + out_parsing = (unsigned short *)&fld_rlt[j][0]; + if (FLD_CUR_LANDMARK % 2) + out_parsing = + out_parsing + ((FLD_CUR_LANDMARK + 1) / 2) * 8; + else + out_parsing = out_parsing + (FLD_CUR_LANDMARK / 2) * 8; + + aie_cfg->fld_out[j].fld_out_rop = *out_parsing; + aie_cfg->fld_out[j].fld_out_rip = *(out_parsing + 1); + aie_cfg->fld_out[j].confidence = *(out_parsing + 2); + aie_cfg->fld_out[j].blinkscore = *(out_parsing + 3); + } +} -- 2.34.1