Skip to content

Commit ea02b93

Browse files
ngphibangnashif
authored andcommitted
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: Phi Bang Nguyen <[email protected]>
1 parent e3ad40f commit ea02b93

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

drivers/video/video_mcux_csi.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ static inline unsigned int video_pix_fmt_bpp(uint32_t pixelformat)
4444
case VIDEO_PIX_FMT_RGB565:
4545
case VIDEO_PIX_FMT_YUYV:
4646
return 2;
47+
case VIDEO_PIX_FMT_XRGB32:
48+
case VIDEO_PIX_FMT_XYUV32:
49+
return 4;
4750
default:
4851
return 0;
4952
}
@@ -113,23 +116,62 @@ static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, status_t statu
113116
return;
114117
}
115118

119+
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
120+
K_HEAP_DEFINE(csi_heap, 1000);
121+
static struct video_format_cap *fmts;
122+
/*
123+
* On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor after passing
124+
* through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be implicitly converted to a
125+
* 32-bits pixel format. For example, an input in RGB565 or YUYV (2-bytes format) will become a
126+
* XRGB32 or XYUV32 (4-bytes format) respectively, at the output of the CSI.
127+
*/
128+
static inline void video_pix_fmt_convert(struct video_format *fmt, bool isGetFmt)
129+
{
130+
switch (fmt->pixelformat) {
131+
case VIDEO_PIX_FMT_XRGB32:
132+
fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565;
133+
break;
134+
case VIDEO_PIX_FMT_XYUV32:
135+
fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV;
136+
break;
137+
case VIDEO_PIX_FMT_RGB565:
138+
fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565;
139+
break;
140+
case VIDEO_PIX_FMT_YUYV:
141+
fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV;
142+
break;
143+
}
144+
145+
fmt->pitch = fmt->width * video_pix_fmt_bpp(fmt->pixelformat);
146+
}
147+
#endif
148+
116149
static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_id ep,
117150
struct video_format *fmt)
118151
{
119152
const struct video_mcux_csi_config *config = dev->config;
120153
struct video_mcux_csi_data *data = dev->data;
121154
unsigned int bpp = video_pix_fmt_bpp(fmt->pixelformat);
122155
status_t ret;
156+
struct video_format format = *fmt;
123157

124158
if (!bpp || ep != VIDEO_EP_OUT) {
125159
return -EINVAL;
126160
}
127161

128162
data->csi_config.bytesPerPixel = bpp;
129163
data->csi_config.linePitch_Bytes = fmt->pitch;
164+
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
165+
if (fmt->pixelformat != VIDEO_PIX_FMT_XRGB32 && fmt->pixelformat != VIDEO_PIX_FMT_XYUV32) {
166+
return -ENOTSUP;
167+
}
168+
video_pix_fmt_convert(&format, false);
169+
data->csi_config.dataBus = kCSI_DataBus24Bit;
170+
#else
171+
data->csi_config.dataBus = kCSI_DataBus8Bit;
172+
#endif
130173
data->csi_config.polarityFlags = kCSI_HsyncActiveHigh | kCSI_DataLatchOnRisingEdge;
131174
data->csi_config.workMode = kCSI_GatedClockMode; /* use VSYNC, HSYNC, and PIXCLK */
132-
data->csi_config.dataBus = kCSI_DataBus8Bit;
133175
data->csi_config.useExtVsync = true;
134176
data->csi_config.height = fmt->height;
135177
data->csi_config.width = fmt->width;
@@ -144,7 +186,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_
144186
return -EIO;
145187
}
146188

147-
if (config->source_dev && video_set_format(config->source_dev, ep, fmt)) {
189+
if (config->source_dev && video_set_format(config->source_dev, ep, &format)) {
148190
return -EIO;
149191
}
150192

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

163205
if (config->source_dev && !video_get_format(config->source_dev, ep, fmt)) {
206+
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
207+
video_pix_fmt_convert(fmt, true);
208+
#endif
164209
/* align CSI with source fmt */
165210
return video_mcux_csi_set_fmt(dev, ep, fmt);
166211
}
@@ -317,6 +362,34 @@ static int video_mcux_csi_get_caps(const struct device *dev, enum video_endpoint
317362
/* Just forward to source dev for now */
318363
if (config->source_dev) {
319364
err = video_get_caps(config->source_dev, ep, caps);
365+
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
366+
/*
367+
* On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor
368+
* after passing through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be
369+
* implicitly converted to a 32-bits pixel format. For example, an input in RGB565
370+
* or YUYV (2-bytes format) will become an XRGB32 or XYUV32 (4-bytes format)
371+
* respectively, at the output of the CSI. So, we change the pixel formats of the
372+
* source caps to reflect this.
373+
*/
374+
int ind = 0;
375+
376+
while (caps->format_caps[ind].pixelformat) {
377+
ind++;
378+
}
379+
k_heap_free(&csi_heap, fmts);
380+
fmts = k_heap_alloc(&csi_heap, (ind + 1) * sizeof(struct video_format_cap),
381+
K_FOREVER);
382+
383+
for (int i = 0; i <= ind; i++) {
384+
memcpy(&fmts[i], &caps->format_caps[i], sizeof(fmts[i]));
385+
if (fmts[i].pixelformat == VIDEO_PIX_FMT_RGB565) {
386+
fmts[i].pixelformat = VIDEO_PIX_FMT_XRGB32;
387+
} else if (fmts[i].pixelformat == VIDEO_PIX_FMT_YUYV) {
388+
fmts[i].pixelformat = VIDEO_PIX_FMT_XYUV32;
389+
}
390+
}
391+
caps->format_caps = fmts;
392+
#endif
320393
}
321394

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

0 commit comments

Comments
 (0)