162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * A virtual stateless device for stateless uAPI development purposes.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This tool's objective is to help the development and testing of userspace
662306a36Sopenharmony_ci * applications that use the V4L2 stateless API to decode media.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * A userspace implementation can use visl to run a decoding loop even when no
962306a36Sopenharmony_ci * hardware is available or when the kernel uAPI for the codec has not been
1062306a36Sopenharmony_ci * upstreamed yet. This can reveal bugs at an early stage.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * This driver can also trace the contents of the V4L2 controls submitted to it.
1362306a36Sopenharmony_ci * It can also dump the contents of the vb2 buffers through a debugfs
1462306a36Sopenharmony_ci * interface. This is in many ways similar to the tracing infrastructure
1562306a36Sopenharmony_ci * available for other popular encode/decode APIs out there and can help develop
1662306a36Sopenharmony_ci * a userspace application by using another (working) one as a reference.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * Note that no actual decoding of video frames is performed by visl. The V4L2
1962306a36Sopenharmony_ci * test pattern generator is used to write various debug information to the
2062306a36Sopenharmony_ci * capture buffers instead.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Copyright (C) 2022 Collabora, Ltd.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Based on the vim2m driver, that is:
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
2762306a36Sopenharmony_ci * Pawel Osciak, <pawel@osciak.com>
2862306a36Sopenharmony_ci * Marek Szyprowski, <m.szyprowski@samsung.com>
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * Based on the vicodec driver, that is:
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Based on the Cedrus VPU driver, that is:
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
3762306a36Sopenharmony_ci * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
3862306a36Sopenharmony_ci * Copyright (C) 2018 Bootlin
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#ifndef _VISL_H_
4262306a36Sopenharmony_ci#define _VISL_H_
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#include <linux/debugfs.h>
4562306a36Sopenharmony_ci#include <linux/list.h>
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#include <media/v4l2-ctrls.h>
4862306a36Sopenharmony_ci#include <media/v4l2-device.h>
4962306a36Sopenharmony_ci#include <media/tpg/v4l2-tpg.h>
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define VISL_NAME		"visl"
5262306a36Sopenharmony_ci#define VISL_M2M_NQUEUES	2
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define TPG_STR_BUF_SZ		2048
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ciextern unsigned int visl_transtime_ms;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct visl_ctrls {
5962306a36Sopenharmony_ci	const struct visl_ctrl_desc *ctrls;
6062306a36Sopenharmony_ci	unsigned int num_ctrls;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct visl_coded_format_desc {
6462306a36Sopenharmony_ci	u32 pixelformat;
6562306a36Sopenharmony_ci	struct v4l2_frmsize_stepwise frmsize;
6662306a36Sopenharmony_ci	const struct visl_ctrls *ctrls;
6762306a36Sopenharmony_ci	unsigned int num_decoded_fmts;
6862306a36Sopenharmony_ci	const u32 *decoded_fmts;
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciextern const struct visl_coded_format_desc visl_coded_fmts[];
7262306a36Sopenharmony_ciextern const size_t num_coded_fmts;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cienum {
7562306a36Sopenharmony_ci	V4L2_M2M_SRC = 0,
7662306a36Sopenharmony_ci	V4L2_M2M_DST = 1,
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ciextern unsigned int visl_debug;
8062306a36Sopenharmony_ci#define dprintk(dev, fmt, arg...) \
8162306a36Sopenharmony_ci	v4l2_dbg(1, visl_debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciextern int visl_dprintk_frame_start;
8462306a36Sopenharmony_ciextern unsigned int visl_dprintk_nframes;
8562306a36Sopenharmony_ciextern bool keep_bitstream_buffers;
8662306a36Sopenharmony_ciextern int bitstream_trace_frame_start;
8762306a36Sopenharmony_ciextern unsigned int bitstream_trace_nframes;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#define frame_dprintk(dev, current, fmt, arg...) \
9062306a36Sopenharmony_ci	do { \
9162306a36Sopenharmony_ci		if (visl_dprintk_frame_start > -1 && \
9262306a36Sopenharmony_ci		    (current) >= visl_dprintk_frame_start && \
9362306a36Sopenharmony_ci		    (current) < visl_dprintk_frame_start + visl_dprintk_nframes) \
9462306a36Sopenharmony_ci			dprintk(dev, fmt, ## arg); \
9562306a36Sopenharmony_ci	} while (0) \
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistruct visl_q_data {
9862306a36Sopenharmony_ci	unsigned int		sequence;
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistruct visl_dev {
10262306a36Sopenharmony_ci	struct v4l2_device	v4l2_dev;
10362306a36Sopenharmony_ci	struct video_device	vfd;
10462306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER
10562306a36Sopenharmony_ci	struct media_device	mdev;
10662306a36Sopenharmony_ci#endif
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	struct mutex		dev_mutex;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	struct v4l2_m2m_dev	*m2m_dev;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#ifdef CONFIG_VISL_DEBUGFS
11362306a36Sopenharmony_ci	struct dentry		*debugfs_root;
11462306a36Sopenharmony_ci	struct dentry		*bitstream_debugfs;
11562306a36Sopenharmony_ci	struct list_head	bitstream_blobs;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	/* Protects the "blob" list */
11862306a36Sopenharmony_ci	struct mutex		bitstream_lock;
11962306a36Sopenharmony_ci#endif
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cienum visl_codec {
12362306a36Sopenharmony_ci	VISL_CODEC_NONE,
12462306a36Sopenharmony_ci	VISL_CODEC_FWHT,
12562306a36Sopenharmony_ci	VISL_CODEC_MPEG2,
12662306a36Sopenharmony_ci	VISL_CODEC_VP8,
12762306a36Sopenharmony_ci	VISL_CODEC_VP9,
12862306a36Sopenharmony_ci	VISL_CODEC_H264,
12962306a36Sopenharmony_ci	VISL_CODEC_HEVC,
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistruct visl_blob {
13362306a36Sopenharmony_ci	struct list_head list;
13462306a36Sopenharmony_ci	struct dentry *dentry;
13562306a36Sopenharmony_ci	struct debugfs_blob_wrapper blob;
13662306a36Sopenharmony_ci};
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistruct visl_ctx {
13962306a36Sopenharmony_ci	struct v4l2_fh		fh;
14062306a36Sopenharmony_ci	struct visl_dev	*dev;
14162306a36Sopenharmony_ci	struct v4l2_ctrl_handler hdl;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	struct mutex		vb_mutex;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	struct visl_q_data	q_data[VISL_M2M_NQUEUES];
14662306a36Sopenharmony_ci	enum   visl_codec	current_codec;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	const struct visl_coded_format_desc *coded_format_desc;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	struct v4l2_format	coded_fmt;
15162306a36Sopenharmony_ci	struct v4l2_format	decoded_fmt;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	struct tpg_data		tpg;
15462306a36Sopenharmony_ci	u64			capture_streamon_jiffies;
15562306a36Sopenharmony_ci	char			*tpg_str_buf;
15662306a36Sopenharmony_ci};
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistruct visl_ctrl_desc {
15962306a36Sopenharmony_ci	struct v4l2_ctrl_config cfg;
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic inline struct visl_ctx *visl_file_to_ctx(struct file *file)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	return container_of(file->private_data, struct visl_ctx, fh);
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic inline struct visl_ctx *visl_v4l2fh_to_ctx(struct v4l2_fh *v4l2_fh)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	return container_of(v4l2_fh, struct visl_ctx, fh);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_civoid *visl_find_control_data(struct visl_ctx *ctx, u32 id);
17362306a36Sopenharmony_cistruct v4l2_ctrl *visl_find_control(struct visl_ctx *ctx, u32 id);
17462306a36Sopenharmony_ciu32 visl_control_num_elems(struct visl_ctx *ctx, u32 id);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci#endif /* _VISL_H_ */
177