]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
media: rzg2l-cru: Support multiple mbus codes per pixel format
authorDaniel Scally <dan.scally+renesas@ideasonboard.com>
Mon, 30 Jun 2025 15:06:51 +0000 (16:06 +0100)
committerHans Verkuil <hverkuil@xs4all.nl>
Thu, 3 Jul 2025 07:04:14 +0000 (09:04 +0200)
As a preliminary step for supporting the CRU pixel formats, extend
the driver such that multiple media bus codes can support each of
the output pixel formats.

Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Daniel Scally <dan.scally+renesas@ideasonboard.com>
Link: https://lore.kernel.org/r/20250630150651.2698237-1-dan.scally@ideasonboard.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c

index bba174973ac34aa13cded0bde6a4e522abef6873..be95b41c37dfdbe80722557fafb5c844e5abc165 100644 (file)
@@ -64,14 +64,18 @@ struct rzg2l_cru_ip {
 
 /**
  * struct rzg2l_cru_ip_format - CRU IP format
- * @code: Media bus code
+ * @codes: Array of up to four media bus codes
  * @datatype: MIPI CSI2 data type
  * @format: 4CC format identifier (V4L2_PIX_FMT_*)
  * @icndmr: ICnDMR register value
  * @yuv: Flag to indicate whether the format is YUV-based.
  */
 struct rzg2l_cru_ip_format {
-       u32 code;
+       /*
+        * RAW output formats might be produced by RAW media codes with any one
+        * of the 4 common bayer patterns.
+        */
+       u32 codes[4];
        u32 datatype;
        u32 format;
        u32 icndmr;
@@ -190,6 +194,8 @@ struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru);
 const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code);
 const struct rzg2l_cru_ip_format *rzg2l_cru_ip_format_to_fmt(u32 format);
 const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index);
+bool rzg2l_cru_ip_fmt_supports_mbus_code(const struct rzg2l_cru_ip_format *fmt,
+                                        unsigned int code);
 
 void rzg2l_cru_enable_interrupts(struct rzg2l_cru_dev *cru);
 void rzg2l_cru_disable_interrupts(struct rzg2l_cru_dev *cru);
index 15fc1028082add27ad3d6fa9e1314b6240ff0d4e..fbbcdb96c4570baf07cc9685c2fc847fb489df89 100644 (file)
 
 static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = {
        {
-               .code = MEDIA_BUS_FMT_UYVY8_1X16,
+               .codes = {
+                       MEDIA_BUS_FMT_UYVY8_1X16,
+               },
                .datatype = MIPI_CSI2_DT_YUV422_8B,
                .format = V4L2_PIX_FMT_UYVY,
                .icndmr = ICnDMR_YCMODE_UYVY,
                .yuv = true,
        },
        {
-               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .codes = {
+                       MEDIA_BUS_FMT_SBGGR8_1X8,
+               },
                .format = V4L2_PIX_FMT_SBGGR8,
                .datatype = MIPI_CSI2_DT_RAW8,
                .icndmr = 0,
                .yuv = false,
        },
        {
-               .code = MEDIA_BUS_FMT_SGBRG8_1X8,
+               .codes = {
+                       MEDIA_BUS_FMT_SGBRG8_1X8,
+               },
                .format = V4L2_PIX_FMT_SGBRG8,
                .datatype = MIPI_CSI2_DT_RAW8,
                .icndmr = 0,
                .yuv = false,
        },
        {
-               .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+               .codes = {
+                       MEDIA_BUS_FMT_SGRBG8_1X8,
+               },
                .format = V4L2_PIX_FMT_SGRBG8,
                .datatype = MIPI_CSI2_DT_RAW8,
                .icndmr = 0,
                .yuv = false,
        },
        {
-               .code = MEDIA_BUS_FMT_SRGGB8_1X8,
+               .codes = {
+                       MEDIA_BUS_FMT_SRGGB8_1X8,
+               },
                .format = V4L2_PIX_FMT_SRGGB8,
                .datatype = MIPI_CSI2_DT_RAW8,
                .icndmr = 0,
@@ -51,11 +61,14 @@ static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = {
 
 const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code)
 {
-       unsigned int i;
+       unsigned int i, j;
 
-       for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++)
-               if (rzg2l_cru_ip_formats[i].code == code)
-                       return &rzg2l_cru_ip_formats[i];
+       for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) {
+               for (j = 0; j < ARRAY_SIZE(rzg2l_cru_ip_formats[i].codes); j++) {
+                       if (rzg2l_cru_ip_formats[i].codes[j] == code)
+                               return &rzg2l_cru_ip_formats[i];
+               }
+       }
 
        return NULL;
 }
@@ -80,6 +93,17 @@ const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index)
        return &rzg2l_cru_ip_formats[index];
 }
 
+bool rzg2l_cru_ip_fmt_supports_mbus_code(const struct rzg2l_cru_ip_format *fmt,
+                                        unsigned int code)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(fmt->codes); i++)
+               if (fmt->codes[i] == code)
+                       return true;
+
+       return false;
+}
 struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
 {
        struct v4l2_subdev_state *state;
@@ -157,7 +181,7 @@ static int rzg2l_cru_ip_set_format(struct v4l2_subdev *sd,
        sink_format = v4l2_subdev_state_get_format(state, fmt->pad);
 
        if (!rzg2l_cru_ip_code_to_fmt(fmt->format.code))
-               sink_format->code = rzg2l_cru_ip_formats[0].code;
+               sink_format->code = rzg2l_cru_ip_formats[0].codes[0];
        else
                sink_format->code = fmt->format.code;
 
@@ -183,11 +207,26 @@ static int rzg2l_cru_ip_enum_mbus_code(struct v4l2_subdev *sd,
                                       struct v4l2_subdev_state *state,
                                       struct v4l2_subdev_mbus_code_enum *code)
 {
-       if (code->index >= ARRAY_SIZE(rzg2l_cru_ip_formats))
-               return -EINVAL;
+       unsigned int index = code->index;
+       unsigned int i, j;
 
-       code->code = rzg2l_cru_ip_formats[code->index].code;
-       return 0;
+       for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) {
+               const struct rzg2l_cru_ip_format *fmt = &rzg2l_cru_ip_formats[i];
+
+               for (j = 0; j < ARRAY_SIZE(fmt->codes); j++) {
+                       if (!fmt->codes[j])
+                               continue;
+
+                       if (!index) {
+                               code->code = fmt->codes[j];
+                               return 0;
+                       }
+
+                       index--;
+               }
+       }
+
+       return -EINVAL;
 }
 
 static int rzg2l_cru_ip_enum_frame_size(struct v4l2_subdev *sd,
index e151e659760997aee04984c88dfc32ecfba2164c..a8817a7066b22f8a8dd1fdab50efabc486e4dfdb 100644 (file)
@@ -1145,7 +1145,7 @@ static int rzg2l_cru_video_link_validate(struct media_link *link)
        if (fmt.format.width != cru->format.width ||
            fmt.format.height != cru->format.height ||
            fmt.format.field != cru->format.field ||
-           video_fmt->code != fmt.format.code)
+           !rzg2l_cru_ip_fmt_supports_mbus_code(video_fmt, fmt.format.code))
                return -EPIPE;
 
        return 0;