1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2013--2024 Intel Corporation
6 #include <linux/align.h>
7 #include <linux/bits.h>
9 #include <linux/completion.h>
10 #include <linux/container_of.h>
11 #include <linux/device.h>
12 #include <linux/list.h>
13 #include <linux/math64.h>
14 #include <linux/minmax.h>
15 #include <linux/module.h>
16 #include <linux/mutex.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/spinlock.h>
19 #include <linux/string.h>
21 #include <media/media-entity.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-dev.h>
24 #include <media/v4l2-fh.h>
25 #include <media/v4l2-ioctl.h>
26 #include <media/v4l2-subdev.h>
27 #include <media/videobuf2-v4l2.h>
32 #include "ipu6-fw-isys.h"
33 #include "ipu6-isys.h"
34 #include "ipu6-isys-csi2.h"
35 #include "ipu6-isys-queue.h"
36 #include "ipu6-isys-video.h"
37 #include "ipu6-platform-regs.h"
39 const struct ipu6_isys_pixelformat ipu6_isys_pfmts
[] = {
40 { V4L2_PIX_FMT_SBGGR12
, 16, 12, MEDIA_BUS_FMT_SBGGR12_1X12
,
41 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
42 { V4L2_PIX_FMT_SGBRG12
, 16, 12, MEDIA_BUS_FMT_SGBRG12_1X12
,
43 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
44 { V4L2_PIX_FMT_SGRBG12
, 16, 12, MEDIA_BUS_FMT_SGRBG12_1X12
,
45 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
46 { V4L2_PIX_FMT_SRGGB12
, 16, 12, MEDIA_BUS_FMT_SRGGB12_1X12
,
47 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
48 { V4L2_PIX_FMT_SBGGR10
, 16, 10, MEDIA_BUS_FMT_SBGGR10_1X10
,
49 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
50 { V4L2_PIX_FMT_SGBRG10
, 16, 10, MEDIA_BUS_FMT_SGBRG10_1X10
,
51 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
52 { V4L2_PIX_FMT_SGRBG10
, 16, 10, MEDIA_BUS_FMT_SGRBG10_1X10
,
53 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
54 { V4L2_PIX_FMT_SRGGB10
, 16, 10, MEDIA_BUS_FMT_SRGGB10_1X10
,
55 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
},
56 { V4L2_PIX_FMT_SBGGR8
, 8, 8, MEDIA_BUS_FMT_SBGGR8_1X8
,
57 IPU6_FW_ISYS_FRAME_FORMAT_RAW8
},
58 { V4L2_PIX_FMT_SGBRG8
, 8, 8, MEDIA_BUS_FMT_SGBRG8_1X8
,
59 IPU6_FW_ISYS_FRAME_FORMAT_RAW8
},
60 { V4L2_PIX_FMT_SGRBG8
, 8, 8, MEDIA_BUS_FMT_SGRBG8_1X8
,
61 IPU6_FW_ISYS_FRAME_FORMAT_RAW8
},
62 { V4L2_PIX_FMT_SRGGB8
, 8, 8, MEDIA_BUS_FMT_SRGGB8_1X8
,
63 IPU6_FW_ISYS_FRAME_FORMAT_RAW8
},
64 { V4L2_PIX_FMT_SBGGR12P
, 12, 12, MEDIA_BUS_FMT_SBGGR12_1X12
,
65 IPU6_FW_ISYS_FRAME_FORMAT_RAW12
},
66 { V4L2_PIX_FMT_SGBRG12P
, 12, 12, MEDIA_BUS_FMT_SGBRG12_1X12
,
67 IPU6_FW_ISYS_FRAME_FORMAT_RAW12
},
68 { V4L2_PIX_FMT_SGRBG12P
, 12, 12, MEDIA_BUS_FMT_SGRBG12_1X12
,
69 IPU6_FW_ISYS_FRAME_FORMAT_RAW12
},
70 { V4L2_PIX_FMT_SRGGB12P
, 12, 12, MEDIA_BUS_FMT_SRGGB12_1X12
,
71 IPU6_FW_ISYS_FRAME_FORMAT_RAW12
},
72 { V4L2_PIX_FMT_SBGGR10P
, 10, 10, MEDIA_BUS_FMT_SBGGR10_1X10
,
73 IPU6_FW_ISYS_FRAME_FORMAT_RAW10
},
74 { V4L2_PIX_FMT_SGBRG10P
, 10, 10, MEDIA_BUS_FMT_SGBRG10_1X10
,
75 IPU6_FW_ISYS_FRAME_FORMAT_RAW10
},
76 { V4L2_PIX_FMT_SGRBG10P
, 10, 10, MEDIA_BUS_FMT_SGRBG10_1X10
,
77 IPU6_FW_ISYS_FRAME_FORMAT_RAW10
},
78 { V4L2_PIX_FMT_SRGGB10P
, 10, 10, MEDIA_BUS_FMT_SRGGB10_1X10
,
79 IPU6_FW_ISYS_FRAME_FORMAT_RAW10
},
80 { V4L2_PIX_FMT_UYVY
, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16
,
81 IPU6_FW_ISYS_FRAME_FORMAT_UYVY
},
82 { V4L2_PIX_FMT_YUYV
, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16
,
83 IPU6_FW_ISYS_FRAME_FORMAT_YUYV
},
84 { V4L2_PIX_FMT_RGB565
, 16, 16, MEDIA_BUS_FMT_RGB565_1X16
,
85 IPU6_FW_ISYS_FRAME_FORMAT_RGB565
},
86 { V4L2_PIX_FMT_BGR24
, 24, 24, MEDIA_BUS_FMT_RGB888_1X24
,
87 IPU6_FW_ISYS_FRAME_FORMAT_RGBA888
},
88 { V4L2_META_FMT_GENERIC_8
, 8, 8, MEDIA_BUS_FMT_META_8
,
89 IPU6_FW_ISYS_FRAME_FORMAT_RAW8
, true },
90 { V4L2_META_FMT_GENERIC_CSI2_10
, 10, 10, MEDIA_BUS_FMT_META_10
,
91 IPU6_FW_ISYS_FRAME_FORMAT_RAW10
, true },
92 { V4L2_META_FMT_GENERIC_CSI2_12
, 12, 12, MEDIA_BUS_FMT_META_12
,
93 IPU6_FW_ISYS_FRAME_FORMAT_RAW12
, true },
94 { V4L2_META_FMT_GENERIC_CSI2_16
, 16, 16, MEDIA_BUS_FMT_META_16
,
95 IPU6_FW_ISYS_FRAME_FORMAT_RAW16
, true },
98 static int video_open(struct file
*file
)
100 struct ipu6_isys_video
*av
= video_drvdata(file
);
101 struct ipu6_isys
*isys
= av
->isys
;
102 struct ipu6_bus_device
*adev
= isys
->adev
;
104 mutex_lock(&isys
->mutex
);
105 if (isys
->need_reset
) {
106 mutex_unlock(&isys
->mutex
);
107 dev_warn(&adev
->auxdev
.dev
, "isys power cycle required\n");
110 mutex_unlock(&isys
->mutex
);
112 return v4l2_fh_open(file
);
115 const struct ipu6_isys_pixelformat
*
116 ipu6_isys_get_isys_format(u32 pixelformat
, u32 type
)
118 const struct ipu6_isys_pixelformat
*default_pfmt
= NULL
;
121 for (i
= 0; i
< ARRAY_SIZE(ipu6_isys_pfmts
); i
++) {
122 const struct ipu6_isys_pixelformat
*pfmt
= &ipu6_isys_pfmts
[i
];
124 if (type
&& ((!pfmt
->is_meta
&&
125 type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) ||
127 type
!= V4L2_BUF_TYPE_META_CAPTURE
)))
133 if (pfmt
->pixelformat
!= pixelformat
)
142 static int ipu6_isys_vidioc_querycap(struct file
*file
, void *fh
,
143 struct v4l2_capability
*cap
)
145 struct ipu6_isys_video
*av
= video_drvdata(file
);
147 strscpy(cap
->driver
, IPU6_ISYS_NAME
, sizeof(cap
->driver
));
148 strscpy(cap
->card
, av
->isys
->media_dev
.model
, sizeof(cap
->card
));
153 static int ipu6_isys_vidioc_enum_fmt(struct file
*file
, void *fh
,
154 struct v4l2_fmtdesc
*f
)
156 unsigned int i
, num_found
;
158 for (i
= 0, num_found
= 0; i
< ARRAY_SIZE(ipu6_isys_pfmts
); i
++) {
159 if ((ipu6_isys_pfmts
[i
].is_meta
&&
160 f
->type
!= V4L2_BUF_TYPE_META_CAPTURE
) ||
161 (!ipu6_isys_pfmts
[i
].is_meta
&&
162 f
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
))
165 if (f
->mbus_code
&& f
->mbus_code
!= ipu6_isys_pfmts
[i
].code
)
168 if (num_found
< f
->index
) {
174 f
->pixelformat
= ipu6_isys_pfmts
[i
].pixelformat
;
182 static int ipu6_isys_vidioc_enum_framesizes(struct file
*file
, void *fh
,
183 struct v4l2_frmsizeenum
*fsize
)
187 if (fsize
->index
> 0)
190 for (i
= 0; i
< ARRAY_SIZE(ipu6_isys_pfmts
); i
++) {
191 if (fsize
->pixel_format
!= ipu6_isys_pfmts
[i
].pixelformat
)
194 fsize
->type
= V4L2_FRMSIZE_TYPE_STEPWISE
;
195 fsize
->stepwise
.min_width
= IPU6_ISYS_MIN_WIDTH
;
196 fsize
->stepwise
.max_width
= IPU6_ISYS_MAX_WIDTH
;
197 fsize
->stepwise
.min_height
= IPU6_ISYS_MIN_HEIGHT
;
198 fsize
->stepwise
.max_height
= IPU6_ISYS_MAX_HEIGHT
;
199 fsize
->stepwise
.step_width
= 2;
200 fsize
->stepwise
.step_height
= 2;
208 static int ipu6_isys_vidioc_g_fmt_vid_cap(struct file
*file
, void *fh
,
209 struct v4l2_format
*f
)
211 struct ipu6_isys_video
*av
= video_drvdata(file
);
213 f
->fmt
.pix
= av
->pix_fmt
;
218 static int ipu6_isys_vidioc_g_fmt_meta_cap(struct file
*file
, void *fh
,
219 struct v4l2_format
*f
)
221 struct ipu6_isys_video
*av
= video_drvdata(file
);
223 f
->fmt
.meta
= av
->meta_fmt
;
228 static void ipu6_isys_try_fmt_cap(struct ipu6_isys_video
*av
, u32 type
,
229 u32
*format
, u32
*width
, u32
*height
,
230 u32
*bytesperline
, u32
*sizeimage
)
232 const struct ipu6_isys_pixelformat
*pfmt
=
233 ipu6_isys_get_isys_format(*format
, type
);
235 *format
= pfmt
->pixelformat
;
236 *width
= clamp(*width
, IPU6_ISYS_MIN_WIDTH
, IPU6_ISYS_MAX_WIDTH
);
237 *height
= clamp(*height
, IPU6_ISYS_MIN_HEIGHT
, IPU6_ISYS_MAX_HEIGHT
);
239 if (pfmt
->bpp
!= pfmt
->bpp_packed
)
240 *bytesperline
= *width
* DIV_ROUND_UP(pfmt
->bpp
, BITS_PER_BYTE
);
242 *bytesperline
= DIV_ROUND_UP(*width
* pfmt
->bpp
, BITS_PER_BYTE
);
244 *bytesperline
= ALIGN(*bytesperline
, av
->isys
->line_align
);
247 * (height + 1) * bytesperline due to a hardware issue: the DMA unit
248 * is a power of two, and a line should be transferred as few units
249 * as possible. The result is that up to line length more data than
250 * the image size may be transferred to memory after the image.
251 * Another limitation is the GDA allocation unit size. For low
252 * resolution it gives a bigger number. Use larger one to avoid
255 *sizeimage
= *bytesperline
* *height
+
257 av
->isys
->pdata
->ipdata
->isys_dma_overshoot
);
260 static void __ipu6_isys_vidioc_try_fmt_vid_cap(struct ipu6_isys_video
*av
,
261 struct v4l2_format
*f
)
263 ipu6_isys_try_fmt_cap(av
, f
->type
, &f
->fmt
.pix
.pixelformat
,
264 &f
->fmt
.pix
.width
, &f
->fmt
.pix
.height
,
265 &f
->fmt
.pix
.bytesperline
, &f
->fmt
.pix
.sizeimage
);
267 f
->fmt
.pix
.field
= V4L2_FIELD_NONE
;
268 f
->fmt
.pix
.colorspace
= V4L2_COLORSPACE_RAW
;
269 f
->fmt
.pix
.ycbcr_enc
= V4L2_YCBCR_ENC_DEFAULT
;
270 f
->fmt
.pix
.quantization
= V4L2_QUANTIZATION_DEFAULT
;
271 f
->fmt
.pix
.xfer_func
= V4L2_XFER_FUNC_DEFAULT
;
274 static int ipu6_isys_vidioc_try_fmt_vid_cap(struct file
*file
, void *fh
,
275 struct v4l2_format
*f
)
277 struct ipu6_isys_video
*av
= video_drvdata(file
);
279 if (vb2_is_busy(&av
->aq
.vbq
))
282 __ipu6_isys_vidioc_try_fmt_vid_cap(av
, f
);
287 static int __ipu6_isys_vidioc_try_fmt_meta_cap(struct ipu6_isys_video
*av
,
288 struct v4l2_format
*f
)
290 ipu6_isys_try_fmt_cap(av
, f
->type
, &f
->fmt
.meta
.dataformat
,
291 &f
->fmt
.meta
.width
, &f
->fmt
.meta
.height
,
292 &f
->fmt
.meta
.bytesperline
,
293 &f
->fmt
.meta
.buffersize
);
298 static int ipu6_isys_vidioc_try_fmt_meta_cap(struct file
*file
, void *fh
,
299 struct v4l2_format
*f
)
301 struct ipu6_isys_video
*av
= video_drvdata(file
);
303 __ipu6_isys_vidioc_try_fmt_meta_cap(av
, f
);
308 static int ipu6_isys_vidioc_s_fmt_vid_cap(struct file
*file
, void *fh
,
309 struct v4l2_format
*f
)
311 struct ipu6_isys_video
*av
= video_drvdata(file
);
313 ipu6_isys_vidioc_try_fmt_vid_cap(file
, fh
, f
);
314 av
->pix_fmt
= f
->fmt
.pix
;
319 static int ipu6_isys_vidioc_s_fmt_meta_cap(struct file
*file
, void *fh
,
320 struct v4l2_format
*f
)
322 struct ipu6_isys_video
*av
= video_drvdata(file
);
324 if (vb2_is_busy(&av
->aq
.vbq
))
327 ipu6_isys_vidioc_try_fmt_meta_cap(file
, fh
, f
);
328 av
->meta_fmt
= f
->fmt
.meta
;
333 static int ipu6_isys_vidioc_reqbufs(struct file
*file
, void *priv
,
334 struct v4l2_requestbuffers
*p
)
336 struct ipu6_isys_video
*av
= video_drvdata(file
);
339 av
->aq
.vbq
.is_multiplanar
= V4L2_TYPE_IS_MULTIPLANAR(p
->type
);
340 av
->aq
.vbq
.is_output
= V4L2_TYPE_IS_OUTPUT(p
->type
);
342 ret
= vb2_queue_change_type(&av
->aq
.vbq
, p
->type
);
346 return vb2_ioctl_reqbufs(file
, priv
, p
);
349 static int ipu6_isys_vidioc_create_bufs(struct file
*file
, void *priv
,
350 struct v4l2_create_buffers
*p
)
352 struct ipu6_isys_video
*av
= video_drvdata(file
);
355 av
->aq
.vbq
.is_multiplanar
= V4L2_TYPE_IS_MULTIPLANAR(p
->format
.type
);
356 av
->aq
.vbq
.is_output
= V4L2_TYPE_IS_OUTPUT(p
->format
.type
);
358 ret
= vb2_queue_change_type(&av
->aq
.vbq
, p
->format
.type
);
362 return vb2_ioctl_create_bufs(file
, priv
, p
);
365 static int link_validate(struct media_link
*link
)
367 struct ipu6_isys_video
*av
=
368 container_of(link
->sink
, struct ipu6_isys_video
, pad
);
369 struct device
*dev
= &av
->isys
->adev
->auxdev
.dev
;
370 struct v4l2_subdev_state
*s_state
;
371 struct v4l2_subdev
*s_sd
;
372 struct v4l2_mbus_framefmt
*s_fmt
;
373 struct media_pad
*s_pad
;
377 if (!link
->source
->entity
)
380 s_sd
= media_entity_to_v4l2_subdev(link
->source
->entity
);
381 s_state
= v4l2_subdev_get_unlocked_active_state(s_sd
);
385 dev_dbg(dev
, "validating link \"%s\":%u -> \"%s\"\n",
386 link
->source
->entity
->name
, link
->source
->index
,
387 link
->sink
->entity
->name
);
389 s_pad
= media_pad_remote_pad_first(&av
->pad
);
390 s_stream
= ipu6_isys_get_src_stream_by_src_pad(s_sd
, s_pad
->index
);
392 v4l2_subdev_lock_state(s_state
);
394 s_fmt
= v4l2_subdev_state_get_format(s_state
, s_pad
->index
, s_stream
);
396 dev_err(dev
, "failed to get source pad format\n");
400 code
= ipu6_isys_get_isys_format(ipu6_isys_get_format(av
), 0)->code
;
402 if (s_fmt
->width
!= ipu6_isys_get_frame_width(av
) ||
403 s_fmt
->height
!= ipu6_isys_get_frame_height(av
) ||
404 s_fmt
->code
!= code
) {
405 dev_dbg(dev
, "format mismatch %dx%d,%x != %dx%d,%x\n",
406 s_fmt
->width
, s_fmt
->height
, s_fmt
->code
,
407 ipu6_isys_get_frame_width(av
),
408 ipu6_isys_get_frame_height(av
), code
);
412 v4l2_subdev_unlock_state(s_state
);
416 v4l2_subdev_unlock_state(s_state
);
421 static void get_stream_opened(struct ipu6_isys_video
*av
)
425 spin_lock_irqsave(&av
->isys
->streams_lock
, flags
);
426 av
->isys
->stream_opened
++;
427 spin_unlock_irqrestore(&av
->isys
->streams_lock
, flags
);
430 static void put_stream_opened(struct ipu6_isys_video
*av
)
434 spin_lock_irqsave(&av
->isys
->streams_lock
, flags
);
435 av
->isys
->stream_opened
--;
436 spin_unlock_irqrestore(&av
->isys
->streams_lock
, flags
);
439 static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video
*av
,
440 struct ipu6_fw_isys_stream_cfg_data_abi
*cfg
)
442 struct media_pad
*src_pad
= media_pad_remote_pad_first(&av
->pad
);
443 struct v4l2_subdev
*sd
= media_entity_to_v4l2_subdev(src_pad
->entity
);
444 struct ipu6_fw_isys_input_pin_info_abi
*input_pin
;
445 struct ipu6_fw_isys_output_pin_info_abi
*output_pin
;
446 struct ipu6_isys_stream
*stream
= av
->stream
;
447 struct ipu6_isys_queue
*aq
= &av
->aq
;
448 struct v4l2_mbus_framefmt fmt
;
449 const struct ipu6_isys_pixelformat
*pfmt
=
450 ipu6_isys_get_isys_format(ipu6_isys_get_format(av
), 0);
451 struct v4l2_rect v4l2_crop
;
452 struct ipu6_isys
*isys
= av
->isys
;
453 struct device
*dev
= &isys
->adev
->auxdev
.dev
;
454 int input_pins
= cfg
->nof_input_pins
++;
459 src_stream
= ipu6_isys_get_src_stream_by_src_pad(sd
, src_pad
->index
);
460 ret
= ipu6_isys_get_stream_pad_fmt(sd
, src_pad
->index
, src_stream
,
463 dev_err(dev
, "can't get stream format (%d)\n", ret
);
467 ret
= ipu6_isys_get_stream_pad_crop(sd
, src_pad
->index
, src_stream
,
470 dev_err(dev
, "can't get stream crop (%d)\n", ret
);
474 input_pin
= &cfg
->input_pins
[input_pins
];
475 input_pin
->input_res
.width
= fmt
.width
;
476 input_pin
->input_res
.height
= fmt
.height
;
477 input_pin
->dt
= av
->dt
;
478 input_pin
->bits_per_pix
= pfmt
->bpp_packed
;
479 input_pin
->mapped_dt
= 0x40; /* invalid mipi data type */
480 input_pin
->mipi_decompression
= 0;
481 input_pin
->capture_mode
= IPU6_FW_ISYS_CAPTURE_MODE_REGULAR
;
482 input_pin
->mipi_store_mode
= pfmt
->bpp
== pfmt
->bpp_packed
?
483 IPU6_FW_ISYS_MIPI_STORE_MODE_DISCARD_LONG_HEADER
:
484 IPU6_FW_ISYS_MIPI_STORE_MODE_NORMAL
;
485 input_pin
->crop_first_and_last_lines
= v4l2_crop
.top
& 1;
487 output_pins
= cfg
->nof_output_pins
++;
488 aq
->fw_output
= output_pins
;
489 stream
->output_pins
[output_pins
].pin_ready
= ipu6_isys_queue_buf_ready
;
490 stream
->output_pins
[output_pins
].aq
= aq
;
492 output_pin
= &cfg
->output_pins
[output_pins
];
493 output_pin
->input_pin_id
= input_pins
;
494 output_pin
->output_res
.width
= ipu6_isys_get_frame_width(av
);
495 output_pin
->output_res
.height
= ipu6_isys_get_frame_height(av
);
497 output_pin
->stride
= ipu6_isys_get_bytes_per_line(av
);
498 if (pfmt
->bpp
!= pfmt
->bpp_packed
)
499 output_pin
->pt
= IPU6_FW_ISYS_PIN_TYPE_RAW_SOC
;
501 output_pin
->pt
= IPU6_FW_ISYS_PIN_TYPE_MIPI
;
502 output_pin
->ft
= pfmt
->css_pixelformat
;
503 output_pin
->send_irq
= 1;
504 memset(output_pin
->ts_offsets
, 0, sizeof(output_pin
->ts_offsets
));
505 output_pin
->s2m_pixel_soc_pixel_remapping
=
506 S2M_PIXEL_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING
;
507 output_pin
->csi_be_soc_pixel_remapping
=
508 CSI_BE_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING
;
510 output_pin
->snoopable
= true;
511 output_pin
->error_handling_enable
= false;
512 output_pin
->sensor_type
= isys
->sensor_type
++;
513 if (isys
->sensor_type
> isys
->pdata
->ipdata
->sensor_type_end
)
514 isys
->sensor_type
= isys
->pdata
->ipdata
->sensor_type_start
;
519 static int start_stream_firmware(struct ipu6_isys_video
*av
,
520 struct ipu6_isys_buffer_list
*bl
)
522 struct ipu6_fw_isys_stream_cfg_data_abi
*stream_cfg
;
523 struct ipu6_fw_isys_frame_buff_set_abi
*buf
= NULL
;
524 struct ipu6_isys_stream
*stream
= av
->stream
;
525 struct device
*dev
= &av
->isys
->adev
->auxdev
.dev
;
526 struct isys_fw_msgs
*msg
= NULL
;
527 struct ipu6_isys_queue
*aq
;
528 int ret
, retout
, tout
;
531 msg
= ipu6_get_fw_msg_buf(stream
);
535 stream_cfg
= &msg
->fw_msg
.stream
;
536 stream_cfg
->src
= stream
->stream_source
;
537 stream_cfg
->vc
= stream
->vc
;
538 stream_cfg
->isl_use
= 0;
539 stream_cfg
->sensor_type
= IPU6_FW_ISYS_SENSOR_MODE_NORMAL
;
541 list_for_each_entry(aq
, &stream
->queues
, node
) {
542 struct ipu6_isys_video
*__av
= ipu6_isys_queue_to_video(aq
);
544 ret
= ipu6_isys_fw_pin_cfg(__av
, stream_cfg
);
546 ipu6_put_fw_msg_buf(av
->isys
, (uintptr_t)stream_cfg
);
551 ipu6_fw_isys_dump_stream_cfg(dev
, stream_cfg
);
553 stream
->nr_output_pins
= stream_cfg
->nof_output_pins
;
555 reinit_completion(&stream
->stream_open_completion
);
557 ret
= ipu6_fw_isys_complex_cmd(av
->isys
, stream
->stream_handle
,
558 stream_cfg
, msg
->dma_addr
,
560 IPU6_FW_ISYS_SEND_TYPE_STREAM_OPEN
);
562 dev_err(dev
, "can't open stream (%d)\n", ret
);
563 ipu6_put_fw_msg_buf(av
->isys
, (uintptr_t)stream_cfg
);
567 get_stream_opened(av
);
569 tout
= wait_for_completion_timeout(&stream
->stream_open_completion
,
570 IPU6_FW_CALL_TIMEOUT_JIFFIES
);
572 ipu6_put_fw_msg_buf(av
->isys
, (uintptr_t)stream_cfg
);
575 dev_err(dev
, "stream open time out\n");
577 goto out_put_stream_opened
;
580 dev_err(dev
, "stream open error: %d\n", stream
->error
);
582 goto out_put_stream_opened
;
584 dev_dbg(dev
, "start stream: open complete\n");
587 msg
= ipu6_get_fw_msg_buf(stream
);
590 goto out_put_stream_opened
;
592 buf
= &msg
->fw_msg
.frame
;
593 ipu6_isys_buf_to_fw_frame_buf(buf
, stream
, bl
);
594 ipu6_isys_buffer_list_queue(bl
,
595 IPU6_ISYS_BUFFER_LIST_FL_ACTIVE
, 0);
598 reinit_completion(&stream
->stream_start_completion
);
601 send_type
= IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE
;
602 ipu6_fw_isys_dump_frame_buff_set(dev
, buf
,
603 stream_cfg
->nof_output_pins
);
604 ret
= ipu6_fw_isys_complex_cmd(av
->isys
, stream
->stream_handle
,
606 sizeof(*buf
), send_type
);
608 send_type
= IPU6_FW_ISYS_SEND_TYPE_STREAM_START
;
609 ret
= ipu6_fw_isys_simple_cmd(av
->isys
, stream
->stream_handle
,
614 dev_err(dev
, "can't start streaming (%d)\n", ret
);
615 goto out_stream_close
;
618 tout
= wait_for_completion_timeout(&stream
->stream_start_completion
,
619 IPU6_FW_CALL_TIMEOUT_JIFFIES
);
621 dev_err(dev
, "stream start time out\n");
623 goto out_stream_close
;
626 dev_err(dev
, "stream start error: %d\n", stream
->error
);
628 goto out_stream_close
;
630 dev_dbg(dev
, "start stream: complete\n");
635 reinit_completion(&stream
->stream_close_completion
);
637 retout
= ipu6_fw_isys_simple_cmd(av
->isys
,
638 stream
->stream_handle
,
639 IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE
);
641 dev_dbg(dev
, "can't close stream (%d)\n", retout
);
642 goto out_put_stream_opened
;
645 tout
= wait_for_completion_timeout(&stream
->stream_close_completion
,
646 IPU6_FW_CALL_TIMEOUT_JIFFIES
);
648 dev_err(dev
, "stream close time out\n");
649 else if (stream
->error
)
650 dev_err(dev
, "stream close error: %d\n", stream
->error
);
652 dev_dbg(dev
, "stream close complete\n");
654 out_put_stream_opened
:
655 put_stream_opened(av
);
660 static void stop_streaming_firmware(struct ipu6_isys_video
*av
)
662 struct device
*dev
= &av
->isys
->adev
->auxdev
.dev
;
663 struct ipu6_isys_stream
*stream
= av
->stream
;
666 reinit_completion(&stream
->stream_stop_completion
);
668 ret
= ipu6_fw_isys_simple_cmd(av
->isys
, stream
->stream_handle
,
669 IPU6_FW_ISYS_SEND_TYPE_STREAM_FLUSH
);
672 dev_err(dev
, "can't stop stream (%d)\n", ret
);
676 tout
= wait_for_completion_timeout(&stream
->stream_stop_completion
,
677 IPU6_FW_CALL_TIMEOUT_JIFFIES
);
679 dev_warn(dev
, "stream stop time out\n");
680 else if (stream
->error
)
681 dev_warn(dev
, "stream stop error: %d\n", stream
->error
);
683 dev_dbg(dev
, "stop stream: complete\n");
686 static void close_streaming_firmware(struct ipu6_isys_video
*av
)
688 struct ipu6_isys_stream
*stream
= av
->stream
;
689 struct device
*dev
= &av
->isys
->adev
->auxdev
.dev
;
692 reinit_completion(&stream
->stream_close_completion
);
694 ret
= ipu6_fw_isys_simple_cmd(av
->isys
, stream
->stream_handle
,
695 IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE
);
697 dev_err(dev
, "can't close stream (%d)\n", ret
);
701 tout
= wait_for_completion_timeout(&stream
->stream_close_completion
,
702 IPU6_FW_CALL_TIMEOUT_JIFFIES
);
704 dev_warn(dev
, "stream close time out\n");
705 else if (stream
->error
)
706 dev_warn(dev
, "stream close error: %d\n", stream
->error
);
708 dev_dbg(dev
, "close stream: complete\n");
710 put_stream_opened(av
);
713 int ipu6_isys_video_prepare_stream(struct ipu6_isys_video
*av
,
714 struct media_entity
*source_entity
,
717 struct ipu6_isys_stream
*stream
= av
->stream
;
718 struct ipu6_isys_csi2
*csi2
;
720 if (WARN_ON(stream
->nr_streaming
))
723 stream
->nr_queues
= nr_queues
;
724 atomic_set(&stream
->sequence
, 0);
726 stream
->seq_index
= 0;
727 memset(stream
->seq
, 0, sizeof(stream
->seq
));
729 if (WARN_ON(!list_empty(&stream
->queues
)))
732 stream
->stream_source
= stream
->asd
->source
;
733 csi2
= ipu6_isys_subdev_to_csi2(stream
->asd
);
734 csi2
->receiver_errors
= 0;
735 stream
->source_entity
= source_entity
;
737 dev_dbg(&av
->isys
->adev
->auxdev
.dev
,
738 "prepare stream: external entity %s\n",
739 stream
->source_entity
->name
);
744 void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video
*av
,
747 struct ipu6_isys
*isys
= av
->isys
;
748 struct ipu6_isys_csi2
*csi2
= NULL
;
749 struct isys_iwake_watermark
*iwake_watermark
= &isys
->iwake_watermark
;
750 struct device
*dev
= &isys
->adev
->auxdev
.dev
;
751 struct v4l2_mbus_framefmt format
;
752 struct v4l2_subdev
*esd
;
753 struct v4l2_control hb
= { .id
= V4L2_CID_HBLANK
, .value
= 0 };
754 unsigned int bpp
, lanes
;
762 esd
= media_entity_to_v4l2_subdev(av
->stream
->source_entity
);
764 av
->watermark
.width
= ipu6_isys_get_frame_width(av
);
765 av
->watermark
.height
= ipu6_isys_get_frame_height(av
);
766 av
->watermark
.sram_gran_shift
= isys
->pdata
->ipdata
->sram_gran_shift
;
767 av
->watermark
.sram_gran_size
= isys
->pdata
->ipdata
->sram_gran_size
;
769 ret
= v4l2_g_ctrl(esd
->ctrl_handler
, &hb
);
770 if (!ret
&& hb
.value
>= 0)
771 av
->watermark
.hblank
= hb
.value
;
773 av
->watermark
.hblank
= 0;
775 csi2
= ipu6_isys_subdev_to_csi2(av
->stream
->asd
);
776 link_freq
= ipu6_isys_csi2_get_link_freq(csi2
);
778 lanes
= csi2
->nlanes
;
779 ret
= ipu6_isys_get_stream_pad_fmt(&csi2
->asd
.sd
, 0,
780 av
->source_stream
, &format
);
782 bpp
= ipu6_isys_mbus_code_to_bpp(format
.code
);
783 pixel_rate
= mul_u64_u32_div(link_freq
, lanes
* 2, bpp
);
787 av
->watermark
.pixel_rate
= pixel_rate
;
790 mutex_lock(&iwake_watermark
->mutex
);
791 iwake_watermark
->force_iwake_disable
= true;
792 mutex_unlock(&iwake_watermark
->mutex
);
793 dev_warn(dev
, "unexpected pixel_rate from %s, disable iwake.\n",
794 av
->stream
->source_entity
->name
);
798 static void calculate_stream_datarate(struct ipu6_isys_video
*av
)
800 struct video_stream_watermark
*watermark
= &av
->watermark
;
801 const struct ipu6_isys_pixelformat
*pfmt
=
802 ipu6_isys_get_isys_format(ipu6_isys_get_format(av
), 0);
803 u32 pages_per_line
, pb_bytes_per_line
, pixels_per_line
, bytes_per_line
;
804 u64 line_time_ns
, stream_data_rate
;
807 shift
= watermark
->sram_gran_shift
;
808 size
= watermark
->sram_gran_size
;
810 pixels_per_line
= watermark
->width
+ watermark
->hblank
;
811 line_time_ns
= div_u64(pixels_per_line
* NSEC_PER_SEC
,
812 watermark
->pixel_rate
);
813 bytes_per_line
= watermark
->width
* pfmt
->bpp
/ 8;
814 pages_per_line
= DIV_ROUND_UP(bytes_per_line
, size
);
815 pb_bytes_per_line
= pages_per_line
<< shift
;
816 stream_data_rate
= div64_u64(pb_bytes_per_line
* 1000, line_time_ns
);
818 watermark
->stream_data_rate
= stream_data_rate
;
821 void ipu6_isys_update_stream_watermark(struct ipu6_isys_video
*av
, bool state
)
823 struct isys_iwake_watermark
*iwake_watermark
=
824 &av
->isys
->iwake_watermark
;
826 if (!av
->watermark
.pixel_rate
)
830 calculate_stream_datarate(av
);
831 mutex_lock(&iwake_watermark
->mutex
);
832 list_add(&av
->watermark
.stream_node
,
833 &iwake_watermark
->video_list
);
834 mutex_unlock(&iwake_watermark
->mutex
);
836 av
->watermark
.stream_data_rate
= 0;
837 mutex_lock(&iwake_watermark
->mutex
);
838 list_del(&av
->watermark
.stream_node
);
839 mutex_unlock(&iwake_watermark
->mutex
);
842 update_watermark_setting(av
->isys
);
845 void ipu6_isys_put_stream(struct ipu6_isys_stream
*stream
)
852 pr_err("ipu6-isys: no available stream\n");
856 dev
= &stream
->isys
->adev
->auxdev
.dev
;
858 spin_lock_irqsave(&stream
->isys
->streams_lock
, flags
);
859 for (i
= 0; i
< IPU6_ISYS_MAX_STREAMS
; i
++) {
860 if (&stream
->isys
->streams
[i
] == stream
) {
861 if (stream
->isys
->streams_ref_count
[i
] > 0)
862 stream
->isys
->streams_ref_count
[i
]--;
864 dev_warn(dev
, "invalid stream %d\n", i
);
869 spin_unlock_irqrestore(&stream
->isys
->streams_lock
, flags
);
872 static struct ipu6_isys_stream
*
873 ipu6_isys_get_stream(struct ipu6_isys_video
*av
, struct ipu6_isys_subdev
*asd
)
875 struct ipu6_isys_stream
*stream
= NULL
;
876 struct ipu6_isys
*isys
= av
->isys
;
884 spin_lock_irqsave(&isys
->streams_lock
, flags
);
885 for (i
= 0; i
< IPU6_ISYS_MAX_STREAMS
; i
++) {
886 if (isys
->streams_ref_count
[i
] && isys
->streams
[i
].vc
== vc
&&
887 isys
->streams
[i
].asd
== asd
) {
888 isys
->streams_ref_count
[i
]++;
889 stream
= &isys
->streams
[i
];
895 for (i
= 0; i
< IPU6_ISYS_MAX_STREAMS
; i
++) {
896 if (!isys
->streams_ref_count
[i
]) {
897 isys
->streams_ref_count
[i
]++;
898 stream
= &isys
->streams
[i
];
905 spin_unlock_irqrestore(&isys
->streams_lock
, flags
);
910 struct ipu6_isys_stream
*
911 ipu6_isys_query_stream_by_handle(struct ipu6_isys
*isys
, u8 stream_handle
)
914 struct ipu6_isys_stream
*stream
= NULL
;
919 if (stream_handle
>= IPU6_ISYS_MAX_STREAMS
) {
920 dev_err(&isys
->adev
->auxdev
.dev
,
921 "stream_handle %d is invalid\n", stream_handle
);
925 spin_lock_irqsave(&isys
->streams_lock
, flags
);
926 if (isys
->streams_ref_count
[stream_handle
] > 0) {
927 isys
->streams_ref_count
[stream_handle
]++;
928 stream
= &isys
->streams
[stream_handle
];
930 spin_unlock_irqrestore(&isys
->streams_lock
, flags
);
935 struct ipu6_isys_stream
*
936 ipu6_isys_query_stream_by_source(struct ipu6_isys
*isys
, int source
, u8 vc
)
938 struct ipu6_isys_stream
*stream
= NULL
;
946 dev_err(&isys
->adev
->auxdev
.dev
,
947 "query stream with invalid port number\n");
951 spin_lock_irqsave(&isys
->streams_lock
, flags
);
952 for (i
= 0; i
< IPU6_ISYS_MAX_STREAMS
; i
++) {
953 if (!isys
->streams_ref_count
[i
])
956 if (isys
->streams
[i
].stream_source
== source
&&
957 isys
->streams
[i
].vc
== vc
) {
958 stream
= &isys
->streams
[i
];
959 isys
->streams_ref_count
[i
]++;
963 spin_unlock_irqrestore(&isys
->streams_lock
, flags
);
968 static u64
get_stream_mask_by_pipeline(struct ipu6_isys_video
*__av
)
970 struct media_pipeline
*pipeline
=
971 media_entity_pipeline(&__av
->vdev
.entity
);
975 for (i
= 0; i
< NR_OF_CSI2_SRC_PADS
; i
++) {
976 struct ipu6_isys_video
*av
= &__av
->csi2
->av
[i
];
978 if (pipeline
== media_entity_pipeline(&av
->vdev
.entity
))
979 stream_mask
|= BIT_ULL(av
->source_stream
);
985 int ipu6_isys_video_set_streaming(struct ipu6_isys_video
*av
, int state
,
986 struct ipu6_isys_buffer_list
*bl
)
988 struct v4l2_subdev_krouting
*routing
;
989 struct ipu6_isys_stream
*stream
= av
->stream
;
990 struct v4l2_subdev_state
*subdev_state
;
991 struct device
*dev
= &av
->isys
->adev
->auxdev
.dev
;
992 struct v4l2_subdev
*sd
;
993 struct media_pad
*r_pad
;
994 u32 sink_pad
, sink_stream
;
999 dev_dbg(dev
, "set stream: %d\n", state
);
1001 if (WARN(!stream
->source_entity
, "No source entity for stream\n"))
1004 sd
= &stream
->asd
->sd
;
1005 r_pad
= media_pad_remote_pad_first(&av
->pad
);
1006 r_stream
= ipu6_isys_get_src_stream_by_src_pad(sd
, r_pad
->index
);
1008 subdev_state
= v4l2_subdev_lock_and_get_active_state(sd
);
1009 routing
= &subdev_state
->routing
;
1010 ret
= v4l2_subdev_routing_find_opposite_end(routing
, r_pad
->index
,
1011 r_stream
, &sink_pad
,
1013 v4l2_subdev_unlock_state(subdev_state
);
1017 stream_mask
= get_stream_mask_by_pipeline(av
);
1019 stop_streaming_firmware(av
);
1021 /* stop sub-device which connects with video */
1022 dev_dbg(dev
, "stream off entity %s pad:%d mask:0x%llx\n",
1023 sd
->name
, r_pad
->index
, stream_mask
);
1024 ret
= v4l2_subdev_disable_streams(sd
, r_pad
->index
,
1027 dev_err(dev
, "stream off %s failed with %d\n", sd
->name
,
1031 close_streaming_firmware(av
);
1033 ret
= start_stream_firmware(av
, bl
);
1035 dev_err(dev
, "start stream of firmware failed\n");
1039 /* start sub-device which connects with video */
1040 dev_dbg(dev
, "stream on %s pad %d mask 0x%llx\n", sd
->name
,
1041 r_pad
->index
, stream_mask
);
1042 ret
= v4l2_subdev_enable_streams(sd
, r_pad
->index
, stream_mask
);
1044 dev_err(dev
, "stream on %s failed with %d\n", sd
->name
,
1046 goto out_media_entity_stop_streaming_firmware
;
1050 av
->streaming
= state
;
1054 out_media_entity_stop_streaming_firmware
:
1055 stop_streaming_firmware(av
);
1060 static const struct v4l2_ioctl_ops ipu6_v4l2_ioctl_ops
= {
1061 .vidioc_querycap
= ipu6_isys_vidioc_querycap
,
1062 .vidioc_enum_fmt_vid_cap
= ipu6_isys_vidioc_enum_fmt
,
1063 .vidioc_enum_fmt_meta_cap
= ipu6_isys_vidioc_enum_fmt
,
1064 .vidioc_enum_framesizes
= ipu6_isys_vidioc_enum_framesizes
,
1065 .vidioc_g_fmt_vid_cap
= ipu6_isys_vidioc_g_fmt_vid_cap
,
1066 .vidioc_s_fmt_vid_cap
= ipu6_isys_vidioc_s_fmt_vid_cap
,
1067 .vidioc_try_fmt_vid_cap
= ipu6_isys_vidioc_try_fmt_vid_cap
,
1068 .vidioc_g_fmt_meta_cap
= ipu6_isys_vidioc_g_fmt_meta_cap
,
1069 .vidioc_s_fmt_meta_cap
= ipu6_isys_vidioc_s_fmt_meta_cap
,
1070 .vidioc_try_fmt_meta_cap
= ipu6_isys_vidioc_try_fmt_meta_cap
,
1071 .vidioc_reqbufs
= ipu6_isys_vidioc_reqbufs
,
1072 .vidioc_create_bufs
= ipu6_isys_vidioc_create_bufs
,
1073 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
1074 .vidioc_querybuf
= vb2_ioctl_querybuf
,
1075 .vidioc_qbuf
= vb2_ioctl_qbuf
,
1076 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
1077 .vidioc_streamon
= vb2_ioctl_streamon
,
1078 .vidioc_streamoff
= vb2_ioctl_streamoff
,
1079 .vidioc_expbuf
= vb2_ioctl_expbuf
,
1082 static const struct media_entity_operations entity_ops
= {
1083 .link_validate
= link_validate
,
1086 static const struct v4l2_file_operations isys_fops
= {
1087 .owner
= THIS_MODULE
,
1088 .poll
= vb2_fop_poll
,
1089 .unlocked_ioctl
= video_ioctl2
,
1090 .mmap
= vb2_fop_mmap
,
1092 .release
= vb2_fop_release
,
1095 int ipu6_isys_fw_open(struct ipu6_isys
*isys
)
1097 struct ipu6_bus_device
*adev
= isys
->adev
;
1098 const struct ipu6_isys_internal_pdata
*ipdata
= isys
->pdata
->ipdata
;
1101 ret
= pm_runtime_resume_and_get(&adev
->auxdev
.dev
);
1105 mutex_lock(&isys
->mutex
);
1107 if (isys
->ref_count
++)
1110 ipu6_configure_spc(adev
->isp
, &ipdata
->hw_variant
,
1111 IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX
, isys
->pdata
->base
,
1112 adev
->pkg_dir
, adev
->pkg_dir_dma_addr
);
1115 * Buffers could have been left to wrong queue at last closure.
1116 * Move them now back to empty buffer queue.
1118 ipu6_cleanup_fw_msg_bufs(isys
);
1122 * Something went wrong in previous shutdown. As we are now
1123 * restarting isys we can safely delete old context.
1125 dev_warn(&adev
->auxdev
.dev
, "clearing old context\n");
1126 ipu6_fw_isys_cleanup(isys
);
1129 ret
= ipu6_fw_isys_init(isys
, ipdata
->num_parallel_streams
);
1134 mutex_unlock(&isys
->mutex
);
1140 mutex_unlock(&isys
->mutex
);
1141 pm_runtime_put(&adev
->auxdev
.dev
);
1146 void ipu6_isys_fw_close(struct ipu6_isys
*isys
)
1148 mutex_lock(&isys
->mutex
);
1151 if (!isys
->ref_count
) {
1152 ipu6_fw_isys_close(isys
);
1154 isys
->need_reset
= true;
1155 dev_warn(&isys
->adev
->auxdev
.dev
,
1156 "failed to close fw isys\n");
1160 mutex_unlock(&isys
->mutex
);
1162 if (isys
->need_reset
)
1163 pm_runtime_put_sync(&isys
->adev
->auxdev
.dev
);
1165 pm_runtime_put(&isys
->adev
->auxdev
.dev
);
1168 int ipu6_isys_setup_video(struct ipu6_isys_video
*av
,
1169 struct media_entity
**source_entity
, int *nr_queues
)
1171 const struct ipu6_isys_pixelformat
*pfmt
=
1172 ipu6_isys_get_isys_format(ipu6_isys_get_format(av
), 0);
1173 struct device
*dev
= &av
->isys
->adev
->auxdev
.dev
;
1174 struct v4l2_mbus_frame_desc_entry entry
;
1175 struct v4l2_subdev_route
*route
= NULL
;
1176 struct v4l2_subdev_route
*r
;
1177 struct v4l2_subdev_state
*state
;
1178 struct ipu6_isys_subdev
*asd
;
1179 struct v4l2_subdev
*remote_sd
;
1180 struct media_pipeline
*pipeline
;
1181 struct media_pad
*source_pad
, *remote_pad
;
1186 remote_pad
= media_pad_remote_pad_unique(&av
->pad
);
1187 if (IS_ERR(remote_pad
)) {
1188 dev_dbg(dev
, "failed to get remote pad\n");
1189 return PTR_ERR(remote_pad
);
1192 remote_sd
= media_entity_to_v4l2_subdev(remote_pad
->entity
);
1193 asd
= to_ipu6_isys_subdev(remote_sd
);
1194 source_pad
= media_pad_remote_pad_first(&remote_pad
->entity
->pads
[0]);
1196 dev_dbg(dev
, "No external source entity\n");
1200 *source_entity
= source_pad
->entity
;
1203 state
= v4l2_subdev_lock_and_get_active_state(remote_sd
);
1204 for_each_active_route(&state
->routing
, r
) {
1207 if (r
->source_pad
== remote_pad
->index
)
1212 v4l2_subdev_unlock_state(state
);
1213 dev_dbg(dev
, "Failed to find route\n");
1216 av
->source_stream
= route
->sink_stream
;
1217 v4l2_subdev_unlock_state(state
);
1219 ret
= ipu6_isys_csi2_get_remote_desc(av
->source_stream
,
1220 to_ipu6_isys_csi2(asd
),
1221 *source_entity
, &entry
);
1222 if (ret
== -ENOIOCTLCMD
) {
1224 av
->dt
= ipu6_isys_mbus_code_to_mipi(pfmt
->code
);
1226 dev_dbg(dev
, "Framedesc: stream %u, len %u, vc %u, dt %#x\n",
1227 entry
.stream
, entry
.length
, entry
.bus
.csi2
.vc
,
1230 av
->vc
= entry
.bus
.csi2
.vc
;
1231 av
->dt
= entry
.bus
.csi2
.dt
;
1233 dev_err(dev
, "failed to get remote frame desc\n");
1237 pipeline
= media_entity_pipeline(&av
->vdev
.entity
);
1239 ret
= video_device_pipeline_alloc_start(&av
->vdev
);
1241 ret
= video_device_pipeline_start(&av
->vdev
, pipeline
);
1243 dev_dbg(dev
, "media pipeline start failed\n");
1247 av
->stream
= ipu6_isys_get_stream(av
, asd
);
1249 video_device_pipeline_stop(&av
->vdev
);
1250 dev_err(dev
, "no available stream for firmware\n");
1258 * Do everything that's needed to initialise things related to video
1259 * buffer queue, video node, and the related media entity. The caller
1260 * is expected to assign isys field and set the name of the video
1263 int ipu6_isys_video_init(struct ipu6_isys_video
*av
)
1265 struct v4l2_format format
= {
1266 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
1272 struct v4l2_format format_meta
= {
1273 .type
= V4L2_BUF_TYPE_META_CAPTURE
,
1281 mutex_init(&av
->mutex
);
1282 av
->vdev
.device_caps
= V4L2_CAP_STREAMING
| V4L2_CAP_IO_MC
|
1283 V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_META_CAPTURE
;
1284 av
->vdev
.vfl_dir
= VFL_DIR_RX
;
1286 ret
= ipu6_isys_queue_init(&av
->aq
);
1288 goto out_free_watermark
;
1290 av
->pad
.flags
= MEDIA_PAD_FL_SINK
| MEDIA_PAD_FL_MUST_CONNECT
;
1291 ret
= media_entity_pads_init(&av
->vdev
.entity
, 1, &av
->pad
);
1293 goto out_vb2_queue_release
;
1295 av
->vdev
.entity
.ops
= &entity_ops
;
1296 av
->vdev
.release
= video_device_release_empty
;
1297 av
->vdev
.fops
= &isys_fops
;
1298 av
->vdev
.v4l2_dev
= &av
->isys
->v4l2_dev
;
1299 if (!av
->vdev
.ioctl_ops
)
1300 av
->vdev
.ioctl_ops
= &ipu6_v4l2_ioctl_ops
;
1301 av
->vdev
.queue
= &av
->aq
.vbq
;
1302 av
->vdev
.lock
= &av
->mutex
;
1304 __ipu6_isys_vidioc_try_fmt_vid_cap(av
, &format
);
1305 av
->pix_fmt
= format
.fmt
.pix
;
1306 __ipu6_isys_vidioc_try_fmt_meta_cap(av
, &format_meta
);
1307 av
->meta_fmt
= format_meta
.fmt
.meta
;
1309 set_bit(V4L2_FL_USES_V4L2_FH
, &av
->vdev
.flags
);
1310 video_set_drvdata(&av
->vdev
, av
);
1312 ret
= video_register_device(&av
->vdev
, VFL_TYPE_VIDEO
, -1);
1314 goto out_media_entity_cleanup
;
1318 out_media_entity_cleanup
:
1319 vb2_video_unregister_device(&av
->vdev
);
1320 media_entity_cleanup(&av
->vdev
.entity
);
1322 out_vb2_queue_release
:
1323 vb2_queue_release(&av
->aq
.vbq
);
1326 mutex_destroy(&av
->mutex
);
1331 void ipu6_isys_video_cleanup(struct ipu6_isys_video
*av
)
1333 vb2_video_unregister_device(&av
->vdev
);
1334 media_entity_cleanup(&av
->vdev
.entity
);
1335 mutex_destroy(&av
->mutex
);
1338 u32
ipu6_isys_get_format(struct ipu6_isys_video
*av
)
1340 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1341 return av
->pix_fmt
.pixelformat
;
1343 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_META_CAPTURE
)
1344 return av
->meta_fmt
.dataformat
;
1349 u32
ipu6_isys_get_data_size(struct ipu6_isys_video
*av
)
1351 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1352 return av
->pix_fmt
.sizeimage
;
1354 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_META_CAPTURE
)
1355 return av
->meta_fmt
.buffersize
;
1360 u32
ipu6_isys_get_bytes_per_line(struct ipu6_isys_video
*av
)
1362 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1363 return av
->pix_fmt
.bytesperline
;
1365 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_META_CAPTURE
)
1366 return av
->meta_fmt
.bytesperline
;
1371 u32
ipu6_isys_get_frame_width(struct ipu6_isys_video
*av
)
1373 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1374 return av
->pix_fmt
.width
;
1376 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_META_CAPTURE
)
1377 return av
->meta_fmt
.width
;
1382 u32
ipu6_isys_get_frame_height(struct ipu6_isys_video
*av
)
1384 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1385 return av
->pix_fmt
.height
;
1387 if (av
->aq
.vbq
.type
== V4L2_BUF_TYPE_META_CAPTURE
)
1388 return av
->meta_fmt
.height
;