301a9a161a37c2ef8db3753970349a2299c40fb2
[AGL/meta-agl-devel.git] / meta-egvirt / recipes-kernel / kernel-module-virtio-video / files / virtio_video_dec.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Decoder for virtio video device.
3  *
4  * Copyright 2020 OpenSynergy GmbH.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include <linux/version.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-ioctl.h>
23
24 #include "virtio_video.h"
25
26 static int virtio_video_dec_start_streaming(struct vb2_queue *vq,
27                                             unsigned int count)
28 {
29         struct virtio_video_stream *stream = vb2_get_drv_priv(vq);
30
31         if (virtio_video_state(stream) == STREAM_STATE_ERROR)
32                 return -EIO;
33
34         if (!V4L2_TYPE_IS_OUTPUT(vq->type) &&
35             virtio_video_state(stream) >= STREAM_STATE_INIT)
36                 virtio_video_state_update(stream, STREAM_STATE_RUNNING);
37
38         return 0;
39 }
40
41 static void virtio_video_dec_stop_streaming(struct vb2_queue *vq)
42 {
43         int queue_type;
44         struct virtio_video_stream *stream = vb2_get_drv_priv(vq);
45
46         if (V4L2_TYPE_IS_OUTPUT(vq->type))
47                 queue_type = VIRTIO_VIDEO_QUEUE_TYPE_INPUT;
48         else
49                 queue_type = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT;
50
51         virtio_video_queue_release_buffers(stream, queue_type);
52         vb2_wait_for_all_buffers(vq);
53 }
54
55 static const struct vb2_ops virtio_video_dec_qops = {
56         .queue_setup     = virtio_video_queue_setup,
57         .buf_init        = virtio_video_buf_init,
58         .buf_cleanup     = virtio_video_buf_cleanup,
59         .buf_queue       = virtio_video_buf_queue,
60         .start_streaming = virtio_video_dec_start_streaming,
61         .stop_streaming  = virtio_video_dec_stop_streaming,
62         .wait_prepare    = vb2_ops_wait_prepare,
63         .wait_finish     = vb2_ops_wait_finish,
64 };
65
66 static int virtio_video_dec_g_ctrl(struct v4l2_ctrl *ctrl)
67 {
68         int ret = 0;
69         struct virtio_video_stream *stream = ctrl2stream(ctrl);
70
71         if (virtio_video_state(stream) == STREAM_STATE_ERROR)
72                 return -EIO;
73
74         switch (ctrl->id) {
75         case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
76                 if (virtio_video_state(stream) >=
77                     STREAM_STATE_DYNAMIC_RES_CHANGE)
78                         ctrl->val = stream->out_info.min_buffers;
79                 else
80                         ctrl->val = 0;
81                 break;
82         default:
83                 ret = -EINVAL;
84                 break;
85         }
86
87         return ret;
88 }
89
90 static const struct v4l2_ctrl_ops virtio_video_dec_ctrl_ops = {
91         .g_volatile_ctrl        = virtio_video_dec_g_ctrl,
92 };
93
94 int virtio_video_dec_init_ctrls(struct virtio_video_stream *stream)
95 {
96         struct v4l2_ctrl *ctrl;
97
98         v4l2_ctrl_handler_init(&stream->ctrl_handler, 2);
99
100         ctrl = v4l2_ctrl_new_std(&stream->ctrl_handler,
101                                 &virtio_video_dec_ctrl_ops,
102                                 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
103                                 MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP,
104                                 MIN_BUFS_DEF);
105
106         if (ctrl)
107                 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
108
109         if (stream->ctrl_handler.error)
110                 return stream->ctrl_handler.error;
111
112         (void)v4l2_ctrl_new_std(&stream->ctrl_handler, NULL,
113                                 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
114                                 MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP,
115                                 stream->in_info.min_buffers);
116
117         if (stream->ctrl_handler.error)
118                 return stream->ctrl_handler.error;
119
120         v4l2_ctrl_handler_setup(&stream->ctrl_handler);
121
122         return 0;
123 }
124
125 int virtio_video_dec_init_queues(void *priv, struct vb2_queue *src_vq,
126                                  struct vb2_queue *dst_vq)
127 {
128         int ret;
129         struct virtio_video_stream *stream = priv;
130         struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
131         struct device *dev = vvd->v4l2_dev.dev;
132
133         src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
134         src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
135         src_vq->drv_priv = stream;
136         src_vq->buf_struct_size = sizeof(struct virtio_video_buffer);
137         src_vq->ops = &virtio_video_dec_qops;
138         src_vq->mem_ops = virtio_video_mem_ops(vvd);
139         src_vq->min_buffers_needed = stream->in_info.min_buffers;
140         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
141         src_vq->lock = &stream->vq_mutex;
142         src_vq->gfp_flags = virtio_video_gfp_flags(vvd);
143         src_vq->dev = dev;
144
145         ret = vb2_queue_init(src_vq);
146         if (ret)
147                 return ret;
148
149         dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
150         dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
151         dst_vq->drv_priv = stream;
152         dst_vq->buf_struct_size = sizeof(struct virtio_video_buffer);
153         dst_vq->ops = &virtio_video_dec_qops;
154         dst_vq->mem_ops = virtio_video_mem_ops(vvd);
155         dst_vq->min_buffers_needed = stream->out_info.min_buffers;
156         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
157         dst_vq->lock = &stream->vq_mutex;
158         dst_vq->gfp_flags = virtio_video_gfp_flags(vvd);
159         dst_vq->dev = dev;
160
161         return vb2_queue_init(dst_vq);
162 }
163
164 static int virtio_video_try_decoder_cmd(struct file *file, void *fh,
165                                         struct v4l2_decoder_cmd *cmd)
166 {
167         struct virtio_video_stream *stream = file2stream(file);
168         struct virtio_video_device *vvd = video_drvdata(file);
169
170         if (virtio_video_state(stream) == STREAM_STATE_ERROR)
171                 return -EIO;
172
173         if (virtio_video_state(stream) == STREAM_STATE_DRAIN)
174                 return -EBUSY;
175
176         switch (cmd->cmd) {
177         case V4L2_DEC_CMD_STOP:
178         case V4L2_DEC_CMD_START:
179                 if (cmd->flags != 0) {
180                         v4l2_err(&vvd->v4l2_dev, "flags=%u are not supported",
181                                  cmd->flags);
182                         return -EINVAL;
183                 }
184                 break;
185         default:
186                 return -EINVAL;
187         }
188
189         return 0;
190 }
191
192 static int virtio_video_decoder_cmd(struct file *file, void *fh,
193                                     struct v4l2_decoder_cmd *cmd)
194 {
195         int ret;
196         struct vb2_queue *src_vq, *dst_vq;
197         struct virtio_video_stream *stream = file2stream(file);
198         struct virtio_video_device *vvd = video_drvdata(file);
199
200         ret = virtio_video_try_decoder_cmd(file, fh, cmd);
201         if (ret < 0)
202                 return ret;
203
204         dst_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx,
205                                  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
206
207         switch (cmd->cmd) {
208         case V4L2_DEC_CMD_START:
209                 vb2_clear_last_buffer_dequeued(dst_vq);
210                 break;
211         case V4L2_DEC_CMD_STOP:
212                 src_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx,
213                                          V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
214
215                 if (!vb2_is_streaming(src_vq)) {
216                         v4l2_dbg(1, vvd->debug,
217                                  &vvd->v4l2_dev, "output is not streaming\n");
218                         return 0;
219                 }
220
221                 if (!vb2_is_streaming(dst_vq)) {
222                         v4l2_dbg(1, vvd->debug,
223                                  &vvd->v4l2_dev, "capture is not streaming\n");
224                         return 0;
225                 }
226
227                 ret = virtio_video_cmd_stream_drain(vvd, stream->stream_id);
228                 if (ret) {
229                         v4l2_err(&vvd->v4l2_dev, "failed to drain stream\n");
230                         return ret;
231                 }
232
233                 virtio_video_state_update(stream, STREAM_STATE_DRAIN);
234                 break;
235         default:
236                 return -EINVAL;
237         }
238
239         return 0;
240 }
241
242 static int virtio_video_dec_enum_fmt_vid_cap(struct file *file, void *fh,
243                                              struct v4l2_fmtdesc *f)
244 {
245         struct virtio_video_stream *stream = file2stream(file);
246         struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
247         struct video_format_info *info;
248         struct video_format *fmt;
249         unsigned long input_mask = 0;
250         int idx = 0, bit_num = 0;
251
252         if (virtio_video_state(stream) == STREAM_STATE_ERROR)
253                 return -EIO;
254
255         if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
256                 return -EINVAL;
257
258         if (f->index >= vvd->num_output_fmts)
259                 return -EINVAL;
260
261         info = &stream->in_info;
262         list_for_each_entry(fmt, &vvd->input_fmt_list, formats_list_entry) {
263                 if (info->fourcc_format == fmt->desc.format) {
264                         input_mask = fmt->desc.mask;
265                         break;
266                 }
267         }
268
269         if (input_mask == 0)
270                 return -EINVAL;
271
272         list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) {
273                 if (test_bit(bit_num, &input_mask)) {
274                         if (f->index == idx) {
275                                 f->pixelformat = fmt->desc.format;
276                                 return 0;
277                         }
278                         idx++;
279                 }
280                 bit_num++;
281         }
282         return -EINVAL;
283 }
284
285
286 int virtio_video_dec_enum_fmt_vid_out(struct file *file, void *fh,
287                                       struct v4l2_fmtdesc *f)
288 {
289         struct virtio_video_stream *stream = file2stream(file);
290         struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
291         struct video_format *fmt;
292         int idx = 0;
293
294         if (virtio_video_state(stream) == STREAM_STATE_ERROR)
295                 return -EIO;
296
297         if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
298                 return -EINVAL;
299
300         if (f->index >= vvd->num_input_fmts)
301                 return -EINVAL;
302
303         list_for_each_entry(fmt, &vvd->input_fmt_list, formats_list_entry) {
304                 if (f->index == idx) {
305                         f->pixelformat = fmt->desc.format;
306                         return 0;
307                 }
308                 idx++;
309         }
310         return -EINVAL;
311 }
312
313 static int virtio_video_dec_s_fmt(struct file *file, void *fh,
314                                   struct v4l2_format *f)
315 {
316         int ret;
317         struct virtio_video_stream *stream = file2stream(file);
318
319         ret = virtio_video_s_fmt(file, fh, f);
320         if (ret)
321                 return ret;
322
323         if (V4L2_TYPE_IS_OUTPUT(f->type)) {
324                 if (virtio_video_state(stream) == STREAM_STATE_IDLE)
325                         virtio_video_state_update(stream, STREAM_STATE_INIT);
326         }
327
328         return 0;
329 }
330
331 static int virtio_video_dec_s_selection(struct file *file, void *fh,
332                                         struct v4l2_selection *sel)
333 {
334         struct virtio_video_stream *stream = file2stream(file);
335         struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
336         int ret;
337
338         if (V4L2_TYPE_IS_OUTPUT(sel->type))
339                 return -EINVAL;
340
341         switch (sel->target) {
342         case V4L2_SEL_TGT_COMPOSE:
343                 stream->out_info.crop.top = sel->r.top;
344                 stream->out_info.crop.left = sel->r.left;
345                 stream->out_info.crop.width = sel->r.width;
346                 stream->out_info.crop.height = sel->r.height;
347                 break;
348         default:
349                 return -EINVAL;
350         }
351
352         ret = virtio_video_cmd_set_params(vvd, stream,  &stream->out_info,
353                                            VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT);
354         if (ret)
355                 return -EINVAL;
356
357         return virtio_video_cmd_get_params(vvd, stream,
358                                            VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT);
359 }
360
361 static const struct v4l2_ioctl_ops virtio_video_dec_ioctl_ops = {
362         .vidioc_querycap        = virtio_video_querycap,
363
364 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
365         .vidioc_enum_fmt_vid_cap        = virtio_video_dec_enum_fmt_vid_cap,
366         .vidioc_enum_fmt_vid_out        = virtio_video_dec_enum_fmt_vid_out,
367 #else
368         .vidioc_enum_fmt_vid_cap_mplane = virtio_video_dec_enum_fmt_vid_cap,
369         .vidioc_enum_fmt_vid_out_mplane = virtio_video_dec_enum_fmt_vid_out,
370 #endif
371         .vidioc_g_fmt_vid_cap_mplane    = virtio_video_g_fmt,
372         .vidioc_s_fmt_vid_cap_mplane    = virtio_video_dec_s_fmt,
373
374         .vidioc_g_fmt_vid_out_mplane    = virtio_video_g_fmt,
375         .vidioc_s_fmt_vid_out_mplane    = virtio_video_dec_s_fmt,
376
377         .vidioc_g_selection = virtio_video_g_selection,
378         .vidioc_s_selection = virtio_video_dec_s_selection,
379
380         .vidioc_try_decoder_cmd = virtio_video_try_decoder_cmd,
381         .vidioc_decoder_cmd     = virtio_video_decoder_cmd,
382         .vidioc_enum_frameintervals = virtio_video_enum_framemintervals,
383         .vidioc_enum_framesizes = virtio_video_enum_framesizes,
384
385         .vidioc_reqbufs         = virtio_video_reqbufs,
386         .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
387         .vidioc_qbuf            = virtio_video_qbuf,
388         .vidioc_dqbuf           = virtio_video_dqbuf,
389         .vidioc_prepare_buf     = v4l2_m2m_ioctl_prepare_buf,
390         .vidioc_create_bufs     = v4l2_m2m_ioctl_create_bufs,
391         .vidioc_expbuf          = v4l2_m2m_ioctl_expbuf,
392
393         .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
394         .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
395
396         .vidioc_subscribe_event = virtio_video_subscribe_event,
397         .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
398 };
399
400 void *virtio_video_dec_get_fmt_list(struct virtio_video_device *vvd)
401 {
402         return &vvd->input_fmt_list;
403 }
404
405 static struct virtio_video_device_ops virtio_video_dec_ops = {
406         .init_ctrls = virtio_video_dec_init_ctrls,
407         .init_queues = virtio_video_dec_init_queues,
408         .get_fmt_list = virtio_video_dec_get_fmt_list,
409 };
410
411 int virtio_video_dec_init(struct virtio_video_device *vvd)
412 {
413         ssize_t num;
414         struct video_device *vd = &vvd->video_dev;
415
416         vd->ioctl_ops = &virtio_video_dec_ioctl_ops;
417         vvd->ops = &virtio_video_dec_ops;
418
419         num = strscpy(vd->name, "stateful-decoder", sizeof(vd->name));
420         if (num < 0)
421                 return num;
422
423         return 0;
424 }