mirror of
https://github.com/torvalds/linux.git
synced 2026-06-05 13:06:59 +02:00
media: renesas: vsp1: Allow setting encoding and quantization
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>
This commit is contained in:
parent
d5e3bc24d5
commit
e6c9597e5f
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user