1*0c078e31SDaniel Almeida /* SPDX-License-Identifier: GPL-2.0 */
2*0c078e31SDaniel Almeida /*
3*0c078e31SDaniel Almeida * A virtual stateless device for stateless uAPI development purposes.
4*0c078e31SDaniel Almeida *
5*0c078e31SDaniel Almeida * This tool's objective is to help the development and testing of userspace
6*0c078e31SDaniel Almeida * applications that use the V4L2 stateless API to decode media.
7*0c078e31SDaniel Almeida *
8*0c078e31SDaniel Almeida * A userspace implementation can use visl to run a decoding loop even when no
9*0c078e31SDaniel Almeida * hardware is available or when the kernel uAPI for the codec has not been
10*0c078e31SDaniel Almeida * upstreamed yet. This can reveal bugs at an early stage.
11*0c078e31SDaniel Almeida *
12*0c078e31SDaniel Almeida * This driver can also trace the contents of the V4L2 controls submitted to it.
13*0c078e31SDaniel Almeida * It can also dump the contents of the vb2 buffers through a debugfs
14*0c078e31SDaniel Almeida * interface. This is in many ways similar to the tracing infrastructure
15*0c078e31SDaniel Almeida * available for other popular encode/decode APIs out there and can help develop
16*0c078e31SDaniel Almeida * a userspace application by using another (working) one as a reference.
17*0c078e31SDaniel Almeida *
18*0c078e31SDaniel Almeida * Note that no actual decoding of video frames is performed by visl. The V4L2
19*0c078e31SDaniel Almeida * test pattern generator is used to write various debug information to the
20*0c078e31SDaniel Almeida * capture buffers instead.
21*0c078e31SDaniel Almeida *
22*0c078e31SDaniel Almeida * Copyright (C) 2022 Collabora, Ltd.
23*0c078e31SDaniel Almeida *
24*0c078e31SDaniel Almeida * Based on the vim2m driver, that is:
25*0c078e31SDaniel Almeida *
26*0c078e31SDaniel Almeida * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
27*0c078e31SDaniel Almeida * Pawel Osciak, <pawel@osciak.com>
28*0c078e31SDaniel Almeida * Marek Szyprowski, <m.szyprowski@samsung.com>
29*0c078e31SDaniel Almeida *
30*0c078e31SDaniel Almeida * Based on the vicodec driver, that is:
31*0c078e31SDaniel Almeida *
32*0c078e31SDaniel Almeida * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
33*0c078e31SDaniel Almeida *
34*0c078e31SDaniel Almeida * Based on the Cedrus VPU driver, that is:
35*0c078e31SDaniel Almeida *
36*0c078e31SDaniel Almeida * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
37*0c078e31SDaniel Almeida * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
38*0c078e31SDaniel Almeida * Copyright (C) 2018 Bootlin
39*0c078e31SDaniel Almeida */
40*0c078e31SDaniel Almeida
41*0c078e31SDaniel Almeida #ifndef _VISL_H_
42*0c078e31SDaniel Almeida #define _VISL_H_
43*0c078e31SDaniel Almeida
44*0c078e31SDaniel Almeida #include <linux/debugfs.h>
45*0c078e31SDaniel Almeida #include <linux/list.h>
46*0c078e31SDaniel Almeida
47*0c078e31SDaniel Almeida #include <media/v4l2-ctrls.h>
48*0c078e31SDaniel Almeida #include <media/v4l2-device.h>
49*0c078e31SDaniel Almeida #include <media/tpg/v4l2-tpg.h>
50*0c078e31SDaniel Almeida
51*0c078e31SDaniel Almeida #define VISL_NAME "visl"
52*0c078e31SDaniel Almeida #define VISL_M2M_NQUEUES 2
53*0c078e31SDaniel Almeida
54*0c078e31SDaniel Almeida #define TPG_STR_BUF_SZ 2048
55*0c078e31SDaniel Almeida
56*0c078e31SDaniel Almeida extern unsigned int visl_transtime_ms;
57*0c078e31SDaniel Almeida
58*0c078e31SDaniel Almeida struct visl_ctrls {
59*0c078e31SDaniel Almeida const struct visl_ctrl_desc *ctrls;
60*0c078e31SDaniel Almeida unsigned int num_ctrls;
61*0c078e31SDaniel Almeida };
62*0c078e31SDaniel Almeida
63*0c078e31SDaniel Almeida struct visl_coded_format_desc {
64*0c078e31SDaniel Almeida u32 pixelformat;
65*0c078e31SDaniel Almeida struct v4l2_frmsize_stepwise frmsize;
66*0c078e31SDaniel Almeida const struct visl_ctrls *ctrls;
67*0c078e31SDaniel Almeida unsigned int num_decoded_fmts;
68*0c078e31SDaniel Almeida const u32 *decoded_fmts;
69*0c078e31SDaniel Almeida };
70*0c078e31SDaniel Almeida
71*0c078e31SDaniel Almeida extern const struct visl_coded_format_desc visl_coded_fmts[];
72*0c078e31SDaniel Almeida extern const size_t num_coded_fmts;
73*0c078e31SDaniel Almeida
74*0c078e31SDaniel Almeida enum {
75*0c078e31SDaniel Almeida V4L2_M2M_SRC = 0,
76*0c078e31SDaniel Almeida V4L2_M2M_DST = 1,
77*0c078e31SDaniel Almeida };
78*0c078e31SDaniel Almeida
79*0c078e31SDaniel Almeida extern unsigned int visl_debug;
80*0c078e31SDaniel Almeida #define dprintk(dev, fmt, arg...) \
81*0c078e31SDaniel Almeida v4l2_dbg(1, visl_debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
82*0c078e31SDaniel Almeida
83*0c078e31SDaniel Almeida extern int visl_dprintk_frame_start;
84*0c078e31SDaniel Almeida extern unsigned int visl_dprintk_nframes;
85*0c078e31SDaniel Almeida extern bool keep_bitstream_buffers;
86*0c078e31SDaniel Almeida extern int bitstream_trace_frame_start;
87*0c078e31SDaniel Almeida extern unsigned int bitstream_trace_nframes;
88*0c078e31SDaniel Almeida
89*0c078e31SDaniel Almeida #define frame_dprintk(dev, current, fmt, arg...) \
90*0c078e31SDaniel Almeida do { \
91*0c078e31SDaniel Almeida if (visl_dprintk_frame_start > -1 && \
92*0c078e31SDaniel Almeida (current) >= visl_dprintk_frame_start && \
93*0c078e31SDaniel Almeida (current) < visl_dprintk_frame_start + visl_dprintk_nframes) \
94*0c078e31SDaniel Almeida dprintk(dev, fmt, ## arg); \
95*0c078e31SDaniel Almeida } while (0) \
96*0c078e31SDaniel Almeida
97*0c078e31SDaniel Almeida struct visl_q_data {
98*0c078e31SDaniel Almeida unsigned int sequence;
99*0c078e31SDaniel Almeida };
100*0c078e31SDaniel Almeida
101*0c078e31SDaniel Almeida struct visl_dev {
102*0c078e31SDaniel Almeida struct v4l2_device v4l2_dev;
103*0c078e31SDaniel Almeida struct video_device vfd;
104*0c078e31SDaniel Almeida #ifdef CONFIG_MEDIA_CONTROLLER
105*0c078e31SDaniel Almeida struct media_device mdev;
106*0c078e31SDaniel Almeida #endif
107*0c078e31SDaniel Almeida
108*0c078e31SDaniel Almeida struct mutex dev_mutex;
109*0c078e31SDaniel Almeida
110*0c078e31SDaniel Almeida struct v4l2_m2m_dev *m2m_dev;
111*0c078e31SDaniel Almeida
112*0c078e31SDaniel Almeida #ifdef CONFIG_VISL_DEBUGFS
113*0c078e31SDaniel Almeida struct dentry *debugfs_root;
114*0c078e31SDaniel Almeida struct dentry *bitstream_debugfs;
115*0c078e31SDaniel Almeida struct list_head bitstream_blobs;
116*0c078e31SDaniel Almeida
117*0c078e31SDaniel Almeida /* Protects the "blob" list */
118*0c078e31SDaniel Almeida struct mutex bitstream_lock;
119*0c078e31SDaniel Almeida #endif
120*0c078e31SDaniel Almeida };
121*0c078e31SDaniel Almeida
122*0c078e31SDaniel Almeida enum visl_codec {
123*0c078e31SDaniel Almeida VISL_CODEC_NONE,
124*0c078e31SDaniel Almeida VISL_CODEC_FWHT,
125*0c078e31SDaniel Almeida VISL_CODEC_MPEG2,
126*0c078e31SDaniel Almeida VISL_CODEC_VP8,
127*0c078e31SDaniel Almeida VISL_CODEC_VP9,
128*0c078e31SDaniel Almeida VISL_CODEC_H264,
129*0c078e31SDaniel Almeida VISL_CODEC_HEVC,
130*0c078e31SDaniel Almeida };
131*0c078e31SDaniel Almeida
132*0c078e31SDaniel Almeida struct visl_blob {
133*0c078e31SDaniel Almeida struct list_head list;
134*0c078e31SDaniel Almeida struct dentry *dentry;
135*0c078e31SDaniel Almeida struct debugfs_blob_wrapper blob;
136*0c078e31SDaniel Almeida };
137*0c078e31SDaniel Almeida
138*0c078e31SDaniel Almeida struct visl_ctx {
139*0c078e31SDaniel Almeida struct v4l2_fh fh;
140*0c078e31SDaniel Almeida struct visl_dev *dev;
141*0c078e31SDaniel Almeida struct v4l2_ctrl_handler hdl;
142*0c078e31SDaniel Almeida
143*0c078e31SDaniel Almeida struct mutex vb_mutex;
144*0c078e31SDaniel Almeida
145*0c078e31SDaniel Almeida struct visl_q_data q_data[VISL_M2M_NQUEUES];
146*0c078e31SDaniel Almeida enum visl_codec current_codec;
147*0c078e31SDaniel Almeida
148*0c078e31SDaniel Almeida const struct visl_coded_format_desc *coded_format_desc;
149*0c078e31SDaniel Almeida
150*0c078e31SDaniel Almeida struct v4l2_format coded_fmt;
151*0c078e31SDaniel Almeida struct v4l2_format decoded_fmt;
152*0c078e31SDaniel Almeida
153*0c078e31SDaniel Almeida struct tpg_data tpg;
154*0c078e31SDaniel Almeida u64 capture_streamon_jiffies;
155*0c078e31SDaniel Almeida char *tpg_str_buf;
156*0c078e31SDaniel Almeida };
157*0c078e31SDaniel Almeida
158*0c078e31SDaniel Almeida struct visl_ctrl_desc {
159*0c078e31SDaniel Almeida struct v4l2_ctrl_config cfg;
160*0c078e31SDaniel Almeida };
161*0c078e31SDaniel Almeida
visl_file_to_ctx(struct file * file)162*0c078e31SDaniel Almeida static inline struct visl_ctx *visl_file_to_ctx(struct file *file)
163*0c078e31SDaniel Almeida {
164*0c078e31SDaniel Almeida return container_of(file->private_data, struct visl_ctx, fh);
165*0c078e31SDaniel Almeida }
166*0c078e31SDaniel Almeida
visl_v4l2fh_to_ctx(struct v4l2_fh * v4l2_fh)167*0c078e31SDaniel Almeida static inline struct visl_ctx *visl_v4l2fh_to_ctx(struct v4l2_fh *v4l2_fh)
168*0c078e31SDaniel Almeida {
169*0c078e31SDaniel Almeida return container_of(v4l2_fh, struct visl_ctx, fh);
170*0c078e31SDaniel Almeida }
171*0c078e31SDaniel Almeida
172*0c078e31SDaniel Almeida void *visl_find_control_data(struct visl_ctx *ctx, u32 id);
173*0c078e31SDaniel Almeida struct v4l2_ctrl *visl_find_control(struct visl_ctx *ctx, u32 id);
174*0c078e31SDaniel Almeida u32 visl_control_num_elems(struct visl_ctx *ctx, u32 id);
175*0c078e31SDaniel Almeida
176*0c078e31SDaniel Almeida #endif /* _VISL_H_ */
177