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-mem2mem.h>
21 #include <media/videobuf2-dma-sg.h>
22 #include <media/v4l2-ioctl.h>
23 #include <media/v4l2-event.h>
24 #include <media/v4l2-ctrls.h>
26 #include "hfi_venus_io.h"
31 #define NUM_B_FRAMES_MAX 4
33 static u32
get_framesize_uncompressed(unsigned int plane
, u32 width
, u32 height
)
35 u32 y_stride
, uv_stride
, y_plane
;
36 u32 y_sclines
, uv_sclines
, uv_plane
;
39 y_stride
= ALIGN(width
, 128);
40 uv_stride
= ALIGN(width
, 128);
41 y_sclines
= ALIGN(height
, 32);
42 uv_sclines
= ALIGN(((height
+ 1) >> 1), 16);
44 y_plane
= y_stride
* y_sclines
;
45 uv_plane
= uv_stride
* uv_sclines
+ SZ_4K
;
46 size
= y_plane
+ uv_plane
+ SZ_8K
;
47 size
= ALIGN(size
, SZ_4K
);
52 static u32
get_framesize_compressed(u32 width
, u32 height
)
54 u32 sz
= ALIGN(height
, 32) * ALIGN(width
, 32) * 3 / 2 / 2;
56 return ALIGN(sz
, SZ_4K
);
60 * Three resons to keep MPLANE formats (despite that the number of planes
62 * - the MPLANE formats allow only one plane to be used
63 * - the downstream driver use MPLANE formats too
64 * - future firmware versions could add support for >1 planes
66 static const struct venus_format venc_formats
[] = {
68 .pixfmt
= V4L2_PIX_FMT_NV12
,
70 .type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
,
72 .pixfmt
= V4L2_PIX_FMT_MPEG4
,
74 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
76 .pixfmt
= V4L2_PIX_FMT_H263
,
78 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
80 .pixfmt
= V4L2_PIX_FMT_H264
,
82 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
84 .pixfmt
= V4L2_PIX_FMT_VP8
,
86 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
90 static const struct venus_format
*
91 find_format(struct venus_inst
*inst
, u32 pixfmt
, u32 type
)
93 const struct venus_format
*fmt
= venc_formats
;
94 unsigned int size
= ARRAY_SIZE(venc_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_CAPTURE_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
= venc_formats
;
116 unsigned int size
= ARRAY_SIZE(venc_formats
);
117 unsigned int i
, k
= 0;
122 for (i
= 0; i
< size
; i
++) {
123 if (fmt
[i
].type
!= type
)
133 if (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
134 !venus_helper_check_codec(inst
, fmt
[i
].pixfmt
))
140 static int venc_v4l2_to_hfi(int id
, int value
)
143 case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL
:
145 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0
:
147 return HFI_MPEG4_LEVEL_0
;
148 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B
:
149 return HFI_MPEG4_LEVEL_0b
;
150 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1
:
151 return HFI_MPEG4_LEVEL_1
;
152 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2
:
153 return HFI_MPEG4_LEVEL_2
;
154 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3
:
155 return HFI_MPEG4_LEVEL_3
;
156 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4
:
157 return HFI_MPEG4_LEVEL_4
;
158 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5
:
159 return HFI_MPEG4_LEVEL_5
;
161 case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE
:
163 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE
:
165 return HFI_MPEG4_PROFILE_SIMPLE
;
166 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE
:
167 return HFI_MPEG4_PROFILE_ADVANCEDSIMPLE
;
169 case V4L2_CID_MPEG_VIDEO_H264_PROFILE
:
171 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE
:
172 return HFI_H264_PROFILE_BASELINE
;
173 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE
:
174 return HFI_H264_PROFILE_CONSTRAINED_BASE
;
175 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN
:
176 return HFI_H264_PROFILE_MAIN
;
177 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH
:
179 return HFI_H264_PROFILE_HIGH
;
181 case V4L2_CID_MPEG_VIDEO_H264_LEVEL
:
183 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0
:
184 return HFI_H264_LEVEL_1
;
185 case V4L2_MPEG_VIDEO_H264_LEVEL_1B
:
186 return HFI_H264_LEVEL_1b
;
187 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1
:
188 return HFI_H264_LEVEL_11
;
189 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2
:
190 return HFI_H264_LEVEL_12
;
191 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3
:
192 return HFI_H264_LEVEL_13
;
193 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0
:
194 return HFI_H264_LEVEL_2
;
195 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1
:
196 return HFI_H264_LEVEL_21
;
197 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2
:
198 return HFI_H264_LEVEL_22
;
199 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0
:
200 return HFI_H264_LEVEL_3
;
201 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1
:
202 return HFI_H264_LEVEL_31
;
203 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2
:
204 return HFI_H264_LEVEL_32
;
205 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0
:
206 return HFI_H264_LEVEL_4
;
207 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1
:
208 return HFI_H264_LEVEL_41
;
209 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2
:
210 return HFI_H264_LEVEL_42
;
211 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0
:
213 return HFI_H264_LEVEL_5
;
214 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1
:
215 return HFI_H264_LEVEL_51
;
217 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE
:
219 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC
:
221 return HFI_H264_ENTROPY_CAVLC
;
222 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC
:
223 return HFI_H264_ENTROPY_CABAC
;
225 case V4L2_CID_MPEG_VIDEO_VPX_PROFILE
:
229 return HFI_VPX_PROFILE_VERSION_0
;
231 return HFI_VPX_PROFILE_VERSION_1
;
233 return HFI_VPX_PROFILE_VERSION_2
;
235 return HFI_VPX_PROFILE_VERSION_3
;
237 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE
:
239 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED
:
241 return HFI_H264_DB_MODE_ALL_BOUNDARY
;
242 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED
:
243 return HFI_H264_DB_MODE_DISABLE
;
244 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
:
245 return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY
;
253 venc_querycap(struct file
*file
, void *fh
, struct v4l2_capability
*cap
)
255 strlcpy(cap
->driver
, "qcom-venus", sizeof(cap
->driver
));
256 strlcpy(cap
->card
, "Qualcomm Venus video encoder", sizeof(cap
->card
));
257 strlcpy(cap
->bus_info
, "platform:qcom-venus", sizeof(cap
->bus_info
));
262 static int venc_enum_fmt(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*f
)
264 struct venus_inst
*inst
= to_inst(file
);
265 const struct venus_format
*fmt
;
267 fmt
= find_format_by_index(inst
, f
->index
, f
->type
);
269 memset(f
->reserved
, 0, sizeof(f
->reserved
));
274 f
->pixelformat
= fmt
->pixfmt
;
279 static const struct venus_format
*
280 venc_try_fmt_common(struct venus_inst
*inst
, struct v4l2_format
*f
)
282 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
283 struct v4l2_plane_pix_format
*pfmt
= pixmp
->plane_fmt
;
284 const struct venus_format
*fmt
;
287 memset(pfmt
[0].reserved
, 0, sizeof(pfmt
[0].reserved
));
288 memset(pixmp
->reserved
, 0, sizeof(pixmp
->reserved
));
290 fmt
= find_format(inst
, pixmp
->pixelformat
, f
->type
);
292 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
293 pixmp
->pixelformat
= V4L2_PIX_FMT_H264
;
294 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
295 pixmp
->pixelformat
= V4L2_PIX_FMT_NV12
;
298 fmt
= find_format(inst
, pixmp
->pixelformat
, f
->type
);
303 pixmp
->width
= clamp(pixmp
->width
, inst
->cap_width
.min
,
304 inst
->cap_width
.max
);
305 pixmp
->height
= clamp(pixmp
->height
, inst
->cap_height
.min
,
306 inst
->cap_height
.max
);
308 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
309 pixmp
->height
= ALIGN(pixmp
->height
, 32);
311 pixmp
->width
= ALIGN(pixmp
->width
, 2);
312 pixmp
->height
= ALIGN(pixmp
->height
, 2);
314 if (pixmp
->field
== V4L2_FIELD_ANY
)
315 pixmp
->field
= V4L2_FIELD_NONE
;
316 pixmp
->num_planes
= fmt
->num_planes
;
319 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
320 for (p
= 0; p
< pixmp
->num_planes
; p
++) {
322 get_framesize_uncompressed(p
, pixmp
->width
,
325 pfmt
[p
].bytesperline
= ALIGN(pixmp
->width
, 128);
328 pfmt
[0].sizeimage
= get_framesize_compressed(pixmp
->width
,
330 pfmt
[0].bytesperline
= 0;
336 static int venc_try_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
338 struct venus_inst
*inst
= to_inst(file
);
340 venc_try_fmt_common(inst
, f
);
345 static int venc_s_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
347 struct venus_inst
*inst
= to_inst(file
);
348 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
349 struct v4l2_pix_format_mplane orig_pixmp
;
350 const struct venus_format
*fmt
;
351 struct v4l2_format format
;
352 u32 pixfmt_out
= 0, pixfmt_cap
= 0;
356 fmt
= venc_try_fmt_common(inst
, f
);
360 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
361 pixfmt_out
= pixmp
->pixelformat
;
362 pixfmt_cap
= inst
->fmt_cap
->pixfmt
;
363 } else if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
364 pixfmt_cap
= pixmp
->pixelformat
;
365 pixfmt_out
= inst
->fmt_out
->pixfmt
;
368 memset(&format
, 0, sizeof(format
));
370 format
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
371 format
.fmt
.pix_mp
.pixelformat
= pixfmt_out
;
372 format
.fmt
.pix_mp
.width
= orig_pixmp
.width
;
373 format
.fmt
.pix_mp
.height
= orig_pixmp
.height
;
374 venc_try_fmt_common(inst
, &format
);
376 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
377 inst
->out_width
= format
.fmt
.pix_mp
.width
;
378 inst
->out_height
= format
.fmt
.pix_mp
.height
;
379 inst
->colorspace
= pixmp
->colorspace
;
380 inst
->ycbcr_enc
= pixmp
->ycbcr_enc
;
381 inst
->quantization
= pixmp
->quantization
;
382 inst
->xfer_func
= pixmp
->xfer_func
;
385 memset(&format
, 0, sizeof(format
));
387 format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
388 format
.fmt
.pix_mp
.pixelformat
= pixfmt_cap
;
389 format
.fmt
.pix_mp
.width
= orig_pixmp
.width
;
390 format
.fmt
.pix_mp
.height
= orig_pixmp
.height
;
391 venc_try_fmt_common(inst
, &format
);
393 inst
->width
= format
.fmt
.pix_mp
.width
;
394 inst
->height
= format
.fmt
.pix_mp
.height
;
396 if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
398 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
404 static int venc_g_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
406 struct v4l2_pix_format_mplane
*pixmp
= &f
->fmt
.pix_mp
;
407 struct venus_inst
*inst
= to_inst(file
);
408 const struct venus_format
*fmt
;
410 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
)
412 else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
417 pixmp
->pixelformat
= fmt
->pixfmt
;
419 if (f
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
420 pixmp
->width
= inst
->width
;
421 pixmp
->height
= inst
->height
;
422 pixmp
->colorspace
= inst
->colorspace
;
423 pixmp
->ycbcr_enc
= inst
->ycbcr_enc
;
424 pixmp
->quantization
= inst
->quantization
;
425 pixmp
->xfer_func
= inst
->xfer_func
;
426 } else if (f
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) {
427 pixmp
->width
= inst
->out_width
;
428 pixmp
->height
= inst
->out_height
;
431 venc_try_fmt_common(inst
, f
);
437 venc_g_selection(struct file
*file
, void *fh
, struct v4l2_selection
*s
)
439 struct venus_inst
*inst
= to_inst(file
);
441 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
445 case V4L2_SEL_TGT_CROP_DEFAULT
:
446 case V4L2_SEL_TGT_CROP_BOUNDS
:
447 s
->r
.width
= inst
->width
;
448 s
->r
.height
= inst
->height
;
450 case V4L2_SEL_TGT_CROP
:
451 s
->r
.width
= inst
->out_width
;
452 s
->r
.height
= inst
->out_height
;
465 venc_s_selection(struct file
*file
, void *fh
, struct v4l2_selection
*s
)
467 struct venus_inst
*inst
= to_inst(file
);
469 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
473 case V4L2_SEL_TGT_CROP
:
474 if (s
->r
.width
!= inst
->out_width
||
475 s
->r
.height
!= inst
->out_height
||
476 s
->r
.top
!= 0 || s
->r
.left
!= 0)
486 static int venc_s_parm(struct file
*file
, void *fh
, struct v4l2_streamparm
*a
)
488 struct venus_inst
*inst
= to_inst(file
);
489 struct v4l2_outputparm
*out
= &a
->parm
.output
;
490 struct v4l2_fract
*timeperframe
= &out
->timeperframe
;
491 u64 us_per_frame
, fps
;
493 if (a
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
494 a
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
497 memset(out
->reserved
, 0, sizeof(out
->reserved
));
499 if (!timeperframe
->denominator
)
500 timeperframe
->denominator
= inst
->timeperframe
.denominator
;
501 if (!timeperframe
->numerator
)
502 timeperframe
->numerator
= inst
->timeperframe
.numerator
;
504 out
->capability
= V4L2_CAP_TIMEPERFRAME
;
506 us_per_frame
= timeperframe
->numerator
* (u64
)USEC_PER_SEC
;
507 do_div(us_per_frame
, timeperframe
->denominator
);
512 fps
= (u64
)USEC_PER_SEC
;
513 do_div(fps
, us_per_frame
);
515 inst
->timeperframe
= *timeperframe
;
521 static int venc_g_parm(struct file
*file
, void *fh
, struct v4l2_streamparm
*a
)
523 struct venus_inst
*inst
= to_inst(file
);
525 if (a
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
526 a
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
529 a
->parm
.output
.capability
|= V4L2_CAP_TIMEPERFRAME
;
530 a
->parm
.output
.timeperframe
= inst
->timeperframe
;
535 static int venc_enum_framesizes(struct file
*file
, void *fh
,
536 struct v4l2_frmsizeenum
*fsize
)
538 struct venus_inst
*inst
= to_inst(file
);
539 const struct venus_format
*fmt
;
541 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
543 fmt
= find_format(inst
, fsize
->pixel_format
,
544 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
);
546 fmt
= find_format(inst
, fsize
->pixel_format
,
547 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
);
555 fsize
->stepwise
.min_width
= inst
->cap_width
.min
;
556 fsize
->stepwise
.max_width
= inst
->cap_width
.max
;
557 fsize
->stepwise
.step_width
= inst
->cap_width
.step_size
;
558 fsize
->stepwise
.min_height
= inst
->cap_height
.min
;
559 fsize
->stepwise
.max_height
= inst
->cap_height
.max
;
560 fsize
->stepwise
.step_height
= inst
->cap_height
.step_size
;
565 static int venc_enum_frameintervals(struct file
*file
, void *fh
,
566 struct v4l2_frmivalenum
*fival
)
568 struct venus_inst
*inst
= to_inst(file
);
569 const struct venus_format
*fmt
;
571 fival
->type
= V4L2_FRMIVAL_TYPE_STEPWISE
;
573 fmt
= find_format(inst
, fival
->pixel_format
,
574 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
);
576 fmt
= find_format(inst
, fival
->pixel_format
,
577 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
);
585 if (!fival
->width
|| !fival
->height
)
588 if (fival
->width
> inst
->cap_width
.max
||
589 fival
->width
< inst
->cap_width
.min
||
590 fival
->height
> inst
->cap_height
.max
||
591 fival
->height
< inst
->cap_height
.min
)
594 fival
->stepwise
.min
.numerator
= 1;
595 fival
->stepwise
.min
.denominator
= inst
->cap_framerate
.max
;
596 fival
->stepwise
.max
.numerator
= 1;
597 fival
->stepwise
.max
.denominator
= inst
->cap_framerate
.min
;
598 fival
->stepwise
.step
.numerator
= 1;
599 fival
->stepwise
.step
.denominator
= inst
->cap_framerate
.max
;
604 static const struct v4l2_ioctl_ops venc_ioctl_ops
= {
605 .vidioc_querycap
= venc_querycap
,
606 .vidioc_enum_fmt_vid_cap_mplane
= venc_enum_fmt
,
607 .vidioc_enum_fmt_vid_out_mplane
= venc_enum_fmt
,
608 .vidioc_s_fmt_vid_cap_mplane
= venc_s_fmt
,
609 .vidioc_s_fmt_vid_out_mplane
= venc_s_fmt
,
610 .vidioc_g_fmt_vid_cap_mplane
= venc_g_fmt
,
611 .vidioc_g_fmt_vid_out_mplane
= venc_g_fmt
,
612 .vidioc_try_fmt_vid_cap_mplane
= venc_try_fmt
,
613 .vidioc_try_fmt_vid_out_mplane
= venc_try_fmt
,
614 .vidioc_g_selection
= venc_g_selection
,
615 .vidioc_s_selection
= venc_s_selection
,
616 .vidioc_reqbufs
= v4l2_m2m_ioctl_reqbufs
,
617 .vidioc_querybuf
= v4l2_m2m_ioctl_querybuf
,
618 .vidioc_create_bufs
= v4l2_m2m_ioctl_create_bufs
,
619 .vidioc_prepare_buf
= v4l2_m2m_ioctl_prepare_buf
,
620 .vidioc_qbuf
= v4l2_m2m_ioctl_qbuf
,
621 .vidioc_expbuf
= v4l2_m2m_ioctl_expbuf
,
622 .vidioc_dqbuf
= v4l2_m2m_ioctl_dqbuf
,
623 .vidioc_streamon
= v4l2_m2m_ioctl_streamon
,
624 .vidioc_streamoff
= v4l2_m2m_ioctl_streamoff
,
625 .vidioc_s_parm
= venc_s_parm
,
626 .vidioc_g_parm
= venc_g_parm
,
627 .vidioc_enum_framesizes
= venc_enum_framesizes
,
628 .vidioc_enum_frameintervals
= venc_enum_frameintervals
,
629 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
630 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
633 static int venc_set_properties(struct venus_inst
*inst
)
635 struct venc_controls
*ctr
= &inst
->controls
.enc
;
636 struct hfi_intra_period intra_period
;
637 struct hfi_profile_level pl
;
638 struct hfi_framerate frate
;
639 struct hfi_bitrate brate
;
640 struct hfi_idr_period idrp
;
641 u32 ptype
, rate_control
, bitrate
, profile
= 0, level
= 0;
644 ptype
= HFI_PROPERTY_CONFIG_FRAME_RATE
;
645 frate
.buffer_type
= HFI_BUFFER_OUTPUT
;
646 frate
.framerate
= inst
->fps
* (1 << 16);
648 ret
= hfi_session_set_property(inst
, ptype
, &frate
);
652 if (inst
->fmt_cap
->pixfmt
== V4L2_PIX_FMT_H264
) {
653 struct hfi_h264_vui_timing_info info
;
654 struct hfi_h264_entropy_control entropy
;
655 struct hfi_h264_db_control deblock
;
657 ptype
= HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO
;
659 info
.fixed_framerate
= 1;
660 info
.time_scale
= NSEC_PER_SEC
;
662 ret
= hfi_session_set_property(inst
, ptype
, &info
);
666 ptype
= HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL
;
667 entropy
.entropy_mode
= venc_v4l2_to_hfi(
668 V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE
,
669 ctr
->h264_entropy_mode
);
670 entropy
.cabac_model
= HFI_H264_CABAC_MODEL_0
;
672 ret
= hfi_session_set_property(inst
, ptype
, &entropy
);
676 ptype
= HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL
;
677 deblock
.mode
= venc_v4l2_to_hfi(
678 V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE
,
679 ctr
->h264_loop_filter_mode
);
680 deblock
.slice_alpha_offset
= ctr
->h264_loop_filter_alpha
;
681 deblock
.slice_beta_offset
= ctr
->h264_loop_filter_beta
;
683 ret
= hfi_session_set_property(inst
, ptype
, &deblock
);
688 /* IDR periodicity, n:
689 * n = 0 - only the first I-frame is IDR frame
690 * n = 1 - all I-frames will be IDR frames
691 * n > 1 - every n-th I-frame will be IDR frame
693 ptype
= HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD
;
695 ret
= hfi_session_set_property(inst
, ptype
, &idrp
);
699 if (ctr
->num_b_frames
) {
700 u32 max_num_b_frames
= NUM_B_FRAMES_MAX
;
702 ptype
= HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES
;
703 ret
= hfi_session_set_property(inst
, ptype
, &max_num_b_frames
);
708 ptype
= HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD
;
709 intra_period
.pframes
= ctr
->num_p_frames
;
710 intra_period
.bframes
= ctr
->num_b_frames
;
712 ret
= hfi_session_set_property(inst
, ptype
, &intra_period
);
716 if (ctr
->bitrate_mode
== V4L2_MPEG_VIDEO_BITRATE_MODE_VBR
)
717 rate_control
= HFI_RATE_CONTROL_VBR_CFR
;
719 rate_control
= HFI_RATE_CONTROL_CBR_CFR
;
721 ptype
= HFI_PROPERTY_PARAM_VENC_RATE_CONTROL
;
722 ret
= hfi_session_set_property(inst
, ptype
, &rate_control
);
729 bitrate
= ctr
->bitrate
;
731 ptype
= HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE
;
732 brate
.bitrate
= bitrate
;
735 ret
= hfi_session_set_property(inst
, ptype
, &brate
);
739 if (!ctr
->bitrate_peak
)
742 bitrate
= ctr
->bitrate_peak
;
744 ptype
= HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE
;
745 brate
.bitrate
= bitrate
;
748 ret
= hfi_session_set_property(inst
, ptype
, &brate
);
752 if (inst
->fmt_cap
->pixfmt
== V4L2_PIX_FMT_H264
) {
753 profile
= venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_PROFILE
,
755 level
= venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_LEVEL
,
757 } else if (inst
->fmt_cap
->pixfmt
== V4L2_PIX_FMT_VP8
) {
758 profile
= venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_VPX_PROFILE
,
761 } else if (inst
->fmt_cap
->pixfmt
== V4L2_PIX_FMT_MPEG4
) {
762 profile
= venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE
,
764 level
= venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL
,
766 } else if (inst
->fmt_cap
->pixfmt
== V4L2_PIX_FMT_H263
) {
771 ptype
= HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT
;
772 pl
.profile
= profile
;
775 ret
= hfi_session_set_property(inst
, ptype
, &pl
);
782 static int venc_init_session(struct venus_inst
*inst
)
786 ret
= hfi_session_init(inst
, inst
->fmt_cap
->pixfmt
);
790 ret
= venus_helper_set_input_resolution(inst
, inst
->width
,
795 ret
= venus_helper_set_output_resolution(inst
, inst
->width
,
800 ret
= venus_helper_set_color_format(inst
, inst
->fmt_out
->pixfmt
);
804 ret
= venc_set_properties(inst
);
810 hfi_session_deinit(inst
);
814 static int venc_out_num_buffers(struct venus_inst
*inst
, unsigned int *num
)
816 struct hfi_buffer_requirements bufreq
;
819 ret
= venc_init_session(inst
);
823 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_INPUT
, &bufreq
);
825 *num
= bufreq
.count_actual
;
827 hfi_session_deinit(inst
);
832 static int venc_queue_setup(struct vb2_queue
*q
,
833 unsigned int *num_buffers
, unsigned int *num_planes
,
834 unsigned int sizes
[], struct device
*alloc_devs
[])
836 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
837 unsigned int p
, num
, min
= 4;
841 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
842 *num_planes
!= inst
->fmt_out
->num_planes
)
845 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
846 *num_planes
!= inst
->fmt_cap
->num_planes
)
849 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
&&
850 sizes
[0] < inst
->input_buf_size
)
853 if (q
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
&&
854 sizes
[0] < inst
->output_buf_size
)
861 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
862 *num_planes
= inst
->fmt_out
->num_planes
;
864 ret
= venc_out_num_buffers(inst
, &num
);
869 *num_buffers
= max(*num_buffers
, num
);
870 inst
->num_input_bufs
= *num_buffers
;
872 for (p
= 0; p
< *num_planes
; ++p
)
873 sizes
[p
] = get_framesize_uncompressed(p
, inst
->width
,
875 inst
->input_buf_size
= sizes
[0];
877 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
878 *num_planes
= inst
->fmt_cap
->num_planes
;
879 *num_buffers
= max(*num_buffers
, min
);
880 inst
->num_output_bufs
= *num_buffers
;
881 sizes
[0] = get_framesize_compressed(inst
->width
, inst
->height
);
882 inst
->output_buf_size
= sizes
[0];
892 static int venc_verify_conf(struct venus_inst
*inst
)
894 struct hfi_buffer_requirements bufreq
;
897 if (!inst
->num_input_bufs
|| !inst
->num_output_bufs
)
900 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_OUTPUT
, &bufreq
);
904 if (inst
->num_output_bufs
< bufreq
.count_actual
||
905 inst
->num_output_bufs
< bufreq
.count_min
)
908 ret
= venus_helper_get_bufreq(inst
, HFI_BUFFER_INPUT
, &bufreq
);
912 if (inst
->num_input_bufs
< bufreq
.count_actual
||
913 inst
->num_input_bufs
< bufreq
.count_min
)
919 static int venc_start_streaming(struct vb2_queue
*q
, unsigned int count
)
921 struct venus_inst
*inst
= vb2_get_drv_priv(q
);
924 mutex_lock(&inst
->lock
);
926 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
927 inst
->streamon_out
= 1;
929 inst
->streamon_cap
= 1;
931 if (!(inst
->streamon_out
& inst
->streamon_cap
)) {
932 mutex_unlock(&inst
->lock
);
936 venus_helper_init_instance(inst
);
938 inst
->sequence_cap
= 0;
939 inst
->sequence_out
= 0;
941 ret
= venc_init_session(inst
);
945 ret
= venc_set_properties(inst
);
949 ret
= venc_verify_conf(inst
);
953 ret
= venus_helper_set_num_bufs(inst
, inst
->num_input_bufs
,
954 inst
->num_output_bufs
);
958 ret
= venus_helper_vb2_start_streaming(inst
);
962 mutex_unlock(&inst
->lock
);
967 hfi_session_deinit(inst
);
969 venus_helper_buffers_done(inst
, VB2_BUF_STATE_QUEUED
);
970 if (q
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
)
971 inst
->streamon_out
= 0;
973 inst
->streamon_cap
= 0;
974 mutex_unlock(&inst
->lock
);
978 static const struct vb2_ops venc_vb2_ops
= {
979 .queue_setup
= venc_queue_setup
,
980 .buf_init
= venus_helper_vb2_buf_init
,
981 .buf_prepare
= venus_helper_vb2_buf_prepare
,
982 .start_streaming
= venc_start_streaming
,
983 .stop_streaming
= venus_helper_vb2_stop_streaming
,
984 .buf_queue
= venus_helper_vb2_buf_queue
,
987 static void venc_buf_done(struct venus_inst
*inst
, unsigned int buf_type
,
988 u32 tag
, u32 bytesused
, u32 data_offset
, u32 flags
,
989 u32 hfi_flags
, u64 timestamp_us
)
991 struct vb2_v4l2_buffer
*vbuf
;
992 struct vb2_buffer
*vb
;
995 if (buf_type
== HFI_BUFFER_INPUT
)
996 type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
998 type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1000 vbuf
= venus_helper_find_buf(inst
, type
, tag
);
1004 vbuf
->flags
= flags
;
1006 if (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) {
1007 vb
= &vbuf
->vb2_buf
;
1008 vb2_set_plane_payload(vb
, 0, bytesused
+ data_offset
);
1009 vb
->planes
[0].data_offset
= data_offset
;
1010 vb
->timestamp
= timestamp_us
* NSEC_PER_USEC
;
1011 vbuf
->sequence
= inst
->sequence_cap
++;
1013 vbuf
->sequence
= inst
->sequence_out
++;
1016 v4l2_m2m_buf_done(vbuf
, VB2_BUF_STATE_DONE
);
1019 static void venc_event_notify(struct venus_inst
*inst
, u32 event
,
1020 struct hfi_event_data
*data
)
1022 struct device
*dev
= inst
->core
->dev_enc
;
1024 if (event
== EVT_SESSION_ERROR
) {
1025 inst
->session_error
= true;
1026 dev_err(dev
, "enc: event session error %x\n", inst
->error
);
1030 static const struct hfi_inst_ops venc_hfi_ops
= {
1031 .buf_done
= venc_buf_done
,
1032 .event_notify
= venc_event_notify
,
1035 static const struct v4l2_m2m_ops venc_m2m_ops
= {
1036 .device_run
= venus_helper_m2m_device_run
,
1037 .job_abort
= venus_helper_m2m_job_abort
,
1040 static int m2m_queue_init(void *priv
, struct vb2_queue
*src_vq
,
1041 struct vb2_queue
*dst_vq
)
1043 struct venus_inst
*inst
= priv
;
1046 src_vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1047 src_vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
1048 src_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1049 src_vq
->ops
= &venc_vb2_ops
;
1050 src_vq
->mem_ops
= &vb2_dma_sg_memops
;
1051 src_vq
->drv_priv
= inst
;
1052 src_vq
->buf_struct_size
= sizeof(struct venus_buffer
);
1053 src_vq
->allow_zero_bytesused
= 1;
1054 src_vq
->min_buffers_needed
= 1;
1055 src_vq
->dev
= inst
->core
->dev
;
1056 if (inst
->core
->res
->hfi_version
== HFI_VERSION_1XX
)
1057 src_vq
->bidirectional
= 1;
1058 ret
= vb2_queue_init(src_vq
);
1062 dst_vq
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1063 dst_vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
1064 dst_vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
1065 dst_vq
->ops
= &venc_vb2_ops
;
1066 dst_vq
->mem_ops
= &vb2_dma_sg_memops
;
1067 dst_vq
->drv_priv
= inst
;
1068 dst_vq
->buf_struct_size
= sizeof(struct venus_buffer
);
1069 dst_vq
->allow_zero_bytesused
= 1;
1070 dst_vq
->min_buffers_needed
= 1;
1071 dst_vq
->dev
= inst
->core
->dev
;
1072 ret
= vb2_queue_init(dst_vq
);
1074 vb2_queue_release(src_vq
);
1081 static void venc_inst_init(struct venus_inst
*inst
)
1083 inst
->fmt_cap
= &venc_formats
[2];
1084 inst
->fmt_out
= &venc_formats
[0];
1086 inst
->height
= ALIGN(720, 32);
1087 inst
->out_width
= 1280;
1088 inst
->out_height
= 720;
1090 inst
->timeperframe
.numerator
= 1;
1091 inst
->timeperframe
.denominator
= 15;
1093 inst
->cap_width
.min
= 96;
1094 inst
->cap_width
.max
= 1920;
1095 if (inst
->core
->res
->hfi_version
== HFI_VERSION_3XX
)
1096 inst
->cap_width
.max
= 3840;
1097 inst
->cap_width
.step_size
= 2;
1098 inst
->cap_height
.min
= 64;
1099 inst
->cap_height
.max
= ALIGN(1080, 32);
1100 if (inst
->core
->res
->hfi_version
== HFI_VERSION_3XX
)
1101 inst
->cap_height
.max
= ALIGN(2160, 32);
1102 inst
->cap_height
.step_size
= 2;
1103 inst
->cap_framerate
.min
= 1;
1104 inst
->cap_framerate
.max
= 30;
1105 inst
->cap_framerate
.step_size
= 1;
1106 inst
->cap_mbs_per_frame
.min
= 24;
1107 inst
->cap_mbs_per_frame
.max
= 8160;
1110 static int venc_open(struct file
*file
)
1112 struct venus_core
*core
= video_drvdata(file
);
1113 struct venus_inst
*inst
;
1116 inst
= kzalloc(sizeof(*inst
), GFP_KERNEL
);
1120 INIT_LIST_HEAD(&inst
->registeredbufs
);
1121 INIT_LIST_HEAD(&inst
->internalbufs
);
1122 INIT_LIST_HEAD(&inst
->list
);
1123 mutex_init(&inst
->lock
);
1126 inst
->session_type
= VIDC_SESSION_TYPE_ENC
;
1128 venus_helper_init_instance(inst
);
1130 ret
= pm_runtime_get_sync(core
->dev_enc
);
1134 ret
= venc_ctrl_init(inst
);
1138 ret
= hfi_session_create(inst
, &venc_hfi_ops
);
1140 goto err_ctrl_deinit
;
1142 venc_inst_init(inst
);
1145 * create m2m device for every instance, the m2m context scheduling
1146 * is made by firmware side so we do not need to care about.
1148 inst
->m2m_dev
= v4l2_m2m_init(&venc_m2m_ops
);
1149 if (IS_ERR(inst
->m2m_dev
)) {
1150 ret
= PTR_ERR(inst
->m2m_dev
);
1151 goto err_session_destroy
;
1154 inst
->m2m_ctx
= v4l2_m2m_ctx_init(inst
->m2m_dev
, inst
, m2m_queue_init
);
1155 if (IS_ERR(inst
->m2m_ctx
)) {
1156 ret
= PTR_ERR(inst
->m2m_ctx
);
1157 goto err_m2m_release
;
1160 v4l2_fh_init(&inst
->fh
, core
->vdev_enc
);
1162 inst
->fh
.ctrl_handler
= &inst
->ctrl_handler
;
1163 v4l2_fh_add(&inst
->fh
);
1164 inst
->fh
.m2m_ctx
= inst
->m2m_ctx
;
1165 file
->private_data
= &inst
->fh
;
1170 v4l2_m2m_release(inst
->m2m_dev
);
1171 err_session_destroy
:
1172 hfi_session_destroy(inst
);
1174 venc_ctrl_deinit(inst
);
1176 pm_runtime_put_sync(core
->dev_enc
);
1182 static int venc_close(struct file
*file
)
1184 struct venus_inst
*inst
= to_inst(file
);
1186 v4l2_m2m_ctx_release(inst
->m2m_ctx
);
1187 v4l2_m2m_release(inst
->m2m_dev
);
1188 venc_ctrl_deinit(inst
);
1189 hfi_session_destroy(inst
);
1190 mutex_destroy(&inst
->lock
);
1191 v4l2_fh_del(&inst
->fh
);
1192 v4l2_fh_exit(&inst
->fh
);
1194 pm_runtime_put_sync(inst
->core
->dev_enc
);
1200 static const struct v4l2_file_operations venc_fops
= {
1201 .owner
= THIS_MODULE
,
1203 .release
= venc_close
,
1204 .unlocked_ioctl
= video_ioctl2
,
1205 .poll
= v4l2_m2m_fop_poll
,
1206 .mmap
= v4l2_m2m_fop_mmap
,
1207 #ifdef CONFIG_COMPAT
1208 .compat_ioctl32
= v4l2_compat_ioctl32
,
1212 static int venc_probe(struct platform_device
*pdev
)
1214 struct device
*dev
= &pdev
->dev
;
1215 struct video_device
*vdev
;
1216 struct venus_core
*core
;
1220 return -EPROBE_DEFER
;
1222 core
= dev_get_drvdata(dev
->parent
);
1224 return -EPROBE_DEFER
;
1226 if (core
->res
->hfi_version
== HFI_VERSION_3XX
) {
1227 core
->core1_clk
= devm_clk_get(dev
, "core");
1228 if (IS_ERR(core
->core1_clk
))
1229 return PTR_ERR(core
->core1_clk
);
1232 platform_set_drvdata(pdev
, core
);
1234 vdev
= video_device_alloc();
1238 strlcpy(vdev
->name
, "qcom-venus-encoder", sizeof(vdev
->name
));
1239 vdev
->release
= video_device_release
;
1240 vdev
->fops
= &venc_fops
;
1241 vdev
->ioctl_ops
= &venc_ioctl_ops
;
1242 vdev
->vfl_dir
= VFL_DIR_M2M
;
1243 vdev
->v4l2_dev
= &core
->v4l2_dev
;
1244 vdev
->device_caps
= V4L2_CAP_VIDEO_M2M_MPLANE
| V4L2_CAP_STREAMING
;
1246 ret
= video_register_device(vdev
, VFL_TYPE_GRABBER
, -1);
1248 goto err_vdev_release
;
1250 core
->vdev_enc
= vdev
;
1251 core
->dev_enc
= dev
;
1253 video_set_drvdata(vdev
, core
);
1254 pm_runtime_enable(dev
);
1259 video_device_release(vdev
);
1263 static int venc_remove(struct platform_device
*pdev
)
1265 struct venus_core
*core
= dev_get_drvdata(pdev
->dev
.parent
);
1267 video_unregister_device(core
->vdev_enc
);
1268 pm_runtime_disable(core
->dev_enc
);
1273 static __maybe_unused
int venc_runtime_suspend(struct device
*dev
)
1275 struct venus_core
*core
= dev_get_drvdata(dev
);
1277 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
1280 writel(0, core
->base
+ WRAPPER_VENC_VCODEC_POWER_CONTROL
);
1281 clk_disable_unprepare(core
->core1_clk
);
1282 writel(1, core
->base
+ WRAPPER_VENC_VCODEC_POWER_CONTROL
);
1287 static __maybe_unused
int venc_runtime_resume(struct device
*dev
)
1289 struct venus_core
*core
= dev_get_drvdata(dev
);
1292 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
1295 writel(0, core
->base
+ WRAPPER_VENC_VCODEC_POWER_CONTROL
);
1296 ret
= clk_prepare_enable(core
->core1_clk
);
1297 writel(1, core
->base
+ WRAPPER_VENC_VCODEC_POWER_CONTROL
);
1302 static const struct dev_pm_ops venc_pm_ops
= {
1303 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1304 pm_runtime_force_resume
)
1305 SET_RUNTIME_PM_OPS(venc_runtime_suspend
, venc_runtime_resume
, NULL
)
1308 static const struct of_device_id venc_dt_match
[] = {
1309 { .compatible
= "venus-encoder" },
1312 MODULE_DEVICE_TABLE(of
, venc_dt_match
);
1314 static struct platform_driver qcom_venus_enc_driver
= {
1315 .probe
= venc_probe
,
1316 .remove
= venc_remove
,
1318 .name
= "qcom-venus-encoder",
1319 .of_match_table
= venc_dt_match
,
1323 module_platform_driver(qcom_venus_enc_driver
);
1325 MODULE_ALIAS("platform:qcom-venus-encoder");
1326 MODULE_DESCRIPTION("Qualcomm Venus video encoder driver");
1327 MODULE_LICENSE("GPL v2");