Files
linux-nv-oot/include/media/mc_common.h
Laxman Dewangan 7abc2d8726 camera: vi: Use proper APIs from v4l2 for Linux6.6
The earlier porting of the driver for Linux 6.6 is not
matching with the previous kernel implementation.

Few V4L2 APIs have been deprecated from Linux 6.6. and
added the new APIs.

Use the correct API available from Linux6.6 for the
replacement as the previous supported kernel APIs.

For reference, the changes in core kernels are:
  The device argument is added in the API v4l2_async_nf_init() with
  commit b8ec754ae4c5 ("media: v4l: async: Set v4l2_device and subdev
  in async notifier init") in Linux 6.6.

  The API is removed with commit bda8953e8c3e ("media: v4l: async: Drop
  v4l2_async_nf_parse_fwnode_endpoints()") in Linux 6.6

Bug 4346767

Change-Id: I94877a8fe6a6764fc3c913fea7ecdbfdc7c793d6
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3042993
(cherry picked from commit 7d931ef33d)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3053710
Reviewed-by: Jonathan Hunter <jonathanh@nvidia.com>
Tested-by: Jonathan Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-01-16 14:55:44 -08:00

452 lines
14 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Tegra Media controller common APIs
*
* Copyright (c) 2012-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#ifndef __CAMERA_MC_COMMON_H__
#define __CAMERA_MC_COMMON_H__
#include <nvidia/conftest.h>
#include <media/media-device.h>
#include <media/media-entity.h>
#include <media/sensor_common.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/videobuf2-core.h>
#include <media/tegra_camera_core.h>
#include <media/csi.h>
#include <linux/workqueue.h>
#include <linux/semaphore.h>
#include <linux/rwsem.h>
#include <linux/version.h>
#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;
#if defined(NV_V4L2_ASYNC_CONNECTION_STRUCT_PRESENT) /* Linux 6.5 */
struct v4l2_async_connection *asc;
#else
struct v4l2_async_subdev asd;
#endif
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 {
unsigned 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 int vi_channel_id[TEGRA_CSI_BLOCKS];
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;
dma_addr_t emb_buf;
void *emb_buf_addr;
unsigned int emb_buf_size;
};
#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;
};
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_enable(struct tegra_mc_vi *vi);
void tegra_vi5_disable(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);
int tegra_capture_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 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 timespec64 *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 timespec64 *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);
void (*vi_unit_get_device_handle)(struct platform_device *pdev,
uint32_t csi_steam_id, struct device **dev);
};
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);
int (*tpg_set_gain)(struct tegra_csi_channel *chan, int gain_ratio_tpg);
};
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