Commit 6f146612 authored by Aakarsh Jain's avatar Aakarsh Jain Committed by Hans Verkuil
Browse files

media: s5p-mfc: Add YV12 and I420 multiplanar format support



YV12 and I420 format (3-plane) support is added. Stride information is
added to all formats and planes since it is necessary for YV12/I420
which are different from width.

Cc: linux-fsd@tesla.com
Signed-off-by: default avatarSmitha T Murthy <smithatmurthy@gmail.com>
Signed-off-by: default avatarAakarsh Jain <aakarsh.jain@samsung.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent e57b6d32
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#define MFC_VERSION_V12			0xC0
#define MFC_NUM_PORTS_V12		1
#define S5P_FIMV_CODEC_VP9_ENC		27
#define MFC_CHROMA_PAD_BYTES_V12        256
#define S5P_FIMV_D_ALIGN_PLANE_SIZE_V12 256

/* Encoder buffer size for MFCv12 */
#define ENC_V120_BASE_SIZE(x, y) \
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7		0xfa70
#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7	0xfa74
#define S5P_FIMV_E_ENCODED_SOURCE_THIRD_ADDR_V7		0xfa78

#define S5P_FIMV_E_VP8_OPTIONS_V7			0xfdb0
#define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7		0xfdb4
+3 −0
Original line number Diff line number Diff line
@@ -17,13 +17,16 @@
#define S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8	0xf108
#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8	0xf144
#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8	0xf148
#define S5P_FIMV_D_THIRD_PLANE_DPB_SIZE_V8	0xf14C
#define S5P_FIMV_D_MV_BUFFER_SIZE_V8		0xf150

#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8	0xf138
#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8	0xf13c
#define S5P_FIMV_D_THIRD_PLANE_DPB_STRIDE_SIZE_V8	0xf140

#define S5P_FIMV_D_FIRST_PLANE_DPB_V8		0xf160
#define S5P_FIMV_D_SECOND_PLANE_DPB_V8		0xf260
#define S5P_FIMV_D_THIRD_PLANE_DPB_V8		0xf360
#define S5P_FIMV_D_MV_BUFFER_V8			0xf460

#define S5P_FIMV_D_NUM_MV_V8			0xf134
+6 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
#define MFC_NO_INSTANCE_SET	-1
#define MFC_ENC_CAP_PLANE_COUNT	1
#define MFC_ENC_OUT_PLANE_COUNT	2
#define VB2_MAX_PLANE_COUNT	3
#define STUFF_BYTE		4
#define MFC_MAX_CTRLS		128

@@ -181,6 +182,7 @@ struct s5p_mfc_buf {
		struct {
			size_t luma;
			size_t chroma;
			size_t chroma_1;
		} raw;
		size_t stream;
	} cookie;
@@ -623,6 +625,8 @@ struct s5p_mfc_codec_ops {
 * @scratch_buf_size:	scratch buffer size
 * @is_10bit:		state to check 10bit support
 * @is_422:		state to check YUV422 10bit format
 * @chroma_size_1:	size of a chroma third plane
 * @stride:		size of stride for all planes
 */
struct s5p_mfc_ctx {
	struct s5p_mfc_dev *dev;
@@ -659,6 +663,7 @@ struct s5p_mfc_ctx {

	int luma_size;
	int chroma_size;
	int chroma_size_1;
	int mv_size;

	unsigned long consumed_stream;
@@ -724,6 +729,7 @@ struct s5p_mfc_ctx {
	size_t scratch_buf_size;
	int is_10bit;
	int is_422;
	int stride[VB2_MAX_PLANE_COUNT];
};

/*
+48 −6
Original line number Diff line number Diff line
@@ -56,6 +56,20 @@ static struct s5p_mfc_fmt formats[] = {
		.num_planes	= 2,
		.versions	= MFC_V6PLUS_BITS,
	},
	{
		.fourcc         = V4L2_PIX_FMT_YUV420M,
		.codec_mode     = S5P_MFC_CODEC_NONE,
		.type           = MFC_FMT_RAW,
		.num_planes     = 3,
		.versions       = MFC_V12_BIT,
	},
	{
		.fourcc         = V4L2_PIX_FMT_YVU420M,
		.codec_mode     = S5P_MFC_CODEC_NONE,
		.type           = MFC_FMT_RAW,
		.num_planes     = 3,
		.versions       = MFC_V12_BIT
	},
	{
		.fourcc		= V4L2_PIX_FMT_H264,
		.codec_mode	= S5P_MFC_CODEC_H264_DEC,
@@ -359,10 +373,15 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
		/* Set pixelformat to the format in which MFC
		   outputs the decoded frame */
		pix_mp->pixelformat = ctx->dst_fmt->fourcc;
		pix_mp->plane_fmt[0].bytesperline = ctx->buf_width;
		pix_mp->plane_fmt[0].bytesperline = ctx->stride[0];
		pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;
		pix_mp->plane_fmt[1].bytesperline = ctx->buf_width;
		pix_mp->plane_fmt[1].bytesperline = ctx->stride[1];
		pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==
				V4L2_PIX_FMT_YVU420M) {
			pix_mp->plane_fmt[2].bytesperline = ctx->stride[2];
			pix_mp->plane_fmt[2].sizeimage = ctx->chroma_size_1;
		}
	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		/* This is run on OUTPUT
		   The buffer contains compressed image
@@ -920,6 +939,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
{
	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
	struct s5p_mfc_dev *dev = ctx->dev;
	const struct v4l2_format_info *format;

	/* Video output for decoding (source)
	 * this can be set after getting an instance */
@@ -936,7 +956,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
	} else if (ctx->state == MFCINST_HEAD_PARSED &&
		   vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
		/* Output plane count is 2 - one for Y and one for CbCr */
		*plane_count = 2;
		format = v4l2_format_info(ctx->dst_fmt->fourcc);
		if (!format) {
			mfc_err("invalid format\n");
			return -EINVAL;
		}
		*plane_count = format->comp_planes;

		/* Setup buffer count */
		if (*buf_count < ctx->pb_count)
			*buf_count = ctx->pb_count;
@@ -955,14 +981,18 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
	    vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
		psize[0] = ctx->luma_size;
		psize[1] = ctx->chroma_size;

		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==
				V4L2_PIX_FMT_YVU420M)
			psize[2] = ctx->chroma_size_1;
		if (IS_MFCV6_PLUS(dev))
			alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
		else
			alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];
		alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];
	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
		   ctx->state == MFCINST_INIT) {
		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==
				V4L2_PIX_FMT_YVU420M)
			alloc_devs[2] = ctx->dev->mem_dev[BANK_L_CTX];
	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) {
		psize[0] = ctx->dec_src_buf_size;
		alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
	} else {
@@ -994,12 +1024,24 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
			mfc_err("Plane buffer (CAPTURE) is too small\n");
			return -EINVAL;
		}
		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==
				V4L2_PIX_FMT_YVU420M) {
			if (vb2_plane_size(vb, 2) < ctx->chroma_size_1) {
				mfc_err("Plane buffer (CAPTURE) is too small\n");
				return -EINVAL;
			}
		}
		i = vb->index;
		ctx->dst_bufs[i].b = vbuf;
		ctx->dst_bufs[i].cookie.raw.luma =
					vb2_dma_contig_plane_dma_addr(vb, 0);
		ctx->dst_bufs[i].cookie.raw.chroma =
					vb2_dma_contig_plane_dma_addr(vb, 1);
		if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==
				V4L2_PIX_FMT_YVU420M) {
			ctx->dst_bufs[i].cookie.raw.chroma_1 =
					vb2_dma_contig_plane_dma_addr(vb, 2);
		}
		ctx->dst_bufs_cnt++;
	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		if (IS_ERR_OR_NULL(ERR_PTR(
Loading