]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: renesas: vsp1: Allow setting encoding and quantization
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tue, 29 Apr 2025 23:29:01 +0000 (02:29 +0300)
committerHans Verkuil <hverkuil@xs4all.nl>
Fri, 2 May 2025 08:16:44 +0000 (10:16 +0200)
The RPF and WPF support different encodings and quantizations when
converting between RGB and YUV formats. Allow setting the corresponding
format parameters from userspace, and configure the hardware
accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Link: https://lore.kernel.org/r/20250429232904.26413-7-laurent.pinchart+renesas@ideasonboard.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/platform/renesas/vsp1/vsp1_pipe.c
drivers/media/platform/renesas/vsp1/vsp1_rpf.c
drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
drivers/media/platform/renesas/vsp1/vsp1_video.c
drivers/media/platform/renesas/vsp1/vsp1_wpf.c

index 94875c499df47e41d4d04742b6bc98a4283eada0..3cbb768cf6adc8cb182d8d31c5b9a9d3565785e7 100644 (file)
@@ -359,33 +359,42 @@ vsp1_get_format_info_by_index(struct vsp1_device *vsp1, unsigned int index,
  * space and limitations of the VSP1. It should be used in the video device and
  * subdev set format handlers.
  *
- * For now, simply hardcode the color space fields to the VSP1 defaults based
- * on the media bus code.
+ * The colorspace and xfer_func fields are freely configurable, as they are out
+ * of scope for VSP processing. The encoding and quantization is hardcoded for
+ * non-YUV formats, and can be configured for YUV formats.
  */
 void vsp1_adjust_color_space(u32 code, u32 *colorspace, u8 *xfer_func,
                             u8 *encoding, u8 *quantization)
 {
+       if (*colorspace == V4L2_COLORSPACE_DEFAULT ||
+           *colorspace >= V4L2_COLORSPACE_LAST)
+               *colorspace = code == MEDIA_BUS_FMT_AYUV8_1X32
+                           ? V4L2_COLORSPACE_SMPTE170M
+                           : V4L2_COLORSPACE_SRGB;
+
+       if (*xfer_func == V4L2_XFER_FUNC_DEFAULT ||
+           *xfer_func >= V4L2_XFER_FUNC_LAST)
+               *xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(*colorspace);
+
        switch (code) {
        case MEDIA_BUS_FMT_ARGB8888_1X32:
        default:
-               *colorspace = V4L2_COLORSPACE_SRGB;
-               *xfer_func = V4L2_XFER_FUNC_SRGB;
                *encoding = V4L2_YCBCR_ENC_601;
                *quantization = V4L2_QUANTIZATION_FULL_RANGE;
                break;
 
        case MEDIA_BUS_FMT_AHSV8888_1X32:
-               *colorspace = V4L2_COLORSPACE_SRGB;
-               *xfer_func = V4L2_XFER_FUNC_SRGB;
                *encoding = V4L2_HSV_ENC_256;
                *quantization = V4L2_QUANTIZATION_FULL_RANGE;
                break;
 
        case MEDIA_BUS_FMT_AYUV8_1X32:
-               *colorspace = V4L2_COLORSPACE_SMPTE170M;
-               *xfer_func = V4L2_XFER_FUNC_709;
-               *encoding = V4L2_YCBCR_ENC_601;
-               *quantization = V4L2_QUANTIZATION_LIM_RANGE;
+               if (*encoding != V4L2_YCBCR_ENC_601 &&
+                   *encoding != V4L2_YCBCR_ENC_709)
+                       *encoding = V4L2_YCBCR_ENC_601;
+               if (*quantization != V4L2_QUANTIZATION_FULL_RANGE &&
+                   *quantization != V4L2_QUANTIZATION_LIM_RANGE)
+                       *quantization = V4L2_QUANTIZATION_LIM_RANGE;
                break;
        }
 }
index 5e84536f0cdd84addba5f685da6c9ae349dca2cd..811f2b7c5cc5dbfbe08b6c06cd8ad1157fef4a89 100644 (file)
@@ -92,8 +92,33 @@ static void rpf_configure_stream(struct vsp1_entity *entity,
        if (fmtinfo->swap_uv)
                infmt |= VI6_RPF_INFMT_SPUVS;
 
-       if (sink_format->code != source_format->code)
-               infmt |= VI6_RPF_INFMT_CSC;
+       if (sink_format->code != source_format->code) {
+               u16 ycbcr_enc;
+               u16 quantization;
+               u32 rdtm;
+
+               if (sink_format->code == MEDIA_BUS_FMT_AYUV8_1X32) {
+                       ycbcr_enc = sink_format->ycbcr_enc;
+                       quantization = sink_format->quantization;
+               } else {
+                       ycbcr_enc = source_format->ycbcr_enc;
+                       quantization = source_format->quantization;
+               }
+
+               if (ycbcr_enc == V4L2_YCBCR_ENC_601 &&
+                   quantization == V4L2_QUANTIZATION_LIM_RANGE)
+                       rdtm = VI6_RPF_INFMT_RDTM_BT601;
+               else if (ycbcr_enc == V4L2_YCBCR_ENC_601 &&
+                        quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                       rdtm = VI6_RPF_INFMT_RDTM_BT601_EXT;
+               else if (ycbcr_enc == V4L2_YCBCR_ENC_709 &&
+                        quantization == V4L2_QUANTIZATION_LIM_RANGE)
+                       rdtm = VI6_RPF_INFMT_RDTM_BT709;
+               else
+                       rdtm = VI6_RPF_INFMT_RDTM_BT709_EXT;
+
+               infmt |= VI6_RPF_INFMT_CSC | rdtm;
+       }
 
        vsp1_rpf_write(rpf, dlb, VI6_RPF_INFMT, infmt);
        vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap);
index 4e8bcf6a59ad8f47f28b78f8d3cd38ea6f005213..9c8085d5d3060abfa247d27cc63dda856970376f 100644 (file)
@@ -36,6 +36,11 @@ static int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
 
        code->code = codes[code->index];
 
+       if (code->pad == RWPF_PAD_SOURCE &&
+           code->code == MEDIA_BUS_FMT_AYUV8_1X32)
+               code->flags = V4L2_SUBDEV_MBUS_CODE_CSC_YCBCR_ENC
+                           | V4L2_SUBDEV_MBUS_CODE_CSC_QUANTIZATION;
+
        return 0;
 }
 
@@ -79,11 +84,13 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
        if (fmt->pad == RWPF_PAD_SOURCE) {
                const struct v4l2_mbus_framefmt *sink_format =
                        v4l2_subdev_state_get_format(state, RWPF_PAD_SINK);
+               u16 flags = fmt->format.flags & V4L2_MBUS_FRAMEFMT_SET_CSC;
+               bool csc;
 
                /*
                 * The RWPF performs format conversion but can't scale, only the
-                * format code can be changed on the source pad when converting
-                * between RGB and YUV.
+                * format code, encoding and quantization can be changed on the
+                * source pad when converting between RGB and YUV.
                 */
                if (sink_format->code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
                    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32)
@@ -91,9 +98,29 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
                else
                        format->code = sink_format->code;
 
+               /*
+                * Encoding and quantization can only be configured when YCbCr
+                * <-> RGB is enabled. The V4L2 API requires userspace to set
+                * the V4L2_MBUS_FRAMEFMT_SET_CSC flag. If either of these
+                * conditions is not met, use the encoding and quantization
+                * values from the sink pad.
+                */
+               csc = (format->code == MEDIA_BUS_FMT_AYUV8_1X32) !=
+                     (sink_format->code == MEDIA_BUS_FMT_AYUV8_1X32);
+
+               if (csc && (flags & V4L2_MBUS_FRAMEFMT_SET_CSC)) {
+                       format->ycbcr_enc = fmt->format.ycbcr_enc;
+                       format->quantization = fmt->format.quantization;
+               } else {
+                       format->ycbcr_enc = sink_format->ycbcr_enc;
+                       format->quantization = sink_format->quantization;
+               }
+
                vsp1_entity_adjust_color_space(format);
 
                fmt->format = *format;
+               fmt->format.flags = flags;
+
                goto done;
        }
 
index 68d495c20a844422a0d68aaf6b797c8a625131f8..bc66fbdde3cc1590072c3917cfe3005fade58307 100644 (file)
@@ -129,6 +129,20 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
        pix->pixelformat = info->fourcc;
        pix->field = V4L2_FIELD_NONE;
 
+       /*
+        * Adjust the colour space fields. On capture devices, userspace needs
+        * to set the V4L2_PIX_FMT_FLAG_SET_CSC to override the defaults. Reset
+        * all fields to *_DEFAULT if the flag isn't set, to then handle
+        * capture and output devices in the same way.
+        */
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+           !(pix->flags & V4L2_PIX_FMT_FLAG_SET_CSC)) {
+               pix->colorspace = V4L2_COLORSPACE_DEFAULT;
+               pix->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+               pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+               pix->quantization = V4L2_QUANTIZATION_DEFAULT;
+       }
+
        vsp1_adjust_color_space(info->mbus, &pix->colorspace, &pix->xfer_func,
                                &pix->ycbcr_enc, &pix->quantization);
 
@@ -908,6 +922,11 @@ static int vsp1_video_enum_format(struct file *file, void *fh,
 
        f->pixelformat = info->fourcc;
 
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+           info->mbus == MEDIA_BUS_FMT_AYUV8_1X32)
+               f->flags = V4L2_FMT_FLAG_CSC_YCBCR_ENC
+                        | V4L2_FMT_FLAG_CSC_QUANTIZATION;
+
        return 0;
 }
 
index f3ea3b17e4cb3126b191a46a2320ed44df0c9e58..30662cfdf83792cb1dba8f904c4290083c3c8b65 100644 (file)
@@ -282,8 +282,33 @@ static void wpf_configure_stream(struct vsp1_entity *entity,
                                       (256 << VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT));
        }
 
-       if (sink_format->code != source_format->code)
-               outfmt |= VI6_WPF_OUTFMT_CSC;
+       if (sink_format->code != source_format->code) {
+               u16 ycbcr_enc;
+               u16 quantization;
+               u32 wrtm;
+
+               if (sink_format->code == MEDIA_BUS_FMT_AYUV8_1X32) {
+                       ycbcr_enc = sink_format->ycbcr_enc;
+                       quantization = sink_format->quantization;
+               } else {
+                       ycbcr_enc = source_format->ycbcr_enc;
+                       quantization = source_format->quantization;
+               }
+
+               if (ycbcr_enc == V4L2_YCBCR_ENC_601 &&
+                   quantization == V4L2_QUANTIZATION_LIM_RANGE)
+                       wrtm = VI6_WPF_OUTFMT_WRTM_BT601;
+               else if (ycbcr_enc == V4L2_YCBCR_ENC_601 &&
+                        quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                       wrtm = VI6_WPF_OUTFMT_WRTM_BT601_EXT;
+               else if (ycbcr_enc == V4L2_YCBCR_ENC_709 &&
+                        quantization == V4L2_QUANTIZATION_LIM_RANGE)
+                       wrtm = VI6_WPF_OUTFMT_WRTM_BT709;
+               else
+                       wrtm = VI6_WPF_OUTFMT_WRTM_BT709_EXT;
+
+               outfmt |= VI6_WPF_OUTFMT_CSC | wrtm;
+       }
 
        wpf->outfmt = outfmt;