[PATCH v2 6/9] media: renesas: vsp1: Allow setting encoding and quantization
Tomi Valkeinen
tomi.valkeinen at ideasonboard.com
Wed Apr 30 11:07:31 UTC 2025
Hi,
On 30/04/2025 02:29, Laurent Pinchart wrote:
> 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 at ideasonboard.com>
> ---
> .../media/platform/renesas/vsp1/vsp1_pipe.c | 29 +++++++++++------
> .../media/platform/renesas/vsp1/vsp1_rpf.c | 29 +++++++++++++++--
> .../media/platform/renesas/vsp1/vsp1_rwpf.c | 31 +++++++++++++++++--
> .../media/platform/renesas/vsp1/vsp1_video.c | 19 ++++++++++++
> .../media/platform/renesas/vsp1/vsp1_wpf.c | 29 +++++++++++++++--
> 5 files changed, 121 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c
> index b9ab6c9c96df..59e26284a90f 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c
> @@ -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;
> }
> }
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_rpf.c b/drivers/media/platform/renesas/vsp1/vsp1_rpf.c
> index 5c8b3ba1bd3c..9f2744af54bc 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_rpf.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_rpf.c
> @@ -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);
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c b/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
> index 4e8bcf6a59ad..9c8085d5d306 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
> @@ -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;
> }
>
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c
> index 68d495c20a84..bc66fbdde3cc 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c
> @@ -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;
> }
>
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_wpf.c b/drivers/media/platform/renesas/vsp1/vsp1_wpf.c
> index f176750ccd98..49af637c8186 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_wpf.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_wpf.c
> @@ -279,8 +279,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;
>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen+renesas at ideasonboard.com>
Tomi
More information about the dri-devel
mailing list