]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: renesas: vsp1: Report colour space information to userspace
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tue, 29 Apr 2025 23:29:00 +0000 (02:29 +0300)
committerHans Verkuil <hverkuil@xs4all.nl>
Fri, 2 May 2025 08:16:44 +0000 (10:16 +0200)
The vsp1 driver implements very partial colour space support: it
hardcodes the colorspace field on all video devices and subdevices to
V4L2_COLORSPACE_SRGB, regardless of the configured format. The
xfer_func, ycbcr_enc and quantization fields are not set (except for
hsv_enc for HSV formats on video devices). This doesn't match the
hardware configuration, which handles YUV data as encoding in BT.601
with limited range.

As a first step towards colour space configuration, keep the colour
space fields hardcoded, but set them based on the selected format type
(RGB, YUV or HSV).

While at it, remove an extra blank line.

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-6-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_brx.c
drivers/media/platform/renesas/vsp1/vsp1_entity.c
drivers/media/platform/renesas/vsp1/vsp1_entity.h
drivers/media/platform/renesas/vsp1/vsp1_hsit.c
drivers/media/platform/renesas/vsp1/vsp1_pipe.c
drivers/media/platform/renesas/vsp1/vsp1_pipe.h
drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
drivers/media/platform/renesas/vsp1/vsp1_sru.c
drivers/media/platform/renesas/vsp1/vsp1_uds.c
drivers/media/platform/renesas/vsp1/vsp1_video.c

index 5dee0490c593b54bee5c7a602a1a46e1ae89b63f..5fc2e5a3bb30f03b35da6c4473038d08d8229e3a 100644 (file)
@@ -15,6 +15,7 @@
 #include "vsp1.h"
 #include "vsp1_brx.h"
 #include "vsp1_dl.h"
+#include "vsp1_entity.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_video.h"
@@ -108,6 +109,8 @@ static void brx_try_format(struct vsp1_brx *brx,
                if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
                    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
                        fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+
+               vsp1_entity_adjust_color_space(fmt);
                break;
 
        default:
@@ -115,13 +118,17 @@ static void brx_try_format(struct vsp1_brx *brx,
                format = v4l2_subdev_state_get_format(sd_state,
                                                      BRX_PAD_SINK(0));
                fmt->code = format->code;
+
+               fmt->colorspace = format->colorspace;
+               fmt->xfer_func = format->xfer_func;
+               fmt->ycbcr_enc = format->ycbcr_enc;
+               fmt->quantization = format->quantization;
                break;
        }
 
        fmt->width = clamp(fmt->width, BRX_MIN_SIZE, BRX_MAX_SIZE);
        fmt->height = clamp(fmt->height, BRX_MIN_SIZE, BRX_MAX_SIZE);
        fmt->field = V4L2_FIELD_NONE;
-       fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
 static int brx_set_format(struct v4l2_subdev *subdev,
index 2096a09a12780ce64d9e8690aa4363bdaef3521e..a6680d531872a7eb7dd7fb1c1a265a7ef5b6047b 100644 (file)
@@ -104,6 +104,20 @@ void vsp1_entity_configure_partition(struct vsp1_entity *entity,
                                                 dl, dlb);
 }
 
+void vsp1_entity_adjust_color_space(struct v4l2_mbus_framefmt *format)
+{
+       u8 xfer_func = format->xfer_func;
+       u8 ycbcr_enc = format->ycbcr_enc;
+       u8 quantization = format->quantization;
+
+       vsp1_adjust_color_space(format->code, &format->colorspace, &xfer_func,
+                               &ycbcr_enc, &quantization);
+
+       format->xfer_func = xfer_func;
+       format->ycbcr_enc = ycbcr_enc;
+       format->quantization = quantization;
+}
+
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Operations
  */
@@ -334,7 +348,13 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
        format->height = clamp_t(unsigned int, fmt->format.height,
                                 min_height, max_height);
        format->field = V4L2_FIELD_NONE;
-       format->colorspace = V4L2_COLORSPACE_SRGB;
+
+       format->colorspace = fmt->format.colorspace;
+       format->xfer_func = fmt->format.xfer_func;
+       format->ycbcr_enc = fmt->format.ycbcr_enc;
+       format->quantization = fmt->format.quantization;
+
+       vsp1_entity_adjust_color_space(format);
 
        fmt->format = *format;
 
index bdcb780a79dafccda3843bd65d337b64d6e12eb3..b7c72d0b7f8e18638ce3f9ac9b6f9f268d529a07 100644 (file)
@@ -171,6 +171,8 @@ void vsp1_entity_configure_partition(struct vsp1_entity *entity,
                                     struct vsp1_dl_list *dl,
                                     struct vsp1_dl_body *dlb);
 
+void vsp1_entity_adjust_color_space(struct v4l2_mbus_framefmt *format);
+
 struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad);
 
 int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
index 8ba2a7c7305c76499557bdc91e2d1606e700cbcc..1fcd1967d3b2c1d0247844b152067e7f3d4827b8 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "vsp1.h"
 #include "vsp1_dl.h"
+#include "vsp1_entity.h"
 #include "vsp1_hsit.h"
 
 #define HSIT_MIN_SIZE                          4U
@@ -96,7 +97,13 @@ static int hsit_set_format(struct v4l2_subdev *subdev,
        format->height = clamp_t(unsigned int, fmt->format.height,
                                 HSIT_MIN_SIZE, HSIT_MAX_SIZE);
        format->field = V4L2_FIELD_NONE;
-       format->colorspace = V4L2_COLORSPACE_SRGB;
+
+       format->colorspace = fmt->format.colorspace;
+       format->xfer_func = fmt->format.xfer_func;
+       format->ycbcr_enc = fmt->format.ycbcr_enc;
+       format->quantization = fmt->format.quantization;
+
+       vsp1_entity_adjust_color_space(format);
 
        fmt->format = *format;
 
@@ -106,6 +113,8 @@ static int hsit_set_format(struct v4l2_subdev *subdev,
        format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32
                     : MEDIA_BUS_FMT_AHSV8888_1X32;
 
+       vsp1_entity_adjust_color_space(format);
+
 done:
        mutex_unlock(&hsit->entity.lock);
        return ret;
index c8ec5bfa7944df542f9ca63d87d386731f85c5ef..94875c499df47e41d4d04742b6bc98a4283eada0 100644 (file)
@@ -346,6 +346,50 @@ vsp1_get_format_info_by_index(struct vsp1_device *vsp1, unsigned int index,
        return NULL;
 }
 
+/**
+ * vsp1_adjust_color_space - Adjust color space fields in a format
+ * @code: the media bus code
+ * @colorspace: the colorspace
+ * @xfer_func: the transfer function
+ * @encoding: the encoding
+ * @quantization: the quantization
+ *
+ * This function adjusts all color space fields of a video device of subdev
+ * format structure, taking into account the requested format, requested color
+ * 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.
+ */
+void vsp1_adjust_color_space(u32 code, u32 *colorspace, u8 *xfer_func,
+                            u8 *encoding, u8 *quantization)
+{
+       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;
+               break;
+       }
+}
+
 /* -----------------------------------------------------------------------------
  * Pipeline Management
  */
index 383951c5bd9017a1a5a71233b8ec94501a02c48d..7f623b8cbe5c621c995eb69ac26a86ddffe89db5 100644 (file)
@@ -183,5 +183,7 @@ const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
 const struct vsp1_format_info *
 vsp1_get_format_info_by_index(struct vsp1_device *vsp1, unsigned int index,
                              u32 code);
+void vsp1_adjust_color_space(u32 code, u32 *colorspace, u8 *xfer_func,
+                            u8 *encoding, u8 *quantization);
 
 #endif /* __VSP1_PIPE_H__ */
index 1b4bac7b7cfa1c8e8a876f9035fb2eb96b7ee43e..4e8bcf6a59ad8f47f28b78f8d3cd38ea6f005213 100644 (file)
@@ -10,6 +10,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
+#include "vsp1_entity.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_video.h"
 
@@ -90,6 +91,8 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
                else
                        format->code = sink_format->code;
 
+               vsp1_entity_adjust_color_space(format);
+
                fmt->format = *format;
                goto done;
        }
@@ -100,7 +103,13 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
        format->height = clamp_t(unsigned int, fmt->format.height,
                                 RWPF_MIN_HEIGHT, rwpf->max_height);
        format->field = V4L2_FIELD_NONE;
-       format->colorspace = V4L2_COLORSPACE_SRGB;
+
+       format->colorspace = fmt->format.colorspace;
+       format->xfer_func = fmt->format.xfer_func;
+       format->ycbcr_enc = fmt->format.ycbcr_enc;
+       format->quantization = fmt->format.quantization;
+
+       vsp1_entity_adjust_color_space(format);
 
        fmt->format = *format;
 
index 1759ce642e6e02e46c59f61751e208696cb493b1..bba2872afaf21f31f77b25af4d14ed0383e1694c 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "vsp1.h"
 #include "vsp1_dl.h"
+#include "vsp1_entity.h"
 #include "vsp1_pipe.h"
 #include "vsp1_sru.h"
 
@@ -178,6 +179,8 @@ static void sru_try_format(struct vsp1_sru *sru,
                    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
                        fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
 
+               vsp1_entity_adjust_color_space(fmt);
+
                fmt->width = clamp(fmt->width, SRU_MIN_SIZE, SRU_MAX_SIZE);
                fmt->height = clamp(fmt->height, SRU_MIN_SIZE, SRU_MAX_SIZE);
                break;
@@ -187,6 +190,11 @@ static void sru_try_format(struct vsp1_sru *sru,
                format = v4l2_subdev_state_get_format(sd_state, SRU_PAD_SINK);
                fmt->code = format->code;
 
+               fmt->colorspace = format->colorspace;
+               fmt->xfer_func = format->xfer_func;
+               fmt->ycbcr_enc = format->ycbcr_enc;
+               fmt->quantization = format->quantization;
+
                /*
                 * We can upscale by 2 in both direction, but not independently.
                 * Compare the input and output rectangles areas (avoiding
@@ -211,7 +219,6 @@ static void sru_try_format(struct vsp1_sru *sru,
        }
 
        fmt->field = V4L2_FIELD_NONE;
-       fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
 static int sru_set_format(struct v4l2_subdev *subdev,
index c5a38478cf8c0959957e73daf638f46a5f94a761..2db473b6f83c17baf7e36ac8ec84a0bb1a05bfc2 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "vsp1.h"
 #include "vsp1_dl.h"
+#include "vsp1_entity.h"
 #include "vsp1_pipe.h"
 #include "vsp1_uds.h"
 
@@ -177,6 +178,8 @@ static void uds_try_format(struct vsp1_uds *uds,
                    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
                        fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
 
+               vsp1_entity_adjust_color_space(fmt);
+
                fmt->width = clamp(fmt->width, UDS_MIN_SIZE, UDS_MAX_SIZE);
                fmt->height = clamp(fmt->height, UDS_MIN_SIZE, UDS_MAX_SIZE);
                break;
@@ -186,6 +189,11 @@ static void uds_try_format(struct vsp1_uds *uds,
                format = v4l2_subdev_state_get_format(sd_state, UDS_PAD_SINK);
                fmt->code = format->code;
 
+               fmt->colorspace = format->colorspace;
+               fmt->xfer_func = format->xfer_func;
+               fmt->ycbcr_enc = format->ycbcr_enc;
+               fmt->quantization = format->quantization;
+
                uds_output_limits(format->width, &minimum, &maximum);
                fmt->width = clamp(fmt->width, minimum, maximum);
                uds_output_limits(format->height, &minimum, &maximum);
@@ -194,7 +202,6 @@ static void uds_try_format(struct vsp1_uds *uds,
        }
 
        fmt->field = V4L2_FIELD_NONE;
-       fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
 static int uds_set_format(struct v4l2_subdev *subdev,
index da578993f4720a94186cac1a078de65738a04b62..68d495c20a844422a0d68aaf6b797c8a625131f8 100644 (file)
@@ -127,12 +127,10 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
                info = vsp1_get_format_info(video->vsp1, VSP1_VIDEO_DEF_FORMAT);
 
        pix->pixelformat = info->fourcc;
-       pix->colorspace = V4L2_COLORSPACE_SRGB;
        pix->field = V4L2_FIELD_NONE;
 
-       if (info->fourcc == V4L2_PIX_FMT_HSV24 ||
-           info->fourcc == V4L2_PIX_FMT_HSV32)
-               pix->hsv_enc = V4L2_HSV_ENC_256;
+       vsp1_adjust_color_space(info->mbus, &pix->colorspace, &pix->xfer_func,
+                               &pix->ycbcr_enc, &pix->quantization);
 
        memset(pix->reserved, 0, sizeof(pix->reserved));
 
@@ -891,7 +889,6 @@ vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
                          | V4L2_CAP_IO_MC | V4L2_CAP_VIDEO_CAPTURE_MPLANE
                          | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
 
-
        strscpy(cap->driver, "vsp1", sizeof(cap->driver));
        strscpy(cap->card, video->video.name, sizeof(cap->card));