* [PATCH 00/16] media: platform: rga: Add RGA3 support
@ 2025-10-07 8:31 Sven Püschel
2025-10-07 8:31 ` [PATCH 01/16] media: rockchip: rga: use clk_bulk api Sven Püschel
` (17 more replies)
0 siblings, 18 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
This series adds support for the Raster Graphic Acceleration 3 (RGA3)
peripheral, which is included in the RK3588 SoC. Unlike the RGA2 it
can use the existing rockchip-iommu-v2 driver to handle iommu mappings.
Also the RK3588 contains two independent RGA3 cores.
Only scaling and format conversions between common 8bit RGB/YUV formats
are implemented. Also the color space conversion is fixed to BT601F.
This already allows a practical usage of the RGA3.
This was tested on a Radxa Rock 5T. With the increased clock speeds in
the devicetree around 160 fps were measured when scaling and converting
from RGBA 480x360 to NV12 3840x2160. Without the clock speed scaling a
default clock division factor of 2 is used and only around 80 fps are
reached with one core. The v4l2-compliance tests only complain about
the already failing colorspace propagation:
v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
...
fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() != col
test VIDIOC_S_FMT: FAIL
...
Total for rockchip-rga device /dev/video0: 47, Succeeded: 46, Failed: 1, Warnings: 0
v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
...
fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() != col
test VIDIOC_S_FMT: FAIL
...
Total for rockchip-rga device /dev/video1: 47, Succeeded: 46, Failed: 1, Warnings: 0
v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
...
fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() != col
test VIDIOC_S_FMT: FAIL
...
Total for rockchip-rga device /dev/video2: 47, Succeeded: 46, Failed: 1, Warnings: 0
Each RGA core is a separate /dev/video device. To distinguish the RGA2
core from the RGA3 cores the Card type is set accordingly. Combining all
cores into a single device and scheduling tasks to the best core might
be a future improvement, if it is desired by upstream to handle the
scheduling and selection in kernel space.
Patch 1-2 are general cleanups
Patch 3-12 prepare the rga driver for the RGA3
Patch 13 documments the RGA3 compatible value
Patch 14 adds the RGA3 cores to the rk3588 dtsi
Patch 15 increases the RGA3 core clock speeds
Patch 16 adds RGA3 support to the rga driver
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
Sven Püschel (16):
media: rockchip: rga: use clk_bulk api
media: rockchip: rga: use stride for offset calculation
media: rockchip: rga: align stride to 16 bytes
media: rockchip: rga: move hw specific parts to a dedicated struct
media: rockchip: rga: use card type to specify rga type
media: rockchip: rga: change offset to dma_addresses
media: rockchip: rga: support external iommus
media: rockchip: rga: remove size from rga_frame
media: rockchip: rga: remove stride from rga_frame
media: rockchip: rga: move rga_fmt to rga-hw.h
media: rockchip: rga: add iommu restore function
media: rockchip: rga: handle error interrupt
media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
arm64: dts: rockchip: add rga3 dt nodes
arm64: dts: rockchip: increase rga3 clock speed
media: rockchip: rga: add rga3 support
.../devicetree/bindings/media/rockchip-rga.yaml | 1 +
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 50 +++
drivers/media/platform/rockchip/rga/Makefile | 2 +-
drivers/media/platform/rockchip/rga/rga-buf.c | 78 ++--
drivers/media/platform/rockchip/rga/rga-hw.c | 356 ++++++++++++---
drivers/media/platform/rockchip/rga/rga-hw.h | 15 +-
drivers/media/platform/rockchip/rga/rga.c | 404 ++++++-----------
drivers/media/platform/rockchip/rga/rga.h | 74 ++--
drivers/media/platform/rockchip/rga/rga3-hw.c | 490 +++++++++++++++++++++
drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++
10 files changed, 1246 insertions(+), 410 deletions(-)
---
base-commit: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328
change-id: 20251001-spu-rga3-8a00e018b120
Best regards,
--
Sven Püschel <s.pueschel@pengutronix.de>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 01/16] media: rockchip: rga: use clk_bulk api
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
@ 2025-10-07 8:31 ` Sven Püschel
2025-10-07 8:31 ` [PATCH 02/16] media: rockchip: rga: use stride for offset calculation Sven Püschel
` (16 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Use the clk_bulk API to avoid code duplication for each of the three
clocks.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga.c | 64 ++++---------------------------
drivers/media/platform/rockchip/rga/rga.h | 5 +--
2 files changed, 9 insertions(+), 60 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 776046de979aa0ded6734216bf179c32ae8fe5a9..6438119a6c7aeff1e89e7aa95dcd5d2921fefa08 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -702,48 +702,10 @@ static const struct video_device rga_videodev = {
.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
};
-static int rga_enable_clocks(struct rockchip_rga *rga)
-{
- int ret;
-
- ret = clk_prepare_enable(rga->sclk);
- if (ret) {
- dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(rga->aclk);
- if (ret) {
- dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
- goto err_disable_sclk;
- }
-
- ret = clk_prepare_enable(rga->hclk);
- if (ret) {
- dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
- goto err_disable_aclk;
- }
-
- return 0;
-
-err_disable_aclk:
- clk_disable_unprepare(rga->aclk);
-err_disable_sclk:
- clk_disable_unprepare(rga->sclk);
-
- return ret;
-}
-
-static void rga_disable_clocks(struct rockchip_rga *rga)
-{
- clk_disable_unprepare(rga->sclk);
- clk_disable_unprepare(rga->hclk);
- clk_disable_unprepare(rga->aclk);
-}
-
static int rga_parse_dt(struct rockchip_rga *rga)
{
struct reset_control *core_rst, *axi_rst, *ahb_rst;
+ int ret;
core_rst = devm_reset_control_get(rga->dev, "core");
if (IS_ERR(core_rst)) {
@@ -775,22 +737,10 @@ static int rga_parse_dt(struct rockchip_rga *rga)
udelay(1);
reset_control_deassert(ahb_rst);
- rga->sclk = devm_clk_get(rga->dev, "sclk");
- if (IS_ERR(rga->sclk)) {
- dev_err(rga->dev, "failed to get sclk clock\n");
- return PTR_ERR(rga->sclk);
- }
-
- rga->aclk = devm_clk_get(rga->dev, "aclk");
- if (IS_ERR(rga->aclk)) {
- dev_err(rga->dev, "failed to get aclk clock\n");
- return PTR_ERR(rga->aclk);
- }
-
- rga->hclk = devm_clk_get(rga->dev, "hclk");
- if (IS_ERR(rga->hclk)) {
- dev_err(rga->dev, "failed to get hclk clock\n");
- return PTR_ERR(rga->hclk);
+ ret = devm_clk_bulk_get(rga->dev, ARRAY_SIZE(rga->clks), rga->clks);
+ if (ret) {
+ dev_err(rga->dev, "failed to get clocks\n");
+ return ret;
}
return 0;
@@ -939,7 +889,7 @@ static int __maybe_unused rga_runtime_suspend(struct device *dev)
{
struct rockchip_rga *rga = dev_get_drvdata(dev);
- rga_disable_clocks(rga);
+ clk_bulk_disable_unprepare(ARRAY_SIZE(rga->clks), rga->clks);
return 0;
}
@@ -948,7 +898,7 @@ static int __maybe_unused rga_runtime_resume(struct device *dev)
{
struct rockchip_rga *rga = dev_get_drvdata(dev);
- return rga_enable_clocks(rga);
+ return clk_bulk_prepare_enable(ARRAY_SIZE(rga->clks), rga->clks);
}
static const struct dev_pm_ops rga_pm = {
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index 72a28b120fabfdce39e7773358d0c9528019e882..a922fac0c01a3627f5149c78a1560341428a4fc1 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -6,6 +6,7 @@
#ifndef __RGA_H__
#define __RGA_H__
+#include <linux/clk.h>
#include <linux/platform_device.h>
#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
@@ -81,9 +82,7 @@ struct rockchip_rga {
struct device *dev;
struct regmap *grf;
void __iomem *regs;
- struct clk *sclk;
- struct clk *aclk;
- struct clk *hclk;
+ struct clk_bulk_data clks[3];
struct rockchip_rga_version version;
/* vfd lock */
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 02/16] media: rockchip: rga: use stride for offset calculation
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
2025-10-07 8:31 ` [PATCH 01/16] media: rockchip: rga: use clk_bulk api Sven Püschel
@ 2025-10-07 8:31 ` Sven Püschel
2025-10-07 8:31 ` [PATCH 03/16] media: rockchip: rga: align stride to 16 bytes Sven Püschel
` (15 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Use the stride instead of the width for the offset calculation. This
ensures that the bytesperline value doesn't need to match the width
value of the image.
Furthermore this patch removes the dependency on the uv_factor property
and instead reuses the v4l2_format_info to determine the correct
division factor.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-buf.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
index 730bdf98565a55704cef92345ccf9f486b99b06e..b5e6b1b527ca81721c64d96d984d5e981449c237 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -14,7 +14,6 @@
#include <media/videobuf2-dma-sg.h>
#include <media/videobuf2-v4l2.h>
-#include "rga-hw.h"
#include "rga.h"
static ssize_t fill_descriptors(struct rga_dma_desc *desc, size_t max_desc,
@@ -92,14 +91,19 @@ static int rga_buf_init(struct vb2_buffer *vb)
return 0;
}
-static int get_plane_offset(struct rga_frame *f, int plane)
+static int get_plane_offset(struct rga_frame *f,
+ const struct v4l2_format_info *info,
+ int plane)
{
+ u32 stride = f->pix.plane_fmt[0].bytesperline;
+
if (plane == 0)
return 0;
if (plane == 1)
- return f->width * f->height;
+ return stride * f->height;
if (plane == 2)
- return f->width * f->height + (f->width * f->height / f->fmt->uv_factor);
+ return stride * f->height +
+ (stride * f->height / info->hdiv / info->vdiv);
return -EINVAL;
}
@@ -145,7 +149,7 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
/* Fill the remaining planes */
info = v4l2_format_info(f->fmt->fourcc);
for (i = info->mem_planes; i < info->comp_planes; i++)
- offsets[i] = get_plane_offset(f, i);
+ offsets[i] = get_plane_offset(f, info, i);
rbuf->offset.y_off = offsets[0];
rbuf->offset.u_off = offsets[1];
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 03/16] media: rockchip: rga: align stride to 16 bytes
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
2025-10-07 8:31 ` [PATCH 01/16] media: rockchip: rga: use clk_bulk api Sven Püschel
2025-10-07 8:31 ` [PATCH 02/16] media: rockchip: rga: use stride for offset calculation Sven Püschel
@ 2025-10-07 8:31 ` Sven Püschel
2025-10-07 18:19 ` Nicolas Dufresne
2025-10-07 8:31 ` [PATCH 04/16] media: rockchip: rga: move hw specific parts to a dedicated struct Sven Püschel
` (14 subsequent siblings)
17 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Align the stride to a multiple of 16 according to the RGA3 requirements
mentioned in the datasheet. This also ensures that the stride of the RGA2
is aligned to 4 bytes, as it needs to divide the value by 4 (one word)
before storing it in the register.
Increasing the stride for the alignment also requires to increase the
sizeimage value. This is usually handled by v4l2_fill_pixfmt_mp, but
it doesn't allow to set a stride alignment. Therefore use the generated
values to calculate the total number of lines to properly update the
sizeimage value after the bytesperline has been aligned.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 6438119a6c7aeff1e89e7aa95dcd5d2921fefa08..3cb7ce470c47e39d694e8176875a75fad2717f96 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -459,6 +459,25 @@ static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f
return 0;
}
+static void align_pixfmt(struct v4l2_pix_format_mplane *pix_fmt)
+{
+ int lines;
+ struct v4l2_plane_pix_format *fmt;
+
+ /*
+ * Align stride to 16 for the RGA3 (based on the datasheet)
+ * To not dismiss the v4l2_fill_pixfmt_mp helper
+ * (and manually write it again), we're approximating the new sizeimage
+ */
+ for (fmt = pix_fmt->plane_fmt;
+ fmt < pix_fmt->plane_fmt + pix_fmt->num_planes;
+ fmt++) {
+ lines = DIV_ROUND_UP(fmt->sizeimage, fmt->bytesperline);
+ fmt->bytesperline = (fmt->bytesperline + 0xf) & ~0xf;
+ fmt->sizeimage = fmt->bytesperline * lines;
+ }
+}
+
static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp;
@@ -474,6 +493,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
return PTR_ERR(frm);
v4l2_fill_pixfmt_mp(pix_fmt, frm->fmt->fourcc, frm->width, frm->height);
+ align_pixfmt(pix_fmt);
pix_fmt->field = V4L2_FIELD_NONE;
pix_fmt->colorspace = frm->colorspace;
@@ -496,6 +516,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
(u32)MIN_HEIGHT, (u32)MAX_HEIGHT);
v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt->height);
+ align_pixfmt(pix_fmt);
pix_fmt->field = V4L2_FIELD_NONE;
return 0;
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 04/16] media: rockchip: rga: move hw specific parts to a dedicated struct
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (2 preceding siblings ...)
2025-10-07 8:31 ` [PATCH 03/16] media: rockchip: rga: align stride to 16 bytes Sven Püschel
@ 2025-10-07 8:31 ` Sven Püschel
2025-10-07 8:31 ` [PATCH 05/16] media: rockchip: rga: use card type to specify rga type Sven Püschel
` (13 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
In preparation for the RGA3 unit, move RGA2 specific parts from rga.c
to rga-hw.c and create a struct to reference the RGA2 specific functions
and formats. This also allows to remove the rga-hw.h reference from the
include list of the rga driver.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-hw.c | 183 ++++++++++++++++++++-
drivers/media/platform/rockchip/rga/rga-hw.h | 3 -
drivers/media/platform/rockchip/rga/rga.c | 228 +++++----------------------
drivers/media/platform/rockchip/rga/rga.h | 23 ++-
4 files changed, 242 insertions(+), 195 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index 43ed742a164929927001ef8e8925a29eb93615b2..871fe8c787c8d8dbd55c111c3fba3953d4debf02 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -437,8 +437,8 @@ static void rga_cmd_set(struct rga_ctx *ctx,
PAGE_SIZE, DMA_BIDIRECTIONAL);
}
-void rga_hw_start(struct rockchip_rga *rga,
- struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
+static void rga_hw_start(struct rockchip_rga *rga,
+ struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
{
struct rga_ctx *ctx = rga->curr;
@@ -452,3 +452,182 @@ void rga_hw_start(struct rockchip_rga *rga,
rga_write(rga, RGA_CMD_CTRL, 0x1);
}
+
+static bool rga_handle_irq(struct rockchip_rga *rga)
+{
+ int intr;
+
+ intr = rga_read(rga, RGA_INT) & 0xf;
+
+ rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
+
+ return intr & 0x04;
+}
+
+static void rga_get_version(struct rockchip_rga *rga)
+{
+ rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
+ rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
+}
+
+static struct rga_fmt formats[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_ARGB32,
+ .color_swap = RGA_COLOR_ALPHA_SWAP,
+ .hw_format = RGA_COLOR_FMT_ABGR8888,
+ .depth = 32,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_ABGR32,
+ .color_swap = RGA_COLOR_RB_SWAP,
+ .hw_format = RGA_COLOR_FMT_ABGR8888,
+ .depth = 32,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_XBGR32,
+ .color_swap = RGA_COLOR_RB_SWAP,
+ .hw_format = RGA_COLOR_FMT_XBGR8888,
+ .depth = 32,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .color_swap = RGA_COLOR_NONE_SWAP,
+ .hw_format = RGA_COLOR_FMT_RGB888,
+ .depth = 24,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_BGR24,
+ .color_swap = RGA_COLOR_RB_SWAP,
+ .hw_format = RGA_COLOR_FMT_RGB888,
+ .depth = 24,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_ARGB444,
+ .color_swap = RGA_COLOR_RB_SWAP,
+ .hw_format = RGA_COLOR_FMT_ABGR4444,
+ .depth = 16,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_ARGB555,
+ .color_swap = RGA_COLOR_RB_SWAP,
+ .hw_format = RGA_COLOR_FMT_ABGR1555,
+ .depth = 16,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .color_swap = RGA_COLOR_RB_SWAP,
+ .hw_format = RGA_COLOR_FMT_BGR565,
+ .depth = 16,
+ .uv_factor = 1,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .color_swap = RGA_COLOR_UV_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV420SP,
+ .depth = 12,
+ .uv_factor = 4,
+ .y_div = 2,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV61,
+ .color_swap = RGA_COLOR_UV_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV422SP,
+ .depth = 16,
+ .uv_factor = 2,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .color_swap = RGA_COLOR_NONE_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV420SP,
+ .depth = 12,
+ .uv_factor = 4,
+ .y_div = 2,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .color_swap = RGA_COLOR_NONE_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV420SP,
+ .depth = 12,
+ .uv_factor = 4,
+ .y_div = 2,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV16,
+ .color_swap = RGA_COLOR_NONE_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV422SP,
+ .depth = 16,
+ .uv_factor = 2,
+ .y_div = 1,
+ .x_div = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .color_swap = RGA_COLOR_NONE_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV420P,
+ .depth = 12,
+ .uv_factor = 4,
+ .y_div = 2,
+ .x_div = 2,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YUV422P,
+ .color_swap = RGA_COLOR_NONE_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV422P,
+
+ .depth = 16,
+ .uv_factor = 2,
+ .y_div = 1,
+ .x_div = 2,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YVU420,
+ .color_swap = RGA_COLOR_UV_SWAP,
+ .hw_format = RGA_COLOR_FMT_YUV420P,
+ .depth = 12,
+ .uv_factor = 4,
+ .y_div = 2,
+ .x_div = 2,
+ },
+};
+
+const struct rga_hw rga2_hw = {
+ .formats = formats,
+ .num_formats = ARRAY_SIZE(formats),
+ .cmdbuf_size = RGA_CMDBUF_SIZE,
+ .min_width = MIN_WIDTH,
+ .max_width = MAX_WIDTH,
+ .min_height = MIN_HEIGHT,
+ .max_height = MAX_HEIGHT,
+
+ .start = rga_hw_start,
+ .handle_irq = rga_handle_irq,
+ .get_version = rga_get_version,
+};
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h
index cc6bd7f5b0300364948fd15109c643199d94e5de..1f52fbfad5fb3b8b773f7f03be0603170c5189f6 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.h
+++ b/drivers/media/platform/rockchip/rga/rga-hw.h
@@ -15,9 +15,6 @@
#define MIN_WIDTH 34
#define MIN_HEIGHT 34
-#define DEFAULT_WIDTH 100
-#define DEFAULT_HEIGHT 100
-
#define RGA_TIMEOUT 500
/* Registers address */
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 3cb7ce470c47e39d694e8176875a75fad2717f96..32d24cdf17e9db38541d2b1615c6337def9362c6 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -25,7 +25,6 @@
#include <media/videobuf2-dma-sg.h>
#include <media/videobuf2-v4l2.h>
-#include "rga-hw.h"
#include "rga.h"
static int debug;
@@ -47,7 +46,7 @@ static void device_run(void *prv)
dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- rga_hw_start(rga, vb_to_rga(src), vb_to_rga(dst));
+ rga->hw->start(rga, vb_to_rga(src), vb_to_rga(dst));
spin_unlock_irqrestore(&rga->ctrl_lock, flags);
}
@@ -55,13 +54,8 @@ static void device_run(void *prv)
static irqreturn_t rga_isr(int irq, void *prv)
{
struct rockchip_rga *rga = prv;
- int intr;
- intr = rga_read(rga, RGA_INT) & 0xf;
-
- rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
-
- if (intr & 0x04) {
+ if (rga->hw->handle_irq(rga)) {
struct vb2_v4l2_buffer *src, *dst;
struct rga_ctx *ctx = rga->curr;
@@ -184,177 +178,17 @@ static int rga_setup_ctrls(struct rga_ctx *ctx)
return 0;
}
-static struct rga_fmt formats[] = {
- {
- .fourcc = V4L2_PIX_FMT_ARGB32,
- .color_swap = RGA_COLOR_ALPHA_SWAP,
- .hw_format = RGA_COLOR_FMT_ABGR8888,
- .depth = 32,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ABGR32,
- .color_swap = RGA_COLOR_RB_SWAP,
- .hw_format = RGA_COLOR_FMT_ABGR8888,
- .depth = 32,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_XBGR32,
- .color_swap = RGA_COLOR_RB_SWAP,
- .hw_format = RGA_COLOR_FMT_XBGR8888,
- .depth = 32,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB24,
- .color_swap = RGA_COLOR_NONE_SWAP,
- .hw_format = RGA_COLOR_FMT_RGB888,
- .depth = 24,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGR24,
- .color_swap = RGA_COLOR_RB_SWAP,
- .hw_format = RGA_COLOR_FMT_RGB888,
- .depth = 24,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ARGB444,
- .color_swap = RGA_COLOR_RB_SWAP,
- .hw_format = RGA_COLOR_FMT_ABGR4444,
- .depth = 16,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ARGB555,
- .color_swap = RGA_COLOR_RB_SWAP,
- .hw_format = RGA_COLOR_FMT_ABGR1555,
- .depth = 16,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB565,
- .color_swap = RGA_COLOR_RB_SWAP,
- .hw_format = RGA_COLOR_FMT_BGR565,
- .depth = 16,
- .uv_factor = 1,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV21,
- .color_swap = RGA_COLOR_UV_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV420SP,
- .depth = 12,
- .uv_factor = 4,
- .y_div = 2,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV61,
- .color_swap = RGA_COLOR_UV_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV422SP,
- .depth = 16,
- .uv_factor = 2,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV12,
- .color_swap = RGA_COLOR_NONE_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV420SP,
- .depth = 12,
- .uv_factor = 4,
- .y_div = 2,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .color_swap = RGA_COLOR_NONE_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV420SP,
- .depth = 12,
- .uv_factor = 4,
- .y_div = 2,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV16,
- .color_swap = RGA_COLOR_NONE_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV422SP,
- .depth = 16,
- .uv_factor = 2,
- .y_div = 1,
- .x_div = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV420,
- .color_swap = RGA_COLOR_NONE_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV420P,
- .depth = 12,
- .uv_factor = 4,
- .y_div = 2,
- .x_div = 2,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV422P,
- .color_swap = RGA_COLOR_NONE_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV422P,
- .depth = 16,
- .uv_factor = 2,
- .y_div = 1,
- .x_div = 2,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVU420,
- .color_swap = RGA_COLOR_UV_SWAP,
- .hw_format = RGA_COLOR_FMT_YUV420P,
- .depth = 12,
- .uv_factor = 4,
- .y_div = 2,
- .x_div = 2,
- },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-
-static struct rga_fmt *rga_fmt_find(u32 pixelformat)
+static struct rga_fmt *rga_fmt_find(struct rockchip_rga *rga, u32 pixelformat)
{
unsigned int i;
- for (i = 0; i < NUM_FORMATS; i++) {
- if (formats[i].fourcc == pixelformat)
- return &formats[i];
+ for (i = 0; i < rga->hw->num_formats; i++) {
+ if (rga->hw->formats[i].fourcc == pixelformat)
+ return &rga->hw->formats[i];
}
return NULL;
}
-static struct rga_frame def_frame = {
- .width = DEFAULT_WIDTH,
- .height = DEFAULT_HEIGHT,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
- .crop.left = 0,
- .crop.top = 0,
- .crop.width = DEFAULT_WIDTH,
- .crop.height = DEFAULT_HEIGHT,
- .fmt = &formats[0],
-};
-
struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type)
{
if (V4L2_TYPE_IS_OUTPUT(type))
@@ -369,6 +203,19 @@ static int rga_open(struct file *file)
struct rockchip_rga *rga = video_drvdata(file);
struct rga_ctx *ctx = NULL;
int ret = 0;
+ struct rga_frame def_frame = {
+ .width = clamp(DEFAULT_WIDTH, rga->hw->min_width, rga->hw->max_width),
+ .height = clamp(DEFAULT_HEIGHT, rga->hw->min_height, rga->hw->max_height),
+ .colorspace = V4L2_COLORSPACE_DEFAULT,
+ .crop.left = 0,
+ .crop.top = 0,
+ .crop.width = clamp(DEFAULT_WIDTH, rga->hw->min_width, rga->hw->max_width),
+ .crop.height = clamp(DEFAULT_HEIGHT, rga->hw->min_height, rga->hw->max_height),
+ .fmt = &rga->hw->formats[0],
+ };
+
+ def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
+ def_frame.size = def_frame.stride * def_frame.height;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -448,12 +295,13 @@ vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
{
+ struct rockchip_rga *rga = video_drvdata(file);
struct rga_fmt *fmt;
- if (f->index >= NUM_FORMATS)
+ if (f->index >= rga->hw->num_formats)
return -EINVAL;
- fmt = &formats[f->index];
+ fmt = &rga->hw->formats[f->index];
f->pixelformat = fmt->fourcc;
return 0;
@@ -504,16 +352,18 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp;
+ struct rockchip_rga *rga = video_drvdata(file);
+ const struct rga_hw *hw = rga->hw;
struct rga_fmt *fmt;
- fmt = rga_fmt_find(pix_fmt->pixelformat);
+ fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
if (!fmt)
- fmt = &formats[0];
+ fmt = &hw->formats[0];
pix_fmt->width = clamp(pix_fmt->width,
- (u32)MIN_WIDTH, (u32)MAX_WIDTH);
+ hw->min_width, hw->max_width);
pix_fmt->height = clamp(pix_fmt->height,
- (u32)MIN_HEIGHT, (u32)MAX_HEIGHT);
+ hw->min_height, hw->max_height);
v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt->height);
align_pixfmt(pix_fmt);
@@ -551,7 +401,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
frm->size = 0;
for (i = 0; i < pix_fmt->num_planes; i++)
frm->size += pix_fmt->plane_fmt[i].sizeimage;
- frm->fmt = rga_fmt_find(pix_fmt->pixelformat);
+ frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
frm->stride = pix_fmt->plane_fmt[0].bytesperline;
frm->colorspace = pix_fmt->colorspace;
@@ -672,7 +522,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
if (s->r.left + s->r.width > f->width ||
s->r.top + s->r.height > f->height ||
- s->r.width < MIN_WIDTH || s->r.height < MIN_HEIGHT) {
+ s->r.width < rga->hw->min_width || s->r.height < rga->hw->min_height) {
v4l2_dbg(debug, 1, &rga->v4l2_dev, "unsupported crop value.\n");
return -EINVAL;
}
@@ -781,6 +631,10 @@ static int rga_probe(struct platform_device *pdev)
if (!rga)
return -ENOMEM;
+ rga->hw = of_device_get_match_data(&pdev->dev);
+ if (!rga->hw)
+ return dev_err_probe(&pdev->dev, -ENODEV, "failed to get match data\n");
+
rga->dev = &pdev->dev;
spin_lock_init(&rga->ctrl_lock);
mutex_init(&rga->mutex);
@@ -844,8 +698,7 @@ static int rga_probe(struct platform_device *pdev)
if (ret < 0)
goto rel_m2m;
- rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
- rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
+ rga->hw->get_version(rga);
v4l2_info(&rga->v4l2_dev, "HW Version: 0x%02x.%02x\n",
rga->version.major, rga->version.minor);
@@ -853,7 +706,7 @@ static int rga_probe(struct platform_device *pdev)
pm_runtime_put(rga->dev);
/* Create CMD buffer */
- rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
+ rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, rga->hw->cmdbuf_size,
&rga->cmdbuf_phy, GFP_KERNEL,
DMA_ATTR_WRITE_COMBINE);
if (!rga->cmdbuf_virt) {
@@ -861,9 +714,6 @@ static int rga_probe(struct platform_device *pdev)
goto rel_m2m;
}
- def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
- def_frame.size = def_frame.stride * def_frame.height;
-
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
if (ret) {
v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
@@ -876,7 +726,7 @@ static int rga_probe(struct platform_device *pdev)
return 0;
free_dma:
- dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
+ dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, rga->cmdbuf_virt,
rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
rel_m2m:
v4l2_m2m_release(rga->m2m_dev);
@@ -894,7 +744,7 @@ static void rga_remove(struct platform_device *pdev)
{
struct rockchip_rga *rga = platform_get_drvdata(pdev);
- dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
+ dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, rga->cmdbuf_virt,
rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
v4l2_info(&rga->v4l2_dev, "Removing\n");
@@ -930,9 +780,11 @@ static const struct dev_pm_ops rga_pm = {
static const struct of_device_id rockchip_rga_match[] = {
{
.compatible = "rockchip,rk3288-rga",
+ .data = &rga2_hw,
},
{
.compatible = "rockchip,rk3399-rga",
+ .data = &rga2_hw,
},
{},
};
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index a922fac0c01a3627f5149c78a1560341428a4fc1..61a00f56ce9b31968881e22bef873612b62e21d9 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -14,6 +14,9 @@
#define RGA_NAME "rockchip-rga"
+#define DEFAULT_WIDTH 100
+#define DEFAULT_HEIGHT 100
+
struct rga_fmt {
u32 fourcc;
int depth;
@@ -74,6 +77,8 @@ static inline struct rga_ctx *file_to_rga_ctx(struct file *filp)
return container_of(file_to_v4l2_fh(filp), struct rga_ctx, fh);
}
+struct rga_hw;
+
struct rockchip_rga {
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
@@ -93,6 +98,8 @@ struct rockchip_rga {
struct rga_ctx *curr;
dma_addr_t cmdbuf_phy;
void *cmdbuf_virt;
+
+ const struct rga_hw *hw;
};
struct rga_addr_offset {
@@ -143,7 +150,19 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
rga_write(rga, reg, temp);
};
-void rga_hw_start(struct rockchip_rga *rga,
- struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
+struct rga_hw {
+ struct rga_fmt *formats;
+ u32 num_formats;
+ size_t cmdbuf_size;
+ u32 min_width, min_height;
+ u32 max_width, max_height;
+
+ void (*start)(struct rockchip_rga *rga,
+ struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
+ bool (*handle_irq)(struct rockchip_rga *rga);
+ void (*get_version)(struct rockchip_rga *rga);
+};
+
+extern const struct rga_hw rga2_hw;
#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 05/16] media: rockchip: rga: use card type to specify rga type
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (3 preceding siblings ...)
2025-10-07 8:31 ` [PATCH 04/16] media: rockchip: rga: move hw specific parts to a dedicated struct Sven Püschel
@ 2025-10-07 8:31 ` Sven Püschel
2025-10-07 8:31 ` [PATCH 06/16] media: rockchip: rga: change offset to dma_addresses Sven Püschel
` (12 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
In preparation of the RGA3 support add a filed to the rga_hw struct
to specify the desired card type value. This allows the user to
differentiate the RGA2 and RGA3 video device nodes.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-hw.c | 1 +
drivers/media/platform/rockchip/rga/rga.c | 4 +++-
drivers/media/platform/rockchip/rga/rga.h | 1 +
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index 871fe8c787c8d8dbd55c111c3fba3953d4debf02..a44befe4054d19e3b921c0827af4d36cf077e61f 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -619,6 +619,7 @@ static struct rga_fmt formats[] = {
};
const struct rga_hw rga2_hw = {
+ .card_type = "rga2",
.formats = formats,
.num_formats = ARRAY_SIZE(formats),
.cmdbuf_size = RGA_CMDBUF_SIZE,
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 32d24cdf17e9db38541d2b1615c6337def9362c6..ce55b48ef9fa8fbb2b265455cc559a4216609d4f 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -286,8 +286,10 @@ static const struct v4l2_file_operations rga_fops = {
static int
vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
{
+ struct rockchip_rga *rga = video_drvdata(file);
+
strscpy(cap->driver, RGA_NAME, sizeof(cap->driver));
- strscpy(cap->card, "rockchip-rga", sizeof(cap->card));
+ strscpy(cap->card, rga->hw->card_type, sizeof(cap->card));
strscpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info));
return 0;
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index 61a00f56ce9b31968881e22bef873612b62e21d9..257267738d5d179d9ec4fcb5c8729783c9b713de 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -151,6 +151,7 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
};
struct rga_hw {
+ const char *card_type;
struct rga_fmt *formats;
u32 num_formats;
size_t cmdbuf_size;
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 06/16] media: rockchip: rga: change offset to dma_addresses
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (4 preceding siblings ...)
2025-10-07 8:31 ` [PATCH 05/16] media: rockchip: rga: use card type to specify rga type Sven Püschel
@ 2025-10-07 8:31 ` Sven Püschel
2025-10-07 8:32 ` [PATCH 07/16] media: rockchip: rga: support external iommus Sven Püschel
` (11 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:31 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Change the offset to dma_addresses, as the current naming is misleading.
The offset naming comes from the fact that it references the offset in
the mapped iommu address space. But from the hardware point of view this
is an address, as also pointed out by the register naming
(e.g. RGA_DST_Y_RGB_BASE_ADDR). Therefore also change the type to
dma_addr_t, as with an external iommu driver this would also be the
correct type.
This change is a preparation for the RGA3 support, which uses an external
iommu and therefore just gets an dma_addr_t for each buffer. The field
renaming allows to reuse the existing fields of rga_vb_buffer to store
these values.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-buf.c | 12 +--
drivers/media/platform/rockchip/rga/rga-hw.c | 105 +++++++++++++-------------
drivers/media/platform/rockchip/rga/rga.h | 12 +--
3 files changed, 64 insertions(+), 65 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
index b5e6b1b527ca81721c64d96d984d5e981449c237..0d188b3176cf3e175e865db5cfa26d565bf846ec 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -118,7 +118,7 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
size_t curr_desc = 0;
int i;
const struct v4l2_format_info *info;
- unsigned int offsets[VIDEO_MAX_PLANES];
+ unsigned int dma_addrs[VIDEO_MAX_PLANES];
if (IS_ERR(f))
return PTR_ERR(f);
@@ -142,18 +142,18 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
"Failed to map video buffer to RGA\n");
return n_desc;
}
- offsets[i] = curr_desc << PAGE_SHIFT;
+ dma_addrs[i] = curr_desc << PAGE_SHIFT;
curr_desc += n_desc;
}
/* Fill the remaining planes */
info = v4l2_format_info(f->fmt->fourcc);
for (i = info->mem_planes; i < info->comp_planes; i++)
- offsets[i] = get_plane_offset(f, info, i);
+ dma_addrs[i] = dma_addrs[0] + get_plane_offset(f, info, i);
- rbuf->offset.y_off = offsets[0];
- rbuf->offset.u_off = offsets[1];
- rbuf->offset.v_off = offsets[2];
+ rbuf->dma_addrs.y_addr = dma_addrs[0];
+ rbuf->dma_addrs.u_addr = dma_addrs[1];
+ rbuf->dma_addrs.v_addr = dma_addrs[2];
return 0;
}
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index a44befe4054d19e3b921c0827af4d36cf077e61f..f3aef0b5ce25870764bd59f4241e2bda332bbd1f 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -16,11 +16,11 @@ enum e_rga_start_pos {
RB = 3,
};
-struct rga_corners_addr_offset {
- struct rga_addr_offset left_top;
- struct rga_addr_offset right_top;
- struct rga_addr_offset left_bottom;
- struct rga_addr_offset right_bottom;
+struct rga_corners_addrs {
+ struct rga_addrs left_top;
+ struct rga_addrs right_top;
+ struct rga_addrs left_bottom;
+ struct rga_addrs right_bottom;
};
static unsigned int rga_get_scaling(unsigned int src, unsigned int dst)
@@ -36,48 +36,47 @@ static unsigned int rga_get_scaling(unsigned int src, unsigned int dst)
return (src > dst) ? ((dst << 16) / src) : ((src << 16) / dst);
}
-static struct rga_corners_addr_offset
-rga_get_addr_offset(struct rga_frame *frm, struct rga_addr_offset *offset,
- unsigned int x, unsigned int y, unsigned int w, unsigned int h)
+static struct rga_corners_addrs
+rga_get_corner_addrs(struct rga_frame *frm, struct rga_addrs *addrs,
+ unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
- struct rga_corners_addr_offset offsets;
- struct rga_addr_offset *lt, *lb, *rt, *rb;
+ struct rga_corners_addrs corner_addrs;
+ struct rga_addrs *lt, *lb, *rt, *rb;
unsigned int x_div = 0,
y_div = 0, uv_stride = 0, pixel_width = 0;
- lt = &offsets.left_top;
- lb = &offsets.left_bottom;
- rt = &offsets.right_top;
- rb = &offsets.right_bottom;
+ lt = &corner_addrs.left_top;
+ lb = &corner_addrs.left_bottom;
+ rt = &corner_addrs.right_top;
+ rb = &corner_addrs.right_bottom;
x_div = frm->fmt->x_div;
y_div = frm->fmt->y_div;
uv_stride = frm->stride / x_div;
pixel_width = frm->stride / frm->width;
- lt->y_off = offset->y_off + y * frm->stride + x * pixel_width;
- lt->u_off = offset->u_off + (y / y_div) * uv_stride + x / x_div;
- lt->v_off = offset->v_off + (y / y_div) * uv_stride + x / x_div;
+ lt->y_addr = addrs->y_addr + y * frm->stride + x * pixel_width;
+ lt->u_addr = addrs->u_addr + (y / y_div) * uv_stride + x / x_div;
+ lt->v_addr = addrs->v_addr + (y / y_div) * uv_stride + x / x_div;
- lb->y_off = lt->y_off + (h - 1) * frm->stride;
- lb->u_off = lt->u_off + (h / y_div - 1) * uv_stride;
- lb->v_off = lt->v_off + (h / y_div - 1) * uv_stride;
+ lb->y_addr = lt->y_addr + (h - 1) * frm->stride;
+ lb->u_addr = lt->u_addr + (h / y_div - 1) * uv_stride;
+ lb->v_addr = lt->v_addr + (h / y_div - 1) * uv_stride;
- rt->y_off = lt->y_off + (w - 1) * pixel_width;
- rt->u_off = lt->u_off + w / x_div - 1;
- rt->v_off = lt->v_off + w / x_div - 1;
+ rt->y_addr = lt->y_addr + (w - 1) * pixel_width;
+ rt->u_addr = lt->u_addr + w / x_div - 1;
+ rt->v_addr = lt->v_addr + w / x_div - 1;
- rb->y_off = lb->y_off + (w - 1) * pixel_width;
- rb->u_off = lb->u_off + w / x_div - 1;
- rb->v_off = lb->v_off + w / x_div - 1;
+ rb->y_addr = lb->y_addr + (w - 1) * pixel_width;
+ rb->u_addr = lb->u_addr + w / x_div - 1;
+ rb->v_addr = lb->v_addr + w / x_div - 1;
- return offsets;
+ return corner_addrs;
}
-static struct rga_addr_offset *rga_lookup_draw_pos(struct
- rga_corners_addr_offset
- * offsets, u32 rotate_mode,
- u32 mirr_mode)
+static struct rga_addrs *rga_lookup_draw_pos(struct rga_corners_addrs *corner_addrs,
+ u32 rotate_mode,
+ u32 mirr_mode)
{
static enum e_rga_start_pos rot_mir_point_matrix[4][4] = {
{
@@ -94,18 +93,18 @@ static struct rga_addr_offset *rga_lookup_draw_pos(struct
},
};
- if (!offsets)
+ if (!corner_addrs)
return NULL;
switch (rot_mir_point_matrix[rotate_mode][mirr_mode]) {
case LT:
- return &offsets->left_top;
+ return &corner_addrs->left_top;
case LB:
- return &offsets->left_bottom;
+ return &corner_addrs->left_bottom;
case RT:
- return &offsets->right_top;
+ return &corner_addrs->right_top;
case RB:
- return &offsets->right_bottom;
+ return &corner_addrs->right_bottom;
}
return NULL;
@@ -310,9 +309,9 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
}
static void rga_cmd_set_src_info(struct rga_ctx *ctx,
- struct rga_addr_offset *offset)
+ struct rga_addrs *addrs)
{
- struct rga_corners_addr_offset src_offsets;
+ struct rga_corners_addrs src_corner_addrs;
struct rockchip_rga *rga = ctx->rga;
u32 *dest = rga->cmdbuf_virt;
unsigned int src_h, src_w, src_x, src_y;
@@ -325,22 +324,22 @@ static void rga_cmd_set_src_info(struct rga_ctx *ctx,
/*
* Calculate the source framebuffer base address with offset pixel.
*/
- src_offsets = rga_get_addr_offset(&ctx->in, offset,
- src_x, src_y, src_w, src_h);
+ src_corner_addrs = rga_get_corner_addrs(&ctx->in, addrs,
+ src_x, src_y, src_w, src_h);
dest[(RGA_SRC_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
- src_offsets.left_top.y_off;
+ src_corner_addrs.left_top.y_addr;
dest[(RGA_SRC_CB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
- src_offsets.left_top.u_off;
+ src_corner_addrs.left_top.u_addr;
dest[(RGA_SRC_CR_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
- src_offsets.left_top.v_off;
+ src_corner_addrs.left_top.v_addr;
}
static void rga_cmd_set_dst_info(struct rga_ctx *ctx,
- struct rga_addr_offset *offset)
+ struct rga_addrs *addrs)
{
- struct rga_addr_offset *dst_offset;
- struct rga_corners_addr_offset offsets;
+ struct rga_addrs *dst_addrs;
+ struct rga_corners_addrs corner_addrs;
struct rockchip_rga *rga = ctx->rga;
u32 *dest = rga->cmdbuf_virt;
unsigned int dst_h, dst_w, dst_x, dst_y;
@@ -375,15 +374,15 @@ static void rga_cmd_set_dst_info(struct rga_ctx *ctx,
/*
* Configure the dest framebuffer base address with pixel offset.
*/
- offsets = rga_get_addr_offset(&ctx->out, offset, dst_x, dst_y, dst_w, dst_h);
- dst_offset = rga_lookup_draw_pos(&offsets, rot_mode, mir_mode);
+ corner_addrs = rga_get_corner_addrs(&ctx->out, addrs, dst_x, dst_y, dst_w, dst_h);
+ dst_addrs = rga_lookup_draw_pos(&corner_addrs, rot_mode, mir_mode);
dest[(RGA_DST_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
- dst_offset->y_off;
+ dst_addrs->y_addr;
dest[(RGA_DST_CB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
- dst_offset->u_off;
+ dst_addrs->u_addr;
dest[(RGA_DST_CR_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] =
- dst_offset->v_off;
+ dst_addrs->v_addr;
}
static void rga_cmd_set_mode(struct rga_ctx *ctx)
@@ -426,8 +425,8 @@ static void rga_cmd_set(struct rga_ctx *ctx,
rga_cmd_set_dst_addr(ctx, dst->dma_desc_pa);
rga_cmd_set_mode(ctx);
- rga_cmd_set_src_info(ctx, &src->offset);
- rga_cmd_set_dst_info(ctx, &dst->offset);
+ rga_cmd_set_src_info(ctx, &src->dma_addrs);
+ rga_cmd_set_dst_info(ctx, &dst->dma_addrs);
rga_cmd_set_trans_info(ctx);
rga_write(rga, RGA_CMD_BASE, rga->cmdbuf_phy);
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index 257267738d5d179d9ec4fcb5c8729783c9b713de..fa47cb35f2623fc5226cb23d1d1d793d5dcd1dc7 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -102,10 +102,10 @@ struct rockchip_rga {
const struct rga_hw *hw;
};
-struct rga_addr_offset {
- unsigned int y_off;
- unsigned int u_off;
- unsigned int v_off;
+struct rga_addrs {
+ dma_addr_t y_addr;
+ dma_addr_t u_addr;
+ dma_addr_t v_addr;
};
struct rga_vb_buffer {
@@ -117,8 +117,8 @@ struct rga_vb_buffer {
dma_addr_t dma_desc_pa;
size_t n_desc;
- /* Plane offsets of this buffer into the mapping */
- struct rga_addr_offset offset;
+ /* Plane DMA addresses after the MMU mapping of the buffer */
+ struct rga_addrs dma_addrs;
};
static inline struct rga_vb_buffer *vb_to_rga(struct vb2_v4l2_buffer *vb)
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 07/16] media: rockchip: rga: support external iommus
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (5 preceding siblings ...)
2025-10-07 8:31 ` [PATCH 06/16] media: rockchip: rga: change offset to dma_addresses Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:32 ` [PATCH 08/16] media: rockchip: rga: remove size from rga_frame Sven Püschel
` (10 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
In preparation for the RGA3 add support for external iommus. This is a
transition step to just disable the RGA2 specific mmu table setup code.
Currently a simple rga_hw struct field is used to set the internal iommu.
But to handle the case of more sophisticated detection mechanisms
(e.g. check for an iommu property in the device tree), it is abstracted
by an inline function.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-buf.c | 46 ++++++++++++++++-----------
drivers/media/platform/rockchip/rga/rga-hw.c | 1 +
drivers/media/platform/rockchip/rga/rga.c | 11 +++++--
drivers/media/platform/rockchip/rga/rga.h | 6 ++++
4 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
index 0d188b3176cf3e175e865db5cfa26d565bf846ec..26b66b0c7e008308c24433f061a738a3985484b6 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -12,6 +12,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-sg.h>
+#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-v4l2.h>
#include "rga.h"
@@ -79,14 +80,16 @@ static int rga_buf_init(struct vb2_buffer *vb)
struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type);
size_t n_desc = 0;
- n_desc = DIV_ROUND_UP(f->size, PAGE_SIZE);
+ if (rga_has_internal_iommu(rga)) {
+ n_desc = DIV_ROUND_UP(f->size, PAGE_SIZE);
- rbuf->n_desc = n_desc;
- rbuf->dma_desc = dma_alloc_coherent(rga->dev,
- rbuf->n_desc * sizeof(*rbuf->dma_desc),
- &rbuf->dma_desc_pa, GFP_KERNEL);
- if (!rbuf->dma_desc)
- return -ENOMEM;
+ rbuf->n_desc = n_desc;
+ rbuf->dma_desc = dma_alloc_coherent(rga->dev,
+ rbuf->n_desc * sizeof(*rbuf->dma_desc),
+ &rbuf->dma_desc_pa, GFP_KERNEL);
+ if (!rbuf->dma_desc)
+ return -ENOMEM;
+ }
return 0;
}
@@ -133,17 +136,21 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
for (i = 0; i < vb->num_planes; i++) {
vb2_set_plane_payload(vb, i, f->pix.plane_fmt[i].sizeimage);
- /* Create local MMU table for RGA */
- n_desc = fill_descriptors(&rbuf->dma_desc[curr_desc],
- rbuf->n_desc - curr_desc,
- vb2_dma_sg_plane_desc(vb, i));
- if (n_desc < 0) {
- v4l2_err(&ctx->rga->v4l2_dev,
- "Failed to map video buffer to RGA\n");
- return n_desc;
+ if (rga_has_internal_iommu(ctx->rga)) {
+ /* Create local MMU table for RGA */
+ n_desc = fill_descriptors(&rbuf->dma_desc[curr_desc],
+ rbuf->n_desc - curr_desc,
+ vb2_dma_sg_plane_desc(vb, i));
+ if (n_desc < 0) {
+ v4l2_err(&ctx->rga->v4l2_dev,
+ "Failed to map video buffer to RGA\n");
+ return n_desc;
+ }
+ dma_addrs[i] = curr_desc << PAGE_SHIFT;
+ curr_desc += n_desc;
+ } else {
+ dma_addrs[i] = vb2_dma_contig_plane_dma_addr(vb, i);
}
- dma_addrs[i] = curr_desc << PAGE_SHIFT;
- curr_desc += n_desc;
}
/* Fill the remaining planes */
@@ -173,8 +180,9 @@ static void rga_buf_cleanup(struct vb2_buffer *vb)
struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct rockchip_rga *rga = ctx->rga;
- dma_free_coherent(rga->dev, rbuf->n_desc * sizeof(*rbuf->dma_desc),
- rbuf->dma_desc, rbuf->dma_desc_pa);
+ if (rga_has_internal_iommu(rga))
+ dma_free_coherent(rga->dev, rbuf->n_desc * sizeof(*rbuf->dma_desc),
+ rbuf->dma_desc, rbuf->dma_desc_pa);
}
static void rga_buf_return_buffers(struct vb2_queue *q,
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index f3aef0b5ce25870764bd59f4241e2bda332bbd1f..04d72ecce7cdd47df8457b97c5ec4cff9cd7430b 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -619,6 +619,7 @@ static struct rga_fmt formats[] = {
const struct rga_hw rga2_hw = {
.card_type = "rga2",
+ .has_internal_iommu = true,
.formats = formats,
.num_formats = ARRAY_SIZE(formats),
.cmdbuf_size = RGA_CMDBUF_SIZE,
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index ce55b48ef9fa8fbb2b265455cc559a4216609d4f..b8e4be3f9acd8a73a3d4e947aeeef9095543fb49 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -23,6 +23,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-sg.h>
+#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-v4l2.h>
#include "rga.h"
@@ -95,13 +96,16 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
src_vq->drv_priv = ctx;
src_vq->ops = &rga_qops;
- src_vq->mem_ops = &vb2_dma_sg_memops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
src_vq->gfp_flags = __GFP_DMA32;
src_vq->buf_struct_size = sizeof(struct rga_vb_buffer);
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
src_vq->lock = &ctx->rga->mutex;
src_vq->dev = ctx->rga->v4l2_dev.dev;
+ if (rga_has_internal_iommu(ctx->rga))
+ src_vq->mem_ops = &vb2_dma_sg_memops;
+
ret = vb2_queue_init(src_vq);
if (ret)
return ret;
@@ -110,13 +114,16 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
dst_vq->drv_priv = ctx;
dst_vq->ops = &rga_qops;
- dst_vq->mem_ops = &vb2_dma_sg_memops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
dst_vq->gfp_flags = __GFP_DMA32;
dst_vq->buf_struct_size = sizeof(struct rga_vb_buffer);
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
dst_vq->lock = &ctx->rga->mutex;
dst_vq->dev = ctx->rga->v4l2_dev.dev;
+ if (rga_has_internal_iommu(ctx->rga))
+ dst_vq->mem_ops = &vb2_dma_sg_memops;
+
return vb2_queue_init(dst_vq);
}
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index fa47cb35f2623fc5226cb23d1d1d793d5dcd1dc7..82ead58719f3baadb77575896ca2d430aa8e3dc6 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -152,6 +152,7 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
struct rga_hw {
const char *card_type;
+ bool has_internal_iommu;
struct rga_fmt *formats;
u32 num_formats;
size_t cmdbuf_size;
@@ -164,6 +165,11 @@ struct rga_hw {
void (*get_version)(struct rockchip_rga *rga);
};
+static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
+{
+ return rga->hw->has_internal_iommu;
+}
+
extern const struct rga_hw rga2_hw;
#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 08/16] media: rockchip: rga: remove size from rga_frame
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (6 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 07/16] media: rockchip: rga: support external iommus Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:32 ` [PATCH 09/16] media: rockchip: rga: remove stride " Sven Püschel
` (9 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
The size member is only used for the mmu page table mapping.
Therefore avoid storing the value and instead only calculate it
in place. This also avoids the calculation entirely when an external
iommu is used.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-buf.c | 6 +++++-
drivers/media/platform/rockchip/rga/rga.c | 8 ++------
drivers/media/platform/rockchip/rga/rga.h | 1 -
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
index 26b66b0c7e008308c24433f061a738a3985484b6..e44fe870fb9e34aa93404b7a60022fe441adf8f9 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -79,9 +79,13 @@ static int rga_buf_init(struct vb2_buffer *vb)
struct rockchip_rga *rga = ctx->rga;
struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type);
size_t n_desc = 0;
+ u32 size = 0;
+ u8 i;
if (rga_has_internal_iommu(rga)) {
- n_desc = DIV_ROUND_UP(f->size, PAGE_SIZE);
+ for (i = 0; i < f->pix.num_planes; i++)
+ size += f->pix.plane_fmt[i].sizeimage;
+ n_desc = DIV_ROUND_UP(size, PAGE_SIZE);
rbuf->n_desc = n_desc;
rbuf->dma_desc = dma_alloc_coherent(rga->dev,
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index b8e4be3f9acd8a73a3d4e947aeeef9095543fb49..c5f25869d0cd08a794330954ec414f0428b647d8 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -222,7 +222,6 @@ static int rga_open(struct file *file)
};
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
- def_frame.size = def_frame.stride * def_frame.height;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -407,9 +406,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
return PTR_ERR(frm);
frm->width = pix_fmt->width;
frm->height = pix_fmt->height;
- frm->size = 0;
- for (i = 0; i < pix_fmt->num_planes; i++)
- frm->size += pix_fmt->plane_fmt[i].sizeimage;
frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
frm->stride = pix_fmt->plane_fmt[0].bytesperline;
frm->colorspace = pix_fmt->colorspace;
@@ -423,10 +419,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
frm->pix = *pix_fmt;
v4l2_dbg(debug, 1, &rga->v4l2_dev,
- "[%s] fmt - %p4cc %dx%d (stride %d, sizeimage %d)\n",
+ "[%s] fmt - %p4cc %dx%d (stride %d)\n",
V4L2_TYPE_IS_OUTPUT(f->type) ? "OUTPUT" : "CAPTURE",
&frm->fmt->fourcc, frm->width, frm->height,
- frm->stride, frm->size);
+ frm->stride);
for (i = 0; i < pix_fmt->num_planes; i++) {
v4l2_dbg(debug, 1, &rga->v4l2_dev,
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index 82ead58719f3baadb77575896ca2d430aa8e3dc6..5aedda2f187e4bfef42c8755c4fc4b1ee5453e8e 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -42,7 +42,6 @@ struct rga_frame {
/* Variables that can calculated once and reused */
u32 stride;
- u32 size;
};
struct rga_dma_desc {
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 09/16] media: rockchip: rga: remove stride from rga_frame
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (7 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 08/16] media: rockchip: rga: remove size from rga_frame Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:32 ` [PATCH 10/16] media: rockchip: rga: move rga_fmt to rga-hw.h Sven Püschel
` (8 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Remove the stride variable from rga_frame. Despite the comment it
didn't involve any calculation and is just a copy of the
plane_fmt[0].bytesperline value. Therefore avoid this struct member
and use the bytesperline value directly in the places where it is
required.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-hw.c | 20 ++++++++++++--------
drivers/media/platform/rockchip/rga/rga.c | 5 +----
drivers/media/platform/rockchip/rga/rga.h | 3 ---
3 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index 04d72ecce7cdd47df8457b97c5ec4cff9cd7430b..66b23c4a4cf1488ce42a7ab1901daaaa55b28fe0 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -43,7 +43,7 @@ rga_get_corner_addrs(struct rga_frame *frm, struct rga_addrs *addrs,
struct rga_corners_addrs corner_addrs;
struct rga_addrs *lt, *lb, *rt, *rb;
unsigned int x_div = 0,
- y_div = 0, uv_stride = 0, pixel_width = 0;
+ y_div = 0, y_stride = 0, uv_stride = 0, pixel_width = 0;
lt = &corner_addrs.left_top;
lb = &corner_addrs.left_bottom;
@@ -52,14 +52,15 @@ rga_get_corner_addrs(struct rga_frame *frm, struct rga_addrs *addrs,
x_div = frm->fmt->x_div;
y_div = frm->fmt->y_div;
- uv_stride = frm->stride / x_div;
- pixel_width = frm->stride / frm->width;
+ y_stride = frm->pix.plane_fmt[0].bytesperline;
+ uv_stride = y_stride / x_div;
+ pixel_width = y_stride / frm->width;
- lt->y_addr = addrs->y_addr + y * frm->stride + x * pixel_width;
+ lt->y_addr = addrs->y_addr + y * y_stride + x * pixel_width;
lt->u_addr = addrs->u_addr + (y / y_div) * uv_stride + x / x_div;
lt->v_addr = addrs->v_addr + (y / y_div) * uv_stride + x / x_div;
- lb->y_addr = lt->y_addr + (h - 1) * frm->stride;
+ lb->y_addr = lt->y_addr + (h - 1) * y_stride;
lb->u_addr = lt->u_addr + (h / y_div - 1) * uv_stride;
lb->v_addr = lt->v_addr + (h / y_div - 1) * uv_stride;
@@ -163,6 +164,7 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
union rga_src_act_info src_act_info;
union rga_dst_vir_info dst_vir_info;
union rga_dst_act_info dst_act_info;
+ u32 in_stride, out_stride;
src_h = ctx->in.crop.height;
src_w = ctx->in.crop.width;
@@ -285,13 +287,15 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
* Calculate the framebuffer virtual strides and active size,
* note that the step of vir_stride / vir_width is 4 byte words
*/
- src_vir_info.data.vir_stride = ctx->in.stride >> 2;
- src_vir_info.data.vir_width = ctx->in.stride >> 2;
+ in_stride = ctx->in.pix.plane_fmt[0].bytesperline;
+ src_vir_info.data.vir_stride = in_stride >> 2;
+ src_vir_info.data.vir_width = in_stride >> 2;
src_act_info.data.act_height = src_h - 1;
src_act_info.data.act_width = src_w - 1;
- dst_vir_info.data.vir_stride = ctx->out.stride >> 2;
+ out_stride = ctx->out.pix.plane_fmt[0].bytesperline;
+ dst_vir_info.data.vir_stride = out_stride >> 2;
dst_act_info.data.act_height = dst_h - 1;
dst_act_info.data.act_width = dst_w - 1;
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index c5f25869d0cd08a794330954ec414f0428b647d8..6e1a4a6dc6309a6d6d9a3aac0fe982e7200c96de 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -221,8 +221,6 @@ static int rga_open(struct file *file)
.fmt = &rga->hw->formats[0],
};
- def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
-
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
@@ -407,7 +405,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
frm->width = pix_fmt->width;
frm->height = pix_fmt->height;
frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
- frm->stride = pix_fmt->plane_fmt[0].bytesperline;
frm->colorspace = pix_fmt->colorspace;
/* Reset crop settings */
@@ -422,7 +419,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
"[%s] fmt - %p4cc %dx%d (stride %d)\n",
V4L2_TYPE_IS_OUTPUT(f->type) ? "OUTPUT" : "CAPTURE",
&frm->fmt->fourcc, frm->width, frm->height,
- frm->stride);
+ pix_fmt->plane_fmt[0].bytesperline);
for (i = 0; i < pix_fmt->num_planes; i++) {
v4l2_dbg(debug, 1, &rga->v4l2_dev,
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index 5aedda2f187e4bfef42c8755c4fc4b1ee5453e8e..d5ec873adc280bc2238b227d2f0c649ca345b836 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -39,9 +39,6 @@ struct rga_frame {
/* Image format */
struct rga_fmt *fmt;
struct v4l2_pix_format_mplane pix;
-
- /* Variables that can calculated once and reused */
- u32 stride;
};
struct rga_dma_desc {
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 10/16] media: rockchip: rga: move rga_fmt to rga-hw.h
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (8 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 09/16] media: rockchip: rga: remove stride " Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:32 ` [PATCH 11/16] media: rockchip: rga: add iommu restore function Sven Püschel
` (7 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Move rga_fmt to rga-hw in preparation of the RGA3 addition, as the struct
contains many RGA2 specific values. They are used to write the correct
register values quickly based on the chosen format. Therefore the
pointer to the rga_fmt struct is kept but changed to an opaque void
pointer outside of the rga-hw.h.
To enumerate and set the correct formats, two helper functions need to
be exposed in the rga_hw struct:
enum_format just get's the vidioc_enum_fmt format and it's return value
is also returned from vidioc_enum_fmt. This is a simple pass-through,
as the implementation is very simple.
try_format is a simple abstraction around the previous rga_find_format.
But unlike rga_find_format, it always returns a valid format.
Therefore the passed fourcc value is also a pointer to update it in case
the passed fourcc value is not supported by the hardware.
Due to the RGA3 supporting different formats on the capture and output
side, an additional parameter is_capture has been added to support
this use-case.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-buf.c | 2 +-
drivers/media/platform/rockchip/rga/rga-hw.c | 52 ++++++++++++++++++++-------
drivers/media/platform/rockchip/rga/rga-hw.h | 12 +++++++
drivers/media/platform/rockchip/rga/rga.c | 45 ++++++++---------------
drivers/media/platform/rockchip/rga/rga.h | 16 ++-------
5 files changed, 71 insertions(+), 56 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
index e44fe870fb9e34aa93404b7a60022fe441adf8f9..ad660d3c8cc737b9f3f41770a14ac13973bc7fea 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -158,7 +158,7 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
}
/* Fill the remaining planes */
- info = v4l2_format_info(f->fmt->fourcc);
+ info = v4l2_format_info(f->pix.pixelformat);
for (i = info->mem_planes; i < info->comp_planes; i++)
dma_addrs[i] = dma_addrs[0] + get_plane_offset(f, info, i);
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index 66b23c4a4cf1488ce42a7ab1901daaaa55b28fe0..d54183d224b3e9c42d5503acf172257f2e736f7b 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -44,14 +44,15 @@ rga_get_corner_addrs(struct rga_frame *frm, struct rga_addrs *addrs,
struct rga_addrs *lt, *lb, *rt, *rb;
unsigned int x_div = 0,
y_div = 0, y_stride = 0, uv_stride = 0, pixel_width = 0;
+ struct rga_fmt *fmt = frm->fmt;
lt = &corner_addrs.left_top;
lb = &corner_addrs.left_bottom;
rt = &corner_addrs.right_top;
rb = &corner_addrs.right_bottom;
- x_div = frm->fmt->x_div;
- y_div = frm->fmt->y_div;
+ x_div = fmt->x_div;
+ y_div = fmt->y_div;
y_stride = frm->pix.plane_fmt[0].bytesperline;
uv_stride = y_stride / x_div;
pixel_width = y_stride / frm->width;
@@ -165,6 +166,8 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
union rga_dst_vir_info dst_vir_info;
union rga_dst_act_info dst_act_info;
u32 in_stride, out_stride;
+ struct rga_fmt *in_fmt = ctx->in.fmt;
+ struct rga_fmt *out_fmt = ctx->out.fmt;
src_h = ctx->in.crop.height;
src_w = ctx->in.crop.width;
@@ -180,18 +183,18 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
dst_vir_info.val = dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2];
dst_act_info.val = dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2];
- src_info.data.format = ctx->in.fmt->hw_format;
- src_info.data.swap = ctx->in.fmt->color_swap;
- dst_info.data.format = ctx->out.fmt->hw_format;
- dst_info.data.swap = ctx->out.fmt->color_swap;
+ src_info.data.format = in_fmt->hw_format;
+ src_info.data.swap = in_fmt->color_swap;
+ dst_info.data.format = out_fmt->hw_format;
+ dst_info.data.swap = out_fmt->color_swap;
/*
* CSC mode must only be set when the colorspace families differ between
* input and output. It must remain unset (zeroed) if both are the same.
*/
- if (RGA_COLOR_FMT_IS_YUV(ctx->in.fmt->hw_format) &&
- RGA_COLOR_FMT_IS_RGB(ctx->out.fmt->hw_format)) {
+ if (RGA_COLOR_FMT_IS_YUV(in_fmt->hw_format) &&
+ RGA_COLOR_FMT_IS_RGB(out_fmt->hw_format)) {
switch (ctx->in.colorspace) {
case V4L2_COLORSPACE_REC709:
src_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
@@ -202,8 +205,8 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
}
}
- if (RGA_COLOR_FMT_IS_RGB(ctx->in.fmt->hw_format) &&
- RGA_COLOR_FMT_IS_YUV(ctx->out.fmt->hw_format)) {
+ if (RGA_COLOR_FMT_IS_RGB(in_fmt->hw_format) &&
+ RGA_COLOR_FMT_IS_YUV(out_fmt->hw_format)) {
switch (ctx->out.colorspace) {
case V4L2_COLORSPACE_REC709:
dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
@@ -621,11 +624,34 @@ static struct rga_fmt formats[] = {
},
};
+static void *rga_try_format(u32 *fourcc, bool is_output)
+{
+ unsigned int i;
+
+ if (!fourcc)
+ return &formats[0];
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (formats[i].fourcc == *fourcc)
+ return &formats[i];
+ }
+
+ *fourcc = formats[0].fourcc;
+ return &formats[0];
+}
+
+static int rga_enum_format(struct v4l2_fmtdesc *f)
+{
+ if (f->index >= ARRAY_SIZE(formats))
+ return -EINVAL;
+
+ f->pixelformat = formats[f->index].fourcc;
+ return 0;
+}
+
const struct rga_hw rga2_hw = {
.card_type = "rga2",
.has_internal_iommu = true,
- .formats = formats,
- .num_formats = ARRAY_SIZE(formats),
.cmdbuf_size = RGA_CMDBUF_SIZE,
.min_width = MIN_WIDTH,
.max_width = MAX_WIDTH,
@@ -635,4 +661,6 @@ const struct rga_hw rga2_hw = {
.start = rga_hw_start,
.handle_irq = rga_handle_irq,
.get_version = rga_get_version,
+ .try_format = rga_try_format,
+ .enum_format = rga_enum_format,
};
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h
index 1f52fbfad5fb3b8b773f7f03be0603170c5189f6..0ac3a05c0e0cfd8ed64277cd67e5936fbd52d28f 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.h
+++ b/drivers/media/platform/rockchip/rga/rga-hw.h
@@ -6,6 +6,8 @@
#ifndef __RGA_HW_H__
#define __RGA_HW_H__
+#include <linux/types.h>
+
#define RGA_CMDBUF_SIZE 0x20
/* Hardware limits */
@@ -428,4 +430,14 @@ union rga_pat_con {
} data;
};
+struct rga_fmt {
+ u32 fourcc;
+ int depth;
+ u8 uv_factor;
+ u8 y_div;
+ u8 x_div;
+ u8 color_swap;
+ u8 hw_format;
+};
+
#endif
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 6e1a4a6dc6309a6d6d9a3aac0fe982e7200c96de..cd4da01645611e5fb51ed94e09b5f1463dad72c5 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -185,17 +185,6 @@ static int rga_setup_ctrls(struct rga_ctx *ctx)
return 0;
}
-static struct rga_fmt *rga_fmt_find(struct rockchip_rga *rga, u32 pixelformat)
-{
- unsigned int i;
-
- for (i = 0; i < rga->hw->num_formats; i++) {
- if (rga->hw->formats[i].fourcc == pixelformat)
- return &rga->hw->formats[i];
- }
- return NULL;
-}
-
struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type)
{
if (V4L2_TYPE_IS_OUTPUT(type))
@@ -210,6 +199,7 @@ static int rga_open(struct file *file)
struct rockchip_rga *rga = video_drvdata(file);
struct rga_ctx *ctx = NULL;
int ret = 0;
+ u32 fourcc;
struct rga_frame def_frame = {
.width = clamp(DEFAULT_WIDTH, rga->hw->min_width, rga->hw->max_width),
.height = clamp(DEFAULT_HEIGHT, rga->hw->min_height, rga->hw->max_height),
@@ -218,7 +208,6 @@ static int rga_open(struct file *file)
.crop.top = 0,
.crop.width = clamp(DEFAULT_WIDTH, rga->hw->min_width, rga->hw->max_width),
.crop.height = clamp(DEFAULT_HEIGHT, rga->hw->min_height, rga->hw->max_height),
- .fmt = &rga->hw->formats[0],
};
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -229,10 +218,14 @@ static int rga_open(struct file *file)
ctx->in = def_frame;
ctx->out = def_frame;
+ fourcc = 0;
+ ctx->in.fmt = rga->hw->try_format(&fourcc, true);
v4l2_fill_pixfmt_mp(&ctx->in.pix,
- ctx->in.fmt->fourcc, ctx->out.width, ctx->out.height);
+ fourcc, ctx->out.width, ctx->out.height);
+ fourcc = 0;
+ ctx->out.fmt = rga->hw->try_format(&fourcc, false);
v4l2_fill_pixfmt_mp(&ctx->out.pix,
- ctx->out.fmt->fourcc, ctx->out.width, ctx->out.height);
+ fourcc, ctx->out.width, ctx->out.height);
if (mutex_lock_interruptible(&rga->mutex)) {
kfree(ctx);
@@ -302,15 +295,8 @@ vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
{
struct rockchip_rga *rga = video_drvdata(file);
- struct rga_fmt *fmt;
- if (f->index >= rga->hw->num_formats)
- return -EINVAL;
-
- fmt = &rga->hw->formats[f->index];
- f->pixelformat = fmt->fourcc;
-
- return 0;
+ return rga->hw->enum_format(f);
}
static void align_pixfmt(struct v4l2_pix_format_mplane *pix_fmt)
@@ -346,7 +332,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
if (IS_ERR(frm))
return PTR_ERR(frm);
- v4l2_fill_pixfmt_mp(pix_fmt, frm->fmt->fourcc, frm->width, frm->height);
+ v4l2_fill_pixfmt_mp(pix_fmt, frm->pix.pixelformat, frm->width, frm->height);
align_pixfmt(pix_fmt);
pix_fmt->field = V4L2_FIELD_NONE;
@@ -360,18 +346,16 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp;
struct rockchip_rga *rga = video_drvdata(file);
const struct rga_hw *hw = rga->hw;
- struct rga_fmt *fmt;
- fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
- if (!fmt)
- fmt = &hw->formats[0];
+ hw->try_format(&pix_fmt->pixelformat,
+ V4L2_TYPE_IS_OUTPUT(f->type));
pix_fmt->width = clamp(pix_fmt->width,
hw->min_width, hw->max_width);
pix_fmt->height = clamp(pix_fmt->height,
hw->min_height, hw->max_height);
- v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt->height);
+ v4l2_fill_pixfmt_mp(pix_fmt, pix_fmt->pixelformat, pix_fmt->width, pix_fmt->height);
align_pixfmt(pix_fmt);
pix_fmt->field = V4L2_FIELD_NONE;
@@ -404,7 +388,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
return PTR_ERR(frm);
frm->width = pix_fmt->width;
frm->height = pix_fmt->height;
- frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
+ frm->fmt = rga->hw->try_format(&pix_fmt->pixelformat,
+ V4L2_TYPE_IS_OUTPUT(f->type));
frm->colorspace = pix_fmt->colorspace;
/* Reset crop settings */
@@ -418,7 +403,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
v4l2_dbg(debug, 1, &rga->v4l2_dev,
"[%s] fmt - %p4cc %dx%d (stride %d)\n",
V4L2_TYPE_IS_OUTPUT(f->type) ? "OUTPUT" : "CAPTURE",
- &frm->fmt->fourcc, frm->width, frm->height,
+ &pix_fmt->pixelformat, frm->width, frm->height,
pix_fmt->plane_fmt[0].bytesperline);
for (i = 0; i < pix_fmt->num_planes; i++) {
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index d5ec873adc280bc2238b227d2f0c649ca345b836..fc4805ba4e8ef7fb311f780a198ba6ba4d3aff17 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -17,16 +17,6 @@
#define DEFAULT_WIDTH 100
#define DEFAULT_HEIGHT 100
-struct rga_fmt {
- u32 fourcc;
- int depth;
- u8 uv_factor;
- u8 y_div;
- u8 x_div;
- u8 color_swap;
- u8 hw_format;
-};
-
struct rga_frame {
/* Original dimensions */
u32 width;
@@ -37,7 +27,7 @@ struct rga_frame {
struct v4l2_rect crop;
/* Image format */
- struct rga_fmt *fmt;
+ void *fmt;
struct v4l2_pix_format_mplane pix;
};
@@ -149,8 +139,6 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
struct rga_hw {
const char *card_type;
bool has_internal_iommu;
- struct rga_fmt *formats;
- u32 num_formats;
size_t cmdbuf_size;
u32 min_width, min_height;
u32 max_width, max_height;
@@ -159,6 +147,8 @@ struct rga_hw {
struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
bool (*handle_irq)(struct rockchip_rga *rga);
void (*get_version)(struct rockchip_rga *rga);
+ void *(*try_format)(u32 *fourcc, bool is_output);
+ int (*enum_format)(struct v4l2_fmtdesc *f);
};
static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 11/16] media: rockchip: rga: add iommu restore function
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (9 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 10/16] media: rockchip: rga: move rga_fmt to rga-hw.h Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 18:30 ` Nicolas Dufresne
2025-10-07 8:32 ` [PATCH 12/16] media: rockchip: rga: handle error interrupt Sven Püschel
` (6 subsequent siblings)
17 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Add an iommu restore function in preparation for the rga3 addition.
This is necessary for a soft reset, as the rga3 will also reset
it's iommu paging table to 0 and disable paging.
The empty domain attach/detach to restore the iommu is copied
from the rkvdec driver.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga.c | 24 ++++++++++++++++++++++++
drivers/media/platform/rockchip/rga/rga.h | 7 +++++++
2 files changed, 31 insertions(+)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index cd4da01645611e5fb51ed94e09b5f1463dad72c5..0a725841b0cfa41bbc5b861b8f5ceac2452fc2b5 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -9,6 +9,7 @@
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
+#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
@@ -560,6 +561,19 @@ static const struct video_device rga_videodev = {
.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
};
+void rga_iommu_restore(struct rockchip_rga *rga)
+{
+ if (rga->empty_domain) {
+ /*
+ * To rewrite mapping into the attached IOMMU core, attach a new empty domain that
+ * will program an empty table, then detach it to restore the default domain and
+ * all cached mappings.
+ */
+ iommu_attach_device(rga->empty_domain, rga->dev);
+ iommu_detach_device(rga->empty_domain, rga->dev);
+ }
+}
+
static int rga_parse_dt(struct rockchip_rga *rga)
{
struct reset_control *core_rst, *axi_rst, *ahb_rst;
@@ -657,6 +671,13 @@ static int rga_probe(struct platform_device *pdev)
goto err_put_clk;
}
+ if (iommu_get_domain_for_dev(rga->dev)) {
+ rga->empty_domain = iommu_paging_domain_alloc(rga->dev);
+
+ if (!rga->empty_domain)
+ dev_warn(rga->dev, "cannot alloc new empty domain\n");
+ }
+
ret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev);
if (ret)
goto err_put_clk;
@@ -741,6 +762,9 @@ static void rga_remove(struct platform_device *pdev)
v4l2_device_unregister(&rga->v4l2_dev);
pm_runtime_disable(rga->dev);
+
+ if (rga->empty_domain)
+ iommu_domain_free(rga->empty_domain);
}
static int __maybe_unused rga_runtime_suspend(struct device *dev)
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index fc4805ba4e8ef7fb311f780a198ba6ba4d3aff17..e19c4c82aca5ae2056f52d525138093fbbb81af8 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -75,6 +75,7 @@ struct rockchip_rga {
void __iomem *regs;
struct clk_bulk_data clks[3];
struct rockchip_rga_version version;
+ struct iommu_domain *empty_domain;
/* vfd lock */
struct mutex mutex;
@@ -114,6 +115,12 @@ static inline struct rga_vb_buffer *vb_to_rga(struct vb2_v4l2_buffer *vb)
struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type);
+/*
+ * This should be called in an interrupt handler to make sure no memory
+ * is mapped through the IOMMU while the empty domain is attached.
+ */
+void rga_iommu_restore(struct rockchip_rga *rga);
+
/* RGA Buffers Manage */
extern const struct vb2_ops rga_qops;
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 12/16] media: rockchip: rga: handle error interrupt
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (10 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 11/16] media: rockchip: rga: add iommu restore function Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 18:47 ` Nicolas Dufresne
2025-10-07 8:32 ` [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3 Sven Püschel
` (5 subsequent siblings)
17 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Handle the error interrupt status in preparation of the RGA3 addition.
This allows the buffer to be marked as done, as it would otherwise
be stuck in the queue.
The RGA3 needs a soft reset to properly work after an error occurred,
as it would otherwise cease to deliver new interrupts. Also the soft
reset avoids additional error interrupts to be triggered, which are
currently not supported by the rga_isr function.
As it is unknown how the RGA2 behaves in the error case, no
error interrupt was enabled and handled.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/rga-hw.c | 6 ++++--
drivers/media/platform/rockchip/rga/rga.c | 32 +++++++++++++++++-----------
drivers/media/platform/rockchip/rga/rga.h | 8 ++++++-
3 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
index d54183d224b3e9c42d5503acf172257f2e736f7b..93822b5b8b15e76862bd022759eaa5cb9552dd76 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -459,7 +459,7 @@ static void rga_hw_start(struct rockchip_rga *rga,
rga_write(rga, RGA_CMD_CTRL, 0x1);
}
-static bool rga_handle_irq(struct rockchip_rga *rga)
+static enum rga_irq_result rga_handle_irq(struct rockchip_rga *rga)
{
int intr;
@@ -467,7 +467,9 @@ static bool rga_handle_irq(struct rockchip_rga *rga)
rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
- return intr & 0x04;
+ if (intr & 0x04)
+ return RGA_IRQ_DONE;
+ return RGA_IRQ_IGNORE;
}
static void rga_get_version(struct rockchip_rga *rga)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 0a725841b0cfa41bbc5b861b8f5ceac2452fc2b5..3b5d2eb8e109f44af76dd2240a239b1fa8a78cee 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -56,30 +56,38 @@ static void device_run(void *prv)
static irqreturn_t rga_isr(int irq, void *prv)
{
struct rockchip_rga *rga = prv;
+ struct vb2_v4l2_buffer *src, *dst;
+ struct rga_ctx *ctx = rga->curr;
+ enum rga_irq_result result;
- if (rga->hw->handle_irq(rga)) {
- struct vb2_v4l2_buffer *src, *dst;
- struct rga_ctx *ctx = rga->curr;
+ result = rga->hw->handle_irq(rga);
+ if (result == RGA_IRQ_IGNORE)
+ return IRQ_HANDLED;
- WARN_ON(!ctx);
+ WARN_ON(!ctx);
- rga->curr = NULL;
+ rga->curr = NULL;
- src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- WARN_ON(!src);
- WARN_ON(!dst);
+ WARN_ON(!src);
+ WARN_ON(!dst);
- v4l2_m2m_buf_copy_metadata(src, dst, true);
+ v4l2_m2m_buf_copy_metadata(src, dst, true);
- dst->sequence = ctx->csequence++;
+ dst->sequence = ctx->csequence++;
+ if (result == RGA_IRQ_DONE) {
v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
- v4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx);
+ } else {
+ v4l2_m2m_buf_done(src, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(dst, VB2_BUF_STATE_ERROR);
}
+ v4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx);
+
return IRQ_HANDLED;
}
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index e19c4c82aca5ae2056f52d525138093fbbb81af8..dc4bb85707d12f5378c4891098cd7ea4a4d75e2d 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -143,6 +143,12 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
rga_write(rga, reg, temp);
};
+enum rga_irq_result {
+ RGA_IRQ_IGNORE,
+ RGA_IRQ_DONE,
+ RGA_IRQ_ERROR,
+};
+
struct rga_hw {
const char *card_type;
bool has_internal_iommu;
@@ -152,7 +158,7 @@ struct rga_hw {
void (*start)(struct rockchip_rga *rga,
struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
- bool (*handle_irq)(struct rockchip_rga *rga);
+ enum rga_irq_result (*handle_irq)(struct rockchip_rga *rga);
void (*get_version)(struct rockchip_rga *rga);
void *(*try_format)(u32 *fourcc, bool is_output);
int (*enum_format)(struct v4l2_fmtdesc *f);
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (11 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 12/16] media: rockchip: rga: handle error interrupt Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:38 ` Krzysztof Kozlowski
2025-10-07 8:32 ` [PATCH 14/16] arm64: dts: rockchip: add rga3 dt nodes Sven Püschel
` (4 subsequent siblings)
17 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Add a new compatible for the rk3588 Rockchip SoC, which features an
RGA3, which is described in the TRM Part2.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
Documentation/devicetree/bindings/media/rockchip-rga.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/media/rockchip-rga.yaml b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
index ac17cda65191be047fc61d0c806f806c6af07c7b..11e86333c56aab55d9358dc88e45e7c1ebfaae9e 100644
--- a/Documentation/devicetree/bindings/media/rockchip-rga.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
@@ -20,6 +20,7 @@ properties:
oneOf:
- const: rockchip,rk3288-rga
- const: rockchip,rk3399-rga
+ - const: rockchip,rk3588-rga3
- items:
- enum:
- rockchip,rk3228-rga
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 14/16] arm64: dts: rockchip: add rga3 dt nodes
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (12 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3 Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:32 ` [PATCH 15/16] arm64: dts: rockchip: increase rga3 clock speed Sven Püschel
` (3 subsequent siblings)
17 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Add devicetree nodes for the RGA3 peripheral in the RK3588.
They are based on the vendor downstream device nodes, but were adjusted
to work with the rockchip-rga and iommu driver kernel.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 46 +++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index 70f03e68ba550d6b9142131dcca86e8ded36e2f1..08885d9c19e0c104ab0f723ec161b83998cfb9c7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -1172,6 +1172,52 @@ rga: rga@fdb80000 {
power-domains = <&power RK3588_PD_VDPU>;
};
+ rga3_core0: rga@fdb60000 {
+ compatible = "rockchip,rk3588-rga3";
+ reg = <0x0 0xfdb60000 0x0 0x200>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "rga3_core0_irq";
+ clocks = <&cru ACLK_RGA3_0>, <&cru HCLK_RGA3_0>, <&cru CLK_RGA3_0_CORE>;
+ clock-names = "aclk", "hclk", "sclk";
+ resets = <&cru SRST_RGA3_0_CORE>, <&cru SRST_A_RGA3_0>, <&cru SRST_H_RGA3_0>;
+ reset-names = "core", "axi", "ahb";
+ power-domains = <&power RK3588_PD_RGA30>;
+ iommus = <&rga3_0_mmu>;
+ };
+
+ rga3_0_mmu: iommu@fdb60f00 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdb60f00 0x0 0x100>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru ACLK_RGA3_0>, <&cru HCLK_RGA3_0>;
+ clock-names = "aclk", "iface";
+ #iommu-cells = <0>;
+ power-domains = <&power RK3588_PD_RGA30>;
+ };
+
+ rga3_core1: rga@fdb70000 {
+ compatible = "rockchip,rk3588-rga3";
+ reg = <0x0 0xfdb70000 0x0 0x200>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "rga3_core1_irq";
+ clocks = <&cru ACLK_RGA3_1>, <&cru HCLK_RGA3_1>, <&cru CLK_RGA3_1_CORE>;
+ clock-names = "aclk", "hclk", "sclk";
+ resets = <&cru SRST_RGA3_1_CORE>, <&cru SRST_A_RGA3_1>, <&cru SRST_H_RGA3_1>;
+ reset-names = "core", "axi", "ahb";
+ power-domains = <&power RK3588_PD_RGA31>;
+ iommus = <&rga3_1_mmu>;
+ };
+
+ rga3_1_mmu: iommu@fdb70f00 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdb70f00 0x0 0x100>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru ACLK_RGA3_1>, <&cru HCLK_RGA3_1>;
+ clock-names = "aclk", "iface";
+ #iommu-cells = <0>;
+ power-domains = <&power RK3588_PD_RGA31>;
+ };
+
vepu121_0: video-codec@fdba0000 {
compatible = "rockchip,rk3588-vepu121";
reg = <0x0 0xfdba0000 0x0 0x800>;
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 15/16] arm64: dts: rockchip: increase rga3 clock speed
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (13 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 14/16] arm64: dts: rockchip: add rga3 dt nodes Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:39 ` Krzysztof Kozlowski
2025-10-07 8:32 ` [PATCH 16/16] media: rockchip: rga: add rga3 support Sven Püschel
` (2 subsequent siblings)
17 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Increase the RGA3 clock speed to get the maximal possible frames
per second. By default the core and axi clock is set to 375Mhz.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index 08885d9c19e0c104ab0f723ec161b83998cfb9c7..57e320267bb629893bb884bf4e8d6bbc22f8d628 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -1179,6 +1179,8 @@ rga3_core0: rga@fdb60000 {
interrupt-names = "rga3_core0_irq";
clocks = <&cru ACLK_RGA3_0>, <&cru HCLK_RGA3_0>, <&cru CLK_RGA3_0_CORE>;
clock-names = "aclk", "hclk", "sclk";
+ assigned-clocks = <&cru CLK_RGA3_0_CORE>, <&cru ACLK_RGA3_0>;
+ assigned-clock-rates = <800000000>, <800000000>;
resets = <&cru SRST_RGA3_0_CORE>, <&cru SRST_A_RGA3_0>, <&cru SRST_H_RGA3_0>;
reset-names = "core", "axi", "ahb";
power-domains = <&power RK3588_PD_RGA30>;
@@ -1202,6 +1204,8 @@ rga3_core1: rga@fdb70000 {
interrupt-names = "rga3_core1_irq";
clocks = <&cru ACLK_RGA3_1>, <&cru HCLK_RGA3_1>, <&cru CLK_RGA3_1_CORE>;
clock-names = "aclk", "hclk", "sclk";
+ assigned-clocks = <&cru CLK_RGA3_1_CORE>, <&cru ACLK_RGA3_1>;
+ assigned-clock-rates = <800000000>, <800000000>;
resets = <&cru SRST_RGA3_1_CORE>, <&cru SRST_A_RGA3_1>, <&cru SRST_H_RGA3_1>;
reset-names = "core", "axi", "ahb";
power-domains = <&power RK3588_PD_RGA31>;
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (14 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 15/16] arm64: dts: rockchip: increase rga3 clock speed Sven Püschel
@ 2025-10-07 8:32 ` Sven Püschel
2025-10-07 8:39 ` Krzysztof Kozlowski
` (2 more replies)
2025-10-07 18:06 ` [PATCH 00/16] media: platform: rga: Add RGA3 support Nicolas Dufresne
2025-10-09 22:03 ` Rob Herring (Arm)
17 siblings, 3 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 8:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel, Sven Püschel
Add support for the RGA3 unit contained in the RK3588.
Only a basic feature set consisting of scaling and color conversion is
implemented. Advanced features like rotation and cropping will just be
ignored. Also the BT601F color space conversion is currently hard coded.
The register address defines were copied from the
vendor Rockchip kernel sources and slightly adjusted to not start at 0
again for the cmd registers.
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
drivers/media/platform/rockchip/rga/Makefile | 2 +-
drivers/media/platform/rockchip/rga/rga.c | 4 +
drivers/media/platform/rockchip/rga/rga.h | 2 +-
drivers/media/platform/rockchip/rga/rga3-hw.c | 490 ++++++++++++++++++++++++++
drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
5 files changed, 682 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/Makefile b/drivers/media/platform/rockchip/rga/Makefile
index 1bbecdc3d8df2ce286652f5544c4a3b52a6d28cf..7326a548f3dc7618403e98974b8c60d45f556fef 100644
--- a/drivers/media/platform/rockchip/rga/Makefile
+++ b/drivers/media/platform/rockchip/rga/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-rockchip-rga-objs := rga.o rga-hw.o rga-buf.o
+rockchip-rga-objs := rga.o rga-hw.o rga3-hw.o rga-buf.o
obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 3b5d2eb8e109f44af76dd2240a239b1fa8a78cee..9d15104fcc1a45553af33bfd637bba0a86329c17 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -805,6 +805,10 @@ static const struct of_device_id rockchip_rga_match[] = {
.compatible = "rockchip,rk3399-rga",
.data = &rga2_hw,
},
+ {
+ .compatible = "rockchip,rk3588-rga3",
+ .data = &rga3_hw,
+ },
{},
};
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index dc4bb85707d12f5378c4891098cd7ea4a4d75e2d..350a4e07cb2ee237fc3676d594e1e7298a028afb 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -169,6 +169,6 @@ static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
return rga->hw->has_internal_iommu;
}
-extern const struct rga_hw rga2_hw;
+extern const struct rga_hw rga2_hw, rga3_hw;
#endif
diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.c b/drivers/media/platform/rockchip/rga/rga3-hw.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e4cd2f96cf866880316c75924f7a4c339851448
--- /dev/null
+++ b/drivers/media/platform/rockchip/rga/rga3-hw.c
@@ -0,0 +1,490 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) Pengutronix e.K.
+ * Author: Sven Püschel <s.pueschel@pengutronix.de>
+ */
+
+#include <linux/pm_runtime.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/printk.h>
+
+#include <media/v4l2-common.h>
+
+#include "rga3-hw.h"
+#include "rga.h"
+
+static unsigned int rga3_get_scaling(unsigned int src, unsigned int dst)
+{
+ if (dst > src) {
+ if (((src - 1) << 16) % (dst - 1) == 0)
+ return ((src - 1) << 16) / (dst - 1) - 1;
+ else
+ return ((src - 1) << 16) / (dst - 1);
+ } else {
+ return ((dst - 1) << 16) / (src - 1) + 1;
+ }
+}
+
+static bool rga3_has_alpha(const struct rga3_fmt *fmt)
+{
+ return fmt->hw_format >= RGA3_COLOR_FMT_FIRST_HAS_ALPHA &&
+ fmt->fourcc != V4L2_PIX_FMT_BGRX32 &&
+ fmt->fourcc != V4L2_PIX_FMT_XBGR32 &&
+ fmt->fourcc != V4L2_PIX_FMT_RGBX32 &&
+ fmt->fourcc != V4L2_PIX_FMT_XRGB32;
+}
+
+static bool rga3_can_capture(const struct rga3_fmt *fmt)
+{
+ return fmt->hw_format <= RGA3_COLOR_FMT_LAST_OUTPUT;
+}
+
+static void rga3_cmd_set_trans_info(struct rga_ctx *ctx)
+{
+ struct rockchip_rga *rga = ctx->rga;
+ u32 *cmd = rga->cmdbuf_virt;
+ unsigned int src_h, src_w, dst_h, dst_w;
+ unsigned int reg;
+ u16 hor_scl_fac, ver_scl_fac;
+
+ src_h = ctx->in.crop.height;
+ src_w = ctx->in.crop.width;
+ dst_h = ctx->out.crop.height;
+ dst_w = ctx->out.crop.width;
+
+ reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_SCALE_HOR_UP, dst_w > src_w)
+ | FIELD_PREP(RGA3_WIN_SCALE_HOR_BYPASS, dst_w == src_w)
+ | FIELD_PREP(RGA3_WIN_SCALE_VER_UP, dst_h > src_h)
+ | FIELD_PREP(RGA3_WIN_SCALE_VER_BYPASS, dst_h == src_h);
+
+ /* stride needs to be in words */
+ reg = RGA3_WIN0_VIR_STRIDE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2;
+ reg = RGA3_WIN0_UV_VIR_STRIDE - RGA3_FIRST_CMD_REG;
+ if (ctx->in.pix.num_planes >= 2)
+ cmd[reg >> 2] = ctx->in.pix.plane_fmt[1].bytesperline >> 2;
+ else
+ cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2;
+ reg = RGA3_WR_VIR_STRIDE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2;
+ reg = RGA3_WR_PL_VIR_STRIDE - RGA3_FIRST_CMD_REG;
+ if (ctx->out.pix.num_planes >= 2)
+ cmd[reg >> 2] = ctx->out.pix.plane_fmt[1].bytesperline >> 2;
+ else
+ cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2;
+
+ reg = RGA3_WIN0_ACT_SIZE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w)
+ | FIELD_PREP(RGA3_HEIGHT, src_h);
+ reg = RGA3_WIN0_SRC_SIZE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w)
+ | FIELD_PREP(RGA3_HEIGHT, src_h);
+
+ reg = RGA3_WIN0_DST_SIZE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, dst_w)
+ | FIELD_PREP(RGA3_HEIGHT, dst_h);
+
+ hor_scl_fac = rga3_get_scaling(src_w, dst_w);
+ ver_scl_fac = rga3_get_scaling(src_h, dst_h);
+ reg = RGA3_WIN0_SCL_FAC - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_SCALE_HOR_FAC, hor_scl_fac)
+ | FIELD_PREP(RGA3_SCALE_VER_FAC, ver_scl_fac);
+
+ if (rga3_has_alpha(ctx->in.fmt)) {
+ /* copy alpha from input */
+ reg = RGA3_OVLP_TOP_ALPHA - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1)
+ | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1);
+ reg = RGA3_OVLP_BOT_ALPHA - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1)
+ | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1);
+ } else {
+ /* just use a 255 alpha value */
+ reg = RGA3_OVLP_TOP_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff)
+ | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1);
+ reg = RGA3_OVLP_BOT_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff)
+ | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1);
+ }
+}
+
+static void rga3_cmd_set_win0_addr(struct rga_ctx *ctx,
+ const struct rga_addrs *addrs)
+{
+ u32 *cmd = ctx->rga->cmdbuf_virt;
+ unsigned int reg;
+
+ reg = RGA3_WIN0_Y_BASE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = addrs->y_addr;
+ reg = RGA3_WIN0_U_BASE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = addrs->u_addr;
+}
+
+static void rga3_cmd_set_wr_addr(struct rga_ctx *ctx,
+ const struct rga_addrs *addrs)
+{
+ u32 *cmd = ctx->rga->cmdbuf_virt;
+ unsigned int reg;
+
+ reg = RGA3_WR_Y_BASE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = addrs->y_addr;
+ reg = RGA3_WR_U_BASE - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] = addrs->u_addr;
+}
+
+static void rga3_cmd_set_win0_format(struct rga_ctx *ctx)
+{
+ u32 *cmd = ctx->rga->cmdbuf_virt;
+ const struct rga3_fmt *in = ctx->in.fmt;
+ const struct rga3_fmt *out = ctx->out.fmt;
+ const struct v4l2_format_info *in_fmt, *out_fmt;
+ unsigned int src_h, src_w, dst_h, dst_w;
+ bool r2y, y2r;
+ u8 rd_format;
+ unsigned int reg;
+
+ src_h = ctx->in.crop.height;
+ src_w = ctx->in.crop.width;
+ dst_h = ctx->out.crop.height;
+ dst_w = ctx->out.crop.width;
+
+ in_fmt = v4l2_format_info(in->fourcc);
+ out_fmt = v4l2_format_info(out->fourcc);
+ r2y = v4l2_is_format_rgb(in_fmt) && v4l2_is_format_yuv(out_fmt);
+ y2r = v4l2_is_format_yuv(in_fmt) && v4l2_is_format_rgb(out_fmt);
+
+ if (in->semi_planar)
+ rd_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
+ else
+ rd_format = RGA3_RDWR_FORMAT_INTERLEAVED;
+
+ reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_PIC_FORMAT, in->hw_format)
+ | FIELD_PREP(RGA3_WIN_YC_SWAP, in->yc_swap)
+ | FIELD_PREP(RGA3_WIN_RBUV_SWAP, in->rbuv_swap)
+ | FIELD_PREP(RGA3_WIN_RD_FORMAT, rd_format)
+ | FIELD_PREP(RGA3_WIN_R2Y, r2y)
+ | FIELD_PREP(RGA3_WIN_Y2R, y2r)
+ | FIELD_PREP(RGA3_WIN_CSC_MODE, RGA3_WIN_CSC_MODE_BT601_F);
+}
+
+static void rga3_cmd_enable_win0(struct rga_ctx *ctx)
+{
+ u32 *cmd = ctx->rga->cmdbuf_virt;
+ unsigned int reg;
+
+ reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_ENABLE, 1);
+}
+
+static void rga3_cmd_set_wr_format(struct rga_ctx *ctx)
+{
+ u32 *cmd = ctx->rga->cmdbuf_virt;
+ const struct rga3_fmt *out = ctx->out.fmt;
+ u8 wr_format;
+ unsigned int reg;
+
+ if (out->semi_planar)
+ wr_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
+ else
+ wr_format = RGA3_RDWR_FORMAT_INTERLEAVED;
+
+ reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] |= FIELD_PREP(RGA3_WR_PIC_FORMAT, out->hw_format)
+ | FIELD_PREP(RGA3_WR_YC_SWAP, out->yc_swap)
+ | FIELD_PREP(RGA3_WR_RBUV_SWAP, out->rbuv_swap)
+ | FIELD_PREP(RGA3_WR_FORMAT, wr_format);
+}
+
+static void rga3_cmd_disable_wr_limitation(struct rga_ctx *ctx)
+{
+ u32 *cmd = ctx->rga->cmdbuf_virt;
+ unsigned int reg;
+
+ /* Use the max value to avoid limiting the write speed */
+ reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG;
+ cmd[reg >> 2] |= FIELD_PREP(RGA3_WR_SW_OUTSTANDING_MAX, 63);
+}
+
+static void rga3_cmd_set(struct rga_ctx *ctx,
+ struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
+{
+ struct rockchip_rga *rga = ctx->rga;
+
+ memset(rga->cmdbuf_virt, 0, RGA3_CMDBUF_SIZE * 4);
+
+ rga3_cmd_set_win0_addr(ctx, &src->dma_addrs);
+ rga3_cmd_set_wr_addr(ctx, &dst->dma_addrs);
+
+ rga3_cmd_set_win0_format(ctx);
+ rga3_cmd_enable_win0(ctx);
+ rga3_cmd_set_trans_info(ctx);
+ rga3_cmd_set_wr_format(ctx);
+ rga3_cmd_disable_wr_limitation(ctx);
+
+ rga_write(rga, RGA3_CMD_ADDR, rga->cmdbuf_phy);
+
+ /* sync CMD buf for RGA */
+ dma_sync_single_for_device(rga->dev, rga->cmdbuf_phy,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+}
+
+static void rga3_hw_start(struct rockchip_rga *rga,
+ struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
+{
+ struct rga_ctx *ctx = rga->curr;
+
+ rga3_cmd_set(ctx, src, dst);
+
+ /* set to master mode and start the conversion */
+ rga_write(rga, RGA3_SYS_CTRL,
+ FIELD_PREP(RGA3_CMD_MODE, RGA3_CMD_MODE_MASTER));
+ rga_write(rga, RGA3_INT_EN,
+ FIELD_PREP(RGA3_INT_FRM_DONE, 1) |
+ FIELD_PREP(RGA3_INT_DMA_READ_BUS_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_FBC_DEC_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_HOR_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_VER_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WR_VER_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WR_HOR_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WR_BUS_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_IN_FIFO_WR_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_IN_FIFO_RD_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_HOR_FIFO_WR_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_HOR_FIFO_RD_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_VER_FIFO_WR_ERR, 1) |
+ FIELD_PREP(RGA3_INT_WIN0_VER_FIFO_RD_ERR, 1));
+ rga_write(rga, RGA3_CMD_CTRL,
+ FIELD_PREP(RGA3_CMD_LINE_START_PULSE, 1));
+}
+
+static void rga3_soft_reset(struct rockchip_rga *rga)
+{
+ u32 i;
+
+ rga_write(rga, RGA3_SYS_CTRL,
+ FIELD_PREP(RGA3_CCLK_SRESET, 1) |
+ FIELD_PREP(RGA3_ACLK_SRESET, 1));
+
+ for (i = 0; i < RGA3_RESET_TIMEOUT; i++) {
+ if (FIELD_GET(RGA3_RO_SRST_DONE, rga_read(rga, RGA3_RO_SRST)))
+ break;
+
+ udelay(1);
+ }
+
+ if (i == RGA3_RESET_TIMEOUT)
+ pr_err("Timeout of %d usec reached while waiting for an rga3 soft reset\n", i);
+
+ rga_write(rga, RGA3_SYS_CTRL, 0);
+ rga_iommu_restore(rga);
+}
+
+static enum rga_irq_result rga3_handle_irq(struct rockchip_rga *rga)
+{
+ u32 intr;
+
+ intr = rga_read(rga, RGA3_INT_RAW);
+ /* clear all interrupts */
+ rga_write(rga, RGA3_INT_CLR, intr);
+
+ if (FIELD_GET(RGA3_INT_FRM_DONE, intr))
+ return RGA_IRQ_DONE;
+ if (FIELD_GET(RGA3_INT_DMA_READ_BUS_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_FBC_DEC_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_HOR_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_VER_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WR_VER_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WR_HOR_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WR_BUS_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_IN_FIFO_WR_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_IN_FIFO_RD_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_HOR_FIFO_WR_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_HOR_FIFO_RD_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_VER_FIFO_WR_ERR, intr) ||
+ FIELD_GET(RGA3_INT_WIN0_VER_FIFO_RD_ERR, intr)) {
+ rga3_soft_reset(rga);
+ return RGA_IRQ_ERROR;
+ }
+
+ return RGA_IRQ_IGNORE;
+}
+
+static void rga3_get_version(struct rockchip_rga *rga)
+{
+ u32 version = rga_read(rga, RGA3_VERSION_NUM);
+
+ rga->version.major = FIELD_GET(RGA3_VERSION_NUM_MAJOR, version);
+ rga->version.minor = FIELD_GET(RGA3_VERSION_NUM_MINOR, version);
+}
+
+static struct rga3_fmt rga3_formats[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .hw_format = RGA3_COLOR_FMT_BGR888,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_BGR24,
+ .hw_format = RGA3_COLOR_FMT_BGR888,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_ABGR32,
+ .hw_format = RGA3_COLOR_FMT_BGRA8888,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGBA32,
+ .hw_format = RGA3_COLOR_FMT_BGRA8888,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_XBGR32,
+ .hw_format = RGA3_COLOR_FMT_BGRA8888,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGBX32,
+ .hw_format = RGA3_COLOR_FMT_BGRA8888,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .hw_format = RGA3_COLOR_FMT_BGR565,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .hw_format = RGA3_COLOR_FMT_YUV420,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .hw_format = RGA3_COLOR_FMT_YUV420,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV21M,
+ .hw_format = RGA3_COLOR_FMT_YUV420,
+ .rbuv_swap = 1,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .hw_format = RGA3_COLOR_FMT_YUV420,
+ .rbuv_swap = 1,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV16M,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV16,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV61M,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .rbuv_swap = 1,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV61,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .rbuv_swap = 1,
+ .semi_planar = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .yc_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .yc_swap = 1,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .hw_format = RGA3_COLOR_FMT_YUV422,
+ .rbuv_swap = 1,
+ },
+ /* Input only formats last to keep rga3_enum_format simple */
+ {
+ .fourcc = V4L2_PIX_FMT_ARGB32,
+ .hw_format = RGA3_COLOR_FMT_ABGR8888,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_BGRA32,
+ .hw_format = RGA3_COLOR_FMT_ABGR8888,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_XRGB32,
+ .hw_format = RGA3_COLOR_FMT_ABGR8888,
+ .rbuv_swap = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_BGRX32,
+ .hw_format = RGA3_COLOR_FMT_ABGR8888,
+ },
+};
+
+static int rga3_enum_format(struct v4l2_fmtdesc *f)
+{
+ struct rga3_fmt *fmt;
+
+ if (f->index >= ARRAY_SIZE(rga3_formats))
+ return -EINVAL;
+
+ fmt = &rga3_formats[f->index];
+ if (V4L2_TYPE_IS_CAPTURE(f->type) && !rga3_can_capture(fmt))
+ return -EINVAL;
+
+ f->pixelformat = fmt->fourcc;
+ return 0;
+}
+
+static void *rga3_try_format(u32 *fourcc, bool is_output)
+{
+ unsigned int i;
+
+ if (!fourcc)
+ return &rga3_formats[0];
+
+ for (i = 0; i < ARRAY_SIZE(rga3_formats); i++) {
+ if (!is_output && !rga3_can_capture(&rga3_formats[i]))
+ continue;
+
+ if (rga3_formats[i].fourcc == *fourcc)
+ return &rga3_formats[i];
+ }
+
+ *fourcc = rga3_formats[0].fourcc;
+ return &rga3_formats[0];
+}
+
+const struct rga_hw rga3_hw = {
+ .card_type = "rga3",
+ .has_internal_iommu = false,
+ .cmdbuf_size = RGA3_CMDBUF_SIZE,
+ .min_width = RGA3_MIN_WIDTH,
+ .min_height = RGA3_MIN_HEIGHT,
+ .max_width = RGA3_MAX_INPUT_WIDTH,
+ .max_height = RGA3_MAX_INPUT_HEIGHT,
+
+ .start = rga3_hw_start,
+ .handle_irq = rga3_handle_irq,
+ .get_version = rga3_get_version,
+ .enum_format = rga3_enum_format,
+ .try_format = rga3_try_format,
+};
diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.h b/drivers/media/platform/rockchip/rga/rga3-hw.h
new file mode 100644
index 0000000000000000000000000000000000000000..3829469e310706c11ecc52f40d3d1eb43a61d9c2
--- /dev/null
+++ b/drivers/media/platform/rockchip/rga/rga3-hw.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) Pengutronix e.K.
+ * Author: Sven Püschel <s.pueschel@pengutronix.de>
+ */
+#ifndef __RGA3_HW_H__
+#define __RGA3_HW_H__
+
+#include <linux/types.h>
+
+#define RGA3_CMDBUF_SIZE 0x2e
+
+#define RGA3_MIN_WIDTH 128
+#define RGA3_MIN_HEIGHT 128
+#define RGA3_MAX_INPUT_WIDTH (8192 - 16)
+#define RGA3_MAX_INPUT_HEIGHT (8192 - 16)
+#define RGA3_RESET_TIMEOUT 1000
+
+/* Registers address */
+/* sys reg */
+#define RGA3_SYS_CTRL 0x000
+#define RGA3_CMD_CTRL 0x004
+#define RGA3_CMD_ADDR 0x008
+#define RGA3_MI_GROUP_CTRL 0x00c
+#define RGA3_ARQOS_CTRL 0x010
+#define RGA3_VERSION_NUM 0x018
+#define RGA3_VERSION_TIM 0x01c
+#define RGA3_INT_EN 0x020
+#define RGA3_INT_RAW 0x024
+#define RGA3_INT_MSK 0x028
+#define RGA3_INT_CLR 0x02c
+#define RGA3_RO_SRST 0x030
+#define RGA3_STATUS0 0x034
+#define RGA3_SCAN_CNT 0x038
+#define RGA3_CMD_STATE 0x040
+
+/* cmd reg */
+#define RGA3_WIN0_RD_CTRL 0x100
+#define RGA3_FIRST_CMD_REG RGA3_WIN0_RD_CTRL
+#define RGA3_WIN0_Y_BASE 0x110
+#define RGA3_WIN0_U_BASE 0x114
+#define RGA3_WIN0_V_BASE 0x118
+#define RGA3_WIN0_VIR_STRIDE 0x11c
+#define RGA3_WIN0_FBC_OFF 0x120
+#define RGA3_WIN0_SRC_SIZE 0x124
+#define RGA3_WIN0_ACT_OFF 0x128
+#define RGA3_WIN0_ACT_SIZE 0x12c
+#define RGA3_WIN0_DST_SIZE 0x130
+#define RGA3_WIN0_SCL_FAC 0x134
+#define RGA3_WIN0_UV_VIR_STRIDE 0x138
+#define RGA3_WIN1_RD_CTRL 0x140
+#define RGA3_WIN1_Y_BASE 0x150
+#define RGA3_WIN1_U_BASE 0x154
+#define RGA3_WIN1_V_BASE 0x158
+#define RGA3_WIN1_VIR_STRIDE 0x15c
+#define RGA3_WIN1_FBC_OFF 0x160
+#define RGA3_WIN1_SRC_SIZE 0x164
+#define RGA3_WIN1_ACT_OFF 0x168
+#define RGA3_WIN1_ACT_SIZE 0x16c
+#define RGA3_WIN1_DST_SIZE 0x170
+#define RGA3_WIN1_SCL_FAC 0x174
+#define RGA3_WIN1_UV_VIR_STRIDE 0x178
+#define RGA3_OVLP_CTRL 0x180
+#define RGA3_OVLP_OFF 0x184
+#define RGA3_OVLP_TOP_KEY_MIN 0x188
+#define RGA3_OVLP_TOP_KEY_MAX 0x18c
+#define RGA3_OVLP_TOP_CTRL 0x190
+#define RGA3_OVLP_BOT_CTRL 0x194
+#define RGA3_OVLP_TOP_ALPHA 0x198
+#define RGA3_OVLP_BOT_ALPHA 0x19c
+#define RGA3_WR_CTRL 0x1a0
+#define RGA3_WR_FBCE_CTRL 0x1a4
+#define RGA3_WR_VIR_STRIDE 0x1a8
+#define RGA3_WR_PL_VIR_STRIDE 0x1ac
+#define RGA3_WR_Y_BASE 0x1b0
+#define RGA3_WR_U_BASE 0x1b4
+#define RGA3_WR_V_BASE 0x1b8
+
+/* Registers value */
+#define RGA3_COLOR_FMT_YUV420 0x0
+#define RGA3_COLOR_FMT_YUV422 0x1
+#define RGA3_COLOR_FMT_YUV420_10B 0x2
+#define RGA3_COLOR_FMT_YUV422_10B 0x3
+/*
+ * Use memory ordering names
+ * instead of the datasheet naming RGB formats in big endian order
+ */
+#define RGA3_COLOR_FMT_BGR565 0x4
+#define RGA3_COLOR_FMT_BGR888 0x5
+#define RGA3_COLOR_FMT_FIRST_HAS_ALPHA RGA3_COLOR_FMT_BGRA8888
+#define RGA3_COLOR_FMT_BGRA8888 0x6
+#define RGA3_COLOR_FMT_LAST_OUTPUT RGA3_COLOR_FMT_BGRA8888
+/* the following are only supported as inputs */
+#define RGA3_COLOR_FMT_ABGR8888 0x7
+/*
+ * the following seem to be unnecessary,
+ * as they can be achieved with RB swaps
+ */
+#define RGA3_COLOR_FMT_RGBA8888 0x8
+#define RGA3_COLOR_FMT_ARGB8888 0x9
+
+#define RGA3_RDWR_FORMAT_SEMI_PLANAR 0x1
+#define RGA3_RDWR_FORMAT_INTERLEAVED 0x2
+
+#define RGA3_CMD_MODE_MASTER 0x1
+
+#define RGA3_WIN_CSC_MODE_BT601_F 0x2
+
+/* RGA masks */
+/* SYS_CTRL */
+#define RGA3_CCLK_SRESET BIT(4)
+#define RGA3_ACLK_SRESET BIT(3)
+#define RGA3_CMD_MODE BIT(1)
+
+/* CMD_CTRL */
+#define RGA3_CMD_LINE_START_PULSE BIT(0)
+
+/* VERSION_NUM */
+#define RGA3_VERSION_NUM_MAJOR GENMASK(31, 28)
+#define RGA3_VERSION_NUM_MINOR GENMASK(27, 20)
+
+/* INT_* */
+#define RGA3_INT_FRM_DONE BIT(0)
+#define RGA3_INT_DMA_READ_BUS_ERR BIT(2)
+#define RGA3_INT_WIN0_FBC_DEC_ERR BIT(5)
+#define RGA3_INT_WIN0_HOR_ERR BIT(6)
+#define RGA3_INT_WIN0_VER_ERR BIT(7)
+#define RGA3_INT_WR_VER_ERR BIT(13)
+#define RGA3_INT_WR_HOR_ERR BIT(14)
+#define RGA3_INT_WR_BUS_ERR BIT(15)
+#define RGA3_INT_WIN0_IN_FIFO_WR_ERR BIT(16)
+#define RGA3_INT_WIN0_IN_FIFO_RD_ERR BIT(17)
+#define RGA3_INT_WIN0_HOR_FIFO_WR_ERR BIT(18)
+#define RGA3_INT_WIN0_HOR_FIFO_RD_ERR BIT(19)
+#define RGA3_INT_WIN0_VER_FIFO_WR_ERR BIT(20)
+#define RGA3_INT_WIN0_VER_FIFO_RD_ERR BIT(21)
+
+/* RO_SRST */
+#define RGA3_RO_SRST_DONE GENMASK(5, 0)
+
+/* *_SIZE */
+#define RGA3_HEIGHT GENMASK(28, 16)
+#define RGA3_WIDTH GENMASK(12, 0)
+
+/* SCL_FAC */
+#define RGA3_SCALE_VER_FAC GENMASK(31, 16)
+#define RGA3_SCALE_HOR_FAC GENMASK(15, 0)
+
+/* WINx_CTRL */
+#define RGA3_WIN_CSC_MODE GENMASK(27, 26)
+#define RGA3_WIN_R2Y BIT(25)
+#define RGA3_WIN_Y2R BIT(24)
+#define RGA3_WIN_SCALE_VER_UP BIT(23)
+#define RGA3_WIN_SCALE_VER_BYPASS BIT(22)
+#define RGA3_WIN_SCALE_HOR_UP BIT(21)
+#define RGA3_WIN_SCALE_HOR_BYPASS BIT(20)
+#define RGA3_WIN_YC_SWAP BIT(13)
+#define RGA3_WIN_RBUV_SWAP BIT(12)
+#define RGA3_WIN_RD_FORMAT GENMASK(9, 8)
+#define RGA3_WIN_PIC_FORMAT GENMASK(7, 4)
+#define RGA3_WIN_ENABLE BIT(0)
+
+/* COLOR_CTRL */
+#define RGA3_OVLP_GLOBAL_ALPHA GENMASK(23, 16)
+#define RGA3_OVLP_COLOR_MODE BIT(0)
+
+/* ALPHA_CTRL */
+#define RGA3_ALPHA_SELECT_MODE BIT(4)
+#define RGA3_ALPHA_BLEND_MODE GENMASK(3, 2)
+
+/* WR_CTRL */
+#define RGA3_WR_YC_SWAP BIT(20)
+#define RGA3_WR_SW_OUTSTANDING_MAX GENMASK(18, 13)
+#define RGA3_WR_RBUV_SWAP BIT(12)
+#define RGA3_WR_FORMAT GENMASK(9, 8)
+#define RGA3_WR_PIC_FORMAT GENMASK(7, 4)
+
+struct rga3_fmt {
+ u32 fourcc;
+ u8 hw_format;
+ bool rbuv_swap;
+ bool yc_swap;
+ bool semi_planar;
+};
+
+#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
2025-10-07 8:32 ` [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3 Sven Püschel
@ 2025-10-07 8:38 ` Krzysztof Kozlowski
2025-10-07 18:12 ` Nicolas Dufresne
0 siblings, 1 reply; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-07 8:38 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
On 07/10/2025 17:32, Sven Püschel wrote:
> Add a new compatible for the rk3588 Rockchip SoC, which features an
> RGA3, which is described in the TRM Part2.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> Documentation/devicetree/bindings/media/rockchip-rga.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/media/rockchip-rga.yaml b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> index ac17cda65191be047fc61d0c806f806c6af07c7b..11e86333c56aab55d9358dc88e45e7c1ebfaae9e 100644
> --- a/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> +++ b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> @@ -20,6 +20,7 @@ properties:
> oneOf:
> - const: rockchip,rk3288-rga
> - const: rockchip,rk3399-rga
> + - const: rockchip,rk3588-rga3
There is already rk3588-rga, so please explain in commit msg
differences, including compatibility or lack thereof. I am confused why
there are two completely different 2D accelerators simultaneously on
that SoC.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 15/16] arm64: dts: rockchip: increase rga3 clock speed
2025-10-07 8:32 ` [PATCH 15/16] arm64: dts: rockchip: increase rga3 clock speed Sven Püschel
@ 2025-10-07 8:39 ` Krzysztof Kozlowski
0 siblings, 0 replies; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-07 8:39 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
On 07/10/2025 17:32, Sven Püschel wrote:
> Increase the RGA3 clock speed to get the maximal possible frames
> per second. By default the core and axi clock is set to 375Mhz.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
> index 08885d9c19e0c104ab0f723ec161b83998cfb9c7..57e320267bb629893bb884bf4e8d6bbc22f8d628 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
> @@ -1179,6 +1179,8 @@ rga3_core0: rga@fdb60000 {
> interrupt-names = "rga3_core0_irq";
> clocks = <&cru ACLK_RGA3_0>, <&cru HCLK_RGA3_0>, <&cru CLK_RGA3_0_CORE>;
> clock-names = "aclk", "hclk", "sclk";
> + assigned-clocks = <&cru CLK_RGA3_0_CORE>, <&cru ACLK_RGA3_0>;
> + assigned-clock-rates = <800000000>, <800000000>;
You just added these nodes, so this must be squashed. Do not add
incomplete code which immediately you fix.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 8:32 ` [PATCH 16/16] media: rockchip: rga: add rga3 support Sven Püschel
@ 2025-10-07 8:39 ` Krzysztof Kozlowski
2025-10-07 16:05 ` Sven Püschel
2025-10-07 18:54 ` Nicolas Dufresne
2025-10-07 19:41 ` Nicolas Dufresne
2025-10-11 5:32 ` kernel test robot
2 siblings, 2 replies; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-07 8:39 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
On 07/10/2025 17:32, Sven Püschel wrote:
> Add support for the RGA3 unit contained in the RK3588.
>
> Only a basic feature set consisting of scaling and color conversion is
> implemented. Advanced features like rotation and cropping will just be
> ignored. Also the BT601F color space conversion is currently hard coded.
>
> The register address defines were copied from the
> vendor Rockchip kernel sources and slightly adjusted to not start at 0
> again for the cmd registers.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/Makefile | 2 +-
> drivers/media/platform/rockchip/rga/rga.c | 4 +
> drivers/media/platform/rockchip/rga/rga.h | 2 +-
> drivers/media/platform/rockchip/rga/rga3-hw.c | 490 ++++++++++++++++++++++++++
> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
> 5 files changed, 682 insertions(+), 2 deletions(-)
Your order of patches is a mess. DTS cannot be in the middle. In fact,
DTS should not be even in this patchset, because you are targeting media.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 8:39 ` Krzysztof Kozlowski
@ 2025-10-07 16:05 ` Sven Püschel
2025-10-08 1:55 ` Krzysztof Kozlowski
2025-10-07 18:54 ` Nicolas Dufresne
1 sibling, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-07 16:05 UTC (permalink / raw)
To: Krzysztof Kozlowski, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
Hi Krzysztof,
On 10/7/25 10:39 AM, Krzysztof Kozlowski wrote:
> On 07/10/2025 17:32, Sven Püschel wrote:
>> Add support for the RGA3 unit contained in the RK3588.
>>
>> Only a basic feature set consisting of scaling and color conversion is
>> implemented. Advanced features like rotation and cropping will just be
>> ignored. Also the BT601F color space conversion is currently hard coded.
>>
>> The register address defines were copied from the
>> vendor Rockchip kernel sources and slightly adjusted to not start at 0
>> again for the cmd registers.
>>
>> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>> ---
>> drivers/media/platform/rockchip/rga/Makefile | 2 +-
>> drivers/media/platform/rockchip/rga/rga.c | 4 +
>> drivers/media/platform/rockchip/rga/rga.h | 2 +-
>> drivers/media/platform/rockchip/rga/rga3-hw.c | 490 ++++++++++++++++++++++++++
>> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
>> 5 files changed, 682 insertions(+), 2 deletions(-)
> Your order of patches is a mess. DTS cannot be in the middle. In fact,
> DTS should not be even in this patchset, because you are targeting media.
sorry to bother you, but could you go into a bit more detail on how it
should be done correctly?
I guess that your message refers to "7. [...] If a driver subsystem
maintainer prefers to apply entire set, instead of their relevant
portion of patchset, please split the DTS patches into separate patchset
with a reference in changelog or cover letter to the bindings submission
on the mailing list." [1]. If this is the case, is there a general rule
to determine if a separate patchset is necessary? (I've also noticed,
that I've wrongly assumed to keep the Documentation and dtsi commit
together and should've moved the dtsi commit to the end of the patchset)
And do I understand it correctly, that the Documentation/ change is at
the correct position (only the dtsi commits being problematic)? Based on
my understanding of "5. The Documentation/ portion of the patch should
come in the series before the code implementing the binding" [1] this
should be right before the actual implementation (after all cleanup and
preparation commits).
Sincerely
Sven
[1]
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/16] media: platform: rga: Add RGA3 support
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (15 preceding siblings ...)
2025-10-07 8:32 ` [PATCH 16/16] media: rockchip: rga: add rga3 support Sven Püschel
@ 2025-10-07 18:06 ` Nicolas Dufresne
2025-10-10 8:33 ` Sven Püschel
2025-10-09 22:03 ` Rob Herring (Arm)
17 siblings, 1 reply; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 18:06 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 5908 bytes --]
Hi,
Le mardi 07 octobre 2025 à 10:31 +0200, Sven Püschel a écrit :
> This series adds support for the Raster Graphic Acceleration 3 (RGA3)
> peripheral, which is included in the RK3588 SoC. Unlike the RGA2 it
> can use the existing rockchip-iommu-v2 driver to handle iommu mappings.
> Also the RK3588 contains two independent RGA3 cores.
Thanks for working on this.
>
> Only scaling and format conversions between common 8bit RGB/YUV formats
> are implemented. Also the color space conversion is fixed to BT601F.
> This already allows a practical usage of the RGA3.
This seems quite limiting, can we expect an update on this, can't be that hard
to fully implement.
>
> This was tested on a Radxa Rock 5T. With the increased clock speeds in
> the devicetree around 160 fps were measured when scaling and converting
This is quite vague, I've checked the patch and you didn't extend either there.
Is that an overclock or was it miss-configured ? Does RK implement a devfreq ?
Should that be moved with a voltage adjustement ? Is there any thermal nearby we
should monitor ?
> from RGBA 480x360 to NV12 3840x2160. Without the clock speed scaling a
> default clock division factor of 2 is used and only around 80 fps are
> reached with one core. The v4l2-compliance tests only complain about
> the already failing colorspace propagation:
Did you do any more format testing to validation all supported combinations ?
This is a tool [0] you can use to test this using GStreamer and how to use it
[1].
[0] https://gitlab.collabora.com/mediatek/aiot/lava-test-definitions/-/tree/main/avvideocompare?ref_type=heads
[1] https://gitlab.collabora.com/mediatek/aiot/linux/-/blob/mediatek-next/.gitlab-ci.yml?ref_type=heads#L282
>
> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> ...
> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
> col
> test VIDIOC_S_FMT: FAIL
> ...
> Total for rockchip-rga device /dev/video0: 47, Succeeded: 46, Failed: 1,
> Warnings: 0
>
> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> ...
> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
> col
> test VIDIOC_S_FMT: FAIL
> ...
> Total for rockchip-rga device /dev/video1: 47, Succeeded: 46, Failed: 1,
> Warnings: 0
>
> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> ...
> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
> col
> test VIDIOC_S_FMT: FAIL
> ...
> Total for rockchip-rga device /dev/video2: 47, Succeeded: 46, Failed: 1,
> Warnings: 0
>
> Each RGA core is a separate /dev/video device. To distinguish the RGA2
> core from the RGA3 cores the Card type is set accordingly. Combining all
> cores into a single device and scheduling tasks to the best core might
> be a future improvement, if it is desired by upstream to handle the
> scheduling and selection in kernel space.
It took me some time to understand why you spoke about multicore here. You
forgot to say here that you add RGA3 into RGA2 driver. Some information on why
you went that path instead of a separate driver.
From high level view, I don't think its a good idea to multi-plex over
heterogeneous core. They may not even produce the exact same pixels for the same
operation. They also don't share the same MMU, and at first glance, the use of
rkiommu in RGA3 means it can no longer handle CPU cache (though I don't know if
this is implemented/supported in upstream RGA2 driver).
>
> Patch 1-2 are general cleanups
> Patch 3-12 prepare the rga driver for the RGA3
> Patch 13 documments the RGA3 compatible value
> Patch 14 adds the RGA3 cores to the rk3588 dtsi
> Patch 15 increases the RGA3 core clock speeds
> Patch 16 adds RGA3 support to the rga driver
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> Sven Püschel (16):
> media: rockchip: rga: use clk_bulk api
> media: rockchip: rga: use stride for offset calculation
> media: rockchip: rga: align stride to 16 bytes
> media: rockchip: rga: move hw specific parts to a dedicated struct
> media: rockchip: rga: use card type to specify rga type
> media: rockchip: rga: change offset to dma_addresses
> media: rockchip: rga: support external iommus
> media: rockchip: rga: remove size from rga_frame
> media: rockchip: rga: remove stride from rga_frame
> media: rockchip: rga: move rga_fmt to rga-hw.h
> media: rockchip: rga: add iommu restore function
> media: rockchip: rga: handle error interrupt
> media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
> arm64: dts: rockchip: add rga3 dt nodes
> arm64: dts: rockchip: increase rga3 clock speed
> media: rockchip: rga: add rga3 support
>
> .../devicetree/bindings/media/rockchip-rga.yaml | 1 +
> arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 50 +++
> drivers/media/platform/rockchip/rga/Makefile | 2 +-
> drivers/media/platform/rockchip/rga/rga-buf.c | 78 ++--
> drivers/media/platform/rockchip/rga/rga-hw.c | 356 ++++++++++++---
> drivers/media/platform/rockchip/rga/rga-hw.h | 15 +-
> drivers/media/platform/rockchip/rga/rga.c | 404 ++++++-----------
> drivers/media/platform/rockchip/rga/rga.h | 74 ++--
> drivers/media/platform/rockchip/rga/rga3-hw.c | 490
> +++++++++++++++++++++
> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++
> 10 files changed, 1246 insertions(+), 410 deletions(-)
> ---
> base-commit: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328
> change-id: 20251001-spu-rga3-8a00e018b120
>
> Best regards,
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
2025-10-07 8:38 ` Krzysztof Kozlowski
@ 2025-10-07 18:12 ` Nicolas Dufresne
0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 18:12 UTC (permalink / raw)
To: Krzysztof Kozlowski, Sven Püschel, Jacob Chen,
Ezequiel Garcia, Mauro Carvalho Chehab, Heiko Stuebner,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 1781 bytes --]
Hi,
Le mardi 07 octobre 2025 à 17:38 +0900, Krzysztof Kozlowski a écrit :
> On 07/10/2025 17:32, Sven Püschel wrote:
> > Add a new compatible for the rk3588 Rockchip SoC, which features an
> > RGA3, which is described in the TRM Part2.
Please write something here. You can't explain why RK did this, but at least
explain what are the differences and additional feature. It should also be super
clear through your patchset everything you didn't support, since when reading
your set, it really have nothing extra implemented.
> >
> > Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> > ---
> > Documentation/devicetree/bindings/media/rockchip-rga.yaml | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> > b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> > index
> > ac17cda65191be047fc61d0c806f806c6af07c7b..11e86333c56aab55d9358dc88e45e7c1eb
> > faae9e 100644
> > --- a/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> > +++ b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
> > @@ -20,6 +20,7 @@ properties:
> > oneOf:
> > - const: rockchip,rk3288-rga
> > - const: rockchip,rk3399-rga
> > + - const: rockchip,rk3588-rga3
>
> There is already rk3588-rga, so please explain in commit msg
> differences, including compatibility or lack thereof. I am confused why
> there are two completely different 2D accelerators simultaneously on
> that SoC.
It is quite strange hardware design, but this is really how the hardware is. I
personally don't expect an explanation from a third party. Its a mirror of the
VOP2 planes really.
Nicolas
>
> Best regards,
> Krzysztof
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 03/16] media: rockchip: rga: align stride to 16 bytes
2025-10-07 8:31 ` [PATCH 03/16] media: rockchip: rga: align stride to 16 bytes Sven Püschel
@ 2025-10-07 18:19 ` Nicolas Dufresne
0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 18:19 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 2964 bytes --]
Hi,
Le mardi 07 octobre 2025 à 10:31 +0200, Sven Püschel a écrit :
> Align the stride to a multiple of 16 according to the RGA3 requirements
> mentioned in the datasheet. This also ensures that the stride of the RGA2
> is aligned to 4 bytes, as it needs to divide the value by 4 (one word)
> before storing it in the register.
>
> Increasing the stride for the alignment also requires to increase the
> sizeimage value. This is usually handled by v4l2_fill_pixfmt_mp, but
> it doesn't allow to set a stride alignment. Therefore use the generated
> values to calculate the total number of lines to properly update the
> sizeimage value after the bytesperline has been aligned.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.c
> b/drivers/media/platform/rockchip/rga/rga.c
> index
> 6438119a6c7aeff1e89e7aa95dcd5d2921fefa08..3cb7ce470c47e39d694e8176875a75fad271
> 7f96 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -459,6 +459,25 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
> struct v4l2_fmtdesc *f
> return 0;
> }
>
> +static void align_pixfmt(struct v4l2_pix_format_mplane *pix_fmt)
> +{
> + int lines;
> + struct v4l2_plane_pix_format *fmt;
> +
> + /*
> + * Align stride to 16 for the RGA3 (based on the datasheet)
> + * To not dismiss the v4l2_fill_pixfmt_mp helper
> + * (and manually write it again), we're approximating the new
> sizeimage
> + */
> + for (fmt = pix_fmt->plane_fmt;
> + fmt < pix_fmt->plane_fmt + pix_fmt->num_planes;
> + fmt++) {
> + lines = DIV_ROUND_UP(fmt->sizeimage, fmt->bytesperline);
> + fmt->bytesperline = (fmt->bytesperline + 0xf) & ~0xf;
> + fmt->sizeimage = fmt->bytesperline * lines;
Instead of open coding this, describe this with struct v4l2_frmsize_stepwise and
then use v4l2_apply_frmsize_constraints().
Nicolas
> + }
> +}
> +
> static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
> {
> struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp;
> @@ -474,6 +493,7 @@ static int vidioc_g_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> return PTR_ERR(frm);
>
> v4l2_fill_pixfmt_mp(pix_fmt, frm->fmt->fourcc, frm->width, frm-
> >height);
> + align_pixfmt(pix_fmt);
>
> pix_fmt->field = V4L2_FIELD_NONE;
> pix_fmt->colorspace = frm->colorspace;
> @@ -496,6 +516,7 @@ static int vidioc_try_fmt(struct file *file, void *priv,
> struct v4l2_format *f)
> (u32)MIN_HEIGHT, (u32)MAX_HEIGHT);
>
> v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt-
> >height);
> + align_pixfmt(pix_fmt);
> pix_fmt->field = V4L2_FIELD_NONE;
>
> return 0;
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 11/16] media: rockchip: rga: add iommu restore function
2025-10-07 8:32 ` [PATCH 11/16] media: rockchip: rga: add iommu restore function Sven Püschel
@ 2025-10-07 18:30 ` Nicolas Dufresne
2025-10-10 8:45 ` Sven Püschel
0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 18:30 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 4223 bytes --]
Hi,
Le mardi 07 octobre 2025 à 10:32 +0200, Sven Püschel a écrit :
> Add an iommu restore function in preparation for the rga3 addition.
> This is necessary for a soft reset, as the rga3 will also reset
> it's iommu paging table to 0 and disable paging.
>
> The empty domain attach/detach to restore the iommu is copied
> from the rkvdec driver.
We did receive negative feedback after the fact on this one. We will likely
upset further the iommu subsystem maintainers with that. Have you considered
adding a restore function in the rkiommu driver, similar to TI mmu and Benjamin
VSI MMU proposal ?
I have no precise objection, I know it works, but adding a restore function
seems also pretty straight forward.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga.c | 24 ++++++++++++++++++++++++
> drivers/media/platform/rockchip/rga/rga.h | 7 +++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.c
> b/drivers/media/platform/rockchip/rga/rga.c
> index
> cd4da01645611e5fb51ed94e09b5f1463dad72c5..0a725841b0cfa41bbc5b861b8f5ceac2452f
> c2b5 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -9,6 +9,7 @@
> #include <linux/delay.h>
> #include <linux/fs.h>
> #include <linux/interrupt.h>
> +#include <linux/iommu.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/pm_runtime.h>
> @@ -560,6 +561,19 @@ static const struct video_device rga_videodev = {
> .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
> };
>
> +void rga_iommu_restore(struct rockchip_rga *rga)
> +{
> + if (rga->empty_domain) {
> + /*
> + * To rewrite mapping into the attached IOMMU core, attach a
> new empty domain that
> + * will program an empty table, then detach it to restore the
> default domain and
> + * all cached mappings.
> + */
> + iommu_attach_device(rga->empty_domain, rga->dev);
> + iommu_detach_device(rga->empty_domain, rga->dev);
> + }
> +}
> +
> static int rga_parse_dt(struct rockchip_rga *rga)
> {
> struct reset_control *core_rst, *axi_rst, *ahb_rst;
> @@ -657,6 +671,13 @@ static int rga_probe(struct platform_device *pdev)
> goto err_put_clk;
> }
>
> + if (iommu_get_domain_for_dev(rga->dev)) {
> + rga->empty_domain = iommu_paging_domain_alloc(rga->dev);
> +
> + if (!rga->empty_domain)
Its an error pointer, see:
https://gitlab.freedesktop.org/linux-media/media-committers/-/commit/6347dc7fb967521a77f9ff0774d25ef0cca4c6cd
> + dev_warn(rga->dev, "cannot alloc new empty
> domain\n");
> + }
> +
> ret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev);
> if (ret)
> goto err_put_clk;
> @@ -741,6 +762,9 @@ static void rga_remove(struct platform_device *pdev)
> v4l2_device_unregister(&rga->v4l2_dev);
>
> pm_runtime_disable(rga->dev);
> +
> + if (rga->empty_domain)
> + iommu_domain_free(rga->empty_domain);
> }
>
> static int __maybe_unused rga_runtime_suspend(struct device *dev)
> diff --git a/drivers/media/platform/rockchip/rga/rga.h
> b/drivers/media/platform/rockchip/rga/rga.h
> index
> fc4805ba4e8ef7fb311f780a198ba6ba4d3aff17..e19c4c82aca5ae2056f52d525138093fbbb8
> 1af8 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -75,6 +75,7 @@ struct rockchip_rga {
> void __iomem *regs;
> struct clk_bulk_data clks[3];
> struct rockchip_rga_version version;
> + struct iommu_domain *empty_domain;
>
> /* vfd lock */
> struct mutex mutex;
> @@ -114,6 +115,12 @@ static inline struct rga_vb_buffer *vb_to_rga(struct
> vb2_v4l2_buffer *vb)
>
> struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type
> type);
>
> +/*
> + * This should be called in an interrupt handler to make sure no memory
> + * is mapped through the IOMMU while the empty domain is attached.
> + */
> +void rga_iommu_restore(struct rockchip_rga *rga);
> +
> /* RGA Buffers Manage */
> extern const struct vb2_ops rga_qops;
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 12/16] media: rockchip: rga: handle error interrupt
2025-10-07 8:32 ` [PATCH 12/16] media: rockchip: rga: handle error interrupt Sven Püschel
@ 2025-10-07 18:47 ` Nicolas Dufresne
0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 18:47 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 5216 bytes --]
Le mardi 07 octobre 2025 à 10:32 +0200, Sven Püschel a écrit :
> Handle the error interrupt status in preparation of the RGA3 addition.
> This allows the buffer to be marked as done, as it would otherwise
> be stuck in the queue.
>
> The RGA3 needs a soft reset to properly work after an error occurred,
> as it would otherwise cease to deliver new interrupts. Also the soft
> reset avoids additional error interrupts to be triggered, which are
> currently not supported by the rga_isr function.
> As it is unknown how the RGA2 behaves in the error case, no
> error interrupt was enabled and handled.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 6 ++++--
> drivers/media/platform/rockchip/rga/rga.c | 32 +++++++++++++++++----------
> -
> drivers/media/platform/rockchip/rga/rga.h | 8 ++++++-
> 3 files changed, 31 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c
> b/drivers/media/platform/rockchip/rga/rga-hw.c
> index
> d54183d224b3e9c42d5503acf172257f2e736f7b..93822b5b8b15e76862bd022759eaa5cb9552
> dd76 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -459,7 +459,7 @@ static void rga_hw_start(struct rockchip_rga *rga,
> rga_write(rga, RGA_CMD_CTRL, 0x1);
> }
>
> -static bool rga_handle_irq(struct rockchip_rga *rga)
> +static enum rga_irq_result rga_handle_irq(struct rockchip_rga *rga)
> {
> int intr;
>
> @@ -467,7 +467,9 @@ static bool rga_handle_irq(struct rockchip_rga *rga)
>
> rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
>
> - return intr & 0x04;
> + if (intr & 0x04)
> + return RGA_IRQ_DONE;
Since you reuse an old driver, would be nice to create proper defines for
RGA_INT bit 3 (current command finish interrupt flag).
> + return RGA_IRQ_IGNORE;
> }
>
> static void rga_get_version(struct rockchip_rga *rga)
> diff --git a/drivers/media/platform/rockchip/rga/rga.c
> b/drivers/media/platform/rockchip/rga/rga.c
> index
> 0a725841b0cfa41bbc5b861b8f5ceac2452fc2b5..3b5d2eb8e109f44af76dd2240a239b1fa8a7
> 8cee 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -56,30 +56,38 @@ static void device_run(void *prv)
> static irqreturn_t rga_isr(int irq, void *prv)
> {
> struct rockchip_rga *rga = prv;
> + struct vb2_v4l2_buffer *src, *dst;
> + struct rga_ctx *ctx = rga->curr;
> + enum rga_irq_result result;
>
> - if (rga->hw->handle_irq(rga)) {
> - struct vb2_v4l2_buffer *src, *dst;
> - struct rga_ctx *ctx = rga->curr;
> + result = rga->hw->handle_irq(rga);
> + if (result == RGA_IRQ_IGNORE)
> + return IRQ_HANDLED;
>
> - WARN_ON(!ctx);
> + WARN_ON(!ctx);
>
> - rga->curr = NULL;
> + rga->curr = NULL;
>
> - src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> - dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> + src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> + dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
>
> - WARN_ON(!src);
> - WARN_ON(!dst);
> + WARN_ON(!src);
> + WARN_ON(!dst);
>
> - v4l2_m2m_buf_copy_metadata(src, dst, true);
> + v4l2_m2m_buf_copy_metadata(src, dst, true);
>
> - dst->sequence = ctx->csequence++;
> + dst->sequence = ctx->csequence++;
>
> + if (result == RGA_IRQ_DONE) {
> v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
> v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
> - v4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx);
> + } else {
> + v4l2_m2m_buf_done(src, VB2_BUF_STATE_ERROR);
> + v4l2_m2m_buf_done(dst, VB2_BUF_STATE_ERROR)
I'm not fan of assumption that its an error on else case. If often lead to
multiple calls. Please use an explicit error return.
> ;
> }
>
> + v4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx);
What if you get an IRQ and none of the flags are raised ? I did see that in the
past, and that least to bad things happening.
> +
> return IRQ_HANDLED;
> }
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.h
> b/drivers/media/platform/rockchip/rga/rga.h
> index
> e19c4c82aca5ae2056f52d525138093fbbb81af8..dc4bb85707d12f5378c4891098cd7ea4a4d7
> 5e2d 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -143,6 +143,12 @@ static inline void rga_mod(struct rockchip_rga *rga, u32
> reg, u32 val, u32 mask)
> rga_write(rga, reg, temp);
> };
>
> +enum rga_irq_result {
> + RGA_IRQ_IGNORE,
> + RGA_IRQ_DONE,
> + RGA_IRQ_ERROR,
> +};
> +
> struct rga_hw {
> const char *card_type;
> bool has_internal_iommu;
> @@ -152,7 +158,7 @@ struct rga_hw {
>
> void (*start)(struct rockchip_rga *rga,
> struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
> - bool (*handle_irq)(struct rockchip_rga *rga);
> + enum rga_irq_result (*handle_irq)(struct rockchip_rga *rga);
> void (*get_version)(struct rockchip_rga *rga);
> void *(*try_format)(u32 *fourcc, bool is_output);
> int (*enum_format)(struct v4l2_fmtdesc *f);
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 8:39 ` Krzysztof Kozlowski
2025-10-07 16:05 ` Sven Püschel
@ 2025-10-07 18:54 ` Nicolas Dufresne
1 sibling, 0 replies; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 18:54 UTC (permalink / raw)
To: Krzysztof Kozlowski, Sven Püschel, Jacob Chen,
Ezequiel Garcia, Mauro Carvalho Chehab, Heiko Stuebner,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 1525 bytes --]
Hi Krzysztof,
Le mardi 07 octobre 2025 à 17:39 +0900, Krzysztof Kozlowski a écrit :
> On 07/10/2025 17:32, Sven Püschel wrote:
> > Add support for the RGA3 unit contained in the RK3588.
> >
> > Only a basic feature set consisting of scaling and color conversion is
> > implemented. Advanced features like rotation and cropping will just be
> > ignored. Also the BT601F color space conversion is currently hard coded.
> >
> > The register address defines were copied from the
> > vendor Rockchip kernel sources and slightly adjusted to not start at 0
> > again for the cmd registers.
> >
> > Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> > ---
> > drivers/media/platform/rockchip/rga/Makefile | 2 +-
> > drivers/media/platform/rockchip/rga/rga.c | 4 +
> > drivers/media/platform/rockchip/rga/rga.h | 2 +-
> > drivers/media/platform/rockchip/rga/rga3-hw.c | 490
> > ++++++++++++++++++++++++++
> > drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
> > 5 files changed, 682 insertions(+), 2 deletions(-)
>
> Your order of patches is a mess. DTS cannot be in the middle. In fact,
> DTS should not be even in this patchset, because you are targeting media.
Indeed, order is broken, though I do appreciate having the DTS as part of the
submission, this way I don't have to chase for them when testing. That being
said, a link or message ID in the cover later would be as good.
Nicolas
>
> Best regards,
> Krzysztof
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 8:32 ` [PATCH 16/16] media: rockchip: rga: add rga3 support Sven Püschel
2025-10-07 8:39 ` Krzysztof Kozlowski
@ 2025-10-07 19:41 ` Nicolas Dufresne
2025-10-10 9:21 ` Sven Püschel
2025-10-11 5:32 ` kernel test robot
2 siblings, 1 reply; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-07 19:41 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 28130 bytes --]
Hi,
Le mardi 07 octobre 2025 à 10:32 +0200, Sven Püschel a écrit :
> Add support for the RGA3 unit contained in the RK3588.
>
> Only a basic feature set consisting of scaling and color conversion is
> implemented. Advanced features like rotation and cropping will just be
> ignored. Also the BT601F color space conversion is currently hard coded.
>
> The register address defines were copied from the
> vendor Rockchip kernel sources and slightly adjusted to not start at 0
> again for the cmd registers.
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/Makefile | 2 +-
> drivers/media/platform/rockchip/rga/rga.c | 4 +
> drivers/media/platform/rockchip/rga/rga.h | 2 +-
> drivers/media/platform/rockchip/rga/rga3-hw.c | 490 ++++++++++++++++++++++++++
> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
> 5 files changed, 682 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/Makefile b/drivers/media/platform/rockchip/rga/Makefile
> index 1bbecdc3d8df2ce286652f5544c4a3b52a6d28cf..7326a548f3dc7618403e98974b8c60d45f556fef 100644
> --- a/drivers/media/platform/rockchip/rga/Makefile
> +++ b/drivers/media/platform/rockchip/rga/Makefile
> @@ -1,4 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> -rockchip-rga-objs := rga.o rga-hw.o rga-buf.o
> +rockchip-rga-objs := rga.o rga-hw.o rga3-hw.o rga-buf.o
>
> obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index 3b5d2eb8e109f44af76dd2240a239b1fa8a78cee..9d15104fcc1a45553af33bfd637bba0a86329c17 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -805,6 +805,10 @@ static const struct of_device_id rockchip_rga_match[] = {
> .compatible = "rockchip,rk3399-rga",
> .data = &rga2_hw,
> },
> + {
> + .compatible = "rockchip,rk3588-rga3",
> + .data = &rga3_hw,
> + },
> {},
> };
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index dc4bb85707d12f5378c4891098cd7ea4a4d75e2d..350a4e07cb2ee237fc3676d594e1e7298a028afb 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -169,6 +169,6 @@ static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
> return rga->hw->has_internal_iommu;
> }
>
> -extern const struct rga_hw rga2_hw;
> +extern const struct rga_hw rga2_hw, rga3_hw;
>
> #endif
> diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.c b/drivers/media/platform/rockchip/rga/rga3-hw.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..6e4cd2f96cf866880316c75924f7a4c339851448
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rga/rga3-hw.c
> @@ -0,0 +1,490 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) Pengutronix e.K.
> + * Author: Sven Püschel <s.pueschel@pengutronix.de>
> + */
> +
> +#include <linux/pm_runtime.h>
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/printk.h>
> +
> +#include <media/v4l2-common.h>
> +
> +#include "rga3-hw.h"
> +#include "rga.h"
> +
> +static unsigned int rga3_get_scaling(unsigned int src, unsigned int dst)
Would be nice to summarize what you are calculating here.
> +{
> + if (dst > src) {
> + if (((src - 1) << 16) % (dst - 1) == 0)
> + return ((src - 1) << 16) / (dst - 1) - 1;
> + else
> + return ((src - 1) << 16) / (dst - 1);
> + } else {
> + return ((dst - 1) << 16) / (src - 1) + 1;
> + }
Its unclear to me why the various -1, and why the factor get reversed depending
up or down scale.
> +}
> +
> +static bool rga3_has_alpha(const struct rga3_fmt *fmt)
> +{
> + return fmt->hw_format >= RGA3_COLOR_FMT_FIRST_HAS_ALPHA &&
> + fmt->fourcc != V4L2_PIX_FMT_BGRX32 &&
> + fmt->fourcc != V4L2_PIX_FMT_XBGR32 &&
> + fmt->fourcc != V4L2_PIX_FMT_RGBX32 &&
> + fmt->fourcc != V4L2_PIX_FMT_XRGB32;
Would be nice to extend v4l2-common ?
> +}
> +
> +static bool rga3_can_capture(const struct rga3_fmt *fmt)
> +{
> + return fmt->hw_format <= RGA3_COLOR_FMT_LAST_OUTPUT;
> +}
> +
> +static void rga3_cmd_set_trans_info(struct rga_ctx *ctx)
Not obvious some the function name, can you add a comment block.
> +{
> + struct rockchip_rga *rga = ctx->rga;
> + u32 *cmd = rga->cmdbuf_virt;
> + unsigned int src_h, src_w, dst_h, dst_w;
> + unsigned int reg;
> + u16 hor_scl_fac, ver_scl_fac;
> +
> + src_h = ctx->in.crop.height;
> + src_w = ctx->in.crop.width;
> + dst_h = ctx->out.crop.height;
> + dst_w = ctx->out.crop.width;
There is no position component to these rectangle ? It is a bit confusing to
called cropped rectangles as src and dest only.
> +
> + reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_SCALE_HOR_UP, dst_w > src_w)
> + | FIELD_PREP(RGA3_WIN_SCALE_HOR_BYPASS, dst_w == src_w)
> + | FIELD_PREP(RGA3_WIN_SCALE_VER_UP, dst_h > src_h)
> + | FIELD_PREP(RGA3_WIN_SCALE_VER_BYPASS, dst_h == src_h);
> +
> + /* stride needs to be in words */
> + reg = RGA3_WIN0_VIR_STRIDE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2;
> + reg = RGA3_WIN0_UV_VIR_STRIDE - RGA3_FIRST_CMD_REG;
> + if (ctx->in.pix.num_planes >= 2)
> + cmd[reg >> 2] = ctx->in.pix.plane_fmt[1].bytesperline >> 2;
> + else
> + cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2;
I find this pattern a bit hacky, and hiding what its for. My reading this is
that if num_planes == 1, the driver does not know how many planes there is, due
to legacy single plane formats, such as NV12 (in contrast to NV12M). So it just
repeat the stride in all places.
That where is bugs me, since you use >=2 if the number of planes if 3, the third
stride is missing, but would also not be equal. If the HW is limited to NV style
of format, then don't use >=2, but rather == 2. And comment about it.
> + reg = RGA3_WR_VIR_STRIDE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2;
> + reg = RGA3_WR_PL_VIR_STRIDE - RGA3_FIRST_CMD_REG;
> + if (ctx->out.pix.num_planes >= 2)
> + cmd[reg >> 2] = ctx->out.pix.plane_fmt[1].bytesperline >> 2;
> + else
> + cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2;
> +
> + reg = RGA3_WIN0_ACT_SIZE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w)
> + | FIELD_PREP(RGA3_HEIGHT, src_h);
> + reg = RGA3_WIN0_SRC_SIZE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w)
> + | FIELD_PREP(RGA3_HEIGHT, src_h);
Just guessing, because the code is not clear, but is that ACT (actual) and SRC
(source). Someone the original image size, and the source rectangle ? In which
case, is it ok to pass twice the cropped size ?
> +
> + reg = RGA3_WIN0_DST_SIZE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, dst_w)
> + | FIELD_PREP(RGA3_HEIGHT, dst_h);
> +
> + hor_scl_fac = rga3_get_scaling(src_w, dst_w);
> + ver_scl_fac = rga3_get_scaling(src_h, dst_h);
> + reg = RGA3_WIN0_SCL_FAC - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_SCALE_HOR_FAC, hor_scl_fac)
> + | FIELD_PREP(RGA3_SCALE_VER_FAC, ver_scl_fac);
> +
> + if (rga3_has_alpha(ctx->in.fmt)) {
> + /* copy alpha from input */
Fair enough, I'd appreciate in the commit message to have an overview of all the
features that are not covered by the driver. Notably you don't support the
second window for blits (V4L2 does not have enough CID to do that either), you
don't seem to fully support S_SELECTION, this is a bit annoying, no background
colors, rotation, and probably more stuff I forget about.
> + reg = RGA3_OVLP_TOP_ALPHA - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1)
> + | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1);
> + reg = RGA3_OVLP_BOT_ALPHA - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1)
> + | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1);
> + } else {
> + /* just use a 255 alpha value */
> + reg = RGA3_OVLP_TOP_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff)
> + | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1);
> + reg = RGA3_OVLP_BOT_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff)
> + | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1);
Have you considered implementing V4L2_CID_ALPHA_COMPONENT ?
> + }
> +}
> +
> +static void rga3_cmd_set_win0_addr(struct rga_ctx *ctx,
> + const struct rga_addrs *addrs)
> +{
> + u32 *cmd = ctx->rga->cmdbuf_virt;
> + unsigned int reg;
> +
> + reg = RGA3_WIN0_Y_BASE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = addrs->y_addr;
> + reg = RGA3_WIN0_U_BASE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = addrs->u_addr;
> +}
> +
> +static void rga3_cmd_set_wr_addr(struct rga_ctx *ctx,
> + const struct rga_addrs *addrs)
> +{
> + u32 *cmd = ctx->rga->cmdbuf_virt;
> + unsigned int reg;
> +
> + reg = RGA3_WR_Y_BASE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = addrs->y_addr;
> + reg = RGA3_WR_U_BASE - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] = addrs->u_addr;
> +}
> +
> +static void rga3_cmd_set_win0_format(struct rga_ctx *ctx)
> +{
> + u32 *cmd = ctx->rga->cmdbuf_virt;
> + const struct rga3_fmt *in = ctx->in.fmt;
> + const struct rga3_fmt *out = ctx->out.fmt;
> + const struct v4l2_format_info *in_fmt, *out_fmt;
> + unsigned int src_h, src_w, dst_h, dst_w;
> + bool r2y, y2r;
> + u8 rd_format;
> + unsigned int reg;
> +
> + src_h = ctx->in.crop.height;
> + src_w = ctx->in.crop.width;
> + dst_h = ctx->out.crop.height;
> + dst_w = ctx->out.crop.width;
> +
> + in_fmt = v4l2_format_info(in->fourcc);
> + out_fmt = v4l2_format_info(out->fourcc);
> + r2y = v4l2_is_format_rgb(in_fmt) && v4l2_is_format_yuv(out_fmt);
> + y2r = v4l2_is_format_yuv(in_fmt) && v4l2_is_format_rgb(out_fmt);
> +
> + if (in->semi_planar)
> + rd_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
> + else
> + rd_format = RGA3_RDWR_FORMAT_INTERLEAVED;
> +
> + reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_PIC_FORMAT, in->hw_format)
> + | FIELD_PREP(RGA3_WIN_YC_SWAP, in->yc_swap)
> + | FIELD_PREP(RGA3_WIN_RBUV_SWAP, in->rbuv_swap)
> + | FIELD_PREP(RGA3_WIN_RD_FORMAT, rd_format)
> + | FIELD_PREP(RGA3_WIN_R2Y, r2y)
> + | FIELD_PREP(RGA3_WIN_Y2R, y2r)
> + | FIELD_PREP(RGA3_WIN_CSC_MODE, RGA3_WIN_CSC_MODE_BT601_F);
I don't think I saw code in the v4l2 part the enforce that only that conversion
is allowed. Just picking a hidden CSC and pixel transfer make your driver
unusable in real world.
My take is that a driver that implement CSC should be really serious about the
CSC aspect. So if you'd like to get a subset in a first iteration, make sure
that the v4l2_format will perfectly reflect that subset so userspace does not
fooled into producing pad colors. In short, this driver only have 2 jobs at the
moment, scale and CSC. Let do that well ?
> +}
> +
> +static void rga3_cmd_enable_win0(struct rga_ctx *ctx)
> +{
> + u32 *cmd = ctx->rga->cmdbuf_virt;
> + unsigned int reg;
> +
> + reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_ENABLE, 1);
> +}
> +
> +static void rga3_cmd_set_wr_format(struct rga_ctx *ctx)
> +{
> + u32 *cmd = ctx->rga->cmdbuf_virt;
> + const struct rga3_fmt *out = ctx->out.fmt;
> + u8 wr_format;
> + unsigned int reg;
> +
> + if (out->semi_planar)
> + wr_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
> + else
> + wr_format = RGA3_RDWR_FORMAT_INTERLEAVED;
> +
> + reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WR_PIC_FORMAT, out->hw_format)
> + | FIELD_PREP(RGA3_WR_YC_SWAP, out->yc_swap)
> + | FIELD_PREP(RGA3_WR_RBUV_SWAP, out->rbuv_swap)
> + | FIELD_PREP(RGA3_WR_FORMAT, wr_format);
> +}
> +
> +static void rga3_cmd_disable_wr_limitation(struct rga_ctx *ctx)
> +{
> + u32 *cmd = ctx->rga->cmdbuf_virt;
> + unsigned int reg;
> +
> + /* Use the max value to avoid limiting the write speed */
> + reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG;
> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WR_SW_OUTSTANDING_MAX, 63);
No issue with the code, but quite an interesting feature. We did discussed in
pas about using the target framerate (well frame duration in v4l2) to avoid
bursting the memory.
> +}
> +
> +static void rga3_cmd_set(struct rga_ctx *ctx,
> + struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
> +{
> + struct rockchip_rga *rga = ctx->rga;
> +
> + memset(rga->cmdbuf_virt, 0, RGA3_CMDBUF_SIZE * 4);
> +
> + rga3_cmd_set_win0_addr(ctx, &src->dma_addrs);
> + rga3_cmd_set_wr_addr(ctx, &dst->dma_addrs);
> +
> + rga3_cmd_set_win0_format(ctx);
> + rga3_cmd_enable_win0(ctx);
> + rga3_cmd_set_trans_info(ctx);
> + rga3_cmd_set_wr_format(ctx);
> + rga3_cmd_disable_wr_limitation(ctx);
> +
> + rga_write(rga, RGA3_CMD_ADDR, rga->cmdbuf_phy);
> +
> + /* sync CMD buf for RGA */
> + dma_sync_single_for_device(rga->dev, rga->cmdbuf_phy,
> + PAGE_SIZE, DMA_BIDIRECTIONAL);
> +}
> +
> +static void rga3_hw_start(struct rockchip_rga *rga,
> + struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
> +{
> + struct rga_ctx *ctx = rga->curr;
> +
> + rga3_cmd_set(ctx, src, dst);
> +
> + /* set to master mode and start the conversion */
> + rga_write(rga, RGA3_SYS_CTRL,
> + FIELD_PREP(RGA3_CMD_MODE, RGA3_CMD_MODE_MASTER));
> + rga_write(rga, RGA3_INT_EN,
> + FIELD_PREP(RGA3_INT_FRM_DONE, 1) |
> + FIELD_PREP(RGA3_INT_DMA_READ_BUS_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_FBC_DEC_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_HOR_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_VER_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WR_VER_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WR_HOR_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WR_BUS_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_IN_FIFO_WR_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_IN_FIFO_RD_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_HOR_FIFO_WR_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_HOR_FIFO_RD_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_VER_FIFO_WR_ERR, 1) |
> + FIELD_PREP(RGA3_INT_WIN0_VER_FIFO_RD_ERR, 1));
> + rga_write(rga, RGA3_CMD_CTRL,
> + FIELD_PREP(RGA3_CMD_LINE_START_PULSE, 1));
> +}
> +
> +static void rga3_soft_reset(struct rockchip_rga *rga)
> +{
> + u32 i;
> +
> + rga_write(rga, RGA3_SYS_CTRL,
> + FIELD_PREP(RGA3_CCLK_SRESET, 1) |
> + FIELD_PREP(RGA3_ACLK_SRESET, 1));
> +
> + for (i = 0; i < RGA3_RESET_TIMEOUT; i++) {
> + if (FIELD_GET(RGA3_RO_SRST_DONE, rga_read(rga, RGA3_RO_SRST)))
> + break;
> +
> + udelay(1);
Did you measure this IP soft reset speed ? Perhaps this delay can be tune to
avoid hugging on a CPU core ?
> + }
> +
> + if (i == RGA3_RESET_TIMEOUT)
> + pr_err("Timeout of %d usec reached while waiting for an rga3 soft reset\n", i);
What next if it failed ? System lockup, or just bunch of errors ?
> +
> + rga_write(rga, RGA3_SYS_CTRL, 0);
> + rga_iommu_restore(rga);
> +}
> +
> +static enum rga_irq_result rga3_handle_irq(struct rockchip_rga *rga)
> +{
> + u32 intr;
> +
> + intr = rga_read(rga, RGA3_INT_RAW);
> + /* clear all interrupts */
> + rga_write(rga, RGA3_INT_CLR, intr);
> +
> + if (FIELD_GET(RGA3_INT_FRM_DONE, intr))
> + return RGA_IRQ_DONE;
> + if (FIELD_GET(RGA3_INT_DMA_READ_BUS_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_FBC_DEC_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_HOR_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_VER_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WR_VER_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WR_HOR_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WR_BUS_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_IN_FIFO_WR_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_IN_FIFO_RD_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_HOR_FIFO_WR_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_HOR_FIFO_RD_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_VER_FIFO_WR_ERR, intr) ||
> + FIELD_GET(RGA3_INT_WIN0_VER_FIFO_RD_ERR, intr)) {
> + rga3_soft_reset(rga);
> + return RGA_IRQ_ERROR;
Are you certain all these errors are fatal in the first place ? That being said,
since you "soft reset", I bet this basically abort any pending operation, so it
should not matter.
> + }
> +
> + return RGA_IRQ_IGNORE;
> +}
> +
> +static void rga3_get_version(struct rockchip_rga *rga)
> +{
> + u32 version = rga_read(rga, RGA3_VERSION_NUM);
> +
> + rga->version.major = FIELD_GET(RGA3_VERSION_NUM_MAJOR, version);
> + rga->version.minor = FIELD_GET(RGA3_VERSION_NUM_MINOR, version);
> +}
> +
> +static struct rga3_fmt rga3_formats[] = {
> + {
> + .fourcc = V4L2_PIX_FMT_RGB24,
> + .hw_format = RGA3_COLOR_FMT_BGR888,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_BGR24,
> + .hw_format = RGA3_COLOR_FMT_BGR888,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_ABGR32,
> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_RGBA32,
> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_XBGR32,
> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_RGBX32,
> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_RGB565,
> + .hw_format = RGA3_COLOR_FMT_BGR565,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV12M,
> + .hw_format = RGA3_COLOR_FMT_YUV420,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV12,
> + .hw_format = RGA3_COLOR_FMT_YUV420,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV21M,
> + .hw_format = RGA3_COLOR_FMT_YUV420,
> + .rbuv_swap = 1,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV21,
> + .hw_format = RGA3_COLOR_FMT_YUV420,
> + .rbuv_swap = 1,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV16M,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV16,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV61M,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .rbuv_swap = 1,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV61,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .rbuv_swap = 1,
> + .semi_planar = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_YUYV,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .yc_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_YVYU,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .yc_swap = 1,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_UYVY,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_VYUY,
> + .hw_format = RGA3_COLOR_FMT_YUV422,
> + .rbuv_swap = 1,
Any chance you could add 10bit formats ? It can handle NV15 and P010. So far
this had been the main reason people have been interested in RGA3 (that and its
AFBC feature, but the later is quite some more work, since we don't have the
common code to compute the header sizes in media/ yet).
> + },
> + /* Input only formats last to keep rga3_enum_format simple */
> + {
> + .fourcc = V4L2_PIX_FMT_ARGB32,
> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_BGRA32,
> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_XRGB32,
> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
> + .rbuv_swap = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_BGRX32,
> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
> + },
> +};
> +
> +static int rga3_enum_format(struct v4l2_fmtdesc *f)
> +{
> + struct rga3_fmt *fmt;
> +
> + if (f->index >= ARRAY_SIZE(rga3_formats))
> + return -EINVAL;
> +
> + fmt = &rga3_formats[f->index];
> + if (V4L2_TYPE_IS_CAPTURE(f->type) && !rga3_can_capture(fmt))
> + return -EINVAL;
> +
> + f->pixelformat = fmt->fourcc;
> + return 0;
> +}
> +
> +static void *rga3_try_format(u32 *fourcc, bool is_output)
This is not really a try_format function, but a tiny subset. If you really like
the "try", perhaps call it rga3_try_pixelformat() ?
> +{
> + unsigned int i;
> +
> + if (!fourcc)
> + return &rga3_formats[0];
> +
> + for (i = 0; i < ARRAY_SIZE(rga3_formats); i++) {
> + if (!is_output && !rga3_can_capture(&rga3_formats[i]))
> + continue;
> +
> + if (rga3_formats[i].fourcc == *fourcc)
> + return &rga3_formats[i];
> + }
> +
> + *fourcc = rga3_formats[0].fourcc;
> + return &rga3_formats[0];
> +}
> +
> +const struct rga_hw rga3_hw = {
> + .card_type = "rga3",
> + .has_internal_iommu = false,
> + .cmdbuf_size = RGA3_CMDBUF_SIZE,
> + .min_width = RGA3_MIN_WIDTH,
> + .min_height = RGA3_MIN_HEIGHT,
> + .max_width = RGA3_MAX_INPUT_WIDTH,
> + .max_height = RGA3_MAX_INPUT_HEIGHT,
> +
> + .start = rga3_hw_start,
> + .handle_irq = rga3_handle_irq,
> + .get_version = rga3_get_version,
> + .enum_format = rga3_enum_format,
> + .try_format = rga3_try_format,
> +};
> diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.h b/drivers/media/platform/rockchip/rga/rga3-hw.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..3829469e310706c11ecc52f40d3d1eb43a61d9c2
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rga/rga3-hw.h
> @@ -0,0 +1,186 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) Pengutronix e.K.
> + * Author: Sven Püschel <s.pueschel@pengutronix.de>
> + */
> +#ifndef __RGA3_HW_H__
> +#define __RGA3_HW_H__
> +
> +#include <linux/types.h>
> +
> +#define RGA3_CMDBUF_SIZE 0x2e
> +
> +#define RGA3_MIN_WIDTH 128
> +#define RGA3_MIN_HEIGHT 128
> +#define RGA3_MAX_INPUT_WIDTH (8192 - 16)
> +#define RGA3_MAX_INPUT_HEIGHT (8192 - 16)
> +#define RGA3_RESET_TIMEOUT 1000
> +
> +/* Registers address */
> +/* sys reg */
> +#define RGA3_SYS_CTRL 0x000
> +#define RGA3_CMD_CTRL 0x004
> +#define RGA3_CMD_ADDR 0x008
> +#define RGA3_MI_GROUP_CTRL 0x00c
> +#define RGA3_ARQOS_CTRL 0x010
> +#define RGA3_VERSION_NUM 0x018
> +#define RGA3_VERSION_TIM 0x01c
> +#define RGA3_INT_EN 0x020
> +#define RGA3_INT_RAW 0x024
> +#define RGA3_INT_MSK 0x028
> +#define RGA3_INT_CLR 0x02c
> +#define RGA3_RO_SRST 0x030
> +#define RGA3_STATUS0 0x034
> +#define RGA3_SCAN_CNT 0x038
> +#define RGA3_CMD_STATE 0x040
> +
> +/* cmd reg */
> +#define RGA3_WIN0_RD_CTRL 0x100
> +#define RGA3_FIRST_CMD_REG RGA3_WIN0_RD_CTRL
> +#define RGA3_WIN0_Y_BASE 0x110
> +#define RGA3_WIN0_U_BASE 0x114
> +#define RGA3_WIN0_V_BASE 0x118
> +#define RGA3_WIN0_VIR_STRIDE 0x11c
> +#define RGA3_WIN0_FBC_OFF 0x120
> +#define RGA3_WIN0_SRC_SIZE 0x124
> +#define RGA3_WIN0_ACT_OFF 0x128
> +#define RGA3_WIN0_ACT_SIZE 0x12c
> +#define RGA3_WIN0_DST_SIZE 0x130
> +#define RGA3_WIN0_SCL_FAC 0x134
> +#define RGA3_WIN0_UV_VIR_STRIDE 0x138
> +#define RGA3_WIN1_RD_CTRL 0x140
> +#define RGA3_WIN1_Y_BASE 0x150
> +#define RGA3_WIN1_U_BASE 0x154
> +#define RGA3_WIN1_V_BASE 0x158
> +#define RGA3_WIN1_VIR_STRIDE 0x15c
> +#define RGA3_WIN1_FBC_OFF 0x160
> +#define RGA3_WIN1_SRC_SIZE 0x164
> +#define RGA3_WIN1_ACT_OFF 0x168
> +#define RGA3_WIN1_ACT_SIZE 0x16c
> +#define RGA3_WIN1_DST_SIZE 0x170
> +#define RGA3_WIN1_SCL_FAC 0x174
> +#define RGA3_WIN1_UV_VIR_STRIDE 0x178
> +#define RGA3_OVLP_CTRL 0x180
> +#define RGA3_OVLP_OFF 0x184
> +#define RGA3_OVLP_TOP_KEY_MIN 0x188
> +#define RGA3_OVLP_TOP_KEY_MAX 0x18c
> +#define RGA3_OVLP_TOP_CTRL 0x190
> +#define RGA3_OVLP_BOT_CTRL 0x194
> +#define RGA3_OVLP_TOP_ALPHA 0x198
> +#define RGA3_OVLP_BOT_ALPHA 0x19c
> +#define RGA3_WR_CTRL 0x1a0
> +#define RGA3_WR_FBCE_CTRL 0x1a4
> +#define RGA3_WR_VIR_STRIDE 0x1a8
> +#define RGA3_WR_PL_VIR_STRIDE 0x1ac
> +#define RGA3_WR_Y_BASE 0x1b0
> +#define RGA3_WR_U_BASE 0x1b4
> +#define RGA3_WR_V_BASE 0x1b8
> +
> +/* Registers value */
> +#define RGA3_COLOR_FMT_YUV420 0x0
> +#define RGA3_COLOR_FMT_YUV422 0x1
> +#define RGA3_COLOR_FMT_YUV420_10B 0x2
> +#define RGA3_COLOR_FMT_YUV422_10B 0x3
> +/*
> + * Use memory ordering names
> + * instead of the datasheet naming RGB formats in big endian order
> + */
> +#define RGA3_COLOR_FMT_BGR565 0x4
> +#define RGA3_COLOR_FMT_BGR888 0x5
> +#define RGA3_COLOR_FMT_FIRST_HAS_ALPHA RGA3_COLOR_FMT_BGRA8888
> +#define RGA3_COLOR_FMT_BGRA8888 0x6
> +#define RGA3_COLOR_FMT_LAST_OUTPUT RGA3_COLOR_FMT_BGRA8888
> +/* the following are only supported as inputs */
> +#define RGA3_COLOR_FMT_ABGR8888 0x7
> +/*
> + * the following seem to be unnecessary,
> + * as they can be achieved with RB swaps
> + */
> +#define RGA3_COLOR_FMT_RGBA8888 0x8
> +#define RGA3_COLOR_FMT_ARGB8888 0x9
> +
> +#define RGA3_RDWR_FORMAT_SEMI_PLANAR 0x1
> +#define RGA3_RDWR_FORMAT_INTERLEAVED 0x2
> +
> +#define RGA3_CMD_MODE_MASTER 0x1
> +
> +#define RGA3_WIN_CSC_MODE_BT601_F 0x2
> +
> +/* RGA masks */
> +/* SYS_CTRL */
> +#define RGA3_CCLK_SRESET BIT(4)
> +#define RGA3_ACLK_SRESET BIT(3)
> +#define RGA3_CMD_MODE BIT(1)
> +
> +/* CMD_CTRL */
> +#define RGA3_CMD_LINE_START_PULSE BIT(0)
> +
> +/* VERSION_NUM */
> +#define RGA3_VERSION_NUM_MAJOR GENMASK(31, 28)
> +#define RGA3_VERSION_NUM_MINOR GENMASK(27, 20)
> +
> +/* INT_* */
> +#define RGA3_INT_FRM_DONE BIT(0)
> +#define RGA3_INT_DMA_READ_BUS_ERR BIT(2)
> +#define RGA3_INT_WIN0_FBC_DEC_ERR BIT(5)
> +#define RGA3_INT_WIN0_HOR_ERR BIT(6)
> +#define RGA3_INT_WIN0_VER_ERR BIT(7)
> +#define RGA3_INT_WR_VER_ERR BIT(13)
> +#define RGA3_INT_WR_HOR_ERR BIT(14)
> +#define RGA3_INT_WR_BUS_ERR BIT(15)
> +#define RGA3_INT_WIN0_IN_FIFO_WR_ERR BIT(16)
> +#define RGA3_INT_WIN0_IN_FIFO_RD_ERR BIT(17)
> +#define RGA3_INT_WIN0_HOR_FIFO_WR_ERR BIT(18)
> +#define RGA3_INT_WIN0_HOR_FIFO_RD_ERR BIT(19)
> +#define RGA3_INT_WIN0_VER_FIFO_WR_ERR BIT(20)
> +#define RGA3_INT_WIN0_VER_FIFO_RD_ERR BIT(21)
> +
> +/* RO_SRST */
> +#define RGA3_RO_SRST_DONE GENMASK(5, 0)
> +
> +/* *_SIZE */
> +#define RGA3_HEIGHT GENMASK(28, 16)
> +#define RGA3_WIDTH GENMASK(12, 0)
> +
> +/* SCL_FAC */
> +#define RGA3_SCALE_VER_FAC GENMASK(31, 16)
> +#define RGA3_SCALE_HOR_FAC GENMASK(15, 0)
> +
> +/* WINx_CTRL */
> +#define RGA3_WIN_CSC_MODE GENMASK(27, 26)
> +#define RGA3_WIN_R2Y BIT(25)
> +#define RGA3_WIN_Y2R BIT(24)
> +#define RGA3_WIN_SCALE_VER_UP BIT(23)
> +#define RGA3_WIN_SCALE_VER_BYPASS BIT(22)
> +#define RGA3_WIN_SCALE_HOR_UP BIT(21)
> +#define RGA3_WIN_SCALE_HOR_BYPASS BIT(20)
> +#define RGA3_WIN_YC_SWAP BIT(13)
> +#define RGA3_WIN_RBUV_SWAP BIT(12)
> +#define RGA3_WIN_RD_FORMAT GENMASK(9, 8)
> +#define RGA3_WIN_PIC_FORMAT GENMASK(7, 4)
> +#define RGA3_WIN_ENABLE BIT(0)
> +
> +/* COLOR_CTRL */
> +#define RGA3_OVLP_GLOBAL_ALPHA GENMASK(23, 16)
> +#define RGA3_OVLP_COLOR_MODE BIT(0)
> +
> +/* ALPHA_CTRL */
> +#define RGA3_ALPHA_SELECT_MODE BIT(4)
> +#define RGA3_ALPHA_BLEND_MODE GENMASK(3, 2)
> +
> +/* WR_CTRL */
> +#define RGA3_WR_YC_SWAP BIT(20)
> +#define RGA3_WR_SW_OUTSTANDING_MAX GENMASK(18, 13)
> +#define RGA3_WR_RBUV_SWAP BIT(12)
> +#define RGA3_WR_FORMAT GENMASK(9, 8)
> +#define RGA3_WR_PIC_FORMAT GENMASK(7, 4)
> +
> +struct rga3_fmt {
> + u32 fourcc;
> + u8 hw_format;
> + bool rbuv_swap;
> + bool yc_swap;
> + bool semi_planar;
> +};
> +
> +#endif
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 16:05 ` Sven Püschel
@ 2025-10-08 1:55 ` Krzysztof Kozlowski
0 siblings, 0 replies; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-08 1:55 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
On 08/10/2025 01:05, Sven Püschel wrote:
> Hi Krzysztof,
>
> On 10/7/25 10:39 AM, Krzysztof Kozlowski wrote:
>> On 07/10/2025 17:32, Sven Püschel wrote:
>>> Add support for the RGA3 unit contained in the RK3588.
>>>
>>> Only a basic feature set consisting of scaling and color conversion is
>>> implemented. Advanced features like rotation and cropping will just be
>>> ignored. Also the BT601F color space conversion is currently hard coded.
>>>
>>> The register address defines were copied from the
>>> vendor Rockchip kernel sources and slightly adjusted to not start at 0
>>> again for the cmd registers.
>>>
>>> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>>> ---
>>> drivers/media/platform/rockchip/rga/Makefile | 2 +-
>>> drivers/media/platform/rockchip/rga/rga.c | 4 +
>>> drivers/media/platform/rockchip/rga/rga.h | 2 +-
>>> drivers/media/platform/rockchip/rga/rga3-hw.c | 490 ++++++++++++++++++++++++++
>>> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
>>> 5 files changed, 682 insertions(+), 2 deletions(-)
>> Your order of patches is a mess. DTS cannot be in the middle. In fact,
>> DTS should not be even in this patchset, because you are targeting media.
>
> sorry to bother you, but could you go into a bit more detail on how it
> should be done correctly?
DTS cannot be before drivers, because this suggests that drivers depends
on DTS, which would be a NAK. See also maintainer soc profile. To avoid
having such impression of fake dependency, DTS must be placed at the end
of patchset (except the obvious part: nothing in your code can depend on
it).
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/16] media: platform: rga: Add RGA3 support
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
` (16 preceding siblings ...)
2025-10-07 18:06 ` [PATCH 00/16] media: platform: rga: Add RGA3 support Nicolas Dufresne
@ 2025-10-09 22:03 ` Rob Herring (Arm)
17 siblings, 0 replies; 36+ messages in thread
From: Rob Herring (Arm) @ 2025-10-09 22:03 UTC (permalink / raw)
To: Sven Püschel
Cc: kernel, linux-kernel, linux-rockchip, Heiko Stuebner,
Ezequiel Garcia, linux-media, Jacob Chen, Mauro Carvalho Chehab,
Conor Dooley, devicetree, linux-arm-kernel, Krzysztof Kozlowski
On Tue, 07 Oct 2025 10:31:53 +0200, Sven Püschel wrote:
> This series adds support for the Raster Graphic Acceleration 3 (RGA3)
> peripheral, which is included in the RK3588 SoC. Unlike the RGA2 it
> can use the existing rockchip-iommu-v2 driver to handle iommu mappings.
> Also the RK3588 contains two independent RGA3 cores.
>
> Only scaling and format conversions between common 8bit RGB/YUV formats
> are implemented. Also the color space conversion is fixed to BT601F.
> This already allows a practical usage of the RGA3.
>
> This was tested on a Radxa Rock 5T. With the increased clock speeds in
> the devicetree around 160 fps were measured when scaling and converting
> from RGBA 480x360 to NV12 3840x2160. Without the clock speed scaling a
> default clock division factor of 2 is used and only around 80 fps are
> reached with one core. The v4l2-compliance tests only complain about
> the already failing colorspace propagation:
>
> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> ...
> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() != col
> test VIDIOC_S_FMT: FAIL
> ...
> Total for rockchip-rga device /dev/video0: 47, Succeeded: 46, Failed: 1, Warnings: 0
>
> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> ...
> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() != col
> test VIDIOC_S_FMT: FAIL
> ...
> Total for rockchip-rga device /dev/video1: 47, Succeeded: 46, Failed: 1, Warnings: 0
>
> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> ...
> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() != col
> test VIDIOC_S_FMT: FAIL
> ...
> Total for rockchip-rga device /dev/video2: 47, Succeeded: 46, Failed: 1, Warnings: 0
>
> Each RGA core is a separate /dev/video device. To distinguish the RGA2
> core from the RGA3 cores the Card type is set accordingly. Combining all
> cores into a single device and scheduling tasks to the best core might
> be a future improvement, if it is desired by upstream to handle the
> scheduling and selection in kernel space.
>
> Patch 1-2 are general cleanups
> Patch 3-12 prepare the rga driver for the RGA3
> Patch 13 documments the RGA3 compatible value
> Patch 14 adds the RGA3 cores to the rk3588 dtsi
> Patch 15 increases the RGA3 core clock speeds
> Patch 16 adds RGA3 support to the rga driver
>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> Sven Püschel (16):
> media: rockchip: rga: use clk_bulk api
> media: rockchip: rga: use stride for offset calculation
> media: rockchip: rga: align stride to 16 bytes
> media: rockchip: rga: move hw specific parts to a dedicated struct
> media: rockchip: rga: use card type to specify rga type
> media: rockchip: rga: change offset to dma_addresses
> media: rockchip: rga: support external iommus
> media: rockchip: rga: remove size from rga_frame
> media: rockchip: rga: remove stride from rga_frame
> media: rockchip: rga: move rga_fmt to rga-hw.h
> media: rockchip: rga: add iommu restore function
> media: rockchip: rga: handle error interrupt
> media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
> arm64: dts: rockchip: add rga3 dt nodes
> arm64: dts: rockchip: increase rga3 clock speed
> media: rockchip: rga: add rga3 support
>
> .../devicetree/bindings/media/rockchip-rga.yaml | 1 +
> arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 50 +++
> drivers/media/platform/rockchip/rga/Makefile | 2 +-
> drivers/media/platform/rockchip/rga/rga-buf.c | 78 ++--
> drivers/media/platform/rockchip/rga/rga-hw.c | 356 ++++++++++++---
> drivers/media/platform/rockchip/rga/rga-hw.h | 15 +-
> drivers/media/platform/rockchip/rga/rga.c | 404 ++++++-----------
> drivers/media/platform/rockchip/rga/rga.h | 74 ++--
> drivers/media/platform/rockchip/rga/rga3-hw.c | 490 +++++++++++++++++++++
> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++
> 10 files changed, 1246 insertions(+), 410 deletions(-)
> ---
> base-commit: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328
> change-id: 20251001-spu-rga3-8a00e018b120
>
> Best regards,
> --
> Sven Püschel <s.pueschel@pengutronix.de>
>
>
>
My bot found new DTB warnings on the .dts files added or changed in this
series.
Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.
If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:
pip3 install dtschema --upgrade
This patch series was applied (using b4) to base:
Base: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328 (use --merge-base to override)
If this is not the correct base, please add 'base-commit' tag
(or use b4 which does this automatically)
New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/rockchip/' for 20251007-spu-rga3-v1-0-36ad85570402@pengutronix.de:
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-h96-max-v58.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-h96-max-v58.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-ultra.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-ultra.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-jaguar.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-jaguar.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b-io.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b-io.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3582-radxa-e52c.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3582-radxa-e52c.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-rock-5t.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5t.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-max.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-max.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-firefly-itx-3588j.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-firefly-itx-3588j.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588s-roc-pc.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-roc-pc.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb60f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi:2255.3-26: Warning (interrupts_property): /iommu@fdb70f00:#interrupt-cells: size is (12), expected multiple of 16
arch/arm64/boot/dts/rockchip/rk3588-evb2-v10.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-evb2-v10.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dtb: rga@fdb60000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dtb: rga@fdb70000 (rockchip,rk3588-rga3): 'interrupt-names', 'iommus' do not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/media/rockchip-rga.yaml#
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/16] media: platform: rga: Add RGA3 support
2025-10-07 18:06 ` [PATCH 00/16] media: platform: rga: Add RGA3 support Nicolas Dufresne
@ 2025-10-10 8:33 ` Sven Püschel
2025-10-10 13:05 ` Nicolas Dufresne
0 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-10 8:33 UTC (permalink / raw)
To: Nicolas Dufresne, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
Hi Nicolas,
On 10/7/25 8:06 PM, Nicolas Dufresne wrote:
> Hi,
>
> Le mardi 07 octobre 2025 à 10:31 +0200, Sven Püschel a écrit :
>> This series adds support for the Raster Graphic Acceleration 3 (RGA3)
>> peripheral, which is included in the RK3588 SoC. Unlike the RGA2 it
>> can use the existing rockchip-iommu-v2 driver to handle iommu mappings.
>> Also the RK3588 contains two independent RGA3 cores.
> Thanks for working on this.
>
>> Only scaling and format conversions between common 8bit RGB/YUV formats
>> are implemented. Also the color space conversion is fixed to BT601F.
>> This already allows a practical usage of the RGA3.
> This seems quite limiting, can we expect an update on this, can't be that hard
> to fully implement.
Sorry, but currently there is no need to have a fully featured
implementation from our side. As the datasheet mentions that the RGA3
should do 4 or 2 pixel/cycle depending on the operation
>> This was tested on a Radxa Rock 5T. With the increased clock speeds in
>> the devicetree around 160 fps were measured when scaling and converting
> This is quite vague, I've checked the patch and you didn't extend either there.
> Is that an overclock or was it miss-configured ? Does RK implement a devfreq ?
> Should that be moved with a voltage adjustement ? Is there any thermal nearby we
> should monitor ?
This is mainly the result of a very low performance in the initial
testing. We were quite disappointed looking at 30 fps output. The
datasheet mentions the core should do 2 or 4 pixel/cycle, so we looked
if the clock speed could be increased. The TRM Part1 mentions that the
RGA3 clock uses a default divider of 2, so I've tweaked the dtsi to
avoid the clock divider and run it on the fastest clock.
But this tweaking only increased the frame rate to around 36fps. After
some brainstorming and testing we found the culprit being the
RGA3_WR_SW_OUTSTANDING_MAX value in the command. With this value maxed
out and without the clock tweaks I've got around 80fps. As the clock
increase resulted in the expected doubling of the fps and my few tests
worked, I've included it in the patch set.
I haven't done any stress testing and don't mind to remove the clock
speed adjustments from the dtsi.
>> from RGBA 480x360 to NV12 3840x2160. Without the clock speed scaling a
>> default clock division factor of 2 is used and only around 80 fps are
>> reached with one core. The v4l2-compliance tests only complain about
>> the already failing colorspace propagation:
> Did you do any more format testing to validation all supported combinations ?
> This is a tool [0] you can use to test this using GStreamer and how to use it
> [1].
Thanks for the link!
I've did some simple format conversion tests with a static test pattern.
The tests mainly converts any combination of RGB/YUV formats (hope I
didn't miss anything) to each other. Then I convert it back to rgba with
gstreamer and compare it's hash.
For scaling I've just tested one upscale, downscale and scale to a non
aligned width/height.
> [0]https://gitlab.collabora.com/mediatek/aiot/lava-test-definitions/-/tree/main/avvideocompare?ref_type=heads
> [1]https://gitlab.collabora.com/mediatek/aiot/linux/-/blob/mediatek-next/.gitlab-ci.yml?ref_type=heads#L282
>> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
>> ...
>> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
>> col
>> test VIDIOC_S_FMT: FAIL
>> ...
>> Total for rockchip-rga device /dev/video0: 47, Succeeded: 46, Failed: 1,
>> Warnings: 0
>>
>> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
>> ...
>> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
>> col
>> test VIDIOC_S_FMT: FAIL
>> ...
>> Total for rockchip-rga device /dev/video1: 47, Succeeded: 46, Failed: 1,
>> Warnings: 0
>>
>> v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
>> ...
>> fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
>> col
>> test VIDIOC_S_FMT: FAIL
>> ...
>> Total for rockchip-rga device /dev/video2: 47, Succeeded: 46, Failed: 1,
>> Warnings: 0
>>
>> Each RGA core is a separate /dev/video device. To distinguish the RGA2
>> core from the RGA3 cores the Card type is set accordingly. Combining all
>> cores into a single device and scheduling tasks to the best core might
>> be a future improvement, if it is desired by upstream to handle the
>> scheduling and selection in kernel space.
> It took me some time to understand why you spoke about multicore here. You
> forgot to say here that you add RGA3 into RGA2 driver. Some information on why
> you went that path instead of a separate driver.
Mostly as I've started by using the rga driver as a basis and just
adjusted the command stream and register values to the RGA3. I was
unsure, if I should create a separate driver.
As it didn't seem unfeasible to have the existing driver handle both
units, I've decided to add it to the existing driver to avoid code
duplication.
But looking at your comments about the wrong announcement of e.g. color
space conversion, I now think that a new driver is probably better to
avoid adding too much of the differences to the struct.
> From high level view, I don't think its a good idea to multi-plex over
> heterogeneous core. They may not even produce the exact same pixels for the same
> operation. They also don't share the same MMU, and at first glance, the use of
> rkiommu in RGA3 means it can no longer handle CPU cache (though I don't know if
> this is implemented/supported in upstream RGA2 driver).
Thanks for the insight. This gives me another reason to create a
separate driver. I'll probably also look into multiplexing the 2 RGA3
cores to only expose one RGA3 video device to userspace (the current
implementation exposes both cores individually to the userspace)
Sincerely
Sven
>> Patch 1-2 are general cleanups
>> Patch 3-12 prepare the rga driver for the RGA3
>> Patch 13 documments the RGA3 compatible value
>> Patch 14 adds the RGA3 cores to the rk3588 dtsi
>> Patch 15 increases the RGA3 core clock speeds
>> Patch 16 adds RGA3 support to the rga driver
>>
>> Signed-off-by: Sven Püschel<s.pueschel@pengutronix.de>
>> ---
>> Sven Püschel (16):
>> media: rockchip: rga: use clk_bulk api
>> media: rockchip: rga: use stride for offset calculation
>> media: rockchip: rga: align stride to 16 bytes
>> media: rockchip: rga: move hw specific parts to a dedicated struct
>> media: rockchip: rga: use card type to specify rga type
>> media: rockchip: rga: change offset to dma_addresses
>> media: rockchip: rga: support external iommus
>> media: rockchip: rga: remove size from rga_frame
>> media: rockchip: rga: remove stride from rga_frame
>> media: rockchip: rga: move rga_fmt to rga-hw.h
>> media: rockchip: rga: add iommu restore function
>> media: rockchip: rga: handle error interrupt
>> media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
>> arm64: dts: rockchip: add rga3 dt nodes
>> arm64: dts: rockchip: increase rga3 clock speed
>> media: rockchip: rga: add rga3 support
>>
>> .../devicetree/bindings/media/rockchip-rga.yaml | 1 +
>> arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 50 +++
>> drivers/media/platform/rockchip/rga/Makefile | 2 +-
>> drivers/media/platform/rockchip/rga/rga-buf.c | 78 ++--
>> drivers/media/platform/rockchip/rga/rga-hw.c | 356 ++++++++++++---
>> drivers/media/platform/rockchip/rga/rga-hw.h | 15 +-
>> drivers/media/platform/rockchip/rga/rga.c | 404 ++++++-----------
>> drivers/media/platform/rockchip/rga/rga.h | 74 ++--
>> drivers/media/platform/rockchip/rga/rga3-hw.c | 490
>> +++++++++++++++++++++
>> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++
>> 10 files changed, 1246 insertions(+), 410 deletions(-)
>> ---
>> base-commit: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328
>> change-id: 20251001-spu-rga3-8a00e018b120
>>
>> Best regards,
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 11/16] media: rockchip: rga: add iommu restore function
2025-10-07 18:30 ` Nicolas Dufresne
@ 2025-10-10 8:45 ` Sven Püschel
2025-10-10 13:10 ` Nicolas Dufresne
0 siblings, 1 reply; 36+ messages in thread
From: Sven Püschel @ 2025-10-10 8:45 UTC (permalink / raw)
To: Nicolas Dufresne, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
On 10/7/25 20:30, Nicolas Dufresne wrote:
> Hi,
>
> Le mardi 07 octobre 2025 à 10:32 +0200, Sven Püschel a écrit :
>> Add an iommu restore function in preparation for the rga3 addition.
>> This is necessary for a soft reset, as the rga3 will also reset
>> it's iommu paging table to 0 and disable paging.
>>
>> The empty domain attach/detach to restore the iommu is copied
>> from the rkvdec driver.
> We did receive negative feedback after the fact on this one. We will likely
> upset further the iommu subsystem maintainers with that. Have you considered
> adding a restore function in the rkiommu driver, similar to TI mmu and Benjamin
> VSI MMU proposal ?
>
> I have no precise objection, I know it works, but adding a restore function
> seems also pretty straight forward.
I haven't considered adding an restore function. I've implemented this
to handle potential command stream failures like scaling beyond the
supported 8x factor. I'll probably drop this for now to keep it simple
and instead correctly announce the constraints to avoid creating invalid
commands in the first place.
>> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>> ---
>> drivers/media/platform/rockchip/rga/rga.c | 24 ++++++++++++++++++++++++
>> drivers/media/platform/rockchip/rga/rga.h | 7 +++++++
>> 2 files changed, 31 insertions(+)
>>
>> diff --git a/drivers/media/platform/rockchip/rga/rga.c
>> b/drivers/media/platform/rockchip/rga/rga.c
>> index
>> cd4da01645611e5fb51ed94e09b5f1463dad72c5..0a725841b0cfa41bbc5b861b8f5ceac2452f
>> c2b5 100644
>> --- a/drivers/media/platform/rockchip/rga/rga.c
>> +++ b/drivers/media/platform/rockchip/rga/rga.c
>> @@ -9,6 +9,7 @@
>> #include <linux/delay.h>
>> #include <linux/fs.h>
>> #include <linux/interrupt.h>
>> +#include <linux/iommu.h>
>> #include <linux/module.h>
>> #include <linux/of.h>
>> #include <linux/pm_runtime.h>
>> @@ -560,6 +561,19 @@ static const struct video_device rga_videodev = {
>> .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
>> };
>>
>> +void rga_iommu_restore(struct rockchip_rga *rga)
>> +{
>> + if (rga->empty_domain) {
>> + /*
>> + * To rewrite mapping into the attached IOMMU core, attach a
>> new empty domain that
>> + * will program an empty table, then detach it to restore the
>> default domain and
>> + * all cached mappings.
>> + */
>> + iommu_attach_device(rga->empty_domain, rga->dev);
>> + iommu_detach_device(rga->empty_domain, rga->dev);
>> + }
>> +}
>> +
>> static int rga_parse_dt(struct rockchip_rga *rga)
>> {
>> struct reset_control *core_rst, *axi_rst, *ahb_rst;
>> @@ -657,6 +671,13 @@ static int rga_probe(struct platform_device *pdev)
>> goto err_put_clk;
>> }
>>
>> + if (iommu_get_domain_for_dev(rga->dev)) {
>> + rga->empty_domain = iommu_paging_domain_alloc(rga->dev);
>> +
>> + if (!rga->empty_domain)
> Its an error pointer, see:
>
> https://gitlab.freedesktop.org/linux-media/media-committers/-/commit/6347dc7fb967521a77f9ff0774d25ef0cca4c6cd
>
>> + dev_warn(rga->dev, "cannot alloc new empty
>> domain\n");
>> + }
>> +
>> ret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev);
>> if (ret)
>> goto err_put_clk;
>> @@ -741,6 +762,9 @@ static void rga_remove(struct platform_device *pdev)
>> v4l2_device_unregister(&rga->v4l2_dev);
>>
>> pm_runtime_disable(rga->dev);
>> +
>> + if (rga->empty_domain)
>> + iommu_domain_free(rga->empty_domain);
>> }
>>
>> static int __maybe_unused rga_runtime_suspend(struct device *dev)
>> diff --git a/drivers/media/platform/rockchip/rga/rga.h
>> b/drivers/media/platform/rockchip/rga/rga.h
>> index
>> fc4805ba4e8ef7fb311f780a198ba6ba4d3aff17..e19c4c82aca5ae2056f52d525138093fbbb8
>> 1af8 100644
>> --- a/drivers/media/platform/rockchip/rga/rga.h
>> +++ b/drivers/media/platform/rockchip/rga/rga.h
>> @@ -75,6 +75,7 @@ struct rockchip_rga {
>> void __iomem *regs;
>> struct clk_bulk_data clks[3];
>> struct rockchip_rga_version version;
>> + struct iommu_domain *empty_domain;
>>
>> /* vfd lock */
>> struct mutex mutex;
>> @@ -114,6 +115,12 @@ static inline struct rga_vb_buffer *vb_to_rga(struct
>> vb2_v4l2_buffer *vb)
>>
>> struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type
>> type);
>>
>> +/*
>> + * This should be called in an interrupt handler to make sure no memory
>> + * is mapped through the IOMMU while the empty domain is attached.
>> + */
>> +void rga_iommu_restore(struct rockchip_rga *rga);
>> +
>> /* RGA Buffers Manage */
>> extern const struct vb2_ops rga_qops;
>>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 19:41 ` Nicolas Dufresne
@ 2025-10-10 9:21 ` Sven Püschel
0 siblings, 0 replies; 36+ messages in thread
From: Sven Püschel @ 2025-10-10 9:21 UTC (permalink / raw)
To: Nicolas Dufresne, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
Hi,
On 10/7/25 21:41, Nicolas Dufresne wrote:
> Hi,
>
> Le mardi 07 octobre 2025 à 10:32 +0200, Sven Püschel a écrit :
>> Add support for the RGA3 unit contained in the RK3588.
>>
>> Only a basic feature set consisting of scaling and color conversion is
>> implemented. Advanced features like rotation and cropping will just be
>> ignored. Also the BT601F color space conversion is currently hard coded.
>>
>> The register address defines were copied from the
>> vendor Rockchip kernel sources and slightly adjusted to not start at 0
>> again for the cmd registers.
>>
>> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>> ---
>> drivers/media/platform/rockchip/rga/Makefile | 2 +-
>> drivers/media/platform/rockchip/rga/rga.c | 4 +
>> drivers/media/platform/rockchip/rga/rga.h | 2 +-
>> drivers/media/platform/rockchip/rga/rga3-hw.c | 490 ++++++++++++++++++++++++++
>> drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++++
>> 5 files changed, 682 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/media/platform/rockchip/rga/Makefile b/drivers/media/platform/rockchip/rga/Makefile
>> index 1bbecdc3d8df2ce286652f5544c4a3b52a6d28cf..7326a548f3dc7618403e98974b8c60d45f556fef 100644
>> --- a/drivers/media/platform/rockchip/rga/Makefile
>> +++ b/drivers/media/platform/rockchip/rga/Makefile
>> @@ -1,4 +1,4 @@
>> # SPDX-License-Identifier: GPL-2.0-only
>> -rockchip-rga-objs := rga.o rga-hw.o rga-buf.o
>> +rockchip-rga-objs := rga.o rga-hw.o rga3-hw.o rga-buf.o
>>
>> obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o
>> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
>> index 3b5d2eb8e109f44af76dd2240a239b1fa8a78cee..9d15104fcc1a45553af33bfd637bba0a86329c17 100644
>> --- a/drivers/media/platform/rockchip/rga/rga.c
>> +++ b/drivers/media/platform/rockchip/rga/rga.c
>> @@ -805,6 +805,10 @@ static const struct of_device_id rockchip_rga_match[] = {
>> .compatible = "rockchip,rk3399-rga",
>> .data = &rga2_hw,
>> },
>> + {
>> + .compatible = "rockchip,rk3588-rga3",
>> + .data = &rga3_hw,
>> + },
>> {},
>> };
>>
>> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
>> index dc4bb85707d12f5378c4891098cd7ea4a4d75e2d..350a4e07cb2ee237fc3676d594e1e7298a028afb 100644
>> --- a/drivers/media/platform/rockchip/rga/rga.h
>> +++ b/drivers/media/platform/rockchip/rga/rga.h
>> @@ -169,6 +169,6 @@ static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
>> return rga->hw->has_internal_iommu;
>> }
>>
>> -extern const struct rga_hw rga2_hw;
>> +extern const struct rga_hw rga2_hw, rga3_hw;
>>
>> #endif
>> diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.c b/drivers/media/platform/rockchip/rga/rga3-hw.c
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..6e4cd2f96cf866880316c75924f7a4c339851448
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/rga/rga3-hw.c
>> @@ -0,0 +1,490 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) Pengutronix e.K.
>> + * Author: Sven Püschel <s.pueschel@pengutronix.de>
>> + */
>> +
>> +#include <linux/pm_runtime.h>
>> +#include <linux/bitfield.h>
>> +#include <linux/delay.h>
>> +#include <linux/printk.h>
>> +
>> +#include <media/v4l2-common.h>
>> +
>> +#include "rga3-hw.h"
>> +#include "rga.h"
>> +
>> +static unsigned int rga3_get_scaling(unsigned int src, unsigned int dst)
> Would be nice to summarize what you are calculating here.
>
>> +{
>> + if (dst > src) {
>> + if (((src - 1) << 16) % (dst - 1) == 0)
>> + return ((src - 1) << 16) / (dst - 1) - 1;
>> + else
>> + return ((src - 1) << 16) / (dst - 1);
>> + } else {
>> + return ((dst - 1) << 16) / (src - 1) + 1;
>> + }
> Its unclear to me why the various -1, and why the factor get reversed depending
> up or down scale.
The calculation is based on the formula in the TRM. While testing I've
notice that it fails in the upscaling case (and also the calulculation
exceeds 16 bits) and that swapping the src/dest values makes it work.
The upscale/downscale operation is already described in a separate bit
of the win0 command register.
>
>> +}
>> +
>> +static bool rga3_has_alpha(const struct rga3_fmt *fmt)
>> +{
>> + return fmt->hw_format >= RGA3_COLOR_FMT_FIRST_HAS_ALPHA &&
>> + fmt->fourcc != V4L2_PIX_FMT_BGRX32 &&
>> + fmt->fourcc != V4L2_PIX_FMT_XBGR32 &&
>> + fmt->fourcc != V4L2_PIX_FMT_RGBX32 &&
>> + fmt->fourcc != V4L2_PIX_FMT_XRGB32;
> Would be nice to extend v4l2-common ?
I agree and I'll add it to my patchset.
>> +}
>> +
>> +static bool rga3_can_capture(const struct rga3_fmt *fmt)
>> +{
>> + return fmt->hw_format <= RGA3_COLOR_FMT_LAST_OUTPUT;
>> +}
>> +
>> +static void rga3_cmd_set_trans_info(struct rga_ctx *ctx)
> Not obvious some the function name, can you add a comment block.
>
>> +{
>> + struct rockchip_rga *rga = ctx->rga;
>> + u32 *cmd = rga->cmdbuf_virt;
>> + unsigned int src_h, src_w, dst_h, dst_w;
>> + unsigned int reg;
>> + u16 hor_scl_fac, ver_scl_fac;
>> +
>> + src_h = ctx->in.crop.height;
>> + src_w = ctx->in.crop.width;
>> + dst_h = ctx->out.crop.height;
>> + dst_w = ctx->out.crop.width;
> There is no position component to these rectangle ? It is a bit confusing to
> called cropped rectangles as src and dest only.
This block is just copied from the rga-hw.c file, which uses the same
variable names and in another function src_x/y for the position components.
>
>> +
>> + reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_SCALE_HOR_UP, dst_w > src_w)
>> + | FIELD_PREP(RGA3_WIN_SCALE_HOR_BYPASS, dst_w == src_w)
>> + | FIELD_PREP(RGA3_WIN_SCALE_VER_UP, dst_h > src_h)
>> + | FIELD_PREP(RGA3_WIN_SCALE_VER_BYPASS, dst_h == src_h);
>> +
>> + /* stride needs to be in words */
>> + reg = RGA3_WIN0_VIR_STRIDE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2;
>> + reg = RGA3_WIN0_UV_VIR_STRIDE - RGA3_FIRST_CMD_REG;
>> + if (ctx->in.pix.num_planes >= 2)
>> + cmd[reg >> 2] = ctx->in.pix.plane_fmt[1].bytesperline >> 2;
>> + else
>> + cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2;
> I find this pattern a bit hacky, and hiding what its for. My reading this is
> that if num_planes == 1, the driver does not know how many planes there is, due
> to legacy single plane formats, such as NV12 (in contrast to NV12M). So it just
> repeat the stride in all places.
>
> That where is bugs me, since you use >=2 if the number of planes if 3, the third
> stride is missing, but would also not be equal. If the HW is limited to NV style
> of format, then don't use >=2, but rather == 2. And comment about it.
Thanks. The HW is limited to 2 memory areas.
>
>> + reg = RGA3_WR_VIR_STRIDE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2;
>> + reg = RGA3_WR_PL_VIR_STRIDE - RGA3_FIRST_CMD_REG;
>> + if (ctx->out.pix.num_planes >= 2)
>> + cmd[reg >> 2] = ctx->out.pix.plane_fmt[1].bytesperline >> 2;
>> + else
>> + cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2;
>> +
>> + reg = RGA3_WIN0_ACT_SIZE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w)
>> + | FIELD_PREP(RGA3_HEIGHT, src_h);
>> + reg = RGA3_WIN0_SRC_SIZE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w)
>> + | FIELD_PREP(RGA3_HEIGHT, src_h);
> Just guessing, because the code is not clear, but is that ACT (actual) and SRC
> (source). Someone the original image size, and the source rectangle ? In which
> case, is it ok to pass twice the cropped size ?
Yeah, not quite correct and just works, as I didn't implement/test
cropping.
>
>> +
>> + reg = RGA3_WIN0_DST_SIZE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, dst_w)
>> + | FIELD_PREP(RGA3_HEIGHT, dst_h);
>> +
>> + hor_scl_fac = rga3_get_scaling(src_w, dst_w);
>> + ver_scl_fac = rga3_get_scaling(src_h, dst_h);
>> + reg = RGA3_WIN0_SCL_FAC - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_SCALE_HOR_FAC, hor_scl_fac)
>> + | FIELD_PREP(RGA3_SCALE_VER_FAC, ver_scl_fac);
>> +
>> + if (rga3_has_alpha(ctx->in.fmt)) {
>> + /* copy alpha from input */
> Fair enough, I'd appreciate in the commit message to have an overview of all the
> features that are not covered by the driver. Notably you don't support the
> second window for blits (V4L2 does not have enough CID to do that either), you
> don't seem to fully support S_SELECTION, this is a bit annoying, no background
> colors, rotation, and probably more stuff I forget about.
>
>> + reg = RGA3_OVLP_TOP_ALPHA - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1)
>> + | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1);
>> + reg = RGA3_OVLP_BOT_ALPHA - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1)
>> + | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1);
>> + } else {
>> + /* just use a 255 alpha value */
>> + reg = RGA3_OVLP_TOP_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff)
>> + | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1);
>> + reg = RGA3_OVLP_BOT_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff)
>> + | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1);
> Have you considered implementing V4L2_CID_ALPHA_COMPONENT ?
No, but thanks for the hint. I'll look into adding it.
>> + }
>> +}
>> +
>> +static void rga3_cmd_set_win0_addr(struct rga_ctx *ctx,
>> + const struct rga_addrs *addrs)
>> +{
>> + u32 *cmd = ctx->rga->cmdbuf_virt;
>> + unsigned int reg;
>> +
>> + reg = RGA3_WIN0_Y_BASE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = addrs->y_addr;
>> + reg = RGA3_WIN0_U_BASE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = addrs->u_addr;
>> +}
>> +
>> +static void rga3_cmd_set_wr_addr(struct rga_ctx *ctx,
>> + const struct rga_addrs *addrs)
>> +{
>> + u32 *cmd = ctx->rga->cmdbuf_virt;
>> + unsigned int reg;
>> +
>> + reg = RGA3_WR_Y_BASE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = addrs->y_addr;
>> + reg = RGA3_WR_U_BASE - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] = addrs->u_addr;
>> +}
>> +
>> +static void rga3_cmd_set_win0_format(struct rga_ctx *ctx)
>> +{
>> + u32 *cmd = ctx->rga->cmdbuf_virt;
>> + const struct rga3_fmt *in = ctx->in.fmt;
>> + const struct rga3_fmt *out = ctx->out.fmt;
>> + const struct v4l2_format_info *in_fmt, *out_fmt;
>> + unsigned int src_h, src_w, dst_h, dst_w;
>> + bool r2y, y2r;
>> + u8 rd_format;
>> + unsigned int reg;
>> +
>> + src_h = ctx->in.crop.height;
>> + src_w = ctx->in.crop.width;
>> + dst_h = ctx->out.crop.height;
>> + dst_w = ctx->out.crop.width;
>> +
>> + in_fmt = v4l2_format_info(in->fourcc);
>> + out_fmt = v4l2_format_info(out->fourcc);
>> + r2y = v4l2_is_format_rgb(in_fmt) && v4l2_is_format_yuv(out_fmt);
>> + y2r = v4l2_is_format_yuv(in_fmt) && v4l2_is_format_rgb(out_fmt);
>> +
>> + if (in->semi_planar)
>> + rd_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
>> + else
>> + rd_format = RGA3_RDWR_FORMAT_INTERLEAVED;
>> +
>> + reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_PIC_FORMAT, in->hw_format)
>> + | FIELD_PREP(RGA3_WIN_YC_SWAP, in->yc_swap)
>> + | FIELD_PREP(RGA3_WIN_RBUV_SWAP, in->rbuv_swap)
>> + | FIELD_PREP(RGA3_WIN_RD_FORMAT, rd_format)
>> + | FIELD_PREP(RGA3_WIN_R2Y, r2y)
>> + | FIELD_PREP(RGA3_WIN_Y2R, y2r)
>> + | FIELD_PREP(RGA3_WIN_CSC_MODE, RGA3_WIN_CSC_MODE_BT601_F);
> I don't think I saw code in the v4l2 part the enforce that only that conversion
> is allowed. Just picking a hidden CSC and pixel transfer make your driver
> unusable in real world.
>
> My take is that a driver that implement CSC should be really serious about the
> CSC aspect. So if you'd like to get a subset in a first iteration, make sure
> that the v4l2_format will perfectly reflect that subset so userspace does not
> fooled into producing pad colors. In short, this driver only have 2 jobs at the
> moment, scale and CSC. Let do that well ?
>
>> +}
>> +
>> +static void rga3_cmd_enable_win0(struct rga_ctx *ctx)
>> +{
>> + u32 *cmd = ctx->rga->cmdbuf_virt;
>> + unsigned int reg;
>> +
>> + reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_ENABLE, 1);
>> +}
>> +
>> +static void rga3_cmd_set_wr_format(struct rga_ctx *ctx)
>> +{
>> + u32 *cmd = ctx->rga->cmdbuf_virt;
>> + const struct rga3_fmt *out = ctx->out.fmt;
>> + u8 wr_format;
>> + unsigned int reg;
>> +
>> + if (out->semi_planar)
>> + wr_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
>> + else
>> + wr_format = RGA3_RDWR_FORMAT_INTERLEAVED;
>> +
>> + reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WR_PIC_FORMAT, out->hw_format)
>> + | FIELD_PREP(RGA3_WR_YC_SWAP, out->yc_swap)
>> + | FIELD_PREP(RGA3_WR_RBUV_SWAP, out->rbuv_swap)
>> + | FIELD_PREP(RGA3_WR_FORMAT, wr_format);
>> +}
>> +
>> +static void rga3_cmd_disable_wr_limitation(struct rga_ctx *ctx)
>> +{
>> + u32 *cmd = ctx->rga->cmdbuf_virt;
>> + unsigned int reg;
>> +
>> + /* Use the max value to avoid limiting the write speed */
>> + reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG;
>> + cmd[reg >> 2] |= FIELD_PREP(RGA3_WR_SW_OUTSTANDING_MAX, 63);
> No issue with the code, but quite an interesting feature. We did discussed in
> pas about using the target framerate (well frame duration in v4l2) to avoid
> bursting the memory.
>
>> +}
>> +
>> +static void rga3_cmd_set(struct rga_ctx *ctx,
>> + struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
>> +{
>> + struct rockchip_rga *rga = ctx->rga;
>> +
>> + memset(rga->cmdbuf_virt, 0, RGA3_CMDBUF_SIZE * 4);
>> +
>> + rga3_cmd_set_win0_addr(ctx, &src->dma_addrs);
>> + rga3_cmd_set_wr_addr(ctx, &dst->dma_addrs);
>> +
>> + rga3_cmd_set_win0_format(ctx);
>> + rga3_cmd_enable_win0(ctx);
>> + rga3_cmd_set_trans_info(ctx);
>> + rga3_cmd_set_wr_format(ctx);
>> + rga3_cmd_disable_wr_limitation(ctx);
>> +
>> + rga_write(rga, RGA3_CMD_ADDR, rga->cmdbuf_phy);
>> +
>> + /* sync CMD buf for RGA */
>> + dma_sync_single_for_device(rga->dev, rga->cmdbuf_phy,
>> + PAGE_SIZE, DMA_BIDIRECTIONAL);
>> +}
>> +
>> +static void rga3_hw_start(struct rockchip_rga *rga,
>> + struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
>> +{
>> + struct rga_ctx *ctx = rga->curr;
>> +
>> + rga3_cmd_set(ctx, src, dst);
>> +
>> + /* set to master mode and start the conversion */
>> + rga_write(rga, RGA3_SYS_CTRL,
>> + FIELD_PREP(RGA3_CMD_MODE, RGA3_CMD_MODE_MASTER));
>> + rga_write(rga, RGA3_INT_EN,
>> + FIELD_PREP(RGA3_INT_FRM_DONE, 1) |
>> + FIELD_PREP(RGA3_INT_DMA_READ_BUS_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_FBC_DEC_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_HOR_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_VER_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WR_VER_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WR_HOR_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WR_BUS_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_IN_FIFO_WR_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_IN_FIFO_RD_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_HOR_FIFO_WR_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_HOR_FIFO_RD_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_VER_FIFO_WR_ERR, 1) |
>> + FIELD_PREP(RGA3_INT_WIN0_VER_FIFO_RD_ERR, 1));
>> + rga_write(rga, RGA3_CMD_CTRL,
>> + FIELD_PREP(RGA3_CMD_LINE_START_PULSE, 1));
>> +}
>> +
>> +static void rga3_soft_reset(struct rockchip_rga *rga)
>> +{
>> + u32 i;
>> +
>> + rga_write(rga, RGA3_SYS_CTRL,
>> + FIELD_PREP(RGA3_CCLK_SRESET, 1) |
>> + FIELD_PREP(RGA3_ACLK_SRESET, 1));
>> +
>> + for (i = 0; i < RGA3_RESET_TIMEOUT; i++) {
>> + if (FIELD_GET(RGA3_RO_SRST_DONE, rga_read(rga, RGA3_RO_SRST)))
>> + break;
>> +
>> + udelay(1);
> Did you measure this IP soft reset speed ? Perhaps this delay can be tune to
> avoid hugging on a CPU core ?
My simple tests with too high scaling always resulted in a value of 0.
I've only copied the delay from the downstream, so there is no problem
reducing this value.
>
>> + }
>> +
>> + if (i == RGA3_RESET_TIMEOUT)
>> + pr_err("Timeout of %d usec reached while waiting for an rga3 soft reset\n", i);
> What next if it failed ? System lockup, or just bunch of errors ?
>
>> +
>> + rga_write(rga, RGA3_SYS_CTRL, 0);
>> + rga_iommu_restore(rga);
>> +}
>> +
>> +static enum rga_irq_result rga3_handle_irq(struct rockchip_rga *rga)
>> +{
>> + u32 intr;
>> +
>> + intr = rga_read(rga, RGA3_INT_RAW);
>> + /* clear all interrupts */
>> + rga_write(rga, RGA3_INT_CLR, intr);
>> +
>> + if (FIELD_GET(RGA3_INT_FRM_DONE, intr))
>> + return RGA_IRQ_DONE;
>> + if (FIELD_GET(RGA3_INT_DMA_READ_BUS_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_FBC_DEC_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_HOR_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_VER_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WR_VER_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WR_HOR_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WR_BUS_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_IN_FIFO_WR_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_IN_FIFO_RD_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_HOR_FIFO_WR_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_HOR_FIFO_RD_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_VER_FIFO_WR_ERR, intr) ||
>> + FIELD_GET(RGA3_INT_WIN0_VER_FIFO_RD_ERR, intr)) {
>> + rga3_soft_reset(rga);
>> + return RGA_IRQ_ERROR;
> Are you certain all these errors are fatal in the first place ? That being said,
> since you "soft reset", I bet this basically abort any pending operation, so it
> should not matter.
>
>> + }
>> +
>> + return RGA_IRQ_IGNORE;
>> +}
>> +
>> +static void rga3_get_version(struct rockchip_rga *rga)
>> +{
>> + u32 version = rga_read(rga, RGA3_VERSION_NUM);
>> +
>> + rga->version.major = FIELD_GET(RGA3_VERSION_NUM_MAJOR, version);
>> + rga->version.minor = FIELD_GET(RGA3_VERSION_NUM_MINOR, version);
>> +}
>> +
>> +static struct rga3_fmt rga3_formats[] = {
>> + {
>> + .fourcc = V4L2_PIX_FMT_RGB24,
>> + .hw_format = RGA3_COLOR_FMT_BGR888,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_BGR24,
>> + .hw_format = RGA3_COLOR_FMT_BGR888,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_ABGR32,
>> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_RGBA32,
>> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_XBGR32,
>> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_RGBX32,
>> + .hw_format = RGA3_COLOR_FMT_BGRA8888,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_RGB565,
>> + .hw_format = RGA3_COLOR_FMT_BGR565,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV12M,
>> + .hw_format = RGA3_COLOR_FMT_YUV420,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV12,
>> + .hw_format = RGA3_COLOR_FMT_YUV420,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV21M,
>> + .hw_format = RGA3_COLOR_FMT_YUV420,
>> + .rbuv_swap = 1,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV21,
>> + .hw_format = RGA3_COLOR_FMT_YUV420,
>> + .rbuv_swap = 1,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV16M,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV16,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV61M,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .rbuv_swap = 1,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV61,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .rbuv_swap = 1,
>> + .semi_planar = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_YUYV,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .yc_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_YVYU,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .yc_swap = 1,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_UYVY,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_VYUY,
>> + .hw_format = RGA3_COLOR_FMT_YUV422,
>> + .rbuv_swap = 1,
> Any chance you could add 10bit formats ? It can handle NV15 and P010. So far
> this had been the main reason people have been interested in RGA3 (that and its
> AFBC feature, but the later is quite some more work, since we don't have the
> common code to compute the header sizes in media/ yet).
If this is just adding them to the struct and it works instantly or with
minor intervention (and doesn't need much adjusting in the testing), I
can add it. Otherwise probably not, as like cropping/rotation it's
currently not a requirement.
>
>> + },
>> + /* Input only formats last to keep rga3_enum_format simple */
>> + {
>> + .fourcc = V4L2_PIX_FMT_ARGB32,
>> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_BGRA32,
>> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_XRGB32,
>> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
>> + .rbuv_swap = 1,
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_BGRX32,
>> + .hw_format = RGA3_COLOR_FMT_ABGR8888,
>> + },
>> +};
>> +
>> +static int rga3_enum_format(struct v4l2_fmtdesc *f)
>> +{
>> + struct rga3_fmt *fmt;
>> +
>> + if (f->index >= ARRAY_SIZE(rga3_formats))
>> + return -EINVAL;
>> +
>> + fmt = &rga3_formats[f->index];
>> + if (V4L2_TYPE_IS_CAPTURE(f->type) && !rga3_can_capture(fmt))
>> + return -EINVAL;
>> +
>> + f->pixelformat = fmt->fourcc;
>> + return 0;
>> +}
>> +
>> +static void *rga3_try_format(u32 *fourcc, bool is_output)
> This is not really a try_format function, but a tiny subset. If you really like
> the "try", perhaps call it rga3_try_pixelformat() ?
>
>> +{
>> + unsigned int i;
>> +
>> + if (!fourcc)
>> + return &rga3_formats[0];
>> +
>> + for (i = 0; i < ARRAY_SIZE(rga3_formats); i++) {
>> + if (!is_output && !rga3_can_capture(&rga3_formats[i]))
>> + continue;
>> +
>> + if (rga3_formats[i].fourcc == *fourcc)
>> + return &rga3_formats[i];
>> + }
>> +
>> + *fourcc = rga3_formats[0].fourcc;
>> + return &rga3_formats[0];
>> +}
>> +
>> +const struct rga_hw rga3_hw = {
>> + .card_type = "rga3",
>> + .has_internal_iommu = false,
>> + .cmdbuf_size = RGA3_CMDBUF_SIZE,
>> + .min_width = RGA3_MIN_WIDTH,
>> + .min_height = RGA3_MIN_HEIGHT,
>> + .max_width = RGA3_MAX_INPUT_WIDTH,
>> + .max_height = RGA3_MAX_INPUT_HEIGHT,
>> +
>> + .start = rga3_hw_start,
>> + .handle_irq = rga3_handle_irq,
>> + .get_version = rga3_get_version,
>> + .enum_format = rga3_enum_format,
>> + .try_format = rga3_try_format,
>> +};
>> diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.h b/drivers/media/platform/rockchip/rga/rga3-hw.h
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..3829469e310706c11ecc52f40d3d1eb43a61d9c2
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/rga/rga3-hw.h
>> @@ -0,0 +1,186 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (C) Pengutronix e.K.
>> + * Author: Sven Püschel <s.pueschel@pengutronix.de>
>> + */
>> +#ifndef __RGA3_HW_H__
>> +#define __RGA3_HW_H__
>> +
>> +#include <linux/types.h>
>> +
>> +#define RGA3_CMDBUF_SIZE 0x2e
>> +
>> +#define RGA3_MIN_WIDTH 128
>> +#define RGA3_MIN_HEIGHT 128
>> +#define RGA3_MAX_INPUT_WIDTH (8192 - 16)
>> +#define RGA3_MAX_INPUT_HEIGHT (8192 - 16)
>> +#define RGA3_RESET_TIMEOUT 1000
>> +
>> +/* Registers address */
>> +/* sys reg */
>> +#define RGA3_SYS_CTRL 0x000
>> +#define RGA3_CMD_CTRL 0x004
>> +#define RGA3_CMD_ADDR 0x008
>> +#define RGA3_MI_GROUP_CTRL 0x00c
>> +#define RGA3_ARQOS_CTRL 0x010
>> +#define RGA3_VERSION_NUM 0x018
>> +#define RGA3_VERSION_TIM 0x01c
>> +#define RGA3_INT_EN 0x020
>> +#define RGA3_INT_RAW 0x024
>> +#define RGA3_INT_MSK 0x028
>> +#define RGA3_INT_CLR 0x02c
>> +#define RGA3_RO_SRST 0x030
>> +#define RGA3_STATUS0 0x034
>> +#define RGA3_SCAN_CNT 0x038
>> +#define RGA3_CMD_STATE 0x040
>> +
>> +/* cmd reg */
>> +#define RGA3_WIN0_RD_CTRL 0x100
>> +#define RGA3_FIRST_CMD_REG RGA3_WIN0_RD_CTRL
>> +#define RGA3_WIN0_Y_BASE 0x110
>> +#define RGA3_WIN0_U_BASE 0x114
>> +#define RGA3_WIN0_V_BASE 0x118
>> +#define RGA3_WIN0_VIR_STRIDE 0x11c
>> +#define RGA3_WIN0_FBC_OFF 0x120
>> +#define RGA3_WIN0_SRC_SIZE 0x124
>> +#define RGA3_WIN0_ACT_OFF 0x128
>> +#define RGA3_WIN0_ACT_SIZE 0x12c
>> +#define RGA3_WIN0_DST_SIZE 0x130
>> +#define RGA3_WIN0_SCL_FAC 0x134
>> +#define RGA3_WIN0_UV_VIR_STRIDE 0x138
>> +#define RGA3_WIN1_RD_CTRL 0x140
>> +#define RGA3_WIN1_Y_BASE 0x150
>> +#define RGA3_WIN1_U_BASE 0x154
>> +#define RGA3_WIN1_V_BASE 0x158
>> +#define RGA3_WIN1_VIR_STRIDE 0x15c
>> +#define RGA3_WIN1_FBC_OFF 0x160
>> +#define RGA3_WIN1_SRC_SIZE 0x164
>> +#define RGA3_WIN1_ACT_OFF 0x168
>> +#define RGA3_WIN1_ACT_SIZE 0x16c
>> +#define RGA3_WIN1_DST_SIZE 0x170
>> +#define RGA3_WIN1_SCL_FAC 0x174
>> +#define RGA3_WIN1_UV_VIR_STRIDE 0x178
>> +#define RGA3_OVLP_CTRL 0x180
>> +#define RGA3_OVLP_OFF 0x184
>> +#define RGA3_OVLP_TOP_KEY_MIN 0x188
>> +#define RGA3_OVLP_TOP_KEY_MAX 0x18c
>> +#define RGA3_OVLP_TOP_CTRL 0x190
>> +#define RGA3_OVLP_BOT_CTRL 0x194
>> +#define RGA3_OVLP_TOP_ALPHA 0x198
>> +#define RGA3_OVLP_BOT_ALPHA 0x19c
>> +#define RGA3_WR_CTRL 0x1a0
>> +#define RGA3_WR_FBCE_CTRL 0x1a4
>> +#define RGA3_WR_VIR_STRIDE 0x1a8
>> +#define RGA3_WR_PL_VIR_STRIDE 0x1ac
>> +#define RGA3_WR_Y_BASE 0x1b0
>> +#define RGA3_WR_U_BASE 0x1b4
>> +#define RGA3_WR_V_BASE 0x1b8
>> +
>> +/* Registers value */
>> +#define RGA3_COLOR_FMT_YUV420 0x0
>> +#define RGA3_COLOR_FMT_YUV422 0x1
>> +#define RGA3_COLOR_FMT_YUV420_10B 0x2
>> +#define RGA3_COLOR_FMT_YUV422_10B 0x3
>> +/*
>> + * Use memory ordering names
>> + * instead of the datasheet naming RGB formats in big endian order
>> + */
>> +#define RGA3_COLOR_FMT_BGR565 0x4
>> +#define RGA3_COLOR_FMT_BGR888 0x5
>> +#define RGA3_COLOR_FMT_FIRST_HAS_ALPHA RGA3_COLOR_FMT_BGRA8888
>> +#define RGA3_COLOR_FMT_BGRA8888 0x6
>> +#define RGA3_COLOR_FMT_LAST_OUTPUT RGA3_COLOR_FMT_BGRA8888
>> +/* the following are only supported as inputs */
>> +#define RGA3_COLOR_FMT_ABGR8888 0x7
>> +/*
>> + * the following seem to be unnecessary,
>> + * as they can be achieved with RB swaps
>> + */
>> +#define RGA3_COLOR_FMT_RGBA8888 0x8
>> +#define RGA3_COLOR_FMT_ARGB8888 0x9
>> +
>> +#define RGA3_RDWR_FORMAT_SEMI_PLANAR 0x1
>> +#define RGA3_RDWR_FORMAT_INTERLEAVED 0x2
>> +
>> +#define RGA3_CMD_MODE_MASTER 0x1
>> +
>> +#define RGA3_WIN_CSC_MODE_BT601_F 0x2
>> +
>> +/* RGA masks */
>> +/* SYS_CTRL */
>> +#define RGA3_CCLK_SRESET BIT(4)
>> +#define RGA3_ACLK_SRESET BIT(3)
>> +#define RGA3_CMD_MODE BIT(1)
>> +
>> +/* CMD_CTRL */
>> +#define RGA3_CMD_LINE_START_PULSE BIT(0)
>> +
>> +/* VERSION_NUM */
>> +#define RGA3_VERSION_NUM_MAJOR GENMASK(31, 28)
>> +#define RGA3_VERSION_NUM_MINOR GENMASK(27, 20)
>> +
>> +/* INT_* */
>> +#define RGA3_INT_FRM_DONE BIT(0)
>> +#define RGA3_INT_DMA_READ_BUS_ERR BIT(2)
>> +#define RGA3_INT_WIN0_FBC_DEC_ERR BIT(5)
>> +#define RGA3_INT_WIN0_HOR_ERR BIT(6)
>> +#define RGA3_INT_WIN0_VER_ERR BIT(7)
>> +#define RGA3_INT_WR_VER_ERR BIT(13)
>> +#define RGA3_INT_WR_HOR_ERR BIT(14)
>> +#define RGA3_INT_WR_BUS_ERR BIT(15)
>> +#define RGA3_INT_WIN0_IN_FIFO_WR_ERR BIT(16)
>> +#define RGA3_INT_WIN0_IN_FIFO_RD_ERR BIT(17)
>> +#define RGA3_INT_WIN0_HOR_FIFO_WR_ERR BIT(18)
>> +#define RGA3_INT_WIN0_HOR_FIFO_RD_ERR BIT(19)
>> +#define RGA3_INT_WIN0_VER_FIFO_WR_ERR BIT(20)
>> +#define RGA3_INT_WIN0_VER_FIFO_RD_ERR BIT(21)
>> +
>> +/* RO_SRST */
>> +#define RGA3_RO_SRST_DONE GENMASK(5, 0)
>> +
>> +/* *_SIZE */
>> +#define RGA3_HEIGHT GENMASK(28, 16)
>> +#define RGA3_WIDTH GENMASK(12, 0)
>> +
>> +/* SCL_FAC */
>> +#define RGA3_SCALE_VER_FAC GENMASK(31, 16)
>> +#define RGA3_SCALE_HOR_FAC GENMASK(15, 0)
>> +
>> +/* WINx_CTRL */
>> +#define RGA3_WIN_CSC_MODE GENMASK(27, 26)
>> +#define RGA3_WIN_R2Y BIT(25)
>> +#define RGA3_WIN_Y2R BIT(24)
>> +#define RGA3_WIN_SCALE_VER_UP BIT(23)
>> +#define RGA3_WIN_SCALE_VER_BYPASS BIT(22)
>> +#define RGA3_WIN_SCALE_HOR_UP BIT(21)
>> +#define RGA3_WIN_SCALE_HOR_BYPASS BIT(20)
>> +#define RGA3_WIN_YC_SWAP BIT(13)
>> +#define RGA3_WIN_RBUV_SWAP BIT(12)
>> +#define RGA3_WIN_RD_FORMAT GENMASK(9, 8)
>> +#define RGA3_WIN_PIC_FORMAT GENMASK(7, 4)
>> +#define RGA3_WIN_ENABLE BIT(0)
>> +
>> +/* COLOR_CTRL */
>> +#define RGA3_OVLP_GLOBAL_ALPHA GENMASK(23, 16)
>> +#define RGA3_OVLP_COLOR_MODE BIT(0)
>> +
>> +/* ALPHA_CTRL */
>> +#define RGA3_ALPHA_SELECT_MODE BIT(4)
>> +#define RGA3_ALPHA_BLEND_MODE GENMASK(3, 2)
>> +
>> +/* WR_CTRL */
>> +#define RGA3_WR_YC_SWAP BIT(20)
>> +#define RGA3_WR_SW_OUTSTANDING_MAX GENMASK(18, 13)
>> +#define RGA3_WR_RBUV_SWAP BIT(12)
>> +#define RGA3_WR_FORMAT GENMASK(9, 8)
>> +#define RGA3_WR_PIC_FORMAT GENMASK(7, 4)
>> +
>> +struct rga3_fmt {
>> + u32 fourcc;
>> + u8 hw_format;
>> + bool rbuv_swap;
>> + bool yc_swap;
>> + bool semi_planar;
>> +};
>> +
>> +#endif
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/16] media: platform: rga: Add RGA3 support
2025-10-10 8:33 ` Sven Püschel
@ 2025-10-10 13:05 ` Nicolas Dufresne
0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-10 13:05 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 11384 bytes --]
Hi Sven,
Le vendredi 10 octobre 2025 à 10:33 +0200, Sven Püschel a écrit :
> Hi Nicolas,
>
> On 10/7/25 8:06 PM, Nicolas Dufresne wrote:
> > Hi,
> >
> > Le mardi 07 octobre 2025 à 10:31 +0200, Sven Püschel a écrit :
> > > This series adds support for the Raster Graphic Acceleration 3 (RGA3)
> > > peripheral, which is included in the RK3588 SoC. Unlike the RGA2 it
> > > can use the existing rockchip-iommu-v2 driver to handle iommu mappings.
> > > Also the RK3588 contains two independent RGA3 cores.
> > Thanks for working on this.
> >
> > > Only scaling and format conversions between common 8bit RGB/YUV formats
> > > are implemented. Also the color space conversion is fixed to BT601F.
> > > This already allows a practical usage of the RGA3.
> > This seems quite limiting, can we expect an update on this, can't be that hard
> > to fully implement.
>
> Sorry, but currently there is no need to have a fully featured
> implementation from our side. As the datasheet mentions that the RGA3
> should do 4 or 2 pixel/cycle depending on the operation
Upon first light review, its only the colorspace (and sub-paramters) aspect that
I believe should be done properly before merging. Proper SELECTION
implementation is on the edge, I'm more on the side of this should be covered
then not to be usable in the wild.
Overall, this is the sad part of adding drivers that don't have a corresponding
spec to define the rules.
>
> > > This was tested on a Radxa Rock 5T. With the increased clock speeds in
> > > the devicetree around 160 fps were measured when scaling and converting
> > This is quite vague, I've checked the patch and you didn't extend either there.
> > Is that an overclock or was it miss-configured ? Does RK implement a devfreq ?
> > Should that be moved with a voltage adjustement ? Is there any thermal nearby we
> > should monitor ?
>
> This is mainly the result of a very low performance in the initial
> testing. We were quite disappointed looking at 30 fps output. The
> datasheet mentions the core should do 2 or 4 pixel/cycle, so we looked
> if the clock speed could be increased. The TRM Part1 mentions that the
> RGA3 clock uses a default divider of 2, so I've tweaked the dtsi to
> avoid the clock divider and run it on the fastest clock.
>
> But this tweaking only increased the frame rate to around 36fps. After
> some brainstorming and testing we found the culprit being the
> RGA3_WR_SW_OUTSTANDING_MAX value in the command. With this value maxed
> out and without the clock tweaks I've got around 80fps. As the clock
> increase resulted in the expected doubling of the fps and my few tests
> worked, I've included it in the patch set.
>
> I haven't done any stress testing and don't mind to remove the clock
> speed adjustments from the dtsi.
Thanks for the input, so yes, in V2 you should stay with the clock rate used by
Rockchip in their BSP, as a safe measure. If there is useful gain needed later
for anyone use case, we can work on the clocking in isolation and find the best
approach without risking wearing out the HW faster then needed.
>
> > > from RGBA 480x360 to NV12 3840x2160. Without the clock speed scaling a
> > > default clock division factor of 2 is used and only around 80 fps are
> > > reached with one core. The v4l2-compliance tests only complain about
> > > the already failing colorspace propagation:
> > Did you do any more format testing to validation all supported combinations ?
> > This is a tool [0] you can use to test this using GStreamer and how to use it
> > [1].
>
> Thanks for the link!
>
> I've did some simple format conversion tests with a static test pattern.
>
> The tests mainly converts any combination of RGB/YUV formats (hope I
> didn't miss anything) to each other. Then I convert it back to rgba with
> gstreamer and compare it's hash.
>
> For scaling I've just tested one upscale, downscale and scale to a non
> aligned width/height.
Thanks for the feedback.
>
> > [0]https://gitlab.collabora.com/mediatek/aiot/lava-test-definitions/-/tree/main/avvideocompare?ref_type=heads
> > [1]https://gitlab.collabora.com/mediatek/aiot/linux/-/blob/mediatek-next/.gitlab-ci.yml?ref_type=heads#L282
> > > v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> > > ...
> > > fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
> > > col
> > > test VIDIOC_S_FMT: FAIL
> > > ...
> > > Total for rockchip-rga device /dev/video0: 47, Succeeded: 46, Failed: 1,
> > > Warnings: 0
> > >
> > > v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> > > ...
> > > fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
> > > col
> > > test VIDIOC_S_FMT: FAIL
> > > ...
> > > Total for rockchip-rga device /dev/video1: 47, Succeeded: 46, Failed: 1,
> > > Warnings: 0
> > >
> > > v4l2-compliance 1.28.1, 64 bits, 64-bit time_t
> > > ...
> > > fail: v4l2-test-formats.cpp(923): fmt_cap.g_colorspace() !=
> > > col
> > > test VIDIOC_S_FMT: FAIL
> > > ...
> > > Total for rockchip-rga device /dev/video2: 47, Succeeded: 46, Failed: 1,
> > > Warnings: 0
> > >
> > > Each RGA core is a separate /dev/video device. To distinguish the RGA2
> > > core from the RGA3 cores the Card type is set accordingly. Combining all
> > > cores into a single device and scheduling tasks to the best core might
> > > be a future improvement, if it is desired by upstream to handle the
> > > scheduling and selection in kernel space.
> > It took me some time to understand why you spoke about multicore here. You
> > forgot to say here that you add RGA3 into RGA2 driver. Some information on why
> > you went that path instead of a separate driver.
>
> Mostly as I've started by using the rga driver as a basis and just
> adjusted the command stream and register values to the RGA3. I was
> unsure, if I should create a separate driver.
> As it didn't seem unfeasible to have the existing driver handle both
> units, I've decided to add it to the existing driver to avoid code
> duplication.
>
> But looking at your comments about the wrong announcement of e.g. color
> space conversion, I now think that a new driver is probably better to
> avoid adding too much of the differences to the struct.
I've discussed this with other devs, there is clearly no single opinion about
it. But some good argument came in in favour of your approach. Code duplication
is one (in fact, there is a lot of boiler plate code in all V4L2 drivers), but
the main thing is that it brings some maintenance to this close to abandoned
driver.
Though it means in v2, you have to push a little bit harder so the format, frame
size, try_format is properly adapted per hardware variants. We try and keep this
information as static as possible, using constant C structure to describe it.
>
> > From high level view, I don't think its a good idea to multi-plex over
> > heterogeneous core. They may not even produce the exact same pixels for the same
> > operation. They also don't share the same MMU, and at first glance, the use of
> > rkiommu in RGA3 means it can no longer handle CPU cache (though I don't know if
> > this is implemented/supported in upstream RGA2 driver).
>
> Thanks for the insight. This gives me another reason to create a
> separate driver. I'll probably also look into multiplexing the 2 RGA3
> cores to only expose one RGA3 video device to userspace (the current
> implementation exposes both cores individually to the userspace)
So no, you might want to keep it like this. I didn't understood when I read this
cover later that there it wasn't just about the RGA2 and the RGA3 core, but that
there is truly 2 RGA3 cores. For now, for the two RGA3 cores, you should mimic
what Sebastian did for the multiple Hantro G1 cores [0]. If you expose each
cores as its own device, removing it later will possibly break existing drivers
and will prevent implementing an in-kernel fair scheduling later.
Detlev is already prototyping scheduling of the two rockchip decoder cores, and
hopefully that should come with helper in v4l2-m2m to register cores so you can
easily schedule them. Note that both have similar challenges around the iommu,
since the dma integration does not seem (someone correct me if I'm wrong) to
already support a device driver with two or more iommus. We also have to decide
if we want the cores in complete isolation per operation or just map everything
in all iommus.
[0] https://www.spinics.net/lists//devicetree/msg708135.html
cheers,
Nicolas
>
> Sincerely
>
> Sven
>
> > > Patch 1-2 are general cleanups
> > > Patch 3-12 prepare the rga driver for the RGA3
> > > Patch 13 documments the RGA3 compatible value
> > > Patch 14 adds the RGA3 cores to the rk3588 dtsi
> > > Patch 15 increases the RGA3 core clock speeds
> > > Patch 16 adds RGA3 support to the rga driver
> > >
> > > Signed-off-by: Sven Püschel<s.pueschel@pengutronix.de>
> > > ---
> > > Sven Püschel (16):
> > > media: rockchip: rga: use clk_bulk api
> > > media: rockchip: rga: use stride for offset calculation
> > > media: rockchip: rga: align stride to 16 bytes
> > > media: rockchip: rga: move hw specific parts to a dedicated struct
> > > media: rockchip: rga: use card type to specify rga type
> > > media: rockchip: rga: change offset to dma_addresses
> > > media: rockchip: rga: support external iommus
> > > media: rockchip: rga: remove size from rga_frame
> > > media: rockchip: rga: remove stride from rga_frame
> > > media: rockchip: rga: move rga_fmt to rga-hw.h
> > > media: rockchip: rga: add iommu restore function
> > > media: rockchip: rga: handle error interrupt
> > > media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
> > > arm64: dts: rockchip: add rga3 dt nodes
> > > arm64: dts: rockchip: increase rga3 clock speed
> > > media: rockchip: rga: add rga3 support
> > >
> > > .../devicetree/bindings/media/rockchip-rga.yaml | 1 +
> > > arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 50 +++
> > > drivers/media/platform/rockchip/rga/Makefile | 2 +-
> > > drivers/media/platform/rockchip/rga/rga-buf.c | 78 ++--
> > > drivers/media/platform/rockchip/rga/rga-hw.c | 356 ++++++++++++---
> > > drivers/media/platform/rockchip/rga/rga-hw.h | 15 +-
> > > drivers/media/platform/rockchip/rga/rga.c | 404 ++++++-----------
> > > drivers/media/platform/rockchip/rga/rga.h | 74 ++--
> > > drivers/media/platform/rockchip/rga/rga3-hw.c | 490
> > > +++++++++++++++++++++
> > > drivers/media/platform/rockchip/rga/rga3-hw.h | 186 ++++++++
> > > 10 files changed, 1246 insertions(+), 410 deletions(-)
> > > ---
> > > base-commit: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328
> > > change-id: 20251001-spu-rga3-8a00e018b120
> > >
> > > Best regards,
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 11/16] media: rockchip: rga: add iommu restore function
2025-10-10 8:45 ` Sven Püschel
@ 2025-10-10 13:10 ` Nicolas Dufresne
0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Dufresne @ 2025-10-10 13:10 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
devicetree, kernel
[-- Attachment #1: Type: text/plain, Size: 5431 bytes --]
Le vendredi 10 octobre 2025 à 10:45 +0200, Sven Püschel a écrit :
>
> On 10/7/25 20:30, Nicolas Dufresne wrote:
> > Hi,
> >
> > Le mardi 07 octobre 2025 à 10:32 +0200, Sven Püschel a écrit :
> > > Add an iommu restore function in preparation for the rga3 addition.
> > > This is necessary for a soft reset, as the rga3 will also reset
> > > it's iommu paging table to 0 and disable paging.
> > >
> > > The empty domain attach/detach to restore the iommu is copied
> > > from the rkvdec driver.
> > We did receive negative feedback after the fact on this one. We will likely
> > upset further the iommu subsystem maintainers with that. Have you considered
> > adding a restore function in the rkiommu driver, similar to TI mmu and Benjamin
> > VSI MMU proposal ?
> >
> > I have no precise objection, I know it works, but adding a restore function
> > seems also pretty straight forward.
>
> I haven't considered adding an restore function. I've implemented this
> to handle potential command stream failures like scaling beyond the
> supported 8x factor. I'll probably drop this for now to keep it simple
> and instead correctly announce the constraints to avoid creating invalid
> commands in the first place.
Ack, though keep a warning around and some comment about the behaviour. We are
human, and may leave some bugs behind, always nice then they are recoverable.
(though PM runtime cycle also would recover that one).
>
> > > Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> > > ---
> > > drivers/media/platform/rockchip/rga/rga.c | 24 ++++++++++++++++++++++++
> > > drivers/media/platform/rockchip/rga/rga.h | 7 +++++++
> > > 2 files changed, 31 insertions(+)
> > >
> > > diff --git a/drivers/media/platform/rockchip/rga/rga.c
> > > b/drivers/media/platform/rockchip/rga/rga.c
> > > index
> > > cd4da01645611e5fb51ed94e09b5f1463dad72c5..0a725841b0cfa41bbc5b861b8f5ceac2452f
> > > c2b5 100644
> > > --- a/drivers/media/platform/rockchip/rga/rga.c
> > > +++ b/drivers/media/platform/rockchip/rga/rga.c
> > > @@ -9,6 +9,7 @@
> > > #include <linux/delay.h>
> > > #include <linux/fs.h>
> > > #include <linux/interrupt.h>
> > > +#include <linux/iommu.h>
> > > #include <linux/module.h>
> > > #include <linux/of.h>
> > > #include <linux/pm_runtime.h>
> > > @@ -560,6 +561,19 @@ static const struct video_device rga_videodev = {
> > > .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
> > > };
> > >
> > > +void rga_iommu_restore(struct rockchip_rga *rga)
> > > +{
> > > + if (rga->empty_domain) {
> > > + /*
> > > + * To rewrite mapping into the attached IOMMU core, attach a
> > > new empty domain that
> > > + * will program an empty table, then detach it to restore the
> > > default domain and
> > > + * all cached mappings.
> > > + */
> > > + iommu_attach_device(rga->empty_domain, rga->dev);
> > > + iommu_detach_device(rga->empty_domain, rga->dev);
> > > + }
> > > +}
> > > +
> > > static int rga_parse_dt(struct rockchip_rga *rga)
> > > {
> > > struct reset_control *core_rst, *axi_rst, *ahb_rst;
> > > @@ -657,6 +671,13 @@ static int rga_probe(struct platform_device *pdev)
> > > goto err_put_clk;
> > > }
> > >
> > > + if (iommu_get_domain_for_dev(rga->dev)) {
> > > + rga->empty_domain = iommu_paging_domain_alloc(rga->dev);
> > > +
> > > + if (!rga->empty_domain)
> > Its an error pointer, see:
> >
> > https://gitlab.freedesktop.org/linux-media/media-committers/-/commit/6347dc7fb967521a77f9ff0774d25ef0cca4c6cd
> >
> > > + dev_warn(rga->dev, "cannot alloc new empty
> > > domain\n");
> > > + }
> > > +
> > > ret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev);
> > > if (ret)
> > > goto err_put_clk;
> > > @@ -741,6 +762,9 @@ static void rga_remove(struct platform_device *pdev)
> > > v4l2_device_unregister(&rga->v4l2_dev);
> > >
> > > pm_runtime_disable(rga->dev);
> > > +
> > > + if (rga->empty_domain)
> > > + iommu_domain_free(rga->empty_domain);
> > > }
> > >
> > > static int __maybe_unused rga_runtime_suspend(struct device *dev)
> > > diff --git a/drivers/media/platform/rockchip/rga/rga.h
> > > b/drivers/media/platform/rockchip/rga/rga.h
> > > index
> > > fc4805ba4e8ef7fb311f780a198ba6ba4d3aff17..e19c4c82aca5ae2056f52d525138093fbbb8
> > > 1af8 100644
> > > --- a/drivers/media/platform/rockchip/rga/rga.h
> > > +++ b/drivers/media/platform/rockchip/rga/rga.h
> > > @@ -75,6 +75,7 @@ struct rockchip_rga {
> > > void __iomem *regs;
> > > struct clk_bulk_data clks[3];
> > > struct rockchip_rga_version version;
> > > + struct iommu_domain *empty_domain;
> > >
> > > /* vfd lock */
> > > struct mutex mutex;
> > > @@ -114,6 +115,12 @@ static inline struct rga_vb_buffer *vb_to_rga(struct
> > > vb2_v4l2_buffer *vb)
> > >
> > > struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type
> > > type);
> > >
> > > +/*
> > > + * This should be called in an interrupt handler to make sure no memory
> > > + * is mapped through the IOMMU while the empty domain is attached.
> > > + */
> > > +void rga_iommu_restore(struct rockchip_rga *rga);
> > > +
> > > /* RGA Buffers Manage */
> > > extern const struct vb2_ops rga_qops;
> > >
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 16/16] media: rockchip: rga: add rga3 support
2025-10-07 8:32 ` [PATCH 16/16] media: rockchip: rga: add rga3 support Sven Püschel
2025-10-07 8:39 ` Krzysztof Kozlowski
2025-10-07 19:41 ` Nicolas Dufresne
@ 2025-10-11 5:32 ` kernel test robot
2 siblings, 0 replies; 36+ messages in thread
From: kernel test robot @ 2025-10-11 5:32 UTC (permalink / raw)
To: Sven Püschel, Jacob Chen, Ezequiel Garcia,
Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: llvm, oe-kbuild-all, linux-media, linux-rockchip,
linux-arm-kernel, linux-kernel, devicetree, kernel,
Sven Püschel
Hi Sven,
kernel test robot noticed the following build warnings:
[auto build test WARNING on afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328]
url: https://github.com/intel-lab-lkp/linux/commits/Sven-P-schel/media-rockchip-rga-use-clk_bulk-api/20251010-104411
base: afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328
patch link: https://lore.kernel.org/r/20251007-spu-rga3-v1-16-36ad85570402%40pengutronix.de
patch subject: [PATCH 16/16] media: rockchip: rga: add rga3 support
config: riscv-randconfig-002-20251011 (https://download.01.org/0day-ci/archive/20251011/202510111354.QeqIltfU-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 39f292ffa13d7ca0d1edff27ac8fd55024bb4d19)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251011/202510111354.QeqIltfU-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510111354.QeqIltfU-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/media/platform/rockchip/rga/rga3-hw.c:144:15: warning: variable 'src_h' set but not used [-Wunused-but-set-variable]
144 | unsigned int src_h, src_w, dst_h, dst_w;
| ^
>> drivers/media/platform/rockchip/rga/rga3-hw.c:144:22: warning: variable 'src_w' set but not used [-Wunused-but-set-variable]
144 | unsigned int src_h, src_w, dst_h, dst_w;
| ^
>> drivers/media/platform/rockchip/rga/rga3-hw.c:144:29: warning: variable 'dst_h' set but not used [-Wunused-but-set-variable]
144 | unsigned int src_h, src_w, dst_h, dst_w;
| ^
>> drivers/media/platform/rockchip/rga/rga3-hw.c:144:36: warning: variable 'dst_w' set but not used [-Wunused-but-set-variable]
144 | unsigned int src_h, src_w, dst_h, dst_w;
| ^
4 warnings generated.
vim +/src_h +144 drivers/media/platform/rockchip/rga/rga3-hw.c
137
138 static void rga3_cmd_set_win0_format(struct rga_ctx *ctx)
139 {
140 u32 *cmd = ctx->rga->cmdbuf_virt;
141 const struct rga3_fmt *in = ctx->in.fmt;
142 const struct rga3_fmt *out = ctx->out.fmt;
143 const struct v4l2_format_info *in_fmt, *out_fmt;
> 144 unsigned int src_h, src_w, dst_h, dst_w;
145 bool r2y, y2r;
146 u8 rd_format;
147 unsigned int reg;
148
149 src_h = ctx->in.crop.height;
150 src_w = ctx->in.crop.width;
151 dst_h = ctx->out.crop.height;
152 dst_w = ctx->out.crop.width;
153
154 in_fmt = v4l2_format_info(in->fourcc);
155 out_fmt = v4l2_format_info(out->fourcc);
156 r2y = v4l2_is_format_rgb(in_fmt) && v4l2_is_format_yuv(out_fmt);
157 y2r = v4l2_is_format_yuv(in_fmt) && v4l2_is_format_rgb(out_fmt);
158
159 if (in->semi_planar)
160 rd_format = RGA3_RDWR_FORMAT_SEMI_PLANAR;
161 else
162 rd_format = RGA3_RDWR_FORMAT_INTERLEAVED;
163
164 reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG;
165 cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_PIC_FORMAT, in->hw_format)
166 | FIELD_PREP(RGA3_WIN_YC_SWAP, in->yc_swap)
167 | FIELD_PREP(RGA3_WIN_RBUV_SWAP, in->rbuv_swap)
168 | FIELD_PREP(RGA3_WIN_RD_FORMAT, rd_format)
169 | FIELD_PREP(RGA3_WIN_R2Y, r2y)
170 | FIELD_PREP(RGA3_WIN_Y2R, y2r)
171 | FIELD_PREP(RGA3_WIN_CSC_MODE, RGA3_WIN_CSC_MODE_BT601_F);
172 }
173
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2025-10-11 5:33 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-07 8:31 [PATCH 00/16] media: platform: rga: Add RGA3 support Sven Püschel
2025-10-07 8:31 ` [PATCH 01/16] media: rockchip: rga: use clk_bulk api Sven Püschel
2025-10-07 8:31 ` [PATCH 02/16] media: rockchip: rga: use stride for offset calculation Sven Püschel
2025-10-07 8:31 ` [PATCH 03/16] media: rockchip: rga: align stride to 16 bytes Sven Püschel
2025-10-07 18:19 ` Nicolas Dufresne
2025-10-07 8:31 ` [PATCH 04/16] media: rockchip: rga: move hw specific parts to a dedicated struct Sven Püschel
2025-10-07 8:31 ` [PATCH 05/16] media: rockchip: rga: use card type to specify rga type Sven Püschel
2025-10-07 8:31 ` [PATCH 06/16] media: rockchip: rga: change offset to dma_addresses Sven Püschel
2025-10-07 8:32 ` [PATCH 07/16] media: rockchip: rga: support external iommus Sven Püschel
2025-10-07 8:32 ` [PATCH 08/16] media: rockchip: rga: remove size from rga_frame Sven Püschel
2025-10-07 8:32 ` [PATCH 09/16] media: rockchip: rga: remove stride " Sven Püschel
2025-10-07 8:32 ` [PATCH 10/16] media: rockchip: rga: move rga_fmt to rga-hw.h Sven Püschel
2025-10-07 8:32 ` [PATCH 11/16] media: rockchip: rga: add iommu restore function Sven Püschel
2025-10-07 18:30 ` Nicolas Dufresne
2025-10-10 8:45 ` Sven Püschel
2025-10-10 13:10 ` Nicolas Dufresne
2025-10-07 8:32 ` [PATCH 12/16] media: rockchip: rga: handle error interrupt Sven Püschel
2025-10-07 18:47 ` Nicolas Dufresne
2025-10-07 8:32 ` [PATCH 13/16] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3 Sven Püschel
2025-10-07 8:38 ` Krzysztof Kozlowski
2025-10-07 18:12 ` Nicolas Dufresne
2025-10-07 8:32 ` [PATCH 14/16] arm64: dts: rockchip: add rga3 dt nodes Sven Püschel
2025-10-07 8:32 ` [PATCH 15/16] arm64: dts: rockchip: increase rga3 clock speed Sven Püschel
2025-10-07 8:39 ` Krzysztof Kozlowski
2025-10-07 8:32 ` [PATCH 16/16] media: rockchip: rga: add rga3 support Sven Püschel
2025-10-07 8:39 ` Krzysztof Kozlowski
2025-10-07 16:05 ` Sven Püschel
2025-10-08 1:55 ` Krzysztof Kozlowski
2025-10-07 18:54 ` Nicolas Dufresne
2025-10-07 19:41 ` Nicolas Dufresne
2025-10-10 9:21 ` Sven Püschel
2025-10-11 5:32 ` kernel test robot
2025-10-07 18:06 ` [PATCH 00/16] media: platform: rga: Add RGA3 support Nicolas Dufresne
2025-10-10 8:33 ` Sven Püschel
2025-10-10 13:05 ` Nicolas Dufresne
2025-10-09 22:03 ` Rob Herring (Arm)
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).