]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/media/platform/qcom/venus/vdec.c
Merge tag 'v5.3-rc4' into patchwork
[linux.git] / drivers / media / platform / qcom / venus / vdec.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4  * Copyright (C) 2017 Linaro Ltd.
5  */
6 #include <linux/clk.h>
7 #include <linux/module.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/platform_device.h>
10 #include <linux/pm_runtime.h>
11 #include <linux/slab.h>
12 #include <media/v4l2-ioctl.h>
13 #include <media/v4l2-event.h>
14 #include <media/v4l2-ctrls.h>
15 #include <media/v4l2-mem2mem.h>
16 #include <media/videobuf2-dma-sg.h>
17
18 #include "hfi_venus_io.h"
19 #include "hfi_parser.h"
20 #include "core.h"
21 #include "helpers.h"
22 #include "vdec.h"
23
24 /*
25  * Three resons to keep MPLANE formats (despite that the number of planes
26  * currently is one):
27  * - the MPLANE formats allow only one plane to be used
28  * - the downstream driver use MPLANE formats too
29  * - future firmware versions could add support for >1 planes
30  */
31 static const struct venus_format vdec_formats[] = {
32         {
33                 .pixfmt = V4L2_PIX_FMT_NV12,
34                 .num_planes = 1,
35                 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
36         }, {
37                 .pixfmt = V4L2_PIX_FMT_MPEG4,
38                 .num_planes = 1,
39                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
40         }, {
41                 .pixfmt = V4L2_PIX_FMT_MPEG2,
42                 .num_planes = 1,
43                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
44         }, {
45                 .pixfmt = V4L2_PIX_FMT_H263,
46                 .num_planes = 1,
47                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
48         }, {
49                 .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
50                 .num_planes = 1,
51                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
52         }, {
53                 .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
54                 .num_planes = 1,
55                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
56         }, {
57                 .pixfmt = V4L2_PIX_FMT_H264,
58                 .num_planes = 1,
59                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
60         }, {
61                 .pixfmt = V4L2_PIX_FMT_VP8,
62                 .num_planes = 1,
63                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
64         }, {
65                 .pixfmt = V4L2_PIX_FMT_VP9,
66                 .num_planes = 1,
67                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
68         }, {
69                 .pixfmt = V4L2_PIX_FMT_XVID,
70                 .num_planes = 1,
71                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
72         }, {
73                 .pixfmt = V4L2_PIX_FMT_HEVC,
74                 .num_planes = 1,
75                 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
76         },
77 };
78
79 static const struct venus_format *
80 find_format(struct venus_inst *inst, u32 pixfmt, u32 type)
81 {
82         const struct venus_format *fmt = vdec_formats;
83         unsigned int size = ARRAY_SIZE(vdec_formats);
84         unsigned int i;
85
86         for (i = 0; i < size; i++) {
87                 if (fmt[i].pixfmt == pixfmt)
88                         break;
89         }
90
91         if (i == size || fmt[i].type != type)
92                 return NULL;
93
94         if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
95             !venus_helper_check_codec(inst, fmt[i].pixfmt))
96                 return NULL;
97
98         return &fmt[i];
99 }
100
101 static const struct venus_format *
102 find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
103 {
104         const struct venus_format *fmt = vdec_formats;
105         unsigned int size = ARRAY_SIZE(vdec_formats);
106         unsigned int i, k = 0;
107
108         if (index > size)
109                 return NULL;
110
111         for (i = 0; i < size; i++) {
112                 bool valid;
113
114                 if (fmt[i].type != type)
115                         continue;
116                 valid = type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ||
117                         venus_helper_check_codec(inst, fmt[i].pixfmt);
118                 if (k == index && valid)
119                         break;
120                 if (valid)
121                         k++;
122         }
123
124         if (i == size)
125                 return NULL;
126
127         return &fmt[i];
128 }
129
130 static const struct venus_format *
131 vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
132 {
133         struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
134         struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt;
135         const struct venus_format *fmt;
136         u32 szimage;
137
138         memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
139         memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
140
141         fmt = find_format(inst, pixmp->pixelformat, f->type);
142         if (!fmt) {
143                 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
144                         pixmp->pixelformat = V4L2_PIX_FMT_NV12;
145                 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
146                         pixmp->pixelformat = V4L2_PIX_FMT_H264;
147                 else
148                         return NULL;
149                 fmt = find_format(inst, pixmp->pixelformat, f->type);
150         }
151
152         pixmp->width = clamp(pixmp->width, frame_width_min(inst),
153                              frame_width_max(inst));
154         pixmp->height = clamp(pixmp->height, frame_height_min(inst),
155                               frame_height_max(inst));
156
157         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
158                 pixmp->height = ALIGN(pixmp->height, 32);
159
160         if (pixmp->field == V4L2_FIELD_ANY)
161                 pixmp->field = V4L2_FIELD_NONE;
162         pixmp->num_planes = fmt->num_planes;
163         pixmp->flags = 0;
164
165         szimage = venus_helper_get_framesz(pixmp->pixelformat, pixmp->width,
166                                            pixmp->height);
167
168         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
169                 pfmt[0].sizeimage = szimage;
170                 pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
171         } else {
172                 pfmt[0].sizeimage = clamp_t(u32, pfmt[0].sizeimage, 0, SZ_8M);
173                 pfmt[0].sizeimage = max(pfmt[0].sizeimage, szimage);
174                 pfmt[0].bytesperline = 0;
175         }
176
177         return fmt;
178 }
179
180 static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
181 {
182         struct venus_inst *inst = to_inst(file);
183
184         vdec_try_fmt_common(inst, f);
185
186         return 0;
187 }
188
189 static int vdec_check_src_change(struct venus_inst *inst)
190 {
191         int ret;
192
193         if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE &&
194             inst->codec_state == VENUS_DEC_STATE_INIT &&
195             !inst->reconfig)
196                 return -EINVAL;
197
198         if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE)
199                 return 0;
200
201         /*
202          * The code snippet below is a workaround for backward compatibility
203          * with applications which doesn't support V4L2 events. It will be
204          * dropped in future once those applications are fixed.
205          */
206
207         if (inst->codec_state != VENUS_DEC_STATE_INIT)
208                 goto done;
209
210         ret = wait_event_timeout(inst->reconf_wait, inst->reconfig,
211                                  msecs_to_jiffies(100));
212         if (!ret)
213                 return -EINVAL;
214
215         if (!(inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) ||
216             !inst->reconfig)
217                 dev_dbg(inst->core->dev, "%s: wrong state\n", __func__);
218
219 done:
220         return 0;
221 }
222
223 static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
224 {
225         struct venus_inst *inst = to_inst(file);
226         const struct venus_format *fmt = NULL;
227         struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
228         int ret;
229
230         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
231                 fmt = inst->fmt_cap;
232         else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
233                 fmt = inst->fmt_out;
234
235         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
236                 ret = vdec_check_src_change(inst);
237                 if (ret)
238                         return ret;
239         }
240
241         pixmp->pixelformat = fmt->pixfmt;
242
243         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
244                 pixmp->width = inst->width;
245                 pixmp->height = inst->height;
246                 pixmp->colorspace = inst->colorspace;
247                 pixmp->ycbcr_enc = inst->ycbcr_enc;
248                 pixmp->quantization = inst->quantization;
249                 pixmp->xfer_func = inst->xfer_func;
250         } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
251                 pixmp->width = inst->out_width;
252                 pixmp->height = inst->out_height;
253         }
254
255         vdec_try_fmt_common(inst, f);
256
257         return 0;
258 }
259
260 static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
261 {
262         struct venus_inst *inst = to_inst(file);
263         struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
264         struct v4l2_pix_format_mplane orig_pixmp;
265         const struct venus_format *fmt;
266         struct v4l2_format format;
267         u32 pixfmt_out = 0, pixfmt_cap = 0;
268
269         orig_pixmp = *pixmp;
270
271         fmt = vdec_try_fmt_common(inst, f);
272
273         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
274                 pixfmt_out = pixmp->pixelformat;
275                 pixfmt_cap = inst->fmt_cap->pixfmt;
276         } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
277                 pixfmt_cap = pixmp->pixelformat;
278                 pixfmt_out = inst->fmt_out->pixfmt;
279         }
280
281         memset(&format, 0, sizeof(format));
282
283         format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
284         format.fmt.pix_mp.pixelformat = pixfmt_out;
285         format.fmt.pix_mp.width = orig_pixmp.width;
286         format.fmt.pix_mp.height = orig_pixmp.height;
287         vdec_try_fmt_common(inst, &format);
288
289         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
290                 inst->out_width = format.fmt.pix_mp.width;
291                 inst->out_height = format.fmt.pix_mp.height;
292                 inst->colorspace = pixmp->colorspace;
293                 inst->ycbcr_enc = pixmp->ycbcr_enc;
294                 inst->quantization = pixmp->quantization;
295                 inst->xfer_func = pixmp->xfer_func;
296                 inst->input_buf_size = pixmp->plane_fmt[0].sizeimage;
297         }
298
299         memset(&format, 0, sizeof(format));
300
301         format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
302         format.fmt.pix_mp.pixelformat = pixfmt_cap;
303         format.fmt.pix_mp.width = orig_pixmp.width;
304         format.fmt.pix_mp.height = orig_pixmp.height;
305         vdec_try_fmt_common(inst, &format);
306
307         inst->width = format.fmt.pix_mp.width;
308         inst->height = format.fmt.pix_mp.height;
309
310         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
311                 inst->fmt_out = fmt;
312         else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
313                 inst->fmt_cap = fmt;
314
315         return 0;
316 }
317
318 static int
319 vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
320 {
321         struct venus_inst *inst = to_inst(file);
322
323         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
324             s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
325                 return -EINVAL;
326
327         switch (s->target) {
328         case V4L2_SEL_TGT_CROP_BOUNDS:
329         case V4L2_SEL_TGT_CROP_DEFAULT:
330         case V4L2_SEL_TGT_CROP:
331                 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
332                         return -EINVAL;
333                 s->r.width = inst->out_width;
334                 s->r.height = inst->out_height;
335                 break;
336         case V4L2_SEL_TGT_COMPOSE_BOUNDS:
337         case V4L2_SEL_TGT_COMPOSE_PADDED:
338                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
339                         return -EINVAL;
340                 s->r.width = inst->width;
341                 s->r.height = inst->height;
342                 break;
343         case V4L2_SEL_TGT_COMPOSE_DEFAULT:
344         case V4L2_SEL_TGT_COMPOSE:
345                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
346                         return -EINVAL;
347                 s->r.width = inst->out_width;
348                 s->r.height = inst->out_height;
349                 break;
350         default:
351                 return -EINVAL;
352         }
353
354         s->r.top = 0;
355         s->r.left = 0;
356
357         return 0;
358 }
359
360 static int
361 vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
362 {
363         strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
364         strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
365         strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
366
367         return 0;
368 }
369
370 static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
371 {
372         struct venus_inst *inst = to_inst(file);
373         const struct venus_format *fmt;
374
375         memset(f->reserved, 0, sizeof(f->reserved));
376
377         fmt = find_format_by_index(inst, f->index, f->type);
378         if (!fmt)
379                 return -EINVAL;
380
381         f->pixelformat = fmt->pixfmt;
382
383         return 0;
384 }
385
386 static int vdec_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
387 {
388         struct venus_inst *inst = to_inst(file);
389         struct v4l2_captureparm *cap = &a->parm.capture;
390         struct v4l2_fract *timeperframe = &cap->timeperframe;
391         u64 us_per_frame, fps;
392
393         if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
394             a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
395                 return -EINVAL;
396
397         memset(cap->reserved, 0, sizeof(cap->reserved));
398         if (!timeperframe->denominator)
399                 timeperframe->denominator = inst->timeperframe.denominator;
400         if (!timeperframe->numerator)
401                 timeperframe->numerator = inst->timeperframe.numerator;
402         cap->readbuffers = 0;
403         cap->extendedmode = 0;
404         cap->capability = V4L2_CAP_TIMEPERFRAME;
405         us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
406         do_div(us_per_frame, timeperframe->denominator);
407
408         if (!us_per_frame)
409                 return -EINVAL;
410
411         fps = (u64)USEC_PER_SEC;
412         do_div(fps, us_per_frame);
413
414         inst->fps = fps;
415         inst->timeperframe = *timeperframe;
416
417         return 0;
418 }
419
420 static int vdec_enum_framesizes(struct file *file, void *fh,
421                                 struct v4l2_frmsizeenum *fsize)
422 {
423         struct venus_inst *inst = to_inst(file);
424         const struct venus_format *fmt;
425
426         fmt = find_format(inst, fsize->pixel_format,
427                           V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
428         if (!fmt) {
429                 fmt = find_format(inst, fsize->pixel_format,
430                                   V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
431                 if (!fmt)
432                         return -EINVAL;
433         }
434
435         if (fsize->index)
436                 return -EINVAL;
437
438         fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
439
440         fsize->stepwise.min_width = frame_width_min(inst);
441         fsize->stepwise.max_width = frame_width_max(inst);
442         fsize->stepwise.step_width = frame_width_step(inst);
443         fsize->stepwise.min_height = frame_height_min(inst);
444         fsize->stepwise.max_height = frame_height_max(inst);
445         fsize->stepwise.step_height = frame_height_step(inst);
446
447         return 0;
448 }
449
450 static int vdec_subscribe_event(struct v4l2_fh *fh,
451                                 const struct v4l2_event_subscription *sub)
452 {
453         struct venus_inst *inst = container_of(fh, struct venus_inst, fh);
454         int ret;
455
456         switch (sub->type) {
457         case V4L2_EVENT_EOS:
458                 return v4l2_event_subscribe(fh, sub, 2, NULL);
459         case V4L2_EVENT_SOURCE_CHANGE:
460                 ret = v4l2_src_change_event_subscribe(fh, sub);
461                 if (ret)
462                         return ret;
463                 inst->subscriptions |= V4L2_EVENT_SOURCE_CHANGE;
464                 return 0;
465         case V4L2_EVENT_CTRL:
466                 return v4l2_ctrl_subscribe_event(fh, sub);
467         default:
468                 return -EINVAL;
469         }
470 }
471
472 static int
473 vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
474 {
475         struct venus_inst *inst = to_inst(file);
476         struct hfi_frame_data fdata = {0};
477         int ret;
478
479         ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
480         if (ret)
481                 return ret;
482
483         mutex_lock(&inst->lock);
484
485         if (cmd->cmd == V4L2_DEC_CMD_STOP) {
486                 /*
487                  * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on
488                  * decoder input to signal EOS.
489                  */
490                 if (!(inst->streamon_out && inst->streamon_cap))
491                         goto unlock;
492
493                 fdata.buffer_type = HFI_BUFFER_INPUT;
494                 fdata.flags |= HFI_BUFFERFLAG_EOS;
495                 fdata.device_addr = 0xdeadb000;
496
497                 ret = hfi_session_process_buf(inst, &fdata);
498
499                 if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING)
500                         inst->codec_state = VENUS_DEC_STATE_DRAIN;
501         }
502
503 unlock:
504         mutex_unlock(&inst->lock);
505         return ret;
506 }
507
508 static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
509         .vidioc_querycap = vdec_querycap,
510         .vidioc_enum_fmt_vid_cap = vdec_enum_fmt,
511         .vidioc_enum_fmt_vid_out = vdec_enum_fmt,
512         .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt,
513         .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt,
514         .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,
515         .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt,
516         .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,
517         .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,
518         .vidioc_g_selection = vdec_g_selection,
519         .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
520         .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
521         .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
522         .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
523         .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
524         .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
525         .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
526         .vidioc_streamon = v4l2_m2m_ioctl_streamon,
527         .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
528         .vidioc_s_parm = vdec_s_parm,
529         .vidioc_enum_framesizes = vdec_enum_framesizes,
530         .vidioc_subscribe_event = vdec_subscribe_event,
531         .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
532         .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
533         .vidioc_decoder_cmd = vdec_decoder_cmd,
534 };
535
536 static int vdec_set_properties(struct venus_inst *inst)
537 {
538         struct vdec_controls *ctr = &inst->controls.dec;
539         struct hfi_enable en = { .enable = 1 };
540         u32 ptype;
541         int ret;
542
543         if (ctr->post_loop_deb_mode) {
544                 ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
545                 ret = hfi_session_set_property(inst, ptype, &en);
546                 if (ret)
547                         return ret;
548         }
549
550         return 0;
551 }
552
553 #define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
554
555 static int vdec_output_conf(struct venus_inst *inst)
556 {
557         struct venus_core *core = inst->core;
558         struct hfi_enable en = { .enable = 1 };
559         u32 width = inst->out_width;
560         u32 height = inst->out_height;
561         u32 out_fmt, out2_fmt;
562         bool ubwc = false;
563         u32 ptype;
564         int ret;
565
566         ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
567         if (ret)
568                 return ret;
569
570         ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_1);
571         if (ret)
572                 return ret;
573
574         if (core->res->hfi_version == HFI_VERSION_1XX) {
575                 ptype = HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
576                 ret = hfi_session_set_property(inst, ptype, &en);
577                 if (ret)
578                         return ret;
579         }
580
581         /* Force searching UBWC formats for bigger then HD resolutions */
582         if (width > 1920 && height > ALIGN(1080, 32))
583                 ubwc = true;
584
585         /* For Venus v4 UBWC format is mandatory */
586         if (IS_V4(core))
587                 ubwc = true;
588
589         ret = venus_helper_get_out_fmts(inst, inst->fmt_cap->pixfmt, &out_fmt,
590                                         &out2_fmt, ubwc);
591         if (ret)
592                 return ret;
593
594         inst->output_buf_size =
595                         venus_helper_get_framesz_raw(out_fmt, width, height);
596         inst->output2_buf_size =
597                         venus_helper_get_framesz_raw(out2_fmt, width, height);
598
599         if (is_ubwc_fmt(out_fmt)) {
600                 inst->opb_buftype = HFI_BUFFER_OUTPUT2;
601                 inst->opb_fmt = out2_fmt;
602                 inst->dpb_buftype = HFI_BUFFER_OUTPUT;
603                 inst->dpb_fmt = out_fmt;
604         } else if (is_ubwc_fmt(out2_fmt)) {
605                 inst->opb_buftype = HFI_BUFFER_OUTPUT;
606                 inst->opb_fmt = out_fmt;
607                 inst->dpb_buftype = HFI_BUFFER_OUTPUT2;
608                 inst->dpb_fmt = out2_fmt;
609         } else {
610                 inst->opb_buftype = HFI_BUFFER_OUTPUT;
611                 inst->opb_fmt = out_fmt;
612                 inst->dpb_buftype = 0;
613                 inst->dpb_fmt = 0;
614         }
615
616         ret = venus_helper_set_raw_format(inst, inst->opb_fmt,
617                                           inst->opb_buftype);
618         if (ret)
619                 return ret;
620
621         if (inst->dpb_fmt) {
622                 ret = venus_helper_set_multistream(inst, false, true);
623                 if (ret)
624                         return ret;
625
626                 ret = venus_helper_set_raw_format(inst, inst->dpb_fmt,
627                                                   inst->dpb_buftype);
628                 if (ret)
629                         return ret;
630
631                 ret = venus_helper_set_output_resolution(inst, width, height,
632                                                          HFI_BUFFER_OUTPUT2);
633                 if (ret)
634                         return ret;
635         }
636
637         if (IS_V3(core) || IS_V4(core)) {
638                 if (inst->output2_buf_size) {
639                         ret = venus_helper_set_bufsize(inst,
640                                                        inst->output2_buf_size,
641                                                        HFI_BUFFER_OUTPUT2);
642                         if (ret)
643                                 return ret;
644                 }
645
646                 if (inst->output_buf_size) {
647                         ret = venus_helper_set_bufsize(inst,
648                                                        inst->output_buf_size,
649                                                        HFI_BUFFER_OUTPUT);
650                         if (ret)
651                                 return ret;
652                 }
653         }
654
655         ret = venus_helper_set_dyn_bufmode(inst);
656         if (ret)
657                 return ret;
658
659         return 0;
660 }
661
662 static int vdec_session_init(struct venus_inst *inst)
663 {
664         int ret;
665
666         ret = hfi_session_init(inst, inst->fmt_out->pixfmt);
667         if (ret == -EINVAL)
668                 return 0;
669         else if (ret)
670                 return ret;
671
672         ret = venus_helper_set_input_resolution(inst, frame_width_min(inst),
673                                                 frame_height_min(inst));
674         if (ret)
675                 goto deinit;
676
677         return 0;
678 deinit:
679         hfi_session_deinit(inst);
680         return ret;
681 }
682
683 static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num,
684                             unsigned int *out_num)
685 {
686         enum hfi_version ver = inst->core->res->hfi_version;
687         struct hfi_buffer_requirements bufreq;
688         int ret;
689
690         *in_num = *out_num = 0;
691
692         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
693         if (ret)
694                 return ret;
695
696         *in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
697
698         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
699         if (ret)
700                 return ret;
701
702         *out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
703
704         return 0;
705 }
706
707 static int vdec_queue_setup(struct vb2_queue *q,
708                             unsigned int *num_buffers, unsigned int *num_planes,
709                             unsigned int sizes[], struct device *alloc_devs[])
710 {
711         struct venus_inst *inst = vb2_get_drv_priv(q);
712         unsigned int in_num, out_num;
713         int ret = 0;
714
715         if (*num_planes) {
716                 unsigned int output_buf_size = venus_helper_get_opb_size(inst);
717
718                 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
719                     *num_planes != inst->fmt_out->num_planes)
720                         return -EINVAL;
721
722                 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
723                     *num_planes != inst->fmt_cap->num_planes)
724                         return -EINVAL;
725
726                 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
727                     sizes[0] < inst->input_buf_size)
728                         return -EINVAL;
729
730                 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
731                     sizes[0] < output_buf_size)
732                         return -EINVAL;
733
734                 return 0;
735         }
736
737         ret = vdec_session_init(inst);
738         if (ret)
739                 return ret;
740
741         ret = vdec_num_buffers(inst, &in_num, &out_num);
742         if (ret)
743                 return ret;
744
745         switch (q->type) {
746         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
747                 *num_planes = inst->fmt_out->num_planes;
748                 sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
749                                                     inst->out_width,
750                                                     inst->out_height);
751                 sizes[0] = max(sizes[0], inst->input_buf_size);
752                 inst->input_buf_size = sizes[0];
753                 *num_buffers = max(*num_buffers, in_num);
754                 inst->num_input_bufs = *num_buffers;
755                 inst->num_output_bufs = out_num;
756                 break;
757         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
758                 *num_planes = inst->fmt_cap->num_planes;
759                 sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
760                                                     inst->width,
761                                                     inst->height);
762                 inst->output_buf_size = sizes[0];
763                 *num_buffers = max(*num_buffers, out_num);
764                 inst->num_output_bufs = *num_buffers;
765
766                 mutex_lock(&inst->lock);
767                 if (inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP)
768                         inst->codec_state = VENUS_DEC_STATE_STOPPED;
769                 mutex_unlock(&inst->lock);
770                 break;
771         default:
772                 ret = -EINVAL;
773                 break;
774         }
775
776         return ret;
777 }
778
779 static int vdec_verify_conf(struct venus_inst *inst)
780 {
781         enum hfi_version ver = inst->core->res->hfi_version;
782         struct hfi_buffer_requirements bufreq;
783         int ret;
784
785         if (!inst->num_input_bufs || !inst->num_output_bufs)
786                 return -EINVAL;
787
788         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
789         if (ret)
790                 return ret;
791
792         if (inst->num_output_bufs < bufreq.count_actual ||
793             inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
794                 return -EINVAL;
795
796         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
797         if (ret)
798                 return ret;
799
800         if (inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
801                 return -EINVAL;
802
803         return 0;
804 }
805
806 static int vdec_start_capture(struct venus_inst *inst)
807 {
808         int ret;
809
810         if (!inst->streamon_out)
811                 return 0;
812
813         if (inst->codec_state == VENUS_DEC_STATE_DECODING) {
814                 if (inst->reconfig)
815                         goto reconfigure;
816
817                 venus_helper_queue_dpb_bufs(inst);
818                 venus_helper_process_initial_cap_bufs(inst);
819                 inst->streamon_cap = 1;
820                 return 0;
821         }
822
823         if (inst->codec_state != VENUS_DEC_STATE_STOPPED)
824                 return 0;
825
826 reconfigure:
827         ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
828         if (ret)
829                 return ret;
830
831         ret = vdec_output_conf(inst);
832         if (ret)
833                 return ret;
834
835         ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
836                                         VB2_MAX_FRAME, VB2_MAX_FRAME);
837         if (ret)
838                 return ret;
839
840         ret = venus_helper_intbufs_realloc(inst);
841         if (ret)
842                 goto err;
843
844         ret = venus_helper_alloc_dpb_bufs(inst);
845         if (ret)
846                 goto err;
847
848         ret = venus_helper_queue_dpb_bufs(inst);
849         if (ret)
850                 goto free_dpb_bufs;
851
852         ret = venus_helper_process_initial_cap_bufs(inst);
853         if (ret)
854                 goto free_dpb_bufs;
855
856         venus_helper_load_scale_clocks(inst->core);
857
858         ret = hfi_session_continue(inst);
859         if (ret)
860                 goto free_dpb_bufs;
861
862         inst->codec_state = VENUS_DEC_STATE_DECODING;
863
864         inst->streamon_cap = 1;
865         inst->sequence_cap = 0;
866         inst->reconfig = false;
867
868         return 0;
869
870 free_dpb_bufs:
871         venus_helper_free_dpb_bufs(inst);
872 err:
873         return ret;
874 }
875
876 static int vdec_start_output(struct venus_inst *inst)
877 {
878         int ret;
879
880         if (inst->codec_state == VENUS_DEC_STATE_SEEK) {
881                 ret = venus_helper_process_initial_out_bufs(inst);
882                 inst->codec_state = VENUS_DEC_STATE_DECODING;
883                 goto done;
884         }
885
886         if (inst->codec_state == VENUS_DEC_STATE_INIT ||
887             inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) {
888                 ret = venus_helper_process_initial_out_bufs(inst);
889                 goto done;
890         }
891
892         if (inst->codec_state != VENUS_DEC_STATE_DEINIT)
893                 return -EINVAL;
894
895         venus_helper_init_instance(inst);
896         inst->sequence_out = 0;
897         inst->reconfig = false;
898
899         ret = vdec_set_properties(inst);
900         if (ret)
901                 return ret;
902
903         ret = vdec_output_conf(inst);
904         if (ret)
905                 return ret;
906
907         ret = vdec_verify_conf(inst);
908         if (ret)
909                 return ret;
910
911         ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
912                                         VB2_MAX_FRAME, VB2_MAX_FRAME);
913         if (ret)
914                 return ret;
915
916         ret = venus_helper_vb2_start_streaming(inst);
917         if (ret)
918                 return ret;
919
920         ret = venus_helper_process_initial_out_bufs(inst);
921         if (ret)
922                 return ret;
923
924         inst->codec_state = VENUS_DEC_STATE_INIT;
925
926 done:
927         inst->streamon_out = 1;
928         return ret;
929 }
930
931 static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
932 {
933         struct venus_inst *inst = vb2_get_drv_priv(q);
934         int ret;
935
936         mutex_lock(&inst->lock);
937
938         if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
939                 ret = vdec_start_capture(inst);
940         else
941                 ret = vdec_start_output(inst);
942
943         if (ret)
944                 goto error;
945
946         mutex_unlock(&inst->lock);
947         return 0;
948
949 error:
950         venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED);
951         mutex_unlock(&inst->lock);
952         return ret;
953 }
954
955 static void vdec_cancel_dst_buffers(struct venus_inst *inst)
956 {
957         struct vb2_v4l2_buffer *buf;
958
959         while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
960                 v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
961 }
962
963 static int vdec_stop_capture(struct venus_inst *inst)
964 {
965         int ret = 0;
966
967         switch (inst->codec_state) {
968         case VENUS_DEC_STATE_DECODING:
969                 ret = hfi_session_flush(inst, HFI_FLUSH_ALL);
970                 /* fallthrough */
971         case VENUS_DEC_STATE_DRAIN:
972                 vdec_cancel_dst_buffers(inst);
973                 inst->codec_state = VENUS_DEC_STATE_STOPPED;
974                 break;
975         case VENUS_DEC_STATE_DRC:
976                 ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
977                 vdec_cancel_dst_buffers(inst);
978                 inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
979                 INIT_LIST_HEAD(&inst->registeredbufs);
980                 venus_helper_free_dpb_bufs(inst);
981                 break;
982         default:
983                 return 0;
984         }
985
986         return ret;
987 }
988
989 static int vdec_stop_output(struct venus_inst *inst)
990 {
991         int ret = 0;
992
993         switch (inst->codec_state) {
994         case VENUS_DEC_STATE_DECODING:
995         case VENUS_DEC_STATE_DRAIN:
996         case VENUS_DEC_STATE_STOPPED:
997                 ret = hfi_session_flush(inst, HFI_FLUSH_ALL);
998                 inst->codec_state = VENUS_DEC_STATE_SEEK;
999                 break;
1000         case VENUS_DEC_STATE_INIT:
1001         case VENUS_DEC_STATE_CAPTURE_SETUP:
1002                 ret = hfi_session_flush(inst, HFI_FLUSH_INPUT);
1003                 break;
1004         default:
1005                 break;
1006         }
1007
1008         return ret;
1009 }
1010
1011 static void vdec_stop_streaming(struct vb2_queue *q)
1012 {
1013         struct venus_inst *inst = vb2_get_drv_priv(q);
1014         int ret = -EINVAL;
1015
1016         mutex_lock(&inst->lock);
1017
1018         if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1019                 ret = vdec_stop_capture(inst);
1020         else
1021                 ret = vdec_stop_output(inst);
1022
1023         venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR);
1024
1025         if (ret)
1026                 goto unlock;
1027
1028         if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1029                 inst->streamon_out = 0;
1030         else
1031                 inst->streamon_cap = 0;
1032
1033 unlock:
1034         mutex_unlock(&inst->lock);
1035 }
1036
1037 static void vdec_session_release(struct venus_inst *inst)
1038 {
1039         struct venus_core *core = inst->core;
1040         int ret, abort = 0;
1041
1042         mutex_lock(&inst->lock);
1043
1044         inst->codec_state = VENUS_DEC_STATE_DEINIT;
1045
1046         ret = hfi_session_stop(inst);
1047         abort = (ret && ret != -EINVAL) ? 1 : 0;
1048         ret = hfi_session_unload_res(inst);
1049         abort = (ret && ret != -EINVAL) ? 1 : 0;
1050         ret = venus_helper_unregister_bufs(inst);
1051         abort = (ret && ret != -EINVAL) ? 1 : 0;
1052         ret = venus_helper_intbufs_free(inst);
1053         abort = (ret && ret != -EINVAL) ? 1 : 0;
1054         ret = hfi_session_deinit(inst);
1055         abort = (ret && ret != -EINVAL) ? 1 : 0;
1056
1057         if (inst->session_error || core->sys_error)
1058                 abort = 1;
1059
1060         if (abort)
1061                 hfi_session_abort(inst);
1062
1063         venus_helper_free_dpb_bufs(inst);
1064         venus_helper_load_scale_clocks(core);
1065         INIT_LIST_HEAD(&inst->registeredbufs);
1066
1067         mutex_unlock(&inst->lock);
1068 }
1069
1070 static int vdec_buf_init(struct vb2_buffer *vb)
1071 {
1072         struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1073
1074         inst->buf_count++;
1075
1076         return venus_helper_vb2_buf_init(vb);
1077 }
1078
1079 static void vdec_buf_cleanup(struct vb2_buffer *vb)
1080 {
1081         struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1082
1083         inst->buf_count--;
1084         if (!inst->buf_count)
1085                 vdec_session_release(inst);
1086 }
1087
1088 static const struct vb2_ops vdec_vb2_ops = {
1089         .queue_setup = vdec_queue_setup,
1090         .buf_init = vdec_buf_init,
1091         .buf_cleanup = vdec_buf_cleanup,
1092         .buf_prepare = venus_helper_vb2_buf_prepare,
1093         .start_streaming = vdec_start_streaming,
1094         .stop_streaming = vdec_stop_streaming,
1095         .buf_queue = venus_helper_vb2_buf_queue,
1096 };
1097
1098 static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
1099                           u32 tag, u32 bytesused, u32 data_offset, u32 flags,
1100                           u32 hfi_flags, u64 timestamp_us)
1101 {
1102         enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
1103         struct vb2_v4l2_buffer *vbuf;
1104         struct vb2_buffer *vb;
1105         unsigned int type;
1106
1107         if (buf_type == HFI_BUFFER_INPUT)
1108                 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1109         else
1110                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1111
1112         vbuf = venus_helper_find_buf(inst, type, tag);
1113         if (!vbuf)
1114                 return;
1115
1116         vbuf->flags = flags;
1117         vbuf->field = V4L2_FIELD_NONE;
1118         vb = &vbuf->vb2_buf;
1119
1120         if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1121                 vb2_set_plane_payload(vb, 0, bytesused);
1122                 vb->planes[0].data_offset = data_offset;
1123                 vb->timestamp = timestamp_us * NSEC_PER_USEC;
1124                 vbuf->sequence = inst->sequence_cap++;
1125
1126                 if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
1127                         const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
1128
1129                         v4l2_event_queue_fh(&inst->fh, &ev);
1130
1131                         if (inst->codec_state == VENUS_DEC_STATE_DRAIN)
1132                                 inst->codec_state = VENUS_DEC_STATE_STOPPED;
1133                 }
1134         } else {
1135                 vbuf->sequence = inst->sequence_out++;
1136         }
1137
1138         venus_helper_get_ts_metadata(inst, timestamp_us, vbuf);
1139
1140         if (hfi_flags & HFI_BUFFERFLAG_READONLY)
1141                 venus_helper_acquire_buf_ref(vbuf);
1142
1143         if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT)
1144                 state = VB2_BUF_STATE_ERROR;
1145
1146         if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) {
1147                 state = VB2_BUF_STATE_ERROR;
1148                 vb2_set_plane_payload(vb, 0, 0);
1149                 vb->timestamp = 0;
1150         }
1151
1152         v4l2_m2m_buf_done(vbuf, state);
1153 }
1154
1155 static void vdec_event_change(struct venus_inst *inst,
1156                               struct hfi_event_data *ev_data, bool sufficient)
1157 {
1158         static const struct v4l2_event ev = {
1159                 .type = V4L2_EVENT_SOURCE_CHANGE,
1160                 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION };
1161         struct device *dev = inst->core->dev_dec;
1162         struct v4l2_format format = {};
1163
1164         mutex_lock(&inst->lock);
1165
1166         format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1167         format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt;
1168         format.fmt.pix_mp.width = ev_data->width;
1169         format.fmt.pix_mp.height = ev_data->height;
1170
1171         vdec_try_fmt_common(inst, &format);
1172
1173         inst->width = format.fmt.pix_mp.width;
1174         inst->height = format.fmt.pix_mp.height;
1175
1176         inst->out_width = ev_data->width;
1177         inst->out_height = ev_data->height;
1178
1179         dev_dbg(dev, "event %s sufficient resources (%ux%u)\n",
1180                 sufficient ? "" : "not", ev_data->width, ev_data->height);
1181
1182         if (sufficient) {
1183                 hfi_session_continue(inst);
1184         } else {
1185                 switch (inst->codec_state) {
1186                 case VENUS_DEC_STATE_INIT:
1187                         inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
1188                         break;
1189                 case VENUS_DEC_STATE_DECODING:
1190                         inst->codec_state = VENUS_DEC_STATE_DRC;
1191                         break;
1192                 default:
1193                         break;
1194                 }
1195         }
1196
1197         inst->reconfig = true;
1198         v4l2_event_queue_fh(&inst->fh, &ev);
1199         wake_up(&inst->reconf_wait);
1200
1201         mutex_unlock(&inst->lock);
1202 }
1203
1204 static void vdec_event_notify(struct venus_inst *inst, u32 event,
1205                               struct hfi_event_data *data)
1206 {
1207         struct venus_core *core = inst->core;
1208         struct device *dev = core->dev_dec;
1209
1210         switch (event) {
1211         case EVT_SESSION_ERROR:
1212                 inst->session_error = true;
1213                 dev_err(dev, "dec: event session error %x\n", inst->error);
1214                 break;
1215         case EVT_SYS_EVENT_CHANGE:
1216                 switch (data->event_type) {
1217                 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
1218                         vdec_event_change(inst, data, true);
1219                         break;
1220                 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
1221                         vdec_event_change(inst, data, false);
1222                         break;
1223                 case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
1224                         venus_helper_release_buf_ref(inst, data->tag);
1225                         break;
1226                 default:
1227                         break;
1228                 }
1229                 break;
1230         default:
1231                 break;
1232         }
1233 }
1234
1235 static const struct hfi_inst_ops vdec_hfi_ops = {
1236         .buf_done = vdec_buf_done,
1237         .event_notify = vdec_event_notify,
1238 };
1239
1240 static void vdec_inst_init(struct venus_inst *inst)
1241 {
1242         inst->hfi_codec = HFI_VIDEO_CODEC_H264;
1243         inst->fmt_out = &vdec_formats[6];
1244         inst->fmt_cap = &vdec_formats[0];
1245         inst->width = frame_width_min(inst);
1246         inst->height = ALIGN(frame_height_min(inst), 32);
1247         inst->out_width = frame_width_min(inst);
1248         inst->out_height = frame_height_min(inst);
1249         inst->fps = 30;
1250         inst->timeperframe.numerator = 1;
1251         inst->timeperframe.denominator = 30;
1252         inst->opb_buftype = HFI_BUFFER_OUTPUT;
1253 }
1254
1255 static void vdec_m2m_device_run(void *priv)
1256 {
1257 }
1258
1259 static const struct v4l2_m2m_ops vdec_m2m_ops = {
1260         .device_run = vdec_m2m_device_run,
1261         .job_abort = venus_helper_m2m_job_abort,
1262 };
1263
1264 static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
1265                           struct vb2_queue *dst_vq)
1266 {
1267         struct venus_inst *inst = priv;
1268         int ret;
1269
1270         src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1271         src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
1272         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1273         src_vq->ops = &vdec_vb2_ops;
1274         src_vq->mem_ops = &vb2_dma_sg_memops;
1275         src_vq->drv_priv = inst;
1276         src_vq->buf_struct_size = sizeof(struct venus_buffer);
1277         src_vq->allow_zero_bytesused = 1;
1278         src_vq->min_buffers_needed = 0;
1279         src_vq->dev = inst->core->dev;
1280         ret = vb2_queue_init(src_vq);
1281         if (ret)
1282                 return ret;
1283
1284         dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1285         dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
1286         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1287         dst_vq->ops = &vdec_vb2_ops;
1288         dst_vq->mem_ops = &vb2_dma_sg_memops;
1289         dst_vq->drv_priv = inst;
1290         dst_vq->buf_struct_size = sizeof(struct venus_buffer);
1291         dst_vq->allow_zero_bytesused = 1;
1292         dst_vq->min_buffers_needed = 0;
1293         dst_vq->dev = inst->core->dev;
1294         ret = vb2_queue_init(dst_vq);
1295         if (ret) {
1296                 vb2_queue_release(src_vq);
1297                 return ret;
1298         }
1299
1300         return 0;
1301 }
1302
1303 static int vdec_open(struct file *file)
1304 {
1305         struct venus_core *core = video_drvdata(file);
1306         struct venus_inst *inst;
1307         int ret;
1308
1309         inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1310         if (!inst)
1311                 return -ENOMEM;
1312
1313         INIT_LIST_HEAD(&inst->dpbbufs);
1314         INIT_LIST_HEAD(&inst->registeredbufs);
1315         INIT_LIST_HEAD(&inst->internalbufs);
1316         INIT_LIST_HEAD(&inst->list);
1317         mutex_init(&inst->lock);
1318
1319         inst->core = core;
1320         inst->session_type = VIDC_SESSION_TYPE_DEC;
1321         inst->num_output_bufs = 1;
1322         inst->codec_state = VENUS_DEC_STATE_DEINIT;
1323         inst->buf_count = 0;
1324         init_waitqueue_head(&inst->reconf_wait);
1325         venus_helper_init_instance(inst);
1326
1327         ret = pm_runtime_get_sync(core->dev_dec);
1328         if (ret < 0)
1329                 goto err_free_inst;
1330
1331         ret = vdec_ctrl_init(inst);
1332         if (ret)
1333                 goto err_put_sync;
1334
1335         ret = hfi_session_create(inst, &vdec_hfi_ops);
1336         if (ret)
1337                 goto err_ctrl_deinit;
1338
1339         vdec_inst_init(inst);
1340
1341         /*
1342          * create m2m device for every instance, the m2m context scheduling
1343          * is made by firmware side so we do not need to care about.
1344          */
1345         inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops);
1346         if (IS_ERR(inst->m2m_dev)) {
1347                 ret = PTR_ERR(inst->m2m_dev);
1348                 goto err_session_destroy;
1349         }
1350
1351         inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
1352         if (IS_ERR(inst->m2m_ctx)) {
1353                 ret = PTR_ERR(inst->m2m_ctx);
1354                 goto err_m2m_release;
1355         }
1356
1357         v4l2_fh_init(&inst->fh, core->vdev_dec);
1358
1359         inst->fh.ctrl_handler = &inst->ctrl_handler;
1360         v4l2_fh_add(&inst->fh);
1361         inst->fh.m2m_ctx = inst->m2m_ctx;
1362         file->private_data = &inst->fh;
1363
1364         return 0;
1365
1366 err_m2m_release:
1367         v4l2_m2m_release(inst->m2m_dev);
1368 err_session_destroy:
1369         hfi_session_destroy(inst);
1370 err_ctrl_deinit:
1371         vdec_ctrl_deinit(inst);
1372 err_put_sync:
1373         pm_runtime_put_sync(core->dev_dec);
1374 err_free_inst:
1375         kfree(inst);
1376         return ret;
1377 }
1378
1379 static int vdec_close(struct file *file)
1380 {
1381         struct venus_inst *inst = to_inst(file);
1382
1383         v4l2_m2m_ctx_release(inst->m2m_ctx);
1384         v4l2_m2m_release(inst->m2m_dev);
1385         vdec_ctrl_deinit(inst);
1386         hfi_session_destroy(inst);
1387         mutex_destroy(&inst->lock);
1388         v4l2_fh_del(&inst->fh);
1389         v4l2_fh_exit(&inst->fh);
1390
1391         pm_runtime_put_sync(inst->core->dev_dec);
1392
1393         kfree(inst);
1394         return 0;
1395 }
1396
1397 static const struct v4l2_file_operations vdec_fops = {
1398         .owner = THIS_MODULE,
1399         .open = vdec_open,
1400         .release = vdec_close,
1401         .unlocked_ioctl = video_ioctl2,
1402         .poll = v4l2_m2m_fop_poll,
1403         .mmap = v4l2_m2m_fop_mmap,
1404 #ifdef CONFIG_COMPAT
1405         .compat_ioctl32 = v4l2_compat_ioctl32,
1406 #endif
1407 };
1408
1409 static int vdec_probe(struct platform_device *pdev)
1410 {
1411         struct device *dev = &pdev->dev;
1412         struct video_device *vdev;
1413         struct venus_core *core;
1414         int ret;
1415
1416         if (!dev->parent)
1417                 return -EPROBE_DEFER;
1418
1419         core = dev_get_drvdata(dev->parent);
1420         if (!core)
1421                 return -EPROBE_DEFER;
1422
1423         if (IS_V3(core) || IS_V4(core)) {
1424                 core->core0_clk = devm_clk_get(dev, "core");
1425                 if (IS_ERR(core->core0_clk))
1426                         return PTR_ERR(core->core0_clk);
1427         }
1428
1429         if (IS_V4(core)) {
1430                 core->core0_bus_clk = devm_clk_get(dev, "bus");
1431                 if (IS_ERR(core->core0_bus_clk))
1432                         return PTR_ERR(core->core0_bus_clk);
1433         }
1434
1435         platform_set_drvdata(pdev, core);
1436
1437         vdev = video_device_alloc();
1438         if (!vdev)
1439                 return -ENOMEM;
1440
1441         strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
1442         vdev->release = video_device_release;
1443         vdev->fops = &vdec_fops;
1444         vdev->ioctl_ops = &vdec_ioctl_ops;
1445         vdev->vfl_dir = VFL_DIR_M2M;
1446         vdev->v4l2_dev = &core->v4l2_dev;
1447         vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1448
1449         ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1450         if (ret)
1451                 goto err_vdev_release;
1452
1453         core->vdev_dec = vdev;
1454         core->dev_dec = dev;
1455
1456         video_set_drvdata(vdev, core);
1457         pm_runtime_enable(dev);
1458
1459         return 0;
1460
1461 err_vdev_release:
1462         video_device_release(vdev);
1463         return ret;
1464 }
1465
1466 static int vdec_remove(struct platform_device *pdev)
1467 {
1468         struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
1469
1470         video_unregister_device(core->vdev_dec);
1471         pm_runtime_disable(core->dev_dec);
1472
1473         return 0;
1474 }
1475
1476 static __maybe_unused int vdec_runtime_suspend(struct device *dev)
1477 {
1478         struct venus_core *core = dev_get_drvdata(dev);
1479         int ret;
1480
1481         if (IS_V1(core))
1482                 return 0;
1483
1484         ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true);
1485         if (ret)
1486                 return ret;
1487
1488         if (IS_V4(core))
1489                 clk_disable_unprepare(core->core0_bus_clk);
1490
1491         clk_disable_unprepare(core->core0_clk);
1492
1493         return venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1494 }
1495
1496 static __maybe_unused int vdec_runtime_resume(struct device *dev)
1497 {
1498         struct venus_core *core = dev_get_drvdata(dev);
1499         int ret;
1500
1501         if (IS_V1(core))
1502                 return 0;
1503
1504         ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true);
1505         if (ret)
1506                 return ret;
1507
1508         ret = clk_prepare_enable(core->core0_clk);
1509         if (ret)
1510                 goto err_power_disable;
1511
1512         if (IS_V4(core))
1513                 ret = clk_prepare_enable(core->core0_bus_clk);
1514
1515         if (ret)
1516                 goto err_unprepare_core0;
1517
1518         return venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1519
1520 err_unprepare_core0:
1521         clk_disable_unprepare(core->core0_clk);
1522 err_power_disable:
1523         venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1524         return ret;
1525 }
1526
1527 static const struct dev_pm_ops vdec_pm_ops = {
1528         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1529                                 pm_runtime_force_resume)
1530         SET_RUNTIME_PM_OPS(vdec_runtime_suspend, vdec_runtime_resume, NULL)
1531 };
1532
1533 static const struct of_device_id vdec_dt_match[] = {
1534         { .compatible = "venus-decoder" },
1535         { }
1536 };
1537 MODULE_DEVICE_TABLE(of, vdec_dt_match);
1538
1539 static struct platform_driver qcom_venus_dec_driver = {
1540         .probe = vdec_probe,
1541         .remove = vdec_remove,
1542         .driver = {
1543                 .name = "qcom-venus-decoder",
1544                 .of_match_table = vdec_dt_match,
1545                 .pm = &vdec_pm_ops,
1546         },
1547 };
1548 module_platform_driver(qcom_venus_dec_driver);
1549
1550 MODULE_ALIAS("platform:qcom-venus-decoder");
1551 MODULE_DESCRIPTION("Qualcomm Venus video decoder driver");
1552 MODULE_LICENSE("GPL v2");