Commit 6eb9b758 authored by Maxime Ripard's avatar Maxime Ripard Committed by Mauro Carvalho Chehab

media: cedrus: Add H264 decoding support

Introduce some basic H264 decoding support in cedrus. So far, only the
baseline profile videos have been tested, and some more advanced features
used in higher profiles are not even implemented.
Reviewed-by: default avatarJernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: default avatarPaul Kocialkowski <paul.kocialkowski@bootlin.com>
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 67e84a98
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o 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 sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
cedrus_mpeg2.o cedrus_h264.o
...@@ -40,6 +40,36 @@ static const struct cedrus_control cedrus_controls[] = { ...@@ -40,6 +40,36 @@ static const struct cedrus_control cedrus_controls[] = {
.codec = CEDRUS_CODEC_MPEG2, .codec = CEDRUS_CODEC_MPEG2,
.required = false, .required = false,
}, },
{
.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
.elem_size = sizeof(struct v4l2_ctrl_h264_decode_params),
.codec = CEDRUS_CODEC_H264,
.required = true,
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS,
.elem_size = sizeof(struct v4l2_ctrl_h264_slice_params),
.codec = CEDRUS_CODEC_H264,
.required = true,
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_SPS,
.elem_size = sizeof(struct v4l2_ctrl_h264_sps),
.codec = CEDRUS_CODEC_H264,
.required = true,
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_PPS,
.elem_size = sizeof(struct v4l2_ctrl_h264_pps),
.codec = CEDRUS_CODEC_H264,
.required = true,
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
.elem_size = sizeof(struct v4l2_ctrl_h264_scaling_matrix),
.codec = CEDRUS_CODEC_H264,
.required = true,
},
}; };
#define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls) #define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls)
...@@ -278,6 +308,7 @@ static int cedrus_probe(struct platform_device *pdev) ...@@ -278,6 +308,7 @@ static int cedrus_probe(struct platform_device *pdev)
} }
dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2; dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2;
dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264;
mutex_init(&dev->dev_mutex); mutex_init(&dev->dev_mutex);
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
enum cedrus_codec { enum cedrus_codec {
CEDRUS_CODEC_MPEG2, CEDRUS_CODEC_MPEG2,
CEDRUS_CODEC_H264,
CEDRUS_CODEC_LAST, CEDRUS_CODEC_LAST,
}; };
...@@ -42,6 +42,12 @@ enum cedrus_irq_status { ...@@ -42,6 +42,12 @@ enum cedrus_irq_status {
CEDRUS_IRQ_OK, CEDRUS_IRQ_OK,
}; };
enum cedrus_h264_pic_type {
CEDRUS_H264_PIC_TYPE_FRAME = 0,
CEDRUS_H264_PIC_TYPE_FIELD,
CEDRUS_H264_PIC_TYPE_MBAFF,
};
struct cedrus_control { struct cedrus_control {
u32 id; u32 id;
u32 elem_size; u32 elem_size;
...@@ -49,6 +55,14 @@ struct cedrus_control { ...@@ -49,6 +55,14 @@ struct cedrus_control {
unsigned char required:1; unsigned char required:1;
}; };
struct cedrus_h264_run {
const struct v4l2_ctrl_h264_decode_params *decode_params;
const struct v4l2_ctrl_h264_pps *pps;
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
const struct v4l2_ctrl_h264_slice_params *slice_params;
const struct v4l2_ctrl_h264_sps *sps;
};
struct cedrus_mpeg2_run { struct cedrus_mpeg2_run {
const struct v4l2_ctrl_mpeg2_slice_params *slice_params; const struct v4l2_ctrl_mpeg2_slice_params *slice_params;
const struct v4l2_ctrl_mpeg2_quantization *quantization; const struct v4l2_ctrl_mpeg2_quantization *quantization;
...@@ -59,12 +73,20 @@ struct cedrus_run { ...@@ -59,12 +73,20 @@ struct cedrus_run {
struct vb2_v4l2_buffer *dst; struct vb2_v4l2_buffer *dst;
union { union {
struct cedrus_h264_run h264;
struct cedrus_mpeg2_run mpeg2; struct cedrus_mpeg2_run mpeg2;
}; };
}; };
struct cedrus_buffer { struct cedrus_buffer {
struct v4l2_m2m_buffer m2m_buf; struct v4l2_m2m_buffer m2m_buf;
union {
struct {
unsigned int position;
enum cedrus_h264_pic_type pic_type;
} h264;
} codec;
}; };
struct cedrus_ctx { struct cedrus_ctx {
...@@ -79,6 +101,19 @@ struct cedrus_ctx { ...@@ -79,6 +101,19 @@ struct cedrus_ctx {
struct v4l2_ctrl **ctrls; struct v4l2_ctrl **ctrls;
struct vb2_buffer *dst_bufs[VIDEO_MAX_FRAME]; struct vb2_buffer *dst_bufs[VIDEO_MAX_FRAME];
union {
struct {
void *mv_col_buf;
dma_addr_t mv_col_buf_dma;
ssize_t mv_col_buf_field_size;
ssize_t mv_col_buf_size;
void *pic_info_buf;
dma_addr_t pic_info_buf_dma;
void *neighbor_info_buf;
dma_addr_t neighbor_info_buf_dma;
} h264;
} codec;
}; };
struct cedrus_dec_ops { struct cedrus_dec_ops {
...@@ -122,6 +157,7 @@ struct cedrus_dev { ...@@ -122,6 +157,7 @@ struct cedrus_dev {
}; };
extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
extern struct cedrus_dec_ops cedrus_dec_ops_h264;
static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val) static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
{ {
......
...@@ -46,6 +46,19 @@ void cedrus_device_run(void *priv) ...@@ -46,6 +46,19 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION); V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
break; break;
case V4L2_PIX_FMT_H264_SLICE_RAW:
run.h264.decode_params = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS);
run.h264.pps = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_H264_PPS);
run.h264.scaling_matrix = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX);
run.h264.slice_params = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS);
run.h264.sps = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_H264_SPS);
break;
default: default:
break; break;
} }
......
This diff is collapsed.
...@@ -46,6 +46,10 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec) ...@@ -46,6 +46,10 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
reg |= VE_MODE_DEC_MPEG; reg |= VE_MODE_DEC_MPEG;
break; break;
case CEDRUS_CODEC_H264:
reg |= VE_MODE_DEC_H264;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -232,4 +232,95 @@ ...@@ -232,4 +232,95 @@
#define VE_DEC_MPEG_ROT_LUMA (VE_ENGINE_DEC_MPEG + 0xcc) #define VE_DEC_MPEG_ROT_LUMA (VE_ENGINE_DEC_MPEG + 0xcc)
#define VE_DEC_MPEG_ROT_CHROMA (VE_ENGINE_DEC_MPEG + 0xd0) #define VE_DEC_MPEG_ROT_CHROMA (VE_ENGINE_DEC_MPEG + 0xd0)
#define VE_H264_SPS 0x200
#define VE_H264_SPS_MBS_ONLY BIT(18)
#define VE_H264_SPS_MB_ADAPTIVE_FRAME_FIELD BIT(17)
#define VE_H264_SPS_DIRECT_8X8_INFERENCE BIT(16)
#define VE_H264_PPS 0x204
#define VE_H264_PPS_ENTROPY_CODING_MODE BIT(15)
#define VE_H264_PPS_WEIGHTED_PRED BIT(4)
#define VE_H264_PPS_CONSTRAINED_INTRA_PRED BIT(1)
#define VE_H264_PPS_TRANSFORM_8X8_MODE BIT(0)
#define VE_H264_SHS 0x208
#define VE_H264_SHS_FIRST_SLICE_IN_PIC BIT(5)
#define VE_H264_SHS_FIELD_PIC BIT(4)
#define VE_H264_SHS_BOTTOM_FIELD BIT(3)
#define VE_H264_SHS_DIRECT_SPATIAL_MV_PRED BIT(2)
#define VE_H264_SHS2 0x20c
#define VE_H264_SHS2_NUM_REF_IDX_ACTIVE_OVRD BIT(12)
#define VE_H264_SHS_WP 0x210
#define VE_H264_SHS_QP 0x21c
#define VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT BIT(24)
#define VE_H264_CTRL 0x220
#define VE_H264_CTRL_VLD_DATA_REQ_INT BIT(2)
#define VE_H264_CTRL_DECODE_ERR_INT BIT(1)
#define VE_H264_CTRL_SLICE_DECODE_INT BIT(0)
#define VE_H264_CTRL_INT_MASK (VE_H264_CTRL_VLD_DATA_REQ_INT | \
VE_H264_CTRL_DECODE_ERR_INT | \
VE_H264_CTRL_SLICE_DECODE_INT)
#define VE_H264_TRIGGER_TYPE 0x224
#define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE (8 << 0)
#define VE_H264_TRIGGER_TYPE_INIT_SWDEC (7 << 0)
#define VE_H264_STATUS 0x228
#define VE_H264_STATUS_VLD_DATA_REQ_INT VE_H264_CTRL_VLD_DATA_REQ_INT
#define VE_H264_STATUS_DECODE_ERR_INT VE_H264_CTRL_DECODE_ERR_INT
#define VE_H264_STATUS_SLICE_DECODE_INT VE_H264_CTRL_SLICE_DECODE_INT
#define VE_H264_STATUS_INT_MASK VE_H264_CTRL_INT_MASK
#define VE_H264_CUR_MB_NUM 0x22c
#define VE_H264_VLD_ADDR 0x230
#define VE_H264_VLD_ADDR_FIRST BIT(30)
#define VE_H264_VLD_ADDR_LAST BIT(29)
#define VE_H264_VLD_ADDR_VALID BIT(28)
#define VE_H264_VLD_ADDR_VAL(x) (((x) & 0x0ffffff0) | ((x) >> 28))
#define VE_H264_VLD_OFFSET 0x234
#define VE_H264_VLD_LEN 0x238
#define VE_H264_VLD_END 0x23c
#define VE_H264_SDROT_CTRL 0x240
#define VE_H264_OUTPUT_FRAME_IDX 0x24c
#define VE_H264_EXTRA_BUFFER1 0x250
#define VE_H264_EXTRA_BUFFER2 0x254
#define VE_H264_BASIC_BITS 0x2dc
#define VE_AVC_SRAM_PORT_OFFSET 0x2e0
#define VE_AVC_SRAM_PORT_DATA 0x2e4
#define VE_ISP_INPUT_SIZE 0xa00
#define VE_ISP_INPUT_STRIDE 0xa04
#define VE_ISP_CTRL 0xa08
#define VE_ISP_INPUT_LUMA 0xa78
#define VE_ISP_INPUT_CHROMA 0xa7c
#define VE_AVC_PARAM 0xb04
#define VE_AVC_QP 0xb08
#define VE_AVC_MOTION_EST 0xb10
#define VE_AVC_CTRL 0xb14
#define VE_AVC_TRIGGER 0xb18
#define VE_AVC_STATUS 0xb1c
#define VE_AVC_BASIC_BITS 0xb20
#define VE_AVC_UNK_BUF 0xb60
#define VE_AVC_VLE_ADDR 0xb80
#define VE_AVC_VLE_END 0xb84
#define VE_AVC_VLE_OFFSET 0xb88
#define VE_AVC_VLE_MAX 0xb8c
#define VE_AVC_VLE_LENGTH 0xb90
#define VE_AVC_REF_LUMA 0xba0
#define VE_AVC_REF_CHROMA 0xba4
#define VE_AVC_REC_LUMA 0xbb0
#define VE_AVC_REC_CHROMA 0xbb4
#define VE_AVC_REF_SLUMA 0xbb8
#define VE_AVC_REC_SLUMA 0xbbc
#define VE_AVC_MB_INFO 0xbc0
#endif #endif
...@@ -37,6 +37,10 @@ static struct cedrus_format cedrus_formats[] = { ...@@ -37,6 +37,10 @@ static struct cedrus_format cedrus_formats[] = {
.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE, .pixelformat = V4L2_PIX_FMT_MPEG2_SLICE,
.directions = CEDRUS_DECODE_SRC, .directions = CEDRUS_DECODE_SRC,
}, },
{
.pixelformat = V4L2_PIX_FMT_H264_SLICE_RAW,
.directions = CEDRUS_DECODE_SRC,
},
{ {
.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12,
.directions = CEDRUS_DECODE_DST, .directions = CEDRUS_DECODE_DST,
...@@ -100,6 +104,7 @@ static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) ...@@ -100,6 +104,7 @@ static void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
switch (pix_fmt->pixelformat) { switch (pix_fmt->pixelformat) {
case V4L2_PIX_FMT_MPEG2_SLICE: case V4L2_PIX_FMT_MPEG2_SLICE:
case V4L2_PIX_FMT_H264_SLICE_RAW:
/* Zero bytes per line for encoded source. */ /* Zero bytes per line for encoded source. */
bytesperline = 0; bytesperline = 0;
...@@ -464,6 +469,10 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) ...@@ -464,6 +469,10 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
ctx->current_codec = CEDRUS_CODEC_MPEG2; ctx->current_codec = CEDRUS_CODEC_MPEG2;
break; break;
case V4L2_PIX_FMT_H264_SLICE_RAW:
ctx->current_codec = CEDRUS_CODEC_H264;
break;
default: default:
return -EINVAL; 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