From nobody Mon Feb 9 22:39:03 2026 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74F84364EB9 for ; Tue, 27 Jan 2026 14:40:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769524853; cv=none; b=DzHOfyzlH3QtzLzqd7le9SfyDkJUmnXFAbiImc8H5261j5qK/pw/rfwD8RzkfBrnVlO8KWLETwIz0XOOpg3jLWe8hemWuha9k2FWtIHq3dN+RSvXCjiGvTRs9o+jZEs/MhIS/m3k30LDR24VlCZon1D+FR0mJhU1zGJaKEHPnak= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769524853; c=relaxed/simple; bh=jVCIMtQ5Oc39w6WM/yRgF86Yn2ql20o6yBm4CyY0j4k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XGF/J38dE2MPKgqT/swzu55xUmqCPZtX/VZ+LjQZFbFPKEBS0dpke2fjFwx51m78AQUzmhxaPFJLwaorYrmdHCjpYfLyftwnbNt76+hfdwVl5VOzVIMQuu2ss0Ps1VszJuwRp+SgVN34o2MR3i45iXmtWLj7tyMRBKUIEYrXjRM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from ptz.office.stw.pengutronix.de ([2a0a:edc0:0:900:1d::77] helo=peter.mobile.pengutronix.de) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1vkkFN-0007YT-4l; Tue, 27 Jan 2026 15:40:49 +0100 From: =?utf-8?q?Sven_P=C3=BCschel?= Date: Tue, 27 Jan 2026 15:39:32 +0100 Subject: [PATCH v3 23/27] media: rockchip: rga: move rga_fmt to rga-hw.h Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260127-spu-rga3-v3-23-77b273067beb@pengutronix.de> References: <20260127-spu-rga3-v3-0-77b273067beb@pengutronix.de> In-Reply-To: <20260127-spu-rga3-v3-0-77b273067beb@pengutronix.de> To: Jacob Chen , Ezequiel Garcia , Mauro Carvalho Chehab , Heiko Stuebner , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, kernel@pengutronix.de, =?utf-8?q?Sven_P=C3=BCschel?= , Nicolas Dufresne X-Mailer: b4 0.14.3 X-SA-Exim-Connect-IP: 2a0a:edc0:0:900:1d::77 X-SA-Exim-Mail-From: s.pueschel@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org 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 Signed-off-by: Sven P=C3=BCschel --- 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 | 39 +++++++-------------- drivers/media/platform/rockchip/rga/rga.h | 14 +++----- 5 files changed, 66 insertions(+), 46 deletions(-) diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/= platform/rockchip/rga/rga-buf.c index c0cc885ba58a8..8632b18cd3fc6 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) } =20 /* Fill the remaining planes */ - info =3D v4l2_format_info(f->fmt->fourcc); + info =3D v4l2_format_info(f->pix.pixelformat); for (i =3D info->mem_planes; i < info->comp_planes; i++) dma_addrs[i] =3D dma_addrs[0] + get_plane_offset(f, info, i); =20 diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/p= latform/rockchip/rga/rga-hw.c index 5d993cf69963d..e76d1994b8684 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 =3D ctx->in.fmt; + struct rga_fmt *out_fmt =3D ctx->out.fmt; =20 src_h =3D ctx->in.crop.height; src_w =3D ctx->in.crop.width; @@ -186,18 +188,18 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ct= x) dst_vir_info.val =3D dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2]; dst_act_info.val =3D dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2]; =20 - src_info.data.format =3D ctx->in.fmt->hw_format; - src_info.data.swap =3D ctx->in.fmt->color_swap; - dst_info.data.format =3D ctx->out.fmt->hw_format; - dst_info.data.swap =3D ctx->out.fmt->color_swap; + src_info.data.format =3D in_fmt->hw_format; + src_info.data.swap =3D in_fmt->color_swap; + dst_info.data.format =3D out_fmt->hw_format; + dst_info.data.swap =3D out_fmt->color_swap; =20 /* * 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. */ =20 - 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 =3D RGA_SRC_CSC_MODE_BT709_R0; @@ -208,8 +210,8 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx) } } =20 - 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 =3D RGA_SRC_CSC_MODE_BT709_R0; @@ -563,11 +565,36 @@ static struct rga_fmt formats[] =3D { }, }; =20 +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 =3D 0; i < ARRAY_SIZE(formats); i++) { + if (formats[i].fourcc =3D=3D format->pixelformat) + return &formats[i]; + } + + format->pixelformat =3D formats[0].fourcc; + return &formats[0]; +} + +static int rga_enum_format(struct v4l2_fmtdesc *f) +{ + if (f->index >=3D ARRAY_SIZE(formats)) + return -EINVAL; + + f->pixelformat =3D formats[f->index].fourcc; + return 0; +} + const struct rga_hw rga2_hw =3D { .card_type =3D "rga2", .has_internal_iommu =3D true, - .formats =3D formats, - .num_formats =3D ARRAY_SIZE(formats), .cmdbuf_size =3D RGA_CMDBUF_SIZE, .min_width =3D MIN_WIDTH, .max_width =3D MAX_WIDTH, @@ -580,4 +607,6 @@ const struct rga_hw rga2_hw =3D { .start =3D rga_hw_start, .handle_irq =3D rga_handle_irq, .get_version =3D rga_get_version, + .adjust_and_map_format =3D rga_adjust_and_map_format, + .enum_format =3D rga_enum_format, }; diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/p= latform/rockchip/rga/rga-hw.h index fffcab0131225..039a3e868733e 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__ =20 +#include + #define RGA_CMDBUF_SIZE 0x20 =20 /* Hardware limits */ @@ -431,4 +433,10 @@ union rga_pat_con { } data; }; =20 +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/plat= form/rockchip/rga/rga.c index 30d09ec77afca..c1371ad0b1ea1 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; } =20 -static struct rga_fmt *rga_fmt_find(struct rockchip_rga *rga, u32 pixelfor= mat) -{ - unsigned int i; - - for (i =3D 0; i < rga->hw->num_formats; i++) { - if (rga->hw->formats[i].fourcc =3D=3D pixelformat) - return &rga->hw->formats[i]; - } - return NULL; -} - struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type ty= pe) { if (V4L2_TYPE_IS_OUTPUT(type)) @@ -217,7 +206,6 @@ static int rga_open(struct file *file) .crop.top =3D 0, .crop.width =3D def_width, .crop.height =3D def_height, - .fmt =3D &rga->hw->formats[0], }; =20 ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); @@ -238,9 +226,12 @@ static int rga_open(struct file *file) ctx->in =3D def_frame; ctx->out =3D def_frame; =20 - v4l2_fill_pixfmt_mp_aligned(&ctx->in.pix, ctx->in.fmt->fourcc, + ctx->in.fmt =3D 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 =3D + 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); =20 if (mutex_lock_interruptible(&rga->mutex)) { @@ -322,13 +313,11 @@ vidioc_querycap(struct file *file, void *priv, struct= v4l2_capability *cap) static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtd= esc *f) { struct rockchip_rga *rga =3D video_drvdata(file); - struct rga_fmt *fmt; - - if (f->index >=3D rga->hw->num_formats) - return -EINVAL; + int ret; =20 - fmt =3D &rga->hw->formats[f->index]; - f->pixelformat =3D fmt->fourcc; + ret =3D rga->hw->enum_format(f); + if (ret !=3D 0) + return ret; =20 if (f->type !=3D V4L2_BUF_TYPE_VIDEO_CAPTURE && f->type !=3D V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) @@ -363,7 +352,6 @@ static int vidioc_try_fmt(struct file *file, void *priv= , struct v4l2_format *f) struct v4l2_pix_format_mplane *pix_fmt =3D &f->fmt.pix_mp; struct rga_ctx *ctx =3D file_to_rga_ctx(file); const struct rga_hw *hw =3D ctx->rga->hw; - struct rga_fmt *fmt; struct v4l2_frmsize_stepwise frmsize =3D { .min_width =3D hw->min_width, .max_width =3D hw->max_width, @@ -394,9 +382,7 @@ static int vidioc_try_fmt(struct file *file, void *priv= , struct v4l2_format *f) pix_fmt->xfer_func =3D frm->pix.xfer_func; } =20 - fmt =3D rga_fmt_find(ctx->rga, pix_fmt->pixelformat); - if (!fmt) - fmt =3D &hw->formats[0]; + hw->adjust_and_map_format(ctx, pix_fmt, V4L2_TYPE_IS_OUTPUT(f->type)); =20 v4l2_apply_frmsize_constraints(&pix_fmt->width, &pix_fmt->height, &frmsiz= e); v4l2_fill_pixfmt_mp_aligned(pix_fmt, pix_fmt->pixelformat, @@ -456,7 +442,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, = struct v4l2_format *f) frm =3D rga_get_frame(ctx, f->type); if (IS_ERR(frm)) return PTR_ERR(frm); - frm->fmt =3D rga_fmt_find(rga, pix_fmt->pixelformat); + frm->fmt =3D rga->hw->adjust_and_map_format(ctx, pix_fmt, + V4L2_TYPE_IS_OUTPUT(f->type)); =20 /* * Copy colorimetry from output to capture as required by the @@ -480,7 +467,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); =20 for (i =3D 0; i < pix_fmt->num_planes; i++) { diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/plat= form/rockchip/rga/rga.h index d203b7dae2b03..d98e57c6d7b57 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 =20 -struct rga_fmt { - u32 fourcc; - u8 color_swap; - u8 hw_format; -}; - struct rga_frame { /* Crop */ struct v4l2_rect crop; =20 /* Image format */ - struct rga_fmt *fmt; + void *fmt; struct v4l2_pix_format_mplane pix; }; =20 @@ -142,8 +136,6 @@ static inline void rga_mod(struct rockchip_rga *rga, u3= 2 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; @@ -155,6 +147,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); }; =20 static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga) --=20 2.52.0