aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Kocialkowski2024-09-06 23:17:24 +0200
committerPaul Kocialkowski2024-09-06 23:17:24 +0200
commit7d5c9f31a2d28e932ddeee750da7af442906c65b (patch)
treedb2c8f052c7e394cb9c76a312ca3a4603d580426
parent5acc2f557495298391ee585237dfe2fd69b5024e (diff)
media: cedrus: Add decoder reset before each runsunxi/cedrus/jpeg-nv16
This reset is internal to the video engine and clears registers for all decode engines (regardless of which one is currently selected). It might also reset some internal logic states. Introduce this for overall safety in case of side-effets caused by consecutive use of an engine(e.g. when not clearing some registers). Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_dec.c1
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.c15
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.h1
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_regs.h10
4 files changed, 27 insertions, 0 deletions
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index fbbf9e6f0f50..31a1e60a3105 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -92,6 +92,7 @@ void cedrus_device_run(void *priv)
v4l2_m2m_buf_copy_metadata(run.src, run.dst, true);
+ cedrus_engine_reset(dev);
cedrus_dst_format_set(dev, &ctx->dst_fmt);
error = ctx->current_codec->setup(ctx, &run);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 17e91bb5c26a..735437480706 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -31,6 +31,21 @@
#include "cedrus_hw.h"
#include "cedrus_regs.h"
+void cedrus_engine_reset(struct cedrus_dev *dev)
+{
+ u32 reg, flags;
+ int ret;
+
+ /* Wait for the cache and memory access to idle. */
+ flags = VE_RESET_SYNC_IDLE | VE_RESET_CACHE_SYNC_IDLE;
+ readl_poll_timeout_atomic(dev->base + VE_RESET, reg,
+ (reg & flags) == flags, 1, 100);
+
+ /* Reset anyway if busy for 100 ms. */
+ cedrus_write(dev, VE_RESET, reg | VE_RESET_DECODER);
+ cedrus_write(dev, VE_RESET, reg);
+}
+
int cedrus_engine_enable(struct cedrus_ctx *ctx)
{
u32 reg = 0;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index 6f1e701b1ea8..8b7d325d2b69 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -16,6 +16,7 @@
#ifndef _CEDRUS_HW_H_
#define _CEDRUS_HW_H_
+void cedrus_engine_reset(struct cedrus_dev *dev);
int cedrus_engine_enable(struct cedrus_ctx *ctx);
void cedrus_engine_disable(struct cedrus_dev *dev);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 94667cab3727..85629f31c727 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -46,6 +46,16 @@
#define VE_MODE_DEC_H264 (0x01 << 0)
#define VE_MODE_DEC_MPEG (0x00 << 0)
+#define VE_RESET 0x04
+
+#define VE_RESET_ENCODER_MASK BIT(25)
+#define VE_RESET_ENCODER BIT(24)
+#define VE_RESET_DECODER_MASK BIT(17)
+#define VE_RESET_DECODER BIT(16)
+#define VE_RESET_SYNC_IDLE BIT(9)
+#define VE_RESET_CACHE_SYNC_IDLE BIT(8)
+#define VE_RESET_RESET BIT(0)
+
#define VE_BUF_CTRL 0x50
#define VE_BUF_CTRL_INTRAPRED_EXT_RAM (0x02 << 2)