linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/1] Rewrite the VP9 codec library in Rust
@ 2024-02-27 21:51 Daniel Almeida
  2024-02-27 21:51 ` [RFC PATCH 1/1] v4l2-core: rewrite the VP9 " Daniel Almeida
  2024-03-07 19:08 ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec " Daniel Almeida
  0 siblings, 2 replies; 10+ messages in thread
From: Daniel Almeida @ 2024-02-27 21:51 UTC (permalink / raw)
  To: wedsonaf, ojeda, mchehab, hverkuil
  Cc: Daniel Almeida, rust-for-linux, linux-kernel, linux-media, kernel


Hi everyone,

This patch ports the VP9 library written by Andrzej into Rust as a
proof-of-concept. This is so that we can evaluate the Rust in V4L2 initiative
with source code in hand.

It converts rkvdec and hantro to use the Rust version of the library. These two
were chosen merely because that's the hardware I currently own. Fluster scores
remain the same when using either the Rust or C version. Please test this.

Much has been spoken at various occasions about drivers and I feel that the
consensus is to wait for now. This is why I am proposing a different approach:
porting our codec libraries to Rust.

IMHO, these components can benefit greatly from Rust, as they implement
complicated algorithms that also happen to process data received from userspace
through V4L2 controls. These algorithms use the data received from userspace in
order to index into a lot of arrays and thus benefit from Rust's memory safety.

The first thing about the code is that it does not include any layer of
bindings. This was pointed out as a blocker several times due to the need of
keeping them in sync with the C code.

The Rust code here also offers a C API for C drivers.This C API is
automatically generated by cbindgen and I have provided instructions on how to
do so. We can even use functions from both the C and Rust libraries at the same
time since the ABI is the same.

The above can come in handy because it means that we can convert a given
codebase piece by piece if need be. C drivers will work as usual through the C
API and any new Rust driver will get to benefit from a native Rust interface.

Please take note that most of the code is *not* in the media tree, so I do not
see how this can further stress our subsystem. I take responsibility for
maintaining stuff in rust/kernel/media and honestly, this library will not need
any further updates for the same reason we have never touched its C
counterpart.

I hope to convince the community that this is a feasible way to slowly
experiment with Rust code without tying us up too much to it.

Lastly, please note that this code is just a proof of concept, we can settle on
a proper patch - with all that entails - if it is well received.

Those with hardware can follow the steps below to test this patch:

a) enable Rust (https://www.kernel.org/doc/html/latest/rust/quick-start.html).
Make sure CONFIG_RUST=y.

b) enable one of the converted drivers (CONFIG_VIDEO_HANTRO or
CONFIG_VIDEO_ROCKCHIP_VDEC). This will select V4L2_VP9_RS.

c) download the Fluster tool (https://github.com/fluendo/fluster)

d) download the VP9 test suite from libvpx (fluster.py download VP9-TEST-VECTORS)

e) make sure you have a recent version of GStreamer (`gst-inspect-1.0
v4l2codecs` must not be empty) 

f) run the test suite (fluster.py run -d GStreamer-VP9-V4L2SL-Gst1.0 -ts VP9-TEST-VECTORS)

g) results should be the same both with and without this patch

-- Daniel


Applies on top of:

commit d9c1fae3e5b225f2e45e0bca519f9a2967cd1062
Author: Alice Ryhl <aliceryhl@google.com>
Date:   Fri Feb 9 11:18:22 2024 +0000

    rust: file: add abstraction for `poll_table`




For those looking for a branch instead:

https://gitlab.collabora.com/dwlsalmeida/for-upstream/-/tree/vp9-rs?ref_type=heads


Daniel Almeida (1):
  v4l2-core: rewrite the VP9 library in Rust

 drivers/media/platform/verisilicon/Kconfig    |    2 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |   38 +-
 .../media/platform/verisilicon/hantro_hw.h    |    8 +-
 drivers/media/v4l2-core/Kconfig               |    4 +
 drivers/staging/media/rkvdec/Kconfig          |    2 +-
 drivers/staging/media/rkvdec/rkvdec-vp9.c     |   52 +-
 include/media/v4l2-vp9-rs.h                   |   97 +
 rust/bindings/bindings_helper.h               |    1 +
 rust/kernel/lib.rs                            |    2 +
 rust/kernel/media.rs                          |    5 +
 rust/kernel/media/v4l2_core.rs                |    6 +
 rust/kernel/media/v4l2_core/cbindgen.toml     |   26 +
 rust/kernel/media/v4l2_core/vp9.rs            | 1999 +++++++++++++++++
 13 files changed, 2192 insertions(+), 50 deletions(-)
 create mode 100644 include/media/v4l2-vp9-rs.h
 create mode 100644 rust/kernel/media.rs
 create mode 100644 rust/kernel/media/v4l2_core.rs
 create mode 100644 rust/kernel/media/v4l2_core/cbindgen.toml
 create mode 100644 rust/kernel/media/v4l2_core/vp9.rs

-- 
2.43.0


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

* [RFC PATCH 1/1] v4l2-core: rewrite the VP9 library in Rust
  2024-02-27 21:51 [RFC PATCH 0/1] Rewrite the VP9 codec library in Rust Daniel Almeida
@ 2024-02-27 21:51 ` Daniel Almeida
  2024-02-28 14:13   ` Alice Ryhl
  2024-03-07 19:08 ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec " Daniel Almeida
  1 sibling, 1 reply; 10+ messages in thread
From: Daniel Almeida @ 2024-02-27 21:51 UTC (permalink / raw)
  To: wedsonaf, ojeda, mchehab, hverkuil
  Cc: Daniel Almeida, rust-for-linux, linux-kernel, linux-media, kernel

---
 drivers/media/platform/verisilicon/Kconfig    |    2 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |   38 +-
 .../media/platform/verisilicon/hantro_hw.h    |    8 +-
 drivers/media/v4l2-core/Kconfig               |    4 +
 drivers/staging/media/rkvdec/Kconfig          |    2 +-
 drivers/staging/media/rkvdec/rkvdec-vp9.c     |   52 +-
 include/media/v4l2-vp9-rs.h                   |   97 +
 rust/bindings/bindings_helper.h               |    1 +
 rust/kernel/lib.rs                            |    2 +
 rust/kernel/media.rs                          |    5 +
 rust/kernel/media/v4l2_core.rs                |    6 +
 rust/kernel/media/v4l2_core/cbindgen.toml     |   26 +
 rust/kernel/media/v4l2_core/vp9.rs            | 1999 +++++++++++++++++
 13 files changed, 2192 insertions(+), 50 deletions(-)
 create mode 100644 include/media/v4l2-vp9-rs.h
 create mode 100644 rust/kernel/media.rs
 create mode 100644 rust/kernel/media/v4l2_core.rs
 create mode 100644 rust/kernel/media/v4l2_core/cbindgen.toml
 create mode 100644 rust/kernel/media/v4l2_core/vp9.rs

diff --git a/drivers/media/platform/verisilicon/Kconfig b/drivers/media/platform/verisilicon/Kconfig
index 24b927d8f182..d8e4e9b5de2f 100644
--- a/drivers/media/platform/verisilicon/Kconfig
+++ b/drivers/media/platform/verisilicon/Kconfig
@@ -12,7 +12,7 @@ config VIDEO_HANTRO
 	select VIDEOBUF2_VMALLOC
 	select V4L2_MEM2MEM_DEV
 	select V4L2_H264
-	select V4L2_VP9
+	select V4L2_VP9_RS
 	help
 	  Support for the Hantro IP based Video Processing Units present on
 	  Rockchip and NXP i.MX8M SoCs, which accelerate video and image
diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 342e543dee4c..eabde1bb326a 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -10,7 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/v4l2-vp9.h>
+#include <media/v4l2-vp9-rs.h>
 
 #include "hantro.h"
 #include "hantro_vp9.h"
@@ -63,7 +63,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 	 *	frame_context_idx = 0
 	 * }
 	 */
-	fctx_idx = v4l2_vp9_reset_frame_ctx(*dec_params, vp9_ctx->frame_context);
+	fctx_idx = v4l2_vp9_reset_frame_ctx_rs(*dec_params, &vp9_ctx->frame_context);
 	vp9_ctx->cur.frame_context_idx = fctx_idx;
 
 	/* 6.1 frame(sz): load_probs() and load_probs2() */
@@ -83,7 +83,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 	 * 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);
+	v4l2_vp9_fw_update_probs_rs(&vp9_ctx->probability_tables, prob_updates, *dec_params);
 
 	return 0;
 }
@@ -422,7 +422,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 		if (segment_enabled) {
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
-			if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
+			if (v4l2_vp9_seg_feat_enabled_rs(vp9_ctx->feature_enabled, feat_id, segid))
 				feat_val = feat_val_clip3(feat_val,
 							  vp9_ctx->feature_data[segid][feat_id],
 							  absolute, 255);
@@ -435,7 +435,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 		if (segment_enabled) {
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
-			if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
+			if (v4l2_vp9_seg_feat_enabled_rs(vp9_ctx->feature_enabled, feat_id, segid))
 				feat_val = feat_val_clip3(feat_val,
 							  vp9_ctx->feature_data[segid][feat_id],
 							  absolute, 63);
@@ -449,7 +449,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
 			if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) &&
-			    v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
+			    v4l2_vp9_seg_feat_enabled_rs(vp9_ctx->feature_enabled, feat_id, segid))
 				feat_val = vp9_ctx->feature_data[segid][feat_id] + 1;
 		}
 		hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
@@ -460,7 +460,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 		if (segment_enabled) {
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
-			feat_val = v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled,
+			feat_val = v4l2_vp9_seg_feat_enabled_rs(vp9_ctx->feature_enabled,
 							     feat_id, segid) ? 1 : 0;
 		}
 		hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
@@ -637,17 +637,17 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram
 	struct hantro_g2_probs *adaptive;
 	struct hantro_g2_mv_probs *mv;
 	const struct v4l2_vp9_segmentation *seg = &dec_params->seg;
-	const struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables;
+	const struct v4l2_vp9_frame_context_rs *probs = &vp9_ctx->probability_tables;
 	int i, j, k, l, m;
 
 	for (i = 0; i < ARRAY_SIZE(all_probs->kf_y_mode_prob); ++i)
 		for (j = 0; j < ARRAY_SIZE(all_probs->kf_y_mode_prob[0]); ++j) {
 			memcpy(all_probs->kf_y_mode_prob[i][j],
-			       v4l2_vp9_kf_y_mode_prob[i][j],
+			       v4l2_vp9_kf_y_mode_prob_rs[i][j],
 			       ARRAY_SIZE(all_probs->kf_y_mode_prob[i][j]));
 
 			all_probs->kf_y_mode_prob_tail[i][j][0] =
-				v4l2_vp9_kf_y_mode_prob[i][j][8];
+				v4l2_vp9_kf_y_mode_prob_rs[i][j][8];
 		}
 
 	memcpy(all_probs->mb_segment_tree_probs, seg->tree_probs,
@@ -657,10 +657,10 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram
 	       sizeof(all_probs->segment_pred_probs));
 
 	for (i = 0; i < ARRAY_SIZE(all_probs->kf_uv_mode_prob); ++i) {
-		memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob[i],
+		memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob_rs[i],
 		       ARRAY_SIZE(all_probs->kf_uv_mode_prob[i]));
 
-		all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob[i][8];
+		all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob_rs[i][8];
 	}
 
 	adaptive = &all_probs->probs;
@@ -692,8 +692,8 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram
 	}
 
 	for (i = 0; i < ARRAY_SIZE(adaptive->partition[0]); ++i) {
-		memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs[i],
-		       sizeof(v4l2_vp9_kf_partition_probs[i]));
+		memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs_rs[i],
+		       sizeof(v4l2_vp9_kf_partition_probs_rs[i]));
 
 		adaptive->partition[0][i][3] = 0;
 	}
@@ -933,7 +933,7 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 
 	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;
+		struct v4l2_vp9_frame_context_rs *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 {
@@ -942,7 +942,7 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 			u8 tx32[2][3];
 			u8 skip[3];
 		} _tx_skip, *tx_skip = &_tx_skip;
-		struct v4l2_vp9_frame_symbol_counts *counts;
+		struct v4l2_vp9_frame_symbol_counts_rs *counts;
 		struct symbol_counts *hantro_cnts;
 		u32 tx16p[2][4];
 		int i;
@@ -968,7 +968,8 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 		}
 		counts->tx16p = &tx16p;
 
-		v4l2_vp9_adapt_coef_probs(probs, counts,
+		v4l2_vp9_adapt_coef_probs_rs(probs,
+								     counts,
 					  !vp9_ctx->last.valid ||
 					  vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME,
 					  frame_is_intra);
@@ -984,7 +985,8 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 				mv_mode[i][3] = hantro_cnts->inter_mode_counts[i][2][1];
 			}
 			counts->mv_mode = &mv_mode;
-			v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts,
+			v4l2_vp9_adapt_noncoef_probs_rs(&vp9_ctx->probability_tables,
+										   counts,
 						     vp9_ctx->cur.reference_mode,
 						     vp9_ctx->cur.interpolation_filter,
 						     vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags);
diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
index 9aec8a79acdc..f8baa898ef53 100644
--- a/drivers/media/platform/verisilicon/hantro_hw.h
+++ b/drivers/media/platform/verisilicon/hantro_hw.h
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/v4l2-controls.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-vp9.h>
+#include <media/v4l2-vp9-rs.h>
 #include <media/videobuf2-core.h>
 
 #include "rockchip_av1_entropymode.h"
@@ -231,9 +231,9 @@ struct hantro_vp9_dec_hw_ctx {
 	struct hantro_aux_buf tile_edge;
 	struct hantro_aux_buf segment_map;
 	struct hantro_aux_buf misc;
-	struct v4l2_vp9_frame_symbol_counts cnts;
-	struct v4l2_vp9_frame_context probability_tables;
-	struct v4l2_vp9_frame_context frame_context[4];
+	struct v4l2_vp9_frame_symbol_counts_rs cnts;
+	struct v4l2_vp9_frame_context_rs probability_tables;
+	struct v4l2_vp9_frame_context_rs frame_context[4];
 	struct hantro_vp9_frame_info cur;
 	struct hantro_vp9_frame_info last;
 
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 331b8e535e5b..f0e3a25db1f2 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -48,6 +48,10 @@ config V4L2_H264
 config V4L2_VP9
 	tristate
 
+# Used by drivers that need the Rust equivalent to v4l2-vp9.ko
+config V4L2_VP9_RS
+	tristate
+
 # Used by drivers that need v4l2-mem2mem.ko
 config V4L2_MEM2MEM_DEV
 	tristate
diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig
index 5f3bdd848a2c..245dc47082d4 100644
--- a/drivers/staging/media/rkvdec/Kconfig
+++ b/drivers/staging/media/rkvdec/Kconfig
@@ -8,7 +8,7 @@ config VIDEO_ROCKCHIP_VDEC
 	select VIDEOBUF2_VMALLOC
 	select V4L2_MEM2MEM_DEV
 	select V4L2_H264
-	select V4L2_VP9
+	select V4L2_VP9_RS
 	help
 	  Support for the Rockchip Video Decoder IP present on Rockchip SoCs,
 	  which accelerates video decoding.
diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c
index 0e7e16f20eeb..907dbc12bac8 100644
--- a/drivers/staging/media/rkvdec/rkvdec-vp9.c
+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c
@@ -19,7 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/v4l2-vp9.h>
+#include <media/v4l2-vp9-rs.h>
 
 #include "rkvdec.h"
 #include "rkvdec-regs.h"
@@ -157,10 +157,10 @@ struct rkvdec_vp9_frame_info {
 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 v4l2_vp9_frame_symbol_counts_rs inter_cnts;
+	struct v4l2_vp9_frame_symbol_counts_rs intra_cnts;
+	struct v4l2_vp9_frame_context_rs probability_tables;
+	struct v4l2_vp9_frame_context_rs frame_context[4];
 	struct rkvdec_vp9_frame_info cur;
 	struct rkvdec_vp9_frame_info last;
 };
@@ -192,7 +192,7 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 	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;
+	const struct v4l2_vp9_frame_context_rs *probs;
 	unsigned int i, j, k;
 
 	rkprobs = &tbl->probs.intra_only;
@@ -209,15 +209,15 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 	}
 
 	/* intra mode prob  80 x 128 bits */
-	for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob); i++) {
+	for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs); 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]);
+		for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0]); j++) {
+			for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0][0]);
 			     k++) {
-				u8 val = v4l2_vp9_kf_y_mode_prob[i][j][k];
+				u8 val = v4l2_vp9_kf_y_mode_prob_rs[i][j][k];
 
 				rkprobs->intra_mode[i].y_mode[idx++] = val;
 				byte_count++;
@@ -229,8 +229,8 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 		}
 	}
 
-	for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob); ++i) {
-		const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob;
+	for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob_rs); ++i) {
+		const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob_rs;
 
 		rkprobs->intra_mode[i / 23].uv_mode[i % 23] = ptr[i];
 	}
@@ -242,7 +242,7 @@ static void init_inter_probs(struct rkvdec_ctx *ctx,
 	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;
+	const struct v4l2_vp9_frame_context_rs *probs;
 	unsigned int i, j, k;
 
 	rkprobs = &tbl->probs.inter;
@@ -315,7 +315,7 @@ static void init_probs(struct rkvdec_ctx *ctx,
 	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;
+	const struct v4l2_vp9_frame_context_rs *probs;
 	bool intra_only;
 
 	dec_params = run->decode_params;
@@ -330,7 +330,7 @@ static void init_probs(struct rkvdec_ctx *ctx,
 
 	/* sb info  5 x 128 bit */
 	memcpy(rkprobs->partition,
-	       intra_only ? v4l2_vp9_kf_partition_probs : probs->partition,
+	       intra_only ? v4l2_vp9_kf_partition_probs_rs : probs->partition,
 	       sizeof(rkprobs->partition));
 
 	memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred));
@@ -448,7 +448,7 @@ static void config_ref_registers(struct rkvdec_ctx *ctx,
 static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
 {
 	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
-	const struct v4l2_vp9_segmentation *seg;
+	struct v4l2_vp9_segmentation *seg;
 	struct rkvdec_dev *rkvdec = ctx->dev;
 	s16 feature_val;
 	int feature_id;
@@ -456,28 +456,28 @@ static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
 
 	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)) {
+	if (v4l2_vp9_seg_feat_enabled_rs(seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
 		val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) |
 		       RKVDEC_SEGID_FRAME_QP_DELTA(feature_val);
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_ALT_L;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
+	if (v4l2_vp9_seg_feat_enabled_rs(seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
 		val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) |
 		       RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val);
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_REF_FRAME;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
+	if (v4l2_vp9_seg_feat_enabled_rs(seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
 		val |= RKVDEC_SEGID_REFERINFO_EN(1) |
 		       RKVDEC_SEGID_REFERINFO(feature_val);
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_SKIP;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
+	if (v4l2_vp9_seg_feat_enabled_rs(seg->feature_enabled, feature_id, segid))
 		val |= RKVDEC_SEGID_FRAME_SKIP_EN(1);
 
 	if (!segid &&
@@ -773,7 +773,7 @@ static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx,
 	 *	frame_context_idx = 0
 	 * }
 	 */
-	fctx_idx = v4l2_vp9_reset_frame_ctx(dec_params, vp9_ctx->frame_context);
+	fctx_idx = v4l2_vp9_reset_frame_ctx_rs(dec_params, &vp9_ctx->frame_context);
 	vp9_ctx->cur.frame_context_idx = fctx_idx;
 
 	/* 6.1 frame(sz): load_probs() and load_probs2() */
@@ -793,7 +793,7 @@ static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx,
 	 * 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);
+	v4l2_vp9_fw_update_probs_rs(&vp9_ctx->probability_tables, prob_updates, dec_params);
 
 	return 0;
 }
@@ -871,7 +871,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 
 	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;
+		struct v4l2_vp9_frame_context_rs *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 {
@@ -880,7 +880,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 			u8 tx32[2][3];
 			u8 skip[3];
 		} _tx_skip, *tx_skip = &_tx_skip;
-		struct v4l2_vp9_frame_symbol_counts *counts;
+		struct v4l2_vp9_frame_symbol_counts_rs *counts;
 
 		/* buffer the forward-updated TX and skip probs */
 		if (frame_is_intra)
@@ -894,7 +894,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 			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,
+		v4l2_vp9_adapt_coef_probs_rs(probs, counts,
 					  !vp9_ctx->last.valid ||
 					  vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME,
 					  frame_is_intra);
@@ -909,7 +909,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 			counts->classes = &classes;
 
 			/* load_probs2() already done */
-			v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts,
+			v4l2_vp9_adapt_noncoef_probs_rs(&vp9_ctx->probability_tables, counts,
 						     vp9_ctx->cur.reference_mode,
 						     vp9_ctx->cur.interpolation_filter,
 						     vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags);
diff --git a/include/media/v4l2-vp9-rs.h b/include/media/v4l2-vp9-rs.h
new file mode 100644
index 000000000000..5f490a0cb671
--- /dev/null
+++ b/include/media/v4l2-vp9-rs.h
@@ -0,0 +1,97 @@
+#ifndef V4L2_VP9_RS_H
+#define V4L2_VP9_RS_H
+
+/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
+
+#include <media/v4l2-ctrls.h>
+
+struct v4l2_vp9_frame_mv_context_rs {
+  uint8_t joint[3];
+  uint8_t sign[2];
+  uint8_t classes[2][10];
+  uint8_t class0_bit[2];
+  uint8_t bits[2][10];
+  uint8_t class0_fr[2][2][3];
+  uint8_t fr[2][3];
+  uint8_t class0_hp[2];
+  uint8_t hp[2];
+};
+
+struct v4l2_vp9_frame_context_rs {
+  uint8_t tx8[2][1];
+  uint8_t tx16[2][2];
+  uint8_t tx32[2][3];
+  uint8_t coef[4][2][2][6][6][3];
+  uint8_t skip[3];
+  uint8_t inter_mode[7][3];
+  uint8_t interp_filter[4][2];
+  uint8_t is_inter[4];
+  uint8_t comp_mode[5];
+  uint8_t single_ref[5][2];
+  uint8_t comp_ref[5];
+  uint8_t y_mode[4][9];
+  uint8_t uv_mode[10][9];
+  uint8_t partition[16][3];
+  struct v4l2_vp9_frame_mv_context_rs mv;
+};
+
+struct v4l2_vp9_frame_symbol_counts_rs {
+  uint32_t (*partition)[16][4];
+  uint32_t (*skip)[3][2];
+  uint32_t (*intra_inter)[4][2];
+  uint32_t (*tx32p)[2][4];
+  uint32_t (*tx16p)[2][4];
+  uint32_t (*tx8p)[2][2];
+  uint32_t (*y_mode)[4][10];
+  uint32_t (*uv_mode)[10][10];
+  uint32_t (*comp)[5][2];
+  uint32_t (*comp_ref)[5][2];
+  uint32_t (*single_ref)[5][2][2];
+  uint32_t (*mv_mode)[7][4];
+  uint32_t (*filter)[4][3];
+  uint32_t (*mv_joint)[4];
+  uint32_t (*sign)[2][2];
+  uint32_t (*classes)[2][11];
+  uint32_t (*class0)[2][2];
+  uint32_t (*bits)[2][10][2];
+  uint32_t (*class0_fp)[2][2][4];
+  uint32_t (*fp)[2][4];
+  uint32_t (*class0_hp)[2][2];
+  uint32_t (*hp)[2][2];
+  uint32_t (*coeff[4][2][2][6][6])[3];
+  uint32_t *eob[4][2][2][6][6][2];
+};
+
+extern const uint8_t v4l2_vp9_kf_y_mode_prob_rs[10][10][9];
+
+extern const uint8_t v4l2_vp9_kf_partition_probs_rs[16][3];
+
+extern const uint8_t v4l2_vp9_kf_uv_mode_prob_rs[10][9];
+
+extern const struct v4l2_vp9_frame_context_rs v4l2_vp9_default_probs_rs;
+
+/**
+ * Counterpart to 6.3 compressed_header(), but parsing has been done in userspace.
+ */
+void v4l2_vp9_fw_update_probs_rs(struct v4l2_vp9_frame_context_rs *probs,
+                                 const struct v4l2_ctrl_vp9_compressed_hdr *deltas,
+                                 const struct v4l2_ctrl_vp9_frame *dec_params);
+
+uint8_t v4l2_vp9_reset_frame_ctx_rs(const struct v4l2_ctrl_vp9_frame *dec_params,
+                                    struct v4l2_vp9_frame_context_rs (*frame_context)[4]);
+
+void v4l2_vp9_adapt_coef_probs_rs(struct v4l2_vp9_frame_context_rs *probs,
+                                  struct v4l2_vp9_frame_symbol_counts_rs *counts,
+                                  bool use_128,
+                                  bool frame_is_intra);
+
+void v4l2_vp9_adapt_noncoef_probs_rs(struct v4l2_vp9_frame_context_rs *probs,
+                                     struct v4l2_vp9_frame_symbol_counts_rs *counts,
+                                     uint8_t reference_mode,
+                                     uint8_t interpolation_filter,
+                                     uint8_t tx_mode,
+                                     uint32_t flags);
+
+bool v4l2_vp9_seg_feat_enabled_rs(uint8_t *feature_enabled, uint32_t feature, uint32_t segid);
+
+#endif /* V4L2_VP9_RS_H */
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index c651d38e5dd6..25e2c06bb967 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/task_work.h>
 #include <linux/workqueue.h>
+#include <linux/v4l2-controls.h>
 
 /* `bindgen` gets confused at certain things. */
 const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index cc39195b0157..724e1d3bf2af 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -39,6 +39,8 @@
 pub mod ioctl;
 #[cfg(CONFIG_KUNIT)]
 pub mod kunit;
+#[cfg(CONFIG_MEDIA_SUPPORT)]
+pub mod media;
 #[cfg(CONFIG_NET)]
 pub mod net;
 pub mod prelude;
diff --git a/rust/kernel/media.rs b/rust/kernel/media.rs
new file mode 100644
index 000000000000..72f5cd716874
--- /dev/null
+++ b/rust/kernel/media.rs
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Media support
+
+pub mod v4l2_core;
\ No newline at end of file
diff --git a/rust/kernel/media/v4l2_core.rs b/rust/kernel/media/v4l2_core.rs
new file mode 100644
index 000000000000..7515fe748a65
--- /dev/null
+++ b/rust/kernel/media/v4l2_core.rs
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! V4L2 Core
+
+#[cfg(CONFIG_V4L2_VP9_RS)]
+pub mod vp9;
\ No newline at end of file
diff --git a/rust/kernel/media/v4l2_core/cbindgen.toml b/rust/kernel/media/v4l2_core/cbindgen.toml
new file mode 100644
index 000000000000..ebbc8a5e2fff
--- /dev/null
+++ b/rust/kernel/media/v4l2_core/cbindgen.toml
@@ -0,0 +1,26 @@
+# Generate the C API with:
+# cbindgen  --lang c  -v --config rust/kernel/media/v4l2_core/cbindgen.toml --output include/media/v4l2-vp9-rs.h -- rust/kernel/media/v4l2_core/vp9.rs
+
+language = "C"
+
+# No <stdarg.h>, <stdbool.h>, <stdint.h>, <stdlib.h>, <uchar.h>
+no_includes = true
+style = "tag"
+
+sys_includes = ["media/v4l2-ctrls.h"]
+autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
+usize_is_size_t = true
+include_guard = "V4L2_VP9_RS_H"
+
+# Rename everything from bindgen
+# See https://github.com/mozilla/cbindgen/issues/621
+# Also rename our mangled structs into snake_case for the C API
+[export.rename]
+"v4l2_ctrl_vp9_compressed_hdr" = "struct v4l2_ctrl_vp9_compressed_hdr"
+"v4l2_ctrl_vp9_frame" = "struct v4l2_ctrl_vp9_frame"
+"FrameContext" = "v4l2_vp9_frame_context_rs"
+"FrameSymbolCounts" = "v4l2_vp9_frame_symbol_counts_rs"
+"FrameMvContext" = "v4l2_vp9_frame_mv_context_rs"
+
+[enum]
+prefix_with_name = true
diff --git a/rust/kernel/media/v4l2_core/vp9.rs b/rust/kernel/media/v4l2_core/vp9.rs
new file mode 100644
index 000000000000..a6380892cb2d
--- /dev/null
+++ b/rust/kernel/media/v4l2_core/vp9.rs
@@ -0,0 +1,1999 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! VP9 helpers
+//! This library was initially written by Andrzej Pietrasiewicz and ported into
+//! Rust by Daniel Almeida.
+
+#![allow(missing_docs)]
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct FrameMvContext {
+    pub joint: [u8; 3],
+    pub sign: [u8; 2],
+    pub classes: [[u8; 10]; 2],
+    pub class0_bit: [u8; 2],
+    pub bits: [[u8; 10]; 2],
+    pub class0_fr: [[[u8; 3]; 2]; 2],
+    pub fr: [[u8; 3]; 2],
+    pub class0_hp: [u8; 2],
+    pub hp: [u8; 2],
+}
+
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct FrameContext {
+    pub tx8: [[u8; 1]; 2],
+    pub tx16: [[u8; 2]; 2],
+    pub tx32: [[u8; 3]; 2],
+    pub coef: [[[[[[u8; 3]; 6]; 6]; 2]; 2]; 4],
+    pub skip: [u8; 3],
+    pub inter_mode: [[u8; 3]; 7],
+    pub interp_filter: [[u8; 2]; 4],
+    pub is_inter: [u8; 4],
+    pub comp_mode: [u8; 5],
+    pub single_ref: [[u8; 2]; 5],
+    pub comp_ref: [u8; 5],
+    pub y_mode: [[u8; 9]; 4],
+    pub uv_mode: [[u8; 9]; 10],
+    pub partition: [[u8; 3]; 16],
+    pub mv: FrameMvContext,
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct FrameSymbolCounts<'a> {
+    pub partition: &'a mut [[u32; 4]; 16],
+    pub skip: &'a mut  [[u32; 2]; 3],
+    pub intra_inter: &'a mut  [[u32; 2]; 4],
+    pub tx32p: &'a mut  [[u32; 4]; 2],
+    pub tx16p: &'a mut  [[u32; 4]; 2],
+    pub tx8p: &'a mut  [[u32; 2]; 2],
+    pub y_mode: &'a mut  [[u32; 10]; 4],
+    pub uv_mode: &'a mut  [[u32; 10]; 10],
+    pub comp: &'a mut  [[u32; 2]; 5],
+    pub comp_ref: &'a mut  [[u32; 2]; 5],
+    pub single_ref: &'a mut  [[[u32; 2]; 2]; 5],
+    pub mv_mode: &'a mut  [[u32; 4]; 7],
+    pub filter: &'a mut  [[u32; 3]; 4],
+    pub mv_joint: &'a mut  [u32; 4],
+    pub sign: &'a mut  [[u32; 2]; 2],
+    pub classes: &'a mut  [[u32; 11]; 2],
+    pub class0: &'a mut  [[u32; 2]; 2],
+    pub bits: &'a mut  [[[u32; 2]; 10]; 2],
+    pub class0_fp: &'a mut  [[[u32; 4]; 2]; 2],
+    pub fp: &'a mut  [[u32; 4]; 2],
+    pub class0_hp: &'a mut  [[u32; 2]; 2],
+    pub hp: &'a mut  [[u32; 2]; 2],
+    pub coeff: [[[[[&'a mut [u32; 3]; 6]; 6]; 2]; 2]; 4],
+    pub eob: [[[[[[&'a mut u32; 2]; 6]; 6]; 2]; 2]; 4],
+}
+
+#[no_mangle]
+pub static v4l2_vp9_kf_y_mode_prob_rs: [[[u8; 9]; 10]; 10] = [
+    [
+        /* above = dc */
+        [137, 30, 42, 148, 151, 207, 70, 52, 91], /*left = dc  */
+        [92, 45, 102, 136, 116, 180, 74, 90, 100], /*left = v   */
+        [73, 32, 19, 187, 222, 215, 46, 34, 100], /*left = h   */
+        [91, 30, 32, 116, 121, 186, 93, 86, 94],  /*left = d45 */
+        [72, 35, 36, 149, 68, 206, 68, 63, 105],  /*left = d135*/
+        [73, 31, 28, 138, 57, 124, 55, 122, 151], /*left = d117*/
+        [67, 23, 21, 140, 126, 197, 40, 37, 171], /*left = d153*/
+        [86, 27, 28, 128, 154, 212, 45, 43, 53],  /*left = d207*/
+        [74, 32, 27, 107, 86, 160, 63, 134, 102], /*left = d63 */
+        [59, 67, 44, 140, 161, 202, 78, 67, 119], /*left = tm  */
+    ],
+    [
+        /* above = v */
+        [63, 36, 126, 146, 123, 158, 60, 90, 96], /*left = dc  */
+        [43, 46, 168, 134, 107, 128, 69, 142, 92], /*left = v   */
+        [44, 29, 68, 159, 201, 177, 50, 57, 77],  /*left = h   */
+        [58, 38, 76, 114, 97, 172, 78, 133, 92],  /*left = d45 */
+        [46, 41, 76, 140, 63, 184, 69, 112, 57],  /*left = d135*/
+        [38, 32, 85, 140, 46, 112, 54, 151, 133], /*left = d117*/
+        [39, 27, 61, 131, 110, 175, 44, 75, 136], /*left = d153*/
+        [52, 30, 74, 113, 130, 175, 51, 64, 58],  /*left = d207*/
+        [47, 35, 80, 100, 74, 143, 64, 163, 74],  /*left = d63 */
+        [36, 61, 116, 114, 128, 162, 80, 125, 82], /*left = tm  */
+    ],
+    [
+        /* above = h */
+        [82, 26, 26, 171, 208, 204, 44, 32, 105], /*left = dc  */
+        [55, 44, 68, 166, 179, 192, 57, 57, 108], /*left = v   */
+        [42, 26, 11, 199, 241, 228, 23, 15, 85],  /*left = h   */
+        [68, 42, 19, 131, 160, 199, 55, 52, 83],  /*left = d45 */
+        [58, 50, 25, 139, 115, 232, 39, 52, 118], /*left = d135*/
+        [50, 35, 33, 153, 104, 162, 64, 59, 131], /*left = d117*/
+        [44, 24, 16, 150, 177, 202, 33, 19, 156], /*left = d153*/
+        [55, 27, 12, 153, 203, 218, 26, 27, 49],  /*left = d207*/
+        [53, 49, 21, 110, 116, 168, 59, 80, 76],  /*left = d63 */
+        [38, 72, 19, 168, 203, 212, 50, 50, 107], /*left = tm  */
+    ],
+    [
+        /* above = d45 */
+        [103, 26, 36, 129, 132, 201, 83, 80, 93], /*left = dc  */
+        [59, 38, 83, 112, 103, 162, 98, 136, 90], /*left = v   */
+        [62, 30, 23, 158, 200, 207, 59, 57, 50],  /*left = h   */
+        [67, 30, 29, 84, 86, 191, 102, 91, 59],   /*left = d45 */
+        [60, 32, 33, 112, 71, 220, 64, 89, 104],  /*left = d135*/
+        [53, 26, 34, 130, 56, 149, 84, 120, 103], /*left = d117*/
+        [53, 21, 23, 133, 109, 210, 56, 77, 172], /*left = d153*/
+        [77, 19, 29, 112, 142, 228, 55, 66, 36],  /*left = d207*/
+        [61, 29, 29, 93, 97, 165, 83, 175, 162],  /*left = d63 */
+        [47, 47, 43, 114, 137, 181, 100, 99, 95], /*left = tm  */
+    ],
+    [
+        /* above = d135 */
+        [69, 23, 29, 128, 83, 199, 46, 44, 101], /*left = dc  */
+        [53, 40, 55, 139, 69, 183, 61, 80, 110], /*left = v   */
+        [40, 29, 19, 161, 180, 207, 43, 24, 91], /*left = h   */
+        [60, 34, 19, 105, 61, 198, 53, 64, 89],  /*left = d45 */
+        [52, 31, 22, 158, 40, 209, 58, 62, 89],  /*left = d135*/
+        [44, 31, 29, 147, 46, 158, 56, 102, 198], /*left = d117*/
+        [35, 19, 12, 135, 87, 209, 41, 45, 167], /*left = d153*/
+        [55, 25, 21, 118, 95, 215, 38, 39, 66],  /*left = d207*/
+        [51, 38, 25, 113, 58, 164, 70, 93, 97],  /*left = d63 */
+        [47, 54, 34, 146, 108, 203, 72, 103, 151], /*left = tm  */
+    ],
+    [
+        /* above = d117 */
+        [64, 19, 37, 156, 66, 138, 49, 95, 133], /*left = dc  */
+        [46, 27, 80, 150, 55, 124, 55, 121, 135], /*left = v   */
+        [36, 23, 27, 165, 149, 166, 54, 64, 118], /*left = h   */
+        [53, 21, 36, 131, 63, 163, 60, 109, 81], /*left = d45 */
+        [40, 26, 35, 154, 40, 185, 51, 97, 123], /*left = d135*/
+        [35, 19, 34, 179, 19, 97, 48, 129, 124], /*left = d117*/
+        [36, 20, 26, 136, 62, 164, 33, 77, 154], /*left = d153*/
+        [45, 18, 32, 130, 90, 157, 40, 79, 91],  /*left = d207*/
+        [45, 26, 28, 129, 45, 129, 49, 147, 123], /*left = d63 */
+        [38, 44, 51, 136, 74, 162, 57, 97, 121], /*left = tm  */
+    ],
+    [
+        /* above = d153 */
+        [75, 17, 22, 136, 138, 185, 32, 34, 166], /*left = dc  */
+        [56, 39, 58, 133, 117, 173, 48, 53, 187], /*left = v   */
+        [35, 21, 12, 161, 212, 207, 20, 23, 145], /*left = h   */
+        [56, 29, 19, 117, 109, 181, 55, 68, 112], /*left = d45 */
+        [47, 29, 17, 153, 64, 220, 59, 51, 114],  /*left = d135*/
+        [46, 16, 24, 136, 76, 147, 41, 64, 172],  /*left = d117*/
+        [34, 17, 11, 108, 152, 187, 13, 15, 209], /*left = d153*/
+        [51, 24, 14, 115, 133, 209, 32, 26, 104], /*left = d207*/
+        [55, 30, 18, 122, 79, 179, 44, 88, 116],  /*left = d63 */
+        [37, 49, 25, 129, 168, 164, 41, 54, 148], /*left = tm  */
+    ],
+    [
+        /* above = d207 */
+        [82, 22, 32, 127, 143, 213, 39, 41, 70], /*left = dc  */
+        [62, 44, 61, 123, 105, 189, 48, 57, 64], /*left = v   */
+        [47, 25, 17, 175, 222, 220, 24, 30, 86], /*left = h   */
+        [68, 36, 17, 106, 102, 206, 59, 74, 74], /*left = d45 */
+        [57, 39, 23, 151, 68, 216, 55, 63, 58],  /*left = d135*/
+        [49, 30, 35, 141, 70, 168, 82, 40, 115], /*left = d117*/
+        [51, 25, 15, 136, 129, 202, 38, 35, 139], /*left = d153*/
+        [68, 26, 16, 111, 141, 215, 29, 28, 28], /*left = d207*/
+        [59, 39, 19, 114, 75, 180, 77, 104, 42], /*left = d63 */
+        [40, 61, 26, 126, 152, 206, 61, 59, 93], /*left = tm  */
+    ],
+    [
+        /* above = d63 */
+        [78, 23, 39, 111, 117, 170, 74, 124, 94], /*left = dc  */
+        [48, 34, 86, 101, 92, 146, 78, 179, 134], /*left = v   */
+        [47, 22, 24, 138, 187, 178, 68, 69, 59],  /*left = h   */
+        [56, 25, 33, 105, 112, 187, 95, 177, 129], /*left = d45 */
+        [48, 31, 27, 114, 63, 183, 82, 116, 56],  /*left = d135*/
+        [43, 28, 37, 121, 63, 123, 61, 192, 169], /*left = d117*/
+        [42, 17, 24, 109, 97, 177, 56, 76, 122],  /*left = d153*/
+        [58, 18, 28, 105, 139, 182, 70, 92, 63],  /*left = d207*/
+        [46, 23, 32, 74, 86, 150, 67, 183, 88],   /*left = d63 */
+        [36, 38, 48, 92, 122, 165, 88, 137, 91],  /*left = tm  */
+    ],
+    [
+        /* above = tm */
+        [65, 70, 60, 155, 159, 199, 61, 60, 81], /*left = dc  */
+        [44, 78, 115, 132, 119, 173, 71, 112, 93], /*left = v   */
+        [39, 38, 21, 184, 227, 206, 42, 32, 64], /*left = h   */
+        [58, 47, 36, 124, 137, 193, 80, 82, 78], /*left = d45 */
+        [49, 50, 35, 144, 95, 205, 63, 78, 59],  /*left = d135*/
+        [41, 53, 52, 148, 71, 142, 65, 128, 51], /*left = d117*/
+        [40, 36, 28, 143, 143, 202, 40, 55, 137], /*left = d153*/
+        [52, 34, 29, 129, 183, 227, 42, 35, 43], /*left = d207*/
+        [42, 44, 44, 104, 105, 164, 64, 130, 80], /*left = d63 */
+        [43, 81, 53, 140, 169, 204, 68, 84, 72], /*left = tm  */
+    ],
+];
+
+#[no_mangle]
+static v4l2_vp9_kf_partition_probs_rs: [[u8; 3]; 16] = [
+    /* 8x8 -> 4x4 */
+    [158, 97, 94], /* a/l both not split   */
+    [93, 24, 99],  /* a split, l not split */
+    [85, 119, 44], /* l split, a not split */
+    [62, 59, 67],  /* a/l both split       */
+    /* 16x16 -> 8x8 */
+    [149, 53, 53], /* a/l both not split   */
+    [94, 20, 48],  /* a split, l not split */
+    [83, 53, 24],  /* l split, a not split */
+    [52, 18, 18],  /* a/l both split       */
+    /* 32x32 -> 16x16 */
+    [150, 40, 39], /* a/l both not split   */
+    [78, 12, 26],  /* a split, l not split */
+    [67, 33, 11],  /* l split, a not split */
+    [24, 7, 5],    /* a/l both split       */
+    /* 64x64 -> 32x32 */
+    [174, 35, 49], /* a/l both not split   */
+    [68, 11, 27],  /* a split, l not split */
+    [57, 15, 9],   /* l split, a not split */
+    [12, 3, 3],    /* a/l both split       */
+];
+
+#[no_mangle]
+static v4l2_vp9_kf_uv_mode_prob_rs: [[u8; 9]; 10] = [
+    [144, 11, 54, 157, 195, 130, 46, 58, 108],  /* y = dc   */
+    [118, 15, 123, 148, 131, 101, 44, 93, 131], /* y = v    */
+    [113, 12, 23, 188, 226, 142, 26, 32, 125],  /* y = h    */
+    [120, 11, 50, 123, 163, 135, 64, 77, 103],  /* y = d45  */
+    [113, 9, 36, 155, 111, 157, 32, 44, 161],   /* y = d135 */
+    [116, 9, 55, 176, 76, 96, 37, 61, 149],     /* y = d117 */
+    [115, 9, 28, 141, 161, 167, 21, 25, 193],   /* y = d153 */
+    [120, 12, 32, 145, 195, 142, 32, 38, 86],   /* y = d207 */
+    [116, 12, 64, 120, 140, 125, 49, 115, 121], /* y = d63  */
+    [102, 19, 66, 162, 182, 122, 35, 59, 128],  /* y = tm   */
+];
+
+#[no_mangle]
+static v4l2_vp9_default_probs_rs: FrameContext = FrameContext {
+    tx8: [[100], [66]],
+    tx16: [[20, 152], [15, 101]],
+    tx32: [[3, 136, 37], [5, 52, 13]],
+    coef: [
+        [
+            /* tx  4x4 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [195, 29, 183],
+                        [84, 49, 136],
+                        [8, 42, 71],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [31, 107, 169],
+                        [35, 99, 159],
+                        [17, 82, 140],
+                        [8, 66, 114],
+                        [2, 44, 76],
+                        [1, 19, 32],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [40, 132, 201],
+                        [29, 114, 187],
+                        [13, 91, 157],
+                        [7, 75, 127],
+                        [3, 58, 95],
+                        [1, 28, 47],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [69, 142, 221],
+                        [42, 122, 201],
+                        [15, 91, 159],
+                        [6, 67, 121],
+                        [1, 42, 77],
+                        [1, 17, 31],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [102, 148, 228],
+                        [67, 117, 204],
+                        [17, 82, 154],
+                        [6, 59, 114],
+                        [2, 39, 75],
+                        [1, 15, 29],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [156, 57, 233],
+                        [119, 57, 212],
+                        [58, 48, 163],
+                        [29, 40, 124],
+                        [12, 30, 81],
+                        [3, 12, 31],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [191, 107, 226],
+                        [124, 117, 204],
+                        [25, 99, 155],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [29, 148, 210],
+                        [37, 126, 194],
+                        [8, 93, 157],
+                        [2, 68, 118],
+                        [1, 39, 69],
+                        [1, 17, 33],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [41, 151, 213],
+                        [27, 123, 193],
+                        [3, 82, 144],
+                        [1, 58, 105],
+                        [1, 32, 60],
+                        [1, 13, 26],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [59, 159, 220],
+                        [23, 126, 198],
+                        [4, 88, 151],
+                        [1, 66, 114],
+                        [1, 38, 71],
+                        [1, 18, 34],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [114, 136, 232],
+                        [51, 114, 207],
+                        [11, 83, 155],
+                        [3, 56, 105],
+                        [1, 33, 65],
+                        [1, 17, 34],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [149, 65, 234],
+                        [121, 57, 215],
+                        [61, 49, 166],
+                        [28, 36, 114],
+                        [12, 25, 76],
+                        [3, 16, 42],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [214, 49, 220],
+                        [132, 63, 188],
+                        [42, 65, 137],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [85, 137, 221],
+                        [104, 131, 216],
+                        [49, 111, 192],
+                        [21, 87, 155],
+                        [2, 49, 87],
+                        [1, 16, 28],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [89, 163, 230],
+                        [90, 137, 220],
+                        [29, 100, 183],
+                        [10, 70, 135],
+                        [2, 42, 81],
+                        [1, 17, 33],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [108, 167, 237],
+                        [55, 133, 222],
+                        [15, 97, 179],
+                        [4, 72, 135],
+                        [1, 45, 85],
+                        [1, 19, 38],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [124, 146, 240],
+                        [66, 124, 224],
+                        [17, 88, 175],
+                        [4, 58, 122],
+                        [1, 36, 75],
+                        [1, 18, 37],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [141, 79, 241],
+                        [126, 70, 227],
+                        [66, 58, 182],
+                        [30, 44, 136],
+                        [12, 34, 96],
+                        [2, 20, 47],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [229, 99, 249],
+                        [143, 111, 235],
+                        [46, 109, 192],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [82, 158, 236],
+                        [94, 146, 224],
+                        [25, 117, 191],
+                        [9, 87, 149],
+                        [3, 56, 99],
+                        [1, 33, 57],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [83, 167, 237],
+                        [68, 145, 222],
+                        [10, 103, 177],
+                        [2, 72, 131],
+                        [1, 41, 79],
+                        [1, 20, 39],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [99, 167, 239],
+                        [47, 141, 224],
+                        [10, 104, 178],
+                        [2, 73, 133],
+                        [1, 44, 85],
+                        [1, 22, 47],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [127, 145, 243],
+                        [71, 129, 228],
+                        [17, 93, 177],
+                        [3, 61, 124],
+                        [1, 41, 84],
+                        [1, 21, 52],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [157, 78, 244],
+                        [140, 72, 231],
+                        [69, 58, 184],
+                        [31, 44, 137],
+                        [14, 38, 105],
+                        [8, 23, 61],
+                    ],
+                ],
+            ],
+        ],
+        [
+            /* tx  8x8 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [125, 34, 187],
+                        [52, 41, 133],
+                        [6, 31, 56],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [37, 109, 153],
+                        [51, 102, 147],
+                        [23, 87, 128],
+                        [8, 67, 101],
+                        [1, 41, 63],
+                        [1, 19, 29],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [31, 154, 185],
+                        [17, 127, 175],
+                        [6, 96, 145],
+                        [2, 73, 114],
+                        [1, 51, 82],
+                        [1, 28, 45],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [23, 163, 200],
+                        [10, 131, 185],
+                        [2, 93, 148],
+                        [1, 67, 111],
+                        [1, 41, 69],
+                        [1, 14, 24],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [29, 176, 217],
+                        [12, 145, 201],
+                        [3, 101, 156],
+                        [1, 69, 111],
+                        [1, 39, 63],
+                        [1, 14, 23],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [57, 192, 233],
+                        [25, 154, 215],
+                        [6, 109, 167],
+                        [3, 78, 118],
+                        [1, 48, 69],
+                        [1, 21, 29],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [202, 105, 245],
+                        [108, 106, 216],
+                        [18, 90, 144],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [33, 172, 219],
+                        [64, 149, 206],
+                        [14, 117, 177],
+                        [5, 90, 141],
+                        [2, 61, 95],
+                        [1, 37, 57],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [33, 179, 220],
+                        [11, 140, 198],
+                        [1, 89, 148],
+                        [1, 60, 104],
+                        [1, 33, 57],
+                        [1, 12, 21],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [30, 181, 221],
+                        [8, 141, 198],
+                        [1, 87, 145],
+                        [1, 58, 100],
+                        [1, 31, 55],
+                        [1, 12, 20],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [32, 186, 224],
+                        [7, 142, 198],
+                        [1, 86, 143],
+                        [1, 58, 100],
+                        [1, 31, 55],
+                        [1, 12, 22],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [57, 192, 227],
+                        [20, 143, 204],
+                        [3, 96, 154],
+                        [1, 68, 112],
+                        [1, 42, 69],
+                        [1, 19, 32],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [212, 35, 215],
+                        [113, 47, 169],
+                        [29, 48, 105],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [74, 129, 203],
+                        [106, 120, 203],
+                        [49, 107, 178],
+                        [19, 84, 144],
+                        [4, 50, 84],
+                        [1, 15, 25],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [71, 172, 217],
+                        [44, 141, 209],
+                        [15, 102, 173],
+                        [6, 76, 133],
+                        [2, 51, 89],
+                        [1, 24, 42],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [64, 185, 231],
+                        [31, 148, 216],
+                        [8, 103, 175],
+                        [3, 74, 131],
+                        [1, 46, 81],
+                        [1, 18, 30],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [65, 196, 235],
+                        [25, 157, 221],
+                        [5, 105, 174],
+                        [1, 67, 120],
+                        [1, 38, 69],
+                        [1, 15, 30],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [65, 204, 238],
+                        [30, 156, 224],
+                        [7, 107, 177],
+                        [2, 70, 124],
+                        [1, 42, 73],
+                        [1, 18, 34],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [225, 86, 251],
+                        [144, 104, 235],
+                        [42, 99, 181],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [85, 175, 239],
+                        [112, 165, 229],
+                        [29, 136, 200],
+                        [12, 103, 162],
+                        [6, 77, 123],
+                        [2, 53, 84],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [75, 183, 239],
+                        [30, 155, 221],
+                        [3, 106, 171],
+                        [1, 74, 128],
+                        [1, 44, 76],
+                        [1, 17, 28],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [73, 185, 240],
+                        [27, 159, 222],
+                        [2, 107, 172],
+                        [1, 75, 127],
+                        [1, 42, 73],
+                        [1, 17, 29],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [62, 190, 238],
+                        [21, 159, 222],
+                        [2, 107, 172],
+                        [1, 72, 122],
+                        [1, 40, 71],
+                        [1, 18, 32],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [61, 199, 240],
+                        [27, 161, 226],
+                        [4, 113, 180],
+                        [1, 76, 129],
+                        [1, 46, 80],
+                        [1, 23, 41],
+                    ],
+                ],
+            ],
+        ],
+        [
+            /* tx  16x16 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [7, 27, 153],
+                        [5, 30, 95],
+                        [1, 16, 30],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [50, 75, 127],
+                        [57, 75, 124],
+                        [27, 67, 108],
+                        [10, 54, 86],
+                        [1, 33, 52],
+                        [1, 12, 18],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [43, 125, 151],
+                        [26, 108, 148],
+                        [7, 83, 122],
+                        [2, 59, 89],
+                        [1, 38, 60],
+                        [1, 17, 27],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [23, 144, 163],
+                        [13, 112, 154],
+                        [2, 75, 117],
+                        [1, 50, 81],
+                        [1, 31, 51],
+                        [1, 14, 23],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [18, 162, 185],
+                        [6, 123, 171],
+                        [1, 78, 125],
+                        [1, 51, 86],
+                        [1, 31, 54],
+                        [1, 14, 23],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [15, 199, 227],
+                        [3, 150, 204],
+                        [1, 91, 146],
+                        [1, 55, 95],
+                        [1, 30, 53],
+                        [1, 11, 20],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [19, 55, 240],
+                        [19, 59, 196],
+                        [3, 52, 105],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [41, 166, 207],
+                        [104, 153, 199],
+                        [31, 123, 181],
+                        [14, 101, 152],
+                        [5, 72, 106],
+                        [1, 36, 52],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [35, 176, 211],
+                        [12, 131, 190],
+                        [2, 88, 144],
+                        [1, 60, 101],
+                        [1, 36, 60],
+                        [1, 16, 28],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [28, 183, 213],
+                        [8, 134, 191],
+                        [1, 86, 142],
+                        [1, 56, 96],
+                        [1, 30, 53],
+                        [1, 12, 20],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [20, 190, 215],
+                        [4, 135, 192],
+                        [1, 84, 139],
+                        [1, 53, 91],
+                        [1, 28, 49],
+                        [1, 11, 20],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [13, 196, 216],
+                        [2, 137, 192],
+                        [1, 86, 143],
+                        [1, 57, 99],
+                        [1, 32, 56],
+                        [1, 13, 24],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [211, 29, 217],
+                        [96, 47, 156],
+                        [22, 43, 87],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [78, 120, 193],
+                        [111, 116, 186],
+                        [46, 102, 164],
+                        [15, 80, 128],
+                        [2, 49, 76],
+                        [1, 18, 28],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [71, 161, 203],
+                        [42, 132, 192],
+                        [10, 98, 150],
+                        [3, 69, 109],
+                        [1, 44, 70],
+                        [1, 18, 29],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [57, 186, 211],
+                        [30, 140, 196],
+                        [4, 93, 146],
+                        [1, 62, 102],
+                        [1, 38, 65],
+                        [1, 16, 27],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [47, 199, 217],
+                        [14, 145, 196],
+                        [1, 88, 142],
+                        [1, 57, 98],
+                        [1, 36, 62],
+                        [1, 15, 26],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [26, 219, 229],
+                        [5, 155, 207],
+                        [1, 94, 151],
+                        [1, 60, 104],
+                        [1, 36, 62],
+                        [1, 16, 28],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [233, 29, 248],
+                        [146, 47, 220],
+                        [43, 52, 140],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [100, 163, 232],
+                        [179, 161, 222],
+                        [63, 142, 204],
+                        [37, 113, 174],
+                        [26, 89, 137],
+                        [18, 68, 97],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [85, 181, 230],
+                        [32, 146, 209],
+                        [7, 100, 164],
+                        [3, 71, 121],
+                        [1, 45, 77],
+                        [1, 18, 30],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [65, 187, 230],
+                        [20, 148, 207],
+                        [2, 97, 159],
+                        [1, 68, 116],
+                        [1, 40, 70],
+                        [1, 14, 29],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [40, 194, 227],
+                        [8, 147, 204],
+                        [1, 94, 155],
+                        [1, 65, 112],
+                        [1, 39, 66],
+                        [1, 14, 26],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [16, 208, 228],
+                        [3, 151, 207],
+                        [1, 98, 160],
+                        [1, 67, 117],
+                        [1, 41, 74],
+                        [1, 17, 31],
+                    ],
+                ],
+            ],
+        ],
+        [
+            /* tx  32x32 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [17, 38, 140],
+                        [7, 34, 80],
+                        [1, 17, 29],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [37, 75, 128],
+                        [41, 76, 128],
+                        [26, 66, 116],
+                        [12, 52, 94],
+                        [2, 32, 55],
+                        [1, 10, 16],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [50, 127, 154],
+                        [37, 109, 152],
+                        [16, 82, 121],
+                        [5, 59, 85],
+                        [1, 35, 54],
+                        [1, 13, 20],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [40, 142, 167],
+                        [17, 110, 157],
+                        [2, 71, 112],
+                        [1, 44, 72],
+                        [1, 27, 45],
+                        [1, 11, 17],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [30, 175, 188],
+                        [9, 124, 169],
+                        [1, 74, 116],
+                        [1, 48, 78],
+                        [1, 30, 49],
+                        [1, 11, 18],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [10, 222, 223],
+                        [2, 150, 194],
+                        [1, 83, 128],
+                        [1, 48, 79],
+                        [1, 27, 45],
+                        [1, 11, 17],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [36, 41, 235],
+                        [29, 36, 193],
+                        [10, 27, 111],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [85, 165, 222],
+                        [177, 162, 215],
+                        [110, 135, 195],
+                        [57, 113, 168],
+                        [23, 83, 120],
+                        [10, 49, 61],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [85, 190, 223],
+                        [36, 139, 200],
+                        [5, 90, 146],
+                        [1, 60, 103],
+                        [1, 38, 65],
+                        [1, 18, 30],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [72, 202, 223],
+                        [23, 141, 199],
+                        [2, 86, 140],
+                        [1, 56, 97],
+                        [1, 36, 61],
+                        [1, 16, 27],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [55, 218, 225],
+                        [13, 145, 200],
+                        [1, 86, 141],
+                        [1, 57, 99],
+                        [1, 35, 61],
+                        [1, 13, 22],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [15, 235, 212],
+                        [1, 132, 184],
+                        [1, 84, 139],
+                        [1, 57, 97],
+                        [1, 34, 56],
+                        [1, 14, 23],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [181, 21, 201],
+                        [61, 37, 123],
+                        [10, 38, 71],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [47, 106, 172],
+                        [95, 104, 173],
+                        [42, 93, 159],
+                        [18, 77, 131],
+                        [4, 50, 81],
+                        [1, 17, 23],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [62, 147, 199],
+                        [44, 130, 189],
+                        [28, 102, 154],
+                        [18, 75, 115],
+                        [2, 44, 65],
+                        [1, 12, 19],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [55, 153, 210],
+                        [24, 130, 194],
+                        [3, 93, 146],
+                        [1, 61, 97],
+                        [1, 31, 50],
+                        [1, 10, 16],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [49, 186, 223],
+                        [17, 148, 204],
+                        [1, 96, 142],
+                        [1, 53, 83],
+                        [1, 26, 44],
+                        [1, 11, 17],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [13, 217, 212],
+                        [2, 136, 180],
+                        [1, 78, 124],
+                        [1, 50, 83],
+                        [1, 29, 49],
+                        [1, 14, 23],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [197, 13, 247],
+                        [82, 17, 222],
+                        [25, 17, 162],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [126, 186, 247],
+                        [234, 191, 243],
+                        [176, 177, 234],
+                        [104, 158, 220],
+                        [66, 128, 186],
+                        [55, 90, 137],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [111, 197, 242],
+                        [46, 158, 219],
+                        [9, 104, 171],
+                        [2, 65, 125],
+                        [1, 44, 80],
+                        [1, 17, 91],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [104, 208, 245],
+                        [39, 168, 224],
+                        [3, 109, 162],
+                        [1, 79, 124],
+                        [1, 50, 102],
+                        [1, 43, 102],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [84, 220, 246],
+                        [31, 177, 231],
+                        [2, 115, 180],
+                        [1, 79, 134],
+                        [1, 55, 77],
+                        [1, 60, 79],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [43, 243, 240],
+                        [8, 180, 217],
+                        [1, 115, 166],
+                        [1, 84, 121],
+                        [1, 51, 67],
+                        [1, 16, 6],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    skip: [192, 128, 64],
+    inter_mode: [
+        [2, 173, 34],
+        [7, 145, 85],
+        [7, 166, 63],
+        [7, 94, 66],
+        [8, 64, 46],
+        [17, 81, 31],
+        [25, 29, 30],
+    ],
+    interp_filter: [[235, 162], [36, 255], [34, 3], [149, 144]],
+    is_inter: [9, 102, 187, 225],
+    comp_mode: [239, 183, 119, 96, 41],
+    single_ref: [[33, 16], [77, 74], [142, 142], [172, 170], [238, 247]],
+    comp_ref: [50, 126, 123, 221, 226],
+    y_mode: [
+        [65, 32, 18, 144, 162, 194, 41, 51, 98],
+        [132, 68, 18, 165, 217, 196, 45, 40, 78],
+        [173, 80, 19, 176, 240, 193, 64, 35, 46],
+        [221, 135, 38, 194, 248, 121, 96, 85, 29],
+    ],
+    uv_mode: [
+        [120, 7, 76, 176, 208, 126, 28, 54, 103],   /* y  dc */
+        [48, 12, 154, 155, 139, 90, 34, 117, 119],  /* y  v */
+        [67, 6, 25, 204, 243, 158, 13, 21, 96],     /* y  h */
+        [97, 5, 44, 131, 176, 139, 48, 68, 97],     /* y  d45 */
+        [83, 5, 42, 156, 111, 152, 26, 49, 152],    /* y  d135 */
+        [80, 5, 58, 178, 74, 83, 33, 62, 145],      /* y  d117 */
+        [86, 5, 32, 154, 192, 168, 14, 22, 163],    /* y  d153 */
+        [85, 5, 32, 156, 216, 148, 19, 29, 73],     /* y  d207 */
+        [77, 7, 64, 116, 132, 122, 37, 126, 120],   /* y  d63 */
+        [101, 21, 107, 181, 192, 103, 19, 67, 125], /* y  tm */
+    ],
+    partition: [
+        /* 8x8 -> 4x4 */
+        [199, 122, 141], /* a/l both not split */
+        [147, 63, 159],  /* a split, l not split */
+        [148, 133, 118], /* l split, a not split */
+        [121, 104, 114], /* a/l both split */
+        /* 16x16 -> 8x8 */
+        [174, 73, 87], /* a/l both not split */
+        [92, 41, 83],  /* a split, l not split */
+        [82, 99, 50],  /* l split, a not split */
+        [53, 39, 39],  /* a/l both split */
+        /* 32x32 -> 16x16 */
+        [177, 58, 59], /* a/l both not split */
+        [68, 26, 63],  /* a split, l not split */
+        [52, 79, 25],  /* l split, a not split */
+        [17, 14, 12],  /* a/l both split */
+        /* 64x64 -> 32x32 */
+        [222, 34, 30], /* a/l both not split */
+        [72, 16, 44],  /* a split, l not split */
+        [58, 32, 12],  /* l split, a not split */
+        [10, 7, 6],    /* a/l both split */
+    ],
+    mv: FrameMvContext {
+        joint: [32, 64, 96],
+        sign: [128, 128],
+        classes: [
+            [224, 144, 192, 168, 192, 176, 192, 198, 198, 245],
+            [216, 128, 176, 160, 176, 176, 192, 198, 198, 208],
+        ],
+        class0_bit: [216, 208],
+        bits: [
+            [136, 140, 148, 160, 176, 192, 224, 234, 234, 240],
+            [136, 140, 148, 160, 176, 192, 224, 234, 234, 240],
+        ],
+        class0_fr: [
+            [[128, 128, 64], [96, 112, 64]],
+            [[128, 128, 64], [96, 112, 64]],
+        ],
+        fr: [[64, 96, 64], [64, 96, 64]],
+        class0_hp: [160, 160],
+        hp: [128, 128],
+    },
+};
+
+#[no_mangle]
+/// Counterpart to 6.3 compressed_header(), but parsing has been done in userspace.
+pub extern "C" fn v4l2_vp9_fw_update_probs_rs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+) {
+    if u32::from(deltas.tx_mode) == bindings::V4L2_VP9_TX_MODE_SELECT {
+        update_tx_probs(probs, deltas);
+    }
+
+    update_coeff_probs(probs, deltas, dec_params);
+    update_skip_probs(probs, deltas);
+
+    if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+        || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0
+    {
+        return;
+    }
+
+    update_inter_mode_probs(probs, deltas);
+
+    if u32::from(dec_params.interpolation_filter) == bindings::V4L2_VP9_INTERP_FILTER_SWITCHABLE {
+        update_interp_filter_probs(probs, deltas);
+    }
+
+    update_is_inter_probs(probs, deltas);
+    update_frame_reference_mode_probs(dec_params.reference_mode.into(), probs, deltas);
+
+    update_y_mode_probs(probs, deltas);
+    update_partition_probs(probs, deltas);
+    update_mv_probs(probs, deltas, dec_params);
+}
+
+#[no_mangle]
+pub extern "C" fn v4l2_vp9_reset_frame_ctx_rs(
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+    frame_context: &mut [FrameContext; 4],
+) -> u8 {
+    let mut fctx_idx = dec_params.frame_context_idx;
+
+    if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+        || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0
+        || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT != 0
+    {
+        /*
+         * setup_past_independence()
+         * We do nothing here. Instead of storing default probs in some intermediate
+         * location and then copying from that location to appropriate contexts
+         * in save_probs() below, we skip that step and save default probs directly
+         * to appropriate contexts.
+         */
+
+        if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+            || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT != 0
+            || u32::from(dec_params.reset_frame_context) == bindings::V4L2_VP9_RESET_FRAME_CTX_ALL
+        {
+            for i in 0..4 {
+                /* save_probs(i) */
+                frame_context[i] = v4l2_vp9_default_probs_rs.clone();
+            }
+        } else if u32::from(dec_params.reset_frame_context)
+            == bindings::V4L2_VP9_RESET_FRAME_CTX_SPEC
+        {
+            /* save_probs(fctx_idx) */
+            frame_context[usize::from(fctx_idx)] = v4l2_vp9_default_probs_rs.clone();
+        }
+
+        fctx_idx = 0;
+    }
+
+    fctx_idx
+}
+
+#[no_mangle]
+pub extern "C" fn v4l2_vp9_adapt_coef_probs_rs(
+    probs: &mut FrameContext,
+    counts: &mut FrameSymbolCounts<'_>,
+    use_128: bool,
+    frame_is_intra: bool,
+) {
+    if frame_is_intra {
+        _adapt_coef_probs(probs, counts, 112);
+    } else {
+        if use_128 {
+            _adapt_coef_probs(probs, counts, 128);
+        } else {
+            _adapt_coef_probs(probs, counts, 112);
+        }
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn v4l2_vp9_adapt_noncoef_probs_rs(
+    probs: &mut FrameContext,
+    counts: &mut FrameSymbolCounts<'_>,
+    reference_mode: u8,
+    interpolation_filter: u8,
+    tx_mode: u8,
+    flags: u32,
+) {
+    for i in 0..probs.is_inter.len() {
+        probs.is_inter[i] = adapt_prob(probs.is_inter[i], counts.intra_inter[i]);
+    }
+
+    for i in 0..probs.comp_mode.len() {
+        probs.comp_mode[i] = adapt_prob(probs.comp_mode[i], counts.comp[i]);
+    }
+
+    for i in 0..probs.comp_ref.len() {
+        probs.comp_ref[i] = adapt_prob(probs.comp_ref[i], counts.comp_ref[i]);
+    }
+
+    if u32::from(reference_mode) != bindings::V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE {
+        for i in 0..probs.single_ref.len() {
+            for j in 0..probs.single_ref[0].len() {
+                probs.single_ref[i][j] =
+                    adapt_prob(probs.single_ref[i][j], counts.single_ref[i][j]);
+            }
+        }
+    }
+
+    for i in 0..probs.inter_mode.len() {
+        adapt_probs_variant_c(&mut probs.inter_mode[i], &counts.mv_mode[i]);
+    }
+
+    for i in 0..probs.y_mode.len() {
+        adapt_probs_variant_d(&mut probs.y_mode[i], &counts.y_mode[i]);
+    }
+
+    for i in 0..probs.uv_mode.len() {
+        adapt_probs_variant_d(&mut probs.uv_mode[i], &counts.uv_mode[i]);
+    }
+
+    for i in 0..probs.partition.len() {
+        adapt_probs_variant_e(&mut probs.partition[i], &counts.partition[i]);
+    }
+
+    for i in 0..probs.skip.len() {
+        probs.skip[i] = adapt_prob(probs.skip[i], counts.skip[i]);
+    }
+
+    if u32::from(interpolation_filter) == bindings::V4L2_VP9_INTERP_FILTER_SWITCHABLE {
+        for i in 0..probs.interp_filter.len() {
+            adapt_probs_variant_f(&mut probs.interp_filter[i], &counts.filter[i]);
+        }
+    }
+
+    if u32::from(tx_mode) == bindings::V4L2_VP9_TX_MODE_SELECT {
+        for i in 0..probs.tx8.len() {
+            adapt_probs_variant_b(&mut probs.tx8[i], &counts.tx8p[i]);
+            adapt_probs_variant_f(&mut probs.tx16[i], &counts.tx16p[i]);
+            adapt_probs_variant_e(&mut probs.tx32[i], &counts.tx32p[i]);
+        }
+    }
+
+    adapt_probs_variant_e(&mut probs.mv.joint, counts.mv_joint);
+
+    for i in 0..probs.mv.sign.len() {
+        probs.mv.sign[i] = adapt_prob(probs.mv.sign[i], counts.sign[i]);
+
+        adapt_probs_variant_g(&mut probs.mv.classes[i], &counts.classes[i]);
+
+        probs.mv.class0_bit[i] = adapt_prob(probs.mv.class0_bit[i], counts.class0[i]);
+
+        for j in 0..probs.mv.bits[0].len() {
+            probs.mv.bits[i][j] = adapt_prob(probs.mv.bits[i][j], counts.bits[i][j]);
+        }
+
+        for j in 0..probs.mv.class0_fr[0].len() {
+            adapt_probs_variant_e(&mut probs.mv.class0_fr[i][j], &counts.class0_fp[i][j]);
+        }
+
+        adapt_probs_variant_e(&mut probs.mv.fr[i], &counts.fp[i]);
+
+        if flags & bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV == 0 {
+            continue;
+        }
+
+        probs.mv.class0_hp[i] = adapt_prob(probs.mv.class0_hp[i], counts.class0_hp[i]);
+
+        probs.mv.hp[i] = adapt_prob(probs.mv.hp[i], counts.hp[i]);
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn v4l2_vp9_seg_feat_enabled_rs(
+    feature_enabled: &mut u8,
+    feature: u32,
+    segid: u32,
+) -> bool {
+    let feature_enabled = unsafe { core::slice::from_raw_parts_mut(feature_enabled, 8) };
+    let mask = 1 << feature;
+    feature_enabled[segid as usize] & mask != 0
+}
+
+fn fastdiv(dividend: u32, divisor: u32) -> u32 {
+    const fn inv<const SZ: usize>() -> [u32; SZ] {
+        let mut ret = [0; SZ];
+        let mut i = 2;
+        let n = SZ - 1;
+
+        while i < n {
+            ret[i - 2] = ((1 << 32) + (i - 1) / i) as u32;
+            i += 1;
+        }
+
+        ret
+    }
+    const SZ: usize = 255;
+    const INV: [u32; SZ] = inv::<SZ>();
+    if divisor - 2 >= SZ as u32 {
+        crate::pr_warn!("fastdiv: divisor {} too large", divisor);
+        return dividend;
+    }
+
+    if divisor == 0 {
+        0
+    } else if divisor == 1 {
+        dividend
+    } else {
+        let ret = (u64::from(dividend) * u64::from(INV[divisor as usize - 2])) >> 32;
+        ret as u32
+    }
+}
+
+fn inv_recenter_nonneg(v: i32, m: i32) -> i32 {
+    if v > 2 * m {
+        v
+    } else if (v & 1) != 0 {
+        m - ((v + 1) >> 1)
+    } else {
+        m + (v >> 1)
+    }
+}
+
+fn update_prob(delta: i32, prob: i32) -> i32 {
+    if delta == 0 {
+        prob
+    } else if prob <= 128 {
+        1 + inv_recenter_nonneg(delta, prob - 1)
+    } else {
+        255 - inv_recenter_nonneg(delta, 255 - prob)
+    }
+}
+
+fn update_tx_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) {
+    for i in 0..probs.tx8.len() {
+        let p8x8 = &mut probs.tx8[i];
+        let p16x16 = &mut probs.tx16[i];
+        let p32x32 = &mut probs.tx32[i];
+
+        let d8x8 = &deltas.tx8[i];
+        let d16x16 = &deltas.tx16[i];
+        let d32x32 = &deltas.tx32[i];
+
+        p8x8[0] = update_prob(d8x8[0].into(), p8x8[0].into()) as u8;
+        p16x16[0] = update_prob(d16x16[0].into(), p16x16[0].into()) as u8;
+        p16x16[1] = update_prob(d16x16[1].into(), p16x16[1].into()) as u8;
+        p32x32[0] = update_prob(d32x32[0].into(), p32x32[0].into()) as u8;
+        p32x32[1] = update_prob(d32x32[1].into(), p32x32[1].into()) as u8;
+        p32x32[2] = update_prob(d32x32[2].into(), p32x32[2].into()) as u8;
+    }
+}
+
+macro_rules! BAND_6 {
+    ($band:expr) => {
+        if $band == 0 {
+            3
+        } else {
+            6
+        }
+    };
+}
+
+fn update_coeff(deltas: &[[[u8; 3]; 6]; 6], probs: &mut [[[u8; 3]; 6]; 6]) {
+    for l in 0..6 {
+        for m in 0..BAND_6!(l) {
+            let p = &mut probs[l][m];
+            let d = &deltas[l][m];
+
+            for n in 0..3 {
+                p[n] = update_prob(d[n].into(), p[n].into()) as u8;
+            }
+        }
+    }
+}
+
+fn update_coeff_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+) {
+    for i in 0..probs.coef.len() {
+        for j in 0..probs.coef[0].len() {
+            for k in 0..probs.coef[0][0].len() {
+                update_coeff(&deltas.coef[i][j][k], &mut probs.coef[i][j][k]);
+            }
+        }
+
+        if usize::from(deltas.tx_mode) == i {
+            break;
+        }
+    }
+}
+
+fn update_skip_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) {
+    for i in 0..probs.skip.len() {
+        probs.skip[i] = update_prob(deltas.skip[i].into(), probs.skip[i].into()) as u8;
+    }
+}
+
+fn update_inter_mode_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..probs.inter_mode.len() {
+        let p = &mut probs.inter_mode[i];
+        let d = &deltas.inter_mode[i];
+
+        p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+        p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+        p[2] = update_prob(d[2].into(), p[2].into()) as u8;
+    }
+}
+
+fn update_interp_filter_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..probs.interp_filter.len() {
+        let p = &mut probs.interp_filter[i];
+        let d = &deltas.interp_filter[i];
+
+        p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+        p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+    }
+}
+
+fn update_is_inter_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..probs.is_inter.len() {
+        probs.is_inter[i] = update_prob(deltas.is_inter[i].into(), probs.is_inter[i].into()) as u8;
+    }
+}
+
+fn update_frame_reference_mode_probs(
+    reference_mode: u32,
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    if reference_mode == bindings::V4L2_VP9_REFERENCE_MODE_SELECT {
+        for i in 0..probs.comp_mode.len() {
+            probs.comp_mode[i] =
+                update_prob(deltas.comp_mode[i].into(), probs.comp_mode[i].into()) as u8;
+        }
+    }
+
+    if reference_mode != bindings::V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE {
+        for i in 0..probs.single_ref.len() {
+            let p = &mut probs.single_ref[i];
+            let d = &deltas.single_ref[i];
+
+            p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+            p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+        }
+    }
+
+    if reference_mode != bindings::V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE {
+        for i in 0..probs.comp_ref.len() {
+            probs.comp_ref[i] =
+                update_prob(deltas.comp_ref[i].into(), probs.comp_ref[i].into()) as u8;
+        }
+    }
+}
+
+fn update_y_mode_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) {
+    for i in 0..probs.y_mode.len() {
+        for j in 0..probs.y_mode[0].len() {
+            probs.y_mode[i][j] =
+                update_prob(deltas.y_mode[i][j].into(), probs.y_mode[i][j].into()) as u8;
+        }
+    }
+}
+
+fn update_partition_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..4 {
+        for j in 0..4 {
+            let p = &mut probs.partition[i * 4 + j];
+            let d = deltas.partition[i * 4 + j];
+
+            p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+            p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+            p[2] = update_prob(d[2].into(), p[2].into()) as u8;
+        }
+    }
+}
+
+fn update_mv_prob(delta: i32, prob: i32) -> i32 {
+    if delta == 0 {
+        prob
+    } else {
+        delta
+    }
+}
+
+fn update_mv_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+) {
+    let p = &mut probs.mv.joint;
+    let d = &deltas.mv.joint;
+
+    p[0] = update_mv_prob(d[0].into(), p[0].into()) as u8;
+    p[1] = update_mv_prob(d[1].into(), p[1].into()) as u8;
+    p[2] = update_mv_prob(d[2].into(), p[2].into()) as u8;
+
+    for i in 0..probs.mv.sign.len() {
+        let p = &mut probs.mv.sign;
+        let d = &deltas.mv.sign;
+        p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+
+        let len = probs.mv.classes[0].len();
+        let p = &mut probs.mv.classes[i];
+        let d = &deltas.mv.classes[i];
+        for j in 0..len {
+            p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8;
+        }
+
+        let p = &mut probs.mv.class0_bit;
+        let d = &deltas.mv.class0_bit;
+        p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+
+        let len = probs.mv.bits[0].len();
+        let p = &mut probs.mv.bits[i];
+        let d = &deltas.mv.bits[i];
+        for j in 0..len {
+            p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8;
+        }
+
+        let len = probs.mv.class0_fr[0].len();
+        for j in 0..len {
+            let p = &mut probs.mv.class0_fr[i][j];
+            let d = &deltas.mv.class0_fr[i][j];
+
+            p[0] = update_mv_prob(d[0].into(), p[0].into()) as u8;
+            p[1] = update_mv_prob(d[1].into(), p[1].into()) as u8;
+            p[2] = update_mv_prob(d[2].into(), p[2].into()) as u8;
+        }
+
+        let len = probs.mv.fr[i].len();
+        let p = &mut probs.mv.fr[i];
+        let d = &deltas.mv.fr[i];
+        for j in 0..len {
+            p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8;
+        }
+
+        if (dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV) != 0 {
+            let p = &mut probs.mv.class0_hp;
+            let d = &deltas.mv.class0_hp;
+            p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+
+            let p = &mut probs.mv.hp;
+            let d = &deltas.mv.hp;
+            p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+        }
+    }
+}
+
+macro_rules! clamp {
+    ($val:expr, $min:expr, $max:expr) => {
+        if $val < $min {
+            $min
+        } else if $val > $max {
+            $max
+        } else {
+            $val
+        }
+    };
+}
+
+fn merge_prob(pre_prob: u8, ct0: u32, ct1: u32, count_sat: u32, max_update_factor: u32) -> u8 {
+    let den = ct0 + ct1;
+
+    if den == 0 {
+        /*
+         * prob = 128, count = 0, update_factor = 0
+         * Round2's argument: pre_prob * 256
+         * (pre_prob * 256 + 128) >> 8 == pre_prob
+         */
+        return pre_prob;
+    }
+
+    let prob = clamp!(((ct0 << 8) + (den >> 1)) / den, 1, 255);
+    let count = core::cmp::min(den, count_sat);
+    let factor = fastdiv(max_update_factor * count, count_sat);
+
+    let pre_prob = u32::from(pre_prob);
+
+    /*
+     * Round2(pre_prob * (256 - factor) + prob * factor, 8)
+     * Round2(pre_prob * 256 + (prob - pre_prob) * factor, 8)
+     * (pre_prob * 256 >> 8) + (((prob - pre_prob) * factor + 128) >> 8)
+     */
+    (pre_prob + (((prob - pre_prob) * factor + 128) >> 8)) as u8
+}
+
+fn noncoef_merge_prob(pre_prob: u8, ct0: u32, ct1: u32) -> u8 {
+    merge_prob(pre_prob, ct0, ct1, 20, 128)
+}
+
+/* 8.4.2 Merge probs process */
+/*
+ * merge_probs() is a recursive function in the spec. We avoid recursion in the kernel.
+ * That said, the "tree" parameter of merge_probs() controls how deep the recursion goes.
+ * It turns out that in all cases the recursive calls boil down to a short-ish series
+ * of merge_prob() invocations (note no "s").
+ *
+ * Variant A
+ * ---------
+ * merge_probs(small_token_tree, 2):
+ *	merge_prob(p[1], c[0], c[1] + c[2])
+ *	merge_prob(p[2], c[1], c[2])
+ *
+ * Variant B
+ * ---------
+ * merge_probs(binary_tree, 0) or
+ * merge_probs(tx_size_8_tree, 0):
+ *	merge_prob(p[0], c[0], c[1])
+ *
+ * Variant C
+ * ---------
+ * merge_probs(inter_mode_tree, 0):
+ *	merge_prob(p[0], c[2], c[1] + c[0] + c[3])
+ *	merge_prob(p[1], c[0], c[1] + c[3])
+ *	merge_prob(p[2], c[1], c[3])
+ *
+ * Variant D
+ * ---------
+ * merge_probs(intra_mode_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + ... + c[9])
+ *	merge_prob(p[1], c[9], c[1] + ... + c[8])
+ *	merge_prob(p[2], c[1], c[2] + ... + c[8])
+ *	merge_prob(p[3], c[2] + c[4] + c[5], c[3] + c[8] + c[6] + c[7])
+ *	merge_prob(p[4], c[2], c[4] + c[5])
+ *	merge_prob(p[5], c[4], c[5])
+ *	merge_prob(p[6], c[3], c[8] + c[6] + c[7])
+ *	merge_prob(p[7], c[8], c[6] + c[7])
+ *	merge_prob(p[8], c[6], c[7])
+ *
+ * Variant E
+ * ---------
+ * merge_probs(partition_tree, 0) or
+ * merge_probs(tx_size_32_tree, 0) or
+ * merge_probs(mv_joint_tree, 0) or
+ * merge_probs(mv_fr_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + c[2] + c[3])
+ *	merge_prob(p[1], c[1], c[2] + c[3])
+ *	merge_prob(p[2], c[2], c[3])
+ *
+ * Variant F
+ * ---------
+ * merge_probs(interp_filter_tree, 0) or
+ * merge_probs(tx_size_16_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + c[2])
+ *	merge_prob(p[1], c[1], c[2])
+ *
+ * Variant G
+ * ---------
+ * merge_probs(mv_class_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + ... + c[10])
+ *	merge_prob(p[1], c[1], c[2] + ... + c[10])
+ *	merge_prob(p[2], c[2] + c[3], c[4] + ... + c[10])
+ *	merge_prob(p[3], c[2], c[3])
+ *	merge_prob(p[4], c[4] + c[5], c[6] + ... + c[10])
+ *	merge_prob(p[5], c[4], c[5])
+ *	merge_prob(p[6], c[6], c[7] + ... + c[10])
+ *	merge_prob(p[7], c[7] + c[8], c[9] + c[10])
+ *	merge_prob(p[8], c[7], c[8])
+ *	merge_prob(p[9], c[9], [10])
+ */
+
+fn merge_probs_variant_a(p: &mut [u8], c: &[u32], count_sat: u32, update_factor: u32) {
+    p[1] = merge_prob(p[1], c[0], c[1] + c[2], count_sat, update_factor);
+    p[2] = merge_prob(p[2], c[1], c[2], count_sat, update_factor);
+}
+
+fn merge_probs_variant_b(p: &mut [u8], c: &[u32], count_sat: u32, update_factor: u32) {
+    p[0] = merge_prob(p[0], c[0], c[1], count_sat, update_factor);
+}
+
+fn merge_probs_variant_c(p: &mut [u8], c: &[u32]) {
+    p[0] = noncoef_merge_prob(p[0], c[2], c[1] + c[0] + c[3]);
+    p[1] = noncoef_merge_prob(p[1], c[0], c[1] + c[3]);
+    p[2] = noncoef_merge_prob(p[2], c[1], c[3]);
+}
+
+fn merge_probs_variant_d(p: &mut [u8], c: &[u32]) {
+    let mut sum: u32 = c[1..=9].iter().sum();
+
+    p[0] = noncoef_merge_prob(p[0], c[0], sum);
+    sum -= c[9];
+    p[1] = noncoef_merge_prob(p[1], c[9], sum);
+    sum -= c[1];
+    p[2] = noncoef_merge_prob(p[2], c[1], sum);
+    let mut s2 = c[2] + c[4] + c[5];
+    sum -= s2;
+    p[3] = noncoef_merge_prob(p[3], s2, sum);
+    s2 -= c[2];
+    p[4] = noncoef_merge_prob(p[4], c[2], s2);
+    p[5] = noncoef_merge_prob(p[5], c[4], c[5]);
+    sum -= c[3];
+    p[6] = noncoef_merge_prob(p[6], c[3], sum);
+    sum -= c[8];
+    p[7] = noncoef_merge_prob(p[7], c[8], sum);
+    p[8] = noncoef_merge_prob(p[8], c[6], c[7]);
+}
+
+fn merge_probs_variant_e(p: &mut [u8], c: &[u32]) {
+    p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2] + c[3]);
+    p[1] = noncoef_merge_prob(p[1], c[1], c[2] + c[3]);
+    p[2] = noncoef_merge_prob(p[2], c[2], c[3]);
+}
+
+fn merge_probs_variant_f(p: &mut [u8], c: &[u32]) {
+    p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2]);
+    p[1] = noncoef_merge_prob(p[1], c[1], c[2]);
+}
+
+fn merge_probs_variant_g(p: &mut [u8], c: &[u32]) {
+    let mut sum: u32 = c[1..=10].iter().sum();
+    p[0] = noncoef_merge_prob(p[0], c[0], sum);
+    sum -= c[1];
+    p[1] = noncoef_merge_prob(p[1], c[1], sum);
+    sum -= c[2] + c[3];
+    p[2] = noncoef_merge_prob(p[2], c[2] + c[3], sum);
+    p[3] = noncoef_merge_prob(p[3], c[2], c[3]);
+    sum -= c[4] + c[5];
+    p[4] = noncoef_merge_prob(p[4], c[4] + c[5], sum);
+    p[5] = noncoef_merge_prob(p[5], c[4], c[5]);
+    sum -= c[6];
+    p[6] = noncoef_merge_prob(p[6], c[6], sum);
+    p[7] = noncoef_merge_prob(p[7], c[7] + c[8], c[9] + c[10]);
+    p[8] = noncoef_merge_prob(p[8], c[7], c[8]);
+    p[9] = noncoef_merge_prob(p[9], c[9], c[10]);
+}
+
+fn adapt_probs_variant_a_coef(p: &mut [u8], c: &[u32], update_factor: u32) {
+    merge_probs_variant_a(p, c, 24, update_factor);
+}
+
+fn adapt_probs_variant_b_coef(p: &mut [u8], c: &[u32], update_factor: u32) {
+    merge_probs_variant_b(p, c, 24, update_factor);
+}
+
+fn _adapt_coeff(
+    i: usize,
+    j: usize,
+    k: usize,
+    probs: &mut FrameContext,
+    counts: &FrameSymbolCounts<'_>,
+    uf: u32,
+) {
+    for l in 0..probs.coef[0][0][0].len() {
+        for m in 0..BAND_6!(l) {
+            let p = &mut probs.coef[i][j][k][l][m];
+            let counts_more_coefs = [
+                *counts.eob[i][j][k][l][m][1],
+                *counts.eob[i][j][k][l][m][0] - *counts.eob[i][j][k][l][m][1],
+            ];
+
+            adapt_probs_variant_a_coef(p, counts.coeff[i][j][k][l][m], uf);
+            adapt_probs_variant_b_coef(p, &counts_more_coefs, uf);
+        }
+    }
+}
+
+fn _adapt_coef_probs(probs: &mut FrameContext, counts: &mut FrameSymbolCounts<'_>, uf: u32) {
+    for i in 0..probs.coef.len() {
+        for j in 0..probs.coef[0].len() {
+            for k in 0..probs.coef[0][0].len() {
+                _adapt_coeff(i, j, k, probs, counts, uf);
+            }
+        }
+    }
+}
+
+fn adapt_probs_variant_b(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_b(p, c, 20, 128);
+}
+
+fn adapt_probs_variant_c(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_c(p, c);
+}
+
+fn adapt_probs_variant_d(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_d(p, c);
+}
+
+fn adapt_probs_variant_e(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_e(p, c);
+}
+
+fn adapt_probs_variant_f(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_f(p, c);
+}
+
+fn adapt_probs_variant_g(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_g(p, c);
+}
+
+fn adapt_prob(prob: u8, counts: [u32; 2]) -> u8 {
+    noncoef_merge_prob(prob, counts[0], counts[1])
+}
-- 
2.43.0


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

* Re: [RFC PATCH 1/1] v4l2-core: rewrite the VP9 library in Rust
  2024-02-27 21:51 ` [RFC PATCH 1/1] v4l2-core: rewrite the VP9 " Daniel Almeida
@ 2024-02-28 14:13   ` Alice Ryhl
  2024-02-28 17:59     ` Daniel Almeida
  0 siblings, 1 reply; 10+ messages in thread
From: Alice Ryhl @ 2024-02-28 14:13 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: wedsonaf, ojeda, mchehab, hverkuil, rust-for-linux, linux-kernel,
	linux-media, kernel

On Tue, Feb 27, 2024 at 10:56 PM Daniel Almeida
<daniel.almeida@collabora.com> wrote:
>
> +#[no_mangle]
> +pub extern "C" fn v4l2_vp9_seg_feat_enabled_rs(
> +    feature_enabled: &mut u8,
> +    feature: u32,
> +    segid: u32,
> +) -> bool {
> +    let feature_enabled = unsafe { core::slice::from_raw_parts_mut(feature_enabled, 8) };
> +    let mask = 1 << feature;
> +    feature_enabled[segid as usize] & mask != 0
> +}

This seems to be the only unsafe block. Impressive!

I recommend taking an `*mut u8` here instead of `&mut u8` if you're
going to use `slice::from_raw_parts_mut`. Or, if cbindgen allows it,
take an `&mut [u8; 8]` instead and eliminate the unsafe block.

Alice

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

* Re: [RFC PATCH 1/1] v4l2-core: rewrite the VP9  library in Rust
  2024-02-28 14:13   ` Alice Ryhl
@ 2024-02-28 17:59     ` Daniel Almeida
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2024-02-28 17:59 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: wedsonaf, ojeda, mchehab, hverkuil, rust-for-linux, linux-kernel,
	linux-media, kernel

Hi Alice!

On Wednesday, February 28, 2024 11:13 -03, Alice Ryhl <aliceryhl@google.com> wrote:

> I recommend taking an `*mut u8` here instead of `&mut u8` if you're
> going to use `slice::from_raw_parts_mut`. Or, if cbindgen allows it,
> take an `&mut [u8; 8]` instead and eliminate the unsafe block.

You're right, the signature here can change to `&mut [u8; 8]` instead. This means no unsafe blocks at all.

Thanks for the tip,

-- Daniel


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

* [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec library in Rust
  2024-02-27 21:51 [RFC PATCH 0/1] Rewrite the VP9 codec library in Rust Daniel Almeida
  2024-02-27 21:51 ` [RFC PATCH 1/1] v4l2-core: rewrite the VP9 " Daniel Almeida
@ 2024-03-07 19:08 ` Daniel Almeida
  2024-03-07 19:08   ` [RFC PATCH v2 1/2] v4l2-core: rewrite the VP9 " Daniel Almeida
                     ` (2 more replies)
  1 sibling, 3 replies; 10+ messages in thread
From: Daniel Almeida @ 2024-03-07 19:08 UTC (permalink / raw)
  To: wedsonaf, ojeda, mchehab, hverkuil
  Cc: Daniel Almeida, rust-for-linux, linux-kernel, linux-media, kernel

Hi Mauro, Hans,

While working on v1 for this patchset, I realized that we can go further by
converting the error-prone sections of our codec drivers to Rust. This also
does not need any bindings in order to work.

As yet another proof-of-concept, I have converted parts of the rkvdec driver.
Refer to instructions in v1 to test this.

Notice how:

1) many problematic memcpy's go away, these become a simple assignment in Rust.

2) it can interop seamlessly with the code in rkvdec-vp9.c that was already
converted in v1 of this series.

3) it can use the Rust version of `seg_feat_enabled` directly in vp9.rs, while
also using the C APIs from the v4l2-vp9-rs library in rkvdec-vp9.c

4) more modern things become available for the programmer, like iterators and
their methods without a performance penalty.

I want to propose the following:

Let's merge a non-RFC version of this series and gate it behind some kconfigs
so that we can switch between the C and Rust implementations. Users get the C
version by default, while we continuously test the Rust components on a CI for
a few months. This will hopefully be enough time until the next Media Summit.

My aim is to eventually deprecate the C parts once we're confident that the
Rust code is stable enough. I will keep my own tree, and send PRs to the media
tree if a rebase or fix is needed.

I believe this will not be disruptive nor require any extra work from anyone
but me.

-- Daniel


Again, applies on top of:

commit d9c1fae3e5b225f2e45e0bca519f9a2967cd1062
Author: Alice Ryhl <aliceryhl@google.com>
Date:   Fri Feb 9 11:18:22 2024 +0000

    rust: file: add abstraction for `poll_table`

For those looking for a branch instead: https://gitlab.collabora.com/dwlsalmeida/for-upstream/-/tree/vp9-rs-rkvdec?ref_type=heads

Daniel Almeida (2):
  v4l2-core: rewrite the VP9 library in Rust
  media: rkvdec: rewrite parts of the driver in Rust

 drivers/media/platform/verisilicon/Kconfig    |    2 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |   38 +-
 .../media/platform/verisilicon/hantro_hw.h    |    8 +-
 drivers/media/v4l2-core/Kconfig               |    5 +
 drivers/staging/media/rkvdec/Kconfig          |    3 +-
 drivers/staging/media/rkvdec/Makefile         |    2 +-
 drivers/staging/media/rkvdec/cbindgen.toml    |   36 +
 drivers/staging/media/rkvdec/common.rs        |   19 +
 drivers/staging/media/rkvdec/regs.rs          |  237 ++
 drivers/staging/media/rkvdec/rkvdec-vp9.c     |  607 +----
 drivers/staging/media/rkvdec/rkvdec_rs.h      |  125 +
 drivers/staging/media/rkvdec/rkvdec_rs.rs     |   14 +
 drivers/staging/media/rkvdec/vp9.rs           |  636 +++++
 include/media/v4l2-vp9-rs.h                   |   99 +
 rust/bindings/bindings_helper.h               |    1 +
 rust/helpers.c                                |    7 +
 rust/kernel/lib.rs                            |    2 +
 rust/kernel/media.rs                          |    5 +
 rust/kernel/media/v4l2_core.rs                |    6 +
 rust/kernel/media/v4l2_core/cbindgen.toml     |   26 +
 rust/kernel/media/v4l2_core/vp9.rs            | 2053 +++++++++++++++++
 21 files changed, 3415 insertions(+), 516 deletions(-)
 create mode 100644 drivers/staging/media/rkvdec/cbindgen.toml
 create mode 100644 drivers/staging/media/rkvdec/common.rs
 create mode 100644 drivers/staging/media/rkvdec/regs.rs
 create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.h
 create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.rs
 create mode 100644 drivers/staging/media/rkvdec/vp9.rs
 create mode 100644 include/media/v4l2-vp9-rs.h
 create mode 100644 rust/kernel/media.rs
 create mode 100644 rust/kernel/media/v4l2_core.rs
 create mode 100644 rust/kernel/media/v4l2_core/cbindgen.toml
 create mode 100644 rust/kernel/media/v4l2_core/vp9.rs

-- 
2.43.0


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

* [RFC PATCH v2 1/2] v4l2-core: rewrite the VP9 library in Rust
  2024-03-07 19:08 ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec " Daniel Almeida
@ 2024-03-07 19:08   ` Daniel Almeida
  2024-03-07 19:08   ` [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver " Daniel Almeida
  2024-03-07 20:04   ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec library " Deborah Brouwer
  2 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2024-03-07 19:08 UTC (permalink / raw)
  To: wedsonaf, ojeda, mchehab, hverkuil
  Cc: Daniel Almeida, rust-for-linux, linux-kernel, linux-media, kernel

---
 drivers/media/platform/verisilicon/Kconfig    |    2 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |   38 +-
 .../media/platform/verisilicon/hantro_hw.h    |    8 +-
 drivers/media/v4l2-core/Kconfig               |    5 +
 drivers/staging/media/rkvdec/Kconfig          |    2 +-
 drivers/staging/media/rkvdec/rkvdec-vp9.c     |   52 +-
 include/media/v4l2-vp9-rs.h                   |   99 +
 rust/bindings/bindings_helper.h               |    1 +
 rust/kernel/lib.rs                            |    2 +
 rust/kernel/media.rs                          |    5 +
 rust/kernel/media/v4l2_core.rs                |    6 +
 rust/kernel/media/v4l2_core/cbindgen.toml     |   26 +
 rust/kernel/media/v4l2_core/vp9.rs            | 2053 +++++++++++++++++
 13 files changed, 2249 insertions(+), 50 deletions(-)
 create mode 100644 include/media/v4l2-vp9-rs.h
 create mode 100644 rust/kernel/media.rs
 create mode 100644 rust/kernel/media/v4l2_core.rs
 create mode 100644 rust/kernel/media/v4l2_core/cbindgen.toml
 create mode 100644 rust/kernel/media/v4l2_core/vp9.rs

diff --git a/drivers/media/platform/verisilicon/Kconfig b/drivers/media/platform/verisilicon/Kconfig
index 24b927d8f182..d8e4e9b5de2f 100644
--- a/drivers/media/platform/verisilicon/Kconfig
+++ b/drivers/media/platform/verisilicon/Kconfig
@@ -12,7 +12,7 @@ config VIDEO_HANTRO
 	select VIDEOBUF2_VMALLOC
 	select V4L2_MEM2MEM_DEV
 	select V4L2_H264
-	select V4L2_VP9
+	select V4L2_VP9_RS
 	help
 	  Support for the Hantro IP based Video Processing Units present on
 	  Rockchip and NXP i.MX8M SoCs, which accelerate video and image
diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 342e543dee4c..43990b550919 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -10,7 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/v4l2-vp9.h>
+#include <media/v4l2-vp9-rs.h>
 
 #include "hantro.h"
 #include "hantro_vp9.h"
@@ -63,7 +63,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 	 *	frame_context_idx = 0
 	 * }
 	 */
-	fctx_idx = v4l2_vp9_reset_frame_ctx(*dec_params, vp9_ctx->frame_context);
+	fctx_idx = v4l2_vp9_reset_frame_ctx_rs(*dec_params, &vp9_ctx->frame_context);
 	vp9_ctx->cur.frame_context_idx = fctx_idx;
 
 	/* 6.1 frame(sz): load_probs() and load_probs2() */
@@ -83,7 +83,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 	 * 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);
+	v4l2_vp9_fw_update_probs_rs(&vp9_ctx->probability_tables, prob_updates, *dec_params);
 
 	return 0;
 }
@@ -422,7 +422,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 		if (segment_enabled) {
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
-			if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
+			if (v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid))
 				feat_val = feat_val_clip3(feat_val,
 							  vp9_ctx->feature_data[segid][feat_id],
 							  absolute, 255);
@@ -435,7 +435,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 		if (segment_enabled) {
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
-			if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
+			if (v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid))
 				feat_val = feat_val_clip3(feat_val,
 							  vp9_ctx->feature_data[segid][feat_id],
 							  absolute, 63);
@@ -449,7 +449,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
 			if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) &&
-			    v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid))
+			    v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid))
 				feat_val = vp9_ctx->feature_data[segid][feat_id] + 1;
 		}
 		hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
@@ -460,7 +460,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr
 		if (segment_enabled) {
 			if (update_data)
 				update_feat_and_flag(vp9_ctx, seg, feat_id, segid);
-			feat_val = v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled,
+			feat_val = v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled,
 							     feat_id, segid) ? 1 : 0;
 		}
 		hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val);
@@ -637,17 +637,17 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram
 	struct hantro_g2_probs *adaptive;
 	struct hantro_g2_mv_probs *mv;
 	const struct v4l2_vp9_segmentation *seg = &dec_params->seg;
-	const struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables;
+	const struct v4l2_vp9_frame_context_rs *probs = &vp9_ctx->probability_tables;
 	int i, j, k, l, m;
 
 	for (i = 0; i < ARRAY_SIZE(all_probs->kf_y_mode_prob); ++i)
 		for (j = 0; j < ARRAY_SIZE(all_probs->kf_y_mode_prob[0]); ++j) {
 			memcpy(all_probs->kf_y_mode_prob[i][j],
-			       v4l2_vp9_kf_y_mode_prob[i][j],
+			       v4l2_vp9_kf_y_mode_prob_rs[i][j],
 			       ARRAY_SIZE(all_probs->kf_y_mode_prob[i][j]));
 
 			all_probs->kf_y_mode_prob_tail[i][j][0] =
-				v4l2_vp9_kf_y_mode_prob[i][j][8];
+				v4l2_vp9_kf_y_mode_prob_rs[i][j][8];
 		}
 
 	memcpy(all_probs->mb_segment_tree_probs, seg->tree_probs,
@@ -657,10 +657,10 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram
 	       sizeof(all_probs->segment_pred_probs));
 
 	for (i = 0; i < ARRAY_SIZE(all_probs->kf_uv_mode_prob); ++i) {
-		memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob[i],
+		memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob_rs[i],
 		       ARRAY_SIZE(all_probs->kf_uv_mode_prob[i]));
 
-		all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob[i][8];
+		all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob_rs[i][8];
 	}
 
 	adaptive = &all_probs->probs;
@@ -692,8 +692,8 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram
 	}
 
 	for (i = 0; i < ARRAY_SIZE(adaptive->partition[0]); ++i) {
-		memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs[i],
-		       sizeof(v4l2_vp9_kf_partition_probs[i]));
+		memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs_rs[i],
+		       sizeof(v4l2_vp9_kf_partition_probs_rs[i]));
 
 		adaptive->partition[0][i][3] = 0;
 	}
@@ -933,7 +933,7 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 
 	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;
+		struct v4l2_vp9_frame_context_rs *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 {
@@ -942,7 +942,7 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 			u8 tx32[2][3];
 			u8 skip[3];
 		} _tx_skip, *tx_skip = &_tx_skip;
-		struct v4l2_vp9_frame_symbol_counts *counts;
+		struct v4l2_vp9_frame_symbol_counts_rs *counts;
 		struct symbol_counts *hantro_cnts;
 		u32 tx16p[2][4];
 		int i;
@@ -968,7 +968,8 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 		}
 		counts->tx16p = &tx16p;
 
-		v4l2_vp9_adapt_coef_probs(probs, counts,
+		v4l2_vp9_adapt_coef_probs_rs(probs,
+								     counts,
 					  !vp9_ctx->last.valid ||
 					  vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME,
 					  frame_is_intra);
@@ -984,7 +985,8 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx)
 				mv_mode[i][3] = hantro_cnts->inter_mode_counts[i][2][1];
 			}
 			counts->mv_mode = &mv_mode;
-			v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts,
+			v4l2_vp9_adapt_noncoef_probs_rs(&vp9_ctx->probability_tables,
+										   counts,
 						     vp9_ctx->cur.reference_mode,
 						     vp9_ctx->cur.interpolation_filter,
 						     vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags);
diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
index 9aec8a79acdc..f8baa898ef53 100644
--- a/drivers/media/platform/verisilicon/hantro_hw.h
+++ b/drivers/media/platform/verisilicon/hantro_hw.h
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/v4l2-controls.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-vp9.h>
+#include <media/v4l2-vp9-rs.h>
 #include <media/videobuf2-core.h>
 
 #include "rockchip_av1_entropymode.h"
@@ -231,9 +231,9 @@ struct hantro_vp9_dec_hw_ctx {
 	struct hantro_aux_buf tile_edge;
 	struct hantro_aux_buf segment_map;
 	struct hantro_aux_buf misc;
-	struct v4l2_vp9_frame_symbol_counts cnts;
-	struct v4l2_vp9_frame_context probability_tables;
-	struct v4l2_vp9_frame_context frame_context[4];
+	struct v4l2_vp9_frame_symbol_counts_rs cnts;
+	struct v4l2_vp9_frame_context_rs probability_tables;
+	struct v4l2_vp9_frame_context_rs frame_context[4];
 	struct hantro_vp9_frame_info cur;
 	struct hantro_vp9_frame_info last;
 
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 331b8e535e5b..878229c2490b 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -48,6 +48,11 @@ config V4L2_H264
 config V4L2_VP9
 	tristate
 
+# Used by drivers that need the Rust equivalent to v4l2-vp9.ko
+config V4L2_VP9_RS
+	tristate
+	depends on RUST
+
 # Used by drivers that need v4l2-mem2mem.ko
 config V4L2_MEM2MEM_DEV
 	tristate
diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig
index 5f3bdd848a2c..245dc47082d4 100644
--- a/drivers/staging/media/rkvdec/Kconfig
+++ b/drivers/staging/media/rkvdec/Kconfig
@@ -8,7 +8,7 @@ config VIDEO_ROCKCHIP_VDEC
 	select VIDEOBUF2_VMALLOC
 	select V4L2_MEM2MEM_DEV
 	select V4L2_H264
-	select V4L2_VP9
+	select V4L2_VP9_RS
 	help
 	  Support for the Rockchip Video Decoder IP present on Rockchip SoCs,
 	  which accelerates video decoding.
diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c
index 0e7e16f20eeb..86c6903d11ab 100644
--- a/drivers/staging/media/rkvdec/rkvdec-vp9.c
+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c
@@ -19,7 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/v4l2-vp9.h>
+#include <media/v4l2-vp9-rs.h>
 
 #include "rkvdec.h"
 #include "rkvdec-regs.h"
@@ -157,10 +157,10 @@ struct rkvdec_vp9_frame_info {
 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 v4l2_vp9_frame_symbol_counts_rs inter_cnts;
+	struct v4l2_vp9_frame_symbol_counts_rs intra_cnts;
+	struct v4l2_vp9_frame_context_rs probability_tables;
+	struct v4l2_vp9_frame_context_rs frame_context[4];
 	struct rkvdec_vp9_frame_info cur;
 	struct rkvdec_vp9_frame_info last;
 };
@@ -192,7 +192,7 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 	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;
+	const struct v4l2_vp9_frame_context_rs *probs;
 	unsigned int i, j, k;
 
 	rkprobs = &tbl->probs.intra_only;
@@ -209,15 +209,15 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 	}
 
 	/* intra mode prob  80 x 128 bits */
-	for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob); i++) {
+	for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs); 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]);
+		for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0]); j++) {
+			for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0][0]);
 			     k++) {
-				u8 val = v4l2_vp9_kf_y_mode_prob[i][j][k];
+				u8 val = v4l2_vp9_kf_y_mode_prob_rs[i][j][k];
 
 				rkprobs->intra_mode[i].y_mode[idx++] = val;
 				byte_count++;
@@ -229,8 +229,8 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx,
 		}
 	}
 
-	for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob); ++i) {
-		const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob;
+	for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob_rs); ++i) {
+		const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob_rs;
 
 		rkprobs->intra_mode[i / 23].uv_mode[i % 23] = ptr[i];
 	}
@@ -242,7 +242,7 @@ static void init_inter_probs(struct rkvdec_ctx *ctx,
 	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;
+	const struct v4l2_vp9_frame_context_rs *probs;
 	unsigned int i, j, k;
 
 	rkprobs = &tbl->probs.inter;
@@ -315,7 +315,7 @@ static void init_probs(struct rkvdec_ctx *ctx,
 	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;
+	const struct v4l2_vp9_frame_context_rs *probs;
 	bool intra_only;
 
 	dec_params = run->decode_params;
@@ -330,7 +330,7 @@ static void init_probs(struct rkvdec_ctx *ctx,
 
 	/* sb info  5 x 128 bit */
 	memcpy(rkprobs->partition,
-	       intra_only ? v4l2_vp9_kf_partition_probs : probs->partition,
+	       intra_only ? v4l2_vp9_kf_partition_probs_rs : probs->partition,
 	       sizeof(rkprobs->partition));
 
 	memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred));
@@ -448,7 +448,7 @@ static void config_ref_registers(struct rkvdec_ctx *ctx,
 static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
 {
 	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
-	const struct v4l2_vp9_segmentation *seg;
+	struct v4l2_vp9_segmentation *seg;
 	struct rkvdec_dev *rkvdec = ctx->dev;
 	s16 feature_val;
 	int feature_id;
@@ -456,28 +456,28 @@ static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
 
 	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)) {
+	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
 		val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) |
 		       RKVDEC_SEGID_FRAME_QP_DELTA(feature_val);
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_ALT_L;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
+	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
 		val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) |
 		       RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val);
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_REF_FRAME;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) {
+	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) {
 		feature_val = seg->feature_data[segid][feature_id];
 		val |= RKVDEC_SEGID_REFERINFO_EN(1) |
 		       RKVDEC_SEGID_REFERINFO(feature_val);
 	}
 
 	feature_id = V4L2_VP9_SEG_LVL_SKIP;
-	if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
+	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid))
 		val |= RKVDEC_SEGID_FRAME_SKIP_EN(1);
 
 	if (!segid &&
@@ -773,7 +773,7 @@ static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx,
 	 *	frame_context_idx = 0
 	 * }
 	 */
-	fctx_idx = v4l2_vp9_reset_frame_ctx(dec_params, vp9_ctx->frame_context);
+	fctx_idx = v4l2_vp9_reset_frame_ctx_rs(dec_params, &vp9_ctx->frame_context);
 	vp9_ctx->cur.frame_context_idx = fctx_idx;
 
 	/* 6.1 frame(sz): load_probs() and load_probs2() */
@@ -793,7 +793,7 @@ static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx,
 	 * 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);
+	v4l2_vp9_fw_update_probs_rs(&vp9_ctx->probability_tables, prob_updates, dec_params);
 
 	return 0;
 }
@@ -871,7 +871,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 
 	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;
+		struct v4l2_vp9_frame_context_rs *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 {
@@ -880,7 +880,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 			u8 tx32[2][3];
 			u8 skip[3];
 		} _tx_skip, *tx_skip = &_tx_skip;
-		struct v4l2_vp9_frame_symbol_counts *counts;
+		struct v4l2_vp9_frame_symbol_counts_rs *counts;
 
 		/* buffer the forward-updated TX and skip probs */
 		if (frame_is_intra)
@@ -894,7 +894,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 			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,
+		v4l2_vp9_adapt_coef_probs_rs(probs, counts,
 					  !vp9_ctx->last.valid ||
 					  vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME,
 					  frame_is_intra);
@@ -909,7 +909,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 			counts->classes = &classes;
 
 			/* load_probs2() already done */
-			v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts,
+			v4l2_vp9_adapt_noncoef_probs_rs(&vp9_ctx->probability_tables, counts,
 						     vp9_ctx->cur.reference_mode,
 						     vp9_ctx->cur.interpolation_filter,
 						     vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags);
diff --git a/include/media/v4l2-vp9-rs.h b/include/media/v4l2-vp9-rs.h
new file mode 100644
index 000000000000..3e93f67b0002
--- /dev/null
+++ b/include/media/v4l2-vp9-rs.h
@@ -0,0 +1,99 @@
+#ifndef V4L2_VP9_RS_H
+#define V4L2_VP9_RS_H
+
+/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
+
+#include <media/v4l2-ctrls.h>
+
+struct v4l2_vp9_frame_mv_context_rs {
+  uint8_t joint[3];
+  uint8_t sign[2];
+  uint8_t classes[2][10];
+  uint8_t class0_bit[2];
+  uint8_t bits[2][10];
+  uint8_t class0_fr[2][2][3];
+  uint8_t fr[2][3];
+  uint8_t class0_hp[2];
+  uint8_t hp[2];
+};
+
+struct v4l2_vp9_frame_context_rs {
+  uint8_t tx8[2][1];
+  uint8_t tx16[2][2];
+  uint8_t tx32[2][3];
+  uint8_t coef[4][2][2][6][6][3];
+  uint8_t skip[3];
+  uint8_t inter_mode[7][3];
+  uint8_t interp_filter[4][2];
+  uint8_t is_inter[4];
+  uint8_t comp_mode[5];
+  uint8_t single_ref[5][2];
+  uint8_t comp_ref[5];
+  uint8_t y_mode[4][9];
+  uint8_t uv_mode[10][9];
+  uint8_t partition[16][3];
+  struct v4l2_vp9_frame_mv_context_rs mv;
+};
+
+struct v4l2_vp9_frame_symbol_counts_rs {
+  uint32_t (*partition)[16][4];
+  uint32_t (*skip)[3][2];
+  uint32_t (*intra_inter)[4][2];
+  uint32_t (*tx32p)[2][4];
+  uint32_t (*tx16p)[2][4];
+  uint32_t (*tx8p)[2][2];
+  uint32_t (*y_mode)[4][10];
+  uint32_t (*uv_mode)[10][10];
+  uint32_t (*comp)[5][2];
+  uint32_t (*comp_ref)[5][2];
+  uint32_t (*single_ref)[5][2][2];
+  uint32_t (*mv_mode)[7][4];
+  uint32_t (*filter)[4][3];
+  uint32_t (*mv_joint)[4];
+  uint32_t (*sign)[2][2];
+  uint32_t (*classes)[2][11];
+  uint32_t (*class0)[2][2];
+  uint32_t (*bits)[2][10][2];
+  uint32_t (*class0_fp)[2][2][4];
+  uint32_t (*fp)[2][4];
+  uint32_t (*class0_hp)[2][2];
+  uint32_t (*hp)[2][2];
+  uint32_t (*coeff[4][2][2][6][6])[3];
+  uint32_t *eob[4][2][2][6][6][2];
+};
+
+extern const uint8_t v4l2_vp9_kf_y_mode_prob_rs[10][10][9];
+
+extern const uint8_t v4l2_vp9_kf_partition_probs_rs[16][3];
+
+extern const uint8_t v4l2_vp9_kf_uv_mode_prob_rs[10][9];
+
+extern const struct v4l2_vp9_frame_context_rs v4l2_vp9_default_probs_rs;
+
+/**
+ * Counterpart to 6.3 compressed_header(), but parsing has been done in userspace.
+ */
+void v4l2_vp9_fw_update_probs_rs(struct v4l2_vp9_frame_context_rs *probs,
+                                 const struct v4l2_ctrl_vp9_compressed_hdr *deltas,
+                                 const struct v4l2_ctrl_vp9_frame *dec_params);
+
+uint8_t v4l2_vp9_reset_frame_ctx_rs(const struct v4l2_ctrl_vp9_frame *dec_params,
+                                    struct v4l2_vp9_frame_context_rs (*frame_context)[4]);
+
+void v4l2_vp9_adapt_coef_probs_rs(struct v4l2_vp9_frame_context_rs *probs,
+                                  struct v4l2_vp9_frame_symbol_counts_rs *counts,
+                                  bool use_128,
+                                  bool frame_is_intra);
+
+void v4l2_vp9_adapt_noncoef_probs_rs(struct v4l2_vp9_frame_context_rs *probs,
+                                     struct v4l2_vp9_frame_symbol_counts_rs *counts,
+                                     uint8_t reference_mode,
+                                     uint8_t interpolation_filter,
+                                     uint8_t tx_mode,
+                                     uint32_t flags);
+
+bool v4l2_vp9_seg_feat_enabled_rs(const uint8_t (*feature_enabled)[8],
+                                  uint32_t feature,
+                                  uint32_t segid);
+
+#endif /* V4L2_VP9_RS_H */
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index c651d38e5dd6..25e2c06bb967 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/task_work.h>
 #include <linux/workqueue.h>
+#include <linux/v4l2-controls.h>
 
 /* `bindgen` gets confused at certain things. */
 const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index cc39195b0157..724e1d3bf2af 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -39,6 +39,8 @@
 pub mod ioctl;
 #[cfg(CONFIG_KUNIT)]
 pub mod kunit;
+#[cfg(CONFIG_MEDIA_SUPPORT)]
+pub mod media;
 #[cfg(CONFIG_NET)]
 pub mod net;
 pub mod prelude;
diff --git a/rust/kernel/media.rs b/rust/kernel/media.rs
new file mode 100644
index 000000000000..72f5cd716874
--- /dev/null
+++ b/rust/kernel/media.rs
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Media support
+
+pub mod v4l2_core;
\ No newline at end of file
diff --git a/rust/kernel/media/v4l2_core.rs b/rust/kernel/media/v4l2_core.rs
new file mode 100644
index 000000000000..7515fe748a65
--- /dev/null
+++ b/rust/kernel/media/v4l2_core.rs
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! V4L2 Core
+
+#[cfg(CONFIG_V4L2_VP9_RS)]
+pub mod vp9;
\ No newline at end of file
diff --git a/rust/kernel/media/v4l2_core/cbindgen.toml b/rust/kernel/media/v4l2_core/cbindgen.toml
new file mode 100644
index 000000000000..ebbc8a5e2fff
--- /dev/null
+++ b/rust/kernel/media/v4l2_core/cbindgen.toml
@@ -0,0 +1,26 @@
+# Generate the C API with:
+# cbindgen  --lang c  -v --config rust/kernel/media/v4l2_core/cbindgen.toml --output include/media/v4l2-vp9-rs.h -- rust/kernel/media/v4l2_core/vp9.rs
+
+language = "C"
+
+# No <stdarg.h>, <stdbool.h>, <stdint.h>, <stdlib.h>, <uchar.h>
+no_includes = true
+style = "tag"
+
+sys_includes = ["media/v4l2-ctrls.h"]
+autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
+usize_is_size_t = true
+include_guard = "V4L2_VP9_RS_H"
+
+# Rename everything from bindgen
+# See https://github.com/mozilla/cbindgen/issues/621
+# Also rename our mangled structs into snake_case for the C API
+[export.rename]
+"v4l2_ctrl_vp9_compressed_hdr" = "struct v4l2_ctrl_vp9_compressed_hdr"
+"v4l2_ctrl_vp9_frame" = "struct v4l2_ctrl_vp9_frame"
+"FrameContext" = "v4l2_vp9_frame_context_rs"
+"FrameSymbolCounts" = "v4l2_vp9_frame_symbol_counts_rs"
+"FrameMvContext" = "v4l2_vp9_frame_mv_context_rs"
+
+[enum]
+prefix_with_name = true
diff --git a/rust/kernel/media/v4l2_core/vp9.rs b/rust/kernel/media/v4l2_core/vp9.rs
new file mode 100644
index 000000000000..62e3c1d7c625
--- /dev/null
+++ b/rust/kernel/media/v4l2_core/vp9.rs
@@ -0,0 +1,2053 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! VP9 helpers
+//! This library was initially written by Andrzej Pietrasiewicz and ported into
+//! Rust by Daniel Almeida.
+
+#![allow(missing_docs)]
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct FrameMvContext {
+    pub joint: [u8; 3],
+    pub sign: [u8; 2],
+    pub classes: [[u8; 10]; 2],
+    pub class0_bit: [u8; 2],
+    pub bits: [[u8; 10]; 2],
+    pub class0_fr: [[[u8; 3]; 2]; 2],
+    pub fr: [[u8; 3]; 2],
+    pub class0_hp: [u8; 2],
+    pub hp: [u8; 2],
+}
+
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct FrameContext {
+    pub tx8: [[u8; 1]; 2],
+    pub tx16: [[u8; 2]; 2],
+    pub tx32: [[u8; 3]; 2],
+    pub coef: [[[[[[u8; 3]; 6]; 6]; 2]; 2]; 4],
+    pub skip: [u8; 3],
+    pub inter_mode: [[u8; 3]; 7],
+    pub interp_filter: [[u8; 2]; 4],
+    pub is_inter: [u8; 4],
+    pub comp_mode: [u8; 5],
+    pub single_ref: [[u8; 2]; 5],
+    pub comp_ref: [u8; 5],
+    pub y_mode: [[u8; 9]; 4],
+    pub uv_mode: [[u8; 9]; 10],
+    pub partition: [[u8; 3]; 16],
+    pub mv: FrameMvContext,
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct FrameSymbolCounts<'a> {
+    pub partition: &'a mut [[u32; 4]; 16],
+    pub skip: &'a mut [[u32; 2]; 3],
+    pub intra_inter: &'a mut [[u32; 2]; 4],
+    pub tx32p: &'a mut [[u32; 4]; 2],
+    pub tx16p: &'a mut [[u32; 4]; 2],
+    pub tx8p: &'a mut [[u32; 2]; 2],
+    pub y_mode: &'a mut [[u32; 10]; 4],
+    pub uv_mode: &'a mut [[u32; 10]; 10],
+    pub comp: &'a mut [[u32; 2]; 5],
+    pub comp_ref: &'a mut [[u32; 2]; 5],
+    pub single_ref: &'a mut [[[u32; 2]; 2]; 5],
+    pub mv_mode: &'a mut [[u32; 4]; 7],
+    pub filter: &'a mut [[u32; 3]; 4],
+    pub mv_joint: &'a mut [u32; 4],
+    pub sign: &'a mut [[u32; 2]; 2],
+    pub classes: &'a mut [[u32; 11]; 2],
+    pub class0: &'a mut [[u32; 2]; 2],
+    pub bits: &'a mut [[[u32; 2]; 10]; 2],
+    pub class0_fp: &'a mut [[[u32; 4]; 2]; 2],
+    pub fp: &'a mut [[u32; 4]; 2],
+    pub class0_hp: &'a mut [[u32; 2]; 2],
+    pub hp: &'a mut [[u32; 2]; 2],
+    pub coeff: [[[[[&'a mut [u32; 3]; 6]; 6]; 2]; 2]; 4],
+    pub eob: [[[[[[&'a mut u32; 2]; 6]; 6]; 2]; 2]; 4],
+}
+
+#[no_mangle]
+pub static v4l2_vp9_kf_y_mode_prob_rs: [[[u8; 9]; 10]; 10] = [
+    [
+        /* above = dc */
+        [137, 30, 42, 148, 151, 207, 70, 52, 91], /*left = dc  */
+        [92, 45, 102, 136, 116, 180, 74, 90, 100], /*left = v   */
+        [73, 32, 19, 187, 222, 215, 46, 34, 100], /*left = h   */
+        [91, 30, 32, 116, 121, 186, 93, 86, 94],  /*left = d45 */
+        [72, 35, 36, 149, 68, 206, 68, 63, 105],  /*left = d135*/
+        [73, 31, 28, 138, 57, 124, 55, 122, 151], /*left = d117*/
+        [67, 23, 21, 140, 126, 197, 40, 37, 171], /*left = d153*/
+        [86, 27, 28, 128, 154, 212, 45, 43, 53],  /*left = d207*/
+        [74, 32, 27, 107, 86, 160, 63, 134, 102], /*left = d63 */
+        [59, 67, 44, 140, 161, 202, 78, 67, 119], /*left = tm  */
+    ],
+    [
+        /* above = v */
+        [63, 36, 126, 146, 123, 158, 60, 90, 96], /*left = dc  */
+        [43, 46, 168, 134, 107, 128, 69, 142, 92], /*left = v   */
+        [44, 29, 68, 159, 201, 177, 50, 57, 77],  /*left = h   */
+        [58, 38, 76, 114, 97, 172, 78, 133, 92],  /*left = d45 */
+        [46, 41, 76, 140, 63, 184, 69, 112, 57],  /*left = d135*/
+        [38, 32, 85, 140, 46, 112, 54, 151, 133], /*left = d117*/
+        [39, 27, 61, 131, 110, 175, 44, 75, 136], /*left = d153*/
+        [52, 30, 74, 113, 130, 175, 51, 64, 58],  /*left = d207*/
+        [47, 35, 80, 100, 74, 143, 64, 163, 74],  /*left = d63 */
+        [36, 61, 116, 114, 128, 162, 80, 125, 82], /*left = tm  */
+    ],
+    [
+        /* above = h */
+        [82, 26, 26, 171, 208, 204, 44, 32, 105], /*left = dc  */
+        [55, 44, 68, 166, 179, 192, 57, 57, 108], /*left = v   */
+        [42, 26, 11, 199, 241, 228, 23, 15, 85],  /*left = h   */
+        [68, 42, 19, 131, 160, 199, 55, 52, 83],  /*left = d45 */
+        [58, 50, 25, 139, 115, 232, 39, 52, 118], /*left = d135*/
+        [50, 35, 33, 153, 104, 162, 64, 59, 131], /*left = d117*/
+        [44, 24, 16, 150, 177, 202, 33, 19, 156], /*left = d153*/
+        [55, 27, 12, 153, 203, 218, 26, 27, 49],  /*left = d207*/
+        [53, 49, 21, 110, 116, 168, 59, 80, 76],  /*left = d63 */
+        [38, 72, 19, 168, 203, 212, 50, 50, 107], /*left = tm  */
+    ],
+    [
+        /* above = d45 */
+        [103, 26, 36, 129, 132, 201, 83, 80, 93], /*left = dc  */
+        [59, 38, 83, 112, 103, 162, 98, 136, 90], /*left = v   */
+        [62, 30, 23, 158, 200, 207, 59, 57, 50],  /*left = h   */
+        [67, 30, 29, 84, 86, 191, 102, 91, 59],   /*left = d45 */
+        [60, 32, 33, 112, 71, 220, 64, 89, 104],  /*left = d135*/
+        [53, 26, 34, 130, 56, 149, 84, 120, 103], /*left = d117*/
+        [53, 21, 23, 133, 109, 210, 56, 77, 172], /*left = d153*/
+        [77, 19, 29, 112, 142, 228, 55, 66, 36],  /*left = d207*/
+        [61, 29, 29, 93, 97, 165, 83, 175, 162],  /*left = d63 */
+        [47, 47, 43, 114, 137, 181, 100, 99, 95], /*left = tm  */
+    ],
+    [
+        /* above = d135 */
+        [69, 23, 29, 128, 83, 199, 46, 44, 101], /*left = dc  */
+        [53, 40, 55, 139, 69, 183, 61, 80, 110], /*left = v   */
+        [40, 29, 19, 161, 180, 207, 43, 24, 91], /*left = h   */
+        [60, 34, 19, 105, 61, 198, 53, 64, 89],  /*left = d45 */
+        [52, 31, 22, 158, 40, 209, 58, 62, 89],  /*left = d135*/
+        [44, 31, 29, 147, 46, 158, 56, 102, 198], /*left = d117*/
+        [35, 19, 12, 135, 87, 209, 41, 45, 167], /*left = d153*/
+        [55, 25, 21, 118, 95, 215, 38, 39, 66],  /*left = d207*/
+        [51, 38, 25, 113, 58, 164, 70, 93, 97],  /*left = d63 */
+        [47, 54, 34, 146, 108, 203, 72, 103, 151], /*left = tm  */
+    ],
+    [
+        /* above = d117 */
+        [64, 19, 37, 156, 66, 138, 49, 95, 133], /*left = dc  */
+        [46, 27, 80, 150, 55, 124, 55, 121, 135], /*left = v   */
+        [36, 23, 27, 165, 149, 166, 54, 64, 118], /*left = h   */
+        [53, 21, 36, 131, 63, 163, 60, 109, 81], /*left = d45 */
+        [40, 26, 35, 154, 40, 185, 51, 97, 123], /*left = d135*/
+        [35, 19, 34, 179, 19, 97, 48, 129, 124], /*left = d117*/
+        [36, 20, 26, 136, 62, 164, 33, 77, 154], /*left = d153*/
+        [45, 18, 32, 130, 90, 157, 40, 79, 91],  /*left = d207*/
+        [45, 26, 28, 129, 45, 129, 49, 147, 123], /*left = d63 */
+        [38, 44, 51, 136, 74, 162, 57, 97, 121], /*left = tm  */
+    ],
+    [
+        /* above = d153 */
+        [75, 17, 22, 136, 138, 185, 32, 34, 166], /*left = dc  */
+        [56, 39, 58, 133, 117, 173, 48, 53, 187], /*left = v   */
+        [35, 21, 12, 161, 212, 207, 20, 23, 145], /*left = h   */
+        [56, 29, 19, 117, 109, 181, 55, 68, 112], /*left = d45 */
+        [47, 29, 17, 153, 64, 220, 59, 51, 114],  /*left = d135*/
+        [46, 16, 24, 136, 76, 147, 41, 64, 172],  /*left = d117*/
+        [34, 17, 11, 108, 152, 187, 13, 15, 209], /*left = d153*/
+        [51, 24, 14, 115, 133, 209, 32, 26, 104], /*left = d207*/
+        [55, 30, 18, 122, 79, 179, 44, 88, 116],  /*left = d63 */
+        [37, 49, 25, 129, 168, 164, 41, 54, 148], /*left = tm  */
+    ],
+    [
+        /* above = d207 */
+        [82, 22, 32, 127, 143, 213, 39, 41, 70], /*left = dc  */
+        [62, 44, 61, 123, 105, 189, 48, 57, 64], /*left = v   */
+        [47, 25, 17, 175, 222, 220, 24, 30, 86], /*left = h   */
+        [68, 36, 17, 106, 102, 206, 59, 74, 74], /*left = d45 */
+        [57, 39, 23, 151, 68, 216, 55, 63, 58],  /*left = d135*/
+        [49, 30, 35, 141, 70, 168, 82, 40, 115], /*left = d117*/
+        [51, 25, 15, 136, 129, 202, 38, 35, 139], /*left = d153*/
+        [68, 26, 16, 111, 141, 215, 29, 28, 28], /*left = d207*/
+        [59, 39, 19, 114, 75, 180, 77, 104, 42], /*left = d63 */
+        [40, 61, 26, 126, 152, 206, 61, 59, 93], /*left = tm  */
+    ],
+    [
+        /* above = d63 */
+        [78, 23, 39, 111, 117, 170, 74, 124, 94], /*left = dc  */
+        [48, 34, 86, 101, 92, 146, 78, 179, 134], /*left = v   */
+        [47, 22, 24, 138, 187, 178, 68, 69, 59],  /*left = h   */
+        [56, 25, 33, 105, 112, 187, 95, 177, 129], /*left = d45 */
+        [48, 31, 27, 114, 63, 183, 82, 116, 56],  /*left = d135*/
+        [43, 28, 37, 121, 63, 123, 61, 192, 169], /*left = d117*/
+        [42, 17, 24, 109, 97, 177, 56, 76, 122],  /*left = d153*/
+        [58, 18, 28, 105, 139, 182, 70, 92, 63],  /*left = d207*/
+        [46, 23, 32, 74, 86, 150, 67, 183, 88],   /*left = d63 */
+        [36, 38, 48, 92, 122, 165, 88, 137, 91],  /*left = tm  */
+    ],
+    [
+        /* above = tm */
+        [65, 70, 60, 155, 159, 199, 61, 60, 81], /*left = dc  */
+        [44, 78, 115, 132, 119, 173, 71, 112, 93], /*left = v   */
+        [39, 38, 21, 184, 227, 206, 42, 32, 64], /*left = h   */
+        [58, 47, 36, 124, 137, 193, 80, 82, 78], /*left = d45 */
+        [49, 50, 35, 144, 95, 205, 63, 78, 59],  /*left = d135*/
+        [41, 53, 52, 148, 71, 142, 65, 128, 51], /*left = d117*/
+        [40, 36, 28, 143, 143, 202, 40, 55, 137], /*left = d153*/
+        [52, 34, 29, 129, 183, 227, 42, 35, 43], /*left = d207*/
+        [42, 44, 44, 104, 105, 164, 64, 130, 80], /*left = d63 */
+        [43, 81, 53, 140, 169, 204, 68, 84, 72], /*left = tm  */
+    ],
+];
+
+#[no_mangle]
+pub static v4l2_vp9_kf_partition_probs_rs: [[u8; 3]; 16] = [
+    /* 8x8 -> 4x4 */
+    [158, 97, 94], /* a/l both not split   */
+    [93, 24, 99],  /* a split, l not split */
+    [85, 119, 44], /* l split, a not split */
+    [62, 59, 67],  /* a/l both split       */
+    /* 16x16 -> 8x8 */
+    [149, 53, 53], /* a/l both not split   */
+    [94, 20, 48],  /* a split, l not split */
+    [83, 53, 24],  /* l split, a not split */
+    [52, 18, 18],  /* a/l both split       */
+    /* 32x32 -> 16x16 */
+    [150, 40, 39], /* a/l both not split   */
+    [78, 12, 26],  /* a split, l not split */
+    [67, 33, 11],  /* l split, a not split */
+    [24, 7, 5],    /* a/l both split       */
+    /* 64x64 -> 32x32 */
+    [174, 35, 49], /* a/l both not split   */
+    [68, 11, 27],  /* a split, l not split */
+    [57, 15, 9],   /* l split, a not split */
+    [12, 3, 3],    /* a/l both split       */
+];
+
+#[no_mangle]
+pub static v4l2_vp9_kf_uv_mode_prob_rs: [[u8; 9]; 10] = [
+    [144, 11, 54, 157, 195, 130, 46, 58, 108],  /* y = dc   */
+    [118, 15, 123, 148, 131, 101, 44, 93, 131], /* y = v    */
+    [113, 12, 23, 188, 226, 142, 26, 32, 125],  /* y = h    */
+    [120, 11, 50, 123, 163, 135, 64, 77, 103],  /* y = d45  */
+    [113, 9, 36, 155, 111, 157, 32, 44, 161],   /* y = d135 */
+    [116, 9, 55, 176, 76, 96, 37, 61, 149],     /* y = d117 */
+    [115, 9, 28, 141, 161, 167, 21, 25, 193],   /* y = d153 */
+    [120, 12, 32, 145, 195, 142, 32, 38, 86],   /* y = d207 */
+    [116, 12, 64, 120, 140, 125, 49, 115, 121], /* y = d63  */
+    [102, 19, 66, 162, 182, 122, 35, 59, 128],  /* y = tm   */
+];
+
+#[no_mangle]
+pub static v4l2_vp9_default_probs_rs: FrameContext = FrameContext {
+    tx8: [[100], [66]],
+    tx16: [[20, 152], [15, 101]],
+    tx32: [[3, 136, 37], [5, 52, 13]],
+    coef: [
+        [
+            /* tx  4x4 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [195, 29, 183],
+                        [84, 49, 136],
+                        [8, 42, 71],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [31, 107, 169],
+                        [35, 99, 159],
+                        [17, 82, 140],
+                        [8, 66, 114],
+                        [2, 44, 76],
+                        [1, 19, 32],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [40, 132, 201],
+                        [29, 114, 187],
+                        [13, 91, 157],
+                        [7, 75, 127],
+                        [3, 58, 95],
+                        [1, 28, 47],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [69, 142, 221],
+                        [42, 122, 201],
+                        [15, 91, 159],
+                        [6, 67, 121],
+                        [1, 42, 77],
+                        [1, 17, 31],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [102, 148, 228],
+                        [67, 117, 204],
+                        [17, 82, 154],
+                        [6, 59, 114],
+                        [2, 39, 75],
+                        [1, 15, 29],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [156, 57, 233],
+                        [119, 57, 212],
+                        [58, 48, 163],
+                        [29, 40, 124],
+                        [12, 30, 81],
+                        [3, 12, 31],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [191, 107, 226],
+                        [124, 117, 204],
+                        [25, 99, 155],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [29, 148, 210],
+                        [37, 126, 194],
+                        [8, 93, 157],
+                        [2, 68, 118],
+                        [1, 39, 69],
+                        [1, 17, 33],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [41, 151, 213],
+                        [27, 123, 193],
+                        [3, 82, 144],
+                        [1, 58, 105],
+                        [1, 32, 60],
+                        [1, 13, 26],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [59, 159, 220],
+                        [23, 126, 198],
+                        [4, 88, 151],
+                        [1, 66, 114],
+                        [1, 38, 71],
+                        [1, 18, 34],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [114, 136, 232],
+                        [51, 114, 207],
+                        [11, 83, 155],
+                        [3, 56, 105],
+                        [1, 33, 65],
+                        [1, 17, 34],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [149, 65, 234],
+                        [121, 57, 215],
+                        [61, 49, 166],
+                        [28, 36, 114],
+                        [12, 25, 76],
+                        [3, 16, 42],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [214, 49, 220],
+                        [132, 63, 188],
+                        [42, 65, 137],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [85, 137, 221],
+                        [104, 131, 216],
+                        [49, 111, 192],
+                        [21, 87, 155],
+                        [2, 49, 87],
+                        [1, 16, 28],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [89, 163, 230],
+                        [90, 137, 220],
+                        [29, 100, 183],
+                        [10, 70, 135],
+                        [2, 42, 81],
+                        [1, 17, 33],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [108, 167, 237],
+                        [55, 133, 222],
+                        [15, 97, 179],
+                        [4, 72, 135],
+                        [1, 45, 85],
+                        [1, 19, 38],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [124, 146, 240],
+                        [66, 124, 224],
+                        [17, 88, 175],
+                        [4, 58, 122],
+                        [1, 36, 75],
+                        [1, 18, 37],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [141, 79, 241],
+                        [126, 70, 227],
+                        [66, 58, 182],
+                        [30, 44, 136],
+                        [12, 34, 96],
+                        [2, 20, 47],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [229, 99, 249],
+                        [143, 111, 235],
+                        [46, 109, 192],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [82, 158, 236],
+                        [94, 146, 224],
+                        [25, 117, 191],
+                        [9, 87, 149],
+                        [3, 56, 99],
+                        [1, 33, 57],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [83, 167, 237],
+                        [68, 145, 222],
+                        [10, 103, 177],
+                        [2, 72, 131],
+                        [1, 41, 79],
+                        [1, 20, 39],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [99, 167, 239],
+                        [47, 141, 224],
+                        [10, 104, 178],
+                        [2, 73, 133],
+                        [1, 44, 85],
+                        [1, 22, 47],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [127, 145, 243],
+                        [71, 129, 228],
+                        [17, 93, 177],
+                        [3, 61, 124],
+                        [1, 41, 84],
+                        [1, 21, 52],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [157, 78, 244],
+                        [140, 72, 231],
+                        [69, 58, 184],
+                        [31, 44, 137],
+                        [14, 38, 105],
+                        [8, 23, 61],
+                    ],
+                ],
+            ],
+        ],
+        [
+            /* tx  8x8 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [125, 34, 187],
+                        [52, 41, 133],
+                        [6, 31, 56],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [37, 109, 153],
+                        [51, 102, 147],
+                        [23, 87, 128],
+                        [8, 67, 101],
+                        [1, 41, 63],
+                        [1, 19, 29],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [31, 154, 185],
+                        [17, 127, 175],
+                        [6, 96, 145],
+                        [2, 73, 114],
+                        [1, 51, 82],
+                        [1, 28, 45],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [23, 163, 200],
+                        [10, 131, 185],
+                        [2, 93, 148],
+                        [1, 67, 111],
+                        [1, 41, 69],
+                        [1, 14, 24],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [29, 176, 217],
+                        [12, 145, 201],
+                        [3, 101, 156],
+                        [1, 69, 111],
+                        [1, 39, 63],
+                        [1, 14, 23],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [57, 192, 233],
+                        [25, 154, 215],
+                        [6, 109, 167],
+                        [3, 78, 118],
+                        [1, 48, 69],
+                        [1, 21, 29],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [202, 105, 245],
+                        [108, 106, 216],
+                        [18, 90, 144],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [33, 172, 219],
+                        [64, 149, 206],
+                        [14, 117, 177],
+                        [5, 90, 141],
+                        [2, 61, 95],
+                        [1, 37, 57],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [33, 179, 220],
+                        [11, 140, 198],
+                        [1, 89, 148],
+                        [1, 60, 104],
+                        [1, 33, 57],
+                        [1, 12, 21],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [30, 181, 221],
+                        [8, 141, 198],
+                        [1, 87, 145],
+                        [1, 58, 100],
+                        [1, 31, 55],
+                        [1, 12, 20],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [32, 186, 224],
+                        [7, 142, 198],
+                        [1, 86, 143],
+                        [1, 58, 100],
+                        [1, 31, 55],
+                        [1, 12, 22],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [57, 192, 227],
+                        [20, 143, 204],
+                        [3, 96, 154],
+                        [1, 68, 112],
+                        [1, 42, 69],
+                        [1, 19, 32],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [212, 35, 215],
+                        [113, 47, 169],
+                        [29, 48, 105],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [74, 129, 203],
+                        [106, 120, 203],
+                        [49, 107, 178],
+                        [19, 84, 144],
+                        [4, 50, 84],
+                        [1, 15, 25],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [71, 172, 217],
+                        [44, 141, 209],
+                        [15, 102, 173],
+                        [6, 76, 133],
+                        [2, 51, 89],
+                        [1, 24, 42],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [64, 185, 231],
+                        [31, 148, 216],
+                        [8, 103, 175],
+                        [3, 74, 131],
+                        [1, 46, 81],
+                        [1, 18, 30],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [65, 196, 235],
+                        [25, 157, 221],
+                        [5, 105, 174],
+                        [1, 67, 120],
+                        [1, 38, 69],
+                        [1, 15, 30],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [65, 204, 238],
+                        [30, 156, 224],
+                        [7, 107, 177],
+                        [2, 70, 124],
+                        [1, 42, 73],
+                        [1, 18, 34],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [225, 86, 251],
+                        [144, 104, 235],
+                        [42, 99, 181],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [85, 175, 239],
+                        [112, 165, 229],
+                        [29, 136, 200],
+                        [12, 103, 162],
+                        [6, 77, 123],
+                        [2, 53, 84],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [75, 183, 239],
+                        [30, 155, 221],
+                        [3, 106, 171],
+                        [1, 74, 128],
+                        [1, 44, 76],
+                        [1, 17, 28],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [73, 185, 240],
+                        [27, 159, 222],
+                        [2, 107, 172],
+                        [1, 75, 127],
+                        [1, 42, 73],
+                        [1, 17, 29],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [62, 190, 238],
+                        [21, 159, 222],
+                        [2, 107, 172],
+                        [1, 72, 122],
+                        [1, 40, 71],
+                        [1, 18, 32],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [61, 199, 240],
+                        [27, 161, 226],
+                        [4, 113, 180],
+                        [1, 76, 129],
+                        [1, 46, 80],
+                        [1, 23, 41],
+                    ],
+                ],
+            ],
+        ],
+        [
+            /* tx  16x16 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [7, 27, 153],
+                        [5, 30, 95],
+                        [1, 16, 30],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [50, 75, 127],
+                        [57, 75, 124],
+                        [27, 67, 108],
+                        [10, 54, 86],
+                        [1, 33, 52],
+                        [1, 12, 18],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [43, 125, 151],
+                        [26, 108, 148],
+                        [7, 83, 122],
+                        [2, 59, 89],
+                        [1, 38, 60],
+                        [1, 17, 27],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [23, 144, 163],
+                        [13, 112, 154],
+                        [2, 75, 117],
+                        [1, 50, 81],
+                        [1, 31, 51],
+                        [1, 14, 23],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [18, 162, 185],
+                        [6, 123, 171],
+                        [1, 78, 125],
+                        [1, 51, 86],
+                        [1, 31, 54],
+                        [1, 14, 23],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [15, 199, 227],
+                        [3, 150, 204],
+                        [1, 91, 146],
+                        [1, 55, 95],
+                        [1, 30, 53],
+                        [1, 11, 20],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [19, 55, 240],
+                        [19, 59, 196],
+                        [3, 52, 105],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [41, 166, 207],
+                        [104, 153, 199],
+                        [31, 123, 181],
+                        [14, 101, 152],
+                        [5, 72, 106],
+                        [1, 36, 52],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [35, 176, 211],
+                        [12, 131, 190],
+                        [2, 88, 144],
+                        [1, 60, 101],
+                        [1, 36, 60],
+                        [1, 16, 28],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [28, 183, 213],
+                        [8, 134, 191],
+                        [1, 86, 142],
+                        [1, 56, 96],
+                        [1, 30, 53],
+                        [1, 12, 20],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [20, 190, 215],
+                        [4, 135, 192],
+                        [1, 84, 139],
+                        [1, 53, 91],
+                        [1, 28, 49],
+                        [1, 11, 20],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [13, 196, 216],
+                        [2, 137, 192],
+                        [1, 86, 143],
+                        [1, 57, 99],
+                        [1, 32, 56],
+                        [1, 13, 24],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [211, 29, 217],
+                        [96, 47, 156],
+                        [22, 43, 87],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [78, 120, 193],
+                        [111, 116, 186],
+                        [46, 102, 164],
+                        [15, 80, 128],
+                        [2, 49, 76],
+                        [1, 18, 28],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [71, 161, 203],
+                        [42, 132, 192],
+                        [10, 98, 150],
+                        [3, 69, 109],
+                        [1, 44, 70],
+                        [1, 18, 29],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [57, 186, 211],
+                        [30, 140, 196],
+                        [4, 93, 146],
+                        [1, 62, 102],
+                        [1, 38, 65],
+                        [1, 16, 27],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [47, 199, 217],
+                        [14, 145, 196],
+                        [1, 88, 142],
+                        [1, 57, 98],
+                        [1, 36, 62],
+                        [1, 15, 26],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [26, 219, 229],
+                        [5, 155, 207],
+                        [1, 94, 151],
+                        [1, 60, 104],
+                        [1, 36, 62],
+                        [1, 16, 28],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [233, 29, 248],
+                        [146, 47, 220],
+                        [43, 52, 140],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [100, 163, 232],
+                        [179, 161, 222],
+                        [63, 142, 204],
+                        [37, 113, 174],
+                        [26, 89, 137],
+                        [18, 68, 97],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [85, 181, 230],
+                        [32, 146, 209],
+                        [7, 100, 164],
+                        [3, 71, 121],
+                        [1, 45, 77],
+                        [1, 18, 30],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [65, 187, 230],
+                        [20, 148, 207],
+                        [2, 97, 159],
+                        [1, 68, 116],
+                        [1, 40, 70],
+                        [1, 14, 29],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [40, 194, 227],
+                        [8, 147, 204],
+                        [1, 94, 155],
+                        [1, 65, 112],
+                        [1, 39, 66],
+                        [1, 14, 26],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [16, 208, 228],
+                        [3, 151, 207],
+                        [1, 98, 160],
+                        [1, 67, 117],
+                        [1, 41, 74],
+                        [1, 17, 31],
+                    ],
+                ],
+            ],
+        ],
+        [
+            /* tx  32x32 */
+            [
+                /* block Type 0 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [17, 38, 140],
+                        [7, 34, 80],
+                        [1, 17, 29],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [37, 75, 128],
+                        [41, 76, 128],
+                        [26, 66, 116],
+                        [12, 52, 94],
+                        [2, 32, 55],
+                        [1, 10, 16],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [50, 127, 154],
+                        [37, 109, 152],
+                        [16, 82, 121],
+                        [5, 59, 85],
+                        [1, 35, 54],
+                        [1, 13, 20],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [40, 142, 167],
+                        [17, 110, 157],
+                        [2, 71, 112],
+                        [1, 44, 72],
+                        [1, 27, 45],
+                        [1, 11, 17],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [30, 175, 188],
+                        [9, 124, 169],
+                        [1, 74, 116],
+                        [1, 48, 78],
+                        [1, 30, 49],
+                        [1, 11, 18],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [10, 222, 223],
+                        [2, 150, 194],
+                        [1, 83, 128],
+                        [1, 48, 79],
+                        [1, 27, 45],
+                        [1, 11, 17],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [36, 41, 235],
+                        [29, 36, 193],
+                        [10, 27, 111],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [85, 165, 222],
+                        [177, 162, 215],
+                        [110, 135, 195],
+                        [57, 113, 168],
+                        [23, 83, 120],
+                        [10, 49, 61],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [85, 190, 223],
+                        [36, 139, 200],
+                        [5, 90, 146],
+                        [1, 60, 103],
+                        [1, 38, 65],
+                        [1, 18, 30],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [72, 202, 223],
+                        [23, 141, 199],
+                        [2, 86, 140],
+                        [1, 56, 97],
+                        [1, 36, 61],
+                        [1, 16, 27],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [55, 218, 225],
+                        [13, 145, 200],
+                        [1, 86, 141],
+                        [1, 57, 99],
+                        [1, 35, 61],
+                        [1, 13, 22],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [15, 235, 212],
+                        [1, 132, 184],
+                        [1, 84, 139],
+                        [1, 57, 97],
+                        [1, 34, 56],
+                        [1, 14, 23],
+                    ],
+                ],
+            ],
+            [
+                /* block Type 1 */
+                [
+                    /* Intra */
+                    [
+                        /* Coeff Band 0 */
+                        [181, 21, 201],
+                        [61, 37, 123],
+                        [10, 38, 71],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [47, 106, 172],
+                        [95, 104, 173],
+                        [42, 93, 159],
+                        [18, 77, 131],
+                        [4, 50, 81],
+                        [1, 17, 23],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [62, 147, 199],
+                        [44, 130, 189],
+                        [28, 102, 154],
+                        [18, 75, 115],
+                        [2, 44, 65],
+                        [1, 12, 19],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [55, 153, 210],
+                        [24, 130, 194],
+                        [3, 93, 146],
+                        [1, 61, 97],
+                        [1, 31, 50],
+                        [1, 10, 16],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [49, 186, 223],
+                        [17, 148, 204],
+                        [1, 96, 142],
+                        [1, 53, 83],
+                        [1, 26, 44],
+                        [1, 11, 17],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [13, 217, 212],
+                        [2, 136, 180],
+                        [1, 78, 124],
+                        [1, 50, 83],
+                        [1, 29, 49],
+                        [1, 14, 23],
+                    ],
+                ],
+                [
+                    /* Inter */
+                    [
+                        /* Coeff Band 0 */
+                        [197, 13, 247],
+                        [82, 17, 222],
+                        [25, 17, 162],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                        [0, 0, 0],
+                    ],
+                    [
+                        /* Coeff Band 1 */
+                        [126, 186, 247],
+                        [234, 191, 243],
+                        [176, 177, 234],
+                        [104, 158, 220],
+                        [66, 128, 186],
+                        [55, 90, 137],
+                    ],
+                    [
+                        /* Coeff Band 2 */
+                        [111, 197, 242],
+                        [46, 158, 219],
+                        [9, 104, 171],
+                        [2, 65, 125],
+                        [1, 44, 80],
+                        [1, 17, 91],
+                    ],
+                    [
+                        /* Coeff Band 3 */
+                        [104, 208, 245],
+                        [39, 168, 224],
+                        [3, 109, 162],
+                        [1, 79, 124],
+                        [1, 50, 102],
+                        [1, 43, 102],
+                    ],
+                    [
+                        /* Coeff Band 4 */
+                        [84, 220, 246],
+                        [31, 177, 231],
+                        [2, 115, 180],
+                        [1, 79, 134],
+                        [1, 55, 77],
+                        [1, 60, 79],
+                    ],
+                    [
+                        /* Coeff Band 5 */
+                        [43, 243, 240],
+                        [8, 180, 217],
+                        [1, 115, 166],
+                        [1, 84, 121],
+                        [1, 51, 67],
+                        [1, 16, 6],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    skip: [192, 128, 64],
+    inter_mode: [
+        [2, 173, 34],
+        [7, 145, 85],
+        [7, 166, 63],
+        [7, 94, 66],
+        [8, 64, 46],
+        [17, 81, 31],
+        [25, 29, 30],
+    ],
+    interp_filter: [[235, 162], [36, 255], [34, 3], [149, 144]],
+    is_inter: [9, 102, 187, 225],
+    comp_mode: [239, 183, 119, 96, 41],
+    single_ref: [[33, 16], [77, 74], [142, 142], [172, 170], [238, 247]],
+    comp_ref: [50, 126, 123, 221, 226],
+    y_mode: [
+        [65, 32, 18, 144, 162, 194, 41, 51, 98],
+        [132, 68, 18, 165, 217, 196, 45, 40, 78],
+        [173, 80, 19, 176, 240, 193, 64, 35, 46],
+        [221, 135, 38, 194, 248, 121, 96, 85, 29],
+    ],
+    uv_mode: [
+        [120, 7, 76, 176, 208, 126, 28, 54, 103],   /* y  dc */
+        [48, 12, 154, 155, 139, 90, 34, 117, 119],  /* y  v */
+        [67, 6, 25, 204, 243, 158, 13, 21, 96],     /* y  h */
+        [97, 5, 44, 131, 176, 139, 48, 68, 97],     /* y  d45 */
+        [83, 5, 42, 156, 111, 152, 26, 49, 152],    /* y  d135 */
+        [80, 5, 58, 178, 74, 83, 33, 62, 145],      /* y  d117 */
+        [86, 5, 32, 154, 192, 168, 14, 22, 163],    /* y  d153 */
+        [85, 5, 32, 156, 216, 148, 19, 29, 73],     /* y  d207 */
+        [77, 7, 64, 116, 132, 122, 37, 126, 120],   /* y  d63 */
+        [101, 21, 107, 181, 192, 103, 19, 67, 125], /* y  tm */
+    ],
+    partition: [
+        /* 8x8 -> 4x4 */
+        [199, 122, 141], /* a/l both not split */
+        [147, 63, 159],  /* a split, l not split */
+        [148, 133, 118], /* l split, a not split */
+        [121, 104, 114], /* a/l both split */
+        /* 16x16 -> 8x8 */
+        [174, 73, 87], /* a/l both not split */
+        [92, 41, 83],  /* a split, l not split */
+        [82, 99, 50],  /* l split, a not split */
+        [53, 39, 39],  /* a/l both split */
+        /* 32x32 -> 16x16 */
+        [177, 58, 59], /* a/l both not split */
+        [68, 26, 63],  /* a split, l not split */
+        [52, 79, 25],  /* l split, a not split */
+        [17, 14, 12],  /* a/l both split */
+        /* 64x64 -> 32x32 */
+        [222, 34, 30], /* a/l both not split */
+        [72, 16, 44],  /* a split, l not split */
+        [58, 32, 12],  /* l split, a not split */
+        [10, 7, 6],    /* a/l both split */
+    ],
+    mv: FrameMvContext {
+        joint: [32, 64, 96],
+        sign: [128, 128],
+        classes: [
+            [224, 144, 192, 168, 192, 176, 192, 198, 198, 245],
+            [216, 128, 176, 160, 176, 176, 192, 198, 198, 208],
+        ],
+        class0_bit: [216, 208],
+        bits: [
+            [136, 140, 148, 160, 176, 192, 224, 234, 234, 240],
+            [136, 140, 148, 160, 176, 192, 224, 234, 234, 240],
+        ],
+        class0_fr: [
+            [[128, 128, 64], [96, 112, 64]],
+            [[128, 128, 64], [96, 112, 64]],
+        ],
+        fr: [[64, 96, 64], [64, 96, 64]],
+        class0_hp: [160, 160],
+        hp: [128, 128],
+    },
+};
+
+pub fn fw_update_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+) {
+    if u32::from(deltas.tx_mode) == bindings::V4L2_VP9_TX_MODE_SELECT {
+        update_tx_probs(probs, deltas);
+    }
+
+    update_coeff_probs(probs, deltas, dec_params);
+    update_skip_probs(probs, deltas);
+
+    if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+        || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0
+    {
+        return;
+    }
+
+    update_inter_mode_probs(probs, deltas);
+
+    if u32::from(dec_params.interpolation_filter) == bindings::V4L2_VP9_INTERP_FILTER_SWITCHABLE {
+        update_interp_filter_probs(probs, deltas);
+    }
+
+    update_is_inter_probs(probs, deltas);
+    update_frame_reference_mode_probs(dec_params.reference_mode.into(), probs, deltas);
+
+    update_y_mode_probs(probs, deltas);
+    update_partition_probs(probs, deltas);
+    update_mv_probs(probs, deltas, dec_params);
+}
+
+pub fn reset_frame_ctx(
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+    frame_context: &mut [FrameContext; 4],
+) -> u8 {
+    let mut fctx_idx = dec_params.frame_context_idx;
+
+    if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+        || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0
+        || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT != 0
+    {
+        /*
+         * setup_past_independence()
+         * We do nothing here. Instead of storing default probs in some intermediate
+         * location and then copying from that location to appropriate contexts
+         * in save_probs() below, we skip that step and save default probs directly
+         * to appropriate contexts.
+         */
+
+        if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+            || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT != 0
+            || u32::from(dec_params.reset_frame_context) == bindings::V4L2_VP9_RESET_FRAME_CTX_ALL
+        {
+            for i in 0..4 {
+                /* save_probs(i) */
+                frame_context[i] = v4l2_vp9_default_probs_rs.clone();
+            }
+        } else if u32::from(dec_params.reset_frame_context)
+            == bindings::V4L2_VP9_RESET_FRAME_CTX_SPEC
+        {
+            /* save_probs(fctx_idx) */
+            frame_context[usize::from(fctx_idx)] = v4l2_vp9_default_probs_rs.clone();
+        }
+
+        fctx_idx = 0;
+    }
+
+    fctx_idx
+}
+
+pub fn adapt_coef_probs(
+    probs: &mut FrameContext,
+    counts: &mut FrameSymbolCounts<'_>,
+    use_128: bool,
+    frame_is_intra: bool,
+) {
+    if frame_is_intra {
+        _adapt_coef_probs(probs, counts, 112);
+    } else {
+        if use_128 {
+            _adapt_coef_probs(probs, counts, 128);
+        } else {
+            _adapt_coef_probs(probs, counts, 112);
+        }
+    }
+}
+
+pub fn adapt_noncoef_probs(
+    probs: &mut FrameContext,
+    counts: &mut FrameSymbolCounts<'_>,
+    reference_mode: u8,
+    interpolation_filter: u8,
+    tx_mode: u8,
+    flags: u32,
+) {
+    for i in 0..probs.is_inter.len() {
+        probs.is_inter[i] = adapt_prob(probs.is_inter[i], counts.intra_inter[i]);
+    }
+
+    for i in 0..probs.comp_mode.len() {
+        probs.comp_mode[i] = adapt_prob(probs.comp_mode[i], counts.comp[i]);
+    }
+
+    for i in 0..probs.comp_ref.len() {
+        probs.comp_ref[i] = adapt_prob(probs.comp_ref[i], counts.comp_ref[i]);
+    }
+
+    if u32::from(reference_mode) != bindings::V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE {
+        for i in 0..probs.single_ref.len() {
+            for j in 0..probs.single_ref[0].len() {
+                probs.single_ref[i][j] =
+                    adapt_prob(probs.single_ref[i][j], counts.single_ref[i][j]);
+            }
+        }
+    }
+
+    for i in 0..probs.inter_mode.len() {
+        adapt_probs_variant_c(&mut probs.inter_mode[i], &counts.mv_mode[i]);
+    }
+
+    for i in 0..probs.y_mode.len() {
+        adapt_probs_variant_d(&mut probs.y_mode[i], &counts.y_mode[i]);
+    }
+
+    for i in 0..probs.uv_mode.len() {
+        adapt_probs_variant_d(&mut probs.uv_mode[i], &counts.uv_mode[i]);
+    }
+
+    for i in 0..probs.partition.len() {
+        adapt_probs_variant_e(&mut probs.partition[i], &counts.partition[i]);
+    }
+
+    for i in 0..probs.skip.len() {
+        probs.skip[i] = adapt_prob(probs.skip[i], counts.skip[i]);
+    }
+
+    if u32::from(interpolation_filter) == bindings::V4L2_VP9_INTERP_FILTER_SWITCHABLE {
+        for i in 0..probs.interp_filter.len() {
+            adapt_probs_variant_f(&mut probs.interp_filter[i], &counts.filter[i]);
+        }
+    }
+
+    if u32::from(tx_mode) == bindings::V4L2_VP9_TX_MODE_SELECT {
+        for i in 0..probs.tx8.len() {
+            adapt_probs_variant_b(&mut probs.tx8[i], &counts.tx8p[i]);
+            adapt_probs_variant_f(&mut probs.tx16[i], &counts.tx16p[i]);
+            adapt_probs_variant_e(&mut probs.tx32[i], &counts.tx32p[i]);
+        }
+    }
+
+    adapt_probs_variant_e(&mut probs.mv.joint, counts.mv_joint);
+
+    for i in 0..probs.mv.sign.len() {
+        probs.mv.sign[i] = adapt_prob(probs.mv.sign[i], counts.sign[i]);
+
+        adapt_probs_variant_g(&mut probs.mv.classes[i], &counts.classes[i]);
+
+        probs.mv.class0_bit[i] = adapt_prob(probs.mv.class0_bit[i], counts.class0[i]);
+
+        for j in 0..probs.mv.bits[0].len() {
+            probs.mv.bits[i][j] = adapt_prob(probs.mv.bits[i][j], counts.bits[i][j]);
+        }
+
+        for j in 0..probs.mv.class0_fr[0].len() {
+            adapt_probs_variant_e(&mut probs.mv.class0_fr[i][j], &counts.class0_fp[i][j]);
+        }
+
+        adapt_probs_variant_e(&mut probs.mv.fr[i], &counts.fp[i]);
+
+        if flags & bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV == 0 {
+            continue;
+        }
+
+        probs.mv.class0_hp[i] = adapt_prob(probs.mv.class0_hp[i], counts.class0_hp[i]);
+
+        probs.mv.hp[i] = adapt_prob(probs.mv.hp[i], counts.hp[i]);
+    }
+}
+
+pub fn seg_feat_enabled(feature_enabled: &[u8; 8], feature: u32, segid: u32) -> bool {
+    let mask = 1 << feature;
+    feature_enabled[segid as usize] & mask != 0
+}
+
+fn fastdiv(dividend: u32, divisor: u32) -> u32 {
+    const fn inv<const SZ: usize>() -> [u32; SZ] {
+        let mut ret = [0; SZ];
+        let mut i = 2;
+        let n = SZ + 1;
+
+        while i <= n {
+            ret[i - 2] = (((1u64 << 32) + (i as u64 - 1)) / i as u64) as u32;
+            i += 1;
+        }
+
+        ret
+    }
+    const SZ: usize = 255;
+    const INV: [u32; SZ] = inv::<SZ>();
+    if divisor - 2 >= SZ as u32 {
+        crate::pr_warn!("fastdiv: divisor {} too large", divisor);
+        return dividend;
+    }
+
+    if divisor == 0 {
+        0
+    } else if divisor == 1 {
+        dividend
+    } else {
+        let ret = (u64::from(dividend) * u64::from(INV[divisor as usize - 2])) >> 32;
+        ret as u32
+    }
+}
+
+fn inv_recenter_nonneg(v: i32, m: i32) -> i32 {
+    if v > 2 * m {
+        v
+    } else if (v & 1) != 0 {
+        m - ((v + 1) >> 1)
+    } else {
+        m + (v >> 1)
+    }
+}
+
+fn update_prob(delta: i32, prob: i32) -> i32 {
+    if delta == 0 {
+        prob
+    } else if prob <= 128 {
+        1 + inv_recenter_nonneg(delta, prob - 1)
+    } else {
+        255 - inv_recenter_nonneg(delta, 255 - prob)
+    }
+}
+
+fn update_tx_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) {
+    for i in 0..probs.tx8.len() {
+        let p8x8 = &mut probs.tx8[i];
+        let p16x16 = &mut probs.tx16[i];
+        let p32x32 = &mut probs.tx32[i];
+
+        let d8x8 = &deltas.tx8[i];
+        let d16x16 = &deltas.tx16[i];
+        let d32x32 = &deltas.tx32[i];
+
+        p8x8[0] = update_prob(d8x8[0].into(), p8x8[0].into()) as u8;
+        p16x16[0] = update_prob(d16x16[0].into(), p16x16[0].into()) as u8;
+        p16x16[1] = update_prob(d16x16[1].into(), p16x16[1].into()) as u8;
+        p32x32[0] = update_prob(d32x32[0].into(), p32x32[0].into()) as u8;
+        p32x32[1] = update_prob(d32x32[1].into(), p32x32[1].into()) as u8;
+        p32x32[2] = update_prob(d32x32[2].into(), p32x32[2].into()) as u8;
+    }
+}
+
+macro_rules! BAND_6 {
+    ($band:expr) => {
+        if $band == 0 {
+            3
+        } else {
+            6
+        }
+    };
+}
+
+fn update_coeff(deltas: &[[[u8; 3]; 6]; 6], probs: &mut [[[u8; 3]; 6]; 6]) {
+    for l in 0..6 {
+        for m in 0..BAND_6!(l) {
+            let p = &mut probs[l][m];
+            let d = &deltas[l][m];
+
+            for n in 0..3 {
+                p[n] = update_prob(d[n].into(), p[n].into()) as u8;
+            }
+        }
+    }
+}
+
+fn update_coeff_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+) {
+    for i in 0..probs.coef.len() {
+        for j in 0..probs.coef[0].len() {
+            for k in 0..probs.coef[0][0].len() {
+                update_coeff(&deltas.coef[i][j][k], &mut probs.coef[i][j][k]);
+            }
+        }
+
+        if usize::from(deltas.tx_mode) == i {
+            break;
+        }
+    }
+}
+
+fn update_skip_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) {
+    for i in 0..probs.skip.len() {
+        probs.skip[i] = update_prob(deltas.skip[i].into(), probs.skip[i].into()) as u8;
+    }
+}
+
+fn update_inter_mode_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..probs.inter_mode.len() {
+        let p = &mut probs.inter_mode[i];
+        let d = &deltas.inter_mode[i];
+
+        p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+        p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+        p[2] = update_prob(d[2].into(), p[2].into()) as u8;
+    }
+}
+
+fn update_interp_filter_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..probs.interp_filter.len() {
+        let p = &mut probs.interp_filter[i];
+        let d = &deltas.interp_filter[i];
+
+        p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+        p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+    }
+}
+
+fn update_is_inter_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..probs.is_inter.len() {
+        probs.is_inter[i] = update_prob(deltas.is_inter[i].into(), probs.is_inter[i].into()) as u8;
+    }
+}
+
+fn update_frame_reference_mode_probs(
+    reference_mode: u32,
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    if reference_mode == bindings::V4L2_VP9_REFERENCE_MODE_SELECT {
+        for i in 0..probs.comp_mode.len() {
+            probs.comp_mode[i] =
+                update_prob(deltas.comp_mode[i].into(), probs.comp_mode[i].into()) as u8;
+        }
+    }
+
+    if reference_mode != bindings::V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE {
+        for i in 0..probs.single_ref.len() {
+            let p = &mut probs.single_ref[i];
+            let d = &deltas.single_ref[i];
+
+            p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+            p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+        }
+    }
+
+    if reference_mode != bindings::V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE {
+        for i in 0..probs.comp_ref.len() {
+            probs.comp_ref[i] =
+                update_prob(deltas.comp_ref[i].into(), probs.comp_ref[i].into()) as u8;
+        }
+    }
+}
+
+fn update_y_mode_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) {
+    for i in 0..probs.y_mode.len() {
+        for j in 0..probs.y_mode[0].len() {
+            probs.y_mode[i][j] =
+                update_prob(deltas.y_mode[i][j].into(), probs.y_mode[i][j].into()) as u8;
+        }
+    }
+}
+
+fn update_partition_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+) {
+    for i in 0..4 {
+        for j in 0..4 {
+            let p = &mut probs.partition[i * 4 + j];
+            let d = deltas.partition[i * 4 + j];
+
+            p[0] = update_prob(d[0].into(), p[0].into()) as u8;
+            p[1] = update_prob(d[1].into(), p[1].into()) as u8;
+            p[2] = update_prob(d[2].into(), p[2].into()) as u8;
+        }
+    }
+}
+
+fn update_mv_prob(delta: i32, prob: i32) -> i32 {
+    if delta == 0 {
+        prob
+    } else {
+        delta
+    }
+}
+
+fn update_mv_probs(
+    probs: &mut FrameContext,
+    deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+    dec_params: &bindings::v4l2_ctrl_vp9_frame,
+) {
+    let p = &mut probs.mv.joint;
+    let d = &deltas.mv.joint;
+
+    p[0] = update_mv_prob(d[0].into(), p[0].into()) as u8;
+    p[1] = update_mv_prob(d[1].into(), p[1].into()) as u8;
+    p[2] = update_mv_prob(d[2].into(), p[2].into()) as u8;
+
+    for i in 0..probs.mv.sign.len() {
+        let p = &mut probs.mv.sign;
+        let d = &deltas.mv.sign;
+        p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+
+        let len = probs.mv.classes[0].len();
+        let p = &mut probs.mv.classes[i];
+        let d = &deltas.mv.classes[i];
+        for j in 0..len {
+            p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8;
+        }
+
+        let p = &mut probs.mv.class0_bit;
+        let d = &deltas.mv.class0_bit;
+        p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+
+        let len = probs.mv.bits[0].len();
+        let p = &mut probs.mv.bits[i];
+        let d = &deltas.mv.bits[i];
+        for j in 0..len {
+            p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8;
+        }
+
+        let len = probs.mv.class0_fr[0].len();
+        for j in 0..len {
+            let p = &mut probs.mv.class0_fr[i][j];
+            let d = &deltas.mv.class0_fr[i][j];
+
+            p[0] = update_mv_prob(d[0].into(), p[0].into()) as u8;
+            p[1] = update_mv_prob(d[1].into(), p[1].into()) as u8;
+            p[2] = update_mv_prob(d[2].into(), p[2].into()) as u8;
+        }
+
+        let len = probs.mv.fr[i].len();
+        let p = &mut probs.mv.fr[i];
+        let d = &deltas.mv.fr[i];
+        for j in 0..len {
+            p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8;
+        }
+
+        if (dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV) != 0 {
+            let p = &mut probs.mv.class0_hp;
+            let d = &deltas.mv.class0_hp;
+            p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+
+            let p = &mut probs.mv.hp;
+            let d = &deltas.mv.hp;
+            p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8;
+        }
+    }
+}
+
+macro_rules! clamp {
+    ($val:expr, $min:expr, $max:expr) => {
+        if $val < $min {
+            $min
+        } else if $val > $max {
+            $max
+        } else {
+            $val
+        }
+    };
+}
+
+fn merge_prob(pre_prob: u8, ct0: u32, ct1: u32, count_sat: u32, max_update_factor: u32) -> u8 {
+    let den = ct0 + ct1;
+
+    if den == 0 {
+        /*
+         * prob = 128, count = 0, update_factor = 0
+         * Round2's argument: pre_prob * 256
+         * (pre_prob * 256 + 128) >> 8 == pre_prob
+         */
+        return pre_prob;
+    }
+
+    let prob = clamp!(((ct0 << 8) + (den >> 1)) / den, 1, 255);
+    let count = core::cmp::min(den, count_sat);
+    let factor = fastdiv(max_update_factor * count, count_sat);
+
+    let prob = i64::from(prob);
+    let count = i64::from(count);
+    let factor = i64::from(factor);
+    let pre_prob = i64::from(pre_prob);
+
+    /*
+     * Round2(pre_prob * (256 - factor) + prob * factor, 8)
+     * Round2(pre_prob * 256 + (prob - pre_prob) * factor, 8)
+     * (pre_prob * 256 >> 8) + (((prob - pre_prob) * factor + 128) >> 8)
+     */
+    (pre_prob + (((prob - pre_prob) * factor + 128) >> 8))
+        .try_into()
+        .unwrap()
+}
+
+fn noncoef_merge_prob(pre_prob: u8, ct0: u32, ct1: u32) -> u8 {
+    merge_prob(pre_prob, ct0, ct1, 20, 128)
+}
+
+/* 8.4.2 Merge probs process */
+/*
+ * merge_probs() is a recursive function in the spec. We avoid recursion in the kernel.
+ * That said, the "tree" parameter of merge_probs() controls how deep the recursion goes.
+ * It turns out that in all cases the recursive calls boil down to a short-ish series
+ * of merge_prob() invocations (note no "s").
+ *
+ * Variant A
+ * ---------
+ * merge_probs(small_token_tree, 2):
+ *	merge_prob(p[1], c[0], c[1] + c[2])
+ *	merge_prob(p[2], c[1], c[2])
+ *
+ * Variant B
+ * ---------
+ * merge_probs(binary_tree, 0) or
+ * merge_probs(tx_size_8_tree, 0):
+ *	merge_prob(p[0], c[0], c[1])
+ *
+ * Variant C
+ * ---------
+ * merge_probs(inter_mode_tree, 0):
+ *	merge_prob(p[0], c[2], c[1] + c[0] + c[3])
+ *	merge_prob(p[1], c[0], c[1] + c[3])
+ *	merge_prob(p[2], c[1], c[3])
+ *
+ * Variant D
+ * ---------
+ * merge_probs(intra_mode_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + ... + c[9])
+ *	merge_prob(p[1], c[9], c[1] + ... + c[8])
+ *	merge_prob(p[2], c[1], c[2] + ... + c[8])
+ *	merge_prob(p[3], c[2] + c[4] + c[5], c[3] + c[8] + c[6] + c[7])
+ *	merge_prob(p[4], c[2], c[4] + c[5])
+ *	merge_prob(p[5], c[4], c[5])
+ *	merge_prob(p[6], c[3], c[8] + c[6] + c[7])
+ *	merge_prob(p[7], c[8], c[6] + c[7])
+ *	merge_prob(p[8], c[6], c[7])
+ *
+ * Variant E
+ * ---------
+ * merge_probs(partition_tree, 0) or
+ * merge_probs(tx_size_32_tree, 0) or
+ * merge_probs(mv_joint_tree, 0) or
+ * merge_probs(mv_fr_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + c[2] + c[3])
+ *	merge_prob(p[1], c[1], c[2] + c[3])
+ *	merge_prob(p[2], c[2], c[3])
+ *
+ * Variant F
+ * ---------
+ * merge_probs(interp_filter_tree, 0) or
+ * merge_probs(tx_size_16_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + c[2])
+ *	merge_prob(p[1], c[1], c[2])
+ *
+ * Variant G
+ * ---------
+ * merge_probs(mv_class_tree, 0):
+ *	merge_prob(p[0], c[0], c[1] + ... + c[10])
+ *	merge_prob(p[1], c[1], c[2] + ... + c[10])
+ *	merge_prob(p[2], c[2] + c[3], c[4] + ... + c[10])
+ *	merge_prob(p[3], c[2], c[3])
+ *	merge_prob(p[4], c[4] + c[5], c[6] + ... + c[10])
+ *	merge_prob(p[5], c[4], c[5])
+ *	merge_prob(p[6], c[6], c[7] + ... + c[10])
+ *	merge_prob(p[7], c[7] + c[8], c[9] + c[10])
+ *	merge_prob(p[8], c[7], c[8])
+ *	merge_prob(p[9], c[9], [10])
+ */
+
+fn merge_probs_variant_a(p: &mut [u8], c: &[u32], count_sat: u32, update_factor: u32) {
+    p[1] = merge_prob(p[1], c[0], c[1] + c[2], count_sat, update_factor);
+    p[2] = merge_prob(p[2], c[1], c[2], count_sat, update_factor);
+}
+
+fn merge_probs_variant_b(p: &mut [u8], c: &[u32], count_sat: u32, update_factor: u32) {
+    p[0] = merge_prob(p[0], c[0], c[1], count_sat, update_factor);
+}
+
+fn merge_probs_variant_c(p: &mut [u8], c: &[u32]) {
+    p[0] = noncoef_merge_prob(p[0], c[2], c[1] + c[0] + c[3]);
+    p[1] = noncoef_merge_prob(p[1], c[0], c[1] + c[3]);
+    p[2] = noncoef_merge_prob(p[2], c[1], c[3]);
+}
+
+fn merge_probs_variant_d(p: &mut [u8], c: &[u32]) {
+    let mut sum: u32 = c[1..=9].iter().sum();
+
+    p[0] = noncoef_merge_prob(p[0], c[0], sum);
+    sum -= c[9];
+    p[1] = noncoef_merge_prob(p[1], c[9], sum);
+    sum -= c[1];
+    p[2] = noncoef_merge_prob(p[2], c[1], sum);
+    let mut s2 = c[2] + c[4] + c[5];
+    sum -= s2;
+    p[3] = noncoef_merge_prob(p[3], s2, sum);
+    s2 -= c[2];
+    p[4] = noncoef_merge_prob(p[4], c[2], s2);
+    p[5] = noncoef_merge_prob(p[5], c[4], c[5]);
+    sum -= c[3];
+    p[6] = noncoef_merge_prob(p[6], c[3], sum);
+    sum -= c[8];
+    p[7] = noncoef_merge_prob(p[7], c[8], sum);
+    p[8] = noncoef_merge_prob(p[8], c[6], c[7]);
+}
+
+fn merge_probs_variant_e(p: &mut [u8], c: &[u32]) {
+    p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2] + c[3]);
+    p[1] = noncoef_merge_prob(p[1], c[1], c[2] + c[3]);
+    p[2] = noncoef_merge_prob(p[2], c[2], c[3]);
+}
+
+fn merge_probs_variant_f(p: &mut [u8], c: &[u32]) {
+    p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2]);
+    p[1] = noncoef_merge_prob(p[1], c[1], c[2]);
+}
+
+fn merge_probs_variant_g(p: &mut [u8], c: &[u32]) {
+    let mut sum: u32 = c[1..=10].iter().sum();
+    p[0] = noncoef_merge_prob(p[0], c[0], sum);
+    sum -= c[1];
+    p[1] = noncoef_merge_prob(p[1], c[1], sum);
+    sum -= c[2] + c[3];
+    p[2] = noncoef_merge_prob(p[2], c[2] + c[3], sum);
+    p[3] = noncoef_merge_prob(p[3], c[2], c[3]);
+    sum -= c[4] + c[5];
+    p[4] = noncoef_merge_prob(p[4], c[4] + c[5], sum);
+    p[5] = noncoef_merge_prob(p[5], c[4], c[5]);
+    sum -= c[6];
+    p[6] = noncoef_merge_prob(p[6], c[6], sum);
+    p[7] = noncoef_merge_prob(p[7], c[7] + c[8], c[9] + c[10]);
+    p[8] = noncoef_merge_prob(p[8], c[7], c[8]);
+    p[9] = noncoef_merge_prob(p[9], c[9], c[10]);
+}
+
+fn adapt_probs_variant_a_coef(p: &mut [u8], c: &[u32], update_factor: u32) {
+    merge_probs_variant_a(p, c, 24, update_factor);
+}
+
+fn adapt_probs_variant_b_coef(p: &mut [u8], c: &[u32], update_factor: u32) {
+    merge_probs_variant_b(p, c, 24, update_factor);
+}
+
+fn _adapt_coeff(
+    i: usize,
+    j: usize,
+    k: usize,
+    probs: &mut FrameContext,
+    counts: &FrameSymbolCounts<'_>,
+    uf: u32,
+) {
+    for l in 0..probs.coef[0][0][0].len() {
+        for m in 0..BAND_6!(l) {
+            let p = &mut probs.coef[i][j][k][l][m];
+            let counts_more_coefs = [
+                *counts.eob[i][j][k][l][m][1],
+                *counts.eob[i][j][k][l][m][0] - *counts.eob[i][j][k][l][m][1],
+            ];
+
+            adapt_probs_variant_a_coef(p, counts.coeff[i][j][k][l][m], uf);
+            adapt_probs_variant_b_coef(p, &counts_more_coefs, uf);
+        }
+    }
+}
+
+fn _adapt_coef_probs(probs: &mut FrameContext, counts: &mut FrameSymbolCounts<'_>, uf: u32) {
+    for i in 0..probs.coef.len() {
+        for j in 0..probs.coef[0].len() {
+            for k in 0..probs.coef[0][0].len() {
+                _adapt_coeff(i, j, k, probs, counts, uf);
+            }
+        }
+    }
+}
+
+fn adapt_probs_variant_b(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_b(p, c, 20, 128);
+}
+
+fn adapt_probs_variant_c(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_c(p, c);
+}
+
+fn adapt_probs_variant_d(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_d(p, c);
+}
+
+fn adapt_probs_variant_e(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_e(p, c);
+}
+
+fn adapt_probs_variant_f(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_f(p, c);
+}
+
+fn adapt_probs_variant_g(p: &mut [u8], c: &[u32]) {
+    merge_probs_variant_g(p, c);
+}
+
+fn adapt_prob(prob: u8, counts: [u32; 2]) -> u8 {
+    noncoef_merge_prob(prob, counts[0], counts[1])
+}
+
+// The C API for C drivers.
+pub mod c {
+    use super::*;
+    #[no_mangle]
+    /// Counterpart to 6.3 compressed_header(), but parsing has been done in userspace.
+    pub extern "C" fn v4l2_vp9_fw_update_probs_rs(
+        probs: &mut FrameContext,
+        deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr,
+        dec_params: &bindings::v4l2_ctrl_vp9_frame,
+    ) {
+        super::fw_update_probs(probs, deltas, dec_params);
+    }
+
+    #[no_mangle]
+    pub extern "C" fn v4l2_vp9_reset_frame_ctx_rs(
+        dec_params: &bindings::v4l2_ctrl_vp9_frame,
+        frame_context: &mut [FrameContext; 4],
+    ) -> u8 {
+        super::reset_frame_ctx(dec_params, frame_context)
+    }
+
+    #[no_mangle]
+    pub extern "C" fn v4l2_vp9_adapt_coef_probs_rs(
+        probs: &mut FrameContext,
+        counts: &mut FrameSymbolCounts<'_>,
+        use_128: bool,
+        frame_is_intra: bool,
+    ) {
+        super::adapt_coef_probs(probs, counts, use_128, frame_is_intra);
+    }
+
+    #[no_mangle]
+    pub extern "C" fn v4l2_vp9_adapt_noncoef_probs_rs(
+        probs: &mut FrameContext,
+        counts: &mut FrameSymbolCounts<'_>,
+        reference_mode: u8,
+        interpolation_filter: u8,
+        tx_mode: u8,
+        flags: u32,
+    ) {
+        super::adapt_noncoef_probs(
+            probs,
+            counts,
+            reference_mode,
+            interpolation_filter,
+            tx_mode,
+            flags,
+        );
+    }
+
+    #[no_mangle]
+    pub extern "C" fn v4l2_vp9_seg_feat_enabled_rs(
+        feature_enabled: &[u8; 8],
+        feature: u32,
+        segid: u32,
+    ) -> bool {
+        super::seg_feat_enabled(feature_enabled, feature, segid)
+    }
+}
-- 
2.43.0


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

* [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver in Rust
  2024-03-07 19:08 ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec " Daniel Almeida
  2024-03-07 19:08   ` [RFC PATCH v2 1/2] v4l2-core: rewrite the VP9 " Daniel Almeida
@ 2024-03-07 19:08   ` Daniel Almeida
  2024-03-07 20:56     ` Nicolas Dufresne
  2024-03-07 20:04   ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec library " Deborah Brouwer
  2 siblings, 1 reply; 10+ messages in thread
From: Daniel Almeida @ 2024-03-07 19:08 UTC (permalink / raw)
  To: wedsonaf, ojeda, mchehab, hverkuil
  Cc: Daniel Almeida, rust-for-linux, linux-kernel, linux-media, kernel

---
 drivers/staging/media/rkvdec/Kconfig       |   1 +
 drivers/staging/media/rkvdec/Makefile      |   2 +-
 drivers/staging/media/rkvdec/cbindgen.toml |  36 ++
 drivers/staging/media/rkvdec/common.rs     |  19 +
 drivers/staging/media/rkvdec/regs.rs       | 237 ++++++++
 drivers/staging/media/rkvdec/rkvdec-vp9.c  | 585 ++++---------------
 drivers/staging/media/rkvdec/rkvdec_rs.h   | 125 ++++
 drivers/staging/media/rkvdec/rkvdec_rs.rs  |  14 +
 drivers/staging/media/rkvdec/vp9.rs        | 636 +++++++++++++++++++++
 rust/helpers.c                             |   7 +
 10 files changed, 1181 insertions(+), 481 deletions(-)
 create mode 100644 drivers/staging/media/rkvdec/cbindgen.toml
 create mode 100644 drivers/staging/media/rkvdec/common.rs
 create mode 100644 drivers/staging/media/rkvdec/regs.rs
 create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.h
 create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.rs
 create mode 100644 drivers/staging/media/rkvdec/vp9.rs

diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig
index 245dc47082d4..1877b6b0153b 100644
--- a/drivers/staging/media/rkvdec/Kconfig
+++ b/drivers/staging/media/rkvdec/Kconfig
@@ -3,6 +3,7 @@ config VIDEO_ROCKCHIP_VDEC
 	tristate "Rockchip Video Decoder driver"
 	depends on ARCH_ROCKCHIP || COMPILE_TEST
 	depends on VIDEO_DEV
+	depends on RUST
 	select MEDIA_CONTROLLER
 	select VIDEOBUF2_DMA_CONTIG
 	select VIDEOBUF2_VMALLOC
diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile
index cb86b429cfaa..8e04aa7dbf16 100644
--- a/drivers/staging/media/rkvdec/Makefile
+++ b/drivers/staging/media/rkvdec/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o
 
-rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o
+rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o rkvdec_rs.o
diff --git a/drivers/staging/media/rkvdec/cbindgen.toml b/drivers/staging/media/rkvdec/cbindgen.toml
new file mode 100644
index 000000000000..3ca785d26cc8
--- /dev/null
+++ b/drivers/staging/media/rkvdec/cbindgen.toml
@@ -0,0 +1,36 @@
+# Generate the C API with:
+# cbindgen  --lang c  -v --config drivers/staging/media/rkvdec/cbindgen.toml --output drivers/staging/media/rkvdec/rkvdec_rs.h -- drivers/staging/media/rkvdec/rkvdec_rs.rs
+
+language = "C"
+
+# No <stdarg.h>, <stdbool.h>, <stdint.h>, <stdlib.h>, <uchar.h>
+no_includes = true
+style = "tag"
+
+sys_includes = ["media/v4l2-ctrls.h", "media/v4l2-vp9-rs.h", "linux/types.h"]
+autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
+usize_is_size_t = true
+include_guard = "RKVDEC_RS_H"
+
+# Rename everything from bindgen
+# See https://github.com/mozilla/cbindgen/issues/621
+# Also rename our mangled structs into snake_case for the C API
+[export.rename]
+"v4l2_ctrl_vp9_frame" = "struct v4l2_ctrl_vp9_frame"
+"v4l2_vp9_segmentation" = "struct v4l2_vp9_segmentation"
+"v4l2_vp9_loop_filter" = "struct v4l2_vp9_loop_filter"
+"Resolution" = "rkvdec_rs_resolution"
+"Mv" = " rkvdec_rs_vp9_mv"
+"InterFrameProbs" = " rkvdec_rs_vp9_inter_frame_probs"
+"IntraModeProbs" = " rkvdec_rs_vp9_intra_mode_probs"
+"IntraOnlyFrameProbs" = " rkvdec_rs_vp9_intra_only_frame_probs"
+"FrameProbs" = " rkvdec_rs_vp9_frame_probs"
+"HwProbs" = " rkvdec_rs_vp9_probs"
+"DecodedBufferInfo" = "rkvdec_rs_decoded_buffer_info"
+"FrameInfo" = "rkvdec_rs_frame_info"
+"BaseRun" = "rkvdec_rs_base_run"
+"Run" = "rkvdec_rs_run"
+"FrameContext" = "struct v4l2_vp9_frame_context_rs"
+
+[enum]
+prefix_with_name = true
diff --git a/drivers/staging/media/rkvdec/common.rs b/drivers/staging/media/rkvdec/common.rs
new file mode 100644
index 000000000000..0f9f35bc915f
--- /dev/null
+++ b/drivers/staging/media/rkvdec/common.rs
@@ -0,0 +1,19 @@
+#![allow(missing_docs)]
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+use kernel::bindings;
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub(crate) struct Resolution {
+    pub(crate) width: u32,
+    pub(crate) height: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub(crate) struct BaseRun {
+    pub(crate) decoded_resolution: Resolution,
+}
diff --git a/drivers/staging/media/rkvdec/regs.rs b/drivers/staging/media/rkvdec/regs.rs
new file mode 100644
index 000000000000..644f4b07063d
--- /dev/null
+++ b/drivers/staging/media/rkvdec/regs.rs
@@ -0,0 +1,237 @@
+#![allow(dead_code)]
+#![allow(unused_macros)]
+
+pub(crate) const RKVDEC_REG_INTERRUPT: u32 = 0x004;
+pub(crate) const RKVDEC_INTERRUPT_DEC_E: u32 = 1 << 0;
+pub(crate) const RKVDEC_CONFIG_DEC_CLK_GATE_E: u32 = 1 << 1;
+pub(crate) const RKVDEC_E_STRMD_CLKGATE_DIS: u32 = 1 << 2;
+pub(crate) const RKVDEC_TIMEOUT_MODE: u32 = 1 << 3;
+pub(crate) const RKVDEC_IRQ_DIS: u32 = 1 << 4;
+pub(crate) const RKVDEC_TIMEOUT_E: u32 = 1 << 5;
+pub(crate) const RKVDEC_BUF_EMPTY_E: u32 = 1 << 6;
+pub(crate) const RKVDEC_STRM_E_WAITDECFIFO_EMPTY: u32 = 1 << 7;
+pub(crate) const RKVDEC_IRQ: u32 = 1 << 8;
+pub(crate) const RKVDEC_IRQ_RAW: u32 = 1 << 9;
+pub(crate) const RKVDEC_E_REWRITE_VALID: u32 = 1 << 10;
+pub(crate) const RKVDEC_COMMONIRQ_MODE: u32 = 1 << 11;
+pub(crate) const RKVDEC_RDY_STA: u32 = 1 << 12;
+pub(crate) const RKVDEC_BUS_STA: u32 = 1 << 13;
+pub(crate) const RKVDEC_ERR_STA: u32 = 1 << 14;
+pub(crate) const RKVDEC_TIMEOUT_STA: u32 = 1 << 15;
+pub(crate) const RKVDEC_BUF_EMPTY_STA: u32 = 1 << 16;
+pub(crate) const RKVDEC_COLMV_REF_ERR_STA: u32 = 1 << 17;
+pub(crate) const RKVDEC_CABU_END_STA: u32 = 1 << 18;
+pub(crate) const RKVDEC_H264ORVP9_ERR_MODE: u32 = 1 << 19;
+pub(crate) const RKVDEC_SOFTRST_EN_P: u32 = 1 << 20;
+pub(crate) const RKVDEC_FORCE_SOFTRESET_VALID: u32 = 1 << 21;
+pub(crate) const RKVDEC_SOFTRESET_RDY: u32 = 1 << 22;
+pub(crate) const RKVDEC_REG_SYSCTRL: u32 = 0x008;
+pub(crate) const RKVDEC_IN_ENDIAN: u32 = 1 << 0;
+pub(crate) const RKVDEC_IN_SWAP32_E: u32 = 1 << 1;
+pub(crate) const RKVDEC_IN_SWAP64_E: u32 = 1 << 2;
+pub(crate) const RKVDEC_STR_ENDIAN: u32 = 1 << 3;
+pub(crate) const RKVDEC_STR_SWAP32_E: u32 = 1 << 4;
+pub(crate) const RKVDEC_STR_SWAP64_E: u32 = 1 << 5;
+pub(crate) const RKVDEC_OUT_ENDIAN: u32 = 1 << 6;
+pub(crate) const RKVDEC_OUT_SWAP32_E: u32 = 1 << 7;
+pub(crate) const RKVDEC_OUT_CBCR_SWAP: u32 = 1 << 8;
+pub(crate) const RKVDEC_RLC_MODE_DIRECT_WRITE: u32 = 1 << 10;
+pub(crate) const RKVDEC_RLC_MODE: u32 = 1 << 11;
+macro_rules! RKVDEC_STRM_START_BIT { ($x:expr) => { ((($x) & 0x7f) << 12) } }
+macro_rules! RKVDEC_MODE { ($x:expr) => { ((($x) & 0x03) << 20) } }
+pub(crate) const RKVDEC_MODE_H264: u32 = 1;
+pub(crate) const RKVDEC_MODE_VP9: u32 = 2;
+pub(crate) const RKVDEC_RPS_MODE: u32 = 1 << 24;
+pub(crate) const RKVDEC_STRM_MODE: u32 = 1 << 25;
+pub(crate) const RKVDEC_H264_STRM_LASTPKT: u32 = 1 << 26;
+pub(crate) const RKVDEC_H264_FIRSTSLICE_FLAG: u32 = 1 << 27;
+pub(crate) const RKVDEC_H264_FRAME_ORSLICE: u32 = 1 << 28;
+pub(crate) const RKVDEC_BUSPR_SLOT_DIS: u32 = 1 << 29;
+pub(crate) const RKVDEC_REG_PICPAR: u32 = 0x00C;
+macro_rules! RKVDEC_Y_HOR_VIRSTRIDE { ($x:expr) => { (($x) & 0x1ff) } }
+pub(crate) const RKVDEC_SLICE_NUM_HIGHBIT: u32 = 1 << 11;
+macro_rules! RKVDEC_UV_HOR_VIRSTRIDE { ($x:expr) => { ((($x) & 0x1ff) << 12) } }
+macro_rules! RKVDEC_SLICE_NUM_LOWBITS { ($x:expr) => { ((($x) & 0x7ff) << 21) } }
+pub(crate) const RKVDEC_REG_STRM_RLC_BASE: u32 = 0x010;
+pub(crate) const RKVDEC_REG_STRM_LEN: u32 = 0x014;
+macro_rules! RKVDEC_STRM_LEN { ($x:expr) => { (($x) & 0x7ffffff) } }
+pub(crate) const RKVDEC_REG_CABACTBL_PROB_BASE: u32 = 0x018;
+pub(crate) const RKVDEC_REG_DECOUT_BASE: u32 = 0x01C;
+pub(crate) const RKVDEC_REG_Y_VIRSTRIDE: u32 = 0x020;
+macro_rules! RKVDEC_Y_VIRSTRIDE { ($x:expr) => { (($x) & 0xfffff) } }
+pub(crate) const RKVDEC_REG_YUV_VIRSTRIDE: u32 = 0x024;
+macro_rules! RKVDEC_YUV_VIRSTRIDE { ($x:expr) => { (($x) & 0x1fffff) } }
+macro_rules! RKVDEC_REG_H264_BASE_REFER { ($x:expr) => { ((($i) * 0x04) + 0x028) } }
+pub(crate) const RKVDEC_REG_H264_BASE_REFER15: u32 = 0x0C0;
+pub(crate) const RKVDEC_FIELD_REF: u32 = 1 << 0;
+pub(crate) const RKVDEC_TOPFIELD_USED_REF: u32 = 1 << 1;
+pub(crate) const RKVDEC_BOTFIELD_USED_REF: u32 = 1 << 2;
+pub(crate) const RKVDEC_COLMV_USED_FLAG_REF: u32 = 1 << 3;
+pub(crate) const RKVDEC_REG_VP9_LAST_FRAME_BASE: u32 = 0x02c;
+pub(crate) const RKVDEC_REG_VP9_GOLDEN_FRAME_BASE: u32 = 0x030;
+pub(crate) const RKVDEC_REG_VP9_ALTREF_FRAME_BASE: u32 = 0x034;
+pub(crate) const RKVDEC_REG_VP9_CPRHEADER_OFFSET: u32 = 0x028;
+macro_rules! RKVDEC_VP9_CPRHEADER_OFFSET { ($x:expr) => { (($x) & 0xffff) } }
+pub(crate) const RKVDEC_REG_VP9_REFERLAST_BASE: u32 = 0x02C;
+pub(crate) const RKVDEC_REG_VP9_REFERGOLDEN_BASE: u32 = 0x030;
+pub(crate) const RKVDEC_REG_VP9_REFERALFTER_BASE: u32 = 0x034;
+pub(crate) const RKVDEC_REG_VP9COUNT_BASE: u32 = 0x038;
+pub(crate) const RKVDEC_VP9COUNT_UPDATE_EN: u32 = 1 << 0;
+pub(crate) const RKVDEC_REG_VP9_SEGIDLAST_BASE: u32 = 0x03C;
+pub(crate) const RKVDEC_REG_VP9_SEGIDCUR_BASE: u32 = 0x040;
+macro_rules! RKVDEC_REG_VP9_FRAME_SIZE { ($x:expr) => { (($x) * 0x04 + 0x044) } }
+macro_rules! RKVDEC_VP9_FRAMEWIDTH { ($x:expr) => { ((($x) & 0xffff) << 0) } }
+macro_rules! RKVDEC_VP9_FRAMEHEIGHT { ($x:expr) => { ((($x) & 0xffff) << 16) } }
+macro_rules! RKVDEC_VP9_SEGID_GRP { ($x:expr) => { (($x) * 0x04 + 0x050) } }
+macro_rules! RKVDEC_SEGID_ABS_DELTA { ($x:expr) => { (($x) & 0x1) } }
+macro_rules! RKVDEC_SEGID_FRAME_QP_DELTA_EN { ($x:expr) => { ((($x) & 0x1) << 1) } }
+macro_rules! RKVDEC_SEGID_FRAME_QP_DELTA { ($x:expr) => { ((($x) & 0x1ff) << 2) } }
+macro_rules! RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN { ($x:expr) => { ((($x) & 0x1) << 11) } }
+macro_rules! RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE { ($x:expr) => { ((($x) & 0x7f) << 12) } }
+macro_rules! RKVDEC_SEGID_REFERINFO_EN { ($x:expr) => { ((($x) & 0x1) << 19) } }
+macro_rules! RKVDEC_SEGID_REFERINFO { ($x:expr) => { ((($x) & 0x03) << 20) } }
+macro_rules! RKVDEC_SEGID_FRAME_SKIP_EN { ($x:expr) => { ((($x) & 0x1) << 22) } }
+pub(crate) const RKVDEC_VP9_CPRHEADER_CONFIG: u32 = 0x070;
+macro_rules! RKVDEC_VP9_TX_MODE { ($x:expr) => { (($x) & 0x07) } }
+macro_rules! RKVDEC_VP9_FRAME_REF_MODE { ($x:expr) => { ((($x) & 0x03) << 3) } }
+macro_rules! RKVDEC_VP9_REF_SCALE { ($x:expr) => { (($x) * 0x04 + 0x074) } }
+macro_rules! RKVDEC_VP9_REF_HOR_SCALE { ($x:expr) => { (($x) & 0xffff) } }
+macro_rules! RKVDEC_VP9_REF_VER_SCALE { ($x:expr) => { ((($x) & 0xffff) << 16) } }
+pub(crate) const RKVDEC_VP9_REF_DELTAS_LASTFRAME: u32 = 0x080;
+macro_rules! RKVDEC_REF_DELTAS_LASTFRAME { ($pos:expr, $val:expr) => { ((($val) & 0x7f) << (($pos) * 7)) } }
+pub(crate) const RKVDEC_VP9_INFO_LASTFRAME: u32 = 0x084;
+macro_rules! RKVDEC_MODE_DELTAS_LASTFRAME { ($pos:expr, $val:expr) => { ((($val) & 0x7f) << (($pos) * 7)) } }
+pub(crate) const RKVDEC_SEG_EN_LASTFRAME: u32 = 1 << 16;
+pub(crate) const RKVDEC_LAST_SHOW_FRAME: u32 = 1 << 17;
+pub(crate) const RKVDEC_LAST_INTRA_ONLY: u32 = 1 << 18;
+pub(crate) const RKVDEC_LAST_WIDHHEIGHT_EQCUR: u32 = 1 << 19;
+macro_rules! RKVDEC_COLOR_SPACE_LASTKEYFRAME { ($x:expr) => { ((($x) & 0x07) << 20) } }
+pub(crate) const RKVDEC_VP9_INTERCMD_BASE: u32 = 0x088;
+pub(crate) const RKVDEC_VP9_INTERCMD_NUM: u32 = 0x08C;
+macro_rules! RKVDEC_INTERCMD_NUM { ($x:expr) => { (($x) & 0xffffff) } }
+pub(crate) const RKVDEC_VP9_LASTTILE_SIZE: u32 = 0x090;
+macro_rules! RKVDEC_LASTTILE_SIZE { ($x:expr) => { (($x) & 0xffffff) } }
+macro_rules! RKVDEC_VP9_HOR_VIRSTRIDE { ($i:expr) => { (($i) * 0x04 + 0x094) } }
+macro_rules! RKVDEC_HOR_Y_VIRSTRIDE { ($x:expr) => { (($x) & 0x1ff) } }
+macro_rules! RKVDEC_HOR_UV_VIRSTRIDE { ($x:expr) => { ((($x) & 0x1ff) << 16) } }
+macro_rules! RKVDEC_REG_H264_POC_REFER0 { ($i:expr) => { ((($i) * 0x04) + 0x064) } }
+macro_rules! RKVDEC_REG_H264_POC_REFER1 { ($i:expr) => { ((($i) * 0x04) + 0x0C4) } }
+macro_rules! RKVDEC_REG_H264_POC_REFER2 { ($i:expr) => { ((($i) * 0x04) + 0x120) } }
+macro_rules! RKVDEC_POC_REFER { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_CUR_POC0: u32 = 0x0A0;
+pub(crate) const RKVDEC_REG_CUR_POC1: u32 = 0x128;
+macro_rules! RKVDEC_CUR_POC { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_RLCWRITE_BASE: u32 = 0x0A4;
+pub(crate) const RKVDEC_REG_PPS_BASE: u32 = 0x0A8;
+pub(crate) const RKVDEC_REG_RPS_BASE: u32 = 0x0AC;
+pub(crate) const RKVDEC_REG_STRMD_ERR_EN: u32 = 0x0B0;
+macro_rules! RKVDEC_STRMD_ERR_EN { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_STRMD_ERR_STA: u32 = 0x0B4;
+macro_rules! RKVDEC_STRMD_ERR_STA { ($x:expr) => { (($x) & 0xfffffff) } }
+macro_rules! RKVDEC_COLMV_ERR_REF_PICIDX { ($x:expr) => { ((($x) & 0x0f) << 28) } }
+pub(crate) const RKVDEC_REG_STRMD_ERR_CTU: u32 = 0x0B8;
+macro_rules! RKVDEC_STRMD_ERR_CTU { ($x:expr) => { (($x) & 0xff) } }
+macro_rules! RKVDEC_STRMD_ERR_CTU_YOFFSET { ($x:expr) => { ((($x) & 0xff) << 8) } }
+macro_rules! RKVDEC_STRMFIFO_SPACE2FULL { ($x:expr) => { ((($x) & 0x7f) << 16) } }
+pub(crate) const RKVDEC_VP9_ERR_EN_CTU0: u32 = 1 << 24;
+pub(crate) const RKVDEC_REG_SAO_CTU_POS: u32 = 0x0BC;
+macro_rules! RKVDEC_SAOWR_XOFFSET { ($x:expr) => { (($x) & 0x1ff) } }
+macro_rules! RKVDEC_SAOWR_YOFFSET { ($x:expr) => { ((($x) & 0x3ff) << 16) } }
+pub(crate) const RKVDEC_VP9_LAST_FRAME_YSTRIDE: u32 = 0x0C0;
+pub(crate) const RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE: u32 = 0x0C4;
+pub(crate) const RKVDEC_VP9_ALTREF_FRAME_YSTRIDE: u32 = 0x0C8;
+macro_rules! RKVDEC_VP9_REF_YSTRIDE { ($x:expr) => { ((($x) & 0xfffff) << 0) } }
+pub(crate) const RKVDEC_VP9_LAST_FRAME_YUVSTRIDE: u32 = 0x0CC;
+macro_rules! RKVDEC_VP9_REF_YUVSTRIDE { ($x:expr) => { ((($x) & 0x1fffff) << 0) } }
+pub(crate) const RKVDEC_VP9_REF_COLMV_BASE: u32 = 0x0D0;
+pub(crate) const RKVDEC_REG_PERFORMANCE_CYCLE: u32 = 0x100;
+macro_rules! RKVDEC_PERFORMANCE_CYCLE { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_AXI_DDR_RDATA: u32 = 0x104;
+macro_rules! RKVDEC_AXI_DDR_RDATA { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_AXI_DDR_WDATA: u32 = 0x108;
+macro_rules! RKVDEC_AXI_DDR_WDATA { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_FPGADEBUG_RESET: u32 = 0x10C;
+pub(crate) const RKVDEC_BUSIFD_RESETN: u32 = 1 << 0;
+pub(crate) const RKVDEC_CABAC_RESETN: u32 = 1 << 1;
+pub(crate) const RKVDEC_DEC_CTRL_RESETN: u32 = 1 << 2;
+pub(crate) const RKVDEC_TRANSD_RESETN: u32 = 1 << 3;
+pub(crate) const RKVDEC_INTRA_RESETN: u32 = 1 << 4;
+pub(crate) const RKVDEC_INTER_RESETN: u32 = 1 << 5;
+pub(crate) const RKVDEC_RECON_RESETN: u32 = 1 << 6;
+pub(crate) const RKVDEC_FILER_RESETN: u32 = 1 << 7;
+pub(crate) const RKVDEC_REG_PERFORMANCE_SEL: u32 = 0x110;
+macro_rules! RKVDEC_PERF_SEL_CNT0 { ($x:expr) => { (($x) & 0x3f) } }
+macro_rules! RKVDEC_PERF_SEL_CNT1 { ($x:expr) => { ((($x) & 0x3f) << 8) } }
+macro_rules! RKVDEC_PERF_SEL_CNT2 { ($x:expr) => { ((($x) & 0x3f) << 16) } }
+macro_rules! RKVDEC_REG_PERFORMANCE_CNT { ($i:expr) => { (($i) * 0x04 + 0x114) } }
+macro_rules! RKVDEC_PERF_CNT { ($x:expr) => { (($x) & 0xffffffff) } }
+pub(crate) const RKVDEC_REG_H264_ERRINFO_BASE: u32 = 0x12C;
+pub(crate) const RKVDEC_REG_H264_ERRINFO_NUM: u32 = 0x130;
+macro_rules! RKVDEC_SLICEDEC_NUM { ($x:expr) => { (($x) & 0x3fff) } }
+pub(crate) const RKVDEC_STRMD_DECT_ERR_FLAG: u32 = 1 << 15;
+macro_rules! RKVDEC_ERR_PKT_NUM { ($x:expr) => { ((($x) & 0x3fff) << 16) } }
+pub(crate) const RKVDEC_REG_H264_ERR_E: u32 = 0x134;
+macro_rules! RKVDEC_H264_ERR_EN_HIGHBITS { ($x:expr) => { (($x) & 0x3fffffff) } }
+pub(crate) const RKVDEC_REG_PREF_LUMA_CACHE_COMMAND: u32 = 0x410;
+pub(crate) const RKVDEC_REG_PREF_CHR_CACHE_COMMAND: u32 = 0x450;
+pub(crate) use RKVDEC_STRM_START_BIT;
+pub(crate) use RKVDEC_MODE;
+pub(crate) use RKVDEC_Y_HOR_VIRSTRIDE;
+pub(crate) use RKVDEC_UV_HOR_VIRSTRIDE;
+pub(crate) use RKVDEC_SLICE_NUM_LOWBITS;
+pub(crate) use RKVDEC_STRM_LEN;
+pub(crate) use RKVDEC_Y_VIRSTRIDE;
+pub(crate) use RKVDEC_YUV_VIRSTRIDE;
+pub(crate) use RKVDEC_REG_H264_BASE_REFER;
+pub(crate) use RKVDEC_VP9_CPRHEADER_OFFSET;
+pub(crate) use RKVDEC_REG_VP9_FRAME_SIZE;
+pub(crate) use RKVDEC_VP9_FRAMEWIDTH;
+pub(crate) use RKVDEC_VP9_FRAMEHEIGHT;
+pub(crate) use RKVDEC_VP9_SEGID_GRP;
+pub(crate) use RKVDEC_SEGID_ABS_DELTA;
+pub(crate) use RKVDEC_SEGID_FRAME_QP_DELTA_EN;
+pub(crate) use RKVDEC_SEGID_FRAME_QP_DELTA;
+pub(crate) use RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN;
+pub(crate) use RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE;
+pub(crate) use RKVDEC_SEGID_REFERINFO_EN;
+pub(crate) use RKVDEC_SEGID_REFERINFO;
+pub(crate) use RKVDEC_SEGID_FRAME_SKIP_EN;
+pub(crate) use RKVDEC_VP9_TX_MODE;
+pub(crate) use RKVDEC_VP9_FRAME_REF_MODE;
+pub(crate) use RKVDEC_VP9_REF_SCALE;
+pub(crate) use RKVDEC_VP9_REF_HOR_SCALE;
+pub(crate) use RKVDEC_VP9_REF_VER_SCALE;
+pub(crate) use RKVDEC_REF_DELTAS_LASTFRAME;
+pub(crate) use RKVDEC_MODE_DELTAS_LASTFRAME;
+pub(crate) use RKVDEC_COLOR_SPACE_LASTKEYFRAME;
+pub(crate) use RKVDEC_INTERCMD_NUM;
+pub(crate) use RKVDEC_LASTTILE_SIZE;
+pub(crate) use RKVDEC_VP9_HOR_VIRSTRIDE;
+pub(crate) use RKVDEC_HOR_Y_VIRSTRIDE;
+pub(crate) use RKVDEC_HOR_UV_VIRSTRIDE;
+pub(crate) use RKVDEC_REG_H264_POC_REFER0;
+pub(crate) use RKVDEC_REG_H264_POC_REFER1;
+pub(crate) use RKVDEC_REG_H264_POC_REFER2;
+pub(crate) use RKVDEC_POC_REFER;
+pub(crate) use RKVDEC_CUR_POC;
+pub(crate) use RKVDEC_STRMD_ERR_EN;
+pub(crate) use RKVDEC_STRMD_ERR_STA;
+pub(crate) use RKVDEC_COLMV_ERR_REF_PICIDX;
+pub(crate) use RKVDEC_STRMD_ERR_CTU;
+pub(crate) use RKVDEC_STRMD_ERR_CTU_YOFFSET;
+pub(crate) use RKVDEC_STRMFIFO_SPACE2FULL;
+pub(crate) use RKVDEC_SAOWR_XOFFSET;
+pub(crate) use RKVDEC_SAOWR_YOFFSET;
+pub(crate) use RKVDEC_VP9_REF_YSTRIDE;
+pub(crate) use RKVDEC_VP9_REF_YUVSTRIDE;
+pub(crate) use RKVDEC_PERFORMANCE_CYCLE;
+pub(crate) use RKVDEC_AXI_DDR_RDATA;
+pub(crate) use RKVDEC_AXI_DDR_WDATA;
+pub(crate) use RKVDEC_PERF_SEL_CNT0;
+pub(crate) use RKVDEC_PERF_SEL_CNT1;
+pub(crate) use RKVDEC_PERF_SEL_CNT2;
+pub(crate) use RKVDEC_REG_PERFORMANCE_CNT;
+pub(crate) use RKVDEC_PERF_CNT;
+pub(crate) use RKVDEC_SLICEDEC_NUM;
+pub(crate) use RKVDEC_ERR_PKT_NUM;
+pub(crate) use RKVDEC_H264_ERR_EN_HIGHBITS;
\ No newline at end of file
diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c
index 86c6903d11ab..5af5a7fdcde2 100644
--- a/drivers/staging/media/rkvdec/rkvdec-vp9.c
+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c
@@ -23,74 +23,15 @@
 
 #include "rkvdec.h"
 #include "rkvdec-regs.h"
+#include "rkvdec_rs.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;
+	struct rkvdec_rs_vp9_probs probs;
 	u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE];
 };
 
@@ -165,188 +106,6 @@ struct rkvdec_vp9_ctx {
 	struct rkvdec_vp9_frame_info last;
 };
 
-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)
-{
-	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_rs *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_rs); 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_rs[0]); j++) {
-			for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0][0]);
-			     k++) {
-				u8 val = v4l2_vp9_kf_y_mode_prob_rs[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_rs); ++i) {
-		const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob_rs;
-
-		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_rs *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_rs *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_rs : 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);
-}
-
 struct rkvdec_vp9_ref_reg {
 	u32 reg_frm_size;
 	u32 reg_hor_stride;
@@ -355,30 +114,6 @@ struct rkvdec_vp9_ref_reg {
 	u32 reg_ref_base;
 };
 
-static struct rkvdec_vp9_ref_reg ref_regs[] = {
-	{
-		.reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0),
-		.reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0),
-		.reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE,
-		.reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE,
-		.reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE,
-	},
-	{
-		.reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1),
-		.reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1),
-		.reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE,
-		.reg_yuv_stride = 0,
-		.reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE,
-	},
-	{
-		.reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2),
-		.reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2),
-		.reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE,
-		.reg_yuv_stride = 0,
-		.reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE,
-	}
-};
-
 static struct rkvdec_decoded_buffer *
 get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
 {
@@ -409,84 +144,6 @@ static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf)
 	       yuv_len;
 }
 
-static void config_ref_registers(struct rkvdec_ctx *ctx,
-				 const struct rkvdec_vp9_run *run,
-				 struct rkvdec_decoded_buffer *ref_buf,
-				 struct rkvdec_vp9_ref_reg *ref_reg)
-{
-	unsigned int aligned_pitch, aligned_height, y_len, yuv_len;
-	struct rkvdec_dev *rkvdec = ctx->dev;
-
-	aligned_height = round_up(ref_buf->vp9.height, 64);
-	writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(ref_buf->vp9.width) |
-		       RKVDEC_VP9_FRAMEHEIGHT(ref_buf->vp9.height),
-		       rkvdec->regs + ref_reg->reg_frm_size);
-
-	writel_relaxed(vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0),
-		       rkvdec->regs + ref_reg->reg_ref_base);
-
-	if (&ref_buf->base.vb == run->base.bufs.dst)
-		return;
-
-	aligned_pitch = round_up(ref_buf->vp9.width * ref_buf->vp9.bit_depth, 512) / 8;
-	y_len = aligned_height * aligned_pitch;
-	yuv_len = (y_len * 3) / 2;
-
-	writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) |
-		       RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16),
-		       rkvdec->regs + ref_reg->reg_hor_stride);
-	writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16),
-		       rkvdec->regs + ref_reg->reg_y_stride);
-
-	if (!ref_reg->reg_yuv_stride)
-		return;
-
-	writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16),
-		       rkvdec->regs + ref_reg->reg_yuv_stride);
-}
-
-static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
-{
-	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
-	struct v4l2_vp9_segmentation *seg;
-	struct rkvdec_dev *rkvdec = ctx->dev;
-	s16 feature_val;
-	int feature_id;
-	u32 val = 0;
-
-	seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg;
-	feature_id = V4L2_VP9_SEG_LVL_ALT_Q;
-	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) {
-		feature_val = seg->feature_data[segid][feature_id];
-		val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) |
-		       RKVDEC_SEGID_FRAME_QP_DELTA(feature_val);
-	}
-
-	feature_id = V4L2_VP9_SEG_LVL_ALT_L;
-	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) {
-		feature_val = seg->feature_data[segid][feature_id];
-		val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) |
-		       RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val);
-	}
-
-	feature_id = V4L2_VP9_SEG_LVL_REF_FRAME;
-	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) {
-		feature_val = seg->feature_data[segid][feature_id];
-		val |= RKVDEC_SEGID_REFERINFO_EN(1) |
-		       RKVDEC_SEGID_REFERINFO(feature_val);
-	}
-
-	feature_id = V4L2_VP9_SEG_LVL_SKIP;
-	if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid))
-		val |= RKVDEC_SEGID_FRAME_SKIP_EN(1);
-
-	if (!segid &&
-	    (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE))
-		val |= RKVDEC_SEGID_ABS_DELTA(1);
-
-	writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid));
-}
-
 static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
 				const struct v4l2_ctrl_vp9_frame *dec_params)
 {
@@ -516,17 +173,11 @@ static void update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx)
 static void config_registers(struct rkvdec_ctx *ctx,
 			     const struct rkvdec_vp9_run *run)
 {
-	unsigned int y_len, uv_len, yuv_len, bit_depth, 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;
-	u32 val, last_frame_info = 0;
-	const struct v4l2_vp9_segmentation *seg;
-	struct rkvdec_dev *rkvdec = ctx->dev;
-	dma_addr_t addr;
 	bool intra_only;
-	unsigned int i;
 
 	dec_params = run->decode_params;
 	dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf);
@@ -541,36 +192,17 @@ static void config_registers(struct rkvdec_ctx *ctx,
 
 	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));
 
-	writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9),
-		       rkvdec->regs + RKVDEC_REG_SYSCTRL);
-
-	bit_depth = dec_params->bit_depth;
-	aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64);
-
-	aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width *
-				 bit_depth,
-				 512) / 8;
-	y_len = aligned_height * aligned_pitch;
-	uv_len = y_len / 2;
-	yuv_len = y_len + uv_len;
-
-	writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) |
-		       RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16),
-		       rkvdec->regs + RKVDEC_REG_PICPAR);
-	writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16),
-		       rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
-	writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16),
-		       rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
-
-	stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0);
-	writel_relaxed(RKVDEC_STRM_LEN(stream_len),
-		       rkvdec->regs + RKVDEC_REG_STRM_LEN);
+	if (!intra_only &&
+	    !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
+	    vp9_ctx->last.valid)
+		mv_ref = last;
+	else
+		mv_ref = dst;
 
 	/*
 	 * Reset count buffer, because decoder only output intra related syntax
@@ -583,114 +215,110 @@ static void config_registers(struct rkvdec_ctx *ctx,
 	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)))
+	    (!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) ||
+	     (dec_params->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], &ref_regs[i]);
-
-	for (i = 0; i < 8; i++)
-		config_seg_registers(ctx, i);
-
-	writel_relaxed(RKVDEC_VP9_TX_MODE(vp9_ctx->cur.tx_mode) |
-		       RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode),
-		       rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG);
-
-	if (!intra_only) {
-		const struct v4l2_vp9_loop_filter *lf;
-		s8 delta;
-
-		if (vp9_ctx->last.valid)
-			lf = &vp9_ctx->last.lf;
-		else
-			lf = &vp9_ctx->cur.lf;
-
-		val = 0;
-		for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) {
-			delta = lf->ref_deltas[i];
-			val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta);
-		}
-
-		writel_relaxed(val,
-			       rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME);
-
-		for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) {
-			delta = lf->mode_deltas[i];
-			last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i,
-									delta);
-		}
-	}
-
-	if (vp9_ctx->last.valid && !intra_only &&
-	    vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)
-		last_frame_info |= RKVDEC_SEG_EN_LASTFRAME;
-
-	if (vp9_ctx->last.valid &&
-	    vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME)
-		last_frame_info |= RKVDEC_LAST_SHOW_FRAME;
-
-	if (vp9_ctx->last.valid &&
-	    vp9_ctx->last.flags &
-	    (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY))
-		last_frame_info |= RKVDEC_LAST_INTRA_ONLY;
-
-	if (vp9_ctx->last.valid &&
-	    last->vp9.width == dst->vp9.width &&
-	    last->vp9.height == dst->vp9.height)
-		last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR;
-
-	writel_relaxed(last_frame_info,
-		       rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME);
-
-	writel_relaxed(stream_len - dec_params->compressed_header_size -
-		       dec_params->uncompressed_header_size,
-		       rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE);
-
-	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;
-		writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) |
-			       RKVDEC_VP9_REF_VER_SCALE(vscale),
-			       rkvdec->regs + RKVDEC_VP9_REF_SCALE(i));
-	}
-
-	addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0);
-	writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
-	addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0);
-	writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
-	writel_relaxed(vp9_ctx->priv_tbl.dma +
-		       offsetof(struct rkvdec_vp9_priv_tbl, probs),
-		       rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
-	writel_relaxed(vp9_ctx->count_tbl.dma,
-		       rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE);
-
-	writel_relaxed(vp9_ctx->priv_tbl.dma +
+	/* pack everything that Rust needs in order to run */
+	struct rkvdec_rs_run rkvdec_rs_run = {
+		.base = {
+			{
+				.width = ctx->decoded_fmt.fmt.pix_mp.width,
+				.height = ctx->decoded_fmt.fmt.pix_mp.height,
+			}
+		},
+		.decode_params = dec_params,
+		.hw_probs = &((struct rkvdec_vp9_priv_tbl *)vp9_ctx->priv_tbl.cpu)->probs,
+		.probability_tables = &vp9_ctx->probability_tables,
+		.src_address = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0),
+		.probs_address = vp9_ctx->priv_tbl.dma + offsetof(struct rkvdec_vp9_priv_tbl, probs),
+		.count_base_address = vp9_ctx->count_tbl.dma,
+		.segid_cur_base_address = vp9_ctx->priv_tbl.dma +
 		       offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
 		       (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid),
-		       rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE);
-	writel_relaxed(vp9_ctx->priv_tbl.dma +
+		.segid_last_base_address = vp9_ctx->priv_tbl.dma +
 		       offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
 		       (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)),
-		       rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE);
-
-	if (!intra_only &&
-	    !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
-	    vp9_ctx->last.valid)
-		mv_ref = last;
-	else
-		mv_ref = dst;
-
-	writel_relaxed(get_mv_base_addr(mv_ref),
-		       rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE);
+		.motion_vectors_base_address = get_mv_base_addr(mv_ref),
+		.dst = {
+			.resolution = {
+				.width = dst->vp9.width,
+				.height = dst->vp9.height,
+			},
+			.bit_depth = dst->vp9.bit_depth,
+			.same_as_dst = true,
+			.dma_address = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0),
+		},
+		.ref_bufs = {
+			[0] = {
+				{
+					.width = ref_bufs[0]->vp9.width,
+					.height = ref_bufs[0]->vp9.height,
+
+				},
+				.bit_depth = ref_bufs[0]->vp9.bit_depth,
+				.same_as_dst = (&ref_bufs[0]->base.vb == run->base.bufs.dst),
+				.dma_address = vb2_dma_contig_plane_dma_addr(&ref_bufs[0]->base.vb.vb2_buf, 0),
+			},
+			[1] = {
+				{
+					.width = ref_bufs[1]->vp9.width,
+					.height = ref_bufs[1]->vp9.height,
+
+				},
+				.bit_depth = ref_bufs[1]->vp9.bit_depth,
+				.same_as_dst = (&ref_bufs[1]->base.vb == run->base.bufs.dst),
+				.dma_address = vb2_dma_contig_plane_dma_addr(&ref_bufs[1]->base.vb.vb2_buf, 0),
+			},
+			[2] = {
+				{
+					.width = ref_bufs[2]->vp9.width,
+					.height = ref_bufs[2]->vp9.height,
+
+				},
+				.bit_depth = ref_bufs[2]->vp9.bit_depth,
+				.same_as_dst = (&ref_bufs[2]->base.vb == run->base.bufs.dst),
+				.dma_address = vb2_dma_contig_plane_dma_addr(&ref_bufs[2]->base.vb.vb2_buf, 0),
+			}
+		},
+		.last = {
+			.resolution = {
+				.width = last->vp9.width,
+				.height = last->vp9.height,
+			},
+			.bit_depth = last->vp9.bit_depth,
+			.same_as_dst = (&last->base.vb == run->base.bufs.dst),
+			.dma_address = vb2_dma_contig_plane_dma_addr(&last->base.vb.vb2_buf, 0),
+		},
+
+		.stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0),
+		.cur_frame_info = {
+			.valid = vp9_ctx->cur.valid,
+			.frame_context_idx = vp9_ctx->cur.frame_context_idx,
+			.reference_mode = vp9_ctx->cur.reference_mode,
+			.tx_mode = vp9_ctx->cur.tx_mode,
+			.interpolation_filter = vp9_ctx->cur.interpolation_filter,
+			.flags = vp9_ctx->cur.flags,
+			.timestamp = vp9_ctx->cur.timestamp,
+			.seg = vp9_ctx->cur.seg,
+			.lf = vp9_ctx->cur.lf,
+		},
+		.last_frame_info = {
+			.valid = vp9_ctx->last.valid,
+			.frame_context_idx = vp9_ctx->last.frame_context_idx,
+			.reference_mode = vp9_ctx->last.reference_mode,
+			.tx_mode = vp9_ctx->last.tx_mode,
+			.interpolation_filter = vp9_ctx->last.interpolation_filter,
+			.flags = vp9_ctx->last.flags,
+			.timestamp = vp9_ctx->last.timestamp,
+			.seg = vp9_ctx->last.seg,
+			.lf = vp9_ctx->last.lf,
+		},
+		.regs = ctx->dev->regs,
+	};
 
-	writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width |
-		       (ctx->decoded_fmt.fmt.pix_mp.height << 16),
-		       rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE);
+	rkvdec_rs_vp9_init_probs(&rkvdec_rs_run);
+	rkvdec_rs_vp9_config_registers(&rkvdec_rs_run);
 }
 
 static int validate_dec_params(struct rkvdec_ctx *ctx,
@@ -810,9 +438,6 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
 		return ret;
 	}
 
-	/* Prepare probs. */
-	init_probs(ctx, &run);
-
 	/* Configure hardware registers. */
 	config_registers(ctx, &run);
 
diff --git a/drivers/staging/media/rkvdec/rkvdec_rs.h b/drivers/staging/media/rkvdec/rkvdec_rs.h
new file mode 100644
index 000000000000..207d0020546c
--- /dev/null
+++ b/drivers/staging/media/rkvdec/rkvdec_rs.h
@@ -0,0 +1,125 @@
+#ifndef RKVDEC_RS_H
+#define RKVDEC_RS_H
+
+/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-vp9-rs.h>
+#include <linux/types.h>
+
+struct rkvdec_rs_resolution {
+  uint32_t width;
+  uint32_t height;
+};
+
+struct rkvdec_rs_base_run {
+  struct rkvdec_rs_resolution decoded_resolution;
+};
+
+struct  rkvdec_rs_vp9_mv {
+  uint8_t joint[3];
+  uint8_t sign[2];
+  uint8_t classes[2][10];
+  uint8_t class0_bit[2];
+  uint8_t bits[2][10];
+  uint8_t class0_fr[2][2][3];
+  uint8_t fr[2][3];
+  uint8_t class0_hp[2];
+  uint8_t hp[2];
+};
+
+struct  rkvdec_rs_vp9_inter_frame_probs {
+  uint8_t y_mode[4][9];
+  uint8_t comp_mode[5];
+  uint8_t comp_ref[5];
+  uint8_t single_ref[5][2];
+  uint8_t inter_mode[7][3];
+  uint8_t interp_filter[4][2];
+  uint8_t padding0[11];
+  uint8_t coef[2][4][2][128];
+  uint8_t uv_mode_0_2[3][9];
+  uint8_t padding1[5];
+  uint8_t uv_mode_3_5[3][9];
+  uint8_t padding2[5];
+  uint8_t uv_mode_6_8[3][9];
+  uint8_t padding3[5];
+  uint8_t uv_mode_9[9];
+  uint8_t padding4[7];
+  uint8_t padding5[16];
+  struct  rkvdec_rs_vp9_mv mv;
+};
+
+struct  rkvdec_rs_vp9_intra_mode_probs {
+  uint8_t y_mode[105];
+  uint8_t uv_mode[23];
+};
+
+struct  rkvdec_rs_vp9_intra_only_frame_probs {
+  uint8_t coef_intra[4][2][128];
+  struct  rkvdec_rs_vp9_intra_mode_probs intra_mode[10];
+};
+
+union  rkvdec_rs_vp9_frame_probs {
+  struct  rkvdec_rs_vp9_inter_frame_probs inter;
+  struct  rkvdec_rs_vp9_intra_only_frame_probs intra_only;
+};
+
+struct  rkvdec_rs_vp9_probs {
+  uint8_t partition[16][3];
+  uint8_t pred[3];
+  uint8_t tree[7];
+  uint8_t skip[3];
+  uint8_t tx32[2][3];
+  uint8_t tx16[2][2];
+  uint8_t tx8[2][1];
+  uint8_t is_inter[4];
+  uint8_t padding0[3];
+  union  rkvdec_rs_vp9_frame_probs frame_probs;
+  uint8_t padding1[11];
+};
+
+struct rkvdec_rs_decoded_buffer_info {
+  struct rkvdec_rs_resolution resolution;
+  uint8_t bit_depth;
+  bool same_as_dst;
+  dma_addr_t dma_address;
+};
+
+struct rkvdec_rs_frame_info {
+  bool valid;
+  uint8_t segmapid;
+  uint8_t frame_context_idx;
+  uint8_t reference_mode;
+  uint8_t tx_mode;
+  uint8_t interpolation_filter;
+  uint32_t flags;
+  uint64_t timestamp;
+  struct v4l2_vp9_segmentation seg;
+  struct v4l2_vp9_loop_filter lf;
+};
+
+struct rkvdec_rs_run {
+  struct rkvdec_rs_base_run base;
+  const struct v4l2_ctrl_vp9_frame *decode_params;
+  struct  rkvdec_rs_vp9_probs *hw_probs;
+  const struct v4l2_vp9_frame_context_rs *probability_tables;
+  dma_addr_t src_address;
+  dma_addr_t probs_address;
+  dma_addr_t count_base_address;
+  dma_addr_t segid_cur_base_address;
+  dma_addr_t segid_last_base_address;
+  dma_addr_t motion_vectors_base_address;
+  struct rkvdec_rs_decoded_buffer_info dst;
+  struct rkvdec_rs_decoded_buffer_info ref_bufs[3];
+  struct rkvdec_rs_decoded_buffer_info last;
+  uint32_t stream_len;
+  struct rkvdec_rs_frame_info cur_frame_info;
+  struct rkvdec_rs_frame_info last_frame_info;
+  void *regs;
+};
+
+void rkvdec_rs_vp9_init_probs(struct rkvdec_rs_run *run);
+
+void rkvdec_rs_vp9_config_registers(struct rkvdec_rs_run *run);
+
+#endif /* RKVDEC_RS_H */
diff --git a/drivers/staging/media/rkvdec/rkvdec_rs.rs b/drivers/staging/media/rkvdec/rkvdec_rs.rs
new file mode 100644
index 000000000000..a7a48b203225
--- /dev/null
+++ b/drivers/staging/media/rkvdec/rkvdec_rs.rs
@@ -0,0 +1,14 @@
+#![allow(missing_docs, unused_imports)]
+
+use kernel::prelude::*;
+
+const __LOG_PREFIX: &[u8] = b"rkvdec_rs\0";
+pub(crate) mod vp9;
+mod common;
+mod regs;
+
+macro_rules! round_up {
+    ($x:expr, $v:expr) => ((($x - 1) | ($v - 1)) + 1)
+}
+
+pub(crate) use round_up;
diff --git a/drivers/staging/media/rkvdec/vp9.rs b/drivers/staging/media/rkvdec/vp9.rs
new file mode 100644
index 000000000000..74ea33eedc4c
--- /dev/null
+++ b/drivers/staging/media/rkvdec/vp9.rs
@@ -0,0 +1,636 @@
+#![allow(missing_docs)]
+
+use crate::common;
+use crate::regs;
+use crate::round_up;
+use kernel::bindings;
+use kernel::media::v4l2_core::vp9;
+
+#[repr(C)]
+#[derive(Debug)]
+struct DecodedBufferInfo {
+    resolution: common::Resolution,
+    bit_depth: u8,
+    same_as_dst: bool,
+    dma_address: bindings::dma_addr_t,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+struct IntraModeProbs {
+    y_mode: [u8; 105],
+    uv_mode: [u8; 23],
+}
+
+impl Default for IntraModeProbs {
+    fn default() -> Self {
+        Self {
+            y_mode: [0; 105],
+            uv_mode: [0; 23],
+        }
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+struct IntraOnlyFrameProbs {
+    coef_intra: [[[u8; 128]; 2]; 4],
+    intra_mode: [IntraModeProbs; 10],
+}
+
+impl Default for IntraOnlyFrameProbs {
+    fn default() -> Self {
+        Self {
+            coef_intra: [[[0; 128]; 2]; 4],
+            intra_mode: [IntraModeProbs::default(); 10],
+        }
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+struct Mv {
+    joint: [u8; 3],
+    sign: [u8; 2],
+    classes: [[u8; 10]; 2],
+    class0_bit: [u8; 2],
+    bits: [[u8; 10]; 2],
+    class0_fr: [[[u8; 3]; 2]; 2],
+    fr: [[u8; 3]; 2],
+    class0_hp: [u8; 2],
+    hp: [u8; 2],
+}
+
+impl Default for Mv {
+    fn default() -> Self {
+        Self {
+            joint: [0; 3],
+            sign: [0; 2],
+            classes: [[0; 10]; 2],
+            class0_bit: [0; 2],
+            bits: [[0; 10]; 2],
+            class0_fr: [[[0; 3]; 2]; 2],
+            fr: [[0; 3]; 2],
+            class0_hp: [0; 2],
+            hp: [0; 2],
+        }
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+struct InterFrameProbs {
+    y_mode: [[u8; 9]; 4],
+    comp_mode: [u8; 5],
+    comp_ref: [u8; 5],
+    single_ref: [[u8; 2]; 5],
+    inter_mode: [[u8; 3]; 7],
+    interp_filter: [[u8; 2]; 4],
+    padding0: [u8; 11],
+    coef: [[[[u8; 128]; 2]; 4]; 2],
+    uv_mode_0_2: [[u8; 9]; 3],
+    padding1: [u8; 5],
+    uv_mode_3_5: [[u8; 9]; 3],
+    padding2: [u8; 5],
+    uv_mode_6_8: [[u8; 9]; 3],
+    padding3: [u8; 5],
+    uv_mode_9: [u8; 9],
+    padding4: [u8; 7],
+    padding5: [u8; 16],
+    mv: Mv,
+}
+
+impl Default for InterFrameProbs {
+    fn default() -> Self {
+        Self {
+            y_mode: [[0; 9]; 4],
+            comp_mode: [0; 5],
+            comp_ref: [0; 5],
+            single_ref: [[0; 2]; 5],
+            inter_mode: [[0; 3]; 7],
+            interp_filter: [[0; 2]; 4],
+            padding0: [0; 11],
+            coef: [[[[0; 128]; 2]; 4]; 2],
+            uv_mode_0_2: [[0; 9]; 3],
+            padding1: [0; 5],
+            uv_mode_3_5: [[0; 9]; 3],
+            padding2: [0; 5],
+            uv_mode_6_8: [[0; 9]; 3],
+            padding3: [0; 5],
+            uv_mode_9: [0; 9],
+            padding4: [0; 7],
+            padding5: [0; 16],
+            mv: Mv::default(),
+        }
+    }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct HwProbs {
+    partition: [[u8; 3]; 16],
+    pred: [u8; 3],
+    tree: [u8; 7],
+    skip: [u8; 3],
+    tx32: [[u8; 3]; 2],
+    tx16: [[u8; 2]; 2],
+    tx8: [[u8; 1]; 2],
+    is_inter: [u8; 4],
+    padding0: [u8; 3],
+    frame_probs: FrameProbs,
+    padding1: [u8; 11],
+}
+
+impl Default for HwProbs {
+    fn default() -> Self {
+        Self {
+            partition: [[0; 3]; 16],
+            pred: [0; 3],
+            tree: [0; 7],
+            skip: [0; 3],
+            tx32: [[0; 3]; 2],
+            tx16: [[0; 2]; 2],
+            tx8: [[0; 1]; 2],
+            is_inter: [0; 4],
+            padding0: [0; 3],
+            frame_probs: FrameProbs {
+                inter: InterFrameProbs::default(),
+            },
+            padding1: [0; 11],
+        }
+    }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+union FrameProbs {
+    inter: InterFrameProbs,
+    intra_only: IntraOnlyFrameProbs,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+struct RefReg {
+    reg_frm_size: u32,
+    reg_hor_stride: u32,
+    reg_y_stride: u32,
+    reg_yuv_stride: u32,
+    reg_ref_base: u32,
+}
+
+static REF_REGS: [RefReg; 3] = {
+    [
+        RefReg {
+            reg_frm_size: regs::RKVDEC_REG_VP9_FRAME_SIZE!(0),
+            reg_hor_stride: regs::RKVDEC_VP9_HOR_VIRSTRIDE!(0),
+            reg_y_stride: regs::RKVDEC_VP9_LAST_FRAME_YSTRIDE,
+            reg_yuv_stride: regs::RKVDEC_VP9_LAST_FRAME_YUVSTRIDE,
+            reg_ref_base: regs::RKVDEC_REG_VP9_LAST_FRAME_BASE,
+        },
+        RefReg {
+            reg_frm_size: regs::RKVDEC_REG_VP9_FRAME_SIZE!(1),
+            reg_hor_stride: regs::RKVDEC_VP9_HOR_VIRSTRIDE!(1),
+            reg_y_stride: regs::RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE,
+            reg_yuv_stride: 0,
+            reg_ref_base: regs::RKVDEC_REG_VP9_GOLDEN_FRAME_BASE,
+        },
+        RefReg {
+            reg_frm_size: regs::RKVDEC_REG_VP9_FRAME_SIZE!(2),
+            reg_hor_stride: regs::RKVDEC_VP9_HOR_VIRSTRIDE!(2),
+            reg_y_stride: regs::RKVDEC_VP9_ALTREF_FRAME_YSTRIDE,
+            reg_yuv_stride: 0,
+            reg_ref_base: regs::RKVDEC_REG_VP9_ALTREF_FRAME_BASE,
+        },
+    ]
+};
+
+#[repr(C)]
+struct FrameInfo {
+    valid: bool,
+    segmapid: u8,
+    frame_context_idx: u8,
+    reference_mode: u8,
+    tx_mode: u8,
+    interpolation_filter: u8,
+    flags: u32,
+    timestamp: u64,
+    seg: bindings::v4l2_vp9_segmentation,
+    lf: bindings::v4l2_vp9_loop_filter,
+}
+
+#[repr(C)]
+pub(crate) struct Run<'a> {
+    base: crate::common::BaseRun,
+    decode_params: &'a bindings::v4l2_ctrl_vp9_frame,
+    hw_probs: &'a mut HwProbs,
+    probability_tables: &'a vp9::FrameContext,
+    src_address: bindings::dma_addr_t,
+    probs_address: bindings::dma_addr_t,
+    count_base_address: bindings::dma_addr_t,
+    segid_cur_base_address: bindings::dma_addr_t,
+    segid_last_base_address: bindings::dma_addr_t,
+    motion_vectors_base_address: bindings::dma_addr_t,
+    dst: DecodedBufferInfo,
+    ref_bufs: [DecodedBufferInfo; 3],
+    last: DecodedBufferInfo,
+    stream_len: u32,
+    cur_frame_info: FrameInfo,
+    last_frame_info: FrameInfo,
+    regs: *mut core::ffi::c_void,
+}
+
+impl<'a> Run<'a> {
+    fn write_register(&self, val: impl Into<u32>, offset: u32) {
+        if offset > regs::RKVDEC_REG_PREF_CHR_CACHE_COMMAND {
+            kernel::pr_warn!(
+                "Invalid register offset: 0x{:x}, ignoring\n",
+                offset as usize
+            );
+            return;
+        }
+
+        // Safety: if we're here, C has mapped this range for us. So long as we
+        // write within it, we are safe.
+        unsafe {
+            let addr = self.regs.add(offset as usize);
+            bindings::writel_relaxed(val.into(), addr);
+        }
+    }
+
+    fn write_coeff_plane(coef: &[[[u8; 3]; 6]; 6], coef_plane: &mut [u8; 128]) {
+        let mut idx = 0;
+        let mut byte_count = 0;
+        for coef in coef.iter().flatten().flatten() {
+            coef_plane[idx] = *coef;
+            idx += 1;
+            byte_count += 1;
+
+            if byte_count == 27 {
+                idx += 5;
+                byte_count = 0;
+            }
+        }
+    }
+
+    fn init_intra_only_probs(&mut self) {
+        // Safety: this was zero-initialized and we only write to it here.
+        let rkprobs = unsafe { &mut self.hw_probs.frame_probs.intra_only };
+        let probs = self.probability_tables;
+
+        for i in 0..probs.coef.len() {
+            for j in 0..probs.coef[0].len() {
+                Self::write_coeff_plane(&probs.coef[i][j][0], &mut rkprobs.coef_intra[i][j]);
+            }
+        }
+
+        for i in 0..vp9::v4l2_vp9_kf_y_mode_prob_rs.len() {
+            let mut byte_count = 0;
+            let mut idx = 0;
+
+            for j in 0..vp9::v4l2_vp9_kf_y_mode_prob_rs[0].len() {
+                for k in 0..vp9::v4l2_vp9_kf_y_mode_prob_rs[0][0].len() {
+                    let val = vp9::v4l2_vp9_kf_y_mode_prob_rs[i][j][k];
+
+                    rkprobs.intra_mode[i].y_mode[idx] = val;
+
+                    idx += 1;
+                    byte_count += 1;
+
+                    if byte_count == 27 {
+                        byte_count = 0;
+                        idx += 5;
+                    }
+                }
+            }
+        }
+
+        for (i, uv_mode) in vp9::v4l2_vp9_kf_uv_mode_prob_rs
+            .iter()
+            .flatten()
+            .enumerate()
+        {
+            rkprobs.intra_mode[i / 23].uv_mode[i % 23] = *uv_mode;
+        }
+    }
+
+    fn init_inter_probs(&mut self) {
+        // Safety: this was zero-initialized and we only write to it here.
+        let rkprobs = unsafe { &mut self.hw_probs.frame_probs.inter };
+        let probs = self.probability_tables;
+
+        rkprobs.y_mode = probs.y_mode;
+        rkprobs.comp_mode = probs.comp_mode;
+        rkprobs.comp_ref = probs.comp_ref;
+        rkprobs.single_ref = probs.single_ref;
+        rkprobs.inter_mode = probs.inter_mode;
+        rkprobs.interp_filter = probs.interp_filter;
+
+        for (i, coef_i) in probs.coef.iter().enumerate() {
+            for (j, coef_j) in coef_i.iter().enumerate() {
+                for (k, _coef_k) in coef_j.iter().enumerate() {
+                    Self::write_coeff_plane(&coef_j[k], &mut rkprobs.coef[k][i][j]);
+                }
+            }
+        }
+
+        rkprobs.uv_mode_0_2.copy_from_slice(&probs.uv_mode[0..3]);
+        rkprobs.uv_mode_3_5.copy_from_slice(&probs.uv_mode[3..6]);
+        rkprobs.uv_mode_6_8.copy_from_slice(&probs.uv_mode[6..9]);
+        rkprobs.uv_mode_9 = probs.uv_mode[9];
+
+        rkprobs.mv.joint = probs.mv.joint;
+        rkprobs.mv.sign = probs.mv.sign;
+        rkprobs.mv.classes = probs.mv.classes;
+        rkprobs.mv.class0_bit = probs.mv.class0_bit;
+        rkprobs.mv.class0_bit = probs.mv.class0_bit;
+        rkprobs.mv.bits = probs.mv.bits;
+        rkprobs.mv.class0_fr = probs.mv.class0_fr;
+        rkprobs.mv.fr = probs.mv.fr;
+        rkprobs.mv.class0_hp = probs.mv.class0_hp;
+        rkprobs.mv.hp = probs.mv.hp;
+    }
+
+    pub(crate) fn init_probs(&mut self) {
+        *self.hw_probs = Default::default();
+
+        let intra_only = self.decode_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+            || self.decode_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0;
+
+        if intra_only {
+            self.hw_probs.partition = vp9::v4l2_vp9_kf_partition_probs_rs;
+        } else {
+            self.hw_probs.partition = self.probability_tables.partition;
+        }
+
+        self.hw_probs.pred = self.decode_params.seg.pred_probs;
+        self.hw_probs.tree = self.decode_params.seg.tree_probs;
+        self.hw_probs.skip = self.probability_tables.skip;
+        self.hw_probs.tx32 = self.probability_tables.tx32;
+        self.hw_probs.tx16 = self.probability_tables.tx16;
+        self.hw_probs.tx8 = self.probability_tables.tx8;
+        self.hw_probs.is_inter = self.probability_tables.is_inter;
+
+        if intra_only {
+            self.init_intra_only_probs();
+        } else {
+            self.init_inter_probs();
+        }
+    }
+
+    fn config_ref_registers(&mut self) {
+        for (ref_buf, ref_reg) in self.ref_bufs.iter().zip(&REF_REGS) {
+            let aligned_height = round_up!(ref_buf.resolution.height, 64);
+
+            self.write_register(
+                regs::RKVDEC_VP9_FRAMEWIDTH!(ref_buf.resolution.width)
+                    | regs::RKVDEC_VP9_FRAMEHEIGHT!(ref_buf.resolution.height),
+                ref_reg.reg_frm_size,
+            );
+
+            self.write_register(
+                u32::try_from(ref_buf.dma_address).unwrap(),
+                ref_reg.reg_ref_base,
+            );
+
+            if ref_buf.same_as_dst {
+                continue;
+            }
+
+            let aligned_pitch =
+                round_up!(ref_buf.resolution.width * u32::from(ref_buf.bit_depth), 512) / 8;
+            let y_len = aligned_height * aligned_pitch;
+            let yuv_len = (y_len * 3) / 2;
+
+            self.write_register(
+                regs::RKVDEC_HOR_Y_VIRSTRIDE!(aligned_pitch / 16)
+                    | regs::RKVDEC_HOR_UV_VIRSTRIDE!(aligned_pitch / 16),
+                ref_reg.reg_hor_stride,
+            );
+
+            self.write_register(
+                regs::RKVDEC_VP9_REF_YSTRIDE!(y_len / 16),
+                ref_reg.reg_y_stride,
+            );
+
+            if ref_reg.reg_yuv_stride == 0 {
+                continue;
+            }
+
+            self.write_register(
+                regs::RKVDEC_VP9_REF_YUVSTRIDE!(yuv_len / 16),
+                ref_reg.reg_yuv_stride,
+            );
+        }
+    }
+
+    fn config_seg_registers(&mut self) {
+        let seg = if self.last_frame_info.valid {
+            &self.last_frame_info.seg
+        } else {
+            &self.cur_frame_info.seg
+        };
+
+        for i in 0..seg.feature_enabled.len() {
+            let mut val = 0;
+            let mut feature_val;
+            let seg_flags = u32::from(seg.flags);
+
+            let feature_id = bindings::V4L2_VP9_SEG_LVL_ALT_Q;
+            if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) {
+                feature_val = seg.feature_data[i][feature_id as usize];
+                val |= regs::RKVDEC_SEGID_FRAME_QP_DELTA_EN!(1)
+                    | regs::RKVDEC_SEGID_FRAME_QP_DELTA!(feature_val as u32);
+            }
+
+            let feature_id = bindings::V4L2_VP9_SEG_LVL_ALT_L;
+            if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) {
+                feature_val = seg.feature_data[i][feature_id as usize];
+                val |= regs::RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN!(1)
+                    | regs::RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE!(feature_val as u32);
+            }
+
+            let feature_id = bindings::V4L2_VP9_SEG_LVL_REF_FRAME;
+            if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) {
+                feature_val = seg.feature_data[i][feature_id as usize];
+                val |= regs::RKVDEC_SEGID_REFERINFO_EN!(1)
+                    | regs::RKVDEC_SEGID_REFERINFO!(feature_val as u32);
+            }
+
+            let feature_id = bindings::V4L2_VP9_SEG_LVL_SKIP;
+            if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) {
+                val |= regs::RKVDEC_SEGID_FRAME_SKIP_EN!(1);
+            }
+
+            if i == 0 && (seg_flags & bindings::V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE != 0)
+            {
+                val |= regs::RKVDEC_SEGID_ABS_DELTA!(1)
+            }
+
+            self.write_register(val, regs::RKVDEC_VP9_SEGID_GRP!(i as u32));
+        }
+    }
+
+    pub(crate) fn config_registers(&mut self) {
+        let dec_params = self.decode_params;
+        let intra_only = dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0
+            || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0;
+
+        self.write_register(
+            regs::RKVDEC_MODE!(regs::RKVDEC_MODE_VP9),
+            regs::RKVDEC_REG_SYSCTRL,
+        );
+
+        let bit_depth = u32::from(dec_params.bit_depth);
+        let aligned_height = round_up!(self.base.decoded_resolution.height, 64);
+        let aligned_pitch = round_up!(self.base.decoded_resolution.width * bit_depth, 512) / 8;
+
+        let y_len = aligned_height * aligned_pitch;
+        let uv_len = y_len / 2;
+        let yuv_len = y_len + uv_len;
+
+        self.write_register(
+            regs::RKVDEC_Y_HOR_VIRSTRIDE!(aligned_pitch / 16)
+                | regs::RKVDEC_UV_HOR_VIRSTRIDE!(aligned_pitch / 16),
+            regs::RKVDEC_REG_PICPAR,
+        );
+
+        self.write_register(
+            regs::RKVDEC_Y_VIRSTRIDE!(y_len / 16),
+            regs::RKVDEC_REG_Y_VIRSTRIDE,
+        );
+        self.write_register(
+            regs::RKVDEC_YUV_VIRSTRIDE!(yuv_len / 16),
+            regs::RKVDEC_REG_YUV_VIRSTRIDE,
+        );
+        self.write_register(
+            regs::RKVDEC_STRM_LEN!(self.stream_len),
+            regs::RKVDEC_REG_STRM_LEN,
+        );
+
+        self.config_ref_registers();
+        self.config_seg_registers();
+
+        let tx_mode = self.cur_frame_info.tx_mode;
+
+        self.write_register(
+            regs::RKVDEC_VP9_TX_MODE!(tx_mode)
+                | regs::RKVDEC_VP9_FRAME_REF_MODE!(dec_params.reference_mode),
+            regs::RKVDEC_VP9_CPRHEADER_CONFIG,
+        );
+
+        let mut last_frame_info = 0;
+        if !intra_only {
+            let lf = if self.last_frame_info.valid {
+                &self.last_frame_info.lf
+            } else {
+                &self.cur_frame_info.lf
+            };
+
+            let mut val = 0;
+            for (i, delta) in lf.ref_deltas.iter().enumerate() {
+                val |= regs::RKVDEC_REF_DELTAS_LASTFRAME!(i, *delta as u32);
+            }
+
+            self.write_register(val, regs::RKVDEC_VP9_REF_DELTAS_LASTFRAME);
+
+            for (i, delta) in lf.mode_deltas.iter().enumerate() {
+                last_frame_info |= regs::RKVDEC_MODE_DELTAS_LASTFRAME!(i, *delta as u32);
+            }
+        }
+
+        let seg_flags = u32::from(dec_params.seg.flags);
+        if self.last_frame_info.valid
+            && !intra_only
+            && seg_flags & bindings::V4L2_VP9_SEGMENTATION_FLAG_ENABLED != 0
+        {
+            last_frame_info |= regs::RKVDEC_SEG_EN_LASTFRAME;
+        }
+
+        if self.last_frame_info.valid
+            && self.last_frame_info.flags & bindings::V4L2_VP9_FRAME_FLAG_SHOW_FRAME != 0
+        {
+            last_frame_info |= regs::RKVDEC_LAST_SHOW_FRAME;
+        }
+
+        if self.last_frame_info.valid
+            && self.last_frame_info.flags
+                & (bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME
+                    | bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY)
+                != 0
+        {
+            last_frame_info |= regs::RKVDEC_LAST_INTRA_ONLY;
+        }
+
+        if self.last_frame_info.valid && self.last.resolution == self.dst.resolution {
+            last_frame_info |= regs::RKVDEC_LAST_WIDHHEIGHT_EQCUR;
+        }
+
+        self.write_register(last_frame_info, regs::RKVDEC_VP9_INFO_LASTFRAME);
+        let last_tile_size = self.stream_len
+            - u32::from(dec_params.compressed_header_size)
+            - u32::from(dec_params.uncompressed_header_size);
+
+        self.write_register(last_tile_size, regs::RKVDEC_VP9_LASTTILE_SIZE);
+
+        for i in 0..REF_REGS.len() {
+            if intra_only {
+                break;
+            }
+
+            let refw = self.ref_bufs[i].resolution.width;
+            let refh = self.ref_bufs[i].resolution.height;
+            let hscale = (refw << 14) / self.dst.resolution.width;
+            let vscale = (refh << 14) / self.dst.resolution.height;
+
+            self.write_register(
+                regs::RKVDEC_VP9_REF_HOR_SCALE!(hscale) | regs::RKVDEC_VP9_REF_VER_SCALE!(vscale),
+                regs::RKVDEC_VP9_REF_SCALE!(i as u32),
+            );
+        }
+
+        self.write_register(
+            u32::try_from(self.dst.dma_address).unwrap(),
+            regs::RKVDEC_REG_DECOUT_BASE,
+        );
+        self.write_register(
+            u32::try_from(self.src_address).unwrap(),
+            regs::RKVDEC_REG_STRM_RLC_BASE,
+        );
+
+        self.write_register(
+            u32::try_from(self.probs_address).unwrap(),
+            regs::RKVDEC_REG_CABACTBL_PROB_BASE,
+        );
+        self.write_register(
+            u32::try_from(self.count_base_address).unwrap(),
+            regs::RKVDEC_REG_VP9COUNT_BASE,
+        );
+        self.write_register(
+            u32::try_from(self.segid_cur_base_address).unwrap(),
+            regs::RKVDEC_REG_VP9_SEGIDCUR_BASE,
+        );
+        self.write_register(
+            u32::try_from(self.segid_last_base_address).unwrap(),
+            regs::RKVDEC_REG_VP9_SEGIDLAST_BASE,
+        );
+
+        self.write_register(
+            u32::try_from(self.motion_vectors_base_address).unwrap(),
+            regs::RKVDEC_VP9_REF_COLMV_BASE,
+        );
+        self.write_register(
+            self.base.decoded_resolution.width | (self.base.decoded_resolution.height << 16),
+            regs::RKVDEC_REG_PERFORMANCE_CYCLE,
+        );
+    }
+}
+
+#[no_mangle]
+pub(crate) extern "C" fn rkvdec_rs_vp9_init_probs(run: &mut Run<'_>) {
+    run.init_probs();
+}
+
+#[no_mangle]
+pub(crate) extern "C" fn rkvdec_rs_vp9_config_registers(run: &mut Run<'_>) {
+    run.config_registers();
+}
diff --git a/rust/helpers.c b/rust/helpers.c
index d146bbf25aec..fde0520e1d57 100644
--- a/rust/helpers.c
+++ b/rust/helpers.c
@@ -20,6 +20,7 @@
  * Sorted alphabetically.
  */
 
+#include "asm/io.h"
 #include <kunit/test-bug.h>
 #include <linux/bug.h>
 #include <linux/build_bug.h>
@@ -272,3 +273,9 @@ static_assert(
 	__alignof__(size_t) == __alignof__(uintptr_t),
 	"Rust code expects C `size_t` to match Rust `usize`"
 );
+
+void rust_helper_writel_relaxed(u32 val, void *addr)
+{
+	writel_relaxed(val, addr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_writel_relaxed);
-- 
2.43.0


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

* Re: [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec library in Rust
  2024-03-07 19:08 ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec " Daniel Almeida
  2024-03-07 19:08   ` [RFC PATCH v2 1/2] v4l2-core: rewrite the VP9 " Daniel Almeida
  2024-03-07 19:08   ` [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver " Daniel Almeida
@ 2024-03-07 20:04   ` Deborah Brouwer
  2 siblings, 0 replies; 10+ messages in thread
From: Deborah Brouwer @ 2024-03-07 20:04 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: wedsonaf, ojeda, mchehab, hverkuil, rust-for-linux, linux-kernel,
	linux-media, kernel

Hi Daniel,

On Thu, Mar 07, 2024 at 04:08:14PM -0300, Daniel Almeida wrote:
> Hi Mauro, Hans,
> 
> While working on v1 for this patchset, I realized that we can go further by
> converting the error-prone sections of our codec drivers to Rust. This also
> does not need any bindings in order to work.
> 
> As yet another proof-of-concept, I have converted parts of the rkvdec driver.
> Refer to instructions in v1 to test this.

I tested this on rk3399 rkvdec with:
./fluster.py run -d GStreamer-VP9-V4L2SL-Gst1.0 -ts VP9-TEST-VECTORS -j1

And I get the same result as on mainline (6.8-rc3)
Ran 220/305 tests successfully               in 913.877 secs

So I can't say I understand all the Rust here but my testing didn't show
any regressions in the VP9 decoding. :)

Deb

> 
> Notice how:
> 
> 1) many problematic memcpy's go away, these become a simple assignment in Rust.
> 
> 2) it can interop seamlessly with the code in rkvdec-vp9.c that was already
> converted in v1 of this series.
> 
> 3) it can use the Rust version of `seg_feat_enabled` directly in vp9.rs, while
> also using the C APIs from the v4l2-vp9-rs library in rkvdec-vp9.c
> 
> 4) more modern things become available for the programmer, like iterators and
> their methods without a performance penalty.
> 
> I want to propose the following:
> 
> Let's merge a non-RFC version of this series and gate it behind some kconfigs
> so that we can switch between the C and Rust implementations. Users get the C
> version by default, while we continuously test the Rust components on a CI for
> a few months. This will hopefully be enough time until the next Media Summit.
> 
> My aim is to eventually deprecate the C parts once we're confident that the
> Rust code is stable enough. I will keep my own tree, and send PRs to the media
> tree if a rebase or fix is needed.
> 
> I believe this will not be disruptive nor require any extra work from anyone
> but me.
> 
> -- Daniel
> 
> 
> Again, applies on top of:
> 
> commit d9c1fae3e5b225f2e45e0bca519f9a2967cd1062
> Author: Alice Ryhl <aliceryhl@google.com>
> Date:   Fri Feb 9 11:18:22 2024 +0000
> 
>     rust: file: add abstraction for `poll_table`
> 
> For those looking for a branch instead: https://gitlab.collabora.com/dwlsalmeida/for-upstream/-/tree/vp9-rs-rkvdec?ref_type=heads
> 
> Daniel Almeida (2):
>   v4l2-core: rewrite the VP9 library in Rust
>   media: rkvdec: rewrite parts of the driver in Rust
> 
>  drivers/media/platform/verisilicon/Kconfig    |    2 +-
>  .../platform/verisilicon/hantro_g2_vp9_dec.c  |   38 +-
>  .../media/platform/verisilicon/hantro_hw.h    |    8 +-
>  drivers/media/v4l2-core/Kconfig               |    5 +
>  drivers/staging/media/rkvdec/Kconfig          |    3 +-
>  drivers/staging/media/rkvdec/Makefile         |    2 +-
>  drivers/staging/media/rkvdec/cbindgen.toml    |   36 +
>  drivers/staging/media/rkvdec/common.rs        |   19 +
>  drivers/staging/media/rkvdec/regs.rs          |  237 ++
>  drivers/staging/media/rkvdec/rkvdec-vp9.c     |  607 +----
>  drivers/staging/media/rkvdec/rkvdec_rs.h      |  125 +
>  drivers/staging/media/rkvdec/rkvdec_rs.rs     |   14 +
>  drivers/staging/media/rkvdec/vp9.rs           |  636 +++++
>  include/media/v4l2-vp9-rs.h                   |   99 +
>  rust/bindings/bindings_helper.h               |    1 +
>  rust/helpers.c                                |    7 +
>  rust/kernel/lib.rs                            |    2 +
>  rust/kernel/media.rs                          |    5 +
>  rust/kernel/media/v4l2_core.rs                |    6 +
>  rust/kernel/media/v4l2_core/cbindgen.toml     |   26 +
>  rust/kernel/media/v4l2_core/vp9.rs            | 2053 +++++++++++++++++
>  21 files changed, 3415 insertions(+), 516 deletions(-)
>  create mode 100644 drivers/staging/media/rkvdec/cbindgen.toml
>  create mode 100644 drivers/staging/media/rkvdec/common.rs
>  create mode 100644 drivers/staging/media/rkvdec/regs.rs
>  create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.h
>  create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.rs
>  create mode 100644 drivers/staging/media/rkvdec/vp9.rs
>  create mode 100644 include/media/v4l2-vp9-rs.h
>  create mode 100644 rust/kernel/media.rs
>  create mode 100644 rust/kernel/media/v4l2_core.rs
>  create mode 100644 rust/kernel/media/v4l2_core/cbindgen.toml
>  create mode 100644 rust/kernel/media/v4l2_core/vp9.rs
> 
> -- 
> 2.43.0
> 
> 

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

* Re: [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver in Rust
  2024-03-07 19:08   ` [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver " Daniel Almeida
@ 2024-03-07 20:56     ` Nicolas Dufresne
  2024-03-07 21:45       ` Daniel Almeida
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Dufresne @ 2024-03-07 20:56 UTC (permalink / raw)
  To: Daniel Almeida, wedsonaf, ojeda, mchehab, hverkuil
  Cc: rust-for-linux, linux-kernel, linux-media, kernel

Hi Daniel,

as I'm already sold to the idea, I decided to discuss other things ;-P see
below.

Le jeudi 07 mars 2024 à 16:08 -0300, Daniel Almeida a écrit :
> +++ b/drivers/staging/media/rkvdec/regs.rs
> @@ -0,0 +1,237 @@
> +#![allow(dead_code)]
> +#![allow(unused_macros)]
> +
> +pub(crate) const RKVDEC_REG_INTERRUPT: u32 = 0x004;
> +pub(crate) const RKVDEC_INTERRUPT_DEC_E: u32 = 1 << 0;
> +pub(crate) const RKVDEC_CONFIG_DEC_CLK_GATE_E: u32 = 1 << 1;
> +pub(crate) const RKVDEC_E_STRMD_CLKGATE_DIS: u32 = 1 << 2;

Regs file are a bit our coded reference information on how the registers are
layout in memory. So I believe the alignment, indent and readability of that
file would at least need polishing.

But to the light of your comment, being able to use more modern utility, isn't
there something in Rust we could use to better map the registers ? These
variables are just mask offset to help someone write specific bits within a list
of 32bit registers (Hantro and RKVDEC have that in common). In downstream mpp
userspace driver, they maps all the register with a C struct.

struct reg123 {
  val1 :3  // bit 31-29
  val2 :20 // bit 28-9
  val3 :9  // bit 8-0
};

I seriously think it looks nicer, and when the compiler does not screw it up
(the main reason we don't use that), it is also a lot safer and simpler to use.
Now, lets forget about C, my question is just if there is something in Rust that
could give us the safety to edit the right portion of a register, but also allow
expressing that map in a readable form.

Note that sometimes, we may want to read the register before editing it,
something MPP giant C struct does not help with.

Nicolas

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

* Re: [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver in Rust
  2024-03-07 20:56     ` Nicolas Dufresne
@ 2024-03-07 21:45       ` Daniel Almeida
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2024-03-07 21:45 UTC (permalink / raw)
  To: Nicolas Dufresne
  Cc: wedsonaf, ojeda, mchehab, hverkuil, rust-for-linux, linux-kernel,
	linux-media, kernel

Hi Nicolas,

> struct reg123 {
>   val1 :3  // bit 31-29
>   val2 :20 // bit 28-9
>   val3 :9  // bit 8-0
> };

What you're describing can be modeled as Ranges in Rust:

```
use core::ops::Range;

struct Foo {
    reg1: Range<u32>,
    reg2: Range<u32>,
    reg3: Range<u32>
}

const FOO_REGMAP: Foo = Foo {
        reg1: 0..3,
        reg2: 3..24,
        reg3: 24..32
};
```

It becomes more useful when you pair that with a bit writer. For an example of previous art, see Faith's work: [0]

This has asserts in the right places so that you do not shoot yourself in the foot. IMHO, such a data structure can be shared with the whole Rust code in the kernel.

You can then describe your writes using the ranges, e.g.: [1] 

But as we've established, instead of writing the ranges down directly, you can simply refer to them as FOO_REGMAP.reg1, FOO_REGMAP.reg2 and so on.

I believe this is both more readable and safer.

[0]: https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/nouveau/compiler/bitview/lib.rs?ref_type=heads

[1]: https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/nouveau/compiler/nak/encode_sm70.rs?ref_type=heads#L228


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

end of thread, other threads:[~2024-03-07 21:45 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-27 21:51 [RFC PATCH 0/1] Rewrite the VP9 codec library in Rust Daniel Almeida
2024-02-27 21:51 ` [RFC PATCH 1/1] v4l2-core: rewrite the VP9 " Daniel Almeida
2024-02-28 14:13   ` Alice Ryhl
2024-02-28 17:59     ` Daniel Almeida
2024-03-07 19:08 ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec " Daniel Almeida
2024-03-07 19:08   ` [RFC PATCH v2 1/2] v4l2-core: rewrite the VP9 " Daniel Almeida
2024-03-07 19:08   ` [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver " Daniel Almeida
2024-03-07 20:56     ` Nicolas Dufresne
2024-03-07 21:45       ` Daniel Almeida
2024-03-07 20:04   ` [RFC PATCH v2 0/2] Rewrite parts of rkvdec driver and the VP9 codec library " Deborah Brouwer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).