1 // SPDX-License-Identifier: GPL-2.0+
2 /* Capture for virtio video device.
4 * Copyright 2021 OpenSynergy GmbH.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <linux/version.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-ioctl.h>
24 #include "virtio_video.h"
26 static int virtio_video_cam_start_streaming(struct vb2_queue *vq,
29 struct virtio_video_stream *stream = vb2_get_drv_priv(vq);
31 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
34 if (virtio_video_state(stream) >= STREAM_STATE_INIT)
35 virtio_video_state_update(stream, STREAM_STATE_RUNNING);
40 static void virtio_video_cam_stop_streaming(struct vb2_queue *vq)
42 struct virtio_video_stream *stream = vb2_get_drv_priv(vq);
44 virtio_video_queue_release_buffers(stream,
45 VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT);
47 vb2_wait_for_all_buffers(vq);
50 static const struct vb2_ops virtio_video_cam_qops = {
51 .queue_setup = virtio_video_queue_setup,
52 .buf_init = virtio_video_buf_init,
53 .buf_cleanup = virtio_video_buf_cleanup,
54 .buf_queue = virtio_video_buf_queue,
55 .start_streaming = virtio_video_cam_start_streaming,
56 .stop_streaming = virtio_video_cam_stop_streaming,
57 .wait_prepare = vb2_ops_wait_prepare,
58 .wait_finish = vb2_ops_wait_finish,
61 static int virtio_video_cam_g_ctrl(struct v4l2_ctrl *ctrl)
64 struct virtio_video_stream *stream = ctrl2stream(ctrl);
66 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
70 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
71 if (virtio_video_state(stream) >=
72 STREAM_STATE_DYNAMIC_RES_CHANGE)
73 ctrl->val = stream->out_info.min_buffers;
85 static const struct v4l2_ctrl_ops virtio_video_cam_ctrl_ops = {
86 .g_volatile_ctrl = virtio_video_cam_g_ctrl,
89 int virtio_video_cam_init_ctrls(struct virtio_video_stream *stream)
91 struct v4l2_ctrl *ctrl;
93 v4l2_ctrl_handler_init(&stream->ctrl_handler, 2);
95 ctrl = v4l2_ctrl_new_std(&stream->ctrl_handler,
96 &virtio_video_cam_ctrl_ops,
97 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
98 MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP,
102 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
104 if (stream->ctrl_handler.error)
105 return stream->ctrl_handler.error;
107 v4l2_ctrl_handler_setup(&stream->ctrl_handler);
112 int virtio_video_cam_init_queues(void *priv, struct vb2_queue *src_vq,
113 struct vb2_queue *dst_vq)
115 struct virtio_video_stream *stream = priv;
116 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
117 struct device *dev = vvd->v4l2_dev.dev;
118 int vq_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
120 if (!vvd->is_mplane_cam)
121 vq_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
123 dst_vq->type = vq_type;
124 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
125 dst_vq->drv_priv = stream;
126 dst_vq->buf_struct_size = sizeof(struct virtio_video_buffer);
127 dst_vq->ops = &virtio_video_cam_qops;
128 dst_vq->mem_ops = virtio_video_mem_ops(vvd);
129 dst_vq->min_buffers_needed = stream->out_info.min_buffers;
130 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
131 dst_vq->lock = &stream->vq_mutex;
132 dst_vq->gfp_flags = virtio_video_gfp_flags(vvd);
135 return vb2_queue_init(dst_vq);
138 int virtio_video_cam_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
140 struct virtio_video_stream *stream = file2stream(file);
141 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
142 struct v4l2_format *fmt_try = f;
143 struct v4l2_format fmt_mp = { 0 };
146 if (!vvd->is_mplane_cam) {
147 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
150 fmt_mp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
153 virtio_video_pix_fmt_sp2mp(&f->fmt.pix, &fmt_try->fmt.pix_mp);
156 ret = virtio_video_try_fmt(stream, fmt_try);
160 if (!vvd->is_mplane_cam) {
161 if (fmt_try->fmt.pix_mp.num_planes != 1)
164 virtio_video_pix_fmt_mp2sp(&fmt_try->fmt.pix_mp, &f->fmt.pix);
170 static int virtio_video_cam_enum_fmt_vid_cap(struct file *file, void *fh,
171 struct v4l2_fmtdesc *f)
173 struct virtio_video_stream *stream = file2stream(file);
174 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
175 struct video_format *fmt;
178 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
181 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
182 f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
185 if (f->index >= vvd->num_output_fmts)
188 list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) {
189 if (f->index == idx) {
190 f->pixelformat = fmt->desc.format;
198 static int virtio_video_cam_g_fmt(struct file *file, void *fh,
199 struct v4l2_format *f)
201 struct virtio_video_stream *stream = file2stream(file);
202 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
203 struct v4l2_format fmt_mp = { 0 };
204 struct v4l2_format *fmt_get = f;
207 if (!vvd->is_mplane_cam) {
208 fmt_mp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
212 ret = virtio_video_g_fmt(file, fh, fmt_get);
216 if (virtio_video_state(stream) == STREAM_STATE_IDLE)
217 virtio_video_state_update(stream, STREAM_STATE_INIT);
219 if (!vvd->is_mplane_cam) {
220 if (fmt_get->fmt.pix_mp.num_planes != 1)
223 virtio_video_pix_fmt_mp2sp(&fmt_get->fmt.pix_mp, &f->fmt.pix);
229 static int virtio_video_cam_s_fmt(struct file *file, void *fh,
230 struct v4l2_format *f)
233 struct virtio_video_stream *stream = file2stream(file);
234 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
235 struct v4l2_format fmt_mp = { 0 };
236 struct v4l2_format *fmt_set = f;
238 if (!vvd->is_mplane_cam) {
239 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
242 fmt_mp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
245 virtio_video_pix_fmt_sp2mp(&f->fmt.pix, &fmt_set->fmt.pix_mp);
248 ret = virtio_video_s_fmt(file, fh, fmt_set);
252 if (virtio_video_state(stream) == STREAM_STATE_IDLE)
253 virtio_video_state_update(stream, STREAM_STATE_INIT);
255 if (!vvd->is_mplane_cam) {
256 if (fmt_set->fmt.pix_mp.num_planes != 1)
259 virtio_video_pix_fmt_mp2sp(&fmt_set->fmt.pix_mp, &f->fmt.pix);
265 static int virtio_video_cam_s_selection(struct file *file, void *fh,
266 struct v4l2_selection *sel)
268 struct virtio_video_stream *stream = file2stream(file);
269 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
272 if (V4L2_TYPE_IS_OUTPUT(sel->type))
275 switch (sel->target) {
276 case V4L2_SEL_TGT_CROP:
277 stream->out_info.crop.top = sel->r.top;
278 stream->out_info.crop.left = sel->r.left;
279 stream->out_info.crop.width = sel->r.width;
280 stream->out_info.crop.height = sel->r.height;
281 v4l2_info(&vvd->v4l2_dev,
282 "Set : top:%d, left:%d, w:%d, h:%d\n",
283 sel->r.top, sel->r.left, sel->r.width, sel->r.height);
289 ret = virtio_video_cmd_set_params(vvd, stream, &stream->out_info,
290 VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT);
294 ret = virtio_video_cmd_get_params(vvd, stream,
295 VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT);
299 static const struct v4l2_ioctl_ops virtio_video_cam_ioctl_ops = {
300 .vidioc_querycap = virtio_video_querycap,
302 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0))
303 .vidioc_enum_fmt_vid_cap_mplane = virtio_video_cam_enum_fmt_vid_cap,
305 .vidioc_try_fmt_vid_cap_mplane = virtio_video_cam_try_fmt,
306 .vidioc_g_fmt_vid_cap_mplane = virtio_video_cam_g_fmt,
307 .vidioc_s_fmt_vid_cap_mplane = virtio_video_cam_s_fmt,
309 .vidioc_enum_fmt_vid_cap = virtio_video_cam_enum_fmt_vid_cap,
310 .vidioc_try_fmt_vid_cap = virtio_video_cam_try_fmt,
311 .vidioc_g_fmt_vid_cap = virtio_video_cam_g_fmt,
312 .vidioc_s_fmt_vid_cap = virtio_video_cam_s_fmt,
314 .vidioc_g_selection = virtio_video_g_selection,
315 .vidioc_s_selection = virtio_video_cam_s_selection,
317 .vidioc_enum_frameintervals = virtio_video_enum_framemintervals,
318 .vidioc_enum_framesizes = virtio_video_enum_framesizes,
320 .vidioc_reqbufs = virtio_video_reqbufs,
321 .vidioc_querybuf = vb2_ioctl_querybuf,
322 .vidioc_qbuf = virtio_video_qbuf,
323 .vidioc_dqbuf = virtio_video_dqbuf,
324 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
325 .vidioc_create_bufs = vb2_ioctl_create_bufs,
326 .vidioc_expbuf = vb2_ioctl_expbuf,
328 .vidioc_streamon = vb2_ioctl_streamon,
329 .vidioc_streamoff = vb2_ioctl_streamoff,
331 .vidioc_subscribe_event = virtio_video_subscribe_event,
332 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
335 void *virtio_video_cam_get_fmt_list(struct virtio_video_device *vvd)
337 return &vvd->output_fmt_list;
340 static struct virtio_video_device_ops virtio_video_cam_ops = {
341 .init_ctrls = virtio_video_cam_init_ctrls,
342 .init_queues = virtio_video_cam_init_queues,
343 .get_fmt_list = virtio_video_cam_get_fmt_list,
346 int virtio_video_cam_init(struct virtio_video_device *vvd)
349 struct video_device *vd = &vvd->video_dev;
351 vd->ioctl_ops = &virtio_video_cam_ioctl_ops;
352 vvd->ops = &virtio_video_cam_ops;
354 num = strscpy(vd->name, "camera", sizeof(vd->name));