f18458921f5dc21b8f53ea6554b8f40fcdeaa282
[sfrench/cifs-2.6.git] / drivers / media / platform / qcom / venus / helpers.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/iopoll.h>
8 #include <linux/interconnect.h>
9 #include <linux/list.h>
10 #include <linux/mutex.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/slab.h>
13 #include <media/videobuf2-dma-sg.h>
14 #include <media/v4l2-mem2mem.h>
15 #include <asm/div64.h>
16
17 #include "core.h"
18 #include "helpers.h"
19 #include "hfi_helper.h"
20 #include "hfi_venus_io.h"
21
22 struct intbuf {
23         struct list_head list;
24         u32 type;
25         size_t size;
26         void *va;
27         dma_addr_t da;
28         unsigned long attrs;
29 };
30
31 bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)
32 {
33         struct venus_core *core = inst->core;
34         u32 session_type = inst->session_type;
35         u32 codec;
36
37         switch (v4l2_pixfmt) {
38         case V4L2_PIX_FMT_H264:
39                 codec = HFI_VIDEO_CODEC_H264;
40                 break;
41         case V4L2_PIX_FMT_H263:
42                 codec = HFI_VIDEO_CODEC_H263;
43                 break;
44         case V4L2_PIX_FMT_MPEG1:
45                 codec = HFI_VIDEO_CODEC_MPEG1;
46                 break;
47         case V4L2_PIX_FMT_MPEG2:
48                 codec = HFI_VIDEO_CODEC_MPEG2;
49                 break;
50         case V4L2_PIX_FMT_MPEG4:
51                 codec = HFI_VIDEO_CODEC_MPEG4;
52                 break;
53         case V4L2_PIX_FMT_VC1_ANNEX_G:
54         case V4L2_PIX_FMT_VC1_ANNEX_L:
55                 codec = HFI_VIDEO_CODEC_VC1;
56                 break;
57         case V4L2_PIX_FMT_VP8:
58                 codec = HFI_VIDEO_CODEC_VP8;
59                 break;
60         case V4L2_PIX_FMT_VP9:
61                 codec = HFI_VIDEO_CODEC_VP9;
62                 break;
63         case V4L2_PIX_FMT_XVID:
64                 codec = HFI_VIDEO_CODEC_DIVX;
65                 break;
66         case V4L2_PIX_FMT_HEVC:
67                 codec = HFI_VIDEO_CODEC_HEVC;
68                 break;
69         default:
70                 return false;
71         }
72
73         if (session_type == VIDC_SESSION_TYPE_ENC && core->enc_codecs & codec)
74                 return true;
75
76         if (session_type == VIDC_SESSION_TYPE_DEC && core->dec_codecs & codec)
77                 return true;
78
79         return false;
80 }
81 EXPORT_SYMBOL_GPL(venus_helper_check_codec);
82
83 int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
84 {
85         struct intbuf *buf;
86         int ret = 0;
87
88         list_for_each_entry(buf, &inst->dpbbufs, list) {
89                 struct hfi_frame_data fdata;
90
91                 memset(&fdata, 0, sizeof(fdata));
92                 fdata.alloc_len = buf->size;
93                 fdata.device_addr = buf->da;
94                 fdata.buffer_type = buf->type;
95
96                 ret = hfi_session_process_buf(inst, &fdata);
97                 if (ret)
98                         goto fail;
99         }
100
101 fail:
102         return ret;
103 }
104 EXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs);
105
106 int venus_helper_free_dpb_bufs(struct venus_inst *inst)
107 {
108         struct intbuf *buf, *n;
109
110         list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
111                 list_del_init(&buf->list);
112                 dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
113                                buf->attrs);
114                 kfree(buf);
115         }
116
117         INIT_LIST_HEAD(&inst->dpbbufs);
118
119         return 0;
120 }
121 EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs);
122
123 int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
124 {
125         struct venus_core *core = inst->core;
126         struct device *dev = core->dev;
127         enum hfi_version ver = core->res->hfi_version;
128         struct hfi_buffer_requirements bufreq;
129         u32 buftype = inst->dpb_buftype;
130         unsigned int dpb_size = 0;
131         struct intbuf *buf;
132         unsigned int i;
133         u32 count;
134         int ret;
135
136         /* no need to allocate dpb buffers */
137         if (!inst->dpb_fmt)
138                 return 0;
139
140         if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)
141                 dpb_size = inst->output_buf_size;
142         else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)
143                 dpb_size = inst->output2_buf_size;
144
145         if (!dpb_size)
146                 return 0;
147
148         ret = venus_helper_get_bufreq(inst, buftype, &bufreq);
149         if (ret)
150                 return ret;
151
152         count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
153
154         for (i = 0; i < count; i++) {
155                 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
156                 if (!buf) {
157                         ret = -ENOMEM;
158                         goto fail;
159                 }
160
161                 buf->type = buftype;
162                 buf->size = dpb_size;
163                 buf->attrs = DMA_ATTR_WRITE_COMBINE |
164                              DMA_ATTR_NO_KERNEL_MAPPING;
165                 buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
166                                           buf->attrs);
167                 if (!buf->va) {
168                         kfree(buf);
169                         ret = -ENOMEM;
170                         goto fail;
171                 }
172
173                 list_add_tail(&buf->list, &inst->dpbbufs);
174         }
175
176         return 0;
177
178 fail:
179         venus_helper_free_dpb_bufs(inst);
180         return ret;
181 }
182 EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs);
183
184 static int intbufs_set_buffer(struct venus_inst *inst, u32 type)
185 {
186         struct venus_core *core = inst->core;
187         struct device *dev = core->dev;
188         struct hfi_buffer_requirements bufreq;
189         struct hfi_buffer_desc bd;
190         struct intbuf *buf;
191         unsigned int i;
192         int ret;
193
194         ret = venus_helper_get_bufreq(inst, type, &bufreq);
195         if (ret)
196                 return 0;
197
198         if (!bufreq.size)
199                 return 0;
200
201         for (i = 0; i < bufreq.count_actual; i++) {
202                 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
203                 if (!buf) {
204                         ret = -ENOMEM;
205                         goto fail;
206                 }
207
208                 buf->type = bufreq.type;
209                 buf->size = bufreq.size;
210                 buf->attrs = DMA_ATTR_WRITE_COMBINE |
211                              DMA_ATTR_NO_KERNEL_MAPPING;
212                 buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
213                                           buf->attrs);
214                 if (!buf->va) {
215                         ret = -ENOMEM;
216                         goto fail;
217                 }
218
219                 memset(&bd, 0, sizeof(bd));
220                 bd.buffer_size = buf->size;
221                 bd.buffer_type = buf->type;
222                 bd.num_buffers = 1;
223                 bd.device_addr = buf->da;
224
225                 ret = hfi_session_set_buffers(inst, &bd);
226                 if (ret) {
227                         dev_err(dev, "set session buffers failed\n");
228                         goto dma_free;
229                 }
230
231                 list_add_tail(&buf->list, &inst->internalbufs);
232         }
233
234         return 0;
235
236 dma_free:
237         dma_free_attrs(dev, buf->size, buf->va, buf->da, buf->attrs);
238 fail:
239         kfree(buf);
240         return ret;
241 }
242
243 static int intbufs_unset_buffers(struct venus_inst *inst)
244 {
245         struct hfi_buffer_desc bd = {0};
246         struct intbuf *buf, *n;
247         int ret = 0;
248
249         list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {
250                 bd.buffer_size = buf->size;
251                 bd.buffer_type = buf->type;
252                 bd.num_buffers = 1;
253                 bd.device_addr = buf->da;
254                 bd.response_required = true;
255
256                 ret = hfi_session_unset_buffers(inst, &bd);
257
258                 list_del_init(&buf->list);
259                 dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
260                                buf->attrs);
261                 kfree(buf);
262         }
263
264         return ret;
265 }
266
267 static const unsigned int intbuf_types_1xx[] = {
268         HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX),
269         HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX),
270         HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX),
271         HFI_BUFFER_INTERNAL_PERSIST,
272         HFI_BUFFER_INTERNAL_PERSIST_1,
273 };
274
275 static const unsigned int intbuf_types_4xx[] = {
276         HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX),
277         HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX),
278         HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX),
279         HFI_BUFFER_INTERNAL_PERSIST,
280         HFI_BUFFER_INTERNAL_PERSIST_1,
281 };
282
283 int venus_helper_intbufs_alloc(struct venus_inst *inst)
284 {
285         const unsigned int *intbuf;
286         size_t arr_sz, i;
287         int ret;
288
289         if (IS_V4(inst->core)) {
290                 arr_sz = ARRAY_SIZE(intbuf_types_4xx);
291                 intbuf = intbuf_types_4xx;
292         } else {
293                 arr_sz = ARRAY_SIZE(intbuf_types_1xx);
294                 intbuf = intbuf_types_1xx;
295         }
296
297         for (i = 0; i < arr_sz; i++) {
298                 ret = intbufs_set_buffer(inst, intbuf[i]);
299                 if (ret)
300                         goto error;
301         }
302
303         return 0;
304
305 error:
306         intbufs_unset_buffers(inst);
307         return ret;
308 }
309 EXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc);
310
311 int venus_helper_intbufs_free(struct venus_inst *inst)
312 {
313         return intbufs_unset_buffers(inst);
314 }
315 EXPORT_SYMBOL_GPL(venus_helper_intbufs_free);
316
317 int venus_helper_intbufs_realloc(struct venus_inst *inst)
318 {
319         enum hfi_version ver = inst->core->res->hfi_version;
320         struct hfi_buffer_desc bd;
321         struct intbuf *buf, *n;
322         int ret;
323
324         list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {
325                 if (buf->type == HFI_BUFFER_INTERNAL_PERSIST ||
326                     buf->type == HFI_BUFFER_INTERNAL_PERSIST_1)
327                         continue;
328
329                 memset(&bd, 0, sizeof(bd));
330                 bd.buffer_size = buf->size;
331                 bd.buffer_type = buf->type;
332                 bd.num_buffers = 1;
333                 bd.device_addr = buf->da;
334                 bd.response_required = true;
335
336                 ret = hfi_session_unset_buffers(inst, &bd);
337
338                 dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
339                                buf->attrs);
340
341                 list_del_init(&buf->list);
342                 kfree(buf);
343         }
344
345         ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH(ver));
346         if (ret)
347                 goto err;
348
349         ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_1(ver));
350         if (ret)
351                 goto err;
352
353         ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_2(ver));
354         if (ret)
355                 goto err;
356
357         return 0;
358 err:
359         return ret;
360 }
361 EXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc);
362
363 static u32 load_per_instance(struct venus_inst *inst)
364 {
365         u32 mbs;
366
367         if (!inst || !(inst->state >= INST_INIT && inst->state < INST_STOP))
368                 return 0;
369
370         mbs = (ALIGN(inst->width, 16) / 16) * (ALIGN(inst->height, 16) / 16);
371
372         return mbs * inst->fps;
373 }
374
375 static u32 load_per_type(struct venus_core *core, u32 session_type)
376 {
377         struct venus_inst *inst = NULL;
378         u32 mbs_per_sec = 0;
379
380         mutex_lock(&core->lock);
381         list_for_each_entry(inst, &core->instances, list) {
382                 if (inst->session_type != session_type)
383                         continue;
384
385                 mbs_per_sec += load_per_instance(inst);
386         }
387         mutex_unlock(&core->lock);
388
389         return mbs_per_sec;
390 }
391
392 static void mbs_to_bw(struct venus_inst *inst, u32 mbs, u32 *avg, u32 *peak)
393 {
394         const struct venus_resources *res = inst->core->res;
395         const struct bw_tbl *bw_tbl;
396         unsigned int num_rows, i;
397
398         *avg = 0;
399         *peak = 0;
400
401         if (mbs == 0)
402                 return;
403
404         if (inst->session_type == VIDC_SESSION_TYPE_ENC) {
405                 num_rows = res->bw_tbl_enc_size;
406                 bw_tbl = res->bw_tbl_enc;
407         } else if (inst->session_type == VIDC_SESSION_TYPE_DEC) {
408                 num_rows = res->bw_tbl_dec_size;
409                 bw_tbl = res->bw_tbl_dec;
410         } else {
411                 return;
412         }
413
414         if (!bw_tbl || num_rows == 0)
415                 return;
416
417         for (i = 0; i < num_rows; i++) {
418                 if (mbs > bw_tbl[i].mbs_per_sec)
419                         break;
420
421                 if (inst->dpb_fmt & HFI_COLOR_FORMAT_10_BIT_BASE) {
422                         *avg = bw_tbl[i].avg_10bit;
423                         *peak = bw_tbl[i].peak_10bit;
424                 } else {
425                         *avg = bw_tbl[i].avg;
426                         *peak = bw_tbl[i].peak;
427                 }
428         }
429 }
430
431 static int load_scale_bw(struct venus_core *core)
432 {
433         struct venus_inst *inst = NULL;
434         u32 mbs_per_sec, avg, peak, total_avg = 0, total_peak = 0;
435
436         mutex_lock(&core->lock);
437         list_for_each_entry(inst, &core->instances, list) {
438                 mbs_per_sec = load_per_instance(inst);
439                 mbs_to_bw(inst, mbs_per_sec, &avg, &peak);
440                 total_avg += avg;
441                 total_peak += peak;
442         }
443         mutex_unlock(&core->lock);
444
445         dev_dbg(core->dev, "total: avg_bw: %u, peak_bw: %u\n",
446                 total_avg, total_peak);
447
448         return icc_set_bw(core->video_path, total_avg, total_peak);
449 }
450
451 int venus_helper_load_scale_clocks(struct venus_core *core)
452 {
453         const struct freq_tbl *table = core->res->freq_tbl;
454         unsigned int num_rows = core->res->freq_tbl_size;
455         unsigned long freq = table[0].freq;
456         struct clk *clk = core->clks[0];
457         struct device *dev = core->dev;
458         u32 mbs_per_sec;
459         unsigned int i;
460         int ret;
461
462         mbs_per_sec = load_per_type(core, VIDC_SESSION_TYPE_ENC) +
463                       load_per_type(core, VIDC_SESSION_TYPE_DEC);
464
465         if (mbs_per_sec > core->res->max_load)
466                 dev_warn(dev, "HW is overloaded, needed: %d max: %d\n",
467                          mbs_per_sec, core->res->max_load);
468
469         if (!mbs_per_sec && num_rows > 1) {
470                 freq = table[num_rows - 1].freq;
471                 goto set_freq;
472         }
473
474         for (i = 0; i < num_rows; i++) {
475                 if (mbs_per_sec > table[i].load)
476                         break;
477                 freq = table[i].freq;
478         }
479
480 set_freq:
481
482         ret = clk_set_rate(clk, freq);
483         if (ret)
484                 goto err;
485
486         ret = clk_set_rate(core->core0_clk, freq);
487         if (ret)
488                 goto err;
489
490         ret = clk_set_rate(core->core1_clk, freq);
491         if (ret)
492                 goto err;
493
494         ret = load_scale_bw(core);
495         if (ret)
496                 goto err;
497
498         return 0;
499
500 err:
501         dev_err(dev, "failed to set clock rate %lu or bandwidth (%d)\n",
502                 freq, ret);
503         return ret;
504 }
505 EXPORT_SYMBOL_GPL(venus_helper_load_scale_clocks);
506
507 static void fill_buffer_desc(const struct venus_buffer *buf,
508                              struct hfi_buffer_desc *bd, bool response)
509 {
510         memset(bd, 0, sizeof(*bd));
511         bd->buffer_type = HFI_BUFFER_OUTPUT;
512         bd->buffer_size = buf->size;
513         bd->num_buffers = 1;
514         bd->device_addr = buf->dma_addr;
515         bd->response_required = response;
516 }
517
518 static void return_buf_error(struct venus_inst *inst,
519                              struct vb2_v4l2_buffer *vbuf)
520 {
521         struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
522
523         if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
524                 v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
525         else
526                 v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf);
527
528         v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
529 }
530
531 static void
532 put_ts_metadata(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
533 {
534         struct vb2_buffer *vb = &vbuf->vb2_buf;
535         unsigned int i;
536         int slot = -1;
537         u64 ts_us = vb->timestamp;
538
539         for (i = 0; i < ARRAY_SIZE(inst->tss); i++) {
540                 if (!inst->tss[i].used) {
541                         slot = i;
542                         break;
543                 }
544         }
545
546         if (slot == -1) {
547                 dev_dbg(inst->core->dev, "%s: no free slot\n", __func__);
548                 return;
549         }
550
551         do_div(ts_us, NSEC_PER_USEC);
552
553         inst->tss[slot].used = true;
554         inst->tss[slot].flags = vbuf->flags;
555         inst->tss[slot].tc = vbuf->timecode;
556         inst->tss[slot].ts_us = ts_us;
557         inst->tss[slot].ts_ns = vb->timestamp;
558 }
559
560 void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us,
561                                   struct vb2_v4l2_buffer *vbuf)
562 {
563         struct vb2_buffer *vb = &vbuf->vb2_buf;
564         unsigned int i;
565
566         for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) {
567                 if (!inst->tss[i].used)
568                         continue;
569
570                 if (inst->tss[i].ts_us != timestamp_us)
571                         continue;
572
573                 inst->tss[i].used = false;
574                 vbuf->flags |= inst->tss[i].flags;
575                 vbuf->timecode = inst->tss[i].tc;
576                 vb->timestamp = inst->tss[i].ts_ns;
577                 break;
578         }
579 }
580 EXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata);
581
582 static int
583 session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
584 {
585         struct venus_buffer *buf = to_venus_buffer(vbuf);
586         struct vb2_buffer *vb = &vbuf->vb2_buf;
587         unsigned int type = vb->type;
588         struct hfi_frame_data fdata;
589         int ret;
590
591         memset(&fdata, 0, sizeof(fdata));
592         fdata.alloc_len = buf->size;
593         fdata.device_addr = buf->dma_addr;
594         fdata.timestamp = vb->timestamp;
595         do_div(fdata.timestamp, NSEC_PER_USEC);
596         fdata.flags = 0;
597         fdata.clnt_data = vbuf->vb2_buf.index;
598
599         if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
600                 fdata.buffer_type = HFI_BUFFER_INPUT;
601                 fdata.filled_len = vb2_get_plane_payload(vb, 0);
602                 fdata.offset = vb->planes[0].data_offset;
603
604                 if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len)
605                         fdata.flags |= HFI_BUFFERFLAG_EOS;
606
607                 if (inst->session_type == VIDC_SESSION_TYPE_DEC)
608                         put_ts_metadata(inst, vbuf);
609         } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
610                 if (inst->session_type == VIDC_SESSION_TYPE_ENC)
611                         fdata.buffer_type = HFI_BUFFER_OUTPUT;
612                 else
613                         fdata.buffer_type = inst->opb_buftype;
614                 fdata.filled_len = 0;
615                 fdata.offset = 0;
616         }
617
618         ret = hfi_session_process_buf(inst, &fdata);
619         if (ret)
620                 return ret;
621
622         return 0;
623 }
624
625 static bool is_dynamic_bufmode(struct venus_inst *inst)
626 {
627         struct venus_core *core = inst->core;
628         struct venus_caps *caps;
629
630         /*
631          * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports
632          * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2.
633          */
634         if (IS_V4(core))
635                 return true;
636
637         caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
638         if (!caps)
639                 return false;
640
641         return caps->cap_bufs_mode_dynamic;
642 }
643
644 int venus_helper_unregister_bufs(struct venus_inst *inst)
645 {
646         struct venus_buffer *buf, *n;
647         struct hfi_buffer_desc bd;
648         int ret = 0;
649
650         if (is_dynamic_bufmode(inst))
651                 return 0;
652
653         list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) {
654                 fill_buffer_desc(buf, &bd, true);
655                 ret = hfi_session_unset_buffers(inst, &bd);
656                 list_del_init(&buf->reg_list);
657         }
658
659         return ret;
660 }
661 EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs);
662
663 static int session_register_bufs(struct venus_inst *inst)
664 {
665         struct venus_core *core = inst->core;
666         struct device *dev = core->dev;
667         struct hfi_buffer_desc bd;
668         struct venus_buffer *buf;
669         int ret = 0;
670
671         if (is_dynamic_bufmode(inst))
672                 return 0;
673
674         list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
675                 fill_buffer_desc(buf, &bd, false);
676                 ret = hfi_session_set_buffers(inst, &bd);
677                 if (ret) {
678                         dev_err(dev, "%s: set buffer failed\n", __func__);
679                         break;
680                 }
681         }
682
683         return ret;
684 }
685
686 static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
687 {
688         switch (v4l2_fmt) {
689         case V4L2_PIX_FMT_NV12:
690                 return HFI_COLOR_FORMAT_NV12;
691         case V4L2_PIX_FMT_NV21:
692                 return HFI_COLOR_FORMAT_NV21;
693         default:
694                 break;
695         }
696
697         return 0;
698 }
699
700 int venus_helper_get_bufreq(struct venus_inst *inst, u32 type,
701                             struct hfi_buffer_requirements *req)
702 {
703         u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
704         union hfi_get_property hprop;
705         unsigned int i;
706         int ret;
707
708         if (req)
709                 memset(req, 0, sizeof(*req));
710
711         ret = hfi_session_get_property(inst, ptype, &hprop);
712         if (ret)
713                 return ret;
714
715         ret = -EINVAL;
716
717         for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) {
718                 if (hprop.bufreq[i].type != type)
719                         continue;
720
721                 if (req)
722                         memcpy(req, &hprop.bufreq[i], sizeof(*req));
723                 ret = 0;
724                 break;
725         }
726
727         return ret;
728 }
729 EXPORT_SYMBOL_GPL(venus_helper_get_bufreq);
730
731 static u32 get_framesize_raw_nv12(u32 width, u32 height)
732 {
733         u32 y_stride, uv_stride, y_plane;
734         u32 y_sclines, uv_sclines, uv_plane;
735         u32 size;
736
737         y_stride = ALIGN(width, 128);
738         uv_stride = ALIGN(width, 128);
739         y_sclines = ALIGN(height, 32);
740         uv_sclines = ALIGN(((height + 1) >> 1), 16);
741
742         y_plane = y_stride * y_sclines;
743         uv_plane = uv_stride * uv_sclines + SZ_4K;
744         size = y_plane + uv_plane + SZ_8K;
745
746         return ALIGN(size, SZ_4K);
747 }
748
749 static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height)
750 {
751         u32 y_meta_stride, y_meta_plane;
752         u32 y_stride, y_plane;
753         u32 uv_meta_stride, uv_meta_plane;
754         u32 uv_stride, uv_plane;
755         u32 extradata = SZ_16K;
756
757         y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64);
758         y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16);
759         y_meta_plane = ALIGN(y_meta_plane, SZ_4K);
760
761         y_stride = ALIGN(width, 128);
762         y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K);
763
764         uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64);
765         uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16);
766         uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K);
767
768         uv_stride = ALIGN(width, 128);
769         uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K);
770
771         return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane +
772                      max(extradata, y_stride * 48), SZ_4K);
773 }
774
775 u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height)
776 {
777         switch (hfi_fmt) {
778         case HFI_COLOR_FORMAT_NV12:
779         case HFI_COLOR_FORMAT_NV21:
780                 return get_framesize_raw_nv12(width, height);
781         case HFI_COLOR_FORMAT_NV12_UBWC:
782                 return get_framesize_raw_nv12_ubwc(width, height);
783         default:
784                 return 0;
785         }
786 }
787 EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw);
788
789 u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height)
790 {
791         u32 hfi_fmt, sz;
792         bool compressed;
793
794         switch (v4l2_fmt) {
795         case V4L2_PIX_FMT_MPEG:
796         case V4L2_PIX_FMT_H264:
797         case V4L2_PIX_FMT_H264_NO_SC:
798         case V4L2_PIX_FMT_H264_MVC:
799         case V4L2_PIX_FMT_H263:
800         case V4L2_PIX_FMT_MPEG1:
801         case V4L2_PIX_FMT_MPEG2:
802         case V4L2_PIX_FMT_MPEG4:
803         case V4L2_PIX_FMT_XVID:
804         case V4L2_PIX_FMT_VC1_ANNEX_G:
805         case V4L2_PIX_FMT_VC1_ANNEX_L:
806         case V4L2_PIX_FMT_VP8:
807         case V4L2_PIX_FMT_VP9:
808         case V4L2_PIX_FMT_HEVC:
809                 compressed = true;
810                 break;
811         default:
812                 compressed = false;
813                 break;
814         }
815
816         if (compressed) {
817                 sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2;
818                 return ALIGN(sz, SZ_4K);
819         }
820
821         hfi_fmt = to_hfi_raw_fmt(v4l2_fmt);
822         if (!hfi_fmt)
823                 return 0;
824
825         return venus_helper_get_framesz_raw(hfi_fmt, width, height);
826 }
827 EXPORT_SYMBOL_GPL(venus_helper_get_framesz);
828
829 int venus_helper_set_input_resolution(struct venus_inst *inst,
830                                       unsigned int width, unsigned int height)
831 {
832         u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
833         struct hfi_framesize fs;
834
835         fs.buffer_type = HFI_BUFFER_INPUT;
836         fs.width = width;
837         fs.height = height;
838
839         return hfi_session_set_property(inst, ptype, &fs);
840 }
841 EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution);
842
843 int venus_helper_set_output_resolution(struct venus_inst *inst,
844                                        unsigned int width, unsigned int height,
845                                        u32 buftype)
846 {
847         u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
848         struct hfi_framesize fs;
849
850         fs.buffer_type = buftype;
851         fs.width = width;
852         fs.height = height;
853
854         return hfi_session_set_property(inst, ptype, &fs);
855 }
856 EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution);
857
858 int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode)
859 {
860         const u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE;
861         struct hfi_video_work_mode wm;
862
863         if (!IS_V4(inst->core))
864                 return 0;
865
866         wm.video_work_mode = mode;
867
868         return hfi_session_set_property(inst, ptype, &wm);
869 }
870 EXPORT_SYMBOL_GPL(venus_helper_set_work_mode);
871
872 int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage)
873 {
874         const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
875         struct hfi_videocores_usage_type cu;
876
877         if (!IS_V4(inst->core))
878                 return 0;
879
880         cu.video_core_enable_mask = usage;
881
882         return hfi_session_set_property(inst, ptype, &cu);
883 }
884 EXPORT_SYMBOL_GPL(venus_helper_set_core_usage);
885
886 int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs,
887                               unsigned int output_bufs,
888                               unsigned int output2_bufs)
889 {
890         u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
891         struct hfi_buffer_count_actual buf_count;
892         int ret;
893
894         buf_count.type = HFI_BUFFER_INPUT;
895         buf_count.count_actual = input_bufs;
896
897         ret = hfi_session_set_property(inst, ptype, &buf_count);
898         if (ret)
899                 return ret;
900
901         buf_count.type = HFI_BUFFER_OUTPUT;
902         buf_count.count_actual = output_bufs;
903
904         ret = hfi_session_set_property(inst, ptype, &buf_count);
905         if (ret)
906                 return ret;
907
908         if (output2_bufs) {
909                 buf_count.type = HFI_BUFFER_OUTPUT2;
910                 buf_count.count_actual = output2_bufs;
911
912                 ret = hfi_session_set_property(inst, ptype, &buf_count);
913         }
914
915         return ret;
916 }
917 EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs);
918
919 int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format,
920                                 u32 buftype)
921 {
922         const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
923         struct hfi_uncompressed_format_select fmt;
924
925         fmt.buffer_type = buftype;
926         fmt.format = hfi_format;
927
928         return hfi_session_set_property(inst, ptype, &fmt);
929 }
930 EXPORT_SYMBOL_GPL(venus_helper_set_raw_format);
931
932 int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt)
933 {
934         u32 hfi_format, buftype;
935
936         if (inst->session_type == VIDC_SESSION_TYPE_DEC)
937                 buftype = HFI_BUFFER_OUTPUT;
938         else if (inst->session_type == VIDC_SESSION_TYPE_ENC)
939                 buftype = HFI_BUFFER_INPUT;
940         else
941                 return -EINVAL;
942
943         hfi_format = to_hfi_raw_fmt(pixfmt);
944         if (!hfi_format)
945                 return -EINVAL;
946
947         return venus_helper_set_raw_format(inst, hfi_format, buftype);
948 }
949 EXPORT_SYMBOL_GPL(venus_helper_set_color_format);
950
951 int venus_helper_set_multistream(struct venus_inst *inst, bool out_en,
952                                  bool out2_en)
953 {
954         struct hfi_multi_stream multi = {0};
955         u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
956         int ret;
957
958         multi.buffer_type = HFI_BUFFER_OUTPUT;
959         multi.enable = out_en;
960
961         ret = hfi_session_set_property(inst, ptype, &multi);
962         if (ret)
963                 return ret;
964
965         multi.buffer_type = HFI_BUFFER_OUTPUT2;
966         multi.enable = out2_en;
967
968         return hfi_session_set_property(inst, ptype, &multi);
969 }
970 EXPORT_SYMBOL_GPL(venus_helper_set_multistream);
971
972 int venus_helper_set_dyn_bufmode(struct venus_inst *inst)
973 {
974         const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
975         struct hfi_buffer_alloc_mode mode;
976         int ret;
977
978         if (!is_dynamic_bufmode(inst))
979                 return 0;
980
981         mode.type = HFI_BUFFER_OUTPUT;
982         mode.mode = HFI_BUFFER_MODE_DYNAMIC;
983
984         ret = hfi_session_set_property(inst, ptype, &mode);
985         if (ret)
986                 return ret;
987
988         mode.type = HFI_BUFFER_OUTPUT2;
989
990         return hfi_session_set_property(inst, ptype, &mode);
991 }
992 EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode);
993
994 int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype)
995 {
996         const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
997         struct hfi_buffer_size_actual bufsz;
998
999         bufsz.type = buftype;
1000         bufsz.size = bufsize;
1001
1002         return hfi_session_set_property(inst, ptype, &bufsz);
1003 }
1004 EXPORT_SYMBOL_GPL(venus_helper_set_bufsize);
1005
1006 unsigned int venus_helper_get_opb_size(struct venus_inst *inst)
1007 {
1008         /* the encoder has only one output */
1009         if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1010                 return inst->output_buf_size;
1011
1012         if (inst->opb_buftype == HFI_BUFFER_OUTPUT)
1013                 return inst->output_buf_size;
1014         else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2)
1015                 return inst->output2_buf_size;
1016
1017         return 0;
1018 }
1019 EXPORT_SYMBOL_GPL(venus_helper_get_opb_size);
1020
1021 static void delayed_process_buf_func(struct work_struct *work)
1022 {
1023         struct venus_buffer *buf, *n;
1024         struct venus_inst *inst;
1025         int ret;
1026
1027         inst = container_of(work, struct venus_inst, delayed_process_work);
1028
1029         mutex_lock(&inst->lock);
1030
1031         if (!(inst->streamon_out & inst->streamon_cap))
1032                 goto unlock;
1033
1034         list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) {
1035                 if (buf->flags & HFI_BUFFERFLAG_READONLY)
1036                         continue;
1037
1038                 ret = session_process_buf(inst, &buf->vb);
1039                 if (ret)
1040                         return_buf_error(inst, &buf->vb);
1041
1042                 list_del_init(&buf->ref_list);
1043         }
1044 unlock:
1045         mutex_unlock(&inst->lock);
1046 }
1047
1048 void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx)
1049 {
1050         struct venus_buffer *buf;
1051
1052         list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
1053                 if (buf->vb.vb2_buf.index == idx) {
1054                         buf->flags &= ~HFI_BUFFERFLAG_READONLY;
1055                         schedule_work(&inst->delayed_process_work);
1056                         break;
1057                 }
1058         }
1059 }
1060 EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref);
1061
1062 void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf)
1063 {
1064         struct venus_buffer *buf = to_venus_buffer(vbuf);
1065
1066         buf->flags |= HFI_BUFFERFLAG_READONLY;
1067 }
1068 EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref);
1069
1070 static int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
1071 {
1072         struct venus_buffer *buf = to_venus_buffer(vbuf);
1073
1074         if (buf->flags & HFI_BUFFERFLAG_READONLY) {
1075                 list_add_tail(&buf->ref_list, &inst->delayed_process);
1076                 schedule_work(&inst->delayed_process_work);
1077                 return 1;
1078         }
1079
1080         return 0;
1081 }
1082
1083 struct vb2_v4l2_buffer *
1084 venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx)
1085 {
1086         struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1087
1088         if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1089                 return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx);
1090         else
1091                 return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx);
1092 }
1093 EXPORT_SYMBOL_GPL(venus_helper_find_buf);
1094
1095 int venus_helper_vb2_buf_init(struct vb2_buffer *vb)
1096 {
1097         struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1098         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1099         struct venus_buffer *buf = to_venus_buffer(vbuf);
1100         struct sg_table *sgt;
1101
1102         sgt = vb2_dma_sg_plane_desc(vb, 0);
1103         if (!sgt)
1104                 return -EFAULT;
1105
1106         buf->size = vb2_plane_size(vb, 0);
1107         buf->dma_addr = sg_dma_address(sgt->sgl);
1108
1109         if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1110                 list_add_tail(&buf->reg_list, &inst->registeredbufs);
1111
1112         return 0;
1113 }
1114 EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init);
1115
1116 int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb)
1117 {
1118         struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1119         unsigned int out_buf_size = venus_helper_get_opb_size(inst);
1120         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1121
1122         if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1123                 if (vbuf->field == V4L2_FIELD_ANY)
1124                         vbuf->field = V4L2_FIELD_NONE;
1125                 if (vbuf->field != V4L2_FIELD_NONE) {
1126                         dev_err(inst->core->dev, "%s field isn't supported\n",
1127                                 __func__);
1128                         return -EINVAL;
1129                 }
1130         }
1131
1132         if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
1133             vb2_plane_size(vb, 0) < out_buf_size)
1134                 return -EINVAL;
1135         if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1136             vb2_plane_size(vb, 0) < inst->input_buf_size)
1137                 return -EINVAL;
1138
1139         return 0;
1140 }
1141 EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare);
1142
1143 void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
1144 {
1145         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1146         struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1147         struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1148         int ret;
1149
1150         mutex_lock(&inst->lock);
1151
1152         v4l2_m2m_buf_queue(m2m_ctx, vbuf);
1153
1154         if (inst->session_type == VIDC_SESSION_TYPE_ENC &&
1155             !(inst->streamon_out && inst->streamon_cap))
1156                 goto unlock;
1157
1158         if (vb2_start_streaming_called(vb->vb2_queue)) {
1159                 ret = is_buf_refed(inst, vbuf);
1160                 if (ret)
1161                         goto unlock;
1162
1163                 ret = session_process_buf(inst, vbuf);
1164                 if (ret)
1165                         return_buf_error(inst, vbuf);
1166         }
1167
1168 unlock:
1169         mutex_unlock(&inst->lock);
1170 }
1171 EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);
1172
1173 void venus_helper_buffers_done(struct venus_inst *inst,
1174                                enum vb2_buffer_state state)
1175 {
1176         struct vb2_v4l2_buffer *buf;
1177
1178         while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))
1179                 v4l2_m2m_buf_done(buf, state);
1180         while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
1181                 v4l2_m2m_buf_done(buf, state);
1182 }
1183 EXPORT_SYMBOL_GPL(venus_helper_buffers_done);
1184
1185 void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
1186 {
1187         struct venus_inst *inst = vb2_get_drv_priv(q);
1188         struct venus_core *core = inst->core;
1189         int ret;
1190
1191         mutex_lock(&inst->lock);
1192
1193         if (inst->streamon_out & inst->streamon_cap) {
1194                 ret = hfi_session_stop(inst);
1195                 ret |= hfi_session_unload_res(inst);
1196                 ret |= venus_helper_unregister_bufs(inst);
1197                 ret |= venus_helper_intbufs_free(inst);
1198                 ret |= hfi_session_deinit(inst);
1199
1200                 if (inst->session_error || core->sys_error)
1201                         ret = -EIO;
1202
1203                 if (ret)
1204                         hfi_session_abort(inst);
1205
1206                 venus_helper_free_dpb_bufs(inst);
1207
1208                 venus_helper_load_scale_clocks(core);
1209                 INIT_LIST_HEAD(&inst->registeredbufs);
1210         }
1211
1212         venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR);
1213
1214         if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1215                 inst->streamon_out = 0;
1216         else
1217                 inst->streamon_cap = 0;
1218
1219         mutex_unlock(&inst->lock);
1220 }
1221 EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);
1222
1223 int venus_helper_process_initial_cap_bufs(struct venus_inst *inst)
1224 {
1225         struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1226         struct v4l2_m2m_buffer *buf, *n;
1227         int ret;
1228
1229         v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
1230                 ret = session_process_buf(inst, &buf->vb);
1231                 if (ret) {
1232                         return_buf_error(inst, &buf->vb);
1233                         return ret;
1234                 }
1235         }
1236
1237         return 0;
1238 }
1239 EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs);
1240
1241 int venus_helper_process_initial_out_bufs(struct venus_inst *inst)
1242 {
1243         struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1244         struct v4l2_m2m_buffer *buf, *n;
1245         int ret;
1246
1247         v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
1248                 ret = session_process_buf(inst, &buf->vb);
1249                 if (ret) {
1250                         return_buf_error(inst, &buf->vb);
1251                         return ret;
1252                 }
1253         }
1254
1255         return 0;
1256 }
1257 EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs);
1258
1259 int venus_helper_vb2_start_streaming(struct venus_inst *inst)
1260 {
1261         struct venus_core *core = inst->core;
1262         int ret;
1263
1264         ret = venus_helper_intbufs_alloc(inst);
1265         if (ret)
1266                 return ret;
1267
1268         ret = session_register_bufs(inst);
1269         if (ret)
1270                 goto err_bufs_free;
1271
1272         venus_helper_load_scale_clocks(core);
1273
1274         ret = hfi_session_load_res(inst);
1275         if (ret)
1276                 goto err_unreg_bufs;
1277
1278         ret = hfi_session_start(inst);
1279         if (ret)
1280                 goto err_unload_res;
1281
1282         return 0;
1283
1284 err_unload_res:
1285         hfi_session_unload_res(inst);
1286 err_unreg_bufs:
1287         venus_helper_unregister_bufs(inst);
1288 err_bufs_free:
1289         venus_helper_intbufs_free(inst);
1290         return ret;
1291 }
1292 EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming);
1293
1294 void venus_helper_m2m_device_run(void *priv)
1295 {
1296         struct venus_inst *inst = priv;
1297         struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
1298         struct v4l2_m2m_buffer *buf, *n;
1299         int ret;
1300
1301         mutex_lock(&inst->lock);
1302
1303         v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
1304                 ret = session_process_buf(inst, &buf->vb);
1305                 if (ret)
1306                         return_buf_error(inst, &buf->vb);
1307         }
1308
1309         v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
1310                 ret = session_process_buf(inst, &buf->vb);
1311                 if (ret)
1312                         return_buf_error(inst, &buf->vb);
1313         }
1314
1315         mutex_unlock(&inst->lock);
1316 }
1317 EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run);
1318
1319 void venus_helper_m2m_job_abort(void *priv)
1320 {
1321         struct venus_inst *inst = priv;
1322
1323         v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx);
1324 }
1325 EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort);
1326
1327 void venus_helper_init_instance(struct venus_inst *inst)
1328 {
1329         if (inst->session_type == VIDC_SESSION_TYPE_DEC) {
1330                 INIT_LIST_HEAD(&inst->delayed_process);
1331                 INIT_WORK(&inst->delayed_process_work,
1332                           delayed_process_buf_func);
1333         }
1334 }
1335 EXPORT_SYMBOL_GPL(venus_helper_init_instance);
1336
1337 static bool find_fmt_from_caps(struct venus_caps *caps, u32 buftype, u32 fmt)
1338 {
1339         unsigned int i;
1340
1341         for (i = 0; i < caps->num_fmts; i++) {
1342                 if (caps->fmts[i].buftype == buftype &&
1343                     caps->fmts[i].fmt == fmt)
1344                         return true;
1345         }
1346
1347         return false;
1348 }
1349
1350 int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
1351                               u32 *out_fmt, u32 *out2_fmt, bool ubwc)
1352 {
1353         struct venus_core *core = inst->core;
1354         struct venus_caps *caps;
1355         u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt);
1356         bool found, found_ubwc;
1357
1358         *out_fmt = *out2_fmt = 0;
1359
1360         if (!fmt)
1361                 return -EINVAL;
1362
1363         caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
1364         if (!caps)
1365                 return -EINVAL;
1366
1367         if (ubwc) {
1368                 ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
1369                 found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
1370                                                 ubwc_fmt);
1371                 found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
1372
1373                 if (found_ubwc && found) {
1374                         *out_fmt = ubwc_fmt;
1375                         *out2_fmt = fmt;
1376                         return 0;
1377                 }
1378         }
1379
1380         found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);
1381         if (found) {
1382                 *out_fmt = fmt;
1383                 *out2_fmt = 0;
1384                 return 0;
1385         }
1386
1387         found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
1388         if (found) {
1389                 *out_fmt = 0;
1390                 *out2_fmt = fmt;
1391                 return 0;
1392         }
1393
1394         return -EINVAL;
1395 }
1396 EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);
1397
1398 int venus_helper_power_enable(struct venus_core *core, u32 session_type,
1399                               bool enable)
1400 {
1401         void __iomem *ctrl, *stat;
1402         u32 val;
1403         int ret;
1404
1405         if (!IS_V3(core) && !IS_V4(core))
1406                 return 0;
1407
1408         if (IS_V3(core)) {
1409                 if (session_type == VIDC_SESSION_TYPE_DEC)
1410                         ctrl = core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL;
1411                 else
1412                         ctrl = core->base + WRAPPER_VENC_VCODEC_POWER_CONTROL;
1413                 if (enable)
1414                         writel(0, ctrl);
1415                 else
1416                         writel(1, ctrl);
1417
1418                 return 0;
1419         }
1420
1421         if (session_type == VIDC_SESSION_TYPE_DEC) {
1422                 ctrl = core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL;
1423                 stat = core->base + WRAPPER_VCODEC0_MMCC_POWER_STATUS;
1424         } else {
1425                 ctrl = core->base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL;
1426                 stat = core->base + WRAPPER_VCODEC1_MMCC_POWER_STATUS;
1427         }
1428
1429         if (enable) {
1430                 writel(0, ctrl);
1431
1432                 ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100);
1433                 if (ret)
1434                         return ret;
1435         } else {
1436                 writel(1, ctrl);
1437
1438                 ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100);
1439                 if (ret)
1440                         return ret;
1441         }
1442
1443         return 0;
1444 }
1445 EXPORT_SYMBOL_GPL(venus_helper_power_enable);