]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: rkvdec: Disable QoS for HEVC and VP9 on RK3328
authorAlex Bee <knaerzche@gmail.com>
Fri, 5 Sep 2025 16:19:23 +0000 (16:19 +0000)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Mon, 3 Nov 2025 07:37:15 +0000 (08:37 +0100)
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 <knaerzche@gmail.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock64, RockPro64, Quartz64-B, NanoPi R5S
Tested-by: Detlev Casanova <detlev.casanova@collabora.com> # RK3399
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
drivers/media/platform/rockchip/rkvdec/rkvdec.c
drivers/media/platform/rockchip/rkvdec/rkvdec.h

index 9b5cf70188db9ac887a0d15df745984dffe74b0a..fc7e6a260b0a77fb2d3b265eba1e98a25b267494 100644 (file)
@@ -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;
index 540c8bdf24e4431afb3a09b1e03a3abafbd047dc..c627b6b6f53a121e4e9f5f039cc42a20fcc7f0fe 100644 (file)
 #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
 
index 0e7e16f20eeb08f4d54bfa8378247b59dec1bf8f..b4bf01e839eff20508e89949763c54294b274998 100644 (file)
@@ -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,
index 5610ad9cb9d027fecc92adb22ecbb48b36bab5c8..5af9aa5ab353b460073356f92e3652afe6ab8474 100644 (file)
@@ -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,
index c47457c954e55f6b41804bf0dcb0d033d65fcd92..566e06fa2b1edc35620a1e3a2c0ef9861780914f 100644 (file)
@@ -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;