cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vdec.c (45183B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
      4 * Copyright (C) 2017 Linaro Ltd.
      5 */
      6#include <linux/clk.h>
      7#include <linux/module.h>
      8#include <linux/mod_devicetable.h>
      9#include <linux/platform_device.h>
     10#include <linux/pm_runtime.h>
     11#include <linux/slab.h>
     12#include <media/v4l2-ioctl.h>
     13#include <media/v4l2-event.h>
     14#include <media/v4l2-ctrls.h>
     15#include <media/v4l2-mem2mem.h>
     16#include <media/videobuf2-dma-contig.h>
     17
     18#include "hfi_venus_io.h"
     19#include "hfi_parser.h"
     20#include "core.h"
     21#include "helpers.h"
     22#include "vdec.h"
     23#include "pm_helpers.h"
     24
     25/*
     26 * Three resons to keep MPLANE formats (despite that the number of planes
     27 * currently is one):
     28 * - the MPLANE formats allow only one plane to be used
     29 * - the downstream driver use MPLANE formats too
     30 * - future firmware versions could add support for >1 planes
     31 */
     32static const struct venus_format vdec_formats[] = {
     33	{
     34		.pixfmt = V4L2_PIX_FMT_QC08C,
     35		.num_planes = 1,
     36		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
     37	}, {
     38		.pixfmt = V4L2_PIX_FMT_QC10C,
     39		.num_planes = 1,
     40		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
     41	},{
     42		.pixfmt = V4L2_PIX_FMT_NV12,
     43		.num_planes = 1,
     44		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
     45	}, {
     46		.pixfmt = V4L2_PIX_FMT_MPEG4,
     47		.num_planes = 1,
     48		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     49		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     50	}, {
     51		.pixfmt = V4L2_PIX_FMT_MPEG2,
     52		.num_planes = 1,
     53		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     54		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     55	}, {
     56		.pixfmt = V4L2_PIX_FMT_H263,
     57		.num_planes = 1,
     58		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     59		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     60	}, {
     61		.pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
     62		.num_planes = 1,
     63		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     64		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     65	}, {
     66		.pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
     67		.num_planes = 1,
     68		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     69		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     70	}, {
     71		.pixfmt = V4L2_PIX_FMT_H264,
     72		.num_planes = 1,
     73		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     74		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     75	}, {
     76		.pixfmt = V4L2_PIX_FMT_VP8,
     77		.num_planes = 1,
     78		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     79		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     80	}, {
     81		.pixfmt = V4L2_PIX_FMT_VP9,
     82		.num_planes = 1,
     83		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     84		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     85	}, {
     86		.pixfmt = V4L2_PIX_FMT_XVID,
     87		.num_planes = 1,
     88		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     89		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     90	}, {
     91		.pixfmt = V4L2_PIX_FMT_HEVC,
     92		.num_planes = 1,
     93		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
     94		.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
     95	},
     96};
     97
     98static const struct venus_format *
     99find_format(struct venus_inst *inst, u32 pixfmt, u32 type)
    100{
    101	const struct venus_format *fmt = vdec_formats;
    102	unsigned int size = ARRAY_SIZE(vdec_formats);
    103	unsigned int i;
    104
    105	for (i = 0; i < size; i++) {
    106		if (fmt[i].pixfmt == pixfmt)
    107			break;
    108	}
    109
    110	if (i == size || fmt[i].type != type)
    111		return NULL;
    112
    113	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
    114	    !venus_helper_check_codec(inst, fmt[i].pixfmt))
    115		return NULL;
    116
    117	if (V4L2_TYPE_IS_CAPTURE(type) &&
    118	    !venus_helper_check_format(inst, fmt[i].pixfmt))
    119		return NULL;
    120
    121	if (V4L2_TYPE_IS_CAPTURE(type) && fmt[i].pixfmt == V4L2_PIX_FMT_QC10C &&
    122	    !(inst->bit_depth == VIDC_BITDEPTH_10))
    123		return NULL;
    124
    125	return &fmt[i];
    126}
    127
    128static const struct venus_format *
    129find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
    130{
    131	const struct venus_format *fmt = vdec_formats;
    132	unsigned int size = ARRAY_SIZE(vdec_formats);
    133	unsigned int i, k = 0;
    134
    135	if (index > size)
    136		return NULL;
    137
    138	for (i = 0; i < size; i++) {
    139		bool valid;
    140
    141		if (fmt[i].type != type)
    142			continue;
    143
    144		if (V4L2_TYPE_IS_OUTPUT(type)) {
    145			valid = venus_helper_check_codec(inst, fmt[i].pixfmt);
    146		} else if (V4L2_TYPE_IS_CAPTURE(type)) {
    147			valid = venus_helper_check_format(inst, fmt[i].pixfmt);
    148
    149			if (fmt[i].pixfmt == V4L2_PIX_FMT_QC10C &&
    150			    !(inst->bit_depth == VIDC_BITDEPTH_10))
    151				valid = false;
    152		}
    153
    154		if (k == index && valid)
    155			break;
    156		if (valid)
    157			k++;
    158	}
    159
    160	if (i == size)
    161		return NULL;
    162
    163	return &fmt[i];
    164}
    165
    166static const struct venus_format *
    167vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
    168{
    169	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
    170	struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt;
    171	const struct venus_format *fmt;
    172	u32 szimage;
    173
    174	memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
    175	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
    176
    177	fmt = find_format(inst, pixmp->pixelformat, f->type);
    178	if (!fmt) {
    179		if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
    180			pixmp->pixelformat = V4L2_PIX_FMT_NV12;
    181		else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
    182			pixmp->pixelformat = V4L2_PIX_FMT_H264;
    183		else
    184			return NULL;
    185		fmt = find_format(inst, pixmp->pixelformat, f->type);
    186	}
    187
    188	pixmp->width = clamp(pixmp->width, frame_width_min(inst),
    189			     frame_width_max(inst));
    190	pixmp->height = clamp(pixmp->height, frame_height_min(inst),
    191			      frame_height_max(inst));
    192
    193	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
    194		pixmp->height = ALIGN(pixmp->height, 32);
    195
    196	if (pixmp->field == V4L2_FIELD_ANY)
    197		pixmp->field = V4L2_FIELD_NONE;
    198	pixmp->num_planes = fmt->num_planes;
    199	pixmp->flags = 0;
    200
    201	szimage = venus_helper_get_framesz(pixmp->pixelformat, pixmp->width,
    202					   pixmp->height);
    203
    204	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
    205		pfmt[0].sizeimage = szimage;
    206		pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
    207	} else {
    208		pfmt[0].sizeimage = clamp_t(u32, pfmt[0].sizeimage, 0, SZ_8M);
    209		pfmt[0].sizeimage = max(pfmt[0].sizeimage, szimage);
    210		pfmt[0].bytesperline = 0;
    211	}
    212
    213	return fmt;
    214}
    215
    216static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
    217{
    218	struct venus_inst *inst = to_inst(file);
    219
    220	vdec_try_fmt_common(inst, f);
    221
    222	return 0;
    223}
    224
    225static int vdec_check_src_change(struct venus_inst *inst)
    226{
    227	int ret;
    228
    229	if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE &&
    230	    inst->codec_state == VENUS_DEC_STATE_INIT &&
    231	    !inst->reconfig)
    232		return -EINVAL;
    233
    234	if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE)
    235		return 0;
    236
    237	/*
    238	 * The code snippet below is a workaround for backward compatibility
    239	 * with applications which doesn't support V4L2 events. It will be
    240	 * dropped in future once those applications are fixed.
    241	 */
    242
    243	if (inst->codec_state != VENUS_DEC_STATE_INIT)
    244		goto done;
    245
    246	ret = wait_event_timeout(inst->reconf_wait, inst->reconfig,
    247				 msecs_to_jiffies(100));
    248	if (!ret)
    249		return -EINVAL;
    250
    251	if (!(inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) ||
    252	    !inst->reconfig)
    253		dev_dbg(inst->core->dev, VDBGH "wrong state\n");
    254
    255done:
    256	return 0;
    257}
    258
    259static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
    260{
    261	struct venus_inst *inst = to_inst(file);
    262	const struct venus_format *fmt = NULL;
    263	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
    264	int ret;
    265
    266	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
    267		fmt = inst->fmt_cap;
    268	else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
    269		fmt = inst->fmt_out;
    270
    271	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
    272		ret = vdec_check_src_change(inst);
    273		if (ret)
    274			return ret;
    275	}
    276
    277	pixmp->pixelformat = fmt->pixfmt;
    278
    279	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
    280		pixmp->width = inst->width;
    281		pixmp->height = inst->height;
    282		pixmp->colorspace = inst->colorspace;
    283		pixmp->ycbcr_enc = inst->ycbcr_enc;
    284		pixmp->quantization = inst->quantization;
    285		pixmp->xfer_func = inst->xfer_func;
    286	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    287		pixmp->width = inst->out_width;
    288		pixmp->height = inst->out_height;
    289	}
    290
    291	vdec_try_fmt_common(inst, f);
    292
    293	return 0;
    294}
    295
    296static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
    297{
    298	struct venus_inst *inst = to_inst(file);
    299	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
    300	struct v4l2_pix_format_mplane orig_pixmp;
    301	const struct venus_format *fmt;
    302	struct v4l2_format format;
    303	u32 pixfmt_out = 0, pixfmt_cap = 0;
    304	struct vb2_queue *q;
    305
    306	q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
    307	if (!q)
    308		return -EINVAL;
    309
    310	if (vb2_is_busy(q))
    311		return -EBUSY;
    312
    313	orig_pixmp = *pixmp;
    314
    315	fmt = vdec_try_fmt_common(inst, f);
    316
    317	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    318		pixfmt_out = pixmp->pixelformat;
    319		pixfmt_cap = inst->fmt_cap->pixfmt;
    320	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
    321		pixfmt_cap = pixmp->pixelformat;
    322		pixfmt_out = inst->fmt_out->pixfmt;
    323	}
    324
    325	memset(&format, 0, sizeof(format));
    326
    327	format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    328	format.fmt.pix_mp.pixelformat = pixfmt_out;
    329	format.fmt.pix_mp.width = orig_pixmp.width;
    330	format.fmt.pix_mp.height = orig_pixmp.height;
    331	vdec_try_fmt_common(inst, &format);
    332
    333	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    334		inst->out_width = format.fmt.pix_mp.width;
    335		inst->out_height = format.fmt.pix_mp.height;
    336		inst->colorspace = pixmp->colorspace;
    337		inst->ycbcr_enc = pixmp->ycbcr_enc;
    338		inst->quantization = pixmp->quantization;
    339		inst->xfer_func = pixmp->xfer_func;
    340		inst->input_buf_size = pixmp->plane_fmt[0].sizeimage;
    341	}
    342
    343	memset(&format, 0, sizeof(format));
    344
    345	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    346	format.fmt.pix_mp.pixelformat = pixfmt_cap;
    347	format.fmt.pix_mp.width = orig_pixmp.width;
    348	format.fmt.pix_mp.height = orig_pixmp.height;
    349	vdec_try_fmt_common(inst, &format);
    350
    351	inst->width = format.fmt.pix_mp.width;
    352	inst->height = format.fmt.pix_mp.height;
    353	inst->crop.top = 0;
    354	inst->crop.left = 0;
    355	inst->crop.width = inst->width;
    356	inst->crop.height = inst->height;
    357
    358	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
    359		inst->fmt_out = fmt;
    360	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
    361		inst->fmt_cap = fmt;
    362		inst->output2_buf_size =
    363			venus_helper_get_framesz(pixfmt_cap, orig_pixmp.width, orig_pixmp.height);
    364	}
    365
    366	return 0;
    367}
    368
    369static int
    370vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
    371{
    372	struct venus_inst *inst = to_inst(file);
    373
    374	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
    375	    s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
    376		return -EINVAL;
    377
    378	s->r.top = 0;
    379	s->r.left = 0;
    380
    381	switch (s->target) {
    382	case V4L2_SEL_TGT_CROP_BOUNDS:
    383	case V4L2_SEL_TGT_CROP_DEFAULT:
    384	case V4L2_SEL_TGT_CROP:
    385		if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
    386			return -EINVAL;
    387		s->r.width = inst->out_width;
    388		s->r.height = inst->out_height;
    389		break;
    390	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
    391	case V4L2_SEL_TGT_COMPOSE_PADDED:
    392		if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    393			return -EINVAL;
    394		s->r.width = inst->width;
    395		s->r.height = inst->height;
    396		break;
    397	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
    398	case V4L2_SEL_TGT_COMPOSE:
    399		if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    400			return -EINVAL;
    401		s->r = inst->crop;
    402		break;
    403	default:
    404		return -EINVAL;
    405	}
    406
    407	return 0;
    408}
    409
    410static int
    411vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
    412{
    413	strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
    414	strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
    415	strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
    416
    417	return 0;
    418}
    419
    420static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
    421{
    422	struct venus_inst *inst = to_inst(file);
    423	const struct venus_format *fmt;
    424
    425	memset(f->reserved, 0, sizeof(f->reserved));
    426
    427	fmt = find_format_by_index(inst, f->index, f->type);
    428	if (!fmt)
    429		return -EINVAL;
    430
    431	f->pixelformat = fmt->pixfmt;
    432	f->flags = fmt->flags;
    433
    434	return 0;
    435}
    436
    437static int vdec_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
    438{
    439	struct venus_inst *inst = to_inst(file);
    440	struct v4l2_captureparm *cap = &a->parm.capture;
    441	struct v4l2_fract *timeperframe = &cap->timeperframe;
    442	u64 us_per_frame, fps;
    443
    444	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
    445	    a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
    446		return -EINVAL;
    447
    448	memset(cap->reserved, 0, sizeof(cap->reserved));
    449	if (!timeperframe->denominator)
    450		timeperframe->denominator = inst->timeperframe.denominator;
    451	if (!timeperframe->numerator)
    452		timeperframe->numerator = inst->timeperframe.numerator;
    453	cap->readbuffers = 0;
    454	cap->extendedmode = 0;
    455	cap->capability = V4L2_CAP_TIMEPERFRAME;
    456	us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
    457	do_div(us_per_frame, timeperframe->denominator);
    458
    459	if (!us_per_frame)
    460		return -EINVAL;
    461
    462	fps = (u64)USEC_PER_SEC;
    463	do_div(fps, us_per_frame);
    464
    465	inst->fps = fps;
    466	inst->timeperframe = *timeperframe;
    467
    468	return 0;
    469}
    470
    471static int vdec_enum_framesizes(struct file *file, void *fh,
    472				struct v4l2_frmsizeenum *fsize)
    473{
    474	struct venus_inst *inst = to_inst(file);
    475	const struct venus_format *fmt;
    476
    477	fmt = find_format(inst, fsize->pixel_format,
    478			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
    479	if (!fmt) {
    480		fmt = find_format(inst, fsize->pixel_format,
    481				  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
    482		if (!fmt)
    483			return -EINVAL;
    484	}
    485
    486	if (fsize->index)
    487		return -EINVAL;
    488
    489	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
    490
    491	fsize->stepwise.min_width = frame_width_min(inst);
    492	fsize->stepwise.max_width = frame_width_max(inst);
    493	fsize->stepwise.step_width = frame_width_step(inst);
    494	fsize->stepwise.min_height = frame_height_min(inst);
    495	fsize->stepwise.max_height = frame_height_max(inst);
    496	fsize->stepwise.step_height = frame_height_step(inst);
    497
    498	return 0;
    499}
    500
    501static int vdec_subscribe_event(struct v4l2_fh *fh,
    502				const struct v4l2_event_subscription *sub)
    503{
    504	struct venus_inst *inst = container_of(fh, struct venus_inst, fh);
    505	int ret;
    506
    507	switch (sub->type) {
    508	case V4L2_EVENT_EOS:
    509		return v4l2_event_subscribe(fh, sub, 2, NULL);
    510	case V4L2_EVENT_SOURCE_CHANGE:
    511		ret = v4l2_src_change_event_subscribe(fh, sub);
    512		if (ret)
    513			return ret;
    514		inst->subscriptions |= V4L2_EVENT_SOURCE_CHANGE;
    515		return 0;
    516	case V4L2_EVENT_CTRL:
    517		return v4l2_ctrl_subscribe_event(fh, sub);
    518	default:
    519		return -EINVAL;
    520	}
    521}
    522
    523static int
    524vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
    525{
    526	struct venus_inst *inst = to_inst(file);
    527	struct hfi_frame_data fdata = {0};
    528	int ret;
    529
    530	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
    531	if (ret)
    532		return ret;
    533
    534	mutex_lock(&inst->lock);
    535
    536	if (cmd->cmd == V4L2_DEC_CMD_STOP) {
    537		/*
    538		 * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on
    539		 * decoder input to signal EOS.
    540		 */
    541		if (!(inst->streamon_out && inst->streamon_cap))
    542			goto unlock;
    543
    544		fdata.buffer_type = HFI_BUFFER_INPUT;
    545		fdata.flags |= HFI_BUFFERFLAG_EOS;
    546		if (IS_V6(inst->core))
    547			fdata.device_addr = 0;
    548		else
    549			fdata.device_addr = 0xdeadb000;
    550
    551		ret = hfi_session_process_buf(inst, &fdata);
    552
    553		if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING) {
    554			inst->codec_state = VENUS_DEC_STATE_DRAIN;
    555			inst->drain_active = true;
    556		}
    557	}
    558
    559unlock:
    560	mutex_unlock(&inst->lock);
    561	return ret;
    562}
    563
    564static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
    565	.vidioc_querycap = vdec_querycap,
    566	.vidioc_enum_fmt_vid_cap = vdec_enum_fmt,
    567	.vidioc_enum_fmt_vid_out = vdec_enum_fmt,
    568	.vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt,
    569	.vidioc_s_fmt_vid_out_mplane = vdec_s_fmt,
    570	.vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,
    571	.vidioc_g_fmt_vid_out_mplane = vdec_g_fmt,
    572	.vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,
    573	.vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,
    574	.vidioc_g_selection = vdec_g_selection,
    575	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
    576	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
    577	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
    578	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
    579	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
    580	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
    581	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
    582	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
    583	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
    584	.vidioc_s_parm = vdec_s_parm,
    585	.vidioc_enum_framesizes = vdec_enum_framesizes,
    586	.vidioc_subscribe_event = vdec_subscribe_event,
    587	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
    588	.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
    589	.vidioc_decoder_cmd = vdec_decoder_cmd,
    590};
    591
    592static int vdec_pm_get(struct venus_inst *inst)
    593{
    594	struct venus_core *core = inst->core;
    595	struct device *dev = core->dev_dec;
    596	int ret;
    597
    598	mutex_lock(&core->pm_lock);
    599	ret = pm_runtime_resume_and_get(dev);
    600	mutex_unlock(&core->pm_lock);
    601
    602	return ret;
    603}
    604
    605static int vdec_pm_put(struct venus_inst *inst, bool autosuspend)
    606{
    607	struct venus_core *core = inst->core;
    608	struct device *dev = core->dev_dec;
    609	int ret;
    610
    611	mutex_lock(&core->pm_lock);
    612
    613	if (autosuspend)
    614		ret = pm_runtime_put_autosuspend(dev);
    615	else
    616		ret = pm_runtime_put_sync(dev);
    617
    618	mutex_unlock(&core->pm_lock);
    619
    620	return ret < 0 ? ret : 0;
    621}
    622
    623static int vdec_pm_get_put(struct venus_inst *inst)
    624{
    625	struct venus_core *core = inst->core;
    626	struct device *dev = core->dev_dec;
    627	int ret = 0;
    628
    629	mutex_lock(&core->pm_lock);
    630
    631	if (pm_runtime_suspended(dev)) {
    632		ret = pm_runtime_resume_and_get(dev);
    633		if (ret < 0)
    634			goto error;
    635
    636		ret = pm_runtime_put_autosuspend(dev);
    637	}
    638
    639error:
    640	mutex_unlock(&core->pm_lock);
    641
    642	return ret < 0 ? ret : 0;
    643}
    644
    645static void vdec_pm_touch(struct venus_inst *inst)
    646{
    647	pm_runtime_mark_last_busy(inst->core->dev_dec);
    648}
    649
    650static int vdec_set_properties(struct venus_inst *inst)
    651{
    652	struct vdec_controls *ctr = &inst->controls.dec;
    653	struct hfi_enable en = { .enable = 1 };
    654	u32 ptype, decode_order, conceal;
    655	int ret;
    656
    657	if (ctr->post_loop_deb_mode) {
    658		ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
    659		ret = hfi_session_set_property(inst, ptype, &en);
    660		if (ret)
    661			return ret;
    662	}
    663
    664	if (ctr->display_delay_enable && ctr->display_delay == 0) {
    665		ptype = HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
    666		decode_order = HFI_OUTPUT_ORDER_DECODE;
    667		ret = hfi_session_set_property(inst, ptype, &decode_order);
    668		if (ret)
    669			return ret;
    670	}
    671
    672	ptype = HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR;
    673	conceal = ctr->conceal_color & 0xffff;
    674	conceal |= ((ctr->conceal_color >> 16) & 0xffff) << 10;
    675	conceal |= ((ctr->conceal_color >> 32) & 0xffff) << 20;
    676
    677	ret = hfi_session_set_property(inst, ptype, &conceal);
    678	if (ret)
    679		return ret;
    680
    681	return 0;
    682}
    683
    684static int vdec_set_work_route(struct venus_inst *inst)
    685{
    686	u32 ptype = HFI_PROPERTY_PARAM_WORK_ROUTE;
    687	struct hfi_video_work_route wr;
    688
    689	if (!IS_V6(inst->core))
    690		return 0;
    691
    692	wr.video_work_route = inst->core->res->num_vpp_pipes;
    693
    694	return hfi_session_set_property(inst, ptype, &wr);
    695}
    696
    697#define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
    698
    699static int vdec_output_conf(struct venus_inst *inst)
    700{
    701	struct venus_core *core = inst->core;
    702	struct hfi_enable en = { .enable = 1 };
    703	struct hfi_buffer_requirements bufreq;
    704	u32 width = inst->width;
    705	u32 height = inst->height;
    706	u32 out_fmt, out2_fmt;
    707	bool ubwc = false;
    708	u32 ptype;
    709	int ret;
    710
    711	ret = venus_helper_set_work_mode(inst);
    712	if (ret)
    713		return ret;
    714
    715	if (core->res->hfi_version == HFI_VERSION_1XX) {
    716		ptype = HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
    717		ret = hfi_session_set_property(inst, ptype, &en);
    718		if (ret)
    719			return ret;
    720	}
    721
    722	/* Force searching UBWC formats for bigger then HD resolutions */
    723	if (width > 1920 && height > ALIGN(1080, 32))
    724		ubwc = true;
    725
    726	/* For Venus v4/v6 UBWC format is mandatory */
    727	if (IS_V4(core) || IS_V6(core))
    728		ubwc = true;
    729
    730	ret = venus_helper_get_out_fmts(inst, inst->fmt_cap->pixfmt, &out_fmt,
    731					&out2_fmt, ubwc);
    732	if (ret)
    733		return ret;
    734
    735	inst->output_buf_size =
    736			venus_helper_get_framesz_raw(out_fmt, width, height);
    737	inst->output2_buf_size =
    738			venus_helper_get_framesz_raw(out2_fmt, width, height);
    739
    740	if (is_ubwc_fmt(out_fmt)) {
    741		inst->opb_buftype = HFI_BUFFER_OUTPUT2;
    742		inst->opb_fmt = out2_fmt;
    743		inst->dpb_buftype = HFI_BUFFER_OUTPUT;
    744		inst->dpb_fmt = out_fmt;
    745	} else if (is_ubwc_fmt(out2_fmt)) {
    746		inst->opb_buftype = HFI_BUFFER_OUTPUT;
    747		inst->opb_fmt = out_fmt;
    748		inst->dpb_buftype = HFI_BUFFER_OUTPUT2;
    749		inst->dpb_fmt = out2_fmt;
    750	} else {
    751		inst->opb_buftype = HFI_BUFFER_OUTPUT;
    752		inst->opb_fmt = out_fmt;
    753		inst->dpb_buftype = 0;
    754		inst->dpb_fmt = 0;
    755	}
    756
    757	ret = venus_helper_set_raw_format(inst, inst->opb_fmt,
    758					  inst->opb_buftype);
    759	if (ret)
    760		return ret;
    761
    762	ret = venus_helper_set_format_constraints(inst);
    763	if (ret)
    764		return ret;
    765
    766	if (inst->dpb_fmt) {
    767		ret = venus_helper_set_multistream(inst, false, true);
    768		if (ret)
    769			return ret;
    770
    771		ret = venus_helper_set_raw_format(inst, inst->dpb_fmt,
    772						  inst->dpb_buftype);
    773		if (ret)
    774			return ret;
    775
    776		ret = venus_helper_set_output_resolution(inst, width, height,
    777							 HFI_BUFFER_OUTPUT2);
    778		if (ret)
    779			return ret;
    780	}
    781
    782	if (IS_V3(core) || IS_V4(core) || IS_V6(core)) {
    783		ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
    784		if (ret)
    785			return ret;
    786
    787		if (bufreq.size > inst->output_buf_size)
    788			return -EINVAL;
    789
    790		if (inst->dpb_fmt) {
    791			ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT2,
    792						      &bufreq);
    793			if (ret)
    794				return ret;
    795
    796			if (bufreq.size > inst->output2_buf_size)
    797				return -EINVAL;
    798		}
    799
    800		if (inst->output2_buf_size) {
    801			ret = venus_helper_set_bufsize(inst,
    802						       inst->output2_buf_size,
    803						       HFI_BUFFER_OUTPUT2);
    804			if (ret)
    805				return ret;
    806		}
    807
    808		if (inst->output_buf_size) {
    809			ret = venus_helper_set_bufsize(inst,
    810						       inst->output_buf_size,
    811						       HFI_BUFFER_OUTPUT);
    812			if (ret)
    813				return ret;
    814		}
    815	}
    816
    817	ret = venus_helper_set_dyn_bufmode(inst);
    818	if (ret)
    819		return ret;
    820
    821	return 0;
    822}
    823
    824static int vdec_session_init(struct venus_inst *inst)
    825{
    826	int ret;
    827
    828	ret = venus_helper_session_init(inst);
    829	if (ret == -EALREADY)
    830		return 0;
    831	else if (ret)
    832		return ret;
    833
    834	ret = venus_helper_set_input_resolution(inst, frame_width_min(inst),
    835						frame_height_min(inst));
    836	if (ret)
    837		goto deinit;
    838
    839	return 0;
    840deinit:
    841	hfi_session_deinit(inst);
    842	return ret;
    843}
    844
    845static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num,
    846			    unsigned int *out_num)
    847{
    848	enum hfi_version ver = inst->core->res->hfi_version;
    849	struct hfi_buffer_requirements bufreq;
    850	int ret;
    851
    852	*in_num = *out_num = 0;
    853
    854	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
    855	if (ret)
    856		return ret;
    857
    858	*in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
    859
    860	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
    861	if (ret)
    862		return ret;
    863
    864	*out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
    865
    866	return 0;
    867}
    868
    869static int vdec_queue_setup(struct vb2_queue *q,
    870			    unsigned int *num_buffers, unsigned int *num_planes,
    871			    unsigned int sizes[], struct device *alloc_devs[])
    872{
    873	struct venus_inst *inst = vb2_get_drv_priv(q);
    874	struct venus_core *core = inst->core;
    875	unsigned int in_num, out_num;
    876	int ret = 0;
    877
    878	if (*num_planes) {
    879		unsigned int output_buf_size = venus_helper_get_opb_size(inst);
    880
    881		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
    882		    *num_planes != inst->fmt_out->num_planes)
    883			return -EINVAL;
    884
    885		if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
    886		    *num_planes != inst->fmt_cap->num_planes)
    887			return -EINVAL;
    888
    889		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
    890		    sizes[0] < inst->input_buf_size)
    891			return -EINVAL;
    892
    893		if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
    894		    sizes[0] < output_buf_size)
    895			return -EINVAL;
    896
    897		return 0;
    898	}
    899
    900	if (test_bit(0, &core->sys_error)) {
    901		if (inst->nonblock)
    902			return -EAGAIN;
    903
    904		ret = wait_event_interruptible(core->sys_err_done,
    905					       !test_bit(0, &core->sys_error));
    906		if (ret)
    907			return ret;
    908	}
    909
    910	ret = vdec_pm_get(inst);
    911	if (ret)
    912		return ret;
    913
    914	ret = vdec_session_init(inst);
    915	if (ret)
    916		goto put_power;
    917
    918	ret = vdec_num_buffers(inst, &in_num, &out_num);
    919	if (ret)
    920		goto put_power;
    921
    922	ret = vdec_pm_put(inst, false);
    923	if (ret)
    924		return ret;
    925
    926	switch (q->type) {
    927	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    928		*num_planes = inst->fmt_out->num_planes;
    929		sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
    930						    inst->out_width,
    931						    inst->out_height);
    932		sizes[0] = max(sizes[0], inst->input_buf_size);
    933		inst->input_buf_size = sizes[0];
    934		*num_buffers = max(*num_buffers, in_num);
    935		inst->num_input_bufs = *num_buffers;
    936		inst->num_output_bufs = out_num;
    937		break;
    938	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    939		*num_planes = inst->fmt_cap->num_planes;
    940		sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
    941						    inst->width,
    942						    inst->height);
    943		inst->output_buf_size = sizes[0];
    944		*num_buffers = max(*num_buffers, out_num);
    945		inst->num_output_bufs = *num_buffers;
    946
    947		mutex_lock(&inst->lock);
    948		if (inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP)
    949			inst->codec_state = VENUS_DEC_STATE_STOPPED;
    950		mutex_unlock(&inst->lock);
    951		break;
    952	default:
    953		ret = -EINVAL;
    954		break;
    955	}
    956
    957	return ret;
    958
    959put_power:
    960	vdec_pm_put(inst, false);
    961	return ret;
    962}
    963
    964static int vdec_verify_conf(struct venus_inst *inst)
    965{
    966	enum hfi_version ver = inst->core->res->hfi_version;
    967	struct hfi_buffer_requirements bufreq;
    968	int ret;
    969
    970	if (!inst->num_input_bufs || !inst->num_output_bufs)
    971		return -EINVAL;
    972
    973	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
    974	if (ret)
    975		return ret;
    976
    977	if (inst->num_output_bufs < bufreq.count_actual ||
    978	    inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
    979		return -EINVAL;
    980
    981	ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
    982	if (ret)
    983		return ret;
    984
    985	if (inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
    986		return -EINVAL;
    987
    988	return 0;
    989}
    990
    991static int vdec_start_capture(struct venus_inst *inst)
    992{
    993	int ret;
    994
    995	if (!inst->streamon_out)
    996		return 0;
    997
    998	if (inst->codec_state == VENUS_DEC_STATE_DECODING) {
    999		if (inst->reconfig)
   1000			goto reconfigure;
   1001
   1002		venus_helper_queue_dpb_bufs(inst);
   1003		venus_helper_process_initial_cap_bufs(inst);
   1004		inst->streamon_cap = 1;
   1005		return 0;
   1006	}
   1007
   1008	if (inst->codec_state != VENUS_DEC_STATE_STOPPED)
   1009		return 0;
   1010
   1011reconfigure:
   1012	ret = vdec_output_conf(inst);
   1013	if (ret)
   1014		return ret;
   1015
   1016	ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
   1017					VB2_MAX_FRAME, VB2_MAX_FRAME);
   1018	if (ret)
   1019		return ret;
   1020
   1021	ret = venus_helper_intbufs_realloc(inst);
   1022	if (ret)
   1023		goto err;
   1024
   1025	venus_pm_load_scale(inst);
   1026
   1027	inst->next_buf_last = false;
   1028
   1029	ret = venus_helper_alloc_dpb_bufs(inst);
   1030	if (ret)
   1031		goto err;
   1032
   1033	ret = hfi_session_continue(inst);
   1034	if (ret)
   1035		goto free_dpb_bufs;
   1036
   1037	ret = venus_helper_queue_dpb_bufs(inst);
   1038	if (ret)
   1039		goto free_dpb_bufs;
   1040
   1041	ret = venus_helper_process_initial_cap_bufs(inst);
   1042	if (ret)
   1043		goto free_dpb_bufs;
   1044
   1045	inst->codec_state = VENUS_DEC_STATE_DECODING;
   1046
   1047	if (inst->drain_active)
   1048		inst->codec_state = VENUS_DEC_STATE_DRAIN;
   1049
   1050	inst->streamon_cap = 1;
   1051	inst->sequence_cap = 0;
   1052	inst->reconfig = false;
   1053	inst->drain_active = false;
   1054
   1055	return 0;
   1056
   1057free_dpb_bufs:
   1058	venus_helper_free_dpb_bufs(inst);
   1059err:
   1060	return ret;
   1061}
   1062
   1063static int vdec_start_output(struct venus_inst *inst)
   1064{
   1065	int ret;
   1066
   1067	if (inst->codec_state == VENUS_DEC_STATE_SEEK) {
   1068		ret = venus_helper_process_initial_out_bufs(inst);
   1069		if (inst->next_buf_last)
   1070			inst->codec_state = VENUS_DEC_STATE_DRC;
   1071		else
   1072			inst->codec_state = VENUS_DEC_STATE_DECODING;
   1073		goto done;
   1074	}
   1075
   1076	if (inst->codec_state == VENUS_DEC_STATE_INIT ||
   1077	    inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) {
   1078		ret = venus_helper_process_initial_out_bufs(inst);
   1079		goto done;
   1080	}
   1081
   1082	if (inst->codec_state != VENUS_DEC_STATE_DEINIT)
   1083		return -EINVAL;
   1084
   1085	venus_helper_init_instance(inst);
   1086	inst->sequence_out = 0;
   1087	inst->reconfig = false;
   1088	inst->next_buf_last = false;
   1089
   1090	ret = vdec_set_properties(inst);
   1091	if (ret)
   1092		return ret;
   1093
   1094	ret = vdec_set_work_route(inst);
   1095	if (ret)
   1096		return ret;
   1097
   1098	ret = vdec_output_conf(inst);
   1099	if (ret)
   1100		return ret;
   1101
   1102	ret = vdec_verify_conf(inst);
   1103	if (ret)
   1104		return ret;
   1105
   1106	ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
   1107					VB2_MAX_FRAME, VB2_MAX_FRAME);
   1108	if (ret)
   1109		return ret;
   1110
   1111	ret = venus_helper_vb2_start_streaming(inst);
   1112	if (ret)
   1113		return ret;
   1114
   1115	ret = venus_helper_process_initial_out_bufs(inst);
   1116	if (ret)
   1117		return ret;
   1118
   1119	inst->codec_state = VENUS_DEC_STATE_INIT;
   1120
   1121done:
   1122	inst->streamon_out = 1;
   1123	return ret;
   1124}
   1125
   1126static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
   1127{
   1128	struct venus_inst *inst = vb2_get_drv_priv(q);
   1129	int ret;
   1130
   1131	mutex_lock(&inst->lock);
   1132
   1133	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
   1134		ret = vdec_start_capture(inst);
   1135	} else {
   1136		ret = vdec_pm_get(inst);
   1137		if (ret)
   1138			goto error;
   1139
   1140		ret = venus_pm_acquire_core(inst);
   1141		if (ret)
   1142			goto put_power;
   1143
   1144		ret = vdec_pm_put(inst, true);
   1145		if (ret)
   1146			goto error;
   1147
   1148		ret = vdec_start_output(inst);
   1149	}
   1150
   1151	if (ret)
   1152		goto error;
   1153
   1154	mutex_unlock(&inst->lock);
   1155	return 0;
   1156
   1157put_power:
   1158	vdec_pm_put(inst, false);
   1159error:
   1160	venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
   1161	mutex_unlock(&inst->lock);
   1162	return ret;
   1163}
   1164
   1165static void vdec_cancel_dst_buffers(struct venus_inst *inst)
   1166{
   1167	struct vb2_v4l2_buffer *buf;
   1168
   1169	while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
   1170		v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
   1171}
   1172
   1173static int vdec_stop_capture(struct venus_inst *inst)
   1174{
   1175	int ret = 0;
   1176
   1177	switch (inst->codec_state) {
   1178	case VENUS_DEC_STATE_DECODING:
   1179		ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
   1180		fallthrough;
   1181	case VENUS_DEC_STATE_DRAIN:
   1182		inst->codec_state = VENUS_DEC_STATE_STOPPED;
   1183		inst->drain_active = false;
   1184		fallthrough;
   1185	case VENUS_DEC_STATE_SEEK:
   1186		vdec_cancel_dst_buffers(inst);
   1187		break;
   1188	case VENUS_DEC_STATE_DRC:
   1189		ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true);
   1190		inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
   1191		venus_helper_free_dpb_bufs(inst);
   1192		break;
   1193	default:
   1194		break;
   1195	}
   1196
   1197	return ret;
   1198}
   1199
   1200static int vdec_stop_output(struct venus_inst *inst)
   1201{
   1202	int ret = 0;
   1203
   1204	switch (inst->codec_state) {
   1205	case VENUS_DEC_STATE_DECODING:
   1206	case VENUS_DEC_STATE_DRAIN:
   1207	case VENUS_DEC_STATE_STOPPED:
   1208	case VENUS_DEC_STATE_DRC:
   1209		ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
   1210		inst->codec_state = VENUS_DEC_STATE_SEEK;
   1211		break;
   1212	case VENUS_DEC_STATE_INIT:
   1213	case VENUS_DEC_STATE_CAPTURE_SETUP:
   1214		ret = hfi_session_flush(inst, HFI_FLUSH_INPUT, true);
   1215		break;
   1216	default:
   1217		break;
   1218	}
   1219
   1220	return ret;
   1221}
   1222
   1223static void vdec_stop_streaming(struct vb2_queue *q)
   1224{
   1225	struct venus_inst *inst = vb2_get_drv_priv(q);
   1226	int ret = -EINVAL;
   1227
   1228	vdec_pm_get_put(inst);
   1229
   1230	mutex_lock(&inst->lock);
   1231
   1232	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
   1233		ret = vdec_stop_capture(inst);
   1234	else
   1235		ret = vdec_stop_output(inst);
   1236
   1237	venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR);
   1238
   1239	inst->session_error = 0;
   1240
   1241	if (ret)
   1242		goto unlock;
   1243
   1244	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
   1245		inst->streamon_out = 0;
   1246	else
   1247		inst->streamon_cap = 0;
   1248
   1249unlock:
   1250	mutex_unlock(&inst->lock);
   1251}
   1252
   1253static void vdec_session_release(struct venus_inst *inst)
   1254{
   1255	struct venus_core *core = inst->core;
   1256	int ret, abort = 0;
   1257
   1258	vdec_pm_get(inst);
   1259
   1260	mutex_lock(&inst->lock);
   1261	inst->codec_state = VENUS_DEC_STATE_DEINIT;
   1262
   1263	ret = hfi_session_stop(inst);
   1264	abort = (ret && ret != -EINVAL) ? 1 : 0;
   1265	ret = hfi_session_unload_res(inst);
   1266	abort = (ret && ret != -EINVAL) ? 1 : 0;
   1267	ret = venus_helper_unregister_bufs(inst);
   1268	abort = (ret && ret != -EINVAL) ? 1 : 0;
   1269	ret = venus_helper_intbufs_free(inst);
   1270	abort = (ret && ret != -EINVAL) ? 1 : 0;
   1271	ret = hfi_session_deinit(inst);
   1272	abort = (ret && ret != -EINVAL) ? 1 : 0;
   1273
   1274	if (inst->session_error || test_bit(0, &core->sys_error))
   1275		abort = 1;
   1276
   1277	if (abort)
   1278		hfi_session_abort(inst);
   1279
   1280	venus_helper_free_dpb_bufs(inst);
   1281	venus_pm_load_scale(inst);
   1282	INIT_LIST_HEAD(&inst->registeredbufs);
   1283	mutex_unlock(&inst->lock);
   1284
   1285	venus_pm_release_core(inst);
   1286	vdec_pm_put(inst, false);
   1287}
   1288
   1289static int vdec_buf_init(struct vb2_buffer *vb)
   1290{
   1291	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
   1292
   1293	inst->buf_count++;
   1294
   1295	return venus_helper_vb2_buf_init(vb);
   1296}
   1297
   1298static void vdec_buf_cleanup(struct vb2_buffer *vb)
   1299{
   1300	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
   1301	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
   1302	struct venus_buffer *buf = to_venus_buffer(vbuf);
   1303
   1304	mutex_lock(&inst->lock);
   1305	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
   1306		if (!list_empty(&inst->registeredbufs))
   1307			list_del_init(&buf->reg_list);
   1308	mutex_unlock(&inst->lock);
   1309
   1310	inst->buf_count--;
   1311	if (!inst->buf_count)
   1312		vdec_session_release(inst);
   1313}
   1314
   1315static void vdec_vb2_buf_queue(struct vb2_buffer *vb)
   1316{
   1317	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
   1318	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
   1319	static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS };
   1320
   1321	vdec_pm_get_put(inst);
   1322
   1323	mutex_lock(&inst->lock);
   1324
   1325	if (inst->next_buf_last && V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
   1326	    inst->codec_state == VENUS_DEC_STATE_DRC) {
   1327		vbuf->flags |= V4L2_BUF_FLAG_LAST;
   1328		vbuf->sequence = inst->sequence_cap++;
   1329		vbuf->field = V4L2_FIELD_NONE;
   1330		vb2_set_plane_payload(vb, 0, 0);
   1331		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
   1332		v4l2_event_queue_fh(&inst->fh, &eos);
   1333		inst->next_buf_last = false;
   1334		mutex_unlock(&inst->lock);
   1335		return;
   1336	}
   1337
   1338	venus_helper_vb2_buf_queue(vb);
   1339	mutex_unlock(&inst->lock);
   1340}
   1341
   1342static const struct vb2_ops vdec_vb2_ops = {
   1343	.queue_setup = vdec_queue_setup,
   1344	.buf_init = vdec_buf_init,
   1345	.buf_cleanup = vdec_buf_cleanup,
   1346	.buf_prepare = venus_helper_vb2_buf_prepare,
   1347	.start_streaming = vdec_start_streaming,
   1348	.stop_streaming = vdec_stop_streaming,
   1349	.buf_queue = vdec_vb2_buf_queue,
   1350};
   1351
   1352static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
   1353			  u32 tag, u32 bytesused, u32 data_offset, u32 flags,
   1354			  u32 hfi_flags, u64 timestamp_us)
   1355{
   1356	enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
   1357	struct vb2_v4l2_buffer *vbuf;
   1358	struct vb2_buffer *vb;
   1359	unsigned int type;
   1360
   1361	vdec_pm_touch(inst);
   1362
   1363	if (buf_type == HFI_BUFFER_INPUT)
   1364		type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   1365	else
   1366		type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1367
   1368	vbuf = venus_helper_find_buf(inst, type, tag);
   1369	if (!vbuf) {
   1370		venus_helper_change_dpb_owner(inst, vbuf, type, buf_type, tag);
   1371		return;
   1372	}
   1373
   1374	vbuf->flags = flags;
   1375	vbuf->field = V4L2_FIELD_NONE;
   1376	vb = &vbuf->vb2_buf;
   1377
   1378	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
   1379		vb2_set_plane_payload(vb, 0, bytesused);
   1380		vb->planes[0].data_offset = data_offset;
   1381		vb->timestamp = timestamp_us * NSEC_PER_USEC;
   1382		vbuf->sequence = inst->sequence_cap++;
   1383
   1384		if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
   1385			const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
   1386
   1387			v4l2_event_queue_fh(&inst->fh, &ev);
   1388
   1389			if (inst->codec_state == VENUS_DEC_STATE_DRAIN) {
   1390				inst->drain_active = false;
   1391				inst->codec_state = VENUS_DEC_STATE_STOPPED;
   1392			}
   1393		}
   1394
   1395		if (!bytesused)
   1396			state = VB2_BUF_STATE_ERROR;
   1397	} else {
   1398		vbuf->sequence = inst->sequence_out++;
   1399	}
   1400
   1401	venus_helper_get_ts_metadata(inst, timestamp_us, vbuf);
   1402
   1403	if (hfi_flags & HFI_BUFFERFLAG_READONLY)
   1404		venus_helper_acquire_buf_ref(vbuf);
   1405
   1406	if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT)
   1407		state = VB2_BUF_STATE_ERROR;
   1408
   1409	if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) {
   1410		state = VB2_BUF_STATE_ERROR;
   1411		vb2_set_plane_payload(vb, 0, 0);
   1412		vb->timestamp = 0;
   1413	}
   1414
   1415	v4l2_m2m_buf_done(vbuf, state);
   1416}
   1417
   1418static void vdec_event_change(struct venus_inst *inst,
   1419			      struct hfi_event_data *ev_data, bool sufficient)
   1420{
   1421	static const struct v4l2_event ev = {
   1422		.type = V4L2_EVENT_SOURCE_CHANGE,
   1423		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION };
   1424	struct device *dev = inst->core->dev_dec;
   1425	struct v4l2_format format = {};
   1426
   1427	mutex_lock(&inst->lock);
   1428
   1429	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1430	format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt;
   1431	format.fmt.pix_mp.width = ev_data->width;
   1432	format.fmt.pix_mp.height = ev_data->height;
   1433
   1434	vdec_try_fmt_common(inst, &format);
   1435
   1436	inst->width = format.fmt.pix_mp.width;
   1437	inst->height = format.fmt.pix_mp.height;
   1438	/*
   1439	 * Some versions of the firmware do not report crop information for
   1440	 * all codecs. For these cases, set the crop to the coded resolution.
   1441	 */
   1442	if (ev_data->input_crop.width > 0 && ev_data->input_crop.height > 0) {
   1443		inst->crop.left = ev_data->input_crop.left;
   1444		inst->crop.top = ev_data->input_crop.top;
   1445		inst->crop.width = ev_data->input_crop.width;
   1446		inst->crop.height = ev_data->input_crop.height;
   1447	} else {
   1448		inst->crop.left = 0;
   1449		inst->crop.top = 0;
   1450		inst->crop.width = ev_data->width;
   1451		inst->crop.height = ev_data->height;
   1452	}
   1453
   1454	inst->fw_min_cnt = ev_data->buf_count;
   1455	/* overwriting this to 11 for vp9 due to fw bug */
   1456	if (inst->hfi_codec == HFI_VIDEO_CODEC_VP9)
   1457		inst->fw_min_cnt = 11;
   1458
   1459	inst->out_width = ev_data->width;
   1460	inst->out_height = ev_data->height;
   1461
   1462	if (inst->bit_depth != ev_data->bit_depth)
   1463		inst->bit_depth = ev_data->bit_depth;
   1464
   1465	if (inst->pic_struct != ev_data->pic_struct)
   1466		inst->pic_struct = ev_data->pic_struct;
   1467
   1468	dev_dbg(dev, VDBGM "event %s sufficient resources (%ux%u)\n",
   1469		sufficient ? "" : "not", ev_data->width, ev_data->height);
   1470
   1471	switch (inst->codec_state) {
   1472	case VENUS_DEC_STATE_INIT:
   1473		inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
   1474		break;
   1475	case VENUS_DEC_STATE_DECODING:
   1476	case VENUS_DEC_STATE_DRAIN:
   1477		inst->codec_state = VENUS_DEC_STATE_DRC;
   1478		break;
   1479	default:
   1480		break;
   1481	}
   1482
   1483	/*
   1484	 * The assumption is that the firmware have to return the last buffer
   1485	 * before this event is received in the v4l2 driver. Also the firmware
   1486	 * itself doesn't mark the last decoder output buffer with HFI EOS flag.
   1487	 */
   1488
   1489	if (inst->codec_state == VENUS_DEC_STATE_DRC) {
   1490		int ret;
   1491
   1492		inst->next_buf_last = true;
   1493
   1494		ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, false);
   1495		if (ret)
   1496			dev_dbg(dev, VDBGH "flush output error %d\n", ret);
   1497	}
   1498
   1499	inst->next_buf_last = true;
   1500	inst->reconfig = true;
   1501	v4l2_event_queue_fh(&inst->fh, &ev);
   1502	wake_up(&inst->reconf_wait);
   1503
   1504	mutex_unlock(&inst->lock);
   1505}
   1506
   1507static void vdec_event_notify(struct venus_inst *inst, u32 event,
   1508			      struct hfi_event_data *data)
   1509{
   1510	struct venus_core *core = inst->core;
   1511	struct device *dev = core->dev_dec;
   1512
   1513	vdec_pm_touch(inst);
   1514
   1515	switch (event) {
   1516	case EVT_SESSION_ERROR:
   1517		inst->session_error = true;
   1518		venus_helper_vb2_queue_error(inst);
   1519		dev_err(dev, "dec: event session error %x\n", inst->error);
   1520		break;
   1521	case EVT_SYS_EVENT_CHANGE:
   1522		switch (data->event_type) {
   1523		case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
   1524			vdec_event_change(inst, data, true);
   1525			break;
   1526		case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
   1527			vdec_event_change(inst, data, false);
   1528			break;
   1529		case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
   1530			venus_helper_release_buf_ref(inst, data->tag);
   1531			break;
   1532		default:
   1533			break;
   1534		}
   1535		break;
   1536	default:
   1537		break;
   1538	}
   1539}
   1540
   1541static void vdec_flush_done(struct venus_inst *inst)
   1542{
   1543	dev_dbg(inst->core->dev_dec, VDBGH "flush done\n");
   1544}
   1545
   1546static const struct hfi_inst_ops vdec_hfi_ops = {
   1547	.buf_done = vdec_buf_done,
   1548	.event_notify = vdec_event_notify,
   1549	.flush_done = vdec_flush_done,
   1550};
   1551
   1552static void vdec_inst_init(struct venus_inst *inst)
   1553{
   1554	inst->hfi_codec = HFI_VIDEO_CODEC_H264;
   1555	inst->fmt_out = &vdec_formats[8];
   1556	inst->fmt_cap = &vdec_formats[0];
   1557	inst->width = frame_width_min(inst);
   1558	inst->height = ALIGN(frame_height_min(inst), 32);
   1559	inst->crop.left = 0;
   1560	inst->crop.top = 0;
   1561	inst->crop.width = inst->width;
   1562	inst->crop.height = inst->height;
   1563	inst->fw_min_cnt = 8;
   1564	inst->out_width = frame_width_min(inst);
   1565	inst->out_height = frame_height_min(inst);
   1566	inst->fps = 30;
   1567	inst->timeperframe.numerator = 1;
   1568	inst->timeperframe.denominator = 30;
   1569	inst->opb_buftype = HFI_BUFFER_OUTPUT;
   1570}
   1571
   1572static void vdec_m2m_device_run(void *priv)
   1573{
   1574}
   1575
   1576static const struct v4l2_m2m_ops vdec_m2m_ops = {
   1577	.device_run = vdec_m2m_device_run,
   1578	.job_abort = venus_helper_m2m_job_abort,
   1579};
   1580
   1581static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
   1582			  struct vb2_queue *dst_vq)
   1583{
   1584	struct venus_inst *inst = priv;
   1585	int ret;
   1586
   1587	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   1588	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
   1589	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
   1590	src_vq->ops = &vdec_vb2_ops;
   1591	src_vq->mem_ops = &vb2_dma_contig_memops;
   1592	src_vq->drv_priv = inst;
   1593	src_vq->buf_struct_size = sizeof(struct venus_buffer);
   1594	src_vq->allow_zero_bytesused = 1;
   1595	src_vq->min_buffers_needed = 0;
   1596	src_vq->dev = inst->core->dev;
   1597	ret = vb2_queue_init(src_vq);
   1598	if (ret)
   1599		return ret;
   1600
   1601	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1602	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
   1603	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
   1604	dst_vq->ops = &vdec_vb2_ops;
   1605	dst_vq->mem_ops = &vb2_dma_contig_memops;
   1606	dst_vq->drv_priv = inst;
   1607	dst_vq->buf_struct_size = sizeof(struct venus_buffer);
   1608	dst_vq->allow_zero_bytesused = 1;
   1609	dst_vq->min_buffers_needed = 0;
   1610	dst_vq->dev = inst->core->dev;
   1611	return vb2_queue_init(dst_vq);
   1612}
   1613
   1614static int vdec_open(struct file *file)
   1615{
   1616	struct venus_core *core = video_drvdata(file);
   1617	struct venus_inst *inst;
   1618	int ret;
   1619
   1620	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
   1621	if (!inst)
   1622		return -ENOMEM;
   1623
   1624	INIT_LIST_HEAD(&inst->dpbbufs);
   1625	INIT_LIST_HEAD(&inst->registeredbufs);
   1626	INIT_LIST_HEAD(&inst->internalbufs);
   1627	INIT_LIST_HEAD(&inst->list);
   1628	mutex_init(&inst->lock);
   1629
   1630	inst->core = core;
   1631	inst->session_type = VIDC_SESSION_TYPE_DEC;
   1632	inst->num_output_bufs = 1;
   1633	inst->codec_state = VENUS_DEC_STATE_DEINIT;
   1634	inst->buf_count = 0;
   1635	inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
   1636	inst->core_acquired = false;
   1637	inst->bit_depth = VIDC_BITDEPTH_8;
   1638	inst->pic_struct = HFI_INTERLACE_FRAME_PROGRESSIVE;
   1639	init_waitqueue_head(&inst->reconf_wait);
   1640	inst->nonblock = file->f_flags & O_NONBLOCK;
   1641
   1642	venus_helper_init_instance(inst);
   1643
   1644	ret = vdec_ctrl_init(inst);
   1645	if (ret)
   1646		goto err_free;
   1647
   1648	ret = hfi_session_create(inst, &vdec_hfi_ops);
   1649	if (ret)
   1650		goto err_ctrl_deinit;
   1651
   1652	vdec_inst_init(inst);
   1653
   1654	ida_init(&inst->dpb_ids);
   1655
   1656	/*
   1657	 * create m2m device for every instance, the m2m context scheduling
   1658	 * is made by firmware side so we do not need to care about.
   1659	 */
   1660	inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops);
   1661	if (IS_ERR(inst->m2m_dev)) {
   1662		ret = PTR_ERR(inst->m2m_dev);
   1663		goto err_session_destroy;
   1664	}
   1665
   1666	inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
   1667	if (IS_ERR(inst->m2m_ctx)) {
   1668		ret = PTR_ERR(inst->m2m_ctx);
   1669		goto err_m2m_release;
   1670	}
   1671
   1672	v4l2_fh_init(&inst->fh, core->vdev_dec);
   1673
   1674	inst->fh.ctrl_handler = &inst->ctrl_handler;
   1675	v4l2_fh_add(&inst->fh);
   1676	inst->fh.m2m_ctx = inst->m2m_ctx;
   1677	file->private_data = &inst->fh;
   1678
   1679	return 0;
   1680
   1681err_m2m_release:
   1682	v4l2_m2m_release(inst->m2m_dev);
   1683err_session_destroy:
   1684	hfi_session_destroy(inst);
   1685err_ctrl_deinit:
   1686	vdec_ctrl_deinit(inst);
   1687err_free:
   1688	kfree(inst);
   1689	return ret;
   1690}
   1691
   1692static int vdec_close(struct file *file)
   1693{
   1694	struct venus_inst *inst = to_inst(file);
   1695
   1696	vdec_pm_get(inst);
   1697
   1698	v4l2_m2m_ctx_release(inst->m2m_ctx);
   1699	v4l2_m2m_release(inst->m2m_dev);
   1700	vdec_ctrl_deinit(inst);
   1701	ida_destroy(&inst->dpb_ids);
   1702	hfi_session_destroy(inst);
   1703	mutex_destroy(&inst->lock);
   1704	v4l2_fh_del(&inst->fh);
   1705	v4l2_fh_exit(&inst->fh);
   1706
   1707	vdec_pm_put(inst, false);
   1708
   1709	kfree(inst);
   1710	return 0;
   1711}
   1712
   1713static const struct v4l2_file_operations vdec_fops = {
   1714	.owner = THIS_MODULE,
   1715	.open = vdec_open,
   1716	.release = vdec_close,
   1717	.unlocked_ioctl = video_ioctl2,
   1718	.poll = v4l2_m2m_fop_poll,
   1719	.mmap = v4l2_m2m_fop_mmap,
   1720};
   1721
   1722static int vdec_probe(struct platform_device *pdev)
   1723{
   1724	struct device *dev = &pdev->dev;
   1725	struct video_device *vdev;
   1726	struct venus_core *core;
   1727	int ret;
   1728
   1729	if (!dev->parent)
   1730		return -EPROBE_DEFER;
   1731
   1732	core = dev_get_drvdata(dev->parent);
   1733	if (!core)
   1734		return -EPROBE_DEFER;
   1735
   1736	platform_set_drvdata(pdev, core);
   1737
   1738	if (core->pm_ops->vdec_get) {
   1739		ret = core->pm_ops->vdec_get(dev);
   1740		if (ret)
   1741			return ret;
   1742	}
   1743
   1744	vdev = video_device_alloc();
   1745	if (!vdev)
   1746		return -ENOMEM;
   1747
   1748	strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
   1749	vdev->release = video_device_release;
   1750	vdev->fops = &vdec_fops;
   1751	vdev->ioctl_ops = &vdec_ioctl_ops;
   1752	vdev->vfl_dir = VFL_DIR_M2M;
   1753	vdev->v4l2_dev = &core->v4l2_dev;
   1754	vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
   1755
   1756	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
   1757	if (ret)
   1758		goto err_vdev_release;
   1759
   1760	core->vdev_dec = vdev;
   1761	core->dev_dec = dev;
   1762
   1763	video_set_drvdata(vdev, core);
   1764	pm_runtime_set_autosuspend_delay(dev, 2000);
   1765	pm_runtime_use_autosuspend(dev);
   1766	pm_runtime_enable(dev);
   1767
   1768	return 0;
   1769
   1770err_vdev_release:
   1771	video_device_release(vdev);
   1772	return ret;
   1773}
   1774
   1775static int vdec_remove(struct platform_device *pdev)
   1776{
   1777	struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
   1778
   1779	video_unregister_device(core->vdev_dec);
   1780	pm_runtime_disable(core->dev_dec);
   1781
   1782	if (core->pm_ops->vdec_put)
   1783		core->pm_ops->vdec_put(core->dev_dec);
   1784
   1785	return 0;
   1786}
   1787
   1788static __maybe_unused int vdec_runtime_suspend(struct device *dev)
   1789{
   1790	struct venus_core *core = dev_get_drvdata(dev);
   1791	const struct venus_pm_ops *pm_ops = core->pm_ops;
   1792	int ret = 0;
   1793
   1794	if (pm_ops->vdec_power)
   1795		ret = pm_ops->vdec_power(dev, POWER_OFF);
   1796
   1797	return ret;
   1798}
   1799
   1800static __maybe_unused int vdec_runtime_resume(struct device *dev)
   1801{
   1802	struct venus_core *core = dev_get_drvdata(dev);
   1803	const struct venus_pm_ops *pm_ops = core->pm_ops;
   1804	int ret = 0;
   1805
   1806	if (pm_ops->vdec_power)
   1807		ret = pm_ops->vdec_power(dev, POWER_ON);
   1808
   1809	return ret;
   1810}
   1811
   1812static const struct dev_pm_ops vdec_pm_ops = {
   1813	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
   1814				pm_runtime_force_resume)
   1815	SET_RUNTIME_PM_OPS(vdec_runtime_suspend, vdec_runtime_resume, NULL)
   1816};
   1817
   1818static const struct of_device_id vdec_dt_match[] = {
   1819	{ .compatible = "venus-decoder" },
   1820	{ }
   1821};
   1822MODULE_DEVICE_TABLE(of, vdec_dt_match);
   1823
   1824static struct platform_driver qcom_venus_dec_driver = {
   1825	.probe = vdec_probe,
   1826	.remove = vdec_remove,
   1827	.driver = {
   1828		.name = "qcom-venus-decoder",
   1829		.of_match_table = vdec_dt_match,
   1830		.pm = &vdec_pm_ops,
   1831	},
   1832};
   1833module_platform_driver(qcom_venus_dec_driver);
   1834
   1835MODULE_ALIAS("platform:qcom-venus-decoder");
   1836MODULE_DESCRIPTION("Qualcomm Venus video decoder driver");
   1837MODULE_LICENSE("GPL v2");