From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
To: Detlev Casanova <detlev.casanova@collabora.com>,
linux-kernel@vger.kernel.org
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>,
Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>,
Heiko Stuebner <heiko@sntech.de>,
Ricardo Ribalda <ribalda@chromium.org>,
Hans Verkuil <hverkuil@kernel.org>,
Hans de Goede <hansg@kernel.org>, Yunke Cao <yunkec@google.com>,
Jonathan Corbet <corbet@lwn.net>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
James Cowgill <james.cowgill@blaize.com>,
linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org,
linux-arm-kernel@lists.infradead.org, kernel@collabora.com,
Jonas Karlman <jonas@kwiboo.se>,
Diederik de Haas <didi.debian@cknow.org>
Subject: Re: [PATCH v8 10/17] media: rkvdec: Add RCB and SRAM support
Date: Sun, 18 Jan 2026 17:08:11 -0500 [thread overview]
Message-ID: <50211f049bee9ebcb6eb40dec40b7143cd744824.camel@collabora.com> (raw)
In-Reply-To: <20260109161538.1294449-11-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 13140 bytes --]
Le vendredi 09 janvier 2026 à 11:15 -0500, Detlev Casanova a écrit :
> The RCB (Rows and Cols Buffers) are a set of buffers used by other
> variations of the decoder to store temporary data.
>
> Those variation come with a dedicated SRAM area used to store those
> buffers for better performances.
>
> The buffer sizes are either the width or height of the frame being
> decoded multiplied by a documented factor and can be stored either
> in SRAM or RAM.
> A fallback to RAM is provided if the SRAM is full (e.g.: multiple
> streams are being decoded at the same time).
>
> To manage the different kind of allocation, an enum is added to the
> rkvdec_aux_buf struct to specify how the buffer was allocated, and
> so, how to free it.
>
> This commit is in preparation of other variants support.
>
> Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock 5B
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> ---
> .../media/platform/rockchip/rkvdec/Makefile | 1 +
> .../platform/rockchip/rkvdec/rkvdec-rcb.c | 179 ++++++++++++++++++
> .../platform/rockchip/rkvdec/rkvdec-rcb.h | 29 +++
> .../media/platform/rockchip/rkvdec/rkvdec.c | 27 ++-
> .../media/platform/rockchip/rkvdec/rkvdec.h | 13 ++
> 5 files changed, 247 insertions(+), 2 deletions(-)
> create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c
> create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h
>
> diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/media/platform/rockchip/rkvdec/Makefile
> index 1b4bc44be23e..3d75103e536d 100644
> --- a/drivers/media/platform/rockchip/rkvdec/Makefile
> +++ b/drivers/media/platform/rockchip/rkvdec/Makefile
> @@ -7,4 +7,5 @@ rockchip-vdec-y += \
> rkvdec-h264-common.o \
> rkvdec-hevc.o \
> rkvdec-hevc-common.o \
> + rkvdec-rcb.o \
> rkvdec-vp9.o
> diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c
> new file mode 100644
> index 000000000000..fdcf1f177379
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c
> @@ -0,0 +1,179 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Rockchip video decoder Rows and Cols Buffers manager
> + *
> + * Copyright (C) 2025 Collabora, Ltd.
> + * Detlev Casanova <detlev.casanova@collabora.com>
> + */
> +
> +#include "rkvdec.h"
> +#include "rkvdec-rcb.h"
> +
> +#include <linux/iommu.h>
> +#include <linux/genalloc.h>
> +#include <linux/sizes.h>
> +#include <linux/types.h>
> +
> +struct rkvdec_rcb_config {
> + struct rkvdec_aux_buf *rcb_bufs;
> + size_t rcb_count;
> +};
> +
> +static size_t rkvdec_rcb_size(const struct rcb_size_info *size_info,
> + unsigned int width, unsigned int height)
> +{
> + return size_info->multiplier * (size_info->axis == PIC_HEIGHT ? height : width);
> +}
> +
> +dma_addr_t rkvdec_rcb_buf_dma_addr(struct rkvdec_ctx *ctx, int id)
> +{
> + return ctx->rcb_config->rcb_bufs[id].dma;
> +}
> +
> +size_t rkvdec_rcb_buf_size(struct rkvdec_ctx *ctx, int id)
> +{
> + return ctx->rcb_config->rcb_bufs[id].size;
> +}
> +
> +int rkvdec_rcb_buf_count(struct rkvdec_ctx *ctx)
> +{
> + return ctx->rcb_config->rcb_count;
> +}
> +
> +void rkvdec_free_rcb(struct rkvdec_ctx *ctx)
> +{
> + struct rkvdec_dev *dev = ctx->dev;
> + struct rkvdec_rcb_config *cfg = ctx->rcb_config;
> + unsigned long virt_addr;
> + int i;
> +
> + if (!cfg)
> + return;
> +
> + for (i = 0; i < cfg->rcb_count; i++) {
> + size_t rcb_size = cfg->rcb_bufs[i].size;
> +
> + if (!cfg->rcb_bufs[i].cpu)
> + continue;
> +
> + switch (cfg->rcb_bufs[i].type) {
> + case RKVDEC_ALLOC_SRAM:
> + virt_addr = (unsigned long)cfg->rcb_bufs[i].cpu;
> +
> + if (dev->iommu_domain)
> + iommu_unmap(dev->iommu_domain, virt_addr, rcb_size);
> + gen_pool_free(dev->sram_pool, virt_addr, rcb_size);
> + break;
> + case RKVDEC_ALLOC_DMA:
> + dma_free_coherent(dev->dev,
> + rcb_size,
> + cfg->rcb_bufs[i].cpu,
> + cfg->rcb_bufs[i].dma);
> + break;
> + }
> + }
> +
> + if (cfg->rcb_bufs)
> + devm_kfree(dev->dev, cfg->rcb_bufs);
> +
> + devm_kfree(dev->dev, cfg);
> +}
> +
> +int rkvdec_allocate_rcb(struct rkvdec_ctx *ctx,
> + const struct rcb_size_info *size_info,
> + size_t rcb_count)
> +{
> + int ret, i;
> + u32 width, height;
> + struct rkvdec_dev *rkvdec = ctx->dev;
> + struct rkvdec_rcb_config *cfg;
> +
> + if (!size_info || !rcb_count) {
> + ctx->rcb_config = NULL;
> + return 0;
> + }
> +
> + ctx->rcb_config = devm_kzalloc(rkvdec->dev, sizeof(*ctx->rcb_config), GFP_KERNEL);
> + if (!ctx->rcb_config)
> + return -ENOMEM;
> +
> + cfg = ctx->rcb_config;
> +
> + cfg->rcb_bufs = devm_kzalloc(rkvdec->dev, sizeof(*cfg->rcb_bufs) * rcb_count, GFP_KERNEL);
> + if (!cfg->rcb_bufs) {
> + ret = -ENOMEM;
> + goto err_alloc;
> + }
> +
> + width = ctx->decoded_fmt.fmt.pix_mp.width;
> + height = ctx->decoded_fmt.fmt.pix_mp.height;
> +
> + for (i = 0; i < rcb_count; i++) {
> + void *cpu = NULL;
> + dma_addr_t dma;
> + size_t rcb_size = rkvdec_rcb_size(&size_info[i], width, height);
> + enum rkvdec_alloc_type alloc_type = RKVDEC_ALLOC_SRAM;
> +
> + /* Try allocating an SRAM buffer */
> + if (ctx->dev->sram_pool) {
> + if (rkvdec->iommu_domain)
> + rcb_size = ALIGN(rcb_size, SZ_4K);
> +
> + cpu = gen_pool_dma_zalloc_align(ctx->dev->sram_pool,
> + rcb_size,
> + &dma,
> + SZ_4K);
> + }
> +
> + /* If an IOMMU is used, map the SRAM address through it */
> + if (cpu && rkvdec->iommu_domain) {
> + unsigned long virt_addr = (unsigned long)cpu;
> + phys_addr_t phys_addr = dma;
> +
> + ret = iommu_map(rkvdec->iommu_domain, virt_addr, phys_addr,
> + rcb_size, IOMMU_READ | IOMMU_WRITE, 0);
> + if (ret) {
> + gen_pool_free(ctx->dev->sram_pool,
> + (unsigned long)cpu,
> + rcb_size);
> + cpu = NULL;
> + goto ram_fallback;
> + }
> +
> + /*
> + * The registers will be configured with the virtual
> + * address so that it goes through the IOMMU
> + */
> + dma = virt_addr;
> + }
> +
> +ram_fallback:
> + /* Fallback to RAM */
> + if (!cpu) {
> + cpu = dma_alloc_coherent(ctx->dev->dev,
> + rcb_size,
> + &dma,
> + GFP_KERNEL);
> + alloc_type = RKVDEC_ALLOC_DMA;
> + }
> +
> + if (!cpu) {
> + ret = -ENOMEM;
> + goto err_alloc;
> + }
> +
> + cfg->rcb_bufs[i].cpu = cpu;
> + cfg->rcb_bufs[i].dma = dma;
> + cfg->rcb_bufs[i].size = rcb_size;
> + cfg->rcb_bufs[i].type = alloc_type;
> +
> + cfg->rcb_count += 1;
> + }
> +
> + return 0;
> +
> +err_alloc:
> + rkvdec_free_rcb(ctx);
> +
> + return ret;
> +}
> diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h
> new file mode 100644
> index 000000000000..30e8002555c8
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Rockchip video decoder Rows and Cols Buffers manager
> + *
> + * Copyright (C) 2025 Collabora, Ltd.
> + * Detlev Casanova <detlev.casanova@collabora.com>
> + */
> +
> +#include <linux/types.h>
> +
> +struct rkvdec_ctx;
> +
> +enum rcb_axis {
> + PIC_WIDTH = 0,
> + PIC_HEIGHT = 1
> +};
> +
> +struct rcb_size_info {
> + u8 multiplier;
> + enum rcb_axis axis;
> +};
> +
> +int rkvdec_allocate_rcb(struct rkvdec_ctx *ctx,
> + const struct rcb_size_info *size_info,
> + size_t rcb_count);
> +dma_addr_t rkvdec_rcb_buf_dma_addr(struct rkvdec_ctx *ctx, int id);
> +size_t rkvdec_rcb_buf_size(struct rkvdec_ctx *ctx, int id);
> +int rkvdec_rcb_buf_count(struct rkvdec_ctx *ctx);
> +void rkvdec_free_rcb(struct rkvdec_ctx *ctx);
> diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> index 92b1c7b62bd2..ff6a09e45462 100644
> --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> @@ -10,6 +10,7 @@
> */
>
> #include <linux/clk.h>
> +#include <linux/genalloc.h>
> #include <linux/interrupt.h>
> #include <linux/iommu.h>
> #include <linux/module.h>
> @@ -28,6 +29,7 @@
>
> #include "rkvdec.h"
> #include "rkvdec-regs.h"
> +#include "rkvdec-rcb.h"
>
> static bool rkvdec_image_fmt_match(enum rkvdec_image_fmt fmt1,
> enum rkvdec_image_fmt fmt2)
> @@ -778,6 +780,7 @@ static int rkvdec_start_streaming(struct vb2_queue *q, unsigned int count)
> {
> struct rkvdec_ctx *ctx = vb2_get_drv_priv(q);
> const struct rkvdec_coded_fmt_desc *desc;
> + const struct rkvdec_variant *variant = ctx->dev->variant;
> int ret;
>
> if (V4L2_TYPE_IS_CAPTURE(q->type))
> @@ -787,13 +790,22 @@ static int rkvdec_start_streaming(struct vb2_queue *q, unsigned int count)
> if (WARN_ON(!desc))
> return -EINVAL;
>
> + ret = rkvdec_allocate_rcb(ctx, variant->rcb_sizes, variant->num_rcb_sizes);
> + if (ret)
> + return ret;
> +
> if (desc->ops->start) {
> ret = desc->ops->start(ctx);
> if (ret)
> - return ret;
> + goto err_ops_start;
> }
>
> return 0;
> +
> +err_ops_start:
> + rkvdec_free_rcb(ctx);
> +
> + return ret;
> }
>
> static void rkvdec_queue_cleanup(struct vb2_queue *vq, u32 state)
> @@ -829,6 +841,8 @@ static void rkvdec_stop_streaming(struct vb2_queue *q)
>
> if (desc->ops->stop)
> desc->ops->stop(ctx);
> +
> + rkvdec_free_rcb(ctx);
> }
>
> rkvdec_queue_cleanup(q, VB2_BUF_STATE_ERROR);
> @@ -1345,6 +1359,10 @@ static int rkvdec_probe(struct platform_device *pdev)
> return ret;
> }
>
> + rkvdec->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
> + if (!rkvdec->sram_pool && rkvdec->variant->num_rcb_sizes > 0)
> + dev_info(&pdev->dev, "No sram node, RCB will be stored in RAM\n");
> +
> pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
> pm_runtime_use_autosuspend(&pdev->dev);
> pm_runtime_enable(&pdev->dev);
> @@ -1353,7 +1371,8 @@ static int rkvdec_probe(struct platform_device *pdev)
> if (ret)
> goto err_disable_runtime_pm;
>
> - if (iommu_get_domain_for_dev(&pdev->dev)) {
> + rkvdec->iommu_domain = iommu_get_domain_for_dev(&pdev->dev);
> + if (rkvdec->iommu_domain) {
> rkvdec->empty_domain = iommu_paging_domain_alloc(rkvdec->dev);
>
> if (IS_ERR(rkvdec->empty_domain)) {
> @@ -1367,6 +1386,10 @@ static int rkvdec_probe(struct platform_device *pdev)
> err_disable_runtime_pm:
> pm_runtime_dont_use_autosuspend(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> +
> + if (rkvdec->sram_pool)
> + gen_pool_destroy(rkvdec->sram_pool);
> +
> return ret;
> }
>
> diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
> index 8c4f96ba5cde..751f39afe7e2 100644
> --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h
> +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
> @@ -19,12 +19,14 @@
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-device.h>
> #include <media/v4l2-ioctl.h>
> +#include <media/v4l2-mem2mem.h>
> #include <media/videobuf2-core.h>
> #include <media/videobuf2-dma-contig.h>
>
> #define RKVDEC_QUIRK_DISABLE_QOS BIT(0)
>
> struct rkvdec_ctx;
> +struct rkvdec_rcb_config;
>
> struct rkvdec_ctrl_desc {
> struct v4l2_ctrl_config cfg;
> @@ -69,6 +71,8 @@ struct rkvdec_variant {
> unsigned int num_regs;
> const struct rkvdec_coded_fmt_desc *coded_fmts;
> size_t num_coded_fmts;
> + const struct rcb_size_info *rcb_sizes;
> + size_t num_rcb_sizes;
> unsigned int quirks;
> };
>
> @@ -119,6 +123,8 @@ struct rkvdec_dev {
> void __iomem *regs;
> struct mutex vdev_lock; /* serializes ioctls */
> struct delayed_work watchdog_work;
> + struct gen_pool *sram_pool;
> + struct iommu_domain *iommu_domain;
> struct iommu_domain *empty_domain;
> const struct rkvdec_variant *variant;
> };
> @@ -131,6 +137,7 @@ struct rkvdec_ctx {
> struct v4l2_ctrl_handler ctrl_hdl;
> struct rkvdec_dev *dev;
> enum rkvdec_image_fmt image_fmt;
> + struct rkvdec_rcb_config *rcb_config;
> void *priv;
> };
>
> @@ -139,10 +146,16 @@ static inline struct rkvdec_ctx *file_to_rkvdec_ctx(struct file *filp)
> return container_of(file_to_v4l2_fh(filp), struct rkvdec_ctx, fh);
> }
>
> +enum rkvdec_alloc_type {
> + RKVDEC_ALLOC_DMA = 0,
> + RKVDEC_ALLOC_SRAM = 1,
> +};
> +
> struct rkvdec_aux_buf {
> void *cpu;
> dma_addr_t dma;
> size_t size;
> + enum rkvdec_alloc_type type;
> };
>
> void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
next prev parent reply other threads:[~2026-01-18 22:08 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-09 16:15 [PATCH v8 00/17] media: rkvdec: Add support for VDPU381 and VDPU383 Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 01/17] media: uapi: HEVC: Add v4l2_ctrl_hevc_ext_sps_[ls]t_rps controls Detlev Casanova
2026-01-18 21:48 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 02/17] media: v4l2-ctrls: Add hevc_ext_sps_[ls]t_rps controls Detlev Casanova
2026-01-18 21:52 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 03/17] media: visl: Add HEVC short and long term RPS sets Detlev Casanova
2026-01-18 21:57 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 04/17] media: rkvdec: Switch to using structs instead of writel Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 05/17] media: rkvdec: Move cabac tables to their own source file Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 06/17] media: rkvdec: Use structs to represent the HW RPS Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 07/17] media: rkvdec: Move h264 functions to common file Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 08/17] media: rkvdec: Move hevc " Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 09/17] media: rkvdec: Add variant specific coded formats list Detlev Casanova
2026-01-18 22:02 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 10/17] media: rkvdec: Add RCB and SRAM support Detlev Casanova
2026-01-18 22:08 ` Nicolas Dufresne [this message]
2026-01-09 16:15 ` [PATCH v8 11/17] media: rkvdec: Support per-variant interrupt handler Detlev Casanova
2026-01-18 22:10 ` Nicolas Dufresne
2026-01-18 22:12 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 12/17] media: rkvdec: Enable all clocks without naming them Detlev Casanova
2026-01-09 16:15 ` [PATCH v8 13/17] media: rkvdec: Disable multicore support Detlev Casanova
2026-01-18 22:13 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 14/17] media: rkvdec: Add H264 support for the VDPU381 variant Detlev Casanova
2026-01-09 20:37 ` Diederik de Haas
2026-01-18 22:18 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 15/17] media: rkvdec: Add H264 support for the VDPU383 variant Detlev Casanova
2026-01-18 22:20 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 16/17] media: rkvdec: Add HEVC support for the VDPU381 variant Detlev Casanova
2026-01-18 22:25 ` Nicolas Dufresne
2026-01-09 16:15 ` [PATCH v8 17/17] media: rkvdec: Add HEVC support for the VDPU383 variant Detlev Casanova
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50211f049bee9ebcb6eb40dec40b7143cd744824.camel@collabora.com \
--to=nicolas.dufresne@collabora.com \
--cc=corbet@lwn.net \
--cc=detlev.casanova@collabora.com \
--cc=didi.debian@cknow.org \
--cc=ezequiel@vanguardiasur.com.ar \
--cc=hansg@kernel.org \
--cc=heiko@sntech.de \
--cc=hverkuil@kernel.org \
--cc=james.cowgill@blaize.com \
--cc=jonas@kwiboo.se \
--cc=kernel@collabora.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=mchehab@kernel.org \
--cc=ribalda@chromium.org \
--cc=sakari.ailus@linux.intel.com \
--cc=yunkec@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®