18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for Renesas R-Car VIN
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2016 Renesas Electronics Corp.
68c2ecf20Sopenharmony_ci * Copyright (C) 2011-2013 Renesas Solutions Corp.
78c2ecf20Sopenharmony_ci * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
88c2ecf20Sopenharmony_ci * Copyright (C) 2008 Magnus Damm
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Based on the soc-camera rcar_vin driver
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#ifndef __RCAR_VIN__
148c2ecf20Sopenharmony_ci#define __RCAR_VIN__
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/kref.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <media/v4l2-async.h>
198c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h>
208c2ecf20Sopenharmony_ci#include <media/v4l2-dev.h>
218c2ecf20Sopenharmony_ci#include <media/v4l2-device.h>
228c2ecf20Sopenharmony_ci#include <media/v4l2-fwnode.h>
238c2ecf20Sopenharmony_ci#include <media/videobuf2-v4l2.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* Number of HW buffers */
268c2ecf20Sopenharmony_ci#define HW_BUFFER_NUM 3
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* Address alignment mask for HW buffers */
298c2ecf20Sopenharmony_ci#define HW_BUFFER_MASK 0x7f
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* Max number on VIN instances that can be in a system */
328c2ecf20Sopenharmony_ci#define RCAR_VIN_NUM 8
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistruct rvin_group;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cienum model_id {
378c2ecf20Sopenharmony_ci	RCAR_H1,
388c2ecf20Sopenharmony_ci	RCAR_M1,
398c2ecf20Sopenharmony_ci	RCAR_GEN2,
408c2ecf20Sopenharmony_ci	RCAR_GEN3,
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cienum rvin_csi_id {
448c2ecf20Sopenharmony_ci	RVIN_CSI20,
458c2ecf20Sopenharmony_ci	RVIN_CSI21,
468c2ecf20Sopenharmony_ci	RVIN_CSI40,
478c2ecf20Sopenharmony_ci	RVIN_CSI41,
488c2ecf20Sopenharmony_ci	RVIN_CSI_MAX,
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/**
528c2ecf20Sopenharmony_ci * STOPPED  - No operation in progress
538c2ecf20Sopenharmony_ci * STARTING - Capture starting up
548c2ecf20Sopenharmony_ci * RUNNING  - Operation in progress have buffers
558c2ecf20Sopenharmony_ci * STOPPING - Stopping operation
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_cienum rvin_dma_state {
588c2ecf20Sopenharmony_ci	STOPPED = 0,
598c2ecf20Sopenharmony_ci	STARTING,
608c2ecf20Sopenharmony_ci	RUNNING,
618c2ecf20Sopenharmony_ci	STOPPING,
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/**
658c2ecf20Sopenharmony_ci * enum rvin_buffer_type
668c2ecf20Sopenharmony_ci *
678c2ecf20Sopenharmony_ci * Describes how a buffer is given to the hardware. To be able
688c2ecf20Sopenharmony_ci * to capture SEQ_TB/BT it's needed to capture to the same vb2
698c2ecf20Sopenharmony_ci * buffer twice so the type of buffer needs to be kept.
708c2ecf20Sopenharmony_ci *
718c2ecf20Sopenharmony_ci * FULL - One capture fills the whole vb2 buffer
728c2ecf20Sopenharmony_ci * HALF_TOP - One capture fills the top half of the vb2 buffer
738c2ecf20Sopenharmony_ci * HALF_BOTTOM - One capture fills the bottom half of the vb2 buffer
748c2ecf20Sopenharmony_ci */
758c2ecf20Sopenharmony_cienum rvin_buffer_type {
768c2ecf20Sopenharmony_ci	FULL,
778c2ecf20Sopenharmony_ci	HALF_TOP,
788c2ecf20Sopenharmony_ci	HALF_BOTTOM,
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/**
828c2ecf20Sopenharmony_ci * struct rvin_video_format - Data format stored in memory
838c2ecf20Sopenharmony_ci * @fourcc:	Pixelformat
848c2ecf20Sopenharmony_ci * @bpp:	Bytes per pixel
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_cistruct rvin_video_format {
878c2ecf20Sopenharmony_ci	u32 fourcc;
888c2ecf20Sopenharmony_ci	u8 bpp;
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/**
928c2ecf20Sopenharmony_ci * struct rvin_parallel_entity - Parallel video input endpoint descriptor
938c2ecf20Sopenharmony_ci * @asd:	sub-device descriptor for async framework
948c2ecf20Sopenharmony_ci * @subdev:	subdevice matched using async framework
958c2ecf20Sopenharmony_ci * @mbus_type:	media bus type
968c2ecf20Sopenharmony_ci * @bus:	media bus parallel configuration
978c2ecf20Sopenharmony_ci * @source_pad:	source pad of remote subdevice
988c2ecf20Sopenharmony_ci * @sink_pad:	sink pad of remote subdevice
998c2ecf20Sopenharmony_ci *
1008c2ecf20Sopenharmony_ci */
1018c2ecf20Sopenharmony_cistruct rvin_parallel_entity {
1028c2ecf20Sopenharmony_ci	struct v4l2_async_subdev asd;
1038c2ecf20Sopenharmony_ci	struct v4l2_subdev *subdev;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	enum v4l2_mbus_type mbus_type;
1068c2ecf20Sopenharmony_ci	struct v4l2_fwnode_bus_parallel bus;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	unsigned int source_pad;
1098c2ecf20Sopenharmony_ci	unsigned int sink_pad;
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/**
1138c2ecf20Sopenharmony_ci * struct rvin_group_route - describes a route from a channel of a
1148c2ecf20Sopenharmony_ci *	CSI-2 receiver to a VIN
1158c2ecf20Sopenharmony_ci *
1168c2ecf20Sopenharmony_ci * @csi:	CSI-2 receiver ID.
1178c2ecf20Sopenharmony_ci * @channel:	Output channel of the CSI-2 receiver.
1188c2ecf20Sopenharmony_ci * @vin:	VIN ID.
1198c2ecf20Sopenharmony_ci * @mask:	Bitmask of the different CHSEL register values that
1208c2ecf20Sopenharmony_ci *		allow for a route from @csi + @chan to @vin.
1218c2ecf20Sopenharmony_ci *
1228c2ecf20Sopenharmony_ci * .. note::
1238c2ecf20Sopenharmony_ci *	Each R-Car CSI-2 receiver has four output channels facing the VIN
1248c2ecf20Sopenharmony_ci *	devices, each channel can carry one CSI-2 Virtual Channel (VC).
1258c2ecf20Sopenharmony_ci *	There is no correlation between channel number and CSI-2 VC. It's
1268c2ecf20Sopenharmony_ci *	up to the CSI-2 receiver driver to configure which VC is output
1278c2ecf20Sopenharmony_ci *	on which channel, the VIN devices only care about output channels.
1288c2ecf20Sopenharmony_ci *
1298c2ecf20Sopenharmony_ci *	There are in some cases multiple CHSEL register settings which would
1308c2ecf20Sopenharmony_ci *	allow for the same route from @csi + @channel to @vin. For example
1318c2ecf20Sopenharmony_ci *	on R-Car H3 both the CHSEL values 0 and 3 allow for a route from
1328c2ecf20Sopenharmony_ci *	CSI40/VC0 to VIN0. All possible CHSEL values for a route need to be
1338c2ecf20Sopenharmony_ci *	recorded as a bitmask in @mask, in this example bit 0 and 3 should
1348c2ecf20Sopenharmony_ci *	be set.
1358c2ecf20Sopenharmony_ci */
1368c2ecf20Sopenharmony_cistruct rvin_group_route {
1378c2ecf20Sopenharmony_ci	enum rvin_csi_id csi;
1388c2ecf20Sopenharmony_ci	unsigned int channel;
1398c2ecf20Sopenharmony_ci	unsigned int vin;
1408c2ecf20Sopenharmony_ci	unsigned int mask;
1418c2ecf20Sopenharmony_ci};
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci/**
1448c2ecf20Sopenharmony_ci * struct rvin_info - Information about the particular VIN implementation
1458c2ecf20Sopenharmony_ci * @model:		VIN model
1468c2ecf20Sopenharmony_ci * @use_mc:		use media controller instead of controlling subdevice
1478c2ecf20Sopenharmony_ci * @nv12:		support outputing NV12 pixel format
1488c2ecf20Sopenharmony_ci * @max_width:		max input width the VIN supports
1498c2ecf20Sopenharmony_ci * @max_height:		max input height the VIN supports
1508c2ecf20Sopenharmony_ci * @routes:		list of possible routes from the CSI-2 recivers to
1518c2ecf20Sopenharmony_ci *			all VINs. The list mush be NULL terminated.
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_cistruct rvin_info {
1548c2ecf20Sopenharmony_ci	enum model_id model;
1558c2ecf20Sopenharmony_ci	bool use_mc;
1568c2ecf20Sopenharmony_ci	bool nv12;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	unsigned int max_width;
1598c2ecf20Sopenharmony_ci	unsigned int max_height;
1608c2ecf20Sopenharmony_ci	const struct rvin_group_route *routes;
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci/**
1648c2ecf20Sopenharmony_ci * struct rvin_dev - Renesas VIN device structure
1658c2ecf20Sopenharmony_ci * @dev:		(OF) device
1668c2ecf20Sopenharmony_ci * @base:		device I/O register space remapped to virtual memory
1678c2ecf20Sopenharmony_ci * @info:		info about VIN instance
1688c2ecf20Sopenharmony_ci *
1698c2ecf20Sopenharmony_ci * @vdev:		V4L2 video device associated with VIN
1708c2ecf20Sopenharmony_ci * @v4l2_dev:		V4L2 device
1718c2ecf20Sopenharmony_ci * @ctrl_handler:	V4L2 control handler
1728c2ecf20Sopenharmony_ci * @notifier:		V4L2 asynchronous subdevs notifier
1738c2ecf20Sopenharmony_ci *
1748c2ecf20Sopenharmony_ci * @parallel:		parallel input subdevice descriptor
1758c2ecf20Sopenharmony_ci *
1768c2ecf20Sopenharmony_ci * @group:		Gen3 CSI group
1778c2ecf20Sopenharmony_ci * @id:			Gen3 group id for this VIN
1788c2ecf20Sopenharmony_ci * @pad:		media pad for the video device entity
1798c2ecf20Sopenharmony_ci *
1808c2ecf20Sopenharmony_ci * @lock:		protects @queue
1818c2ecf20Sopenharmony_ci * @queue:		vb2 buffers queue
1828c2ecf20Sopenharmony_ci * @scratch:		cpu address for scratch buffer
1838c2ecf20Sopenharmony_ci * @scratch_phys:	physical address of the scratch buffer
1848c2ecf20Sopenharmony_ci *
1858c2ecf20Sopenharmony_ci * @qlock:		protects @buf_hw, @buf_list, @sequence and @state
1868c2ecf20Sopenharmony_ci * @buf_hw:		Keeps track of buffers given to HW slot
1878c2ecf20Sopenharmony_ci * @buf_list:		list of queued buffers
1888c2ecf20Sopenharmony_ci * @sequence:		V4L2 buffers sequence number
1898c2ecf20Sopenharmony_ci * @state:		keeps track of operation state
1908c2ecf20Sopenharmony_ci *
1918c2ecf20Sopenharmony_ci * @is_csi:		flag to mark the VIN as using a CSI-2 subdevice
1928c2ecf20Sopenharmony_ci *
1938c2ecf20Sopenharmony_ci * @mbus_code:		media bus format code
1948c2ecf20Sopenharmony_ci * @format:		active V4L2 pixel format
1958c2ecf20Sopenharmony_ci *
1968c2ecf20Sopenharmony_ci * @crop:		active cropping
1978c2ecf20Sopenharmony_ci * @compose:		active composing
1988c2ecf20Sopenharmony_ci * @src_rect:		active size of the video source
1998c2ecf20Sopenharmony_ci * @std:		active video standard of the video source
2008c2ecf20Sopenharmony_ci *
2018c2ecf20Sopenharmony_ci * @alpha:		Alpha component to fill in for supported pixel formats
2028c2ecf20Sopenharmony_ci */
2038c2ecf20Sopenharmony_cistruct rvin_dev {
2048c2ecf20Sopenharmony_ci	struct device *dev;
2058c2ecf20Sopenharmony_ci	void __iomem *base;
2068c2ecf20Sopenharmony_ci	const struct rvin_info *info;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	struct video_device vdev;
2098c2ecf20Sopenharmony_ci	struct v4l2_device v4l2_dev;
2108c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler ctrl_handler;
2118c2ecf20Sopenharmony_ci	struct v4l2_async_notifier notifier;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	struct rvin_parallel_entity *parallel;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	struct rvin_group *group;
2168c2ecf20Sopenharmony_ci	unsigned int id;
2178c2ecf20Sopenharmony_ci	struct media_pad pad;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	struct mutex lock;
2208c2ecf20Sopenharmony_ci	struct vb2_queue queue;
2218c2ecf20Sopenharmony_ci	void *scratch;
2228c2ecf20Sopenharmony_ci	dma_addr_t scratch_phys;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	spinlock_t qlock;
2258c2ecf20Sopenharmony_ci	struct {
2268c2ecf20Sopenharmony_ci		struct vb2_v4l2_buffer *buffer;
2278c2ecf20Sopenharmony_ci		enum rvin_buffer_type type;
2288c2ecf20Sopenharmony_ci		dma_addr_t phys;
2298c2ecf20Sopenharmony_ci	} buf_hw[HW_BUFFER_NUM];
2308c2ecf20Sopenharmony_ci	struct list_head buf_list;
2318c2ecf20Sopenharmony_ci	unsigned int sequence;
2328c2ecf20Sopenharmony_ci	enum rvin_dma_state state;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	bool is_csi;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	u32 mbus_code;
2378c2ecf20Sopenharmony_ci	struct v4l2_pix_format format;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	struct v4l2_rect crop;
2408c2ecf20Sopenharmony_ci	struct v4l2_rect compose;
2418c2ecf20Sopenharmony_ci	struct v4l2_rect src_rect;
2428c2ecf20Sopenharmony_ci	v4l2_std_id std;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	unsigned int alpha;
2458c2ecf20Sopenharmony_ci};
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci#define vin_to_source(vin)		((vin)->parallel->subdev)
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci/* Debug */
2508c2ecf20Sopenharmony_ci#define vin_dbg(d, fmt, arg...)		dev_dbg(d->dev, fmt, ##arg)
2518c2ecf20Sopenharmony_ci#define vin_info(d, fmt, arg...)	dev_info(d->dev, fmt, ##arg)
2528c2ecf20Sopenharmony_ci#define vin_warn(d, fmt, arg...)	dev_warn(d->dev, fmt, ##arg)
2538c2ecf20Sopenharmony_ci#define vin_err(d, fmt, arg...)		dev_err(d->dev, fmt, ##arg)
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci/**
2568c2ecf20Sopenharmony_ci * struct rvin_group - VIN CSI2 group information
2578c2ecf20Sopenharmony_ci * @refcount:		number of VIN instances using the group
2588c2ecf20Sopenharmony_ci *
2598c2ecf20Sopenharmony_ci * @mdev:		media device which represents the group
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci * @lock:		protects the count, notifier, vin and csi members
2628c2ecf20Sopenharmony_ci * @count:		number of enabled VIN instances found in DT
2638c2ecf20Sopenharmony_ci * @notifier:		group notifier for CSI-2 async subdevices
2648c2ecf20Sopenharmony_ci * @vin:		VIN instances which are part of the group
2658c2ecf20Sopenharmony_ci * @csi:		array of pairs of fwnode and subdev pointers
2668c2ecf20Sopenharmony_ci *			to all CSI-2 subdevices.
2678c2ecf20Sopenharmony_ci */
2688c2ecf20Sopenharmony_cistruct rvin_group {
2698c2ecf20Sopenharmony_ci	struct kref refcount;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	struct media_device mdev;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	struct mutex lock;
2748c2ecf20Sopenharmony_ci	unsigned int count;
2758c2ecf20Sopenharmony_ci	struct v4l2_async_notifier notifier;
2768c2ecf20Sopenharmony_ci	struct rvin_dev *vin[RCAR_VIN_NUM];
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	struct {
2798c2ecf20Sopenharmony_ci		struct fwnode_handle *fwnode;
2808c2ecf20Sopenharmony_ci		struct v4l2_subdev *subdev;
2818c2ecf20Sopenharmony_ci	} csi[RVIN_CSI_MAX];
2828c2ecf20Sopenharmony_ci};
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ciint rvin_dma_register(struct rvin_dev *vin, int irq);
2858c2ecf20Sopenharmony_civoid rvin_dma_unregister(struct rvin_dev *vin);
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ciint rvin_v4l2_register(struct rvin_dev *vin);
2888c2ecf20Sopenharmony_civoid rvin_v4l2_unregister(struct rvin_dev *vin);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ciconst struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
2918c2ecf20Sopenharmony_ci						       u32 pixelformat);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci/* Cropping, composing and scaling */
2958c2ecf20Sopenharmony_civoid rvin_crop_scale_comp(struct rvin_dev *vin);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ciint rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
2988c2ecf20Sopenharmony_civoid rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci#endif
301