Commit 86caab29 authored by Paul Kocialkowski's avatar Paul Kocialkowski Committed by Mauro Carvalho Chehab
Browse files

media: cedrus: Add HEVC/H.265 decoding support



This introduces support for HEVC/H.265 to the Cedrus VPU driver, with
both uni-directional and bi-directional prediction modes supported.

Field-coded (interlaced) pictures, custom quantization matrices and
10-bit output are not supported at this point.

Signed-off-by: default avatarPaul Kocialkowski <paul.kocialkowski@bootlin.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent de06f289
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2,4 +2,4 @@
obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o

sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
		 cedrus_mpeg2.o cedrus_h264.o
		 cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o
+48 −4
Original line number Diff line number Diff line
@@ -95,6 +95,45 @@ static const struct cedrus_control cedrus_controls[] = {
		.codec		= CEDRUS_CODEC_H264,
		.required	= false,
	},
	{
		.cfg = {
			.id	= V4L2_CID_MPEG_VIDEO_HEVC_SPS,
		},
		.codec		= CEDRUS_CODEC_H265,
		.required	= true,
	},
	{
		.cfg = {
			.id	= V4L2_CID_MPEG_VIDEO_HEVC_PPS,
		},
		.codec		= CEDRUS_CODEC_H265,
		.required	= true,
	},
	{
		.cfg = {
			.id	= V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
		},
		.codec		= CEDRUS_CODEC_H265,
		.required	= true,
	},
	{
		.cfg = {
			.id	= V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE,
			.max	= V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED,
			.def	= V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED,
		},
		.codec		= CEDRUS_CODEC_H265,
		.required	= false,
	},
	{
		.cfg = {
			.id	= V4L2_CID_MPEG_VIDEO_HEVC_START_CODE,
			.max	= V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE,
			.def	= V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE,
		},
		.codec		= CEDRUS_CODEC_H265,
		.required	= false,
	},
};

#define CEDRUS_CONTROLS_COUNT	ARRAY_SIZE(cedrus_controls)
@@ -340,6 +379,7 @@ static int cedrus_probe(struct platform_device *pdev)

	dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2;
	dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264;
	dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265;

	mutex_init(&dev->dev_mutex);

@@ -450,22 +490,26 @@ static const struct cedrus_variant sun8i_a33_cedrus_variant = {
};

static const struct cedrus_variant sun8i_h3_cedrus_variant = {
	.capabilities	= CEDRUS_CAPABILITY_UNTILED,
	.capabilities	= CEDRUS_CAPABILITY_UNTILED |
			  CEDRUS_CAPABILITY_H265_DEC,
	.mod_rate	= 402000000,
};

static const struct cedrus_variant sun50i_a64_cedrus_variant = {
	.capabilities	= CEDRUS_CAPABILITY_UNTILED,
	.capabilities	= CEDRUS_CAPABILITY_UNTILED |
			  CEDRUS_CAPABILITY_H265_DEC,
	.mod_rate	= 402000000,
};

static const struct cedrus_variant sun50i_h5_cedrus_variant = {
	.capabilities	= CEDRUS_CAPABILITY_UNTILED,
	.capabilities	= CEDRUS_CAPABILITY_UNTILED |
			  CEDRUS_CAPABILITY_H265_DEC,
	.mod_rate	= 402000000,
};

static const struct cedrus_variant sun50i_h6_cedrus_variant = {
	.capabilities	= CEDRUS_CAPABILITY_UNTILED,
	.capabilities	= CEDRUS_CAPABILITY_UNTILED |
			  CEDRUS_CAPABILITY_H265_DEC,
	.quirks		= CEDRUS_QUIRK_NO_DMA_OFFSET,
	.mod_rate	= 600000000,
};
+18 −0
Original line number Diff line number Diff line
@@ -27,12 +27,14 @@
#define CEDRUS_NAME			"cedrus"

#define CEDRUS_CAPABILITY_UNTILED	BIT(0)
#define CEDRUS_CAPABILITY_H265_DEC	BIT(1)

#define CEDRUS_QUIRK_NO_DMA_OFFSET	BIT(0)

enum cedrus_codec {
	CEDRUS_CODEC_MPEG2,
	CEDRUS_CODEC_H264,
	CEDRUS_CODEC_H265,
	CEDRUS_CODEC_LAST,
};

@@ -67,6 +69,12 @@ struct cedrus_mpeg2_run {
	const struct v4l2_ctrl_mpeg2_quantization	*quantization;
};

struct cedrus_h265_run {
	const struct v4l2_ctrl_hevc_sps			*sps;
	const struct v4l2_ctrl_hevc_pps			*pps;
	const struct v4l2_ctrl_hevc_slice_params	*slice_params;
};

struct cedrus_run {
	struct vb2_v4l2_buffer	*src;
	struct vb2_v4l2_buffer	*dst;
@@ -74,6 +82,7 @@ struct cedrus_run {
	union {
		struct cedrus_h264_run	h264;
		struct cedrus_mpeg2_run	mpeg2;
		struct cedrus_h265_run	h265;
	};
};

@@ -110,6 +119,14 @@ struct cedrus_ctx {
			void		*neighbor_info_buf;
			dma_addr_t	neighbor_info_buf_dma;
		} h264;
		struct {
			void		*mv_col_buf;
			dma_addr_t	mv_col_buf_addr;
			ssize_t		mv_col_buf_size;
			ssize_t		mv_col_buf_unit_size;
			void		*neighbor_info_buf;
			dma_addr_t	neighbor_info_buf_addr;
		} h265;
	} codec;
};

@@ -155,6 +172,7 @@ struct cedrus_dev {

extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
extern struct cedrus_dec_ops cedrus_dec_ops_h264;
extern struct cedrus_dec_ops cedrus_dec_ops_h265;

static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
{
+9 −0
Original line number Diff line number Diff line
@@ -59,6 +59,15 @@ void cedrus_device_run(void *priv)
			V4L2_CID_MPEG_VIDEO_H264_SPS);
		break;

	case V4L2_PIX_FMT_HEVC_SLICE:
		run.h265.sps = cedrus_find_control_data(ctx,
			V4L2_CID_MPEG_VIDEO_HEVC_SPS);
		run.h265.pps = cedrus_find_control_data(ctx,
			V4L2_CID_MPEG_VIDEO_HEVC_PPS);
		run.h265.slice_params = cedrus_find_control_data(ctx,
			V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
		break;

	default:
		break;
	}
+616 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading