1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2020-2021 NXP
4 */
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 8
36#define VENC_MIN_BUFFER_OUT 6
37#define VENC_MIN_BUFFER_CAP 6
38
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_COMPRESSED
90 },
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(filp: file);
106 const struct vpu_format *fmt;
107
108 memset(f->reserved, 0, sizeof(f->reserved));
109 fmt = vpu_helper_enum_format(inst, type: f->type, index: 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(filp: 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, type: 0, pixelfmt: 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(filp: 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, type: 0, pixelfmt: 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(filp: 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, type: 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(fmt: cur_fmt, plane_no: 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(filp: file);
208 struct vpu_format fmt;
209
210 vpu_try_fmt_common(inst, f, fmt: &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(filp: 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(m2m_ctx: inst->fh.m2m_ctx, type: 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: &fmt))
231 return -EINVAL;
232
233 cur_fmt = vpu_get_format(inst, type: 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(filp: 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, type: 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(filp: 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, type: 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(given_numerator: venc->params.frame_rate.numerator,
317 given_denominator: venc->params.frame_rate.denominator,
318 max_numerator: venc->params.frame_rate.numerator,
319 max_denominator: venc->params.frame_rate.denominator,
320 best_numerator: &n, best_denominator: &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(filp: 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(filp: 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(filp: file);
454 int ret;
455
456 ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec: 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, eos: true);
464 else
465 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, elems: 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 vpu_inst_lock(inst);
522 switch (ctrl->id) {
523 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
524 venc->params.profile = ctrl->val;
525 break;
526 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
527 venc->params.level = ctrl->val;
528 break;
529 case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
530 venc->params.rc_enable = ctrl->val;
531 break;
532 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
533 venc->params.rc_mode = ctrl->val;
534 break;
535 case V4L2_CID_MPEG_VIDEO_BITRATE:
536 if (ctrl->val != venc->params.bitrate)
537 venc->bitrate_change = true;
538 venc->params.bitrate = ctrl->val;
539 break;
540 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
541 venc->params.bitrate_max = ctrl->val;
542 break;
543 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
544 venc->params.gop_length = ctrl->val;
545 break;
546 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
547 venc->params.bframes = ctrl->val;
548 break;
549 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
550 venc->params.i_frame_qp = ctrl->val;
551 break;
552 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
553 venc->params.p_frame_qp = ctrl->val;
554 break;
555 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
556 venc->params.b_frame_qp = ctrl->val;
557 break;
558 case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
559 venc->request_key_frame = 1;
560 break;
561 case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:
562 venc->cpb_size = ctrl->val * 1024;
563 break;
564 case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
565 venc->params.sar.enable = ctrl->val;
566 break;
567 case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
568 venc->params.sar.idc = ctrl->val;
569 break;
570 case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
571 venc->params.sar.width = ctrl->val;
572 break;
573 case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
574 venc->params.sar.height = ctrl->val;
575 break;
576 case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
577 break;
578 default:
579 ret = -EINVAL;
580 break;
581 }
582 vpu_inst_unlock(inst);
583
584 return ret;
585}
586
587static const struct v4l2_ctrl_ops venc_ctrl_ops = {
588 .s_ctrl = venc_op_s_ctrl,
589 .g_volatile_ctrl = vpu_helper_g_volatile_ctrl,
590};
591
592static int venc_ctrl_init(struct vpu_inst *inst)
593{
594 struct v4l2_ctrl *ctrl;
595 int ret;
596
597 ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20);
598 if (ret)
599 return ret;
600
601 v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
602 V4L2_CID_MPEG_VIDEO_H264_PROFILE,
603 max: V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
604 mask: ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
605 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
606 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
607 def: V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
608
609 v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
610 V4L2_CID_MPEG_VIDEO_H264_LEVEL,
611 max: V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
612 mask: 0x0,
613 def: V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
614
615 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
616 V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, min: 0, max: 1, step: 1, def: 1);
617
618 v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
619 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
620 max: V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
621 mask: ~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
622 (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)),
623 def: V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
624
625 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
626 V4L2_CID_MPEG_VIDEO_BITRATE,
627 BITRATE_MIN,
628 BITRATE_MAX,
629 BITRATE_STEP,
630 BITRATE_DEFAULT);
631
632 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
633 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
634 BITRATE_MIN, BITRATE_MAX,
635 BITRATE_STEP,
636 BITRATE_DEFAULT_PEAK);
637
638 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
639 V4L2_CID_MPEG_VIDEO_GOP_SIZE, min: 1, max: 8000, step: 1, def: 30);
640
641 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
642 V4L2_CID_MPEG_VIDEO_B_FRAMES, min: 0, max: 4, step: 1, def: 0);
643
644 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
645 V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, min: 1, max: 51, step: 1, def: 26);
646 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
647 V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, min: 1, max: 51, step: 1, def: 28);
648 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
649 V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, min: 1, max: 51, step: 1, def: 30);
650 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
651 V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, min: 0, max: 0, step: 0, def: 0);
652 ctrl = v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
653 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, min: 1, max: 32, step: 1, def: 2);
654 if (ctrl)
655 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
656 ctrl = v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
657 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, min: 1, max: 32, step: 1, def: 2);
658 if (ctrl)
659 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
660
661 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
662 V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, min: 64, max: 10240, step: 1, def: 1024);
663
664 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
665 V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, min: 0, max: 1, step: 1, def: 1);
666 v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
667 V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
668 max: V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
669 mask: 0x0,
670 def: V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1);
671 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
672 V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
673 min: 0, USHRT_MAX, step: 1, def: 1);
674 v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
675 V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,
676 min: 0, USHRT_MAX, step: 1, def: 1);
677 v4l2_ctrl_new_std_menu(hdl: &inst->ctrl_handler, ops: &venc_ctrl_ops,
678 V4L2_CID_MPEG_VIDEO_HEADER_MODE,
679 max: V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
680 mask: ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
681 def: V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
682
683 if (inst->ctrl_handler.error) {
684 ret = inst->ctrl_handler.error;
685 v4l2_ctrl_handler_free(hdl: &inst->ctrl_handler);
686 return ret;
687 }
688
689 ret = v4l2_ctrl_handler_setup(hdl: &inst->ctrl_handler);
690 if (ret) {
691 dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);
692 v4l2_ctrl_handler_free(hdl: &inst->ctrl_handler);
693 return ret;
694 }
695
696 return 0;
697}
698
699static bool venc_check_ready(struct vpu_inst *inst, unsigned int type)
700{
701 struct venc_t *venc = inst->priv;
702
703 if (V4L2_TYPE_IS_OUTPUT(type)) {
704 if (vpu_helper_get_free_space(inst) < venc->cpb_size)
705 return false;
706 return venc->input_ready;
707 }
708
709 if (list_empty(head: &venc->frames))
710 return false;
711 return true;
712}
713
714static u32 venc_get_enable_mask(u32 type)
715{
716 if (V4L2_TYPE_IS_OUTPUT(type))
717 return VENC_OUTPUT_ENABLE;
718 else
719 return VENC_CAPTURE_ENABLE;
720}
721
722static void venc_set_enable(struct venc_t *venc, u32 type, int enable)
723{
724 u32 mask = venc_get_enable_mask(type);
725
726 if (enable)
727 venc->enable |= mask;
728 else
729 venc->enable &= ~mask;
730}
731
732static u32 venc_get_enable(struct venc_t *venc, u32 type)
733{
734 return venc->enable & venc_get_enable_mask(type);
735}
736
737static void venc_input_done(struct vpu_inst *inst)
738{
739 struct venc_t *venc = inst->priv;
740
741 vpu_inst_lock(inst);
742 venc->input_ready = true;
743 vpu_process_output_buffer(inst);
744 if (inst->state == VPU_CODEC_STATE_DRAIN)
745 venc_drain(inst);
746 vpu_inst_unlock(inst);
747}
748
749/*
750 * It's hardware limitation, that there may be several bytes
751 * redundant data at the beginning of frame.
752 * For android platform, the redundant data may cause cts test fail
753 * So driver will strip them
754 */
755static int venc_precheck_encoded_frame(struct vpu_inst *inst, struct venc_frame_t *frame)
756{
757 struct venc_t *venc;
758 int skipped;
759
760 if (!frame || !frame->bytesused)
761 return -EINVAL;
762
763 venc = inst->priv;
764 skipped = vpu_helper_find_startcode(stream_buffer: &inst->stream_buffer,
765 pixelformat: inst->cap_format.pixfmt,
766 offset: frame->info.wptr - inst->stream_buffer.phys,
767 bytesused: frame->bytesused);
768 if (skipped > 0) {
769 frame->bytesused -= skipped;
770 frame->info.wptr = vpu_helper_step_walk(stream_buffer: &inst->stream_buffer,
771 pos: frame->info.wptr, step: skipped);
772 venc->skipped_bytes += skipped;
773 venc->skipped_count++;
774 }
775
776 return 0;
777}
778
779static int venc_get_one_encoded_frame(struct vpu_inst *inst,
780 struct venc_frame_t *frame,
781 struct vb2_v4l2_buffer *vbuf)
782{
783 struct venc_t *venc = inst->priv;
784 struct vb2_v4l2_buffer *src_buf;
785
786 if (!vbuf)
787 return -EAGAIN;
788
789 src_buf = vpu_find_buf_by_sequence(inst, type: inst->out_format.type, sequence: frame->info.frame_id);
790 if (src_buf) {
791 v4l2_m2m_buf_copy_metadata(out_vb: src_buf, cap_vb: vbuf, copy_frame_flags: true);
792 vpu_set_buffer_state(vbuf: src_buf, state: VPU_BUF_STATE_IDLE);
793 v4l2_m2m_src_buf_remove_by_buf(m2m_ctx: inst->fh.m2m_ctx, vbuf: src_buf);
794 v4l2_m2m_buf_done(buf: src_buf, state: VB2_BUF_STATE_DONE);
795 } else {
796 vbuf->vb2_buf.timestamp = frame->info.timestamp;
797 }
798 if (!venc_get_enable(venc: inst->priv, type: vbuf->vb2_buf.type)) {
799 v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_ERROR);
800 return 0;
801 }
802 if (frame->bytesused > vbuf->vb2_buf.planes[0].length) {
803 v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_ERROR);
804 return -ENOMEM;
805 }
806
807 venc_precheck_encoded_frame(inst, frame);
808
809 if (frame->bytesused) {
810 u32 rptr = frame->info.wptr;
811 void *dst = vb2_plane_vaddr(vb: &vbuf->vb2_buf, plane_no: 0);
812
813 vpu_helper_copy_from_stream_buffer(stream_buffer: &inst->stream_buffer,
814 rptr: &rptr, size: frame->bytesused, dst);
815 vpu_iface_update_stream_buffer(inst, ptr: rptr, write: 0);
816 }
817 vb2_set_plane_payload(vb: &vbuf->vb2_buf, plane_no: 0, size: frame->bytesused);
818 vbuf->sequence = frame->info.frame_id;
819 vbuf->field = inst->cap_format.field;
820 vbuf->flags |= frame->info.pic_type;
821 vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_IDLE);
822 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
823 v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_DONE);
824 venc->ready_count++;
825
826 if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)
827 dev_dbg(inst->dev, "[%d][%d]key frame\n", inst->id, frame->info.frame_id);
828
829 return 0;
830}
831
832static int venc_get_encoded_frames(struct vpu_inst *inst)
833{
834 struct venc_t *venc;
835 struct venc_frame_t *frame;
836 struct venc_frame_t *tmp;
837
838 if (!inst->fh.m2m_ctx)
839 return 0;
840 venc = inst->priv;
841 list_for_each_entry_safe(frame, tmp, &venc->frames, list) {
842 if (venc_get_one_encoded_frame(inst, frame,
843 vbuf: v4l2_m2m_dst_buf_remove(m2m_ctx: inst->fh.m2m_ctx)))
844 break;
845 list_del_init(entry: &frame->list);
846 vfree(addr: frame);
847 }
848
849 return 0;
850}
851
852static int venc_frame_encoded(struct vpu_inst *inst, void *arg)
853{
854 struct vpu_enc_pic_info *info = arg;
855 struct venc_frame_t *frame;
856 struct venc_t *venc;
857 int ret = 0;
858
859 if (!info)
860 return -EINVAL;
861 venc = inst->priv;
862 frame = vzalloc(size: sizeof(*frame));
863 if (!frame)
864 return -ENOMEM;
865
866 memcpy(&frame->info, info, sizeof(frame->info));
867 frame->bytesused = info->frame_size;
868
869 vpu_inst_lock(inst);
870 list_add_tail(new: &frame->list, head: &venc->frames);
871 venc->encode_count++;
872 venc_get_encoded_frames(inst);
873 vpu_inst_unlock(inst);
874
875 return ret;
876}
877
878static void venc_set_last_buffer_dequeued(struct vpu_inst *inst)
879{
880 struct venc_t *venc = inst->priv;
881
882 if (venc->stopped && list_empty(head: &venc->frames))
883 vpu_set_last_buffer_dequeued(inst, eos: true);
884}
885
886static void venc_stop_done(struct vpu_inst *inst)
887{
888 struct venc_t *venc = inst->priv;
889
890 vpu_inst_lock(inst);
891 venc->stopped = true;
892 venc_set_last_buffer_dequeued(inst);
893 vpu_inst_unlock(inst);
894
895 wake_up_all(&venc->wq);
896}
897
898static void venc_event_notify(struct vpu_inst *inst, u32 event, void *data)
899{
900}
901
902static void venc_release(struct vpu_inst *inst)
903{
904}
905
906static void venc_cleanup(struct vpu_inst *inst)
907{
908 struct venc_t *venc;
909
910 if (!inst)
911 return;
912
913 venc = inst->priv;
914 vfree(addr: venc);
915 inst->priv = NULL;
916 vfree(addr: inst);
917}
918
919static int venc_start_session(struct vpu_inst *inst, u32 type)
920{
921 struct venc_t *venc = inst->priv;
922 int stream_buffer_size;
923 int ret;
924
925 venc_set_enable(venc, type, enable: 1);
926 if ((venc->enable & VENC_ENABLE_MASK) != VENC_ENABLE_MASK)
927 return 0;
928
929 vpu_iface_init_instance(inst);
930 stream_buffer_size = vpu_iface_get_stream_buffer_size(core: inst->core);
931 if (stream_buffer_size > 0) {
932 inst->stream_buffer.length = max_t(u32, stream_buffer_size, venc->cpb_size * 3);
933 ret = vpu_alloc_dma(core: inst->core, buf: &inst->stream_buffer);
934 if (ret)
935 goto error;
936
937 inst->use_stream_buffer = true;
938 vpu_iface_config_stream_buffer(inst, buf: &inst->stream_buffer);
939 }
940
941 ret = vpu_iface_set_encode_params(inst, params: &venc->params, update: 0);
942 if (ret)
943 goto error;
944 ret = vpu_session_configure_codec(inst);
945 if (ret)
946 goto error;
947
948 inst->state = VPU_CODEC_STATE_CONFIGURED;
949 /*vpu_iface_config_memory_resource*/
950
951 /*config enc expert mode parameter*/
952 ret = vpu_iface_set_encode_params(inst, params: &venc->params, update: 1);
953 if (ret)
954 goto error;
955
956 ret = vpu_session_start(inst);
957 if (ret)
958 goto error;
959 inst->state = VPU_CODEC_STATE_STARTED;
960
961 venc->bitrate_change = false;
962 venc->input_ready = true;
963 venc->frame_count = 0;
964 venc->encode_count = 0;
965 venc->ready_count = 0;
966 venc->stopped = false;
967 vpu_process_output_buffer(inst);
968 if (venc->frame_count == 0)
969 dev_err(inst->dev, "[%d] there is no input when starting\n", inst->id);
970
971 return 0;
972error:
973 venc_set_enable(venc, type, enable: 0);
974 inst->state = VPU_CODEC_STATE_DEINIT;
975
976 vpu_free_dma(buf: &inst->stream_buffer);
977 return ret;
978}
979
980static void venc_cleanup_mem_resource(struct vpu_inst *inst)
981{
982 struct venc_t *venc;
983 u32 i;
984
985 venc = inst->priv;
986
987 for (i = 0; i < ARRAY_SIZE(venc->enc); i++)
988 vpu_free_dma(buf: &venc->enc[i]);
989 for (i = 0; i < ARRAY_SIZE(venc->ref); i++)
990 vpu_free_dma(buf: &venc->ref[i]);
991}
992
993static void venc_request_mem_resource(struct vpu_inst *inst,
994 u32 enc_frame_size,
995 u32 enc_frame_num,
996 u32 ref_frame_size,
997 u32 ref_frame_num,
998 u32 act_frame_size,
999 u32 act_frame_num)
1000{
1001 struct venc_t *venc;
1002 u32 i;
1003 int ret;
1004
1005 venc = inst->priv;
1006 if (enc_frame_num > ARRAY_SIZE(venc->enc)) {
1007 dev_err(inst->dev, "[%d] enc num(%d) is out of range\n", inst->id, enc_frame_num);
1008 return;
1009 }
1010 if (ref_frame_num > ARRAY_SIZE(venc->ref)) {
1011 dev_err(inst->dev, "[%d] ref num(%d) is out of range\n", inst->id, ref_frame_num);
1012 return;
1013 }
1014 if (act_frame_num > ARRAY_SIZE(venc->act)) {
1015 dev_err(inst->dev, "[%d] act num(%d) is out of range\n", inst->id, act_frame_num);
1016 return;
1017 }
1018
1019 for (i = 0; i < enc_frame_num; i++) {
1020 venc->enc[i].length = enc_frame_size;
1021 ret = vpu_alloc_dma(core: inst->core, buf: &venc->enc[i]);
1022 if (ret) {
1023 venc_cleanup_mem_resource(inst);
1024 return;
1025 }
1026 }
1027 for (i = 0; i < ref_frame_num; i++) {
1028 venc->ref[i].length = ref_frame_size;
1029 ret = vpu_alloc_dma(core: inst->core, buf: &venc->ref[i]);
1030 if (ret) {
1031 venc_cleanup_mem_resource(inst);
1032 return;
1033 }
1034 }
1035 if (act_frame_num != 1 || act_frame_size > inst->act.length) {
1036 venc_cleanup_mem_resource(inst);
1037 return;
1038 }
1039 venc->act[0].length = act_frame_size;
1040 venc->act[0].phys = inst->act.phys;
1041 venc->act[0].virt = inst->act.virt;
1042
1043 for (i = 0; i < enc_frame_num; i++)
1044 vpu_iface_config_memory_resource(inst, type: MEM_RES_ENC, index: i, buf: &venc->enc[i]);
1045 for (i = 0; i < ref_frame_num; i++)
1046 vpu_iface_config_memory_resource(inst, type: MEM_RES_REF, index: i, buf: &venc->ref[i]);
1047 for (i = 0; i < act_frame_num; i++)
1048 vpu_iface_config_memory_resource(inst, type: MEM_RES_ACT, index: i, buf: &venc->act[i]);
1049}
1050
1051static void venc_cleanup_frames(struct venc_t *venc)
1052{
1053 struct venc_frame_t *frame;
1054 struct venc_frame_t *tmp;
1055
1056 list_for_each_entry_safe(frame, tmp, &venc->frames, list) {
1057 list_del_init(entry: &frame->list);
1058 vfree(addr: frame);
1059 }
1060}
1061
1062static int venc_stop_session(struct vpu_inst *inst, u32 type)
1063{
1064 struct venc_t *venc = inst->priv;
1065
1066 venc_set_enable(venc, type, enable: 0);
1067 if (venc->enable & VENC_ENABLE_MASK)
1068 return 0;
1069
1070 if (inst->state == VPU_CODEC_STATE_DEINIT)
1071 return 0;
1072
1073 if (inst->state != VPU_CODEC_STATE_STOP)
1074 venc_request_eos(inst);
1075
1076 call_void_vop(inst, wait_prepare);
1077 if (!wait_event_timeout(venc->wq, venc->stopped, VPU_TIMEOUT)) {
1078 set_bit(nr: inst->id, addr: &inst->core->hang_mask);
1079 vpu_session_debug(inst);
1080 }
1081 call_void_vop(inst, wait_finish);
1082
1083 inst->state = VPU_CODEC_STATE_DEINIT;
1084 venc_cleanup_frames(venc: inst->priv);
1085 vpu_free_dma(buf: &inst->stream_buffer);
1086 venc_cleanup_mem_resource(inst);
1087
1088 return 0;
1089}
1090
1091static int venc_process_output(struct vpu_inst *inst, struct vb2_buffer *vb)
1092{
1093 struct venc_t *venc = inst->priv;
1094 struct vb2_v4l2_buffer *vbuf;
1095 u32 flags;
1096
1097 if (inst->state == VPU_CODEC_STATE_DEINIT)
1098 return -EINVAL;
1099
1100 vbuf = to_vb2_v4l2_buffer(vb);
1101 if (inst->state == VPU_CODEC_STATE_STARTED)
1102 inst->state = VPU_CODEC_STATE_ACTIVE;
1103
1104 flags = vbuf->flags;
1105 if (venc->request_key_frame) {
1106 vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1107 venc->request_key_frame = 0;
1108 }
1109 if (venc->bitrate_change) {
1110 vpu_session_update_parameters(inst, arg: &venc->params);
1111 venc->bitrate_change = false;
1112 }
1113 dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp);
1114 vpu_iface_input_frame(inst, vb);
1115 vbuf->flags = flags;
1116 venc->input_ready = false;
1117 venc->frame_count++;
1118 vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_INUSE);
1119
1120 return 0;
1121}
1122
1123static int venc_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb)
1124{
1125 struct venc_t *venc;
1126 struct venc_frame_t *frame = NULL;
1127 struct vb2_v4l2_buffer *vbuf;
1128 int ret;
1129
1130 venc = inst->priv;
1131 if (list_empty(head: &venc->frames))
1132 return -EINVAL;
1133
1134 frame = list_first_entry(&venc->frames, struct venc_frame_t, list);
1135 vbuf = to_vb2_v4l2_buffer(vb);
1136 v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx: inst->fh.m2m_ctx, vbuf);
1137 ret = venc_get_one_encoded_frame(inst, frame, vbuf);
1138 if (ret)
1139 return ret;
1140
1141 list_del_init(entry: &frame->list);
1142 vfree(addr: frame);
1143 return 0;
1144}
1145
1146static void venc_on_queue_empty(struct vpu_inst *inst, u32 type)
1147{
1148 struct venc_t *venc = inst->priv;
1149
1150 if (V4L2_TYPE_IS_OUTPUT(type))
1151 return;
1152
1153 if (venc->stopped)
1154 venc_set_last_buffer_dequeued(inst);
1155}
1156
1157static int venc_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)
1158{
1159 struct venc_t *venc = inst->priv;
1160 int num = -1;
1161
1162 switch (i) {
1163 case 0:
1164 num = scnprintf(buf: str, size, fmt: "profile = %d\n", venc->params.profile);
1165 break;
1166 case 1:
1167 num = scnprintf(buf: str, size, fmt: "level = %d\n", venc->params.level);
1168 break;
1169 case 2:
1170 num = scnprintf(buf: str, size, fmt: "fps = %d/%d\n",
1171 venc->params.frame_rate.numerator,
1172 venc->params.frame_rate.denominator);
1173 break;
1174 case 3:
1175 num = scnprintf(buf: str, size, fmt: "%d x %d -> %d x %d\n",
1176 venc->params.src_width,
1177 venc->params.src_height,
1178 venc->params.out_width,
1179 venc->params.out_height);
1180 break;
1181 case 4:
1182 num = scnprintf(buf: str, size, fmt: "(%d, %d) %d x %d\n",
1183 venc->params.crop.left,
1184 venc->params.crop.top,
1185 venc->params.crop.width,
1186 venc->params.crop.height);
1187 break;
1188 case 5:
1189 num = scnprintf(buf: str, size,
1190 fmt: "enable = 0x%x, input = %d, encode = %d, ready = %d, stopped = %d\n",
1191 venc->enable,
1192 venc->frame_count, venc->encode_count,
1193 venc->ready_count,
1194 venc->stopped);
1195 break;
1196 case 6:
1197 num = scnprintf(buf: str, size, fmt: "gop = %d\n", venc->params.gop_length);
1198 break;
1199 case 7:
1200 num = scnprintf(buf: str, size, fmt: "bframes = %d\n", venc->params.bframes);
1201 break;
1202 case 8:
1203 num = scnprintf(buf: str, size, fmt: "rc: %s, mode = %d, bitrate = %d(%d), qp = %d\n",
1204 venc->params.rc_enable ? "enable" : "disable",
1205 venc->params.rc_mode,
1206 venc->params.bitrate,
1207 venc->params.bitrate_max,
1208 venc->params.i_frame_qp);
1209 break;
1210 case 9:
1211 num = scnprintf(buf: str, size, fmt: "sar: enable = %d, idc = %d, %d x %d\n",
1212 venc->params.sar.enable,
1213 venc->params.sar.idc,
1214 venc->params.sar.width,
1215 venc->params.sar.height);
1216
1217 break;
1218 case 10:
1219 num = scnprintf(buf: str, size,
1220 fmt: "colorspace: primaries = %d, transfer = %d, matrix = %d, full_range = %d\n",
1221 venc->params.color.primaries,
1222 venc->params.color.transfer,
1223 venc->params.color.matrix,
1224 venc->params.color.full_range);
1225 break;
1226 case 11:
1227 num = scnprintf(buf: str, size, fmt: "skipped: count = %d, bytes = %d\n",
1228 venc->skipped_count, venc->skipped_bytes);
1229 break;
1230 default:
1231 break;
1232 }
1233
1234 return num;
1235}
1236
1237static struct vpu_inst_ops venc_inst_ops = {
1238 .ctrl_init = venc_ctrl_init,
1239 .check_ready = venc_check_ready,
1240 .input_done = venc_input_done,
1241 .get_one_frame = venc_frame_encoded,
1242 .stop_done = venc_stop_done,
1243 .event_notify = venc_event_notify,
1244 .release = venc_release,
1245 .cleanup = venc_cleanup,
1246 .start = venc_start_session,
1247 .mem_request = venc_request_mem_resource,
1248 .stop = venc_stop_session,
1249 .process_output = venc_process_output,
1250 .process_capture = venc_process_capture,
1251 .on_queue_empty = venc_on_queue_empty,
1252 .get_debug_info = venc_get_debug_info,
1253 .wait_prepare = vpu_inst_unlock,
1254 .wait_finish = vpu_inst_lock,
1255};
1256
1257static void venc_init(struct file *file)
1258{
1259 struct vpu_inst *inst = to_inst(filp: file);
1260 struct venc_t *venc;
1261 struct v4l2_format f;
1262 struct v4l2_streamparm parm;
1263
1264 venc = inst->priv;
1265 venc->params.qp_min = 1;
1266 venc->params.qp_max = 51;
1267 venc->params.qp_min_i = 1;
1268 venc->params.qp_max_i = 51;
1269 venc->params.bitrate_min = BITRATE_MIN;
1270
1271 memset(&f, 0, sizeof(f));
1272 f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1273 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
1274 f.fmt.pix_mp.width = 1280;
1275 f.fmt.pix_mp.height = 720;
1276 f.fmt.pix_mp.field = V4L2_FIELD_NONE;
1277 venc_s_fmt(file, fh: &inst->fh, f: &f);
1278
1279 memset(&f, 0, sizeof(f));
1280 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1281 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
1282 f.fmt.pix_mp.width = 1280;
1283 f.fmt.pix_mp.height = 720;
1284 f.fmt.pix_mp.field = V4L2_FIELD_NONE;
1285 venc_s_fmt(file, fh: &inst->fh, f: &f);
1286
1287 memset(&parm, 0, sizeof(parm));
1288 parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1289 parm.parm.capture.timeperframe.numerator = 1;
1290 parm.parm.capture.timeperframe.denominator = 30;
1291 venc_s_parm(file, fh: &inst->fh, parm: &parm);
1292}
1293
1294static int venc_open(struct file *file)
1295{
1296 struct vpu_inst *inst;
1297 struct venc_t *venc;
1298 int ret;
1299
1300 inst = vzalloc(size: sizeof(*inst));
1301 if (!inst)
1302 return -ENOMEM;
1303
1304 venc = vzalloc(size: sizeof(*venc));
1305 if (!venc) {
1306 vfree(addr: inst);
1307 return -ENOMEM;
1308 }
1309
1310 inst->ops = &venc_inst_ops;
1311 inst->formats = venc_formats;
1312 inst->type = VPU_CORE_TYPE_ENC;
1313 inst->priv = venc;
1314 INIT_LIST_HEAD(list: &venc->frames);
1315 init_waitqueue_head(&venc->wq);
1316
1317 ret = vpu_v4l2_open(file, inst);
1318 if (ret)
1319 return ret;
1320
1321 inst->min_buffer_out = VENC_MIN_BUFFER_OUT;
1322 inst->min_buffer_cap = VENC_MIN_BUFFER_CAP;
1323 venc_init(file);
1324
1325 return 0;
1326}
1327
1328static const struct v4l2_file_operations venc_fops = {
1329 .owner = THIS_MODULE,
1330 .open = venc_open,
1331 .release = vpu_v4l2_close,
1332 .unlocked_ioctl = video_ioctl2,
1333 .poll = v4l2_m2m_fop_poll,
1334 .mmap = v4l2_m2m_fop_mmap,
1335};
1336
1337const struct v4l2_ioctl_ops *venc_get_ioctl_ops(void)
1338{
1339 return &venc_ioctl_ops;
1340}
1341
1342const struct v4l2_file_operations *venc_get_fops(void)
1343{
1344 return &venc_fops;
1345}
1346

source code of linux/drivers/media/platform/amphion/venc.c