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