/* SPDX-License-Identifier: GPL-2.0 */ /* * V4L2 Capture ISI subdev for i.MX8QXP/QM platform * * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which * used to process image from camera sensor to memory or DC * Copyright 2019-2020 NXP */ #ifndef __MXC_ISI_CORE_H__ #define __MXC_ISI_CORE_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct clk_bulk_data; struct dentry; struct device; struct media_intf_devnode; struct regmap; struct v4l2_m2m_dev; /* Pipeline pads */ #define MXC_ISI_PIPE_PAD_SINK 0 #define MXC_ISI_PIPE_PAD_SOURCE 1 #define MXC_ISI_PIPE_PADS_NUM 2 #define MXC_ISI_MIN_WIDTH 1U #define MXC_ISI_MIN_HEIGHT 1U #define MXC_ISI_MAX_WIDTH_UNCHAINED 2048U #define MXC_ISI_MAX_WIDTH_CHAINED 4096U #define MXC_ISI_MAX_HEIGHT 8191U #define MXC_ISI_DEF_WIDTH 1920U #define MXC_ISI_DEF_HEIGHT 1080U #define MXC_ISI_DEF_MBUS_CODE_SINK MEDIA_BUS_FMT_UYVY8_1X16 #define MXC_ISI_DEF_MBUS_CODE_SOURCE MEDIA_BUS_FMT_YUV8_1X24 #define MXC_ISI_DEF_PIXEL_FORMAT V4L2_PIX_FMT_YUYV #define MXC_ISI_DEF_COLOR_SPACE V4L2_COLORSPACE_SRGB #define MXC_ISI_DEF_YCBCR_ENC V4L2_YCBCR_ENC_601 #define MXC_ISI_DEF_QUANTIZATION V4L2_QUANTIZATION_LIM_RANGE #define MXC_ISI_DEF_XFER_FUNC V4L2_XFER_FUNC_SRGB #define MXC_ISI_DRIVER_NAME "mxc-isi" #define MXC_ISI_CAPTURE "mxc-isi-cap" #define MXC_ISI_M2M "mxc-isi-m2m" #define MXC_MAX_PLANES 3 struct mxc_isi_dev; struct mxc_isi_m2m_ctx; enum mxc_isi_buf_id { MXC_ISI_BUF1 = 0x0, MXC_ISI_BUF2, }; enum mxc_isi_encoding { MXC_ISI_ENC_RAW, MXC_ISI_ENC_RGB, MXC_ISI_ENC_YUV, }; enum mxc_isi_input_id { /* Inputs from the crossbar switch range from 0 to 15 */ MXC_ISI_INPUT_MEM = 16, }; enum mxc_isi_video_type { MXC_ISI_VIDEO_CAP = BIT(0), MXC_ISI_VIDEO_M2M_OUT = BIT(1), MXC_ISI_VIDEO_M2M_CAP = BIT(2), }; struct mxc_isi_format_info { u32 mbus_code; u32 fourcc; enum mxc_isi_video_type type; u32 isi_in_format; u32 isi_out_format; u8 mem_planes; u8 color_planes; u8 depth[MXC_MAX_PLANES]; u8 hsub; u8 vsub; enum mxc_isi_encoding encoding; }; struct mxc_isi_bus_format_info { u32 mbus_code; u32 output; u32 pads; enum mxc_isi_encoding encoding; }; struct mxc_isi_buffer { struct vb2_v4l2_buffer v4l2_buf; struct list_head list; dma_addr_t dma_addrs[3]; enum mxc_isi_buf_id id; bool discard; }; struct mxc_isi_reg { u32 offset; u32 mask; }; struct mxc_isi_ier_reg { /* Overflow Y/U/V trigger enable*/ struct mxc_isi_reg oflw_y_buf_en; struct mxc_isi_reg oflw_u_buf_en; struct mxc_isi_reg oflw_v_buf_en; /* Excess overflow Y/U/V trigger enable*/ struct mxc_isi_reg excs_oflw_y_buf_en; struct mxc_isi_reg excs_oflw_u_buf_en; struct mxc_isi_reg excs_oflw_v_buf_en; /* Panic Y/U/V trigger enable*/ struct mxc_isi_reg panic_y_buf_en; struct mxc_isi_reg panic_v_buf_en; struct mxc_isi_reg panic_u_buf_en; }; struct mxc_isi_panic_thd { u32 mask; u32 offset; u32 threshold; }; struct mxc_isi_set_thd { struct mxc_isi_panic_thd panic_set_thd_y; struct mxc_isi_panic_thd panic_set_thd_u; struct mxc_isi_panic_thd panic_set_thd_v; }; struct mxc_gasket_ops { void (*enable)(struct mxc_isi_dev *isi, const struct v4l2_mbus_frame_desc *fd, const struct v4l2_mbus_framefmt *fmt, const unsigned int port); void (*disable)(struct mxc_isi_dev *isi, const unsigned int port); }; enum model { MXC_ISI_IMX8MN, MXC_ISI_IMX8MP, MXC_ISI_IMX93, }; struct mxc_isi_plat_data { enum model model; unsigned int num_ports; unsigned int num_channels; unsigned int reg_offset; const struct mxc_isi_ier_reg *ier_reg; const struct mxc_isi_set_thd *set_thd; const struct mxc_gasket_ops *gasket_ops; const struct clk_bulk_data *clks; unsigned int num_clks; bool buf_active_reverse; bool has_36bit_dma; }; struct mxc_isi_dma_buffer { size_t size; void *addr; dma_addr_t dma; }; struct mxc_isi_input { unsigned int enable_count; }; struct mxc_isi_crossbar { struct mxc_isi_dev *isi; unsigned int num_sinks; unsigned int num_sources; struct mxc_isi_input *inputs; struct v4l2_subdev sd; struct media_pad *pads; }; struct mxc_isi_video { struct mxc_isi_pipe *pipe; struct video_device vdev; struct media_pad pad; /* Protects is_streaming, and the vdev and vb2_q operations */ struct mutex lock; bool is_streaming; struct v4l2_pix_format_mplane pix; const struct mxc_isi_format_info *fmtinfo; struct { struct v4l2_ctrl_handler handler; unsigned int alpha; bool hflip; bool vflip; } ctrls; struct vb2_queue vb2_q; struct mxc_isi_buffer buf_discard[3]; struct list_head out_pending; struct list_head out_active; struct list_head out_discard; u32 frame_count; /* Protects out_pending, out_active, out_discard and frame_count */ spinlock_t buf_lock; struct mxc_isi_dma_buffer discard_buffer[MXC_MAX_PLANES]; }; typedef void(*mxc_isi_pipe_irq_t)(struct mxc_isi_pipe *, u32); struct mxc_isi_pipe { struct mxc_isi_dev *isi; u32 id; void __iomem *regs; struct media_pipeline pipe; struct v4l2_subdev sd; struct media_pad pads[MXC_ISI_PIPE_PADS_NUM]; struct mxc_isi_video video; /* * Protects use_count, irq_handler, res_available, res_acquired, * chained_res, and the CHNL_CTRL register. */ struct mutex lock; unsigned int use_count; mxc_isi_pipe_irq_t irq_handler; #define MXC_ISI_CHANNEL_RES_LINE_BUF BIT(0) #define MXC_ISI_CHANNEL_RES_OUTPUT_BUF BIT(1) u8 available_res; u8 acquired_res; u8 chained_res; bool chained; }; struct mxc_isi_m2m { struct mxc_isi_dev *isi; struct mxc_isi_pipe *pipe; struct media_pad pad; struct video_device vdev; struct media_intf_devnode *intf; struct v4l2_m2m_dev *m2m_dev; /* Protects last_ctx, usage_count and chained_count */ struct mutex lock; struct mxc_isi_m2m_ctx *last_ctx; int usage_count; int chained_count; }; struct mxc_isi_dev { struct device *dev; const struct mxc_isi_plat_data *pdata; void __iomem *regs; struct clk_bulk_data *clks; struct regmap *gasket; struct mxc_isi_crossbar crossbar; struct mxc_isi_pipe *pipes; struct mxc_isi_m2m m2m; struct media_device media_dev; struct v4l2_device v4l2_dev; struct v4l2_async_notifier notifier; struct dentry *debugfs_root; }; extern const struct mxc_gasket_ops mxc_imx8_gasket_ops; extern const struct mxc_gasket_ops mxc_imx93_gasket_ops; int mxc_isi_crossbar_init(struct mxc_isi_dev *isi); void mxc_isi_crossbar_cleanup(struct mxc_isi_crossbar *xbar); int mxc_isi_crossbar_register(struct mxc_isi_crossbar *xbar); void mxc_isi_crossbar_unregister(struct mxc_isi_crossbar *xbar); const struct mxc_isi_bus_format_info * mxc_isi_bus_format_by_code(u32 code, unsigned int pad); const struct mxc_isi_bus_format_info * mxc_isi_bus_format_by_index(unsigned int index, unsigned int pad); const struct mxc_isi_format_info * mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type); const struct mxc_isi_format_info * mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type); const struct mxc_isi_format_info * mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix, enum mxc_isi_video_type type); int mxc_isi_pipe_init(struct mxc_isi_dev *isi, unsigned int id); void mxc_isi_pipe_cleanup(struct mxc_isi_pipe *pipe); int mxc_isi_pipe_acquire(struct mxc_isi_pipe *pipe, mxc_isi_pipe_irq_t irq_handler); void mxc_isi_pipe_release(struct mxc_isi_pipe *pipe); int mxc_isi_pipe_enable(struct mxc_isi_pipe *pipe); void mxc_isi_pipe_disable(struct mxc_isi_pipe *pipe); int mxc_isi_video_register(struct mxc_isi_pipe *pipe, struct v4l2_device *v4l2_dev); void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe); void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe); int mxc_isi_video_resume(struct mxc_isi_pipe *pipe); int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format, const struct mxc_isi_format_info *info, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[]); void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3], const struct mxc_isi_format_info *info, const struct v4l2_pix_format_mplane *pix); int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2, const struct mxc_isi_format_info *info, const struct v4l2_pix_format_mplane *pix); #ifdef CONFIG_VIDEO_IMX8_ISI_M2M int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev); int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi); #else static inline int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev) { return 0; } static inline int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi) { return 0; } #endif int mxc_isi_channel_acquire(struct mxc_isi_pipe *pipe, mxc_isi_pipe_irq_t irq_handler, bool bypass); void mxc_isi_channel_release(struct mxc_isi_pipe *pipe); void mxc_isi_channel_get(struct mxc_isi_pipe *pipe); void mxc_isi_channel_put(struct mxc_isi_pipe *pipe); void mxc_isi_channel_enable(struct mxc_isi_pipe *pipe); void mxc_isi_channel_disable(struct mxc_isi_pipe *pipe); int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass); void mxc_isi_channel_unchain(struct mxc_isi_pipe *pipe); void mxc_isi_channel_config(struct mxc_isi_pipe *pipe, enum mxc_isi_input_id input, const struct v4l2_area *in_size, const struct v4l2_area *scale, const struct v4l2_rect *crop, enum mxc_isi_encoding in_encoding, enum mxc_isi_encoding out_encoding); void mxc_isi_channel_set_input_format(struct mxc_isi_pipe *pipe, const struct mxc_isi_format_info *info, const struct v4l2_pix_format_mplane *format); void mxc_isi_channel_set_output_format(struct mxc_isi_pipe *pipe, const struct mxc_isi_format_info *info, struct v4l2_pix_format_mplane *format); void mxc_isi_channel_m2m_start(struct mxc_isi_pipe *pipe); void mxc_isi_channel_set_alpha(struct mxc_isi_pipe *pipe, u8 alpha); void mxc_isi_channel_set_flip(struct mxc_isi_pipe *pipe, bool hflip, bool vflip); void mxc_isi_channel_set_inbuf(struct mxc_isi_pipe *pipe, dma_addr_t dma_addr); void mxc_isi_channel_set_outbuf(struct mxc_isi_pipe *pipe, const dma_addr_t dma_addrs[3], enum mxc_isi_buf_id buf_id); u32 mxc_isi_channel_irq_status(struct mxc_isi_pipe *pipe, bool clear); void mxc_isi_channel_irq_clear(struct mxc_isi_pipe *pipe); #if IS_ENABLED(CONFIG_DEBUG_FS) void mxc_isi_debug_init(struct mxc_isi_dev *isi); void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi); #else static inline void mxc_isi_debug_init(struct mxc_isi_dev *isi) { } static inline void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi) { } #endif #endif /* __MXC_ISI_CORE_H__ */