1 From c54b8d2fc79c684deacc81a94f6baa1cb56c62be Mon Sep 17 00:00:00 2001
2 From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
3 Date: Wed, 27 Sep 2023 17:18:09 +0300
4 Subject: [PATCH] media: rp1: cfe: Dual purpose video nodes
6 The RP1 CSI-2 DMA can capture both video and metadata just fine, but at
7 the moment the video nodes are only set to support either video or
10 Make the changes to support both video and metadata. This mostly means
11 tracking both video format and metadata format separately for each video
12 node, and using vb2_queue_change_type() to change the vb2 queue type
15 Briefly, this means that the user can get/set both video and meta
16 formats to a single video node. The vb2 queue buffer type will be
17 changed when the user calls REQBUFS or CREATE_BUFS ioctls. This buffer
18 type will be then used as the "mode" for the video node when the user
19 starts the streaming, and based on that either the video or the meta
22 A bunch of macros are added (node_supports_xxx()), which tell if a node
23 can support a particular mode, whereas the existing macros
24 (is_xxx_node()) will tell if the node is currently in a particular mode.
25 Note that the latter will only work correctly between the start of the
26 streaming and the end of the streaming, and thus should be only used in
29 However, as the userspace (libcamera) does not support dual purpose
30 video nodes, for the time being let's keep the second video node as
31 V4L2_CAP_META_CAPTURE only to keep the userspace working.
33 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
35 .../media/platform/raspberrypi/rp1_cfe/cfe.c | 271 ++++++++++++------
36 1 file changed, 182 insertions(+), 89 deletions(-)
38 --- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c
39 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c
40 @@ -116,7 +116,7 @@ const struct v4l2_mbus_framefmt cfe_defa
42 /* CSI2 HW output nodes first. */
48 /* FE only nodes from here on. */
49 @@ -130,8 +130,7 @@ enum node_ids {
50 struct node_description {
53 - enum v4l2_buf_type buf_type;
56 unsigned int pad_flags;
57 unsigned int link_pad;
59 @@ -140,58 +139,55 @@ struct node_description {
60 static const struct node_description node_desc[NUM_NODES] = {
63 - .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
64 - .cap = V4L2_CAP_VIDEO_CAPTURE,
65 + .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE,
66 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
67 .link_pad = CSI2_NUM_CHANNELS + 0
69 - /* This node is assigned for the embedded data channel! */
70 - [CSI2_CH1_EMBEDDED] = {
72 + * TODO: This node should be named "csi2_ch1" and the caps should be set
73 + * to both video and meta capture. However, to keep compatibility with
74 + * the current libcamera, keep the name as "embedded" and support
75 + * only meta capture.
79 - .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
80 - .cap = V4L2_CAP_META_CAPTURE,
81 + .caps = V4L2_CAP_META_CAPTURE,
82 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
83 .link_pad = CSI2_NUM_CHANNELS + 1
87 - .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
88 - .cap = V4L2_CAP_META_CAPTURE,
89 + .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE,
90 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
91 .link_pad = CSI2_NUM_CHANNELS + 2
95 - .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
96 - .cap = V4L2_CAP_META_CAPTURE,
97 + .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE,
98 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
99 .link_pad = CSI2_NUM_CHANNELS + 3
103 - .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
104 - .cap = V4L2_CAP_VIDEO_CAPTURE,
105 + .caps = V4L2_CAP_VIDEO_CAPTURE,
106 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
107 .link_pad = FE_OUTPUT0_PAD
111 - .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
112 - .cap = V4L2_CAP_VIDEO_CAPTURE,
113 + .caps = V4L2_CAP_VIDEO_CAPTURE,
114 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
115 .link_pad = FE_OUTPUT1_PAD
119 - .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
120 - .cap = V4L2_CAP_META_CAPTURE,
121 + .caps = V4L2_CAP_META_CAPTURE,
122 .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
123 .link_pad = FE_STATS_PAD
127 - .buf_type = V4L2_BUF_TYPE_META_OUTPUT,
128 - .cap = V4L2_CAP_META_OUTPUT,
129 + .caps = V4L2_CAP_META_OUTPUT,
130 .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT,
131 .link_pad = FE_CONFIG_PAD
133 @@ -200,17 +196,29 @@ static const struct node_description nod
134 #define is_fe_node(node) (((node)->id) >= FE_OUT0)
135 #define is_csi2_node(node) (!is_fe_node(node))
137 +#define node_supports_image_output(node) \
138 + (!!(node_desc[(node)->id].caps & V4L2_CAP_VIDEO_CAPTURE))
139 +#define node_supports_meta_output(node) \
140 + (!!(node_desc[(node)->id].caps & V4L2_CAP_META_CAPTURE))
141 +#define node_supports_image_input(node) \
142 + (!!(node_desc[(node)->id].caps & V4L2_CAP_VIDEO_OUTPUT))
143 +#define node_supports_meta_input(node) \
144 + (!!(node_desc[(node)->id].caps & V4L2_CAP_META_OUTPUT))
145 +#define node_supports_image(node) \
146 + (node_supports_image_output(node) || node_supports_image_input(node))
147 +#define node_supports_meta(node) \
148 + (node_supports_meta_output(node) || node_supports_meta_input(node))
150 #define is_image_output_node(node) \
151 - (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
152 + ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
153 #define is_image_input_node(node) \
154 - (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
155 + ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
156 #define is_image_node(node) \
157 (is_image_output_node(node) || is_image_input_node(node))
159 #define is_meta_output_node(node) \
160 - (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE)
161 + ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_CAPTURE)
162 #define is_meta_input_node(node) \
163 - (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT)
164 + ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_OUTPUT)
165 #define is_meta_node(node) \
166 (is_meta_output_node(node) || is_meta_input_node(node))
168 @@ -250,7 +258,9 @@ struct cfe_node {
169 /* Pointer pointing to next v4l2_buffer */
170 struct cfe_buffer *next_frm;
171 /* Used to store current pixel format */
172 - struct v4l2_format fmt;
173 + struct v4l2_format vid_fmt;
174 + /* Used to store current meta format */
175 + struct v4l2_format meta_fmt;
176 /* Buffer queue used in video-buf */
177 struct vb2_queue buffer_queue;
178 /* Queue of filled frames */
179 @@ -433,20 +443,21 @@ static int format_show(struct seq_file *
180 seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i,
181 node_desc[i].name, state);
183 - if (is_image_node(node))
184 + if (node_supports_image(node))
185 seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n"
186 "resolution: %ux%u\nbpl: %u\nsize: %u\n",
187 - V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat),
188 - node->fmt.fmt.pix.pixelformat,
189 - node->fmt.fmt.pix.width,
190 - node->fmt.fmt.pix.height,
191 - node->fmt.fmt.pix.bytesperline,
192 - node->fmt.fmt.pix.sizeimage);
194 + V4L2_FOURCC_CONV_ARGS(node->vid_fmt.fmt.pix.pixelformat),
195 + node->vid_fmt.fmt.pix.pixelformat,
196 + node->vid_fmt.fmt.pix.width,
197 + node->vid_fmt.fmt.pix.height,
198 + node->vid_fmt.fmt.pix.bytesperline,
199 + node->vid_fmt.fmt.pix.sizeimage);
201 + if (node_supports_meta(node))
202 seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\nsize: %u\n",
203 - V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat),
204 - node->fmt.fmt.meta.dataformat,
205 - node->fmt.fmt.meta.buffersize);
206 + V4L2_FOURCC_CONV_ARGS(node->meta_fmt.fmt.meta.dataformat),
207 + node->meta_fmt.fmt.meta.dataformat,
208 + node->meta_fmt.fmt.meta.buffersize);
212 @@ -571,11 +582,11 @@ static void cfe_schedule_next_csi2_job(s
213 node_desc[node->id].name, &buf->vb.vb2_buf);
215 if (is_meta_node(node)) {
216 - size = node->fmt.fmt.meta.buffersize;
217 + size = node->meta_fmt.fmt.meta.buffersize;
220 - size = node->fmt.fmt.pix.sizeimage;
221 - stride = node->fmt.fmt.pix.bytesperline;
222 + size = node->vid_fmt.fmt.pix.sizeimage;
223 + stride = node->vid_fmt.fmt.pix.bytesperline;
226 addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
227 @@ -867,10 +878,10 @@ static void cfe_start_channel(struct cfe
228 width = source_fmt->width;
229 height = source_fmt->height;
231 - if (node->fmt.fmt.pix.pixelformat ==
232 + if (node->vid_fmt.fmt.pix.pixelformat ==
233 fmt->remap[CFE_REMAP_16BIT])
234 mode = CSI2_MODE_REMAP;
235 - else if (node->fmt.fmt.pix.pixelformat ==
236 + else if (node->vid_fmt.fmt.pix.pixelformat ==
237 fmt->remap[CFE_REMAP_COMPRESSED]) {
238 mode = CSI2_MODE_COMPRESSED;
239 csi2_set_compression(&cfe->csi2, node->id,
240 @@ -884,7 +895,7 @@ static void cfe_start_channel(struct cfe
244 - node->id == CSI2_CH1_EMBEDDED ? true : false,
245 + is_meta_node(node) ? true : false,
249 @@ -947,10 +958,11 @@ static int cfe_queue_setup(struct vb2_qu
251 struct cfe_node *node = vb2_get_drv_priv(vq);
252 struct cfe_device *cfe = node->cfe;
253 - unsigned int size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage :
254 - node->fmt.fmt.meta.buffersize;
255 + unsigned int size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage :
256 + node->meta_fmt.fmt.meta.buffersize;
258 - cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
259 + cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name,
260 + node->buffer_queue.type);
262 if (vq->num_buffers + *nbuffers < 3)
263 *nbuffers = 3 - vq->num_buffers;
264 @@ -979,8 +991,8 @@ static int cfe_buffer_prepare(struct vb2
265 cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__,
266 node_desc[node->id].name, vb);
268 - size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage :
269 - node->fmt.fmt.meta.buffersize;
270 + size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage :
271 + node->meta_fmt.fmt.meta.buffersize;
272 if (vb2_plane_size(vb, 0) < size) {
273 cfe_err("data will not fit into plane (%lu < %lu)\n",
274 vb2_plane_size(vb, 0), size);
275 @@ -995,8 +1007,8 @@ static int cfe_buffer_prepare(struct vb2
277 memcpy(&b->config, addr, sizeof(struct pisp_fe_config));
278 return pisp_fe_validate_config(&cfe->fe, &b->config,
279 - &cfe->node[FE_OUT0].fmt,
280 - &cfe->node[FE_OUT1].fmt);
281 + &cfe->node[FE_OUT0].vid_fmt,
282 + &cfe->node[FE_OUT1].vid_fmt);
286 @@ -1256,7 +1268,7 @@ static int cfe_enum_fmt_vid_cap(struct f
287 struct cfe_device *cfe = node->cfe;
290 - if (!is_image_output_node(node))
291 + if (!node_supports_image_output(node))
294 cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
295 @@ -1292,10 +1304,10 @@ static int cfe_g_fmt(struct file *file,
297 cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
299 - if (f->type != node->buffer_queue.type)
300 + if (!node_supports_image(node))
304 + *f = node->vid_fmt;
308 @@ -1310,7 +1322,7 @@ static int try_fmt_vid_cap(struct cfe_no
309 f->fmt.pix.width, f->fmt.pix.height,
310 V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat));
312 - if (!is_image_output_node(node))
313 + if (!node_supports_image_output(node))
317 @@ -1351,11 +1363,11 @@ static int cfe_s_fmt_vid_cap(struct file
322 + node->vid_fmt = *f;
324 cfe_dbg("%s: Set %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", __func__,
325 - node->fmt.fmt.pix.width, node->fmt.fmt.pix.height,
326 - V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat));
327 + node->vid_fmt.fmt.pix.width, node->vid_fmt.fmt.pix.height,
328 + V4L2_FOURCC_CONV_ARGS(node->vid_fmt.fmt.pix.pixelformat));
332 @@ -1379,11 +1391,11 @@ static int cfe_enum_fmt_meta(struct file
334 cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
336 - if (!is_meta_node(node) || f->index != 0)
337 + if (!node_supports_meta(node) || f->index != 0)
341 - case CSI2_CH1_EMBEDDED:
342 + case CSI2_CH0...CSI2_CH3:
343 f->pixelformat = V4L2_META_FMT_SENSOR_DATA;
346 @@ -1399,8 +1411,11 @@ static int cfe_enum_fmt_meta(struct file
348 static int try_fmt_meta(struct cfe_node *node, struct v4l2_format *f)
350 + if (!node_supports_meta(node))
354 - case CSI2_CH1_EMBEDDED:
355 + case CSI2_CH0...CSI2_CH3:
356 f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA;
357 if (!f->fmt.meta.buffersize)
358 f->fmt.meta.buffersize = DEFAULT_EMBEDDED_SIZE;
359 @@ -1422,6 +1437,21 @@ static int try_fmt_meta(struct cfe_node
363 +static int cfe_g_fmt_meta(struct file *file, void *priv, struct v4l2_format *f)
365 + struct cfe_node *node = video_drvdata(file);
366 + struct cfe_device *cfe = node->cfe;
368 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
370 + if (!node_supports_meta(node))
373 + *f = node->meta_fmt;
378 static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f)
380 struct cfe_node *node = video_drvdata(file);
381 @@ -1434,17 +1464,17 @@ static int cfe_s_fmt_meta(struct file *f
385 - if (f->type != node->buffer_queue.type)
386 + if (!node_supports_meta(node))
389 ret = try_fmt_meta(node, f);
394 + node->meta_fmt = *f;
396 cfe_dbg("%s: Set " V4L2_FOURCC_CONV "\n", __func__,
397 - V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat));
398 + V4L2_FOURCC_CONV_ARGS(node->meta_fmt.fmt.meta.dataformat));
402 @@ -1491,6 +1521,52 @@ static int cfe_enum_framesizes(struct fi
406 +static int cfe_vb2_ioctl_reqbufs(struct file *file, void *priv,
407 + struct v4l2_requestbuffers *p)
409 + struct video_device *vdev = video_devdata(file);
410 + struct cfe_node *node = video_get_drvdata(vdev);
411 + struct cfe_device *cfe = node->cfe;
414 + cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name,
417 + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
418 + p->type != V4L2_BUF_TYPE_META_CAPTURE &&
419 + p->type != V4L2_BUF_TYPE_META_OUTPUT)
422 + ret = vb2_queue_change_type(vdev->queue, p->type);
426 + return vb2_ioctl_reqbufs(file, priv, p);
429 +static int cfe_vb2_ioctl_create_bufs(struct file *file, void *priv,
430 + struct v4l2_create_buffers *p)
432 + struct video_device *vdev = video_devdata(file);
433 + struct cfe_node *node = video_get_drvdata(vdev);
434 + struct cfe_device *cfe = node->cfe;
437 + cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name,
440 + if (p->format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
441 + p->format.type != V4L2_BUF_TYPE_META_CAPTURE &&
442 + p->format.type != V4L2_BUF_TYPE_META_OUTPUT)
445 + ret = vb2_queue_change_type(vdev->queue, p->format.type);
449 + return vb2_ioctl_create_bufs(file, priv, p);
452 static int cfe_subscribe_event(struct v4l2_fh *fh,
453 const struct v4l2_event_subscription *sub)
455 @@ -1498,12 +1574,13 @@ static int cfe_subscribe_event(struct v4
458 case V4L2_EVENT_FRAME_SYNC:
459 - if (!is_image_output_node(node))
460 + if (!node_supports_image_output(node))
463 return v4l2_event_subscribe(fh, sub, 2, NULL);
464 case V4L2_EVENT_SOURCE_CHANGE:
465 - if (is_meta_input_node(node))
466 + if (!node_supports_image_output(node) &&
467 + !node_supports_meta_output(node))
470 return v4l2_event_subscribe(fh, sub, 4, NULL);
471 @@ -1520,19 +1597,19 @@ static const struct v4l2_ioctl_ops cfe_i
472 .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap,
474 .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta,
475 - .vidioc_g_fmt_meta_cap = cfe_g_fmt,
476 + .vidioc_g_fmt_meta_cap = cfe_g_fmt_meta,
477 .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta,
478 .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta,
480 .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta,
481 - .vidioc_g_fmt_meta_out = cfe_g_fmt,
482 + .vidioc_g_fmt_meta_out = cfe_g_fmt_meta,
483 .vidioc_s_fmt_meta_out = cfe_s_fmt_meta,
484 .vidioc_try_fmt_meta_out = cfe_try_fmt_meta,
486 .vidioc_enum_framesizes = cfe_enum_framesizes,
488 - .vidioc_reqbufs = vb2_ioctl_reqbufs,
489 - .vidioc_create_bufs = vb2_ioctl_create_bufs,
490 + .vidioc_reqbufs = cfe_vb2_ioctl_reqbufs,
491 + .vidioc_create_bufs = cfe_vb2_ioctl_create_bufs,
492 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
493 .vidioc_querybuf = vb2_ioctl_querybuf,
494 .vidioc_qbuf = vb2_ioctl_qbuf,
495 @@ -1610,7 +1687,7 @@ static int cfe_video_link_validate(struc
498 if (is_image_output_node(node)) {
499 - struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix;
500 + struct v4l2_pix_format *pix_fmt = &node->vid_fmt.fmt.pix;
501 const struct cfe_fmt *fmt = NULL;
504 @@ -1636,8 +1713,8 @@ static int cfe_video_link_validate(struc
508 - } else if (node->id == CSI2_CH1_EMBEDDED) {
509 - struct v4l2_meta_format *meta_fmt = &node->fmt.fmt.meta;
510 + } else if (is_csi2_node(node) && is_meta_output_node(node)) {
511 + struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta;
513 if (source_fmt->width * source_fmt->height !=
514 meta_fmt->buffersize ||
515 @@ -1698,15 +1775,17 @@ static int cfe_video_link_notify(struct
517 if (link->source->entity != csi2)
519 - if (link->sink->index != 0)
520 + if (link->sink->entity != fe)
522 - if (link->source->index == node_desc[CSI2_CH1_EMBEDDED].link_pad)
523 + if (link->sink->index != 0)
526 cfe->fe_csi2_channel = -1;
527 - if (link->sink->entity == fe && (link->flags & MEDIA_LNK_FL_ENABLED)) {
528 + if (link->flags & MEDIA_LNK_FL_ENABLED) {
529 if (link->source->index == node_desc[CSI2_CH0].link_pad)
530 cfe->fe_csi2_channel = CSI2_CH0;
531 + else if (link->source->index == node_desc[CSI2_CH1].link_pad)
532 + cfe->fe_csi2_channel = CSI2_CH1;
533 else if (link->source->index == node_desc[CSI2_CH2].link_pad)
534 cfe->fe_csi2_channel = CSI2_CH2;
535 else if (link->source->index == node_desc[CSI2_CH3].link_pad)
536 @@ -1763,30 +1842,42 @@ static int cfe_register_node(struct cfe_
540 - if (is_image_node(node)) {
541 + if (node_supports_image(node)) {
542 + if (node_supports_image_output(node))
543 + node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
545 + node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
547 fmt = find_format_by_code(cfe_default_format.code);
549 cfe_err("Failed to find format code\n");
553 - node->fmt.fmt.pix.pixelformat = fmt->fourcc;
554 - v4l2_fill_pix_format(&node->fmt.fmt.pix, &cfe_default_format);
555 + node->vid_fmt.fmt.pix.pixelformat = fmt->fourcc;
556 + v4l2_fill_pix_format(&node->vid_fmt.fmt.pix, &cfe_default_format);
558 - ret = try_fmt_vid_cap(node, &node->fmt);
559 + ret = try_fmt_vid_cap(node, &node->vid_fmt);
563 - ret = try_fmt_meta(node, &node->fmt);
566 + if (node_supports_meta(node)) {
567 + if (node_supports_meta_output(node))
568 + node->meta_fmt.type = V4L2_BUF_TYPE_META_CAPTURE;
570 + node->meta_fmt.type = V4L2_BUF_TYPE_META_OUTPUT;
572 + ret = try_fmt_meta(node, &node->meta_fmt);
576 - node->fmt.type = node_desc[id].buf_type;
578 mutex_init(&node->lock);
580 q = &node->buffer_queue;
581 - q->type = node_desc[id].buf_type;
582 + q->type = node_supports_image(node) ? node->vid_fmt.type :
583 + node->meta_fmt.type;
584 q->io_modes = VB2_MMAP | VB2_DMABUF;
586 q->ops = &cfe_video_qops;
587 @@ -1812,11 +1903,13 @@ static int cfe_register_node(struct cfe_
588 vdev->ioctl_ops = &cfe_ioctl_ops;
589 vdev->entity.ops = &cfe_media_entity_ops;
590 vdev->v4l2_dev = &cfe->v4l2_dev;
591 - vdev->vfl_dir = (is_image_output_node(node) || is_meta_output_node(node))
592 - ? VFL_DIR_RX : VFL_DIR_TX;
593 + vdev->vfl_dir = (node_supports_image_output(node) ||
594 + node_supports_meta_output(node)) ?
598 vdev->lock = &node->lock;
599 - vdev->device_caps = node_desc[id].cap;
600 + vdev->device_caps = node_desc[id].caps;
601 vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC;
603 /* Define the device names */
604 @@ -1829,7 +1922,7 @@ static int cfe_register_node(struct cfe_
605 node->pad.flags = node_desc[id].pad_flags;
606 media_entity_pads_init(&vdev->entity, 1, &node->pad);
608 - if (is_meta_node(node)) {
609 + if (!node_supports_image(node)) {
610 v4l2_disable_ioctl(&node->video_dev,
611 VIDIOC_ENUM_FRAMEINTERVALS);
612 v4l2_disable_ioctl(&node->video_dev,
613 @@ -1907,7 +2000,7 @@ static int cfe_link_node_pads(struct cfe
617 - if (node->id != CSI2_CH1_EMBEDDED) {
618 + if (node_supports_image(node)) {
619 /* CSI2 channel # -> FE Input */
620 ret = media_create_pad_link(&cfe->csi2.sd.entity,
621 node_desc[i].link_pad,