18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
48c2ecf20Sopenharmony_ci * Copyright (C) 2017 Linaro Ltd.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci#include <linux/clk.h>
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
98c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
108c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include <media/v4l2-mem2mem.h>
138c2ecf20Sopenharmony_ci#include <media/videobuf2-dma-sg.h>
148c2ecf20Sopenharmony_ci#include <media/v4l2-ioctl.h>
158c2ecf20Sopenharmony_ci#include <media/v4l2-event.h>
168c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "hfi_venus_io.h"
198c2ecf20Sopenharmony_ci#include "hfi_parser.h"
208c2ecf20Sopenharmony_ci#include "core.h"
218c2ecf20Sopenharmony_ci#include "helpers.h"
228c2ecf20Sopenharmony_ci#include "venc.h"
238c2ecf20Sopenharmony_ci#include "pm_helpers.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define NUM_B_FRAMES_MAX	4
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/*
288c2ecf20Sopenharmony_ci * Three resons to keep MPLANE formats (despite that the number of planes
298c2ecf20Sopenharmony_ci * currently is one):
308c2ecf20Sopenharmony_ci * - the MPLANE formats allow only one plane to be used
318c2ecf20Sopenharmony_ci * - the downstream driver use MPLANE formats too
328c2ecf20Sopenharmony_ci * - future firmware versions could add support for >1 planes
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_cistatic const struct venus_format venc_formats[] = {
358c2ecf20Sopenharmony_ci	{
368c2ecf20Sopenharmony_ci		.pixfmt = V4L2_PIX_FMT_NV12,
378c2ecf20Sopenharmony_ci		.num_planes = 1,
388c2ecf20Sopenharmony_ci		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
398c2ecf20Sopenharmony_ci	}, {
408c2ecf20Sopenharmony_ci		.pixfmt = V4L2_PIX_FMT_MPEG4,
418c2ecf20Sopenharmony_ci		.num_planes = 1,
428c2ecf20Sopenharmony_ci		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
438c2ecf20Sopenharmony_ci	}, {
448c2ecf20Sopenharmony_ci		.pixfmt = V4L2_PIX_FMT_H263,
458c2ecf20Sopenharmony_ci		.num_planes = 1,
468c2ecf20Sopenharmony_ci		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
478c2ecf20Sopenharmony_ci	}, {
488c2ecf20Sopenharmony_ci		.pixfmt = V4L2_PIX_FMT_H264,
498c2ecf20Sopenharmony_ci		.num_planes = 1,
508c2ecf20Sopenharmony_ci		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
518c2ecf20Sopenharmony_ci	}, {
528c2ecf20Sopenharmony_ci		.pixfmt = V4L2_PIX_FMT_VP8,
538c2ecf20Sopenharmony_ci		.num_planes = 1,
548c2ecf20Sopenharmony_ci		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
558c2ecf20Sopenharmony_ci	}, {
568c2ecf20Sopenharmony_ci		.pixfmt = V4L2_PIX_FMT_HEVC,
578c2ecf20Sopenharmony_ci		.num_planes = 1,
588c2ecf20Sopenharmony_ci		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
598c2ecf20Sopenharmony_ci	},
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic const struct venus_format *
638c2ecf20Sopenharmony_cifind_format(struct venus_inst *inst, u32 pixfmt, u32 type)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	const struct venus_format *fmt = venc_formats;
668c2ecf20Sopenharmony_ci	unsigned int size = ARRAY_SIZE(venc_formats);
678c2ecf20Sopenharmony_ci	unsigned int i;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	for (i = 0; i < size; i++) {
708c2ecf20Sopenharmony_ci		if (fmt[i].pixfmt == pixfmt)
718c2ecf20Sopenharmony_ci			break;
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	if (i == size || fmt[i].type != type)
758c2ecf20Sopenharmony_ci		return NULL;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
788c2ecf20Sopenharmony_ci	    !venus_helper_check_codec(inst, fmt[i].pixfmt))
798c2ecf20Sopenharmony_ci		return NULL;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	return &fmt[i];
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic const struct venus_format *
858c2ecf20Sopenharmony_cifind_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	const struct venus_format *fmt = venc_formats;
888c2ecf20Sopenharmony_ci	unsigned int size = ARRAY_SIZE(venc_formats);
898c2ecf20Sopenharmony_ci	unsigned int i, k = 0;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	if (index > size)
928c2ecf20Sopenharmony_ci		return NULL;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	for (i = 0; i < size; i++) {
958c2ecf20Sopenharmony_ci		bool valid;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci		if (fmt[i].type != type)
988c2ecf20Sopenharmony_ci			continue;
998c2ecf20Sopenharmony_ci		valid = type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
1008c2ecf20Sopenharmony_ci			venus_helper_check_codec(inst, fmt[i].pixfmt);
1018c2ecf20Sopenharmony_ci		if (k == index && valid)
1028c2ecf20Sopenharmony_ci			break;
1038c2ecf20Sopenharmony_ci		if (valid)
1048c2ecf20Sopenharmony_ci			k++;
1058c2ecf20Sopenharmony_ci	}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	if (i == size)
1088c2ecf20Sopenharmony_ci		return NULL;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	return &fmt[i];
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic int venc_v4l2_to_hfi(int id, int value)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	switch (id) {
1168c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
1178c2ecf20Sopenharmony_ci		switch (value) {
1188c2ecf20Sopenharmony_ci		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
1198c2ecf20Sopenharmony_ci		default:
1208c2ecf20Sopenharmony_ci			return HFI_H264_ENTROPY_CAVLC;
1218c2ecf20Sopenharmony_ci		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
1228c2ecf20Sopenharmony_ci			return HFI_H264_ENTROPY_CABAC;
1238c2ecf20Sopenharmony_ci		}
1248c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
1258c2ecf20Sopenharmony_ci		switch (value) {
1268c2ecf20Sopenharmony_ci		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
1278c2ecf20Sopenharmony_ci		default:
1288c2ecf20Sopenharmony_ci			return HFI_H264_DB_MODE_ALL_BOUNDARY;
1298c2ecf20Sopenharmony_ci		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
1308c2ecf20Sopenharmony_ci			return HFI_H264_DB_MODE_DISABLE;
1318c2ecf20Sopenharmony_ci		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
1328c2ecf20Sopenharmony_ci			return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
1338c2ecf20Sopenharmony_ci		}
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	return 0;
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic int
1408c2ecf20Sopenharmony_civenc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
1438c2ecf20Sopenharmony_ci	strscpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card));
1448c2ecf20Sopenharmony_ci	strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	return 0;
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
1528c2ecf20Sopenharmony_ci	const struct venus_format *fmt;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	fmt = find_format_by_index(inst, f->index, f->type);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	memset(f->reserved, 0, sizeof(f->reserved));
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	if (!fmt)
1598c2ecf20Sopenharmony_ci		return -EINVAL;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	f->pixelformat = fmt->pixfmt;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	return 0;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic const struct venus_format *
1678c2ecf20Sopenharmony_civenc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
1708c2ecf20Sopenharmony_ci	struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt;
1718c2ecf20Sopenharmony_ci	const struct venus_format *fmt;
1728c2ecf20Sopenharmony_ci	u32 sizeimage;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
1758c2ecf20Sopenharmony_ci	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	fmt = find_format(inst, pixmp->pixelformat, f->type);
1788c2ecf20Sopenharmony_ci	if (!fmt) {
1798c2ecf20Sopenharmony_ci		if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1808c2ecf20Sopenharmony_ci			pixmp->pixelformat = V4L2_PIX_FMT_H264;
1818c2ecf20Sopenharmony_ci		else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1828c2ecf20Sopenharmony_ci			pixmp->pixelformat = V4L2_PIX_FMT_NV12;
1838c2ecf20Sopenharmony_ci		else
1848c2ecf20Sopenharmony_ci			return NULL;
1858c2ecf20Sopenharmony_ci		fmt = find_format(inst, pixmp->pixelformat, f->type);
1868c2ecf20Sopenharmony_ci		if (!fmt)
1878c2ecf20Sopenharmony_ci			return NULL;
1888c2ecf20Sopenharmony_ci	}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	pixmp->width = clamp(pixmp->width, frame_width_min(inst),
1918c2ecf20Sopenharmony_ci			     frame_width_max(inst));
1928c2ecf20Sopenharmony_ci	pixmp->height = clamp(pixmp->height, frame_height_min(inst),
1938c2ecf20Sopenharmony_ci			      frame_height_max(inst));
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1968c2ecf20Sopenharmony_ci		pixmp->height = ALIGN(pixmp->height, 32);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	pixmp->width = ALIGN(pixmp->width, 2);
1998c2ecf20Sopenharmony_ci	pixmp->height = ALIGN(pixmp->height, 2);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	if (pixmp->field == V4L2_FIELD_ANY)
2028c2ecf20Sopenharmony_ci		pixmp->field = V4L2_FIELD_NONE;
2038c2ecf20Sopenharmony_ci	pixmp->num_planes = fmt->num_planes;
2048c2ecf20Sopenharmony_ci	pixmp->flags = 0;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	sizeimage = venus_helper_get_framesz(pixmp->pixelformat,
2078c2ecf20Sopenharmony_ci					     pixmp->width,
2088c2ecf20Sopenharmony_ci					     pixmp->height);
2098c2ecf20Sopenharmony_ci	pfmt[0].sizeimage = max(ALIGN(pfmt[0].sizeimage, SZ_4K), sizeimage);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
2128c2ecf20Sopenharmony_ci		pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
2138c2ecf20Sopenharmony_ci	else
2148c2ecf20Sopenharmony_ci		pfmt[0].bytesperline = 0;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	return fmt;
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	venc_try_fmt_common(inst, f);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	return 0;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
2318c2ecf20Sopenharmony_ci	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
2328c2ecf20Sopenharmony_ci	struct v4l2_pix_format_mplane orig_pixmp;
2338c2ecf20Sopenharmony_ci	const struct venus_format *fmt;
2348c2ecf20Sopenharmony_ci	struct v4l2_format format;
2358c2ecf20Sopenharmony_ci	u32 pixfmt_out = 0, pixfmt_cap = 0;
2368c2ecf20Sopenharmony_ci	struct vb2_queue *q;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
2398c2ecf20Sopenharmony_ci	if (!q)
2408c2ecf20Sopenharmony_ci		return -EINVAL;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (vb2_is_busy(q))
2438c2ecf20Sopenharmony_ci		return -EBUSY;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	orig_pixmp = *pixmp;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	fmt = venc_try_fmt_common(inst, f);
2488c2ecf20Sopenharmony_ci	if (!fmt)
2498c2ecf20Sopenharmony_ci		return -EINVAL;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2528c2ecf20Sopenharmony_ci		pixfmt_out = pixmp->pixelformat;
2538c2ecf20Sopenharmony_ci		pixfmt_cap = inst->fmt_cap->pixfmt;
2548c2ecf20Sopenharmony_ci	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2558c2ecf20Sopenharmony_ci		pixfmt_cap = pixmp->pixelformat;
2568c2ecf20Sopenharmony_ci		pixfmt_out = inst->fmt_out->pixfmt;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	memset(&format, 0, sizeof(format));
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2628c2ecf20Sopenharmony_ci	format.fmt.pix_mp.pixelformat = pixfmt_out;
2638c2ecf20Sopenharmony_ci	format.fmt.pix_mp.width = orig_pixmp.width;
2648c2ecf20Sopenharmony_ci	format.fmt.pix_mp.height = orig_pixmp.height;
2658c2ecf20Sopenharmony_ci	venc_try_fmt_common(inst, &format);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2688c2ecf20Sopenharmony_ci		inst->out_width = format.fmt.pix_mp.width;
2698c2ecf20Sopenharmony_ci		inst->out_height = format.fmt.pix_mp.height;
2708c2ecf20Sopenharmony_ci		inst->colorspace = pixmp->colorspace;
2718c2ecf20Sopenharmony_ci		inst->ycbcr_enc = pixmp->ycbcr_enc;
2728c2ecf20Sopenharmony_ci		inst->quantization = pixmp->quantization;
2738c2ecf20Sopenharmony_ci		inst->xfer_func = pixmp->xfer_func;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	memset(&format, 0, sizeof(format));
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2798c2ecf20Sopenharmony_ci	format.fmt.pix_mp.pixelformat = pixfmt_cap;
2808c2ecf20Sopenharmony_ci	format.fmt.pix_mp.width = orig_pixmp.width;
2818c2ecf20Sopenharmony_ci	format.fmt.pix_mp.height = orig_pixmp.height;
2828c2ecf20Sopenharmony_ci	venc_try_fmt_common(inst, &format);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	inst->width = format.fmt.pix_mp.width;
2858c2ecf20Sopenharmony_ci	inst->height = format.fmt.pix_mp.height;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
2888c2ecf20Sopenharmony_ci		inst->fmt_out = fmt;
2898c2ecf20Sopenharmony_ci	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2908c2ecf20Sopenharmony_ci		inst->fmt_cap = fmt;
2918c2ecf20Sopenharmony_ci		inst->output_buf_size = pixmp->plane_fmt[0].sizeimage;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	return 0;
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
3008c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
3018c2ecf20Sopenharmony_ci	const struct venus_format *fmt;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
3048c2ecf20Sopenharmony_ci		fmt = inst->fmt_cap;
3058c2ecf20Sopenharmony_ci	else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
3068c2ecf20Sopenharmony_ci		fmt = inst->fmt_out;
3078c2ecf20Sopenharmony_ci	else
3088c2ecf20Sopenharmony_ci		return -EINVAL;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	pixmp->pixelformat = fmt->pixfmt;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
3138c2ecf20Sopenharmony_ci		pixmp->width = inst->width;
3148c2ecf20Sopenharmony_ci		pixmp->height = inst->height;
3158c2ecf20Sopenharmony_ci		pixmp->colorspace = inst->colorspace;
3168c2ecf20Sopenharmony_ci		pixmp->ycbcr_enc = inst->ycbcr_enc;
3178c2ecf20Sopenharmony_ci		pixmp->quantization = inst->quantization;
3188c2ecf20Sopenharmony_ci		pixmp->xfer_func = inst->xfer_func;
3198c2ecf20Sopenharmony_ci	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
3208c2ecf20Sopenharmony_ci		pixmp->width = inst->out_width;
3218c2ecf20Sopenharmony_ci		pixmp->height = inst->out_height;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	venc_try_fmt_common(inst, f);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return 0;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic int
3308c2ecf20Sopenharmony_civenc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
3358c2ecf20Sopenharmony_ci		return -EINVAL;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	switch (s->target) {
3388c2ecf20Sopenharmony_ci	case V4L2_SEL_TGT_CROP_DEFAULT:
3398c2ecf20Sopenharmony_ci	case V4L2_SEL_TGT_CROP_BOUNDS:
3408c2ecf20Sopenharmony_ci		s->r.width = inst->width;
3418c2ecf20Sopenharmony_ci		s->r.height = inst->height;
3428c2ecf20Sopenharmony_ci		break;
3438c2ecf20Sopenharmony_ci	case V4L2_SEL_TGT_CROP:
3448c2ecf20Sopenharmony_ci		s->r.width = inst->out_width;
3458c2ecf20Sopenharmony_ci		s->r.height = inst->out_height;
3468c2ecf20Sopenharmony_ci		break;
3478c2ecf20Sopenharmony_ci	default:
3488c2ecf20Sopenharmony_ci		return -EINVAL;
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	s->r.top = 0;
3528c2ecf20Sopenharmony_ci	s->r.left = 0;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	return 0;
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic int
3588c2ecf20Sopenharmony_civenc_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
3638c2ecf20Sopenharmony_ci		return -EINVAL;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	switch (s->target) {
3668c2ecf20Sopenharmony_ci	case V4L2_SEL_TGT_CROP:
3678c2ecf20Sopenharmony_ci		if (s->r.width != inst->out_width ||
3688c2ecf20Sopenharmony_ci		    s->r.height != inst->out_height ||
3698c2ecf20Sopenharmony_ci		    s->r.top != 0 || s->r.left != 0)
3708c2ecf20Sopenharmony_ci			return -EINVAL;
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	default:
3738c2ecf20Sopenharmony_ci		return -EINVAL;
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return 0;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
3828c2ecf20Sopenharmony_ci	struct v4l2_outputparm *out = &a->parm.output;
3838c2ecf20Sopenharmony_ci	struct v4l2_fract *timeperframe = &out->timeperframe;
3848c2ecf20Sopenharmony_ci	u64 us_per_frame, fps;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
3878c2ecf20Sopenharmony_ci	    a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
3888c2ecf20Sopenharmony_ci		return -EINVAL;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	memset(out->reserved, 0, sizeof(out->reserved));
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	if (!timeperframe->denominator)
3938c2ecf20Sopenharmony_ci		timeperframe->denominator = inst->timeperframe.denominator;
3948c2ecf20Sopenharmony_ci	if (!timeperframe->numerator)
3958c2ecf20Sopenharmony_ci		timeperframe->numerator = inst->timeperframe.numerator;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	out->capability = V4L2_CAP_TIMEPERFRAME;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
4008c2ecf20Sopenharmony_ci	do_div(us_per_frame, timeperframe->denominator);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (!us_per_frame)
4038c2ecf20Sopenharmony_ci		return -EINVAL;
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	fps = (u64)USEC_PER_SEC;
4068c2ecf20Sopenharmony_ci	do_div(fps, us_per_frame);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	inst->timeperframe = *timeperframe;
4098c2ecf20Sopenharmony_ci	inst->fps = fps;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return 0;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
4198c2ecf20Sopenharmony_ci	    a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
4208c2ecf20Sopenharmony_ci		return -EINVAL;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	a->parm.output.capability |= V4L2_CAP_TIMEPERFRAME;
4238c2ecf20Sopenharmony_ci	a->parm.output.timeperframe = inst->timeperframe;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	return 0;
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_cistatic int venc_enum_framesizes(struct file *file, void *fh,
4298c2ecf20Sopenharmony_ci				struct v4l2_frmsizeenum *fsize)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
4328c2ecf20Sopenharmony_ci	const struct venus_format *fmt;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	fmt = find_format(inst, fsize->pixel_format,
4378c2ecf20Sopenharmony_ci			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4388c2ecf20Sopenharmony_ci	if (!fmt) {
4398c2ecf20Sopenharmony_ci		fmt = find_format(inst, fsize->pixel_format,
4408c2ecf20Sopenharmony_ci				  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4418c2ecf20Sopenharmony_ci		if (!fmt)
4428c2ecf20Sopenharmony_ci			return -EINVAL;
4438c2ecf20Sopenharmony_ci	}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	if (fsize->index)
4468c2ecf20Sopenharmony_ci		return -EINVAL;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	fsize->stepwise.min_width = frame_width_min(inst);
4498c2ecf20Sopenharmony_ci	fsize->stepwise.max_width = frame_width_max(inst);
4508c2ecf20Sopenharmony_ci	fsize->stepwise.step_width = frame_width_step(inst);
4518c2ecf20Sopenharmony_ci	fsize->stepwise.min_height = frame_height_min(inst);
4528c2ecf20Sopenharmony_ci	fsize->stepwise.max_height = frame_height_max(inst);
4538c2ecf20Sopenharmony_ci	fsize->stepwise.step_height = frame_height_step(inst);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	return 0;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic int venc_enum_frameintervals(struct file *file, void *fh,
4598c2ecf20Sopenharmony_ci				    struct v4l2_frmivalenum *fival)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
4628c2ecf20Sopenharmony_ci	const struct venus_format *fmt;
4638c2ecf20Sopenharmony_ci	unsigned int framerate_factor = 1;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	fmt = find_format(inst, fival->pixel_format,
4688c2ecf20Sopenharmony_ci			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4698c2ecf20Sopenharmony_ci	if (!fmt) {
4708c2ecf20Sopenharmony_ci		fmt = find_format(inst, fival->pixel_format,
4718c2ecf20Sopenharmony_ci				  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4728c2ecf20Sopenharmony_ci		if (!fmt)
4738c2ecf20Sopenharmony_ci			return -EINVAL;
4748c2ecf20Sopenharmony_ci	}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	if (fival->index)
4778c2ecf20Sopenharmony_ci		return -EINVAL;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	if (!fival->width || !fival->height)
4808c2ecf20Sopenharmony_ci		return -EINVAL;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	if (fival->width > frame_width_max(inst) ||
4838c2ecf20Sopenharmony_ci	    fival->width < frame_width_min(inst) ||
4848c2ecf20Sopenharmony_ci	    fival->height > frame_height_max(inst) ||
4858c2ecf20Sopenharmony_ci	    fival->height < frame_height_min(inst))
4868c2ecf20Sopenharmony_ci		return -EINVAL;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	if (IS_V1(inst->core)) {
4898c2ecf20Sopenharmony_ci		/* framerate is reported in 1/65535 fps unit */
4908c2ecf20Sopenharmony_ci		framerate_factor = (1 << 16);
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	fival->stepwise.min.numerator = 1;
4948c2ecf20Sopenharmony_ci	fival->stepwise.min.denominator = frate_max(inst) / framerate_factor;
4958c2ecf20Sopenharmony_ci	fival->stepwise.max.numerator = 1;
4968c2ecf20Sopenharmony_ci	fival->stepwise.max.denominator = frate_min(inst) / framerate_factor;
4978c2ecf20Sopenharmony_ci	fival->stepwise.step.numerator = 1;
4988c2ecf20Sopenharmony_ci	fival->stepwise.step.denominator = frate_max(inst) / framerate_factor;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	return 0;
5018c2ecf20Sopenharmony_ci}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_cistatic const struct v4l2_ioctl_ops venc_ioctl_ops = {
5048c2ecf20Sopenharmony_ci	.vidioc_querycap = venc_querycap,
5058c2ecf20Sopenharmony_ci	.vidioc_enum_fmt_vid_cap = venc_enum_fmt,
5068c2ecf20Sopenharmony_ci	.vidioc_enum_fmt_vid_out = venc_enum_fmt,
5078c2ecf20Sopenharmony_ci	.vidioc_s_fmt_vid_cap_mplane = venc_s_fmt,
5088c2ecf20Sopenharmony_ci	.vidioc_s_fmt_vid_out_mplane = venc_s_fmt,
5098c2ecf20Sopenharmony_ci	.vidioc_g_fmt_vid_cap_mplane = venc_g_fmt,
5108c2ecf20Sopenharmony_ci	.vidioc_g_fmt_vid_out_mplane = venc_g_fmt,
5118c2ecf20Sopenharmony_ci	.vidioc_try_fmt_vid_cap_mplane = venc_try_fmt,
5128c2ecf20Sopenharmony_ci	.vidioc_try_fmt_vid_out_mplane = venc_try_fmt,
5138c2ecf20Sopenharmony_ci	.vidioc_g_selection = venc_g_selection,
5148c2ecf20Sopenharmony_ci	.vidioc_s_selection = venc_s_selection,
5158c2ecf20Sopenharmony_ci	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
5168c2ecf20Sopenharmony_ci	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
5178c2ecf20Sopenharmony_ci	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
5188c2ecf20Sopenharmony_ci	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
5198c2ecf20Sopenharmony_ci	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
5208c2ecf20Sopenharmony_ci	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
5218c2ecf20Sopenharmony_ci	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
5228c2ecf20Sopenharmony_ci	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
5238c2ecf20Sopenharmony_ci	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
5248c2ecf20Sopenharmony_ci	.vidioc_s_parm = venc_s_parm,
5258c2ecf20Sopenharmony_ci	.vidioc_g_parm = venc_g_parm,
5268c2ecf20Sopenharmony_ci	.vidioc_enum_framesizes = venc_enum_framesizes,
5278c2ecf20Sopenharmony_ci	.vidioc_enum_frameintervals = venc_enum_frameintervals,
5288c2ecf20Sopenharmony_ci	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
5298c2ecf20Sopenharmony_ci	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
5308c2ecf20Sopenharmony_ci};
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_cistatic int venc_set_properties(struct venus_inst *inst)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	struct venc_controls *ctr = &inst->controls.enc;
5358c2ecf20Sopenharmony_ci	struct hfi_intra_period intra_period;
5368c2ecf20Sopenharmony_ci	struct hfi_framerate frate;
5378c2ecf20Sopenharmony_ci	struct hfi_bitrate brate;
5388c2ecf20Sopenharmony_ci	struct hfi_idr_period idrp;
5398c2ecf20Sopenharmony_ci	struct hfi_quantization quant;
5408c2ecf20Sopenharmony_ci	struct hfi_quantization_range quant_range;
5418c2ecf20Sopenharmony_ci	u32 ptype, rate_control, bitrate;
5428c2ecf20Sopenharmony_ci	u32 profile, level;
5438c2ecf20Sopenharmony_ci	int ret;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
5468c2ecf20Sopenharmony_ci	if (ret)
5478c2ecf20Sopenharmony_ci		return ret;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
5508c2ecf20Sopenharmony_ci	frate.buffer_type = HFI_BUFFER_OUTPUT;
5518c2ecf20Sopenharmony_ci	frate.framerate = inst->fps * (1 << 16);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &frate);
5548c2ecf20Sopenharmony_ci	if (ret)
5558c2ecf20Sopenharmony_ci		return ret;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) {
5588c2ecf20Sopenharmony_ci		struct hfi_h264_vui_timing_info info;
5598c2ecf20Sopenharmony_ci		struct hfi_h264_entropy_control entropy;
5608c2ecf20Sopenharmony_ci		struct hfi_h264_db_control deblock;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci		ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
5638c2ecf20Sopenharmony_ci		info.enable = 1;
5648c2ecf20Sopenharmony_ci		info.fixed_framerate = 1;
5658c2ecf20Sopenharmony_ci		info.time_scale = NSEC_PER_SEC;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci		ret = hfi_session_set_property(inst, ptype, &info);
5688c2ecf20Sopenharmony_ci		if (ret)
5698c2ecf20Sopenharmony_ci			return ret;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci		ptype = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
5728c2ecf20Sopenharmony_ci		entropy.entropy_mode = venc_v4l2_to_hfi(
5738c2ecf20Sopenharmony_ci					  V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
5748c2ecf20Sopenharmony_ci					  ctr->h264_entropy_mode);
5758c2ecf20Sopenharmony_ci		entropy.cabac_model = HFI_H264_CABAC_MODEL_0;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci		ret = hfi_session_set_property(inst, ptype, &entropy);
5788c2ecf20Sopenharmony_ci		if (ret)
5798c2ecf20Sopenharmony_ci			return ret;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci		ptype = HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
5828c2ecf20Sopenharmony_ci		deblock.mode = venc_v4l2_to_hfi(
5838c2ecf20Sopenharmony_ci				      V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
5848c2ecf20Sopenharmony_ci				      ctr->h264_loop_filter_mode);
5858c2ecf20Sopenharmony_ci		deblock.slice_alpha_offset = ctr->h264_loop_filter_alpha;
5868c2ecf20Sopenharmony_ci		deblock.slice_beta_offset = ctr->h264_loop_filter_beta;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci		ret = hfi_session_set_property(inst, ptype, &deblock);
5898c2ecf20Sopenharmony_ci		if (ret)
5908c2ecf20Sopenharmony_ci			return ret;
5918c2ecf20Sopenharmony_ci	}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	/* IDR periodicity, n:
5948c2ecf20Sopenharmony_ci	 * n = 0 - only the first I-frame is IDR frame
5958c2ecf20Sopenharmony_ci	 * n = 1 - all I-frames will be IDR frames
5968c2ecf20Sopenharmony_ci	 * n > 1 - every n-th I-frame will be IDR frame
5978c2ecf20Sopenharmony_ci	 */
5988c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
5998c2ecf20Sopenharmony_ci	idrp.idr_period = 0;
6008c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &idrp);
6018c2ecf20Sopenharmony_ci	if (ret)
6028c2ecf20Sopenharmony_ci		return ret;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (ctr->num_b_frames) {
6058c2ecf20Sopenharmony_ci		u32 max_num_b_frames = NUM_B_FRAMES_MAX;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci		ptype = HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES;
6088c2ecf20Sopenharmony_ci		ret = hfi_session_set_property(inst, ptype, &max_num_b_frames);
6098c2ecf20Sopenharmony_ci		if (ret)
6108c2ecf20Sopenharmony_ci			return ret;
6118c2ecf20Sopenharmony_ci	}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
6148c2ecf20Sopenharmony_ci	intra_period.pframes = ctr->num_p_frames;
6158c2ecf20Sopenharmony_ci	intra_period.bframes = ctr->num_b_frames;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &intra_period);
6188c2ecf20Sopenharmony_ci	if (ret)
6198c2ecf20Sopenharmony_ci		return ret;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (!ctr->rc_enable)
6228c2ecf20Sopenharmony_ci		rate_control = HFI_RATE_CONTROL_OFF;
6238c2ecf20Sopenharmony_ci	else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
6248c2ecf20Sopenharmony_ci		rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_VBR_VFR :
6258c2ecf20Sopenharmony_ci						      HFI_RATE_CONTROL_VBR_CFR;
6268c2ecf20Sopenharmony_ci	else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
6278c2ecf20Sopenharmony_ci		rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_CBR_VFR :
6288c2ecf20Sopenharmony_ci						      HFI_RATE_CONTROL_CBR_CFR;
6298c2ecf20Sopenharmony_ci	else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
6308c2ecf20Sopenharmony_ci		rate_control = HFI_RATE_CONTROL_CQ;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
6338c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &rate_control);
6348c2ecf20Sopenharmony_ci	if (ret)
6358c2ecf20Sopenharmony_ci		return ret;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) {
6388c2ecf20Sopenharmony_ci		struct hfi_heic_frame_quality quality = {};
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci		ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
6418c2ecf20Sopenharmony_ci		quality.frame_quality = ctr->const_quality;
6428c2ecf20Sopenharmony_ci		ret = hfi_session_set_property(inst, ptype, &quality);
6438c2ecf20Sopenharmony_ci		if (ret)
6448c2ecf20Sopenharmony_ci			return ret;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	if (!ctr->bitrate)
6488c2ecf20Sopenharmony_ci		bitrate = 64000;
6498c2ecf20Sopenharmony_ci	else
6508c2ecf20Sopenharmony_ci		bitrate = ctr->bitrate;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
6538c2ecf20Sopenharmony_ci	brate.bitrate = bitrate;
6548c2ecf20Sopenharmony_ci	brate.layer_id = 0;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &brate);
6578c2ecf20Sopenharmony_ci	if (ret)
6588c2ecf20Sopenharmony_ci		return ret;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	if (!ctr->bitrate_peak)
6618c2ecf20Sopenharmony_ci		bitrate *= 2;
6628c2ecf20Sopenharmony_ci	else
6638c2ecf20Sopenharmony_ci		bitrate = ctr->bitrate_peak;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
6668c2ecf20Sopenharmony_ci	brate.bitrate = bitrate;
6678c2ecf20Sopenharmony_ci	brate.layer_id = 0;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &brate);
6708c2ecf20Sopenharmony_ci	if (ret)
6718c2ecf20Sopenharmony_ci		return ret;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP;
6748c2ecf20Sopenharmony_ci	quant.qp_i = ctr->h264_i_qp;
6758c2ecf20Sopenharmony_ci	quant.qp_p = ctr->h264_p_qp;
6768c2ecf20Sopenharmony_ci	quant.qp_b = ctr->h264_b_qp;
6778c2ecf20Sopenharmony_ci	quant.layer_id = 0;
6788c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &quant);
6798c2ecf20Sopenharmony_ci	if (ret)
6808c2ecf20Sopenharmony_ci		return ret;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
6838c2ecf20Sopenharmony_ci	quant_range.min_qp = ctr->h264_min_qp;
6848c2ecf20Sopenharmony_ci	quant_range.max_qp = ctr->h264_max_qp;
6858c2ecf20Sopenharmony_ci	quant_range.layer_id = 0;
6868c2ecf20Sopenharmony_ci	ret = hfi_session_set_property(inst, ptype, &quant_range);
6878c2ecf20Sopenharmony_ci	if (ret)
6888c2ecf20Sopenharmony_ci		return ret;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	switch (inst->hfi_codec) {
6918c2ecf20Sopenharmony_ci	case HFI_VIDEO_CODEC_H264:
6928c2ecf20Sopenharmony_ci		profile = ctr->profile.h264;
6938c2ecf20Sopenharmony_ci		level = ctr->level.h264;
6948c2ecf20Sopenharmony_ci		break;
6958c2ecf20Sopenharmony_ci	case HFI_VIDEO_CODEC_MPEG4:
6968c2ecf20Sopenharmony_ci		profile = ctr->profile.mpeg4;
6978c2ecf20Sopenharmony_ci		level = ctr->level.mpeg4;
6988c2ecf20Sopenharmony_ci		break;
6998c2ecf20Sopenharmony_ci	case HFI_VIDEO_CODEC_VP8:
7008c2ecf20Sopenharmony_ci		profile = ctr->profile.vp8;
7018c2ecf20Sopenharmony_ci		level = 0;
7028c2ecf20Sopenharmony_ci		break;
7038c2ecf20Sopenharmony_ci	case HFI_VIDEO_CODEC_VP9:
7048c2ecf20Sopenharmony_ci		profile = ctr->profile.vp9;
7058c2ecf20Sopenharmony_ci		level = ctr->level.vp9;
7068c2ecf20Sopenharmony_ci		break;
7078c2ecf20Sopenharmony_ci	case HFI_VIDEO_CODEC_HEVC:
7088c2ecf20Sopenharmony_ci		profile = ctr->profile.hevc;
7098c2ecf20Sopenharmony_ci		level = ctr->level.hevc;
7108c2ecf20Sopenharmony_ci		break;
7118c2ecf20Sopenharmony_ci	case HFI_VIDEO_CODEC_MPEG2:
7128c2ecf20Sopenharmony_ci	default:
7138c2ecf20Sopenharmony_ci		profile = 0;
7148c2ecf20Sopenharmony_ci		level = 0;
7158c2ecf20Sopenharmony_ci		break;
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	ret = venus_helper_set_profile_level(inst, profile, level);
7198c2ecf20Sopenharmony_ci	if (ret)
7208c2ecf20Sopenharmony_ci		return ret;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	return 0;
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_cistatic int venc_init_session(struct venus_inst *inst)
7268c2ecf20Sopenharmony_ci{
7278c2ecf20Sopenharmony_ci	int ret;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	ret = hfi_session_init(inst, inst->fmt_cap->pixfmt);
7308c2ecf20Sopenharmony_ci	if (ret)
7318c2ecf20Sopenharmony_ci		return ret;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	ret = venus_helper_set_input_resolution(inst, inst->width,
7348c2ecf20Sopenharmony_ci						inst->height);
7358c2ecf20Sopenharmony_ci	if (ret)
7368c2ecf20Sopenharmony_ci		goto deinit;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	ret = venus_helper_set_output_resolution(inst, inst->width,
7398c2ecf20Sopenharmony_ci						 inst->height,
7408c2ecf20Sopenharmony_ci						 HFI_BUFFER_OUTPUT);
7418c2ecf20Sopenharmony_ci	if (ret)
7428c2ecf20Sopenharmony_ci		goto deinit;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	ret = venus_helper_set_color_format(inst, inst->fmt_out->pixfmt);
7458c2ecf20Sopenharmony_ci	if (ret)
7468c2ecf20Sopenharmony_ci		goto deinit;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	ret = venus_helper_init_codec_freq_data(inst);
7498c2ecf20Sopenharmony_ci	if (ret)
7508c2ecf20Sopenharmony_ci		goto deinit;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	ret = venc_set_properties(inst);
7538c2ecf20Sopenharmony_ci	if (ret)
7548c2ecf20Sopenharmony_ci		goto deinit;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	return 0;
7578c2ecf20Sopenharmony_cideinit:
7588c2ecf20Sopenharmony_ci	hfi_session_deinit(inst);
7598c2ecf20Sopenharmony_ci	return ret;
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cistatic int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	struct hfi_buffer_requirements bufreq;
7658c2ecf20Sopenharmony_ci	int ret;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	ret = venc_init_session(inst);
7688c2ecf20Sopenharmony_ci	if (ret)
7698c2ecf20Sopenharmony_ci		return ret;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	*num = bufreq.count_actual;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	hfi_session_deinit(inst);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	return ret;
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_cistatic int venc_queue_setup(struct vb2_queue *q,
7818c2ecf20Sopenharmony_ci			    unsigned int *num_buffers, unsigned int *num_planes,
7828c2ecf20Sopenharmony_ci			    unsigned int sizes[], struct device *alloc_devs[])
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	struct venus_inst *inst = vb2_get_drv_priv(q);
7858c2ecf20Sopenharmony_ci	unsigned int num, min = 4;
7868c2ecf20Sopenharmony_ci	int ret = 0;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	if (*num_planes) {
7898c2ecf20Sopenharmony_ci		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
7908c2ecf20Sopenharmony_ci		    *num_planes != inst->fmt_out->num_planes)
7918c2ecf20Sopenharmony_ci			return -EINVAL;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci		if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
7948c2ecf20Sopenharmony_ci		    *num_planes != inst->fmt_cap->num_planes)
7958c2ecf20Sopenharmony_ci			return -EINVAL;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
7988c2ecf20Sopenharmony_ci		    sizes[0] < inst->input_buf_size)
7998c2ecf20Sopenharmony_ci			return -EINVAL;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci		if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
8028c2ecf20Sopenharmony_ci		    sizes[0] < inst->output_buf_size)
8038c2ecf20Sopenharmony_ci			return -EINVAL;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci		return 0;
8068c2ecf20Sopenharmony_ci	}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	switch (q->type) {
8098c2ecf20Sopenharmony_ci	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
8108c2ecf20Sopenharmony_ci		*num_planes = inst->fmt_out->num_planes;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci		ret = venc_out_num_buffers(inst, &num);
8138c2ecf20Sopenharmony_ci		if (ret)
8148c2ecf20Sopenharmony_ci			break;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci		num = max(num, min);
8178c2ecf20Sopenharmony_ci		*num_buffers = max(*num_buffers, num);
8188c2ecf20Sopenharmony_ci		inst->num_input_bufs = *num_buffers;
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci		sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
8218c2ecf20Sopenharmony_ci						    inst->width,
8228c2ecf20Sopenharmony_ci						    inst->height);
8238c2ecf20Sopenharmony_ci		inst->input_buf_size = sizes[0];
8248c2ecf20Sopenharmony_ci		break;
8258c2ecf20Sopenharmony_ci	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
8268c2ecf20Sopenharmony_ci		*num_planes = inst->fmt_cap->num_planes;
8278c2ecf20Sopenharmony_ci		*num_buffers = max(*num_buffers, min);
8288c2ecf20Sopenharmony_ci		inst->num_output_bufs = *num_buffers;
8298c2ecf20Sopenharmony_ci		sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
8308c2ecf20Sopenharmony_ci						    inst->width,
8318c2ecf20Sopenharmony_ci						    inst->height);
8328c2ecf20Sopenharmony_ci		sizes[0] = max(sizes[0], inst->output_buf_size);
8338c2ecf20Sopenharmony_ci		inst->output_buf_size = sizes[0];
8348c2ecf20Sopenharmony_ci		break;
8358c2ecf20Sopenharmony_ci	default:
8368c2ecf20Sopenharmony_ci		ret = -EINVAL;
8378c2ecf20Sopenharmony_ci		break;
8388c2ecf20Sopenharmony_ci	}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	return ret;
8418c2ecf20Sopenharmony_ci}
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_cistatic int venc_verify_conf(struct venus_inst *inst)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	enum hfi_version ver = inst->core->res->hfi_version;
8468c2ecf20Sopenharmony_ci	struct hfi_buffer_requirements bufreq;
8478c2ecf20Sopenharmony_ci	int ret;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (!inst->num_input_bufs || !inst->num_output_bufs)
8508c2ecf20Sopenharmony_ci		return -EINVAL;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
8538c2ecf20Sopenharmony_ci	if (ret)
8548c2ecf20Sopenharmony_ci		return ret;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	if (inst->num_output_bufs < bufreq.count_actual ||
8578c2ecf20Sopenharmony_ci	    inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
8588c2ecf20Sopenharmony_ci		return -EINVAL;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
8618c2ecf20Sopenharmony_ci	if (ret)
8628c2ecf20Sopenharmony_ci		return ret;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	if (inst->num_input_bufs < bufreq.count_actual ||
8658c2ecf20Sopenharmony_ci	    inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
8668c2ecf20Sopenharmony_ci		return -EINVAL;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	return 0;
8698c2ecf20Sopenharmony_ci}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_cistatic int venc_start_streaming(struct vb2_queue *q, unsigned int count)
8728c2ecf20Sopenharmony_ci{
8738c2ecf20Sopenharmony_ci	struct venus_inst *inst = vb2_get_drv_priv(q);
8748c2ecf20Sopenharmony_ci	int ret;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	mutex_lock(&inst->lock);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
8798c2ecf20Sopenharmony_ci		inst->streamon_out = 1;
8808c2ecf20Sopenharmony_ci	else
8818c2ecf20Sopenharmony_ci		inst->streamon_cap = 1;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	if (!(inst->streamon_out & inst->streamon_cap)) {
8848c2ecf20Sopenharmony_ci		mutex_unlock(&inst->lock);
8858c2ecf20Sopenharmony_ci		return 0;
8868c2ecf20Sopenharmony_ci	}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	venus_helper_init_instance(inst);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	inst->sequence_cap = 0;
8918c2ecf20Sopenharmony_ci	inst->sequence_out = 0;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	ret = venc_init_session(inst);
8948c2ecf20Sopenharmony_ci	if (ret)
8958c2ecf20Sopenharmony_ci		goto bufs_done;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	ret = venus_pm_acquire_core(inst);
8988c2ecf20Sopenharmony_ci	if (ret)
8998c2ecf20Sopenharmony_ci		goto deinit_sess;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	ret = venc_set_properties(inst);
9028c2ecf20Sopenharmony_ci	if (ret)
9038c2ecf20Sopenharmony_ci		goto deinit_sess;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	ret = venc_verify_conf(inst);
9068c2ecf20Sopenharmony_ci	if (ret)
9078c2ecf20Sopenharmony_ci		goto deinit_sess;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
9108c2ecf20Sopenharmony_ci					inst->num_output_bufs, 0);
9118c2ecf20Sopenharmony_ci	if (ret)
9128c2ecf20Sopenharmony_ci		goto deinit_sess;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	ret = venus_helper_vb2_start_streaming(inst);
9158c2ecf20Sopenharmony_ci	if (ret)
9168c2ecf20Sopenharmony_ci		goto deinit_sess;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	mutex_unlock(&inst->lock);
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	return 0;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_cideinit_sess:
9238c2ecf20Sopenharmony_ci	hfi_session_deinit(inst);
9248c2ecf20Sopenharmony_cibufs_done:
9258c2ecf20Sopenharmony_ci	venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
9268c2ecf20Sopenharmony_ci	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
9278c2ecf20Sopenharmony_ci		inst->streamon_out = 0;
9288c2ecf20Sopenharmony_ci	else
9298c2ecf20Sopenharmony_ci		inst->streamon_cap = 0;
9308c2ecf20Sopenharmony_ci	mutex_unlock(&inst->lock);
9318c2ecf20Sopenharmony_ci	return ret;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_cistatic const struct vb2_ops venc_vb2_ops = {
9358c2ecf20Sopenharmony_ci	.queue_setup = venc_queue_setup,
9368c2ecf20Sopenharmony_ci	.buf_init = venus_helper_vb2_buf_init,
9378c2ecf20Sopenharmony_ci	.buf_prepare = venus_helper_vb2_buf_prepare,
9388c2ecf20Sopenharmony_ci	.start_streaming = venc_start_streaming,
9398c2ecf20Sopenharmony_ci	.stop_streaming = venus_helper_vb2_stop_streaming,
9408c2ecf20Sopenharmony_ci	.buf_queue = venus_helper_vb2_buf_queue,
9418c2ecf20Sopenharmony_ci};
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_cistatic void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
9448c2ecf20Sopenharmony_ci			  u32 tag, u32 bytesused, u32 data_offset, u32 flags,
9458c2ecf20Sopenharmony_ci			  u32 hfi_flags, u64 timestamp_us)
9468c2ecf20Sopenharmony_ci{
9478c2ecf20Sopenharmony_ci	struct vb2_v4l2_buffer *vbuf;
9488c2ecf20Sopenharmony_ci	struct vb2_buffer *vb;
9498c2ecf20Sopenharmony_ci	unsigned int type;
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	if (buf_type == HFI_BUFFER_INPUT)
9528c2ecf20Sopenharmony_ci		type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9538c2ecf20Sopenharmony_ci	else
9548c2ecf20Sopenharmony_ci		type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	vbuf = venus_helper_find_buf(inst, type, tag);
9578c2ecf20Sopenharmony_ci	if (!vbuf)
9588c2ecf20Sopenharmony_ci		return;
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	vbuf->flags = flags;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
9638c2ecf20Sopenharmony_ci		vb = &vbuf->vb2_buf;
9648c2ecf20Sopenharmony_ci		vb2_set_plane_payload(vb, 0, bytesused + data_offset);
9658c2ecf20Sopenharmony_ci		vb->planes[0].data_offset = data_offset;
9668c2ecf20Sopenharmony_ci		vb->timestamp = timestamp_us * NSEC_PER_USEC;
9678c2ecf20Sopenharmony_ci		vbuf->sequence = inst->sequence_cap++;
9688c2ecf20Sopenharmony_ci	} else {
9698c2ecf20Sopenharmony_ci		vbuf->sequence = inst->sequence_out++;
9708c2ecf20Sopenharmony_ci	}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic void venc_event_notify(struct venus_inst *inst, u32 event,
9768c2ecf20Sopenharmony_ci			      struct hfi_event_data *data)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	struct device *dev = inst->core->dev_enc;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	if (event == EVT_SESSION_ERROR) {
9818c2ecf20Sopenharmony_ci		inst->session_error = true;
9828c2ecf20Sopenharmony_ci		dev_err(dev, "enc: event session error %x\n", inst->error);
9838c2ecf20Sopenharmony_ci	}
9848c2ecf20Sopenharmony_ci}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_cistatic const struct hfi_inst_ops venc_hfi_ops = {
9878c2ecf20Sopenharmony_ci	.buf_done = venc_buf_done,
9888c2ecf20Sopenharmony_ci	.event_notify = venc_event_notify,
9898c2ecf20Sopenharmony_ci};
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_cistatic const struct v4l2_m2m_ops venc_m2m_ops = {
9928c2ecf20Sopenharmony_ci	.device_run = venus_helper_m2m_device_run,
9938c2ecf20Sopenharmony_ci	.job_abort = venus_helper_m2m_job_abort,
9948c2ecf20Sopenharmony_ci};
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_cistatic int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
9978c2ecf20Sopenharmony_ci			  struct vb2_queue *dst_vq)
9988c2ecf20Sopenharmony_ci{
9998c2ecf20Sopenharmony_ci	struct venus_inst *inst = priv;
10008c2ecf20Sopenharmony_ci	int ret;
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10038c2ecf20Sopenharmony_ci	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
10048c2ecf20Sopenharmony_ci	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
10058c2ecf20Sopenharmony_ci	src_vq->ops = &venc_vb2_ops;
10068c2ecf20Sopenharmony_ci	src_vq->mem_ops = &vb2_dma_sg_memops;
10078c2ecf20Sopenharmony_ci	src_vq->drv_priv = inst;
10088c2ecf20Sopenharmony_ci	src_vq->buf_struct_size = sizeof(struct venus_buffer);
10098c2ecf20Sopenharmony_ci	src_vq->allow_zero_bytesused = 1;
10108c2ecf20Sopenharmony_ci	src_vq->min_buffers_needed = 1;
10118c2ecf20Sopenharmony_ci	src_vq->dev = inst->core->dev;
10128c2ecf20Sopenharmony_ci	if (inst->core->res->hfi_version == HFI_VERSION_1XX)
10138c2ecf20Sopenharmony_ci		src_vq->bidirectional = 1;
10148c2ecf20Sopenharmony_ci	ret = vb2_queue_init(src_vq);
10158c2ecf20Sopenharmony_ci	if (ret)
10168c2ecf20Sopenharmony_ci		return ret;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10198c2ecf20Sopenharmony_ci	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
10208c2ecf20Sopenharmony_ci	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
10218c2ecf20Sopenharmony_ci	dst_vq->ops = &venc_vb2_ops;
10228c2ecf20Sopenharmony_ci	dst_vq->mem_ops = &vb2_dma_sg_memops;
10238c2ecf20Sopenharmony_ci	dst_vq->drv_priv = inst;
10248c2ecf20Sopenharmony_ci	dst_vq->buf_struct_size = sizeof(struct venus_buffer);
10258c2ecf20Sopenharmony_ci	dst_vq->allow_zero_bytesused = 1;
10268c2ecf20Sopenharmony_ci	dst_vq->min_buffers_needed = 1;
10278c2ecf20Sopenharmony_ci	dst_vq->dev = inst->core->dev;
10288c2ecf20Sopenharmony_ci	return vb2_queue_init(dst_vq);
10298c2ecf20Sopenharmony_ci}
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_cistatic void venc_inst_init(struct venus_inst *inst)
10328c2ecf20Sopenharmony_ci{
10338c2ecf20Sopenharmony_ci	inst->fmt_cap = &venc_formats[2];
10348c2ecf20Sopenharmony_ci	inst->fmt_out = &venc_formats[0];
10358c2ecf20Sopenharmony_ci	inst->width = 1280;
10368c2ecf20Sopenharmony_ci	inst->height = ALIGN(720, 32);
10378c2ecf20Sopenharmony_ci	inst->out_width = 1280;
10388c2ecf20Sopenharmony_ci	inst->out_height = 720;
10398c2ecf20Sopenharmony_ci	inst->fps = 15;
10408c2ecf20Sopenharmony_ci	inst->timeperframe.numerator = 1;
10418c2ecf20Sopenharmony_ci	inst->timeperframe.denominator = 15;
10428c2ecf20Sopenharmony_ci	inst->hfi_codec = HFI_VIDEO_CODEC_H264;
10438c2ecf20Sopenharmony_ci}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_cistatic int venc_open(struct file *file)
10468c2ecf20Sopenharmony_ci{
10478c2ecf20Sopenharmony_ci	struct venus_core *core = video_drvdata(file);
10488c2ecf20Sopenharmony_ci	struct venus_inst *inst;
10498c2ecf20Sopenharmony_ci	int ret;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
10528c2ecf20Sopenharmony_ci	if (!inst)
10538c2ecf20Sopenharmony_ci		return -ENOMEM;
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&inst->dpbbufs);
10568c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&inst->registeredbufs);
10578c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&inst->internalbufs);
10588c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&inst->list);
10598c2ecf20Sopenharmony_ci	mutex_init(&inst->lock);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	inst->core = core;
10628c2ecf20Sopenharmony_ci	inst->session_type = VIDC_SESSION_TYPE_ENC;
10638c2ecf20Sopenharmony_ci	inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
10648c2ecf20Sopenharmony_ci	inst->core_acquired = false;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	venus_helper_init_instance(inst);
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	ret = pm_runtime_get_sync(core->dev_enc);
10698c2ecf20Sopenharmony_ci	if (ret < 0)
10708c2ecf20Sopenharmony_ci		goto err_put_sync;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	ret = venc_ctrl_init(inst);
10738c2ecf20Sopenharmony_ci	if (ret)
10748c2ecf20Sopenharmony_ci		goto err_put_sync;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	ret = hfi_session_create(inst, &venc_hfi_ops);
10778c2ecf20Sopenharmony_ci	if (ret)
10788c2ecf20Sopenharmony_ci		goto err_ctrl_deinit;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	venc_inst_init(inst);
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	/*
10838c2ecf20Sopenharmony_ci	 * create m2m device for every instance, the m2m context scheduling
10848c2ecf20Sopenharmony_ci	 * is made by firmware side so we do not need to care about.
10858c2ecf20Sopenharmony_ci	 */
10868c2ecf20Sopenharmony_ci	inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops);
10878c2ecf20Sopenharmony_ci	if (IS_ERR(inst->m2m_dev)) {
10888c2ecf20Sopenharmony_ci		ret = PTR_ERR(inst->m2m_dev);
10898c2ecf20Sopenharmony_ci		goto err_session_destroy;
10908c2ecf20Sopenharmony_ci	}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
10938c2ecf20Sopenharmony_ci	if (IS_ERR(inst->m2m_ctx)) {
10948c2ecf20Sopenharmony_ci		ret = PTR_ERR(inst->m2m_ctx);
10958c2ecf20Sopenharmony_ci		goto err_m2m_release;
10968c2ecf20Sopenharmony_ci	}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	v4l2_fh_init(&inst->fh, core->vdev_enc);
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	inst->fh.ctrl_handler = &inst->ctrl_handler;
11018c2ecf20Sopenharmony_ci	v4l2_fh_add(&inst->fh);
11028c2ecf20Sopenharmony_ci	inst->fh.m2m_ctx = inst->m2m_ctx;
11038c2ecf20Sopenharmony_ci	file->private_data = &inst->fh;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	return 0;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_cierr_m2m_release:
11088c2ecf20Sopenharmony_ci	v4l2_m2m_release(inst->m2m_dev);
11098c2ecf20Sopenharmony_cierr_session_destroy:
11108c2ecf20Sopenharmony_ci	hfi_session_destroy(inst);
11118c2ecf20Sopenharmony_cierr_ctrl_deinit:
11128c2ecf20Sopenharmony_ci	venc_ctrl_deinit(inst);
11138c2ecf20Sopenharmony_cierr_put_sync:
11148c2ecf20Sopenharmony_ci	pm_runtime_put_sync(core->dev_enc);
11158c2ecf20Sopenharmony_ci	kfree(inst);
11168c2ecf20Sopenharmony_ci	return ret;
11178c2ecf20Sopenharmony_ci}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_cistatic int venc_close(struct file *file)
11208c2ecf20Sopenharmony_ci{
11218c2ecf20Sopenharmony_ci	struct venus_inst *inst = to_inst(file);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	v4l2_m2m_ctx_release(inst->m2m_ctx);
11248c2ecf20Sopenharmony_ci	v4l2_m2m_release(inst->m2m_dev);
11258c2ecf20Sopenharmony_ci	venc_ctrl_deinit(inst);
11268c2ecf20Sopenharmony_ci	hfi_session_destroy(inst);
11278c2ecf20Sopenharmony_ci	mutex_destroy(&inst->lock);
11288c2ecf20Sopenharmony_ci	v4l2_fh_del(&inst->fh);
11298c2ecf20Sopenharmony_ci	v4l2_fh_exit(&inst->fh);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	pm_runtime_put_sync(inst->core->dev_enc);
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	kfree(inst);
11348c2ecf20Sopenharmony_ci	return 0;
11358c2ecf20Sopenharmony_ci}
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_cistatic const struct v4l2_file_operations venc_fops = {
11388c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
11398c2ecf20Sopenharmony_ci	.open = venc_open,
11408c2ecf20Sopenharmony_ci	.release = venc_close,
11418c2ecf20Sopenharmony_ci	.unlocked_ioctl = video_ioctl2,
11428c2ecf20Sopenharmony_ci	.poll = v4l2_m2m_fop_poll,
11438c2ecf20Sopenharmony_ci	.mmap = v4l2_m2m_fop_mmap,
11448c2ecf20Sopenharmony_ci};
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_cistatic int venc_probe(struct platform_device *pdev)
11478c2ecf20Sopenharmony_ci{
11488c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
11498c2ecf20Sopenharmony_ci	struct video_device *vdev;
11508c2ecf20Sopenharmony_ci	struct venus_core *core;
11518c2ecf20Sopenharmony_ci	int ret;
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	if (!dev->parent)
11548c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	core = dev_get_drvdata(dev->parent);
11578c2ecf20Sopenharmony_ci	if (!core)
11588c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, core);
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	if (core->pm_ops->venc_get) {
11638c2ecf20Sopenharmony_ci		ret = core->pm_ops->venc_get(dev);
11648c2ecf20Sopenharmony_ci		if (ret)
11658c2ecf20Sopenharmony_ci			return ret;
11668c2ecf20Sopenharmony_ci	}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	vdev = video_device_alloc();
11698c2ecf20Sopenharmony_ci	if (!vdev)
11708c2ecf20Sopenharmony_ci		return -ENOMEM;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
11738c2ecf20Sopenharmony_ci	vdev->release = video_device_release;
11748c2ecf20Sopenharmony_ci	vdev->fops = &venc_fops;
11758c2ecf20Sopenharmony_ci	vdev->ioctl_ops = &venc_ioctl_ops;
11768c2ecf20Sopenharmony_ci	vdev->vfl_dir = VFL_DIR_M2M;
11778c2ecf20Sopenharmony_ci	vdev->v4l2_dev = &core->v4l2_dev;
11788c2ecf20Sopenharmony_ci	vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
11818c2ecf20Sopenharmony_ci	if (ret)
11828c2ecf20Sopenharmony_ci		goto err_vdev_release;
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	core->vdev_enc = vdev;
11858c2ecf20Sopenharmony_ci	core->dev_enc = dev;
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	video_set_drvdata(vdev, core);
11888c2ecf20Sopenharmony_ci	pm_runtime_enable(dev);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	return 0;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_cierr_vdev_release:
11938c2ecf20Sopenharmony_ci	video_device_release(vdev);
11948c2ecf20Sopenharmony_ci	return ret;
11958c2ecf20Sopenharmony_ci}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_cistatic int venc_remove(struct platform_device *pdev)
11988c2ecf20Sopenharmony_ci{
11998c2ecf20Sopenharmony_ci	struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	video_unregister_device(core->vdev_enc);
12028c2ecf20Sopenharmony_ci	pm_runtime_disable(core->dev_enc);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	if (core->pm_ops->venc_put)
12058c2ecf20Sopenharmony_ci		core->pm_ops->venc_put(core->dev_enc);
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	return 0;
12088c2ecf20Sopenharmony_ci}
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_cistatic __maybe_unused int venc_runtime_suspend(struct device *dev)
12118c2ecf20Sopenharmony_ci{
12128c2ecf20Sopenharmony_ci	struct venus_core *core = dev_get_drvdata(dev);
12138c2ecf20Sopenharmony_ci	const struct venus_pm_ops *pm_ops = core->pm_ops;
12148c2ecf20Sopenharmony_ci	int ret = 0;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	if (pm_ops->venc_power)
12178c2ecf20Sopenharmony_ci		ret = pm_ops->venc_power(dev, POWER_OFF);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	return ret;
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_cistatic __maybe_unused int venc_runtime_resume(struct device *dev)
12238c2ecf20Sopenharmony_ci{
12248c2ecf20Sopenharmony_ci	struct venus_core *core = dev_get_drvdata(dev);
12258c2ecf20Sopenharmony_ci	const struct venus_pm_ops *pm_ops = core->pm_ops;
12268c2ecf20Sopenharmony_ci	int ret = 0;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	if (pm_ops->venc_power)
12298c2ecf20Sopenharmony_ci		ret = pm_ops->venc_power(dev, POWER_ON);
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	return ret;
12328c2ecf20Sopenharmony_ci}
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_cistatic const struct dev_pm_ops venc_pm_ops = {
12358c2ecf20Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
12368c2ecf20Sopenharmony_ci				pm_runtime_force_resume)
12378c2ecf20Sopenharmony_ci	SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL)
12388c2ecf20Sopenharmony_ci};
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_cistatic const struct of_device_id venc_dt_match[] = {
12418c2ecf20Sopenharmony_ci	{ .compatible = "venus-encoder" },
12428c2ecf20Sopenharmony_ci	{ }
12438c2ecf20Sopenharmony_ci};
12448c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, venc_dt_match);
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_cistatic struct platform_driver qcom_venus_enc_driver = {
12478c2ecf20Sopenharmony_ci	.probe = venc_probe,
12488c2ecf20Sopenharmony_ci	.remove = venc_remove,
12498c2ecf20Sopenharmony_ci	.driver = {
12508c2ecf20Sopenharmony_ci		.name = "qcom-venus-encoder",
12518c2ecf20Sopenharmony_ci		.of_match_table = venc_dt_match,
12528c2ecf20Sopenharmony_ci		.pm = &venc_pm_ops,
12538c2ecf20Sopenharmony_ci	},
12548c2ecf20Sopenharmony_ci};
12558c2ecf20Sopenharmony_cimodule_platform_driver(qcom_venus_enc_driver);
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:qcom-venus-encoder");
12588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm Venus video encoder driver");
12598c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1260