Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant
@ 2026-07-26 20:25 Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 1/4] media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9 Venkata Atchuta Bheemeswara Sarma Darbha
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Venkata Atchuta Bheemeswara Sarma Darbha @ 2026-07-26 20:25 UTC (permalink / raw)
  To: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne, Venkata Atchuta Bheemeswara Sarma Darbha,
	Igor Paunovic, Francesco Saverio Pavone

Hi All,
This patch series adds the initial VP9 support for VDPU381 present in rk3588.

VDPU381 supports VP9 Profile 0 and Profile 2 up to 7680x4320@30fps.

Tested with fluster (suite : VP9-TEST-VECTORS, decoder: GStreamer-VP9-V4L2SL-Gst1.0).
The 224/305 score has been reproduced independently on three RK3588 boards
across three kernel bases: Orange Pi 5 Pro (RK3588S, 7.2.0-rc3),
Orange Pi 5 Plus (RK3588, 7.0) and Radxa Rock 5B+ (RK3588, 7.1).

Most of the remaining failures fall into a few known categories:

- All vp90-2-02-size-*.webm variants where either dimension is
  smaller than 64 pixels fail because the hardware does not support
  frames smaller than 64x64:
  vp90-2-02-size-08x08.webm, vp90-2-02-size-08x10.webm,
  vp90-2-02-size-08x16.webm, vp90-2-02-size-08x18.webm,
  vp90-2-02-size-08x32.webm, vp90-2-02-size-08x34.webm,
  vp90-2-02-size-08x64.webm, vp90-2-02-size-08x66.webm,
  vp90-2-02-size-10x08.webm, vp90-2-02-size-10x10.webm,
  vp90-2-02-size-10x16.webm, vp90-2-02-size-10x18.webm,
  vp90-2-02-size-10x32.webm, vp90-2-02-size-10x34.webm,
  vp90-2-02-size-10x64.webm, vp90-2-02-size-10x66.webm,
  vp90-2-02-size-16x08.webm, vp90-2-02-size-16x10.webm,
  vp90-2-02-size-16x16.webm, vp90-2-02-size-16x18.webm,
  vp90-2-02-size-16x32.webm, vp90-2-02-size-16x34.webm,
  vp90-2-02-size-16x64.webm, vp90-2-02-size-16x66.webm,
  vp90-2-02-size-18x08.webm, vp90-2-02-size-18x10.webm,
  vp90-2-02-size-18x18.webm, vp90-2-02-size-18x32.webm,
  vp90-2-02-size-18x34.webm, vp90-2-02-size-18x64.webm,
  vp90-2-02-size-18x66.webm, vp90-2-02-size-32x08.webm,
  vp90-2-02-size-32x10.webm, vp90-2-02-size-32x18.webm,
  vp90-2-02-size-32x34.webm, vp90-2-02-size-32x66.webm,
  vp90-2-02-size-34x08.webm, vp90-2-02-size-34x10.webm,
  vp90-2-02-size-34x16.webm, vp90-2-02-size-34x34.webm,
  vp90-2-02-size-34x64.webm, vp90-2-02-size-34x66.webm,
  vp90-2-02-size-64x08.webm, vp90-2-02-size-64x10.webm,
  vp90-2-02-size-66x08.webm, vp90-2-02-size-66x10.webm.

- vp90-2-05-resize.ivf, vp90-2-18-resize.ivf and all
  vp90-2-21-resize_inter_*.webm variants fail. These streams change
  resolution mid-stream on a non-keyframe, and a reference frame
  from before the resize ends up unavailable by the time it's
  needed again. This is being actively looked into:
  vp90-2-05-resize.ivf, vp90-2-18-resize.ivf,
  vp90-2-21-resize_inter_1280x720_5_1-2.webm,
  vp90-2-21-resize_inter_1280x720_5_3-4.webm,
  vp90-2-21-resize_inter_1280x720_7_1-2.webm,
  vp90-2-21-resize_inter_1280x720_7_3-4.webm,
  vp90-2-21-resize_inter_1920x1080_5_1-2.webm,
  vp90-2-21-resize_inter_1920x1080_5_3-4.webm,
  vp90-2-21-resize_inter_1920x1080_7_1-2.webm,
  vp90-2-21-resize_inter_1920x1080_7_3-4.webm,
  vp90-2-21-resize_inter_320x180_5_1-2.webm,
  vp90-2-21-resize_inter_320x180_5_3-4.webm,
  vp90-2-21-resize_inter_320x180_7_1-2.webm,
  vp90-2-21-resize_inter_320x180_7_3-4.webm,
  vp90-2-21-resize_inter_320x240_5_1-2.webm,
  vp90-2-21-resize_inter_320x240_5_3-4.webm,
  vp90-2-21-resize_inter_320x240_7_1-2.webm,
  vp90-2-21-resize_inter_320x240_7_3-4.webm,
  vp90-2-21-resize_inter_640x360_5_1-2.webm,
  vp90-2-21-resize_inter_640x360_5_3-4.webm,
  vp90-2-21-resize_inter_640x360_7_1-2.webm,
  vp90-2-21-resize_inter_640x360_7_3-4.webm,
  vp90-2-21-resize_inter_640x480_5_1-2.webm,
  vp90-2-21-resize_inter_640x480_5_3-4.webm,
  vp90-2-21-resize_inter_640x480_7_1-2.webm,
  vp90-2-21-resize_inter_640x480_7_3-4.webm.

- vp90-2-09-aq2.webm,
  vp90-2-09-lf_deltas.webm,
  vp90-2-15-segkey_adpq.webm,
  vp90-2-19-skip-01.webm,
  vp90-2-19-skip-02.webm,
  vp90-2-19-skip.webm,  vp90-2-22-svc_1280x720_3.ivf,
  are still failing and not yet root-caused.

- vp91-2-04-yuv422.webm
  vp91-2-04-yuv444.webm
  fail because the hardware does not support the format these
  streams use (4:2:2/4:4:4), only 4:2:0.

The base vdpu381 VP9 driver support was introduced by me. Profile 2 support
was added by Igor Paunovic. Francesco Saverio Pavone fixed bugs in
the segmentation map size calculation and in the altref vertical
scale factor. Igor Paunovic also fixed a decoded-frame stride bug, aligning
bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt().

---
Igor Paunovic (1):
      media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()

Venkata Atchuta Bheemeswara Sarma Darbha (3):
      media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9
      media: rkvdec: Move vp9 functions to common file
      media: rkvdec: Add VP9 support for VDPU381 variant

 drivers/media/platform/rockchip/rkvdec/Makefile    |    2 +
 .../platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h |  234 +++++
 .../platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c  | 1067 ++++++++++++++++++++
 .../platform/rockchip/rkvdec/rkvdec-vp9-common.c   |   65 ++
 .../platform/rockchip/rkvdec/rkvdec-vp9-common.h   |   92 ++
 .../media/platform/rockchip/rkvdec/rkvdec-vp9.c    |  121 +--
 drivers/media/platform/rockchip/rkvdec/rkvdec.c    |   73 +-
 drivers/media/platform/rockchip/rkvdec/rkvdec.h    |    1 +
 8 files changed, 1537 insertions(+), 118 deletions(-)
---
base-commit: 1229e2e57a5c2980ccd457b9b53ea0eed5a22ab3
change-id: 20260726-b4-add-rkvdec2-vp9-vdpu381-3d1bd8fca4f5

Best regards,
--  
Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>



^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/4] media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9
  2026-07-26 20:25 [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
@ 2026-07-26 20:25 ` Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 2/4] media: rkvdec: Move vp9 functions to common file Venkata Atchuta Bheemeswara Sarma Darbha
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Venkata Atchuta Bheemeswara Sarma Darbha @ 2026-07-26 20:25 UTC (permalink / raw)
  To: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne, Venkata Atchuta Bheemeswara Sarma Darbha

This change is in preparation for the upcoming commits and to denote
that this function is not to be confused with the similar function
found in rkvdec's hevc.

Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
---
 drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
index 2751f5396ee8..d4243ce230c7 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
@@ -349,7 +349,7 @@ static void init_probs(struct rkvdec_ctx *ctx,
 }
 
 static struct rkvdec_decoded_buffer *
-get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
+get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
 {
 	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
 	struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
@@ -489,12 +489,12 @@ static void config_registers(struct rkvdec_ctx *ctx,
 
 	dec_params = run->decode_params;
 	dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf);
-	ref_bufs[0] = get_ref_buf(ctx, &dst->base.vb, dec_params->last_frame_ts);
-	ref_bufs[1] = get_ref_buf(ctx, &dst->base.vb, dec_params->golden_frame_ts);
-	ref_bufs[2] = get_ref_buf(ctx, &dst->base.vb, dec_params->alt_frame_ts);
+	ref_bufs[0] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->last_frame_ts);
+	ref_bufs[1] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->golden_frame_ts);
+	ref_bufs[2] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->alt_frame_ts);
 
 	if (vp9_ctx->last.valid)
-		last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
+		last = get_ref_buf_vp9(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
 	else
 		last = dst;
 

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/4] media: rkvdec: Move vp9 functions to common file
  2026-07-26 20:25 [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 1/4] media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9 Venkata Atchuta Bheemeswara Sarma Darbha
@ 2026-07-26 20:25 ` Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 3/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Venkata Atchuta Bheemeswara Sarma Darbha @ 2026-07-26 20:25 UTC (permalink / raw)
  To: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne, Venkata Atchuta Bheemeswara Sarma Darbha

Refactor common VP9 functions in preparation for adding the VDPU381
variant

Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
---
 drivers/media/platform/rockchip/rkvdec/Makefile    |   1 +
 .../platform/rockchip/rkvdec/rkvdec-vp9-common.c   |  65 ++++++++++++
 .../platform/rockchip/rkvdec/rkvdec-vp9-common.h   |  92 +++++++++++++++++
 .../media/platform/rockchip/rkvdec/rkvdec-vp9.c    | 113 +--------------------
 4 files changed, 159 insertions(+), 112 deletions(-)

diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/media/platform/rockchip/rkvdec/Makefile
index e629d571e4d8..2bbd67b2db11 100644
--- a/drivers/media/platform/rockchip/rkvdec/Makefile
+++ b/drivers/media/platform/rockchip/rkvdec/Makefile
@@ -12,4 +12,5 @@ rockchip-vdec-y += \
 		   rkvdec-vdpu381-hevc.o \
 		   rkvdec-vdpu383-h264.o \
 		   rkvdec-vdpu383-hevc.o \
+		   rkvdec-vp9-common.o \
 		   rkvdec-vp9.o
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c
new file mode 100644
index 000000000000..a802f0acd27b
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip video decoder VP9 common functions
+ *
+ * Copyright (C) 2019 Collabora, Ltd.
+ *	Boris Brezillon <boris.brezillon@collabora.com>
+ * Copyright (C) 2021 Collabora, Ltd.
+ *	Andrzej Pietrasiewicz <andrzej.p@collabora.com>
+ *
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
+ *	Alpha Lin <Alpha.Lin@rock-chips.com>
+ */
+#include <linux/v4l2-common.h>
+#include <media/v4l2-h264.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "rkvdec.h"
+#include "rkvdec-vp9-common.h"
+
+void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
+{
+	unsigned int idx = 0, byte_count = 0;
+	int k, m, n;
+	u8 p;
+
+	for (k = 0; k < 6; k++) {
+		for (m = 0; m < 6; m++) {
+			for (n = 0; n < 3; n++) {
+				p = coef[k][m][n];
+				coeff_plane[idx++] = p;
+				byte_count++;
+				if (byte_count == 27) {
+					idx += 5;
+					byte_count = 0;
+				}
+			}
+		}
+	}
+}
+
+struct rkvdec_decoded_buffer *
+get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
+{
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
+	struct vb2_buffer *buf;
+
+	/*
+	 * If a ref is unused or invalid, address of current destination
+	 * buffer is returned.
+	 */
+	buf = vb2_find_buffer(cap_q, timestamp);
+	if (!buf)
+		buf = &dst->vb2_buf;
+
+	return vb2_to_rkvdec_decoded_buf(buf);
+}
+
+void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
+			 const struct v4l2_ctrl_vp9_frame *dec_params)
+{
+	buf->vp9.width = dec_params->frame_width_minus_1 + 1;
+	buf->vp9.height = dec_params->frame_height_minus_1 + 1;
+	buf->vp9.bit_depth = dec_params->bit_depth;
+}
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h
new file mode 100644
index 000000000000..0d042215fad2
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip video decoder VP9 common functions
+ *
+ * Copyright (C) 2019 Collabora, Ltd.
+ *	Boris Brezillon <boris.brezillon@collabora.com>
+ * Copyright (C) 2021 Collabora, Ltd.
+ *	Andrzej Pietrasiewicz <andrzej.p@collabora.com>
+ *
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
+ *	Alpha Lin <Alpha.Lin@rock-chips.com>
+ */
+
+#include <media/v4l2-h264.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-vp9.h>
+
+#include "rkvdec.h"
+
+struct rkvdec_vp9_run {
+	struct rkvdec_run base;
+	const struct v4l2_ctrl_vp9_frame *decode_params;
+};
+
+struct rkvdec_vp9_intra_mode_probs {
+	u8 y_mode[105];
+	u8 uv_mode[23];
+};
+
+struct rkvdec_vp9_intra_only_frame_probs {
+	u8 coef_intra[4][2][128];
+	struct rkvdec_vp9_intra_mode_probs intra_mode[10];
+};
+
+struct rkvdec_vp9_inter_frame_probs {
+	u8 y_mode[4][9];
+	u8 comp_mode[5];
+	u8 comp_ref[5];
+	u8 single_ref[5][2];
+	u8 inter_mode[7][3];
+	u8 interp_filter[4][2];
+	u8 padding0[11];
+	u8 coef[2][4][2][128];
+	u8 uv_mode_0_2[3][9];
+	u8 padding1[5];
+	u8 uv_mode_3_5[3][9];
+	u8 padding2[5];
+	u8 uv_mode_6_8[3][9];
+	u8 padding3[5];
+	u8 uv_mode_9[9];
+	u8 padding4[7];
+	u8 padding5[16];
+	struct {
+		u8 joint[3];
+		u8 sign[2];
+		u8 classes[2][10];
+		u8 class0_bit[2];
+		u8 bits[2][10];
+		u8 class0_fr[2][2][3];
+		u8 fr[2][3];
+		u8 class0_hp[2];
+		u8 hp[2];
+		u8 padding6[3];
+	} mv;
+};
+
+struct rkvdec_vp9_probs {
+	u8 partition[16][3];
+	u8 pred[3];
+	u8 tree[7];
+	u8 skip[3];
+	u8 tx32[2][3];
+	u8 tx16[2][2];
+	u8 tx8[2][1];
+	u8 is_inter[4];
+	/* 128 bit alignment */
+	u8 padding0[3];
+	union {
+		struct rkvdec_vp9_inter_frame_probs inter;
+		struct rkvdec_vp9_intra_only_frame_probs intra_only;
+	};
+	/* 128 bit alignment */
+	u8 padding1[8];
+};
+
+void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane);
+
+struct rkvdec_decoded_buffer *
+get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp);
+
+void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
+			 const struct v4l2_ctrl_vp9_frame *dec_params);
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
index d4243ce230c7..495738762713 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
@@ -23,71 +23,12 @@
 
 #include "rkvdec.h"
 #include "rkvdec-regs.h"
+#include "rkvdec-vp9-common.h"
 
 #define RKVDEC_VP9_PROBE_SIZE		4864
 #define RKVDEC_VP9_COUNT_SIZE		13232
 #define RKVDEC_VP9_MAX_SEGMAP_SIZE	73728
 
-struct rkvdec_vp9_intra_mode_probs {
-	u8 y_mode[105];
-	u8 uv_mode[23];
-};
-
-struct rkvdec_vp9_intra_only_frame_probs {
-	u8 coef_intra[4][2][128];
-	struct rkvdec_vp9_intra_mode_probs intra_mode[10];
-};
-
-struct rkvdec_vp9_inter_frame_probs {
-	u8 y_mode[4][9];
-	u8 comp_mode[5];
-	u8 comp_ref[5];
-	u8 single_ref[5][2];
-	u8 inter_mode[7][3];
-	u8 interp_filter[4][2];
-	u8 padding0[11];
-	u8 coef[2][4][2][128];
-	u8 uv_mode_0_2[3][9];
-	u8 padding1[5];
-	u8 uv_mode_3_5[3][9];
-	u8 padding2[5];
-	u8 uv_mode_6_8[3][9];
-	u8 padding3[5];
-	u8 uv_mode_9[9];
-	u8 padding4[7];
-	u8 padding5[16];
-	struct {
-		u8 joint[3];
-		u8 sign[2];
-		u8 classes[2][10];
-		u8 class0_bit[2];
-		u8 bits[2][10];
-		u8 class0_fr[2][2][3];
-		u8 fr[2][3];
-		u8 class0_hp[2];
-		u8 hp[2];
-	} mv;
-};
-
-struct rkvdec_vp9_probs {
-	u8 partition[16][3];
-	u8 pred[3];
-	u8 tree[7];
-	u8 skip[3];
-	u8 tx32[2][3];
-	u8 tx16[2][2];
-	u8 tx8[2][1];
-	u8 is_inter[4];
-	/* 128 bit alignment */
-	u8 padding0[3];
-	union {
-		struct rkvdec_vp9_inter_frame_probs inter;
-		struct rkvdec_vp9_intra_only_frame_probs intra_only;
-	};
-	/* 128 bit alignment */
-	u8 padding1[11];
-};
-
 /* Data structure describing auxiliary buffer format. */
 struct rkvdec_vp9_priv_tbl {
 	struct rkvdec_vp9_probs probs;
@@ -136,11 +77,6 @@ struct rkvdec_vp9_intra_frame_symbol_counts {
 	struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6];
 };
 
-struct rkvdec_vp9_run {
-	struct rkvdec_run base;
-	const struct v4l2_ctrl_vp9_frame *decode_params;
-};
-
 struct rkvdec_vp9_frame_info {
 	u32 valid : 1;
 	u32 segmapid : 1;
@@ -166,27 +102,6 @@ struct rkvdec_vp9_ctx {
 	struct rkvdec_regs regs;
 };
 
-static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
-{
-	unsigned int idx = 0, byte_count = 0;
-	int k, m, n;
-	u8 p;
-
-	for (k = 0; k < 6; k++) {
-		for (m = 0; m < 6; m++) {
-			for (n = 0; n < 3; n++) {
-				p = coef[k][m][n];
-				coeff_plane[idx++] = p;
-				byte_count++;
-				if (byte_count == 27) {
-					idx += 5;
-					byte_count = 0;
-				}
-			}
-		}
-	}
-}
-
 static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 				  const struct rkvdec_vp9_run *run)
 {
@@ -348,24 +263,6 @@ static void init_probs(struct rkvdec_ctx *ctx,
 		init_inter_probs(ctx, run);
 }
 
-static struct rkvdec_decoded_buffer *
-get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
-{
-	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
-	struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
-	struct vb2_buffer *buf;
-
-	/*
-	 * If a ref is unused or invalid, address of current destination
-	 * buffer is returned.
-	 */
-	buf = vb2_find_buffer(cap_q, timestamp);
-	if (!buf)
-		buf = &dst->vb2_buf;
-
-	return vb2_to_rkvdec_decoded_buf(buf);
-}
-
 static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf)
 {
 	unsigned int aligned_pitch, aligned_height, yuv_len;
@@ -446,14 +343,6 @@ static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
 		(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE);
 }
 
-static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
-				const struct v4l2_ctrl_vp9_frame *dec_params)
-{
-	buf->vp9.width = dec_params->frame_width_minus_1 + 1;
-	buf->vp9.height = dec_params->frame_height_minus_1 + 1;
-	buf->vp9.bit_depth = dec_params->bit_depth;
-}
-
 static void update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx,
 				struct rkvdec_decoded_buffer *buf,
 				const struct v4l2_ctrl_vp9_frame *dec_params)

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/4] media: rkvdec: Add VP9 support for VDPU381 variant
  2026-07-26 20:25 [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 1/4] media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9 Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 2/4] media: rkvdec: Move vp9 functions to common file Venkata Atchuta Bheemeswara Sarma Darbha
@ 2026-07-26 20:25 ` Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-26 20:25 ` [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt() Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-27  6:44 ` [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Francesco Saverio Pavone
  4 siblings, 0 replies; 11+ messages in thread
From: Venkata Atchuta Bheemeswara Sarma Darbha @ 2026-07-26 20:25 UTC (permalink / raw)
  To: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne, Igor Paunovic, Francesco Saverio Pavone,
	Venkata Atchuta Bheemeswara Sarma Darbha

Add support for VP9 decoding on VDPU381 used with RK3588. VDPU381
supports VP9 Profile 0 and Profile 2 up to 7680x4320@30fps.

Co-developed-by: Igor Paunovic <royalnet026@gmail.com>
Signed-off-by: Igor Paunovic <royalnet026@gmail.com>
Co-developed-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
---
 drivers/media/platform/rockchip/rkvdec/Makefile    |    1 +
 .../platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h |  234 +++++
 .../platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c  | 1067 ++++++++++++++++++++
 drivers/media/platform/rockchip/rkvdec/rkvdec.c    |   61 ++
 drivers/media/platform/rockchip/rkvdec/rkvdec.h    |    1 +
 5 files changed, 1364 insertions(+)

diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/media/platform/rockchip/rkvdec/Makefile
index 2bbd67b2db11..5eae59e87fce 100644
--- a/drivers/media/platform/rockchip/rkvdec/Makefile
+++ b/drivers/media/platform/rockchip/rkvdec/Makefile
@@ -10,6 +10,7 @@ rockchip-vdec-y += \
 		   rkvdec-rcb.o \
 		   rkvdec-vdpu381-h264.o \
 		   rkvdec-vdpu381-hevc.o \
+		   rkvdec-vdpu381-vp9.o \
 		   rkvdec-vdpu383-h264.o \
 		   rkvdec-vdpu383-hevc.o \
 		   rkvdec-vp9-common.o \
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h
index 6da36031df2d..7b92ac38681c 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h
@@ -4,6 +4,8 @@
  *
  * Copyright (C) 2024 Collabora, Ltd.
  *  Detlev Casanova <detlev.casanova@collabora.com>
+ *
+ * Copyright (C) 2025 Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
  */
 
 #include <linux/types.h>
@@ -382,6 +384,211 @@ struct rkvdec_vdpu381_regs_hevc_params {
 
 } __packed;
 
+struct rkvdec_vdpu381_vp9_set {
+	u32 vp9_cprheader_offset : 16;
+	u32 reserved			 : 16;
+} __packed;
+
+/* base: OFFSET_CODEC_PARAMS_REGS */
+struct rkvdec_vdpu381_regs_vp9_params {
+	struct rkvdec_vdpu381_vp9_set reg064;
+
+	u32 cur_top_poc;
+	u32 reserved0;
+
+	struct rkvdec_vdpu381_vp9_segid_grp {
+		u32 vp9_segid_abs_delta		 : 1;
+		u32 vp9_segid_frame_qp_delta_en  : 1;
+		u32 vp9_segid_frame_qp_delta     : 9;
+		u32 vp9_segid_frame_loopfilter_value_en : 1;
+		u32 vp9_segid_frame_loopfilter_value : 7;
+		u32 vp9_segid_referinfo_en : 1;
+		u32 vp9_segid_referinfo : 2;
+		u32 vp9_segid_frame_skip_en : 1;
+		u32 reserved : 9;
+	} reg67_74[8];
+
+	struct rkvdec_vdpu381_vp9_info_lastframe {
+		u32 vp9_mode_deltas_lastframe : 14;
+		u32 reserved0 : 2;
+		u32 segmentation_enable_lstframe : 1;
+		u32 vp9_last_showframe : 1;
+		u32 vp9_last_intra_only : 1;
+		u32 vp9_last_widhheight_eqcur :1;
+		u32 vp9_color_sapce_lastkeyframe : 3;
+		u32 reserved1 : 9;
+	} reg75;
+
+	struct rkvdec_vdpu381_vp9_cprheader_config {
+		u32 vp9_tx_mode : 3;
+		u32 vp9_frame_reference_mode : 2;
+		u32 reserved : 27;
+	} reg76;
+
+	struct rkvdec_vdpu381_vp9_intercmd_num {
+		u32 vp9_intercmd_num : 24;
+		u32 reserved : 8;
+	} reg77;
+
+	u32 reg78_vp9_stream_size;
+
+	struct rkvdec_vdpu381_vp9_lastf_y_hor_virstride {
+		u32 vp9_lastfy_hor_virstride : 16;
+		u32 reserved : 16;
+	} reg79;
+
+	struct rkvdec_vdpu381_vp9_lastf_uv_hor_virstride {
+		u32 vp9_lastfuv_hor_virstride : 16;
+		u32 reserved : 16;
+	} reg80;
+
+	struct rkvdec_vdpu381_vp9_goldenf_y_hor_virstride {
+		u32 vp9_goldenfy_hor_virstride : 16;
+		u32 reserved : 16;
+	} reg81;
+
+	struct rkvdec_vdpu381_vp9_golden_uv_hot_virstride {
+		u32 vp9_goldenuv_hor_virstride : 16;
+		u32 reserved : 16;
+	} reg82;
+
+	struct rkvdec_vdpu381_vp9_altreff_y_hor_virstride {
+		u32 vp9_altreffy_hor_virstride :16;
+		u32 reserved : 16;
+	} reg83;
+
+	struct rkvdec_vdpu381_vp9_altreff_uv_hor_virstride {
+		u32 vp9_altreff_uv_hor_virstride : 16;
+		u32 reserved : 16;
+	} reg84;
+
+	struct rkvdec_vdpu381_vp9_lastf_y_virstride {
+		u32 vp9_lastfy_virstride : 28;
+		u32 reserved : 4;
+	} reg85;
+
+	struct rkvdec_vdpu381_vp9_golden_y_virstride {
+		u32 vp9_goldeny_virstride : 28;
+		u32 reserved : 4;
+	} reg86;
+
+	struct rkvdec_vdpu381_vp9_altref_y_virstride {
+		u32 vp9_altrefy_virstride : 28;
+		u32 reserved : 4;
+	} reg87;
+
+	struct rkvdec_vdpu381_vp9_lref_hor_scale {
+		u32 vp9_lref_hor_scale : 16;
+		u32 reserved : 16;
+	} reg88;
+
+	struct rkvdec_vdpu381_vp9_lref_ver_scale {
+		u32 vp9_lref_ver_scale : 16;
+		u32 reserved : 16;
+	} reg89;
+
+	struct rkvdec_vdpu381_vp9_gref_hor_scale {
+		u32 vp9_gref_hor_scale : 16;
+		u32 reserved : 16;
+	} reg90;
+
+	struct rkvdec_vdpu381_vp9_gref_ver_scale {
+		u32 vp9_gref_ver_scale :16;
+		u32 reserved : 16;
+	} reg91;
+
+	struct rkvdec_vdpu381_vp9_aref_hor_scale {
+		u32 vp9_aref_hor_scale : 16;
+		u32 reserved : 16;
+	} reg92;
+
+	struct rkvdec_vdpu381_vp9_aref_ver_scale {
+		u32 vp9_aref_ver_scale : 16;
+		u32 reserved : 16;
+	} reg93;
+
+	struct rkvdec_vdpu381_vp9_ref_deltas_lastframe {
+		u32 vp9_ref_deltas_lastframe : 28;
+		u32 reserved : 4;
+	} reg94;
+
+	u32 reg95_vp9_last_poc;
+
+	u32 reg96_vp9_golden_poc;
+
+	u32 reg97_vp9_altref_poc;
+
+	u32 reg98_vp9_col_ref_poc;
+
+	struct rkvdec_vdpu381_vp9_prob_ref_poc {
+		u32 vp9_prob_ref_poc : 16;
+		u32 reserved : 16;
+	} reg99;
+
+	struct rkvdec_vdpu381_vp9_segid_ref_poc {
+		u32 vp9_segid_ref_poc : 16;
+		u32 reserved : 16;
+	} reg100;
+
+	u32 reserved1[2];
+
+	struct rkvdec_vdpu381_vp9_prob_en {
+		u32 reserved : 20;
+		u32 vp9_prob_update_en : 1;
+		u32 vp9_refresh_en : 1;
+		u32 vp9_prob_save_en : 1;
+		u32 vp9_intra_only_flag : 1;
+		u32 vp9_txfmmode_rfsh_en : 1;
+		u32 vp9_ref_mode_rfsh_en : 1;
+		u32 vp9_single_ref_rfsh_en : 1;
+		u32 vp9_comp_ref_rfsh_en : 1;
+		u32 vp9_interp_filter_switch_en : 1;
+		u32 vp9_allow_high_precision_mv : 1;
+		u32 vp9_last_key_frame_flag : 1;
+		u32 vp9_inter_coef_rfsh_flag :1;
+	} reg103;
+
+	u32 reserved2;
+
+	struct rkvdec_vdpu381_vp9_cnt_upd_en_avs2_headlen {
+		u32 avs2_head_len : 4;
+		u32 vp9count_update_en : 1;
+		u32 reserved : 27;
+	} reg105;
+
+	struct rkvdec_vdpu381_vp9_frame_width_last {
+		u32 vp9_framewidth_last : 16;
+		u32 reserved : 16;
+	} reg106;
+
+	struct rkvdec_vdpu381_vp9_frame_height_last {
+		u32 vp9_frameheight_last: 16;
+		u32 reserved : 16;
+	} reg107;
+
+	struct rkvdec_vdpu381_vp9_frame_width_golden {
+		u32 vp9_framewidth_golden : 16;
+		u32 reserved : 16;
+	} reg108;
+
+	struct rkvdec_vdpu381_vp9_frame_height_golden {
+		u32 vp9_frameheight_golden : 16;
+		u32 reserved : 16;
+	} reg109;
+
+	struct rkvdec_vdpu381_vp9_frame_width_altref {
+		u32 vp9_framewidth_altref : 16;
+		u32 reserved : 16;
+	} reg110;
+
+	struct rkvdec_vdpu381_vp9_frame_height_altref {
+		u32 vp9_frameheight_altref : 16;
+		u32 reserved : 16;
+	} reg111;
+
+	u32 reserved3;
+} __packed;
+
 /* base: OFFSET_CODEC_ADDR_REGS */
 struct rkvdec_vdpu381_regs_h26x_addr {
 	u32 reserved_160;
@@ -394,6 +601,26 @@ struct rkvdec_vdpu381_regs_h26x_addr {
 	u32 reg199_cabactbl_base;
 } __packed;
 
+struct rkvdec_vdpu381_regs_vp9_addr {
+	u32 vp9_delta_prob_base;
+	u32 reserved0;
+	u32 vp9_last_prob_base;
+	u32 reserved1;
+	u32 vp9_referlast_base;
+	u32 vp9_refergolden_base;
+	u32 vp9_referalfter_base;
+	u32 vp9_count_base;
+	u32 vp9_segidlast_base;
+	u32 avp9_segidcur_base;
+	u32 vp9_refcolmv_base;
+	u32 vp9_intercmd_base;
+	u32 vp9_update_prob_wr_bas;
+	u32 reserved2[7];
+	u32 scanlist_addr;
+	u32 colmv_base[16];
+	u32 cabactbl_base;
+} __packed;
+
 struct rkvdec_vdpu381_regs_h26x_highpoc {
 	struct {
 		u32 ref0_poc_highbit	: 4;
@@ -427,4 +654,11 @@ struct rkvdec_vdpu381_regs_hevc {
 	struct rkvdec_vdpu381_regs_h26x_highpoc		hevc_highpoc;
 } __packed;
 
+struct rkvdec_vdpu381_regs_vp9 {
+	struct rkvdec_vdpu381_regs_common			common;
+	struct rkvdec_vdpu381_regs_vp9_params		vp9_param;
+	struct rkvdec_vdpu381_regs_common_addr		common_addr;
+	struct rkvdec_vdpu381_regs_vp9_addr			vp9_addr;
+} __packed;
+
 #endif /* __RKVDEC_REGS_H__ */
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c
new file mode 100644
index 000000000000..9aa75a522440
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c
@@ -0,0 +1,1067 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip Video Decoder VP9 backend
+ *
+ * Copyright (C) 2025 Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
+ *
+ * Copyright (C) 2019 Collabora, Ltd.
+ *	Boris Brezillon <boris.brezillon@collabora.com>
+ * Copyright (C) 2021 Collabora, Ltd.
+ *	Andrzej Pietrasiewicz <andrzej.p@collabora.com>
+ *
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
+ *	Alpha Lin <Alpha.Lin@rock-chips.com>
+ */
+
+/*
+ * For following the vp9 spec please start reading this driver
+ * code from rkvdec_vp9_run() followed by rkvdec_vp9_done().
+ */
+
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-vp9.h>
+
+#include "rkvdec-rcb.h"
+#include "rkvdec.h"
+#include "rkvdec-vdpu381-regs.h"
+#include "rkvdec-vp9-common.h"
+
+#define RKVDEC_VP9_PROBE_SIZE      4864
+#define RKVDEC_VP9_COUNT_SIZE      13208
+/*
+ * VP9 segmap size: ceil(width/64) * ceil(height/64) * 256 / 4
+ * For 4K (3840x2160): 60 * 34 * 64 = 130,560 bytes
+ * For 8K (7680x4320): 120 * 68 * 64 = 522,240 bytes
+ * Use 8K-safe value to cover all supported resolutions.
+ */
+#define RKVDEC_VP9_MAX_SEGMAP_SIZE 524288
+
+/* Data structure describing auxiliary buffer format. */
+struct rkvdec_vp9_priv_tbl {
+	struct rkvdec_vp9_probs probs;
+	u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE];
+};
+
+struct rkvdec_vp9_refs_counts {
+	u32 eob[2];
+	u32 coeff[3];
+};
+
+struct rkvdec_vp9_inter_frame_symbol_counts {
+	u32 partition[16][4];
+	u32 skip[3][2];
+	u32 inter[4][2];
+	u32 tx32p[2][4];
+	u32 tx16p[2][4];
+	u32 tx8p[2][2];
+	u32 y_mode[4][10];
+	u32 uv_mode[10][10];
+	u32 comp[5][2];
+	u32 comp_ref[5][2];
+	u32 single_ref[5][2][2];
+	u32 mv_mode[7][4];
+	u32 filter[4][3];
+	u32 mv_joint[4];
+	u32 sign[2][2];
+	/* add 1 element for align */
+	u32 classes[2][11 + 1];
+	u32 class0[2][2];
+	u32 bits[2][10][2];
+	u32 class0_fp[2][2][4];
+	u32 fp[2][4];
+	u32 class0_hp[2][2];
+	u32 hp[2][2];
+	struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6];
+};
+
+struct rkvdec_vp9_intra_frame_symbol_counts {
+	u32 partition[4][4][4];
+	u32 skip[3][2];
+	u32 intra[4][2];
+	u32 tx32p[2][4];
+	u32 tx16p[2][4];
+	u32 tx8p[2][2];
+	struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6];
+};
+
+struct rkvdec_vp9_frame_info {
+	u32 valid : 1;
+	u32 segmapid : 1;
+	u32 frame_context_idx : 2;
+	u32 reference_mode : 2;
+	u32 tx_mode : 3;
+	u32 interpolation_filter : 3;
+	u32 flags;
+	u64 timestamp;
+	struct v4l2_vp9_segmentation seg;
+	struct v4l2_vp9_loop_filter lf;
+};
+
+struct rkvdec_vp9_ctx {
+	struct rkvdec_aux_buf priv_tbl;
+	struct rkvdec_aux_buf count_tbl;
+	struct v4l2_vp9_frame_symbol_counts inter_cnts;
+	struct v4l2_vp9_frame_symbol_counts intra_cnts;
+	struct v4l2_vp9_frame_context probability_tables;
+	struct v4l2_vp9_frame_context frame_context[4];
+	struct rkvdec_vp9_frame_info cur;
+	struct rkvdec_vp9_frame_info last;
+	struct rkvdec_vdpu381_regs_vp9 regs;
+};
+
+static void init_intra_only_probs(struct rkvdec_ctx *ctx,
+				  const struct rkvdec_vp9_run *run)
+{
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu;
+	struct rkvdec_vp9_intra_only_frame_probs *rkprobs;
+	const struct v4l2_vp9_frame_context *probs;
+	unsigned int i, j, k;
+
+	rkprobs = &tbl->probs.intra_only;
+	probs = &vp9_ctx->probability_tables;
+
+	/*
+	 * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related
+	 * prob 64 x 128 bits
+	 */
+	for (i = 0; i < ARRAY_SIZE(probs->coef); i++) {
+		for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++)
+			write_coeff_plane(probs->coef[i][j][0],
+					  rkprobs->coef_intra[i][j]);
+	}
+
+	/* intra mode prob  80 x 128 bits */
+	for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob); i++) {
+		unsigned int byte_count = 0;
+		int idx = 0;
+
+		/* vp9_kf_y_mode_prob */
+		for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob[0]); j++) {
+			for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob[0][0]);
+			     k++) {
+				u8 val = v4l2_vp9_kf_y_mode_prob[i][j][k];
+
+				rkprobs->intra_mode[i].y_mode[idx++] = val;
+				byte_count++;
+				if (byte_count == 27) {
+					byte_count = 0;
+					idx += 5;
+				}
+			}
+		}
+	}
+
+	for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob); ++i) {
+		const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob;
+
+		rkprobs->intra_mode[i / 23].uv_mode[i % 23] = ptr[i];
+	}
+}
+
+static void init_inter_probs(struct rkvdec_ctx *ctx,
+			     const struct rkvdec_vp9_run *run)
+{
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu;
+	struct rkvdec_vp9_inter_frame_probs *rkprobs;
+	const struct v4l2_vp9_frame_context *probs;
+	unsigned int i, j, k;
+
+	rkprobs = &tbl->probs.inter;
+	probs = &vp9_ctx->probability_tables;
+
+	/*
+	 * inter probs
+	 * 151 x 128 bits, aligned to 152 x 128 bits
+	 * inter only
+	 * intra_y_mode & inter_block info 6 x 128 bits
+	 */
+
+	memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode));
+	memcpy(rkprobs->comp_mode, probs->comp_mode,
+	       sizeof(rkprobs->comp_mode));
+	memcpy(rkprobs->comp_ref, probs->comp_ref,
+	       sizeof(rkprobs->comp_ref));
+	memcpy(rkprobs->single_ref, probs->single_ref,
+	       sizeof(rkprobs->single_ref));
+	memcpy(rkprobs->inter_mode, probs->inter_mode,
+	       sizeof(rkprobs->inter_mode));
+	memcpy(rkprobs->interp_filter, probs->interp_filter,
+	       sizeof(rkprobs->interp_filter));
+
+	/* 128 x 128 bits coeff related */
+	for (i = 0; i < ARRAY_SIZE(probs->coef); i++) {
+		for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) {
+			for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++)
+				write_coeff_plane(probs->coef[i][j][k],
+						  rkprobs->coef[k][i][j]);
+		}
+	}
+
+	/* intra uv mode 6 x 128 */
+	memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0],
+	       sizeof(rkprobs->uv_mode_0_2));
+	memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3],
+	       sizeof(rkprobs->uv_mode_3_5));
+	memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6],
+	       sizeof(rkprobs->uv_mode_6_8));
+	memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9],
+	       sizeof(rkprobs->uv_mode_9));
+
+	/* mv related 6 x 128 */
+	memcpy(rkprobs->mv.joint, probs->mv.joint,
+	       sizeof(rkprobs->mv.joint));
+	memcpy(rkprobs->mv.sign, probs->mv.sign,
+	       sizeof(rkprobs->mv.sign));
+	memcpy(rkprobs->mv.classes, probs->mv.classes,
+	       sizeof(rkprobs->mv.classes));
+	memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit,
+	       sizeof(rkprobs->mv.class0_bit));
+	memcpy(rkprobs->mv.bits, probs->mv.bits,
+	       sizeof(rkprobs->mv.bits));
+	memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr,
+	       sizeof(rkprobs->mv.class0_fr));
+	memcpy(rkprobs->mv.fr, probs->mv.fr,
+	       sizeof(rkprobs->mv.fr));
+	memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp,
+	       sizeof(rkprobs->mv.class0_hp));
+	memcpy(rkprobs->mv.hp, probs->mv.hp,
+	       sizeof(rkprobs->mv.hp));
+}
+
+static void init_probs(struct rkvdec_ctx *ctx,
+		       const struct rkvdec_vp9_run *run)
+{
+	const struct v4l2_ctrl_vp9_frame *dec_params;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu;
+	struct rkvdec_vp9_probs *rkprobs = &tbl->probs;
+	const struct v4l2_vp9_segmentation *seg;
+	const struct v4l2_vp9_frame_context *probs;
+	bool intra_only;
+
+	dec_params = run->decode_params;
+	probs = &vp9_ctx->probability_tables;
+	seg = &dec_params->seg;
+
+	memset(rkprobs, 0, sizeof(*rkprobs));
+
+	intra_only = !!(dec_params->flags &
+			(V4L2_VP9_FRAME_FLAG_KEY_FRAME |
+			 V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
+
+	/* sb info  5 x 128 bit */
+	memcpy(rkprobs->partition,
+	       intra_only ? v4l2_vp9_kf_partition_probs : probs->partition,
+	       sizeof(rkprobs->partition));
+
+	memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred));
+	memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree));
+	memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip));
+	memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32));
+	memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16));
+	memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8));
+	memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter));
+
+	if (intra_only)
+		init_intra_only_probs(ctx, run);
+	else
+		init_inter_probs(ctx, run);
+}
+
+static void config_ref_registers(struct rkvdec_ctx *ctx,
+				 const struct rkvdec_vp9_run *run,
+				 struct rkvdec_decoded_buffer *ref_buf,
+				 int i)
+{
+	unsigned int aligned_pitch, aligned_height, y_len;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vdpu381_regs_vp9 *regs = &vp9_ctx->regs;
+
+	aligned_height = round_up(ref_buf->vp9.height, 64);
+
+	switch (i) {
+	case 0:
+		regs->vp9_param.reg107.vp9_frameheight_last = ref_buf->vp9.height;
+		regs->vp9_param.reg106.vp9_framewidth_last = ref_buf->vp9.width;
+		break;
+	case 1:
+		regs->vp9_param.reg109.vp9_frameheight_golden = ref_buf->vp9.height;
+		regs->vp9_param.reg108.vp9_framewidth_golden = ref_buf->vp9.width;
+		break;
+	case 2:
+		regs->vp9_param.reg111.vp9_frameheight_altref = ref_buf->vp9.height;
+		regs->vp9_param.reg110.vp9_framewidth_altref = ref_buf->vp9.width;
+		break;
+	}
+
+	switch (i) {
+	case 0:
+		regs->vp9_addr.vp9_referlast_base =
+			vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0);
+		break;
+	case 1:
+		regs->vp9_addr.vp9_refergolden_base =
+			vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0);
+		break;
+	case 2:
+		regs->vp9_addr.vp9_referalfter_base =
+			vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0);
+		break;
+	}
+
+	if (&ref_buf->base.vb == run->base.bufs.dst)
+		return;
+
+	/* Real buffer stride, not display-width-derived (see config_registers). */
+	aligned_pitch = ctx->decoded_fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
+	y_len = aligned_height * aligned_pitch;
+
+	switch (i) {
+	case 0:
+		regs->vp9_param.reg79.vp9_lastfy_hor_virstride = aligned_pitch / 16;
+		regs->vp9_param.reg80.vp9_lastfuv_hor_virstride = aligned_pitch / 16;
+		regs->vp9_param.reg85.vp9_lastfy_virstride = y_len / 16;
+		break;
+	case 1:
+		regs->vp9_param.reg81.vp9_goldenfy_hor_virstride = aligned_pitch / 16;
+		regs->vp9_param.reg82.vp9_goldenuv_hor_virstride = aligned_pitch / 16;
+		regs->vp9_param.reg86.vp9_goldeny_virstride = y_len / 16;
+		break;
+	case 2:
+		regs->vp9_param.reg83.vp9_altreffy_hor_virstride = aligned_pitch / 16;
+		regs->vp9_param.reg84.vp9_altreff_uv_hor_virstride = aligned_pitch / 16;
+		regs->vp9_param.reg87.vp9_altrefy_virstride = y_len / 16;
+		break;
+	}
+}
+
+static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
+{
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vdpu381_regs_vp9 *regs = &vp9_ctx->regs;
+	const struct v4l2_vp9_segmentation *seg;
+	s16 feature_val;
+	int feature_id;
+
+	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];
+		regs->vp9_param.reg67_74[segid].vp9_segid_frame_qp_delta_en = 1;
+		regs->vp9_param.reg67_74[segid].vp9_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];
+		regs->vp9_param.reg67_74[segid].vp9_segid_frame_loopfilter_value_en = 1;
+		regs->vp9_param.reg67_74[segid].vp9_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];
+		regs->vp9_param.reg67_74[segid].vp9_segid_referinfo_en = 1;
+		regs->vp9_param.reg67_74[segid].vp9_segid_referinfo = feature_val;
+	}
+
+	feature_id = V4L2_VP9_SEG_LVL_SKIP;
+	regs->vp9_param.reg67_74[segid].vp9_segid_frame_skip_en =
+		v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid);
+
+	regs->vp9_param.reg67_74[segid].vp9_segid_abs_delta = !segid &&
+		(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE);
+}
+
+static void update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx,
+				struct rkvdec_decoded_buffer *buf,
+				const struct v4l2_ctrl_vp9_frame *dec_params)
+{
+	vp9_ctx->cur.valid = true;
+	vp9_ctx->cur.reference_mode = dec_params->reference_mode;
+	vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter;
+	vp9_ctx->cur.flags = dec_params->flags;
+	vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp;
+	vp9_ctx->cur.seg = dec_params->seg;
+	vp9_ctx->cur.lf = dec_params->lf;
+}
+
+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_ctx *ctx)
+{
+	struct rkvdec_dev *rkvdec = ctx->dev;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+
+	rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_REGS,
+			   &vp9_ctx->regs.common,
+			   sizeof(vp9_ctx->regs.common));
+	rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_PARAMS_REGS,
+			   &vp9_ctx->regs.vp9_param,
+			   sizeof(vp9_ctx->regs.vp9_param));
+	rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_ADDR_REGS,
+			   &vp9_ctx->regs.common_addr,
+			   sizeof(vp9_ctx->regs.common_addr));
+	rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_ADDR_REGS,
+			   &vp9_ctx->regs.vp9_addr,
+			   sizeof(vp9_ctx->regs.vp9_addr));
+}
+
+static dma_addr_t get_mv_base_addr(struct rkvdec_ctx *ctx, struct rkvdec_decoded_buffer *buf)
+{
+	unsigned int aligned_pitch, aligned_height, yuv_len;
+
+	aligned_height = round_up(buf->vp9.height, 64);
+
+	aligned_pitch = ctx->decoded_fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
+	yuv_len = (aligned_height * aligned_pitch * 3) / 2;
+
+	return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) +
+	       yuv_len;
+}
+
+static void config_registers(struct rkvdec_ctx *ctx,
+			     const struct rkvdec_vp9_run *run)
+{
+	unsigned int y_len, aligned_height, aligned_pitch, stream_len;
+	const struct v4l2_ctrl_vp9_frame *dec_params;
+	struct rkvdec_decoded_buffer *ref_bufs[3];
+	struct rkvdec_decoded_buffer *dst, *last, *mv_ref;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vdpu381_regs_vp9 *regs = &vp9_ctx->regs;
+	const struct v4l2_vp9_segmentation *seg;
+	u32 pixels;
+
+	dma_addr_t rlc_addr, dst_addr;
+	bool intra_only;
+	unsigned int i;
+
+	dec_params = run->decode_params;
+	dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf);
+	ref_bufs[0] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->last_frame_ts);
+	ref_bufs[1] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->golden_frame_ts);
+	ref_bufs[2] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->alt_frame_ts);
+
+	if (vp9_ctx->last.valid)
+		last = get_ref_buf_vp9(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
+	else
+		last = dst;
+
+	update_dec_buf_info(dst, dec_params);
+	update_ctx_cur_info(vp9_ctx, dst, dec_params);
+	seg = &dec_params->seg;
+
+	intra_only = !!(dec_params->flags &
+			(V4L2_VP9_FRAME_FLAG_KEY_FRAME |
+			 V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
+
+	regs->common.reg009_dec_mode.dec_mode = VDPU381_MODE_VP9;
+
+	regs->vp9_param.reg103.vp9_intra_only_flag = intra_only;
+
+	/* Set config */
+	regs->common.reg011_important_en.buf_empty_en = 1;
+	regs->common.reg011_important_en.dec_clkgate_e = 1;
+	regs->common.reg011_important_en.dec_timeout_e = 1;
+
+	aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64);
+
+	/* use capture buffer's bytesperline as hw stride, same as HEVC. */
+	aligned_pitch = ctx->decoded_fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
+	y_len = aligned_height * aligned_pitch;
+
+	pixels = ctx->decoded_fmt.fmt.pix_mp.height * ctx->decoded_fmt.fmt.pix_mp.width;
+
+	regs->common.reg018_y_hor_stride.y_hor_virstride = aligned_pitch / 16;
+	regs->common.reg019_uv_hor_stride.uv_hor_virstride = aligned_pitch / 16;
+	regs->common.reg020_y_stride.y_virstride = y_len / 16;
+
+	stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0);
+
+	regs->common.reg016_stream_len = stream_len;
+
+	/* Activate block gating */
+	regs->common.reg026_block_gating_en.inter_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.filterd_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.strmd_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.mcp_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.busifd_auto_gating_e = 0;
+	regs->common.reg026_block_gating_en.dec_ctrl_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.intra_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.mc_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.transd_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.sram_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.cru_auto_gating_e = 1;
+	regs->common.reg026_block_gating_en.reg_cfg_gating_en = 1;
+
+	/* Set timeout threshold */
+	if (pixels < RKVDEC_1080P_PIXELS)
+		regs->common.reg032_timeout_threshold = RKVDEC_TIMEOUT_1080p;
+	else if (pixels < RKVDEC_4K_PIXELS)
+		regs->common.reg032_timeout_threshold = RKVDEC_TIMEOUT_4K;
+	else if (pixels < RKVDEC_8K_PIXELS)
+		regs->common.reg032_timeout_threshold = RKVDEC_TIMEOUT_8K;
+	else
+		regs->common.reg032_timeout_threshold = RKVDEC_TIMEOUT_MAX;
+
+	/*
+	 * Reset count buffer, because decoder only output intra related syntax
+	 * counts when decoding intra frame, but update entropy need to update
+	 * all the probabilities.
+	 */
+	if (intra_only)
+		memset(vp9_ctx->count_tbl.cpu, 0, vp9_ctx->count_tbl.size);
+
+	vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid;
+	if (!intra_only &&
+	    !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
+	    (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) ||
+	     (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP)))
+		vp9_ctx->cur.segmapid++;
+
+	for (i = 0; i < ARRAY_SIZE(ref_bufs); i++)
+		config_ref_registers(ctx, run, ref_bufs[i], i);
+
+	for (i = 0; i < 8; i++)
+		config_seg_registers(ctx, i);
+
+	regs->vp9_param.reg76.vp9_tx_mode = vp9_ctx->cur.tx_mode;
+	regs->vp9_param.reg76.vp9_frame_reference_mode = dec_params->reference_mode;
+
+	if (!intra_only) {
+		const struct v4l2_vp9_loop_filter *lf;
+
+		if (vp9_ctx->last.valid)
+			lf = &vp9_ctx->last.lf;
+		else
+			lf = &vp9_ctx->cur.lf;
+
+		for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++)
+			regs->vp9_param.reg94.vp9_ref_deltas_lastframe |=
+				(lf->ref_deltas[i] & 0x7f) << (7 * i);
+
+		for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++)
+			regs->vp9_param.reg75.vp9_mode_deltas_lastframe |=
+				(lf->mode_deltas[i] & 0x7f) << (7 * i);
+	}
+
+	regs->vp9_param.reg75.segmentation_enable_lstframe =
+		vp9_ctx->last.valid && !intra_only &&
+		vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED;
+
+	regs->vp9_param.reg75.vp9_last_showframe =
+		vp9_ctx->last.valid &&
+		vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME;
+
+	regs->vp9_param.reg75.vp9_last_intra_only =
+		vp9_ctx->last.valid &&
+		vp9_ctx->last.flags &
+		(V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY);
+
+	regs->vp9_param.reg75.vp9_last_widhheight_eqcur =
+		vp9_ctx->last.valid &&
+		last->vp9.width == dst->vp9.width &&
+		last->vp9.height == dst->vp9.height;
+
+	regs->vp9_param.reg78_vp9_stream_size = stream_len;
+
+	for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) {
+		unsigned int refw = ref_bufs[i]->vp9.width;
+		unsigned int refh = ref_bufs[i]->vp9.height;
+		u32 hscale, vscale;
+
+		hscale = (refw << 14) /	dst->vp9.width;
+		vscale = (refh << 14) / dst->vp9.height;
+
+		switch (i) {
+		case 0:
+			regs->vp9_param.reg88.vp9_lref_hor_scale = hscale;
+			regs->vp9_param.reg89.vp9_lref_ver_scale = vscale;
+			break;
+		case 1:
+			regs->vp9_param.reg90.vp9_gref_hor_scale = hscale;
+			regs->vp9_param.reg91.vp9_gref_ver_scale = vscale;
+			break;
+		case 2:
+			regs->vp9_param.reg92.vp9_aref_hor_scale = hscale;
+			regs->vp9_param.reg93.vp9_aref_ver_scale = vscale;
+			break;
+		}
+	}
+
+	/* Set rlc base address (input stream) */
+	rlc_addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0);
+	regs->common_addr.rlc_base = rlc_addr;
+	regs->common_addr.rlcwrite_base = rlc_addr;
+
+	/* Set output base address */
+	dst_addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0);
+	regs->common_addr.decout_base = dst_addr;
+	regs->common_addr.error_ref_base = dst_addr;
+
+	/* Set colmv address */
+	regs->common_addr.colmv_cur_base = dst_addr + ctx->colmv_offset;
+
+	/* Set RCB addresses */
+	for (i = 0; i < rkvdec_rcb_buf_count(ctx); i++)
+		regs->common_addr.rcb_base[i] = rkvdec_rcb_buf_dma_addr(ctx, i);
+
+	regs->vp9_addr.cabactbl_base = vp9_ctx->priv_tbl.dma +
+		offsetof(struct rkvdec_vp9_priv_tbl, probs);
+
+	regs->vp9_addr.vp9_count_base = vp9_ctx->count_tbl.dma;
+
+	regs->vp9_addr.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_addr.avp9_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) &&
+	    vp9_ctx->last.valid)
+		mv_ref = last;
+	else
+		mv_ref = dst;
+
+	regs->vp9_addr.vp9_refcolmv_base = get_mv_base_addr(ctx, mv_ref);
+
+	rkvdec_write_regs(ctx);
+}
+
+static int validate_dec_params(struct rkvdec_ctx *ctx,
+			       const struct v4l2_ctrl_vp9_frame *dec_params)
+{
+	unsigned int aligned_width, aligned_height;
+
+	aligned_width = round_up(dec_params->frame_width_minus_1 + 1, 64);
+	aligned_height = round_up(dec_params->frame_height_minus_1 + 1, 64);
+
+	/*
+	 * Userspace should update the capture/decoded format when the
+	 * resolution changes.
+	 */
+	if (aligned_width != ctx->decoded_fmt.fmt.pix_mp.width ||
+	    aligned_height != ctx->decoded_fmt.fmt.pix_mp.height) {
+		dev_err(ctx->dev->dev,
+			"unexpected bitstream resolution %dx%d\n",
+			dec_params->frame_width_minus_1 + 1,
+			dec_params->frame_height_minus_1 + 1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx,
+				   struct rkvdec_vp9_run *run)
+{
+	const struct v4l2_ctrl_vp9_frame *dec_params;
+	const struct v4l2_ctrl_vp9_compressed_hdr *prob_updates;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct v4l2_ctrl *ctrl;
+	unsigned int fctx_idx;
+	int ret;
+
+	/* v4l2-specific stuff */
+	rkvdec_run_preamble(ctx, &run->base);
+
+	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
+			      V4L2_CID_STATELESS_VP9_FRAME);
+	if (WARN_ON(!ctrl))
+		return -EINVAL;
+	dec_params = ctrl->p_cur.p;
+
+	ret = validate_dec_params(ctx, dec_params);
+	if (ret)
+		return ret;
+
+	run->decode_params = dec_params;
+
+	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_VP9_COMPRESSED_HDR);
+	if (WARN_ON(!ctrl))
+		return -EINVAL;
+	prob_updates = ctrl->p_cur.p;
+	vp9_ctx->cur.tx_mode = prob_updates->tx_mode;
+
+	/*
+	 * vp9 stuff
+	 *
+	 * by this point the userspace has done all parts of 6.2 uncompressed_header()
+	 * except this fragment:
+	 * if ( FrameIsIntra || error_resilient_mode ) {
+	 *	setup_past_independence ( )
+	 *	if ( frame_type == KEY_FRAME || error_resilient_mode == 1 ||
+	 *	     reset_frame_context == 3 ) {
+	 *		for ( i = 0; i < 4; i ++ ) {
+	 *			save_probs( i )
+	 *		}
+	 *	} else if ( reset_frame_context == 2 ) {
+	 *		save_probs( frame_context_idx )
+	 *	}
+	 *	frame_context_idx = 0
+	 * }
+	 */
+	fctx_idx = v4l2_vp9_reset_frame_ctx(dec_params, vp9_ctx->frame_context);
+	vp9_ctx->cur.frame_context_idx = fctx_idx;
+
+	/* 6.1 frame(sz): load_probs() and load_probs2() */
+	vp9_ctx->probability_tables = vp9_ctx->frame_context[fctx_idx];
+
+	/*
+	 * The userspace has also performed 6.3 compressed_header(), but handling the
+	 * probs in a special way. All probs which need updating, except MV-related,
+	 * have been read from the bitstream and translated through inv_map_table[],
+	 * but no 6.3.6 inv_recenter_nonneg(v, m) has been performed. The values passed
+	 * by userspace are either translated values (there are no 0 values in
+	 * inv_map_table[]), or zero to indicate no update. All MV-related probs which need
+	 * updating have been read from the bitstream and (mv_prob << 1) | 1 has been
+	 * performed. The values passed by userspace are either new values
+	 * to replace old ones (the above mentioned shift and bitwise or never result in
+	 * a zero) or zero to indicate no update.
+	 * fw_update_probs() performs actual probs updates or leaves probs as-is
+	 * for values for which a zero was passed from userspace.
+	 */
+	v4l2_vp9_fw_update_probs(&vp9_ctx->probability_tables, prob_updates, dec_params);
+
+	return 0;
+}
+
+static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
+{
+	struct rkvdec_dev *rkvdec = ctx->dev;
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vp9_run run = { };
+	int ret;
+	u32 watchdog_time;
+
+	ret = rkvdec_vp9_run_preamble(ctx, &run);
+
+	if (ret) {
+		rkvdec_run_postamble(ctx, &run.base);
+
+		return ret;
+	}
+
+	/* Prepare probs. */
+	init_probs(ctx, &run);
+
+	/* Configure hardware registers. */
+	config_registers(ctx, &run);
+
+	rkvdec_run_postamble(ctx, &run.base);
+
+	u64 timeout_threshold = vp9_ctx->regs.common.reg032_timeout_threshold;
+	unsigned long axi_rate = clk_get_rate(rkvdec->axi_clk);
+
+	if (axi_rate)
+		watchdog_time = 2 * (1000 * timeout_threshold) / axi_rate;
+	else
+		watchdog_time = 2000;
+
+	schedule_delayed_work(&rkvdec->watchdog_work,
+			      msecs_to_jiffies(watchdog_time));
+
+	writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E);
+
+	return 0;
+}
+
+#define copy_tx_and_skip(p1, p2)				\
+do {								\
+	memcpy((p1)->tx8, (p2)->tx8, sizeof((p1)->tx8));	\
+	memcpy((p1)->tx16, (p2)->tx16, sizeof((p1)->tx16));	\
+	memcpy((p1)->tx32, (p2)->tx32, sizeof((p1)->tx32));	\
+	memcpy((p1)->skip, (p2)->skip, sizeof((p1)->skip));	\
+} while (0)
+
+static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
+			    struct vb2_v4l2_buffer *src_buf,
+			    struct vb2_v4l2_buffer *dst_buf,
+			    enum vb2_buffer_state result)
+{
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	unsigned int fctx_idx;
+
+	/* v4l2-specific stuff */
+	if (result == VB2_BUF_STATE_ERROR)
+		goto out_update_last;
+
+	/*
+	 * vp9 stuff
+	 *
+	 * 6.1.2 refresh_probs()
+	 *
+	 * In the spec a complementary condition goes last in 6.1.2 refresh_probs(),
+	 * but it makes no sense to perform all the activities from the first "if"
+	 * there if we actually are not refreshing the frame context. On top of that,
+	 * because of 6.2 uncompressed_header() whenever error_resilient_mode == 1,
+	 * refresh_frame_context == 0. Consequently, if we don't jump to out_update_last
+	 * it means error_resilient_mode must be 0.
+	 */
+	if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX))
+		goto out_update_last;
+
+	fctx_idx = vp9_ctx->cur.frame_context_idx;
+
+	if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) {
+		/* error_resilient_mode == 0 && frame_parallel_decoding_mode == 0 */
+		struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables;
+		bool frame_is_intra = vp9_ctx->cur.flags &
+		    (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY);
+		struct tx_and_skip {
+			u8 tx8[2][1];
+			u8 tx16[2][2];
+			u8 tx32[2][3];
+			u8 skip[3];
+		} _tx_skip, *tx_skip = &_tx_skip;
+		struct v4l2_vp9_frame_symbol_counts *counts;
+
+		/* buffer the forward-updated TX and skip probs */
+		if (frame_is_intra)
+			copy_tx_and_skip(tx_skip, probs);
+
+		/* 6.1.2 refresh_probs(): load_probs() and load_probs2() */
+		*probs = vp9_ctx->frame_context[fctx_idx];
+
+		/* if FrameIsIntra then undo the effect of load_probs2() */
+		if (frame_is_intra)
+			copy_tx_and_skip(probs, tx_skip);
+
+		counts = frame_is_intra ? &vp9_ctx->intra_cnts : &vp9_ctx->inter_cnts;
+		v4l2_vp9_adapt_coef_probs(probs, counts,
+					  !vp9_ctx->last.valid ||
+					  vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME,
+					  frame_is_intra);
+		if (!frame_is_intra) {
+			const struct rkvdec_vp9_inter_frame_symbol_counts *inter_cnts;
+			u32 classes[2][11];
+			int i;
+
+			inter_cnts = vp9_ctx->count_tbl.cpu;
+			for (i = 0; i < ARRAY_SIZE(classes); ++i)
+				memcpy(classes[i], inter_cnts->classes[i], sizeof(classes[0]));
+			counts->classes = &classes;
+
+			/* load_probs2() already done */
+			v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts,
+						     vp9_ctx->cur.reference_mode,
+						     vp9_ctx->cur.interpolation_filter,
+						     vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags);
+		}
+	}
+
+	/* 6.1.2 refresh_probs(): save_probs(fctx_idx) */
+	vp9_ctx->frame_context[fctx_idx] = vp9_ctx->probability_tables;
+
+out_update_last:
+	update_ctx_last_info(vp9_ctx);
+}
+
+static void rkvdec_init_v4l2_vp9_count_tbl(struct rkvdec_ctx *ctx)
+{
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_vp9_intra_frame_symbol_counts *intra_cnts = vp9_ctx->count_tbl.cpu;
+	struct rkvdec_vp9_inter_frame_symbol_counts *inter_cnts = vp9_ctx->count_tbl.cpu;
+	int i, j, k, l, m;
+
+	vp9_ctx->inter_cnts.partition = &inter_cnts->partition;
+	vp9_ctx->inter_cnts.skip = &inter_cnts->skip;
+	vp9_ctx->inter_cnts.intra_inter = &inter_cnts->inter;
+	vp9_ctx->inter_cnts.tx32p = &inter_cnts->tx32p;
+	vp9_ctx->inter_cnts.tx16p = &inter_cnts->tx16p;
+	vp9_ctx->inter_cnts.tx8p = &inter_cnts->tx8p;
+
+	vp9_ctx->intra_cnts.partition = (u32 (*)[16][4])(&intra_cnts->partition);
+	vp9_ctx->intra_cnts.skip = &intra_cnts->skip;
+	vp9_ctx->intra_cnts.intra_inter = &intra_cnts->intra;
+	vp9_ctx->intra_cnts.tx32p = &intra_cnts->tx32p;
+	vp9_ctx->intra_cnts.tx16p = &intra_cnts->tx16p;
+	vp9_ctx->intra_cnts.tx8p = &intra_cnts->tx8p;
+
+	vp9_ctx->inter_cnts.y_mode = &inter_cnts->y_mode;
+	vp9_ctx->inter_cnts.uv_mode = &inter_cnts->uv_mode;
+	vp9_ctx->inter_cnts.comp = &inter_cnts->comp;
+	vp9_ctx->inter_cnts.comp_ref = &inter_cnts->comp_ref;
+	vp9_ctx->inter_cnts.single_ref = &inter_cnts->single_ref;
+	vp9_ctx->inter_cnts.mv_mode = &inter_cnts->mv_mode;
+	vp9_ctx->inter_cnts.filter = &inter_cnts->filter;
+	vp9_ctx->inter_cnts.mv_joint = &inter_cnts->mv_joint;
+	vp9_ctx->inter_cnts.sign = &inter_cnts->sign;
+	/*
+	 * rk hardware actually uses "u32 classes[2][11 + 1];"
+	 * instead of "u32 classes[2][11];", so this must be explicitly
+	 * copied into vp9_ctx->classes when passing the data to the
+	 * vp9 library function
+	 */
+	vp9_ctx->inter_cnts.class0 = &inter_cnts->class0;
+	vp9_ctx->inter_cnts.bits = &inter_cnts->bits;
+	vp9_ctx->inter_cnts.class0_fp = &inter_cnts->class0_fp;
+	vp9_ctx->inter_cnts.fp = &inter_cnts->fp;
+	vp9_ctx->inter_cnts.class0_hp = &inter_cnts->class0_hp;
+	vp9_ctx->inter_cnts.hp = &inter_cnts->hp;
+
+#define INNERMOST_LOOP \
+	do {										\
+		for (m = 0; m < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0][0][0][0]); ++m) {\
+			vp9_ctx->inter_cnts.coeff[i][j][k][l][m] =			\
+				&inter_cnts->ref_cnt[k][i][j][l][m].coeff;		\
+			vp9_ctx->inter_cnts.eob[i][j][k][l][m][0] =			\
+				&inter_cnts->ref_cnt[k][i][j][l][m].eob[0];		\
+			vp9_ctx->inter_cnts.eob[i][j][k][l][m][1] =			\
+				&inter_cnts->ref_cnt[k][i][j][l][m].eob[1];		\
+											\
+			vp9_ctx->intra_cnts.coeff[i][j][k][l][m] =			\
+				&intra_cnts->ref_cnt[k][i][j][l][m].coeff;		\
+			vp9_ctx->intra_cnts.eob[i][j][k][l][m][0] =			\
+				&intra_cnts->ref_cnt[k][i][j][l][m].eob[0];		\
+			vp9_ctx->intra_cnts.eob[i][j][k][l][m][1] =			\
+				&intra_cnts->ref_cnt[k][i][j][l][m].eob[1];		\
+		}									\
+	} while (0)
+
+	for (i = 0; i < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff); ++i)
+		for (j = 0; j < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0]); ++j)
+			for (k = 0; k < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0][0]); ++k)
+				for (l = 0; l < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0][0][0]); ++l)
+					INNERMOST_LOOP;
+#undef INNERMOST_LOOP
+}
+
+static int rkvdec_vp9_validate_frame(const struct v4l2_ctrl_vp9_frame *frame)
+{
+	if (frame->profile == 1 || frame->profile == 3)
+		return -EINVAL;
+
+	if (frame->bit_depth != 8 && frame->bit_depth != 10)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rkvdec_vp9_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
+{
+	if (ctrl->id == V4L2_CID_STATELESS_VP9_FRAME)
+		return rkvdec_vp9_validate_frame(ctrl->p_new.p_vp9_frame);
+
+	return 0;
+}
+
+static int rkvdec_vp9_start(struct rkvdec_ctx *ctx)
+{
+	struct rkvdec_dev *rkvdec = ctx->dev;
+	struct rkvdec_vp9_priv_tbl *priv_tbl;
+	struct rkvdec_vp9_ctx *vp9_ctx;
+	unsigned char *count_tbl;
+	struct v4l2_ctrl *ctrl;
+	int ret;
+
+	/* frame header */
+	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_VP9_FRAME);
+	if (!ctrl)
+		return -EINVAL;
+
+	ret = rkvdec_vp9_validate_frame(ctrl->p_new.p_vp9_frame);
+	if (ret)
+		return ret;
+
+	vp9_ctx = kzalloc_obj(*vp9_ctx);
+	if (!vp9_ctx)
+		return -ENOMEM;
+
+	ctx->priv = vp9_ctx;
+
+	BUILD_BUG_ON(sizeof(priv_tbl->probs) % 16); /* ensure probs size is 128-bit aligned */
+	priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl),
+				      &vp9_ctx->priv_tbl.dma, GFP_KERNEL);
+	if (!priv_tbl) {
+		ret = -ENOMEM;
+		goto err_free_ctx;
+	}
+
+	vp9_ctx->priv_tbl.size = sizeof(*priv_tbl);
+	vp9_ctx->priv_tbl.cpu = priv_tbl;
+
+	count_tbl = dma_alloc_coherent(rkvdec->dev, RKVDEC_VP9_COUNT_SIZE,
+				       &vp9_ctx->count_tbl.dma, GFP_KERNEL);
+	if (!count_tbl) {
+		ret = -ENOMEM;
+		goto err_free_priv_tbl;
+	}
+
+	vp9_ctx->count_tbl.size = RKVDEC_VP9_COUNT_SIZE;
+	vp9_ctx->count_tbl.cpu = count_tbl;
+	rkvdec_init_v4l2_vp9_count_tbl(ctx);
+
+	return 0;
+
+err_free_priv_tbl:
+	dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size,
+			  vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma);
+
+err_free_ctx:
+	kfree(vp9_ctx);
+	return ret;
+}
+
+static void rkvdec_vp9_stop(struct rkvdec_ctx *ctx)
+{
+	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+	struct rkvdec_dev *rkvdec = ctx->dev;
+
+	dma_free_coherent(rkvdec->dev, vp9_ctx->count_tbl.size,
+			  vp9_ctx->count_tbl.cpu, vp9_ctx->count_tbl.dma);
+
+	dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size,
+			  vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma);
+
+	kfree(vp9_ctx);
+}
+
+static int rkvdec_vp9_adjust_fmt(struct rkvdec_ctx *ctx,
+				 struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
+
+	fmt->num_planes = 1;
+	if (!fmt->plane_fmt[0].sizeimage)
+		fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 2;
+	return 0;
+}
+
+static enum rkvdec_image_fmt
+rkvdec_vp9_get_image_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
+{
+	const struct v4l2_ctrl_vp9_frame *frame = ctrl->p_new.p_vp9_frame;
+
+	if (ctrl->id != V4L2_CID_STATELESS_VP9_FRAME)
+		return RKVDEC_IMG_FMT_ANY;
+
+	switch (frame->bit_depth) {
+	case 8:
+		return RKVDEC_IMG_FMT_420_8BIT;
+	case 10:
+		return RKVDEC_IMG_FMT_420_10BIT;
+	default:
+		return RKVDEC_IMG_FMT_ANY;
+	}
+}
+
+const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_vp9_fmt_ops = {
+	.adjust_fmt = rkvdec_vp9_adjust_fmt,
+	.start = rkvdec_vp9_start,
+	.stop = rkvdec_vp9_stop,
+	.run = rkvdec_vp9_run,
+	.done = rkvdec_vp9_done,
+	.try_ctrl = rkvdec_vp9_try_ctrl,
+	.get_image_fmt = rkvdec_vp9_get_image_fmt,
+};
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
index 1d1e9bfef8e9..436bb460f04e 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
@@ -443,6 +443,45 @@ static const struct rkvdec_decoded_fmt_desc rkvdec_vp9_decoded_fmts[] = {
 	},
 };
 
+static const struct rkvdec_ctrl_desc vdpu381_vp9_ctrl_descs[] = {
+	{
+		.cfg.id = V4L2_CID_STATELESS_VP9_FRAME,
+		.cfg.ops = &rkvdec_ctrl_ops,
+	},
+	{
+		.cfg.id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
+	},
+	{
+		.cfg.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
+		.cfg.min = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+		.cfg.max = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+		.cfg.def = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+		/* profiles 1/3 are 4:2:2/4:4:4 which VDPU381 cannot decode */
+		.cfg.menu_skip_mask = BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_1),
+	},
+	{
+		.cfg.id = V4L2_CID_MPEG_VIDEO_VP9_LEVEL,
+		.cfg.min = V4L2_MPEG_VIDEO_VP9_LEVEL_1_0,
+		.cfg.max = V4L2_MPEG_VIDEO_VP9_LEVEL_6_1,
+	},
+};
+
+static const struct rkvdec_ctrls vdpu381_vp9_ctrls = {
+	.ctrls = vdpu381_vp9_ctrl_descs,
+	.num_ctrls = ARRAY_SIZE(vdpu381_vp9_ctrl_descs),
+};
+
+static const struct rkvdec_decoded_fmt_desc rkvdec_vdpu381_vp9_decoded_fmts[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.image_fmt = RKVDEC_IMG_FMT_420_8BIT,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV15,
+		.image_fmt =  RKVDEC_IMG_FMT_420_10BIT,
+	},
+};
+
 static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
 	{
 		.fourcc = V4L2_PIX_FMT_HEVC_SLICE,
@@ -543,6 +582,21 @@ static const struct rkvdec_coded_fmt_desc vdpu381_coded_fmts[] = {
 		.decoded_fmts = rkvdec_h264_decoded_fmts,
 		.subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF,
 	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9_FRAME,
+		.frmsize = {
+			.min_width = 64,
+			.max_width = 65472,
+			.step_width = 64,
+			.min_height = 64,
+			.max_height = 65472,
+			.step_height = 64,
+		},
+		.ctrls = &vdpu381_vp9_ctrls,
+		.ops = &rkvdec_vdpu381_vp9_fmt_ops,
+		.num_decoded_fmts = ARRAY_SIZE(rkvdec_vdpu381_vp9_decoded_fmts),
+		.decoded_fmts = rkvdec_vdpu381_vp9_decoded_fmts,
+	}
 };
 
 static const struct rkvdec_coded_fmt_desc vdpu383_coded_fmts[] = {
@@ -799,6 +853,13 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv,
 	 * Note that this will propagates any size changes to the decoded format.
 	 */
 	ctx->image_fmt = RKVDEC_IMG_FMT_ANY;
+
+	/* VP9 bit depth is per-frame, not up-front like HEVC's SPS;
+	 * default to 8-bit/NV12 until get_image_fmt() switches it.
+	 */
+	if (desc->fourcc == V4L2_PIX_FMT_VP9_FRAME)
+		ctx->image_fmt = RKVDEC_IMG_FMT_420_8BIT;
+
 	rkvdec_reset_decoded_fmt(ctx);
 
 	/* Propagate colorspace information to capture. */
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
index a24be6638b6b..d73ec9442a69 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
@@ -191,6 +191,7 @@ extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops;
 /* VDPU381 ops */
 extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_h264_fmt_ops;
 extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_hevc_fmt_ops;
+extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu381_vp9_fmt_ops;
 
 /* VDPU383 ops */
 extern const struct rkvdec_coded_fmt_ops rkvdec_vdpu383_h264_fmt_ops;

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
  2026-07-26 20:25 [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
                   ` (2 preceding siblings ...)
  2026-07-26 20:25 ` [PATCH 3/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
@ 2026-07-26 20:25 ` Venkata Atchuta Bheemeswara Sarma Darbha
  2026-07-27 15:58   ` Detlev Casanova
  2026-07-27  6:44 ` [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Francesco Saverio Pavone
  4 siblings, 1 reply; 11+ messages in thread
From: Venkata Atchuta Bheemeswara Sarma Darbha @ 2026-07-26 20:25 UTC (permalink / raw)
  To: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne, Igor Paunovic, Francesco Saverio Pavone,
	Venkata Atchuta Bheemeswara Sarma Darbha

From: Igor Paunovic <royalnet026@gmail.com>

Ensure bytesperline is 64-byte aligned and scale sizeimage accordingly.

Signed-off-by: Igor Paunovic <royalnet026@gmail.com>
Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
---
 drivers/media/platform/rockchip/rkvdec/rkvdec.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
index 436bb460f04e..6ab6530b1cc9 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
@@ -102,12 +102,20 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
 				       struct v4l2_pix_format_mplane *pix_mp)
 {
 	const struct rkvdec_variant *variant = ctx->dev->variant;
+	struct v4l2_plane_pix_format *plane = &pix_mp->plane_fmt[0];
+	u32 aligned_bpl;
 
 	v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width, pix_mp->height);
 
-	ctx->colmv_offset = pix_mp->plane_fmt[0].sizeimage;
+	/* ensure bpl is 64 byte aligned and scale sizeimage accordingly. */
+	aligned_bpl = ALIGN(plane->bytesperline, 64);
+	if (aligned_bpl != plane->bytesperline) {
+		plane->sizeimage = plane->sizeimage / plane->bytesperline * aligned_bpl;
+		plane->bytesperline = aligned_bpl;
+	}
 
-	pix_mp->plane_fmt[0].sizeimage += variant->ops->colmv_size(pix_mp->width, pix_mp->height);
+	ctx->colmv_offset = plane->sizeimage;
+	plane->sizeimage += variant->ops->colmv_size(pix_mp->width, pix_mp->height);
 }
 
 static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f,

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant
  2026-07-26 20:25 [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
                   ` (3 preceding siblings ...)
  2026-07-26 20:25 ` [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt() Venkata Atchuta Bheemeswara Sarma Darbha
@ 2026-07-27  6:44 ` Francesco Saverio Pavone
  2026-07-27  8:25   ` Igor Paunovic
  4 siblings, 1 reply; 11+ messages in thread
From: Francesco Saverio Pavone @ 2026-07-27  6:44 UTC (permalink / raw)
  To: Venkata Atchuta Bheemeswara Sarma Darbha
  Cc: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner, linux-media, linux-rockchip, linux-arm-kernel,
	linux-kernel, Nicolas Dufresne, Igor Paunovic

Rock 5B+ leg of the three-board run in the cover letter, as a tag you can
pick up. 7.1 base carrying this code, not a build of the series as posted.

Francesco Saverio Pavone <pavone.lawyer@gmail.com>


Il giorno dom 26 lug 2026 alle ore 22:28 Venkata Atchuta Bheemeswara
Sarma Darbha <vdarbha0473@gmail.com> ha scritto:
>
> Hi All,
> This patch series adds the initial VP9 support for VDPU381 present in rk3588.
>
> VDPU381 supports VP9 Profile 0 and Profile 2 up to 7680x4320@30fps.
>
> Tested with fluster (suite : VP9-TEST-VECTORS, decoder: GStreamer-VP9-V4L2SL-Gst1.0).
> The 224/305 score has been reproduced independently on three RK3588 boards
> across three kernel bases: Orange Pi 5 Pro (RK3588S, 7.2.0-rc3),
> Orange Pi 5 Plus (RK3588, 7.0) and Radxa Rock 5B+ (RK3588, 7.1).
>
> Most of the remaining failures fall into a few known categories:
>
> - All vp90-2-02-size-*.webm variants where either dimension is
>   smaller than 64 pixels fail because the hardware does not support
>   frames smaller than 64x64:
>   vp90-2-02-size-08x08.webm, vp90-2-02-size-08x10.webm,
>   vp90-2-02-size-08x16.webm, vp90-2-02-size-08x18.webm,
>   vp90-2-02-size-08x32.webm, vp90-2-02-size-08x34.webm,
>   vp90-2-02-size-08x64.webm, vp90-2-02-size-08x66.webm,
>   vp90-2-02-size-10x08.webm, vp90-2-02-size-10x10.webm,
>   vp90-2-02-size-10x16.webm, vp90-2-02-size-10x18.webm,
>   vp90-2-02-size-10x32.webm, vp90-2-02-size-10x34.webm,
>   vp90-2-02-size-10x64.webm, vp90-2-02-size-10x66.webm,
>   vp90-2-02-size-16x08.webm, vp90-2-02-size-16x10.webm,
>   vp90-2-02-size-16x16.webm, vp90-2-02-size-16x18.webm,
>   vp90-2-02-size-16x32.webm, vp90-2-02-size-16x34.webm,
>   vp90-2-02-size-16x64.webm, vp90-2-02-size-16x66.webm,
>   vp90-2-02-size-18x08.webm, vp90-2-02-size-18x10.webm,
>   vp90-2-02-size-18x18.webm, vp90-2-02-size-18x32.webm,
>   vp90-2-02-size-18x34.webm, vp90-2-02-size-18x64.webm,
>   vp90-2-02-size-18x66.webm, vp90-2-02-size-32x08.webm,
>   vp90-2-02-size-32x10.webm, vp90-2-02-size-32x18.webm,
>   vp90-2-02-size-32x34.webm, vp90-2-02-size-32x66.webm,
>   vp90-2-02-size-34x08.webm, vp90-2-02-size-34x10.webm,
>   vp90-2-02-size-34x16.webm, vp90-2-02-size-34x34.webm,
>   vp90-2-02-size-34x64.webm, vp90-2-02-size-34x66.webm,
>   vp90-2-02-size-64x08.webm, vp90-2-02-size-64x10.webm,
>   vp90-2-02-size-66x08.webm, vp90-2-02-size-66x10.webm.
>
> - vp90-2-05-resize.ivf, vp90-2-18-resize.ivf and all
>   vp90-2-21-resize_inter_*.webm variants fail. These streams change
>   resolution mid-stream on a non-keyframe, and a reference frame
>   from before the resize ends up unavailable by the time it's
>   needed again. This is being actively looked into:
>   vp90-2-05-resize.ivf, vp90-2-18-resize.ivf,
>   vp90-2-21-resize_inter_1280x720_5_1-2.webm,
>   vp90-2-21-resize_inter_1280x720_5_3-4.webm,
>   vp90-2-21-resize_inter_1280x720_7_1-2.webm,
>   vp90-2-21-resize_inter_1280x720_7_3-4.webm,
>   vp90-2-21-resize_inter_1920x1080_5_1-2.webm,
>   vp90-2-21-resize_inter_1920x1080_5_3-4.webm,
>   vp90-2-21-resize_inter_1920x1080_7_1-2.webm,
>   vp90-2-21-resize_inter_1920x1080_7_3-4.webm,
>   vp90-2-21-resize_inter_320x180_5_1-2.webm,
>   vp90-2-21-resize_inter_320x180_5_3-4.webm,
>   vp90-2-21-resize_inter_320x180_7_1-2.webm,
>   vp90-2-21-resize_inter_320x180_7_3-4.webm,
>   vp90-2-21-resize_inter_320x240_5_1-2.webm,
>   vp90-2-21-resize_inter_320x240_5_3-4.webm,
>   vp90-2-21-resize_inter_320x240_7_1-2.webm,
>   vp90-2-21-resize_inter_320x240_7_3-4.webm,
>   vp90-2-21-resize_inter_640x360_5_1-2.webm,
>   vp90-2-21-resize_inter_640x360_5_3-4.webm,
>   vp90-2-21-resize_inter_640x360_7_1-2.webm,
>   vp90-2-21-resize_inter_640x360_7_3-4.webm,
>   vp90-2-21-resize_inter_640x480_5_1-2.webm,
>   vp90-2-21-resize_inter_640x480_5_3-4.webm,
>   vp90-2-21-resize_inter_640x480_7_1-2.webm,
>   vp90-2-21-resize_inter_640x480_7_3-4.webm.
>
> - vp90-2-09-aq2.webm,
>   vp90-2-09-lf_deltas.webm,
>   vp90-2-15-segkey_adpq.webm,
>   vp90-2-19-skip-01.webm,
>   vp90-2-19-skip-02.webm,
>   vp90-2-19-skip.webm,  vp90-2-22-svc_1280x720_3.ivf,
>   are still failing and not yet root-caused.
>
> - vp91-2-04-yuv422.webm
>   vp91-2-04-yuv444.webm
>   fail because the hardware does not support the format these
>   streams use (4:2:2/4:4:4), only 4:2:0.
>
> The base vdpu381 VP9 driver support was introduced by me. Profile 2 support
> was added by Igor Paunovic. Francesco Saverio Pavone fixed bugs in
> the segmentation map size calculation and in the altref vertical
> scale factor. Igor Paunovic also fixed a decoded-frame stride bug, aligning
> bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt().
>
> ---
> Igor Paunovic (1):
>       media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
>
> Venkata Atchuta Bheemeswara Sarma Darbha (3):
>       media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9
>       media: rkvdec: Move vp9 functions to common file
>       media: rkvdec: Add VP9 support for VDPU381 variant
>
>  drivers/media/platform/rockchip/rkvdec/Makefile    |    2 +
>  .../platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h |  234 +++++
>  .../platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c  | 1067 ++++++++++++++++++++
>  .../platform/rockchip/rkvdec/rkvdec-vp9-common.c   |   65 ++
>  .../platform/rockchip/rkvdec/rkvdec-vp9-common.h   |   92 ++
>  .../media/platform/rockchip/rkvdec/rkvdec-vp9.c    |  121 +--
>  drivers/media/platform/rockchip/rkvdec/rkvdec.c    |   73 +-
>  drivers/media/platform/rockchip/rkvdec/rkvdec.h    |    1 +
>  8 files changed, 1537 insertions(+), 118 deletions(-)
> ---
> base-commit: 1229e2e57a5c2980ccd457b9b53ea0eed5a22ab3
> change-id: 20260726-b4-add-rkvdec2-vp9-vdpu381-3d1bd8fca4f5
>
> Best regards,
> --
> Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant
  2026-07-27  6:44 ` [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Francesco Saverio Pavone
@ 2026-07-27  8:25   ` Igor Paunovic
  0 siblings, 0 replies; 11+ messages in thread
From: Igor Paunovic @ 2026-07-27  8:25 UTC (permalink / raw)
  To: Francesco Saverio Pavone
  Cc: Venkata Atchuta Bheemeswara Sarma Darbha, Detlev Casanova,
	Ezequiel Garcia, Mauro Carvalho Chehab, Heiko Stuebner,
	linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne

Orange Pi 5 Plus leg of the three-board run in the cover letter, as a
tag you can pick up. 7.0 base carrying this code, not a build of the
series as posted.

Tested-by: Igor Paunovic royalnet026@gmail.com


On Mon, Jul 27, 2026 at 8:44 AM Francesco Saverio Pavone
<pavone.lawyer@gmail.com> wrote:
>
> Rock 5B+ leg of the three-board run in the cover letter, as a tag you can
> pick up. 7.1 base carrying this code, not a build of the series as posted.
>
> Francesco Saverio Pavone <pavone.lawyer@gmail.com>
>
>
> Il giorno dom 26 lug 2026 alle ore 22:28 Venkata Atchuta Bheemeswara
> Sarma Darbha <vdarbha0473@gmail.com> ha scritto:
> >
> > Hi All,
> > This patch series adds the initial VP9 support for VDPU381 present in rk3588.
> >
> > VDPU381 supports VP9 Profile 0 and Profile 2 up to 7680x4320@30fps.
> >
> > Tested with fluster (suite : VP9-TEST-VECTORS, decoder: GStreamer-VP9-V4L2SL-Gst1.0).
> > The 224/305 score has been reproduced independently on three RK3588 boards
> > across three kernel bases: Orange Pi 5 Pro (RK3588S, 7.2.0-rc3),
> > Orange Pi 5 Plus (RK3588, 7.0) and Radxa Rock 5B+ (RK3588, 7.1).
> >
> > Most of the remaining failures fall into a few known categories:
> >
> > - All vp90-2-02-size-*.webm variants where either dimension is
> >   smaller than 64 pixels fail because the hardware does not support
> >   frames smaller than 64x64:
> >   vp90-2-02-size-08x08.webm, vp90-2-02-size-08x10.webm,
> >   vp90-2-02-size-08x16.webm, vp90-2-02-size-08x18.webm,
> >   vp90-2-02-size-08x32.webm, vp90-2-02-size-08x34.webm,
> >   vp90-2-02-size-08x64.webm, vp90-2-02-size-08x66.webm,
> >   vp90-2-02-size-10x08.webm, vp90-2-02-size-10x10.webm,
> >   vp90-2-02-size-10x16.webm, vp90-2-02-size-10x18.webm,
> >   vp90-2-02-size-10x32.webm, vp90-2-02-size-10x34.webm,
> >   vp90-2-02-size-10x64.webm, vp90-2-02-size-10x66.webm,
> >   vp90-2-02-size-16x08.webm, vp90-2-02-size-16x10.webm,
> >   vp90-2-02-size-16x16.webm, vp90-2-02-size-16x18.webm,
> >   vp90-2-02-size-16x32.webm, vp90-2-02-size-16x34.webm,
> >   vp90-2-02-size-16x64.webm, vp90-2-02-size-16x66.webm,
> >   vp90-2-02-size-18x08.webm, vp90-2-02-size-18x10.webm,
> >   vp90-2-02-size-18x18.webm, vp90-2-02-size-18x32.webm,
> >   vp90-2-02-size-18x34.webm, vp90-2-02-size-18x64.webm,
> >   vp90-2-02-size-18x66.webm, vp90-2-02-size-32x08.webm,
> >   vp90-2-02-size-32x10.webm, vp90-2-02-size-32x18.webm,
> >   vp90-2-02-size-32x34.webm, vp90-2-02-size-32x66.webm,
> >   vp90-2-02-size-34x08.webm, vp90-2-02-size-34x10.webm,
> >   vp90-2-02-size-34x16.webm, vp90-2-02-size-34x34.webm,
> >   vp90-2-02-size-34x64.webm, vp90-2-02-size-34x66.webm,
> >   vp90-2-02-size-64x08.webm, vp90-2-02-size-64x10.webm,
> >   vp90-2-02-size-66x08.webm, vp90-2-02-size-66x10.webm.
> >
> > - vp90-2-05-resize.ivf, vp90-2-18-resize.ivf and all
> >   vp90-2-21-resize_inter_*.webm variants fail. These streams change
> >   resolution mid-stream on a non-keyframe, and a reference frame
> >   from before the resize ends up unavailable by the time it's
> >   needed again. This is being actively looked into:
> >   vp90-2-05-resize.ivf, vp90-2-18-resize.ivf,
> >   vp90-2-21-resize_inter_1280x720_5_1-2.webm,
> >   vp90-2-21-resize_inter_1280x720_5_3-4.webm,
> >   vp90-2-21-resize_inter_1280x720_7_1-2.webm,
> >   vp90-2-21-resize_inter_1280x720_7_3-4.webm,
> >   vp90-2-21-resize_inter_1920x1080_5_1-2.webm,
> >   vp90-2-21-resize_inter_1920x1080_5_3-4.webm,
> >   vp90-2-21-resize_inter_1920x1080_7_1-2.webm,
> >   vp90-2-21-resize_inter_1920x1080_7_3-4.webm,
> >   vp90-2-21-resize_inter_320x180_5_1-2.webm,
> >   vp90-2-21-resize_inter_320x180_5_3-4.webm,
> >   vp90-2-21-resize_inter_320x180_7_1-2.webm,
> >   vp90-2-21-resize_inter_320x180_7_3-4.webm,
> >   vp90-2-21-resize_inter_320x240_5_1-2.webm,
> >   vp90-2-21-resize_inter_320x240_5_3-4.webm,
> >   vp90-2-21-resize_inter_320x240_7_1-2.webm,
> >   vp90-2-21-resize_inter_320x240_7_3-4.webm,
> >   vp90-2-21-resize_inter_640x360_5_1-2.webm,
> >   vp90-2-21-resize_inter_640x360_5_3-4.webm,
> >   vp90-2-21-resize_inter_640x360_7_1-2.webm,
> >   vp90-2-21-resize_inter_640x360_7_3-4.webm,
> >   vp90-2-21-resize_inter_640x480_5_1-2.webm,
> >   vp90-2-21-resize_inter_640x480_5_3-4.webm,
> >   vp90-2-21-resize_inter_640x480_7_1-2.webm,
> >   vp90-2-21-resize_inter_640x480_7_3-4.webm.
> >
> > - vp90-2-09-aq2.webm,
> >   vp90-2-09-lf_deltas.webm,
> >   vp90-2-15-segkey_adpq.webm,
> >   vp90-2-19-skip-01.webm,
> >   vp90-2-19-skip-02.webm,
> >   vp90-2-19-skip.webm,  vp90-2-22-svc_1280x720_3.ivf,
> >   are still failing and not yet root-caused.
> >
> > - vp91-2-04-yuv422.webm
> >   vp91-2-04-yuv444.webm
> >   fail because the hardware does not support the format these
> >   streams use (4:2:2/4:4:4), only 4:2:0.
> >
> > The base vdpu381 VP9 driver support was introduced by me. Profile 2 support
> > was added by Igor Paunovic. Francesco Saverio Pavone fixed bugs in
> > the segmentation map size calculation and in the altref vertical
> > scale factor. Igor Paunovic also fixed a decoded-frame stride bug, aligning
> > bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt().
> >
> > ---
> > Igor Paunovic (1):
> >       media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
> >
> > Venkata Atchuta Bheemeswara Sarma Darbha (3):
> >       media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9
> >       media: rkvdec: Move vp9 functions to common file
> >       media: rkvdec: Add VP9 support for VDPU381 variant
> >
> >  drivers/media/platform/rockchip/rkvdec/Makefile    |    2 +
> >  .../platform/rockchip/rkvdec/rkvdec-vdpu381-regs.h |  234 +++++
> >  .../platform/rockchip/rkvdec/rkvdec-vdpu381-vp9.c  | 1067 ++++++++++++++++++++
> >  .../platform/rockchip/rkvdec/rkvdec-vp9-common.c   |   65 ++
> >  .../platform/rockchip/rkvdec/rkvdec-vp9-common.h   |   92 ++
> >  .../media/platform/rockchip/rkvdec/rkvdec-vp9.c    |  121 +--
> >  drivers/media/platform/rockchip/rkvdec/rkvdec.c    |   73 +-
> >  drivers/media/platform/rockchip/rkvdec/rkvdec.h    |    1 +
> >  8 files changed, 1537 insertions(+), 118 deletions(-)
> > ---
> > base-commit: 1229e2e57a5c2980ccd457b9b53ea0eed5a22ab3
> > change-id: 20260726-b4-add-rkvdec2-vp9-vdpu381-3d1bd8fca4f5
> >
> > Best regards,
> > --
> > Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
> >


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
  2026-07-26 20:25 ` [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt() Venkata Atchuta Bheemeswara Sarma Darbha
@ 2026-07-27 15:58   ` Detlev Casanova
  2026-07-27 17:07     ` Igor Paunovic
  0 siblings, 1 reply; 11+ messages in thread
From: Detlev Casanova @ 2026-07-27 15:58 UTC (permalink / raw)
  To: Ezequiel Garcia, Mauro Carvalho Chehab, Heiko Stuebner,
	Venkata Atchuta Bheemeswara Sarma Darbha
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne, Igor Paunovic, Francesco Saverio Pavone,
	Venkata Atchuta Bheemeswara Sarma Darbha

Hi !

On Sunday, 26 July 2026 16:25:37 EDT Venkata Atchuta Bheemeswara Sarma Darbha 
wrote:
> From: Igor Paunovic <royalnet026@gmail.com>
> 
> Ensure bytesperline is 64-byte aligned and scale sizeimage accordingly.
> 
> Signed-off-by: Igor Paunovic <royalnet026@gmail.com>
> Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
> Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha
> <vdarbha0473@gmail.com> ---
>  drivers/media/platform/rockchip/rkvdec/rkvdec.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index
> 436bb460f04e..6ab6530b1cc9 100644
> --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> @@ -102,12 +102,20 @@ static void rkvdec_fill_decoded_pixfmt(struct
> rkvdec_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp)
>  {
>  	const struct rkvdec_variant *variant = ctx->dev->variant;
> +	struct v4l2_plane_pix_format *plane = &pix_mp->plane_fmt[0];
> +	u32 aligned_bpl;
> 
>  	v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width,
> pix_mp->height);
> 
> -	ctx->colmv_offset = pix_mp->plane_fmt[0].sizeimage;
> +	/* ensure bpl is 64 byte aligned and scale sizeimage accordingly. 
*/
> +	aligned_bpl = ALIGN(plane->bytesperline, 64);
> +	if (aligned_bpl != plane->bytesperline) {
> +		plane->sizeimage = plane->sizeimage / plane-
>bytesperline * aligned_bpl;
> +		plane->bytesperline = aligned_bpl;
> +	}

This shouldn't be needed. As you set step_width to 64, 
v4l2_apply_frmsize_constraints() should already do the alignment.

Do you have more context as to when width is not aligned ?

> 
> -	pix_mp->plane_fmt[0].sizeimage += variant->ops->colmv_size(pix_mp-
>width,
> pix_mp->height); +	ctx->colmv_offset = plane->sizeimage;
> +	plane->sizeimage += variant->ops->colmv_size(pix_mp->width,
> pix_mp->height); }
> 
>  static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f,

Regards,
Detlev.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
  2026-07-27 15:58   ` Detlev Casanova
@ 2026-07-27 17:07     ` Igor Paunovic
  2026-07-27 17:42       ` Francesco Saverio Pavone
  0 siblings, 1 reply; 11+ messages in thread
From: Igor Paunovic @ 2026-07-27 17:07 UTC (permalink / raw)
  To: Detlev Casanova
  Cc: Ezequiel Garcia, Mauro Carvalho Chehab, Heiko Stuebner,
	Venkata Atchuta Bheemeswara Sarma Darbha, linux-media,
	linux-rockchip, linux-arm-kernel, linux-kernel, Nicolas Dufresne,
	Francesco Saverio Pavone

Hi

> This shouldn't be needed. As you set step_width to 64,
> v4l2_apply_frmsize_constraints() should already do the alignment.
> Do you have more context as to when width is not aligned ?

You're right that the width is aligned -- step_width = 64 handles that.
This isn't the width though, it's the stride, and it only bites on the
10-bit (Profile 2) capture format.

For 8-bit NV12 the luma stride equals the width, so once the width is
64-aligned the stride is too and this block is a no-op.

The 10-bit capture format is NV15, whose luma stride is width * 5 / 4
(bpp {5, 10}, bpp_div {4, 4} in v4l2-common.c). That isn't a multiple
of 64 even when the width is: a 1920-wide Profile 2 frame gives a
2400-byte stride, while the VDPU381 needs the luma stride 64-byte
aligned (2432). v4l2_apply_frmsize_constraints() only rounds the width
and height, and v4l2_fill_pixfmt_mp() fills the stride with alignment 1,
so NV15 comes out unaligned and the decoded frame is corrupted without
this. I can show the before/after on a 10-bit vector if that's useful.

If you'd rather express it through the framework than with a manual
ALIGN() here, v4l2_fill_pixfmt_mp_aligned(pixfmt, pixelformat, width,
height, 64) produces the same bytesperline and sizeimage -- happy to
switch to that in v2.

Igor


On Mon, Jul 27, 2026 at 5:58 PM Detlev Casanova
<detlev.casanova@collabora.com> wrote:
>
> Hi !
>
> On Sunday, 26 July 2026 16:25:37 EDT Venkata Atchuta Bheemeswara Sarma Darbha
> wrote:
> > From: Igor Paunovic <royalnet026@gmail.com>
> >
> > Ensure bytesperline is 64-byte aligned and scale sizeimage accordingly.
> >
> > Signed-off-by: Igor Paunovic <royalnet026@gmail.com>
> > Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
> > Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha
> > <vdarbha0473@gmail.com> ---
> >  drivers/media/platform/rockchip/rkvdec/rkvdec.c | 12 ++++++++++--
> >  1 file changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index
> > 436bb460f04e..6ab6530b1cc9 100644
> > --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > @@ -102,12 +102,20 @@ static void rkvdec_fill_decoded_pixfmt(struct
> > rkvdec_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp)
> >  {
> >       const struct rkvdec_variant *variant = ctx->dev->variant;
> > +     struct v4l2_plane_pix_format *plane = &pix_mp->plane_fmt[0];
> > +     u32 aligned_bpl;
> >
> >       v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width,
> > pix_mp->height);
> >
> > -     ctx->colmv_offset = pix_mp->plane_fmt[0].sizeimage;
> > +     /* ensure bpl is 64 byte aligned and scale sizeimage accordingly.
> */
> > +     aligned_bpl = ALIGN(plane->bytesperline, 64);
> > +     if (aligned_bpl != plane->bytesperline) {
> > +             plane->sizeimage = plane->sizeimage / plane-
> >bytesperline * aligned_bpl;
> > +             plane->bytesperline = aligned_bpl;
> > +     }
>
> This shouldn't be needed. As you set step_width to 64,
> v4l2_apply_frmsize_constraints() should already do the alignment.
>
> Do you have more context as to when width is not aligned ?
>
> >
> > -     pix_mp->plane_fmt[0].sizeimage += variant->ops->colmv_size(pix_mp-
> >width,
> > pix_mp->height); +    ctx->colmv_offset = plane->sizeimage;
> > +     plane->sizeimage += variant->ops->colmv_size(pix_mp->width,
> > pix_mp->height); }
> >
> >  static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f,
>
> Regards,
> Detlev.
>
>
>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
  2026-07-27 17:07     ` Igor Paunovic
@ 2026-07-27 17:42       ` Francesco Saverio Pavone
  2026-07-27 17:56         ` Igor Paunovic
  0 siblings, 1 reply; 11+ messages in thread
From: Francesco Saverio Pavone @ 2026-07-27 17:42 UTC (permalink / raw)
  To: Igor Paunovic
  Cc: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner, Venkata Atchuta Bheemeswara Sarma Darbha,
	linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne

Hi,

> The 10-bit capture format is NV15, whose luma stride is width * 5 / 4
> [...] while the VDPU381 needs the luma stride 64-byte aligned (2432).
> [...] so NV15 comes out unaligned and the decoded frame is corrupted
> without this. I can show the before/after on a 10-bit vector if that's
> useful.

The arithmetic is right, the hardware requirement does not reproduce here.
I built the same tree twice, changing only this hunk, and measured on a
Rock 5B+ (RK3588, VDPU381):
test with ALIGN without ALIGN libvpx
1920x1080 VP9 Profile 2, 10-bit 8f40faddd32e 8f40faddd32e 8f40faddd32e
1080x1920 VP9 Profile 2, 10-bit 68400b913caa 68400b913caa 68400b913caa
fluster VP9-TEST-VECTORS 224/305 224/305 -
Both clips are the shapes that reach the ALIGN: 1920 gives an NV15 stride
of 2400 (2400 % 64 = 32) and the portrait clip rounds to a capture width of
1088, stride 1360 (1360 % 64 = 16). md5 is of the decoded frames converted
to I420, same pipeline for hardware and software. The 8-bit control on the
same pipeline is byte-identical too, so the comparison is not hiding a
conversion artefact.
That matches what the registers ask for. The stride goes into the hardware
as bytesperline / 16 (y_hor_virstride, uv_hor_virstride, and the VP9
reference ones), and width * 5 / 4 with a 64-aligned width is always a
multiple of 16, so step_width = 64 already guarantees the alignment the
hardware needs. Rounding to 64 only pads the stride reported to userspace,
for every variant and every coded format, not just the 10-bit case.
If you did see corruption without this, I suspect the other hunk in the
same patch was missing too. Taking the MV and reference pitch from
bytesperline instead of the bitstream width is the part that makes the
register value and the buffer layout agree, and it is the one I would keep.
My A/B has that hunk on both sides, so what I varied is only the ALIGN. If
you have a vector that fails with the pitch fix in place and the ALIGN
removed, I would like to run it.
One small thing on the v2 suggestion: v4l2_fill_pixfmt_mp_aligned() does
not exist in 7.2-rc5. v4l2-common.h exports v4l2_fill_pixfmt() and
v4l2_fill_pixfmt_mp() only, so that would be a new helper to add rather
than a drop-in replacement.

Sav

Il giorno lun 27 lug 2026 alle ore 19:07 Igor Paunovic
<royalnet026@gmail.com> ha scritto:
>
> Hi
>
> > This shouldn't be needed. As you set step_width to 64,
> > v4l2_apply_frmsize_constraints() should already do the alignment.
> > Do you have more context as to when width is not aligned ?
>
> You're right that the width is aligned -- step_width = 64 handles that.
> This isn't the width though, it's the stride, and it only bites on the
> 10-bit (Profile 2) capture format.
>
> For 8-bit NV12 the luma stride equals the width, so once the width is
> 64-aligned the stride is too and this block is a no-op.
>
> The 10-bit capture format is NV15, whose luma stride is width * 5 / 4
> (bpp {5, 10}, bpp_div {4, 4} in v4l2-common.c). That isn't a multiple
> of 64 even when the width is: a 1920-wide Profile 2 frame gives a
> 2400-byte stride, while the VDPU381 needs the luma stride 64-byte
> aligned (2432). v4l2_apply_frmsize_constraints() only rounds the width
> and height, and v4l2_fill_pixfmt_mp() fills the stride with alignment 1,
> so NV15 comes out unaligned and the decoded frame is corrupted without
> this. I can show the before/after on a 10-bit vector if that's useful.
>
> If you'd rather express it through the framework than with a manual
> ALIGN() here, v4l2_fill_pixfmt_mp_aligned(pixfmt, pixelformat, width,
> height, 64) produces the same bytesperline and sizeimage -- happy to
> switch to that in v2.
>
> Igor
>
>
> On Mon, Jul 27, 2026 at 5:58 PM Detlev Casanova
> <detlev.casanova@collabora.com> wrote:
> >
> > Hi !
> >
> > On Sunday, 26 July 2026 16:25:37 EDT Venkata Atchuta Bheemeswara Sarma Darbha
> > wrote:
> > > From: Igor Paunovic <royalnet026@gmail.com>
> > >
> > > Ensure bytesperline is 64-byte aligned and scale sizeimage accordingly.
> > >
> > > Signed-off-by: Igor Paunovic <royalnet026@gmail.com>
> > > Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
> > > Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha
> > > <vdarbha0473@gmail.com> ---
> > >  drivers/media/platform/rockchip/rkvdec/rkvdec.c | 12 ++++++++++--
> > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > > b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index
> > > 436bb460f04e..6ab6530b1cc9 100644
> > > --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > > +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > > @@ -102,12 +102,20 @@ static void rkvdec_fill_decoded_pixfmt(struct
> > > rkvdec_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp)
> > >  {
> > >       const struct rkvdec_variant *variant = ctx->dev->variant;
> > > +     struct v4l2_plane_pix_format *plane = &pix_mp->plane_fmt[0];
> > > +     u32 aligned_bpl;
> > >
> > >       v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width,
> > > pix_mp->height);
> > >
> > > -     ctx->colmv_offset = pix_mp->plane_fmt[0].sizeimage;
> > > +     /* ensure bpl is 64 byte aligned and scale sizeimage accordingly.
> > */
> > > +     aligned_bpl = ALIGN(plane->bytesperline, 64);
> > > +     if (aligned_bpl != plane->bytesperline) {
> > > +             plane->sizeimage = plane->sizeimage / plane-
> > >bytesperline * aligned_bpl;
> > > +             plane->bytesperline = aligned_bpl;
> > > +     }
> >
> > This shouldn't be needed. As you set step_width to 64,
> > v4l2_apply_frmsize_constraints() should already do the alignment.
> >
> > Do you have more context as to when width is not aligned ?
> >
> > >
> > > -     pix_mp->plane_fmt[0].sizeimage += variant->ops->colmv_size(pix_mp-
> > >width,
> > > pix_mp->height); +    ctx->colmv_offset = plane->sizeimage;
> > > +     plane->sizeimage += variant->ops->colmv_size(pix_mp->width,
> > > pix_mp->height); }
> > >
> > >  static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f,
> >
> > Regards,
> > Detlev.
> >
> >
> >


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt()
  2026-07-27 17:42       ` Francesco Saverio Pavone
@ 2026-07-27 17:56         ` Igor Paunovic
  0 siblings, 0 replies; 11+ messages in thread
From: Igor Paunovic @ 2026-07-27 17:56 UTC (permalink / raw)
  To: Francesco Saverio Pavone
  Cc: Detlev Casanova, Ezequiel Garcia, Mauro Carvalho Chehab,
	Heiko Stuebner, Venkata Atchuta Bheemeswara Sarma Darbha,
	linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	Nicolas Dufresne

HI

Thank you for measuring it -- that settles it, and you're right. The
byte-exact A/B on both the landscape and portrait shapes that reach
the ALIGN is conclusive: the hunk makes no difference to the decoded
output.

Tracing it back through the registers after your mail confirms your
explanation. The luma and reference strides are programmed as
bytesperline / 16 (reg018/019 and the VP9 lastf/golden/altref
hor_virstride fields), so the hardware only needs a 16-byte-aligned
stride, and width * 5 / 4 on a 64-aligned width is always a multiple
of 16. step_width = 64 already guarantees what the hardware asks for.
My "corrupted without this" was reasoned from the ALIGN constant
rather than measured against this tree with the pitch fix in place --
that was my mistake.

You're right that the real fix is taking the MV and reference pitch
from bytesperline instead of the bitstream width -- that's what makes
the register value and the buffer layout agree, and it's already in
the "Add VP9 support" patch ("Real buffer stride, not
display-width-derived"). I don't have a vector that fails with that in
place and the ALIGN removed.

So this patch should be dropped in v2; the pitch derivation carries
it. And thanks for the catch on v4l2_fill_pixfmt_mp_aligned() --
you're right it isn't in 7.2-rc5, so that suggestion doesn't apply
either.

Igor


On Mon, Jul 27, 2026 at 7:43 PM Francesco Saverio Pavone
<pavone.lawyer@gmail.com> wrote:
>
> Hi,
>
> > The 10-bit capture format is NV15, whose luma stride is width * 5 / 4
> > [...] while the VDPU381 needs the luma stride 64-byte aligned (2432).
> > [...] so NV15 comes out unaligned and the decoded frame is corrupted
> > without this. I can show the before/after on a 10-bit vector if that's
> > useful.
>
> The arithmetic is right, the hardware requirement does not reproduce here.
> I built the same tree twice, changing only this hunk, and measured on a
> Rock 5B+ (RK3588, VDPU381):
> test with ALIGN without ALIGN libvpx
> 1920x1080 VP9 Profile 2, 10-bit 8f40faddd32e 8f40faddd32e 8f40faddd32e
> 1080x1920 VP9 Profile 2, 10-bit 68400b913caa 68400b913caa 68400b913caa
> fluster VP9-TEST-VECTORS 224/305 224/305 -
> Both clips are the shapes that reach the ALIGN: 1920 gives an NV15 stride
> of 2400 (2400 % 64 = 32) and the portrait clip rounds to a capture width of
> 1088, stride 1360 (1360 % 64 = 16). md5 is of the decoded frames converted
> to I420, same pipeline for hardware and software. The 8-bit control on the
> same pipeline is byte-identical too, so the comparison is not hiding a
> conversion artefact.
> That matches what the registers ask for. The stride goes into the hardware
> as bytesperline / 16 (y_hor_virstride, uv_hor_virstride, and the VP9
> reference ones), and width * 5 / 4 with a 64-aligned width is always a
> multiple of 16, so step_width = 64 already guarantees the alignment the
> hardware needs. Rounding to 64 only pads the stride reported to userspace,
> for every variant and every coded format, not just the 10-bit case.
> If you did see corruption without this, I suspect the other hunk in the
> same patch was missing too. Taking the MV and reference pitch from
> bytesperline instead of the bitstream width is the part that makes the
> register value and the buffer layout agree, and it is the one I would keep.
> My A/B has that hunk on both sides, so what I varied is only the ALIGN. If
> you have a vector that fails with the pitch fix in place and the ALIGN
> removed, I would like to run it.
> One small thing on the v2 suggestion: v4l2_fill_pixfmt_mp_aligned() does
> not exist in 7.2-rc5. v4l2-common.h exports v4l2_fill_pixfmt() and
> v4l2_fill_pixfmt_mp() only, so that would be a new helper to add rather
> than a drop-in replacement.
>
> Sav
>
> Il giorno lun 27 lug 2026 alle ore 19:07 Igor Paunovic
> <royalnet026@gmail.com> ha scritto:
> >
> > Hi
> >
> > > This shouldn't be needed. As you set step_width to 64,
> > > v4l2_apply_frmsize_constraints() should already do the alignment.
> > > Do you have more context as to when width is not aligned ?
> >
> > You're right that the width is aligned -- step_width = 64 handles that.
> > This isn't the width though, it's the stride, and it only bites on the
> > 10-bit (Profile 2) capture format.
> >
> > For 8-bit NV12 the luma stride equals the width, so once the width is
> > 64-aligned the stride is too and this block is a no-op.
> >
> > The 10-bit capture format is NV15, whose luma stride is width * 5 / 4
> > (bpp {5, 10}, bpp_div {4, 4} in v4l2-common.c). That isn't a multiple
> > of 64 even when the width is: a 1920-wide Profile 2 frame gives a
> > 2400-byte stride, while the VDPU381 needs the luma stride 64-byte
> > aligned (2432). v4l2_apply_frmsize_constraints() only rounds the width
> > and height, and v4l2_fill_pixfmt_mp() fills the stride with alignment 1,
> > so NV15 comes out unaligned and the decoded frame is corrupted without
> > this. I can show the before/after on a 10-bit vector if that's useful.
> >
> > If you'd rather express it through the framework than with a manual
> > ALIGN() here, v4l2_fill_pixfmt_mp_aligned(pixfmt, pixelformat, width,
> > height, 64) produces the same bytesperline and sizeimage -- happy to
> > switch to that in v2.
> >
> > Igor
> >
> >
> > On Mon, Jul 27, 2026 at 5:58 PM Detlev Casanova
> > <detlev.casanova@collabora.com> wrote:
> > >
> > > Hi !
> > >
> > > On Sunday, 26 July 2026 16:25:37 EDT Venkata Atchuta Bheemeswara Sarma Darbha
> > > wrote:
> > > > From: Igor Paunovic <royalnet026@gmail.com>
> > > >
> > > > Ensure bytesperline is 64-byte aligned and scale sizeimage accordingly.
> > > >
> > > > Signed-off-by: Igor Paunovic <royalnet026@gmail.com>
> > > > Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
> > > > Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha
> > > > <vdarbha0473@gmail.com> ---
> > > >  drivers/media/platform/rockchip/rkvdec/rkvdec.c | 12 ++++++++++--
> > > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > > > b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index
> > > > 436bb460f04e..6ab6530b1cc9 100644
> > > > --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > > > +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> > > > @@ -102,12 +102,20 @@ static void rkvdec_fill_decoded_pixfmt(struct
> > > > rkvdec_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp)
> > > >  {
> > > >       const struct rkvdec_variant *variant = ctx->dev->variant;
> > > > +     struct v4l2_plane_pix_format *plane = &pix_mp->plane_fmt[0];
> > > > +     u32 aligned_bpl;
> > > >
> > > >       v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, pix_mp->width,
> > > > pix_mp->height);
> > > >
> > > > -     ctx->colmv_offset = pix_mp->plane_fmt[0].sizeimage;
> > > > +     /* ensure bpl is 64 byte aligned and scale sizeimage accordingly.
> > > */
> > > > +     aligned_bpl = ALIGN(plane->bytesperline, 64);
> > > > +     if (aligned_bpl != plane->bytesperline) {
> > > > +             plane->sizeimage = plane->sizeimage / plane-
> > > >bytesperline * aligned_bpl;
> > > > +             plane->bytesperline = aligned_bpl;
> > > > +     }
> > >
> > > This shouldn't be needed. As you set step_width to 64,
> > > v4l2_apply_frmsize_constraints() should already do the alignment.
> > >
> > > Do you have more context as to when width is not aligned ?
> > >
> > > >
> > > > -     pix_mp->plane_fmt[0].sizeimage += variant->ops->colmv_size(pix_mp-
> > > >width,
> > > > pix_mp->height); +    ctx->colmv_offset = plane->sizeimage;
> > > > +     plane->sizeimage += variant->ops->colmv_size(pix_mp->width,
> > > > pix_mp->height); }
> > > >
> > > >  static void rkvdec_reset_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f,
> > >
> > > Regards,
> > > Detlev.
> > >
> > >
> > >


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-07-27 17:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-26 20:25 [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
2026-07-26 20:25 ` [PATCH 1/4] media: rkvdec: vp9: Changing get_ref_buf function name to get_ref_buf_vp9 Venkata Atchuta Bheemeswara Sarma Darbha
2026-07-26 20:25 ` [PATCH 2/4] media: rkvdec: Move vp9 functions to common file Venkata Atchuta Bheemeswara Sarma Darbha
2026-07-26 20:25 ` [PATCH 3/4] media: rkvdec: Add VP9 support for VDPU381 variant Venkata Atchuta Bheemeswara Sarma Darbha
2026-07-26 20:25 ` [PATCH 4/4] media: rkvdec: align bytesperline to 64 bytes in rkvdec_fill_decoded_pixfmt() Venkata Atchuta Bheemeswara Sarma Darbha
2026-07-27 15:58   ` Detlev Casanova
2026-07-27 17:07     ` Igor Paunovic
2026-07-27 17:42       ` Francesco Saverio Pavone
2026-07-27 17:56         ` Igor Paunovic
2026-07-27  6:44 ` [PATCH 0/4] media: rkvdec: Add VP9 support for VDPU381 variant Francesco Saverio Pavone
2026-07-27  8:25   ` Igor Paunovic

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox