Linux-libre 5.3-gnu
[librecmc/linux-libre.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
137         memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
138         memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
139
140         fmt = find_format(inst, pixmp->pixelformat, f->type);
141         if (!fmt) {
142                 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
143                         pixmp->pixelformat = V4L2_PIX_FMT_NV12;
144                 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
145                         pixmp->pixelformat = V4L2_PIX_FMT_H264;
146                 else
147                         return NULL;
148                 fmt = find_format(inst, pixmp->pixelformat, f->type);
149         }
150
151         pixmp->width = clamp(pixmp->width, frame_width_min(inst),
152                              frame_width_max(inst));
153         pixmp->height = clamp(pixmp->height, frame_height_min(inst),
154                               frame_height_max(inst));
155
156         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
157                 pixmp->height = ALIGN(pixmp->height, 32);
158
159         if (pixmp->field == V4L2_FIELD_ANY)
160                 pixmp->field = V4L2_FIELD_NONE;
161         pixmp->num_planes = fmt->num_planes;
162         pixmp->flags = 0;
163
164         pfmt[0].sizeimage = venus_helper_get_framesz(pixmp->pixelformat,
165                                                      pixmp->width,
166                                                      pixmp->height);
167
168         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
169                 pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
170         else
171                 pfmt[0].bytesperline = 0;
172
173         return fmt;
174 }
175
176 static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
177 {
178         struct venus_inst *inst = to_inst(file);
179
180         vdec_try_fmt_common(inst, f);
181
182         return 0;
183 }
184
185 static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
186 {
187         struct venus_inst *inst = to_inst(file);
188         const struct venus_format *fmt = NULL;
189         struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
190
191         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
192                 fmt = inst->fmt_cap;
193         else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
194                 fmt = inst->fmt_out;
195
196         if (inst->reconfig) {
197                 struct v4l2_format format = {};
198
199                 inst->out_width = inst->reconfig_width;
200                 inst->out_height = inst->reconfig_height;
201                 inst->reconfig = false;
202
203                 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
204                 format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt;
205                 format.fmt.pix_mp.width = inst->out_width;
206                 format.fmt.pix_mp.height = inst->out_height;
207
208                 vdec_try_fmt_common(inst, &format);
209
210                 inst->width = format.fmt.pix_mp.width;
211                 inst->height = format.fmt.pix_mp.height;
212         }
213
214         pixmp->pixelformat = fmt->pixfmt;
215
216         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
217                 pixmp->width = inst->width;
218                 pixmp->height = inst->height;
219                 pixmp->colorspace = inst->colorspace;
220                 pixmp->ycbcr_enc = inst->ycbcr_enc;
221                 pixmp->quantization = inst->quantization;
222                 pixmp->xfer_func = inst->xfer_func;
223         } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
224                 pixmp->width = inst->out_width;
225                 pixmp->height = inst->out_height;
226         }
227
228         vdec_try_fmt_common(inst, f);
229
230         return 0;
231 }
232
233 static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
234 {
235         struct venus_inst *inst = to_inst(file);
236         struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
237         struct v4l2_pix_format_mplane orig_pixmp;
238         const struct venus_format *fmt;
239         struct v4l2_format format;
240         u32 pixfmt_out = 0, pixfmt_cap = 0;
241
242         orig_pixmp = *pixmp;
243
244         fmt = vdec_try_fmt_common(inst, f);
245
246         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
247                 pixfmt_out = pixmp->pixelformat;
248                 pixfmt_cap = inst->fmt_cap->pixfmt;
249         } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
250                 pixfmt_cap = pixmp->pixelformat;
251                 pixfmt_out = inst->fmt_out->pixfmt;
252         }
253
254         memset(&format, 0, sizeof(format));
255
256         format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
257         format.fmt.pix_mp.pixelformat = pixfmt_out;
258         format.fmt.pix_mp.width = orig_pixmp.width;
259         format.fmt.pix_mp.height = orig_pixmp.height;
260         vdec_try_fmt_common(inst, &format);
261
262         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
263                 inst->out_width = format.fmt.pix_mp.width;
264                 inst->out_height = format.fmt.pix_mp.height;
265                 inst->colorspace = pixmp->colorspace;
266                 inst->ycbcr_enc = pixmp->ycbcr_enc;
267                 inst->quantization = pixmp->quantization;
268                 inst->xfer_func = pixmp->xfer_func;
269         }
270
271         memset(&format, 0, sizeof(format));
272
273         format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
274         format.fmt.pix_mp.pixelformat = pixfmt_cap;
275         format.fmt.pix_mp.width = orig_pixmp.width;
276         format.fmt.pix_mp.height = orig_pixmp.height;
277         vdec_try_fmt_common(inst, &format);
278
279         inst->width = format.fmt.pix_mp.width;
280         inst->height = format.fmt.pix_mp.height;
281
282         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
283                 inst->fmt_out = fmt;
284         else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
285                 inst->fmt_cap = fmt;
286
287         return 0;
288 }
289
290 static int
291 vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
292 {
293         struct venus_inst *inst = to_inst(file);
294
295         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
296             s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
297                 return -EINVAL;
298
299         switch (s->target) {
300         case V4L2_SEL_TGT_CROP_BOUNDS:
301         case V4L2_SEL_TGT_CROP_DEFAULT:
302         case V4L2_SEL_TGT_CROP:
303                 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
304                         return -EINVAL;
305                 s->r.width = inst->out_width;
306                 s->r.height = inst->out_height;
307                 break;
308         case V4L2_SEL_TGT_COMPOSE_BOUNDS:
309         case V4L2_SEL_TGT_COMPOSE_PADDED:
310                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
311                         return -EINVAL;
312                 s->r.width = inst->width;
313                 s->r.height = inst->height;
314                 break;
315         case V4L2_SEL_TGT_COMPOSE_DEFAULT:
316         case V4L2_SEL_TGT_COMPOSE:
317                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
318                         return -EINVAL;
319                 s->r.width = inst->out_width;
320                 s->r.height = inst->out_height;
321                 break;
322         default:
323                 return -EINVAL;
324         }
325
326         s->r.top = 0;
327         s->r.left = 0;
328
329         return 0;
330 }
331
332 static int
333 vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
334 {
335         strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
336         strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
337         strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
338
339         return 0;
340 }
341
342 static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
343 {
344         struct venus_inst *inst = to_inst(file);
345         const struct venus_format *fmt;
346
347         memset(f->reserved, 0, sizeof(f->reserved));
348
349         fmt = find_format_by_index(inst, f->index, f->type);
350         if (!fmt)
351                 return -EINVAL;
352
353         f->pixelformat = fmt->pixfmt;
354
355         return 0;
356 }
357
358 static int vdec_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
359 {
360         struct venus_inst *inst = to_inst(file);
361         struct v4l2_captureparm *cap = &a->parm.capture;
362         struct v4l2_fract *timeperframe = &cap->timeperframe;
363         u64 us_per_frame, fps;
364
365         if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
366             a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
367                 return -EINVAL;
368
369         memset(cap->reserved, 0, sizeof(cap->reserved));
370         if (!timeperframe->denominator)
371                 timeperframe->denominator = inst->timeperframe.denominator;
372         if (!timeperframe->numerator)
373                 timeperframe->numerator = inst->timeperframe.numerator;
374         cap->readbuffers = 0;
375         cap->extendedmode = 0;
376         cap->capability = V4L2_CAP_TIMEPERFRAME;
377         us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
378         do_div(us_per_frame, timeperframe->denominator);
379
380         if (!us_per_frame)
381                 return -EINVAL;
382
383         fps = (u64)USEC_PER_SEC;
384         do_div(fps, us_per_frame);
385
386         inst->fps = fps;
387         inst->timeperframe = *timeperframe;
388
389         return 0;
390 }
391
392 static int vdec_enum_framesizes(struct file *file, void *fh,
393                                 struct v4l2_frmsizeenum *fsize)
394 {
395         struct venus_inst *inst = to_inst(file);
396         const struct venus_format *fmt;
397
398         fmt = find_format(inst, fsize->pixel_format,
399                           V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
400         if (!fmt) {
401                 fmt = find_format(inst, fsize->pixel_format,
402                                   V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
403                 if (!fmt)
404                         return -EINVAL;
405         }
406
407         if (fsize->index)
408                 return -EINVAL;
409
410         fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
411
412         fsize->stepwise.min_width = frame_width_min(inst);
413         fsize->stepwise.max_width = frame_width_max(inst);
414         fsize->stepwise.step_width = frame_width_step(inst);
415         fsize->stepwise.min_height = frame_height_min(inst);
416         fsize->stepwise.max_height = frame_height_max(inst);
417         fsize->stepwise.step_height = frame_height_step(inst);
418
419         return 0;
420 }
421
422 static int vdec_subscribe_event(struct v4l2_fh *fh,
423                                 const struct v4l2_event_subscription *sub)
424 {
425         switch (sub->type) {
426         case V4L2_EVENT_EOS:
427                 return v4l2_event_subscribe(fh, sub, 2, NULL);
428         case V4L2_EVENT_SOURCE_CHANGE:
429                 return v4l2_src_change_event_subscribe(fh, sub);
430         case V4L2_EVENT_CTRL:
431                 return v4l2_ctrl_subscribe_event(fh, sub);
432         default:
433                 return -EINVAL;
434         }
435 }
436
437 static int
438 vdec_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
439 {
440         switch (cmd->cmd) {
441         case V4L2_DEC_CMD_STOP:
442                 if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK)
443                         return -EINVAL;
444                 break;
445         default:
446                 return -EINVAL;
447         }
448
449         return 0;
450 }
451
452 static int
453 vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
454 {
455         struct venus_inst *inst = to_inst(file);
456         struct hfi_frame_data fdata = {0};
457         int ret;
458
459         ret = vdec_try_decoder_cmd(file, fh, cmd);
460         if (ret)
461                 return ret;
462
463         mutex_lock(&inst->lock);
464
465         /*
466          * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder
467          * input to signal EOS.
468          */
469         if (!(inst->streamon_out & inst->streamon_cap))
470                 goto unlock;
471
472         fdata.buffer_type = HFI_BUFFER_INPUT;
473         fdata.flags |= HFI_BUFFERFLAG_EOS;
474         fdata.device_addr = 0xdeadbeef;
475
476         ret = hfi_session_process_buf(inst, &fdata);
477
478 unlock:
479         mutex_unlock(&inst->lock);
480         return ret;
481 }
482
483 static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
484         .vidioc_querycap = vdec_querycap,
485         .vidioc_enum_fmt_vid_cap = vdec_enum_fmt,
486         .vidioc_enum_fmt_vid_out = vdec_enum_fmt,
487         .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt,
488         .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt,
489         .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,
490         .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt,
491         .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,
492         .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,
493         .vidioc_g_selection = vdec_g_selection,
494         .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
495         .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
496         .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
497         .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
498         .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
499         .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
500         .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
501         .vidioc_streamon = v4l2_m2m_ioctl_streamon,
502         .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
503         .vidioc_s_parm = vdec_s_parm,
504         .vidioc_enum_framesizes = vdec_enum_framesizes,
505         .vidioc_subscribe_event = vdec_subscribe_event,
506         .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
507         .vidioc_try_decoder_cmd = vdec_try_decoder_cmd,
508         .vidioc_decoder_cmd = vdec_decoder_cmd,
509 };
510
511 static int vdec_set_properties(struct venus_inst *inst)
512 {
513         struct vdec_controls *ctr = &inst->controls.dec;
514         struct hfi_enable en = { .enable = 1 };
515         u32 ptype;
516         int ret;
517
518         if (ctr->post_loop_deb_mode) {
519                 ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
520                 ret = hfi_session_set_property(inst, ptype, &en);
521                 if (ret)
522                         return ret;
523         }
524
525         return 0;
526 }
527
528 #define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
529
530 static int vdec_output_conf(struct venus_inst *inst)
531 {
532         struct venus_core *core = inst->core;
533         struct hfi_enable en = { .enable = 1 };
534         u32 width = inst->out_width;
535         u32 height = inst->out_height;
536         u32 out_fmt, out2_fmt;
537         bool ubwc = false;
538         u32 ptype;
539         int ret;
540
541         ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
542         if (ret)
543                 return ret;
544
545         ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_1);
546         if (ret)
547                 return ret;
548
549         if (core->res->hfi_version == HFI_VERSION_1XX) {
550                 ptype = HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
551                 ret = hfi_session_set_property(inst, ptype, &en);
552                 if (ret)
553                         return ret;
554         }
555
556         /* Force searching UBWC formats for bigger then HD resolutions */
557         if (width > 1920 && height > ALIGN(1080, 32))
558                 ubwc = true;
559
560         /* For Venus v4 UBWC format is mandatory */
561         if (IS_V4(core))
562                 ubwc = true;
563
564         ret = venus_helper_get_out_fmts(inst, inst->fmt_cap->pixfmt, &out_fmt,
565                                         &out2_fmt, ubwc);
566         if (ret)
567                 return ret;
568
569         inst->output_buf_size =
570                         venus_helper_get_framesz_raw(out_fmt, width, height);
571         inst->output2_buf_size =
572                         venus_helper_get_framesz_raw(out2_fmt, width, height);
573
574         if (is_ubwc_fmt(out_fmt)) {
575                 inst->opb_buftype = HFI_BUFFER_OUTPUT2;
576                 inst->opb_fmt = out2_fmt;
577                 inst->dpb_buftype = HFI_BUFFER_OUTPUT;
578                 inst->dpb_fmt = out_fmt;
579         } else if (is_ubwc_fmt(out2_fmt)) {
580                 inst->opb_buftype = HFI_BUFFER_OUTPUT;
581                 inst->opb_fmt = out_fmt;
582                 inst->dpb_buftype = HFI_BUFFER_OUTPUT2;
583                 inst->dpb_fmt = out2_fmt;
584         } else {
585                 inst->opb_buftype = HFI_BUFFER_OUTPUT;
586                 inst->opb_fmt = out_fmt;
587                 inst->dpb_buftype = 0;
588                 inst->dpb_fmt = 0;
589         }
590
591         ret = venus_helper_set_raw_format(inst, inst->opb_fmt,
592                                           inst->opb_buftype);
593         if (ret)
594                 return ret;
595
596         if (inst->dpb_fmt) {
597                 ret = venus_helper_set_multistream(inst, false, true);
598                 if (ret)
599                         return ret;
600
601                 ret = venus_helper_set_raw_format(inst, inst->dpb_fmt,
602                                                   inst->dpb_buftype);
603                 if (ret)
604                         return ret;
605
606                 ret = venus_helper_set_output_resolution(inst, width, height,
607                                                          HFI_BUFFER_OUTPUT2);
608                 if (ret)
609                         return ret;
610         }
611
612         if (IS_V3(core) || IS_V4(core)) {
613                 if (inst->output2_buf_size) {
614                         ret = venus_helper_set_bufsize(inst,
615                                                        inst->output2_buf_size,
616                                                        HFI_BUFFER_OUTPUT2);
617                         if (ret)
618                                 return ret;
619                 }
620
621                 if (inst->output_buf_size) {
622                         ret = venus_helper_set_bufsize(inst,
623                                                        inst->output_buf_size,
624                                                        HFI_BUFFER_OUTPUT);
625                         if (ret)
626                                 return ret;
627                 }
628         }
629
630         ret = venus_helper_set_dyn_bufmode(inst);
631         if (ret)
632                 return ret;
633
634         return 0;
635 }
636
637 static int vdec_init_session(struct venus_inst *inst)
638 {
639         int ret;
640
641         ret = hfi_session_init(inst, inst->fmt_out->pixfmt);
642         if (ret)
643                 return ret;
644
645         ret = venus_helper_set_input_resolution(inst, inst->out_width,
646                                                 inst->out_height);
647         if (ret)
648                 goto deinit;
649
650         ret = venus_helper_set_color_format(inst, inst->fmt_cap->pixfmt);
651         if (ret)
652                 goto deinit;
653
654         return 0;
655 deinit:
656         hfi_session_deinit(inst);
657         return ret;
658 }
659
660 static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num,
661                             unsigned int *out_num)
662 {
663         enum hfi_version ver = inst->core->res->hfi_version;
664         struct hfi_buffer_requirements bufreq;
665         int ret;
666
667         *in_num = *out_num = 0;
668
669         ret = vdec_init_session(inst);
670         if (ret)
671                 return ret;
672
673         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
674         if (ret)
675                 goto deinit;
676
677         *in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
678
679         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
680         if (ret)
681                 goto deinit;
682
683         *out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
684
685 deinit:
686         hfi_session_deinit(inst);
687
688         return ret;
689 }
690
691 static int vdec_queue_setup(struct vb2_queue *q,
692                             unsigned int *num_buffers, unsigned int *num_planes,
693                             unsigned int sizes[], struct device *alloc_devs[])
694 {
695         struct venus_inst *inst = vb2_get_drv_priv(q);
696         unsigned int in_num, out_num;
697         int ret = 0;
698
699         if (*num_planes) {
700                 unsigned int output_buf_size = venus_helper_get_opb_size(inst);
701
702                 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
703                     *num_planes != inst->fmt_out->num_planes)
704                         return -EINVAL;
705
706                 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
707                     *num_planes != inst->fmt_cap->num_planes)
708                         return -EINVAL;
709
710                 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
711                     sizes[0] < inst->input_buf_size)
712                         return -EINVAL;
713
714                 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
715                     sizes[0] < output_buf_size)
716                         return -EINVAL;
717
718                 return 0;
719         }
720
721         ret = vdec_num_buffers(inst, &in_num, &out_num);
722         if (ret)
723                 return ret;
724
725         switch (q->type) {
726         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
727                 *num_planes = inst->fmt_out->num_planes;
728                 sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
729                                                     inst->out_width,
730                                                     inst->out_height);
731                 inst->input_buf_size = sizes[0];
732                 *num_buffers = max(*num_buffers, in_num);
733                 inst->num_input_bufs = *num_buffers;
734                 inst->num_output_bufs = out_num;
735                 break;
736         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
737                 *num_planes = inst->fmt_cap->num_planes;
738                 sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
739                                                     inst->width,
740                                                     inst->height);
741                 inst->output_buf_size = sizes[0];
742                 *num_buffers = max(*num_buffers, out_num);
743                 inst->num_output_bufs = *num_buffers;
744                 break;
745         default:
746                 ret = -EINVAL;
747                 break;
748         }
749
750         return ret;
751 }
752
753 static int vdec_verify_conf(struct venus_inst *inst)
754 {
755         enum hfi_version ver = inst->core->res->hfi_version;
756         struct hfi_buffer_requirements bufreq;
757         int ret;
758
759         if (!inst->num_input_bufs || !inst->num_output_bufs)
760                 return -EINVAL;
761
762         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
763         if (ret)
764                 return ret;
765
766         if (inst->num_output_bufs < bufreq.count_actual ||
767             inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
768                 return -EINVAL;
769
770         ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
771         if (ret)
772                 return ret;
773
774         if (inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
775                 return -EINVAL;
776
777         return 0;
778 }
779
780 static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
781 {
782         struct venus_inst *inst = vb2_get_drv_priv(q);
783         int ret;
784
785         mutex_lock(&inst->lock);
786
787         if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
788                 inst->streamon_out = 1;
789         else
790                 inst->streamon_cap = 1;
791
792         if (!(inst->streamon_out & inst->streamon_cap)) {
793                 mutex_unlock(&inst->lock);
794                 return 0;
795         }
796
797         venus_helper_init_instance(inst);
798
799         inst->reconfig = false;
800         inst->sequence_cap = 0;
801         inst->sequence_out = 0;
802
803         ret = vdec_init_session(inst);
804         if (ret)
805                 goto bufs_done;
806
807         ret = vdec_set_properties(inst);
808         if (ret)
809                 goto deinit_sess;
810
811         ret = vdec_output_conf(inst);
812         if (ret)
813                 goto deinit_sess;
814
815         ret = vdec_verify_conf(inst);
816         if (ret)
817                 goto deinit_sess;
818
819         ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
820                                         VB2_MAX_FRAME, VB2_MAX_FRAME);
821         if (ret)
822                 goto deinit_sess;
823
824         ret = venus_helper_alloc_dpb_bufs(inst);
825         if (ret)
826                 goto deinit_sess;
827
828         ret = venus_helper_vb2_start_streaming(inst);
829         if (ret)
830                 goto deinit_sess;
831
832         mutex_unlock(&inst->lock);
833
834         return 0;
835
836 deinit_sess:
837         hfi_session_deinit(inst);
838 bufs_done:
839         venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED);
840         if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
841                 inst->streamon_out = 0;
842         else
843                 inst->streamon_cap = 0;
844         mutex_unlock(&inst->lock);
845         return ret;
846 }
847
848 static const struct vb2_ops vdec_vb2_ops = {
849         .queue_setup = vdec_queue_setup,
850         .buf_init = venus_helper_vb2_buf_init,
851         .buf_prepare = venus_helper_vb2_buf_prepare,
852         .start_streaming = vdec_start_streaming,
853         .stop_streaming = venus_helper_vb2_stop_streaming,
854         .buf_queue = venus_helper_vb2_buf_queue,
855 };
856
857 static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
858                           u32 tag, u32 bytesused, u32 data_offset, u32 flags,
859                           u32 hfi_flags, u64 timestamp_us)
860 {
861         enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
862         struct vb2_v4l2_buffer *vbuf;
863         struct vb2_buffer *vb;
864         unsigned int type;
865
866         if (buf_type == HFI_BUFFER_INPUT)
867                 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
868         else
869                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
870
871         vbuf = venus_helper_find_buf(inst, type, tag);
872         if (!vbuf)
873                 return;
874
875         vbuf->flags = flags;
876         vbuf->field = V4L2_FIELD_NONE;
877
878         if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
879                 vb = &vbuf->vb2_buf;
880                 vb2_set_plane_payload(vb, 0, bytesused);
881                 vb->planes[0].data_offset = data_offset;
882                 vb->timestamp = timestamp_us * NSEC_PER_USEC;
883                 vbuf->sequence = inst->sequence_cap++;
884
885                 if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
886                         const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
887
888                         v4l2_event_queue_fh(&inst->fh, &ev);
889                 }
890         } else {
891                 vbuf->sequence = inst->sequence_out++;
892         }
893
894         if (hfi_flags & HFI_BUFFERFLAG_READONLY)
895                 venus_helper_acquire_buf_ref(vbuf);
896
897         if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT)
898                 state = VB2_BUF_STATE_ERROR;
899
900         v4l2_m2m_buf_done(vbuf, state);
901 }
902
903 static void vdec_event_notify(struct venus_inst *inst, u32 event,
904                               struct hfi_event_data *data)
905 {
906         struct venus_core *core = inst->core;
907         struct device *dev = core->dev_dec;
908         static const struct v4l2_event ev = {
909                 .type = V4L2_EVENT_SOURCE_CHANGE,
910                 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION };
911
912         switch (event) {
913         case EVT_SESSION_ERROR:
914                 inst->session_error = true;
915                 dev_err(dev, "dec: event session error %x\n", inst->error);
916                 break;
917         case EVT_SYS_EVENT_CHANGE:
918                 switch (data->event_type) {
919                 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
920                         hfi_session_continue(inst);
921                         dev_dbg(dev, "event sufficient resources\n");
922                         break;
923                 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
924                         inst->reconfig_height = data->height;
925                         inst->reconfig_width = data->width;
926                         inst->reconfig = true;
927
928                         v4l2_event_queue_fh(&inst->fh, &ev);
929
930                         dev_dbg(dev, "event not sufficient resources (%ux%u)\n",
931                                 data->width, data->height);
932                         break;
933                 case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
934                         venus_helper_release_buf_ref(inst, data->tag);
935                         break;
936                 default:
937                         break;
938                 }
939                 break;
940         default:
941                 break;
942         }
943 }
944
945 static const struct hfi_inst_ops vdec_hfi_ops = {
946         .buf_done = vdec_buf_done,
947         .event_notify = vdec_event_notify,
948 };
949
950 static void vdec_inst_init(struct venus_inst *inst)
951 {
952         inst->fmt_out = &vdec_formats[6];
953         inst->fmt_cap = &vdec_formats[0];
954         inst->width = 1280;
955         inst->height = ALIGN(720, 32);
956         inst->out_width = 1280;
957         inst->out_height = 720;
958         inst->fps = 30;
959         inst->timeperframe.numerator = 1;
960         inst->timeperframe.denominator = 30;
961         inst->hfi_codec = HFI_VIDEO_CODEC_H264;
962 }
963
964 static const struct v4l2_m2m_ops vdec_m2m_ops = {
965         .device_run = venus_helper_m2m_device_run,
966         .job_abort = venus_helper_m2m_job_abort,
967 };
968
969 static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
970                           struct vb2_queue *dst_vq)
971 {
972         struct venus_inst *inst = priv;
973         int ret;
974
975         src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
976         src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
977         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
978         src_vq->ops = &vdec_vb2_ops;
979         src_vq->mem_ops = &vb2_dma_sg_memops;
980         src_vq->drv_priv = inst;
981         src_vq->buf_struct_size = sizeof(struct venus_buffer);
982         src_vq->allow_zero_bytesused = 1;
983         src_vq->min_buffers_needed = 1;
984         src_vq->dev = inst->core->dev;
985         ret = vb2_queue_init(src_vq);
986         if (ret)
987                 return ret;
988
989         dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
990         dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
991         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
992         dst_vq->ops = &vdec_vb2_ops;
993         dst_vq->mem_ops = &vb2_dma_sg_memops;
994         dst_vq->drv_priv = inst;
995         dst_vq->buf_struct_size = sizeof(struct venus_buffer);
996         dst_vq->allow_zero_bytesused = 1;
997         dst_vq->min_buffers_needed = 1;
998         dst_vq->dev = inst->core->dev;
999         ret = vb2_queue_init(dst_vq);
1000         if (ret) {
1001                 vb2_queue_release(src_vq);
1002                 return ret;
1003         }
1004
1005         return 0;
1006 }
1007
1008 static int vdec_open(struct file *file)
1009 {
1010         struct venus_core *core = video_drvdata(file);
1011         struct venus_inst *inst;
1012         int ret;
1013
1014         inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1015         if (!inst)
1016                 return -ENOMEM;
1017
1018         INIT_LIST_HEAD(&inst->dpbbufs);
1019         INIT_LIST_HEAD(&inst->registeredbufs);
1020         INIT_LIST_HEAD(&inst->internalbufs);
1021         INIT_LIST_HEAD(&inst->list);
1022         mutex_init(&inst->lock);
1023
1024         inst->core = core;
1025         inst->session_type = VIDC_SESSION_TYPE_DEC;
1026         inst->num_output_bufs = 1;
1027
1028         venus_helper_init_instance(inst);
1029
1030         ret = pm_runtime_get_sync(core->dev_dec);
1031         if (ret < 0)
1032                 goto err_free_inst;
1033
1034         ret = vdec_ctrl_init(inst);
1035         if (ret)
1036                 goto err_put_sync;
1037
1038         ret = hfi_session_create(inst, &vdec_hfi_ops);
1039         if (ret)
1040                 goto err_ctrl_deinit;
1041
1042         vdec_inst_init(inst);
1043
1044         /*
1045          * create m2m device for every instance, the m2m context scheduling
1046          * is made by firmware side so we do not need to care about.
1047          */
1048         inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops);
1049         if (IS_ERR(inst->m2m_dev)) {
1050                 ret = PTR_ERR(inst->m2m_dev);
1051                 goto err_session_destroy;
1052         }
1053
1054         inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
1055         if (IS_ERR(inst->m2m_ctx)) {
1056                 ret = PTR_ERR(inst->m2m_ctx);
1057                 goto err_m2m_release;
1058         }
1059
1060         v4l2_fh_init(&inst->fh, core->vdev_dec);
1061
1062         inst->fh.ctrl_handler = &inst->ctrl_handler;
1063         v4l2_fh_add(&inst->fh);
1064         inst->fh.m2m_ctx = inst->m2m_ctx;
1065         file->private_data = &inst->fh;
1066
1067         return 0;
1068
1069 err_m2m_release:
1070         v4l2_m2m_release(inst->m2m_dev);
1071 err_session_destroy:
1072         hfi_session_destroy(inst);
1073 err_ctrl_deinit:
1074         vdec_ctrl_deinit(inst);
1075 err_put_sync:
1076         pm_runtime_put_sync(core->dev_dec);
1077 err_free_inst:
1078         kfree(inst);
1079         return ret;
1080 }
1081
1082 static int vdec_close(struct file *file)
1083 {
1084         struct venus_inst *inst = to_inst(file);
1085
1086         v4l2_m2m_ctx_release(inst->m2m_ctx);
1087         v4l2_m2m_release(inst->m2m_dev);
1088         vdec_ctrl_deinit(inst);
1089         hfi_session_destroy(inst);
1090         mutex_destroy(&inst->lock);
1091         v4l2_fh_del(&inst->fh);
1092         v4l2_fh_exit(&inst->fh);
1093
1094         pm_runtime_put_sync(inst->core->dev_dec);
1095
1096         kfree(inst);
1097         return 0;
1098 }
1099
1100 static const struct v4l2_file_operations vdec_fops = {
1101         .owner = THIS_MODULE,
1102         .open = vdec_open,
1103         .release = vdec_close,
1104         .unlocked_ioctl = video_ioctl2,
1105         .poll = v4l2_m2m_fop_poll,
1106         .mmap = v4l2_m2m_fop_mmap,
1107 #ifdef CONFIG_COMPAT
1108         .compat_ioctl32 = v4l2_compat_ioctl32,
1109 #endif
1110 };
1111
1112 static int vdec_probe(struct platform_device *pdev)
1113 {
1114         struct device *dev = &pdev->dev;
1115         struct video_device *vdev;
1116         struct venus_core *core;
1117         int ret;
1118
1119         if (!dev->parent)
1120                 return -EPROBE_DEFER;
1121
1122         core = dev_get_drvdata(dev->parent);
1123         if (!core)
1124                 return -EPROBE_DEFER;
1125
1126         if (IS_V3(core) || IS_V4(core)) {
1127                 core->core0_clk = devm_clk_get(dev, "core");
1128                 if (IS_ERR(core->core0_clk))
1129                         return PTR_ERR(core->core0_clk);
1130         }
1131
1132         if (IS_V4(core)) {
1133                 core->core0_bus_clk = devm_clk_get(dev, "bus");
1134                 if (IS_ERR(core->core0_bus_clk))
1135                         return PTR_ERR(core->core0_bus_clk);
1136         }
1137
1138         platform_set_drvdata(pdev, core);
1139
1140         vdev = video_device_alloc();
1141         if (!vdev)
1142                 return -ENOMEM;
1143
1144         strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
1145         vdev->release = video_device_release;
1146         vdev->fops = &vdec_fops;
1147         vdev->ioctl_ops = &vdec_ioctl_ops;
1148         vdev->vfl_dir = VFL_DIR_M2M;
1149         vdev->v4l2_dev = &core->v4l2_dev;
1150         vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1151
1152         ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1153         if (ret)
1154                 goto err_vdev_release;
1155
1156         core->vdev_dec = vdev;
1157         core->dev_dec = dev;
1158
1159         video_set_drvdata(vdev, core);
1160         pm_runtime_enable(dev);
1161
1162         return 0;
1163
1164 err_vdev_release:
1165         video_device_release(vdev);
1166         return ret;
1167 }
1168
1169 static int vdec_remove(struct platform_device *pdev)
1170 {
1171         struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
1172
1173         video_unregister_device(core->vdev_dec);
1174         pm_runtime_disable(core->dev_dec);
1175
1176         return 0;
1177 }
1178
1179 static __maybe_unused int vdec_runtime_suspend(struct device *dev)
1180 {
1181         struct venus_core *core = dev_get_drvdata(dev);
1182         int ret;
1183
1184         if (IS_V1(core))
1185                 return 0;
1186
1187         ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true);
1188         if (ret)
1189                 return ret;
1190
1191         if (IS_V4(core))
1192                 clk_disable_unprepare(core->core0_bus_clk);
1193
1194         clk_disable_unprepare(core->core0_clk);
1195
1196         return venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1197 }
1198
1199 static __maybe_unused int vdec_runtime_resume(struct device *dev)
1200 {
1201         struct venus_core *core = dev_get_drvdata(dev);
1202         int ret;
1203
1204         if (IS_V1(core))
1205                 return 0;
1206
1207         ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true);
1208         if (ret)
1209                 return ret;
1210
1211         ret = clk_prepare_enable(core->core0_clk);
1212         if (ret)
1213                 goto err_power_disable;
1214
1215         if (IS_V4(core))
1216                 ret = clk_prepare_enable(core->core0_bus_clk);
1217
1218         if (ret)
1219                 goto err_unprepare_core0;
1220
1221         return venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1222
1223 err_unprepare_core0:
1224         clk_disable_unprepare(core->core0_clk);
1225 err_power_disable:
1226         venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1227         return ret;
1228 }
1229
1230 static const struct dev_pm_ops vdec_pm_ops = {
1231         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1232                                 pm_runtime_force_resume)
1233         SET_RUNTIME_PM_OPS(vdec_runtime_suspend, vdec_runtime_resume, NULL)
1234 };
1235
1236 static const struct of_device_id vdec_dt_match[] = {
1237         { .compatible = "venus-decoder" },
1238         { }
1239 };
1240 MODULE_DEVICE_TABLE(of, vdec_dt_match);
1241
1242 static struct platform_driver qcom_venus_dec_driver = {
1243         .probe = vdec_probe,
1244         .remove = vdec_remove,
1245         .driver = {
1246                 .name = "qcom-venus-decoder",
1247                 .of_match_table = vdec_dt_match,
1248                 .pm = &vdec_pm_ops,
1249         },
1250 };
1251 module_platform_driver(qcom_venus_dec_driver);
1252
1253 MODULE_ALIAS("platform:qcom-venus-decoder");
1254 MODULE_DESCRIPTION("Qualcomm Venus video decoder driver");
1255 MODULE_LICENSE("GPL v2");