// SPDX-License-Identifier: GPL-2.0 /* * Samsung Exynos SoC series Pablo driver * * Copyright (c) 2021 Samsung Electronics Co., Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef IS_SUBDEV_H #define IS_SUBDEV_H #include "is-video.h" #include "is-work.h" #define SUBDEV_INTERNAL_BUF_MAX (8) struct is_device_sensor; struct is_device_ischain; struct is_groupmgr; struct is_group; enum is_subdev_device_type { IS_SENSOR_SUBDEV, IS_ISCHAIN_SUBDEV, }; enum is_subdev_state { IS_SUBDEV_OPEN, IS_SUBDEV_START, IS_SUBDEV_RUN, IS_SUBDEV_FORCE_SET, IS_SUBDEV_EXTERNAL_USE, IS_SUBDEV_INTERNAL_USE, IS_SUBDEV_INTERNAL_S_FMT, IS_SUBDEV_VOTF_USE, IS_SUBDEV_IOVA_EXTENSION_USE, }; enum pablo_subdev_get_type { PSGT_REGION_NUM, PSGT_RTA_FRAME_INFO, }; enum is_lme_subdev { IS_LME_SUBDEV_MBMV = 0, }; struct is_subdev_path { u32 width; u32 height; struct is_crop canv; struct is_crop crop; }; /* Caution: Do not exceed 64 */ enum is_subdev_id { ENTRY_SENSOR, ENTRY_SSVC0, ENTRY_SSVC1, ENTRY_SSVC2, ENTRY_SSVC3, ENTRY_3AA, ENTRY_3AC, ENTRY_3AP, ENTRY_3AF, ENTRY_3AG, ENTRY_3AO, ENTRY_3AL, ENTRY_ISP, ENTRY_IXC, ENTRY_IXP, ENTRY_IXT, ENTRY_IXG, ENTRY_IXV, ENTRY_IXW, ENTRY_MEXC, /* MEIP or MCH*/ ENTRY_MCS, ENTRY_M0P, ENTRY_M1P, ENTRY_M2P, ENTRY_M3P, ENTRY_M4P, ENTRY_M5P, ENTRY_VRA, ENTRY_PAF, /* PDP(PATSTAT) Bayer RDMA */ ENTRY_PDAF, /* PDP(PATSTAT) AF RDMA */ ENTRY_PDST, /* PDP(PATSTAT) PD STAT WDMA */ ENTRY_ORB, /* ORBMCH */ ENTRY_ORBXC,/* ORB */ ENTRY_YPP, /* YUVPP */ ENTRY_LME, ENTRY_LMES, ENTRY_LMEC, ENTRY_CSTAT_CDAF, ENTRY_CSTAT_PRE_THUMB, ENTRY_CSTAT_AE_THUMB, ENTRY_CSTAT_AWB_THUMB, ENTRY_CSTAT_RGBY_HIST, ENTRY_CSTAT_CDS, ENTRY_BYRP, ENTRY_BYRP_HDR, ENTRY_BYRP_BYR, ENTRY_RGBP, ENTRY_RGBP_HF, ENTRY_RGBP_SF, ENTRY_RGBP_YUV, ENTRY_RGBP_RGB, ENTRY_MCFP, ENTRY_MCFP_VIDEO, ENTRY_MCFP_STILL, ENTRY_YUVP_SEG, ENTRY_YUVP_DRC, ENTRY_YUVP_SVHIST, ENTRY_YUVP_YUV, ENTRY_LME_PROCESSED, ENTRY_LME_MBMV, ENTRY_INTERNAL, ENTRY_END, }; #define ENTRY_SS_VC0 ENTRY_SSVC0 #define ENTRY_SS_VC1 ENTRY_SSVC1 #define ENTRY_SS_VC2 ENTRY_SSVC2 #define ENTRY_SS_VC3 ENTRY_SSVC3 #define ENTRY_SS_VC4 ENTRY_3AA #define ENTRY_SS_VC5 ENTRY_3AC #define ENTRY_SS_VC6 ENTRY_3AP #define ENTRY_SS_VC7 ENTRY_3AF #define ENTRY_SS_VC8 ENTRY_3AG #define ENTRY_SS_VC9 ENTRY_3AO #define ENTRY_SS_MCB0 ENTRY_3AL #define ENTRY_SS_MCB1 ENTRY_ISP #define ENTRY_SS_MCB2 ENTRY_IXC #define ENTRY_SS_MCB3 ENTRY_IXP #define ENTRY_SS_BNS ENTRY_IXT #define ENTRY_CSTAT ENTRY_IXG #define ENTRY_CSTAT_LME_DS0 ENTRY_IXV #define ENTRY_CSTAT_LME_DS1 ENTRY_IXW #define ETNRY_CSTAT_FDPIG ENTRY_MEXC #define ENTRY_CSTAT_RGBHIST ENTRY_CLH #define ENTRY_CSTAT_SVHIST ENTRY_CLHC #define ENTRY_CSTAT_DRC ENTRY_ORBXC #define ENTRY_YUVP ENTRY_YPP #define ENTRY_MCSC ENTRY_MCS #define ENTRY_MCSC_P0 ENTRY_M0P #define ENTRY_MCSC_P1 ENTRY_M1P #define ENTRY_MCSC_P2 ENTRY_M2P #define ENTRY_MCSC_P3 ENTRY_M3P #define ENTRY_MCSC_P4 ENTRY_M4P #define ENTRY_MCSC_P5 ENTRY_M5P #define ENTRY_LME_PREV ENTRY_LMES #define ENTRY_LME_PURE ENTRY_LMEC static ulong is_subdev_wq_id[ENTRY_END] = { [ENTRY_SENSOR ... ENTRY_END-1] = WORK_MAX_MAP, [ENTRY_SENSOR] = WORK_SHOT_DONE, [ENTRY_SSVC0] = WORK_MAX_MAP, [ENTRY_SSVC1] = WORK_MAX_MAP, [ENTRY_SSVC2] = WORK_MAX_MAP, [ENTRY_SSVC3] = WORK_MAX_MAP, [ENTRY_3AA] = WORK_SHOT_DONE, [ENTRY_3AC] = WORK_30C_FDONE, [ENTRY_3AP] = WORK_30P_FDONE, [ENTRY_3AF] = WORK_30F_FDONE, [ENTRY_3AG] = WORK_30G_FDONE, [ENTRY_3AO] = WORK_30O_FDONE, [ENTRY_3AL] = WORK_30L_FDONE, [ENTRY_ISP] = WORK_SHOT_DONE, [ENTRY_IXC] = WORK_I0C_FDONE, [ENTRY_IXP] = WORK_I0P_FDONE, [ENTRY_IXT] = WORK_I0T_FDONE, [ENTRY_IXG] = WORK_I0G_FDONE, [ENTRY_IXV] = WORK_I0V_FDONE, [ENTRY_IXW] = WORK_I0W_FDONE, [ENTRY_MEXC] = WORK_ME0C_FDONE, [ENTRY_MCS] = WORK_SHOT_DONE, [ENTRY_M0P] = WORK_M0P_FDONE, [ENTRY_M1P] = WORK_M1P_FDONE, [ENTRY_M2P] = WORK_M2P_FDONE, [ENTRY_M3P] = WORK_M3P_FDONE, [ENTRY_M4P] = WORK_M4P_FDONE, [ENTRY_M5P] = WORK_M5P_FDONE, [ENTRY_VRA] = WORK_SHOT_DONE, [ENTRY_PAF] = WORK_SHOT_DONE, [ENTRY_PDAF] = WORK_MAX_MAP, [ENTRY_PDST] = WORK_MAX_MAP, [ENTRY_ORB] = WORK_SHOT_DONE, [ENTRY_ORBXC] = WORK_ORB0C_FDONE, [ENTRY_YPP] = WORK_SHOT_DONE, [ENTRY_LME] = WORK_SHOT_DONE, [ENTRY_LMES] = WORK_LME0S_FDONE, [ENTRY_LMEC] = WORK_LME0C_FDONE, [ENTRY_BYRP] = WORK_SHOT_DONE, [ENTRY_RGBP] = WORK_SHOT_DONE, [ENTRY_MCFP] = WORK_SHOT_DONE, }; struct is_subdev_ops { int (*bypass)(struct is_subdev *subdev, void *device_data, struct is_frame *frame, bool bypass); int (*cfg)(struct is_subdev *subdev, void *device_data, struct is_frame *frame, struct is_crop *incrop, struct is_crop *otcrop, IS_DECLARE_PMAP(pmap)); int (*tag)(struct is_subdev *subdev, void *device_data, struct is_frame *frame, struct camera2_node *node); int (*get)(struct is_subdev *subdev, struct is_device_ischain *idi, struct is_frame *frame, enum pablo_subdev_get_type type, void *result); }; enum subdev_ch_mode { SCM_WO_PAF_HW, SCM_W_PAF_HW, SCM_MAX, }; struct is_subdev { u32 id; u32 vid; /* video id */ u32 cid; /* capture node id */ enum chain_work_map wq_id; /* workqueue id */ char name[4]; u32 instance; unsigned long state; u32 constraints_width; /* spec in width */ u32 constraints_height; /* spec in height */ u32 param_otf_in; u32 param_dma_in; u32 param_otf_ot; u32 param_dma_ot; struct is_subdev_path input; struct is_subdev_path output; struct list_head list; /* for internal use */ struct is_framemgr internal_framemgr; u32 batch_num; u32 buffer_num; u32 bits_per_pixel; u32 memory_bitwidth; u32 sbwc_type; u32 lossy_byte32num; struct is_priv_buf *pb_subdev[SUBDEV_INTERNAL_BUF_MAX]; struct is_priv_buf *pb_capture_subdev[SUBDEV_INTERNAL_BUF_MAX][CAPTURE_NODE_MAX]; bool use_shared_framemgr; char data_type[15]; struct is_video_ctx *vctx; struct is_subdev *leader; const struct is_subdev_ops *ops; }; int is_sensor_subdev_open(struct is_device_sensor *device, struct is_video_ctx *vctx); int is_sensor_subdev_close(struct is_device_sensor *device, struct is_video_ctx *vctx); int is_ischain_subdev_open(struct is_device_ischain *device, struct is_video_ctx *vctx); int is_ischain_subdev_close(struct is_device_ischain *device, struct is_video_ctx *vctx); /*common subdev*/ int is_subdev_probe(struct is_subdev *subdev, u32 instance, u32 id, const char *name, const struct is_subdev_ops *sops); int is_subdev_open(struct is_subdev *subdev, struct is_video_ctx *vctx, void *ctl_data, u32 instance); int is_subdev_close(struct is_subdev *subdev); int pablo_subdev_buffer_init(struct is_subdev *is, struct vb2_buffer *vb); int is_subdev_buffer_queue(struct is_subdev *subdev, struct vb2_buffer *vb); int is_subdev_buffer_finish(struct is_subdev *subdev, struct vb2_buffer *vb); int is_vra_trigger(struct is_device_ischain *device, struct is_subdev *subdev, struct is_frame *frame); int is_sensor_subdev_reqbuf(void *qdevice, struct is_queue *queue, u32 count); bool is_subdev_check_vid(uint32_t vid); struct is_subdev * video2subdev(enum is_subdev_device_type device_type, void *device, u32 vid); struct is_queue_ops *is_get_sensor_subdev_qops(void); struct is_queue_ops *is_get_ischain_subdev_qops(void); bool is_subdev_internal_use_shared_framemgr(const struct is_subdev *subdev); void is_subdev_internal_get_sbwc_type(const struct is_subdev *subdev, u32 *sbwc_type, u32 *lossy_byte32num); int is_subdev_internal_get_buffer_size(const struct is_subdev *subdev, u32 *width, u32 *height, u32 *sbwc_block_width, u32 *sbwc_block_height); void is_subdev_internal_lock_shared_framemgr(struct is_subdev *subdev); void is_subdev_internal_unlock_shared_framemgr(struct is_subdev *subdev); int is_subdev_internal_get_shared_framemgr(struct is_subdev *subdev, struct is_framemgr **framemgr, u32 width, u32 height); int is_subdev_internal_put_shared_framemgr(struct is_subdev *subdev); int is_subdev_internal_get_cap_node_num(const struct is_subdev *subdev); int is_subdev_internal_get_out_node_info(const struct is_subdev *subdev, u32 *num_planes, u32 scenario, char *heapname); int is_subdev_internal_get_cap_node_info(const struct is_subdev *subdev, u32 *vid, u32 *num_planes, u32 *buffer_size, u32 index, u32 scenario, char *heapname); /* internal subdev use */ int is_subdev_internal_open(void *device, enum is_device_type type, int vid, struct is_subdev *subdev); int is_subdev_internal_close(void *device, enum is_device_type type, struct is_subdev *subdev); int is_subdev_internal_s_format(void *device, enum is_device_type type, struct is_subdev *subdev, u32 width, u32 height, u32 bits_per_pixel, u32 sbwc_type, u32 lossy_byte32num, u32 buffer_num, const char *type_name); struct is_sensor_cfg; int is_subdev_internal_g_bpp(void *device, enum is_device_type type, struct is_subdev *subdev, struct is_sensor_cfg *sensor_cfg); int is_subdev_internal_start(void *device, enum is_device_type type, struct is_subdev *subdev); int is_subdev_internal_stop(void *device, enum is_device_type type, struct is_subdev *subdev); int __mcsc_dma_out_cfg(struct is_device_ischain *device, struct is_frame *ldr_frame, struct camera2_node *node, u32 pindex, IS_DECLARE_PMAP(pmap), int index); #define GET_SUBDEV_FRAMEMGR(subdev) \ ({ struct is_framemgr *framemgr; \ if ((subdev) && (subdev)->vctx) \ framemgr = &(subdev)->vctx->queue.framemgr; \ else if ((subdev) && test_bit(IS_SUBDEV_INTERNAL_USE, &((subdev)->state))) \ framemgr = &(subdev)->internal_framemgr; \ else \ framemgr = NULL; \ framemgr;}) #define GET_SUBDEV_I_FRAMEMGR(subdev) \ ({ struct is_framemgr *framemgr; \ if (subdev) \ framemgr = &(subdev)->internal_framemgr; \ else \ framemgr = NULL; \ framemgr; }) #define GET_SUBDEV_QUEUE(subdev) \ (((subdev) && (subdev)->vctx) ? (&(subdev)->vctx->queue) : NULL) #define CALL_SOPS(s, op, args...) (((s) && (s)->ops && (s)->ops->op) ? ((s)->ops->op(s, args)) : 0) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif