1 From 68ed2d82179cf40557f448fd47979a54a12d6345 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 15 Oct 2021 17:57:27 +0100
4 Subject: [PATCH] media/bcm2835-unicam: Add support for configuration
7 Adds Media Controller API support for more complex pipelines.
8 libcamera is about to switch to using this mechanism for configuring
11 This can be enabled by either a module parameter, or device tree.
13 Various functions have been moved to group video-centric and
14 mc-centric functions together.
16 Based on a similar conversion done to ti-vpe.
18 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
20 .../media/platform/bcm2835/bcm2835-unicam.c | 2125 ++++++++++-------
21 1 file changed, 1314 insertions(+), 811 deletions(-)
23 --- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
24 +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
25 @@ -84,6 +84,10 @@ static int debug;
26 module_param(debug, int, 0644);
27 MODULE_PARM_DESC(debug, "Debug level 0-3");
29 +static int media_controller;
30 +module_param(media_controller, int, 0644);
31 +MODULE_PARM_DESC(media_controller, "Use media controller API");
33 #define unicam_dbg(level, dev, fmt, arg...) \
34 v4l2_dbg(level, debug, &(dev)->v4l2_dev, fmt, ##arg)
35 #define unicam_info(dev, fmt, arg...) \
36 @@ -120,7 +124,7 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
39 /* Default size of the embedded buffer */
40 -#define UNICAM_EMBEDDED_SIZE 8192
41 +#define UNICAM_EMBEDDED_SIZE 16384
44 * Size of the dummy buffer. Can be any size really, but the DMA
45 @@ -134,6 +138,22 @@ enum pad_types {
49 +#define MASK_CS_DEFAULT BIT(V4L2_COLORSPACE_DEFAULT)
50 +#define MASK_CS_SMPTE170M BIT(V4L2_COLORSPACE_SMPTE170M)
51 +#define MASK_CS_SMPTE240M BIT(V4L2_COLORSPACE_SMPTE240M)
52 +#define MASK_CS_REC709 BIT(V4L2_COLORSPACE_REC709)
53 +#define MASK_CS_BT878 BIT(V4L2_COLORSPACE_BT878)
54 +#define MASK_CS_470_M BIT(V4L2_COLORSPACE_470_SYSTEM_M)
55 +#define MASK_CS_470_BG BIT(V4L2_COLORSPACE_470_SYSTEM_BG)
56 +#define MASK_CS_JPEG BIT(V4L2_COLORSPACE_JPEG)
57 +#define MASK_CS_SRGB BIT(V4L2_COLORSPACE_SRGB)
58 +#define MASK_CS_OPRGB BIT(V4L2_COLORSPACE_OPRGB)
59 +#define MASK_CS_BT2020 BIT(V4L2_COLORSPACE_BT2020)
60 +#define MASK_CS_RAW BIT(V4L2_COLORSPACE_RAW)
61 +#define MASK_CS_DCI_P3 BIT(V4L2_COLORSPACE_DCI_P3)
63 +#define MAX_COLORSPACE 32
66 * struct unicam_fmt - Unicam media bus format information
67 * @pixelformat: V4L2 pixel format FCC identifier. 0 if n/a.
68 @@ -142,8 +162,14 @@ enum pad_types {
69 * @code: V4L2 media bus format code.
70 * @depth: Bits per pixel as delivered from the source.
71 * @csi_dt: CSI data type.
72 + * @valid_colorspaces: Bitmask of valid colorspaces so that the Media Controller
73 + * centric try_fmt can validate the colorspace and pass
75 * @check_variants: Flag to denote that there are multiple mediabus formats
76 * still in the list that could match this V4L2 format.
77 + * @mc_skip: Media Controller shouldn't list this format via ENUM_FMT as it is
78 + * a duplicate of an earlier format.
79 + * @metadata_fmt: This format only applies to the metadata pad.
83 @@ -151,7 +177,10 @@ struct unicam_fmt {
88 + u32 valid_colorspaces;
89 + u8 check_variants:1;
94 static const struct unicam_fmt formats[] = {
95 @@ -162,173 +191,216 @@ static const struct unicam_fmt formats[]
99 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
102 .fourcc = V4L2_PIX_FMT_UYVY,
103 .code = MEDIA_BUS_FMT_UYVY8_2X8,
107 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
110 .fourcc = V4L2_PIX_FMT_YVYU,
111 .code = MEDIA_BUS_FMT_YVYU8_2X8,
115 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
118 .fourcc = V4L2_PIX_FMT_VYUY,
119 .code = MEDIA_BUS_FMT_VYUY8_2X8,
123 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
126 .fourcc = V4L2_PIX_FMT_YUYV,
127 .code = MEDIA_BUS_FMT_YUYV8_1X16,
131 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
134 .fourcc = V4L2_PIX_FMT_UYVY,
135 .code = MEDIA_BUS_FMT_UYVY8_1X16,
139 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
142 .fourcc = V4L2_PIX_FMT_YVYU,
143 .code = MEDIA_BUS_FMT_YVYU8_1X16,
147 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
150 .fourcc = V4L2_PIX_FMT_VYUY,
151 .code = MEDIA_BUS_FMT_VYUY8_1X16,
155 + .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 |
159 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
160 .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
163 + .valid_colorspaces = MASK_CS_SRGB,
165 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
166 .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
170 + .valid_colorspaces = MASK_CS_SRGB,
172 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
173 .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
176 + .valid_colorspaces = MASK_CS_SRGB,
178 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
179 .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
182 + .valid_colorspaces = MASK_CS_SRGB,
184 .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
185 .code = MEDIA_BUS_FMT_RGB888_1X24,
188 + .valid_colorspaces = MASK_CS_SRGB,
190 .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
191 .code = MEDIA_BUS_FMT_BGR888_1X24,
194 + .valid_colorspaces = MASK_CS_SRGB,
196 .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
197 .code = MEDIA_BUS_FMT_ARGB8888_1X32,
200 + .valid_colorspaces = MASK_CS_SRGB,
203 .fourcc = V4L2_PIX_FMT_SBGGR8,
204 .code = MEDIA_BUS_FMT_SBGGR8_1X8,
207 + .valid_colorspaces = MASK_CS_RAW,
209 .fourcc = V4L2_PIX_FMT_SGBRG8,
210 .code = MEDIA_BUS_FMT_SGBRG8_1X8,
213 + .valid_colorspaces = MASK_CS_RAW,
215 .fourcc = V4L2_PIX_FMT_SGRBG8,
216 .code = MEDIA_BUS_FMT_SGRBG8_1X8,
219 + .valid_colorspaces = MASK_CS_RAW,
221 .fourcc = V4L2_PIX_FMT_SRGGB8,
222 .code = MEDIA_BUS_FMT_SRGGB8_1X8,
225 + .valid_colorspaces = MASK_CS_RAW,
227 .fourcc = V4L2_PIX_FMT_SBGGR10P,
228 .repacked_fourcc = V4L2_PIX_FMT_SBGGR10,
229 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
232 + .valid_colorspaces = MASK_CS_RAW,
234 .fourcc = V4L2_PIX_FMT_SGBRG10P,
235 .repacked_fourcc = V4L2_PIX_FMT_SGBRG10,
236 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
239 + .valid_colorspaces = MASK_CS_RAW,
241 .fourcc = V4L2_PIX_FMT_SGRBG10P,
242 .repacked_fourcc = V4L2_PIX_FMT_SGRBG10,
243 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
246 + .valid_colorspaces = MASK_CS_RAW,
248 .fourcc = V4L2_PIX_FMT_SRGGB10P,
249 .repacked_fourcc = V4L2_PIX_FMT_SRGGB10,
250 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
253 + .valid_colorspaces = MASK_CS_RAW,
255 .fourcc = V4L2_PIX_FMT_SBGGR12P,
256 .repacked_fourcc = V4L2_PIX_FMT_SBGGR12,
257 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
260 + .valid_colorspaces = MASK_CS_RAW,
262 .fourcc = V4L2_PIX_FMT_SGBRG12P,
263 .repacked_fourcc = V4L2_PIX_FMT_SGBRG12,
264 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
267 + .valid_colorspaces = MASK_CS_RAW,
269 .fourcc = V4L2_PIX_FMT_SGRBG12P,
270 .repacked_fourcc = V4L2_PIX_FMT_SGRBG12,
271 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
274 + .valid_colorspaces = MASK_CS_RAW,
276 .fourcc = V4L2_PIX_FMT_SRGGB12P,
277 .repacked_fourcc = V4L2_PIX_FMT_SRGGB12,
278 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
281 + .valid_colorspaces = MASK_CS_RAW,
283 .fourcc = V4L2_PIX_FMT_SBGGR14P,
284 .repacked_fourcc = V4L2_PIX_FMT_SBGGR14,
285 .code = MEDIA_BUS_FMT_SBGGR14_1X14,
288 + .valid_colorspaces = MASK_CS_RAW,
290 .fourcc = V4L2_PIX_FMT_SGBRG14P,
291 .repacked_fourcc = V4L2_PIX_FMT_SGBRG14,
292 .code = MEDIA_BUS_FMT_SGBRG14_1X14,
295 + .valid_colorspaces = MASK_CS_RAW,
297 .fourcc = V4L2_PIX_FMT_SGRBG14P,
298 .repacked_fourcc = V4L2_PIX_FMT_SGRBG14,
299 .code = MEDIA_BUS_FMT_SGRBG14_1X14,
302 + .valid_colorspaces = MASK_CS_RAW,
304 .fourcc = V4L2_PIX_FMT_SRGGB14P,
305 .repacked_fourcc = V4L2_PIX_FMT_SRGGB14,
306 .code = MEDIA_BUS_FMT_SRGGB14_1X14,
309 + .valid_colorspaces = MASK_CS_RAW,
312 * 16 bit Bayer formats could be supported, but there is no CSI2
313 @@ -341,30 +413,35 @@ static const struct unicam_fmt formats[]
314 .code = MEDIA_BUS_FMT_Y8_1X8,
317 + .valid_colorspaces = MASK_CS_RAW,
319 .fourcc = V4L2_PIX_FMT_Y10P,
320 .repacked_fourcc = V4L2_PIX_FMT_Y10,
321 .code = MEDIA_BUS_FMT_Y10_1X10,
324 + .valid_colorspaces = MASK_CS_RAW,
326 .fourcc = V4L2_PIX_FMT_Y12P,
327 .repacked_fourcc = V4L2_PIX_FMT_Y12,
328 .code = MEDIA_BUS_FMT_Y12_1X12,
331 + .valid_colorspaces = MASK_CS_RAW,
333 .fourcc = V4L2_PIX_FMT_Y14P,
334 .repacked_fourcc = V4L2_PIX_FMT_Y14,
335 .code = MEDIA_BUS_FMT_Y14_1X14,
338 + .valid_colorspaces = MASK_CS_RAW,
340 /* Embedded data format */
342 .fourcc = V4L2_META_FMT_SENSOR_DATA,
343 .code = MEDIA_BUS_FMT_SENSOR_DATA,
349 @@ -409,6 +486,7 @@ struct unicam_node {
350 struct unicam_device *dev;
351 struct media_pad pad;
352 unsigned int embedded_lines;
353 + struct media_pipeline pipe;
355 * Dummy buffer intended to be used by unicam
356 * if we have no other queued buffers to swap to.
357 @@ -460,6 +538,8 @@ struct unicam_device {
359 struct unicam_node node[MAX_NODES];
360 struct v4l2_ctrl_handler ctrl_handler;
365 static inline struct unicam_device *
366 @@ -909,6 +989,7 @@ static irqreturn_t unicam_isr(int irq, v
370 +/* V4L2 Common IOCTLs */
371 static int unicam_querycap(struct file *file, void *priv,
372 struct v4l2_capability *cap)
374 @@ -926,6 +1007,38 @@ static int unicam_querycap(struct file *
378 +static int unicam_log_status(struct file *file, void *fh)
380 + struct unicam_node *node = video_drvdata(file);
381 + struct unicam_device *dev = node->dev;
384 + /* status for sub devices */
385 + v4l2_device_call_all(&dev->v4l2_dev, 0, core, log_status);
387 + unicam_info(dev, "-----Receiver status-----\n");
388 + unicam_info(dev, "V4L2 width/height: %ux%u\n",
389 + node->v_fmt.fmt.pix.width, node->v_fmt.fmt.pix.height);
390 + unicam_info(dev, "Mediabus format: %08x\n", node->fmt->code);
391 + unicam_info(dev, "V4L2 format: %08x\n",
392 + node->v_fmt.fmt.pix.pixelformat);
393 + reg = reg_read(dev, UNICAM_IPIPE);
394 + unicam_info(dev, "Unpacking/packing: %u / %u\n",
395 + get_field(reg, UNICAM_PUM_MASK),
396 + get_field(reg, UNICAM_PPM_MASK));
397 + unicam_info(dev, "----Live data----\n");
398 + unicam_info(dev, "Programmed stride: %4u\n",
399 + reg_read(dev, UNICAM_IBLS));
400 + unicam_info(dev, "Detected resolution: %ux%u\n",
401 + reg_read(dev, UNICAM_IHSTA),
402 + reg_read(dev, UNICAM_IVSTA));
403 + unicam_info(dev, "Write pointer: %08x\n",
404 + reg_read(dev, UNICAM_IBWP));
409 +/* V4L2 Video Centric IOCTLs */
410 static int unicam_enum_fmt_vid_cap(struct file *file, void *priv,
411 struct v4l2_fmtdesc *f)
413 @@ -1270,6 +1383,727 @@ static int unicam_g_fmt_meta_cap(struct
417 +static int unicam_enum_input(struct file *file, void *priv,
418 + struct v4l2_input *inp)
420 + struct unicam_node *node = video_drvdata(file);
421 + struct unicam_device *dev = node->dev;
424 + if (inp->index != 0)
427 + inp->type = V4L2_INPUT_TYPE_CAMERA;
428 + if (v4l2_subdev_has_op(dev->sensor, video, s_dv_timings)) {
429 + inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
431 + } else if (v4l2_subdev_has_op(dev->sensor, video, s_std)) {
432 + inp->capabilities = V4L2_IN_CAP_STD;
433 + if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std) < 0)
434 + inp->std = V4L2_STD_ALL;
436 + inp->capabilities = 0;
440 + if (v4l2_subdev_has_op(dev->sensor, video, g_input_status)) {
441 + ret = v4l2_subdev_call(dev->sensor, video, g_input_status,
447 + snprintf(inp->name, sizeof(inp->name), "Camera 0");
451 +static int unicam_g_input(struct file *file, void *priv, unsigned int *i)
458 +static int unicam_s_input(struct file *file, void *priv, unsigned int i)
461 + * FIXME: Ideally we would like to be able to query the source
462 + * subdevice for information over the input connectors it supports,
463 + * and map that through in to a call to video_ops->s_routing.
464 + * There is no infrastructure support for defining that within
465 + * devicetree at present. Until that is implemented we can't
466 + * map a user physical connector number to s_routing input number.
474 +static int unicam_querystd(struct file *file, void *priv,
477 + struct unicam_node *node = video_drvdata(file);
478 + struct unicam_device *dev = node->dev;
480 + return v4l2_subdev_call(dev->sensor, video, querystd, std);
483 +static int unicam_g_std(struct file *file, void *priv, v4l2_std_id *std)
485 + struct unicam_node *node = video_drvdata(file);
486 + struct unicam_device *dev = node->dev;
488 + return v4l2_subdev_call(dev->sensor, video, g_std, std);
491 +static int unicam_s_std(struct file *file, void *priv, v4l2_std_id std)
493 + struct unicam_node *node = video_drvdata(file);
494 + struct unicam_device *dev = node->dev;
496 + v4l2_std_id current_std;
498 + ret = v4l2_subdev_call(dev->sensor, video, g_std, ¤t_std);
502 + if (std == current_std)
505 + if (vb2_is_busy(&node->buffer_queue))
508 + ret = v4l2_subdev_call(dev->sensor, video, s_std, std);
510 + /* Force recomputation of bytesperline */
511 + node->v_fmt.fmt.pix.bytesperline = 0;
513 + unicam_reset_format(node);
518 +static int unicam_s_edid(struct file *file, void *priv, struct v4l2_edid *edid)
520 + struct unicam_node *node = video_drvdata(file);
521 + struct unicam_device *dev = node->dev;
523 + return v4l2_subdev_call(dev->sensor, pad, set_edid, edid);
526 +static int unicam_g_edid(struct file *file, void *priv, struct v4l2_edid *edid)
528 + struct unicam_node *node = video_drvdata(file);
529 + struct unicam_device *dev = node->dev;
531 + return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
534 +static int unicam_s_selection(struct file *file, void *priv,
535 + struct v4l2_selection *sel)
537 + struct unicam_node *node = video_drvdata(file);
538 + struct unicam_device *dev = node->dev;
539 + struct v4l2_subdev_selection sdsel = {
540 + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
541 + .target = sel->target,
542 + .flags = sel->flags,
546 + if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
549 + return v4l2_subdev_call(dev->sensor, pad, set_selection, NULL, &sdsel);
552 +static int unicam_g_selection(struct file *file, void *priv,
553 + struct v4l2_selection *sel)
555 + struct unicam_node *node = video_drvdata(file);
556 + struct unicam_device *dev = node->dev;
557 + struct v4l2_subdev_selection sdsel = {
558 + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
559 + .target = sel->target,
563 + if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
566 + ret = v4l2_subdev_call(dev->sensor, pad, get_selection, NULL, &sdsel);
573 +static int unicam_enum_framesizes(struct file *file, void *priv,
574 + struct v4l2_frmsizeenum *fsize)
576 + struct unicam_node *node = video_drvdata(file);
577 + struct unicam_device *dev = node->dev;
578 + const struct unicam_fmt *fmt;
579 + struct v4l2_subdev_frame_size_enum fse;
582 + /* check for valid format */
583 + fmt = find_format_by_pix(dev, fsize->pixel_format);
585 + unicam_dbg(3, dev, "Invalid pixel code: %x\n",
586 + fsize->pixel_format);
589 + fse.code = fmt->code;
591 + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
592 + fse.index = fsize->index;
593 + fse.pad = node->src_pad_id;
595 + ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
599 + unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
600 + __func__, fse.index, fse.code, fse.min_width, fse.max_width,
601 + fse.min_height, fse.max_height);
603 + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
604 + fsize->discrete.width = fse.max_width;
605 + fsize->discrete.height = fse.max_height;
610 +static int unicam_enum_frameintervals(struct file *file, void *priv,
611 + struct v4l2_frmivalenum *fival)
613 + struct unicam_node *node = video_drvdata(file);
614 + struct unicam_device *dev = node->dev;
615 + const struct unicam_fmt *fmt;
616 + struct v4l2_subdev_frame_interval_enum fie = {
617 + .index = fival->index,
618 + .pad = node->src_pad_id,
619 + .width = fival->width,
620 + .height = fival->height,
621 + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
625 + fmt = find_format_by_pix(dev, fival->pixel_format);
629 + fie.code = fmt->code;
630 + ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval,
635 + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
636 + fival->discrete = fie.interval;
641 +static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
643 + struct unicam_node *node = video_drvdata(file);
644 + struct unicam_device *dev = node->dev;
646 + return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a);
649 +static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
651 + struct unicam_node *node = video_drvdata(file);
652 + struct unicam_device *dev = node->dev;
654 + return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a);
657 +static int unicam_g_dv_timings(struct file *file, void *priv,
658 + struct v4l2_dv_timings *timings)
660 + struct unicam_node *node = video_drvdata(file);
661 + struct unicam_device *dev = node->dev;
663 + return v4l2_subdev_call(dev->sensor, video, g_dv_timings, timings);
666 +static int unicam_s_dv_timings(struct file *file, void *priv,
667 + struct v4l2_dv_timings *timings)
669 + struct unicam_node *node = video_drvdata(file);
670 + struct unicam_device *dev = node->dev;
671 + struct v4l2_dv_timings current_timings;
674 + ret = v4l2_subdev_call(dev->sensor, video, g_dv_timings,
680 + if (v4l2_match_dv_timings(timings, ¤t_timings, 0, false))
683 + if (vb2_is_busy(&node->buffer_queue))
686 + ret = v4l2_subdev_call(dev->sensor, video, s_dv_timings, timings);
688 + /* Force recomputation of bytesperline */
689 + node->v_fmt.fmt.pix.bytesperline = 0;
691 + unicam_reset_format(node);
696 +static int unicam_query_dv_timings(struct file *file, void *priv,
697 + struct v4l2_dv_timings *timings)
699 + struct unicam_node *node = video_drvdata(file);
700 + struct unicam_device *dev = node->dev;
702 + return v4l2_subdev_call(dev->sensor, video, query_dv_timings, timings);
705 +static int unicam_enum_dv_timings(struct file *file, void *priv,
706 + struct v4l2_enum_dv_timings *timings)
708 + struct unicam_node *node = video_drvdata(file);
709 + struct unicam_device *dev = node->dev;
712 + timings->pad = node->src_pad_id;
713 + ret = v4l2_subdev_call(dev->sensor, pad, enum_dv_timings, timings);
714 + timings->pad = node->pad_id;
719 +static int unicam_dv_timings_cap(struct file *file, void *priv,
720 + struct v4l2_dv_timings_cap *cap)
722 + struct unicam_node *node = video_drvdata(file);
723 + struct unicam_device *dev = node->dev;
726 + cap->pad = node->src_pad_id;
727 + ret = v4l2_subdev_call(dev->sensor, pad, dv_timings_cap, cap);
728 + cap->pad = node->pad_id;
733 +static int unicam_subscribe_event(struct v4l2_fh *fh,
734 + const struct v4l2_event_subscription *sub)
736 + switch (sub->type) {
737 + case V4L2_EVENT_FRAME_SYNC:
738 + return v4l2_event_subscribe(fh, sub, 2, NULL);
739 + case V4L2_EVENT_SOURCE_CHANGE:
740 + return v4l2_event_subscribe(fh, sub, 4, NULL);
743 + return v4l2_ctrl_subscribe_event(fh, sub);
746 +static void unicam_notify(struct v4l2_subdev *sd,
747 + unsigned int notification, void *arg)
749 + struct unicam_device *dev = to_unicam_device(sd->v4l2_dev);
751 + switch (notification) {
752 + case V4L2_DEVICE_NOTIFY_EVENT:
753 + v4l2_event_queue(&dev->node[IMAGE_PAD].video_dev, arg);
760 +/* unicam capture ioctl operations */
761 +static const struct v4l2_ioctl_ops unicam_ioctl_ops = {
762 + .vidioc_querycap = unicam_querycap,
763 + .vidioc_enum_fmt_vid_cap = unicam_enum_fmt_vid_cap,
764 + .vidioc_g_fmt_vid_cap = unicam_g_fmt_vid_cap,
765 + .vidioc_s_fmt_vid_cap = unicam_s_fmt_vid_cap,
766 + .vidioc_try_fmt_vid_cap = unicam_try_fmt_vid_cap,
768 + .vidioc_enum_fmt_meta_cap = unicam_enum_fmt_meta_cap,
769 + .vidioc_g_fmt_meta_cap = unicam_g_fmt_meta_cap,
770 + .vidioc_s_fmt_meta_cap = unicam_g_fmt_meta_cap,
771 + .vidioc_try_fmt_meta_cap = unicam_g_fmt_meta_cap,
773 + .vidioc_enum_input = unicam_enum_input,
774 + .vidioc_g_input = unicam_g_input,
775 + .vidioc_s_input = unicam_s_input,
777 + .vidioc_querystd = unicam_querystd,
778 + .vidioc_s_std = unicam_s_std,
779 + .vidioc_g_std = unicam_g_std,
781 + .vidioc_g_edid = unicam_g_edid,
782 + .vidioc_s_edid = unicam_s_edid,
784 + .vidioc_enum_framesizes = unicam_enum_framesizes,
785 + .vidioc_enum_frameintervals = unicam_enum_frameintervals,
787 + .vidioc_g_selection = unicam_g_selection,
788 + .vidioc_s_selection = unicam_s_selection,
790 + .vidioc_g_parm = unicam_g_parm,
791 + .vidioc_s_parm = unicam_s_parm,
793 + .vidioc_s_dv_timings = unicam_s_dv_timings,
794 + .vidioc_g_dv_timings = unicam_g_dv_timings,
795 + .vidioc_query_dv_timings = unicam_query_dv_timings,
796 + .vidioc_enum_dv_timings = unicam_enum_dv_timings,
797 + .vidioc_dv_timings_cap = unicam_dv_timings_cap,
799 + .vidioc_reqbufs = vb2_ioctl_reqbufs,
800 + .vidioc_create_bufs = vb2_ioctl_create_bufs,
801 + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
802 + .vidioc_querybuf = vb2_ioctl_querybuf,
803 + .vidioc_qbuf = vb2_ioctl_qbuf,
804 + .vidioc_dqbuf = vb2_ioctl_dqbuf,
805 + .vidioc_expbuf = vb2_ioctl_expbuf,
806 + .vidioc_streamon = vb2_ioctl_streamon,
807 + .vidioc_streamoff = vb2_ioctl_streamoff,
809 + .vidioc_log_status = unicam_log_status,
810 + .vidioc_subscribe_event = unicam_subscribe_event,
811 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
814 +/* V4L2 Media Controller Centric IOCTLs */
816 +static int unicam_mc_enum_fmt_vid_cap(struct file *file, void *priv,
817 + struct v4l2_fmtdesc *f)
821 + for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) {
822 + if (f->mbus_code && formats[i].code != f->mbus_code)
824 + if (formats[i].mc_skip || formats[i].metadata_fmt)
827 + if (formats[i].fourcc) {
828 + if (j == f->index) {
829 + f->pixelformat = formats[i].fourcc;
830 + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
835 + if (formats[i].repacked_fourcc) {
836 + if (j == f->index) {
837 + f->pixelformat = formats[i].repacked_fourcc;
838 + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
848 +static int unicam_mc_g_fmt_vid_cap(struct file *file, void *priv,
849 + struct v4l2_format *f)
851 + struct unicam_node *node = video_drvdata(file);
853 + if (node->pad_id != IMAGE_PAD)
861 +static void unicam_mc_try_fmt(struct unicam_node *node, struct v4l2_format *f,
862 + const struct unicam_fmt **ret_fmt)
864 + struct v4l2_pix_format *v4l2_format = &f->fmt.pix;
865 + struct unicam_device *dev = node->dev;
866 + const struct unicam_fmt *fmt;
870 + * Default to the first format if the requested pixel format code isn't
873 + fmt = find_format_by_pix(dev, v4l2_format->pixelformat);
876 + v4l2_format->pixelformat = fmt->fourcc;
879 + unicam_calc_format_size_bpl(dev, fmt, f);
881 + if (v4l2_format->field == V4L2_FIELD_ANY)
882 + v4l2_format->field = V4L2_FIELD_NONE;
887 + if (v4l2_format->colorspace >= MAX_COLORSPACE ||
888 + !(fmt->valid_colorspaces & (1 << v4l2_format->colorspace))) {
889 + v4l2_format->colorspace = __ffs(fmt->valid_colorspaces);
891 + v4l2_format->xfer_func =
892 + V4L2_MAP_XFER_FUNC_DEFAULT(v4l2_format->colorspace);
893 + v4l2_format->ycbcr_enc =
894 + V4L2_MAP_YCBCR_ENC_DEFAULT(v4l2_format->colorspace);
895 + is_rgb = v4l2_format->colorspace == V4L2_COLORSPACE_SRGB;
896 + v4l2_format->quantization =
897 + V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb,
898 + v4l2_format->colorspace,
899 + v4l2_format->ycbcr_enc);
902 + unicam_dbg(3, dev, "%s: %08x %ux%u (bytesperline %u sizeimage %u)\n",
903 + __func__, v4l2_format->pixelformat,
904 + v4l2_format->width, v4l2_format->height,
905 + v4l2_format->bytesperline, v4l2_format->sizeimage);
908 +static int unicam_mc_try_fmt_vid_cap(struct file *file, void *priv,
909 + struct v4l2_format *f)
911 + struct unicam_node *node = video_drvdata(file);
913 + unicam_mc_try_fmt(node, f, NULL);
917 +static int unicam_mc_s_fmt_vid_cap(struct file *file, void *priv,
918 + struct v4l2_format *f)
920 + struct unicam_node *node = video_drvdata(file);
921 + struct unicam_device *dev = node->dev;
922 + const struct unicam_fmt *fmt;
924 + if (vb2_is_busy(&node->buffer_queue)) {
925 + unicam_dbg(3, dev, "%s device busy\n", __func__);
929 + unicam_mc_try_fmt(node, f, &fmt);
937 +static int unicam_mc_enum_framesizes(struct file *file, void *fh,
938 + struct v4l2_frmsizeenum *fsize)
940 + struct unicam_node *node = video_drvdata(file);
941 + struct unicam_device *dev = node->dev;
943 + if (fsize->index > 0)
946 + if (!find_format_by_pix(dev, fsize->pixel_format)) {
947 + unicam_dbg(3, dev, "Invalid pixel format 0x%08x\n",
948 + fsize->pixel_format);
952 + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
953 + fsize->stepwise.min_width = MIN_WIDTH;
954 + fsize->stepwise.max_width = MAX_WIDTH;
955 + fsize->stepwise.step_width = 1;
956 + fsize->stepwise.min_height = MIN_HEIGHT;
957 + fsize->stepwise.max_height = MAX_HEIGHT;
958 + fsize->stepwise.step_height = 1;
963 +static int unicam_mc_enum_fmt_meta_cap(struct file *file, void *priv,
964 + struct v4l2_fmtdesc *f)
968 + for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) {
969 + if (f->mbus_code && formats[i].code != f->mbus_code)
971 + if (!formats[i].metadata_fmt)
974 + if (formats[i].fourcc) {
975 + if (j == f->index) {
976 + f->pixelformat = formats[i].fourcc;
977 + f->type = V4L2_BUF_TYPE_META_CAPTURE;
987 +static int unicam_mc_g_fmt_meta_cap(struct file *file, void *priv,
988 + struct v4l2_format *f)
990 + struct unicam_node *node = video_drvdata(file);
992 + if (node->pad_id != METADATA_PAD)
1000 +static int unicam_mc_try_fmt_meta_cap(struct file *file, void *priv,
1001 + struct v4l2_format *f)
1003 + struct unicam_node *node = video_drvdata(file);
1005 + if (node->pad_id != METADATA_PAD)
1008 + f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA;
1013 +static int unicam_mc_s_fmt_meta_cap(struct file *file, void *priv,
1014 + struct v4l2_format *f)
1016 + struct unicam_node *node = video_drvdata(file);
1018 + if (node->pad_id != METADATA_PAD)
1021 + unicam_mc_try_fmt_meta_cap(file, priv, f);
1028 +static const struct v4l2_ioctl_ops unicam_mc_ioctl_ops = {
1029 + .vidioc_querycap = unicam_querycap,
1030 + .vidioc_enum_fmt_vid_cap = unicam_mc_enum_fmt_vid_cap,
1031 + .vidioc_g_fmt_vid_cap = unicam_mc_g_fmt_vid_cap,
1032 + .vidioc_try_fmt_vid_cap = unicam_mc_try_fmt_vid_cap,
1033 + .vidioc_s_fmt_vid_cap = unicam_mc_s_fmt_vid_cap,
1035 + .vidioc_enum_fmt_meta_cap = unicam_mc_enum_fmt_meta_cap,
1036 + .vidioc_g_fmt_meta_cap = unicam_mc_g_fmt_meta_cap,
1037 + .vidioc_try_fmt_meta_cap = unicam_mc_try_fmt_meta_cap,
1038 + .vidioc_s_fmt_meta_cap = unicam_mc_s_fmt_meta_cap,
1040 + .vidioc_enum_framesizes = unicam_mc_enum_framesizes,
1041 + .vidioc_reqbufs = vb2_ioctl_reqbufs,
1042 + .vidioc_create_bufs = vb2_ioctl_create_bufs,
1043 + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1044 + .vidioc_querybuf = vb2_ioctl_querybuf,
1045 + .vidioc_qbuf = vb2_ioctl_qbuf,
1046 + .vidioc_dqbuf = vb2_ioctl_dqbuf,
1047 + .vidioc_expbuf = vb2_ioctl_expbuf,
1048 + .vidioc_streamon = vb2_ioctl_streamon,
1049 + .vidioc_streamoff = vb2_ioctl_streamoff,
1051 + .vidioc_log_status = unicam_log_status,
1052 + .vidioc_subscribe_event = unicam_subscribe_event,
1053 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1057 +unicam_mc_subdev_link_validate_get_format(struct media_pad *pad,
1058 + struct v4l2_subdev_format *fmt)
1060 + if (is_media_entity_v4l2_subdev(pad->entity)) {
1061 + struct v4l2_subdev *sd =
1062 + media_entity_to_v4l2_subdev(pad->entity);
1064 + fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
1065 + fmt->pad = pad->index;
1066 + return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
1072 +static int unicam_mc_video_link_validate(struct media_link *link)
1074 + struct video_device *vd = container_of(link->sink->entity,
1075 + struct video_device, entity);
1076 + struct unicam_node *node = container_of(vd, struct unicam_node,
1078 + struct unicam_device *unicam = node->dev;
1079 + struct v4l2_subdev_format source_fmt;
1082 + if (!media_entity_remote_pad(link->sink->entity->pads)) {
1083 + unicam_dbg(1, unicam,
1084 + "video node %s pad not connected\n", vd->name);
1088 + ret = unicam_mc_subdev_link_validate_get_format(link->source,
1093 + if (node->pad_id == IMAGE_PAD) {
1094 + struct v4l2_pix_format *pix_fmt = &node->v_fmt.fmt.pix;
1095 + const struct unicam_fmt *fmt;
1097 + if (source_fmt.format.width != pix_fmt->width ||
1098 + source_fmt.format.height != pix_fmt->height) {
1099 + unicam_err(unicam,
1100 + "Wrong width or height %ux%u (remote pad set to %ux%u)\n",
1101 + pix_fmt->width, pix_fmt->height,
1102 + source_fmt.format.width,
1103 + source_fmt.format.height);
1107 + fmt = find_format_by_code(source_fmt.format.code);
1109 + if (!fmt || (fmt->fourcc != pix_fmt->pixelformat &&
1110 + fmt->repacked_fourcc != pix_fmt->pixelformat))
1113 + struct v4l2_meta_format *meta_fmt = &node->v_fmt.fmt.meta;
1115 + if (source_fmt.format.width != meta_fmt->buffersize ||
1116 + source_fmt.format.height != 1 ||
1117 + source_fmt.format.code != MEDIA_BUS_FMT_SENSOR_DATA) {
1118 + unicam_err(unicam,
1119 + "Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n",
1120 + meta_fmt->buffersize, 1,
1121 + MEDIA_BUS_FMT_SENSOR_DATA,
1122 + source_fmt.format.width,
1123 + source_fmt.format.height,
1124 + source_fmt.format.code);
1132 +static const struct media_entity_operations unicam_mc_entity_ops = {
1133 + .link_validate = unicam_mc_video_link_validate,
1136 +/* videobuf2 Operations */
1138 static int unicam_queue_setup(struct vb2_queue *vq,
1139 unsigned int *nbuffers,
1140 unsigned int *nplanes,
1141 @@ -1667,6 +2501,12 @@ static int unicam_start_streaming(struct
1145 + ret = media_pipeline_start(&node->video_dev.entity, &node->pipe);
1147 + unicam_err(dev, "Failed to start media pipeline: %d\n", ret);
1151 dev->active_data_lanes = dev->max_data_lanes;
1153 if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
1154 @@ -1676,7 +2516,7 @@ static int unicam_start_streaming(struct
1156 if (ret < 0 && ret != -ENOIOCTLCMD) {
1157 unicam_dbg(3, dev, "g_mbus_config failed\n");
1159 + goto error_pipeline;
1162 dev->active_data_lanes =
1163 @@ -1689,7 +2529,7 @@ static int unicam_start_streaming(struct
1164 dev->active_data_lanes,
1165 dev->max_data_lanes);
1168 + goto error_pipeline;
1172 @@ -1699,13 +2539,13 @@ static int unicam_start_streaming(struct
1173 ret = clk_set_min_rate(dev->vpu_clock, MIN_VPU_CLOCK_RATE);
1175 unicam_err(dev, "failed to set up VPU clock\n");
1177 + goto error_pipeline;
1180 ret = clk_prepare_enable(dev->vpu_clock);
1182 unicam_err(dev, "Failed to enable VPU clock: %d\n", ret);
1184 + goto error_pipeline;
1187 ret = clk_set_rate(dev->clock, 100 * 1000 * 1000);
1188 @@ -1756,6 +2596,8 @@ err_vpu_clock:
1189 if (clk_set_min_rate(dev->vpu_clock, 0))
1190 unicam_err(dev, "failed to reset the VPU clock\n");
1191 clk_disable_unprepare(dev->vpu_clock);
1193 + media_pipeline_stop(&node->video_dev.entity);
1195 unicam_runtime_put(dev);
1197 @@ -1783,6 +2625,8 @@ static void unicam_stop_streaming(struct
1199 unicam_disable(dev);
1201 + media_pipeline_stop(&node->video_dev.entity);
1203 if (dev->clocks_enabled) {
1204 if (clk_set_min_rate(dev->vpu_clock, 0))
1205 unicam_err(dev, "failed to reset the min VPU clock\n");
1206 @@ -1807,379 +2651,6 @@ static void unicam_stop_streaming(struct
1207 unicam_return_buffers(node, VB2_BUF_STATE_ERROR);
1210 -static int unicam_enum_input(struct file *file, void *priv,
1211 - struct v4l2_input *inp)
1213 - struct unicam_node *node = video_drvdata(file);
1214 - struct unicam_device *dev = node->dev;
1217 - if (inp->index != 0)
1220 - inp->type = V4L2_INPUT_TYPE_CAMERA;
1221 - if (v4l2_subdev_has_op(dev->sensor, video, s_dv_timings)) {
1222 - inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
1224 - } else if (v4l2_subdev_has_op(dev->sensor, video, s_std)) {
1225 - inp->capabilities = V4L2_IN_CAP_STD;
1226 - if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std) < 0)
1227 - inp->std = V4L2_STD_ALL;
1229 - inp->capabilities = 0;
1233 - if (v4l2_subdev_has_op(dev->sensor, video, g_input_status)) {
1234 - ret = v4l2_subdev_call(dev->sensor, video, g_input_status,
1240 - snprintf(inp->name, sizeof(inp->name), "Camera 0");
1244 -static int unicam_g_input(struct file *file, void *priv, unsigned int *i)
1251 -static int unicam_s_input(struct file *file, void *priv, unsigned int i)
1254 - * FIXME: Ideally we would like to be able to query the source
1255 - * subdevice for information over the input connectors it supports,
1256 - * and map that through in to a call to video_ops->s_routing.
1257 - * There is no infrastructure support for defining that within
1258 - * devicetree at present. Until that is implemented we can't
1259 - * map a user physical connector number to s_routing input number.
1267 -static int unicam_querystd(struct file *file, void *priv,
1270 - struct unicam_node *node = video_drvdata(file);
1271 - struct unicam_device *dev = node->dev;
1273 - return v4l2_subdev_call(dev->sensor, video, querystd, std);
1276 -static int unicam_g_std(struct file *file, void *priv, v4l2_std_id *std)
1278 - struct unicam_node *node = video_drvdata(file);
1279 - struct unicam_device *dev = node->dev;
1281 - return v4l2_subdev_call(dev->sensor, video, g_std, std);
1284 -static int unicam_s_std(struct file *file, void *priv, v4l2_std_id std)
1286 - struct unicam_node *node = video_drvdata(file);
1287 - struct unicam_device *dev = node->dev;
1289 - v4l2_std_id current_std;
1291 - ret = v4l2_subdev_call(dev->sensor, video, g_std, ¤t_std);
1295 - if (std == current_std)
1298 - if (vb2_is_busy(&node->buffer_queue))
1301 - ret = v4l2_subdev_call(dev->sensor, video, s_std, std);
1303 - /* Force recomputation of bytesperline */
1304 - node->v_fmt.fmt.pix.bytesperline = 0;
1306 - unicam_reset_format(node);
1311 -static int unicam_s_edid(struct file *file, void *priv, struct v4l2_edid *edid)
1313 - struct unicam_node *node = video_drvdata(file);
1314 - struct unicam_device *dev = node->dev;
1316 - return v4l2_subdev_call(dev->sensor, pad, set_edid, edid);
1319 -static int unicam_g_edid(struct file *file, void *priv, struct v4l2_edid *edid)
1321 - struct unicam_node *node = video_drvdata(file);
1322 - struct unicam_device *dev = node->dev;
1324 - return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
1327 -static int unicam_s_selection(struct file *file, void *priv,
1328 - struct v4l2_selection *sel)
1330 - struct unicam_node *node = video_drvdata(file);
1331 - struct unicam_device *dev = node->dev;
1332 - struct v4l2_subdev_selection sdsel = {
1333 - .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1334 - .target = sel->target,
1335 - .flags = sel->flags,
1339 - if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1342 - return v4l2_subdev_call(dev->sensor, pad, set_selection, NULL, &sdsel);
1345 -static int unicam_g_selection(struct file *file, void *priv,
1346 - struct v4l2_selection *sel)
1348 - struct unicam_node *node = video_drvdata(file);
1349 - struct unicam_device *dev = node->dev;
1350 - struct v4l2_subdev_selection sdsel = {
1351 - .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1352 - .target = sel->target,
1356 - if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1359 - ret = v4l2_subdev_call(dev->sensor, pad, get_selection, NULL, &sdsel);
1366 -static int unicam_enum_framesizes(struct file *file, void *priv,
1367 - struct v4l2_frmsizeenum *fsize)
1369 - struct unicam_node *node = video_drvdata(file);
1370 - struct unicam_device *dev = node->dev;
1371 - const struct unicam_fmt *fmt;
1372 - struct v4l2_subdev_frame_size_enum fse;
1375 - /* check for valid format */
1376 - fmt = find_format_by_pix(dev, fsize->pixel_format);
1378 - unicam_dbg(3, dev, "Invalid pixel code: %x\n",
1379 - fsize->pixel_format);
1382 - fse.code = fmt->code;
1384 - fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1385 - fse.index = fsize->index;
1386 - fse.pad = node->src_pad_id;
1388 - ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
1392 - unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
1393 - __func__, fse.index, fse.code, fse.min_width, fse.max_width,
1394 - fse.min_height, fse.max_height);
1396 - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1397 - fsize->discrete.width = fse.max_width;
1398 - fsize->discrete.height = fse.max_height;
1403 -static int unicam_enum_frameintervals(struct file *file, void *priv,
1404 - struct v4l2_frmivalenum *fival)
1406 - struct unicam_node *node = video_drvdata(file);
1407 - struct unicam_device *dev = node->dev;
1408 - const struct unicam_fmt *fmt;
1409 - struct v4l2_subdev_frame_interval_enum fie = {
1410 - .index = fival->index,
1411 - .pad = node->src_pad_id,
1412 - .width = fival->width,
1413 - .height = fival->height,
1414 - .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1418 - fmt = find_format_by_pix(dev, fival->pixel_format);
1422 - fie.code = fmt->code;
1423 - ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval,
1428 - fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1429 - fival->discrete = fie.interval;
1434 -static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1436 - struct unicam_node *node = video_drvdata(file);
1437 - struct unicam_device *dev = node->dev;
1439 - return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a);
1442 -static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1444 - struct unicam_node *node = video_drvdata(file);
1445 - struct unicam_device *dev = node->dev;
1447 - return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a);
1450 -static int unicam_g_dv_timings(struct file *file, void *priv,
1451 - struct v4l2_dv_timings *timings)
1453 - struct unicam_node *node = video_drvdata(file);
1454 - struct unicam_device *dev = node->dev;
1456 - return v4l2_subdev_call(dev->sensor, video, g_dv_timings, timings);
1459 -static int unicam_s_dv_timings(struct file *file, void *priv,
1460 - struct v4l2_dv_timings *timings)
1462 - struct unicam_node *node = video_drvdata(file);
1463 - struct unicam_device *dev = node->dev;
1464 - struct v4l2_dv_timings current_timings;
1467 - ret = v4l2_subdev_call(dev->sensor, video, g_dv_timings,
1468 - ¤t_timings);
1473 - if (v4l2_match_dv_timings(timings, ¤t_timings, 0, false))
1476 - if (vb2_is_busy(&node->buffer_queue))
1479 - ret = v4l2_subdev_call(dev->sensor, video, s_dv_timings, timings);
1481 - /* Force recomputation of bytesperline */
1482 - node->v_fmt.fmt.pix.bytesperline = 0;
1484 - unicam_reset_format(node);
1489 -static int unicam_query_dv_timings(struct file *file, void *priv,
1490 - struct v4l2_dv_timings *timings)
1492 - struct unicam_node *node = video_drvdata(file);
1493 - struct unicam_device *dev = node->dev;
1495 - return v4l2_subdev_call(dev->sensor, video, query_dv_timings, timings);
1498 -static int unicam_enum_dv_timings(struct file *file, void *priv,
1499 - struct v4l2_enum_dv_timings *timings)
1501 - struct unicam_node *node = video_drvdata(file);
1502 - struct unicam_device *dev = node->dev;
1505 - timings->pad = node->src_pad_id;
1506 - ret = v4l2_subdev_call(dev->sensor, pad, enum_dv_timings, timings);
1507 - timings->pad = node->pad_id;
1512 -static int unicam_dv_timings_cap(struct file *file, void *priv,
1513 - struct v4l2_dv_timings_cap *cap)
1515 - struct unicam_node *node = video_drvdata(file);
1516 - struct unicam_device *dev = node->dev;
1519 - cap->pad = node->src_pad_id;
1520 - ret = v4l2_subdev_call(dev->sensor, pad, dv_timings_cap, cap);
1521 - cap->pad = node->pad_id;
1526 -static int unicam_subscribe_event(struct v4l2_fh *fh,
1527 - const struct v4l2_event_subscription *sub)
1529 - switch (sub->type) {
1530 - case V4L2_EVENT_FRAME_SYNC:
1531 - return v4l2_event_subscribe(fh, sub, 2, NULL);
1532 - case V4L2_EVENT_SOURCE_CHANGE:
1533 - return v4l2_event_subscribe(fh, sub, 4, NULL);
1536 - return v4l2_ctrl_subscribe_event(fh, sub);
1539 -static int unicam_log_status(struct file *file, void *fh)
1541 - struct unicam_node *node = video_drvdata(file);
1542 - struct unicam_device *dev = node->dev;
1545 - /* status for sub devices */
1546 - v4l2_device_call_all(&dev->v4l2_dev, 0, core, log_status);
1548 - unicam_info(dev, "-----Receiver status-----\n");
1549 - unicam_info(dev, "V4L2 width/height: %ux%u\n",
1550 - node->v_fmt.fmt.pix.width, node->v_fmt.fmt.pix.height);
1551 - unicam_info(dev, "Mediabus format: %08x\n", node->fmt->code);
1552 - unicam_info(dev, "V4L2 format: %08x\n",
1553 - node->v_fmt.fmt.pix.pixelformat);
1554 - reg = reg_read(dev, UNICAM_IPIPE);
1555 - unicam_info(dev, "Unpacking/packing: %u / %u\n",
1556 - get_field(reg, UNICAM_PUM_MASK),
1557 - get_field(reg, UNICAM_PPM_MASK));
1558 - unicam_info(dev, "----Live data----\n");
1559 - unicam_info(dev, "Programmed stride: %4u\n",
1560 - reg_read(dev, UNICAM_IBLS));
1561 - unicam_info(dev, "Detected resolution: %ux%u\n",
1562 - reg_read(dev, UNICAM_IHSTA),
1563 - reg_read(dev, UNICAM_IVSTA));
1564 - unicam_info(dev, "Write pointer: %08x\n",
1565 - reg_read(dev, UNICAM_IBWP));
1570 -static void unicam_notify(struct v4l2_subdev *sd,
1571 - unsigned int notification, void *arg)
1573 - struct unicam_device *dev = to_unicam_device(sd->v4l2_dev);
1575 - switch (notification) {
1576 - case V4L2_DEVICE_NOTIFY_EVENT:
1577 - v4l2_event_queue(&dev->node[IMAGE_PAD].video_dev, arg);
1584 static const struct vb2_ops unicam_video_qops = {
1585 .wait_prepare = vb2_ops_wait_prepare,
1586 @@ -2262,60 +2733,6 @@ static const struct v4l2_file_operations
1587 .mmap = vb2_fop_mmap,
1590 -/* unicam capture ioctl operations */
1591 -static const struct v4l2_ioctl_ops unicam_ioctl_ops = {
1592 - .vidioc_querycap = unicam_querycap,
1593 - .vidioc_enum_fmt_vid_cap = unicam_enum_fmt_vid_cap,
1594 - .vidioc_g_fmt_vid_cap = unicam_g_fmt_vid_cap,
1595 - .vidioc_s_fmt_vid_cap = unicam_s_fmt_vid_cap,
1596 - .vidioc_try_fmt_vid_cap = unicam_try_fmt_vid_cap,
1598 - .vidioc_enum_fmt_meta_cap = unicam_enum_fmt_meta_cap,
1599 - .vidioc_g_fmt_meta_cap = unicam_g_fmt_meta_cap,
1600 - .vidioc_s_fmt_meta_cap = unicam_g_fmt_meta_cap,
1601 - .vidioc_try_fmt_meta_cap = unicam_g_fmt_meta_cap,
1603 - .vidioc_enum_input = unicam_enum_input,
1604 - .vidioc_g_input = unicam_g_input,
1605 - .vidioc_s_input = unicam_s_input,
1607 - .vidioc_querystd = unicam_querystd,
1608 - .vidioc_s_std = unicam_s_std,
1609 - .vidioc_g_std = unicam_g_std,
1611 - .vidioc_g_edid = unicam_g_edid,
1612 - .vidioc_s_edid = unicam_s_edid,
1614 - .vidioc_enum_framesizes = unicam_enum_framesizes,
1615 - .vidioc_enum_frameintervals = unicam_enum_frameintervals,
1617 - .vidioc_g_selection = unicam_g_selection,
1618 - .vidioc_s_selection = unicam_s_selection,
1620 - .vidioc_g_parm = unicam_g_parm,
1621 - .vidioc_s_parm = unicam_s_parm,
1623 - .vidioc_s_dv_timings = unicam_s_dv_timings,
1624 - .vidioc_g_dv_timings = unicam_g_dv_timings,
1625 - .vidioc_query_dv_timings = unicam_query_dv_timings,
1626 - .vidioc_enum_dv_timings = unicam_enum_dv_timings,
1627 - .vidioc_dv_timings_cap = unicam_dv_timings_cap,
1629 - .vidioc_reqbufs = vb2_ioctl_reqbufs,
1630 - .vidioc_create_bufs = vb2_ioctl_create_bufs,
1631 - .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1632 - .vidioc_querybuf = vb2_ioctl_querybuf,
1633 - .vidioc_qbuf = vb2_ioctl_qbuf,
1634 - .vidioc_dqbuf = vb2_ioctl_dqbuf,
1635 - .vidioc_expbuf = vb2_ioctl_expbuf,
1636 - .vidioc_streamon = vb2_ioctl_streamon,
1637 - .vidioc_streamoff = vb2_ioctl_streamoff,
1639 - .vidioc_log_status = unicam_log_status,
1640 - .vidioc_subscribe_event = unicam_subscribe_event,
1641 - .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1645 unicam_async_bound(struct v4l2_async_notifier *notifier,
1646 struct v4l2_subdev *subdev,
1647 @@ -2366,11 +2783,11 @@ static void unicam_node_release(struct v
1648 unicam_put(node->dev);
1651 -static int register_node(struct unicam_device *unicam, struct unicam_node *node,
1652 - enum v4l2_buf_type type, int pad_id)
1653 +static int unicam_set_default_format(struct unicam_device *unicam,
1654 + struct unicam_node *node,
1656 + const struct unicam_fmt **ret_fmt)
1658 - struct video_device *vdev;
1659 - struct vb2_queue *q;
1660 struct v4l2_mbus_framefmt mbus_fmt = {0};
1661 const struct unicam_fmt *fmt;
1663 @@ -2415,15 +2832,69 @@ static int register_node(struct unicam_d
1664 node->v_fmt.fmt.meta.dataformat = fmt->fourcc;
1672 +static void unicam_mc_set_default_format(struct unicam_node *node, int pad_id)
1674 + if (pad_id == IMAGE_PAD) {
1675 + struct v4l2_pix_format *pix_fmt = &node->v_fmt.fmt.pix;
1677 + pix_fmt->width = 640;
1678 + pix_fmt->height = 480;
1679 + pix_fmt->field = V4L2_FIELD_NONE;
1680 + pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
1681 + pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
1682 + pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
1683 + pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
1684 + pix_fmt->pixelformat = formats[0].fourcc;
1685 + unicam_calc_format_size_bpl(node->dev, &formats[0],
1687 + node->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1689 + node->fmt = &formats[0];
1691 + const struct unicam_fmt *fmt;
1693 + /* Fix this node format as embedded data. */
1694 + fmt = find_format_by_code(MEDIA_BUS_FMT_SENSOR_DATA);
1695 + node->v_fmt.fmt.meta.dataformat = fmt->fourcc;
1698 + node->v_fmt.fmt.meta.buffersize = UNICAM_EMBEDDED_SIZE;
1699 + node->embedded_lines = 1;
1700 + node->v_fmt.type = V4L2_BUF_TYPE_META_CAPTURE;
1704 +static int register_node(struct unicam_device *unicam, struct unicam_node *node,
1705 + enum v4l2_buf_type type, int pad_id)
1707 + struct video_device *vdev;
1708 + struct vb2_queue *q;
1712 node->pad_id = pad_id;
1715 - /* Read current subdev format */
1717 - unicam_reset_format(node);
1718 + if (!unicam->mc_api) {
1719 + const struct unicam_fmt *fmt;
1721 - if (v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
1722 + ret = unicam_set_default_format(unicam, node, pad_id, &fmt);
1726 + /* Read current subdev format */
1728 + unicam_reset_format(node);
1730 + unicam_mc_set_default_format(node, pad_id);
1733 + if (!unicam->mc_api &&
1734 + v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
1735 v4l2_std_id tvnorms;
1737 if (WARN_ON(!v4l2_subdev_has_op(unicam->sensor, video,
1738 @@ -2446,12 +2917,15 @@ static int register_node(struct unicam_d
1740 vdev = &node->video_dev;
1741 if (pad_id == IMAGE_PAD) {
1742 - /* Add controls from the subdevice */
1743 - ret = v4l2_ctrl_add_handler(&unicam->ctrl_handler,
1744 - unicam->sensor->ctrl_handler, NULL,
1748 + if (!unicam->mc_api) {
1749 + /* Add controls from the subdevice */
1750 + ret = v4l2_ctrl_add_handler(&unicam->ctrl_handler,
1751 + unicam->sensor->ctrl_handler,
1759 * If the sensor subdevice has any controls, associate the node
1760 @@ -2483,7 +2957,8 @@ static int register_node(struct unicam_d
1762 vdev->release = unicam_node_release;
1763 vdev->fops = &unicam_fops;
1764 - vdev->ioctl_ops = &unicam_ioctl_ops;
1765 + vdev->ioctl_ops = unicam->mc_api ? &unicam_mc_ioctl_ops :
1766 + &unicam_ioctl_ops;
1767 vdev->v4l2_dev = &unicam->v4l2_dev;
1768 vdev->vfl_dir = VFL_DIR_RX;
1770 @@ -2491,6 +2966,10 @@ static int register_node(struct unicam_d
1771 vdev->device_caps = (pad_id == IMAGE_PAD) ?
1772 V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_META_CAPTURE;
1773 vdev->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
1774 + if (unicam->mc_api) {
1775 + vdev->device_caps |= V4L2_CAP_IO_MC;
1776 + vdev->entity.ops = &unicam_mc_entity_ops;
1779 /* Define the device names */
1780 snprintf(vdev->name, sizeof(vdev->name), "%s-%s", UNICAM_MODULE_NAME,
1781 @@ -2510,48 +2989,61 @@ static int register_node(struct unicam_d
1782 unicam_err(unicam, "Unable to allocate dummy buffer.\n");
1786 - if (pad_id == METADATA_PAD ||
1787 - !v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
1788 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD);
1789 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_STD);
1790 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUMSTD);
1792 - if (pad_id == METADATA_PAD ||
1793 - !v4l2_subdev_has_op(unicam->sensor, video, querystd))
1794 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERYSTD);
1795 - if (pad_id == METADATA_PAD ||
1796 - !v4l2_subdev_has_op(unicam->sensor, video, s_dv_timings)) {
1797 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_EDID);
1798 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_EDID);
1799 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_DV_TIMINGS_CAP);
1800 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_DV_TIMINGS);
1801 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_DV_TIMINGS);
1802 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUM_DV_TIMINGS);
1803 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERY_DV_TIMINGS);
1805 - if (pad_id == METADATA_PAD ||
1806 - !v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
1807 - v4l2_disable_ioctl(&node->video_dev,
1808 - VIDIOC_ENUM_FRAMEINTERVALS);
1809 - if (pad_id == METADATA_PAD ||
1810 - !v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
1811 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_PARM);
1812 - if (pad_id == METADATA_PAD ||
1813 - !v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
1814 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_PARM);
1816 - if (pad_id == METADATA_PAD ||
1817 - !v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
1818 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUM_FRAMESIZES);
1820 - if (node->pad_id == METADATA_PAD ||
1821 - !v4l2_subdev_has_op(unicam->sensor, pad, set_selection))
1822 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_SELECTION);
1824 - if (node->pad_id == METADATA_PAD ||
1825 - !v4l2_subdev_has_op(unicam->sensor, pad, get_selection))
1826 - v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_SELECTION);
1827 + if (!unicam->mc_api) {
1828 + if (pad_id == METADATA_PAD ||
1829 + !v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
1830 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD);
1831 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_STD);
1832 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUMSTD);
1834 + if (pad_id == METADATA_PAD ||
1835 + !v4l2_subdev_has_op(unicam->sensor, video, querystd))
1836 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERYSTD);
1837 + if (pad_id == METADATA_PAD ||
1838 + !v4l2_subdev_has_op(unicam->sensor, video, s_dv_timings)) {
1839 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_EDID);
1840 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_EDID);
1841 + v4l2_disable_ioctl(&node->video_dev,
1842 + VIDIOC_DV_TIMINGS_CAP);
1843 + v4l2_disable_ioctl(&node->video_dev,
1844 + VIDIOC_G_DV_TIMINGS);
1845 + v4l2_disable_ioctl(&node->video_dev,
1846 + VIDIOC_S_DV_TIMINGS);
1847 + v4l2_disable_ioctl(&node->video_dev,
1848 + VIDIOC_ENUM_DV_TIMINGS);
1849 + v4l2_disable_ioctl(&node->video_dev,
1850 + VIDIOC_QUERY_DV_TIMINGS);
1852 + if (pad_id == METADATA_PAD ||
1853 + !v4l2_subdev_has_op(unicam->sensor, pad,
1854 + enum_frame_interval))
1855 + v4l2_disable_ioctl(&node->video_dev,
1856 + VIDIOC_ENUM_FRAMEINTERVALS);
1857 + if (pad_id == METADATA_PAD ||
1858 + !v4l2_subdev_has_op(unicam->sensor, video,
1859 + g_frame_interval))
1860 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_PARM);
1861 + if (pad_id == METADATA_PAD ||
1862 + !v4l2_subdev_has_op(unicam->sensor, video,
1863 + s_frame_interval))
1864 + v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_PARM);
1866 + if (pad_id == METADATA_PAD ||
1867 + !v4l2_subdev_has_op(unicam->sensor, pad,
1869 + v4l2_disable_ioctl(&node->video_dev,
1870 + VIDIOC_ENUM_FRAMESIZES);
1872 + if (node->pad_id == METADATA_PAD ||
1873 + !v4l2_subdev_has_op(unicam->sensor, pad, set_selection))
1874 + v4l2_disable_ioctl(&node->video_dev,
1875 + VIDIOC_S_SELECTION);
1877 + if (node->pad_id == METADATA_PAD ||
1878 + !v4l2_subdev_has_op(unicam->sensor, pad, get_selection))
1879 + v4l2_disable_ioctl(&node->video_dev,
1880 + VIDIOC_G_SELECTION);
1883 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1885 @@ -2618,7 +3110,7 @@ static int unicam_async_complete(struct
1886 if (unicam->sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) {
1887 if (source_pads < MAX_NODES) {
1888 unicam->node[source_pads].src_pad_id = i;
1889 - unicam_err(unicam, "source pad %u is index %u\n",
1890 + unicam_dbg(3, unicam, "source pad %u is index %u\n",
1894 @@ -2647,7 +3139,10 @@ static int unicam_async_complete(struct
1898 - ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev);
1899 + if (unicam->mc_api)
1900 + ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
1902 + ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev);
1904 unicam_err(unicam, "Unable to register subdev nodes.\n");
1906 @@ -2807,6 +3302,14 @@ static int unicam_probe(struct platform_
1907 kref_init(&unicam->kref);
1908 unicam->pdev = pdev;
1911 + * Adopt the current setting of the module parameter, and check if
1912 + * device tree requests it.
1914 + unicam->mc_api = media_controller;
1915 + if (of_property_read_bool(pdev->dev.of_node, "brcm,media-controller"))
1916 + unicam->mc_api = true;
1918 unicam->base = devm_platform_ioremap_resource(pdev, 0);
1919 if (IS_ERR(unicam->base)) {
1920 unicam_err(unicam, "Failed to get main io block\n");