1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 4 * Copyright (C) 2017 Linaro Ltd. 5 */ 6#include <linux/clk.h> 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-mem2mem.h> 13#include <media/videobuf2-dma-sg.h> 14#include <media/v4l2-ioctl.h> 15#include <media/v4l2-event.h> 16#include <media/v4l2-ctrls.h> 17 18#include "hfi_venus_io.h" 19#include "hfi_parser.h" 20#include "core.h" 21#include "helpers.h" 22#include "venc.h" 23#include "pm_helpers.h" 24 25#define NUM_B_FRAMES_MAX 4 26 27/* 28 * Three resons to keep MPLANE formats (despite that the number of planes 29 * currently is one): 30 * - the MPLANE formats allow only one plane to be used 31 * - the downstream driver use MPLANE formats too 32 * - future firmware versions could add support for >1 planes 33 */ 34static const struct venus_format venc_formats[] = { 35 { 36 .pixfmt = V4L2_PIX_FMT_NV12, 37 .num_planes = 1, 38 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 39 }, { 40 .pixfmt = V4L2_PIX_FMT_MPEG4, 41 .num_planes = 1, 42 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 43 }, { 44 .pixfmt = V4L2_PIX_FMT_H263, 45 .num_planes = 1, 46 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 47 }, { 48 .pixfmt = V4L2_PIX_FMT_H264, 49 .num_planes = 1, 50 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 51 }, { 52 .pixfmt = V4L2_PIX_FMT_VP8, 53 .num_planes = 1, 54 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 55 }, { 56 .pixfmt = V4L2_PIX_FMT_HEVC, 57 .num_planes = 1, 58 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 59 }, 60}; 61 62static const struct venus_format * 63find_format(struct venus_inst *inst, u32 pixfmt, u32 type) 64{ 65 const struct venus_format *fmt = venc_formats; 66 unsigned int size = ARRAY_SIZE(venc_formats); 67 unsigned int i; 68 69 for (i = 0; i < size; i++) { 70 if (fmt[i].pixfmt == pixfmt) 71 break; 72 } 73 74 if (i == size || fmt[i].type != type) 75 return NULL; 76 77 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 78 !venus_helper_check_codec(inst, fmt[i].pixfmt)) 79 return NULL; 80 81 return &fmt[i]; 82} 83 84static const struct venus_format * 85find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type) 86{ 87 const struct venus_format *fmt = venc_formats; 88 unsigned int size = ARRAY_SIZE(venc_formats); 89 unsigned int i, k = 0; 90 91 if (index > size) 92 return NULL; 93 94 for (i = 0; i < size; i++) { 95 bool valid; 96 97 if (fmt[i].type != type) 98 continue; 99 valid = type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || 100 venus_helper_check_codec(inst, fmt[i].pixfmt); 101 if (k == index && valid) 102 break; 103 if (valid) 104 k++; 105 } 106 107 if (i == size) 108 return NULL; 109 110 return &fmt[i]; 111} 112 113static int venc_v4l2_to_hfi(int id, int value) 114{ 115 switch (id) { 116 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: 117 switch (value) { 118 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC: 119 default: 120 return HFI_H264_ENTROPY_CAVLC; 121 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC: 122 return HFI_H264_ENTROPY_CABAC; 123 } 124 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: 125 switch (value) { 126 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED: 127 default: 128 return HFI_H264_DB_MODE_ALL_BOUNDARY; 129 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED: 130 return HFI_H264_DB_MODE_DISABLE; 131 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: 132 return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY; 133 } 134 } 135 136 return 0; 137} 138 139static int 140venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 141{ 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)); 145 146 return 0; 147} 148 149static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) 150{ 151 struct venus_inst *inst = to_inst(file); 152 const struct venus_format *fmt; 153 154 fmt = find_format_by_index(inst, f->index, f->type); 155 156 memset(f->reserved, 0, sizeof(f->reserved)); 157 158 if (!fmt) 159 return -EINVAL; 160 161 f->pixelformat = fmt->pixfmt; 162 163 return 0; 164} 165 166static const struct venus_format * 167venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) 168{ 169 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 170 struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; 171 const struct venus_format *fmt; 172 u32 sizeimage; 173 174 memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); 175 memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); 176 177 fmt = find_format(inst, pixmp->pixelformat, f->type); 178 if (!fmt) { 179 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 180 pixmp->pixelformat = V4L2_PIX_FMT_H264; 181 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 182 pixmp->pixelformat = V4L2_PIX_FMT_NV12; 183 else 184 return NULL; 185 fmt = find_format(inst, pixmp->pixelformat, f->type); 186 if (!fmt) 187 return NULL; 188 } 189 190 pixmp->width = clamp(pixmp->width, frame_width_min(inst), 191 frame_width_max(inst)); 192 pixmp->height = clamp(pixmp->height, frame_height_min(inst), 193 frame_height_max(inst)); 194 195 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 196 pixmp->height = ALIGN(pixmp->height, 32); 197 198 pixmp->width = ALIGN(pixmp->width, 2); 199 pixmp->height = ALIGN(pixmp->height, 2); 200 201 if (pixmp->field == V4L2_FIELD_ANY) 202 pixmp->field = V4L2_FIELD_NONE; 203 pixmp->num_planes = fmt->num_planes; 204 pixmp->flags = 0; 205 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); 210 211 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 212 pfmt[0].bytesperline = ALIGN(pixmp->width, 128); 213 else 214 pfmt[0].bytesperline = 0; 215 216 return fmt; 217} 218 219static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f) 220{ 221 struct venus_inst *inst = to_inst(file); 222 223 venc_try_fmt_common(inst, f); 224 225 return 0; 226} 227 228static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) 229{ 230 struct venus_inst *inst = to_inst(file); 231 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 232 struct v4l2_pix_format_mplane orig_pixmp; 233 const struct venus_format *fmt; 234 struct v4l2_format format; 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; 244 245 orig_pixmp = *pixmp; 246 247 fmt = venc_try_fmt_common(inst, f); 248 if (!fmt) 249 return -EINVAL; 250 251 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 252 pixfmt_out = pixmp->pixelformat; 253 pixfmt_cap = inst->fmt_cap->pixfmt; 254 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 255 pixfmt_cap = pixmp->pixelformat; 256 pixfmt_out = inst->fmt_out->pixfmt; 257 } 258 259 memset(&format, 0, sizeof(format)); 260 261 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 262 format.fmt.pix_mp.pixelformat = pixfmt_out; 263 format.fmt.pix_mp.width = orig_pixmp.width; 264 format.fmt.pix_mp.height = orig_pixmp.height; 265 venc_try_fmt_common(inst, &format); 266 267 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 268 inst->out_width = format.fmt.pix_mp.width; 269 inst->out_height = format.fmt.pix_mp.height; 270 inst->colorspace = pixmp->colorspace; 271 inst->ycbcr_enc = pixmp->ycbcr_enc; 272 inst->quantization = pixmp->quantization; 273 inst->xfer_func = pixmp->xfer_func; 274 } 275 276 memset(&format, 0, sizeof(format)); 277 278 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 279 format.fmt.pix_mp.pixelformat = pixfmt_cap; 280 format.fmt.pix_mp.width = orig_pixmp.width; 281 format.fmt.pix_mp.height = orig_pixmp.height; 282 venc_try_fmt_common(inst, &format); 283 284 inst->width = format.fmt.pix_mp.width; 285 inst->height = format.fmt.pix_mp.height; 286 287 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 288 inst->fmt_out = fmt; 289 else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 290 inst->fmt_cap = fmt; 291 inst->output_buf_size = pixmp->plane_fmt[0].sizeimage; 292 } 293 294 return 0; 295} 296 297static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) 298{ 299 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 300 struct venus_inst *inst = to_inst(file); 301 const struct venus_format *fmt; 302 303 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 304 fmt = inst->fmt_cap; 305 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 306 fmt = inst->fmt_out; 307 else 308 return -EINVAL; 309 310 pixmp->pixelformat = fmt->pixfmt; 311 312 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 313 pixmp->width = inst->width; 314 pixmp->height = inst->height; 315 pixmp->colorspace = inst->colorspace; 316 pixmp->ycbcr_enc = inst->ycbcr_enc; 317 pixmp->quantization = inst->quantization; 318 pixmp->xfer_func = inst->xfer_func; 319 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 320 pixmp->width = inst->out_width; 321 pixmp->height = inst->out_height; 322 } 323 324 venc_try_fmt_common(inst, f); 325 326 return 0; 327} 328 329static int 330venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) 331{ 332 struct venus_inst *inst = to_inst(file); 333 334 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 335 return -EINVAL; 336 337 switch (s->target) { 338 case V4L2_SEL_TGT_CROP_DEFAULT: 339 case V4L2_SEL_TGT_CROP_BOUNDS: 340 s->r.width = inst->width; 341 s->r.height = inst->height; 342 break; 343 case V4L2_SEL_TGT_CROP: 344 s->r.width = inst->out_width; 345 s->r.height = inst->out_height; 346 break; 347 default: 348 return -EINVAL; 349 } 350 351 s->r.top = 0; 352 s->r.left = 0; 353 354 return 0; 355} 356 357static int 358venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) 359{ 360 struct venus_inst *inst = to_inst(file); 361 362 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 363 return -EINVAL; 364 365 switch (s->target) { 366 case V4L2_SEL_TGT_CROP: 367 if (s->r.width != inst->out_width || 368 s->r.height != inst->out_height || 369 s->r.top != 0 || s->r.left != 0) 370 return -EINVAL; 371 break; 372 default: 373 return -EINVAL; 374 } 375 376 return 0; 377} 378 379static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 380{ 381 struct venus_inst *inst = to_inst(file); 382 struct v4l2_outputparm *out = &a->parm.output; 383 struct v4l2_fract *timeperframe = &out->timeperframe; 384 u64 us_per_frame, fps; 385 386 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 387 a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 388 return -EINVAL; 389 390 memset(out->reserved, 0, sizeof(out->reserved)); 391 392 if (!timeperframe->denominator) 393 timeperframe->denominator = inst->timeperframe.denominator; 394 if (!timeperframe->numerator) 395 timeperframe->numerator = inst->timeperframe.numerator; 396 397 out->capability = V4L2_CAP_TIMEPERFRAME; 398 399 us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; 400 do_div(us_per_frame, timeperframe->denominator); 401 402 if (!us_per_frame) 403 return -EINVAL; 404 405 fps = (u64)USEC_PER_SEC; 406 do_div(fps, us_per_frame); 407 408 inst->timeperframe = *timeperframe; 409 inst->fps = fps; 410 411 return 0; 412} 413 414static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 415{ 416 struct venus_inst *inst = to_inst(file); 417 418 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 419 a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 420 return -EINVAL; 421 422 a->parm.output.capability |= V4L2_CAP_TIMEPERFRAME; 423 a->parm.output.timeperframe = inst->timeperframe; 424 425 return 0; 426} 427 428static int venc_enum_framesizes(struct file *file, void *fh, 429 struct v4l2_frmsizeenum *fsize) 430{ 431 struct venus_inst *inst = to_inst(file); 432 const struct venus_format *fmt; 433 434 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 435 436 fmt = find_format(inst, fsize->pixel_format, 437 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 438 if (!fmt) { 439 fmt = find_format(inst, fsize->pixel_format, 440 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 441 if (!fmt) 442 return -EINVAL; 443 } 444 445 if (fsize->index) 446 return -EINVAL; 447 448 fsize->stepwise.min_width = frame_width_min(inst); 449 fsize->stepwise.max_width = frame_width_max(inst); 450 fsize->stepwise.step_width = frame_width_step(inst); 451 fsize->stepwise.min_height = frame_height_min(inst); 452 fsize->stepwise.max_height = frame_height_max(inst); 453 fsize->stepwise.step_height = frame_height_step(inst); 454 455 return 0; 456} 457 458static int venc_enum_frameintervals(struct file *file, void *fh, 459 struct v4l2_frmivalenum *fival) 460{ 461 struct venus_inst *inst = to_inst(file); 462 const struct venus_format *fmt; 463 unsigned int framerate_factor = 1; 464 465 fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; 466 467 fmt = find_format(inst, fival->pixel_format, 468 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 469 if (!fmt) { 470 fmt = find_format(inst, fival->pixel_format, 471 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 472 if (!fmt) 473 return -EINVAL; 474 } 475 476 if (fival->index) 477 return -EINVAL; 478 479 if (!fival->width || !fival->height) 480 return -EINVAL; 481 482 if (fival->width > frame_width_max(inst) || 483 fival->width < frame_width_min(inst) || 484 fival->height > frame_height_max(inst) || 485 fival->height < frame_height_min(inst)) 486 return -EINVAL; 487 488 if (IS_V1(inst->core)) { 489 /* framerate is reported in 1/65535 fps unit */ 490 framerate_factor = (1 << 16); 491 } 492 493 fival->stepwise.min.numerator = 1; 494 fival->stepwise.min.denominator = frate_max(inst) / framerate_factor; 495 fival->stepwise.max.numerator = 1; 496 fival->stepwise.max.denominator = frate_min(inst) / framerate_factor; 497 fival->stepwise.step.numerator = 1; 498 fival->stepwise.step.denominator = frate_max(inst) / framerate_factor; 499 500 return 0; 501} 502 503static const struct v4l2_ioctl_ops venc_ioctl_ops = { 504 .vidioc_querycap = venc_querycap, 505 .vidioc_enum_fmt_vid_cap = venc_enum_fmt, 506 .vidioc_enum_fmt_vid_out = venc_enum_fmt, 507 .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt, 508 .vidioc_s_fmt_vid_out_mplane = venc_s_fmt, 509 .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt, 510 .vidioc_g_fmt_vid_out_mplane = venc_g_fmt, 511 .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt, 512 .vidioc_try_fmt_vid_out_mplane = venc_try_fmt, 513 .vidioc_g_selection = venc_g_selection, 514 .vidioc_s_selection = venc_s_selection, 515 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 516 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 517 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 518 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 519 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 520 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 521 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 522 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 523 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 524 .vidioc_s_parm = venc_s_parm, 525 .vidioc_g_parm = venc_g_parm, 526 .vidioc_enum_framesizes = venc_enum_framesizes, 527 .vidioc_enum_frameintervals = venc_enum_frameintervals, 528 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 529 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 530}; 531 532static int venc_set_properties(struct venus_inst *inst) 533{ 534 struct venc_controls *ctr = &inst->controls.enc; 535 struct hfi_intra_period intra_period; 536 struct hfi_framerate frate; 537 struct hfi_bitrate brate; 538 struct hfi_idr_period idrp; 539 struct hfi_quantization quant; 540 struct hfi_quantization_range quant_range; 541 u32 ptype, rate_control, bitrate; 542 u32 profile, level; 543 int ret; 544 545 ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); 546 if (ret) 547 return ret; 548 549 ptype = HFI_PROPERTY_CONFIG_FRAME_RATE; 550 frate.buffer_type = HFI_BUFFER_OUTPUT; 551 frate.framerate = inst->fps * (1 << 16); 552 553 ret = hfi_session_set_property(inst, ptype, &frate); 554 if (ret) 555 return ret; 556 557 if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) { 558 struct hfi_h264_vui_timing_info info; 559 struct hfi_h264_entropy_control entropy; 560 struct hfi_h264_db_control deblock; 561 562 ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO; 563 info.enable = 1; 564 info.fixed_framerate = 1; 565 info.time_scale = NSEC_PER_SEC; 566 567 ret = hfi_session_set_property(inst, ptype, &info); 568 if (ret) 569 return ret; 570 571 ptype = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL; 572 entropy.entropy_mode = venc_v4l2_to_hfi( 573 V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, 574 ctr->h264_entropy_mode); 575 entropy.cabac_model = HFI_H264_CABAC_MODEL_0; 576 577 ret = hfi_session_set_property(inst, ptype, &entropy); 578 if (ret) 579 return ret; 580 581 ptype = HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL; 582 deblock.mode = venc_v4l2_to_hfi( 583 V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, 584 ctr->h264_loop_filter_mode); 585 deblock.slice_alpha_offset = ctr->h264_loop_filter_alpha; 586 deblock.slice_beta_offset = ctr->h264_loop_filter_beta; 587 588 ret = hfi_session_set_property(inst, ptype, &deblock); 589 if (ret) 590 return ret; 591 } 592 593 /* IDR periodicity, n: 594 * n = 0 - only the first I-frame is IDR frame 595 * n = 1 - all I-frames will be IDR frames 596 * n > 1 - every n-th I-frame will be IDR frame 597 */ 598 ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD; 599 idrp.idr_period = 0; 600 ret = hfi_session_set_property(inst, ptype, &idrp); 601 if (ret) 602 return ret; 603 604 if (ctr->num_b_frames) { 605 u32 max_num_b_frames = NUM_B_FRAMES_MAX; 606 607 ptype = HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES; 608 ret = hfi_session_set_property(inst, ptype, &max_num_b_frames); 609 if (ret) 610 return ret; 611 } 612 613 ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD; 614 intra_period.pframes = ctr->num_p_frames; 615 intra_period.bframes = ctr->num_b_frames; 616 617 ret = hfi_session_set_property(inst, ptype, &intra_period); 618 if (ret) 619 return ret; 620 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; 631 632 ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL; 633 ret = hfi_session_set_property(inst, ptype, &rate_control); 634 if (ret) 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 } 646 647 if (!ctr->bitrate) 648 bitrate = 64000; 649 else 650 bitrate = ctr->bitrate; 651 652 ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; 653 brate.bitrate = bitrate; 654 brate.layer_id = 0; 655 656 ret = hfi_session_set_property(inst, ptype, &brate); 657 if (ret) 658 return ret; 659 660 if (!ctr->bitrate_peak) 661 bitrate *= 2; 662 else 663 bitrate = ctr->bitrate_peak; 664 665 ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE; 666 brate.bitrate = bitrate; 667 brate.layer_id = 0; 668 669 ret = hfi_session_set_property(inst, ptype, &brate); 670 if (ret) 671 return ret; 672 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; 701 level = 0; 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: 713 profile = 0; 714 level = 0; 715 break; 716 } 717 718 ret = venus_helper_set_profile_level(inst, profile, level); 719 if (ret) 720 return ret; 721 722 return 0; 723} 724 725static int venc_init_session(struct venus_inst *inst) 726{ 727 int ret; 728 729 ret = hfi_session_init(inst, inst->fmt_cap->pixfmt); 730 if (ret) 731 return ret; 732 733 ret = venus_helper_set_input_resolution(inst, inst->width, 734 inst->height); 735 if (ret) 736 goto deinit; 737 738 ret = venus_helper_set_output_resolution(inst, inst->width, 739 inst->height, 740 HFI_BUFFER_OUTPUT); 741 if (ret) 742 goto deinit; 743 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); 749 if (ret) 750 goto deinit; 751 752 ret = venc_set_properties(inst); 753 if (ret) 754 goto deinit; 755 756 return 0; 757deinit: 758 hfi_session_deinit(inst); 759 return ret; 760} 761 762static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num) 763{ 764 struct hfi_buffer_requirements bufreq; 765 int ret; 766 767 ret = venc_init_session(inst); 768 if (ret) 769 return ret; 770 771 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); 772 773 *num = bufreq.count_actual; 774 775 hfi_session_deinit(inst); 776 777 return ret; 778} 779 780static int venc_queue_setup(struct vb2_queue *q, 781 unsigned int *num_buffers, unsigned int *num_planes, 782 unsigned int sizes[], struct device *alloc_devs[]) 783{ 784 struct venus_inst *inst = vb2_get_drv_priv(q); 785 unsigned int num, min = 4; 786 int ret = 0; 787 788 if (*num_planes) { 789 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 790 *num_planes != inst->fmt_out->num_planes) 791 return -EINVAL; 792 793 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 794 *num_planes != inst->fmt_cap->num_planes) 795 return -EINVAL; 796 797 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 798 sizes[0] < inst->input_buf_size) 799 return -EINVAL; 800 801 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 802 sizes[0] < inst->output_buf_size) 803 return -EINVAL; 804 805 return 0; 806 } 807 808 switch (q->type) { 809 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 810 *num_planes = inst->fmt_out->num_planes; 811 812 ret = venc_out_num_buffers(inst, &num); 813 if (ret) 814 break; 815 816 num = max(num, min); 817 *num_buffers = max(*num_buffers, num); 818 inst->num_input_bufs = *num_buffers; 819 820 sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt, 821 inst->width, 822 inst->height); 823 inst->input_buf_size = sizes[0]; 824 break; 825 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 826 *num_planes = inst->fmt_cap->num_planes; 827 *num_buffers = max(*num_buffers, min); 828 inst->num_output_bufs = *num_buffers; 829 sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt, 830 inst->width, 831 inst->height); 832 sizes[0] = max(sizes[0], inst->output_buf_size); 833 inst->output_buf_size = sizes[0]; 834 break; 835 default: 836 ret = -EINVAL; 837 break; 838 } 839 840 return ret; 841} 842 843static int venc_verify_conf(struct venus_inst *inst) 844{ 845 enum hfi_version ver = inst->core->res->hfi_version; 846 struct hfi_buffer_requirements bufreq; 847 int ret; 848 849 if (!inst->num_input_bufs || !inst->num_output_bufs) 850 return -EINVAL; 851 852 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); 853 if (ret) 854 return ret; 855 856 if (inst->num_output_bufs < bufreq.count_actual || 857 inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) 858 return -EINVAL; 859 860 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); 861 if (ret) 862 return ret; 863 864 if (inst->num_input_bufs < bufreq.count_actual || 865 inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) 866 return -EINVAL; 867 868 return 0; 869} 870 871static int venc_start_streaming(struct vb2_queue *q, unsigned int count) 872{ 873 struct venus_inst *inst = vb2_get_drv_priv(q); 874 int ret; 875 876 mutex_lock(&inst->lock); 877 878 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 879 inst->streamon_out = 1; 880 else 881 inst->streamon_cap = 1; 882 883 if (!(inst->streamon_out & inst->streamon_cap)) { 884 mutex_unlock(&inst->lock); 885 return 0; 886 } 887 888 venus_helper_init_instance(inst); 889 890 inst->sequence_cap = 0; 891 inst->sequence_out = 0; 892 893 ret = venc_init_session(inst); 894 if (ret) 895 goto bufs_done; 896 897 ret = venus_pm_acquire_core(inst); 898 if (ret) 899 goto deinit_sess; 900 901 ret = venc_set_properties(inst); 902 if (ret) 903 goto deinit_sess; 904 905 ret = venc_verify_conf(inst); 906 if (ret) 907 goto deinit_sess; 908 909 ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, 910 inst->num_output_bufs, 0); 911 if (ret) 912 goto deinit_sess; 913 914 ret = venus_helper_vb2_start_streaming(inst); 915 if (ret) 916 goto deinit_sess; 917 918 mutex_unlock(&inst->lock); 919 920 return 0; 921 922deinit_sess: 923 hfi_session_deinit(inst); 924bufs_done: 925 venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); 926 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 927 inst->streamon_out = 0; 928 else 929 inst->streamon_cap = 0; 930 mutex_unlock(&inst->lock); 931 return ret; 932} 933 934static const struct vb2_ops venc_vb2_ops = { 935 .queue_setup = venc_queue_setup, 936 .buf_init = venus_helper_vb2_buf_init, 937 .buf_prepare = venus_helper_vb2_buf_prepare, 938 .start_streaming = venc_start_streaming, 939 .stop_streaming = venus_helper_vb2_stop_streaming, 940 .buf_queue = venus_helper_vb2_buf_queue, 941}; 942 943static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type, 944 u32 tag, u32 bytesused, u32 data_offset, u32 flags, 945 u32 hfi_flags, u64 timestamp_us) 946{ 947 struct vb2_v4l2_buffer *vbuf; 948 struct vb2_buffer *vb; 949 unsigned int type; 950 951 if (buf_type == HFI_BUFFER_INPUT) 952 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 953 else 954 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 955 956 vbuf = venus_helper_find_buf(inst, type, tag); 957 if (!vbuf) 958 return; 959 960 vbuf->flags = flags; 961 962 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 963 vb = &vbuf->vb2_buf; 964 vb2_set_plane_payload(vb, 0, bytesused + data_offset); 965 vb->planes[0].data_offset = data_offset; 966 vb->timestamp = timestamp_us * NSEC_PER_USEC; 967 vbuf->sequence = inst->sequence_cap++; 968 } else { 969 vbuf->sequence = inst->sequence_out++; 970 } 971 972 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 973} 974 975static void venc_event_notify(struct venus_inst *inst, u32 event, 976 struct hfi_event_data *data) 977{ 978 struct device *dev = inst->core->dev_enc; 979 980 if (event == EVT_SESSION_ERROR) { 981 inst->session_error = true; 982 dev_err(dev, "enc: event session error %x\n", inst->error); 983 } 984} 985 986static const struct hfi_inst_ops venc_hfi_ops = { 987 .buf_done = venc_buf_done, 988 .event_notify = venc_event_notify, 989}; 990 991static const struct v4l2_m2m_ops venc_m2m_ops = { 992 .device_run = venus_helper_m2m_device_run, 993 .job_abort = venus_helper_m2m_job_abort, 994}; 995 996static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, 997 struct vb2_queue *dst_vq) 998{ 999 struct venus_inst *inst = priv; 1000 int ret; 1001 1002 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1003 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 1004 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 1005 src_vq->ops = &venc_vb2_ops; 1006 src_vq->mem_ops = &vb2_dma_sg_memops; 1007 src_vq->drv_priv = inst; 1008 src_vq->buf_struct_size = sizeof(struct venus_buffer); 1009 src_vq->allow_zero_bytesused = 1; 1010 src_vq->min_buffers_needed = 1; 1011 src_vq->dev = inst->core->dev; 1012 if (inst->core->res->hfi_version == HFI_VERSION_1XX) 1013 src_vq->bidirectional = 1; 1014 ret = vb2_queue_init(src_vq); 1015 if (ret) 1016 return ret; 1017 1018 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1019 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 1020 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 1021 dst_vq->ops = &venc_vb2_ops; 1022 dst_vq->mem_ops = &vb2_dma_sg_memops; 1023 dst_vq->drv_priv = inst; 1024 dst_vq->buf_struct_size = sizeof(struct venus_buffer); 1025 dst_vq->allow_zero_bytesused = 1; 1026 dst_vq->min_buffers_needed = 1; 1027 dst_vq->dev = inst->core->dev; 1028 return vb2_queue_init(dst_vq); 1029} 1030 1031static void venc_inst_init(struct venus_inst *inst) 1032{ 1033 inst->fmt_cap = &venc_formats[2]; 1034 inst->fmt_out = &venc_formats[0]; 1035 inst->width = 1280; 1036 inst->height = ALIGN(720, 32); 1037 inst->out_width = 1280; 1038 inst->out_height = 720; 1039 inst->fps = 15; 1040 inst->timeperframe.numerator = 1; 1041 inst->timeperframe.denominator = 15; 1042 inst->hfi_codec = HFI_VIDEO_CODEC_H264; 1043} 1044 1045static int venc_open(struct file *file) 1046{ 1047 struct venus_core *core = video_drvdata(file); 1048 struct venus_inst *inst; 1049 int ret; 1050 1051 inst = kzalloc(sizeof(*inst), GFP_KERNEL); 1052 if (!inst) 1053 return -ENOMEM; 1054 1055 INIT_LIST_HEAD(&inst->dpbbufs); 1056 INIT_LIST_HEAD(&inst->registeredbufs); 1057 INIT_LIST_HEAD(&inst->internalbufs); 1058 INIT_LIST_HEAD(&inst->list); 1059 mutex_init(&inst->lock); 1060 1061 inst->core = core; 1062 inst->session_type = VIDC_SESSION_TYPE_ENC; 1063 inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT; 1064 inst->core_acquired = false; 1065 1066 venus_helper_init_instance(inst); 1067 1068 ret = pm_runtime_get_sync(core->dev_enc); 1069 if (ret < 0) 1070 goto err_put_sync; 1071 1072 ret = venc_ctrl_init(inst); 1073 if (ret) 1074 goto err_put_sync; 1075 1076 ret = hfi_session_create(inst, &venc_hfi_ops); 1077 if (ret) 1078 goto err_ctrl_deinit; 1079 1080 venc_inst_init(inst); 1081 1082 /* 1083 * create m2m device for every instance, the m2m context scheduling 1084 * is made by firmware side so we do not need to care about. 1085 */ 1086 inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops); 1087 if (IS_ERR(inst->m2m_dev)) { 1088 ret = PTR_ERR(inst->m2m_dev); 1089 goto err_session_destroy; 1090 } 1091 1092 inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init); 1093 if (IS_ERR(inst->m2m_ctx)) { 1094 ret = PTR_ERR(inst->m2m_ctx); 1095 goto err_m2m_release; 1096 } 1097 1098 v4l2_fh_init(&inst->fh, core->vdev_enc); 1099 1100 inst->fh.ctrl_handler = &inst->ctrl_handler; 1101 v4l2_fh_add(&inst->fh); 1102 inst->fh.m2m_ctx = inst->m2m_ctx; 1103 file->private_data = &inst->fh; 1104 1105 return 0; 1106 1107err_m2m_release: 1108 v4l2_m2m_release(inst->m2m_dev); 1109err_session_destroy: 1110 hfi_session_destroy(inst); 1111err_ctrl_deinit: 1112 venc_ctrl_deinit(inst); 1113err_put_sync: 1114 pm_runtime_put_sync(core->dev_enc); 1115 kfree(inst); 1116 return ret; 1117} 1118 1119static int venc_close(struct file *file) 1120{ 1121 struct venus_inst *inst = to_inst(file); 1122 1123 v4l2_m2m_ctx_release(inst->m2m_ctx); 1124 v4l2_m2m_release(inst->m2m_dev); 1125 venc_ctrl_deinit(inst); 1126 hfi_session_destroy(inst); 1127 mutex_destroy(&inst->lock); 1128 v4l2_fh_del(&inst->fh); 1129 v4l2_fh_exit(&inst->fh); 1130 1131 pm_runtime_put_sync(inst->core->dev_enc); 1132 1133 kfree(inst); 1134 return 0; 1135} 1136 1137static const struct v4l2_file_operations venc_fops = { 1138 .owner = THIS_MODULE, 1139 .open = venc_open, 1140 .release = venc_close, 1141 .unlocked_ioctl = video_ioctl2, 1142 .poll = v4l2_m2m_fop_poll, 1143 .mmap = v4l2_m2m_fop_mmap, 1144}; 1145 1146static int venc_probe(struct platform_device *pdev) 1147{ 1148 struct device *dev = &pdev->dev; 1149 struct video_device *vdev; 1150 struct venus_core *core; 1151 int ret; 1152 1153 if (!dev->parent) 1154 return -EPROBE_DEFER; 1155 1156 core = dev_get_drvdata(dev->parent); 1157 if (!core) 1158 return -EPROBE_DEFER; 1159 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 } 1167 1168 vdev = video_device_alloc(); 1169 if (!vdev) 1170 return -ENOMEM; 1171 1172 strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name)); 1173 vdev->release = video_device_release; 1174 vdev->fops = &venc_fops; 1175 vdev->ioctl_ops = &venc_ioctl_ops; 1176 vdev->vfl_dir = VFL_DIR_M2M; 1177 vdev->v4l2_dev = &core->v4l2_dev; 1178 vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 1179 1180 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 1181 if (ret) 1182 goto err_vdev_release; 1183 1184 core->vdev_enc = vdev; 1185 core->dev_enc = dev; 1186 1187 video_set_drvdata(vdev, core); 1188 pm_runtime_enable(dev); 1189 1190 return 0; 1191 1192err_vdev_release: 1193 video_device_release(vdev); 1194 return ret; 1195} 1196 1197static int venc_remove(struct platform_device *pdev) 1198{ 1199 struct venus_core *core = dev_get_drvdata(pdev->dev.parent); 1200 1201 video_unregister_device(core->vdev_enc); 1202 pm_runtime_disable(core->dev_enc); 1203 1204 if (core->pm_ops->venc_put) 1205 core->pm_ops->venc_put(core->dev_enc); 1206 1207 return 0; 1208} 1209 1210static __maybe_unused int venc_runtime_suspend(struct device *dev) 1211{ 1212 struct venus_core *core = dev_get_drvdata(dev); 1213 const struct venus_pm_ops *pm_ops = core->pm_ops; 1214 int ret = 0; 1215 1216 if (pm_ops->venc_power) 1217 ret = pm_ops->venc_power(dev, POWER_OFF); 1218 1219 return ret; 1220} 1221 1222static __maybe_unused int venc_runtime_resume(struct device *dev) 1223{ 1224 struct venus_core *core = dev_get_drvdata(dev); 1225 const struct venus_pm_ops *pm_ops = core->pm_ops; 1226 int ret = 0; 1227 1228 if (pm_ops->venc_power) 1229 ret = pm_ops->venc_power(dev, POWER_ON); 1230 1231 return ret; 1232} 1233 1234static const struct dev_pm_ops venc_pm_ops = { 1235 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1236 pm_runtime_force_resume) 1237 SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL) 1238}; 1239 1240static const struct of_device_id venc_dt_match[] = { 1241 { .compatible = "venus-encoder" }, 1242 { } 1243}; 1244MODULE_DEVICE_TABLE(of, venc_dt_match); 1245 1246static struct platform_driver qcom_venus_enc_driver = { 1247 .probe = venc_probe, 1248 .remove = venc_remove, 1249 .driver = { 1250 .name = "qcom-venus-encoder", 1251 .of_match_table = venc_dt_match, 1252 .pm = &venc_pm_ops, 1253 }, 1254}; 1255module_platform_driver(qcom_venus_enc_driver); 1256 1257MODULE_ALIAS("platform:qcom-venus-encoder"); 1258MODULE_DESCRIPTION("Qualcomm Venus video encoder driver"); 1259MODULE_LICENSE("GPL v2"); 1260