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.
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>
18 #include "hfi_venus_io.h"
19 #include "hfi_parser.h"
23 #include "pm_helpers.h"
26 * Three resons to keep MPLANE formats (despite that the number of planes
28 * - the MPLANE formats allow only one plane to be used
29 * - the downstream driver use MPLANE formats too
30 * - future firmware versions could add support for >1 planes
32 static const struct venus_format vdec_formats
[] = {
34 .pixfmt
= V4L2_PIX_FMT_NV12
,
36 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
38 .pixfmt
= V4L2_PIX_FMT_MPEG4
,
40 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
41 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
43 .pixfmt
= V4L2_PIX_FMT_MPEG2
,
45 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
46 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
48 .pixfmt
= V4L2_PIX_FMT_H263
,
50 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
51 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
53 .pixfmt
= V4L2_PIX_FMT_VC1_ANNEX_G
,
55 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
56 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
58 .pixfmt
= V4L2_PIX_FMT_VC1_ANNEX_L
,
60 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
61 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
63 .pixfmt
= V4L2_PIX_FMT_H264
,
65 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
66 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
68 .pixfmt
= V4L2_PIX_FMT_VP8
,
70 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
71 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
73 .pixfmt
= V4L2_PIX_FMT_VP9
,
75 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
76 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
78 .pixfmt
= V4L2_PIX_FMT_XVID
,
80 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
81 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
83 .pixfmt
= V4L2_PIX_FMT_HEVC
,
85 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
86 .flags
= V4L2_FMT_FLAG_DYN_RESOLUTION
,
90 static const struct venus_format
*
91 find_format(struct venus_inst
*inst
, u32 pixfmt
, u32 type
)
93 const struct venus_format
*fmt
= vdec_formats
;
94 unsigned int size
= ARRAY_SIZE(vdec_formats
);
97 for (i
= 0; i
< size
; i
++) {
98 if (fmt
[i
].pixfmt
== pixfmt
)
102 if (i
== size
|| fmt
[i
].type
!= type
)
105 if (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
106 !venus_helper_check_codec(inst
, fmt
[i
].pixfmt
))
112 static const struct venus_format
*
113 find_format_by_index(struct venus_inst
*inst
, unsigned int index
, u32 type
)
115 const struct venus_format
*fmt
= vdec_formats
;
116 unsigned int size
= ARRAY_SIZE(vdec_formats
);
117 unsigned int i
, k
= 0;
122 for (i
= 0; i
< size
; i
++) {
125 if (fmt
[i
].type
!= type
)
127 valid
= type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
||
128 venus_helper_check_codec(inst
, fmt
[i
].pixfmt
);
129 if (k
== index
&& valid
)
141 static const struct venus_format
*
142 vdec_try_fmt_common(struct venus_inst
*inst
, struct v4l2_format
*f
)
144 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
145 struct v4l2_plane_pix_format
*pfmt
= pixmp
->plane_fmt
;
146 const struct venus_format
*fmt
;
149 memset(pfmt
[0].reserved
, 0, sizeof(pfmt
[0].reserved
));
150 memset(pixmp
->reserved
, 0, sizeof(pixmp
->reserved
));
152 fmt
= find_format(inst
, pixmp
->pixelformat
, f
->type
);
154 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
155 pixmp
->pixelformat
= V4L2_PIX_FMT_NV12
;
156 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
157 pixmp
->pixelformat
= V4L2_PIX_FMT_H264
;
160 fmt
= find_format(inst
, pixmp
->pixelformat
, f
->type
);
163 pixmp
->width
= clamp(pixmp
->width
, frame_width_min(inst
),
164 frame_width_max(inst
));
165 pixmp
->height
= clamp(pixmp
->height
, frame_height_min(inst
),
166 frame_height_max(inst
));
168 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
169 pixmp
->height
= ALIGN(pixmp
->height
, 32);
171 if (pixmp
->field
== V4L2_FIELD_ANY
)
172 pixmp
->field
= V4L2_FIELD_NONE
;
173 pixmp
->num_planes
= fmt
->num_planes
;
176 szimage
= venus_helper_get_framesz(pixmp
->pixelformat
, pixmp
->width
,
179 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
180 pfmt
[0].sizeimage
= szimage
;
181 pfmt
[0].bytesperline
= ALIGN(pixmp
->width
, 128);
183 pfmt
[0].sizeimage
= clamp_t(u32
, pfmt
[0].sizeimage
, 0, SZ_8M
);
184 pfmt
[0].sizeimage
= max(pfmt
[0].sizeimage
, szimage
);
185 pfmt
[0].bytesperline
= 0;
191 static int vdec_try_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
193 struct venus_inst
*inst
= to_inst(file
);
195 vdec_try_fmt_common(inst
, f
);
200 static int vdec_check_src_change(struct venus_inst
*inst
)
204 if (inst
->subscriptions
& V4L2_EVENT_SOURCE_CHANGE
&&
205 inst
->codec_state
== VENUS_DEC_STATE_INIT
&&
209 if (inst
->subscriptions
& V4L2_EVENT_SOURCE_CHANGE
)
213 * The code snippet below is a workaround for backward compatibility
214 * with applications which doesn't support V4L2 events. It will be
215 * dropped in future once those applications are fixed.
218 if (inst
->codec_state
!= VENUS_DEC_STATE_INIT
)
221 ret
= wait_event_timeout(inst
->reconf_wait
, inst
->reconfig
,
222 msecs_to_jiffies(100));
226 if (!(inst
->codec_state
== VENUS_DEC_STATE_CAPTURE_SETUP
) ||
228 dev_dbg(inst
->core
->dev
, VDBGH
"wrong state\n");
234 static int vdec_g_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
236 struct venus_inst
*inst
= to_inst(file
);
237 const struct venus_format
*fmt
= NULL
;
238 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
241 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
243 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
246 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
247 ret
= vdec_check_src_change(inst
);
252 pixmp
->pixelformat
= fmt
->pixfmt
;
254 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
255 pixmp
->width
= inst
->width
;
256 pixmp
->height
= inst
->height
;
257 pixmp
->colorspace
= inst
->colorspace
;
258 pixmp
->ycbcr_enc
= inst
->ycbcr_enc
;
259 pixmp
->quantization
= inst
->quantization
;
260 pixmp
->xfer_func
= inst
->xfer_func
;
261 } else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
262 pixmp
->width
= inst
->out_width
;
263 pixmp
->height
= inst
->out_height
;
266 vdec_try_fmt_common(inst
, f
);
271 static int vdec_s_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
273 struct venus_inst
*inst
= to_inst(file
);
274 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
275 struct v4l2_pix_format_mplane orig_pixmp
;
276 const struct venus_format
*fmt
;
277 struct v4l2_format format
;
278 u32 pixfmt_out
= 0, pixfmt_cap
= 0;
281 q
= v4l2_m2m_get_vq(inst
->m2m_ctx
, f
->type
);
290 fmt
= vdec_try_fmt_common(inst
, f
);
292 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
293 pixfmt_out
= pixmp
->pixelformat
;
294 pixfmt_cap
= inst
->fmt_cap
->pixfmt
;
295 } else if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
296 pixfmt_cap
= pixmp
->pixelformat
;
297 pixfmt_out
= inst
->fmt_out
->pixfmt
;
300 memset(&format
, 0, sizeof(format
));
302 format
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
303 format
.fmt
.pix_mp
.pixelformat
= pixfmt_out
;
304 format
.fmt
.pix_mp
.width
= orig_pixmp
.width
;
305 format
.fmt
.pix_mp
.height
= orig_pixmp
.height
;
306 vdec_try_fmt_common(inst
, &format
);
308 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
309 inst
->out_width
= format
.fmt
.pix_mp
.width
;
310 inst
->out_height
= format
.fmt
.pix_mp
.height
;
311 inst
->colorspace
= pixmp
->colorspace
;
312 inst
->ycbcr_enc
= pixmp
->ycbcr_enc
;
313 inst
->quantization
= pixmp
->quantization
;
314 inst
->xfer_func
= pixmp
->xfer_func
;
315 inst
->input_buf_size
= pixmp
->plane_fmt
[0].sizeimage
;
318 memset(&format
, 0, sizeof(format
));
320 format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
321 format
.fmt
.pix_mp
.pixelformat
= pixfmt_cap
;
322 format
.fmt
.pix_mp
.width
= orig_pixmp
.width
;
323 format
.fmt
.pix_mp
.height
= orig_pixmp
.height
;
324 vdec_try_fmt_common(inst
, &format
);
326 inst
->width
= format
.fmt
.pix_mp
.width
;
327 inst
->height
= format
.fmt
.pix_mp
.height
;
330 inst
->crop
.width
= inst
->width
;
331 inst
->crop
.height
= inst
->height
;
333 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
335 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
342 vdec_g_selection(struct file
*file
, void *fh
, struct v4l2_selection
*s
)
344 struct venus_inst
*inst
= to_inst(file
);
346 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
&&
347 s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
354 case V4L2_SEL_TGT_CROP_BOUNDS
:
355 case V4L2_SEL_TGT_CROP_DEFAULT
:
356 case V4L2_SEL_TGT_CROP
:
357 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
359 s
->r
.width
= inst
->out_width
;
360 s
->r
.height
= inst
->out_height
;
362 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
363 case V4L2_SEL_TGT_COMPOSE_PADDED
:
364 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
366 s
->r
.width
= inst
->width
;
367 s
->r
.height
= inst
->height
;
369 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
370 case V4L2_SEL_TGT_COMPOSE
:
371 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
383 vdec_querycap(struct file
*file
, void *fh
, struct v4l2_capability
*cap
)
385 strscpy(cap
->driver
, "qcom-venus", sizeof(cap
->driver
));
386 strscpy(cap
->card
, "Qualcomm Venus video decoder", sizeof(cap
->card
));
387 strscpy(cap
->bus_info
, "platform:qcom-venus", sizeof(cap
->bus_info
));
392 static int vdec_enum_fmt(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*f
)
394 struct venus_inst
*inst
= to_inst(file
);
395 const struct venus_format
*fmt
;
397 memset(f
->reserved
, 0, sizeof(f
->reserved
));
399 fmt
= find_format_by_index(inst
, f
->index
, f
->type
);
403 f
->pixelformat
= fmt
->pixfmt
;
404 f
->flags
= fmt
->flags
;
409 static int vdec_s_parm(struct file
*file
, void *fh
, struct v4l2_streamparm
*a
)
411 struct venus_inst
*inst
= to_inst(file
);
412 struct v4l2_captureparm
*cap
= &a
->parm
.capture
;
413 struct v4l2_fract
*timeperframe
= &cap
->timeperframe
;
414 u64 us_per_frame
, fps
;
416 if (a
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
417 a
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
420 memset(cap
->reserved
, 0, sizeof(cap
->reserved
));
421 if (!timeperframe
->denominator
)
422 timeperframe
->denominator
= inst
->timeperframe
.denominator
;
423 if (!timeperframe
->numerator
)
424 timeperframe
->numerator
= inst
->timeperframe
.numerator
;
425 cap
->readbuffers
= 0;
426 cap
->extendedmode
= 0;
427 cap
->capability
= V4L2_CAP_TIMEPERFRAME
;
428 us_per_frame
= timeperframe
->numerator
* (u64
)USEC_PER_SEC
;
429 do_div(us_per_frame
, timeperframe
->denominator
);
434 fps
= (u64
)USEC_PER_SEC
;
435 do_div(fps
, us_per_frame
);
438 inst
->timeperframe
= *timeperframe
;
443 static int vdec_enum_framesizes(struct file
*file
, void *fh
,
444 struct v4l2_frmsizeenum
*fsize
)
446 struct venus_inst
*inst
= to_inst(file
);
447 const struct venus_format
*fmt
;
449 fmt
= find_format(inst
, fsize
->pixel_format
,
450 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
);
452 fmt
= find_format(inst
, fsize
->pixel_format
,
453 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
);
461 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
463 fsize
->stepwise
.min_width
= frame_width_min(inst
);
464 fsize
->stepwise
.max_width
= frame_width_max(inst
);
465 fsize
->stepwise
.step_width
= frame_width_step(inst
);
466 fsize
->stepwise
.min_height
= frame_height_min(inst
);
467 fsize
->stepwise
.max_height
= frame_height_max(inst
);
468 fsize
->stepwise
.step_height
= frame_height_step(inst
);
473 static int vdec_subscribe_event(struct v4l2_fh
*fh
,
474 const struct v4l2_event_subscription
*sub
)
476 struct venus_inst
*inst
= container_of(fh
, struct venus_inst
, fh
);
481 return v4l2_event_subscribe(fh
, sub
, 2, NULL
);
482 case V4L2_EVENT_SOURCE_CHANGE
:
483 ret
= v4l2_src_change_event_subscribe(fh
, sub
);
486 inst
->subscriptions
|= V4L2_EVENT_SOURCE_CHANGE
;
488 case V4L2_EVENT_CTRL
:
489 return v4l2_ctrl_subscribe_event(fh
, sub
);
496 vdec_decoder_cmd(struct file
*file
, void *fh
, struct v4l2_decoder_cmd
*cmd
)
498 struct venus_inst
*inst
= to_inst(file
);
499 struct hfi_frame_data fdata
= {0};
502 ret
= v4l2_m2m_ioctl_try_decoder_cmd(file
, fh
, cmd
);
506 mutex_lock(&inst
->lock
);
508 if (cmd
->cmd
== V4L2_DEC_CMD_STOP
) {
510 * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on
511 * decoder input to signal EOS.
513 if (!(inst
->streamon_out
&& inst
->streamon_cap
))
516 fdata
.buffer_type
= HFI_BUFFER_INPUT
;
517 fdata
.flags
|= HFI_BUFFERFLAG_EOS
;
518 fdata
.device_addr
= 0xdeadb000;
520 ret
= hfi_session_process_buf(inst
, &fdata
);
522 if (!ret
&& inst
->codec_state
== VENUS_DEC_STATE_DECODING
)
523 inst
->codec_state
= VENUS_DEC_STATE_DRAIN
;
527 mutex_unlock(&inst
->lock
);
531 static const struct v4l2_ioctl_ops vdec_ioctl_ops
= {
532 .vidioc_querycap
= vdec_querycap
,
533 .vidioc_enum_fmt_vid_cap
= vdec_enum_fmt
,
534 .vidioc_enum_fmt_vid_out
= vdec_enum_fmt
,
535 .vidioc_s_fmt_vid_cap_mplane
= vdec_s_fmt
,
536 .vidioc_s_fmt_vid_out_mplane
= vdec_s_fmt
,
537 .vidioc_g_fmt_vid_cap_mplane
= vdec_g_fmt
,
538 .vidioc_g_fmt_vid_out_mplane
= vdec_g_fmt
,
539 .vidioc_try_fmt_vid_cap_mplane
= vdec_try_fmt
,
540 .vidioc_try_fmt_vid_out_mplane
= vdec_try_fmt
,
541 .vidioc_g_selection
= vdec_g_selection
,
542 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
543 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
544 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
545 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
546 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
547 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
548 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
549 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
550 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
551 .vidioc_s_parm
= vdec_s_parm
,
552 .vidioc_enum_framesizes
= vdec_enum_framesizes
,
553 .vidioc_subscribe_event
= vdec_subscribe_event
,
554 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
555 .vidioc_try_decoder_cmd
= v4l2_m2m_ioctl_try_decoder_cmd
,
556 .vidioc_decoder_cmd
= vdec_decoder_cmd
,
559 static int vdec_pm_get(struct venus_inst
*inst
)
561 struct venus_core
*core
= inst
->core
;
562 struct device
*dev
= core
->dev_dec
;
565 mutex_lock(&core
->pm_lock
);
566 ret
= pm_runtime_get_sync(dev
);
567 mutex_unlock(&core
->pm_lock
);
569 return ret
< 0 ? ret
: 0;
572 static int vdec_pm_put(struct venus_inst
*inst
, bool autosuspend
)
574 struct venus_core
*core
= inst
->core
;
575 struct device
*dev
= core
->dev_dec
;
578 mutex_lock(&core
->pm_lock
);
581 ret
= pm_runtime_put_autosuspend(dev
);
583 ret
= pm_runtime_put_sync(dev
);
585 mutex_unlock(&core
->pm_lock
);
587 return ret
< 0 ? ret
: 0;
590 static int vdec_pm_get_put(struct venus_inst
*inst
)
592 struct venus_core
*core
= inst
->core
;
593 struct device
*dev
= core
->dev_dec
;
596 mutex_lock(&core
->pm_lock
);
598 if (pm_runtime_suspended(dev
)) {
599 ret
= pm_runtime_get_sync(dev
);
603 ret
= pm_runtime_put_autosuspend(dev
);
607 mutex_unlock(&core
->pm_lock
);
609 return ret
< 0 ? ret
: 0;
612 static void vdec_pm_touch(struct venus_inst
*inst
)
614 pm_runtime_mark_last_busy(inst
->core
->dev_dec
);
617 static int vdec_set_properties(struct venus_inst
*inst
)
619 struct vdec_controls
*ctr
= &inst
->controls
.dec
;
620 struct hfi_enable en
= { .enable
= 1 };
624 if (ctr
->post_loop_deb_mode
) {
625 ptype
= HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER
;
626 ret
= hfi_session_set_property(inst
, ptype
, &en
);
634 #define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
636 static int vdec_output_conf(struct venus_inst
*inst
)
638 struct venus_core
*core
= inst
->core
;
639 struct hfi_enable en
= { .enable
= 1 };
640 u32 width
= inst
->out_width
;
641 u32 height
= inst
->out_height
;
642 u32 out_fmt
, out2_fmt
;
647 ret
= venus_helper_set_work_mode(inst
, VIDC_WORK_MODE_2
);
651 if (core
->res
->hfi_version
== HFI_VERSION_1XX
) {
652 ptype
= HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER
;
653 ret
= hfi_session_set_property(inst
, ptype
, &en
);
658 /* Force searching UBWC formats for bigger then HD resolutions */
659 if (width
> 1920 && height
> ALIGN(1080, 32))
662 /* For Venus v4 UBWC format is mandatory */
666 ret
= venus_helper_get_out_fmts(inst
, inst
->fmt_cap
->pixfmt
, &out_fmt
,
671 inst
->output_buf_size
=
672 venus_helper_get_framesz_raw(out_fmt
, width
, height
);
673 inst
->output2_buf_size
=
674 venus_helper_get_framesz_raw(out2_fmt
, width
, height
);
676 if (is_ubwc_fmt(out_fmt
)) {
677 inst
->opb_buftype
= HFI_BUFFER_OUTPUT2
;
678 inst
->opb_fmt
= out2_fmt
;
679 inst
->dpb_buftype
= HFI_BUFFER_OUTPUT
;
680 inst
->dpb_fmt
= out_fmt
;
681 } else if (is_ubwc_fmt(out2_fmt
)) {
682 inst
->opb_buftype
= HFI_BUFFER_OUTPUT
;
683 inst
->opb_fmt
= out_fmt
;
684 inst
->dpb_buftype
= HFI_BUFFER_OUTPUT2
;
685 inst
->dpb_fmt
= out2_fmt
;
687 inst
->opb_buftype
= HFI_BUFFER_OUTPUT
;
688 inst
->opb_fmt
= out_fmt
;
689 inst
->dpb_buftype
= 0;
693 ret
= venus_helper_set_raw_format(inst
, inst
->opb_fmt
,
699 ret
= venus_helper_set_multistream(inst
, false, true);
703 ret
= venus_helper_set_raw_format(inst
, inst
->dpb_fmt
,
708 ret
= venus_helper_set_output_resolution(inst
, width
, height
,
714 if (IS_V3(core
) || IS_V4(core
)) {
715 if (inst
->output2_buf_size
) {
716 ret
= venus_helper_set_bufsize(inst
,
717 inst
->output2_buf_size
,
723 if (inst
->output_buf_size
) {
724 ret
= venus_helper_set_bufsize(inst
,
725 inst
->output_buf_size
,
732 ret
= venus_helper_set_dyn_bufmode(inst
);
739 static int vdec_session_init(struct venus_inst
*inst
)
743 ret
= hfi_session_init(inst
, inst
->fmt_out
->pixfmt
);
749 ret
= venus_helper_set_input_resolution(inst
, frame_width_min(inst
),
750 frame_height_min(inst
));
754 ret
= venus_helper_init_codec_freq_data(inst
);
760 hfi_session_deinit(inst
);
764 static int vdec_num_buffers(struct venus_inst
*inst
, unsigned int *in_num
,
765 unsigned int *out_num
)
767 enum hfi_version ver
= inst
->core
->res
->hfi_version
;
768 struct hfi_buffer_requirements bufreq
;
771 *in_num
= *out_num
= 0;
773 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_INPUT
, &bufreq
);
777 *in_num
= HFI_BUFREQ_COUNT_MIN(&bufreq
, ver
);
779 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_OUTPUT
, &bufreq
);
783 *out_num
= HFI_BUFREQ_COUNT_MIN(&bufreq
, ver
);
788 static int vdec_queue_setup(struct vb2_queue
*q
,
789 unsigned int *num_buffers
, unsigned int *num_planes
,
790 unsigned int sizes
[], struct device
*alloc_devs
[])
792 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
793 unsigned int in_num
, out_num
;
797 unsigned int output_buf_size
= venus_helper_get_opb_size(inst
);
799 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
800 *num_planes
!= inst
->fmt_out
->num_planes
)
803 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
804 *num_planes
!= inst
->fmt_cap
->num_planes
)
807 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
808 sizes
[0] < inst
->input_buf_size
)
811 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
812 sizes
[0] < output_buf_size
)
818 ret
= vdec_pm_get(inst
);
822 ret
= vdec_session_init(inst
);
826 ret
= vdec_num_buffers(inst
, &in_num
, &out_num
);
830 ret
= vdec_pm_put(inst
, false);
835 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
836 *num_planes
= inst
->fmt_out
->num_planes
;
837 sizes
[0] = venus_helper_get_framesz(inst
->fmt_out
->pixfmt
,
840 sizes
[0] = max(sizes
[0], inst
->input_buf_size
);
841 inst
->input_buf_size
= sizes
[0];
842 *num_buffers
= max(*num_buffers
, in_num
);
843 inst
->num_input_bufs
= *num_buffers
;
844 inst
->num_output_bufs
= out_num
;
846 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
847 *num_planes
= inst
->fmt_cap
->num_planes
;
848 sizes
[0] = venus_helper_get_framesz(inst
->fmt_cap
->pixfmt
,
851 inst
->output_buf_size
= sizes
[0];
852 *num_buffers
= max(*num_buffers
, out_num
);
853 inst
->num_output_bufs
= *num_buffers
;
855 mutex_lock(&inst
->lock
);
856 if (inst
->codec_state
== VENUS_DEC_STATE_CAPTURE_SETUP
)
857 inst
->codec_state
= VENUS_DEC_STATE_STOPPED
;
858 mutex_unlock(&inst
->lock
);
868 vdec_pm_put(inst
, false);
872 static int vdec_verify_conf(struct venus_inst
*inst
)
874 enum hfi_version ver
= inst
->core
->res
->hfi_version
;
875 struct hfi_buffer_requirements bufreq
;
878 if (!inst
->num_input_bufs
|| !inst
->num_output_bufs
)
881 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_OUTPUT
, &bufreq
);
885 if (inst
->num_output_bufs
< bufreq
.count_actual
||
886 inst
->num_output_bufs
< HFI_BUFREQ_COUNT_MIN(&bufreq
, ver
))
889 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_INPUT
, &bufreq
);
893 if (inst
->num_input_bufs
< HFI_BUFREQ_COUNT_MIN(&bufreq
, ver
))
899 static int vdec_start_capture(struct venus_inst
*inst
)
903 if (!inst
->streamon_out
)
906 if (inst
->codec_state
== VENUS_DEC_STATE_DECODING
) {
910 venus_helper_queue_dpb_bufs(inst
);
911 venus_helper_process_initial_cap_bufs(inst
);
912 inst
->streamon_cap
= 1;
916 if (inst
->codec_state
!= VENUS_DEC_STATE_STOPPED
)
920 ret
= hfi_session_flush(inst
, HFI_FLUSH_OUTPUT
, true);
924 ret
= vdec_output_conf(inst
);
928 ret
= venus_helper_set_num_bufs(inst
, inst
->num_input_bufs
,
929 VB2_MAX_FRAME
, VB2_MAX_FRAME
);
933 ret
= venus_helper_intbufs_realloc(inst
);
937 ret
= venus_helper_alloc_dpb_bufs(inst
);
941 ret
= venus_helper_queue_dpb_bufs(inst
);
945 ret
= venus_helper_process_initial_cap_bufs(inst
);
949 venus_pm_load_scale(inst
);
951 ret
= hfi_session_continue(inst
);
955 inst
->codec_state
= VENUS_DEC_STATE_DECODING
;
957 inst
->streamon_cap
= 1;
958 inst
->sequence_cap
= 0;
959 inst
->reconfig
= false;
964 venus_helper_free_dpb_bufs(inst
);
969 static int vdec_start_output(struct venus_inst
*inst
)
973 if (inst
->codec_state
== VENUS_DEC_STATE_SEEK
) {
974 ret
= venus_helper_process_initial_out_bufs(inst
);
975 inst
->codec_state
= VENUS_DEC_STATE_DECODING
;
979 if (inst
->codec_state
== VENUS_DEC_STATE_INIT
||
980 inst
->codec_state
== VENUS_DEC_STATE_CAPTURE_SETUP
) {
981 ret
= venus_helper_process_initial_out_bufs(inst
);
985 if (inst
->codec_state
!= VENUS_DEC_STATE_DEINIT
)
988 venus_helper_init_instance(inst
);
989 inst
->sequence_out
= 0;
990 inst
->reconfig
= false;
992 ret
= vdec_set_properties(inst
);
996 ret
= vdec_output_conf(inst
);
1000 ret
= vdec_verify_conf(inst
);
1004 ret
= venus_helper_set_num_bufs(inst
, inst
->num_input_bufs
,
1005 VB2_MAX_FRAME
, VB2_MAX_FRAME
);
1009 ret
= venus_helper_vb2_start_streaming(inst
);
1013 ret
= venus_helper_process_initial_out_bufs(inst
);
1017 inst
->codec_state
= VENUS_DEC_STATE_INIT
;
1020 inst
->streamon_out
= 1;
1024 static int vdec_start_streaming(struct vb2_queue
*q
, unsigned int count
)
1026 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
1029 mutex_lock(&inst
->lock
);
1031 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
1032 ret
= vdec_start_capture(inst
);
1034 ret
= vdec_pm_get(inst
);
1038 ret
= venus_pm_acquire_core(inst
);
1042 ret
= vdec_pm_put(inst
, true);
1046 ret
= vdec_start_output(inst
);
1052 mutex_unlock(&inst
->lock
);
1056 vdec_pm_put(inst
, false);
1058 venus_helper_buffers_done(inst
, q
->type
, VB2_BUF_STATE_QUEUED
);
1059 mutex_unlock(&inst
->lock
);
1063 static void vdec_cancel_dst_buffers(struct venus_inst
*inst
)
1065 struct vb2_v4l2_buffer
*buf
;
1067 while ((buf
= v4l2_m2m_dst_buf_remove(inst
->m2m_ctx
)))
1068 v4l2_m2m_buf_done(buf
, VB2_BUF_STATE_ERROR
);
1071 static int vdec_stop_capture(struct venus_inst
*inst
)
1075 switch (inst
->codec_state
) {
1076 case VENUS_DEC_STATE_DECODING
:
1077 ret
= hfi_session_flush(inst
, HFI_FLUSH_ALL
, true);
1079 case VENUS_DEC_STATE_DRAIN
:
1080 vdec_cancel_dst_buffers(inst
);
1081 inst
->codec_state
= VENUS_DEC_STATE_STOPPED
;
1083 case VENUS_DEC_STATE_DRC
:
1086 case VENUS_DEC_STATE_DRC_FLUSH_DONE
:
1087 inst
->codec_state
= VENUS_DEC_STATE_CAPTURE_SETUP
;
1088 venus_helper_free_dpb_bufs(inst
);
1097 static int vdec_stop_output(struct venus_inst
*inst
)
1101 switch (inst
->codec_state
) {
1102 case VENUS_DEC_STATE_DECODING
:
1103 case VENUS_DEC_STATE_DRAIN
:
1104 case VENUS_DEC_STATE_STOPPED
:
1105 ret
= hfi_session_flush(inst
, HFI_FLUSH_ALL
, true);
1106 inst
->codec_state
= VENUS_DEC_STATE_SEEK
;
1108 case VENUS_DEC_STATE_INIT
:
1109 case VENUS_DEC_STATE_CAPTURE_SETUP
:
1110 ret
= hfi_session_flush(inst
, HFI_FLUSH_INPUT
, true);
1119 static void vdec_stop_streaming(struct vb2_queue
*q
)
1121 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
1124 mutex_lock(&inst
->lock
);
1126 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
1127 ret
= vdec_stop_capture(inst
);
1129 ret
= vdec_stop_output(inst
);
1131 venus_helper_buffers_done(inst
, q
->type
, VB2_BUF_STATE_ERROR
);
1136 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
1137 inst
->streamon_out
= 0;
1139 inst
->streamon_cap
= 0;
1142 mutex_unlock(&inst
->lock
);
1145 static void vdec_session_release(struct venus_inst
*inst
)
1147 struct venus_core
*core
= inst
->core
;
1152 mutex_lock(&inst
->lock
);
1153 inst
->codec_state
= VENUS_DEC_STATE_DEINIT
;
1155 ret
= hfi_session_stop(inst
);
1156 abort
= (ret
&& ret
!= -EINVAL
) ? 1 : 0;
1157 ret
= hfi_session_unload_res(inst
);
1158 abort
= (ret
&& ret
!= -EINVAL
) ? 1 : 0;
1159 ret
= venus_helper_unregister_bufs(inst
);
1160 abort
= (ret
&& ret
!= -EINVAL
) ? 1 : 0;
1161 ret
= venus_helper_intbufs_free(inst
);
1162 abort
= (ret
&& ret
!= -EINVAL
) ? 1 : 0;
1163 ret
= hfi_session_deinit(inst
);
1164 abort
= (ret
&& ret
!= -EINVAL
) ? 1 : 0;
1166 if (inst
->session_error
|| core
->sys_error
)
1170 hfi_session_abort(inst
);
1172 venus_helper_free_dpb_bufs(inst
);
1173 venus_pm_load_scale(inst
);
1174 INIT_LIST_HEAD(&inst
->registeredbufs
);
1175 mutex_unlock(&inst
->lock
);
1177 venus_pm_release_core(inst
);
1178 vdec_pm_put(inst
, false);
1181 static int vdec_buf_init(struct vb2_buffer
*vb
)
1183 struct venus_inst
*inst
= vb2_get_drv_priv(vb
->vb2_queue
);
1187 return venus_helper_vb2_buf_init(vb
);
1190 static void vdec_buf_cleanup(struct vb2_buffer
*vb
)
1192 struct venus_inst
*inst
= vb2_get_drv_priv(vb
->vb2_queue
);
1193 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
1194 struct venus_buffer
*buf
= to_venus_buffer(vbuf
);
1196 mutex_lock(&inst
->lock
);
1197 if (vb
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
1198 if (!list_empty(&inst
->registeredbufs
))
1199 list_del_init(&buf
->reg_list
);
1200 mutex_unlock(&inst
->lock
);
1203 if (!inst
->buf_count
)
1204 vdec_session_release(inst
);
1207 static void vdec_vb2_buf_queue(struct vb2_buffer
*vb
)
1209 struct venus_inst
*inst
= vb2_get_drv_priv(vb
->vb2_queue
);
1211 vdec_pm_get_put(inst
);
1213 venus_helper_vb2_buf_queue(vb
);
1216 static const struct vb2_ops vdec_vb2_ops
= {
1217 .queue_setup
= vdec_queue_setup
,
1218 .buf_init
= vdec_buf_init
,
1219 .buf_cleanup
= vdec_buf_cleanup
,
1220 .buf_prepare
= venus_helper_vb2_buf_prepare
,
1221 .start_streaming
= vdec_start_streaming
,
1222 .stop_streaming
= vdec_stop_streaming
,
1223 .buf_queue
= vdec_vb2_buf_queue
,
1226 static void vdec_buf_done(struct venus_inst
*inst
, unsigned int buf_type
,
1227 u32 tag
, u32 bytesused
, u32 data_offset
, u32 flags
,
1228 u32 hfi_flags
, u64 timestamp_us
)
1230 enum vb2_buffer_state state
= VB2_BUF_STATE_DONE
;
1231 struct vb2_v4l2_buffer
*vbuf
;
1232 struct vb2_buffer
*vb
;
1235 vdec_pm_touch(inst
);
1237 if (buf_type
== HFI_BUFFER_INPUT
)
1238 type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1240 type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1242 vbuf
= venus_helper_find_buf(inst
, type
, tag
);
1246 vbuf
->flags
= flags
;
1247 vbuf
->field
= V4L2_FIELD_NONE
;
1248 vb
= &vbuf
->vb2_buf
;
1250 if (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
1251 vb2_set_plane_payload(vb
, 0, bytesused
);
1252 vb
->planes
[0].data_offset
= data_offset
;
1253 vb
->timestamp
= timestamp_us
* NSEC_PER_USEC
;
1254 vbuf
->sequence
= inst
->sequence_cap
++;
1256 if (inst
->last_buf
== vb
) {
1257 inst
->last_buf
= NULL
;
1258 vbuf
->flags
|= V4L2_BUF_FLAG_LAST
;
1259 vb2_set_plane_payload(vb
, 0, 0);
1263 if (vbuf
->flags
& V4L2_BUF_FLAG_LAST
) {
1264 const struct v4l2_event ev
= { .type
= V4L2_EVENT_EOS
};
1266 v4l2_event_queue_fh(&inst
->fh
, &ev
);
1268 if (inst
->codec_state
== VENUS_DEC_STATE_DRAIN
)
1269 inst
->codec_state
= VENUS_DEC_STATE_STOPPED
;
1273 state
= VB2_BUF_STATE_ERROR
;
1275 vbuf
->sequence
= inst
->sequence_out
++;
1278 venus_helper_get_ts_metadata(inst
, timestamp_us
, vbuf
);
1280 if (hfi_flags
& HFI_BUFFERFLAG_READONLY
)
1281 venus_helper_acquire_buf_ref(vbuf
);
1283 if (hfi_flags
& HFI_BUFFERFLAG_DATACORRUPT
)
1284 state
= VB2_BUF_STATE_ERROR
;
1286 if (hfi_flags
& HFI_BUFFERFLAG_DROP_FRAME
) {
1287 state
= VB2_BUF_STATE_ERROR
;
1288 vb2_set_plane_payload(vb
, 0, 0);
1292 v4l2_m2m_buf_done(vbuf
, state
);
1295 static void vdec_event_change(struct venus_inst
*inst
,
1296 struct hfi_event_data
*ev_data
, bool sufficient
)
1298 static const struct v4l2_event ev
= {
1299 .type
= V4L2_EVENT_SOURCE_CHANGE
,
1300 .u
.src_change
.changes
= V4L2_EVENT_SRC_CH_RESOLUTION
};
1301 struct device
*dev
= inst
->core
->dev_dec
;
1302 struct v4l2_format format
= {};
1304 mutex_lock(&inst
->lock
);
1306 format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1307 format
.fmt
.pix_mp
.pixelformat
= inst
->fmt_cap
->pixfmt
;
1308 format
.fmt
.pix_mp
.width
= ev_data
->width
;
1309 format
.fmt
.pix_mp
.height
= ev_data
->height
;
1311 vdec_try_fmt_common(inst
, &format
);
1313 inst
->width
= format
.fmt
.pix_mp
.width
;
1314 inst
->height
= format
.fmt
.pix_mp
.height
;
1316 * Some versions of the firmware do not report crop information for
1317 * all codecs. For these cases, set the crop to the coded resolution.
1319 if (ev_data
->input_crop
.width
> 0 && ev_data
->input_crop
.height
> 0) {
1320 inst
->crop
.left
= ev_data
->input_crop
.left
;
1321 inst
->crop
.top
= ev_data
->input_crop
.top
;
1322 inst
->crop
.width
= ev_data
->input_crop
.width
;
1323 inst
->crop
.height
= ev_data
->input_crop
.height
;
1325 inst
->crop
.left
= 0;
1327 inst
->crop
.width
= ev_data
->width
;
1328 inst
->crop
.height
= ev_data
->height
;
1331 inst
->out_width
= ev_data
->width
;
1332 inst
->out_height
= ev_data
->height
;
1334 if (inst
->bit_depth
!= ev_data
->bit_depth
)
1335 inst
->bit_depth
= ev_data
->bit_depth
;
1337 dev_dbg(dev
, VDBGM
"event %s sufficient resources (%ux%u)\n",
1338 sufficient
? "" : "not", ev_data
->width
, ev_data
->height
);
1341 hfi_session_continue(inst
);
1343 switch (inst
->codec_state
) {
1344 case VENUS_DEC_STATE_INIT
:
1345 inst
->codec_state
= VENUS_DEC_STATE_CAPTURE_SETUP
;
1347 case VENUS_DEC_STATE_DECODING
:
1348 inst
->codec_state
= VENUS_DEC_STATE_DRC
;
1356 * The assumption is that the firmware have to return the last buffer
1357 * before this event is received in the v4l2 driver. Also the firmware
1358 * itself doesn't mark the last decoder output buffer with HFI EOS flag.
1361 if (!sufficient
&& inst
->codec_state
== VENUS_DEC_STATE_DRC
) {
1362 struct vb2_v4l2_buffer
*last
;
1365 last
= v4l2_m2m_last_dst_buf(inst
->m2m_ctx
);
1367 inst
->last_buf
= &last
->vb2_buf
;
1369 ret
= hfi_session_flush(inst
, HFI_FLUSH_OUTPUT
, false);
1371 dev_dbg(dev
, VDBGH
"flush output error %d\n", ret
);
1374 inst
->reconfig
= true;
1375 v4l2_event_queue_fh(&inst
->fh
, &ev
);
1376 wake_up(&inst
->reconf_wait
);
1378 mutex_unlock(&inst
->lock
);
1381 static void vdec_event_notify(struct venus_inst
*inst
, u32 event
,
1382 struct hfi_event_data
*data
)
1384 struct venus_core
*core
= inst
->core
;
1385 struct device
*dev
= core
->dev_dec
;
1387 vdec_pm_touch(inst
);
1390 case EVT_SESSION_ERROR
:
1391 inst
->session_error
= true;
1392 dev_err(dev
, "dec: event session error %x\n", inst
->error
);
1394 case EVT_SYS_EVENT_CHANGE
:
1395 switch (data
->event_type
) {
1396 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES
:
1397 vdec_event_change(inst
, data
, true);
1399 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES
:
1400 vdec_event_change(inst
, data
, false);
1402 case HFI_EVENT_RELEASE_BUFFER_REFERENCE
:
1403 venus_helper_release_buf_ref(inst
, data
->tag
);
1414 static void vdec_flush_done(struct venus_inst
*inst
)
1416 if (inst
->codec_state
== VENUS_DEC_STATE_DRC
)
1417 inst
->codec_state
= VENUS_DEC_STATE_DRC_FLUSH_DONE
;
1420 static const struct hfi_inst_ops vdec_hfi_ops
= {
1421 .buf_done
= vdec_buf_done
,
1422 .event_notify
= vdec_event_notify
,
1423 .flush_done
= vdec_flush_done
,
1426 static void vdec_inst_init(struct venus_inst
*inst
)
1428 inst
->hfi_codec
= HFI_VIDEO_CODEC_H264
;
1429 inst
->fmt_out
= &vdec_formats
[6];
1430 inst
->fmt_cap
= &vdec_formats
[0];
1431 inst
->width
= frame_width_min(inst
);
1432 inst
->height
= ALIGN(frame_height_min(inst
), 32);
1433 inst
->crop
.left
= 0;
1435 inst
->crop
.width
= inst
->width
;
1436 inst
->crop
.height
= inst
->height
;
1437 inst
->out_width
= frame_width_min(inst
);
1438 inst
->out_height
= frame_height_min(inst
);
1440 inst
->timeperframe
.numerator
= 1;
1441 inst
->timeperframe
.denominator
= 30;
1442 inst
->opb_buftype
= HFI_BUFFER_OUTPUT
;
1445 static void vdec_m2m_device_run(void *priv
)
1449 static const struct v4l2_m2m_ops vdec_m2m_ops
= {
1450 .device_run
= vdec_m2m_device_run
,
1451 .job_abort
= venus_helper_m2m_job_abort
,
1454 static int m2m_queue_init(void *priv
, struct vb2_queue
*src_vq
,
1455 struct vb2_queue
*dst_vq
)
1457 struct venus_inst
*inst
= priv
;
1460 src_vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1461 src_vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
1462 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1463 src_vq
->ops
= &vdec_vb2_ops
;
1464 src_vq
->mem_ops
= &vb2_dma_sg_memops
;
1465 src_vq
->drv_priv
= inst
;
1466 src_vq
->buf_struct_size
= sizeof(struct venus_buffer
);
1467 src_vq
->allow_zero_bytesused
= 1;
1468 src_vq
->min_buffers_needed
= 0;
1469 src_vq
->dev
= inst
->core
->dev
;
1470 ret
= vb2_queue_init(src_vq
);
1474 dst_vq
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1475 dst_vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
1476 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1477 dst_vq
->ops
= &vdec_vb2_ops
;
1478 dst_vq
->mem_ops
= &vb2_dma_sg_memops
;
1479 dst_vq
->drv_priv
= inst
;
1480 dst_vq
->buf_struct_size
= sizeof(struct venus_buffer
);
1481 dst_vq
->allow_zero_bytesused
= 1;
1482 dst_vq
->min_buffers_needed
= 0;
1483 dst_vq
->dev
= inst
->core
->dev
;
1484 return vb2_queue_init(dst_vq
);
1487 static int vdec_open(struct file
*file
)
1489 struct venus_core
*core
= video_drvdata(file
);
1490 struct venus_inst
*inst
;
1493 inst
= kzalloc(sizeof(*inst
), GFP_KERNEL
);
1497 INIT_LIST_HEAD(&inst
->dpbbufs
);
1498 INIT_LIST_HEAD(&inst
->registeredbufs
);
1499 INIT_LIST_HEAD(&inst
->internalbufs
);
1500 INIT_LIST_HEAD(&inst
->list
);
1501 mutex_init(&inst
->lock
);
1504 inst
->session_type
= VIDC_SESSION_TYPE_DEC
;
1505 inst
->num_output_bufs
= 1;
1506 inst
->codec_state
= VENUS_DEC_STATE_DEINIT
;
1507 inst
->buf_count
= 0;
1508 inst
->clk_data
.core_id
= VIDC_CORE_ID_DEFAULT
;
1509 inst
->core_acquired
= false;
1510 inst
->bit_depth
= VIDC_BITDEPTH_8
;
1511 init_waitqueue_head(&inst
->reconf_wait
);
1512 venus_helper_init_instance(inst
);
1514 ret
= vdec_ctrl_init(inst
);
1518 ret
= hfi_session_create(inst
, &vdec_hfi_ops
);
1520 goto err_ctrl_deinit
;
1522 vdec_inst_init(inst
);
1525 * create m2m device for every instance, the m2m context scheduling
1526 * is made by firmware side so we do not need to care about.
1528 inst
->m2m_dev
= v4l2_m2m_init(&vdec_m2m_ops
);
1529 if (IS_ERR(inst
->m2m_dev
)) {
1530 ret
= PTR_ERR(inst
->m2m_dev
);
1531 goto err_session_destroy
;
1534 inst
->m2m_ctx
= v4l2_m2m_ctx_init(inst
->m2m_dev
, inst
, m2m_queue_init
);
1535 if (IS_ERR(inst
->m2m_ctx
)) {
1536 ret
= PTR_ERR(inst
->m2m_ctx
);
1537 goto err_m2m_release
;
1540 v4l2_fh_init(&inst
->fh
, core
->vdev_dec
);
1542 inst
->fh
.ctrl_handler
= &inst
->ctrl_handler
;
1543 v4l2_fh_add(&inst
->fh
);
1544 inst
->fh
.m2m_ctx
= inst
->m2m_ctx
;
1545 file
->private_data
= &inst
->fh
;
1550 v4l2_m2m_release(inst
->m2m_dev
);
1551 err_session_destroy
:
1552 hfi_session_destroy(inst
);
1554 vdec_ctrl_deinit(inst
);
1560 static int vdec_close(struct file
*file
)
1562 struct venus_inst
*inst
= to_inst(file
);
1566 v4l2_m2m_ctx_release(inst
->m2m_ctx
);
1567 v4l2_m2m_release(inst
->m2m_dev
);
1568 vdec_ctrl_deinit(inst
);
1569 hfi_session_destroy(inst
);
1570 mutex_destroy(&inst
->lock
);
1571 v4l2_fh_del(&inst
->fh
);
1572 v4l2_fh_exit(&inst
->fh
);
1574 vdec_pm_put(inst
, false);
1580 static const struct v4l2_file_operations vdec_fops
= {
1581 .owner
= THIS_MODULE
,
1583 .release
= vdec_close
,
1584 .unlocked_ioctl
= video_ioctl2
,
1585 .poll
= v4l2_m2m_fop_poll
,
1586 .mmap
= v4l2_m2m_fop_mmap
,
1589 static int vdec_probe(struct platform_device
*pdev
)
1591 struct device
*dev
= &pdev
->dev
;
1592 struct video_device
*vdev
;
1593 struct venus_core
*core
;
1597 return -EPROBE_DEFER
;
1599 core
= dev_get_drvdata(dev
->parent
);
1601 return -EPROBE_DEFER
;
1603 platform_set_drvdata(pdev
, core
);
1605 if (core
->pm_ops
->vdec_get
) {
1606 ret
= core
->pm_ops
->vdec_get(dev
);
1611 vdev
= video_device_alloc();
1615 strscpy(vdev
->name
, "qcom-venus-decoder", sizeof(vdev
->name
));
1616 vdev
->release
= video_device_release
;
1617 vdev
->fops
= &vdec_fops
;
1618 vdev
->ioctl_ops
= &vdec_ioctl_ops
;
1619 vdev
->vfl_dir
= VFL_DIR_M2M
;
1620 vdev
->v4l2_dev
= &core
->v4l2_dev
;
1621 vdev
->device_caps
= V4L2_CAP_VIDEO_M2M_MPLANE
| V4L2_CAP_STREAMING
;
1623 ret
= video_register_device(vdev
, VFL_TYPE_VIDEO
, -1);
1625 goto err_vdev_release
;
1627 core
->vdev_dec
= vdev
;
1628 core
->dev_dec
= dev
;
1630 video_set_drvdata(vdev
, core
);
1631 pm_runtime_set_autosuspend_delay(dev
, 2000);
1632 pm_runtime_use_autosuspend(dev
);
1633 pm_runtime_enable(dev
);
1638 video_device_release(vdev
);
1642 static int vdec_remove(struct platform_device
*pdev
)
1644 struct venus_core
*core
= dev_get_drvdata(pdev
->dev
.parent
);
1646 video_unregister_device(core
->vdev_dec
);
1647 pm_runtime_disable(core
->dev_dec
);
1649 if (core
->pm_ops
->vdec_put
)
1650 core
->pm_ops
->vdec_put(core
->dev_dec
);
1655 static __maybe_unused
int vdec_runtime_suspend(struct device
*dev
)
1657 struct venus_core
*core
= dev_get_drvdata(dev
);
1658 const struct venus_pm_ops
*pm_ops
= core
->pm_ops
;
1661 if (pm_ops
->vdec_power
)
1662 ret
= pm_ops
->vdec_power(dev
, POWER_OFF
);
1667 static __maybe_unused
int vdec_runtime_resume(struct device
*dev
)
1669 struct venus_core
*core
= dev_get_drvdata(dev
);
1670 const struct venus_pm_ops
*pm_ops
= core
->pm_ops
;
1673 if (pm_ops
->vdec_power
)
1674 ret
= pm_ops
->vdec_power(dev
, POWER_ON
);
1679 static const struct dev_pm_ops vdec_pm_ops
= {
1680 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1681 pm_runtime_force_resume
)
1682 SET_RUNTIME_PM_OPS(vdec_runtime_suspend
, vdec_runtime_resume
, NULL
)
1685 static const struct of_device_id vdec_dt_match
[] = {
1686 { .compatible
= "venus-decoder" },
1689 MODULE_DEVICE_TABLE(of
, vdec_dt_match
);
1691 static struct platform_driver qcom_venus_dec_driver
= {
1692 .probe
= vdec_probe
,
1693 .remove
= vdec_remove
,
1695 .name
= "qcom-venus-decoder",
1696 .of_match_table
= vdec_dt_match
,
1700 module_platform_driver(qcom_venus_dec_driver
);
1702 MODULE_ALIAS("platform:qcom-venus-decoder");
1703 MODULE_DESCRIPTION("Qualcomm Venus video decoder driver");
1704 MODULE_LICENSE("GPL v2");