2 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
3 * Copyright (C) 2017 Linaro Ltd.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/clk.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/slab.h>
20 #include <media/v4l2-ioctl.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-mem2mem.h>
24 #include <media/videobuf2-dma-sg.h>
26 #include "hfi_venus_io.h"
31 static u32
get_framesize_uncompressed(unsigned int plane
, u32 width
, u32 height
)
33 u32 y_stride
, uv_stride
, y_plane
;
34 u32 y_sclines
, uv_sclines
, uv_plane
;
37 y_stride
= ALIGN(width
, 128);
38 uv_stride
= ALIGN(width
, 128);
39 y_sclines
= ALIGN(height
, 32);
40 uv_sclines
= ALIGN(((height
+ 1) >> 1), 16);
42 y_plane
= y_stride
* y_sclines
;
43 uv_plane
= uv_stride
* uv_sclines
+ SZ_4K
;
44 size
= y_plane
+ uv_plane
+ SZ_8K
;
46 return ALIGN(size
, SZ_4K
);
49 static u32
get_framesize_compressed(unsigned int width
, unsigned int height
)
51 return ((width
* height
* 3 / 2) / 2) + 128;
55 * Three resons to keep MPLANE formats (despite that the number of planes
57 * - the MPLANE formats allow only one plane to be used
58 * - the downstream driver use MPLANE formats too
59 * - future firmware versions could add support for >1 planes
61 static const struct venus_format vdec_formats
[] = {
63 .pixfmt
= V4L2_PIX_FMT_NV12
,
65 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
67 .pixfmt
= V4L2_PIX_FMT_MPEG4
,
69 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
71 .pixfmt
= V4L2_PIX_FMT_MPEG2
,
73 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
75 .pixfmt
= V4L2_PIX_FMT_H263
,
77 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
79 .pixfmt
= V4L2_PIX_FMT_VC1_ANNEX_G
,
81 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
83 .pixfmt
= V4L2_PIX_FMT_VC1_ANNEX_L
,
85 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
87 .pixfmt
= V4L2_PIX_FMT_H264
,
89 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
91 .pixfmt
= V4L2_PIX_FMT_VP8
,
93 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
95 .pixfmt
= V4L2_PIX_FMT_VP9
,
97 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
99 .pixfmt
= V4L2_PIX_FMT_XVID
,
101 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
105 static const struct venus_format
*
106 find_format(struct venus_inst
*inst
, u32 pixfmt
, u32 type
)
108 const struct venus_format
*fmt
= vdec_formats
;
109 unsigned int size
= ARRAY_SIZE(vdec_formats
);
112 for (i
= 0; i
< size
; i
++) {
113 if (fmt
[i
].pixfmt
== pixfmt
)
117 if (i
== size
|| fmt
[i
].type
!= type
)
120 if (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
121 !venus_helper_check_codec(inst
, fmt
[i
].pixfmt
))
127 static const struct venus_format
*
128 find_format_by_index(struct venus_inst
*inst
, unsigned int index
, u32 type
)
130 const struct venus_format
*fmt
= vdec_formats
;
131 unsigned int size
= ARRAY_SIZE(vdec_formats
);
132 unsigned int i
, k
= 0;
137 for (i
= 0; i
< size
; i
++) {
138 if (fmt
[i
].type
!= type
)
148 if (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
149 !venus_helper_check_codec(inst
, fmt
[i
].pixfmt
))
155 static const struct venus_format
*
156 vdec_try_fmt_common(struct venus_inst
*inst
, struct v4l2_format
*f
)
158 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
159 struct v4l2_plane_pix_format
*pfmt
= pixmp
->plane_fmt
;
160 const struct venus_format
*fmt
;
163 memset(pfmt
[0].reserved
, 0, sizeof(pfmt
[0].reserved
));
164 memset(pixmp
->reserved
, 0, sizeof(pixmp
->reserved
));
166 fmt
= find_format(inst
, pixmp
->pixelformat
, f
->type
);
168 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
169 pixmp
->pixelformat
= V4L2_PIX_FMT_NV12
;
170 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
171 pixmp
->pixelformat
= V4L2_PIX_FMT_H264
;
174 fmt
= find_format(inst
, pixmp
->pixelformat
, f
->type
);
179 pixmp
->width
= clamp(pixmp
->width
, inst
->cap_width
.min
,
180 inst
->cap_width
.max
);
181 pixmp
->height
= clamp(pixmp
->height
, inst
->cap_height
.min
,
182 inst
->cap_height
.max
);
184 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
185 pixmp
->height
= ALIGN(pixmp
->height
, 32);
187 if (pixmp
->field
== V4L2_FIELD_ANY
)
188 pixmp
->field
= V4L2_FIELD_NONE
;
189 pixmp
->num_planes
= fmt
->num_planes
;
192 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
193 for (p
= 0; p
< pixmp
->num_planes
; p
++) {
195 get_framesize_uncompressed(p
, pixmp
->width
,
197 pfmt
[p
].bytesperline
= ALIGN(pixmp
->width
, 128);
200 pfmt
[0].sizeimage
= get_framesize_compressed(pixmp
->width
,
202 pfmt
[0].bytesperline
= 0;
208 static int vdec_try_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
210 struct venus_inst
*inst
= to_inst(file
);
212 vdec_try_fmt_common(inst
, f
);
217 static int vdec_g_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
219 struct venus_inst
*inst
= to_inst(file
);
220 const struct venus_format
*fmt
= NULL
;
221 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
223 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
225 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
228 if (inst
->reconfig
) {
229 struct v4l2_format format
= {};
231 inst
->out_width
= inst
->reconfig_width
;
232 inst
->out_height
= inst
->reconfig_height
;
233 inst
->reconfig
= false;
235 format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
236 format
.fmt
.pix_mp
.pixelformat
= inst
->fmt_cap
->pixfmt
;
237 format
.fmt
.pix_mp
.width
= inst
->out_width
;
238 format
.fmt
.pix_mp
.height
= inst
->out_height
;
240 vdec_try_fmt_common(inst
, &format
);
242 inst
->width
= format
.fmt
.pix_mp
.width
;
243 inst
->height
= format
.fmt
.pix_mp
.height
;
246 pixmp
->pixelformat
= fmt
->pixfmt
;
248 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
249 pixmp
->width
= inst
->width
;
250 pixmp
->height
= inst
->height
;
251 pixmp
->colorspace
= inst
->colorspace
;
252 pixmp
->ycbcr_enc
= inst
->ycbcr_enc
;
253 pixmp
->quantization
= inst
->quantization
;
254 pixmp
->xfer_func
= inst
->xfer_func
;
255 } else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
256 pixmp
->width
= inst
->out_width
;
257 pixmp
->height
= inst
->out_height
;
260 vdec_try_fmt_common(inst
, f
);
265 static int vdec_s_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
267 struct venus_inst
*inst
= to_inst(file
);
268 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
269 struct v4l2_pix_format_mplane orig_pixmp
;
270 const struct venus_format
*fmt
;
271 struct v4l2_format format
;
272 u32 pixfmt_out
= 0, pixfmt_cap
= 0;
276 fmt
= vdec_try_fmt_common(inst
, f
);
278 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
279 pixfmt_out
= pixmp
->pixelformat
;
280 pixfmt_cap
= inst
->fmt_cap
->pixfmt
;
281 } else if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
282 pixfmt_cap
= pixmp
->pixelformat
;
283 pixfmt_out
= inst
->fmt_out
->pixfmt
;
286 memset(&format
, 0, sizeof(format
));
288 format
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
289 format
.fmt
.pix_mp
.pixelformat
= pixfmt_out
;
290 format
.fmt
.pix_mp
.width
= orig_pixmp
.width
;
291 format
.fmt
.pix_mp
.height
= orig_pixmp
.height
;
292 vdec_try_fmt_common(inst
, &format
);
294 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
295 inst
->out_width
= format
.fmt
.pix_mp
.width
;
296 inst
->out_height
= format
.fmt
.pix_mp
.height
;
297 inst
->colorspace
= pixmp
->colorspace
;
298 inst
->ycbcr_enc
= pixmp
->ycbcr_enc
;
299 inst
->quantization
= pixmp
->quantization
;
300 inst
->xfer_func
= pixmp
->xfer_func
;
303 memset(&format
, 0, sizeof(format
));
305 format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
306 format
.fmt
.pix_mp
.pixelformat
= pixfmt_cap
;
307 format
.fmt
.pix_mp
.width
= orig_pixmp
.width
;
308 format
.fmt
.pix_mp
.height
= orig_pixmp
.height
;
309 vdec_try_fmt_common(inst
, &format
);
311 inst
->width
= format
.fmt
.pix_mp
.width
;
312 inst
->height
= format
.fmt
.pix_mp
.height
;
314 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
316 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
323 vdec_g_selection(struct file
*file
, void *fh
, struct v4l2_selection
*s
)
325 struct venus_inst
*inst
= to_inst(file
);
327 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
&&
328 s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
332 case V4L2_SEL_TGT_CROP_BOUNDS
:
333 case V4L2_SEL_TGT_CROP_DEFAULT
:
334 case V4L2_SEL_TGT_CROP
:
335 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
337 s
->r
.width
= inst
->out_width
;
338 s
->r
.height
= inst
->out_height
;
340 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
341 case V4L2_SEL_TGT_COMPOSE_PADDED
:
342 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
344 s
->r
.width
= inst
->width
;
345 s
->r
.height
= inst
->height
;
347 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
348 case V4L2_SEL_TGT_COMPOSE
:
349 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
351 s
->r
.width
= inst
->out_width
;
352 s
->r
.height
= inst
->out_height
;
365 vdec_querycap(struct file
*file
, void *fh
, struct v4l2_capability
*cap
)
367 strlcpy(cap
->driver
, "qcom-venus", sizeof(cap
->driver
));
368 strlcpy(cap
->card
, "Qualcomm Venus video decoder", sizeof(cap
->card
));
369 strlcpy(cap
->bus_info
, "platform:qcom-venus", sizeof(cap
->bus_info
));
374 static int vdec_enum_fmt(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*f
)
376 struct venus_inst
*inst
= to_inst(file
);
377 const struct venus_format
*fmt
;
379 memset(f
->reserved
, 0, sizeof(f
->reserved
));
381 fmt
= find_format_by_index(inst
, f
->index
, f
->type
);
385 f
->pixelformat
= fmt
->pixfmt
;
390 static int vdec_s_parm(struct file
*file
, void *fh
, struct v4l2_streamparm
*a
)
392 struct venus_inst
*inst
= to_inst(file
);
393 struct v4l2_captureparm
*cap
= &a
->parm
.capture
;
394 struct v4l2_fract
*timeperframe
= &cap
->timeperframe
;
395 u64 us_per_frame
, fps
;
397 if (a
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
398 a
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
401 memset(cap
->reserved
, 0, sizeof(cap
->reserved
));
402 if (!timeperframe
->denominator
)
403 timeperframe
->denominator
= inst
->timeperframe
.denominator
;
404 if (!timeperframe
->numerator
)
405 timeperframe
->numerator
= inst
->timeperframe
.numerator
;
406 cap
->readbuffers
= 0;
407 cap
->extendedmode
= 0;
408 cap
->capability
= V4L2_CAP_TIMEPERFRAME
;
409 us_per_frame
= timeperframe
->numerator
* (u64
)USEC_PER_SEC
;
410 do_div(us_per_frame
, timeperframe
->denominator
);
415 fps
= (u64
)USEC_PER_SEC
;
416 do_div(fps
, us_per_frame
);
419 inst
->timeperframe
= *timeperframe
;
424 static int vdec_enum_framesizes(struct file
*file
, void *fh
,
425 struct v4l2_frmsizeenum
*fsize
)
427 struct venus_inst
*inst
= to_inst(file
);
428 const struct venus_format
*fmt
;
430 fmt
= find_format(inst
, fsize
->pixel_format
,
431 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
);
433 fmt
= find_format(inst
, fsize
->pixel_format
,
434 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
);
442 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
444 fsize
->stepwise
.min_width
= inst
->cap_width
.min
;
445 fsize
->stepwise
.max_width
= inst
->cap_width
.max
;
446 fsize
->stepwise
.step_width
= inst
->cap_width
.step_size
;
447 fsize
->stepwise
.min_height
= inst
->cap_height
.min
;
448 fsize
->stepwise
.max_height
= inst
->cap_height
.max
;
449 fsize
->stepwise
.step_height
= inst
->cap_height
.step_size
;
454 static int vdec_subscribe_event(struct v4l2_fh
*fh
,
455 const struct v4l2_event_subscription
*sub
)
459 return v4l2_event_subscribe(fh
, sub
, 2, NULL
);
460 case V4L2_EVENT_SOURCE_CHANGE
:
461 return v4l2_src_change_event_subscribe(fh
, sub
);
462 case V4L2_EVENT_CTRL
:
463 return v4l2_ctrl_subscribe_event(fh
, sub
);
470 vdec_try_decoder_cmd(struct file
*file
, void *fh
, struct v4l2_decoder_cmd
*cmd
)
473 case V4L2_DEC_CMD_STOP
:
474 if (cmd
->flags
& V4L2_DEC_CMD_STOP_TO_BLACK
)
485 vdec_decoder_cmd(struct file
*file
, void *fh
, struct v4l2_decoder_cmd
*cmd
)
487 struct venus_inst
*inst
= to_inst(file
);
488 struct hfi_frame_data fdata
= {0};
491 ret
= vdec_try_decoder_cmd(file
, fh
, cmd
);
495 mutex_lock(&inst
->lock
);
498 * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder
499 * input to signal EOS.
501 if (!(inst
->streamon_out
& inst
->streamon_cap
))
504 fdata
.buffer_type
= HFI_BUFFER_INPUT
;
505 fdata
.flags
|= HFI_BUFFERFLAG_EOS
;
506 fdata
.device_addr
= 0xdeadbeef;
508 ret
= hfi_session_process_buf(inst
, &fdata
);
511 mutex_unlock(&inst
->lock
);
515 static const struct v4l2_ioctl_ops vdec_ioctl_ops
= {
516 .vidioc_querycap
= vdec_querycap
,
517 .vidioc_enum_fmt_vid_cap_mplane
= vdec_enum_fmt
,
518 .vidioc_enum_fmt_vid_out_mplane
= vdec_enum_fmt
,
519 .vidioc_s_fmt_vid_cap_mplane
= vdec_s_fmt
,
520 .vidioc_s_fmt_vid_out_mplane
= vdec_s_fmt
,
521 .vidioc_g_fmt_vid_cap_mplane
= vdec_g_fmt
,
522 .vidioc_g_fmt_vid_out_mplane
= vdec_g_fmt
,
523 .vidioc_try_fmt_vid_cap_mplane
= vdec_try_fmt
,
524 .vidioc_try_fmt_vid_out_mplane
= vdec_try_fmt
,
525 .vidioc_g_selection
= vdec_g_selection
,
526 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
527 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
528 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
529 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
530 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
531 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
532 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
533 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
534 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
535 .vidioc_s_parm
= vdec_s_parm
,
536 .vidioc_enum_framesizes
= vdec_enum_framesizes
,
537 .vidioc_subscribe_event
= vdec_subscribe_event
,
538 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
539 .vidioc_try_decoder_cmd
= vdec_try_decoder_cmd
,
540 .vidioc_decoder_cmd
= vdec_decoder_cmd
,
543 static int vdec_set_properties(struct venus_inst
*inst
)
545 struct vdec_controls
*ctr
= &inst
->controls
.dec
;
546 struct venus_core
*core
= inst
->core
;
547 struct hfi_enable en
= { .enable
= 1 };
551 if (core
->res
->hfi_version
== HFI_VERSION_1XX
) {
552 ptype
= HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER
;
553 ret
= hfi_session_set_property(inst
, ptype
, &en
);
558 if (core
->res
->hfi_version
== HFI_VERSION_3XX
||
559 inst
->cap_bufs_mode_dynamic
) {
560 struct hfi_buffer_alloc_mode mode
;
562 ptype
= HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE
;
563 mode
.type
= HFI_BUFFER_OUTPUT
;
564 mode
.mode
= HFI_BUFFER_MODE_DYNAMIC
;
566 ret
= hfi_session_set_property(inst
, ptype
, &mode
);
571 if (ctr
->post_loop_deb_mode
) {
572 ptype
= HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER
;
574 ret
= hfi_session_set_property(inst
, ptype
, &en
);
582 static int vdec_init_session(struct venus_inst
*inst
)
586 ret
= hfi_session_init(inst
, inst
->fmt_out
->pixfmt
);
590 ret
= venus_helper_set_input_resolution(inst
, inst
->out_width
,
595 ret
= venus_helper_set_color_format(inst
, inst
->fmt_cap
->pixfmt
);
601 hfi_session_deinit(inst
);
605 static int vdec_cap_num_buffers(struct venus_inst
*inst
, unsigned int *num
)
607 struct hfi_buffer_requirements bufreq
;
610 ret
= vdec_init_session(inst
);
614 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_OUTPUT
, &bufreq
);
616 *num
= bufreq
.count_actual
;
618 hfi_session_deinit(inst
);
623 static int vdec_queue_setup(struct vb2_queue
*q
,
624 unsigned int *num_buffers
, unsigned int *num_planes
,
625 unsigned int sizes
[], struct device
*alloc_devs
[])
627 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
632 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
633 *num_planes
!= inst
->fmt_out
->num_planes
)
636 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
637 *num_planes
!= inst
->fmt_cap
->num_planes
)
640 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
641 sizes
[0] < inst
->input_buf_size
)
644 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
645 sizes
[0] < inst
->output_buf_size
)
652 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
653 *num_planes
= inst
->fmt_out
->num_planes
;
654 sizes
[0] = get_framesize_compressed(inst
->out_width
,
656 inst
->input_buf_size
= sizes
[0];
657 inst
->num_input_bufs
= *num_buffers
;
659 ret
= vdec_cap_num_buffers(inst
, &num
);
663 inst
->num_output_bufs
= num
;
665 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
666 *num_planes
= inst
->fmt_cap
->num_planes
;
668 ret
= vdec_cap_num_buffers(inst
, &num
);
672 *num_buffers
= max(*num_buffers
, num
);
674 for (p
= 0; p
< *num_planes
; p
++)
675 sizes
[p
] = get_framesize_uncompressed(p
, inst
->width
,
678 inst
->num_output_bufs
= *num_buffers
;
679 inst
->output_buf_size
= sizes
[0];
689 static int vdec_verify_conf(struct venus_inst
*inst
)
691 struct hfi_buffer_requirements bufreq
;
694 if (!inst
->num_input_bufs
|| !inst
->num_output_bufs
)
697 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_OUTPUT
, &bufreq
);
701 if (inst
->num_output_bufs
< bufreq
.count_actual
||
702 inst
->num_output_bufs
< bufreq
.count_min
)
705 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_INPUT
, &bufreq
);
709 if (inst
->num_input_bufs
< bufreq
.count_min
)
715 static int vdec_start_streaming(struct vb2_queue
*q
, unsigned int count
)
717 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
718 struct venus_core
*core
= inst
->core
;
722 mutex_lock(&inst
->lock
);
724 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
725 inst
->streamon_out
= 1;
727 inst
->streamon_cap
= 1;
729 if (!(inst
->streamon_out
& inst
->streamon_cap
)) {
730 mutex_unlock(&inst
->lock
);
734 venus_helper_init_instance(inst
);
736 inst
->reconfig
= false;
737 inst
->sequence_cap
= 0;
738 inst
->sequence_out
= 0;
740 ret
= vdec_init_session(inst
);
744 ret
= vdec_set_properties(inst
);
748 if (core
->res
->hfi_version
== HFI_VERSION_3XX
) {
749 struct hfi_buffer_size_actual buf_sz
;
751 ptype
= HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL
;
752 buf_sz
.type
= HFI_BUFFER_OUTPUT
;
753 buf_sz
.size
= inst
->output_buf_size
;
755 ret
= hfi_session_set_property(inst
, ptype
, &buf_sz
);
760 ret
= vdec_verify_conf(inst
);
764 ret
= venus_helper_set_num_bufs(inst
, inst
->num_input_bufs
,
769 ret
= venus_helper_vb2_start_streaming(inst
);
773 mutex_unlock(&inst
->lock
);
778 hfi_session_deinit(inst
);
780 venus_helper_buffers_done(inst
, VB2_BUF_STATE_QUEUED
);
781 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
782 inst
->streamon_out
= 0;
784 inst
->streamon_cap
= 0;
785 mutex_unlock(&inst
->lock
);
789 static const struct vb2_ops vdec_vb2_ops
= {
790 .queue_setup
= vdec_queue_setup
,
791 .buf_init
= venus_helper_vb2_buf_init
,
792 .buf_prepare
= venus_helper_vb2_buf_prepare
,
793 .start_streaming
= vdec_start_streaming
,
794 .stop_streaming
= venus_helper_vb2_stop_streaming
,
795 .buf_queue
= venus_helper_vb2_buf_queue
,
798 static void vdec_buf_done(struct venus_inst
*inst
, unsigned int buf_type
,
799 u32 tag
, u32 bytesused
, u32 data_offset
, u32 flags
,
800 u32 hfi_flags
, u64 timestamp_us
)
802 enum vb2_buffer_state state
= VB2_BUF_STATE_DONE
;
803 struct vb2_v4l2_buffer
*vbuf
;
804 struct vb2_buffer
*vb
;
807 if (buf_type
== HFI_BUFFER_INPUT
)
808 type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
810 type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
812 vbuf
= venus_helper_find_buf(inst
, type
, tag
);
817 vbuf
->field
= V4L2_FIELD_NONE
;
819 if (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
821 vb
->planes
[0].bytesused
=
822 max_t(unsigned int, inst
->output_buf_size
, bytesused
);
823 vb
->planes
[0].data_offset
= data_offset
;
824 vb
->timestamp
= timestamp_us
* NSEC_PER_USEC
;
825 vbuf
->sequence
= inst
->sequence_cap
++;
827 if (vbuf
->flags
& V4L2_BUF_FLAG_LAST
) {
828 const struct v4l2_event ev
= { .type
= V4L2_EVENT_EOS
};
830 v4l2_event_queue_fh(&inst
->fh
, &ev
);
833 vbuf
->sequence
= inst
->sequence_out
++;
836 if (hfi_flags
& HFI_BUFFERFLAG_READONLY
)
837 venus_helper_acquire_buf_ref(vbuf
);
839 if (hfi_flags
& HFI_BUFFERFLAG_DATACORRUPT
)
840 state
= VB2_BUF_STATE_ERROR
;
842 v4l2_m2m_buf_done(vbuf
, state
);
845 static void vdec_event_notify(struct venus_inst
*inst
, u32 event
,
846 struct hfi_event_data
*data
)
848 struct venus_core
*core
= inst
->core
;
849 struct device
*dev
= core
->dev_dec
;
850 static const struct v4l2_event ev
= {
851 .type
= V4L2_EVENT_SOURCE_CHANGE
,
852 .u
.src_change
.changes
= V4L2_EVENT_SRC_CH_RESOLUTION
};
855 case EVT_SESSION_ERROR
:
856 inst
->session_error
= true;
857 dev_err(dev
, "dec: event session error %x\n", inst
->error
);
859 case EVT_SYS_EVENT_CHANGE
:
860 switch (data
->event_type
) {
861 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES
:
862 hfi_session_continue(inst
);
863 dev_dbg(dev
, "event sufficient resources\n");
865 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES
:
866 inst
->reconfig_height
= data
->height
;
867 inst
->reconfig_width
= data
->width
;
868 inst
->reconfig
= true;
870 v4l2_event_queue_fh(&inst
->fh
, &ev
);
872 dev_dbg(dev
, "event not sufficient resources (%ux%u)\n",
873 data
->width
, data
->height
);
875 case HFI_EVENT_RELEASE_BUFFER_REFERENCE
:
876 venus_helper_release_buf_ref(inst
, data
->tag
);
887 static const struct hfi_inst_ops vdec_hfi_ops
= {
888 .buf_done
= vdec_buf_done
,
889 .event_notify
= vdec_event_notify
,
892 static void vdec_inst_init(struct venus_inst
*inst
)
894 inst
->fmt_out
= &vdec_formats
[6];
895 inst
->fmt_cap
= &vdec_formats
[0];
897 inst
->height
= ALIGN(720, 32);
898 inst
->out_width
= 1280;
899 inst
->out_height
= 720;
901 inst
->timeperframe
.numerator
= 1;
902 inst
->timeperframe
.denominator
= 30;
904 inst
->cap_width
.min
= 64;
905 inst
->cap_width
.max
= 1920;
906 if (inst
->core
->res
->hfi_version
== HFI_VERSION_3XX
)
907 inst
->cap_width
.max
= 3840;
908 inst
->cap_width
.step_size
= 1;
909 inst
->cap_height
.min
= 64;
910 inst
->cap_height
.max
= ALIGN(1080, 32);
911 if (inst
->core
->res
->hfi_version
== HFI_VERSION_3XX
)
912 inst
->cap_height
.max
= ALIGN(2160, 32);
913 inst
->cap_height
.step_size
= 1;
914 inst
->cap_framerate
.min
= 1;
915 inst
->cap_framerate
.max
= 30;
916 inst
->cap_framerate
.step_size
= 1;
917 inst
->cap_mbs_per_frame
.min
= 16;
918 inst
->cap_mbs_per_frame
.max
= 8160;
921 static const struct v4l2_m2m_ops vdec_m2m_ops
= {
922 .device_run
= venus_helper_m2m_device_run
,
923 .job_abort
= venus_helper_m2m_job_abort
,
926 static int m2m_queue_init(void *priv
, struct vb2_queue
*src_vq
,
927 struct vb2_queue
*dst_vq
)
929 struct venus_inst
*inst
= priv
;
932 src_vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
933 src_vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
934 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
935 src_vq
->ops
= &vdec_vb2_ops
;
936 src_vq
->mem_ops
= &vb2_dma_sg_memops
;
937 src_vq
->drv_priv
= inst
;
938 src_vq
->buf_struct_size
= sizeof(struct venus_buffer
);
939 src_vq
->allow_zero_bytesused
= 1;
940 src_vq
->min_buffers_needed
= 1;
941 src_vq
->dev
= inst
->core
->dev
;
942 ret
= vb2_queue_init(src_vq
);
946 dst_vq
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
947 dst_vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
948 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
949 dst_vq
->ops
= &vdec_vb2_ops
;
950 dst_vq
->mem_ops
= &vb2_dma_sg_memops
;
951 dst_vq
->drv_priv
= inst
;
952 dst_vq
->buf_struct_size
= sizeof(struct venus_buffer
);
953 dst_vq
->allow_zero_bytesused
= 1;
954 dst_vq
->min_buffers_needed
= 1;
955 dst_vq
->dev
= inst
->core
->dev
;
956 ret
= vb2_queue_init(dst_vq
);
958 vb2_queue_release(src_vq
);
965 static int vdec_open(struct file
*file
)
967 struct venus_core
*core
= video_drvdata(file
);
968 struct venus_inst
*inst
;
971 inst
= kzalloc(sizeof(*inst
), GFP_KERNEL
);
975 INIT_LIST_HEAD(&inst
->registeredbufs
);
976 INIT_LIST_HEAD(&inst
->internalbufs
);
977 INIT_LIST_HEAD(&inst
->list
);
978 mutex_init(&inst
->lock
);
981 inst
->session_type
= VIDC_SESSION_TYPE_DEC
;
982 inst
->num_output_bufs
= 1;
984 venus_helper_init_instance(inst
);
986 ret
= pm_runtime_get_sync(core
->dev_dec
);
990 ret
= vdec_ctrl_init(inst
);
994 ret
= hfi_session_create(inst
, &vdec_hfi_ops
);
996 goto err_ctrl_deinit
;
998 vdec_inst_init(inst
);
1001 * create m2m device for every instance, the m2m context scheduling
1002 * is made by firmware side so we do not need to care about.
1004 inst
->m2m_dev
= v4l2_m2m_init(&vdec_m2m_ops
);
1005 if (IS_ERR(inst
->m2m_dev
)) {
1006 ret
= PTR_ERR(inst
->m2m_dev
);
1007 goto err_session_destroy
;
1010 inst
->m2m_ctx
= v4l2_m2m_ctx_init(inst
->m2m_dev
, inst
, m2m_queue_init
);
1011 if (IS_ERR(inst
->m2m_ctx
)) {
1012 ret
= PTR_ERR(inst
->m2m_ctx
);
1013 goto err_m2m_release
;
1016 v4l2_fh_init(&inst
->fh
, core
->vdev_dec
);
1018 inst
->fh
.ctrl_handler
= &inst
->ctrl_handler
;
1019 v4l2_fh_add(&inst
->fh
);
1020 inst
->fh
.m2m_ctx
= inst
->m2m_ctx
;
1021 file
->private_data
= &inst
->fh
;
1026 v4l2_m2m_release(inst
->m2m_dev
);
1027 err_session_destroy
:
1028 hfi_session_destroy(inst
);
1030 vdec_ctrl_deinit(inst
);
1032 pm_runtime_put_sync(core
->dev_dec
);
1038 static int vdec_close(struct file
*file
)
1040 struct venus_inst
*inst
= to_inst(file
);
1042 v4l2_m2m_ctx_release(inst
->m2m_ctx
);
1043 v4l2_m2m_release(inst
->m2m_dev
);
1044 vdec_ctrl_deinit(inst
);
1045 hfi_session_destroy(inst
);
1046 mutex_destroy(&inst
->lock
);
1047 v4l2_fh_del(&inst
->fh
);
1048 v4l2_fh_exit(&inst
->fh
);
1050 pm_runtime_put_sync(inst
->core
->dev_dec
);
1056 static const struct v4l2_file_operations vdec_fops
= {
1057 .owner
= THIS_MODULE
,
1059 .release
= vdec_close
,
1060 .unlocked_ioctl
= video_ioctl2
,
1061 .poll
= v4l2_m2m_fop_poll
,
1062 .mmap
= v4l2_m2m_fop_mmap
,
1063 #ifdef CONFIG_COMPAT
1064 .compat_ioctl32
= v4l2_compat_ioctl32
,
1068 static int vdec_probe(struct platform_device
*pdev
)
1070 struct device
*dev
= &pdev
->dev
;
1071 struct video_device
*vdev
;
1072 struct venus_core
*core
;
1076 return -EPROBE_DEFER
;
1078 core
= dev_get_drvdata(dev
->parent
);
1080 return -EPROBE_DEFER
;
1082 if (core
->res
->hfi_version
== HFI_VERSION_3XX
) {
1083 core
->core0_clk
= devm_clk_get(dev
, "core");
1084 if (IS_ERR(core
->core0_clk
))
1085 return PTR_ERR(core
->core0_clk
);
1088 platform_set_drvdata(pdev
, core
);
1090 vdev
= video_device_alloc();
1094 strlcpy(vdev
->name
, "qcom-venus-decoder", sizeof(vdev
->name
));
1095 vdev
->release
= video_device_release
;
1096 vdev
->fops
= &vdec_fops
;
1097 vdev
->ioctl_ops
= &vdec_ioctl_ops
;
1098 vdev
->vfl_dir
= VFL_DIR_M2M
;
1099 vdev
->v4l2_dev
= &core
->v4l2_dev
;
1100 vdev
->device_caps
= V4L2_CAP_VIDEO_M2M_MPLANE
| V4L2_CAP_STREAMING
;
1102 ret
= video_register_device(vdev
, VFL_TYPE_GRABBER
, -1);
1104 goto err_vdev_release
;
1106 core
->vdev_dec
= vdev
;
1107 core
->dev_dec
= dev
;
1109 video_set_drvdata(vdev
, core
);
1110 pm_runtime_enable(dev
);
1115 video_device_release(vdev
);
1119 static int vdec_remove(struct platform_device
*pdev
)
1121 struct venus_core
*core
= dev_get_drvdata(pdev
->dev
.parent
);
1123 video_unregister_device(core
->vdev_dec
);
1124 pm_runtime_disable(core
->dev_dec
);
1129 static __maybe_unused
int vdec_runtime_suspend(struct device
*dev
)
1131 struct venus_core
*core
= dev_get_drvdata(dev
);
1133 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
1136 writel(0, core
->base
+ WRAPPER_VDEC_VCODEC_POWER_CONTROL
);
1137 clk_disable_unprepare(core
->core0_clk
);
1138 writel(1, core
->base
+ WRAPPER_VDEC_VCODEC_POWER_CONTROL
);
1143 static __maybe_unused
int vdec_runtime_resume(struct device
*dev
)
1145 struct venus_core
*core
= dev_get_drvdata(dev
);
1148 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
1151 writel(0, core
->base
+ WRAPPER_VDEC_VCODEC_POWER_CONTROL
);
1152 ret
= clk_prepare_enable(core
->core0_clk
);
1153 writel(1, core
->base
+ WRAPPER_VDEC_VCODEC_POWER_CONTROL
);
1158 static const struct dev_pm_ops vdec_pm_ops
= {
1159 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1160 pm_runtime_force_resume
)
1161 SET_RUNTIME_PM_OPS(vdec_runtime_suspend
, vdec_runtime_resume
, NULL
)
1164 static const struct of_device_id vdec_dt_match
[] = {
1165 { .compatible
= "venus-decoder" },
1168 MODULE_DEVICE_TABLE(of
, vdec_dt_match
);
1170 static struct platform_driver qcom_venus_dec_driver
= {
1171 .probe
= vdec_probe
,
1172 .remove
= vdec_remove
,
1174 .name
= "qcom-venus-decoder",
1175 .of_match_table
= vdec_dt_match
,
1179 module_platform_driver(qcom_venus_dec_driver
);
1181 MODULE_ALIAS("platform:qcom-venus-decoder");
1182 MODULE_DESCRIPTION("Qualcomm Venus video decoder driver");
1183 MODULE_LICENSE("GPL v2");