media: renesas: vsp1: Report colour space information to userspace

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>
This commit is contained in:
Laurent Pinchart 2025-04-30 02:29:00 +03:00 committed by Hans Verkuil
parent b6e57605ef
commit d5e3bc24d5
10 changed files with 115 additions and 11 deletions

View 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,

View 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;

View 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,

View 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;

View 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
*/

View 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__ */

View 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;

View 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,

View 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,

View 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));