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-contig.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	[VENUS_FMT_NV12] = {
36		.pixfmt = V4L2_PIX_FMT_NV12,
37		.num_planes = 1,
38		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
39	},
40	[VENUS_FMT_H264] = {
41		.pixfmt = V4L2_PIX_FMT_H264,
42		.num_planes = 1,
43		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
44	},
45	[VENUS_FMT_VP8] = {
46		.pixfmt = V4L2_PIX_FMT_VP8,
47		.num_planes = 1,
48		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
49	},
50	[VENUS_FMT_HEVC] = {
51		.pixfmt = V4L2_PIX_FMT_HEVC,
52		.num_planes = 1,
53		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
54	},
55	[VENUS_FMT_MPEG4] = {
56		.pixfmt = V4L2_PIX_FMT_MPEG4,
57		.num_planes = 1,
58		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
59	},
60	[VENUS_FMT_H263] = {
61		.pixfmt = V4L2_PIX_FMT_H263,
62		.num_planes = 1,
63		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
64	},
65};
66
67static const struct venus_format *
68find_format(struct venus_inst *inst, u32 pixfmt, u32 type)
69{
70	const struct venus_format *fmt = venc_formats;
71	unsigned int size = ARRAY_SIZE(venc_formats);
72	unsigned int i;
73
74	for (i = 0; i < size; i++) {
75		if (fmt[i].pixfmt == pixfmt)
76			break;
77	}
78
79	if (i == size || fmt[i].type != type)
80		return NULL;
81
82	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
83	    !venus_helper_check_codec(inst, fmt[i].pixfmt))
84		return NULL;
85
86	return &fmt[i];
87}
88
89static const struct venus_format *
90find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
91{
92	const struct venus_format *fmt = venc_formats;
93	unsigned int size = ARRAY_SIZE(venc_formats);
94	unsigned int i, k = 0;
95
96	if (index > size)
97		return NULL;
98
99	for (i = 0; i < size; i++) {
100		bool valid;
101
102		if (fmt[i].type != type)
103			continue;
104		valid = type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
105			venus_helper_check_codec(inst, fmt[i].pixfmt);
106		if (k == index && valid)
107			break;
108		if (valid)
109			k++;
110	}
111
112	if (i == size)
113		return NULL;
114
115	return &fmt[i];
116}
117
118static int venc_v4l2_to_hfi(int id, int value)
119{
120	switch (id) {
121	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
122		switch (value) {
123		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
124		default:
125			return HFI_H264_ENTROPY_CAVLC;
126		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
127			return HFI_H264_ENTROPY_CABAC;
128		}
129	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
130		switch (value) {
131		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
132		default:
133			return HFI_H264_DB_MODE_ALL_BOUNDARY;
134		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
135			return HFI_H264_DB_MODE_DISABLE;
136		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
137			return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
138		}
139	}
140
141	return 0;
142}
143
144static int
145venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
146{
147	strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
148	strscpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card));
149	strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
150
151	return 0;
152}
153
154static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
155{
156	struct venus_inst *inst = to_inst(file);
157	const struct venus_format *fmt;
158
159	fmt = find_format_by_index(inst, f->index, f->type);
160
161	memset(f->reserved, 0, sizeof(f->reserved));
162
163	if (!fmt)
164		return -EINVAL;
165
166	f->pixelformat = fmt->pixfmt;
167
168	return 0;
169}
170
171static const struct venus_format *
172venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
173{
174	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
175	struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt;
176	const struct venus_format *fmt;
177	u32 sizeimage;
178
179	memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
180	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
181
182	fmt = find_format(inst, pixmp->pixelformat, f->type);
183	if (!fmt) {
184		if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
185			pixmp->pixelformat = V4L2_PIX_FMT_H264;
186		else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
187			pixmp->pixelformat = V4L2_PIX_FMT_NV12;
188		else
189			return NULL;
190		fmt = find_format(inst, pixmp->pixelformat, f->type);
191		if (!fmt)
192			return NULL;
193	}
194
195	pixmp->width = clamp(pixmp->width, frame_width_min(inst),
196			     frame_width_max(inst));
197	pixmp->height = clamp(pixmp->height, frame_height_min(inst),
198			      frame_height_max(inst));
199
200	pixmp->width = ALIGN(pixmp->width, 128);
201	pixmp->height = ALIGN(pixmp->height, 32);
202
203	pixmp->width = ALIGN(pixmp->width, 2);
204	pixmp->height = ALIGN(pixmp->height, 2);
205
206	if (pixmp->field == V4L2_FIELD_ANY)
207		pixmp->field = V4L2_FIELD_NONE;
208	pixmp->num_planes = fmt->num_planes;
209	pixmp->flags = 0;
210
211	sizeimage = venus_helper_get_framesz(pixmp->pixelformat,
212					     pixmp->width,
213					     pixmp->height);
214	pfmt[0].sizeimage = max(ALIGN(pfmt[0].sizeimage, SZ_4K), sizeimage);
215
216	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
217		pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
218	else
219		pfmt[0].bytesperline = 0;
220
221	return fmt;
222}
223
224static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
225{
226	struct venus_inst *inst = to_inst(file);
227
228	venc_try_fmt_common(inst, f);
229
230	return 0;
231}
232
233static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
234{
235	struct venus_inst *inst = to_inst(file);
236	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
237	struct v4l2_pix_format_mplane orig_pixmp;
238	const struct venus_format *fmt;
239	struct v4l2_format format;
240	u32 pixfmt_out = 0, pixfmt_cap = 0;
241	struct vb2_queue *q;
242
243	q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
244	if (!q)
245		return -EINVAL;
246
247	if (vb2_is_busy(q))
248		return -EBUSY;
249
250	orig_pixmp = *pixmp;
251
252	fmt = venc_try_fmt_common(inst, f);
253	if (!fmt)
254		return -EINVAL;
255
256	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
257		pixfmt_out = pixmp->pixelformat;
258		pixfmt_cap = inst->fmt_cap->pixfmt;
259	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
260		pixfmt_cap = pixmp->pixelformat;
261		pixfmt_out = inst->fmt_out->pixfmt;
262	}
263
264	memset(&format, 0, sizeof(format));
265
266	format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
267	format.fmt.pix_mp.pixelformat = pixfmt_out;
268	format.fmt.pix_mp.width = orig_pixmp.width;
269	format.fmt.pix_mp.height = orig_pixmp.height;
270	venc_try_fmt_common(inst, &format);
271
272	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
273		inst->out_width = format.fmt.pix_mp.width;
274		inst->out_height = format.fmt.pix_mp.height;
275		inst->colorspace = pixmp->colorspace;
276		inst->ycbcr_enc = pixmp->ycbcr_enc;
277		inst->quantization = pixmp->quantization;
278		inst->xfer_func = pixmp->xfer_func;
279	}
280
281	memset(&format, 0, sizeof(format));
282
283	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
284	format.fmt.pix_mp.pixelformat = pixfmt_cap;
285	format.fmt.pix_mp.width = orig_pixmp.width;
286	format.fmt.pix_mp.height = orig_pixmp.height;
287	venc_try_fmt_common(inst, &format);
288
289	inst->width = format.fmt.pix_mp.width;
290	inst->height = format.fmt.pix_mp.height;
291
292	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
293		inst->fmt_out = fmt;
294	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
295		inst->fmt_cap = fmt;
296		inst->output_buf_size = pixmp->plane_fmt[0].sizeimage;
297	}
298
299	return 0;
300}
301
302static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
303{
304	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
305	struct venus_inst *inst = to_inst(file);
306	const struct venus_format *fmt;
307
308	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
309		fmt = inst->fmt_cap;
310	else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
311		fmt = inst->fmt_out;
312	else
313		return -EINVAL;
314
315	pixmp->pixelformat = fmt->pixfmt;
316
317	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
318		pixmp->width = inst->width;
319		pixmp->height = inst->height;
320		pixmp->colorspace = inst->colorspace;
321		pixmp->ycbcr_enc = inst->ycbcr_enc;
322		pixmp->quantization = inst->quantization;
323		pixmp->xfer_func = inst->xfer_func;
324	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
325		pixmp->width = inst->out_width;
326		pixmp->height = inst->out_height;
327	}
328
329	venc_try_fmt_common(inst, f);
330
331	return 0;
332}
333
334static int
335venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
336{
337	struct venus_inst *inst = to_inst(file);
338
339	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
340		return -EINVAL;
341
342	switch (s->target) {
343	case V4L2_SEL_TGT_CROP_DEFAULT:
344	case V4L2_SEL_TGT_CROP_BOUNDS:
345		s->r.width = inst->out_width;
346		s->r.height = inst->out_height;
347		break;
348	case V4L2_SEL_TGT_CROP:
349		s->r.width = inst->width;
350		s->r.height = inst->height;
351		break;
352	default:
353		return -EINVAL;
354	}
355
356	s->r.top = 0;
357	s->r.left = 0;
358
359	return 0;
360}
361
362static int
363venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
364{
365	struct venus_inst *inst = to_inst(file);
366
367	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
368		return -EINVAL;
369
370	if (s->r.width > inst->out_width ||
371	    s->r.height > inst->out_height)
372		return -EINVAL;
373
374	s->r.width = ALIGN(s->r.width, 2);
375	s->r.height = ALIGN(s->r.height, 2);
376
377	switch (s->target) {
378	case V4L2_SEL_TGT_CROP:
379		s->r.top = 0;
380		s->r.left = 0;
381		inst->width = s->r.width;
382		inst->height = s->r.height;
383		break;
384	default:
385		return -EINVAL;
386	}
387
388	return 0;
389}
390
391static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
392{
393	struct venus_inst *inst = to_inst(file);
394	struct v4l2_outputparm *out = &a->parm.output;
395	struct v4l2_fract *timeperframe = &out->timeperframe;
396	u64 us_per_frame, fps;
397
398	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
399	    a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
400		return -EINVAL;
401
402	memset(out->reserved, 0, sizeof(out->reserved));
403
404	if (!timeperframe->denominator)
405		timeperframe->denominator = inst->timeperframe.denominator;
406	if (!timeperframe->numerator)
407		timeperframe->numerator = inst->timeperframe.numerator;
408
409	out->capability = V4L2_CAP_TIMEPERFRAME;
410
411	us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
412	do_div(us_per_frame, timeperframe->denominator);
413
414	if (!us_per_frame)
415		return -EINVAL;
416
417	fps = (u64)USEC_PER_SEC;
418	do_div(fps, us_per_frame);
419
420	inst->timeperframe = *timeperframe;
421	inst->fps = fps;
422
423	return 0;
424}
425
426static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
427{
428	struct venus_inst *inst = to_inst(file);
429
430	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
431	    a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
432		return -EINVAL;
433
434	a->parm.output.capability |= V4L2_CAP_TIMEPERFRAME;
435	a->parm.output.timeperframe = inst->timeperframe;
436
437	return 0;
438}
439
440static int venc_enum_framesizes(struct file *file, void *fh,
441				struct v4l2_frmsizeenum *fsize)
442{
443	struct venus_inst *inst = to_inst(file);
444	const struct venus_format *fmt;
445
446	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
447
448	fmt = find_format(inst, fsize->pixel_format,
449			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
450	if (!fmt) {
451		fmt = find_format(inst, fsize->pixel_format,
452				  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
453		if (!fmt)
454			return -EINVAL;
455	}
456
457	if (fsize->index)
458		return -EINVAL;
459
460	fsize->stepwise.min_width = frame_width_min(inst);
461	fsize->stepwise.max_width = frame_width_max(inst);
462	fsize->stepwise.step_width = frame_width_step(inst);
463	fsize->stepwise.min_height = frame_height_min(inst);
464	fsize->stepwise.max_height = frame_height_max(inst);
465	fsize->stepwise.step_height = frame_height_step(inst);
466
467	return 0;
468}
469
470static int venc_enum_frameintervals(struct file *file, void *fh,
471				    struct v4l2_frmivalenum *fival)
472{
473	struct venus_inst *inst = to_inst(file);
474	const struct venus_format *fmt;
475	unsigned int framerate_factor = 1;
476
477	fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
478
479	fmt = find_format(inst, fival->pixel_format,
480			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
481	if (!fmt) {
482		fmt = find_format(inst, fival->pixel_format,
483				  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
484		if (!fmt)
485			return -EINVAL;
486	}
487
488	if (fival->index)
489		return -EINVAL;
490
491	if (!fival->width || !fival->height)
492		return -EINVAL;
493
494	if (fival->width > frame_width_max(inst) ||
495	    fival->width < frame_width_min(inst) ||
496	    fival->height > frame_height_max(inst) ||
497	    fival->height < frame_height_min(inst))
498		return -EINVAL;
499
500	if (IS_V1(inst->core)) {
501		/* framerate is reported in 1/65535 fps unit */
502		framerate_factor = (1 << 16);
503	}
504
505	fival->stepwise.min.numerator = 1;
506	fival->stepwise.min.denominator = frate_max(inst) / framerate_factor;
507	fival->stepwise.max.numerator = 1;
508	fival->stepwise.max.denominator = frate_min(inst) / framerate_factor;
509	fival->stepwise.step.numerator = 1;
510	fival->stepwise.step.denominator = frate_max(inst) / framerate_factor;
511
512	return 0;
513}
514
515static int venc_subscribe_event(struct v4l2_fh *fh,
516				const struct v4l2_event_subscription *sub)
517{
518	switch (sub->type) {
519	case V4L2_EVENT_EOS:
520		return v4l2_event_subscribe(fh, sub, 2, NULL);
521	case V4L2_EVENT_CTRL:
522		return v4l2_ctrl_subscribe_event(fh, sub);
523	default:
524		return -EINVAL;
525	}
526}
527
528static int
529venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd)
530{
531	struct venus_inst *inst = to_inst(file);
532	struct hfi_frame_data fdata = {0};
533	int ret = 0;
534
535	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);
536	if (ret)
537		return ret;
538
539	mutex_lock(&inst->lock);
540
541	if (cmd->cmd == V4L2_ENC_CMD_STOP &&
542	    inst->enc_state == VENUS_ENC_STATE_ENCODING) {
543		/*
544		 * Implement V4L2_ENC_CMD_STOP by enqueue an empty buffer on
545		 * encoder input to signal EOS.
546		 */
547		if (!(inst->streamon_out && inst->streamon_cap))
548			goto unlock;
549
550		fdata.buffer_type = HFI_BUFFER_INPUT;
551		fdata.flags |= HFI_BUFFERFLAG_EOS;
552		fdata.device_addr = 0xdeadb000;
553
554		ret = hfi_session_process_buf(inst, &fdata);
555
556		inst->enc_state = VENUS_ENC_STATE_DRAIN;
557	} else if (cmd->cmd == V4L2_ENC_CMD_START) {
558		if (inst->enc_state == VENUS_ENC_STATE_DRAIN) {
559			ret = -EBUSY;
560			goto unlock;
561		}
562		if (inst->enc_state == VENUS_ENC_STATE_STOPPED) {
563			vb2_clear_last_buffer_dequeued(&inst->fh.m2m_ctx->cap_q_ctx.q);
564			inst->enc_state = VENUS_ENC_STATE_ENCODING;
565		}
566	}
567
568unlock:
569	mutex_unlock(&inst->lock);
570	return ret;
571}
572
573static const struct v4l2_ioctl_ops venc_ioctl_ops = {
574	.vidioc_querycap = venc_querycap,
575	.vidioc_enum_fmt_vid_cap = venc_enum_fmt,
576	.vidioc_enum_fmt_vid_out = venc_enum_fmt,
577	.vidioc_s_fmt_vid_cap_mplane = venc_s_fmt,
578	.vidioc_s_fmt_vid_out_mplane = venc_s_fmt,
579	.vidioc_g_fmt_vid_cap_mplane = venc_g_fmt,
580	.vidioc_g_fmt_vid_out_mplane = venc_g_fmt,
581	.vidioc_try_fmt_vid_cap_mplane = venc_try_fmt,
582	.vidioc_try_fmt_vid_out_mplane = venc_try_fmt,
583	.vidioc_g_selection = venc_g_selection,
584	.vidioc_s_selection = venc_s_selection,
585	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
586	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
587	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
588	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
589	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
590	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
591	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
592	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
593	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
594	.vidioc_s_parm = venc_s_parm,
595	.vidioc_g_parm = venc_g_parm,
596	.vidioc_enum_framesizes = venc_enum_framesizes,
597	.vidioc_enum_frameintervals = venc_enum_frameintervals,
598	.vidioc_subscribe_event = venc_subscribe_event,
599	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
600	.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
601	.vidioc_encoder_cmd = venc_encoder_cmd,
602};
603
604static int venc_pm_get(struct venus_inst *inst)
605{
606	struct venus_core *core = inst->core;
607	struct device *dev = core->dev_enc;
608	int ret;
609
610	mutex_lock(&core->pm_lock);
611	ret = pm_runtime_resume_and_get(dev);
612	mutex_unlock(&core->pm_lock);
613
614	return ret < 0 ? ret : 0;
615}
616
617static int venc_pm_put(struct venus_inst *inst, bool autosuspend)
618{
619	struct venus_core *core = inst->core;
620	struct device *dev = core->dev_enc;
621	int ret;
622
623	mutex_lock(&core->pm_lock);
624
625	if (autosuspend)
626		ret = pm_runtime_put_autosuspend(dev);
627	else
628		ret = pm_runtime_put_sync(dev);
629
630	mutex_unlock(&core->pm_lock);
631
632	return ret < 0 ? ret : 0;
633}
634
635static int venc_pm_get_put(struct venus_inst *inst)
636{
637	struct venus_core *core = inst->core;
638	struct device *dev = core->dev_enc;
639	int ret = 0;
640
641	mutex_lock(&core->pm_lock);
642
643	if (pm_runtime_suspended(dev)) {
644		ret = pm_runtime_resume_and_get(dev);
645		if (ret < 0)
646			goto error;
647
648		ret = pm_runtime_put_autosuspend(dev);
649	}
650
651error:
652	mutex_unlock(&core->pm_lock);
653
654	return ret < 0 ? ret : 0;
655}
656
657static void venc_pm_touch(struct venus_inst *inst)
658{
659	pm_runtime_mark_last_busy(inst->core->dev_enc);
660}
661
662static int venc_set_properties(struct venus_inst *inst)
663{
664	struct venc_controls *ctr = &inst->controls.enc;
665	struct hfi_intra_period intra_period;
666	struct hfi_framerate frate;
667	struct hfi_bitrate brate;
668	struct hfi_idr_period idrp;
669	struct hfi_quantization quant;
670	struct hfi_quantization_range quant_range;
671	struct hfi_quantization_range_v2 quant_range_v2;
672	struct hfi_enable en;
673	struct hfi_ltr_mode ltr_mode;
674	struct hfi_intra_refresh intra_refresh = {};
675	u32 ptype, rate_control, bitrate;
676	u32 profile, level;
677	int ret;
678
679	ret = venus_helper_set_work_mode(inst);
680	if (ret)
681		return ret;
682
683	ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
684	frate.buffer_type = HFI_BUFFER_OUTPUT;
685	frate.framerate = inst->fps * (1 << 16);
686
687	ret = hfi_session_set_property(inst, ptype, &frate);
688	if (ret)
689		return ret;
690
691	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) {
692		struct hfi_h264_vui_timing_info info;
693		struct hfi_h264_entropy_control entropy;
694		struct hfi_h264_db_control deblock;
695		struct hfi_h264_8x8_transform h264_transform;
696
697		ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
698		info.enable = 1;
699		info.fixed_framerate = 1;
700		info.time_scale = NSEC_PER_SEC;
701
702		ret = hfi_session_set_property(inst, ptype, &info);
703		if (ret)
704			return ret;
705
706		ptype = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
707		entropy.entropy_mode = venc_v4l2_to_hfi(
708					  V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
709					  ctr->h264_entropy_mode);
710		entropy.cabac_model = HFI_H264_CABAC_MODEL_0;
711
712		ret = hfi_session_set_property(inst, ptype, &entropy);
713		if (ret)
714			return ret;
715
716		ptype = HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
717		deblock.mode = venc_v4l2_to_hfi(
718				      V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
719				      ctr->h264_loop_filter_mode);
720		deblock.slice_alpha_offset = ctr->h264_loop_filter_alpha;
721		deblock.slice_beta_offset = ctr->h264_loop_filter_beta;
722
723		ret = hfi_session_set_property(inst, ptype, &deblock);
724		if (ret)
725			return ret;
726
727		ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
728		h264_transform.enable_type = 0;
729		if (ctr->profile.h264 == V4L2_MPEG_VIDEO_H264_PROFILE_HIGH ||
730		    ctr->profile.h264 == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH)
731			h264_transform.enable_type = ctr->h264_8x8_transform;
732
733		ret = hfi_session_set_property(inst, ptype, &h264_transform);
734		if (ret)
735			return ret;
736
737	}
738
739	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
740	    inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
741		/* IDR periodicity, n:
742		 * n = 0 - only the first I-frame is IDR frame
743		 * n = 1 - all I-frames will be IDR frames
744		 * n > 1 - every n-th I-frame will be IDR frame
745		 */
746		ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
747		idrp.idr_period = 0;
748		ret = hfi_session_set_property(inst, ptype, &idrp);
749		if (ret)
750			return ret;
751	}
752
753	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC &&
754	    ctr->profile.hevc == V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10) {
755		struct hfi_hdr10_pq_sei hdr10;
756		unsigned int c;
757
758		ptype = HFI_PROPERTY_PARAM_VENC_HDR10_PQ_SEI;
759
760		for (c = 0; c < 3; c++) {
761			hdr10.mastering.display_primaries_x[c] =
762				ctr->mastering.display_primaries_x[c];
763			hdr10.mastering.display_primaries_y[c] =
764				ctr->mastering.display_primaries_y[c];
765		}
766
767		hdr10.mastering.white_point_x = ctr->mastering.white_point_x;
768		hdr10.mastering.white_point_y = ctr->mastering.white_point_y;
769		hdr10.mastering.max_display_mastering_luminance =
770			ctr->mastering.max_display_mastering_luminance;
771		hdr10.mastering.min_display_mastering_luminance =
772			ctr->mastering.min_display_mastering_luminance;
773
774		hdr10.cll.max_content_light = ctr->cll.max_content_light_level;
775		hdr10.cll.max_pic_average_light =
776			ctr->cll.max_pic_average_light_level;
777
778		ret = hfi_session_set_property(inst, ptype, &hdr10);
779		if (ret)
780			return ret;
781	}
782
783	if (ctr->num_b_frames) {
784		u32 max_num_b_frames = NUM_B_FRAMES_MAX;
785
786		ptype = HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES;
787		ret = hfi_session_set_property(inst, ptype, &max_num_b_frames);
788		if (ret)
789			return ret;
790	}
791
792	ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
793	intra_period.pframes = ctr->num_p_frames;
794	intra_period.bframes = ctr->num_b_frames;
795
796	ret = hfi_session_set_property(inst, ptype, &intra_period);
797	if (ret)
798		return ret;
799
800	if (!ctr->rc_enable)
801		rate_control = HFI_RATE_CONTROL_OFF;
802	else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
803		rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_VBR_VFR :
804						      HFI_RATE_CONTROL_VBR_CFR;
805	else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
806		rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_CBR_VFR :
807						      HFI_RATE_CONTROL_CBR_CFR;
808	else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
809		rate_control = HFI_RATE_CONTROL_CQ;
810
811	ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
812	ret = hfi_session_set_property(inst, ptype, &rate_control);
813	if (ret)
814		return ret;
815
816	if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) {
817		struct hfi_heic_frame_quality quality = {};
818
819		ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
820		quality.frame_quality = ctr->const_quality;
821		ret = hfi_session_set_property(inst, ptype, &quality);
822		if (ret)
823			return ret;
824	}
825
826	if (!ctr->bitrate)
827		bitrate = 64000;
828	else
829		bitrate = ctr->bitrate;
830
831	ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
832	brate.bitrate = bitrate;
833	brate.layer_id = 0;
834
835	ret = hfi_session_set_property(inst, ptype, &brate);
836	if (ret)
837		return ret;
838
839	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
840	    inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
841		ptype = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
842		if (ctr->header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)
843			en.enable = 0;
844		else
845			en.enable = 1;
846
847		ret = hfi_session_set_property(inst, ptype, &en);
848		if (ret)
849			return ret;
850	}
851
852	if (!ctr->bitrate_peak)
853		bitrate *= 2;
854	else
855		bitrate = ctr->bitrate_peak;
856
857	ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
858	brate.bitrate = bitrate;
859	brate.layer_id = 0;
860
861	ret = hfi_session_set_property(inst, ptype, &brate);
862	if (ret)
863		return ret;
864
865	ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP;
866	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
867		quant.qp_i = ctr->hevc_i_qp;
868		quant.qp_p = ctr->hevc_p_qp;
869		quant.qp_b = ctr->hevc_b_qp;
870	} else {
871		quant.qp_i = ctr->h264_i_qp;
872		quant.qp_p = ctr->h264_p_qp;
873		quant.qp_b = ctr->h264_b_qp;
874	}
875	quant.layer_id = 0;
876	ret = hfi_session_set_property(inst, ptype, &quant);
877	if (ret)
878		return ret;
879
880	if (inst->core->res->hfi_version == HFI_VERSION_4XX ||
881	    inst->core->res->hfi_version == HFI_VERSION_6XX) {
882		ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2;
883
884		if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
885			quant_range_v2.min_qp.qp_packed = ctr->hevc_min_qp;
886			quant_range_v2.max_qp.qp_packed = ctr->hevc_max_qp;
887		} else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) {
888			quant_range_v2.min_qp.qp_packed = ctr->vp8_min_qp;
889			quant_range_v2.max_qp.qp_packed = ctr->vp8_max_qp;
890		} else {
891			quant_range_v2.min_qp.qp_packed = ctr->h264_min_qp;
892			quant_range_v2.max_qp.qp_packed = ctr->h264_max_qp;
893		}
894
895		ret = hfi_session_set_property(inst, ptype, &quant_range_v2);
896	} else {
897		ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
898
899		if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
900			quant_range.min_qp = ctr->hevc_min_qp;
901			quant_range.max_qp = ctr->hevc_max_qp;
902		} else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) {
903			quant_range.min_qp = ctr->vp8_min_qp;
904			quant_range.max_qp = ctr->vp8_max_qp;
905		} else {
906			quant_range.min_qp = ctr->h264_min_qp;
907			quant_range.max_qp = ctr->h264_max_qp;
908		}
909
910		quant_range.layer_id = 0;
911		ret = hfi_session_set_property(inst, ptype, &quant_range);
912	}
913
914	if (ret)
915		return ret;
916
917	ptype = HFI_PROPERTY_PARAM_VENC_LTRMODE;
918	ltr_mode.ltr_count = ctr->ltr_count;
919	ltr_mode.ltr_mode = HFI_LTR_MODE_MANUAL;
920	ltr_mode.trust_mode = 1;
921	ret = hfi_session_set_property(inst, ptype, &ltr_mode);
922	if (ret)
923		return ret;
924
925	switch (inst->hfi_codec) {
926	case HFI_VIDEO_CODEC_H264:
927		profile = ctr->profile.h264;
928		level = ctr->level.h264;
929		break;
930	case HFI_VIDEO_CODEC_MPEG4:
931		profile = ctr->profile.mpeg4;
932		level = ctr->level.mpeg4;
933		break;
934	case HFI_VIDEO_CODEC_VP8:
935		profile = ctr->profile.vp8;
936		level = 0;
937		break;
938	case HFI_VIDEO_CODEC_VP9:
939		profile = ctr->profile.vp9;
940		level = ctr->level.vp9;
941		break;
942	case HFI_VIDEO_CODEC_HEVC:
943		profile = ctr->profile.hevc;
944		level = ctr->level.hevc;
945		break;
946	case HFI_VIDEO_CODEC_MPEG2:
947	default:
948		profile = 0;
949		level = 0;
950		break;
951	}
952
953	ret = venus_helper_set_profile_level(inst, profile, level);
954	if (ret)
955		return ret;
956
957	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
958	    inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
959		struct hfi_enable en = {};
960
961		ptype = HFI_PROPERTY_PARAM_VENC_H264_GENERATE_AUDNAL;
962
963		if (ctr->aud_enable)
964			en.enable = 1;
965
966		ret = hfi_session_set_property(inst, ptype, &en);
967	}
968
969	if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
970	     inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) &&
971	    (rate_control == HFI_RATE_CONTROL_CBR_VFR ||
972	     rate_control == HFI_RATE_CONTROL_CBR_CFR)) {
973		intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
974		intra_refresh.cir_mbs = 0;
975
976		if (ctr->intra_refresh_period) {
977			u32 mbs;
978
979			mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16);
980			mbs /= 16 * 16;
981			if (mbs % ctr->intra_refresh_period)
982				mbs++;
983			mbs /= ctr->intra_refresh_period;
984
985			intra_refresh.cir_mbs = mbs;
986			if (ctr->intra_refresh_type ==
987			    V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC)
988				intra_refresh.mode = HFI_INTRA_REFRESH_CYCLIC;
989			else
990				intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
991		}
992
993		ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
994
995		ret = hfi_session_set_property(inst, ptype, &intra_refresh);
996		if (ret)
997			return ret;
998	}
999
1000	return 0;
1001}
1002
1003static int venc_init_session(struct venus_inst *inst)
1004{
1005	int ret;
1006
1007	ret = venus_helper_session_init(inst);
1008	if (ret == -EALREADY)
1009		return 0;
1010	else if (ret)
1011		return ret;
1012
1013	ret = venus_helper_set_stride(inst, inst->out_width,
1014				      inst->out_height);
1015	if (ret)
1016		goto deinit;
1017
1018	ret = venus_helper_set_input_resolution(inst, inst->width,
1019						inst->height);
1020	if (ret)
1021		goto deinit;
1022
1023	ret = venus_helper_set_output_resolution(inst, inst->width,
1024						 inst->height,
1025						 HFI_BUFFER_OUTPUT);
1026	if (ret)
1027		goto deinit;
1028
1029	ret = venus_helper_set_color_format(inst, inst->fmt_out->pixfmt);
1030	if (ret)
1031		goto deinit;
1032
1033	ret = venc_set_properties(inst);
1034	if (ret)
1035		goto deinit;
1036
1037	return 0;
1038deinit:
1039	hfi_session_deinit(inst);
1040	return ret;
1041}
1042
1043static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num)
1044{
1045	struct hfi_buffer_requirements bufreq;
1046	int ret;
1047
1048	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
1049	if (ret)
1050		return ret;
1051
1052	*num = bufreq.count_actual;
1053
1054	return 0;
1055}
1056
1057static int venc_queue_setup(struct vb2_queue *q,
1058			    unsigned int *num_buffers, unsigned int *num_planes,
1059			    unsigned int sizes[], struct device *alloc_devs[])
1060{
1061	struct venus_inst *inst = vb2_get_drv_priv(q);
1062	struct venus_core *core = inst->core;
1063	unsigned int num, min = 4;
1064	int ret;
1065
1066	if (*num_planes) {
1067		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1068		    *num_planes != inst->fmt_out->num_planes)
1069			return -EINVAL;
1070
1071		if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
1072		    *num_planes != inst->fmt_cap->num_planes)
1073			return -EINVAL;
1074
1075		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1076		    sizes[0] < inst->input_buf_size)
1077			return -EINVAL;
1078
1079		if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
1080		    sizes[0] < inst->output_buf_size)
1081			return -EINVAL;
1082
1083		return 0;
1084	}
1085
1086	if (test_bit(0, &core->sys_error)) {
1087		if (inst->nonblock)
1088			return -EAGAIN;
1089
1090		ret = wait_event_interruptible(core->sys_err_done,
1091					       !test_bit(0, &core->sys_error));
1092		if (ret)
1093			return ret;
1094	}
1095
1096	ret = venc_pm_get(inst);
1097	if (ret)
1098		return ret;
1099
1100	mutex_lock(&inst->lock);
1101	ret = venc_init_session(inst);
1102	mutex_unlock(&inst->lock);
1103
1104	if (ret)
1105		goto put_power;
1106
1107	ret = venc_pm_put(inst, false);
1108	if (ret)
1109		return ret;
1110
1111	switch (q->type) {
1112	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1113		*num_planes = inst->fmt_out->num_planes;
1114
1115		ret = venc_out_num_buffers(inst, &num);
1116		if (ret)
1117			break;
1118
1119		num = max(num, min);
1120		*num_buffers = max(*num_buffers, num);
1121		inst->num_input_bufs = *num_buffers;
1122
1123		sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
1124						    inst->out_width,
1125						    inst->out_height);
1126		inst->input_buf_size = sizes[0];
1127		break;
1128	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1129		*num_planes = inst->fmt_cap->num_planes;
1130		*num_buffers = max(*num_buffers, min);
1131		inst->num_output_bufs = *num_buffers;
1132		sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
1133						    inst->width,
1134						    inst->height);
1135		sizes[0] = max(sizes[0], inst->output_buf_size);
1136		inst->output_buf_size = sizes[0];
1137		break;
1138	default:
1139		ret = -EINVAL;
1140		break;
1141	}
1142
1143	return ret;
1144put_power:
1145	venc_pm_put(inst, false);
1146	return ret;
1147}
1148
1149static int venc_buf_init(struct vb2_buffer *vb)
1150{
1151	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1152
1153	inst->buf_count++;
1154
1155	return venus_helper_vb2_buf_init(vb);
1156}
1157
1158static void venc_release_session(struct venus_inst *inst)
1159{
1160	int ret;
1161
1162	venc_pm_get(inst);
1163
1164	mutex_lock(&inst->lock);
1165
1166	ret = hfi_session_deinit(inst);
1167	if (ret || inst->session_error)
1168		hfi_session_abort(inst);
1169
1170	mutex_unlock(&inst->lock);
1171
1172	venus_pm_load_scale(inst);
1173	INIT_LIST_HEAD(&inst->registeredbufs);
1174	venus_pm_release_core(inst);
1175
1176	venc_pm_put(inst, false);
1177}
1178
1179static void venc_buf_cleanup(struct vb2_buffer *vb)
1180{
1181	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1182	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1183	struct venus_buffer *buf = to_venus_buffer(vbuf);
1184
1185	mutex_lock(&inst->lock);
1186	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1187		if (!list_empty(&inst->registeredbufs))
1188			list_del_init(&buf->reg_list);
1189	mutex_unlock(&inst->lock);
1190
1191	inst->buf_count--;
1192	if (!inst->buf_count)
1193		venc_release_session(inst);
1194}
1195
1196static int venc_verify_conf(struct venus_inst *inst)
1197{
1198	enum hfi_version ver = inst->core->res->hfi_version;
1199	struct hfi_buffer_requirements bufreq;
1200	int ret;
1201
1202	if (!inst->num_input_bufs || !inst->num_output_bufs)
1203		return -EINVAL;
1204
1205	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
1206	if (ret)
1207		return ret;
1208
1209	if (inst->num_output_bufs < bufreq.count_actual ||
1210	    inst->num_output_bufs < hfi_bufreq_get_count_min(&bufreq, ver))
1211		return -EINVAL;
1212
1213	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
1214	if (ret)
1215		return ret;
1216
1217	if (inst->num_input_bufs < bufreq.count_actual ||
1218	    inst->num_input_bufs < hfi_bufreq_get_count_min(&bufreq, ver))
1219		return -EINVAL;
1220
1221	return 0;
1222}
1223
1224static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
1225{
1226	struct venus_inst *inst = vb2_get_drv_priv(q);
1227	int ret;
1228
1229	mutex_lock(&inst->lock);
1230
1231	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1232		inst->streamon_out = 1;
1233	else
1234		inst->streamon_cap = 1;
1235
1236	if (!(inst->streamon_out & inst->streamon_cap)) {
1237		mutex_unlock(&inst->lock);
1238		return 0;
1239	}
1240
1241	venus_helper_init_instance(inst);
1242
1243	inst->sequence_cap = 0;
1244	inst->sequence_out = 0;
1245
1246	ret = venc_pm_get(inst);
1247	if (ret)
1248		goto error;
1249
1250	ret = venus_pm_acquire_core(inst);
1251	if (ret)
1252		goto put_power;
1253
1254	ret = venc_pm_put(inst, true);
1255	if (ret)
1256		goto error;
1257
1258	ret = venc_set_properties(inst);
1259	if (ret)
1260		goto error;
1261
1262	ret = venc_verify_conf(inst);
1263	if (ret)
1264		goto error;
1265
1266	ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
1267					inst->num_output_bufs, 0);
1268	if (ret)
1269		goto error;
1270
1271	ret = venus_helper_vb2_start_streaming(inst);
1272	if (ret)
1273		goto error;
1274
1275	inst->enc_state = VENUS_ENC_STATE_ENCODING;
1276
1277	mutex_unlock(&inst->lock);
1278
1279	return 0;
1280
1281put_power:
1282	venc_pm_put(inst, false);
1283error:
1284	venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
1285	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1286		inst->streamon_out = 0;
1287	else
1288		inst->streamon_cap = 0;
1289	mutex_unlock(&inst->lock);
1290	return ret;
1291}
1292
1293static void venc_vb2_buf_queue(struct vb2_buffer *vb)
1294{
1295	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1296	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1297
1298	venc_pm_get_put(inst);
1299
1300	mutex_lock(&inst->lock);
1301
1302	if (inst->enc_state == VENUS_ENC_STATE_STOPPED) {
1303		vbuf->sequence = inst->sequence_cap++;
1304		vbuf->field = V4L2_FIELD_NONE;
1305		vb2_set_plane_payload(vb, 0, 0);
1306		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
1307		mutex_unlock(&inst->lock);
1308		return;
1309	}
1310
1311	venus_helper_vb2_buf_queue(vb);
1312	mutex_unlock(&inst->lock);
1313}
1314
1315static const struct vb2_ops venc_vb2_ops = {
1316	.queue_setup = venc_queue_setup,
1317	.buf_init = venc_buf_init,
1318	.buf_cleanup = venc_buf_cleanup,
1319	.buf_prepare = venus_helper_vb2_buf_prepare,
1320	.start_streaming = venc_start_streaming,
1321	.stop_streaming = venus_helper_vb2_stop_streaming,
1322	.buf_queue = venc_vb2_buf_queue,
1323};
1324
1325static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
1326			  u32 tag, u32 bytesused, u32 data_offset, u32 flags,
1327			  u32 hfi_flags, u64 timestamp_us)
1328{
1329	struct vb2_v4l2_buffer *vbuf;
1330	struct vb2_buffer *vb;
1331	unsigned int type;
1332
1333	venc_pm_touch(inst);
1334
1335	if (buf_type == HFI_BUFFER_INPUT)
1336		type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1337	else
1338		type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1339
1340	vbuf = venus_helper_find_buf(inst, type, tag);
1341	if (!vbuf)
1342		return;
1343
1344	vbuf->flags = flags;
1345
1346	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1347		vb = &vbuf->vb2_buf;
1348		vb2_set_plane_payload(vb, 0, bytesused + data_offset);
1349		vb->planes[0].data_offset = data_offset;
1350		vb->timestamp = timestamp_us * NSEC_PER_USEC;
1351		vbuf->sequence = inst->sequence_cap++;
1352		if ((vbuf->flags & V4L2_BUF_FLAG_LAST) &&
1353		    inst->enc_state == VENUS_ENC_STATE_DRAIN) {
1354			inst->enc_state = VENUS_ENC_STATE_STOPPED;
1355		}
1356	} else {
1357		vbuf->sequence = inst->sequence_out++;
1358	}
1359
1360	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
1361}
1362
1363static void venc_event_notify(struct venus_inst *inst, u32 event,
1364			      struct hfi_event_data *data)
1365{
1366	struct device *dev = inst->core->dev_enc;
1367
1368	venc_pm_touch(inst);
1369
1370	if (event == EVT_SESSION_ERROR) {
1371		inst->session_error = true;
1372		venus_helper_vb2_queue_error(inst);
1373		dev_err(dev, "enc: event session error %x\n", inst->error);
1374	}
1375}
1376
1377static const struct hfi_inst_ops venc_hfi_ops = {
1378	.buf_done = venc_buf_done,
1379	.event_notify = venc_event_notify,
1380};
1381
1382static const struct v4l2_m2m_ops venc_m2m_ops = {
1383	.device_run = venus_helper_m2m_device_run,
1384	.job_abort = venus_helper_m2m_job_abort,
1385};
1386
1387static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
1388			  struct vb2_queue *dst_vq)
1389{
1390	struct venus_inst *inst = priv;
1391	int ret;
1392
1393	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1394	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1395	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1396	src_vq->ops = &venc_vb2_ops;
1397	src_vq->mem_ops = &vb2_dma_contig_memops;
1398	src_vq->drv_priv = inst;
1399	src_vq->buf_struct_size = sizeof(struct venus_buffer);
1400	src_vq->allow_zero_bytesused = 1;
1401	src_vq->min_queued_buffers = 1;
1402	src_vq->dev = inst->core->dev;
1403	src_vq->lock = &inst->ctx_q_lock;
1404	if (inst->core->res->hfi_version == HFI_VERSION_1XX)
1405		src_vq->bidirectional = 1;
1406	ret = vb2_queue_init(src_vq);
1407	if (ret)
1408		return ret;
1409
1410	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1411	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1412	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1413	dst_vq->ops = &venc_vb2_ops;
1414	dst_vq->mem_ops = &vb2_dma_contig_memops;
1415	dst_vq->drv_priv = inst;
1416	dst_vq->buf_struct_size = sizeof(struct venus_buffer);
1417	dst_vq->allow_zero_bytesused = 1;
1418	dst_vq->min_queued_buffers = 1;
1419	dst_vq->dev = inst->core->dev;
1420	dst_vq->lock = &inst->ctx_q_lock;
1421	return vb2_queue_init(dst_vq);
1422}
1423
1424static void venc_inst_init(struct venus_inst *inst)
1425{
1426	inst->fmt_cap = &venc_formats[VENUS_FMT_H264];
1427	inst->fmt_out = &venc_formats[VENUS_FMT_NV12];
1428	inst->width = 1280;
1429	inst->height = ALIGN(720, 32);
1430	inst->out_width = 1280;
1431	inst->out_height = 720;
1432	inst->fps = 15;
1433	inst->timeperframe.numerator = 1;
1434	inst->timeperframe.denominator = 15;
1435	inst->hfi_codec = HFI_VIDEO_CODEC_H264;
1436}
1437
1438static int venc_open(struct file *file)
1439{
1440	struct venus_core *core = video_drvdata(file);
1441	struct venus_inst *inst;
1442	int ret;
1443
1444	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1445	if (!inst)
1446		return -ENOMEM;
1447
1448	INIT_LIST_HEAD(&inst->dpbbufs);
1449	INIT_LIST_HEAD(&inst->registeredbufs);
1450	INIT_LIST_HEAD(&inst->internalbufs);
1451	INIT_LIST_HEAD(&inst->list);
1452	mutex_init(&inst->lock);
1453	mutex_init(&inst->ctx_q_lock);
1454
1455	inst->core = core;
1456	inst->session_type = VIDC_SESSION_TYPE_ENC;
1457	inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
1458	inst->core_acquired = false;
1459	inst->nonblock = file->f_flags & O_NONBLOCK;
1460
1461	if (inst->enc_state == VENUS_ENC_STATE_DEINIT)
1462		inst->enc_state = VENUS_ENC_STATE_INIT;
1463
1464	venus_helper_init_instance(inst);
1465
1466	ret = venc_ctrl_init(inst);
1467	if (ret)
1468		goto err_free;
1469
1470	ret = hfi_session_create(inst, &venc_hfi_ops);
1471	if (ret)
1472		goto err_ctrl_deinit;
1473
1474	venc_inst_init(inst);
1475
1476	/*
1477	 * create m2m device for every instance, the m2m context scheduling
1478	 * is made by firmware side so we do not need to care about.
1479	 */
1480	inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops);
1481	if (IS_ERR(inst->m2m_dev)) {
1482		ret = PTR_ERR(inst->m2m_dev);
1483		goto err_session_destroy;
1484	}
1485
1486	inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
1487	if (IS_ERR(inst->m2m_ctx)) {
1488		ret = PTR_ERR(inst->m2m_ctx);
1489		goto err_m2m_release;
1490	}
1491
1492	v4l2_fh_init(&inst->fh, core->vdev_enc);
1493
1494	inst->fh.ctrl_handler = &inst->ctrl_handler;
1495	v4l2_fh_add(&inst->fh);
1496	inst->fh.m2m_ctx = inst->m2m_ctx;
1497	file->private_data = &inst->fh;
1498
1499	return 0;
1500
1501err_m2m_release:
1502	v4l2_m2m_release(inst->m2m_dev);
1503err_session_destroy:
1504	hfi_session_destroy(inst);
1505err_ctrl_deinit:
1506	venc_ctrl_deinit(inst);
1507err_free:
1508	kfree(inst);
1509	return ret;
1510}
1511
1512static int venc_close(struct file *file)
1513{
1514	struct venus_inst *inst = to_inst(file);
1515
1516	venc_pm_get(inst);
1517
1518	v4l2_m2m_ctx_release(inst->m2m_ctx);
1519	v4l2_m2m_release(inst->m2m_dev);
1520	venc_ctrl_deinit(inst);
1521	hfi_session_destroy(inst);
1522	mutex_destroy(&inst->lock);
1523	mutex_destroy(&inst->ctx_q_lock);
1524	v4l2_fh_del(&inst->fh);
1525	v4l2_fh_exit(&inst->fh);
1526
1527	inst->enc_state = VENUS_ENC_STATE_DEINIT;
1528
1529	venc_pm_put(inst, false);
1530
1531	kfree(inst);
1532	return 0;
1533}
1534
1535static const struct v4l2_file_operations venc_fops = {
1536	.owner = THIS_MODULE,
1537	.open = venc_open,
1538	.release = venc_close,
1539	.unlocked_ioctl = video_ioctl2,
1540	.poll = v4l2_m2m_fop_poll,
1541	.mmap = v4l2_m2m_fop_mmap,
1542};
1543
1544static int venc_probe(struct platform_device *pdev)
1545{
1546	struct device *dev = &pdev->dev;
1547	struct video_device *vdev;
1548	struct venus_core *core;
1549	int ret;
1550
1551	if (!dev->parent)
1552		return -EPROBE_DEFER;
1553
1554	core = dev_get_drvdata(dev->parent);
1555	if (!core)
1556		return -EPROBE_DEFER;
1557
1558	platform_set_drvdata(pdev, core);
1559
1560	if (core->pm_ops->venc_get) {
1561		ret = core->pm_ops->venc_get(dev);
1562		if (ret)
1563			return ret;
1564	}
1565
1566	vdev = video_device_alloc();
1567	if (!vdev)
1568		return -ENOMEM;
1569
1570	strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
1571	vdev->release = video_device_release;
1572	vdev->fops = &venc_fops;
1573	vdev->ioctl_ops = &venc_ioctl_ops;
1574	vdev->vfl_dir = VFL_DIR_M2M;
1575	vdev->v4l2_dev = &core->v4l2_dev;
1576	vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1577
1578	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1579	if (ret)
1580		goto err_vdev_release;
1581
1582	core->vdev_enc = vdev;
1583	core->dev_enc = dev;
1584
1585	video_set_drvdata(vdev, core);
1586	pm_runtime_set_autosuspend_delay(dev, 2000);
1587	pm_runtime_use_autosuspend(dev);
1588	pm_runtime_enable(dev);
1589
1590	return 0;
1591
1592err_vdev_release:
1593	video_device_release(vdev);
1594	return ret;
1595}
1596
1597static void venc_remove(struct platform_device *pdev)
1598{
1599	struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
1600
1601	video_unregister_device(core->vdev_enc);
1602	pm_runtime_disable(core->dev_enc);
1603
1604	if (core->pm_ops->venc_put)
1605		core->pm_ops->venc_put(core->dev_enc);
1606}
1607
1608static __maybe_unused int venc_runtime_suspend(struct device *dev)
1609{
1610	struct venus_core *core = dev_get_drvdata(dev);
1611	const struct venus_pm_ops *pm_ops = core->pm_ops;
1612	int ret = 0;
1613
1614	if (pm_ops->venc_power)
1615		ret = pm_ops->venc_power(dev, POWER_OFF);
1616
1617	return ret;
1618}
1619
1620static __maybe_unused int venc_runtime_resume(struct device *dev)
1621{
1622	struct venus_core *core = dev_get_drvdata(dev);
1623	const struct venus_pm_ops *pm_ops = core->pm_ops;
1624	int ret = 0;
1625
1626	if (pm_ops->venc_power)
1627		ret = pm_ops->venc_power(dev, POWER_ON);
1628
1629	return ret;
1630}
1631
1632static const struct dev_pm_ops venc_pm_ops = {
1633	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1634				pm_runtime_force_resume)
1635	SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL)
1636};
1637
1638static const struct of_device_id venc_dt_match[] = {
1639	{ .compatible = "venus-encoder" },
1640	{ }
1641};
1642MODULE_DEVICE_TABLE(of, venc_dt_match);
1643
1644static struct platform_driver qcom_venus_enc_driver = {
1645	.probe = venc_probe,
1646	.remove_new = venc_remove,
1647	.driver = {
1648		.name = "qcom-venus-encoder",
1649		.of_match_table = venc_dt_match,
1650		.pm = &venc_pm_ops,
1651	},
1652};
1653module_platform_driver(qcom_venus_enc_driver);
1654
1655MODULE_ALIAS("platform:qcom-venus-encoder");
1656MODULE_DESCRIPTION("Qualcomm Venus video encoder driver");
1657MODULE_LICENSE("GPL v2");
1658