Commit ea02b93e authored by Phi Bang Nguyen's avatar Phi Bang Nguyen Committed by Anas Nashif
Browse files

drivers: video: csi: Add support for i.MX RT11XX



On i.MX RT11XX which has MIPI CSI-2 Rx, image data from the camera sensor
after passing through the camera pipeline (MIPI CSI-2 Rx --> Video Mux -->
CSI) will be implicitly converted to a 32-bits pixel formats. For example,
an input in RGB565 / YUYV (2-bytes format) will become an XRGB32 / XYUV32
(4-bytes format), respectively. Make changes to support this.

Signed-off-by: default avatarPhi Bang Nguyen <phibang.nguyen@nxp.com>
parent e3ad40f8
Loading
Loading
Loading
Loading
+75 −2
Original line number Diff line number Diff line
@@ -44,6 +44,9 @@ static inline unsigned int video_pix_fmt_bpp(uint32_t pixelformat)
	case VIDEO_PIX_FMT_RGB565:
	case VIDEO_PIX_FMT_YUYV:
		return 2;
	case VIDEO_PIX_FMT_XRGB32:
	case VIDEO_PIX_FMT_XYUV32:
		return 4;
	default:
		return 0;
	}
@@ -113,6 +116,36 @@ done:
	return;
}

#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
K_HEAP_DEFINE(csi_heap, 1000);
static struct video_format_cap *fmts;
/*
 * On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor after passing
 * through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be implicitly converted to a
 * 32-bits pixel format. For example, an input in RGB565 or YUYV (2-bytes format) will become a
 * XRGB32 or XYUV32 (4-bytes format) respectively, at the output of the CSI.
 */
static inline void video_pix_fmt_convert(struct video_format *fmt, bool isGetFmt)
{
	switch (fmt->pixelformat) {
	case VIDEO_PIX_FMT_XRGB32:
		fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565;
		break;
	case VIDEO_PIX_FMT_XYUV32:
		fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV;
		break;
	case VIDEO_PIX_FMT_RGB565:
		fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565;
		break;
	case VIDEO_PIX_FMT_YUYV:
		fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV;
		break;
	}

	fmt->pitch = fmt->width * video_pix_fmt_bpp(fmt->pixelformat);
}
#endif

static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_id ep,
				  struct video_format *fmt)
{
@@ -120,6 +153,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_
	struct video_mcux_csi_data *data = dev->data;
	unsigned int bpp = video_pix_fmt_bpp(fmt->pixelformat);
	status_t ret;
	struct video_format format = *fmt;

	if (!bpp || ep != VIDEO_EP_OUT) {
		return -EINVAL;
@@ -127,9 +161,17 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_

	data->csi_config.bytesPerPixel = bpp;
	data->csi_config.linePitch_Bytes = fmt->pitch;
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
	if (fmt->pixelformat != VIDEO_PIX_FMT_XRGB32 && fmt->pixelformat != VIDEO_PIX_FMT_XYUV32) {
		return -ENOTSUP;
	}
	video_pix_fmt_convert(&format, false);
	data->csi_config.dataBus = kCSI_DataBus24Bit;
#else
	data->csi_config.dataBus = kCSI_DataBus8Bit;
#endif
	data->csi_config.polarityFlags = kCSI_HsyncActiveHigh | kCSI_DataLatchOnRisingEdge;
	data->csi_config.workMode = kCSI_GatedClockMode; /* use VSYNC, HSYNC, and PIXCLK */
	data->csi_config.dataBus = kCSI_DataBus8Bit;
	data->csi_config.useExtVsync = true;
	data->csi_config.height = fmt->height;
	data->csi_config.width = fmt->width;
@@ -144,7 +186,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_
		return -EIO;
	}

	if (config->source_dev && video_set_format(config->source_dev, ep, fmt)) {
	if (config->source_dev && video_set_format(config->source_dev, ep, &format)) {
		return -EIO;
	}

@@ -161,6 +203,9 @@ static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_
	}

	if (config->source_dev && !video_get_format(config->source_dev, ep, fmt)) {
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
		video_pix_fmt_convert(fmt, true);
#endif
		/* align CSI with source fmt */
		return video_mcux_csi_set_fmt(dev, ep, fmt);
	}
@@ -317,6 +362,34 @@ static int video_mcux_csi_get_caps(const struct device *dev, enum video_endpoint
	/* Just forward to source dev for now */
	if (config->source_dev) {
		err = video_get_caps(config->source_dev, ep, caps);
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
		/*
		 * On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor
		 * after passing through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be
		 * implicitly converted to a 32-bits pixel format. For example, an input in RGB565
		 * or YUYV (2-bytes format) will become an XRGB32 or XYUV32 (4-bytes format)
		 * respectively, at the output of the CSI. So, we change the pixel formats of the
		 * source caps to reflect this.
		 */
		int ind = 0;

		while (caps->format_caps[ind].pixelformat) {
			ind++;
		}
		k_heap_free(&csi_heap, fmts);
		fmts = k_heap_alloc(&csi_heap, (ind + 1) * sizeof(struct video_format_cap),
				    K_FOREVER);

		for (int i = 0; i <= ind; i++) {
			memcpy(&fmts[i], &caps->format_caps[i], sizeof(fmts[i]));
			if (fmts[i].pixelformat == VIDEO_PIX_FMT_RGB565) {
				fmts[i].pixelformat = VIDEO_PIX_FMT_XRGB32;
			} else if (fmts[i].pixelformat == VIDEO_PIX_FMT_YUYV) {
				fmts[i].pixelformat = VIDEO_PIX_FMT_XYUV32;
			}
		}
		caps->format_caps = fmts;
#endif
	}

	/* NXP MCUX CSI request at least 2 buffer before starting */