brintos

brintos / linux-shallow public Read only

0
0
Text · 34.8 KiB · 91e102d Raw
1259 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c4 *5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.6 *		http://www.samsung.com/7 * Kamil Debski, <k.debski@samsung.com>8 */9 10#include <linux/clk.h>11#include <linux/interrupt.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/platform_device.h>15#include <linux/sched.h>16#include <linux/slab.h>17#include <linux/videodev2.h>18#include <linux/workqueue.h>19#include <media/v4l2-ctrls.h>20#include <media/v4l2-event.h>21#include <media/videobuf2-v4l2.h>22#include "s5p_mfc_common.h"23#include "s5p_mfc_ctrl.h"24#include "s5p_mfc_debug.h"25#include "s5p_mfc_dec.h"26#include "s5p_mfc_intr.h"27#include "s5p_mfc_opr.h"28#include "s5p_mfc_pm.h"29 30static const struct s5p_mfc_fmt formats[] = {31	{32		.fourcc		= V4L2_PIX_FMT_NV12MT_16X16,33		.codec_mode	= S5P_MFC_CODEC_NONE,34		.type		= MFC_FMT_RAW,35		.num_planes	= 2,36		.versions	= MFC_V6_BIT | MFC_V7_BIT,37	},38	{39		.fourcc		= V4L2_PIX_FMT_NV12MT,40		.codec_mode	= S5P_MFC_CODEC_NONE,41		.type		= MFC_FMT_RAW,42		.num_planes	= 2,43		.versions	= MFC_V5_BIT,44	},45	{46		.fourcc		= V4L2_PIX_FMT_NV12M,47		.codec_mode	= S5P_MFC_CODEC_NONE,48		.type		= MFC_FMT_RAW,49		.num_planes	= 2,50		.versions	= MFC_V6PLUS_BITS,51	},52	{53		.fourcc		= V4L2_PIX_FMT_NV21M,54		.codec_mode	= S5P_MFC_CODEC_NONE,55		.type		= MFC_FMT_RAW,56		.num_planes	= 2,57		.versions	= MFC_V6PLUS_BITS,58	},59	{60		.fourcc         = V4L2_PIX_FMT_YUV420M,61		.codec_mode     = S5P_MFC_CODEC_NONE,62		.type           = MFC_FMT_RAW,63		.num_planes     = 3,64		.versions       = MFC_V12_BIT,65	},66	{67		.fourcc         = V4L2_PIX_FMT_YVU420M,68		.codec_mode     = S5P_MFC_CODEC_NONE,69		.type           = MFC_FMT_RAW,70		.num_planes     = 3,71		.versions       = MFC_V12_BIT72	},73	{74		.fourcc		= V4L2_PIX_FMT_H264,75		.codec_mode	= S5P_MFC_CODEC_H264_DEC,76		.type		= MFC_FMT_DEC,77		.num_planes	= 1,78		.versions	= MFC_V5PLUS_BITS,79		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION |80				  V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,81	},82	{83		.fourcc		= V4L2_PIX_FMT_H264_MVC,84		.codec_mode	= S5P_MFC_CODEC_H264_MVC_DEC,85		.type		= MFC_FMT_DEC,86		.num_planes	= 1,87		.versions	= MFC_V6PLUS_BITS,88		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION |89				  V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,90	},91	{92		.fourcc		= V4L2_PIX_FMT_H263,93		.codec_mode	= S5P_MFC_CODEC_H263_DEC,94		.type		= MFC_FMT_DEC,95		.num_planes	= 1,96		.versions	= MFC_V5PLUS_BITS,97		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION,98	},99	{100		.fourcc		= V4L2_PIX_FMT_MPEG1,101		.codec_mode	= S5P_MFC_CODEC_MPEG2_DEC,102		.type		= MFC_FMT_DEC,103		.num_planes	= 1,104		.versions	= MFC_V5PLUS_BITS,105		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION |106				  V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,107	},108	{109		.fourcc		= V4L2_PIX_FMT_MPEG2,110		.codec_mode	= S5P_MFC_CODEC_MPEG2_DEC,111		.type		= MFC_FMT_DEC,112		.num_planes	= 1,113		.versions	= MFC_V5PLUS_BITS,114		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION |115				  V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,116	},117	{118		.fourcc		= V4L2_PIX_FMT_MPEG4,119		.codec_mode	= S5P_MFC_CODEC_MPEG4_DEC,120		.type		= MFC_FMT_DEC,121		.num_planes	= 1,122		.versions	= MFC_V5PLUS_BITS,123		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION |124				  V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,125	},126	{127		.fourcc		= V4L2_PIX_FMT_XVID,128		.codec_mode	= S5P_MFC_CODEC_MPEG4_DEC,129		.type		= MFC_FMT_DEC,130		.num_planes	= 1,131		.versions	= MFC_V5PLUS_BITS,132		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION,133	},134	{135		.fourcc		= V4L2_PIX_FMT_VC1_ANNEX_G,136		.codec_mode	= S5P_MFC_CODEC_VC1_DEC,137		.type		= MFC_FMT_DEC,138		.num_planes	= 1,139		.versions	= MFC_V5PLUS_BITS,140		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION,141	},142	{143		.fourcc		= V4L2_PIX_FMT_VC1_ANNEX_L,144		.codec_mode	= S5P_MFC_CODEC_VC1RCV_DEC,145		.type		= MFC_FMT_DEC,146		.num_planes	= 1,147		.versions	= MFC_V5PLUS_BITS,148		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION,149	},150	{151		.fourcc		= V4L2_PIX_FMT_VP8,152		.codec_mode	= S5P_MFC_CODEC_VP8_DEC,153		.type		= MFC_FMT_DEC,154		.num_planes	= 1,155		.versions	= MFC_V6PLUS_BITS,156		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION,157	},158	{159		.fourcc		= V4L2_PIX_FMT_HEVC,160		.codec_mode	= S5P_FIMV_CODEC_HEVC_DEC,161		.type		= MFC_FMT_DEC,162		.num_planes	= 1,163		.versions	= MFC_V10PLUS_BITS,164		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION |165				  V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,166	},167	{168		.fourcc		= V4L2_PIX_FMT_VP9,169		.codec_mode	= S5P_FIMV_CODEC_VP9_DEC,170		.type		= MFC_FMT_DEC,171		.num_planes	= 1,172		.versions	= MFC_V10PLUS_BITS,173		.flags		= V4L2_FMT_FLAG_DYN_RESOLUTION,174	},175};176 177#define NUM_FORMATS ARRAY_SIZE(formats)178 179/* Find selected format description */180static const struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)181{182	unsigned int i;183 184	for (i = 0; i < NUM_FORMATS; i++) {185		if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&186		    formats[i].type == t)187			return &formats[i];188	}189	return NULL;190}191 192static struct mfc_control controls[] = {193	{194		.id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,195		.type = V4L2_CTRL_TYPE_INTEGER,196		.name = "H264 Display Delay",197		.minimum = 0,198		.maximum = 16383,199		.step = 1,200		.default_value = 0,201	},202	{203		.id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,204		.type = V4L2_CTRL_TYPE_INTEGER,205		.minimum = 0,206		.maximum = 16383,207		.step = 1,208		.default_value = 0,209	},210	{211		.id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE,212		.type = V4L2_CTRL_TYPE_BOOLEAN,213		.name = "H264 Display Delay Enable",214		.minimum = 0,215		.maximum = 1,216		.step = 1,217		.default_value = 0,218	},219	{220		.id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,221		.type = V4L2_CTRL_TYPE_BOOLEAN,222		.minimum = 0,223		.maximum = 1,224		.default_value = 0,225	},226	{227		.id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER,228		.type = V4L2_CTRL_TYPE_BOOLEAN,229		.name = "Mpeg4 Loop Filter Enable",230		.minimum = 0,231		.maximum = 1,232		.step = 1,233		.default_value = 0,234	},235	{236		.id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,237		.type = V4L2_CTRL_TYPE_BOOLEAN,238		.name = "Slice Interface Enable",239		.minimum = 0,240		.maximum = 1,241		.step = 1,242		.default_value = 0,243	},244	{245		.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,246		.type = V4L2_CTRL_TYPE_INTEGER,247		.name = "Minimum number of cap bufs",248		.minimum = 1,249		.maximum = 32,250		.step = 1,251		.default_value = 1,252		.is_volatile = 1,253	},254};255 256#define NUM_CTRLS ARRAY_SIZE(controls)257 258/* Check whether a context should be run on hardware */259static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)260{261	/* Context is to parse header */262	if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)263		return 1;264	/* Context is to decode a frame */265	if (ctx->src_queue_cnt >= 1 &&266	    ctx->state == MFCINST_RUNNING &&267	    ctx->dst_queue_cnt >= ctx->pb_count)268		return 1;269	/* Context is to return last frame */270	if (ctx->state == MFCINST_FINISHING &&271	    ctx->dst_queue_cnt >= ctx->pb_count)272		return 1;273	/* Context is to set buffers */274	if (ctx->src_queue_cnt >= 1 &&275	    ctx->state == MFCINST_HEAD_PARSED &&276	    ctx->capture_state == QUEUE_BUFS_MMAPED)277		return 1;278	/* Resolution change */279	if ((ctx->state == MFCINST_RES_CHANGE_INIT ||280		ctx->state == MFCINST_RES_CHANGE_FLUSH) &&281		ctx->dst_queue_cnt >= ctx->pb_count)282		return 1;283	if (ctx->state == MFCINST_RES_CHANGE_END &&284		ctx->src_queue_cnt >= 1)285		return 1;286	mfc_debug(2, "ctx is not ready\n");287	return 0;288}289 290static const struct s5p_mfc_codec_ops decoder_codec_ops = {291	.pre_seq_start		= NULL,292	.post_seq_start		= NULL,293	.pre_frame_start	= NULL,294	.post_frame_start	= NULL,295};296 297/* Query capabilities of the device */298static int vidioc_querycap(struct file *file, void *priv,299			   struct v4l2_capability *cap)300{301	struct s5p_mfc_dev *dev = video_drvdata(file);302 303	strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));304	strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card));305	return 0;306}307 308/* Enumerate format */309static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,310							bool out)311{312	struct s5p_mfc_dev *dev = video_drvdata(file);313	int i, j = 0;314 315	for (i = 0; i < ARRAY_SIZE(formats); ++i) {316		if (out && formats[i].type != MFC_FMT_DEC)317			continue;318		else if (!out && formats[i].type != MFC_FMT_RAW)319			continue;320		else if ((dev->variant->version_bit & formats[i].versions) == 0)321			continue;322 323		if (j == f->index)324			break;325		++j;326	}327	if (i == ARRAY_SIZE(formats))328		return -EINVAL;329	f->pixelformat = formats[i].fourcc;330	return 0;331}332 333static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,334				   struct v4l2_fmtdesc *f)335{336	return vidioc_enum_fmt(file, f, false);337}338 339static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,340				   struct v4l2_fmtdesc *f)341{342	return vidioc_enum_fmt(file, f, true);343}344 345/* Get format */346static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)347{348	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);349	struct v4l2_pix_format_mplane *pix_mp;350 351	mfc_debug_enter();352	pix_mp = &f->fmt.pix_mp;353	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&354	    (ctx->state == MFCINST_GOT_INST || ctx->state ==355						MFCINST_RES_CHANGE_END)) {356		/* If the MFC is parsing the header,357		 * so wait until it is finished */358		s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,359									0);360	}361	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&362	    ctx->state >= MFCINST_HEAD_PARSED &&363	    ctx->state < MFCINST_ABORT) {364		/* This is run on CAPTURE (decode output) */365		/* Width and height are set to the dimensions366		   of the movie, the buffer is bigger and367		   further processing stages should crop to this368		   rectangle. */369		pix_mp->width = ctx->buf_width;370		pix_mp->height = ctx->buf_height;371		pix_mp->field = V4L2_FIELD_NONE;372		pix_mp->num_planes = ctx->dst_fmt->num_planes;373		/* Set pixelformat to the format in which MFC374		   outputs the decoded frame */375		pix_mp->pixelformat = ctx->dst_fmt->fourcc;376		pix_mp->plane_fmt[0].bytesperline = ctx->stride[0];377		pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;378		pix_mp->plane_fmt[1].bytesperline = ctx->stride[1];379		pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;380		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==381				V4L2_PIX_FMT_YVU420M) {382			pix_mp->plane_fmt[2].bytesperline = ctx->stride[2];383			pix_mp->plane_fmt[2].sizeimage = ctx->chroma_size_1;384		}385	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {386		/* This is run on OUTPUT387		   The buffer contains compressed image388		   so width and height have no meaning */389		pix_mp->width = 0;390		pix_mp->height = 0;391		pix_mp->field = V4L2_FIELD_NONE;392		pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size;393		pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size;394		pix_mp->pixelformat = ctx->src_fmt->fourcc;395		pix_mp->num_planes = ctx->src_fmt->num_planes;396	} else {397		mfc_err("Format could not be read\n");398		mfc_debug(2, "%s-- with error\n", __func__);399		return -EINVAL;400	}401	mfc_debug_leave();402	return 0;403}404 405/* Try format */406static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)407{408	struct s5p_mfc_dev *dev = video_drvdata(file);409	const struct s5p_mfc_fmt *fmt;410 411	mfc_debug(2, "Type is %d\n", f->type);412	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {413		fmt = find_format(f, MFC_FMT_DEC);414		if (!fmt) {415			mfc_err("Unsupported format for source.\n");416			return -EINVAL;417		}418		if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) {419			mfc_err("Unknown codec\n");420			return -EINVAL;421		}422		if ((dev->variant->version_bit & fmt->versions) == 0) {423			mfc_err("Unsupported format by this MFC version.\n");424			return -EINVAL;425		}426	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {427		fmt = find_format(f, MFC_FMT_RAW);428		if (!fmt) {429			mfc_err("Unsupported format for destination.\n");430			return -EINVAL;431		}432		if ((dev->variant->version_bit & fmt->versions) == 0) {433			mfc_err("Unsupported format by this MFC version.\n");434			return -EINVAL;435		}436	}437 438	return 0;439}440 441/* Set format */442static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)443{444	struct s5p_mfc_dev *dev = video_drvdata(file);445	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);446	int ret = 0;447	struct v4l2_pix_format_mplane *pix_mp;448	const struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;449 450	mfc_debug_enter();451	ret = vidioc_try_fmt(file, priv, f);452	pix_mp = &f->fmt.pix_mp;453	if (ret)454		return ret;455	if (vb2_is_streaming(&ctx->vq_src) || vb2_is_streaming(&ctx->vq_dst)) {456		v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);457		ret = -EBUSY;458		goto out;459	}460	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {461		/* dst_fmt is validated by call to vidioc_try_fmt */462		ctx->dst_fmt = find_format(f, MFC_FMT_RAW);463		ret = 0;464		goto out;465	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {466		/* src_fmt is validated by call to vidioc_try_fmt */467		ctx->src_fmt = find_format(f, MFC_FMT_DEC);468		ctx->codec_mode = ctx->src_fmt->codec_mode;469		mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);470		pix_mp->height = 0;471		pix_mp->width = 0;472		if (pix_mp->plane_fmt[0].sizeimage == 0)473			pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =474								DEF_CPB_SIZE;475		else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)476			ctx->dec_src_buf_size = buf_size->cpb;477		else478			ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;479		pix_mp->plane_fmt[0].bytesperline = 0;480		ctx->state = MFCINST_INIT;481		ret = 0;482		goto out;483	} else {484		mfc_err("Wrong type error for S_FMT : %d", f->type);485		ret = -EINVAL;486		goto out;487	}488 489out:490	mfc_debug_leave();491	return ret;492}493 494static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,495				struct v4l2_requestbuffers *reqbufs)496{497	int ret = 0;498 499	s5p_mfc_clock_on(dev);500 501	if (reqbufs->count == 0) {502		mfc_debug(2, "Freeing buffers\n");503		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);504		if (ret)505			goto out;506		ctx->src_bufs_cnt = 0;507		ctx->output_state = QUEUE_FREE;508	} else if (ctx->output_state == QUEUE_FREE) {509		/* Can only request buffers when we have a valid format set. */510		WARN_ON(ctx->src_bufs_cnt != 0);511		if (ctx->state != MFCINST_INIT) {512			mfc_err("Reqbufs called in an invalid state\n");513			ret = -EINVAL;514			goto out;515		}516 517		mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n",518				reqbufs->count);519		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);520		if (ret)521			goto out;522 523		ret = s5p_mfc_open_mfc_inst(dev, ctx);524		if (ret) {525			reqbufs->count = 0;526			vb2_reqbufs(&ctx->vq_src, reqbufs);527			goto out;528		}529 530		ctx->output_state = QUEUE_BUFS_REQUESTED;531	} else {532		mfc_err("Buffers have already been requested\n");533		ret = -EINVAL;534	}535out:536	s5p_mfc_clock_off(dev);537	if (ret)538		mfc_err("Failed allocating buffers for OUTPUT queue\n");539	return ret;540}541 542static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,543				struct v4l2_requestbuffers *reqbufs)544{545	int ret = 0;546 547	s5p_mfc_clock_on(dev);548 549	if (reqbufs->count == 0) {550		mfc_debug(2, "Freeing buffers\n");551		ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);552		if (ret)553			goto out;554		s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);555		ctx->dst_bufs_cnt = 0;556	} else if (ctx->capture_state == QUEUE_FREE) {557		WARN_ON(ctx->dst_bufs_cnt != 0);558		mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n",559				reqbufs->count);560		ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);561		if (ret)562			goto out;563 564		ctx->capture_state = QUEUE_BUFS_REQUESTED;565		ctx->total_dpb_count = reqbufs->count;566 567		ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);568		if (ret) {569			mfc_err("Failed to allocate decoding buffers\n");570			reqbufs->count = 0;571			vb2_reqbufs(&ctx->vq_dst, reqbufs);572			ret = -ENOMEM;573			ctx->capture_state = QUEUE_FREE;574			goto out;575		}576 577		WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count);578		ctx->capture_state = QUEUE_BUFS_MMAPED;579 580		if (s5p_mfc_ctx_ready(ctx))581			set_work_bit_irqsave(ctx);582		s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);583		s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,584					  0);585	} else {586		mfc_err("Buffers have already been requested\n");587		ret = -EINVAL;588	}589out:590	s5p_mfc_clock_off(dev);591	if (ret)592		mfc_err("Failed allocating buffers for CAPTURE queue\n");593	return ret;594}595 596/* Request buffers */597static int vidioc_reqbufs(struct file *file, void *priv,598					  struct v4l2_requestbuffers *reqbufs)599{600	struct s5p_mfc_dev *dev = video_drvdata(file);601	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);602 603	if (reqbufs->memory != V4L2_MEMORY_MMAP) {604		mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n");605		return -EINVAL;606	}607 608	if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {609		return reqbufs_output(dev, ctx, reqbufs);610	} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {611		return reqbufs_capture(dev, ctx, reqbufs);612	} else {613		mfc_err("Invalid type requested\n");614		return -EINVAL;615	}616}617 618/* Query buffer */619static int vidioc_querybuf(struct file *file, void *priv,620						   struct v4l2_buffer *buf)621{622	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);623	int ret;624	int i;625 626	if (buf->memory != V4L2_MEMORY_MMAP) {627		mfc_err("Only mmapped buffers can be used\n");628		return -EINVAL;629	}630	mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);631	if (ctx->state == MFCINST_GOT_INST &&632			buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {633		ret = vb2_querybuf(&ctx->vq_src, buf);634	} else if (ctx->state == MFCINST_RUNNING &&635			buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {636		ret = vb2_querybuf(&ctx->vq_dst, buf);637		for (i = 0; i < buf->length; i++)638			buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;639	} else {640		mfc_err("vidioc_querybuf called in an inappropriate state\n");641		ret = -EINVAL;642	}643	mfc_debug_leave();644	return ret;645}646 647/* Queue a buffer */648static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)649{650	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);651 652	if (ctx->state == MFCINST_ERROR) {653		mfc_err("Call on QBUF after unrecoverable error\n");654		return -EIO;655	}656	if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)657		return vb2_qbuf(&ctx->vq_src, NULL, buf);658	else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)659		return vb2_qbuf(&ctx->vq_dst, NULL, buf);660	return -EINVAL;661}662 663/* Dequeue a buffer */664static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)665{666	const struct v4l2_event ev = {667		.type = V4L2_EVENT_EOS668	};669	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);670	int ret;671 672	if (ctx->state == MFCINST_ERROR) {673		mfc_err_limited("Call on DQBUF after unrecoverable error\n");674		return -EIO;675	}676 677	switch (buf->type) {678	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:679		return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);680	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:681		ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);682		if (ret)683			return ret;684 685		if (ctx->state == MFCINST_FINISHED &&686		    (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS))687			v4l2_event_queue_fh(&ctx->fh, &ev);688		return 0;689	default:690		return -EINVAL;691	}692}693 694/* Export DMA buffer */695static int vidioc_expbuf(struct file *file, void *priv,696	struct v4l2_exportbuffer *eb)697{698	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);699 700	if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)701		return vb2_expbuf(&ctx->vq_src, eb);702	if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)703		return vb2_expbuf(&ctx->vq_dst, eb);704	return -EINVAL;705}706 707/* Stream on */708static int vidioc_streamon(struct file *file, void *priv,709			   enum v4l2_buf_type type)710{711	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);712	int ret = -EINVAL;713 714	mfc_debug_enter();715	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)716		ret = vb2_streamon(&ctx->vq_src, type);717	else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)718		ret = vb2_streamon(&ctx->vq_dst, type);719	mfc_debug_leave();720	return ret;721}722 723/* Stream off, which equals to a pause */724static int vidioc_streamoff(struct file *file, void *priv,725			    enum v4l2_buf_type type)726{727	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);728 729	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)730		return vb2_streamoff(&ctx->vq_src, type);731	else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)732		return vb2_streamoff(&ctx->vq_dst, type);733	return -EINVAL;734}735 736/* Set controls - v4l2 control framework */737static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)738{739	struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);740 741	switch (ctrl->id) {742	case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:743	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:744		ctx->display_delay = ctrl->val;745		break;746	case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE:747	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:748		ctx->display_delay_enable = ctrl->val;749		break;750	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:751		ctx->loop_filter_mpeg4 = ctrl->val;752		break;753	case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:754		ctx->slice_interface = ctrl->val;755		break;756	default:757		mfc_err("Invalid control 0x%08x\n", ctrl->id);758		return -EINVAL;759	}760	return 0;761}762 763static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)764{765	struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);766	struct s5p_mfc_dev *dev = ctx->dev;767 768	switch (ctrl->id) {769	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:770		if (ctx->state >= MFCINST_HEAD_PARSED &&771		    ctx->state < MFCINST_ABORT) {772			ctrl->val = ctx->pb_count;773			break;774		} else if (ctx->state != MFCINST_INIT &&775				ctx->state != MFCINST_RES_CHANGE_END) {776			v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");777			return -EINVAL;778		}779		/* Should wait for the header to be parsed */780		s5p_mfc_wait_for_done_ctx(ctx,781				S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);782		if (ctx->state >= MFCINST_HEAD_PARSED &&783		    ctx->state < MFCINST_ABORT) {784			ctrl->val = ctx->pb_count;785		} else {786			v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");787			return -EINVAL;788		}789		break;790	}791	return 0;792}793 794 795static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {796	.s_ctrl = s5p_mfc_dec_s_ctrl,797	.g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl,798};799 800/* Get compose information */801static int vidioc_g_selection(struct file *file, void *priv,802			      struct v4l2_selection *s)803{804	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);805	struct s5p_mfc_dev *dev = ctx->dev;806	u32 left, right, top, bottom;807	u32 width, height;808 809	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)810		return -EINVAL;811 812	if (ctx->state != MFCINST_HEAD_PARSED &&813	    ctx->state != MFCINST_RUNNING &&814	    ctx->state != MFCINST_FINISHING &&815	    ctx->state != MFCINST_FINISHED) {816		mfc_err("Can not get compose information\n");817		return -EINVAL;818	}819	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {820		left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);821		right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;822		left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;823		top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);824		bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;825		top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;826		width = ctx->img_width - left - right;827		height = ctx->img_height - top - bottom;828		mfc_debug(2, "Composing info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d\n",829			  left, top, s->r.width, s->r.height, right, bottom,830			  ctx->buf_width, ctx->buf_height);831	} else {832		left = 0;833		top = 0;834		width = ctx->img_width;835		height = ctx->img_height;836		mfc_debug(2, "Composing info: w=%d h=%d fw=%d fh=%d\n",837			  s->r.width, s->r.height, ctx->buf_width,838			  ctx->buf_height);839	}840 841	switch (s->target) {842	case V4L2_SEL_TGT_COMPOSE:843	case V4L2_SEL_TGT_COMPOSE_DEFAULT:844	case V4L2_SEL_TGT_COMPOSE_BOUNDS:845		s->r.left = left;846		s->r.top = top;847		s->r.width = width;848		s->r.height = height;849		break;850	default:851		return -EINVAL;852	}853	return 0;854}855 856static int vidioc_decoder_cmd(struct file *file, void *priv,857			      struct v4l2_decoder_cmd *cmd)858{859	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);860	struct s5p_mfc_dev *dev = ctx->dev;861	struct s5p_mfc_buf *buf;862	unsigned long flags;863 864	switch (cmd->cmd) {865	case V4L2_DEC_CMD_STOP:866		if (cmd->flags != 0)867			return -EINVAL;868 869		if (!vb2_is_streaming(&ctx->vq_src))870			return -EINVAL;871 872		spin_lock_irqsave(&dev->irqlock, flags);873		if (list_empty(&ctx->src_queue)) {874			mfc_err("EOS: empty src queue, entering finishing state");875			ctx->state = MFCINST_FINISHING;876			if (s5p_mfc_ctx_ready(ctx))877				set_work_bit_irqsave(ctx);878			spin_unlock_irqrestore(&dev->irqlock, flags);879			s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);880		} else {881			mfc_err("EOS: marking last buffer of stream");882			buf = list_entry(ctx->src_queue.prev,883						struct s5p_mfc_buf, list);884			if (buf->flags & MFC_BUF_FLAG_USED)885				ctx->state = MFCINST_FINISHING;886			else887				buf->flags |= MFC_BUF_FLAG_EOS;888			spin_unlock_irqrestore(&dev->irqlock, flags);889		}890		break;891	default:892		return -EINVAL;893	}894	return 0;895}896 897static int vidioc_subscribe_event(struct v4l2_fh *fh,898				const struct  v4l2_event_subscription *sub)899{900	switch (sub->type) {901	case V4L2_EVENT_EOS:902		return v4l2_event_subscribe(fh, sub, 2, NULL);903	case V4L2_EVENT_SOURCE_CHANGE:904		return v4l2_src_change_event_subscribe(fh, sub);905	default:906		return -EINVAL;907	}908}909 910 911/* v4l2_ioctl_ops */912static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {913	.vidioc_querycap = vidioc_querycap,914	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,915	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,916	.vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,917	.vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,918	.vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,919	.vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,920	.vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,921	.vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,922	.vidioc_reqbufs = vidioc_reqbufs,923	.vidioc_querybuf = vidioc_querybuf,924	.vidioc_qbuf = vidioc_qbuf,925	.vidioc_dqbuf = vidioc_dqbuf,926	.vidioc_expbuf = vidioc_expbuf,927	.vidioc_streamon = vidioc_streamon,928	.vidioc_streamoff = vidioc_streamoff,929	.vidioc_g_selection = vidioc_g_selection,930	.vidioc_decoder_cmd = vidioc_decoder_cmd,931	.vidioc_subscribe_event = vidioc_subscribe_event,932	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,933};934 935static int s5p_mfc_queue_setup(struct vb2_queue *vq,936			unsigned int *buf_count,937			unsigned int *plane_count, unsigned int psize[],938			struct device *alloc_devs[])939{940	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);941	struct s5p_mfc_dev *dev = ctx->dev;942	const struct v4l2_format_info *format;943 944	/* Video output for decoding (source)945	 * this can be set after getting an instance */946	if (ctx->state == MFCINST_INIT &&947	    vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {948		/* A single plane is required for input */949		*plane_count = 1;950		if (*buf_count < 1)951			*buf_count = 1;952		if (*buf_count > MFC_MAX_BUFFERS)953			*buf_count = MFC_MAX_BUFFERS;954	/* Video capture for decoding (destination)955	 * this can be set after the header was parsed */956	} else if (ctx->state == MFCINST_HEAD_PARSED &&957		   vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {958		/* Output plane count is 2 - one for Y and one for CbCr */959		format = v4l2_format_info(ctx->dst_fmt->fourcc);960		if (!format) {961			mfc_err("invalid format\n");962			return -EINVAL;963		}964		*plane_count = format->comp_planes;965 966		/* Setup buffer count */967		if (*buf_count < ctx->pb_count)968			*buf_count = ctx->pb_count;969		if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB)970			*buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB;971		if (*buf_count > MFC_MAX_BUFFERS)972			*buf_count = MFC_MAX_BUFFERS;973	} else {974		mfc_err("State seems invalid. State = %d, vq->type = %d\n",975							ctx->state, vq->type);976		return -EINVAL;977	}978	mfc_debug(2, "Buffer count=%d, plane count=%d\n",979						*buf_count, *plane_count);980	if (ctx->state == MFCINST_HEAD_PARSED &&981	    vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {982		psize[0] = ctx->luma_size;983		psize[1] = ctx->chroma_size;984		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==985				V4L2_PIX_FMT_YVU420M)986			psize[2] = ctx->chroma_size_1;987		if (IS_MFCV6_PLUS(dev))988			alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];989		else990			alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];991		alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];992		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==993				V4L2_PIX_FMT_YVU420M)994			alloc_devs[2] = ctx->dev->mem_dev[BANK_L_CTX];995	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) {996		psize[0] = ctx->dec_src_buf_size;997		alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];998	} else {999		mfc_err("This video node is dedicated to decoding. Decoding not initialized\n");1000		return -EINVAL;1001	}1002	return 0;1003}1004 1005static int s5p_mfc_buf_init(struct vb2_buffer *vb)1006{1007	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1008	struct vb2_queue *vq = vb->vb2_queue;1009	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);1010	unsigned int i;1011 1012	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1013		if (ctx->capture_state == QUEUE_BUFS_MMAPED)1014			return 0;1015		for (i = 0; i < ctx->dst_fmt->num_planes; i++) {1016			if (IS_ERR_OR_NULL(ERR_PTR(1017					vb2_dma_contig_plane_dma_addr(vb, i)))) {1018				mfc_err("Plane mem not allocated\n");1019				return -EINVAL;1020			}1021		}1022		if (vb2_plane_size(vb, 0) < ctx->luma_size ||1023			vb2_plane_size(vb, 1) < ctx->chroma_size) {1024			mfc_err("Plane buffer (CAPTURE) is too small\n");1025			return -EINVAL;1026		}1027		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==1028				V4L2_PIX_FMT_YVU420M) {1029			if (vb2_plane_size(vb, 2) < ctx->chroma_size_1) {1030				mfc_err("Plane buffer (CAPTURE) is too small\n");1031				return -EINVAL;1032			}1033		}1034		i = vb->index;1035		ctx->dst_bufs[i].b = vbuf;1036		ctx->dst_bufs[i].cookie.raw.luma =1037					vb2_dma_contig_plane_dma_addr(vb, 0);1038		ctx->dst_bufs[i].cookie.raw.chroma =1039					vb2_dma_contig_plane_dma_addr(vb, 1);1040		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==1041				V4L2_PIX_FMT_YVU420M) {1042			ctx->dst_bufs[i].cookie.raw.chroma_1 =1043					vb2_dma_contig_plane_dma_addr(vb, 2);1044		}1045		ctx->dst_bufs_cnt++;1046	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1047		if (IS_ERR_OR_NULL(ERR_PTR(1048					vb2_dma_contig_plane_dma_addr(vb, 0)))) {1049			mfc_err("Plane memory not allocated\n");1050			return -EINVAL;1051		}1052		if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) {1053			mfc_err("Plane buffer (OUTPUT) is too small\n");1054			return -EINVAL;1055		}1056 1057		i = vb->index;1058		ctx->src_bufs[i].b = vbuf;1059		ctx->src_bufs[i].cookie.stream =1060					vb2_dma_contig_plane_dma_addr(vb, 0);1061		ctx->src_bufs_cnt++;1062	} else {1063		mfc_err("s5p_mfc_buf_init: unknown queue type\n");1064		return -EINVAL;1065	}1066	return 0;1067}1068 1069static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)1070{1071	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);1072	struct s5p_mfc_dev *dev = ctx->dev;1073 1074	v4l2_ctrl_handler_setup(&ctx->ctrl_handler);1075	if (ctx->state == MFCINST_FINISHING ||1076		ctx->state == MFCINST_FINISHED)1077		ctx->state = MFCINST_RUNNING;1078	/* If context is ready then dev = work->data;schedule it to run */1079	if (s5p_mfc_ctx_ready(ctx))1080		set_work_bit_irqsave(ctx);1081	s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);1082	return 0;1083}1084 1085static void s5p_mfc_stop_streaming(struct vb2_queue *q)1086{1087	unsigned long flags;1088	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);1089	struct s5p_mfc_dev *dev = ctx->dev;1090	int aborted = 0;1091 1092	spin_lock_irqsave(&dev->irqlock, flags);1093	if ((ctx->state == MFCINST_FINISHING ||1094		ctx->state ==  MFCINST_RUNNING) &&1095		dev->curr_ctx == ctx->num && dev->hw_lock) {1096		ctx->state = MFCINST_ABORT;1097		spin_unlock_irqrestore(&dev->irqlock, flags);1098		s5p_mfc_wait_for_done_ctx(ctx,1099					S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);1100		aborted = 1;1101		spin_lock_irqsave(&dev->irqlock, flags);1102	}1103	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1104		s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);1105		INIT_LIST_HEAD(&ctx->dst_queue);1106		ctx->dst_queue_cnt = 0;1107		ctx->dpb_flush_flag = 1;1108		ctx->dec_dst_flag = 0;1109		if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {1110			ctx->state = MFCINST_FLUSH;1111			set_work_bit_irqsave(ctx);1112			s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);1113			spin_unlock_irqrestore(&dev->irqlock, flags);1114			if (s5p_mfc_wait_for_done_ctx(ctx,1115				S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))1116				mfc_err("Err flushing buffers\n");1117			spin_lock_irqsave(&dev->irqlock, flags);1118		}1119	} else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1120		s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);1121		INIT_LIST_HEAD(&ctx->src_queue);1122		ctx->src_queue_cnt = 0;1123	}1124	if (aborted)1125		ctx->state = MFCINST_RUNNING;1126	spin_unlock_irqrestore(&dev->irqlock, flags);1127}1128 1129 1130static void s5p_mfc_buf_queue(struct vb2_buffer *vb)1131{1132	struct vb2_queue *vq = vb->vb2_queue;1133	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);1134	struct s5p_mfc_dev *dev = ctx->dev;1135	unsigned long flags;1136	struct s5p_mfc_buf *mfc_buf;1137 1138	if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1139		mfc_buf = &ctx->src_bufs[vb->index];1140		mfc_buf->flags &= ~MFC_BUF_FLAG_USED;1141		spin_lock_irqsave(&dev->irqlock, flags);1142		list_add_tail(&mfc_buf->list, &ctx->src_queue);1143		ctx->src_queue_cnt++;1144		spin_unlock_irqrestore(&dev->irqlock, flags);1145	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1146		mfc_buf = &ctx->dst_bufs[vb->index];1147		mfc_buf->flags &= ~MFC_BUF_FLAG_USED;1148		/* Mark destination as available for use by MFC */1149		spin_lock_irqsave(&dev->irqlock, flags);1150		set_bit(vb->index, &ctx->dec_dst_flag);1151		list_add_tail(&mfc_buf->list, &ctx->dst_queue);1152		ctx->dst_queue_cnt++;1153		spin_unlock_irqrestore(&dev->irqlock, flags);1154	} else {1155		mfc_err("Unsupported buffer type (%d)\n", vq->type);1156	}1157	if (s5p_mfc_ctx_ready(ctx))1158		set_work_bit_irqsave(ctx);1159	s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);1160}1161 1162static const struct vb2_ops s5p_mfc_dec_qops = {1163	.queue_setup		= s5p_mfc_queue_setup,1164	.wait_prepare		= vb2_ops_wait_prepare,1165	.wait_finish		= vb2_ops_wait_finish,1166	.buf_init		= s5p_mfc_buf_init,1167	.start_streaming	= s5p_mfc_start_streaming,1168	.stop_streaming		= s5p_mfc_stop_streaming,1169	.buf_queue		= s5p_mfc_buf_queue,1170};1171 1172const struct s5p_mfc_codec_ops *get_dec_codec_ops(void)1173{1174	return &decoder_codec_ops;1175}1176 1177const struct vb2_ops *get_dec_queue_ops(void)1178{1179	return &s5p_mfc_dec_qops;1180}1181 1182const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void)1183{1184	return &s5p_mfc_dec_ioctl_ops;1185}1186 1187#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_CODEC) \1188						&& V4L2_CTRL_DRIVER_PRIV(x))1189 1190int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)1191{1192	struct v4l2_ctrl_config cfg;1193	int i;1194 1195	v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);1196	if (ctx->ctrl_handler.error) {1197		mfc_err("v4l2_ctrl_handler_init failed\n");1198		return ctx->ctrl_handler.error;1199	}1200 1201	for (i = 0; i < NUM_CTRLS; i++) {1202		if (IS_MFC51_PRIV(controls[i].id)) {1203			memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));1204			cfg.ops = &s5p_mfc_dec_ctrl_ops;1205			cfg.id = controls[i].id;1206			cfg.min = controls[i].minimum;1207			cfg.max = controls[i].maximum;1208			cfg.def = controls[i].default_value;1209			cfg.name = controls[i].name;1210			cfg.type = controls[i].type;1211 1212			cfg.step = controls[i].step;1213			cfg.menu_skip_mask = 0;1214 1215			ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,1216					&cfg, NULL);1217		} else {1218			ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler,1219					&s5p_mfc_dec_ctrl_ops,1220					controls[i].id, controls[i].minimum,1221					controls[i].maximum, controls[i].step,1222					controls[i].default_value);1223		}1224		if (ctx->ctrl_handler.error) {1225			mfc_err("Adding control (%d) failed\n", i);1226			return ctx->ctrl_handler.error;1227		}1228		if (controls[i].is_volatile && ctx->ctrls[i])1229			ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;1230	}1231	return 0;1232}1233 1234void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)1235{1236	int i;1237 1238	v4l2_ctrl_handler_free(&ctx->ctrl_handler);1239	for (i = 0; i < NUM_CTRLS; i++)1240		ctx->ctrls[i] = NULL;1241}1242 1243void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)1244{1245	struct v4l2_format f;1246	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;1247	ctx->src_fmt = find_format(&f, MFC_FMT_DEC);1248	if (IS_MFCV8_PLUS(ctx->dev))1249		f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;1250	else if (IS_MFCV6_PLUS(ctx->dev))1251		f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;1252	else1253		f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT;1254	ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);1255	mfc_debug(2, "Default src_fmt is %p, dest_fmt is %p\n",1256			ctx->src_fmt, ctx->dst_fmt);1257}1258 1259