linux (Allwinner): rebase patches for 6.2-rc1

This commit is contained in:
Rudi Heitbaum 2022-12-28 06:08:07 +00:00
parent 83ec8acf6b
commit 56c75e7140
4 changed files with 0 additions and 646 deletions

View File

@ -1,50 +0,0 @@
From b6d288bb8823e11114297d1e406ccd977106aaf9 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 9 Nov 2019 13:06:15 +0100
Subject: [PATCH 28/44] media: cedrus: Add callback for buffer cleanup
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.h | 1 +
drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++++
2 files changed, 14 insertions(+)
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -166,6 +166,7 @@ struct cedrus_dec_ops {
int (*start)(struct cedrus_ctx *ctx);
void (*stop)(struct cedrus_ctx *ctx);
void (*trigger)(struct cedrus_ctx *ctx);
+ void (*buf_cleanup)(struct cedrus_ctx *ctx, struct cedrus_buffer *buf);
};
struct cedrus_variant {
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -469,6 +469,18 @@ static int cedrus_buf_prepare(struct vb2
return 0;
}
+static void cedrus_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
+ struct cedrus_dev *dev = ctx->dev;
+ struct cedrus_dec_ops *ops = dev->dec_ops[ctx->current_codec];
+
+ if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ops->buf_cleanup)
+ ops->buf_cleanup(ctx,
+ vb2_to_cedrus_buffer(vq->bufs[vb->index]));
+}
+
static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
@@ -551,6 +563,7 @@ static void cedrus_buf_request_complete(
static struct vb2_ops cedrus_qops = {
.queue_setup = cedrus_queue_setup,
.buf_prepare = cedrus_buf_prepare,
+ .buf_cleanup = cedrus_buf_cleanup,
.buf_queue = cedrus_buf_queue,
.buf_out_validate = cedrus_buf_out_validate,
.buf_request_complete = cedrus_buf_request_complete,

View File

@ -1,240 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 9 Nov 2019 13:22:05 +0100
Subject: [PATCH] media: cedrus: hevc: Improve buffer management
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +-
.../staging/media/sunxi/cedrus/cedrus_h265.c | 119 ++++++++++--------
2 files changed, 69 insertions(+), 59 deletions(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index ab7653c8915e..54a860ec738d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -106,6 +106,11 @@ struct cedrus_buffer {
unsigned int position;
enum cedrus_h264_pic_type pic_type;
} h264;
+ struct {
+ void *mv_col_buf;
+ dma_addr_t mv_col_buf_dma;
+ ssize_t mv_col_buf_size;
+ } h265;
} codec;
};
@@ -139,10 +144,6 @@ struct cedrus_ctx {
ssize_t intra_pred_buf_size;
} 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;
void *entry_points_buf;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 4b01d3881214..4d425196d415 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -91,26 +91,65 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
static inline dma_addr_t
cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
- unsigned int index, unsigned int field)
+ unsigned int index,
+ const struct v4l2_ctrl_hevc_sps *sps)
{
- return ctx->codec.h265.mv_col_buf_addr + index *
- ctx->codec.h265.mv_col_buf_unit_size +
- field * ctx->codec.h265.mv_col_buf_unit_size / 2;
+ struct cedrus_buffer *cedrus_buf = NULL;
+ struct vb2_buffer *buf = NULL;
+ struct vb2_queue *vq;
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ if (vq)
+ buf = vb2_get_buffer(vq, index);
+
+ if (buf)
+ cedrus_buf = vb2_to_cedrus_buffer(buf);
+
+ if (!cedrus_buf)
+ return 0;
+
+ if (!cedrus_buf->codec.h265.mv_col_buf_size) {
+ unsigned int log2_max_luma_coding_block_size;
+ unsigned int ctb_size_luma;
+
+ log2_max_luma_coding_block_size =
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size;
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
+
+ cedrus_buf->codec.h265.mv_col_buf_size =
+ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma) *
+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) *
+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
+
+ cedrus_buf->codec.h265.mv_col_buf =
+ dma_alloc_attrs(ctx->dev->dev,
+ cedrus_buf->codec.h265.mv_col_buf_size,
+ &cedrus_buf->codec.h265.mv_col_buf_dma,
+ GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
+
+ if (!cedrus_buf->codec.h265.mv_col_buf) {
+ cedrus_buf->codec.h265.mv_col_buf_size = 0;
+ cedrus_buf->codec.h265.mv_col_buf_dma = 0;
+ }
+ }
+
+ return cedrus_buf->codec.h265.mv_col_buf_dma;
}
static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
unsigned int index,
bool field_pic,
u32 pic_order_cnt[],
- struct vb2_buffer *buf)
+ struct vb2_buffer *buf,
+ const struct v4l2_ctrl_hevc_sps *sps)
{
struct cedrus_dev *dev = ctx->dev;
dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buf, 0);
dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buf, 1);
dma_addr_t mv_col_buf_addr[2] = {
- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buf->index, 0),
- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buf->index,
- field_pic ? 1 : 0)
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buf->index, sps),
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buf->index, sps)
};
u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
@@ -134,7 +173,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
const struct v4l2_hevc_dpb_entry *dpb,
- u8 num_active_dpb_entries)
+ u8 num_active_dpb_entries,
+ const struct v4l2_ctrl_hevc_sps *sps)
{
struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -149,7 +189,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
pic_order_cnt,
- buf);
+ buf, sps);
}
}
@@ -388,36 +428,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
width_in_ctb_luma =
DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
- /* MV column buffer size and allocation. */
- if (!ctx->codec.h265.mv_col_buf_size) {
- unsigned int num_buffers =
- run->dst->vb2_buf.vb2_queue->num_buffers;
-
- /*
- * Each CTB requires a MV col buffer with a specific unit size.
- * Since the address is given with missing lsb bits, 1 KiB is
- * added to each buffer to ensure proper alignment.
- */
- ctx->codec.h265.mv_col_buf_unit_size =
- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
-
- ctx->codec.h265.mv_col_buf_size = num_buffers *
- ctx->codec.h265.mv_col_buf_unit_size;
-
- /* Buffer is never accessed by CPU, so we can skip kernel mapping. */
- ctx->codec.h265.mv_col_buf =
- dma_alloc_attrs(dev->dev,
- ctx->codec.h265.mv_col_buf_size,
- &ctx->codec.h265.mv_col_buf_addr,
- GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
- if (!ctx->codec.h265.mv_col_buf) {
- ctx->codec.h265.mv_col_buf_size = 0;
- return -ENOMEM;
- }
- }
-
/* Activate H265 engine. */
cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
@@ -672,7 +681,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
/* Write decoded picture buffer in pic list. */
cedrus_h265_frame_info_write_dpb(ctx, decode_params->dpb,
- decode_params->num_active_dpb_entries);
+ decode_params->num_active_dpb_entries, sps);
/* Output frame. */
@@ -683,7 +692,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
slice_params->pic_struct != 0,
pic_order_cnt,
- &run->dst->vb2_buf);
+ &run->dst->vb2_buf, sps);
cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
@@ -732,9 +741,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
- /* The buffer size is calculated at setup time. */
- ctx->codec.h265.mv_col_buf_size = 0;
-
/* Buffer is never accessed by CPU, so we can skip kernel mapping. */
ctx->codec.h265.neighbor_info_buf =
dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
@@ -761,15 +767,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
- if (ctx->codec.h265.mv_col_buf_size > 0) {
- dma_free_attrs(dev->dev, ctx->codec.h265.mv_col_buf_size,
- ctx->codec.h265.mv_col_buf,
- ctx->codec.h265.mv_col_buf_addr,
- DMA_ATTR_NO_KERNEL_MAPPING);
-
- ctx->codec.h265.mv_col_buf_size = 0;
- }
-
dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
ctx->codec.h265.neighbor_info_buf,
ctx->codec.h265.neighbor_info_buf_addr,
@@ -786,6 +783,17 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
}
+static void cedrus_h265_buf_cleanup(struct cedrus_ctx *ctx,
+ struct cedrus_buffer *buf)
+{
+ if (buf->codec.h265.mv_col_buf_size)
+ dma_free_attrs(ctx->dev->dev,
+ buf->codec.h265.mv_col_buf_size,
+ buf->codec.h265.mv_col_buf,
+ buf->codec.h265.mv_col_buf_dma,
+ DMA_ATTR_NO_KERNEL_MAPPING);
+}
+
struct cedrus_dec_ops cedrus_dec_ops_h265 = {
.irq_clear = cedrus_h265_irq_clear,
.irq_disable = cedrus_h265_irq_disable,
@@ -794,4 +802,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = {
.start = cedrus_h265_start,
.stop = cedrus_h265_stop,
.trigger = cedrus_h265_trigger,
+ .buf_cleanup = cedrus_h265_buf_cleanup,
};

View File

@ -1,201 +0,0 @@
From a881ce25cba8e45c6a86b5a680981c3b14b5b1e1 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 9 Nov 2019 14:12:42 +0100
Subject: [PATCH 30/44] media: cedrus: h264: Improve buffer management
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.h | 3 +
.../staging/media/sunxi/cedrus/cedrus_h264.c | 93 ++++++++-----------
2 files changed, 44 insertions(+), 52 deletions(-)
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -104,6 +104,9 @@ struct cedrus_buffer {
struct {
unsigned int position;
enum cedrus_h264_pic_type pic_type;
+ void *mv_col_buf;
+ dma_addr_t mv_col_buf_dma;
+ ssize_t mv_col_buf_size;
} h264;
struct {
void *mv_col_buf;
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struc
}
static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx,
- unsigned int position,
+ struct cedrus_buffer *buf,
unsigned int field)
{
- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma;
+ dma_addr_t addr = buf->codec.h264.mv_col_buf_dma;
- /* Adjust for the position */
- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2;
-
- /* Adjust for the field */
- addr += field * ctx->codec.h264.mv_col_buf_field_size;
+ /* Adjust for the field */
+ if (field)
+ addr += buf->codec.h264.mv_col_buf_size / 2;
return addr;
}
@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct c
struct cedrus_h264_sram_ref_pic *pic)
{
struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf;
- unsigned int position = buf->codec.h264.position;
pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt);
pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt);
@@ -85,9 +82,9 @@ static void cedrus_fill_ref_pic(struct c
pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0));
pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1));
pic->mv_col_top_ptr =
- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0));
+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 0));
pic->mv_col_bot_ptr =
- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1));
+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 1));
}
static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
@@ -146,6 +143,28 @@ static void cedrus_write_frame_list(stru
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
output_buf->codec.h264.position = position;
+ if (!output_buf->codec.h264.mv_col_buf_size) {
+ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
+ unsigned int field_size;
+
+ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
+ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
+ field_size = field_size * 2;
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
+ field_size = field_size * 2;
+
+ output_buf->codec.h264.mv_col_buf_size = field_size * 2;
+ output_buf->codec.h264.mv_col_buf =
+ dma_alloc_attrs(dev->dev,
+ output_buf->codec.h264.mv_col_buf_size,
+ &output_buf->codec.h264.mv_col_buf_dma,
+ GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
+
+ if (!output_buf->codec.h264.mv_col_buf)
+ output_buf->codec.h264.mv_col_buf_size = 0;
+ }
+
if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)
output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD;
else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
@@ -516,8 +535,6 @@ static int cedrus_h264_start(struct cedr
{
struct cedrus_dev *dev = ctx->dev;
unsigned int pic_info_size;
- unsigned int field_size;
- unsigned int mv_col_size;
int ret;
/* Formula for picture buffer size is taken from CedarX source. */
@@ -560,38 +577,6 @@ static int cedrus_h264_start(struct cedr
goto err_pic_buf;
}
- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
-
- /*
- * FIXME: This is actually conditional to
- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we
- * might have to rework this if memory efficiency ever is
- * something we need to work on.
- */
- field_size = field_size * 2;
-
- /*
- * FIXME: This is actually conditional to
- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might
- * have to rework this if memory efficiency ever is something
- * we need to work on.
- */
- field_size = field_size * 2;
- ctx->codec.h264.mv_col_buf_field_size = field_size;
-
- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM;
- ctx->codec.h264.mv_col_buf_size = mv_col_size;
- ctx->codec.h264.mv_col_buf =
- dma_alloc_attrs(dev->dev,
- ctx->codec.h264.mv_col_buf_size,
- &ctx->codec.h264.mv_col_buf_dma,
- GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
- if (!ctx->codec.h264.mv_col_buf) {
- ret = -ENOMEM;
- goto err_neighbor_buf;
- }
-
if (ctx->src_fmt.width > 2048) {
/*
* Formulas for deblock and intra prediction buffer sizes
@@ -606,7 +592,7 @@ static int cedrus_h264_start(struct cedr
GFP_KERNEL);
if (!ctx->codec.h264.deblk_buf) {
ret = -ENOMEM;
- goto err_mv_col_buf;
+ goto err_neighbor_buf;
}
/*
@@ -633,12 +619,6 @@ err_deblk_buf:
ctx->codec.h264.deblk_buf,
ctx->codec.h264.deblk_buf_dma);
-err_mv_col_buf:
- dma_free_attrs(dev->dev, ctx->codec.h264.mv_col_buf_size,
- ctx->codec.h264.mv_col_buf,
- ctx->codec.h264.mv_col_buf_dma,
- DMA_ATTR_NO_KERNEL_MAPPING);
-
err_neighbor_buf:
dma_free_attrs(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
ctx->codec.h264.neighbor_info_buf,
@@ -654,10 +635,6 @@ static void cedrus_h264_stop(struct cedr
{
struct cedrus_dev *dev = ctx->dev;
- dma_free_attrs(dev->dev, ctx->codec.h264.mv_col_buf_size,
- ctx->codec.h264.mv_col_buf,
- ctx->codec.h264.mv_col_buf_dma,
- DMA_ATTR_NO_KERNEL_MAPPING);
dma_free_attrs(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
ctx->codec.h264.neighbor_info_buf,
ctx->codec.h264.neighbor_info_buf_dma,
@@ -681,6 +659,17 @@ static void cedrus_h264_trigger(struct c
VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE);
}
+static void cedrus_h264_buf_cleanup(struct cedrus_ctx *ctx,
+ struct cedrus_buffer *buf)
+{
+ if (buf->codec.h264.mv_col_buf_size)
+ dma_free_attrs(ctx->dev->dev,
+ buf->codec.h264.mv_col_buf_size,
+ buf->codec.h264.mv_col_buf,
+ buf->codec.h264.mv_col_buf_dma,
+ DMA_ATTR_NO_KERNEL_MAPPING);
+}
+
struct cedrus_dec_ops cedrus_dec_ops_h264 = {
.irq_clear = cedrus_h264_irq_clear,
.irq_disable = cedrus_h264_irq_disable,
@@ -689,4 +677,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h26
.start = cedrus_h264_start,
.stop = cedrus_h264_stop,
.trigger = cedrus_h264_trigger,
+ .buf_cleanup = cedrus_h264_buf_cleanup,
};

View File

@ -1,155 +0,0 @@
From 54389b5956af51023b073a08eeb7a746a4a37119 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sun, 15 Mar 2020 21:35:39 +0100
Subject: [PATCH 31/44] WIp: 10-bit HEVC support
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.c | 4 +--
.../staging/media/sunxi/cedrus/cedrus_h265.c | 12 ++++++++
.../staging/media/sunxi/cedrus/cedrus_regs.h | 4 +++
.../staging/media/sunxi/cedrus/cedrus_video.c | 30 +++++++++++++++----
.../staging/media/sunxi/cedrus/cedrus_video.h | 2 +-
5 files changed, 44 insertions(+), 8 deletions(-)
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -289,7 +289,7 @@ static int cedrus_open(struct file *file
goto err_ctrls;
}
ctx->dst_fmt.pixelformat = V4L2_PIX_FMT_NV12_32L32;
- cedrus_prepare_format(&ctx->dst_fmt);
+ cedrus_prepare_format(&ctx->dst_fmt, 0);
ctx->src_fmt.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE;
/*
* TILED_NV12 has more strict requirements, so copy the width and
@@ -297,7 +297,7 @@ static int cedrus_open(struct file *file
*/
ctx->src_fmt.width = ctx->dst_fmt.width;
ctx->src_fmt.height = ctx->dst_fmt.height;
- cedrus_prepare_format(&ctx->src_fmt);
+ cedrus_prepare_format(&ctx->src_fmt, 0);
v4l2_fh_add(&ctx->fh);
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -534,6 +534,18 @@ static void cedrus_h265_setup(struct ced
cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg);
+ if (sps->bit_depth_luma_minus8 == 2) {
+ unsigned int size;
+
+ size = ALIGN(ctx->src_fmt.width, 16) * ALIGN(ctx->src_fmt.height, 16);
+
+ reg = (size * 3) / 2;
+ cedrus_write(dev, VE_DEC_H265_OFFSET_ADDR_FIRST_OUT, reg);
+
+ reg = DIV_ROUND_UP(ctx->src_fmt.width, 4);
+ cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, ALIGN(reg, 32));
+ }
+
/* PPS. */
reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) |
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -499,6 +499,10 @@
#define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80)
+#define VE_DEC_H265_OFFSET_ADDR_FIRST_OUT (VE_ENGINE_DEC_H265 + 0x84)
+#define VE_DEC_H265_OFFSET_ADDR_SECOND_OUT (VE_ENGINE_DEC_H265 + 0x88)
+#define VE_DEC_H265_10BIT_CONFIGURE (VE_ENGINE_DEC_H265 + 0x8c)
+
#define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \
SHIFT_AND_MASK_BITS(a, 31, 24)
#define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -100,7 +100,7 @@ static struct cedrus_format *cedrus_find
return &cedrus_formats[i];
}
-void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
+void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended)
{
unsigned int width = pix_fmt->width;
unsigned int height = pix_fmt->height;
@@ -155,6 +155,17 @@ void cedrus_prepare_format(struct v4l2_p
break;
}
+ if (extended) {
+ unsigned int extra_size;
+
+ extra_size = DIV_ROUND_UP(pix_fmt->width, 4);
+ extra_size = ALIGN(extra_size, 32);
+ extra_size *= ALIGN(pix_fmt->height, 16) * 3;
+ extra_size /= 2;
+
+ sizeimage += extra_size;
+ }
+
pix_fmt->width = width;
pix_fmt->height = height;
@@ -247,17 +258,27 @@ static int cedrus_try_fmt_vid_cap(struct
struct cedrus_ctx *ctx = cedrus_file2ctx(file);
struct cedrus_dev *dev = ctx->dev;
struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
+ const struct v4l2_ctrl_hevc_sps *sps;
struct cedrus_format *fmt =
cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST,
dev->capabilities);
+ int extended;
if (!fmt)
return -EINVAL;
+ sps = cedrus_find_control_data(ctx, V4L2_CID_STATELESS_HEVC_SPS);
+
+ /* The 10-bitHEVC decoder needs extra size on the output buffer. */
+ extended = ctx->src_fmt.pixelformat == V4L2_PIX_FMT_HEVC_SLICE &&
+ sps->bit_depth_luma_minus8 == 2;
+
pix_fmt->pixelformat = fmt->pixelformat;
pix_fmt->width = ctx->src_fmt.width;
pix_fmt->height = ctx->src_fmt.height;
- cedrus_prepare_format(pix_fmt);
+
+ pix_fmt->pixelformat = fmt->pixelformat;
+ cedrus_prepare_format(pix_fmt, extended);
return 0;
}
@@ -275,8 +296,7 @@ static int cedrus_try_fmt_vid_out(struct
if (!fmt)
return -EINVAL;
- pix_fmt->pixelformat = fmt->pixelformat;
- cedrus_prepare_format(pix_fmt);
+ cedrus_prepare_format(pix_fmt, 0);
return 0;
}
@@ -357,7 +377,7 @@ static int cedrus_s_fmt_vid_out(struct f
ctx->dst_fmt.quantization = f->fmt.pix.quantization;
ctx->dst_fmt.width = ctx->src_fmt.width;
ctx->dst_fmt.height = ctx->src_fmt.height;
- cedrus_prepare_format(&ctx->dst_fmt);
+ cedrus_prepare_format(&ctx->dst_fmt, 0);
return 0;
}
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h
@@ -26,6 +26,6 @@ extern const struct v4l2_ioctl_ops cedru
int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq);
-void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt);
+void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended);
#endif