1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2017 Linaro Ltd.
6 #include <linux/list.h>
7 #include <linux/mutex.h>
8 #include <linux/slab.h>
9 #include <linux/kernel.h>
10 #include <media/videobuf2-dma-sg.h>
11 #include <media/v4l2-mem2mem.h>
12 #include <asm/div64.h>
16 #include "hfi_helper.h"
17 #include "pm_helpers.h"
20 struct list_head list
;
28 bool venus_helper_check_codec(struct venus_inst
*inst
, u32 v4l2_pixfmt
)
30 struct venus_core
*core
= inst
->core
;
31 u32 session_type
= inst
->session_type
;
34 switch (v4l2_pixfmt
) {
35 case V4L2_PIX_FMT_H264
:
36 codec
= HFI_VIDEO_CODEC_H264
;
38 case V4L2_PIX_FMT_H263
:
39 codec
= HFI_VIDEO_CODEC_H263
;
41 case V4L2_PIX_FMT_MPEG1
:
42 codec
= HFI_VIDEO_CODEC_MPEG1
;
44 case V4L2_PIX_FMT_MPEG2
:
45 codec
= HFI_VIDEO_CODEC_MPEG2
;
47 case V4L2_PIX_FMT_MPEG4
:
48 codec
= HFI_VIDEO_CODEC_MPEG4
;
50 case V4L2_PIX_FMT_VC1_ANNEX_G
:
51 case V4L2_PIX_FMT_VC1_ANNEX_L
:
52 codec
= HFI_VIDEO_CODEC_VC1
;
54 case V4L2_PIX_FMT_VP8
:
55 codec
= HFI_VIDEO_CODEC_VP8
;
57 case V4L2_PIX_FMT_VP9
:
58 codec
= HFI_VIDEO_CODEC_VP9
;
60 case V4L2_PIX_FMT_XVID
:
61 codec
= HFI_VIDEO_CODEC_DIVX
;
63 case V4L2_PIX_FMT_HEVC
:
64 codec
= HFI_VIDEO_CODEC_HEVC
;
70 if (session_type
== VIDC_SESSION_TYPE_ENC
&& core
->enc_codecs
& codec
)
73 if (session_type
== VIDC_SESSION_TYPE_DEC
&& core
->dec_codecs
& codec
)
78 EXPORT_SYMBOL_GPL(venus_helper_check_codec
);
80 int venus_helper_queue_dpb_bufs(struct venus_inst
*inst
)
85 list_for_each_entry(buf
, &inst
->dpbbufs
, list
) {
86 struct hfi_frame_data fdata
;
88 memset(&fdata
, 0, sizeof(fdata
));
89 fdata
.alloc_len
= buf
->size
;
90 fdata
.device_addr
= buf
->da
;
91 fdata
.buffer_type
= buf
->type
;
93 ret
= hfi_session_process_buf(inst
, &fdata
);
101 EXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs
);
103 int venus_helper_free_dpb_bufs(struct venus_inst
*inst
)
105 struct intbuf
*buf
, *n
;
107 list_for_each_entry_safe(buf
, n
, &inst
->dpbbufs
, list
) {
108 list_del_init(&buf
->list
);
109 dma_free_attrs(inst
->core
->dev
, buf
->size
, buf
->va
, buf
->da
,
114 INIT_LIST_HEAD(&inst
->dpbbufs
);
118 EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs
);
120 int venus_helper_alloc_dpb_bufs(struct venus_inst
*inst
)
122 struct venus_core
*core
= inst
->core
;
123 struct device
*dev
= core
->dev
;
124 enum hfi_version ver
= core
->res
->hfi_version
;
125 struct hfi_buffer_requirements bufreq
;
126 u32 buftype
= inst
->dpb_buftype
;
127 unsigned int dpb_size
= 0;
133 /* no need to allocate dpb buffers */
137 if (inst
->dpb_buftype
== HFI_BUFFER_OUTPUT
)
138 dpb_size
= inst
->output_buf_size
;
139 else if (inst
->dpb_buftype
== HFI_BUFFER_OUTPUT2
)
140 dpb_size
= inst
->output2_buf_size
;
145 ret
= venus_helper_get_bufreq(inst
, buftype
, &bufreq
);
149 count
= HFI_BUFREQ_COUNT_MIN(&bufreq
, ver
);
151 for (i
= 0; i
< count
; i
++) {
152 buf
= kzalloc(sizeof(*buf
), GFP_KERNEL
);
159 buf
->size
= dpb_size
;
160 buf
->attrs
= DMA_ATTR_WRITE_COMBINE
|
161 DMA_ATTR_NO_KERNEL_MAPPING
;
162 buf
->va
= dma_alloc_attrs(dev
, buf
->size
, &buf
->da
, GFP_KERNEL
,
170 list_add_tail(&buf
->list
, &inst
->dpbbufs
);
176 venus_helper_free_dpb_bufs(inst
);
179 EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs
);
181 static int intbufs_set_buffer(struct venus_inst
*inst
, u32 type
)
183 struct venus_core
*core
= inst
->core
;
184 struct device
*dev
= core
->dev
;
185 struct hfi_buffer_requirements bufreq
;
186 struct hfi_buffer_desc bd
;
191 ret
= venus_helper_get_bufreq(inst
, type
, &bufreq
);
198 for (i
= 0; i
< bufreq
.count_actual
; i
++) {
199 buf
= kzalloc(sizeof(*buf
), GFP_KERNEL
);
205 buf
->type
= bufreq
.type
;
206 buf
->size
= bufreq
.size
;
207 buf
->attrs
= DMA_ATTR_WRITE_COMBINE
|
208 DMA_ATTR_NO_KERNEL_MAPPING
;
209 buf
->va
= dma_alloc_attrs(dev
, buf
->size
, &buf
->da
, GFP_KERNEL
,
216 memset(&bd
, 0, sizeof(bd
));
217 bd
.buffer_size
= buf
->size
;
218 bd
.buffer_type
= buf
->type
;
220 bd
.device_addr
= buf
->da
;
222 ret
= hfi_session_set_buffers(inst
, &bd
);
224 dev_err(dev
, "set session buffers failed\n");
228 list_add_tail(&buf
->list
, &inst
->internalbufs
);
234 dma_free_attrs(dev
, buf
->size
, buf
->va
, buf
->da
, buf
->attrs
);
240 static int intbufs_unset_buffers(struct venus_inst
*inst
)
242 struct hfi_buffer_desc bd
= {0};
243 struct intbuf
*buf
, *n
;
246 list_for_each_entry_safe(buf
, n
, &inst
->internalbufs
, list
) {
247 bd
.buffer_size
= buf
->size
;
248 bd
.buffer_type
= buf
->type
;
250 bd
.device_addr
= buf
->da
;
251 bd
.response_required
= true;
253 ret
= hfi_session_unset_buffers(inst
, &bd
);
255 list_del_init(&buf
->list
);
256 dma_free_attrs(inst
->core
->dev
, buf
->size
, buf
->va
, buf
->da
,
264 static const unsigned int intbuf_types_1xx
[] = {
265 HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX
),
266 HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX
),
267 HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX
),
268 HFI_BUFFER_INTERNAL_PERSIST
,
269 HFI_BUFFER_INTERNAL_PERSIST_1
,
272 static const unsigned int intbuf_types_4xx
[] = {
273 HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX
),
274 HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX
),
275 HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX
),
276 HFI_BUFFER_INTERNAL_PERSIST
,
277 HFI_BUFFER_INTERNAL_PERSIST_1
,
280 int venus_helper_intbufs_alloc(struct venus_inst
*inst
)
282 const unsigned int *intbuf
;
286 if (IS_V4(inst
->core
)) {
287 arr_sz
= ARRAY_SIZE(intbuf_types_4xx
);
288 intbuf
= intbuf_types_4xx
;
290 arr_sz
= ARRAY_SIZE(intbuf_types_1xx
);
291 intbuf
= intbuf_types_1xx
;
294 for (i
= 0; i
< arr_sz
; i
++) {
295 ret
= intbufs_set_buffer(inst
, intbuf
[i
]);
303 intbufs_unset_buffers(inst
);
306 EXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc
);
308 int venus_helper_intbufs_free(struct venus_inst
*inst
)
310 return intbufs_unset_buffers(inst
);
312 EXPORT_SYMBOL_GPL(venus_helper_intbufs_free
);
314 int venus_helper_intbufs_realloc(struct venus_inst
*inst
)
316 enum hfi_version ver
= inst
->core
->res
->hfi_version
;
317 struct hfi_buffer_desc bd
;
318 struct intbuf
*buf
, *n
;
321 list_for_each_entry_safe(buf
, n
, &inst
->internalbufs
, list
) {
322 if (buf
->type
== HFI_BUFFER_INTERNAL_PERSIST
||
323 buf
->type
== HFI_BUFFER_INTERNAL_PERSIST_1
)
326 memset(&bd
, 0, sizeof(bd
));
327 bd
.buffer_size
= buf
->size
;
328 bd
.buffer_type
= buf
->type
;
330 bd
.device_addr
= buf
->da
;
331 bd
.response_required
= true;
333 ret
= hfi_session_unset_buffers(inst
, &bd
);
335 dma_free_attrs(inst
->core
->dev
, buf
->size
, buf
->va
, buf
->da
,
338 list_del_init(&buf
->list
);
342 ret
= intbufs_set_buffer(inst
, HFI_BUFFER_INTERNAL_SCRATCH(ver
));
346 ret
= intbufs_set_buffer(inst
, HFI_BUFFER_INTERNAL_SCRATCH_1(ver
));
350 ret
= intbufs_set_buffer(inst
, HFI_BUFFER_INTERNAL_SCRATCH_2(ver
));
358 EXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc
);
360 static void fill_buffer_desc(const struct venus_buffer
*buf
,
361 struct hfi_buffer_desc
*bd
, bool response
)
363 memset(bd
, 0, sizeof(*bd
));
364 bd
->buffer_type
= HFI_BUFFER_OUTPUT
;
365 bd
->buffer_size
= buf
->size
;
367 bd
->device_addr
= buf
->dma_addr
;
368 bd
->response_required
= response
;
371 static void return_buf_error(struct venus_inst
*inst
,
372 struct vb2_v4l2_buffer
*vbuf
)
374 struct v4l2_m2m_ctx
*m2m_ctx
= inst
->m2m_ctx
;
376 if (vbuf
->vb2_buf
.type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
377 v4l2_m2m_src_buf_remove_by_buf(m2m_ctx
, vbuf
);
379 v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx
, vbuf
);
381 v4l2_m2m_buf_done(vbuf
, VB2_BUF_STATE_ERROR
);
385 put_ts_metadata(struct venus_inst
*inst
, struct vb2_v4l2_buffer
*vbuf
)
387 struct vb2_buffer
*vb
= &vbuf
->vb2_buf
;
390 u64 ts_us
= vb
->timestamp
;
392 for (i
= 0; i
< ARRAY_SIZE(inst
->tss
); i
++) {
393 if (!inst
->tss
[i
].used
) {
400 dev_dbg(inst
->core
->dev
, VDBGL
"no free slot\n");
404 do_div(ts_us
, NSEC_PER_USEC
);
406 inst
->tss
[slot
].used
= true;
407 inst
->tss
[slot
].flags
= vbuf
->flags
;
408 inst
->tss
[slot
].tc
= vbuf
->timecode
;
409 inst
->tss
[slot
].ts_us
= ts_us
;
410 inst
->tss
[slot
].ts_ns
= vb
->timestamp
;
413 void venus_helper_get_ts_metadata(struct venus_inst
*inst
, u64 timestamp_us
,
414 struct vb2_v4l2_buffer
*vbuf
)
416 struct vb2_buffer
*vb
= &vbuf
->vb2_buf
;
419 for (i
= 0; i
< ARRAY_SIZE(inst
->tss
); ++i
) {
420 if (!inst
->tss
[i
].used
)
423 if (inst
->tss
[i
].ts_us
!= timestamp_us
)
426 inst
->tss
[i
].used
= false;
427 vbuf
->flags
|= inst
->tss
[i
].flags
;
428 vbuf
->timecode
= inst
->tss
[i
].tc
;
429 vb
->timestamp
= inst
->tss
[i
].ts_ns
;
433 EXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata
);
436 session_process_buf(struct venus_inst
*inst
, struct vb2_v4l2_buffer
*vbuf
)
438 struct venus_buffer
*buf
= to_venus_buffer(vbuf
);
439 struct vb2_buffer
*vb
= &vbuf
->vb2_buf
;
440 unsigned int type
= vb
->type
;
441 struct hfi_frame_data fdata
;
444 memset(&fdata
, 0, sizeof(fdata
));
445 fdata
.alloc_len
= buf
->size
;
446 fdata
.device_addr
= buf
->dma_addr
;
447 fdata
.timestamp
= vb
->timestamp
;
448 do_div(fdata
.timestamp
, NSEC_PER_USEC
);
450 fdata
.clnt_data
= vbuf
->vb2_buf
.index
;
452 if (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
453 fdata
.buffer_type
= HFI_BUFFER_INPUT
;
454 fdata
.filled_len
= vb2_get_plane_payload(vb
, 0);
455 fdata
.offset
= vb
->planes
[0].data_offset
;
457 if (vbuf
->flags
& V4L2_BUF_FLAG_LAST
|| !fdata
.filled_len
)
458 fdata
.flags
|= HFI_BUFFERFLAG_EOS
;
460 if (inst
->session_type
== VIDC_SESSION_TYPE_DEC
)
461 put_ts_metadata(inst
, vbuf
);
463 venus_pm_load_scale(inst
);
464 } else if (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
465 if (inst
->session_type
== VIDC_SESSION_TYPE_ENC
)
466 fdata
.buffer_type
= HFI_BUFFER_OUTPUT
;
468 fdata
.buffer_type
= inst
->opb_buftype
;
469 fdata
.filled_len
= 0;
473 ret
= hfi_session_process_buf(inst
, &fdata
);
480 static bool is_dynamic_bufmode(struct venus_inst
*inst
)
482 struct venus_core
*core
= inst
->core
;
483 struct venus_caps
*caps
;
486 * v4 doesn't send BUFFER_ALLOC_MODE_SUPPORTED property and supports
487 * dynamic buffer mode by default for HFI_BUFFER_OUTPUT/OUTPUT2.
492 caps
= venus_caps_by_codec(core
, inst
->hfi_codec
, inst
->session_type
);
496 return caps
->cap_bufs_mode_dynamic
;
499 int venus_helper_unregister_bufs(struct venus_inst
*inst
)
501 struct venus_buffer
*buf
, *n
;
502 struct hfi_buffer_desc bd
;
505 if (is_dynamic_bufmode(inst
))
508 list_for_each_entry_safe(buf
, n
, &inst
->registeredbufs
, reg_list
) {
509 fill_buffer_desc(buf
, &bd
, true);
510 ret
= hfi_session_unset_buffers(inst
, &bd
);
511 list_del_init(&buf
->reg_list
);
516 EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs
);
518 static int session_register_bufs(struct venus_inst
*inst
)
520 struct venus_core
*core
= inst
->core
;
521 struct device
*dev
= core
->dev
;
522 struct hfi_buffer_desc bd
;
523 struct venus_buffer
*buf
;
526 if (is_dynamic_bufmode(inst
))
529 list_for_each_entry(buf
, &inst
->registeredbufs
, reg_list
) {
530 fill_buffer_desc(buf
, &bd
, false);
531 ret
= hfi_session_set_buffers(inst
, &bd
);
533 dev_err(dev
, "%s: set buffer failed\n", __func__
);
541 static u32
to_hfi_raw_fmt(u32 v4l2_fmt
)
544 case V4L2_PIX_FMT_NV12
:
545 return HFI_COLOR_FORMAT_NV12
;
546 case V4L2_PIX_FMT_NV21
:
547 return HFI_COLOR_FORMAT_NV21
;
555 int venus_helper_get_bufreq(struct venus_inst
*inst
, u32 type
,
556 struct hfi_buffer_requirements
*req
)
558 u32 ptype
= HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS
;
559 union hfi_get_property hprop
;
564 memset(req
, 0, sizeof(*req
));
566 ret
= hfi_session_get_property(inst
, ptype
, &hprop
);
572 for (i
= 0; i
< HFI_BUFFER_TYPE_MAX
; i
++) {
573 if (hprop
.bufreq
[i
].type
!= type
)
577 memcpy(req
, &hprop
.bufreq
[i
], sizeof(*req
));
584 EXPORT_SYMBOL_GPL(venus_helper_get_bufreq
);
591 static const struct id_mapping mpeg4_profiles
[] = {
592 { HFI_MPEG4_PROFILE_SIMPLE
, V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE
},
593 { HFI_MPEG4_PROFILE_ADVANCEDSIMPLE
, V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE
},
596 static const struct id_mapping mpeg4_levels
[] = {
597 { HFI_MPEG4_LEVEL_0
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0
},
598 { HFI_MPEG4_LEVEL_0b
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B
},
599 { HFI_MPEG4_LEVEL_1
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_1
},
600 { HFI_MPEG4_LEVEL_2
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_2
},
601 { HFI_MPEG4_LEVEL_3
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_3
},
602 { HFI_MPEG4_LEVEL_4
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_4
},
603 { HFI_MPEG4_LEVEL_5
, V4L2_MPEG_VIDEO_MPEG4_LEVEL_5
},
606 static const struct id_mapping mpeg2_profiles
[] = {
607 { HFI_MPEG2_PROFILE_SIMPLE
, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE
},
608 { HFI_MPEG2_PROFILE_MAIN
, V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN
},
609 { HFI_MPEG2_PROFILE_SNR
, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE
},
610 { HFI_MPEG2_PROFILE_SPATIAL
, V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE
},
611 { HFI_MPEG2_PROFILE_HIGH
, V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH
},
614 static const struct id_mapping mpeg2_levels
[] = {
615 { HFI_MPEG2_LEVEL_LL
, V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW
},
616 { HFI_MPEG2_LEVEL_ML
, V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN
},
617 { HFI_MPEG2_LEVEL_H14
, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440
},
618 { HFI_MPEG2_LEVEL_HL
, V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH
},
621 static const struct id_mapping h264_profiles
[] = {
622 { HFI_H264_PROFILE_BASELINE
, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE
},
623 { HFI_H264_PROFILE_MAIN
, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN
},
624 { HFI_H264_PROFILE_HIGH
, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH
},
625 { HFI_H264_PROFILE_STEREO_HIGH
, V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH
},
626 { HFI_H264_PROFILE_MULTIVIEW_HIGH
, V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH
},
627 { HFI_H264_PROFILE_CONSTRAINED_BASE
, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE
},
628 { HFI_H264_PROFILE_CONSTRAINED_HIGH
, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH
},
631 static const struct id_mapping h264_levels
[] = {
632 { HFI_H264_LEVEL_1
, V4L2_MPEG_VIDEO_H264_LEVEL_1_0
},
633 { HFI_H264_LEVEL_1b
, V4L2_MPEG_VIDEO_H264_LEVEL_1B
},
634 { HFI_H264_LEVEL_11
, V4L2_MPEG_VIDEO_H264_LEVEL_1_1
},
635 { HFI_H264_LEVEL_12
, V4L2_MPEG_VIDEO_H264_LEVEL_1_2
},
636 { HFI_H264_LEVEL_13
, V4L2_MPEG_VIDEO_H264_LEVEL_1_3
},
637 { HFI_H264_LEVEL_2
, V4L2_MPEG_VIDEO_H264_LEVEL_2_0
},
638 { HFI_H264_LEVEL_21
, V4L2_MPEG_VIDEO_H264_LEVEL_2_1
},
639 { HFI_H264_LEVEL_22
, V4L2_MPEG_VIDEO_H264_LEVEL_2_2
},
640 { HFI_H264_LEVEL_3
, V4L2_MPEG_VIDEO_H264_LEVEL_3_0
},
641 { HFI_H264_LEVEL_31
, V4L2_MPEG_VIDEO_H264_LEVEL_3_1
},
642 { HFI_H264_LEVEL_32
, V4L2_MPEG_VIDEO_H264_LEVEL_3_2
},
643 { HFI_H264_LEVEL_4
, V4L2_MPEG_VIDEO_H264_LEVEL_4_0
},
644 { HFI_H264_LEVEL_41
, V4L2_MPEG_VIDEO_H264_LEVEL_4_1
},
645 { HFI_H264_LEVEL_42
, V4L2_MPEG_VIDEO_H264_LEVEL_4_2
},
646 { HFI_H264_LEVEL_5
, V4L2_MPEG_VIDEO_H264_LEVEL_5_0
},
647 { HFI_H264_LEVEL_51
, V4L2_MPEG_VIDEO_H264_LEVEL_5_1
},
648 { HFI_H264_LEVEL_52
, V4L2_MPEG_VIDEO_H264_LEVEL_5_1
},
651 static const struct id_mapping hevc_profiles
[] = {
652 { HFI_HEVC_PROFILE_MAIN
, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN
},
653 { HFI_HEVC_PROFILE_MAIN_STILL_PIC
, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE
},
654 { HFI_HEVC_PROFILE_MAIN10
, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10
},
657 static const struct id_mapping hevc_levels
[] = {
658 { HFI_HEVC_LEVEL_1
, V4L2_MPEG_VIDEO_HEVC_LEVEL_1
},
659 { HFI_HEVC_LEVEL_2
, V4L2_MPEG_VIDEO_HEVC_LEVEL_2
},
660 { HFI_HEVC_LEVEL_21
, V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1
},
661 { HFI_HEVC_LEVEL_3
, V4L2_MPEG_VIDEO_HEVC_LEVEL_3
},
662 { HFI_HEVC_LEVEL_31
, V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1
},
663 { HFI_HEVC_LEVEL_4
, V4L2_MPEG_VIDEO_HEVC_LEVEL_4
},
664 { HFI_HEVC_LEVEL_41
, V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1
},
665 { HFI_HEVC_LEVEL_5
, V4L2_MPEG_VIDEO_HEVC_LEVEL_5
},
666 { HFI_HEVC_LEVEL_51
, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1
},
667 { HFI_HEVC_LEVEL_52
, V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2
},
668 { HFI_HEVC_LEVEL_6
, V4L2_MPEG_VIDEO_HEVC_LEVEL_6
},
669 { HFI_HEVC_LEVEL_61
, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1
},
670 { HFI_HEVC_LEVEL_62
, V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2
},
673 static const struct id_mapping vp8_profiles
[] = {
674 { HFI_VPX_PROFILE_VERSION_0
, V4L2_MPEG_VIDEO_VP8_PROFILE_0
},
675 { HFI_VPX_PROFILE_VERSION_1
, V4L2_MPEG_VIDEO_VP8_PROFILE_1
},
676 { HFI_VPX_PROFILE_VERSION_2
, V4L2_MPEG_VIDEO_VP8_PROFILE_2
},
677 { HFI_VPX_PROFILE_VERSION_3
, V4L2_MPEG_VIDEO_VP8_PROFILE_3
},
680 static const struct id_mapping vp9_profiles
[] = {
681 { HFI_VP9_PROFILE_P0
, V4L2_MPEG_VIDEO_VP9_PROFILE_0
},
682 { HFI_VP9_PROFILE_P2_10B
, V4L2_MPEG_VIDEO_VP9_PROFILE_2
},
685 static const struct id_mapping vp9_levels
[] = {
686 { HFI_VP9_LEVEL_1
, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0
},
687 { HFI_VP9_LEVEL_11
, V4L2_MPEG_VIDEO_VP9_LEVEL_1_1
},
688 { HFI_VP9_LEVEL_2
, V4L2_MPEG_VIDEO_VP9_LEVEL_2_0
},
689 { HFI_VP9_LEVEL_21
, V4L2_MPEG_VIDEO_VP9_LEVEL_2_1
},
690 { HFI_VP9_LEVEL_3
, V4L2_MPEG_VIDEO_VP9_LEVEL_3_0
},
691 { HFI_VP9_LEVEL_31
, V4L2_MPEG_VIDEO_VP9_LEVEL_3_1
},
692 { HFI_VP9_LEVEL_4
, V4L2_MPEG_VIDEO_VP9_LEVEL_4_0
},
693 { HFI_VP9_LEVEL_41
, V4L2_MPEG_VIDEO_VP9_LEVEL_4_1
},
694 { HFI_VP9_LEVEL_5
, V4L2_MPEG_VIDEO_VP9_LEVEL_5_0
},
695 { HFI_VP9_LEVEL_51
, V4L2_MPEG_VIDEO_VP9_LEVEL_5_1
},
696 { HFI_VP9_LEVEL_6
, V4L2_MPEG_VIDEO_VP9_LEVEL_6_0
},
697 { HFI_VP9_LEVEL_61
, V4L2_MPEG_VIDEO_VP9_LEVEL_6_1
},
700 static u32
find_v4l2_id(u32 hfi_id
, const struct id_mapping
*array
, unsigned int array_sz
)
704 if (!array
|| !array_sz
)
707 for (i
= 0; i
< array_sz
; i
++)
708 if (hfi_id
== array
[i
].hfi_id
)
709 return array
[i
].v4l2_id
;
714 static u32
find_hfi_id(u32 v4l2_id
, const struct id_mapping
*array
, unsigned int array_sz
)
718 if (!array
|| !array_sz
)
721 for (i
= 0; i
< array_sz
; i
++)
722 if (v4l2_id
== array
[i
].v4l2_id
)
723 return array
[i
].hfi_id
;
729 v4l2_id_profile_level(u32 hfi_codec
, struct hfi_profile_level
*pl
, u32
*profile
, u32
*level
)
731 u32 hfi_pf
= pl
->profile
;
732 u32 hfi_lvl
= pl
->level
;
735 case HFI_VIDEO_CODEC_H264
:
736 *profile
= find_v4l2_id(hfi_pf
, h264_profiles
, ARRAY_SIZE(h264_profiles
));
737 *level
= find_v4l2_id(hfi_lvl
, h264_levels
, ARRAY_SIZE(h264_levels
));
739 case HFI_VIDEO_CODEC_MPEG2
:
740 *profile
= find_v4l2_id(hfi_pf
, mpeg2_profiles
, ARRAY_SIZE(mpeg2_profiles
));
741 *level
= find_v4l2_id(hfi_lvl
, mpeg2_levels
, ARRAY_SIZE(mpeg2_levels
));
743 case HFI_VIDEO_CODEC_MPEG4
:
744 *profile
= find_v4l2_id(hfi_pf
, mpeg4_profiles
, ARRAY_SIZE(mpeg4_profiles
));
745 *level
= find_v4l2_id(hfi_lvl
, mpeg4_levels
, ARRAY_SIZE(mpeg4_levels
));
747 case HFI_VIDEO_CODEC_VP8
:
748 *profile
= find_v4l2_id(hfi_pf
, vp8_profiles
, ARRAY_SIZE(vp8_profiles
));
751 case HFI_VIDEO_CODEC_VP9
:
752 *profile
= find_v4l2_id(hfi_pf
, vp9_profiles
, ARRAY_SIZE(vp9_profiles
));
753 *level
= find_v4l2_id(hfi_lvl
, vp9_levels
, ARRAY_SIZE(vp9_levels
));
755 case HFI_VIDEO_CODEC_HEVC
:
756 *profile
= find_v4l2_id(hfi_pf
, hevc_profiles
, ARRAY_SIZE(hevc_profiles
));
757 *level
= find_v4l2_id(hfi_lvl
, hevc_levels
, ARRAY_SIZE(hevc_levels
));
765 hfi_id_profile_level(u32 hfi_codec
, u32 v4l2_pf
, u32 v4l2_lvl
, struct hfi_profile_level
*pl
)
768 case HFI_VIDEO_CODEC_H264
:
769 pl
->profile
= find_hfi_id(v4l2_pf
, h264_profiles
, ARRAY_SIZE(h264_profiles
));
770 pl
->level
= find_hfi_id(v4l2_lvl
, h264_levels
, ARRAY_SIZE(h264_levels
));
772 case HFI_VIDEO_CODEC_MPEG2
:
773 pl
->profile
= find_hfi_id(v4l2_pf
, mpeg2_profiles
, ARRAY_SIZE(mpeg2_profiles
));
774 pl
->level
= find_hfi_id(v4l2_lvl
, mpeg2_levels
, ARRAY_SIZE(mpeg2_levels
));
776 case HFI_VIDEO_CODEC_MPEG4
:
777 pl
->profile
= find_hfi_id(v4l2_pf
, mpeg4_profiles
, ARRAY_SIZE(mpeg4_profiles
));
778 pl
->level
= find_hfi_id(v4l2_lvl
, mpeg4_levels
, ARRAY_SIZE(mpeg4_levels
));
780 case HFI_VIDEO_CODEC_VP8
:
781 pl
->profile
= find_hfi_id(v4l2_pf
, vp8_profiles
, ARRAY_SIZE(vp8_profiles
));
784 case HFI_VIDEO_CODEC_VP9
:
785 pl
->profile
= find_hfi_id(v4l2_pf
, vp9_profiles
, ARRAY_SIZE(vp9_profiles
));
786 pl
->level
= find_hfi_id(v4l2_lvl
, vp9_levels
, ARRAY_SIZE(vp9_levels
));
788 case HFI_VIDEO_CODEC_HEVC
:
789 pl
->profile
= find_hfi_id(v4l2_pf
, hevc_profiles
, ARRAY_SIZE(hevc_profiles
));
790 pl
->level
= find_hfi_id(v4l2_lvl
, hevc_levels
, ARRAY_SIZE(hevc_levels
));
797 int venus_helper_get_profile_level(struct venus_inst
*inst
, u32
*profile
, u32
*level
)
799 const u32 ptype
= HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT
;
800 union hfi_get_property hprop
;
803 ret
= hfi_session_get_property(inst
, ptype
, &hprop
);
807 v4l2_id_profile_level(inst
->hfi_codec
, &hprop
.profile_level
, profile
, level
);
811 EXPORT_SYMBOL_GPL(venus_helper_get_profile_level
);
813 int venus_helper_set_profile_level(struct venus_inst
*inst
, u32 profile
, u32 level
)
815 const u32 ptype
= HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT
;
816 struct hfi_profile_level pl
;
818 hfi_id_profile_level(inst
->hfi_codec
, profile
, level
, &pl
);
820 return hfi_session_set_property(inst
, ptype
, &pl
);
822 EXPORT_SYMBOL_GPL(venus_helper_set_profile_level
);
824 static u32
get_framesize_raw_nv12(u32 width
, u32 height
)
826 u32 y_stride
, uv_stride
, y_plane
;
827 u32 y_sclines
, uv_sclines
, uv_plane
;
830 y_stride
= ALIGN(width
, 128);
831 uv_stride
= ALIGN(width
, 128);
832 y_sclines
= ALIGN(height
, 32);
833 uv_sclines
= ALIGN(((height
+ 1) >> 1), 16);
835 y_plane
= y_stride
* y_sclines
;
836 uv_plane
= uv_stride
* uv_sclines
+ SZ_4K
;
837 size
= y_plane
+ uv_plane
+ SZ_8K
;
839 return ALIGN(size
, SZ_4K
);
842 static u32
get_framesize_raw_nv12_ubwc(u32 width
, u32 height
)
844 u32 y_meta_stride
, y_meta_plane
;
845 u32 y_stride
, y_plane
;
846 u32 uv_meta_stride
, uv_meta_plane
;
847 u32 uv_stride
, uv_plane
;
848 u32 extradata
= SZ_16K
;
850 y_meta_stride
= ALIGN(DIV_ROUND_UP(width
, 32), 64);
851 y_meta_plane
= y_meta_stride
* ALIGN(DIV_ROUND_UP(height
, 8), 16);
852 y_meta_plane
= ALIGN(y_meta_plane
, SZ_4K
);
854 y_stride
= ALIGN(width
, 128);
855 y_plane
= ALIGN(y_stride
* ALIGN(height
, 32), SZ_4K
);
857 uv_meta_stride
= ALIGN(DIV_ROUND_UP(width
/ 2, 16), 64);
858 uv_meta_plane
= uv_meta_stride
* ALIGN(DIV_ROUND_UP(height
/ 2, 8), 16);
859 uv_meta_plane
= ALIGN(uv_meta_plane
, SZ_4K
);
861 uv_stride
= ALIGN(width
, 128);
862 uv_plane
= ALIGN(uv_stride
* ALIGN(height
/ 2, 32), SZ_4K
);
864 return ALIGN(y_meta_plane
+ y_plane
+ uv_meta_plane
+ uv_plane
+
865 max(extradata
, y_stride
* 48), SZ_4K
);
868 static u32
get_framesize_raw_p010(u32 width
, u32 height
)
870 u32 y_plane
, uv_plane
, y_stride
, uv_stride
, y_sclines
, uv_sclines
;
872 y_stride
= ALIGN(width
* 2, 256);
873 uv_stride
= ALIGN(width
* 2, 256);
874 y_sclines
= ALIGN(height
, 32);
875 uv_sclines
= ALIGN((height
+ 1) >> 1, 16);
876 y_plane
= y_stride
* y_sclines
;
877 uv_plane
= uv_stride
* uv_sclines
;
879 return ALIGN((y_plane
+ uv_plane
), SZ_4K
);
882 static u32
get_framesize_raw_p010_ubwc(u32 width
, u32 height
)
884 u32 y_stride
, uv_stride
, y_sclines
, uv_sclines
;
885 u32 y_ubwc_plane
, uv_ubwc_plane
;
886 u32 y_meta_stride
, y_meta_scanlines
;
887 u32 uv_meta_stride
, uv_meta_scanlines
;
888 u32 y_meta_plane
, uv_meta_plane
;
891 y_stride
= ALIGN(width
* 2, 256);
892 uv_stride
= ALIGN(width
* 2, 256);
893 y_sclines
= ALIGN(height
, 16);
894 uv_sclines
= ALIGN((height
+ 1) >> 1, 16);
896 y_ubwc_plane
= ALIGN(y_stride
* y_sclines
, SZ_4K
);
897 uv_ubwc_plane
= ALIGN(uv_stride
* uv_sclines
, SZ_4K
);
898 y_meta_stride
= ALIGN(DIV_ROUND_UP(width
, 32), 64);
899 y_meta_scanlines
= ALIGN(DIV_ROUND_UP(height
, 4), 16);
900 y_meta_plane
= ALIGN(y_meta_stride
* y_meta_scanlines
, SZ_4K
);
901 uv_meta_stride
= ALIGN(DIV_ROUND_UP((width
+ 1) >> 1, 16), 64);
902 uv_meta_scanlines
= ALIGN(DIV_ROUND_UP((height
+ 1) >> 1, 4), 16);
903 uv_meta_plane
= ALIGN(uv_meta_stride
* uv_meta_scanlines
, SZ_4K
);
905 size
= y_ubwc_plane
+ uv_ubwc_plane
+ y_meta_plane
+ uv_meta_plane
;
907 return ALIGN(size
, SZ_4K
);
910 static u32
get_framesize_raw_yuv420_tp10_ubwc(u32 width
, u32 height
)
912 u32 y_stride
, uv_stride
, y_sclines
, uv_sclines
;
913 u32 y_ubwc_plane
, uv_ubwc_plane
;
914 u32 y_meta_stride
, y_meta_scanlines
;
915 u32 uv_meta_stride
, uv_meta_scanlines
;
916 u32 y_meta_plane
, uv_meta_plane
;
917 u32 extradata
= SZ_16K
;
920 y_stride
= ALIGN(ALIGN(width
, 192) * 4 / 3, 256);
921 uv_stride
= ALIGN(ALIGN(width
, 192) * 4 / 3, 256);
922 y_sclines
= ALIGN(height
, 16);
923 uv_sclines
= ALIGN((height
+ 1) >> 1, 16);
925 y_ubwc_plane
= ALIGN(y_stride
* y_sclines
, SZ_4K
);
926 uv_ubwc_plane
= ALIGN(uv_stride
* uv_sclines
, SZ_4K
);
927 y_meta_stride
= ALIGN(DIV_ROUND_UP(width
, 48), 64);
928 y_meta_scanlines
= ALIGN(DIV_ROUND_UP(height
, 4), 16);
929 y_meta_plane
= ALIGN(y_meta_stride
* y_meta_scanlines
, SZ_4K
);
930 uv_meta_stride
= ALIGN(DIV_ROUND_UP((width
+ 1) >> 1, 24), 64);
931 uv_meta_scanlines
= ALIGN(DIV_ROUND_UP((height
+ 1) >> 1, 4), 16);
932 uv_meta_plane
= ALIGN(uv_meta_stride
* uv_meta_scanlines
, SZ_4K
);
934 size
= y_ubwc_plane
+ uv_ubwc_plane
+ y_meta_plane
+ uv_meta_plane
;
935 size
+= max(extradata
+ SZ_8K
, y_stride
* 48);
937 return ALIGN(size
, SZ_4K
);
940 u32
venus_helper_get_framesz_raw(u32 hfi_fmt
, u32 width
, u32 height
)
943 case HFI_COLOR_FORMAT_NV12
:
944 case HFI_COLOR_FORMAT_NV21
:
945 return get_framesize_raw_nv12(width
, height
);
946 case HFI_COLOR_FORMAT_NV12_UBWC
:
947 return get_framesize_raw_nv12_ubwc(width
, height
);
948 case HFI_COLOR_FORMAT_P010
:
949 return get_framesize_raw_p010(width
, height
);
950 case HFI_COLOR_FORMAT_P010_UBWC
:
951 return get_framesize_raw_p010_ubwc(width
, height
);
952 case HFI_COLOR_FORMAT_YUV420_TP10_UBWC
:
953 return get_framesize_raw_yuv420_tp10_ubwc(width
, height
);
958 EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw
);
960 u32
venus_helper_get_framesz(u32 v4l2_fmt
, u32 width
, u32 height
)
966 case V4L2_PIX_FMT_MPEG
:
967 case V4L2_PIX_FMT_H264
:
968 case V4L2_PIX_FMT_H264_NO_SC
:
969 case V4L2_PIX_FMT_H264_MVC
:
970 case V4L2_PIX_FMT_H263
:
971 case V4L2_PIX_FMT_MPEG1
:
972 case V4L2_PIX_FMT_MPEG2
:
973 case V4L2_PIX_FMT_MPEG4
:
974 case V4L2_PIX_FMT_XVID
:
975 case V4L2_PIX_FMT_VC1_ANNEX_G
:
976 case V4L2_PIX_FMT_VC1_ANNEX_L
:
977 case V4L2_PIX_FMT_VP8
:
978 case V4L2_PIX_FMT_VP9
:
979 case V4L2_PIX_FMT_HEVC
:
988 sz
= ALIGN(height
, 32) * ALIGN(width
, 32) * 3 / 2 / 2;
989 return ALIGN(sz
, SZ_4K
);
992 hfi_fmt
= to_hfi_raw_fmt(v4l2_fmt
);
996 return venus_helper_get_framesz_raw(hfi_fmt
, width
, height
);
998 EXPORT_SYMBOL_GPL(venus_helper_get_framesz
);
1000 int venus_helper_set_input_resolution(struct venus_inst
*inst
,
1001 unsigned int width
, unsigned int height
)
1003 u32 ptype
= HFI_PROPERTY_PARAM_FRAME_SIZE
;
1004 struct hfi_framesize fs
;
1006 fs
.buffer_type
= HFI_BUFFER_INPUT
;
1010 return hfi_session_set_property(inst
, ptype
, &fs
);
1012 EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution
);
1014 int venus_helper_set_output_resolution(struct venus_inst
*inst
,
1015 unsigned int width
, unsigned int height
,
1018 u32 ptype
= HFI_PROPERTY_PARAM_FRAME_SIZE
;
1019 struct hfi_framesize fs
;
1021 fs
.buffer_type
= buftype
;
1025 return hfi_session_set_property(inst
, ptype
, &fs
);
1027 EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution
);
1029 int venus_helper_set_work_mode(struct venus_inst
*inst
, u32 mode
)
1031 const u32 ptype
= HFI_PROPERTY_PARAM_WORK_MODE
;
1032 struct hfi_video_work_mode wm
;
1034 if (!IS_V4(inst
->core
))
1037 wm
.video_work_mode
= mode
;
1039 return hfi_session_set_property(inst
, ptype
, &wm
);
1041 EXPORT_SYMBOL_GPL(venus_helper_set_work_mode
);
1043 int venus_helper_init_codec_freq_data(struct venus_inst
*inst
)
1045 const struct codec_freq_data
*data
;
1046 unsigned int i
, data_size
;
1050 if (!IS_V4(inst
->core
))
1053 data
= inst
->core
->res
->codec_freq_data
;
1054 data_size
= inst
->core
->res
->codec_freq_data_size
;
1055 pixfmt
= inst
->session_type
== VIDC_SESSION_TYPE_DEC
?
1056 inst
->fmt_out
->pixfmt
: inst
->fmt_cap
->pixfmt
;
1058 for (i
= 0; i
< data_size
; i
++) {
1059 if (data
[i
].pixfmt
== pixfmt
&&
1060 data
[i
].session_type
== inst
->session_type
) {
1061 inst
->clk_data
.codec_freq_data
= &data
[i
];
1066 if (!inst
->clk_data
.codec_freq_data
)
1071 EXPORT_SYMBOL_GPL(venus_helper_init_codec_freq_data
);
1073 int venus_helper_set_num_bufs(struct venus_inst
*inst
, unsigned int input_bufs
,
1074 unsigned int output_bufs
,
1075 unsigned int output2_bufs
)
1077 u32 ptype
= HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL
;
1078 struct hfi_buffer_count_actual buf_count
;
1081 buf_count
.type
= HFI_BUFFER_INPUT
;
1082 buf_count
.count_actual
= input_bufs
;
1084 ret
= hfi_session_set_property(inst
, ptype
, &buf_count
);
1088 buf_count
.type
= HFI_BUFFER_OUTPUT
;
1089 buf_count
.count_actual
= output_bufs
;
1091 ret
= hfi_session_set_property(inst
, ptype
, &buf_count
);
1096 buf_count
.type
= HFI_BUFFER_OUTPUT2
;
1097 buf_count
.count_actual
= output2_bufs
;
1099 ret
= hfi_session_set_property(inst
, ptype
, &buf_count
);
1104 EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs
);
1106 int venus_helper_set_raw_format(struct venus_inst
*inst
, u32 hfi_format
,
1109 const u32 ptype
= HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT
;
1110 struct hfi_uncompressed_format_select fmt
;
1112 fmt
.buffer_type
= buftype
;
1113 fmt
.format
= hfi_format
;
1115 return hfi_session_set_property(inst
, ptype
, &fmt
);
1117 EXPORT_SYMBOL_GPL(venus_helper_set_raw_format
);
1119 int venus_helper_set_color_format(struct venus_inst
*inst
, u32 pixfmt
)
1121 u32 hfi_format
, buftype
;
1123 if (inst
->session_type
== VIDC_SESSION_TYPE_DEC
)
1124 buftype
= HFI_BUFFER_OUTPUT
;
1125 else if (inst
->session_type
== VIDC_SESSION_TYPE_ENC
)
1126 buftype
= HFI_BUFFER_INPUT
;
1130 hfi_format
= to_hfi_raw_fmt(pixfmt
);
1134 return venus_helper_set_raw_format(inst
, hfi_format
, buftype
);
1136 EXPORT_SYMBOL_GPL(venus_helper_set_color_format
);
1138 int venus_helper_set_multistream(struct venus_inst
*inst
, bool out_en
,
1141 struct hfi_multi_stream multi
= {0};
1142 u32 ptype
= HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM
;
1145 multi
.buffer_type
= HFI_BUFFER_OUTPUT
;
1146 multi
.enable
= out_en
;
1148 ret
= hfi_session_set_property(inst
, ptype
, &multi
);
1152 multi
.buffer_type
= HFI_BUFFER_OUTPUT2
;
1153 multi
.enable
= out2_en
;
1155 return hfi_session_set_property(inst
, ptype
, &multi
);
1157 EXPORT_SYMBOL_GPL(venus_helper_set_multistream
);
1159 int venus_helper_set_dyn_bufmode(struct venus_inst
*inst
)
1161 const u32 ptype
= HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE
;
1162 struct hfi_buffer_alloc_mode mode
;
1165 if (!is_dynamic_bufmode(inst
))
1168 mode
.type
= HFI_BUFFER_OUTPUT
;
1169 mode
.mode
= HFI_BUFFER_MODE_DYNAMIC
;
1171 ret
= hfi_session_set_property(inst
, ptype
, &mode
);
1175 mode
.type
= HFI_BUFFER_OUTPUT2
;
1177 return hfi_session_set_property(inst
, ptype
, &mode
);
1179 EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode
);
1181 int venus_helper_set_bufsize(struct venus_inst
*inst
, u32 bufsize
, u32 buftype
)
1183 const u32 ptype
= HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL
;
1184 struct hfi_buffer_size_actual bufsz
;
1186 bufsz
.type
= buftype
;
1187 bufsz
.size
= bufsize
;
1189 return hfi_session_set_property(inst
, ptype
, &bufsz
);
1191 EXPORT_SYMBOL_GPL(venus_helper_set_bufsize
);
1193 unsigned int venus_helper_get_opb_size(struct venus_inst
*inst
)
1195 /* the encoder has only one output */
1196 if (inst
->session_type
== VIDC_SESSION_TYPE_ENC
)
1197 return inst
->output_buf_size
;
1199 if (inst
->opb_buftype
== HFI_BUFFER_OUTPUT
)
1200 return inst
->output_buf_size
;
1201 else if (inst
->opb_buftype
== HFI_BUFFER_OUTPUT2
)
1202 return inst
->output2_buf_size
;
1206 EXPORT_SYMBOL_GPL(venus_helper_get_opb_size
);
1208 static void delayed_process_buf_func(struct work_struct
*work
)
1210 struct venus_buffer
*buf
, *n
;
1211 struct venus_inst
*inst
;
1214 inst
= container_of(work
, struct venus_inst
, delayed_process_work
);
1216 mutex_lock(&inst
->lock
);
1218 if (!(inst
->streamon_out
& inst
->streamon_cap
))
1221 list_for_each_entry_safe(buf
, n
, &inst
->delayed_process
, ref_list
) {
1222 if (buf
->flags
& HFI_BUFFERFLAG_READONLY
)
1225 ret
= session_process_buf(inst
, &buf
->vb
);
1227 return_buf_error(inst
, &buf
->vb
);
1229 list_del_init(&buf
->ref_list
);
1232 mutex_unlock(&inst
->lock
);
1235 void venus_helper_release_buf_ref(struct venus_inst
*inst
, unsigned int idx
)
1237 struct venus_buffer
*buf
;
1239 list_for_each_entry(buf
, &inst
->registeredbufs
, reg_list
) {
1240 if (buf
->vb
.vb2_buf
.index
== idx
) {
1241 buf
->flags
&= ~HFI_BUFFERFLAG_READONLY
;
1242 schedule_work(&inst
->delayed_process_work
);
1247 EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref
);
1249 void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer
*vbuf
)
1251 struct venus_buffer
*buf
= to_venus_buffer(vbuf
);
1253 buf
->flags
|= HFI_BUFFERFLAG_READONLY
;
1255 EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref
);
1257 static int is_buf_refed(struct venus_inst
*inst
, struct vb2_v4l2_buffer
*vbuf
)
1259 struct venus_buffer
*buf
= to_venus_buffer(vbuf
);
1261 if (buf
->flags
& HFI_BUFFERFLAG_READONLY
) {
1262 list_add_tail(&buf
->ref_list
, &inst
->delayed_process
);
1263 schedule_work(&inst
->delayed_process_work
);
1270 struct vb2_v4l2_buffer
*
1271 venus_helper_find_buf(struct venus_inst
*inst
, unsigned int type
, u32 idx
)
1273 struct v4l2_m2m_ctx
*m2m_ctx
= inst
->m2m_ctx
;
1275 if (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
1276 return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx
, idx
);
1278 return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx
, idx
);
1280 EXPORT_SYMBOL_GPL(venus_helper_find_buf
);
1282 int venus_helper_vb2_buf_init(struct vb2_buffer
*vb
)
1284 struct venus_inst
*inst
= vb2_get_drv_priv(vb
->vb2_queue
);
1285 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1286 struct venus_buffer
*buf
= to_venus_buffer(vbuf
);
1287 struct sg_table
*sgt
;
1289 sgt
= vb2_dma_sg_plane_desc(vb
, 0);
1293 buf
->size
= vb2_plane_size(vb
, 0);
1294 buf
->dma_addr
= sg_dma_address(sgt
->sgl
);
1296 if (vb
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
1297 list_add_tail(&buf
->reg_list
, &inst
->registeredbufs
);
1301 EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init
);
1303 int venus_helper_vb2_buf_prepare(struct vb2_buffer
*vb
)
1305 struct venus_inst
*inst
= vb2_get_drv_priv(vb
->vb2_queue
);
1306 unsigned int out_buf_size
= venus_helper_get_opb_size(inst
);
1307 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1309 if (V4L2_TYPE_IS_OUTPUT(vb
->vb2_queue
->type
)) {
1310 if (vbuf
->field
== V4L2_FIELD_ANY
)
1311 vbuf
->field
= V4L2_FIELD_NONE
;
1312 if (vbuf
->field
!= V4L2_FIELD_NONE
) {
1313 dev_err(inst
->core
->dev
, "%s field isn't supported\n",
1319 if (vb
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
1320 vb2_plane_size(vb
, 0) < out_buf_size
)
1322 if (vb
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
1323 vb2_plane_size(vb
, 0) < inst
->input_buf_size
)
1328 EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare
);
1330 static void cache_payload(struct venus_inst
*inst
, struct vb2_buffer
*vb
)
1332 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1333 unsigned int idx
= vbuf
->vb2_buf
.index
;
1335 if (vbuf
->vb2_buf
.type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
1336 inst
->payloads
[idx
] = vb2_get_plane_payload(vb
, 0);
1339 void venus_helper_vb2_buf_queue(struct vb2_buffer
*vb
)
1341 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1342 struct venus_inst
*inst
= vb2_get_drv_priv(vb
->vb2_queue
);
1343 struct v4l2_m2m_ctx
*m2m_ctx
= inst
->m2m_ctx
;
1346 mutex_lock(&inst
->lock
);
1348 v4l2_m2m_buf_queue(m2m_ctx
, vbuf
);
1350 cache_payload(inst
, vb
);
1352 if (inst
->session_type
== VIDC_SESSION_TYPE_ENC
&&
1353 !(inst
->streamon_out
&& inst
->streamon_cap
))
1356 if (vb2_start_streaming_called(vb
->vb2_queue
)) {
1357 ret
= is_buf_refed(inst
, vbuf
);
1361 ret
= session_process_buf(inst
, vbuf
);
1363 return_buf_error(inst
, vbuf
);
1367 mutex_unlock(&inst
->lock
);
1369 EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue
);
1371 void venus_helper_buffers_done(struct venus_inst
*inst
, unsigned int type
,
1372 enum vb2_buffer_state state
)
1374 struct vb2_v4l2_buffer
*buf
;
1376 if (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
1377 while ((buf
= v4l2_m2m_src_buf_remove(inst
->m2m_ctx
)))
1378 v4l2_m2m_buf_done(buf
, state
);
1379 } else if (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
1380 while ((buf
= v4l2_m2m_dst_buf_remove(inst
->m2m_ctx
)))
1381 v4l2_m2m_buf_done(buf
, state
);
1384 EXPORT_SYMBOL_GPL(venus_helper_buffers_done
);
1386 void venus_helper_vb2_stop_streaming(struct vb2_queue
*q
)
1388 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
1389 struct venus_core
*core
= inst
->core
;
1392 mutex_lock(&inst
->lock
);
1394 if (inst
->streamon_out
& inst
->streamon_cap
) {
1395 ret
= hfi_session_stop(inst
);
1396 ret
|= hfi_session_unload_res(inst
);
1397 ret
|= venus_helper_unregister_bufs(inst
);
1398 ret
|= venus_helper_intbufs_free(inst
);
1399 ret
|= hfi_session_deinit(inst
);
1401 if (inst
->session_error
|| core
->sys_error
)
1405 hfi_session_abort(inst
);
1407 venus_helper_free_dpb_bufs(inst
);
1409 venus_pm_load_scale(inst
);
1410 INIT_LIST_HEAD(&inst
->registeredbufs
);
1413 venus_helper_buffers_done(inst
, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
1414 VB2_BUF_STATE_ERROR
);
1415 venus_helper_buffers_done(inst
, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
1416 VB2_BUF_STATE_ERROR
);
1418 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
1419 inst
->streamon_out
= 0;
1421 inst
->streamon_cap
= 0;
1423 venus_pm_release_core(inst
);
1425 mutex_unlock(&inst
->lock
);
1427 EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming
);
1429 int venus_helper_process_initial_cap_bufs(struct venus_inst
*inst
)
1431 struct v4l2_m2m_ctx
*m2m_ctx
= inst
->m2m_ctx
;
1432 struct v4l2_m2m_buffer
*buf
, *n
;
1435 v4l2_m2m_for_each_dst_buf_safe(m2m_ctx
, buf
, n
) {
1436 ret
= session_process_buf(inst
, &buf
->vb
);
1438 return_buf_error(inst
, &buf
->vb
);
1445 EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs
);
1447 int venus_helper_process_initial_out_bufs(struct venus_inst
*inst
)
1449 struct v4l2_m2m_ctx
*m2m_ctx
= inst
->m2m_ctx
;
1450 struct v4l2_m2m_buffer
*buf
, *n
;
1453 v4l2_m2m_for_each_src_buf_safe(m2m_ctx
, buf
, n
) {
1454 ret
= session_process_buf(inst
, &buf
->vb
);
1456 return_buf_error(inst
, &buf
->vb
);
1463 EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs
);
1465 int venus_helper_vb2_start_streaming(struct venus_inst
*inst
)
1469 ret
= venus_helper_intbufs_alloc(inst
);
1473 ret
= session_register_bufs(inst
);
1477 venus_pm_load_scale(inst
);
1479 ret
= hfi_session_load_res(inst
);
1481 goto err_unreg_bufs
;
1483 ret
= hfi_session_start(inst
);
1485 goto err_unload_res
;
1490 hfi_session_unload_res(inst
);
1492 venus_helper_unregister_bufs(inst
);
1494 venus_helper_intbufs_free(inst
);
1497 EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming
);
1499 void venus_helper_m2m_device_run(void *priv
)
1501 struct venus_inst
*inst
= priv
;
1502 struct v4l2_m2m_ctx
*m2m_ctx
= inst
->m2m_ctx
;
1503 struct v4l2_m2m_buffer
*buf
, *n
;
1506 mutex_lock(&inst
->lock
);
1508 v4l2_m2m_for_each_dst_buf_safe(m2m_ctx
, buf
, n
) {
1509 ret
= session_process_buf(inst
, &buf
->vb
);
1511 return_buf_error(inst
, &buf
->vb
);
1514 v4l2_m2m_for_each_src_buf_safe(m2m_ctx
, buf
, n
) {
1515 ret
= session_process_buf(inst
, &buf
->vb
);
1517 return_buf_error(inst
, &buf
->vb
);
1520 mutex_unlock(&inst
->lock
);
1522 EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run
);
1524 void venus_helper_m2m_job_abort(void *priv
)
1526 struct venus_inst
*inst
= priv
;
1528 v4l2_m2m_job_finish(inst
->m2m_dev
, inst
->m2m_ctx
);
1530 EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort
);
1532 void venus_helper_init_instance(struct venus_inst
*inst
)
1534 if (inst
->session_type
== VIDC_SESSION_TYPE_DEC
) {
1535 INIT_LIST_HEAD(&inst
->delayed_process
);
1536 INIT_WORK(&inst
->delayed_process_work
,
1537 delayed_process_buf_func
);
1540 EXPORT_SYMBOL_GPL(venus_helper_init_instance
);
1542 static bool find_fmt_from_caps(struct venus_caps
*caps
, u32 buftype
, u32 fmt
)
1546 for (i
= 0; i
< caps
->num_fmts
; i
++) {
1547 if (caps
->fmts
[i
].buftype
== buftype
&&
1548 caps
->fmts
[i
].fmt
== fmt
)
1555 int venus_helper_get_out_fmts(struct venus_inst
*inst
, u32 v4l2_fmt
,
1556 u32
*out_fmt
, u32
*out2_fmt
, bool ubwc
)
1558 struct venus_core
*core
= inst
->core
;
1559 struct venus_caps
*caps
;
1560 u32 ubwc_fmt
, fmt
= to_hfi_raw_fmt(v4l2_fmt
);
1561 bool found
, found_ubwc
;
1563 *out_fmt
= *out2_fmt
= 0;
1568 caps
= venus_caps_by_codec(core
, inst
->hfi_codec
, inst
->session_type
);
1572 if (inst
->bit_depth
== VIDC_BITDEPTH_10
&&
1573 inst
->session_type
== VIDC_SESSION_TYPE_DEC
) {
1575 find_fmt_from_caps(caps
, HFI_BUFFER_OUTPUT
,
1576 HFI_COLOR_FORMAT_YUV420_TP10_UBWC
);
1577 found
= find_fmt_from_caps(caps
, HFI_BUFFER_OUTPUT2
,
1578 HFI_COLOR_FORMAT_NV12
);
1579 if (found_ubwc
&& found
) {
1581 * Hard-code DPB buffers to be 10bit UBWC and decoder
1582 * output buffers in 8bit NV12 until V4L2 is able to
1583 * expose compressed/tiled formats to applications.
1585 *out_fmt
= HFI_COLOR_FORMAT_YUV420_TP10_UBWC
;
1586 *out2_fmt
= HFI_COLOR_FORMAT_NV12
;
1594 ubwc_fmt
= fmt
| HFI_COLOR_FORMAT_UBWC_BASE
;
1595 found_ubwc
= find_fmt_from_caps(caps
, HFI_BUFFER_OUTPUT
,
1597 found
= find_fmt_from_caps(caps
, HFI_BUFFER_OUTPUT2
, fmt
);
1599 if (found_ubwc
&& found
) {
1600 *out_fmt
= ubwc_fmt
;
1606 found
= find_fmt_from_caps(caps
, HFI_BUFFER_OUTPUT
, fmt
);
1613 found
= find_fmt_from_caps(caps
, HFI_BUFFER_OUTPUT2
, fmt
);
1622 EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts
);