| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. |
|---|
| 3 | 4 | * Copyright (C) 2017 Linaro Ltd. |
|---|
| 4 | | - * |
|---|
| 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. |
|---|
| 8 | | - * |
|---|
| 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. |
|---|
| 13 | | - * |
|---|
| 14 | 5 | */ |
|---|
| 15 | 6 | #include <linux/clk.h> |
|---|
| 16 | 7 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 29 | 20 | #include "core.h" |
|---|
| 30 | 21 | #include "helpers.h" |
|---|
| 31 | 22 | #include "venc.h" |
|---|
| 23 | +#include "pm_helpers.h" |
|---|
| 32 | 24 | |
|---|
| 33 | 25 | #define NUM_B_FRAMES_MAX 4 |
|---|
| 34 | 26 | |
|---|
| .. | .. |
|---|
| 121 | 113 | static int venc_v4l2_to_hfi(int id, int value) |
|---|
| 122 | 114 | { |
|---|
| 123 | 115 | switch (id) { |
|---|
| 124 | | - case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
|---|
| 125 | | - switch (value) { |
|---|
| 126 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0: |
|---|
| 127 | | - default: |
|---|
| 128 | | - return HFI_MPEG4_LEVEL_0; |
|---|
| 129 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B: |
|---|
| 130 | | - return HFI_MPEG4_LEVEL_0b; |
|---|
| 131 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1: |
|---|
| 132 | | - return HFI_MPEG4_LEVEL_1; |
|---|
| 133 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2: |
|---|
| 134 | | - return HFI_MPEG4_LEVEL_2; |
|---|
| 135 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3: |
|---|
| 136 | | - return HFI_MPEG4_LEVEL_3; |
|---|
| 137 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4: |
|---|
| 138 | | - return HFI_MPEG4_LEVEL_4; |
|---|
| 139 | | - case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5: |
|---|
| 140 | | - return HFI_MPEG4_LEVEL_5; |
|---|
| 141 | | - } |
|---|
| 142 | | - case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
|---|
| 143 | | - switch (value) { |
|---|
| 144 | | - case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE: |
|---|
| 145 | | - default: |
|---|
| 146 | | - return HFI_MPEG4_PROFILE_SIMPLE; |
|---|
| 147 | | - case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE: |
|---|
| 148 | | - return HFI_MPEG4_PROFILE_ADVANCEDSIMPLE; |
|---|
| 149 | | - } |
|---|
| 150 | | - case V4L2_CID_MPEG_VIDEO_H264_PROFILE: |
|---|
| 151 | | - switch (value) { |
|---|
| 152 | | - case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: |
|---|
| 153 | | - return HFI_H264_PROFILE_BASELINE; |
|---|
| 154 | | - case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: |
|---|
| 155 | | - return HFI_H264_PROFILE_CONSTRAINED_BASE; |
|---|
| 156 | | - case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: |
|---|
| 157 | | - return HFI_H264_PROFILE_MAIN; |
|---|
| 158 | | - case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: |
|---|
| 159 | | - default: |
|---|
| 160 | | - return HFI_H264_PROFILE_HIGH; |
|---|
| 161 | | - } |
|---|
| 162 | | - case V4L2_CID_MPEG_VIDEO_H264_LEVEL: |
|---|
| 163 | | - switch (value) { |
|---|
| 164 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: |
|---|
| 165 | | - return HFI_H264_LEVEL_1; |
|---|
| 166 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_1B: |
|---|
| 167 | | - return HFI_H264_LEVEL_1b; |
|---|
| 168 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: |
|---|
| 169 | | - return HFI_H264_LEVEL_11; |
|---|
| 170 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: |
|---|
| 171 | | - return HFI_H264_LEVEL_12; |
|---|
| 172 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: |
|---|
| 173 | | - return HFI_H264_LEVEL_13; |
|---|
| 174 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: |
|---|
| 175 | | - return HFI_H264_LEVEL_2; |
|---|
| 176 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: |
|---|
| 177 | | - return HFI_H264_LEVEL_21; |
|---|
| 178 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: |
|---|
| 179 | | - return HFI_H264_LEVEL_22; |
|---|
| 180 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: |
|---|
| 181 | | - return HFI_H264_LEVEL_3; |
|---|
| 182 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: |
|---|
| 183 | | - return HFI_H264_LEVEL_31; |
|---|
| 184 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: |
|---|
| 185 | | - return HFI_H264_LEVEL_32; |
|---|
| 186 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: |
|---|
| 187 | | - return HFI_H264_LEVEL_4; |
|---|
| 188 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: |
|---|
| 189 | | - return HFI_H264_LEVEL_41; |
|---|
| 190 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: |
|---|
| 191 | | - return HFI_H264_LEVEL_42; |
|---|
| 192 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: |
|---|
| 193 | | - default: |
|---|
| 194 | | - return HFI_H264_LEVEL_5; |
|---|
| 195 | | - case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: |
|---|
| 196 | | - return HFI_H264_LEVEL_51; |
|---|
| 197 | | - } |
|---|
| 198 | 116 | case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: |
|---|
| 199 | 117 | switch (value) { |
|---|
| 200 | 118 | case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC: |
|---|
| .. | .. |
|---|
| 202 | 120 | return HFI_H264_ENTROPY_CAVLC; |
|---|
| 203 | 121 | case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC: |
|---|
| 204 | 122 | return HFI_H264_ENTROPY_CABAC; |
|---|
| 205 | | - } |
|---|
| 206 | | - case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: |
|---|
| 207 | | - switch (value) { |
|---|
| 208 | | - case 0: |
|---|
| 209 | | - default: |
|---|
| 210 | | - return HFI_VPX_PROFILE_VERSION_0; |
|---|
| 211 | | - case 1: |
|---|
| 212 | | - return HFI_VPX_PROFILE_VERSION_1; |
|---|
| 213 | | - case 2: |
|---|
| 214 | | - return HFI_VPX_PROFILE_VERSION_2; |
|---|
| 215 | | - case 3: |
|---|
| 216 | | - return HFI_VPX_PROFILE_VERSION_3; |
|---|
| 217 | 123 | } |
|---|
| 218 | 124 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: |
|---|
| 219 | 125 | switch (value) { |
|---|
| .. | .. |
|---|
| 225 | 131 | case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: |
|---|
| 226 | 132 | return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY; |
|---|
| 227 | 133 | } |
|---|
| 228 | | - case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: |
|---|
| 229 | | - switch (value) { |
|---|
| 230 | | - case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN: |
|---|
| 231 | | - default: |
|---|
| 232 | | - return HFI_HEVC_PROFILE_MAIN; |
|---|
| 233 | | - case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE: |
|---|
| 234 | | - return HFI_HEVC_PROFILE_MAIN_STILL_PIC; |
|---|
| 235 | | - case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10: |
|---|
| 236 | | - return HFI_HEVC_PROFILE_MAIN10; |
|---|
| 237 | | - } |
|---|
| 238 | | - case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: |
|---|
| 239 | | - switch (value) { |
|---|
| 240 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_1: |
|---|
| 241 | | - default: |
|---|
| 242 | | - return HFI_HEVC_LEVEL_1; |
|---|
| 243 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_2: |
|---|
| 244 | | - return HFI_HEVC_LEVEL_2; |
|---|
| 245 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1: |
|---|
| 246 | | - return HFI_HEVC_LEVEL_21; |
|---|
| 247 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_3: |
|---|
| 248 | | - return HFI_HEVC_LEVEL_3; |
|---|
| 249 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1: |
|---|
| 250 | | - return HFI_HEVC_LEVEL_31; |
|---|
| 251 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_4: |
|---|
| 252 | | - return HFI_HEVC_LEVEL_4; |
|---|
| 253 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1: |
|---|
| 254 | | - return HFI_HEVC_LEVEL_41; |
|---|
| 255 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_5: |
|---|
| 256 | | - return HFI_HEVC_LEVEL_5; |
|---|
| 257 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1: |
|---|
| 258 | | - return HFI_HEVC_LEVEL_51; |
|---|
| 259 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2: |
|---|
| 260 | | - return HFI_HEVC_LEVEL_52; |
|---|
| 261 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_6: |
|---|
| 262 | | - return HFI_HEVC_LEVEL_6; |
|---|
| 263 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1: |
|---|
| 264 | | - return HFI_HEVC_LEVEL_61; |
|---|
| 265 | | - case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2: |
|---|
| 266 | | - return HFI_HEVC_LEVEL_62; |
|---|
| 267 | | - } |
|---|
| 268 | 134 | } |
|---|
| 269 | 135 | |
|---|
| 270 | 136 | return 0; |
|---|
| .. | .. |
|---|
| 273 | 139 | static int |
|---|
| 274 | 140 | venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) |
|---|
| 275 | 141 | { |
|---|
| 276 | | - strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver)); |
|---|
| 277 | | - strlcpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card)); |
|---|
| 278 | | - strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); |
|---|
| 142 | + strscpy(cap->driver, "qcom-venus", sizeof(cap->driver)); |
|---|
| 143 | + strscpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card)); |
|---|
| 144 | + strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); |
|---|
| 279 | 145 | |
|---|
| 280 | 146 | return 0; |
|---|
| 281 | 147 | } |
|---|
| .. | .. |
|---|
| 303 | 169 | struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; |
|---|
| 304 | 170 | struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; |
|---|
| 305 | 171 | const struct venus_format *fmt; |
|---|
| 172 | + u32 sizeimage; |
|---|
| 306 | 173 | |
|---|
| 307 | 174 | memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); |
|---|
| 308 | 175 | memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); |
|---|
| .. | .. |
|---|
| 336 | 203 | pixmp->num_planes = fmt->num_planes; |
|---|
| 337 | 204 | pixmp->flags = 0; |
|---|
| 338 | 205 | |
|---|
| 339 | | - pfmt[0].sizeimage = venus_helper_get_framesz(pixmp->pixelformat, |
|---|
| 340 | | - pixmp->width, |
|---|
| 341 | | - pixmp->height); |
|---|
| 206 | + sizeimage = venus_helper_get_framesz(pixmp->pixelformat, |
|---|
| 207 | + pixmp->width, |
|---|
| 208 | + pixmp->height); |
|---|
| 209 | + pfmt[0].sizeimage = max(ALIGN(pfmt[0].sizeimage, SZ_4K), sizeimage); |
|---|
| 342 | 210 | |
|---|
| 343 | 211 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
|---|
| 344 | 212 | pfmt[0].bytesperline = ALIGN(pixmp->width, 128); |
|---|
| .. | .. |
|---|
| 365 | 233 | const struct venus_format *fmt; |
|---|
| 366 | 234 | struct v4l2_format format; |
|---|
| 367 | 235 | u32 pixfmt_out = 0, pixfmt_cap = 0; |
|---|
| 236 | + struct vb2_queue *q; |
|---|
| 237 | + |
|---|
| 238 | + q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); |
|---|
| 239 | + if (!q) |
|---|
| 240 | + return -EINVAL; |
|---|
| 241 | + |
|---|
| 242 | + if (vb2_is_busy(q)) |
|---|
| 243 | + return -EBUSY; |
|---|
| 368 | 244 | |
|---|
| 369 | 245 | orig_pixmp = *pixmp; |
|---|
| 370 | 246 | |
|---|
| .. | .. |
|---|
| 410 | 286 | |
|---|
| 411 | 287 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
|---|
| 412 | 288 | inst->fmt_out = fmt; |
|---|
| 413 | | - else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
|---|
| 289 | + else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
|---|
| 414 | 290 | inst->fmt_cap = fmt; |
|---|
| 291 | + inst->output_buf_size = pixmp->plane_fmt[0].sizeimage; |
|---|
| 292 | + } |
|---|
| 415 | 293 | |
|---|
| 416 | 294 | return 0; |
|---|
| 417 | 295 | } |
|---|
| .. | .. |
|---|
| 582 | 460 | { |
|---|
| 583 | 461 | struct venus_inst *inst = to_inst(file); |
|---|
| 584 | 462 | const struct venus_format *fmt; |
|---|
| 463 | + unsigned int framerate_factor = 1; |
|---|
| 585 | 464 | |
|---|
| 586 | 465 | fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; |
|---|
| 587 | 466 | |
|---|
| .. | .. |
|---|
| 606 | 485 | fival->height < frame_height_min(inst)) |
|---|
| 607 | 486 | return -EINVAL; |
|---|
| 608 | 487 | |
|---|
| 488 | + if (IS_V1(inst->core)) { |
|---|
| 489 | + /* framerate is reported in 1/65535 fps unit */ |
|---|
| 490 | + framerate_factor = (1 << 16); |
|---|
| 491 | + } |
|---|
| 492 | + |
|---|
| 609 | 493 | fival->stepwise.min.numerator = 1; |
|---|
| 610 | | - fival->stepwise.min.denominator = frate_max(inst); |
|---|
| 494 | + fival->stepwise.min.denominator = frate_max(inst) / framerate_factor; |
|---|
| 611 | 495 | fival->stepwise.max.numerator = 1; |
|---|
| 612 | | - fival->stepwise.max.denominator = frate_min(inst); |
|---|
| 496 | + fival->stepwise.max.denominator = frate_min(inst) / framerate_factor; |
|---|
| 613 | 497 | fival->stepwise.step.numerator = 1; |
|---|
| 614 | | - fival->stepwise.step.denominator = frate_max(inst); |
|---|
| 498 | + fival->stepwise.step.denominator = frate_max(inst) / framerate_factor; |
|---|
| 615 | 499 | |
|---|
| 616 | 500 | return 0; |
|---|
| 617 | 501 | } |
|---|
| 618 | 502 | |
|---|
| 619 | 503 | static const struct v4l2_ioctl_ops venc_ioctl_ops = { |
|---|
| 620 | 504 | .vidioc_querycap = venc_querycap, |
|---|
| 621 | | - .vidioc_enum_fmt_vid_cap_mplane = venc_enum_fmt, |
|---|
| 622 | | - .vidioc_enum_fmt_vid_out_mplane = venc_enum_fmt, |
|---|
| 505 | + .vidioc_enum_fmt_vid_cap = venc_enum_fmt, |
|---|
| 506 | + .vidioc_enum_fmt_vid_out = venc_enum_fmt, |
|---|
| 623 | 507 | .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt, |
|---|
| 624 | 508 | .vidioc_s_fmt_vid_out_mplane = venc_s_fmt, |
|---|
| 625 | 509 | .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt, |
|---|
| .. | .. |
|---|
| 649 | 533 | { |
|---|
| 650 | 534 | struct venc_controls *ctr = &inst->controls.enc; |
|---|
| 651 | 535 | struct hfi_intra_period intra_period; |
|---|
| 652 | | - struct hfi_profile_level pl; |
|---|
| 653 | 536 | struct hfi_framerate frate; |
|---|
| 654 | 537 | struct hfi_bitrate brate; |
|---|
| 655 | 538 | struct hfi_idr_period idrp; |
|---|
| 656 | | - u32 ptype, rate_control, bitrate, profile = 0, level = 0; |
|---|
| 539 | + struct hfi_quantization quant; |
|---|
| 540 | + struct hfi_quantization_range quant_range; |
|---|
| 541 | + u32 ptype, rate_control, bitrate; |
|---|
| 542 | + u32 profile, level; |
|---|
| 657 | 543 | int ret; |
|---|
| 658 | 544 | |
|---|
| 659 | 545 | ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); |
|---|
| 660 | | - if (ret) |
|---|
| 661 | | - return ret; |
|---|
| 662 | | - |
|---|
| 663 | | - ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_2); |
|---|
| 664 | 546 | if (ret) |
|---|
| 665 | 547 | return ret; |
|---|
| 666 | 548 | |
|---|
| .. | .. |
|---|
| 736 | 618 | if (ret) |
|---|
| 737 | 619 | return ret; |
|---|
| 738 | 620 | |
|---|
| 739 | | - if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
|---|
| 740 | | - rate_control = HFI_RATE_CONTROL_VBR_CFR; |
|---|
| 741 | | - else |
|---|
| 742 | | - rate_control = HFI_RATE_CONTROL_CBR_CFR; |
|---|
| 621 | + if (!ctr->rc_enable) |
|---|
| 622 | + rate_control = HFI_RATE_CONTROL_OFF; |
|---|
| 623 | + else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
|---|
| 624 | + rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_VBR_VFR : |
|---|
| 625 | + HFI_RATE_CONTROL_VBR_CFR; |
|---|
| 626 | + else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
|---|
| 627 | + rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_CBR_VFR : |
|---|
| 628 | + HFI_RATE_CONTROL_CBR_CFR; |
|---|
| 629 | + else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) |
|---|
| 630 | + rate_control = HFI_RATE_CONTROL_CQ; |
|---|
| 743 | 631 | |
|---|
| 744 | 632 | ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL; |
|---|
| 745 | 633 | ret = hfi_session_set_property(inst, ptype, &rate_control); |
|---|
| 746 | 634 | if (ret) |
|---|
| 747 | 635 | return ret; |
|---|
| 636 | + |
|---|
| 637 | + if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) { |
|---|
| 638 | + struct hfi_heic_frame_quality quality = {}; |
|---|
| 639 | + |
|---|
| 640 | + ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY; |
|---|
| 641 | + quality.frame_quality = ctr->const_quality; |
|---|
| 642 | + ret = hfi_session_set_property(inst, ptype, &quality); |
|---|
| 643 | + if (ret) |
|---|
| 644 | + return ret; |
|---|
| 645 | + } |
|---|
| 748 | 646 | |
|---|
| 749 | 647 | if (!ctr->bitrate) |
|---|
| 750 | 648 | bitrate = 64000; |
|---|
| .. | .. |
|---|
| 772 | 670 | if (ret) |
|---|
| 773 | 671 | return ret; |
|---|
| 774 | 672 | |
|---|
| 775 | | - if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) { |
|---|
| 776 | | - profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_PROFILE, |
|---|
| 777 | | - ctr->profile.h264); |
|---|
| 778 | | - level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_LEVEL, |
|---|
| 779 | | - ctr->level.h264); |
|---|
| 780 | | - } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) { |
|---|
| 781 | | - profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_VP8_PROFILE, |
|---|
| 782 | | - ctr->profile.vpx); |
|---|
| 673 | + ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP; |
|---|
| 674 | + quant.qp_i = ctr->h264_i_qp; |
|---|
| 675 | + quant.qp_p = ctr->h264_p_qp; |
|---|
| 676 | + quant.qp_b = ctr->h264_b_qp; |
|---|
| 677 | + quant.layer_id = 0; |
|---|
| 678 | + ret = hfi_session_set_property(inst, ptype, &quant); |
|---|
| 679 | + if (ret) |
|---|
| 680 | + return ret; |
|---|
| 681 | + |
|---|
| 682 | + ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE; |
|---|
| 683 | + quant_range.min_qp = ctr->h264_min_qp; |
|---|
| 684 | + quant_range.max_qp = ctr->h264_max_qp; |
|---|
| 685 | + quant_range.layer_id = 0; |
|---|
| 686 | + ret = hfi_session_set_property(inst, ptype, &quant_range); |
|---|
| 687 | + if (ret) |
|---|
| 688 | + return ret; |
|---|
| 689 | + |
|---|
| 690 | + switch (inst->hfi_codec) { |
|---|
| 691 | + case HFI_VIDEO_CODEC_H264: |
|---|
| 692 | + profile = ctr->profile.h264; |
|---|
| 693 | + level = ctr->level.h264; |
|---|
| 694 | + break; |
|---|
| 695 | + case HFI_VIDEO_CODEC_MPEG4: |
|---|
| 696 | + profile = ctr->profile.mpeg4; |
|---|
| 697 | + level = ctr->level.mpeg4; |
|---|
| 698 | + break; |
|---|
| 699 | + case HFI_VIDEO_CODEC_VP8: |
|---|
| 700 | + profile = ctr->profile.vp8; |
|---|
| 783 | 701 | level = 0; |
|---|
| 784 | | - } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_MPEG4) { |
|---|
| 785 | | - profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, |
|---|
| 786 | | - ctr->profile.mpeg4); |
|---|
| 787 | | - level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, |
|---|
| 788 | | - ctr->level.mpeg4); |
|---|
| 789 | | - } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H263) { |
|---|
| 702 | + break; |
|---|
| 703 | + case HFI_VIDEO_CODEC_VP9: |
|---|
| 704 | + profile = ctr->profile.vp9; |
|---|
| 705 | + level = ctr->level.vp9; |
|---|
| 706 | + break; |
|---|
| 707 | + case HFI_VIDEO_CODEC_HEVC: |
|---|
| 708 | + profile = ctr->profile.hevc; |
|---|
| 709 | + level = ctr->level.hevc; |
|---|
| 710 | + break; |
|---|
| 711 | + case HFI_VIDEO_CODEC_MPEG2: |
|---|
| 712 | + default: |
|---|
| 790 | 713 | profile = 0; |
|---|
| 791 | 714 | level = 0; |
|---|
| 792 | | - } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) { |
|---|
| 793 | | - profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, |
|---|
| 794 | | - ctr->profile.hevc); |
|---|
| 795 | | - level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, |
|---|
| 796 | | - ctr->level.hevc); |
|---|
| 715 | + break; |
|---|
| 797 | 716 | } |
|---|
| 798 | 717 | |
|---|
| 799 | | - ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; |
|---|
| 800 | | - pl.profile = profile; |
|---|
| 801 | | - pl.level = level; |
|---|
| 802 | | - |
|---|
| 803 | | - ret = hfi_session_set_property(inst, ptype, &pl); |
|---|
| 718 | + ret = venus_helper_set_profile_level(inst, profile, level); |
|---|
| 804 | 719 | if (ret) |
|---|
| 805 | 720 | return ret; |
|---|
| 806 | 721 | |
|---|
| .. | .. |
|---|
| 827 | 742 | goto deinit; |
|---|
| 828 | 743 | |
|---|
| 829 | 744 | ret = venus_helper_set_color_format(inst, inst->fmt_out->pixfmt); |
|---|
| 745 | + if (ret) |
|---|
| 746 | + goto deinit; |
|---|
| 747 | + |
|---|
| 748 | + ret = venus_helper_init_codec_freq_data(inst); |
|---|
| 830 | 749 | if (ret) |
|---|
| 831 | 750 | goto deinit; |
|---|
| 832 | 751 | |
|---|
| .. | .. |
|---|
| 910 | 829 | sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt, |
|---|
| 911 | 830 | inst->width, |
|---|
| 912 | 831 | inst->height); |
|---|
| 832 | + sizes[0] = max(sizes[0], inst->output_buf_size); |
|---|
| 913 | 833 | inst->output_buf_size = sizes[0]; |
|---|
| 914 | 834 | break; |
|---|
| 915 | 835 | default: |
|---|
| .. | .. |
|---|
| 974 | 894 | if (ret) |
|---|
| 975 | 895 | goto bufs_done; |
|---|
| 976 | 896 | |
|---|
| 897 | + ret = venus_pm_acquire_core(inst); |
|---|
| 898 | + if (ret) |
|---|
| 899 | + goto deinit_sess; |
|---|
| 900 | + |
|---|
| 977 | 901 | ret = venc_set_properties(inst); |
|---|
| 978 | 902 | if (ret) |
|---|
| 979 | 903 | goto deinit_sess; |
|---|
| .. | .. |
|---|
| 998 | 922 | deinit_sess: |
|---|
| 999 | 923 | hfi_session_deinit(inst); |
|---|
| 1000 | 924 | bufs_done: |
|---|
| 1001 | | - venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED); |
|---|
| 925 | + venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); |
|---|
| 1002 | 926 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
|---|
| 1003 | 927 | inst->streamon_out = 0; |
|---|
| 1004 | 928 | else |
|---|
| .. | .. |
|---|
| 1076 | 1000 | int ret; |
|---|
| 1077 | 1001 | |
|---|
| 1078 | 1002 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
|---|
| 1079 | | - src_vq->io_modes = VB2_MMAP | VB2_DMABUF; |
|---|
| 1003 | + src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
|---|
| 1080 | 1004 | src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
|---|
| 1081 | 1005 | src_vq->ops = &venc_vb2_ops; |
|---|
| 1082 | 1006 | src_vq->mem_ops = &vb2_dma_sg_memops; |
|---|
| .. | .. |
|---|
| 1092 | 1016 | return ret; |
|---|
| 1093 | 1017 | |
|---|
| 1094 | 1018 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
|---|
| 1095 | | - dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; |
|---|
| 1019 | + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
|---|
| 1096 | 1020 | dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
|---|
| 1097 | 1021 | dst_vq->ops = &venc_vb2_ops; |
|---|
| 1098 | 1022 | dst_vq->mem_ops = &vb2_dma_sg_memops; |
|---|
| .. | .. |
|---|
| 1101 | 1025 | dst_vq->allow_zero_bytesused = 1; |
|---|
| 1102 | 1026 | dst_vq->min_buffers_needed = 1; |
|---|
| 1103 | 1027 | dst_vq->dev = inst->core->dev; |
|---|
| 1104 | | - ret = vb2_queue_init(dst_vq); |
|---|
| 1105 | | - if (ret) { |
|---|
| 1106 | | - vb2_queue_release(src_vq); |
|---|
| 1107 | | - return ret; |
|---|
| 1108 | | - } |
|---|
| 1109 | | - |
|---|
| 1110 | | - return 0; |
|---|
| 1028 | + return vb2_queue_init(dst_vq); |
|---|
| 1111 | 1029 | } |
|---|
| 1112 | 1030 | |
|---|
| 1113 | 1031 | static void venc_inst_init(struct venus_inst *inst) |
|---|
| .. | .. |
|---|
| 1142 | 1060 | |
|---|
| 1143 | 1061 | inst->core = core; |
|---|
| 1144 | 1062 | inst->session_type = VIDC_SESSION_TYPE_ENC; |
|---|
| 1063 | + inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT; |
|---|
| 1064 | + inst->core_acquired = false; |
|---|
| 1145 | 1065 | |
|---|
| 1146 | 1066 | venus_helper_init_instance(inst); |
|---|
| 1147 | 1067 | |
|---|
| 1148 | 1068 | ret = pm_runtime_get_sync(core->dev_enc); |
|---|
| 1149 | 1069 | if (ret < 0) |
|---|
| 1150 | | - goto err_free_inst; |
|---|
| 1070 | + goto err_put_sync; |
|---|
| 1151 | 1071 | |
|---|
| 1152 | 1072 | ret = venc_ctrl_init(inst); |
|---|
| 1153 | 1073 | if (ret) |
|---|
| .. | .. |
|---|
| 1192 | 1112 | venc_ctrl_deinit(inst); |
|---|
| 1193 | 1113 | err_put_sync: |
|---|
| 1194 | 1114 | pm_runtime_put_sync(core->dev_enc); |
|---|
| 1195 | | -err_free_inst: |
|---|
| 1196 | 1115 | kfree(inst); |
|---|
| 1197 | 1116 | return ret; |
|---|
| 1198 | 1117 | } |
|---|
| .. | .. |
|---|
| 1238 | 1157 | if (!core) |
|---|
| 1239 | 1158 | return -EPROBE_DEFER; |
|---|
| 1240 | 1159 | |
|---|
| 1241 | | - if (IS_V3(core) || IS_V4(core)) { |
|---|
| 1242 | | - core->core1_clk = devm_clk_get(dev, "core"); |
|---|
| 1243 | | - if (IS_ERR(core->core1_clk)) |
|---|
| 1244 | | - return PTR_ERR(core->core1_clk); |
|---|
| 1245 | | - } |
|---|
| 1246 | | - |
|---|
| 1247 | | - if (IS_V4(core)) { |
|---|
| 1248 | | - core->core1_bus_clk = devm_clk_get(dev, "bus"); |
|---|
| 1249 | | - if (IS_ERR(core->core1_bus_clk)) |
|---|
| 1250 | | - return PTR_ERR(core->core1_bus_clk); |
|---|
| 1251 | | - } |
|---|
| 1252 | | - |
|---|
| 1253 | 1160 | platform_set_drvdata(pdev, core); |
|---|
| 1161 | + |
|---|
| 1162 | + if (core->pm_ops->venc_get) { |
|---|
| 1163 | + ret = core->pm_ops->venc_get(dev); |
|---|
| 1164 | + if (ret) |
|---|
| 1165 | + return ret; |
|---|
| 1166 | + } |
|---|
| 1254 | 1167 | |
|---|
| 1255 | 1168 | vdev = video_device_alloc(); |
|---|
| 1256 | 1169 | if (!vdev) |
|---|
| 1257 | 1170 | return -ENOMEM; |
|---|
| 1258 | 1171 | |
|---|
| 1259 | | - strlcpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name)); |
|---|
| 1172 | + strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name)); |
|---|
| 1260 | 1173 | vdev->release = video_device_release; |
|---|
| 1261 | 1174 | vdev->fops = &venc_fops; |
|---|
| 1262 | 1175 | vdev->ioctl_ops = &venc_ioctl_ops; |
|---|
| .. | .. |
|---|
| 1264 | 1177 | vdev->v4l2_dev = &core->v4l2_dev; |
|---|
| 1265 | 1178 | vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
|---|
| 1266 | 1179 | |
|---|
| 1267 | | - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 1180 | + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 1268 | 1181 | if (ret) |
|---|
| 1269 | 1182 | goto err_vdev_release; |
|---|
| 1270 | 1183 | |
|---|
| .. | .. |
|---|
| 1288 | 1201 | video_unregister_device(core->vdev_enc); |
|---|
| 1289 | 1202 | pm_runtime_disable(core->dev_enc); |
|---|
| 1290 | 1203 | |
|---|
| 1204 | + if (core->pm_ops->venc_put) |
|---|
| 1205 | + core->pm_ops->venc_put(core->dev_enc); |
|---|
| 1206 | + |
|---|
| 1291 | 1207 | return 0; |
|---|
| 1292 | 1208 | } |
|---|
| 1293 | 1209 | |
|---|
| 1294 | 1210 | static __maybe_unused int venc_runtime_suspend(struct device *dev) |
|---|
| 1295 | 1211 | { |
|---|
| 1296 | 1212 | struct venus_core *core = dev_get_drvdata(dev); |
|---|
| 1297 | | - int ret; |
|---|
| 1213 | + const struct venus_pm_ops *pm_ops = core->pm_ops; |
|---|
| 1214 | + int ret = 0; |
|---|
| 1298 | 1215 | |
|---|
| 1299 | | - if (IS_V1(core)) |
|---|
| 1300 | | - return 0; |
|---|
| 1216 | + if (pm_ops->venc_power) |
|---|
| 1217 | + ret = pm_ops->venc_power(dev, POWER_OFF); |
|---|
| 1301 | 1218 | |
|---|
| 1302 | | - ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, true); |
|---|
| 1303 | | - if (ret) |
|---|
| 1304 | | - return ret; |
|---|
| 1305 | | - |
|---|
| 1306 | | - if (IS_V4(core)) |
|---|
| 1307 | | - clk_disable_unprepare(core->core1_bus_clk); |
|---|
| 1308 | | - |
|---|
| 1309 | | - clk_disable_unprepare(core->core1_clk); |
|---|
| 1310 | | - |
|---|
| 1311 | | - return venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, false); |
|---|
| 1219 | + return ret; |
|---|
| 1312 | 1220 | } |
|---|
| 1313 | 1221 | |
|---|
| 1314 | 1222 | static __maybe_unused int venc_runtime_resume(struct device *dev) |
|---|
| 1315 | 1223 | { |
|---|
| 1316 | 1224 | struct venus_core *core = dev_get_drvdata(dev); |
|---|
| 1317 | | - int ret; |
|---|
| 1225 | + const struct venus_pm_ops *pm_ops = core->pm_ops; |
|---|
| 1226 | + int ret = 0; |
|---|
| 1318 | 1227 | |
|---|
| 1319 | | - if (IS_V1(core)) |
|---|
| 1320 | | - return 0; |
|---|
| 1228 | + if (pm_ops->venc_power) |
|---|
| 1229 | + ret = pm_ops->venc_power(dev, POWER_ON); |
|---|
| 1321 | 1230 | |
|---|
| 1322 | | - ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, true); |
|---|
| 1323 | | - if (ret) |
|---|
| 1324 | | - return ret; |
|---|
| 1325 | | - |
|---|
| 1326 | | - ret = clk_prepare_enable(core->core1_clk); |
|---|
| 1327 | | - if (ret) |
|---|
| 1328 | | - goto err_power_disable; |
|---|
| 1329 | | - |
|---|
| 1330 | | - if (IS_V4(core)) |
|---|
| 1331 | | - ret = clk_prepare_enable(core->core1_bus_clk); |
|---|
| 1332 | | - |
|---|
| 1333 | | - if (ret) |
|---|
| 1334 | | - goto err_unprepare_core1; |
|---|
| 1335 | | - |
|---|
| 1336 | | - return venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, false); |
|---|
| 1337 | | - |
|---|
| 1338 | | -err_unprepare_core1: |
|---|
| 1339 | | - clk_disable_unprepare(core->core1_clk); |
|---|
| 1340 | | -err_power_disable: |
|---|
| 1341 | | - venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, false); |
|---|
| 1342 | 1231 | return ret; |
|---|
| 1343 | 1232 | } |
|---|
| 1344 | 1233 | |
|---|