162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * ispvideo.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * TI OMAP3 ISP - Generic video node
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2009-2010 Nokia Corporation
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
1062306a36Sopenharmony_ci *	     Sakari Ailus <sakari.ailus@iki.fi>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#ifndef OMAP3_ISP_VIDEO_H
1462306a36Sopenharmony_ci#define OMAP3_ISP_VIDEO_H
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/v4l2-mediabus.h>
1762306a36Sopenharmony_ci#include <media/media-entity.h>
1862306a36Sopenharmony_ci#include <media/v4l2-dev.h>
1962306a36Sopenharmony_ci#include <media/v4l2-fh.h>
2062306a36Sopenharmony_ci#include <media/videobuf2-v4l2.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define ISP_VIDEO_DRIVER_NAME		"ispvideo"
2362306a36Sopenharmony_ci#define ISP_VIDEO_DRIVER_VERSION	"0.0.2"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct isp_device;
2662306a36Sopenharmony_cistruct isp_video;
2762306a36Sopenharmony_cistruct v4l2_mbus_framefmt;
2862306a36Sopenharmony_cistruct v4l2_pix_format;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * struct isp_format_info - ISP media bus format information
3262306a36Sopenharmony_ci * @code: V4L2 media bus format code
3362306a36Sopenharmony_ci * @truncated: V4L2 media bus format code for the same format truncated to 10
3462306a36Sopenharmony_ci *	bits. Identical to @code if the format is 10 bits wide or less.
3562306a36Sopenharmony_ci * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
3662306a36Sopenharmony_ci *	format. Identical to @code if the format is not DPCM compressed.
3762306a36Sopenharmony_ci * @flavor: V4L2 media bus format code for the same pixel layout but
3862306a36Sopenharmony_ci *	shifted to be 8 bits per pixel. =0 if format is not shiftable.
3962306a36Sopenharmony_ci * @pixelformat: V4L2 pixel format FCC identifier
4062306a36Sopenharmony_ci * @width: Bits per pixel (when transferred over a bus)
4162306a36Sopenharmony_ci * @bpp: Bytes per pixel (when stored in memory)
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_cistruct isp_format_info {
4462306a36Sopenharmony_ci	u32 code;
4562306a36Sopenharmony_ci	u32 truncated;
4662306a36Sopenharmony_ci	u32 uncompressed;
4762306a36Sopenharmony_ci	u32 flavor;
4862306a36Sopenharmony_ci	u32 pixelformat;
4962306a36Sopenharmony_ci	unsigned int width;
5062306a36Sopenharmony_ci	unsigned int bpp;
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cienum isp_pipeline_stream_state {
5462306a36Sopenharmony_ci	ISP_PIPELINE_STREAM_STOPPED = 0,
5562306a36Sopenharmony_ci	ISP_PIPELINE_STREAM_CONTINUOUS = 1,
5662306a36Sopenharmony_ci	ISP_PIPELINE_STREAM_SINGLESHOT = 2,
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cienum isp_pipeline_state {
6062306a36Sopenharmony_ci	/* The stream has been started on the input video node. */
6162306a36Sopenharmony_ci	ISP_PIPELINE_STREAM_INPUT = 1,
6262306a36Sopenharmony_ci	/* The stream has been started on the output video node. */
6362306a36Sopenharmony_ci	ISP_PIPELINE_STREAM_OUTPUT = 2,
6462306a36Sopenharmony_ci	/* At least one buffer is queued on the input video node. */
6562306a36Sopenharmony_ci	ISP_PIPELINE_QUEUE_INPUT = 4,
6662306a36Sopenharmony_ci	/* At least one buffer is queued on the output video node. */
6762306a36Sopenharmony_ci	ISP_PIPELINE_QUEUE_OUTPUT = 8,
6862306a36Sopenharmony_ci	/* The input entity is idle, ready to be started. */
6962306a36Sopenharmony_ci	ISP_PIPELINE_IDLE_INPUT = 16,
7062306a36Sopenharmony_ci	/* The output entity is idle, ready to be started. */
7162306a36Sopenharmony_ci	ISP_PIPELINE_IDLE_OUTPUT = 32,
7262306a36Sopenharmony_ci	/* The pipeline is currently streaming. */
7362306a36Sopenharmony_ci	ISP_PIPELINE_STREAM = 64,
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/*
7762306a36Sopenharmony_ci * struct isp_pipeline - An ISP hardware pipeline
7862306a36Sopenharmony_ci * @field: The field being processed by the pipeline
7962306a36Sopenharmony_ci * @error: A hardware error occurred during capture
8062306a36Sopenharmony_ci * @ent_enum: Entities in the pipeline
8162306a36Sopenharmony_ci */
8262306a36Sopenharmony_cistruct isp_pipeline {
8362306a36Sopenharmony_ci	struct media_pipeline pipe;
8462306a36Sopenharmony_ci	spinlock_t lock;		/* Pipeline state and queue flags */
8562306a36Sopenharmony_ci	unsigned int state;
8662306a36Sopenharmony_ci	enum isp_pipeline_stream_state stream_state;
8762306a36Sopenharmony_ci	struct isp_video *input;
8862306a36Sopenharmony_ci	struct isp_video *output;
8962306a36Sopenharmony_ci	struct media_entity_enum ent_enum;
9062306a36Sopenharmony_ci	unsigned long l3_ick;
9162306a36Sopenharmony_ci	unsigned int max_rate;
9262306a36Sopenharmony_ci	enum v4l2_field field;
9362306a36Sopenharmony_ci	atomic_t frame_number;
9462306a36Sopenharmony_ci	bool do_propagation; /* of frame number */
9562306a36Sopenharmony_ci	bool error;
9662306a36Sopenharmony_ci	struct v4l2_fract max_timeperframe;
9762306a36Sopenharmony_ci	struct v4l2_subdev *external;
9862306a36Sopenharmony_ci	unsigned int external_rate;
9962306a36Sopenharmony_ci	unsigned int external_width;
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic inline struct isp_pipeline *to_isp_pipeline(struct media_entity *entity)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	struct media_pipeline *pipe = media_entity_pipeline(entity);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	if (!pipe)
10762306a36Sopenharmony_ci		return NULL;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	return container_of(pipe, struct isp_pipeline, pipe);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic inline int isp_pipeline_ready(struct isp_pipeline *pipe)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	return pipe->state == (ISP_PIPELINE_STREAM_INPUT |
11562306a36Sopenharmony_ci			       ISP_PIPELINE_STREAM_OUTPUT |
11662306a36Sopenharmony_ci			       ISP_PIPELINE_QUEUE_INPUT |
11762306a36Sopenharmony_ci			       ISP_PIPELINE_QUEUE_OUTPUT |
11862306a36Sopenharmony_ci			       ISP_PIPELINE_IDLE_INPUT |
11962306a36Sopenharmony_ci			       ISP_PIPELINE_IDLE_OUTPUT);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/**
12362306a36Sopenharmony_ci * struct isp_buffer - ISP video buffer
12462306a36Sopenharmony_ci * @vb: videobuf2 buffer
12562306a36Sopenharmony_ci * @irqlist: List head for insertion into IRQ queue
12662306a36Sopenharmony_ci * @dma: DMA address
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_cistruct isp_buffer {
12962306a36Sopenharmony_ci	struct vb2_v4l2_buffer vb;
13062306a36Sopenharmony_ci	struct list_head irqlist;
13162306a36Sopenharmony_ci	dma_addr_t dma;
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#define to_isp_buffer(buf)	container_of(buf, struct isp_buffer, vb)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cienum isp_video_dmaqueue_flags {
13762306a36Sopenharmony_ci	/* Set if DMA queue becomes empty when ISP_PIPELINE_STREAM_CONTINUOUS */
13862306a36Sopenharmony_ci	ISP_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0),
13962306a36Sopenharmony_ci	/* Set when queuing buffer to an empty DMA queue */
14062306a36Sopenharmony_ci	ISP_VIDEO_DMAQUEUE_QUEUED = (1 << 1),
14162306a36Sopenharmony_ci};
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci#define isp_video_dmaqueue_flags_clr(video)	\
14462306a36Sopenharmony_ci			({ (video)->dmaqueue_flags = 0; })
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/*
14762306a36Sopenharmony_ci * struct isp_video_operations - ISP video operations
14862306a36Sopenharmony_ci * @queue:	Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
14962306a36Sopenharmony_ci *		if there was no buffer previously queued.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistruct isp_video_operations {
15262306a36Sopenharmony_ci	int(*queue)(struct isp_video *video, struct isp_buffer *buffer);
15362306a36Sopenharmony_ci};
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistruct isp_video {
15662306a36Sopenharmony_ci	struct video_device video;
15762306a36Sopenharmony_ci	enum v4l2_buf_type type;
15862306a36Sopenharmony_ci	struct media_pad pad;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	struct mutex mutex;		/* format and crop settings */
16162306a36Sopenharmony_ci	atomic_t active;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	struct isp_device *isp;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	unsigned int capture_mem;
16662306a36Sopenharmony_ci	unsigned int bpl_alignment;	/* alignment value */
16762306a36Sopenharmony_ci	unsigned int bpl_zero_padding;	/* whether the alignment is optional */
16862306a36Sopenharmony_ci	unsigned int bpl_max;		/* maximum bytes per line value */
16962306a36Sopenharmony_ci	unsigned int bpl_value;		/* bytes per line value */
17062306a36Sopenharmony_ci	unsigned int bpl_padding;	/* padding at end of line */
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	/* Pipeline state */
17362306a36Sopenharmony_ci	struct isp_pipeline pipe;
17462306a36Sopenharmony_ci	struct mutex stream_lock;	/* pipeline and stream states */
17562306a36Sopenharmony_ci	bool error;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	/* Video buffers queue */
17862306a36Sopenharmony_ci	struct vb2_queue *queue;
17962306a36Sopenharmony_ci	struct mutex queue_lock;	/* protects the queue */
18062306a36Sopenharmony_ci	spinlock_t irqlock;		/* protects dmaqueue */
18162306a36Sopenharmony_ci	struct list_head dmaqueue;
18262306a36Sopenharmony_ci	enum isp_video_dmaqueue_flags dmaqueue_flags;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	const struct isp_video_operations *ops;
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci#define to_isp_video(vdev)	container_of(vdev, struct isp_video, video)
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct isp_video_fh {
19062306a36Sopenharmony_ci	struct v4l2_fh vfh;
19162306a36Sopenharmony_ci	struct isp_video *video;
19262306a36Sopenharmony_ci	struct vb2_queue queue;
19362306a36Sopenharmony_ci	struct v4l2_format format;
19462306a36Sopenharmony_ci	struct v4l2_fract timeperframe;
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci#define to_isp_video_fh(fh)	container_of(fh, struct isp_video_fh, vfh)
19862306a36Sopenharmony_ci#define isp_video_queue_to_isp_video_fh(q) \
19962306a36Sopenharmony_ci				container_of(q, struct isp_video_fh, queue)
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ciint omap3isp_video_init(struct isp_video *video, const char *name);
20262306a36Sopenharmony_civoid omap3isp_video_cleanup(struct isp_video *video);
20362306a36Sopenharmony_ciint omap3isp_video_register(struct isp_video *video,
20462306a36Sopenharmony_ci			    struct v4l2_device *vdev);
20562306a36Sopenharmony_civoid omap3isp_video_unregister(struct isp_video *video);
20662306a36Sopenharmony_cistruct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video);
20762306a36Sopenharmony_civoid omap3isp_video_cancel_stream(struct isp_video *video);
20862306a36Sopenharmony_civoid omap3isp_video_resume(struct isp_video *video, int continuous);
20962306a36Sopenharmony_cistruct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ciconst struct isp_format_info *
21262306a36Sopenharmony_ciomap3isp_video_format_info(u32 code);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci#endif /* OMAP3_ISP_VIDEO_H */
215