* [Allwinner] Add analogue audio to H6, enable Cedrus, remove deprecated patches, adjust config * Cleanup
111 lines
3.9 KiB
Diff
111 lines
3.9 KiB
Diff
|
|
From b4e33e09e7938513bfaba034731c7e84e73c6a5b Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 09:27:51 +0200
|
|
Subject: [PATCH] media: cedrus: Fix decoding for some H264 videos
|
|
|
|
It seems that for some H264 videos at least one bitstream parsing
|
|
trigger must be called in order to be decoded correctly. There is no
|
|
explanation why this helps, but it was observed that two sample videos
|
|
with this fix are now decoded correctly and there is no regression with
|
|
others.
|
|
|
|
Acked-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
|
---
|
|
.../staging/media/sunxi/cedrus/cedrus_h264.c | 30 +++++++++++++++++--
|
|
.../staging/media/sunxi/cedrus/cedrus_regs.h | 3 ++
|
|
2 files changed, 30 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index cd85668f9c80..db336449c4f2 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -6,6 +6,7 @@
|
|
* Copyright (c) 2018 Bootlin
|
|
*/
|
|
|
|
+#include <linux/delay.h>
|
|
#include <linux/types.h>
|
|
|
|
#include <media/videobuf2-dma-contig.h>
|
|
@@ -289,6 +290,28 @@ static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx,
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+ * It turns out that using VE_H264_VLD_OFFSET to skip bits is not reliable. In
|
|
+ * rare cases frame is not decoded correctly. However, setting offset to 0 and
|
|
+ * skipping appropriate amount of bits with flush bits trigger always works.
|
|
+ */
|
|
+static void cedrus_skip_bits(struct cedrus_dev *dev, int num)
|
|
+{
|
|
+ int count = 0;
|
|
+
|
|
+ while (count < num) {
|
|
+ int tmp = min(num - count, 32);
|
|
+
|
|
+ cedrus_write(dev, VE_H264_TRIGGER_TYPE,
|
|
+ VE_H264_TRIGGER_TYPE_FLUSH_BITS |
|
|
+ VE_H264_TRIGGER_TYPE_N_BITS(tmp));
|
|
+ while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VLD_BUSY)
|
|
+ udelay(1);
|
|
+
|
|
+ count += tmp;
|
|
+ }
|
|
+}
|
|
+
|
|
static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
struct cedrus_run *run)
|
|
{
|
|
@@ -299,14 +322,13 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
struct vb2_buffer *src_buf = &run->src->vb2_buf;
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
dma_addr_t src_buf_addr;
|
|
- u32 offset = slice->header_bit_size;
|
|
- u32 len = (slice->size * 8) - offset;
|
|
+ u32 len = slice->size * 8;
|
|
unsigned int pic_width_in_mbs;
|
|
bool mbaff_pic;
|
|
u32 reg;
|
|
|
|
cedrus_write(dev, VE_H264_VLD_LEN, len);
|
|
- cedrus_write(dev, VE_H264_VLD_OFFSET, offset);
|
|
+ cedrus_write(dev, VE_H264_VLD_OFFSET, 0);
|
|
|
|
src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
|
|
cedrus_write(dev, VE_H264_VLD_END,
|
|
@@ -325,6 +347,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|
cedrus_write(dev, VE_H264_TRIGGER_TYPE,
|
|
VE_H264_TRIGGER_TYPE_INIT_SWDEC);
|
|
|
|
+ cedrus_skip_bits(dev, slice->header_bit_size);
|
|
+
|
|
if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
|
|
(slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
|
|
slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
index 6fc28d21a6c7..4275a307d282 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
@@ -541,13 +541,16 @@
|
|
VE_H264_CTRL_SLICE_DECODE_INT)
|
|
|
|
#define VE_H264_TRIGGER_TYPE 0x224
|
|
+#define VE_H264_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8)
|
|
#define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE (8 << 0)
|
|
#define VE_H264_TRIGGER_TYPE_INIT_SWDEC (7 << 0)
|
|
+#define VE_H264_TRIGGER_TYPE_FLUSH_BITS (3 << 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_VLD_BUSY BIT(8)
|
|
|
|
#define VE_H264_STATUS_INT_MASK VE_H264_CTRL_INT_MASK
|
|
|
|
--
|
|
2.24.0
|