On Thu May 21 00:44:29 2026 +0200, Sven Püschel wrote:
> 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.
> 
> adjust_and_map_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 format value is also a pointer to update
> it in case the values are 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. The additional ctx parameter is also added to allow the
> RGA3 to limit the colorimetry only if an RGB<->YCrCb transformation
> happens.
> 
> Reviewed-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Sven Püschel <[email protected]>
> Signed-off-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/platform/rockchip/rga/rga-buf.c |  2 +-
 drivers/media/platform/rockchip/rga/rga-hw.c  | 49 +++++++++++++++++++++------
 drivers/media/platform/rockchip/rga/rga-hw.h  |  8 +++++
 drivers/media/platform/rockchip/rga/rga.c     | 41 ++++++++--------------
 drivers/media/platform/rockchip/rga/rga.h     | 14 +++-----
 5 files changed, 67 insertions(+), 47 deletions(-)

---

diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c 
b/drivers/media/platform/rockchip/rga/rga-buf.c
index 092c2bdf6b67..c0ea6003336b 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -162,7 +162,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 fac3975e2d0c..616ea1bc1131 100644
--- a/drivers/media/platform/rockchip/rga/rga-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -171,6 +171,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;
@@ -186,18 +188,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.pix.colorspace) {
                case V4L2_COLORSPACE_REC709:
                        src_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
@@ -208,8 +210,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.pix.colorspace) {
                case V4L2_COLORSPACE_REC709:
                        dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
@@ -563,11 +565,36 @@ static struct rga_fmt formats[] = {
        },
 };
 
+static void *rga_adjust_and_map_format(struct rga_ctx *ctx,
+                                      struct v4l2_pix_format_mplane *format,
+                                      bool is_output)
+{
+       unsigned int i;
+
+       if (!format)
+               return &formats[0];
+
+       for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               if (formats[i].fourcc == format->pixelformat)
+                       return &formats[i];
+       }
+
+       format->pixelformat = 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,
@@ -580,4 +607,6 @@ const struct rga_hw rga2_hw = {
        .start = rga_hw_start,
        .handle_irq = rga_handle_irq,
        .get_version = rga_get_version,
+       .adjust_and_map_format = rga_adjust_and_map_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 805ec23e5e3f..14ffa5ebd453 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 0x80
 
 /* Hardware limits */
@@ -431,4 +433,10 @@ union rga_pat_con {
        } data;
 };
 
+struct rga_fmt {
+       u32 fourcc;
+       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 e52d0577b236..1878b4e26360 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -232,17 +232,6 @@ int rga_check_scaling(const struct rga_hw *hw, const 
struct v4l2_rect *crop_in,
        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))
@@ -264,7 +253,6 @@ static int rga_open(struct file *file)
                .crop.top = 0,
                .crop.width = def_width,
                .crop.height = def_height,
-               .fmt = &rga->hw->formats[0],
        };
 
        ctx = kzalloc_obj(*ctx);
@@ -286,9 +274,12 @@ static int rga_open(struct file *file)
        ctx->in = def_frame;
        ctx->out = def_frame;
 
-       v4l2_fill_pixfmt_mp_aligned(&ctx->in.pix, ctx->in.fmt->fourcc,
+       ctx->in.fmt = rga->hw->adjust_and_map_format(ctx, &ctx->in.pix, true);
+       v4l2_fill_pixfmt_mp_aligned(&ctx->in.pix, ctx->in.pix.pixelformat,
                                    def_width, def_height, 
rga->hw->stride_alignment);
-       v4l2_fill_pixfmt_mp_aligned(&ctx->out.pix, ctx->out.fmt->fourcc,
+       ctx->out.fmt =
+               rga->hw->adjust_and_map_format(ctx, &ctx->out.pix, false);
+       v4l2_fill_pixfmt_mp_aligned(&ctx->out.pix, ctx->out.pix.pixelformat,
                                    def_width, def_height, 
rga->hw->stride_alignment);
 
        if (mutex_lock_interruptible(&rga->mutex)) {
@@ -370,13 +361,11 @@ 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;
+       int ret;
 
-       fmt = &rga->hw->formats[f->index];
-       f->pixelformat = fmt->fourcc;
+       ret = rga->hw->enum_format(f);
+       if (ret != 0)
+               return ret;
 
        if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
            f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -411,7 +400,6 @@ 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 rga_ctx *ctx = file_to_rga_ctx(file);
        const struct rga_hw *hw = ctx->rga->hw;
-       struct rga_fmt *fmt;
        struct v4l2_frmsize_stepwise frmsize = {
                .min_width = hw->min_width,
                .max_width = hw->max_width,
@@ -442,12 +430,10 @@ static int vidioc_try_fmt(struct file *file, void *priv, 
struct v4l2_format *f)
                pix_fmt->xfer_func = frm->pix.xfer_func;
        }
 
-       fmt = rga_fmt_find(ctx->rga, pix_fmt->pixelformat);
-       if (!fmt)
-               fmt = &hw->formats[0];
+       hw->adjust_and_map_format(ctx, pix_fmt, V4L2_TYPE_IS_OUTPUT(f->type));
 
        v4l2_apply_frmsize_constraints(&pix_fmt->width, &pix_fmt->height, 
&frmsize);
-       v4l2_fill_pixfmt_mp_aligned(pix_fmt, fmt->fourcc,
+       v4l2_fill_pixfmt_mp_aligned(pix_fmt, pix_fmt->pixelformat,
                                    pix_fmt->width, pix_fmt->height, 
hw->stride_alignment);
        pix_fmt->field = V4L2_FIELD_NONE;
 
@@ -478,7 +464,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, 
struct v4l2_format *f)
        frm = rga_get_frame(ctx, f->type);
        if (IS_ERR(frm))
                return PTR_ERR(frm);
-       frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
+       frm->fmt = rga->hw->adjust_and_map_format(ctx, pix_fmt,
+                                                 V4L2_TYPE_IS_OUTPUT(f->type));
 
        /*
         * Copy colorimetry from output to capture as required by the
@@ -503,7 +490,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, pix_fmt->width, pix_fmt->height,
+                 &pix_fmt->pixelformat, pix_fmt->width, pix_fmt->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 227ab6c0532c..effe364a86b0 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -17,18 +17,12 @@
 #define DEFAULT_WIDTH 100
 #define DEFAULT_HEIGHT 100
 
-struct rga_fmt {
-       u32 fourcc;
-       u8 color_swap;
-       u8 hw_format;
-};
-
 struct rga_frame {
        /* Crop */
        struct v4l2_rect crop;
 
        /* Image format */
-       struct rga_fmt *fmt;
+       void *fmt;
        struct v4l2_pix_format_mplane pix;
 };
 
@@ -146,8 +140,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 +151,10 @@ 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 *(*adjust_and_map_format)(struct rga_ctx *ctx,
+                                      struct v4l2_pix_format_mplane *format,
+                                      bool is_output);
+       int (*enum_format)(struct v4l2_fmtdesc *f);
 };
 
 static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to