/* * drivers/media/platform/tegra/camera/mc_common.h * * Tegra Media controller common APIs * * Copyright (c) 2012-2021, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __CAMERA_MC_COMMON_H__ #define __CAMERA_MC_COMMON_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_FORMAT_NUM 64 #define MAX_SUBDEVICES 4 #define QUEUED_BUFFERS 4 #define ENABLE 1 #define DISABLE 0 #define MAX_SYNCPT_PER_CHANNEL 3 #define CAPTURE_MIN_BUFFERS 1U #define CAPTURE_MAX_BUFFERS 240U #define TEGRA_MEM_FORMAT 0 #define TEGRA_ISP_FORMAT 1 enum channel_capture_state { CAPTURE_IDLE = 0, CAPTURE_GOOD, CAPTURE_TIMEOUT, CAPTURE_ERROR, }; enum tegra_vi_pg_mode { TEGRA_VI_PG_DISABLED = 0, TEGRA_VI_PG_DIRECT, TEGRA_VI_PG_PATCH, }; enum interlaced_type { Top_Bottom = 0, Interleaved, }; /** * struct tegra_channel_buffer - video channel buffer * @buf: vb2 buffer base object * @queue: buffer list entry in the channel queued buffers list * @chan: channel that uses the buffer * @vb2_state: V4L2 buffer state (active, done, error) * @capture_descr_index: Index into the VI capture descriptor queue * @addr: Tegra IOVA buffer address for VI output */ struct tegra_channel_buffer { struct vb2_v4l2_buffer buf; struct list_head queue; struct tegra_channel *chan; unsigned int vb2_state; unsigned int capture_descr_index[TEGRA_CSI_BLOCKS]; dma_addr_t addr; u32 thresh[TEGRA_CSI_BLOCKS]; int version; int state; }; #define to_tegra_channel_buffer(vb) \ container_of(vb, struct tegra_channel_buffer, buf) /** * struct tegra_vi_graph_entity - Entity in the video graph * @list: list entry in a graph entities list * @node: the entity's DT node * @entity: media entity, from the corresponding V4L2 subdev * @asd: subdev asynchronous registration information * @subdev: V4L2 subdev */ struct tegra_vi_graph_entity { struct list_head list; struct device_node *node; struct media_entity *entity; struct v4l2_async_subdev asd; struct v4l2_subdev *subdev; }; /** * struct tegra_channel - Tegra video channel * @list: list entry in a composite device dmas list * @video: V4L2 video device associated with the video channel * @video_lock: * @pad: media pad for the video device entity * @pipe: pipeline belonging to the channel * * @vi: composite device DT node port number for the channel * * @kthread_capture: kernel thread task structure of this video channel * @wait: wait queue structure for kernel thread * * @format: active V4L2 pixel format * @fmtinfo: format information corresponding to the active @format * * @queue: vb2 buffers queue * @alloc_ctx: allocation context for the vb2 @queue * @sequence: V4L2 buffers sequence number * * @capture: list of queued buffers for capture * @queued_lock: protects the buf_queued list * * @csi: CSI register bases * @stride_align: channel buffer stride alignment, default is 1 * @width_align: image width alignment, default is 1 * @height_align: channel buffer height alignment, default is 1 * @size_align: channel buffer size alignment, default is 1 * @port: CSI port of this video channel * @io_id: Tegra IO rail ID of this video channel * * @fmts_bitmap: a bitmap for formats supported * @bypass: bypass flag for VI bypass mode * @restart_version: incremented every time either capture or release threads * wants to reset VI. it is appended to each buffer processed * by the capture thread, and inspected by each buffer * processed by the receive thread. * @capture_version: thread-local copy of @restart_version created when the * capture thread resets the VI. */ struct tegra_channel { int id; struct list_head list; struct video_device *video; struct media_pad pad; struct media_pipeline pipe; struct mutex video_lock; struct tegra_mc_vi *vi; struct v4l2_subdev *subdev[MAX_SUBDEVICES]; struct v4l2_subdev *subdev_on_csi; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_pix_format format; const struct tegra_video_format *fmtinfo; const struct tegra_video_format *video_formats[MAX_FORMAT_NUM]; unsigned int num_video_formats; struct mutex stop_kthread_lock; unsigned char port[TEGRA_CSI_BLOCKS]; unsigned int virtual_channel; unsigned int syncpt[TEGRA_CSI_BLOCKS][MAX_SYNCPT_PER_CHANNEL]; unsigned int syncpoint_fifo[TEGRA_CSI_BLOCKS][MAX_SYNCPT_PER_CHANNEL]; unsigned int buffer_offset[TEGRA_CSI_BLOCKS]; unsigned int *buffer_state; struct vb2_v4l2_buffer **buffers; unsigned long timeout; atomic_t restart_version; int capture_version; unsigned int save_index; unsigned int free_index; unsigned int num_buffers; spinlock_t buffer_lock; unsigned int released_bufs; unsigned int capture_queue_depth; unsigned int capture_descr_index; unsigned int capture_descr_sequence; unsigned int capture_reqs_enqueued; struct task_struct *kthread_capture_start; struct task_struct *kthread_release; wait_queue_head_t start_wait; wait_queue_head_t release_wait; struct task_struct *kthread_capture_dequeue; wait_queue_head_t dequeue_wait; struct vb2_queue queue; void *alloc_ctx; bool init_done; struct list_head capture; struct list_head release; struct list_head dequeue; spinlock_t start_lock; spinlock_t release_lock; spinlock_t dequeue_lock; struct work_struct status_work; struct work_struct error_work; void __iomem *csibase[TEGRA_CSI_BLOCKS]; unsigned int stride_align; unsigned int preferred_stride; unsigned int width_align; unsigned int height_align; unsigned int size_align; unsigned int valid_ports; unsigned int total_ports; unsigned int numlanes; unsigned int io_id; unsigned int num_subdevs; unsigned int sequence; unsigned int saved_ctx_bypass; unsigned int saved_ctx_pgmode; unsigned int gang_mode; unsigned int gang_width; unsigned int gang_height; unsigned int gang_bytesperline; unsigned int gang_sizeimage; unsigned int embedded_data_width; unsigned int embedded_data_height; DECLARE_BITMAP(fmts_bitmap, MAX_FORMAT_NUM); atomic_t power_on_refcnt; struct v4l2_fh *fh; bool bypass; bool write_ispformat; bool low_latency; enum tegra_vi_pg_mode pg_mode; bool bfirst_fstart; enum channel_capture_state capture_state; bool queue_error; spinlock_t capture_state_lock; atomic_t is_streaming; int requested_kbyteps; unsigned long requested_hz; struct vi_notify_channel *vnc[TEGRA_CSI_BLOCKS]; int vnc_id[TEGRA_CSI_BLOCKS]; int grp_id; struct v4l2_async_notifier notifier; struct list_head entities; struct device_node *endpoint_node; /* endpoint of_node in vi */ unsigned int subdevs_bound; unsigned int link_status; struct nvcsi_deskew_context *deskew_ctx; struct tegra_vi_channel *tegra_vi_channel[TEGRA_CSI_BLOCKS]; struct capture_descriptor *request[TEGRA_CSI_BLOCKS]; bool is_slvsec; int is_interlaced; enum interlaced_type interlace_type; int interlace_bplfactor; atomic_t syncpt_depth; struct rw_semaphore reset_lock; }; #define to_tegra_channel(vdev) \ container_of(vdev, struct tegra_channel, video) /** * struct tegra_mc_vi - NVIDIA Tegra Media controller structure * @v4l2_dev: V4L2 device * @media_dev: media device * @dev: device struct * @tegra_camera: tegra camera structure * @nvhost_device_data: NvHost VI device information * * @notifier: V4L2 asynchronous subdevs notifier * @entities: entities in the graph as a list of tegra_vi_graph_entity * @num_subdevs: number of subdevs in the pipeline * * @channels: list of channels at the pipeline output and input * * @ctrl_handler: V4L2 control handler * @pattern: test pattern generator V4L2 control * @pg_mode: test pattern generator mode (disabled/direct/patch) * * @has_sensors: a flag to indicate whether is a real sensor connecting */ struct tegra_mc_vi { struct vi *vi; struct platform_device *ndev; struct v4l2_device v4l2_dev; struct media_device media_dev; struct device *dev; struct nvhost_device_data *ndata; struct regulator *reg; struct clk *clk; struct clk *parent_clk; unsigned int num_channels; unsigned int num_subdevs; struct tegra_csi_device *csi; struct list_head vi_chans; struct tegra_channel *tpg_start; void __iomem *iomem; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *pattern; enum tegra_vi_pg_mode pg_mode; bool has_sensors; atomic_t power_on_refcnt; atomic_t vb2_dma_alloc_refcnt; struct mutex bw_update_lock; unsigned long aggregated_kbyteps; unsigned long max_requested_hz; struct mutex mipical_lock; bool bypass; const struct tegra_vi_fops *fops; dma_addr_t emb_buf; void *emb_buf_addr; unsigned int emb_buf_size; }; int tegra_vi_get_port_info(struct tegra_channel *chan, struct device_node *node, unsigned int index); void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi); int tegra_vi_v4l2_init(struct tegra_mc_vi *vi); int tegra_vi_tpg_graph_init(struct tegra_mc_vi *vi); int tegra_vi_graph_init(struct tegra_mc_vi *vi); void tegra_vi_graph_cleanup(struct tegra_mc_vi *vi); int tegra_channel_init(struct tegra_channel *chan); void tegra_vi_channels_unregister(struct tegra_mc_vi *vi); int tegra_vi_channels_init(struct tegra_mc_vi *vi); int tegra_channel_cleanup(struct tegra_channel *chan); int tegra_vi_channels_cleanup(struct tegra_mc_vi *vi); int tegra_channel_init_subdevices(struct tegra_channel *chan); void tegra_channel_remove_subdevices(struct tegra_channel *chan); struct v4l2_subdev *tegra_channel_find_linked_csi_subdev( struct tegra_channel *chan); int tegra_vi2_power_on(struct tegra_mc_vi *vi); void tegra_vi2_power_off(struct tegra_mc_vi *vi); int tegra_vi4_power_on(struct tegra_mc_vi *vi); void tegra_vi4_power_off(struct tegra_mc_vi *vi); int tegra_vi5_power_on(struct tegra_mc_vi *vi); void tegra_vi5_power_off(struct tegra_mc_vi *vi); int tegra_clean_unlinked_channels(struct tegra_mc_vi *vi); int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl); int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi, struct platform_device *pdev); void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi); void tegra_channel_ec_close(struct tegra_mc_vi *mc_vi); void tegra_channel_query_hdmiin_unplug(struct tegra_channel *chan, struct v4l2_event *event); int tegra_vi_mfi_work(struct tegra_mc_vi *vi, int csiport); int tpg_vi_media_controller_init(struct tegra_mc_vi *mc_vi, int pg_mode); void tpg_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi); struct tegra_mc_vi *tegra_get_mc_vi(void); u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan, unsigned int index); int tegra_core_get_idx_by_code(struct tegra_channel *chan, unsigned int code, unsigned offset); int tegra_core_get_code_by_fourcc(struct tegra_channel *chan, unsigned int fourcc, unsigned int offset); const struct tegra_video_format *tegra_core_get_format_by_code( struct tegra_channel *chan, unsigned int code, unsigned offset); const struct tegra_video_format *tegra_core_get_format_by_fourcc( struct tegra_channel *chan, u32 fourcc); void tegra_channel_queued_buf_done(struct tegra_channel *chan, enum vb2_buffer_state state, bool multi_queue); int tegra_channel_set_stream(struct tegra_channel *chan, bool on); int tegra_channel_write_blobs(struct tegra_channel *chan); void tegra_channel_ring_buffer(struct tegra_channel *chan, struct vb2_v4l2_buffer *vb, struct timespec *ts, int state); struct tegra_channel_buffer *dequeue_buffer(struct tegra_channel *chan, bool requeue); struct tegra_channel_buffer *dequeue_dequeue_buffer(struct tegra_channel *chan); int tegra_channel_error_recover(struct tegra_channel *chan, bool queue_error); int tegra_channel_alloc_buffer_queue(struct tegra_channel *chan, unsigned int num_buffers); void tegra_channel_dealloc_buffer_queue(struct tegra_channel *chan); void tegra_channel_init_ring_buffer(struct tegra_channel *chan); void free_ring_buffers(struct tegra_channel *chan, int frames); void release_buffer(struct tegra_channel *chan, struct tegra_channel_buffer *buf); void set_timestamp(struct tegra_channel_buffer *buf, const struct timespec *ts); void enqueue_inflight(struct tegra_channel *chan, struct tegra_channel_buffer *buf); struct tegra_channel_buffer *dequeue_inflight(struct tegra_channel *chan); int tegra_channel_set_power(struct tegra_channel *chan, bool on); int tegra_channel_init_video(struct tegra_channel *chan); int tegra_channel_cleanup_video(struct tegra_channel *chan); struct tegra_vi_fops { int (*vi_power_on)(struct tegra_channel *chan); void (*vi_power_off)(struct tegra_channel *chan); int (*vi_start_streaming)(struct vb2_queue *vq, u32 count); int (*vi_stop_streaming)(struct vb2_queue *vq); int (*vi_setup_queue)(struct tegra_channel *chan, unsigned int *nbuffers); int (*vi_error_recover)(struct tegra_channel *chan, bool queue_error); int (*vi_add_ctrls)(struct tegra_channel *chan); void (*vi_init_video_formats)(struct tegra_channel *chan); long (*vi_default_ioctl)(struct file *file, void *fh, bool use_prio, unsigned int cmd, void *arg); int (*vi_mfi_work)(struct tegra_mc_vi *vi, int port); void (*vi_stride_align)(unsigned int *bpl); }; struct tegra_csi_fops { int (*csi_power_on)(struct tegra_csi_device *csi); int (*csi_power_off)(struct tegra_csi_device *csi); int (*csi_start_streaming)(struct tegra_csi_channel *chan, int port_idx); void (*csi_stop_streaming)(struct tegra_csi_channel *chan, int port_idx); void (*csi_override_format)(struct tegra_csi_channel *chan, int port_idx); int (*csi_error_recover)(struct tegra_csi_channel *chan, int port_idx); int (*mipical)(struct tegra_csi_channel *chan); int (*hw_init)(struct tegra_csi_device *csi); }; struct tegra_t210_vi_data { struct nvhost_device_data *info; const struct tegra_vi_fops *vi_fops; const struct tegra_csi_fops *csi_fops; }; struct tegra_vi_data { struct nvhost_device_data *info; const struct tegra_vi_fops *vi_fops; }; struct tegra_csi_data { struct nvhost_device_data *info; const struct tegra_csi_fops *csi_fops; }; #endif