1348 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2020-2021 NXP4 */5 6#include <linux/init.h>7#include <linux/interconnect.h>8#include <linux/ioctl.h>9#include <linux/list.h>10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/delay.h>13#include <linux/videodev2.h>14#include <linux/ktime.h>15#include <linux/rational.h>16#include <linux/vmalloc.h>17#include <media/v4l2-device.h>18#include <media/v4l2-event.h>19#include <media/v4l2-mem2mem.h>20#include <media/v4l2-ioctl.h>21#include <media/videobuf2-v4l2.h>22#include <media/videobuf2-dma-contig.h>23#include <media/videobuf2-vmalloc.h>24#include "vpu.h"25#include "vpu_defs.h"26#include "vpu_core.h"27#include "vpu_helpers.h"28#include "vpu_v4l2.h"29#include "vpu_cmds.h"30#include "vpu_rpc.h"31 32#define VENC_OUTPUT_ENABLE BIT(0)33#define VENC_CAPTURE_ENABLE BIT(1)34#define VENC_ENABLE_MASK (VENC_OUTPUT_ENABLE | VENC_CAPTURE_ENABLE)35#define VENC_MAX_BUF_CNT 836#define VENC_MIN_BUFFER_OUT 637#define VENC_MIN_BUFFER_CAP 638 39struct venc_t {40 struct vpu_encode_params params;41 u32 request_key_frame;42 u32 input_ready;43 u32 cpb_size;44 bool bitrate_change;45 46 struct vpu_buffer enc[VENC_MAX_BUF_CNT];47 struct vpu_buffer ref[VENC_MAX_BUF_CNT];48 struct vpu_buffer act[VENC_MAX_BUF_CNT];49 struct list_head frames;50 u32 frame_count;51 u32 encode_count;52 u32 ready_count;53 u32 enable;54 u32 stopped;55 56 u32 skipped_count;57 u32 skipped_bytes;58 59 wait_queue_head_t wq;60};61 62struct venc_frame_t {63 struct list_head list;64 struct vpu_enc_pic_info info;65 u32 bytesused;66 s64 timestamp;67};68 69static const struct vpu_format venc_formats[] = {70 {71 .pixfmt = V4L2_PIX_FMT_NV12M,72 .mem_planes = 2,73 .comp_planes = 2,74 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,75 .sibling = V4L2_PIX_FMT_NV12,76 },77 {78 .pixfmt = V4L2_PIX_FMT_NV12,79 .mem_planes = 1,80 .comp_planes = 2,81 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,82 .sibling = V4L2_PIX_FMT_NV12M,83 },84 {85 .pixfmt = V4L2_PIX_FMT_H264,86 .mem_planes = 1,87 .comp_planes = 1,88 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,89 .flags = V4L2_FMT_FLAG_COMPRESSED90 },91 {0, 0, 0, 0},92};93 94static int venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)95{96 strscpy(cap->driver, "amphion-vpu", sizeof(cap->driver));97 strscpy(cap->card, "amphion vpu encoder", sizeof(cap->card));98 strscpy(cap->bus_info, "platform: amphion-vpu", sizeof(cap->bus_info));99 100 return 0;101}102 103static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)104{105 struct vpu_inst *inst = to_inst(file);106 const struct vpu_format *fmt;107 108 memset(f->reserved, 0, sizeof(f->reserved));109 fmt = vpu_helper_enum_format(inst, f->type, f->index);110 if (!fmt)111 return -EINVAL;112 113 f->pixelformat = fmt->pixfmt;114 f->flags = fmt->flags;115 116 return 0;117}118 119static int venc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize)120{121 struct vpu_inst *inst = to_inst(file);122 const struct vpu_core_resources *res;123 124 if (!fsize || fsize->index)125 return -EINVAL;126 127 if (!vpu_helper_find_format(inst, 0, fsize->pixel_format))128 return -EINVAL;129 130 res = vpu_get_resource(inst);131 if (!res)132 return -EINVAL;133 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;134 fsize->stepwise.max_width = res->max_width;135 fsize->stepwise.max_height = res->max_height;136 fsize->stepwise.min_width = res->min_width;137 fsize->stepwise.min_height = res->min_height;138 fsize->stepwise.step_width = res->step_width;139 fsize->stepwise.step_height = res->step_height;140 141 return 0;142}143 144static int venc_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *fival)145{146 struct vpu_inst *inst = to_inst(file);147 const struct vpu_core_resources *res;148 149 if (!fival || fival->index)150 return -EINVAL;151 152 if (!vpu_helper_find_format(inst, 0, fival->pixel_format))153 return -EINVAL;154 155 if (!fival->width || !fival->height)156 return -EINVAL;157 158 res = vpu_get_resource(inst);159 if (!res)160 return -EINVAL;161 if (fival->width < res->min_width || fival->width > res->max_width ||162 fival->height < res->min_height || fival->height > res->max_height)163 return -EINVAL;164 165 fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;166 fival->stepwise.min.numerator = 1;167 fival->stepwise.min.denominator = USHRT_MAX;168 fival->stepwise.max.numerator = USHRT_MAX;169 fival->stepwise.max.denominator = 1;170 fival->stepwise.step.numerator = 1;171 fival->stepwise.step.denominator = 1;172 173 return 0;174}175 176static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)177{178 struct vpu_inst *inst = to_inst(file);179 struct venc_t *venc = inst->priv;180 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;181 struct vpu_format *cur_fmt;182 int i;183 184 cur_fmt = vpu_get_format(inst, f->type);185 186 pixmp->pixelformat = cur_fmt->pixfmt;187 pixmp->num_planes = cur_fmt->mem_planes;188 pixmp->width = cur_fmt->width;189 pixmp->height = cur_fmt->height;190 pixmp->field = cur_fmt->field;191 pixmp->flags = cur_fmt->flags;192 for (i = 0; i < pixmp->num_planes; i++) {193 pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i];194 pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(cur_fmt, i);195 }196 197 f->fmt.pix_mp.colorspace = venc->params.color.primaries;198 f->fmt.pix_mp.xfer_func = venc->params.color.transfer;199 f->fmt.pix_mp.ycbcr_enc = venc->params.color.matrix;200 f->fmt.pix_mp.quantization = venc->params.color.full_range;201 202 return 0;203}204 205static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f)206{207 struct vpu_inst *inst = to_inst(file);208 struct vpu_format fmt;209 210 vpu_try_fmt_common(inst, f, &fmt);211 212 return 0;213}214 215static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)216{217 struct vpu_inst *inst = to_inst(file);218 struct vpu_format fmt;219 struct vpu_format *cur_fmt;220 struct vb2_queue *q;221 struct venc_t *venc = inst->priv;222 struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;223 224 q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type);225 if (!q)226 return -EINVAL;227 if (vb2_is_busy(q))228 return -EBUSY;229 230 if (vpu_try_fmt_common(inst, f, &fmt))231 return -EINVAL;232 233 cur_fmt = vpu_get_format(inst, f->type);234 235 memcpy(cur_fmt, &fmt, sizeof(*cur_fmt));236 237 if (V4L2_TYPE_IS_OUTPUT(f->type)) {238 venc->params.input_format = cur_fmt->pixfmt;239 venc->params.src_stride = cur_fmt->bytesperline[0];240 venc->params.src_width = cur_fmt->width;241 venc->params.src_height = cur_fmt->height;242 venc->params.crop.left = 0;243 venc->params.crop.top = 0;244 venc->params.crop.width = cur_fmt->width;245 venc->params.crop.height = cur_fmt->height;246 } else {247 venc->params.codec_format = cur_fmt->pixfmt;248 venc->params.out_width = cur_fmt->width;249 venc->params.out_height = cur_fmt->height;250 }251 252 if (V4L2_TYPE_IS_OUTPUT(f->type)) {253 venc->params.color.primaries = pix_mp->colorspace;254 venc->params.color.transfer = pix_mp->xfer_func;255 venc->params.color.matrix = pix_mp->ycbcr_enc;256 venc->params.color.full_range = pix_mp->quantization;257 }258 259 pix_mp->colorspace = venc->params.color.primaries;260 pix_mp->xfer_func = venc->params.color.transfer;261 pix_mp->ycbcr_enc = venc->params.color.matrix;262 pix_mp->quantization = venc->params.color.full_range;263 264 return 0;265}266 267static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm)268{269 struct vpu_inst *inst = to_inst(file);270 struct venc_t *venc = inst->priv;271 struct v4l2_fract *timeperframe;272 273 if (!parm)274 return -EINVAL;275 276 if (!V4L2_TYPE_IS_OUTPUT(parm->type))277 return -EINVAL;278 279 if (!vpu_helper_check_type(inst, parm->type))280 return -EINVAL;281 282 timeperframe = &parm->parm.capture.timeperframe;283 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;284 parm->parm.capture.readbuffers = 0;285 timeperframe->numerator = venc->params.frame_rate.numerator;286 timeperframe->denominator = venc->params.frame_rate.denominator;287 288 return 0;289}290 291static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *parm)292{293 struct vpu_inst *inst = to_inst(file);294 struct venc_t *venc = inst->priv;295 struct v4l2_fract *timeperframe;296 unsigned long n, d;297 298 if (!parm)299 return -EINVAL;300 301 if (!V4L2_TYPE_IS_OUTPUT(parm->type))302 return -EINVAL;303 304 if (!vpu_helper_check_type(inst, parm->type))305 return -EINVAL;306 307 timeperframe = &parm->parm.capture.timeperframe;308 if (!timeperframe->numerator)309 timeperframe->numerator = venc->params.frame_rate.numerator;310 if (!timeperframe->denominator)311 timeperframe->denominator = venc->params.frame_rate.denominator;312 313 venc->params.frame_rate.numerator = timeperframe->numerator;314 venc->params.frame_rate.denominator = timeperframe->denominator;315 316 rational_best_approximation(venc->params.frame_rate.numerator,317 venc->params.frame_rate.denominator,318 venc->params.frame_rate.numerator,319 venc->params.frame_rate.denominator,320 &n, &d);321 venc->params.frame_rate.numerator = n;322 venc->params.frame_rate.denominator = d;323 324 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;325 memset(parm->parm.capture.reserved, 0, sizeof(parm->parm.capture.reserved));326 327 return 0;328}329 330static int venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)331{332 struct vpu_inst *inst = to_inst(file);333 struct venc_t *venc = inst->priv;334 335 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)336 return -EINVAL;337 338 switch (s->target) {339 case V4L2_SEL_TGT_CROP_DEFAULT:340 case V4L2_SEL_TGT_CROP_BOUNDS:341 s->r.left = 0;342 s->r.top = 0;343 s->r.width = inst->out_format.width;344 s->r.height = inst->out_format.height;345 break;346 case V4L2_SEL_TGT_CROP:347 s->r = venc->params.crop;348 break;349 default:350 return -EINVAL;351 }352 353 return 0;354}355 356static int venc_valid_crop(struct venc_t *venc, const struct vpu_core_resources *res)357{358 struct v4l2_rect *rect = NULL;359 u32 min_width;360 u32 min_height;361 u32 src_width;362 u32 src_height;363 364 rect = &venc->params.crop;365 min_width = res->min_width;366 min_height = res->min_height;367 src_width = venc->params.src_width;368 src_height = venc->params.src_height;369 370 if (rect->width == 0 || rect->height == 0)371 return -EINVAL;372 if (rect->left > src_width - min_width || rect->top > src_height - min_height)373 return -EINVAL;374 375 rect->width = min(rect->width, src_width - rect->left);376 rect->width = max_t(u32, rect->width, min_width);377 378 rect->height = min(rect->height, src_height - rect->top);379 rect->height = max_t(u32, rect->height, min_height);380 381 return 0;382}383 384static int venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s)385{386 struct vpu_inst *inst = to_inst(file);387 const struct vpu_core_resources *res;388 struct venc_t *venc = inst->priv;389 390 res = vpu_get_resource(inst);391 if (!res)392 return -EINVAL;393 394 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)395 return -EINVAL;396 if (s->target != V4L2_SEL_TGT_CROP)397 return -EINVAL;398 399 venc->params.crop.left = ALIGN(s->r.left, res->step_width);400 venc->params.crop.top = ALIGN(s->r.top, res->step_height);401 venc->params.crop.width = ALIGN(s->r.width, res->step_width);402 venc->params.crop.height = ALIGN(s->r.height, res->step_height);403 if (venc_valid_crop(venc, res)) {404 venc->params.crop.left = 0;405 venc->params.crop.top = 0;406 venc->params.crop.width = venc->params.src_width;407 venc->params.crop.height = venc->params.src_height;408 }409 410 inst->crop = venc->params.crop;411 412 return 0;413}414 415static int venc_drain(struct vpu_inst *inst)416{417 struct venc_t *venc = inst->priv;418 int ret;419 420 if (!inst->fh.m2m_ctx)421 return 0;422 423 if (inst->state != VPU_CODEC_STATE_DRAIN)424 return 0;425 426 if (!vpu_is_source_empty(inst))427 return 0;428 429 if (!venc->input_ready)430 return 0;431 432 venc->input_ready = false;433 vpu_trace(inst->dev, "[%d]\n", inst->id);434 ret = vpu_session_stop(inst);435 if (ret)436 return ret;437 inst->state = VPU_CODEC_STATE_STOP;438 wake_up_all(&venc->wq);439 440 return 0;441}442 443static int venc_request_eos(struct vpu_inst *inst)444{445 inst->state = VPU_CODEC_STATE_DRAIN;446 venc_drain(inst);447 448 return 0;449}450 451static int venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd)452{453 struct vpu_inst *inst = to_inst(file);454 int ret;455 456 ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);457 if (ret)458 return ret;459 460 vpu_inst_lock(inst);461 if (cmd->cmd == V4L2_ENC_CMD_STOP) {462 if (inst->state == VPU_CODEC_STATE_DEINIT)463 vpu_set_last_buffer_dequeued(inst, true);464 else465 venc_request_eos(inst);466 }467 vpu_inst_unlock(inst);468 469 return 0;470}471 472static int venc_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)473{474 switch (sub->type) {475 case V4L2_EVENT_EOS:476 return v4l2_event_subscribe(fh, sub, 0, NULL);477 case V4L2_EVENT_CTRL:478 return v4l2_ctrl_subscribe_event(fh, sub);479 default:480 return -EINVAL;481 }482}483 484static const struct v4l2_ioctl_ops venc_ioctl_ops = {485 .vidioc_querycap = venc_querycap,486 .vidioc_enum_fmt_vid_cap = venc_enum_fmt,487 .vidioc_enum_fmt_vid_out = venc_enum_fmt,488 .vidioc_enum_framesizes = venc_enum_framesizes,489 .vidioc_enum_frameintervals = venc_enum_frameintervals,490 .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt,491 .vidioc_g_fmt_vid_out_mplane = venc_g_fmt,492 .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt,493 .vidioc_try_fmt_vid_out_mplane = venc_try_fmt,494 .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt,495 .vidioc_s_fmt_vid_out_mplane = venc_s_fmt,496 .vidioc_g_parm = venc_g_parm,497 .vidioc_s_parm = venc_s_parm,498 .vidioc_g_selection = venc_g_selection,499 .vidioc_s_selection = venc_s_selection,500 .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,501 .vidioc_encoder_cmd = venc_encoder_cmd,502 .vidioc_subscribe_event = venc_subscribe_event,503 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,504 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,505 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,506 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,507 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,508 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,509 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,510 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,511 .vidioc_streamon = v4l2_m2m_ioctl_streamon,512 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,513};514 515static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)516{517 struct vpu_inst *inst = ctrl_to_inst(ctrl);518 struct venc_t *venc = inst->priv;519 int ret = 0;520 521 switch (ctrl->id) {522 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:523 venc->params.profile = ctrl->val;524 break;525 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:526 venc->params.level = ctrl->val;527 break;528 case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:529 venc->params.rc_enable = ctrl->val;530 break;531 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:532 venc->params.rc_mode = ctrl->val;533 break;534 case V4L2_CID_MPEG_VIDEO_BITRATE:535 if (ctrl->val != venc->params.bitrate)536 venc->bitrate_change = true;537 venc->params.bitrate = ctrl->val;538 break;539 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:540 venc->params.bitrate_max = ctrl->val;541 break;542 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:543 venc->params.gop_length = ctrl->val;544 break;545 case V4L2_CID_MPEG_VIDEO_B_FRAMES:546 venc->params.bframes = ctrl->val;547 break;548 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:549 venc->params.i_frame_qp = ctrl->val;550 break;551 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:552 venc->params.p_frame_qp = ctrl->val;553 break;554 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:555 venc->params.b_frame_qp = ctrl->val;556 break;557 case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:558 venc->request_key_frame = 1;559 break;560 case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:561 venc->cpb_size = ctrl->val * 1024;562 break;563 case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:564 venc->params.sar.enable = ctrl->val;565 break;566 case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:567 venc->params.sar.idc = ctrl->val;568 break;569 case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:570 venc->params.sar.width = ctrl->val;571 break;572 case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:573 venc->params.sar.height = ctrl->val;574 break;575 case V4L2_CID_MPEG_VIDEO_HEADER_MODE:576 break;577 default:578 ret = -EINVAL;579 break;580 }581 582 return ret;583}584 585static const struct v4l2_ctrl_ops venc_ctrl_ops = {586 .s_ctrl = venc_op_s_ctrl,587 .g_volatile_ctrl = vpu_helper_g_volatile_ctrl,588};589 590static int venc_ctrl_init(struct vpu_inst *inst)591{592 struct v4l2_ctrl *ctrl;593 int ret;594 595 ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20);596 if (ret)597 return ret;598 599 v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,600 V4L2_CID_MPEG_VIDEO_H264_PROFILE,601 V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,602 ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |603 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |604 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),605 V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);606 607 v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,608 V4L2_CID_MPEG_VIDEO_H264_LEVEL,609 V4L2_MPEG_VIDEO_H264_LEVEL_5_1,610 0x0,611 V4L2_MPEG_VIDEO_H264_LEVEL_4_0);612 613 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,614 V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1);615 616 v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,617 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,618 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,619 ~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |620 (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)),621 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);622 623 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,624 V4L2_CID_MPEG_VIDEO_BITRATE,625 BITRATE_MIN,626 BITRATE_MAX,627 BITRATE_STEP,628 BITRATE_DEFAULT);629 630 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,631 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,632 BITRATE_MIN, BITRATE_MAX,633 BITRATE_STEP,634 BITRATE_DEFAULT_PEAK);635 636 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,637 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 8000, 1, 30);638 639 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,640 V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 4, 1, 0);641 642 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,643 V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 26);644 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,645 V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 28);646 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,647 V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, 1, 51, 1, 30);648 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,649 V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, 0, 0, 0, 0);650 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,651 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2);652 if (ctrl)653 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;654 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,655 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 2);656 if (ctrl)657 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;658 659 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,660 V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, 64, 10240, 1, 1024);661 662 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,663 V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, 0, 1, 1, 1);664 v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,665 V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,666 V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,667 0x0,668 V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1);669 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,670 V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,671 0, USHRT_MAX, 1, 1);672 v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,673 V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,674 0, USHRT_MAX, 1, 1);675 v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,676 V4L2_CID_MPEG_VIDEO_HEADER_MODE,677 V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,678 ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),679 V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);680 681 v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,682 V4L2_CID_MPEG_VIDEO_AVERAGE_QP, 0, 51, 1, 0);683 684 if (inst->ctrl_handler.error) {685 ret = inst->ctrl_handler.error;686 v4l2_ctrl_handler_free(&inst->ctrl_handler);687 return ret;688 }689 690 ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);691 if (ret) {692 dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);693 v4l2_ctrl_handler_free(&inst->ctrl_handler);694 return ret;695 }696 697 return 0;698}699 700static bool venc_check_ready(struct vpu_inst *inst, unsigned int type)701{702 struct venc_t *venc = inst->priv;703 704 if (V4L2_TYPE_IS_OUTPUT(type)) {705 if (vpu_helper_get_free_space(inst) < venc->cpb_size)706 return false;707 return venc->input_ready;708 }709 710 if (list_empty(&venc->frames))711 return false;712 return true;713}714 715static u32 venc_get_enable_mask(u32 type)716{717 if (V4L2_TYPE_IS_OUTPUT(type))718 return VENC_OUTPUT_ENABLE;719 else720 return VENC_CAPTURE_ENABLE;721}722 723static void venc_set_enable(struct venc_t *venc, u32 type, int enable)724{725 u32 mask = venc_get_enable_mask(type);726 727 if (enable)728 venc->enable |= mask;729 else730 venc->enable &= ~mask;731}732 733static u32 venc_get_enable(struct venc_t *venc, u32 type)734{735 return venc->enable & venc_get_enable_mask(type);736}737 738static void venc_input_done(struct vpu_inst *inst)739{740 struct venc_t *venc = inst->priv;741 742 vpu_inst_lock(inst);743 venc->input_ready = true;744 vpu_process_output_buffer(inst);745 if (inst->state == VPU_CODEC_STATE_DRAIN)746 venc_drain(inst);747 vpu_inst_unlock(inst);748}749 750/*751 * It's hardware limitation, that there may be several bytes752 * redundant data at the beginning of frame.753 * For android platform, the redundant data may cause cts test fail754 * So driver will strip them755 */756static int venc_precheck_encoded_frame(struct vpu_inst *inst, struct venc_frame_t *frame)757{758 struct venc_t *venc;759 int skipped;760 761 if (!frame || !frame->bytesused)762 return -EINVAL;763 764 venc = inst->priv;765 skipped = vpu_helper_find_startcode(&inst->stream_buffer,766 inst->cap_format.pixfmt,767 frame->info.wptr - inst->stream_buffer.phys,768 frame->bytesused);769 if (skipped > 0) {770 frame->bytesused -= skipped;771 frame->info.wptr = vpu_helper_step_walk(&inst->stream_buffer,772 frame->info.wptr, skipped);773 venc->skipped_bytes += skipped;774 venc->skipped_count++;775 }776 777 return 0;778}779 780static int venc_get_one_encoded_frame(struct vpu_inst *inst,781 struct venc_frame_t *frame,782 struct vb2_v4l2_buffer *vbuf)783{784 struct venc_t *venc = inst->priv;785 struct vb2_v4l2_buffer *src_buf;786 787 if (!vbuf)788 return -EAGAIN;789 790 src_buf = vpu_find_buf_by_sequence(inst, inst->out_format.type, frame->info.frame_id);791 if (src_buf) {792 v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);793 vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);794 v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, src_buf);795 v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);796 } else {797 vbuf->vb2_buf.timestamp = frame->info.timestamp;798 }799 if (!venc_get_enable(inst->priv, vbuf->vb2_buf.type)) {800 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);801 return 0;802 }803 if (frame->bytesused > vbuf->vb2_buf.planes[0].length) {804 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);805 return -ENOMEM;806 }807 808 venc_precheck_encoded_frame(inst, frame);809 810 if (frame->bytesused) {811 u32 rptr = frame->info.wptr;812 void *dst = vb2_plane_vaddr(&vbuf->vb2_buf, 0);813 814 vpu_helper_copy_from_stream_buffer(&inst->stream_buffer,815 &rptr, frame->bytesused, dst);816 vpu_iface_update_stream_buffer(inst, rptr, 0);817 }818 vb2_set_plane_payload(&vbuf->vb2_buf, 0, frame->bytesused);819 vbuf->sequence = frame->info.frame_id;820 vbuf->field = inst->cap_format.field;821 vbuf->flags |= frame->info.pic_type;822 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);823 vpu_set_buffer_average_qp(vbuf, frame->info.average_qp);824 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);825 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);826 venc->ready_count++;827 828 if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)829 dev_dbg(inst->dev, "[%d][%d]key frame\n", inst->id, frame->info.frame_id);830 831 return 0;832}833 834static int venc_get_encoded_frames(struct vpu_inst *inst)835{836 struct venc_t *venc;837 struct venc_frame_t *frame;838 struct venc_frame_t *tmp;839 840 if (!inst->fh.m2m_ctx)841 return 0;842 venc = inst->priv;843 list_for_each_entry_safe(frame, tmp, &venc->frames, list) {844 if (venc_get_one_encoded_frame(inst, frame,845 v4l2_m2m_dst_buf_remove(inst->fh.m2m_ctx)))846 break;847 list_del_init(&frame->list);848 vfree(frame);849 }850 851 return 0;852}853 854static int venc_frame_encoded(struct vpu_inst *inst, void *arg)855{856 struct vpu_enc_pic_info *info = arg;857 struct venc_frame_t *frame;858 struct venc_t *venc;859 int ret = 0;860 861 if (!info)862 return -EINVAL;863 venc = inst->priv;864 frame = vzalloc(sizeof(*frame));865 if (!frame)866 return -ENOMEM;867 868 memcpy(&frame->info, info, sizeof(frame->info));869 frame->bytesused = info->frame_size;870 871 vpu_inst_lock(inst);872 list_add_tail(&frame->list, &venc->frames);873 venc->encode_count++;874 venc_get_encoded_frames(inst);875 vpu_inst_unlock(inst);876 877 return ret;878}879 880static void venc_set_last_buffer_dequeued(struct vpu_inst *inst)881{882 struct venc_t *venc = inst->priv;883 884 if (venc->stopped && list_empty(&venc->frames))885 vpu_set_last_buffer_dequeued(inst, true);886}887 888static void venc_stop_done(struct vpu_inst *inst)889{890 struct venc_t *venc = inst->priv;891 892 vpu_inst_lock(inst);893 venc->stopped = true;894 venc_set_last_buffer_dequeued(inst);895 vpu_inst_unlock(inst);896 897 wake_up_all(&venc->wq);898}899 900static void venc_event_notify(struct vpu_inst *inst, u32 event, void *data)901{902}903 904static void venc_release(struct vpu_inst *inst)905{906}907 908static void venc_cleanup(struct vpu_inst *inst)909{910 struct venc_t *venc;911 912 if (!inst)913 return;914 915 venc = inst->priv;916 vfree(venc);917 inst->priv = NULL;918 vfree(inst);919}920 921static int venc_start_session(struct vpu_inst *inst, u32 type)922{923 struct venc_t *venc = inst->priv;924 int stream_buffer_size;925 int ret;926 927 venc_set_enable(venc, type, 1);928 if ((venc->enable & VENC_ENABLE_MASK) != VENC_ENABLE_MASK)929 return 0;930 931 vpu_iface_init_instance(inst);932 stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core);933 if (stream_buffer_size > 0) {934 inst->stream_buffer.length = max_t(u32, stream_buffer_size, venc->cpb_size * 3);935 ret = vpu_alloc_dma(inst->core, &inst->stream_buffer);936 if (ret)937 goto error;938 939 inst->use_stream_buffer = true;940 vpu_iface_config_stream_buffer(inst, &inst->stream_buffer);941 }942 943 ret = vpu_iface_set_encode_params(inst, &venc->params, 0);944 if (ret)945 goto error;946 ret = vpu_session_configure_codec(inst);947 if (ret)948 goto error;949 950 inst->state = VPU_CODEC_STATE_CONFIGURED;951 /*vpu_iface_config_memory_resource*/952 953 /*config enc expert mode parameter*/954 ret = vpu_iface_set_encode_params(inst, &venc->params, 1);955 if (ret)956 goto error;957 958 ret = vpu_session_start(inst);959 if (ret)960 goto error;961 inst->state = VPU_CODEC_STATE_STARTED;962 963 venc->bitrate_change = false;964 venc->input_ready = true;965 venc->frame_count = 0;966 venc->encode_count = 0;967 venc->ready_count = 0;968 venc->stopped = false;969 vpu_process_output_buffer(inst);970 if (venc->frame_count == 0)971 dev_err(inst->dev, "[%d] there is no input when starting\n", inst->id);972 973 return 0;974error:975 venc_set_enable(venc, type, 0);976 inst->state = VPU_CODEC_STATE_DEINIT;977 978 vpu_free_dma(&inst->stream_buffer);979 return ret;980}981 982static void venc_cleanup_mem_resource(struct vpu_inst *inst)983{984 struct venc_t *venc;985 u32 i;986 987 venc = inst->priv;988 989 for (i = 0; i < ARRAY_SIZE(venc->enc); i++)990 vpu_free_dma(&venc->enc[i]);991 for (i = 0; i < ARRAY_SIZE(venc->ref); i++)992 vpu_free_dma(&venc->ref[i]);993}994 995static void venc_request_mem_resource(struct vpu_inst *inst,996 u32 enc_frame_size,997 u32 enc_frame_num,998 u32 ref_frame_size,999 u32 ref_frame_num,1000 u32 act_frame_size,1001 u32 act_frame_num)1002{1003 struct venc_t *venc;1004 u32 i;1005 int ret;1006 1007 venc = inst->priv;1008 if (enc_frame_num > ARRAY_SIZE(venc->enc)) {1009 dev_err(inst->dev, "[%d] enc num(%d) is out of range\n", inst->id, enc_frame_num);1010 return;1011 }1012 if (ref_frame_num > ARRAY_SIZE(venc->ref)) {1013 dev_err(inst->dev, "[%d] ref num(%d) is out of range\n", inst->id, ref_frame_num);1014 return;1015 }1016 if (act_frame_num > ARRAY_SIZE(venc->act)) {1017 dev_err(inst->dev, "[%d] act num(%d) is out of range\n", inst->id, act_frame_num);1018 return;1019 }1020 1021 for (i = 0; i < enc_frame_num; i++) {1022 venc->enc[i].length = enc_frame_size;1023 ret = vpu_alloc_dma(inst->core, &venc->enc[i]);1024 if (ret) {1025 venc_cleanup_mem_resource(inst);1026 return;1027 }1028 }1029 for (i = 0; i < ref_frame_num; i++) {1030 venc->ref[i].length = ref_frame_size;1031 ret = vpu_alloc_dma(inst->core, &venc->ref[i]);1032 if (ret) {1033 venc_cleanup_mem_resource(inst);1034 return;1035 }1036 }1037 if (act_frame_num != 1 || act_frame_size > inst->act.length) {1038 venc_cleanup_mem_resource(inst);1039 return;1040 }1041 venc->act[0].length = act_frame_size;1042 venc->act[0].phys = inst->act.phys;1043 venc->act[0].virt = inst->act.virt;1044 1045 for (i = 0; i < enc_frame_num; i++)1046 vpu_iface_config_memory_resource(inst, MEM_RES_ENC, i, &venc->enc[i]);1047 for (i = 0; i < ref_frame_num; i++)1048 vpu_iface_config_memory_resource(inst, MEM_RES_REF, i, &venc->ref[i]);1049 for (i = 0; i < act_frame_num; i++)1050 vpu_iface_config_memory_resource(inst, MEM_RES_ACT, i, &venc->act[i]);1051}1052 1053static void venc_cleanup_frames(struct venc_t *venc)1054{1055 struct venc_frame_t *frame;1056 struct venc_frame_t *tmp;1057 1058 list_for_each_entry_safe(frame, tmp, &venc->frames, list) {1059 list_del_init(&frame->list);1060 vfree(frame);1061 }1062}1063 1064static int venc_stop_session(struct vpu_inst *inst, u32 type)1065{1066 struct venc_t *venc = inst->priv;1067 1068 venc_set_enable(venc, type, 0);1069 if (venc->enable & VENC_ENABLE_MASK)1070 return 0;1071 1072 if (inst->state == VPU_CODEC_STATE_DEINIT)1073 return 0;1074 1075 if (inst->state != VPU_CODEC_STATE_STOP)1076 venc_request_eos(inst);1077 1078 call_void_vop(inst, wait_prepare);1079 if (!wait_event_timeout(venc->wq, venc->stopped, VPU_TIMEOUT)) {1080 set_bit(inst->id, &inst->core->hang_mask);1081 vpu_session_debug(inst);1082 }1083 call_void_vop(inst, wait_finish);1084 1085 inst->state = VPU_CODEC_STATE_DEINIT;1086 venc_cleanup_frames(inst->priv);1087 vpu_free_dma(&inst->stream_buffer);1088 venc_cleanup_mem_resource(inst);1089 1090 return 0;1091}1092 1093static int venc_process_output(struct vpu_inst *inst, struct vb2_buffer *vb)1094{1095 struct venc_t *venc = inst->priv;1096 struct vb2_v4l2_buffer *vbuf;1097 u32 flags;1098 1099 if (inst->state == VPU_CODEC_STATE_DEINIT)1100 return -EINVAL;1101 1102 vbuf = to_vb2_v4l2_buffer(vb);1103 if (inst->state == VPU_CODEC_STATE_STARTED)1104 inst->state = VPU_CODEC_STATE_ACTIVE;1105 1106 flags = vbuf->flags;1107 if (venc->request_key_frame) {1108 vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;1109 venc->request_key_frame = 0;1110 }1111 if (venc->bitrate_change) {1112 vpu_session_update_parameters(inst, &venc->params);1113 venc->bitrate_change = false;1114 }1115 dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp);1116 vpu_iface_input_frame(inst, vb);1117 vbuf->flags = flags;1118 venc->input_ready = false;1119 venc->frame_count++;1120 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);1121 1122 return 0;1123}1124 1125static int venc_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb)1126{1127 struct venc_t *venc;1128 struct venc_frame_t *frame = NULL;1129 struct vb2_v4l2_buffer *vbuf;1130 int ret;1131 1132 venc = inst->priv;1133 if (list_empty(&venc->frames))1134 return -EINVAL;1135 1136 frame = list_first_entry(&venc->frames, struct venc_frame_t, list);1137 vbuf = to_vb2_v4l2_buffer(vb);1138 v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);1139 ret = venc_get_one_encoded_frame(inst, frame, vbuf);1140 if (ret)1141 return ret;1142 1143 list_del_init(&frame->list);1144 vfree(frame);1145 return 0;1146}1147 1148static void venc_on_queue_empty(struct vpu_inst *inst, u32 type)1149{1150 struct venc_t *venc = inst->priv;1151 1152 if (V4L2_TYPE_IS_OUTPUT(type))1153 return;1154 1155 if (venc->stopped)1156 venc_set_last_buffer_dequeued(inst);1157}1158 1159static int venc_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)1160{1161 struct venc_t *venc = inst->priv;1162 int num = -1;1163 1164 switch (i) {1165 case 0:1166 num = scnprintf(str, size, "profile = %d\n", venc->params.profile);1167 break;1168 case 1:1169 num = scnprintf(str, size, "level = %d\n", venc->params.level);1170 break;1171 case 2:1172 num = scnprintf(str, size, "fps = %d/%d\n",1173 venc->params.frame_rate.numerator,1174 venc->params.frame_rate.denominator);1175 break;1176 case 3:1177 num = scnprintf(str, size, "%d x %d -> %d x %d\n",1178 venc->params.src_width,1179 venc->params.src_height,1180 venc->params.out_width,1181 venc->params.out_height);1182 break;1183 case 4:1184 num = scnprintf(str, size, "(%d, %d) %d x %d\n",1185 venc->params.crop.left,1186 venc->params.crop.top,1187 venc->params.crop.width,1188 venc->params.crop.height);1189 break;1190 case 5:1191 num = scnprintf(str, size,1192 "enable = 0x%x, input = %d, encode = %d, ready = %d, stopped = %d\n",1193 venc->enable,1194 venc->frame_count, venc->encode_count,1195 venc->ready_count,1196 venc->stopped);1197 break;1198 case 6:1199 num = scnprintf(str, size, "gop = %d\n", venc->params.gop_length);1200 break;1201 case 7:1202 num = scnprintf(str, size, "bframes = %d\n", venc->params.bframes);1203 break;1204 case 8:1205 num = scnprintf(str, size, "rc: %s, mode = %d, bitrate = %d(%d), qp = %d\n",1206 venc->params.rc_enable ? "enable" : "disable",1207 venc->params.rc_mode,1208 venc->params.bitrate,1209 venc->params.bitrate_max,1210 venc->params.i_frame_qp);1211 break;1212 case 9:1213 num = scnprintf(str, size, "sar: enable = %d, idc = %d, %d x %d\n",1214 venc->params.sar.enable,1215 venc->params.sar.idc,1216 venc->params.sar.width,1217 venc->params.sar.height);1218 1219 break;1220 case 10:1221 num = scnprintf(str, size,1222 "colorspace: primaries = %d, transfer = %d, matrix = %d, full_range = %d\n",1223 venc->params.color.primaries,1224 venc->params.color.transfer,1225 venc->params.color.matrix,1226 venc->params.color.full_range);1227 break;1228 case 11:1229 num = scnprintf(str, size, "skipped: count = %d, bytes = %d\n",1230 venc->skipped_count, venc->skipped_bytes);1231 break;1232 default:1233 break;1234 }1235 1236 return num;1237}1238 1239static struct vpu_inst_ops venc_inst_ops = {1240 .ctrl_init = venc_ctrl_init,1241 .check_ready = venc_check_ready,1242 .input_done = venc_input_done,1243 .get_one_frame = venc_frame_encoded,1244 .stop_done = venc_stop_done,1245 .event_notify = venc_event_notify,1246 .release = venc_release,1247 .cleanup = venc_cleanup,1248 .start = venc_start_session,1249 .mem_request = venc_request_mem_resource,1250 .stop = venc_stop_session,1251 .process_output = venc_process_output,1252 .process_capture = venc_process_capture,1253 .on_queue_empty = venc_on_queue_empty,1254 .get_debug_info = venc_get_debug_info,1255 .wait_prepare = vpu_inst_unlock,1256 .wait_finish = vpu_inst_lock,1257};1258 1259static void venc_init(struct file *file)1260{1261 struct vpu_inst *inst = to_inst(file);1262 struct venc_t *venc;1263 struct v4l2_format f;1264 struct v4l2_streamparm parm;1265 1266 venc = inst->priv;1267 venc->params.qp_min = 1;1268 venc->params.qp_max = 51;1269 venc->params.qp_min_i = 1;1270 venc->params.qp_max_i = 51;1271 venc->params.bitrate_min = BITRATE_MIN;1272 1273 memset(&f, 0, sizeof(f));1274 f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;1275 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;1276 f.fmt.pix_mp.width = 1280;1277 f.fmt.pix_mp.height = 720;1278 f.fmt.pix_mp.field = V4L2_FIELD_NONE;1279 venc_s_fmt(file, &inst->fh, &f);1280 1281 memset(&f, 0, sizeof(f));1282 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;1283 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;1284 f.fmt.pix_mp.width = 1280;1285 f.fmt.pix_mp.height = 720;1286 f.fmt.pix_mp.field = V4L2_FIELD_NONE;1287 venc_s_fmt(file, &inst->fh, &f);1288 1289 memset(&parm, 0, sizeof(parm));1290 parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;1291 parm.parm.capture.timeperframe.numerator = 1;1292 parm.parm.capture.timeperframe.denominator = 30;1293 venc_s_parm(file, &inst->fh, &parm);1294}1295 1296static int venc_open(struct file *file)1297{1298 struct vpu_inst *inst;1299 struct venc_t *venc;1300 int ret;1301 1302 inst = vzalloc(sizeof(*inst));1303 if (!inst)1304 return -ENOMEM;1305 1306 venc = vzalloc(sizeof(*venc));1307 if (!venc) {1308 vfree(inst);1309 return -ENOMEM;1310 }1311 1312 inst->ops = &venc_inst_ops;1313 inst->formats = venc_formats;1314 inst->type = VPU_CORE_TYPE_ENC;1315 inst->priv = venc;1316 INIT_LIST_HEAD(&venc->frames);1317 init_waitqueue_head(&venc->wq);1318 1319 ret = vpu_v4l2_open(file, inst);1320 if (ret)1321 return ret;1322 1323 inst->min_buffer_out = VENC_MIN_BUFFER_OUT;1324 inst->min_buffer_cap = VENC_MIN_BUFFER_CAP;1325 venc_init(file);1326 1327 return 0;1328}1329 1330static const struct v4l2_file_operations venc_fops = {1331 .owner = THIS_MODULE,1332 .open = venc_open,1333 .release = vpu_v4l2_close,1334 .unlocked_ioctl = video_ioctl2,1335 .poll = v4l2_m2m_fop_poll,1336 .mmap = v4l2_m2m_fop_mmap,1337};1338 1339const struct v4l2_ioctl_ops *venc_get_ioctl_ops(void)1340{1341 return &venc_ioctl_ops;1342}1343 1344const struct v4l2_file_operations *venc_get_fops(void)1345{1346 return &venc_fops;1347}1348