On Fri Sep 5 16:19:23 2025 +0000, Alex Bee wrote:
> The RK3328 VDEC has a HW quirk that require QoS to be disabled when HEVC
> or VP9 is decoded, otherwise the decoded picture may become corrupted.
> 
> Add a RK3328 variant with a quirk flag to disable QoS when before
> decoding is started.
> 
> Signed-off-by: Alex Bee <[email protected]>
> Signed-off-by: Jonas Karlman <[email protected]>
> Tested-by: Diederik de Haas <[email protected]>  # Rock64, RockPro64, 
> Quartz64-B, NanoPi R5S
> Tested-by: Detlev Casanova <[email protected]> # RK3399
> Signed-off-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 .../media/platform/rockchip/rkvdec/rkvdec-hevc.c   |  3 +++
 .../media/platform/rockchip/rkvdec/rkvdec-regs.h   |  2 ++
 .../media/platform/rockchip/rkvdec/rkvdec-vp9.c    |  4 ++++
 drivers/media/platform/rockchip/rkvdec/rkvdec.c    | 24 ++++++++++++++++++++++
 drivers/media/platform/rockchip/rkvdec/rkvdec.h    |  5 +++++
 5 files changed, 38 insertions(+)

---

diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c 
b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
index 9b5cf70188db..fc7e6a260b0a 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
@@ -789,6 +789,9 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx)
        writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
        writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
 
+       if (rkvdec->variant->quirks & RKVDEC_QUIRK_DISABLE_QOS)
+               rkvdec_quirks_disable_qos(ctx);
+
        /* Start decoding! */
        reg = (run.pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) ?
                0 : RKVDEC_WR_DDR_ALIGN_EN;
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h 
b/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
index 540c8bdf24e4..c627b6b6f53a 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
@@ -219,6 +219,8 @@
 #define RKVDEC_REG_H264_ERR_E                          0x134
 #define RKVDEC_H264_ERR_EN_HIGHBITS(x)                 ((x) & 0x3fffffff)
 
+#define RKVDEC_REG_QOS_CTRL                            0x18C
+
 #define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND             0x410
 #define RKVDEC_REG_PREF_CHR_CACHE_COMMAND              0x450
 
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c 
b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
index 0e7e16f20eeb..b4bf01e839ef 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
@@ -824,6 +824,10 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
        writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
 
        writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
+
+       if (rkvdec->variant->quirks & RKVDEC_QUIRK_DISABLE_QOS)
+               rkvdec_quirks_disable_qos(ctx);
+
        /* Start decoding! */
        writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E |
               RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E,
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c 
b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
index 5610ad9cb9d0..5af9aa5ab353 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
@@ -902,6 +902,18 @@ void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct 
rkvdec_run *run)
                v4l2_ctrl_request_complete(src_req, &ctx->ctrl_hdl);
 }
 
+void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx)
+{
+       struct rkvdec_dev *rkvdec = ctx->dev;
+       u32 reg;
+
+       /* Set undocumented swreg_block_gating_e field */
+       reg = readl(rkvdec->regs + RKVDEC_REG_QOS_CTRL);
+       reg &= GENMASK(31, 16);
+       reg |= 0xEFFF;
+       writel(reg, rkvdec->regs + RKVDEC_REG_QOS_CTRL);
+}
+
 static void rkvdec_device_run(void *priv)
 {
        struct rkvdec_ctx *ctx = priv;
@@ -1225,6 +1237,14 @@ static const struct rkvdec_variant rk3288_rkvdec_variant 
= {
        .capabilities = RKVDEC_CAPABILITY_HEVC,
 };
 
+static const struct rkvdec_variant rk3328_rkvdec_variant = {
+       .num_regs = 109,
+       .capabilities = RKVDEC_CAPABILITY_HEVC |
+                       RKVDEC_CAPABILITY_H264 |
+                       RKVDEC_CAPABILITY_VP9,
+       .quirks = RKVDEC_QUIRK_DISABLE_QOS,
+};
+
 static const struct rkvdec_variant rk3399_rkvdec_variant = {
        .num_regs = 78,
        .capabilities = RKVDEC_CAPABILITY_HEVC |
@@ -1237,6 +1257,10 @@ static const struct of_device_id of_rkvdec_match[] = {
                .compatible = "rockchip,rk3288-vdec",
                .data = &rk3288_rkvdec_variant,
        },
+       {
+               .compatible = "rockchip,rk3328-vdec",
+               .data = &rk3328_rkvdec_variant,
+       },
        {
                .compatible = "rockchip,rk3399-vdec",
                .data = &rk3399_rkvdec_variant,
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h 
b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
index c47457c954e5..566e06fa2b1e 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
@@ -26,6 +26,8 @@
 #define RKVDEC_CAPABILITY_H264         BIT(1)
 #define RKVDEC_CAPABILITY_VP9          BIT(2)
 
+#define RKVDEC_QUIRK_DISABLE_QOS       BIT(0)
+
 struct rkvdec_ctx;
 
 struct rkvdec_ctrl_desc {
@@ -70,6 +72,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf)
 struct rkvdec_variant {
        unsigned int num_regs;
        unsigned int capabilities;
+       unsigned int quirks;
 };
 
 struct rkvdec_coded_fmt_ops {
@@ -149,6 +152,8 @@ struct rkvdec_aux_buf {
 void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
 void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
 
+void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx);
+
 extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops;
 extern const struct rkvdec_coded_fmt_ops rkvdec_hevc_fmt_ops;
 extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops;
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to