Commit 907122f5 authored by Daniel Scally's avatar Daniel Scally Committed by Hans Verkuil
Browse files

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: default avatarLad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarDaniel Scally <dan.scally+renesas@ideasonboard.com>
Link: https://lore.kernel.org/r/20250630150651.2698237-1-dan.scally@ideasonboard.com


Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
parent ace92cce
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -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);
+53 −14
Original line number Diff line number Diff line
@@ -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)
	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,13 +207,28 @@ 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;

	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;

	code->code = rzg2l_cru_ip_formats[code->index].code;
			if (!index) {
				code->code = fmt->codes[j];
				return 0;
			}

			index--;
		}
	}

	return -EINVAL;
}

static int rzg2l_cru_ip_enum_frame_size(struct v4l2_subdev *sd,
					struct v4l2_subdev_state *state,
					struct v4l2_subdev_frame_size_enum *fse)
+1 −1
Original line number Diff line number Diff line
@@ -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;