lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250527150043.174415-1-detlev.casanova@collabora.com>
Date: Tue, 27 May 2025 11:00:22 -0400
From: Detlev Casanova <detlev.casanova@...labora.com>
To: linux-kernel@...r.kernel.org
Cc: Ezequiel Garcia <ezequiel@...guardiasur.com.ar>,
	Mauro Carvalho Chehab <mchehab@...nel.org>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	linux-media@...r.kernel.org,
	linux-rockchip@...ts.infradead.org,
	linux-staging@...ts.linux.dev,
	kernel@...labora.com,
	Detlev Casanova <detlev.casanova@...labora.com>
Subject: [PATCH] media: rkvdec: Switch to using structs instead of writel

In an effort to merge the rkvdec2 driver [1] with this one, switch from
writel() calls to using structs to represent the register mappings.

This is done in order to have all supported decoders use the same format
in the future and ease reading of the code.

Using structs also improves stability as the hardware is tested and
validated downstream using a similar method.
It was noticed, on decoders, that:
 - Some registers require to be writen in increasing order [2]
 - Some registers, even if unrelated, need to be written to their reset
   values (it was the case here for axi_ddr_[rw]data).

Using structs can also help improving performance later when, e.g.
multicore support is added on RK3588.

Performance seems to be slightly improved, but at least, not made worse.
Running fluster's JVT-AVC_V1 test suite with GStreamer on the Radxa ROCK
PI 4 SE gives the following times:

Before this patch:

- --jobs 1: Ran 129/135 tests successfully               in 77.167 secs
- --jobs 6: Ran 129/135 tests successfully               in 23.046 secs

With this patch:
- --jobs 1: Ran 129/135 tests successfully               in 70.698 secs
- --jobs 6: Ran 129/135 tests successfully               in 22.917 secs

This also shows that the fluster score hasn't changed.

[1]: https://lore.kernel.org/all/20250325213303.826925-1-detlev.casanova@collabora.com/
[2]: https://lore.kernel.org/all/20200127143009.15677-5-andrzej.p@collabora.com/

Signed-off-by: Detlev Casanova <detlev.casanova@...labora.com>
---
 drivers/staging/media/rkvdec/rkvdec-h264.c | 168 +++---
 drivers/staging/media/rkvdec/rkvdec-regs.h | 567 ++++++++++++++-------
 drivers/staging/media/rkvdec/rkvdec-vp9.c  | 239 ++++-----
 drivers/staging/media/rkvdec/rkvdec.c      |   1 -
 4 files changed, 559 insertions(+), 416 deletions(-)

diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
index 4fc167b42cf0c..85ca4a8967ceb 100644
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
@@ -115,6 +115,7 @@ struct rkvdec_h264_run {
 struct rkvdec_h264_ctx {
 	struct rkvdec_aux_buf priv_tbl;
 	struct rkvdec_h264_reflists reflists;
+	struct rkvdec_regs regs;
 };
 
 #define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n,		\
@@ -839,46 +840,43 @@ static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx,
 	       sizeof(scaling->scaling_list_8x8));
 }
 
-/*
- * dpb poc related registers table
- */
-static const u32 poc_reg_tbl_top_field[16] = {
-	RKVDEC_REG_H264_POC_REFER0(0),
-	RKVDEC_REG_H264_POC_REFER0(2),
-	RKVDEC_REG_H264_POC_REFER0(4),
-	RKVDEC_REG_H264_POC_REFER0(6),
-	RKVDEC_REG_H264_POC_REFER0(8),
-	RKVDEC_REG_H264_POC_REFER0(10),
-	RKVDEC_REG_H264_POC_REFER0(12),
-	RKVDEC_REG_H264_POC_REFER0(14),
-	RKVDEC_REG_H264_POC_REFER1(1),
-	RKVDEC_REG_H264_POC_REFER1(3),
-	RKVDEC_REG_H264_POC_REFER1(5),
-	RKVDEC_REG_H264_POC_REFER1(7),
-	RKVDEC_REG_H264_POC_REFER1(9),
-	RKVDEC_REG_H264_POC_REFER1(11),
-	RKVDEC_REG_H264_POC_REFER1(13),
-	RKVDEC_REG_H264_POC_REFER2(0)
-};
+static void set_poc_reg(struct rkvdec_regs *regs, uint32_t poc, int id, bool bottom)
+{
+	if (!bottom) {
+		switch (id) {
+		case 0 ... 7:
+			regs->h264.ref0_14_poc[id * 2] = poc;
+			break;
+		case 8 ... 14:
+			regs->h264.ref15_29_poc[(id - 8) * 2 + 1] = poc;
+			break;
+		case 15:
+			regs->h264.ref30_poc = poc;
+			break;
+		}
+	} else {
+		switch (id) {
+		case 0 ... 6:
+			regs->h264.ref0_14_poc[id * 2 + 1] = poc;
+			break;
+		case 7 ... 14:
+			regs->h264.ref15_29_poc[(id - 7) * 2] = poc;
+			break;
+		case 15:
+			regs->h264.ref31_poc = poc;
+			break;
+		}
+	}
+}
 
-static const u32 poc_reg_tbl_bottom_field[16] = {
-	RKVDEC_REG_H264_POC_REFER0(1),
-	RKVDEC_REG_H264_POC_REFER0(3),
-	RKVDEC_REG_H264_POC_REFER0(5),
-	RKVDEC_REG_H264_POC_REFER0(7),
-	RKVDEC_REG_H264_POC_REFER0(9),
-	RKVDEC_REG_H264_POC_REFER0(11),
-	RKVDEC_REG_H264_POC_REFER0(13),
-	RKVDEC_REG_H264_POC_REFER1(0),
-	RKVDEC_REG_H264_POC_REFER1(2),
-	RKVDEC_REG_H264_POC_REFER1(4),
-	RKVDEC_REG_H264_POC_REFER1(6),
-	RKVDEC_REG_H264_POC_REFER1(8),
-	RKVDEC_REG_H264_POC_REFER1(10),
-	RKVDEC_REG_H264_POC_REFER1(12),
-	RKVDEC_REG_H264_POC_REFER1(14),
-	RKVDEC_REG_H264_POC_REFER2(1)
-};
+static void rkvdec_write_regs(struct rkvdec_dev *dev, struct rkvdec_regs *regs)
+{
+#ifdef CONFIG_ARM64
+	__iowrite32_copy(dev->regs, regs, sizeof(*regs) / 4);
+#else
+	memcpy_toio(dev->regs, regs, sizeof(*regs));
+#endif
+}
 
 static void config_registers(struct rkvdec_ctx *ctx,
 			     struct rkvdec_h264_run *run)
@@ -893,6 +891,7 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	struct vb2_v4l2_buffer *src_buf = run->base.bufs.src;
 	struct vb2_v4l2_buffer *dst_buf = run->base.bufs.dst;
 	const struct v4l2_format *f;
+	struct rkvdec_regs *regs = &h264_ctx->regs;
 	dma_addr_t rlc_addr;
 	dma_addr_t refer_addr;
 	u32 rlc_len;
@@ -902,10 +901,11 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	u32 yuv_virstride = 0;
 	u32 offset;
 	dma_addr_t dst_addr;
-	u32 reg, i;
+	u32 i;
+
+	memset(regs, 0, sizeof(*regs));
 
-	reg = RKVDEC_MODE(RKVDEC_MODE_H264);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL);
+	regs->common.reg02.dec_mode = RKVDEC_MODE_H264;
 
 	f = &ctx->decoded_fmt;
 	dst_fmt = &f->fmt.pix_mp;
@@ -920,39 +920,35 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	else if (sps->chroma_format_idc == 2)
 		yuv_virstride += 2 * y_virstride;
 
-	reg = RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) |
-	      RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) |
-	      RKVDEC_SLICE_NUM_HIGHBIT |
-	      RKVDEC_SLICE_NUM_LOWBITS(0x7ff);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR);
+	regs->common.reg03.uv_hor_virstride = hor_virstride / 16;
+	regs->common.reg03.y_hor_virstride = hor_virstride / 16;
+	regs->common.reg03.slice_num_highbit = 1;
+	regs->common.reg03.slice_num_lowbits = 0x7ff;
 
 	/* config rlc base address */
 	rlc_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
-	writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
-	writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_RLCWRITE_BASE);
+	regs->common.strm_rlc_base = rlc_addr;
+	regs->h264.rlcwrite_base = rlc_addr;
 
 	rlc_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
-	reg = RKVDEC_STRM_LEN(rlc_len);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN);
+	regs->common.stream_len = rlc_len;
 
 	/* config cabac table */
 	offset = offsetof(struct rkvdec_h264_priv_tbl, cabac_table);
-	writel_relaxed(priv_start_addr + offset,
-		       rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
+	regs->common.cabactbl_base = priv_start_addr + offset;
 
 	/* config output base address */
 	dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-	writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
+	regs->common.decout_base = dst_addr;
 
-	reg = RKVDEC_Y_VIRSTRIDE(y_virstride / 16);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
+	regs->common.reg08.y_virstride = y_virstride / 16;
 
-	reg = RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
+	regs->common.reg09.yuv_virstride = yuv_virstride / 16;
 
 	/* config ref pic address & poc */
 	for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
 		struct vb2_buffer *vb_buf = run->ref_buf[i];
+		struct ref_base *base;
 
 		/*
 		 * If a DPB entry is unused or invalid, address of current destination
@@ -962,54 +958,36 @@ static void config_registers(struct rkvdec_ctx *ctx,
 			vb_buf = &dst_buf->vb2_buf;
 		refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0);
 
-		if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
-			refer_addr |= RKVDEC_COLMV_USED_FLAG_REF;
-		if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)
-			refer_addr |= RKVDEC_FIELD_REF;
-
-		if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF)
-			refer_addr |= RKVDEC_TOPFIELD_USED_REF;
-		if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
-			refer_addr |= RKVDEC_BOTFIELD_USED_REF;
-
-		writel_relaxed(dpb[i].top_field_order_cnt,
-			       rkvdec->regs +  poc_reg_tbl_top_field[i]);
-		writel_relaxed(dpb[i].bottom_field_order_cnt,
-			       rkvdec->regs + poc_reg_tbl_bottom_field[i]);
-
 		if (i < V4L2_H264_NUM_DPB_ENTRIES - 1)
-			writel_relaxed(refer_addr,
-				       rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i));
+			base = &regs->h264.ref0_14_base[i];
 		else
-			writel_relaxed(refer_addr,
-				       rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15);
-	}
+			base = &regs->h264.ref15_base;
 
-	reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0);
+		base->field_ref = !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD);
+		base->colmv_used_flag_ref = !!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE);
+		base->topfield_used_ref = !!(dpb[i].fields & V4L2_H264_TOP_FIELD_REF);
+		base->botfield_used_ref = !!(dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF);
+		base->base_addr = refer_addr >> 4;
 
-	reg = RKVDEC_CUR_POC(dec_params->bottom_field_order_cnt);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC1);
+		set_poc_reg(regs, dpb[i].top_field_order_cnt, i, false);
+		set_poc_reg(regs, dpb[i].bottom_field_order_cnt, i, true);
+	}
+
+	regs->h264.cur_poc = dec_params->top_field_order_cnt;
+	regs->h264.cur_poc1 = dec_params->bottom_field_order_cnt;
 
 	/* config hw pps address */
 	offset = offsetof(struct rkvdec_h264_priv_tbl, param_set);
-	writel_relaxed(priv_start_addr + offset,
-		       rkvdec->regs + RKVDEC_REG_PPS_BASE);
+	regs->h264.pps_base = priv_start_addr + offset;
 
 	/* config hw rps address */
 	offset = offsetof(struct rkvdec_h264_priv_tbl, rps);
-	writel_relaxed(priv_start_addr + offset,
-		       rkvdec->regs + RKVDEC_REG_RPS_BASE);
-
-	reg = RKVDEC_AXI_DDR_RDATA(0);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA);
-
-	reg = RKVDEC_AXI_DDR_WDATA(0);
-	writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA);
+	regs->h264.rps_base = priv_start_addr + offset;
 
 	offset = offsetof(struct rkvdec_h264_priv_tbl, err_info);
-	writel_relaxed(priv_start_addr + offset,
-		       rkvdec->regs + RKVDEC_REG_H264_ERRINFO_BASE);
+	regs->h264.errorinfo_base = priv_start_addr + offset;
+
+	rkvdec_write_regs(rkvdec, regs);
 }
 
 #define RKVDEC_H264_MAX_DEPTH_IN_BYTES		2
@@ -1162,8 +1140,6 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
 
 	schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000));
 
-	writel(0, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
-	writel(0, rkvdec->regs + RKVDEC_REG_H264_ERR_E);
 	writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
 	writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
 
diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h
index 15b9bee92016c..541c5cb6f4bb1 100644
--- a/drivers/staging/media/rkvdec/rkvdec-regs.h
+++ b/drivers/staging/media/rkvdec/rkvdec-regs.h
@@ -3,7 +3,12 @@
 #ifndef RKVDEC_REGS_H_
 #define RKVDEC_REGS_H_
 
-/* rkvcodec registers */
+#include <linux/types.h>
+
+/*
+ * REG_INTERRUPT is accessed via writel to enable the decoder after
+ * configuring it and clear interrupt strmd_error_status
+ */
 #define RKVDEC_REG_INTERRUPT				0x004
 #define RKVDEC_INTERRUPT_DEC_E				BIT(0)
 #define RKVDEC_CONFIG_DEC_CLK_GATE_E			BIT(1)
@@ -29,195 +34,381 @@
 #define RKVDEC_FORCE_SOFTRESET_VALID			BIT(21)
 #define RKVDEC_SOFTRESET_RDY				BIT(22)
 
-#define RKVDEC_REG_SYSCTRL				0x008
-#define RKVDEC_IN_ENDIAN				BIT(0)
-#define RKVDEC_IN_SWAP32_E				BIT(1)
-#define RKVDEC_IN_SWAP64_E				BIT(2)
-#define RKVDEC_STR_ENDIAN				BIT(3)
-#define RKVDEC_STR_SWAP32_E				BIT(4)
-#define RKVDEC_STR_SWAP64_E				BIT(5)
-#define RKVDEC_OUT_ENDIAN				BIT(6)
-#define RKVDEC_OUT_SWAP32_E				BIT(7)
-#define RKVDEC_OUT_CBCR_SWAP				BIT(8)
-#define RKVDEC_RLC_MODE_DIRECT_WRITE			BIT(10)
-#define RKVDEC_RLC_MODE					BIT(11)
-#define RKVDEC_STRM_START_BIT(x)			(((x) & 0x7f) << 12)
-#define RKVDEC_MODE(x)					(((x) & 0x03) << 20)
+/*
+ * Cache configuration is not covered in the rang of the register struct
+ */
+#define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND		0x410
+#define RKVDEC_REG_PREF_CHR_CACHE_COMMAND		0x450
+
+/*
+ * Define the mode values
+ */
 #define RKVDEC_MODE_H264				1
 #define RKVDEC_MODE_VP9					2
-#define RKVDEC_RPS_MODE					BIT(24)
-#define RKVDEC_STRM_MODE				BIT(25)
-#define RKVDEC_H264_STRM_LASTPKT			BIT(26)
-#define RKVDEC_H264_FIRSTSLICE_FLAG			BIT(27)
-#define RKVDEC_H264_FRAME_ORSLICE			BIT(28)
-#define RKVDEC_BUSPR_SLOT_DIS				BIT(29)
-
-#define RKVDEC_REG_PICPAR				0x00C
-#define RKVDEC_Y_HOR_VIRSTRIDE(x)			((x) & 0x1ff)
-#define RKVDEC_SLICE_NUM_HIGHBIT			BIT(11)
-#define RKVDEC_UV_HOR_VIRSTRIDE(x)			(((x) & 0x1ff) << 12)
-#define RKVDEC_SLICE_NUM_LOWBITS(x)			(((x) & 0x7ff) << 21)
-
-#define RKVDEC_REG_STRM_RLC_BASE			0x010
-
-#define RKVDEC_REG_STRM_LEN				0x014
-#define RKVDEC_STRM_LEN(x)				((x) & 0x7ffffff)
-
-#define RKVDEC_REG_CABACTBL_PROB_BASE			0x018
-#define RKVDEC_REG_DECOUT_BASE				0x01C
-
-#define RKVDEC_REG_Y_VIRSTRIDE				0x020
-#define RKVDEC_Y_VIRSTRIDE(x)				((x) & 0xfffff)
-
-#define RKVDEC_REG_YUV_VIRSTRIDE			0x024
-#define RKVDEC_YUV_VIRSTRIDE(x)				((x) & 0x1fffff)
-#define RKVDEC_REG_H264_BASE_REFER(i)			(((i) * 0x04) + 0x028)
-
-#define RKVDEC_REG_H264_BASE_REFER15			0x0C0
-#define RKVDEC_FIELD_REF				BIT(0)
-#define RKVDEC_TOPFIELD_USED_REF			BIT(1)
-#define RKVDEC_BOTFIELD_USED_REF			BIT(2)
-#define RKVDEC_COLMV_USED_FLAG_REF			BIT(3)
-
-#define RKVDEC_REG_VP9_LAST_FRAME_BASE			0x02c
-#define RKVDEC_REG_VP9_GOLDEN_FRAME_BASE		0x030
-#define RKVDEC_REG_VP9_ALTREF_FRAME_BASE		0x034
-
-#define RKVDEC_REG_VP9_CPRHEADER_OFFSET			0x028
-#define RKVDEC_VP9_CPRHEADER_OFFSET(x)			((x) & 0xffff)
-
-#define RKVDEC_REG_VP9_REFERLAST_BASE			0x02C
-#define RKVDEC_REG_VP9_REFERGOLDEN_BASE			0x030
-#define RKVDEC_REG_VP9_REFERALFTER_BASE			0x034
-
-#define RKVDEC_REG_VP9COUNT_BASE			0x038
-#define RKVDEC_VP9COUNT_UPDATE_EN			BIT(0)
-
-#define RKVDEC_REG_VP9_SEGIDLAST_BASE			0x03C
-#define RKVDEC_REG_VP9_SEGIDCUR_BASE			0x040
-#define RKVDEC_REG_VP9_FRAME_SIZE(i)			((i) * 0x04 + 0x044)
-#define RKVDEC_VP9_FRAMEWIDTH(x)			(((x) & 0xffff) << 0)
-#define RKVDEC_VP9_FRAMEHEIGHT(x)			(((x) & 0xffff) << 16)
-
-#define RKVDEC_VP9_SEGID_GRP(i)				((i) * 0x04 + 0x050)
-#define RKVDEC_SEGID_ABS_DELTA(x)			((x) & 0x1)
-#define RKVDEC_SEGID_FRAME_QP_DELTA_EN(x)		(((x) & 0x1) << 1)
-#define RKVDEC_SEGID_FRAME_QP_DELTA(x)			(((x) & 0x1ff) << 2)
-#define RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(x)	(((x) & 0x1) << 11)
-#define RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(x)		(((x) & 0x7f) << 12)
-#define RKVDEC_SEGID_REFERINFO_EN(x)			(((x) & 0x1) << 19)
-#define RKVDEC_SEGID_REFERINFO(x)			(((x) & 0x03) << 20)
-#define RKVDEC_SEGID_FRAME_SKIP_EN(x)			(((x) & 0x1) << 22)
-
-#define RKVDEC_VP9_CPRHEADER_CONFIG			0x070
-#define RKVDEC_VP9_TX_MODE(x)				((x) & 0x07)
-#define RKVDEC_VP9_FRAME_REF_MODE(x)			(((x) & 0x03) << 3)
-
-#define RKVDEC_VP9_REF_SCALE(i)				((i) * 0x04 + 0x074)
-#define RKVDEC_VP9_REF_HOR_SCALE(x)			((x) & 0xffff)
-#define RKVDEC_VP9_REF_VER_SCALE(x)			(((x) & 0xffff) << 16)
-
-#define RKVDEC_VP9_REF_DELTAS_LASTFRAME			0x080
-#define RKVDEC_REF_DELTAS_LASTFRAME(pos, val)		(((val) & 0x7f) << ((pos) * 7))
-
-#define RKVDEC_VP9_INFO_LASTFRAME			0x084
-#define RKVDEC_MODE_DELTAS_LASTFRAME(pos, val)		(((val) & 0x7f) << ((pos) * 7))
-#define RKVDEC_SEG_EN_LASTFRAME				BIT(16)
-#define RKVDEC_LAST_SHOW_FRAME				BIT(17)
-#define RKVDEC_LAST_INTRA_ONLY				BIT(18)
-#define RKVDEC_LAST_WIDHHEIGHT_EQCUR			BIT(19)
-#define RKVDEC_COLOR_SPACE_LASTKEYFRAME(x)		(((x) & 0x07) << 20)
-
-#define RKVDEC_VP9_INTERCMD_BASE			0x088
-
-#define RKVDEC_VP9_INTERCMD_NUM				0x08C
-#define RKVDEC_INTERCMD_NUM(x)				((x) & 0xffffff)
-
-#define RKVDEC_VP9_LASTTILE_SIZE			0x090
-#define RKVDEC_LASTTILE_SIZE(x)				((x) & 0xffffff)
-
-#define RKVDEC_VP9_HOR_VIRSTRIDE(i)			((i) * 0x04 + 0x094)
-#define RKVDEC_HOR_Y_VIRSTRIDE(x)			((x) & 0x1ff)
-#define RKVDEC_HOR_UV_VIRSTRIDE(x)			(((x) & 0x1ff) << 16)
-
-#define RKVDEC_REG_H264_POC_REFER0(i)			(((i) * 0x04) + 0x064)
-#define RKVDEC_REG_H264_POC_REFER1(i)			(((i) * 0x04) + 0x0C4)
-#define RKVDEC_REG_H264_POC_REFER2(i)			(((i) * 0x04) + 0x120)
-#define RKVDEC_POC_REFER(x)				((x) & 0xffffffff)
-
-#define RKVDEC_REG_CUR_POC0				0x0A0
-#define RKVDEC_REG_CUR_POC1				0x128
-#define RKVDEC_CUR_POC(x)				((x) & 0xffffffff)
-
-#define RKVDEC_REG_RLCWRITE_BASE			0x0A4
-#define RKVDEC_REG_PPS_BASE				0x0A8
-#define RKVDEC_REG_RPS_BASE				0x0AC
-
-#define RKVDEC_REG_STRMD_ERR_EN				0x0B0
-#define RKVDEC_STRMD_ERR_EN(x)				((x) & 0xffffffff)
-
-#define RKVDEC_REG_STRMD_ERR_STA			0x0B4
-#define RKVDEC_STRMD_ERR_STA(x)				((x) & 0xfffffff)
-#define RKVDEC_COLMV_ERR_REF_PICIDX(x)			(((x) & 0x0f) << 28)
-
-#define RKVDEC_REG_STRMD_ERR_CTU			0x0B8
-#define RKVDEC_STRMD_ERR_CTU(x)				((x) & 0xff)
-#define RKVDEC_STRMD_ERR_CTU_YOFFSET(x)			(((x) & 0xff) << 8)
-#define RKVDEC_STRMFIFO_SPACE2FULL(x)			(((x) & 0x7f) << 16)
-#define RKVDEC_VP9_ERR_EN_CTU0				BIT(24)
-
-#define RKVDEC_REG_SAO_CTU_POS				0x0BC
-#define RKVDEC_SAOWR_XOFFSET(x)				((x) & 0x1ff)
-#define RKVDEC_SAOWR_YOFFSET(x)				(((x) & 0x3ff) << 16)
-
-#define RKVDEC_VP9_LAST_FRAME_YSTRIDE			0x0C0
-#define RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE			0x0C4
-#define RKVDEC_VP9_ALTREF_FRAME_YSTRIDE			0x0C8
-#define RKVDEC_VP9_REF_YSTRIDE(x)			(((x) & 0xfffff) << 0)
-
-#define RKVDEC_VP9_LAST_FRAME_YUVSTRIDE			0x0CC
-#define RKVDEC_VP9_REF_YUVSTRIDE(x)			(((x) & 0x1fffff) << 0)
-
-#define RKVDEC_VP9_REF_COLMV_BASE			0x0D0
-
-#define RKVDEC_REG_PERFORMANCE_CYCLE			0x100
-#define RKVDEC_PERFORMANCE_CYCLE(x)			((x) & 0xffffffff)
-
-#define RKVDEC_REG_AXI_DDR_RDATA			0x104
-#define RKVDEC_AXI_DDR_RDATA(x)				((x) & 0xffffffff)
-
-#define RKVDEC_REG_AXI_DDR_WDATA			0x108
-#define RKVDEC_AXI_DDR_WDATA(x)				((x) & 0xffffffff)
-
-#define RKVDEC_REG_FPGADEBUG_RESET			0x10C
-#define RKVDEC_BUSIFD_RESETN				BIT(0)
-#define RKVDEC_CABAC_RESETN				BIT(1)
-#define RKVDEC_DEC_CTRL_RESETN				BIT(2)
-#define RKVDEC_TRANSD_RESETN				BIT(3)
-#define RKVDEC_INTRA_RESETN				BIT(4)
-#define RKVDEC_INTER_RESETN				BIT(5)
-#define RKVDEC_RECON_RESETN				BIT(6)
-#define RKVDEC_FILER_RESETN				BIT(7)
 
-#define RKVDEC_REG_PERFORMANCE_SEL			0x110
-#define RKVDEC_PERF_SEL_CNT0(x)				((x) & 0x3f)
-#define RKVDEC_PERF_SEL_CNT1(x)				(((x) & 0x3f) << 8)
-#define RKVDEC_PERF_SEL_CNT2(x)				(((x) & 0x3f) << 16)
-
-#define RKVDEC_REG_PERFORMANCE_CNT(i)			((i) * 0x04 + 0x114)
-#define RKVDEC_PERF_CNT(x)				((x) & 0xffffffff)
-
-#define RKVDEC_REG_H264_ERRINFO_BASE			0x12C
-
-#define RKVDEC_REG_H264_ERRINFO_NUM			0x130
-#define RKVDEC_SLICEDEC_NUM(x)				((x) & 0x3fff)
-#define RKVDEC_STRMD_DECT_ERR_FLAG			BIT(15)
-#define RKVDEC_ERR_PKT_NUM(x)				(((x) & 0x3fff) << 16)
-
-#define RKVDEC_REG_H264_ERR_E				0x134
-#define RKVDEC_H264_ERR_EN_HIGHBITS(x)			((x) & 0x3fffffff)
-
-#define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND		0x410
-#define RKVDEC_REG_PREF_CHR_CACHE_COMMAND		0x450
+/* rkvcodec registers */
+struct rkvdec_common_regs {
+	struct rkvdec_id {
+		u32 minor_ver	: 8;
+		u32 level	: 1;
+		u32 dec_support	: 3;
+		u32 profile	: 1;
+		u32 reserved0	: 1;
+		u32 codec_flag	: 1;
+		u32 reserved1	: 1;
+		u32 prod_num	: 16;
+	} reg00;
+
+	struct rkvdec_int {
+		u32 dec_e			: 1;
+		u32 dec_clkgate_e		: 1;
+		u32 reserved0			: 1;
+		u32 timeout_mode		: 1;
+		u32 dec_irq_dis			: 1;
+		u32 dec_timeout_e		: 1;
+		u32 buf_empty_en		: 1;
+		u32 stmerror_waitdecfifo_empty	: 1;
+		u32 dec_irq			: 1;
+		u32 dec_irq_raw			: 1;
+		u32 reserved2			: 2;
+		u32 dec_rdy_sta			: 1;
+		u32 dec_bus_sta			: 1;
+		u32 dec_error_sta		: 1;
+		u32 dec_timeout_sta		: 1;
+		u32 dec_empty_sta		: 1;
+		u32 colmv_ref_error_sta		: 1;
+		u32 cabu_end_sta		: 1;
+		u32 h264orvp9_error_mode	: 1;
+		u32 softrst_en_p		: 1;
+		u32 force_softreset_valid	: 1;
+		u32 softreset_rdy		: 1;
+		u32 reserved1			: 9;
+	} reg01;
+
+	struct rkvdec_sysctrl {
+		u32 in_endian			: 1;
+		u32 in_swap32_e			: 1;
+		u32 in_swap64_e			: 1;
+		u32 str_endian			: 1;
+		u32 str_swap32_e		: 1;
+		u32 str_swap64_e		: 1;
+		u32 out_endian			: 1;
+		u32 out_swap32_e		: 1;
+		u32 out_cbcr_swap		: 1;
+		u32 reserved0			: 1;
+		u32 rlc_mode_direct_write	: 1;
+		u32 rlc_mode			: 1;
+		u32 strm_start_bit		: 7;
+		u32 reserved1			: 1;
+		u32 dec_mode			: 2;
+		u32 reserved2			: 2;
+		u32 rps_mode			: 1;
+		u32 stream_mode			: 1;
+		u32 stream_lastpacket		: 1;
+		u32 firstslice_flag		: 1;
+		u32 frame_orslice		: 1;
+		u32 buspr_slot_disable		: 1;
+		u32 reserved3			: 2;
+	} reg02;
+
+	struct rkvdec_picpar {
+		u32 y_hor_virstride	: 9;
+		u32 reserved		: 2;
+		u32 slice_num_highbit	: 1;
+		u32 uv_hor_virstride	: 9;
+		u32 slice_num_lowbits	: 11;
+	} reg03;
+
+	u32 strm_rlc_base;
+	u32 stream_len;
+	u32 cabactbl_base;
+	u32 decout_base;
+
+	struct rkvdec_y_virstride {
+		u32 y_virstride	: 20;
+		u32 reserved0	: 12;
+	} reg08;
+
+	struct rkvdec_yuv_virstride {
+		u32 yuv_virstride	: 21;
+		u32 reserved0		: 11;
+	} reg09;
+} __packed;
+
+struct ref_base {
+	u32 field_ref		: 1;
+	u32 topfield_used_ref	: 1;
+	u32 botfield_used_ref	: 1;
+	u32 colmv_used_flag_ref	: 1;
+	u32 base_addr		: 28;
+};
+
+struct rkvdec_h264_regs {
+	struct ref_base ref0_14_base[15];
+	u32 ref0_14_poc[15];
+
+	u32 cur_poc;
+	u32 rlcwrite_base;
+	u32 pps_base;
+	u32 rps_base;
+
+	u32 strmd_error_e;
+
+	struct {
+		u32 strmd_error_status		: 28;
+		u32 colmv_error_ref_picidx	: 4;
+	} reg45;
+
+	struct {
+		u32 strmd_error_ctu_xoffset	: 8;
+		u32 strmd_error_ctu_yoffset	: 8;
+		u32 streamfifo_space2full	: 7;
+		u32 reserved0			: 1;
+		u32 vp9_error_ctu0_en		: 1;
+		u32 reserved1			: 7;
+	} reg46;
+
+	struct {
+		u32 saowr_xoffet	: 9;
+		u32 reserved0		: 7;
+		u32 saowr_yoffset	: 10;
+		u32 reserved1		: 6;
+	} reg47;
+
+	struct ref_base ref15_base;
+
+	u32 ref15_29_poc[15];
+
+	u32 performance_cycle;
+	u32 axi_ddr_rdata;
+	u32 axi_ddr_wdata;
+
+	struct {
+		u32 busifd_resetn	: 1;
+		u32 cabac_resetn	: 1;
+		u32 dec_ctrl_resetn	: 1;
+		u32 transd_resetn	: 1;
+		u32 intra_resetn	: 1;
+		u32 inter_resetn	: 1;
+		u32 recon_resetn	: 1;
+		u32 filer_resetn	: 1;
+		u32 reserved0		: 24;
+	} reg67;
+
+	struct {
+		u32 perf_cnt0_sel	: 6;
+		u32 reserved0		: 2;
+		u32 perf_cnt1_sel	: 6;
+		u32 reserved1		: 2;
+		u32 perf_cnt2_sel	: 6;
+		u32 reserved2		: 10;
+	} reg68;
+
+	u32 perf_cnt0;
+	u32 perf_cnt1;
+	u32 perf_cnt2;
+	u32 ref30_poc;
+	u32 ref31_poc;
+	u32 cur_poc1;
+	u32 errorinfo_base;
+
+	struct {
+		u32 slicedec_num		: 14;
+		u32 reserved0			: 1;
+		u32 strmd_detect_error_flag	: 1;
+		u32 error_packet_num		: 14;
+		u32 reserved1			: 2;
+	} reg76;
+
+	struct {
+		u32 error_en_highbits	: 30;
+		u32 reserved		: 2;
+	} reg77;
+} __packed;
+
+struct rkvdec_vp9_regs {
+	struct cprheader_offset {
+		u32 cprheader_offset	: 16;
+		u32 reserved		: 16;
+	} reg10;
+
+	u32 refer_bases[3];
+	u32 count_base;
+	u32 segidlast_base;
+	u32 segidcur_base;
+
+	struct frame_sizes {
+		u32 framewidth		: 16;
+		u32 frameheight		: 16;
+	} reg17_19[3];
+
+	struct segid_grp {
+		u32 segid_abs_delta			: 1;
+		u32 segid_frame_qp_delta_en		: 1;
+		u32 segid_frame_qp_delta		: 9;
+		u32 segid_frame_loopfilter_value_en	: 1;
+		u32 segid_frame_loopfilter_value	: 7;
+		u32 segid_referinfo_en			: 1;
+		u32 segid_referinfo			: 2;
+		u32 segid_frame_skip_en			: 1;
+		u32 reserved				: 9;
+	} reg20_27[8];
+
+	struct cprheader_config {
+		u32 tx_mode			: 3;
+		u32 frame_reference_mode	: 2;
+		u32 reserved			: 27;
+	} reg28;
+
+	struct ref_scale {
+		u32 ref_hor_scale		: 16;
+		u32 ref_ver_scale		: 16;
+	} reg29_31[3];
+
+	struct ref_deltas_lastframe {
+		u32 ref_deltas_lastframe0	: 7;
+		u32 ref_deltas_lastframe1	: 7;
+		u32 ref_deltas_lastframe2	: 7;
+		u32 ref_deltas_lastframe3	: 7;
+		u32 reserved			: 4;
+	} reg32;
+
+	struct info_lastframe {
+		u32 mode_deltas_lastframe0		: 7;
+		u32 mode_deltas_lastframe1		: 7;
+		u32 reserved0				: 2;
+		u32 segmentation_enable_lstframe	: 1;
+		u32 last_show_frame			: 1;
+		u32 last_intra_only			: 1;
+		u32 last_widthheight_eqcur		: 1;
+		u32 color_space_lastkeyframe		: 3;
+		u32 reserved1				: 9;
+	} reg33;
+
+	u32 intercmd_base;
+
+	struct intercmd_num {
+		u32 intercmd_num	: 24;
+		u32 reserved		: 8;
+	} reg35;
+
+	struct lasttile_size {
+		u32 lasttile_size	: 24;
+		u32 reserved		: 8;
+	} reg36;
+
+	struct hor_virstride {
+		u32 y_hor_virstride	: 9;
+		u32 reserved0		: 7;
+		u32 uv_hor_virstride	: 9;
+		u32 reserved1		: 7;
+	} reg37_39[3];
+
+	u32 cur_poc;
+
+	struct rlcwrite_base {
+		u32 reserved		: 3;
+		u32 rlcwrite_base	: 29;
+	} reg41;
+
+	struct pps_base {
+		u32 reserved	: 4;
+		u32 pps_base	: 28;
+	} reg42;
+
+	struct rps_base {
+		u32 reserved	: 4;
+		u32 rps_base	: 28;
+	} reg43;
+
+	struct strmd_error_en {
+		u32 strmd_error_e	: 28;
+		u32 reserved		: 4;
+	} reg44;
+
+	u32 vp9_error_info0;
+
+	struct strmd_error_ctu {
+		u32 strmd_error_ctu_xoffset	: 8;
+		u32 strmd_error_ctu_yoffset	: 8;
+		u32 streamfifo_space2full	: 7;
+		u32 reserved0			: 1;
+		u32 error_ctu0_en		: 1;
+		u32 reserved1			: 7;
+	} reg46;
+
+	struct sao_ctu_position {
+		u32 saowr_xoffet	: 9;
+		u32 reserved0		: 7;
+		u32 saowr_yoffset	: 10;
+		u32 reserved1		: 6;
+	} reg47;
+
+	struct ystride {
+		u32 virstride	: 20;
+		u32 reserved	: 12;
+	} reg48_50[3];
+
+	struct lastref_yuvstride {
+		u32 lastref_yuv_virstride	: 21;
+		u32 reserved			: 11;
+	} reg51;
+
+	u32 refcolmv_base;
+
+	u32 reserved0[11];
+
+	u32 performance_cycle;
+	u32 axi_ddr_rdata;
+	u32 axi_ddr_wdata;
+
+	struct fpgadebug_reset {
+		u32 busifd_resetn	: 1;
+		u32 cabac_resetn	: 1;
+		u32 dec_ctrl_resetn	: 1;
+		u32 transd_resetn	: 1;
+		u32 intra_resetn	: 1;
+		u32 inter_resetn	: 1;
+		u32 recon_resetn	: 1;
+		u32 filer_resetn	: 1;
+		u32 reserved		: 24;
+	} reg67;
+
+	struct performance_sel {
+		u32 perf_cnt0_sel	: 6;
+		u32 reserved0		: 2;
+		u32 perf_cnt1_sel	: 6;
+		u32 reserved1		: 2;
+		u32 perf_cnt2_sel	: 6;
+		u32 reserved		: 10;
+	} reg68;
+
+	u32 perf_cnt0;
+	u32 perf_cnt1;
+	u32 perf_cnt2;
+
+	u32 reserved1[3];
+
+	u32 vp9_error_info1;
+
+	struct error_ctu1 {
+		u32 vp9_error_ctu1_x	: 6;
+		u32 reserved0		: 2;
+		u32 vp9_error_ctu1_y	: 6;
+		u32 reserved1		: 1;
+		u32 vp9_error_ctu1_en	: 1;
+		u32 reserved2		: 16;
+	} reg76;
+
+	u32 reserved2;
+} __packed;
+
+struct rkvdec_regs {
+	struct rkvdec_common_regs common;
+	union {
+		struct rkvdec_h264_regs h264;
+		struct rkvdec_vp9_regs  vp9;
+	};
+} __packed;
 
 #endif /* RKVDEC_REGS_H_ */
diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c
index 0e7e16f20eeb0..d33b9ecceefe3 100644
--- a/drivers/staging/media/rkvdec/rkvdec-vp9.c
+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c
@@ -163,6 +163,7 @@ struct rkvdec_vp9_ctx {
 	struct v4l2_vp9_frame_context frame_context[4];
 	struct rkvdec_vp9_frame_info cur;
 	struct rkvdec_vp9_frame_info last;
+	struct rkvdec_regs regs;
 };
 
 static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
@@ -347,38 +348,6 @@ static void init_probs(struct rkvdec_ctx *ctx,
 		init_inter_probs(ctx, run);
 }
 
-struct rkvdec_vp9_ref_reg {
-	u32 reg_frm_size;
-	u32 reg_hor_stride;
-	u32 reg_y_stride;
-	u32 reg_yuv_stride;
-	u32 reg_ref_base;
-};
-
-static struct rkvdec_vp9_ref_reg ref_regs[] = {
-	{
-		.reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0),
-		.reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0),
-		.reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE,
-		.reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE,
-		.reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE,
-	},
-	{
-		.reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1),
-		.reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1),
-		.reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE,
-		.reg_yuv_stride = 0,
-		.reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE,
-	},
-	{
-		.reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2),
-		.reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2),
-		.reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE,
-		.reg_yuv_stride = 0,
-		.reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE,
-	}
-};
-
 static struct rkvdec_decoded_buffer *
 get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
 {
@@ -412,18 +381,17 @@ static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf)
 static void config_ref_registers(struct rkvdec_ctx *ctx,
 				 const struct rkvdec_vp9_run *run,
 				 struct rkvdec_decoded_buffer *ref_buf,
-				 struct rkvdec_vp9_ref_reg *ref_reg)
+				 int i)
 {
 	unsigned int aligned_pitch, aligned_height, y_len, yuv_len;
-	struct rkvdec_dev *rkvdec = ctx->dev;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_regs *regs = &vp9_ctx->regs;
 
 	aligned_height = round_up(ref_buf->vp9.height, 64);
-	writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(ref_buf->vp9.width) |
-		       RKVDEC_VP9_FRAMEHEIGHT(ref_buf->vp9.height),
-		       rkvdec->regs + ref_reg->reg_frm_size);
+	regs->vp9.reg17_19[i].frameheight = ref_buf->vp9.height;
+	regs->vp9.reg17_19[i].framewidth = ref_buf->vp9.width;
 
-	writel_relaxed(vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0),
-		       rkvdec->regs + ref_reg->reg_ref_base);
+	regs->vp9.refer_bases[i] = vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0);
 
 	if (&ref_buf->base.vb == run->base.bufs.dst)
 		return;
@@ -432,59 +400,50 @@ static void config_ref_registers(struct rkvdec_ctx *ctx,
 	y_len = aligned_height * aligned_pitch;
 	yuv_len = (y_len * 3) / 2;
 
-	writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) |
-		       RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16),
-		       rkvdec->regs + ref_reg->reg_hor_stride);
-	writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16),
-		       rkvdec->regs + ref_reg->reg_y_stride);
+	regs->vp9.reg37_39[i].y_hor_virstride = aligned_pitch / 16;
+	regs->vp9.reg37_39[i].uv_hor_virstride = aligned_pitch / 16;
+	regs->vp9.reg48_50[i].virstride = y_len / 16;
 
-	if (!ref_reg->reg_yuv_stride)
-		return;
-
-	writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16),
-		       rkvdec->regs + ref_reg->reg_yuv_stride);
+	if (!i)
+		regs->vp9.reg51.lastref_yuv_virstride = yuv_len / 16;
 }
 
 static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
 {
 	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_regs *regs = &vp9_ctx->regs;
 	const struct v4l2_vp9_segmentation *seg;
-	struct rkvdec_dev *rkvdec = ctx->dev;
 	s16 feature_val;
 	int feature_id;
-	u32 val = 0;
 
 	seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg;
 	feature_id = V4L2_VP9_SEG_LVL_ALT_Q;
 	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
-		val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) |
-		       RKVDEC_SEGID_FRAME_QP_DELTA(feature_val);
+		regs->vp9.reg20_27[segid].segid_frame_qp_delta_en = 1;
+		regs->vp9.reg20_27[segid].segid_frame_qp_delta = feature_val;
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_ALT_L;
 	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
-		val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) |
-		       RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val);
+		regs->vp9.reg20_27[segid].segid_frame_loopfilter_value_en = 1;
+		regs->vp9.reg20_27[segid].segid_frame_loopfilter_value = feature_val;
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_REF_FRAME;
 	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
-		val |= RKVDEC_SEGID_REFERINFO_EN(1) |
-		       RKVDEC_SEGID_REFERINFO(feature_val);
+		regs->vp9.reg20_27[segid].segid_referinfo_en = 1;
+		regs->vp9.reg20_27[segid].segid_referinfo = feature_val;
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_SKIP;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
-		val |= RKVDEC_SEGID_FRAME_SKIP_EN(1);
+	regs->vp9.reg20_27[segid].segid_frame_skip_en =
+		v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid);
 
-	if (!segid &&
-	    (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE))
-		val |= RKVDEC_SEGID_ABS_DELTA(1);
-
-	writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid));
+	regs->vp9.reg20_27[segid].segid_abs_delta = !segid &&
+		(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE);
 }
 
 static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
@@ -513,6 +472,15 @@ static void update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx)
 	vp9_ctx->last = vp9_ctx->cur;
 }
 
+static void rkvdec_write_regs(struct rkvdec_dev *dev, struct rkvdec_regs *regs)
+{
+#ifdef CONFIG_ARM64
+	__iowrite32_copy(dev->regs, regs, sizeof(*regs) / 4);
+#else
+	memcpy_toio(dev->regs, regs, sizeof(*regs));
+#endif
+}
+
 static void config_registers(struct rkvdec_ctx *ctx,
 			     const struct rkvdec_vp9_run *run)
 {
@@ -521,7 +489,8 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	struct rkvdec_decoded_buffer *ref_bufs[3];
 	struct rkvdec_decoded_buffer *dst, *last, *mv_ref;
 	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
-	u32 val, last_frame_info = 0;
+	struct rkvdec_regs *regs = &vp9_ctx->regs;
+	u32 val;
 	const struct v4l2_vp9_segmentation *seg;
 	struct rkvdec_dev *rkvdec = ctx->dev;
 	dma_addr_t addr;
@@ -547,8 +516,7 @@ static void config_registers(struct rkvdec_ctx *ctx,
 			(V4L2_VP9_FRAME_FLAG_KEY_FRAME |
 			 V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
 
-	writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9),
-		       rkvdec->regs + RKVDEC_REG_SYSCTRL);
+	regs->common.reg02.dec_mode = RKVDEC_MODE_VP9;
 
 	bit_depth = dec_params->bit_depth;
 	aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64);
@@ -560,17 +528,14 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	uv_len = y_len / 2;
 	yuv_len = y_len + uv_len;
 
-	writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) |
-		       RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16),
-		       rkvdec->regs + RKVDEC_REG_PICPAR);
-	writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16),
-		       rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
-	writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16),
-		       rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
+	regs->common.reg03.y_hor_virstride = aligned_pitch / 16;
+	regs->common.reg03.uv_hor_virstride = aligned_pitch / 16;
+	regs->common.reg08.y_virstride = y_len / 16;
+	regs->common.reg09.yuv_virstride = yuv_len / 16;
 
 	stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0);
-	writel_relaxed(RKVDEC_STRM_LEN(stream_len),
-		       rkvdec->regs + RKVDEC_REG_STRM_LEN);
+
+	regs->common.stream_len = stream_len;
 
 	/*
 	 * Reset count buffer, because decoder only output intra related syntax
@@ -588,14 +553,13 @@ static void config_registers(struct rkvdec_ctx *ctx,
 		vp9_ctx->cur.segmapid++;
 
 	for (i = 0; i < ARRAY_SIZE(ref_bufs); i++)
-		config_ref_registers(ctx, run, ref_bufs[i], &ref_regs[i]);
+		config_ref_registers(ctx, run, ref_bufs[i], i);
 
 	for (i = 0; i < 8; i++)
 		config_seg_registers(ctx, i);
 
-	writel_relaxed(RKVDEC_VP9_TX_MODE(vp9_ctx->cur.tx_mode) |
-		       RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode),
-		       rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG);
+	regs->vp9.reg28.tx_mode = vp9_ctx->cur.tx_mode;
+	regs->vp9.reg28.frame_reference_mode = dec_params->reference_mode;
 
 	if (!intra_only) {
 		const struct v4l2_vp9_loop_filter *lf;
@@ -609,43 +573,56 @@ static void config_registers(struct rkvdec_ctx *ctx,
 		val = 0;
 		for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) {
 			delta = lf->ref_deltas[i];
-			val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta);
+			switch (i) {
+			case 0:
+				regs->vp9.reg32.ref_deltas_lastframe0 = delta;
+				break;
+			case 1:
+				regs->vp9.reg32.ref_deltas_lastframe1 = delta;
+				break;
+			case 2:
+				regs->vp9.reg32.ref_deltas_lastframe2 = delta;
+				break;
+			case 3:
+				regs->vp9.reg32.ref_deltas_lastframe3 = delta;
+				break;
+			}
 		}
 
-		writel_relaxed(val,
-			       rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME);
-
 		for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) {
 			delta = lf->mode_deltas[i];
-			last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i,
-									delta);
+			switch (i) {
+			case 0:
+				regs->vp9.reg33.mode_deltas_lastframe0 = delta;
+				break;
+			case 1:
+				regs->vp9.reg33.mode_deltas_lastframe1 = delta;
+				break;
+			}
 		}
 	}
 
-	if (vp9_ctx->last.valid && !intra_only &&
-	    vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)
-		last_frame_info |= RKVDEC_SEG_EN_LASTFRAME;
-
-	if (vp9_ctx->last.valid &&
-	    vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME)
-		last_frame_info |= RKVDEC_LAST_SHOW_FRAME;
+	regs->vp9.reg33.segmentation_enable_lstframe =
+		vp9_ctx->last.valid && !intra_only &&
+		vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED;
 
-	if (vp9_ctx->last.valid &&
-	    vp9_ctx->last.flags &
-	    (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY))
-		last_frame_info |= RKVDEC_LAST_INTRA_ONLY;
+	regs->vp9.reg33.last_show_frame =
+		vp9_ctx->last.valid &&
+		vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME;
 
-	if (vp9_ctx->last.valid &&
-	    last->vp9.width == dst->vp9.width &&
-	    last->vp9.height == dst->vp9.height)
-		last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR;
+	regs->vp9.reg33.last_intra_only =
+		vp9_ctx->last.valid &&
+		vp9_ctx->last.flags &
+		(V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY);
 
-	writel_relaxed(last_frame_info,
-		       rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME);
+	regs->vp9.reg33.last_widthheight_eqcur =
+		vp9_ctx->last.valid &&
+		last->vp9.width == dst->vp9.width &&
+		last->vp9.height == dst->vp9.height;
 
-	writel_relaxed(stream_len - dec_params->compressed_header_size -
-		       dec_params->uncompressed_header_size,
-		       rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE);
+	regs->vp9.reg36.lasttile_size =
+		stream_len - dec_params->compressed_header_size -
+		dec_params->uncompressed_header_size;
 
 	for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) {
 		unsigned int refw = ref_bufs[i]->vp9.width;
@@ -654,29 +631,28 @@ static void config_registers(struct rkvdec_ctx *ctx,
 
 		hscale = (refw << 14) /	dst->vp9.width;
 		vscale = (refh << 14) / dst->vp9.height;
-		writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) |
-			       RKVDEC_VP9_REF_VER_SCALE(vscale),
-			       rkvdec->regs + RKVDEC_VP9_REF_SCALE(i));
+
+		regs->vp9.reg29_31[i].ref_hor_scale = hscale;
+		regs->vp9.reg29_31[i].ref_ver_scale = vscale;
 	}
 
 	addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0);
-	writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
+	regs->common.decout_base = addr;
 	addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0);
-	writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
-	writel_relaxed(vp9_ctx->priv_tbl.dma +
-		       offsetof(struct rkvdec_vp9_priv_tbl, probs),
-		       rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
-	writel_relaxed(vp9_ctx->count_tbl.dma,
-		       rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE);
-
-	writel_relaxed(vp9_ctx->priv_tbl.dma +
-		       offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
-		       (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid),
-		       rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE);
-	writel_relaxed(vp9_ctx->priv_tbl.dma +
-		       offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
-		       (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)),
-		       rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE);
+	regs->common.strm_rlc_base = addr;
+
+	regs->common.cabactbl_base = vp9_ctx->priv_tbl.dma +
+		offsetof(struct rkvdec_vp9_priv_tbl, probs);
+
+	regs->vp9.count_base = vp9_ctx->count_tbl.dma;
+
+	regs->vp9.segidlast_base = vp9_ctx->priv_tbl.dma +
+		offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
+		(RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid));
+
+	regs->vp9.segidcur_base = vp9_ctx->priv_tbl.dma +
+		offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
+		(RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid);
 
 	if (!intra_only &&
 	    !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
@@ -685,12 +661,14 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	else
 		mv_ref = dst;
 
-	writel_relaxed(get_mv_base_addr(mv_ref),
-		       rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE);
+	regs->vp9.refcolmv_base = get_mv_base_addr(mv_ref);
+
+	regs->vp9.performance_cycle = ctx->decoded_fmt.fmt.pix_mp.width |
+		       (ctx->decoded_fmt.fmt.pix_mp.height << 16);
+
+	regs->vp9.reg44.strmd_error_e = 0xe;
 
-	writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width |
-		       (ctx->decoded_fmt.fmt.pix_mp.height << 16),
-		       rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE);
+	rkvdec_write_regs(rkvdec, regs);
 }
 
 static int validate_dec_params(struct rkvdec_ctx *ctx,
@@ -823,7 +801,6 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
 	writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
 	writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
 
-	writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
 	/* Start decoding! */
 	writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E |
 	       RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E,
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index 2a44406d397f8..8d36411b663b8 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -999,7 +999,6 @@ static void rkvdec_watchdog_func(struct work_struct *work)
 	if (ctx) {
 		dev_err(rkvdec->dev, "Frame processing timed out!\n");
 		writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT);
-		writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL);
 		rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR);
 	}
 }
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ