/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ /* * Copyright (C) 2025 Amlogic, Inc. All rights reserved */ #ifndef __C4_ISP_COMMON_H__ #define __C4_ISP_COMMON_H__ #include #include #include #include #include #include #include #include #define FPGA_TOP_ISP_CFG 0x2c #define FPGA_DBG_FRC_OUT_CNT 0x44 #define FPGA_DE_EN_CNT 0xc8 #define ISP_IPP_VSYNC0 BIT(0) #define ISP_IPP_VSYNC1 BIT(1) #define ISP_IPP_VSYNC2 BIT(2) #define ISP_IPP_VSYNC3 BIT(3) #define ISP_FE_DONE BIT(4) #define ISP_BE_DONE BIT(5) #define MIPI_TOP_IRQ BIT(11) #define ISP_INTF_IRQ BIT(12) #define ISP_CORE_IRQ BIT(13) #define ISP_BE_RST BIT(14) #define ISP_FE_RST BIT(15) #define ISP_BADDR_SCOUT0 0x1b000000 #define ISP_FRM_STEP_Y8 0x01000000 #define C4_ISP_DRIVER_NAME "c4-isp" #define C4_ISP_CLOCK_NUM_MAX 3 #define C4_ISP_DEFAULT_WIDTH 1920 #define C4_ISP_DEFAULT_HEIGHT 1080 #define C4_ISP_MAX_WIDTH 4656 #define C4_ISP_MAX_HEIGHT (1536*4) #define C4_ISP_MIN_WIDTH 160 #define C4_ISP_MIN_HEIGHT 120 #define C4_ISP_CORE_LINE_TILE_SIZE 4000 #define C4_ISP_CORE_LINE_BUFF_MAX 4224 #define C4_ISP_TILE_NUM_MAX 8 #define C4_ISP_TILE_HSIZE_MAX 1088 #define C4_OPP_TILE_OUT_SIZE_MAX 2 #define C4_OPP_TILE_NUM_MAX 96 #define C4_ISP_HDR_HWLK_LDF_VSIZE 1024 #define C4_ISP_WMIF_STRIDE_ALIGN_BYTES 64 #define C4_ISP_WMIF_STRIDE_ALIGN_DIV 16 #define V4L2_CID_C4_ISP_BASE (V4L2_CID_USER_BASE + 0xd000) #define V4L2_CID_C4_ISP_WORK_MODE (V4L2_CID_C4_ISP_BASE + 1) #define V4L2_CID_C4_ISP_IMAGE_MODE (V4L2_CID_C4_ISP_BASE + 2) #define V4L2_CID_C4_ISP_OUTPUT_MODE (V4L2_CID_C4_ISP_BASE + 3) #define V4L2_CID_C4_ISP_OUTPUT_FPS (V4L2_CID_C4_ISP_BASE + 4) #define V4L2_CID_C4_IPP_BASE (V4L2_CID_USER_BASE + 0xd100) #define V4L2_CID_C4_IPP_WORK_MODE (V4L2_CID_C4_IPP_BASE + 1) #define V4L2_CID_C4_IPP_IMAGE_MODE (V4L2_CID_C4_IPP_BASE + 2) #define V4L2_CID_C4_IPP_PATTERN_GEN (V4L2_CID_C4_IPP_BASE + 3) #define V4L2_CID_C4_VIDEO_BASE (V4L2_CID_USER_BASE + 0xd200) #define V4L2_CID_C4_VIDEO_OUTPUT_FPS (V4L2_CID_C4_VIDEO_BASE + 1) #define C4_V4L2_VIDEO_BEGIN_NUM 60 /* Private v4l2 event */ #define AML_ISP_V4L2_EVENT_STREAM_START (V4L2_EVENT_PRIVATE_START + 1) #define AML_ISP_V4L2_EVENT_STREAM_STOP (V4L2_EVENT_PRIVATE_START + 2) enum c4_isp_virt_id { C4_ISP_VIRT_0, C4_ISP_VIRT_1, C4_ISP_VIRT_2, C4_ISP_VIRT_3, C4_ISP_VIRT_MAX }; enum c4_ipp_work_mode { C4_IPP_SINGLE_VC_MODE, C4_IPP_MULTI_VC_SYNC_MODE, C4_IPP_MULTI_VC_SEP_MODE, C4_IPP_WORK_MODE_MAX }; enum c4_ipp_image_mode { C4_IPP_IMAGE_SDR, C4_IPP_IMAGE_HDR, C4_IPP_IMAGE_MAX }; enum c4_ipp_pads { C4_IPP_PAD_SINK_VIDEO, C4_IPP_PAD_SOURCE_VIDEO_ISP, /* For VC0 ~ VC3 */ C4_IPP_PAD_SOURCE_VIDEO_0, C4_IPP_PAD_SOURCE_VIDEO_1, C4_IPP_PAD_SOURCE_VIDEO_2, C4_IPP_PAD_SOURCE_VIDEO_3, C4_IPP_PAD_MAX }; enum c4_ipp_cap_devs { C4_IPP_CAP_DEV_0, C4_IPP_CAP_DEV_1, C4_IPP_CAP_DEV_2, C4_IPP_CAP_DEV_3, C4_IPP_NUM_CAP_DEVS }; enum c4_isp_work_mode { C4_ISP_RAW2DDR_MODE, C4_ISP_ALLSCAN_MODE, C4_ISP_SCANTILE_MODE, C4_ISP_ALLTILE_MODE, C4_ISP_OFFTILE_MODE, C4_ISP_OFFPOST_MODE, C4_ISP_OFFHUGE_MODE, C4_ISP_WORK_MODE_MAX }; enum c4_isp_image_mode { C4_ISP_IMAGE_SDR, C4_ISP_IMAGE_HDR, C4_ISP_IMAGE_MAX }; enum c4_isp_output_mode { C4_ISP_OUTPUT_ALL_OFF, C4_ISP_OUTPUT_OPP, C4_ISP_OUTPUT_MIF, C4_ISP_OUTPUT_ALL_ON, C4_ISP_OUTPUT_MAX }; enum c4_isp_core_pads { C4_ISP_CORE_PAD_SINK_VIDEO, C4_ISP_CORE_PAD_SINK_PARAMS, C4_ISP_CORE_PAD_SOURCE_STATS, C4_ISP_CORE_PAD_SOURCE_RAW, C4_ISP_CORE_PAD_SOURCE_VIDEO_0, C4_ISP_CORE_PAD_SOURCE_VIDEO_1, C4_ISP_CORE_PAD_SOURCE_VIDEO_2, C4_ISP_CORE_PAD_SOURCE_VIDEO_3, C4_ISP_CORE_PAD_MAX }; enum c4_isp_resizer_ids { C4_ISP_RSZ_0, C4_ISP_RSZ_1, C4_ISP_RSZ_2, C4_ISP_RSZ_3, C4_ISP_RSZ_MAX }; enum c4_isp_resizer_pads { C4_ISP_RSZ_PAD_SINK, C4_ISP_RSZ_PAD_SOURCE, C4_ISP_RSZ_PAD_MAX }; enum c4_isp_cap_devs { C4_ISP_CAP_DEV_0, C4_ISP_CAP_DEV_1, C4_ISP_CAP_DEV_2, C4_ISP_CAP_DEV_3, C4_ISP_NUM_CAP_DEVS }; enum c4_isp_planes { C4_ISP_PLANE_Y, C4_ISP_PLANE_UV, C4_ISP_NUM_PLANES }; enum c4_isp_hv_mode { C4_ISP_HV_MODE_VERTICAL, C4_ISP_HV_MODE_HORIZONTAL, C4_ISP_HV_MODE_MAX }; struct c4_isp_tile_cfg { u8 mode; //0:scanline 1:tile avg 2:dyn sw coord(active) 3:dyn sw act_size u8 blank; u16 hsize; u16 vsize; u16 hnum; u16 vnum; u16 hsize_max; u16 vsize_max; u16 avg_hsize; u16 avg_vsize; u32 crop_en; u32 ovlap[4]; // {3:T 2:B 1:L 0:R} u32 ihbgn[C4_ISP_TILE_NUM_MAX]; // AVG:act_hsize SW0:ihbgn SW1: act_hsize x8 u32 ihend[C4_ISP_TILE_NUM_MAX]; u32 ivbgn[C4_ISP_TILE_NUM_MAX]; // AVG:act_vsize SW0:ivbgn SW1: act_vsize x8 u32 ivend[C4_ISP_TILE_NUM_MAX]; u32 ohbgn[C4_ISP_TILE_NUM_MAX]; u32 ohend[C4_ISP_TILE_NUM_MAX]; u32 ovbgn[C4_ISP_TILE_NUM_MAX]; u32 ovend[C4_ISP_TILE_NUM_MAX]; }; struct c4_isp_tile_info { u16 max_hsize; u16 max_vsize; u8 hnum; u8 vnum; u16 hidx; u16 vidx; u16 bndry[4]; u16 h_st; u16 v_st; u16 h_ed; u16 v_ed; u16 lap_align[4]; }; struct c4_isp_hwlink_info { bool hwlk0_en; // FE -> BE bool hwlk1_en; // DISP0 -> VENC bool hwlk2_en; // IPP -> FE u16 tile0_vsize; u16 tile_vsizex2; u16 tile_buf_vsize; u16 fe_buf_size; u16 frm_vsize_t; u16 tile_rtnr_buf_size; u16 tile_yuvtnr_buf_size; u16 mipi_buf_size; }; struct c4_isp_pps_params { u16 frm_size; u16 src_size[C4_ISP_RSZ_MAX]; u16 dst_size[C4_ISP_RSZ_MAX]; bool crop_en[C4_ISP_RSZ_MAX]; u16 crop_bgn[C4_ISP_RSZ_MAX]; u16 crop_end[C4_ISP_RSZ_MAX]; u32 postsc_en[C4_ISP_RSZ_MAX]; u8 postsc_tap_num[C4_ISP_RSZ_MAX]; u8 postsc_chrm_tap_num[C4_ISP_RSZ_MAX]; u64 postsc_integer_part[C4_ISP_RSZ_MAX]; u64 postsc_fraction_part[C4_ISP_RSZ_MAX]; u64 postsc_phase_step[C4_ISP_RSZ_MAX]; bool shrk_en[C4_ISP_RSZ_MAX]; u32 shrk_ratio[C4_ISP_RSZ_MAX]; u8 tile_num[C4_ISP_RSZ_MAX]; u8 tile_inum; u8 tile_onum[C4_ISP_RSZ_MAX]; u8 tile_align_num[C4_ISP_RSZ_MAX]; u16 tile_size; u32 tile_alive_num[C4_ISP_RSZ_MAX][3]; u8 tile_alive[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u16 tile_in_bgn[C4_OPP_TILE_NUM_MAX]; u16 tile_in_end[C4_OPP_TILE_NUM_MAX]; u16 isp_in_hbgn[C4_OPP_TILE_NUM_MAX]; u16 isp_in_hend[C4_OPP_TILE_NUM_MAX]; u16 tile_out_bgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u16 tile_out_end[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u16 src_tot_bgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u16 src_tot_end[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u16 dst_bgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u16 dst_end[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 shrk_out_hbgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 shrk_out_hend[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 shrk_in_hbgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 shrk_in_hend[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_out_hbgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_out_hbgn_chrm[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_out_hend[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_out_hend_chrm[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_in_hbgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_in_hbgn_chrm[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_in_hend[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 scale_in_hend_chrm[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 opp_in_hbgn[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; u32 opp_in_hend[C4_ISP_RSZ_MAX][C4_OPP_TILE_NUM_MAX]; }; struct c4_ipp_format_info { u32 code; u8 bpp; bool is_raw; }; struct c4_ipp_cfg_info { enum c4_ipp_work_mode work_mode; enum c4_ipp_image_mode img_mode; bool pd_stat_en; bool patgen_en; }; struct c4_ipp { struct v4l2_subdev sd; struct media_pad pads[C4_IPP_PAD_MAX]; struct media_pad *src_pad; struct v4l2_ctrl_handler ctrls; struct c4_isp_device *isp; struct c4_ipp_cfg_info cfg_info; u32 start_count; }; struct c4_isp_core_format_info { u32 code; u32 pads; u8 xofst; u8 yofst; u8 bpp; u8 bayer_x_ofst; u8 bayer_y_ofst; u32 vfce_grgb_comb_en0; u32 vfce_grgb_comb_en1; u32 vfcd_grgb_comb_en0; u32 vfcd_grgb_comb_en1; u32 pixel_type0; u32 pixel_type1; bool is_raw; }; struct c4_isp_core_cfg_info { enum c4_isp_work_mode work_mode; enum c4_isp_image_mode img_mode; enum c4_isp_output_mode out_mode; bool pd_stat_en; bool rawtnr_en; bool yuvtnr_en; bool lcge_en; bool fe2be_link; u32 out_fps; }; struct c4_isp_cap_format_info { u32 code; u32 fourcc; u32 format; u32 plane0_bits; u32 plane1_bits; u32 plane0_pack; u32 plane1_pack; u8 num_planes; u8 uv_swap; u8 bpp[2]; u8 hdiv; u8 vdiv; }; struct c4_isp_cap_buffer { struct vb2_v4l2_buffer vb; // isp_plane_num identify the plane number for isp hw. fixed 2. int isp_plane_num; dma_addr_t dma_addr[C4_ISP_NUM_PLANES]; struct list_head list; }; struct c4_isp_stats_buffer { struct vb2_v4l2_buffer vb; dma_addr_t dma_addr; void *vaddr; struct list_head list; }; struct c4_isp_params_buffer { struct vb2_v4l2_buffer vb; void *cfg; struct list_head list; }; struct c4_isp_data_buffer { void *vaddr; dma_addr_t dma_addr; u32 size; struct list_head list; }; struct c4_isp_core_buffer { u32 offset; spinlock_t lock; struct list_head waiting; struct list_head done; struct c4_isp_data_buffer *cur_buff; struct c4_isp_data_buffer *done_buff; struct c4_isp_data_buffer buff[2]; }; struct c4_isp_core { struct v4l2_subdev sd; struct media_pad pads[C4_ISP_CORE_PAD_MAX]; struct media_pad *src_pad; struct v4l2_ctrl_handler ctrls; struct c4_isp_device *isp; struct c4_isp_core_cfg_info cfg_info; u32 start_count; struct c4_isp_core_buffer ipp_raw0; struct c4_isp_core_buffer ipp_raw1; struct c4_isp_core_buffer fe_raw; struct c4_isp_core_buffer bnr_alp; struct c4_isp_core_buffer bnr_mn; struct c4_isp_core_buffer yuvnr_body; struct c4_isp_core_buffer yuvnr_alp; }; struct c4_isp_resizer { enum c4_isp_resizer_ids id; struct v4l2_subdev sd; struct media_pad pads[C4_ISP_RSZ_PAD_MAX]; struct v4l2_subdev *src_sd; struct c4_isp_device *isp; u32 src_pad; bool streaming; u32 shrk_ram_ofst; struct c4_isp_tile_cfg tile; struct c4_isp_pps_params *hsc; struct c4_isp_pps_params *vsc; enum c4_isp_work_mode work_mode; enum c4_isp_output_mode out_mode; }; struct c4_isp_stats { struct vb2_queue vb2_q; struct video_device vdev; struct v4l2_format vfmt; struct media_pad pad; struct mutex lock; /* Protects vb2_q, vdev */ struct c4_isp_device *isp; struct c4_isp_stats_buffer *buff; spinlock_t buff_lock; /* Protects stats buffer */ struct list_head pending; }; struct c4_isp_params { struct vb2_queue vb2_q; struct video_device vdev; struct v4l2_format vfmt; struct media_pad pad; struct mutex lock; /* Protects vb2_q, vdev */ struct c4_isp_device *isp; struct c4_isp_params_buffer *buff; spinlock_t buff_lock; /* Protects params buffer */ struct list_head pending; }; struct c4_isp_capture { u8 id; struct vb2_queue vb2_q; struct video_device vdev; struct v4l2_ctrl_handler ctrl_handler; struct media_pad pad; struct mutex lock; /* Protects vb2_q, vdev */ struct c4_isp_device *isp; struct c4_isp_resizer *rsz; struct c4_isp_data_buffer dummy_buff; struct c4_isp_cap_buffer *buff; spinlock_t buff_lock; /* Protects stream buffer */ struct list_head pending; struct completion done; /* Only for import device */ struct { const struct c4_isp_cap_format_info *info; struct v4l2_pix_format_mplane pix_mp; } format; u32 sub_frame_num; bool is_subs_evt; u32 fps_output; u32 pass_frame_num; u32 drop_frame_num; }; struct c4_isp_thread_info { struct task_struct *thread; struct list_head pending; struct c4_isp_cap_buffer *buff; spinlock_t buff_lock; struct completion done; u32 start_count; }; struct c4_ipp_rdma_info { u8 rdma_start_cnt; struct mutex rdma_mutex; struct mutex rdma_runtime_mutex; u16 rdma_init_cnt; struct c4_isp_data_buffer rdma_init; u16 rdma_cfg_cnt; struct c4_isp_data_buffer rdma_cfg; }; struct c4_isp_match_info { enum c4_isp_virt_id id; char *clocks[C4_ISP_CLOCK_NUM_MAX]; u32 clock_num; }; struct c4_isp_device { struct device *dev; struct device *hw_dev; struct device *isp_pd; struct device *opp_pd; void __iomem *base; void __iomem *disp; void __iomem *intr; void __iomem *ddma; struct clk_bulk_data clks[C4_ISP_CLOCK_NUM_MAX]; struct v4l2_async_notifier notifier; struct v4l2_device v4l2_dev; struct media_device media_dev; struct media_pipeline vc_pipe; /* For virtual channel path*/ struct media_pipeline sc_pipe; /* For PPS scaler path */ struct c4_ipp ipp; struct c4_isp_capture ipp_caps[C4_IPP_NUM_CAP_DEVS]; struct c4_isp_core core; struct c4_isp_resizer resizers[C4_ISP_RSZ_MAX]; struct c4_isp_stats stats; struct c4_isp_params params; struct c4_isp_capture raw; struct c4_isp_capture imp; struct c4_isp_capture caps[C4_ISP_NUM_CAP_DEVS]; struct c4_isp_tile_cfg core_tile; struct c4_isp_hwlink_info hwlk; bool rdma_alloc_en; bool rdma_en; u8 rdma_inited_cnt; u8 rdma_wr_phase; struct c4_isp_data_buffer *febe_rdma_orig; struct c4_isp_data_buffer febe_rdma_base; struct c4_isp_data_buffer febe_rdma_fdn; u16 febe_rdma_init_reg_cnt; struct c4_isp_data_buffer febe_rdma_init; u16 febe_rdma_cfg_reg_cnt; struct c4_isp_data_buffer febe_rdma_cfg; struct c4_isp_data_buffer *disp_rdma_orig; struct c4_isp_data_buffer disp_rdma_base; u16 disp_rdma_init_reg_cnt; struct c4_isp_data_buffer disp_rdma_init; bool ipp_rdma_work; struct c4_ipp_rdma_info *ipp_rdma_info; bool fpga_env; bool sending; bool streaming; u32 be_frm_seq; u32 ipp_frm_seq; struct c4_isp_pps_params hsc; struct c4_isp_pps_params vsc; struct c4_isp_thread_info *thrd_info; const struct c4_isp_match_info *info; struct proc_dir_entry *proc_entry; }; int c4_ipp_register(struct c4_isp_device *isp); void c4_ipp_unregister(struct c4_isp_device *isp); void c4_ipp_multi_vc_isr(struct c4_isp_device *isp); int c4_ipp_caps_register(struct c4_isp_device *isp); void c4_ipp_caps_unregister(struct c4_isp_device *isp); void c4_ipp_caps_isr(struct c4_isp_device *isp, enum c4_ipp_cap_devs cap_id); void c4_isp_core_queue_sof(struct c4_isp_device *isp); int c4_isp_core_register(struct c4_isp_device *isp); void c4_isp_core_unregister(struct c4_isp_device *isp); void c4_isp_core_nr_isr(struct c4_isp_device *isp); int c4_isp_resizers_register(struct c4_isp_device *isp); void c4_isp_resizers_unregister(struct c4_isp_device *isp); int c4_isp_captures_register(struct c4_isp_device *isp); void c4_isp_captures_unregister(struct c4_isp_device *isp); void c4_isp_captures_isr(struct c4_isp_device *isp, enum c4_isp_cap_devs id); int c4_isp_stats_register(struct c4_isp_device *isp); void c4_isp_stats_unregister(struct c4_isp_device *isp); void c4_isp_stats_pre_cfg(struct c4_isp_device *isp);; void c4_isp_stats_isr(struct c4_isp_device *isp); int c4_isp_params_register(struct c4_isp_device *isp); void c4_isp_params_unregister(struct c4_isp_device *isp); void c4_isp_params_pre_cfg(struct c4_isp_device *isp); void c4_isp_params_isr(struct c4_isp_device *isp); int c4_isp_raw_register(struct c4_isp_device *isp); void c4_isp_raw_unregister(struct c4_isp_device *isp); void c4_isp_raw_isr(struct c4_isp_device *isp); int c4_isp_imp_register(struct c4_isp_device *isp); void c4_isp_imp_unregister(struct c4_isp_device *isp); int c4_isp_offline_thread_start(struct c4_isp_device *isp); void c4_isp_offline_thread_stop(struct c4_isp_device *isp); void c4_isp_offline_thread_isr(struct c4_isp_device *isp); #endif