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

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
......@@ -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
......@@ -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,
};
......
......@@ -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)
{
......
......@@ -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;
}
......
This diff is collapsed.
......@@ -50,6 +50,10 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
reg |= VE_MODE_DEC_H264;
break;
case CEDRUS_CODEC_H265:
reg |= VE_MODE_DEC_H265;
break;
default:
return -EINVAL;
}
......
......@@ -41,6 +41,11 @@ static struct cedrus_format cedrus_formats[] = {
.pixelformat = V4L2_PIX_FMT_H264_SLICE,
.directions = CEDRUS_DECODE_SRC,
},
{
.pixelformat = V4L2_PIX_FMT_HEVC_SLICE,
.directions = CEDRUS_DECODE_SRC,
.capabilities = CEDRUS_CAPABILITY_H265_DEC,
},
{
.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12,
.directions = CEDRUS_DECODE_DST,
......@@ -102,6 +107,7 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
switch (pix_fmt->pixelformat) {
case V4L2_PIX_FMT_MPEG2_SLICE:
case V4L2_PIX_FMT_H264_SLICE:
case V4L2_PIX_FMT_HEVC_SLICE:
/* Zero bytes per line for encoded source. */
bytesperline = 0;
/* Choose some minimum size since this can't be 0 */
......@@ -439,6 +445,10 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
ctx->current_codec = CEDRUS_CODEC_H264;
break;
case V4L2_PIX_FMT_HEVC_SLICE:
ctx->current_codec = CEDRUS_CODEC_H265;
break;
default:
return -EINVAL;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment