media: rzg2l-cru: Support multiple mbus codes per pixel format

As a preliminary step for supporting the CRU pixel formats, extend
the driver such that multiple media bus codes can support each of
the output pixel formats.

Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Daniel Scally <dan.scally+renesas@ideasonboard.com>
Link: https://lore.kernel.org/r/20250630150651.2698237-1-dan.scally@ideasonboard.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
This commit is contained in:
Daniel Scally 2025-06-30 16:06:51 +01:00 committed by Hans Verkuil
parent ace92ccef0
commit 907122f552
3 changed files with 62 additions and 17 deletions

View File

@ -64,14 +64,18 @@ struct rzg2l_cru_ip {
/**
* struct rzg2l_cru_ip_format - CRU IP format
* @code: Media bus code
* @codes: Array of up to four media bus codes
* @datatype: MIPI CSI2 data type
* @format: 4CC format identifier (V4L2_PIX_FMT_*)
* @icndmr: ICnDMR register value
* @yuv: Flag to indicate whether the format is YUV-based.
*/
struct rzg2l_cru_ip_format {
u32 code;
/*
* RAW output formats might be produced by RAW media codes with any one
* of the 4 common bayer patterns.
*/
u32 codes[4];
u32 datatype;
u32 format;
u32 icndmr;
@ -190,6 +194,8 @@ struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru);
const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code);
const struct rzg2l_cru_ip_format *rzg2l_cru_ip_format_to_fmt(u32 format);
const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index);
bool rzg2l_cru_ip_fmt_supports_mbus_code(const struct rzg2l_cru_ip_format *fmt,
unsigned int code);
void rzg2l_cru_enable_interrupts(struct rzg2l_cru_dev *cru);
void rzg2l_cru_disable_interrupts(struct rzg2l_cru_dev *cru);

View File

@ -13,35 +13,45 @@
static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = {
{
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.codes = {
MEDIA_BUS_FMT_UYVY8_1X16,
},
.datatype = MIPI_CSI2_DT_YUV422_8B,
.format = V4L2_PIX_FMT_UYVY,
.icndmr = ICnDMR_YCMODE_UYVY,
.yuv = true,
},
{
.code = MEDIA_BUS_FMT_SBGGR8_1X8,
.codes = {
MEDIA_BUS_FMT_SBGGR8_1X8,
},
.format = V4L2_PIX_FMT_SBGGR8,
.datatype = MIPI_CSI2_DT_RAW8,
.icndmr = 0,
.yuv = false,
},
{
.code = MEDIA_BUS_FMT_SGBRG8_1X8,
.codes = {
MEDIA_BUS_FMT_SGBRG8_1X8,
},
.format = V4L2_PIX_FMT_SGBRG8,
.datatype = MIPI_CSI2_DT_RAW8,
.icndmr = 0,
.yuv = false,
},
{
.code = MEDIA_BUS_FMT_SGRBG8_1X8,
.codes = {
MEDIA_BUS_FMT_SGRBG8_1X8,
},
.format = V4L2_PIX_FMT_SGRBG8,
.datatype = MIPI_CSI2_DT_RAW8,
.icndmr = 0,
.yuv = false,
},
{
.code = MEDIA_BUS_FMT_SRGGB8_1X8,
.codes = {
MEDIA_BUS_FMT_SRGGB8_1X8,
},
.format = V4L2_PIX_FMT_SRGGB8,
.datatype = MIPI_CSI2_DT_RAW8,
.icndmr = 0,
@ -51,11 +61,14 @@ static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = {
const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code)
{
unsigned int i;
unsigned int i, j;
for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++)
if (rzg2l_cru_ip_formats[i].code == code)
return &rzg2l_cru_ip_formats[i];
for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) {
for (j = 0; j < ARRAY_SIZE(rzg2l_cru_ip_formats[i].codes); j++) {
if (rzg2l_cru_ip_formats[i].codes[j] == code)
return &rzg2l_cru_ip_formats[i];
}
}
return NULL;
}
@ -80,6 +93,17 @@ const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index)
return &rzg2l_cru_ip_formats[index];
}
bool rzg2l_cru_ip_fmt_supports_mbus_code(const struct rzg2l_cru_ip_format *fmt,
unsigned int code)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(fmt->codes); i++)
if (fmt->codes[i] == code)
return true;
return false;
}
struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
{
struct v4l2_subdev_state *state;
@ -157,7 +181,7 @@ static int rzg2l_cru_ip_set_format(struct v4l2_subdev *sd,
sink_format = v4l2_subdev_state_get_format(state, fmt->pad);
if (!rzg2l_cru_ip_code_to_fmt(fmt->format.code))
sink_format->code = rzg2l_cru_ip_formats[0].code;
sink_format->code = rzg2l_cru_ip_formats[0].codes[0];
else
sink_format->code = fmt->format.code;
@ -183,11 +207,26 @@ static int rzg2l_cru_ip_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= ARRAY_SIZE(rzg2l_cru_ip_formats))
return -EINVAL;
unsigned int index = code->index;
unsigned int i, j;
code->code = rzg2l_cru_ip_formats[code->index].code;
return 0;
for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) {
const struct rzg2l_cru_ip_format *fmt = &rzg2l_cru_ip_formats[i];
for (j = 0; j < ARRAY_SIZE(fmt->codes); j++) {
if (!fmt->codes[j])
continue;
if (!index) {
code->code = fmt->codes[j];
return 0;
}
index--;
}
}
return -EINVAL;
}
static int rzg2l_cru_ip_enum_frame_size(struct v4l2_subdev *sd,

View File

@ -1145,7 +1145,7 @@ static int rzg2l_cru_video_link_validate(struct media_link *link)
if (fmt.format.width != cru->format.width ||
fmt.format.height != cru->format.height ||
fmt.format.field != cru->format.field ||
video_fmt->code != fmt.format.code)
!rzg2l_cru_ip_fmt_supports_mbus_code(video_fmt, fmt.format.code))
return -EPIPE;
return 0;