brintos

brintos / linux-shallow public Read only

0
0
Text · 43.7 KiB · 6a38a0f Raw
1766 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2020-2021 NXP4 */5 6#include <linux/init.h>7#include <linux/interconnect.h>8#include <linux/ioctl.h>9#include <linux/list.h>10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/vmalloc.h>13#include <linux/videodev2.h>14#include <media/v4l2-device.h>15#include <media/v4l2-event.h>16#include <media/v4l2-mem2mem.h>17#include <media/v4l2-ioctl.h>18#include <media/videobuf2-v4l2.h>19#include <media/videobuf2-dma-contig.h>20#include <media/videobuf2-vmalloc.h>21#include "vpu.h"22#include "vpu_defs.h"23#include "vpu_core.h"24#include "vpu_helpers.h"25#include "vpu_v4l2.h"26#include "vpu_cmds.h"27#include "vpu_rpc.h"28 29#define VDEC_MIN_BUFFER_CAP		830#define VDEC_MIN_BUFFER_OUT		831 32struct vdec_fs_info {33	char name[8];34	u32 type;35	u32 max_count;36	u32 req_count;37	u32 count;38	u32 index;39	u32 size;40	struct vpu_buffer buffer[32];41	u32 tag;42};43 44struct vdec_t {45	u32 seq_hdr_found;46	struct vpu_buffer udata;47	struct vpu_decode_params params;48	struct vpu_dec_codec_info codec_info;49	enum vpu_codec_state state;50 51	struct vpu_vb2_buffer *slots[VB2_MAX_FRAME];52	u32 req_frame_count;53	struct vdec_fs_info mbi;54	struct vdec_fs_info dcp;55	u32 seq_tag;56 57	bool reset_codec;58	bool fixed_fmt;59	u32 decoded_frame_count;60	u32 display_frame_count;61	u32 sequence;62	u32 eos_received;63	bool is_source_changed;64	u32 source_change;65	u32 drain;66	bool aborting;67};68 69static const struct vpu_format vdec_formats[] = {70	{71		.pixfmt = V4L2_PIX_FMT_NV12M_8L128,72		.mem_planes = 2,73		.comp_planes = 2,74		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,75		.sibling = V4L2_PIX_FMT_NV12_8L128,76	},77	{78		.pixfmt = V4L2_PIX_FMT_NV12_8L128,79		.mem_planes = 1,80		.comp_planes = 2,81		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,82		.sibling = V4L2_PIX_FMT_NV12M_8L128,83	},84	{85		.pixfmt = V4L2_PIX_FMT_NV12M_10BE_8L128,86		.mem_planes = 2,87		.comp_planes = 2,88		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,89		.sibling = V4L2_PIX_FMT_NV12_10BE_8L128,90	},91	{92		.pixfmt = V4L2_PIX_FMT_NV12_10BE_8L128,93		.mem_planes = 1,94		.comp_planes = 2,95		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,96		.sibling = V4L2_PIX_FMT_NV12M_10BE_8L12897	},98	{99		.pixfmt = V4L2_PIX_FMT_H264,100		.mem_planes = 1,101		.comp_planes = 1,102		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,103		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED104	},105	{106		.pixfmt = V4L2_PIX_FMT_H264_MVC,107		.mem_planes = 1,108		.comp_planes = 1,109		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,110		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED111	},112	{113		.pixfmt = V4L2_PIX_FMT_HEVC,114		.mem_planes = 1,115		.comp_planes = 1,116		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,117		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED118	},119	{120		.pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,121		.mem_planes = 1,122		.comp_planes = 1,123		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,124		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED125	},126	{127		.pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,128		.mem_planes = 1,129		.comp_planes = 1,130		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,131		.flags = V4L2_FMT_FLAG_COMPRESSED132	},133	{134		.pixfmt = V4L2_PIX_FMT_MPEG2,135		.mem_planes = 1,136		.comp_planes = 1,137		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,138		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED139	},140	{141		.pixfmt = V4L2_PIX_FMT_MPEG4,142		.mem_planes = 1,143		.comp_planes = 1,144		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,145		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED146	},147	{148		.pixfmt = V4L2_PIX_FMT_XVID,149		.mem_planes = 1,150		.comp_planes = 1,151		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,152		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED153	},154	{155		.pixfmt = V4L2_PIX_FMT_VP8,156		.mem_planes = 1,157		.comp_planes = 1,158		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,159		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED160	},161	{162		.pixfmt = V4L2_PIX_FMT_H263,163		.mem_planes = 1,164		.comp_planes = 1,165		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,166		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED167	},168	{169		.pixfmt = V4L2_PIX_FMT_SPK,170		.mem_planes = 1,171		.comp_planes = 1,172		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,173		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED174	},175	{176		.pixfmt = V4L2_PIX_FMT_RV30,177		.mem_planes = 1,178		.comp_planes = 1,179		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,180		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED181	},182	{183		.pixfmt = V4L2_PIX_FMT_RV40,184		.mem_planes = 1,185		.comp_planes = 1,186		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,187		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED188	},189	{0, 0, 0, 0},190};191 192static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)193{194	struct vpu_inst *inst = ctrl_to_inst(ctrl);195	struct vdec_t *vdec = inst->priv;196	int ret = 0;197 198	switch (ctrl->id) {199	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:200		vdec->params.display_delay_enable = ctrl->val;201		break;202	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:203		vdec->params.display_delay = ctrl->val;204		break;205	default:206		ret = -EINVAL;207		break;208	}209 210	return ret;211}212 213static const struct v4l2_ctrl_ops vdec_ctrl_ops = {214	.s_ctrl = vdec_op_s_ctrl,215	.g_volatile_ctrl = vpu_helper_g_volatile_ctrl,216};217 218static int vdec_ctrl_init(struct vpu_inst *inst)219{220	struct v4l2_ctrl *ctrl;221	int ret;222 223	ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20);224	if (ret)225		return ret;226 227	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,228			  V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,229			  0, 0, 1, 0);230 231	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,232			  V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,233			  0, 1, 1, 0);234 235	ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,236				 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2);237	if (ctrl)238		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;239 240	ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,241				 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 2);242	if (ctrl)243		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;244 245	if (inst->ctrl_handler.error) {246		ret = inst->ctrl_handler.error;247		v4l2_ctrl_handler_free(&inst->ctrl_handler);248		return ret;249	}250 251	ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);252	if (ret) {253		dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);254		v4l2_ctrl_handler_free(&inst->ctrl_handler);255		return ret;256	}257 258	return 0;259}260 261static void vdec_handle_resolution_change(struct vpu_inst *inst)262{263	struct vdec_t *vdec = inst->priv;264	struct vb2_queue *q;265 266	if (!inst->fh.m2m_ctx)267		return;268 269	if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)270		return;271	if (!vdec->source_change)272		return;273 274	q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);275	if (!list_empty(&q->done_list))276		return;277 278	vdec->source_change--;279	vpu_notify_source_change(inst);280	vpu_set_last_buffer_dequeued(inst, false);281}282 283static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force)284{285	struct vdec_t *vdec = inst->priv;286	enum vpu_codec_state pre_state = inst->state;287 288	if (state == VPU_CODEC_STATE_SEEK) {289		if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)290			vdec->state = inst->state;291		else292			vdec->state = VPU_CODEC_STATE_ACTIVE;293	}294	if (inst->state != VPU_CODEC_STATE_SEEK || force)295		inst->state = state;296	else if (state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)297		vdec->state = VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE;298 299	if (inst->state != pre_state)300		vpu_trace(inst->dev, "[%d] %s -> %s\n", inst->id,301			  vpu_codec_state_name(pre_state), vpu_codec_state_name(inst->state));302 303	if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)304		vdec_handle_resolution_change(inst);305 306	return 0;307}308 309static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst)310{311	struct vdec_t *vdec = inst->priv;312 313	if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)314		return;315 316	if (vdec->eos_received) {317		if (!vpu_set_last_buffer_dequeued(inst, true)) {318			vdec->eos_received--;319			vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0);320		}321	}322}323 324static int vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)325{326	strscpy(cap->driver, "amphion-vpu", sizeof(cap->driver));327	strscpy(cap->card, "amphion vpu decoder", sizeof(cap->card));328	strscpy(cap->bus_info, "platform: amphion-vpu", sizeof(cap->bus_info));329 330	return 0;331}332 333static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)334{335	struct vpu_inst *inst = to_inst(file);336	struct vdec_t *vdec = inst->priv;337	const struct vpu_format *fmt;338	int ret = -EINVAL;339 340	vpu_inst_lock(inst);341	if (V4L2_TYPE_IS_CAPTURE(f->type) && vdec->fixed_fmt) {342		fmt = vpu_get_format(inst, f->type);343		if (f->index == 1)344			fmt = vpu_helper_find_sibling(inst, f->type, fmt->pixfmt);345		if (f->index > 1)346			fmt = NULL;347	} else {348		fmt = vpu_helper_enum_format(inst, f->type, f->index);349	}350	if (!fmt)351		goto exit;352 353	memset(f->reserved, 0, sizeof(f->reserved));354	f->pixelformat = fmt->pixfmt;355	f->flags = fmt->flags;356	ret = 0;357exit:358	vpu_inst_unlock(inst);359	return ret;360}361 362static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)363{364	struct vpu_inst *inst = to_inst(file);365	struct vdec_t *vdec = inst->priv;366	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;367	struct vpu_format *cur_fmt;368	int i;369 370	vpu_inst_lock(inst);371	cur_fmt = vpu_get_format(inst, f->type);372 373	pixmp->pixelformat = cur_fmt->pixfmt;374	pixmp->num_planes = cur_fmt->mem_planes;375	pixmp->width = cur_fmt->width;376	pixmp->height = cur_fmt->height;377	pixmp->field = cur_fmt->field;378	pixmp->flags = cur_fmt->flags;379	for (i = 0; i < pixmp->num_planes; i++) {380		pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i];381		pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(cur_fmt, i);382	}383 384	f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries;385	f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars;386	f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs;387	f->fmt.pix_mp.quantization = vdec->codec_info.full_range;388	vpu_inst_unlock(inst);389 390	return 0;391}392 393static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)394{395	struct vpu_inst *inst = to_inst(file);396	struct vdec_t *vdec = inst->priv;397	struct vpu_format fmt;398 399	vpu_inst_lock(inst);400	if (V4L2_TYPE_IS_CAPTURE(f->type) && vdec->fixed_fmt) {401		struct vpu_format *cap_fmt = vpu_get_format(inst, f->type);402 403		if (!vpu_helper_match_format(inst, cap_fmt->type, cap_fmt->pixfmt,404					     f->fmt.pix_mp.pixelformat))405			f->fmt.pix_mp.pixelformat = cap_fmt->pixfmt;406	}407 408	vpu_try_fmt_common(inst, f, &fmt);409 410	if (vdec->fixed_fmt) {411		f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries;412		f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars;413		f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs;414		f->fmt.pix_mp.quantization = vdec->codec_info.full_range;415	} else {416		f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;417		f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;418		f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;419		f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;420	}421	vpu_inst_unlock(inst);422 423	return 0;424}425 426static int vdec_s_fmt_common(struct vpu_inst *inst, struct v4l2_format *f)427{428	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;429	struct vpu_format fmt;430	struct vpu_format *cur_fmt;431	struct vb2_queue *q;432	struct vdec_t *vdec = inst->priv;433	int i;434 435	if (!inst->fh.m2m_ctx)436		return -EINVAL;437 438	q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type);439	if (!q)440		return -EINVAL;441	if (vb2_is_busy(q))442		return -EBUSY;443 444	if (vpu_try_fmt_common(inst, f, &fmt))445		return -EINVAL;446 447	cur_fmt = vpu_get_format(inst, f->type);448	if (V4L2_TYPE_IS_OUTPUT(f->type) && inst->state != VPU_CODEC_STATE_DEINIT) {449		if (cur_fmt->pixfmt != fmt.pixfmt) {450			vdec->reset_codec = true;451			vdec->fixed_fmt = false;452		}453	}454	if (V4L2_TYPE_IS_OUTPUT(f->type) || !vdec->fixed_fmt) {455		memcpy(cur_fmt, &fmt, sizeof(*cur_fmt));456	} else {457		if (vpu_helper_match_format(inst, f->type, cur_fmt->pixfmt, pixmp->pixelformat)) {458			cur_fmt->pixfmt = fmt.pixfmt;459			cur_fmt->mem_planes = fmt.mem_planes;460		}461		pixmp->pixelformat = cur_fmt->pixfmt;462		pixmp->num_planes = cur_fmt->mem_planes;463		pixmp->width = cur_fmt->width;464		pixmp->height = cur_fmt->height;465		for (i = 0; i < pixmp->num_planes; i++) {466			pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i];467			pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(cur_fmt, i);468		}469		pixmp->field = cur_fmt->field;470	}471 472	if (!vdec->fixed_fmt) {473		if (V4L2_TYPE_IS_OUTPUT(f->type)) {474			vdec->params.codec_format = cur_fmt->pixfmt;475			vdec->codec_info.color_primaries = f->fmt.pix_mp.colorspace;476			vdec->codec_info.transfer_chars = f->fmt.pix_mp.xfer_func;477			vdec->codec_info.matrix_coeffs = f->fmt.pix_mp.ycbcr_enc;478			vdec->codec_info.full_range = f->fmt.pix_mp.quantization;479		} else {480			vdec->params.output_format = cur_fmt->pixfmt;481			inst->crop.left = 0;482			inst->crop.top = 0;483			inst->crop.width = cur_fmt->width;484			inst->crop.height = cur_fmt->height;485		}486	}487 488	vpu_trace(inst->dev, "[%d] %c%c%c%c %dx%d\n", inst->id,489		  f->fmt.pix_mp.pixelformat,490		  f->fmt.pix_mp.pixelformat >> 8,491		  f->fmt.pix_mp.pixelformat >> 16,492		  f->fmt.pix_mp.pixelformat >> 24,493		  f->fmt.pix_mp.width,494		  f->fmt.pix_mp.height);495 496	return 0;497}498 499static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)500{501	struct vpu_inst *inst = to_inst(file);502	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;503	struct vdec_t *vdec = inst->priv;504	int ret = 0;505 506	vpu_inst_lock(inst);507	ret = vdec_s_fmt_common(inst, f);508	if (ret)509		goto exit;510 511	if (V4L2_TYPE_IS_OUTPUT(f->type) && !vdec->fixed_fmt) {512		struct v4l2_format fc;513 514		memset(&fc, 0, sizeof(fc));515		fc.type = inst->cap_format.type;516		fc.fmt.pix_mp.pixelformat = inst->cap_format.pixfmt;517		fc.fmt.pix_mp.width = pixmp->width;518		fc.fmt.pix_mp.height = pixmp->height;519		vdec_s_fmt_common(inst, &fc);520	}521 522	f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries;523	f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars;524	f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs;525	f->fmt.pix_mp.quantization = vdec->codec_info.full_range;526 527exit:528	vpu_inst_unlock(inst);529	return ret;530}531 532static int vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)533{534	struct vpu_inst *inst = to_inst(file);535 536	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)537		return -EINVAL;538 539	switch (s->target) {540	case V4L2_SEL_TGT_COMPOSE:541	case V4L2_SEL_TGT_COMPOSE_DEFAULT:542	case V4L2_SEL_TGT_COMPOSE_PADDED:543		s->r = inst->crop;544		break;545	case V4L2_SEL_TGT_COMPOSE_BOUNDS:546		s->r.left = 0;547		s->r.top = 0;548		s->r.width = inst->cap_format.width;549		s->r.height = inst->cap_format.height;550		break;551	default:552		return -EINVAL;553	}554 555	return 0;556}557 558static int vdec_drain(struct vpu_inst *inst)559{560	struct vdec_t *vdec = inst->priv;561 562	if (!inst->fh.m2m_ctx)563		return 0;564 565	if (!vdec->drain)566		return 0;567 568	if (!vpu_is_source_empty(inst))569		return 0;570 571	if (!vdec->params.frame_count) {572		vpu_set_last_buffer_dequeued(inst, true);573		return 0;574	}575 576	vpu_iface_add_scode(inst, SCODE_PADDING_EOS);577	vdec->params.end_flag = 1;578	vpu_iface_set_decode_params(inst, &vdec->params, 1);579	vdec->drain = 0;580	vpu_trace(inst->dev, "[%d] frame_count = %d\n", inst->id, vdec->params.frame_count);581 582	return 0;583}584 585static int vdec_cmd_start(struct vpu_inst *inst)586{587	struct vdec_t *vdec = inst->priv;588 589	switch (inst->state) {590	case VPU_CODEC_STATE_STARTED:591	case VPU_CODEC_STATE_DRAIN:592	case VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE:593		vdec_update_state(inst, VPU_CODEC_STATE_ACTIVE, 0);594		break;595	default:596		break;597	}598	vpu_process_capture_buffer(inst);599	if (vdec->eos_received)600		vdec_set_last_buffer_dequeued(inst);601	return 0;602}603 604static int vdec_cmd_stop(struct vpu_inst *inst)605{606	struct vdec_t *vdec = inst->priv;607 608	vpu_trace(inst->dev, "[%d]\n", inst->id);609 610	if (inst->state == VPU_CODEC_STATE_DEINIT) {611		vpu_set_last_buffer_dequeued(inst, true);612	} else {613		vdec->drain = 1;614		vdec_drain(inst);615	}616 617	return 0;618}619 620static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)621{622	struct vpu_inst *inst = to_inst(file);623	int ret;624 625	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);626	if (ret)627		return ret;628 629	vpu_inst_lock(inst);630	switch (cmd->cmd) {631	case V4L2_DEC_CMD_START:632		vdec_cmd_start(inst);633		break;634	case V4L2_DEC_CMD_STOP:635		vdec_cmd_stop(inst);636		break;637	default:638		break;639	}640	vpu_inst_unlock(inst);641 642	return 0;643}644 645static int vdec_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)646{647	switch (sub->type) {648	case V4L2_EVENT_EOS:649		return v4l2_event_subscribe(fh, sub, 0, NULL);650	case V4L2_EVENT_SOURCE_CHANGE:651		return v4l2_src_change_event_subscribe(fh, sub);652	case V4L2_EVENT_CTRL:653		return v4l2_ctrl_subscribe_event(fh, sub);654	default:655		return -EINVAL;656	}657 658	return 0;659}660 661static const struct v4l2_ioctl_ops vdec_ioctl_ops = {662	.vidioc_querycap               = vdec_querycap,663	.vidioc_enum_fmt_vid_cap       = vdec_enum_fmt,664	.vidioc_enum_fmt_vid_out       = vdec_enum_fmt,665	.vidioc_g_fmt_vid_cap_mplane   = vdec_g_fmt,666	.vidioc_g_fmt_vid_out_mplane   = vdec_g_fmt,667	.vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,668	.vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,669	.vidioc_s_fmt_vid_cap_mplane   = vdec_s_fmt,670	.vidioc_s_fmt_vid_out_mplane   = vdec_s_fmt,671	.vidioc_g_selection            = vdec_g_selection,672	.vidioc_try_decoder_cmd        = v4l2_m2m_ioctl_try_decoder_cmd,673	.vidioc_decoder_cmd            = vdec_decoder_cmd,674	.vidioc_subscribe_event        = vdec_subscribe_event,675	.vidioc_unsubscribe_event      = v4l2_event_unsubscribe,676	.vidioc_reqbufs                = v4l2_m2m_ioctl_reqbufs,677	.vidioc_create_bufs	       = v4l2_m2m_ioctl_create_bufs,678	.vidioc_prepare_buf	       = v4l2_m2m_ioctl_prepare_buf,679	.vidioc_querybuf               = v4l2_m2m_ioctl_querybuf,680	.vidioc_qbuf                   = v4l2_m2m_ioctl_qbuf,681	.vidioc_expbuf                 = v4l2_m2m_ioctl_expbuf,682	.vidioc_dqbuf                  = v4l2_m2m_ioctl_dqbuf,683	.vidioc_streamon               = v4l2_m2m_ioctl_streamon,684	.vidioc_streamoff              = v4l2_m2m_ioctl_streamoff,685};686 687static bool vdec_check_ready(struct vpu_inst *inst, unsigned int type)688{689	struct vdec_t *vdec = inst->priv;690 691	if (V4L2_TYPE_IS_OUTPUT(type))692		return true;693 694	if (vdec->req_frame_count)695		return true;696 697	return false;698}699 700static struct vb2_v4l2_buffer *vdec_get_src_buffer(struct vpu_inst *inst, u32 count)701{702	if (count > 1)703		vpu_skip_frame(inst, count - 1);704 705	return vpu_next_src_buf(inst);706}707 708static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)709{710	struct vdec_t *vdec = inst->priv;711	struct vpu_dec_pic_info *info = arg;712	struct vpu_vb2_buffer *vpu_buf;713	struct vb2_v4l2_buffer *vbuf;714	struct vb2_v4l2_buffer *src_buf;715	int ret = 0;716 717	if (!info || info->id >= ARRAY_SIZE(vdec->slots))718		return -EINVAL;719 720	vpu_inst_lock(inst);721	vpu_buf = vdec->slots[info->id];722	if (!vpu_buf) {723		dev_err(inst->dev, "[%d] decoded invalid frame[%d]\n", inst->id, info->id);724		ret = -EINVAL;725		goto exit;726	}727	vbuf = &vpu_buf->m2m_buf.vb;728	src_buf = vdec_get_src_buffer(inst, info->consumed_count);729	if (src_buf) {730		v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);731		if (info->consumed_count) {732			v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);733			vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);734			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);735		} else {736			vpu_set_buffer_state(src_buf, VPU_BUF_STATE_DECODED);737		}738	}739	if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED)740		dev_info(inst->dev, "[%d] buf[%d] has been decoded\n", inst->id, info->id);741	vpu_set_buffer_state(vbuf, VPU_BUF_STATE_DECODED);742	vdec->decoded_frame_count++;743	if (vdec->params.display_delay_enable) {744		struct vpu_format *cur_fmt;745 746		cur_fmt = vpu_get_format(inst, inst->cap_format.type);747		vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);748		for (int i = 0; i < vbuf->vb2_buf.num_planes; i++)749			vb2_set_plane_payload(&vbuf->vb2_buf,750					      i, vpu_get_fmt_plane_size(cur_fmt, i));751		vbuf->field = cur_fmt->field;752		vbuf->sequence = vdec->sequence++;753		dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);754 755		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);756		vdec->display_frame_count++;757	}758exit:759	vpu_inst_unlock(inst);760 761	return ret;762}763 764static struct vpu_vb2_buffer *vdec_find_buffer(struct vpu_inst *inst, u32 luma)765{766	struct vdec_t *vdec = inst->priv;767	int i;768 769	for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) {770		if (!vdec->slots[i])771			continue;772		if (luma == vdec->slots[i]->luma)773			return vdec->slots[i];774	}775 776	return NULL;777}778 779static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)780{781	struct vdec_t *vdec = inst->priv;782	struct vpu_format *cur_fmt;783	struct vpu_vb2_buffer *vpu_buf;784	struct vb2_v4l2_buffer *vbuf;785	int i;786 787	if (!frame)788		return;789 790	vpu_inst_lock(inst);791	if (!vdec->params.display_delay_enable)792		vdec->sequence++;793	vpu_buf = vdec_find_buffer(inst, frame->luma);794	vpu_inst_unlock(inst);795	if (!vpu_buf) {796		dev_err(inst->dev, "[%d] can't find buffer, id = %d, addr = 0x%x\n",797			inst->id, frame->id, frame->luma);798		return;799	}800	if (frame->skipped) {801		dev_dbg(inst->dev, "[%d] frame skip\n", inst->id);802		return;803	}804 805	cur_fmt = vpu_get_format(inst, inst->cap_format.type);806	vbuf = &vpu_buf->m2m_buf.vb;807	if (vbuf->vb2_buf.index != frame->id)808		dev_err(inst->dev, "[%d] buffer id(%d, %d) dismatch\n",809			inst->id, vbuf->vb2_buf.index, frame->id);810 811	if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_READY && vdec->params.display_delay_enable)812		return;813 814	if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_DECODED)815		dev_err(inst->dev, "[%d] buffer(%d) ready without decoded\n", inst->id, frame->id);816 817	vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);818	for (i = 0; i < vbuf->vb2_buf.num_planes; i++)819		vb2_set_plane_payload(&vbuf->vb2_buf, i, vpu_get_fmt_plane_size(cur_fmt, i));820	vbuf->field = cur_fmt->field;821	vbuf->sequence = vdec->sequence;822	dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);823 824	v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);825	vpu_inst_lock(inst);826	vdec->display_frame_count++;827	vpu_inst_unlock(inst);828	dev_dbg(inst->dev, "[%d] decoded : %d, display : %d, sequence : %d\n",829		inst->id, vdec->decoded_frame_count, vdec->display_frame_count, vdec->sequence);830}831 832static void vdec_stop_done(struct vpu_inst *inst)833{834	struct vdec_t *vdec = inst->priv;835 836	vpu_inst_lock(inst);837	vdec_update_state(inst, VPU_CODEC_STATE_DEINIT, 0);838	vdec->seq_hdr_found = 0;839	vdec->req_frame_count = 0;840	vdec->reset_codec = false;841	vdec->fixed_fmt = false;842	vdec->params.end_flag = 0;843	vdec->drain = 0;844	vdec->params.frame_count = 0;845	vdec->decoded_frame_count = 0;846	vdec->display_frame_count = 0;847	vdec->sequence = 0;848	vdec->eos_received = 0;849	vdec->is_source_changed = false;850	vdec->source_change = 0;851	inst->total_input_count = 0;852	vpu_inst_unlock(inst);853}854 855static bool vdec_check_source_change(struct vpu_inst *inst)856{857	struct vdec_t *vdec = inst->priv;858	const struct vpu_format *sibling;859 860	if (!inst->fh.m2m_ctx)861		return false;862 863	if (vdec->reset_codec)864		return false;865 866	sibling = vpu_helper_find_sibling(inst, inst->cap_format.type, inst->cap_format.pixfmt);867	if (sibling && vdec->codec_info.pixfmt == sibling->pixfmt)868		vdec->codec_info.pixfmt = inst->cap_format.pixfmt;869 870	if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx)))871		return true;872	if (inst->cap_format.pixfmt != vdec->codec_info.pixfmt)873		return true;874	if (inst->cap_format.width != vdec->codec_info.decoded_width)875		return true;876	if (inst->cap_format.height != vdec->codec_info.decoded_height)877		return true;878	if (vpu_get_num_buffers(inst, inst->cap_format.type) < inst->min_buffer_cap)879		return true;880	if (inst->crop.left != vdec->codec_info.offset_x)881		return true;882	if (inst->crop.top != vdec->codec_info.offset_y)883		return true;884	if (inst->crop.width != vdec->codec_info.width)885		return true;886	if (inst->crop.height != vdec->codec_info.height)887		return true;888 889	return false;890}891 892static void vdec_init_fmt(struct vpu_inst *inst)893{894	struct vdec_t *vdec = inst->priv;895	struct v4l2_format f;896 897	memset(&f, 0, sizeof(f));898	f.type = inst->cap_format.type;899	f.fmt.pix_mp.pixelformat = vdec->codec_info.pixfmt;900	f.fmt.pix_mp.width = vdec->codec_info.decoded_width;901	f.fmt.pix_mp.height = vdec->codec_info.decoded_height;902	if (vdec->codec_info.progressive)903		f.fmt.pix_mp.field = V4L2_FIELD_NONE;904	else905		f.fmt.pix_mp.field = V4L2_FIELD_SEQ_TB;906	vpu_try_fmt_common(inst, &f, &inst->cap_format);907 908	inst->out_format.width = vdec->codec_info.width;909	inst->out_format.height = vdec->codec_info.height;910}911 912static void vdec_init_crop(struct vpu_inst *inst)913{914	struct vdec_t *vdec = inst->priv;915 916	inst->crop.left = vdec->codec_info.offset_x;917	inst->crop.top = vdec->codec_info.offset_y;918	inst->crop.width = vdec->codec_info.width;919	inst->crop.height = vdec->codec_info.height;920}921 922static void vdec_init_mbi(struct vpu_inst *inst)923{924	struct vdec_t *vdec = inst->priv;925 926	vdec->mbi.size = vdec->codec_info.mbi_size;927	vdec->mbi.max_count = ARRAY_SIZE(vdec->mbi.buffer);928	scnprintf(vdec->mbi.name, sizeof(vdec->mbi.name), "mbi");929	vdec->mbi.type = MEM_RES_MBI;930	vdec->mbi.tag = vdec->seq_tag;931}932 933static void vdec_init_dcp(struct vpu_inst *inst)934{935	struct vdec_t *vdec = inst->priv;936 937	vdec->dcp.size = vdec->codec_info.dcp_size;938	vdec->dcp.max_count = ARRAY_SIZE(vdec->dcp.buffer);939	scnprintf(vdec->dcp.name, sizeof(vdec->dcp.name), "dcp");940	vdec->dcp.type = MEM_RES_DCP;941	vdec->dcp.tag = vdec->seq_tag;942}943 944static void vdec_request_one_fs(struct vdec_fs_info *fs)945{946	fs->req_count++;947	if (fs->req_count > fs->max_count)948		fs->req_count = fs->max_count;949}950 951static int vdec_alloc_fs_buffer(struct vpu_inst *inst, struct vdec_fs_info *fs)952{953	struct vpu_buffer *buffer;954 955	if (!fs->size)956		return -EINVAL;957 958	if (fs->count >= fs->req_count)959		return -EINVAL;960 961	buffer = &fs->buffer[fs->count];962	if (buffer->virt && buffer->length >= fs->size)963		return 0;964 965	vpu_free_dma(buffer);966	buffer->length = fs->size;967	return vpu_alloc_dma(inst->core, buffer);968}969 970static void vdec_alloc_fs(struct vpu_inst *inst, struct vdec_fs_info *fs)971{972	int ret;973 974	while (fs->count < fs->req_count) {975		ret = vdec_alloc_fs_buffer(inst, fs);976		if (ret)977			break;978		fs->count++;979	}980}981 982static void vdec_clear_fs(struct vdec_fs_info *fs)983{984	u32 i;985 986	if (!fs)987		return;988 989	for (i = 0; i < ARRAY_SIZE(fs->buffer); i++)990		vpu_free_dma(&fs->buffer[i]);991	memset(fs, 0, sizeof(*fs));992}993 994static int vdec_response_fs(struct vpu_inst *inst, struct vdec_fs_info *fs)995{996	struct vpu_fs_info info;997	int ret;998 999	if (fs->index >= fs->count)1000		return 0;1001 1002	memset(&info, 0, sizeof(info));1003	info.id = fs->index;1004	info.type = fs->type;1005	info.tag = fs->tag;1006	info.luma_addr = fs->buffer[fs->index].phys;1007	info.luma_size = fs->buffer[fs->index].length;1008	ret = vpu_session_alloc_fs(inst, &info);1009	if (ret)1010		return ret;1011 1012	fs->index++;1013	return 0;1014}1015 1016static int vdec_response_frame_abnormal(struct vpu_inst *inst)1017{1018	struct vdec_t *vdec = inst->priv;1019	struct vpu_fs_info info;1020	int ret;1021 1022	if (!vdec->req_frame_count)1023		return 0;1024 1025	memset(&info, 0, sizeof(info));1026	info.type = MEM_RES_FRAME;1027	info.tag = vdec->seq_tag + 0xf0;1028	ret = vpu_session_alloc_fs(inst, &info);1029	if (ret)1030		return ret;1031	vdec->req_frame_count--;1032 1033	return 0;1034}1035 1036static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf)1037{1038	struct vdec_t *vdec = inst->priv;1039	struct vpu_vb2_buffer *vpu_buf;1040	struct vpu_fs_info info;1041	int ret;1042 1043	if (inst->state != VPU_CODEC_STATE_ACTIVE)1044		return -EINVAL;1045 1046	if (vdec->aborting)1047		return -EINVAL;1048 1049	if (!vdec->req_frame_count)1050		return -EINVAL;1051 1052	if (!vbuf)1053		return -EINVAL;1054 1055	if (vdec->slots[vbuf->vb2_buf.index]) {1056		dev_err(inst->dev, "[%d] repeat alloc fs %d\n",1057			inst->id, vbuf->vb2_buf.index);1058		return -EINVAL;1059	}1060 1061	dev_dbg(inst->dev, "[%d] state = %s, alloc fs %d, tag = 0x%x\n",1062		inst->id, vpu_codec_state_name(inst->state), vbuf->vb2_buf.index, vdec->seq_tag);1063	vpu_buf = to_vpu_vb2_buffer(vbuf);1064 1065	memset(&info, 0, sizeof(info));1066	info.id = vbuf->vb2_buf.index;1067	info.type = MEM_RES_FRAME;1068	info.tag = vdec->seq_tag;1069	info.luma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 0);1070	info.luma_size = inst->cap_format.sizeimage[0];1071	if (vbuf->vb2_buf.num_planes > 1)1072		info.chroma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 1);1073	else1074		info.chroma_addr = info.luma_addr + info.luma_size;1075	info.chromau_size = inst->cap_format.sizeimage[1];1076	info.bytesperline = inst->cap_format.bytesperline[0];1077	ret = vpu_session_alloc_fs(inst, &info);1078	if (ret)1079		return ret;1080 1081	vpu_buf->tag = info.tag;1082	vpu_buf->luma = info.luma_addr;1083	vpu_buf->chroma_u = info.chroma_addr;1084	vpu_buf->chroma_v = 0;1085	vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);1086	vdec->slots[info.id] = vpu_buf;1087	vdec->req_frame_count--;1088 1089	return 0;1090}1091 1092static void vdec_response_fs_request(struct vpu_inst *inst, bool force)1093{1094	struct vdec_t *vdec = inst->priv;1095	int i;1096	int ret;1097 1098	if (force) {1099		for (i = vdec->req_frame_count; i > 0; i--)1100			vdec_response_frame_abnormal(inst);1101		return;1102	}1103 1104	for (i = vdec->req_frame_count; i > 0; i--) {1105		ret = vpu_process_capture_buffer(inst);1106		if (ret)1107			break;1108		if (vdec->eos_received)1109			break;1110	}1111 1112	for (i = vdec->mbi.index; i < vdec->mbi.count; i++) {1113		if (vdec_response_fs(inst, &vdec->mbi))1114			break;1115		if (vdec->eos_received)1116			break;1117	}1118	for (i = vdec->dcp.index; i < vdec->dcp.count; i++) {1119		if (vdec_response_fs(inst, &vdec->dcp))1120			break;1121		if (vdec->eos_received)1122			break;1123	}1124}1125 1126static void vdec_response_fs_release(struct vpu_inst *inst, u32 id, u32 tag)1127{1128	struct vpu_fs_info info;1129 1130	memset(&info, 0, sizeof(info));1131	info.id = id;1132	info.tag = tag;1133	vpu_session_release_fs(inst, &info);1134}1135 1136static void vdec_recycle_buffer(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf)1137{1138	if (!inst->fh.m2m_ctx)1139		return;1140	if (vbuf->vb2_buf.state != VB2_BUF_STATE_ACTIVE)1141		return;1142	if (vpu_find_buf_by_idx(inst, vbuf->vb2_buf.type, vbuf->vb2_buf.index))1143		return;1144	v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf);1145}1146 1147static void vdec_clear_slots(struct vpu_inst *inst)1148{1149	struct vdec_t *vdec = inst->priv;1150	struct vpu_vb2_buffer *vpu_buf;1151	struct vb2_v4l2_buffer *vbuf;1152	int i;1153 1154	for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) {1155		if (!vdec->slots[i])1156			continue;1157 1158		vpu_buf = vdec->slots[i];1159		vbuf = &vpu_buf->m2m_buf.vb;1160 1161		vpu_trace(inst->dev, "clear slot %d\n", i);1162		vdec_response_fs_release(inst, i, vpu_buf->tag);1163		vdec_recycle_buffer(inst, vbuf);1164		vdec->slots[i]->state = VPU_BUF_STATE_IDLE;1165		vdec->slots[i] = NULL;1166	}1167}1168 1169static void vdec_event_seq_hdr(struct vpu_inst *inst, struct vpu_dec_codec_info *hdr)1170{1171	struct vdec_t *vdec = inst->priv;1172 1173	vpu_inst_lock(inst);1174	memcpy(&vdec->codec_info, hdr, sizeof(vdec->codec_info));1175 1176	vpu_trace(inst->dev, "[%d] %d x %d, crop : (%d, %d) %d x %d, %d, %d\n",1177		  inst->id,1178		  vdec->codec_info.decoded_width,1179		  vdec->codec_info.decoded_height,1180		  vdec->codec_info.offset_x,1181		  vdec->codec_info.offset_y,1182		  vdec->codec_info.width,1183		  vdec->codec_info.height,1184		  hdr->num_ref_frms,1185		  hdr->num_dpb_frms);1186	inst->min_buffer_cap = hdr->num_ref_frms + hdr->num_dpb_frms;1187	vdec->is_source_changed = vdec_check_source_change(inst);1188	vdec_init_fmt(inst);1189	vdec_init_crop(inst);1190	vdec_init_mbi(inst);1191	vdec_init_dcp(inst);1192	if (!vdec->seq_hdr_found) {1193		vdec->seq_tag = vdec->codec_info.tag;1194		if (vdec->is_source_changed) {1195			vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0);1196			vdec->source_change++;1197			vdec_handle_resolution_change(inst);1198			vdec->is_source_changed = false;1199		}1200	}1201	if (vdec->seq_tag != vdec->codec_info.tag) {1202		vdec_response_fs_request(inst, true);1203		vpu_trace(inst->dev, "[%d] seq tag change: %d -> %d\n",1204			  inst->id, vdec->seq_tag, vdec->codec_info.tag);1205	}1206	vdec->seq_hdr_found++;1207	vdec->fixed_fmt = true;1208	vpu_inst_unlock(inst);1209}1210 1211static void vdec_event_resolution_change(struct vpu_inst *inst)1212{1213	struct vdec_t *vdec = inst->priv;1214 1215	vpu_trace(inst->dev, "[%d]\n", inst->id);1216	vpu_inst_lock(inst);1217	vdec->seq_tag = vdec->codec_info.tag;1218	vdec_clear_fs(&vdec->mbi);1219	vdec_clear_fs(&vdec->dcp);1220	vdec_clear_slots(inst);1221	vdec_init_mbi(inst);1222	vdec_init_dcp(inst);1223	if (vdec->is_source_changed) {1224		vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0);1225		vdec->source_change++;1226		vdec_handle_resolution_change(inst);1227		vdec->is_source_changed = false;1228	}1229	vpu_inst_unlock(inst);1230}1231 1232static void vdec_event_req_fs(struct vpu_inst *inst, struct vpu_fs_info *fs)1233{1234	struct vdec_t *vdec = inst->priv;1235 1236	if (!fs)1237		return;1238 1239	vpu_inst_lock(inst);1240 1241	switch (fs->type) {1242	case MEM_RES_FRAME:1243		vdec->req_frame_count++;1244		break;1245	case MEM_RES_MBI:1246		vdec_request_one_fs(&vdec->mbi);1247		break;1248	case MEM_RES_DCP:1249		vdec_request_one_fs(&vdec->dcp);1250		break;1251	default:1252		break;1253	}1254 1255	vdec_alloc_fs(inst, &vdec->mbi);1256	vdec_alloc_fs(inst, &vdec->dcp);1257 1258	vdec_response_fs_request(inst, false);1259 1260	vpu_inst_unlock(inst);1261}1262 1263static void vdec_evnet_rel_fs(struct vpu_inst *inst, struct vpu_fs_info *fs)1264{1265	struct vdec_t *vdec = inst->priv;1266	struct vpu_vb2_buffer *vpu_buf;1267	struct vb2_v4l2_buffer *vbuf;1268 1269	if (!fs || fs->id >= ARRAY_SIZE(vdec->slots))1270		return;1271	if (fs->type != MEM_RES_FRAME)1272		return;1273 1274	if (fs->id >= vpu_get_num_buffers(inst, inst->cap_format.type)) {1275		dev_err(inst->dev, "[%d] invalid fs(%d) to release\n", inst->id, fs->id);1276		return;1277	}1278 1279	vpu_inst_lock(inst);1280	vpu_buf = vdec->slots[fs->id];1281	vdec->slots[fs->id] = NULL;1282 1283	if (!vpu_buf) {1284		dev_dbg(inst->dev, "[%d] fs[%d] has bee released\n", inst->id, fs->id);1285		goto exit;1286	}1287 1288	vbuf = &vpu_buf->m2m_buf.vb;1289	if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) {1290		dev_dbg(inst->dev, "[%d] frame skip\n", inst->id);1291		vdec->sequence++;1292	}1293 1294	vdec_response_fs_release(inst, fs->id, vpu_buf->tag);1295	if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_READY)1296		vdec_recycle_buffer(inst, vbuf);1297 1298	vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);1299	vpu_process_capture_buffer(inst);1300 1301exit:1302	vpu_inst_unlock(inst);1303}1304 1305static void vdec_event_eos(struct vpu_inst *inst)1306{1307	struct vdec_t *vdec = inst->priv;1308 1309	vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n",1310		  inst->id,1311		  vdec->params.frame_count,1312		  vdec->decoded_frame_count,1313		  vdec->display_frame_count,1314		  vdec->sequence);1315	vpu_inst_lock(inst);1316	vdec->eos_received++;1317	vdec->fixed_fmt = false;1318	inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP;1319	vdec_set_last_buffer_dequeued(inst);1320	vpu_inst_unlock(inst);1321}1322 1323static void vdec_event_notify(struct vpu_inst *inst, u32 event, void *data)1324{1325	switch (event) {1326	case VPU_MSG_ID_SEQ_HDR_FOUND:1327		vdec_event_seq_hdr(inst, data);1328		break;1329	case VPU_MSG_ID_RES_CHANGE:1330		vdec_event_resolution_change(inst);1331		break;1332	case VPU_MSG_ID_FRAME_REQ:1333		vdec_event_req_fs(inst, data);1334		break;1335	case VPU_MSG_ID_FRAME_RELEASE:1336		vdec_evnet_rel_fs(inst, data);1337		break;1338	case VPU_MSG_ID_PIC_EOS:1339		vdec_event_eos(inst);1340		break;1341	default:1342		break;1343	}1344}1345 1346static int vdec_process_output(struct vpu_inst *inst, struct vb2_buffer *vb)1347{1348	struct vdec_t *vdec = inst->priv;1349	struct vb2_v4l2_buffer *vbuf;1350	struct vpu_rpc_buffer_desc desc;1351	u32 free_space;1352	int ret;1353 1354	vbuf = to_vb2_v4l2_buffer(vb);1355	dev_dbg(inst->dev, "[%d] dec output [%d] %d : %ld\n",1356		inst->id, vbuf->sequence, vb->index, vb2_get_plane_payload(vb, 0));1357 1358	if (inst->state == VPU_CODEC_STATE_DEINIT)1359		return -EINVAL;1360	if (vdec->reset_codec)1361		return -EINVAL;1362 1363	if (inst->state == VPU_CODEC_STATE_STARTED)1364		vdec_update_state(inst, VPU_CODEC_STATE_ACTIVE, 0);1365 1366	ret = vpu_iface_get_stream_buffer_desc(inst, &desc);1367	if (ret)1368		return ret;1369 1370	free_space = vpu_helper_get_free_space(inst);1371	if (free_space < vb2_get_plane_payload(vb, 0) + 0x40000)1372		return -ENOMEM;1373 1374	vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);1375	ret = vpu_iface_input_frame(inst, vb);1376	if (ret < 0)1377		return -ENOMEM;1378 1379	dev_dbg(inst->dev, "[%d][INPUT  TS]%32lld\n", inst->id, vb->timestamp);1380	vdec->params.frame_count++;1381 1382	if (vdec->drain)1383		vdec_drain(inst);1384 1385	return 0;1386}1387 1388static int vdec_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb)1389{1390	struct vdec_t *vdec = inst->priv;1391	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1392	int ret;1393 1394	if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)1395		return -EINVAL;1396	if (vdec->reset_codec)1397		return -EINVAL;1398 1399	ret = vdec_response_frame(inst, vbuf);1400	if (ret)1401		return ret;1402	v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);1403	return 0;1404}1405 1406static void vdec_on_queue_empty(struct vpu_inst *inst, u32 type)1407{1408	struct vdec_t *vdec = inst->priv;1409 1410	if (V4L2_TYPE_IS_OUTPUT(type))1411		return;1412 1413	vdec_handle_resolution_change(inst);1414	if (vdec->eos_received)1415		vdec_set_last_buffer_dequeued(inst);1416}1417 1418static void vdec_abort(struct vpu_inst *inst)1419{1420	struct vdec_t *vdec = inst->priv;1421	struct vpu_rpc_buffer_desc desc;1422	int ret;1423 1424	vpu_trace(inst->dev, "[%d] state = %s\n", inst->id, vpu_codec_state_name(inst->state));1425 1426	vdec->aborting = true;1427	vpu_iface_add_scode(inst, SCODE_PADDING_ABORT);1428	vdec->params.end_flag = 1;1429	vpu_iface_set_decode_params(inst, &vdec->params, 1);1430 1431	vpu_session_abort(inst);1432 1433	ret = vpu_iface_get_stream_buffer_desc(inst, &desc);1434	if (!ret)1435		vpu_iface_update_stream_buffer(inst, desc.rptr, 1);1436 1437	vpu_session_rst_buf(inst);1438	vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n",1439		  inst->id,1440		  vdec->params.frame_count,1441		  vdec->decoded_frame_count,1442		  vdec->display_frame_count,1443		  vdec->sequence);1444	if (!vdec->seq_hdr_found)1445		vdec->reset_codec = true;1446	vdec->params.end_flag = 0;1447	vdec->drain = 0;1448	vdec->params.frame_count = 0;1449	vdec->decoded_frame_count = 0;1450	vdec->display_frame_count = 0;1451	vdec->sequence = 0;1452	vdec->aborting = false;1453	inst->extra_size = 0;1454}1455 1456static void vdec_stop(struct vpu_inst *inst, bool free)1457{1458	struct vdec_t *vdec = inst->priv;1459 1460	vdec_clear_slots(inst);1461	if (inst->state != VPU_CODEC_STATE_DEINIT)1462		vpu_session_stop(inst);1463	vdec_clear_fs(&vdec->mbi);1464	vdec_clear_fs(&vdec->dcp);1465	if (free) {1466		vpu_free_dma(&vdec->udata);1467		vpu_free_dma(&inst->stream_buffer);1468	}1469	vdec_update_state(inst, VPU_CODEC_STATE_DEINIT, 1);1470	vdec->reset_codec = false;1471}1472 1473static void vdec_release(struct vpu_inst *inst)1474{1475	if (inst->id != VPU_INST_NULL_ID)1476		vpu_trace(inst->dev, "[%d]\n", inst->id);1477	vdec_stop(inst, true);1478}1479 1480static void vdec_cleanup(struct vpu_inst *inst)1481{1482	struct vdec_t *vdec;1483 1484	if (!inst)1485		return;1486 1487	vdec = inst->priv;1488	vfree(vdec);1489	inst->priv = NULL;1490	vfree(inst);1491}1492 1493static void vdec_init_params(struct vdec_t *vdec)1494{1495	vdec->params.frame_count = 0;1496	vdec->params.end_flag = 0;1497}1498 1499static int vdec_start(struct vpu_inst *inst)1500{1501	struct vdec_t *vdec = inst->priv;1502	int stream_buffer_size;1503	int ret;1504 1505	if (inst->state != VPU_CODEC_STATE_DEINIT)1506		return 0;1507 1508	vpu_trace(inst->dev, "[%d]\n", inst->id);1509	if (!vdec->udata.virt) {1510		vdec->udata.length = 0x1000;1511		ret = vpu_alloc_dma(inst->core, &vdec->udata);1512		if (ret) {1513			dev_err(inst->dev, "[%d] alloc udata fail\n", inst->id);1514			goto error;1515		}1516	}1517 1518	if (!inst->stream_buffer.virt) {1519		stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core);1520		if (stream_buffer_size > 0) {1521			inst->stream_buffer.length = stream_buffer_size;1522			ret = vpu_alloc_dma(inst->core, &inst->stream_buffer);1523			if (ret) {1524				dev_err(inst->dev, "[%d] alloc stream buffer fail\n", inst->id);1525				goto error;1526			}1527			inst->use_stream_buffer = true;1528		}1529	}1530 1531	if (inst->use_stream_buffer)1532		vpu_iface_config_stream_buffer(inst, &inst->stream_buffer);1533	vpu_iface_init_instance(inst);1534	vdec->params.udata.base = vdec->udata.phys;1535	vdec->params.udata.size = vdec->udata.length;1536	ret = vpu_iface_set_decode_params(inst, &vdec->params, 0);1537	if (ret) {1538		dev_err(inst->dev, "[%d] set decode params fail\n", inst->id);1539		goto error;1540	}1541 1542	vdec_init_params(vdec);1543	ret = vpu_session_start(inst);1544	if (ret) {1545		dev_err(inst->dev, "[%d] start fail\n", inst->id);1546		goto error;1547	}1548 1549	vdec_update_state(inst, VPU_CODEC_STATE_STARTED, 0);1550 1551	return 0;1552error:1553	vpu_free_dma(&vdec->udata);1554	vpu_free_dma(&inst->stream_buffer);1555	return ret;1556}1557 1558static int vdec_start_session(struct vpu_inst *inst, u32 type)1559{1560	struct vdec_t *vdec = inst->priv;1561	int ret = 0;1562 1563	if (V4L2_TYPE_IS_OUTPUT(type)) {1564		if (vdec->reset_codec)1565			vdec_stop(inst, false);1566		if (inst->state == VPU_CODEC_STATE_DEINIT) {1567			ret = vdec_start(inst);1568			if (ret)1569				return ret;1570		}1571	}1572 1573	if (V4L2_TYPE_IS_OUTPUT(type)) {1574		vdec_update_state(inst, vdec->state, 1);1575		vdec->eos_received = 0;1576		vpu_process_output_buffer(inst);1577	} else {1578		vdec_cmd_start(inst);1579	}1580	if (inst->state == VPU_CODEC_STATE_ACTIVE)1581		vdec_response_fs_request(inst, false);1582 1583	return ret;1584}1585 1586static int vdec_stop_session(struct vpu_inst *inst, u32 type)1587{1588	struct vdec_t *vdec = inst->priv;1589 1590	if (inst->state == VPU_CODEC_STATE_DEINIT)1591		return 0;1592 1593	if (V4L2_TYPE_IS_OUTPUT(type)) {1594		vdec_update_state(inst, VPU_CODEC_STATE_SEEK, 0);1595		vdec->drain = 0;1596		vdec_abort(inst);1597	} else {1598		if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) {1599			if (vb2_is_streaming(v4l2_m2m_get_src_vq(inst->fh.m2m_ctx)))1600				vdec_abort(inst);1601			vdec->eos_received = 0;1602		}1603		vdec_clear_slots(inst);1604	}1605 1606	return 0;1607}1608 1609static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)1610{1611	struct vdec_t *vdec = inst->priv;1612	int num = -1;1613 1614	switch (i) {1615	case 0:1616		num = scnprintf(str, size,1617				"req_frame_count = %d\ninterlaced = %d\n",1618				vdec->req_frame_count,1619				vdec->codec_info.progressive ? 0 : 1);1620		break;1621	case 1:1622		num = scnprintf(str, size,1623				"mbi: size = 0x%x request = %d, alloc = %d, response = %d\n",1624				vdec->mbi.size,1625				vdec->mbi.req_count,1626				vdec->mbi.count,1627				vdec->mbi.index);1628		break;1629	case 2:1630		num = scnprintf(str, size,1631				"dcp: size = 0x%x request = %d, alloc = %d, response = %d\n",1632				vdec->dcp.size,1633				vdec->dcp.req_count,1634				vdec->dcp.count,1635				vdec->dcp.index);1636		break;1637	case 3:1638		num = scnprintf(str, size, "input_frame_count = %d\n", vdec->params.frame_count);1639		break;1640	case 4:1641		num = scnprintf(str, size, "decoded_frame_count = %d\n", vdec->decoded_frame_count);1642		break;1643	case 5:1644		num = scnprintf(str, size, "display_frame_count = %d\n", vdec->display_frame_count);1645		break;1646	case 6:1647		num = scnprintf(str, size, "sequence = %d\n", vdec->sequence);1648		break;1649	case 7:1650		num = scnprintf(str, size, "drain = %d, eos = %d, source_change = %d\n",1651				vdec->drain, vdec->eos_received, vdec->source_change);1652		break;1653	case 8:1654		num = scnprintf(str, size, "fps = %d/%d\n",1655				vdec->codec_info.frame_rate.numerator,1656				vdec->codec_info.frame_rate.denominator);1657		break;1658	case 9:1659		num = scnprintf(str, size, "colorspace: %d, %d, %d, %d (%d)\n",1660				vdec->codec_info.color_primaries,1661				vdec->codec_info.transfer_chars,1662				vdec->codec_info.matrix_coeffs,1663				vdec->codec_info.full_range,1664				vdec->codec_info.vui_present);1665		break;1666	default:1667		break;1668	}1669 1670	return num;1671}1672 1673static struct vpu_inst_ops vdec_inst_ops = {1674	.ctrl_init = vdec_ctrl_init,1675	.check_ready = vdec_check_ready,1676	.buf_done = vdec_buf_done,1677	.get_one_frame = vdec_frame_decoded,1678	.stop_done = vdec_stop_done,1679	.event_notify = vdec_event_notify,1680	.release = vdec_release,1681	.cleanup = vdec_cleanup,1682	.start = vdec_start_session,1683	.stop = vdec_stop_session,1684	.process_output = vdec_process_output,1685	.process_capture = vdec_process_capture,1686	.on_queue_empty = vdec_on_queue_empty,1687	.get_debug_info = vdec_get_debug_info,1688	.wait_prepare = vpu_inst_unlock,1689	.wait_finish = vpu_inst_lock,1690};1691 1692static void vdec_init(struct file *file)1693{1694	struct vpu_inst *inst = to_inst(file);1695	struct v4l2_format f;1696 1697	memset(&f, 0, sizeof(f));1698	f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;1699	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;1700	f.fmt.pix_mp.width = 1280;1701	f.fmt.pix_mp.height = 720;1702	f.fmt.pix_mp.field = V4L2_FIELD_NONE;1703	vdec_s_fmt(file, &inst->fh, &f);1704 1705	memset(&f, 0, sizeof(f));1706	f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;1707	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M_8L128;1708	f.fmt.pix_mp.width = 1280;1709	f.fmt.pix_mp.height = 720;1710	f.fmt.pix_mp.field = V4L2_FIELD_NONE;1711	vdec_s_fmt(file, &inst->fh, &f);1712}1713 1714static int vdec_open(struct file *file)1715{1716	struct vpu_inst *inst;1717	struct vdec_t *vdec;1718	int ret;1719 1720	inst = vzalloc(sizeof(*inst));1721	if (!inst)1722		return -ENOMEM;1723 1724	vdec = vzalloc(sizeof(*vdec));1725	if (!vdec) {1726		vfree(inst);1727		return -ENOMEM;1728	}1729 1730	inst->ops = &vdec_inst_ops;1731	inst->formats = vdec_formats;1732	inst->type = VPU_CORE_TYPE_DEC;1733	inst->priv = vdec;1734 1735	ret = vpu_v4l2_open(file, inst);1736	if (ret)1737		return ret;1738 1739	vdec->fixed_fmt = false;1740	vdec->state = VPU_CODEC_STATE_ACTIVE;1741	inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP;1742	inst->min_buffer_out = VDEC_MIN_BUFFER_OUT;1743	vdec_init(file);1744 1745	return 0;1746}1747 1748static const struct v4l2_file_operations vdec_fops = {1749	.owner = THIS_MODULE,1750	.open = vdec_open,1751	.release = vpu_v4l2_close,1752	.unlocked_ioctl = video_ioctl2,1753	.poll = v4l2_m2m_fop_poll,1754	.mmap = v4l2_m2m_fop_mmap,1755};1756 1757const struct v4l2_ioctl_ops *vdec_get_ioctl_ops(void)1758{1759	return &vdec_ioctl_ops;1760}1761 1762const struct v4l2_file_operations *vdec_get_fops(void)1763{1764	return &vdec_fops;1765}1766