Merge tag 'drm-misc-next-2021-10-14' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / drivers / staging / media / sunxi / cedrus / cedrus_video.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Cedrus VPU driver
4  *
5  * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
6  * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
7  * Copyright (C) 2018 Bootlin
8  *
9  * Based on the vim2m driver, that is:
10  *
11  * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
12  * Pawel Osciak, <pawel@osciak.com>
13  * Marek Szyprowski, <m.szyprowski@samsung.com>
14  */
15
16 #include <linux/pm_runtime.h>
17
18 #include <media/videobuf2-dma-contig.h>
19 #include <media/v4l2-device.h>
20 #include <media/v4l2-ioctl.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-mem2mem.h>
23
24 #include "cedrus.h"
25 #include "cedrus_video.h"
26 #include "cedrus_dec.h"
27 #include "cedrus_hw.h"
28
29 #define CEDRUS_DECODE_SRC       BIT(0)
30 #define CEDRUS_DECODE_DST       BIT(1)
31
32 #define CEDRUS_MIN_WIDTH        16U
33 #define CEDRUS_MIN_HEIGHT       16U
34 #define CEDRUS_MAX_WIDTH        4096U
35 #define CEDRUS_MAX_HEIGHT       2304U
36
37 static struct cedrus_format cedrus_formats[] = {
38         {
39                 .pixelformat    = V4L2_PIX_FMT_MPEG2_SLICE,
40                 .directions     = CEDRUS_DECODE_SRC,
41                 .capabilities   = CEDRUS_CAPABILITY_MPEG2_DEC,
42         },
43         {
44                 .pixelformat    = V4L2_PIX_FMT_H264_SLICE,
45                 .directions     = CEDRUS_DECODE_SRC,
46                 .capabilities   = CEDRUS_CAPABILITY_H264_DEC,
47         },
48         {
49                 .pixelformat    = V4L2_PIX_FMT_HEVC_SLICE,
50                 .directions     = CEDRUS_DECODE_SRC,
51                 .capabilities   = CEDRUS_CAPABILITY_H265_DEC,
52         },
53         {
54                 .pixelformat    = V4L2_PIX_FMT_VP8_FRAME,
55                 .directions     = CEDRUS_DECODE_SRC,
56                 .capabilities   = CEDRUS_CAPABILITY_VP8_DEC,
57         },
58         {
59                 .pixelformat    = V4L2_PIX_FMT_SUNXI_TILED_NV12,
60                 .directions     = CEDRUS_DECODE_DST,
61         },
62         {
63                 .pixelformat    = V4L2_PIX_FMT_NV12,
64                 .directions     = CEDRUS_DECODE_DST,
65                 .capabilities   = CEDRUS_CAPABILITY_UNTILED,
66         },
67 };
68
69 #define CEDRUS_FORMATS_COUNT    ARRAY_SIZE(cedrus_formats)
70
71 static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file)
72 {
73         return container_of(file->private_data, struct cedrus_ctx, fh);
74 }
75
76 static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions,
77                                                 unsigned int capabilities)
78 {
79         struct cedrus_format *first_valid_fmt = NULL;
80         struct cedrus_format *fmt;
81         unsigned int i;
82
83         for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) {
84                 fmt = &cedrus_formats[i];
85
86                 if ((fmt->capabilities & capabilities) != fmt->capabilities ||
87                     !(fmt->directions & directions))
88                         continue;
89
90                 if (fmt->pixelformat == pixelformat)
91                         break;
92
93                 if (!first_valid_fmt)
94                         first_valid_fmt = fmt;
95         }
96
97         if (i == CEDRUS_FORMATS_COUNT)
98                 return first_valid_fmt;
99
100         return &cedrus_formats[i];
101 }
102
103 void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
104 {
105         unsigned int width = pix_fmt->width;
106         unsigned int height = pix_fmt->height;
107         unsigned int sizeimage = pix_fmt->sizeimage;
108         unsigned int bytesperline = pix_fmt->bytesperline;
109
110         pix_fmt->field = V4L2_FIELD_NONE;
111
112         /* Limit to hardware min/max. */
113         width = clamp(width, CEDRUS_MIN_WIDTH, CEDRUS_MAX_WIDTH);
114         height = clamp(height, CEDRUS_MIN_HEIGHT, CEDRUS_MAX_HEIGHT);
115
116         switch (pix_fmt->pixelformat) {
117         case V4L2_PIX_FMT_MPEG2_SLICE:
118         case V4L2_PIX_FMT_H264_SLICE:
119         case V4L2_PIX_FMT_HEVC_SLICE:
120         case V4L2_PIX_FMT_VP8_FRAME:
121                 /* Zero bytes per line for encoded source. */
122                 bytesperline = 0;
123                 /* Choose some minimum size since this can't be 0 */
124                 sizeimage = max_t(u32, SZ_1K, sizeimage);
125                 break;
126
127         case V4L2_PIX_FMT_SUNXI_TILED_NV12:
128                 /* 32-aligned stride. */
129                 bytesperline = ALIGN(width, 32);
130
131                 /* 32-aligned height. */
132                 height = ALIGN(height, 32);
133
134                 /* Luma plane size. */
135                 sizeimage = bytesperline * height;
136
137                 /* Chroma plane size. */
138                 sizeimage += bytesperline * ALIGN(height, 64) / 2;
139
140                 break;
141
142         case V4L2_PIX_FMT_NV12:
143                 /* 16-aligned stride. */
144                 bytesperline = ALIGN(width, 16);
145
146                 /* 16-aligned height. */
147                 height = ALIGN(height, 16);
148
149                 /* Luma plane size. */
150                 sizeimage = bytesperline * height;
151
152                 /* Chroma plane size. */
153                 sizeimage += bytesperline * height / 2;
154
155                 break;
156         }
157
158         pix_fmt->width = width;
159         pix_fmt->height = height;
160
161         pix_fmt->bytesperline = bytesperline;
162         pix_fmt->sizeimage = sizeimage;
163 }
164
165 static int cedrus_querycap(struct file *file, void *priv,
166                            struct v4l2_capability *cap)
167 {
168         strscpy(cap->driver, CEDRUS_NAME, sizeof(cap->driver));
169         strscpy(cap->card, CEDRUS_NAME, sizeof(cap->card));
170         snprintf(cap->bus_info, sizeof(cap->bus_info),
171                  "platform:%s", CEDRUS_NAME);
172
173         return 0;
174 }
175
176 static int cedrus_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
177                            u32 direction)
178 {
179         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
180         struct cedrus_dev *dev = ctx->dev;
181         unsigned int capabilities = dev->capabilities;
182         struct cedrus_format *fmt;
183         unsigned int i, index;
184
185         /* Index among formats that match the requested direction. */
186         index = 0;
187
188         for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) {
189                 fmt = &cedrus_formats[i];
190
191                 if (fmt->capabilities && (fmt->capabilities & capabilities) !=
192                     fmt->capabilities)
193                         continue;
194
195                 if (!(cedrus_formats[i].directions & direction))
196                         continue;
197
198                 if (index == f->index)
199                         break;
200
201                 index++;
202         }
203
204         /* Matched format. */
205         if (i < CEDRUS_FORMATS_COUNT) {
206                 f->pixelformat = cedrus_formats[i].pixelformat;
207
208                 return 0;
209         }
210
211         return -EINVAL;
212 }
213
214 static int cedrus_enum_fmt_vid_cap(struct file *file, void *priv,
215                                    struct v4l2_fmtdesc *f)
216 {
217         return cedrus_enum_fmt(file, f, CEDRUS_DECODE_DST);
218 }
219
220 static int cedrus_enum_fmt_vid_out(struct file *file, void *priv,
221                                    struct v4l2_fmtdesc *f)
222 {
223         return cedrus_enum_fmt(file, f, CEDRUS_DECODE_SRC);
224 }
225
226 static int cedrus_g_fmt_vid_cap(struct file *file, void *priv,
227                                 struct v4l2_format *f)
228 {
229         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
230
231         f->fmt.pix = ctx->dst_fmt;
232         return 0;
233 }
234
235 static int cedrus_g_fmt_vid_out(struct file *file, void *priv,
236                                 struct v4l2_format *f)
237 {
238         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
239
240         f->fmt.pix = ctx->src_fmt;
241         return 0;
242 }
243
244 static int cedrus_try_fmt_vid_cap(struct file *file, void *priv,
245                                   struct v4l2_format *f)
246 {
247         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
248         struct cedrus_dev *dev = ctx->dev;
249         struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
250         struct cedrus_format *fmt =
251                 cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST,
252                                    dev->capabilities);
253
254         if (!fmt)
255                 return -EINVAL;
256
257         pix_fmt->pixelformat = fmt->pixelformat;
258         pix_fmt->width = ctx->src_fmt.width;
259         pix_fmt->height = ctx->src_fmt.height;
260         cedrus_prepare_format(pix_fmt);
261
262         return 0;
263 }
264
265 static int cedrus_try_fmt_vid_out(struct file *file, void *priv,
266                                   struct v4l2_format *f)
267 {
268         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
269         struct cedrus_dev *dev = ctx->dev;
270         struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
271         struct cedrus_format *fmt =
272                 cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC,
273                                    dev->capabilities);
274
275         if (!fmt)
276                 return -EINVAL;
277
278         pix_fmt->pixelformat = fmt->pixelformat;
279         cedrus_prepare_format(pix_fmt);
280
281         return 0;
282 }
283
284 static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
285                                 struct v4l2_format *f)
286 {
287         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
288         struct vb2_queue *vq;
289         int ret;
290
291         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
292         if (vb2_is_busy(vq))
293                 return -EBUSY;
294
295         ret = cedrus_try_fmt_vid_cap(file, priv, f);
296         if (ret)
297                 return ret;
298
299         ctx->dst_fmt = f->fmt.pix;
300
301         return 0;
302 }
303
304 static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
305                                 struct v4l2_format *f)
306 {
307         struct cedrus_ctx *ctx = cedrus_file2ctx(file);
308         struct vb2_queue *vq;
309         struct vb2_queue *peer_vq;
310         int ret;
311
312         ret = cedrus_try_fmt_vid_out(file, priv, f);
313         if (ret)
314                 return ret;
315
316         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
317         /*
318          * In order to support dynamic resolution change,
319          * the decoder admits a resolution change, as long
320          * as the pixelformat remains. Can't be done if streaming.
321          */
322         if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
323             f->fmt.pix.pixelformat != ctx->src_fmt.pixelformat))
324                 return -EBUSY;
325         /*
326          * Since format change on the OUTPUT queue will reset
327          * the CAPTURE queue, we can't allow doing so
328          * when the CAPTURE queue has buffers allocated.
329          */
330         peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
331                                   V4L2_BUF_TYPE_VIDEO_CAPTURE);
332         if (vb2_is_busy(peer_vq))
333                 return -EBUSY;
334
335         ret = cedrus_try_fmt_vid_out(file, priv, f);
336         if (ret)
337                 return ret;
338
339         ctx->src_fmt = f->fmt.pix;
340
341         switch (ctx->src_fmt.pixelformat) {
342         case V4L2_PIX_FMT_H264_SLICE:
343         case V4L2_PIX_FMT_HEVC_SLICE:
344                 vq->subsystem_flags |=
345                         VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
346                 break;
347         default:
348                 vq->subsystem_flags &=
349                         ~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
350                 break;
351         }
352
353         /* Propagate format information to capture. */
354         ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
355         ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
356         ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
357         ctx->dst_fmt.quantization = f->fmt.pix.quantization;
358         ctx->dst_fmt.width = ctx->src_fmt.width;
359         ctx->dst_fmt.height = ctx->src_fmt.height;
360         cedrus_prepare_format(&ctx->dst_fmt);
361
362         return 0;
363 }
364
365 const struct v4l2_ioctl_ops cedrus_ioctl_ops = {
366         .vidioc_querycap                = cedrus_querycap,
367
368         .vidioc_enum_fmt_vid_cap        = cedrus_enum_fmt_vid_cap,
369         .vidioc_g_fmt_vid_cap           = cedrus_g_fmt_vid_cap,
370         .vidioc_try_fmt_vid_cap         = cedrus_try_fmt_vid_cap,
371         .vidioc_s_fmt_vid_cap           = cedrus_s_fmt_vid_cap,
372
373         .vidioc_enum_fmt_vid_out        = cedrus_enum_fmt_vid_out,
374         .vidioc_g_fmt_vid_out           = cedrus_g_fmt_vid_out,
375         .vidioc_try_fmt_vid_out         = cedrus_try_fmt_vid_out,
376         .vidioc_s_fmt_vid_out           = cedrus_s_fmt_vid_out,
377
378         .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
379         .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
380         .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
381         .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
382         .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
383         .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
384         .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
385
386         .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
387         .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
388
389         .vidioc_try_decoder_cmd         = v4l2_m2m_ioctl_stateless_try_decoder_cmd,
390         .vidioc_decoder_cmd             = v4l2_m2m_ioctl_stateless_decoder_cmd,
391
392         .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
393         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
394 };
395
396 static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
397                               unsigned int *nplanes, unsigned int sizes[],
398                               struct device *alloc_devs[])
399 {
400         struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
401         struct v4l2_pix_format *pix_fmt;
402
403         if (V4L2_TYPE_IS_OUTPUT(vq->type))
404                 pix_fmt = &ctx->src_fmt;
405         else
406                 pix_fmt = &ctx->dst_fmt;
407
408         if (*nplanes) {
409                 if (sizes[0] < pix_fmt->sizeimage)
410                         return -EINVAL;
411         } else {
412                 sizes[0] = pix_fmt->sizeimage;
413                 *nplanes = 1;
414         }
415
416         return 0;
417 }
418
419 static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state)
420 {
421         struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
422         struct vb2_v4l2_buffer *vbuf;
423
424         for (;;) {
425                 if (V4L2_TYPE_IS_OUTPUT(vq->type))
426                         vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
427                 else
428                         vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
429
430                 if (!vbuf)
431                         return;
432
433                 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
434                                            &ctx->hdl);
435                 v4l2_m2m_buf_done(vbuf, state);
436         }
437 }
438
439 static int cedrus_buf_out_validate(struct vb2_buffer *vb)
440 {
441         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
442
443         vbuf->field = V4L2_FIELD_NONE;
444         return 0;
445 }
446
447 static int cedrus_buf_prepare(struct vb2_buffer *vb)
448 {
449         struct vb2_queue *vq = vb->vb2_queue;
450         struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
451         struct v4l2_pix_format *pix_fmt;
452
453         if (V4L2_TYPE_IS_OUTPUT(vq->type))
454                 pix_fmt = &ctx->src_fmt;
455         else
456                 pix_fmt = &ctx->dst_fmt;
457
458         if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
459                 return -EINVAL;
460
461         /*
462          * Buffer's bytesused must be written by driver for CAPTURE buffers.
463          * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
464          * it to buffer length).
465          */
466         if (V4L2_TYPE_IS_CAPTURE(vq->type))
467                 vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
468
469         return 0;
470 }
471
472 static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
473 {
474         struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
475         struct cedrus_dev *dev = ctx->dev;
476         int ret = 0;
477
478         switch (ctx->src_fmt.pixelformat) {
479         case V4L2_PIX_FMT_MPEG2_SLICE:
480                 ctx->current_codec = CEDRUS_CODEC_MPEG2;
481                 break;
482
483         case V4L2_PIX_FMT_H264_SLICE:
484                 ctx->current_codec = CEDRUS_CODEC_H264;
485                 break;
486
487         case V4L2_PIX_FMT_HEVC_SLICE:
488                 ctx->current_codec = CEDRUS_CODEC_H265;
489                 break;
490
491         case V4L2_PIX_FMT_VP8_FRAME:
492                 ctx->current_codec = CEDRUS_CODEC_VP8;
493                 break;
494
495         default:
496                 return -EINVAL;
497         }
498
499         if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
500                 ret = pm_runtime_resume_and_get(dev->dev);
501                 if (ret < 0)
502                         goto err_cleanup;
503
504                 if (dev->dec_ops[ctx->current_codec]->start) {
505                         ret = dev->dec_ops[ctx->current_codec]->start(ctx);
506                         if (ret)
507                                 goto err_pm;
508                 }
509         }
510
511         return 0;
512
513 err_pm:
514         pm_runtime_put(dev->dev);
515 err_cleanup:
516         cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
517
518         return ret;
519 }
520
521 static void cedrus_stop_streaming(struct vb2_queue *vq)
522 {
523         struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
524         struct cedrus_dev *dev = ctx->dev;
525
526         if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
527                 if (dev->dec_ops[ctx->current_codec]->stop)
528                         dev->dec_ops[ctx->current_codec]->stop(ctx);
529
530                 pm_runtime_put(dev->dev);
531         }
532
533         cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
534 }
535
536 static void cedrus_buf_queue(struct vb2_buffer *vb)
537 {
538         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
539         struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
540
541         v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
542 }
543
544 static void cedrus_buf_request_complete(struct vb2_buffer *vb)
545 {
546         struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
547
548         v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
549 }
550
551 static struct vb2_ops cedrus_qops = {
552         .queue_setup            = cedrus_queue_setup,
553         .buf_prepare            = cedrus_buf_prepare,
554         .buf_queue              = cedrus_buf_queue,
555         .buf_out_validate       = cedrus_buf_out_validate,
556         .buf_request_complete   = cedrus_buf_request_complete,
557         .start_streaming        = cedrus_start_streaming,
558         .stop_streaming         = cedrus_stop_streaming,
559         .wait_prepare           = vb2_ops_wait_prepare,
560         .wait_finish            = vb2_ops_wait_finish,
561 };
562
563 int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
564                       struct vb2_queue *dst_vq)
565 {
566         struct cedrus_ctx *ctx = priv;
567         int ret;
568
569         src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
570         src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
571         src_vq->drv_priv = ctx;
572         src_vq->buf_struct_size = sizeof(struct cedrus_buffer);
573         src_vq->min_buffers_needed = 1;
574         src_vq->ops = &cedrus_qops;
575         src_vq->mem_ops = &vb2_dma_contig_memops;
576         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
577         src_vq->lock = &ctx->dev->dev_mutex;
578         src_vq->dev = ctx->dev->dev;
579         src_vq->supports_requests = true;
580         src_vq->requires_requests = true;
581
582         ret = vb2_queue_init(src_vq);
583         if (ret)
584                 return ret;
585
586         dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
587         dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
588         dst_vq->drv_priv = ctx;
589         dst_vq->buf_struct_size = sizeof(struct cedrus_buffer);
590         dst_vq->min_buffers_needed = 1;
591         dst_vq->ops = &cedrus_qops;
592         dst_vq->mem_ops = &vb2_dma_contig_memops;
593         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
594         dst_vq->lock = &ctx->dev->dev_mutex;
595         dst_vq->dev = ctx->dev->dev;
596
597         return vb2_queue_init(dst_vq);
598 }