From 7d5c9f31a2d28e932ddeee750da7af442906c65b Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 6 Sep 2024 23:17:24 +0200 Subject: media: cedrus: Add decoder reset before each run 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 --- drivers/staging/media/sunxi/cedrus/cedrus_dec.c | 1 + drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 15 +++++++++++++++ drivers/staging/media/sunxi/cedrus/cedrus_hw.h | 1 + drivers/staging/media/sunxi/cedrus/cedrus_regs.h | 10 ++++++++++ 4 files changed, 27 insertions(+) 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) -- cgit v1.2.3