1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 StarFive Technology Co., Ltd.
7 #include <media/media-entity.h>
8 #include <media/v4l2-mc.h>
9 #include <media/videobuf2-dma-sg.h>
10 #include <media/videobuf2-vmalloc.h>
11 #include <media/videobuf2-dma-contig.h>
13 #define USE_MEDIA_PIPELINE
15 static const struct stfcamss_format_info formats_pix_st7110_wr[] = {
16 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
17 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
18 { MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_PIX_FMT_RGB565, 1,
19 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
20 { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1,
21 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
22 { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1,
23 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
24 { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1,
25 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
26 { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1,
27 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
28 { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 1,
29 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
30 { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 1,
31 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
32 { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 1,
33 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
34 { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 1,
35 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
38 static const struct stfcamss_format_info formats_raw_st7110_isp[] = {
39 { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 1,
40 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
41 { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 1,
42 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
43 { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 1,
44 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
45 { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 1,
46 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
49 static const struct stfcamss_format_info formats_pix_st7110_isp[] = {
50 // { MEDIA_BUS_FMT_YUYV12_2X12, V4L2_PIX_FMT_NV12M, 2,
51 // { { 1, 1 }, { 1, 1 } }, { { 1, 1 }, { 1, 1 } }, { 8 , 4 } },
52 { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1,
53 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
54 { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV21, 1,
55 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
58 static const struct stfcamss_format_info formats_st7110_isp_iti[] = {
60 { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 1,
61 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
62 { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 1,
63 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
64 { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 1,
65 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
66 { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 1,
67 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
68 { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 1,
69 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
70 { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 1,
71 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
72 { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 1,
73 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
74 { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 1,
75 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
78 { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1,
79 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
80 { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV21, 1,
81 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
84 { MEDIA_BUS_FMT_YUV8_1X24, V4L2_PIX_FMT_NV24, 1,
85 { { 1, 1 } }, { { 1, 3 } }, { 8 } },
86 { MEDIA_BUS_FMT_VUY8_1X24, V4L2_PIX_FMT_NV42, 1,
87 { { 1, 1 } }, { { 1, 3 } }, { 8 } },
90 static int video_find_format(u32 code, u32 pixelformat,
91 const struct stfcamss_format_info *formats,
92 unsigned int nformats)
96 for (i = 0; i < nformats; i++) {
97 if (formats[i].code == code &&
98 formats[i].pixelformat == pixelformat)
102 for (i = 0; i < nformats; i++)
103 if (formats[i].code == code)
106 for (i = 0; i < nformats; i++)
107 if (formats[i].pixelformat == pixelformat)
113 static int __video_try_fmt(struct stfcamss_video *video,
114 struct v4l2_format *f, int is_mp)
116 struct v4l2_pix_format *pix;
117 struct v4l2_pix_format_mplane *pix_mp;
118 const struct stfcamss_format_info *fi;
123 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
125 pix_mp = &f->fmt.pix_mp;
128 for (i = 0; i < video->nformats; i++)
129 if (pix_mp->pixelformat
130 == video->formats[i].pixelformat)
133 if (i == video->nformats)
134 i = 0; /* default format */
136 fi = &video->formats[i];
137 width = pix_mp->width;
138 height = pix_mp->height;
140 memset(pix_mp, 0, sizeof(*pix_mp));
142 pix_mp->pixelformat = fi->pixelformat;
143 pix_mp->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH,
144 STFCAMSS_FRAME_MAX_WIDTH);
145 pix_mp->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT,
146 STFCAMSS_FRAME_MAX_HEIGHT);
147 pix_mp->num_planes = fi->planes;
148 for (j = 0; j < pix_mp->num_planes; j++) {
149 bpl = pix_mp->width / fi->hsub[j].numerator *
150 fi->hsub[j].denominator * fi->bpp[j] / 8;
151 bpl = ALIGN(bpl, video->bpl_alignment);
152 pix_mp->plane_fmt[j].bytesperline = bpl;
153 pix_mp->plane_fmt[j].sizeimage = pix_mp->height /
154 fi->vsub[j].numerator
155 * fi->vsub[j].denominator * bpl;
158 pix_mp->field = V4L2_FIELD_NONE;
159 pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
162 V4L2_MAP_YCBCR_ENC_DEFAULT(pix_mp->colorspace);
163 pix_mp->quantization =
164 V4L2_MAP_QUANTIZATION_DEFAULT(true,
165 pix_mp->colorspace, pix_mp->ycbcr_enc);
167 V4L2_MAP_XFER_FUNC_DEFAULT(pix_mp->colorspace);
169 st_info(ST_VIDEO, "w, h = %d, %d, bpp = %d\n", pix_mp->width,
170 pix_mp->height, fi->bpp[0]);
171 st_info(ST_VIDEO, "i = %d, p = %d, s = 0x%x\n", i,
172 pix_mp->num_planes, pix_mp->plane_fmt[0].sizeimage);
175 for (i = 0; i < video->nformats; i++)
176 if (pix->pixelformat == video->formats[i].pixelformat)
179 if (i == video->nformats)
180 i = 0; /* default format */
182 fi = &video->formats[i];
184 height = pix->height;
186 memset(pix, 0, sizeof(*pix));
188 pix->pixelformat = fi->pixelformat;
189 pix->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH,
190 STFCAMSS_FRAME_MAX_WIDTH);
191 pix->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT,
192 STFCAMSS_FRAME_MAX_HEIGHT);
193 bpl = pix->width / fi->hsub[0].numerator *
194 fi->hsub[0].denominator * fi->bpp[0] / 8;
195 bpl = ALIGN(bpl, video->bpl_alignment);
196 pix->bytesperline = bpl;
197 pix->sizeimage = pix->height /
198 fi->vsub[0].numerator
199 * fi->vsub[0].denominator * bpl;
201 pix->field = V4L2_FIELD_NONE;
202 pix->colorspace = V4L2_COLORSPACE_SRGB;
205 V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
207 V4L2_MAP_QUANTIZATION_DEFAULT(true,
208 pix->colorspace, pix->ycbcr_enc);
210 V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
212 st_info(ST_VIDEO, "w, h = %d, %d, bpp = %d\n", pix->width,
213 pix->height, fi->bpp[0]);
214 st_info(ST_VIDEO, "i = %d, s = 0x%x\n", i, pix->sizeimage);
219 static int stf_video_init_format(struct stfcamss_video *video, int is_mp)
222 struct v4l2_format format = {
227 .pixelformat = V4L2_PIX_FMT_RGB565,
231 ret = __video_try_fmt(video, &format, is_mp);
236 video->active_fmt = format;
241 static int video_queue_setup(struct vb2_queue *q,
242 unsigned int *num_buffers, unsigned int *num_planes,
243 unsigned int sizes[], struct device *alloc_devs[])
245 struct stfcamss_video *video = vb2_get_drv_priv(q);
246 const struct v4l2_pix_format *format =
247 &video->active_fmt.fmt.pix;
248 const struct v4l2_pix_format_mplane *format_mp =
249 &video->active_fmt.fmt.pix_mp;
252 st_debug(ST_VIDEO, "%s, planes = %d\n", __func__, *num_planes);
256 if (*num_planes != format_mp->num_planes)
259 for (i = 0; i < *num_planes; i++)
261 format_mp->plane_fmt[i].sizeimage)
267 *num_planes = format_mp->num_planes;
269 for (i = 0; i < *num_planes; i++)
270 sizes[i] = format_mp->plane_fmt[i].sizeimage;
273 if (*num_planes != 1)
276 if (sizes[0] < format->sizeimage)
281 sizes[0] = format->sizeimage;
283 st_err(ST_VIDEO, "%s: error size is zero!!!\n", __func__);
285 if ((stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC)
286 == STF_ISP_PAD_SRC_SCD_Y) &&
287 sizes[0] < ISP_SCD_Y_BUFFER_SIZE) {
288 sizes[0] = ISP_SCD_Y_BUFFER_SIZE;
291 st_info(ST_VIDEO, "%s, planes = %d, size = %d\n",
292 __func__, *num_planes, sizes[0]);
296 static int video_buf_init(struct vb2_buffer *vb)
298 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
299 struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
300 struct stfcamss_buffer *buffer =
301 container_of(vbuf, struct stfcamss_buffer, vb);
302 const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
303 const struct v4l2_pix_format_mplane *fmt_mp =
304 &video->active_fmt.fmt.pix_mp;
305 //struct sg_table *sgt;
308 buffer->sizeimage = 0;
311 for (i = 0; i < fmt_mp->num_planes; i++) {
312 paddr = vb2_plane_cookie(vb, i);
313 buffer->addr[i] = *paddr;
314 buffer->sizeimage += vb2_plane_size(vb, i);
317 if (fmt_mp->num_planes == 1
318 && (fmt_mp->pixelformat == V4L2_PIX_FMT_NV12
319 || fmt_mp->pixelformat == V4L2_PIX_FMT_NV21
320 || fmt_mp->pixelformat == V4L2_PIX_FMT_NV16
321 || fmt_mp->pixelformat == V4L2_PIX_FMT_NV61))
322 buffer->addr[1] = buffer->addr[0] +
323 fmt_mp->plane_fmt[0].bytesperline *
326 paddr = vb2_plane_cookie(vb, 0);
327 buffer->sizeimage = vb2_plane_size(vb, 0);
328 buffer->addr[0] = *paddr;
329 if (fmt->pixelformat == V4L2_PIX_FMT_NV12
330 || fmt->pixelformat == V4L2_PIX_FMT_NV21
331 || fmt->pixelformat == V4L2_PIX_FMT_NV16
332 || fmt->pixelformat == V4L2_PIX_FMT_NV61)
333 buffer->addr[1] = buffer->addr[0] +
338 if (stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC)
339 == STF_ISP_PAD_SRC_SCD_Y)
340 buffer->addr[1] = buffer->addr[0] + ISP_YHIST_BUFFER_SIZE;
345 static int video_buf_prepare(struct vb2_buffer *vb)
347 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
348 struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
349 const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
350 const struct v4l2_pix_format_mplane *fmt_mp =
351 &video->active_fmt.fmt.pix_mp;
355 for (i = 0; i < fmt_mp->num_planes; i++) {
356 if (fmt_mp->plane_fmt[i].sizeimage
357 > vb2_plane_size(vb, i))
360 vb2_set_plane_payload(vb, i,
361 fmt_mp->plane_fmt[i].sizeimage);
364 if (fmt->sizeimage > vb2_plane_size(vb, 0)) {
365 st_err(ST_VIDEO, "sizeimage = %d, plane size = %d\n",
366 fmt->sizeimage, (unsigned int)vb2_plane_size(vb, 0));
369 vb2_set_plane_payload(vb, 0, fmt->sizeimage);
372 vbuf->field = V4L2_FIELD_NONE;
377 static void video_buf_queue(struct vb2_buffer *vb)
379 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
380 struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
381 struct stfcamss_buffer *buffer =
382 container_of(vbuf, struct stfcamss_buffer, vb);
384 video->ops->queue_buffer(video, buffer);
387 static int video_mbus_to_pix_mp(const struct v4l2_mbus_framefmt *mbus,
388 struct v4l2_pix_format_mplane *pix,
389 const struct stfcamss_format_info *f,
390 unsigned int alignment)
395 memset(pix, 0, sizeof(*pix));
396 v4l2_fill_pix_format_mplane(pix, mbus);
397 pix->pixelformat = f->pixelformat;
398 pix->num_planes = f->planes;
399 for (i = 0; i < pix->num_planes; i++) {
400 bytesperline = pix->width / f->hsub[i].numerator *
401 f->hsub[i].denominator * f->bpp[i] / 8;
402 bytesperline = ALIGN(bytesperline, alignment);
403 pix->plane_fmt[i].bytesperline = bytesperline;
404 pix->plane_fmt[i].sizeimage = pix->height /
405 f->vsub[i].numerator * f->vsub[i].denominator *
412 static int video_mbus_to_pix(const struct v4l2_mbus_framefmt *mbus,
413 struct v4l2_pix_format *pix,
414 const struct stfcamss_format_info *f,
415 unsigned int alignment)
419 memset(pix, 0, sizeof(*pix));
420 v4l2_fill_pix_format(pix, mbus);
421 pix->pixelformat = f->pixelformat;
422 bytesperline = pix->width / f->hsub[0].numerator *
423 f->hsub[0].denominator * f->bpp[0] / 8;
424 bytesperline = ALIGN(bytesperline, alignment);
425 pix->bytesperline = bytesperline;
426 pix->sizeimage = pix->height /
427 f->vsub[0].numerator * f->vsub[0].denominator *
432 static struct v4l2_subdev *video_remote_subdev(
433 struct stfcamss_video *video, u32 *pad)
435 struct media_pad *remote;
437 remote = media_entity_remote_pad(&video->pad);
439 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
443 *pad = remote->index;
445 return media_entity_to_v4l2_subdev(remote->entity);
448 static int video_get_subdev_format(struct stfcamss_video *video,
449 struct v4l2_format *format)
451 struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
452 struct v4l2_pix_format_mplane *pix_mp =
453 &video->active_fmt.fmt.pix_mp;
454 struct v4l2_subdev_format fmt;
455 struct v4l2_subdev *subdev;
460 subdev = video_remote_subdev(video, &pad);
465 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
467 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
472 pixelformat = pix_mp->pixelformat;
474 pixelformat = pix->pixelformat;
475 ret = video_find_format(fmt.format.code, pixelformat,
476 video->formats, video->nformats);
480 format->type = video->type;
483 return video_mbus_to_pix_mp(&fmt.format, &format->fmt.pix_mp,
484 &video->formats[ret], video->bpl_alignment);
486 return video_mbus_to_pix(&fmt.format, &format->fmt.pix,
487 &video->formats[ret], video->bpl_alignment);
490 static int video_check_format(struct stfcamss_video *video)
492 struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
493 struct v4l2_pix_format_mplane *pix_mp =
494 &video->active_fmt.fmt.pix_mp;
495 struct v4l2_format format;
496 struct v4l2_pix_format *sd_pix = &format.fmt.pix;
497 struct v4l2_pix_format_mplane *sd_pix_mp = &format.fmt.pix_mp;
501 sd_pix_mp->pixelformat = pix_mp->pixelformat;
502 ret = video_get_subdev_format(video, &format);
506 if (pix_mp->pixelformat != sd_pix_mp->pixelformat ||
507 pix_mp->height > sd_pix_mp->height ||
508 pix_mp->width > sd_pix_mp->width ||
509 pix_mp->num_planes != sd_pix_mp->num_planes ||
510 pix_mp->field != format.fmt.pix_mp.field) {
513 "0x%x 0x%x\n0x%x 0x%x\n0x%x 0x%x\n",
515 pix_mp->pixelformat, sd_pix_mp->pixelformat,
516 pix_mp->height, sd_pix_mp->height,
517 pix_mp->field, format.fmt.pix_mp.field);
522 sd_pix->pixelformat = pix->pixelformat;
523 ret = video_get_subdev_format(video, &format);
527 if (pix->pixelformat != sd_pix->pixelformat ||
528 pix->height > sd_pix->height ||
529 pix->width > sd_pix->width ||
530 pix->field != format.fmt.pix.field) {
533 "0x%x 0x%x\n0x%x 0x%x\n0x%x 0x%x\n",
535 pix->pixelformat, sd_pix->pixelformat,
536 pix->height, sd_pix->height,
537 pix->field, format.fmt.pix.field);
544 static int video_start_streaming(struct vb2_queue *q, unsigned int count)
546 struct stfcamss_video *video = vb2_get_drv_priv(q);
547 struct video_device *vdev = &video->vdev;
548 struct media_entity *entity;
549 struct media_pad *pad;
550 struct v4l2_subdev *subdev;
553 #ifdef USE_MEDIA_PIPELINE
554 // ret = media_pipeline_start(&vdev->entity, &video->pipe);
555 ret = media_pipeline_start(&vdev->entity, &video->stfcamss->pipe);
558 "Failed to media_pipeline_start: %d\n", ret);
562 ret = video_check_format(video);
565 entity = &vdev->entity;
567 pad = &entity->pads[0];
568 if (!(pad->flags & MEDIA_PAD_FL_SINK))
571 pad = media_entity_remote_pad(pad);
572 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
575 entity = pad->entity;
576 subdev = media_entity_to_v4l2_subdev(entity);
578 ret = v4l2_subdev_call(subdev, video, s_stream, 1);
579 if (ret < 0 && ret != -ENOIOCTLCMD)
585 #ifdef USE_MEDIA_PIPELINE
586 media_pipeline_stop(&vdev->entity);
588 video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
592 static void video_stop_streaming(struct vb2_queue *q)
594 struct stfcamss_video *video = vb2_get_drv_priv(q);
595 struct video_device *vdev = &video->vdev;
596 struct media_entity *entity;
597 struct media_pad *pad;
598 struct v4l2_subdev *subdev;
600 entity = &vdev->entity;
602 pad = &entity->pads[0];
603 if (!(pad->flags & MEDIA_PAD_FL_SINK))
606 pad = media_entity_remote_pad(pad);
607 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
610 entity = pad->entity;
611 subdev = media_entity_to_v4l2_subdev(entity);
613 v4l2_subdev_call(subdev, video, s_stream, 0);
616 #ifdef USE_MEDIA_PIPELINE
617 media_pipeline_stop(&vdev->entity);
619 video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
622 static const struct vb2_ops stf_video_vb2_q_ops = {
623 .queue_setup = video_queue_setup,
624 .wait_prepare = vb2_ops_wait_prepare,
625 .wait_finish = vb2_ops_wait_finish,
626 .buf_init = video_buf_init,
627 .buf_prepare = video_buf_prepare,
628 .buf_queue = video_buf_queue,
629 .start_streaming = video_start_streaming,
630 .stop_streaming = video_stop_streaming,
633 /* -----------------------------------------------------
637 static int getcrop_pad_id(int video_id)
639 return stf_vin_map_isp_pad(video_id, STF_ISP_PAD_SRC);
642 static int video_querycap(struct file *file, void *fh,
643 struct v4l2_capability *cap)
645 struct stfcamss_video *video = video_drvdata(file);
647 strscpy(cap->driver, "stf camss", sizeof(cap->driver));
648 strscpy(cap->card, "Starfive Camera Subsystem", sizeof(cap->card));
649 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
650 dev_name(video->stfcamss->dev));
654 static int video_get_unique_pixelformat_by_index(struct stfcamss_video *video,
659 /* find index "i" of "k"th unique pixelformat in formats array */
661 for (i = 0; i < video->nformats; i++) {
662 for (j = 0; j < i; j++) {
663 if (video->formats[i].pixelformat ==
664 video->formats[j].pixelformat)
678 static int video_get_pixelformat_by_mbus_code(struct stfcamss_video *video,
683 for (i = 0; i < video->nformats; i++) {
684 if (video->formats[i].code == mcode)
691 static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
693 struct stfcamss_video *video = video_drvdata(file);
696 st_debug(ST_VIDEO, "%s:\n0x%x 0x%x\n 0x%x, 0x%x\n0x%x\n",
698 f->type, video->type,
699 f->index, video->nformats,
702 if (f->type != video->type)
704 if (f->index >= video->nformats)
708 /* Each entry in formats[] table has unique mbus_code */
712 i = video_get_pixelformat_by_mbus_code(video, f->mbus_code);
714 i = video_get_unique_pixelformat_by_index(video, f->index);
720 f->pixelformat = video->formats[i].pixelformat;
725 static struct v4l2_subdev *get_senname(struct file *file, const char *name)
727 struct stfcamss_video *video = video_drvdata(file);
728 struct video_device *vdev = &video->vdev;
729 struct media_entity *entity = &vdev->entity;
730 struct v4l2_subdev *subdev;
731 struct media_pad *pad;
734 strcpy(vin_name, entity->name);
736 pad = &entity->pads[0];
737 if (!(pad->flags & MEDIA_PAD_FL_SINK))
739 pad = media_entity_remote_pad(pad);
740 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
742 entity = pad->entity;
744 if (!strncmp(vin_name, entity->name, 13)) {
745 st_err(ST_VIDEO, "===== [%s] Please configure pipeline first =====\n", name);
748 subdev = media_entity_to_v4l2_subdev(entity);
753 static int video_enum_framesizes(struct file *file, void *fh,
754 struct v4l2_frmsizeenum *fsize)
756 struct v4l2_subdev_frame_size_enum fse = {0};
757 struct v4l2_subdev_mbus_code_enum code = {0};
758 struct stfcamss_video *video = video_drvdata(file);
759 struct video_device *vdev = &video->vdev;
760 struct media_entity *entity = &vdev->entity;
761 struct media_entity *sensor;
762 struct v4l2_subdev *subdev;
763 struct media_pad *pad;
764 bool support_selection = false;
768 for (i = 0; i < video->nformats; i++) {
769 if (video->formats[i].pixelformat == fsize->pixel_format)
773 if (i == video->nformats)
776 entity = &vdev->entity;
778 pad = &entity->pads[0];
779 if (!(pad->flags & MEDIA_PAD_FL_SINK))
782 pad = media_entity_remote_pad(pad);
783 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
786 entity = pad->entity;
787 subdev = media_entity_to_v4l2_subdev(entity);
789 if (subdev->ops->pad->set_selection) {
790 support_selection = true;
795 if (support_selection) {
798 fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
799 fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH;
800 fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH;
801 fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT;
802 fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT;
803 fsize->stepwise.step_width = 1;
804 fsize->stepwise.step_height = 1;
806 entity = &vdev->entity;
807 sensor = stfcamss_find_sensor(entity);
811 subdev = media_entity_to_v4l2_subdev(sensor);
813 code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
814 ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code);
817 fse.index = fsize->index;
818 fse.code = code.code;
819 fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
820 ret = v4l2_subdev_call(subdev, pad, enum_frame_size, NULL, &fse);
823 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
824 fsize->discrete.width = fse.min_width;
825 fsize->discrete.height = fse.min_height;
831 static int video_enum_frameintervals(struct file *file, void *fh,
832 struct v4l2_frmivalenum *fival)
835 struct stfcamss_video *video = video_drvdata(file);
836 struct video_device *vdev = &video->vdev;
837 struct media_entity *entity = &vdev->entity;
838 struct media_entity *sensor;
839 struct v4l2_subdev *subdev;
840 struct v4l2_subdev_mbus_code_enum code = {0};
841 struct v4l2_subdev_frame_interval_enum fie = {0};
843 sensor = stfcamss_find_sensor(entity);
846 fie.index = fival->index;
847 fie.width = fival->width;
848 fie.height = fival->height;
849 fie.which = V4L2_SUBDEV_FORMAT_ACTIVE;
850 subdev = media_entity_to_v4l2_subdev(sensor);
853 code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
855 ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code);
859 fie.code = code.code;
860 ret = v4l2_subdev_call(subdev, pad, enum_frame_interval, NULL, &fie);
864 fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
865 fival->discrete = fie.interval;
870 static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
872 struct stfcamss_video *video = video_drvdata(file);
874 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
875 st_debug(ST_VIDEO, "%s, active_fmt.type = 0x%x,0x%x\n",
876 __func__, video->active_fmt.type,
877 video->active_fmt.fmt.pix.pixelformat);
878 *f = video->active_fmt;
882 static int video_g_fmt_mp(struct file *file, void *fh, struct v4l2_format *f)
884 struct stfcamss_video *video = video_drvdata(file);
886 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
887 st_debug(ST_VIDEO, "%s, active_fmt.type = 0x%x\n",
888 __func__, video->active_fmt.type);
889 *f = video->active_fmt;
893 static int video_entity_s_fmt(struct stfcamss_video *video,
894 struct media_entity *entity,
895 struct v4l2_subdev_state *state,
896 struct v4l2_subdev_format *fmt, u32 dst_code)
898 struct v4l2_subdev *subdev;
899 struct media_pad *pad;
900 struct v4l2_mbus_framefmt *mf = &fmt->format;
901 u32 width, height, code;
907 subdev = media_entity_to_v4l2_subdev(entity);
909 if (index >= entity->num_pads)
911 pad = &entity->pads[index];
912 pad = media_entity_remote_pad(pad);
913 if (pad && is_media_entity_v4l2_subdev(pad->entity)) {
917 ret = v4l2_subdev_call(subdev, pad, set_fmt, state, fmt);
919 "\"%s\":%d pad fmt set to 0x%x %ux%u, dst_code = 0x%x, ret=%d\n",
920 subdev->name, fmt->pad, mf->code,
921 mf->width, mf->height, dst_code, ret);
922 if (mf->code != code ||
923 mf->width != width || mf->height != height) {
925 "\"%s\":%d pad fmt has been"
926 " changed to 0x%x %ux%u\n",
927 subdev->name, fmt->pad, mf->code,
928 mf->width, mf->height);
931 ret = video_entity_s_fmt(video, pad->entity, state, fmt, dst_code);
934 if (ret < 0 && ret != -ENOIOCTLCMD)
941 static int video_pipeline_s_fmt(struct stfcamss_video *video,
942 struct v4l2_subdev_state *state,
943 struct v4l2_format *f)
945 struct video_device *vdev = &video->vdev;
946 struct media_entity *entity = &vdev->entity;
947 struct v4l2_subdev *subdev;
949 struct v4l2_subdev_format fmt = {
950 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
951 .reserved = {getcrop_pad_id(video->id)}
953 struct v4l2_mbus_framefmt *mf = &fmt.format;
954 struct v4l2_pix_format *pix = &f->fmt.pix;
955 struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
956 struct media_entity *sensor;
957 u32 width, height, code;
958 struct media_pad *pad;
960 /* pix to mbus format */
962 index = video_find_format(mf->code,
964 video->formats, video->nformats);
967 v4l2_fill_mbus_format_mplane(mf, pix_mp);
968 mf->code = video->formats[index].code;
970 index = video_find_format(mf->code,
972 video->formats, video->nformats);
975 v4l2_fill_mbus_format(mf, pix, video->formats[index].code);
980 sensor = stfcamss_find_sensor(entity);
982 subdev = media_entity_to_v4l2_subdev(sensor);
983 ret = v4l2_subdev_call(subdev, pad, set_fmt, state, &fmt);
985 "\"%s\":%d pad fmt set to 0x%x %ux%u\n",
986 subdev->name, fmt.pad, mf->code,
987 mf->width, mf->height);
988 if (mf->code != code ||
989 mf->width != width || mf->height != height) {
991 "\"%s\":%d pad fmt has been"
992 " changed to 0x%x %ux%u\n",
993 subdev->name, fmt.pad, mf->code,
994 mf->width, mf->height);
997 st_err(ST_VIDEO, "Can't find sensor\n");
1001 * Starting from sensor subdevice, walk within
1002 * pipeline and set format on each subdevice
1004 sensor = stfcamss_find_sensor(entity);
1005 pad = media_entity_remote_pad(&sensor->pads[0]);
1006 ret = video_entity_s_fmt(video, pad->entity, state, &fmt, code);
1008 if (ret < 0 && ret != -ENOIOCTLCMD) {
1012 index = video_find_format(mf->code,
1013 video->formats[index].pixelformat,
1014 video->formats, video->nformats);
1015 st_debug(ST_VIDEO, "%s, code=%x, index=%d\n",
1016 __func__, mf->code, index);
1022 video_mbus_to_pix_mp(mf, pix_mp,
1023 &video->formats[index], video->bpl_alignment);
1025 video_mbus_to_pix(mf, pix,
1026 &video->formats[index], video->bpl_alignment);
1028 ret = __video_try_fmt(video, f, video->is_mp);
1035 static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
1037 struct stfcamss_video *video = video_drvdata(file);
1040 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x, v4l2fmt=%x\n",
1041 __func__, f->type, f->fmt.pix.pixelformat);
1043 if (vb2_is_busy(&video->vb2_q))
1046 ret = __video_try_fmt(video, f, false);
1050 ret = video_pipeline_s_fmt(video, NULL, f);
1052 st_debug(ST_VIDEO, "%s, pixelformat=0x%x, ret=%d\n",
1053 __func__, f->fmt.pix.pixelformat, ret);
1057 video->active_fmt = *f;
1062 static int video_s_fmt_mp(struct file *file, void *fh, struct v4l2_format *f)
1064 struct stfcamss_video *video = video_drvdata(file);
1067 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
1068 if (vb2_is_busy(&video->vb2_q))
1071 ret = __video_try_fmt(video, f, true);
1075 ret = video_pipeline_s_fmt(video, NULL, f);
1079 video->active_fmt = *f;
1084 static int video_try_fmt(struct file *file,
1085 void *fh, struct v4l2_format *f)
1087 struct stfcamss_video *video = video_drvdata(file);
1089 return __video_try_fmt(video, f, false);
1092 static int video_try_fmt_mp(struct file *file,
1093 void *fh, struct v4l2_format *f)
1095 struct stfcamss_video *video = video_drvdata(file);
1097 return __video_try_fmt(video, f, true);
1100 static int video_enum_input(struct file *file, void *fh,
1101 struct v4l2_input *input)
1103 if (input->index > 0)
1106 strscpy(input->name, "camera", sizeof(input->name));
1107 input->type = V4L2_INPUT_TYPE_CAMERA;
1112 static int video_g_input(struct file *file, void *fh, unsigned int *input)
1119 static int video_s_input(struct file *file, void *fh, unsigned int input)
1121 return input == 0 ? 0 : -EINVAL;
1124 static int video_g_parm(struct file *file, void *priv,
1125 struct v4l2_streamparm *p)
1127 struct stfcamss_video *video = video_drvdata(file);
1128 struct video_device *vdev = &video->vdev;
1129 struct media_entity *entity;
1130 struct v4l2_subdev *subdev;
1131 struct media_pad *pad;
1132 int ret, is_support = 0;
1134 entity = &vdev->entity;
1136 pad = &entity->pads[0];
1137 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1140 pad = media_entity_remote_pad(pad);
1141 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1144 entity = pad->entity;
1145 subdev = media_entity_to_v4l2_subdev(entity);
1147 ret = v4l2_g_parm_cap(vdev, subdev, p);
1148 if (ret < 0 && ret != -ENOIOCTLCMD)
1154 return is_support ? 0 : ret;
1157 static int video_s_parm(struct file *file, void *priv,
1158 struct v4l2_streamparm *p)
1160 struct stfcamss_video *video = video_drvdata(file);
1161 struct video_device *vdev = &video->vdev;
1162 struct media_entity *entity;
1163 struct v4l2_subdev *subdev;
1164 struct media_pad *pad;
1165 struct v4l2_streamparm tmp_p;
1166 int ret, is_support = 0;
1168 entity = &vdev->entity;
1170 pad = &entity->pads[0];
1171 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1174 pad = media_entity_remote_pad(pad);
1175 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1178 entity = pad->entity;
1179 subdev = media_entity_to_v4l2_subdev(entity);
1182 ret = v4l2_s_parm_cap(vdev, subdev, &tmp_p);
1183 if (ret < 0 && ret != -ENOIOCTLCMD)
1191 return is_support ? 0 : ret;
1195 int video_g_pixelaspect(struct file *file, void *fh,
1196 int buf_type, struct v4l2_fract *aspect)
1201 int video_g_selection(struct file *file, void *fh,
1202 struct v4l2_selection *s)
1204 struct stfcamss_video *video = video_drvdata(file);
1205 struct video_device *vdev = &video->vdev;
1206 struct media_entity *entity;
1207 struct v4l2_subdev *subdev;
1208 struct media_pad *pad;
1209 struct v4l2_subdev_selection sel = {
1210 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1211 .pad = getcrop_pad_id(video->id),
1212 .target = s->target,
1218 st_debug(ST_VIDEO, "%s, target = 0x%x, 0x%x\n",
1219 __func__, sel.target, s->target);
1220 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1221 && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1224 entity = &vdev->entity;
1226 pad = &entity->pads[0];
1227 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1230 pad = media_entity_remote_pad(pad);
1231 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1234 entity = pad->entity;
1235 subdev = media_entity_to_v4l2_subdev(entity);
1237 ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sel);
1240 s->flags = sel.flags;
1243 if (ret != -ENOIOCTLCMD)
1250 int video_s_selection(struct file *file, void *fh,
1251 struct v4l2_selection *s)
1253 struct stfcamss_video *video = video_drvdata(file);
1254 struct video_device *vdev = &video->vdev;
1255 struct media_entity *entity;
1256 struct v4l2_subdev *subdev;
1257 struct media_pad *pad;
1258 struct v4l2_subdev_selection sel = {
1259 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1260 .pad = getcrop_pad_id(video->id),
1261 .target = s->target,
1265 struct v4l2_pix_format *format = &video->active_fmt.fmt.pix;
1266 struct v4l2_pix_format_mplane *format_mp =
1267 &video->active_fmt.fmt.pix_mp;
1270 st_debug(ST_VIDEO, "%s, target = 0x%x, 0x%x\n",
1271 __func__, sel.target, s->target);
1272 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1273 && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1276 entity = &vdev->entity;
1278 pad = &entity->pads[0];
1279 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1282 pad = media_entity_remote_pad(pad);
1283 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1286 entity = pad->entity;
1287 subdev = media_entity_to_v4l2_subdev(entity);
1289 ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sel);
1292 s->flags = sel.flags;
1293 format->width = s->r.width;
1294 format->height = s->r.height;
1295 format_mp->width = s->r.width;
1296 format_mp->height = s->r.height;
1297 ret = __video_try_fmt(video, &video->active_fmt,
1303 if (ret != -ENOIOCTLCMD)
1307 st_debug(ST_VIDEO, "ret = 0x%x, -EINVAL = 0x%x\n", ret, -EINVAL);
1312 int video_g_ctrl(struct file *file, void *fh,
1313 struct v4l2_control *ctrls)
1315 struct v4l2_subdev *subdev;
1318 subdev = get_senname(file, (char *)__func__);
1322 ret = v4l2_g_ctrl(subdev->ctrl_handler, ctrls);
1327 static int video_s_ctrl(struct file *file, void *fh,
1328 struct v4l2_control *ctrl)
1330 struct v4l2_subdev *subdev;
1331 struct v4l2_fh *vfh;
1334 subdev = get_senname(file, (char *)__func__);
1338 vfh = container_of(&subdev->ctrl_handler, struct v4l2_fh, ctrl_handler);
1339 if (!vfh->ctrl_handler)
1342 ret = v4l2_s_ctrl(vfh, subdev->ctrl_handler, ctrl);
1348 static int video_query_ext_ctrl(struct file *file, void *fh,
1349 struct v4l2_query_ext_ctrl *qec)
1351 struct v4l2_subdev *subdev;
1354 subdev = get_senname(file, (char *)__func__);
1358 ret = v4l2_query_ext_ctrl(subdev->ctrl_handler, qec);
1364 static int video_g_ext_ctrls(struct file *file, void *fh,
1365 struct v4l2_ext_controls *ctrls)
1367 struct stfcamss_video *video = video_drvdata(file);
1368 struct video_device *vdev = &video->vdev;
1369 struct v4l2_subdev *subdev;
1372 subdev = get_senname(file, (char *)__func__);
1376 ret = v4l2_g_ext_ctrls(subdev->ctrl_handler,
1377 vdev, subdev->v4l2_dev->mdev, ctrls);
1382 static int video_queryctrl(struct file *file, void *fh,
1383 struct v4l2_queryctrl *qc)
1385 struct stfcamss_video *video = video_drvdata(file);
1386 struct video_device *vdev = &video->vdev;
1387 struct media_entity *entity = &vdev->entity;
1388 struct media_entity *sensor;
1389 struct v4l2_subdev *subdev;
1392 sensor = stfcamss_find_sensor(entity);
1394 subdev = media_entity_to_v4l2_subdev(sensor);
1395 ret = v4l2_queryctrl(subdev->ctrl_handler, qc);
1397 // st_err(ST_VIDEO, "== [%s] Please configure pipeline first ==\n", __func__);
1404 static int video_s_ext_ctrls(struct file *file, void *fh,
1405 struct v4l2_ext_controls *ctrls)
1407 struct stfcamss_video *video = video_drvdata(file);
1408 struct video_device *vdev = &video->vdev;
1409 struct v4l2_subdev *subdev;
1410 struct v4l2_fh *vfh;
1413 subdev = get_senname(file, (char *)__func__);
1417 vfh = container_of(&subdev->ctrl_handler, struct v4l2_fh, ctrl_handler);
1418 if (!vfh->ctrl_handler)
1420 ret = v4l2_s_ext_ctrls(vfh, subdev->ctrl_handler,
1421 vdev, subdev->v4l2_dev->mdev, ctrls);
1426 static int video_try_ext_ctrls(struct file *file, void *fh,
1427 struct v4l2_ext_controls *ctrls)
1429 struct stfcamss_video *video = video_drvdata(file);
1430 struct video_device *vdev = &video->vdev;
1431 struct v4l2_subdev *subdev;
1432 struct v4l2_fh *vfh;
1435 subdev = get_senname(file, (char *)__func__);
1439 vfh = container_of(&subdev->ctrl_handler, struct v4l2_fh, ctrl_handler);
1440 if (!vfh->ctrl_handler)
1442 ret = v4l2_try_ext_ctrls(vfh->ctrl_handler,
1443 vdev, subdev->v4l2_dev->mdev, ctrls);
1450 static int video_querymenu(struct file *file, void *fh,
1451 struct v4l2_querymenu *qm)
1453 struct v4l2_subdev *subdev;
1456 subdev = get_senname(file, (char *)__func__);
1460 ret = v4l2_querymenu(subdev->ctrl_handler, qm);
1466 static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = {
1467 .vidioc_querycap = video_querycap,
1468 .vidioc_enum_fmt_vid_cap = video_enum_fmt,
1469 .vidioc_enum_framesizes = video_enum_framesizes,
1470 .vidioc_enum_frameintervals = video_enum_frameintervals,
1471 .vidioc_g_fmt_vid_cap = video_g_fmt,
1472 .vidioc_s_fmt_vid_cap = video_s_fmt,
1473 .vidioc_try_fmt_vid_cap = video_try_fmt,
1474 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1475 .vidioc_querybuf = vb2_ioctl_querybuf,
1476 .vidioc_qbuf = vb2_ioctl_qbuf,
1477 .vidioc_expbuf = vb2_ioctl_expbuf,
1478 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1479 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1480 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1481 .vidioc_streamon = vb2_ioctl_streamon,
1482 .vidioc_streamoff = vb2_ioctl_streamoff,
1483 .vidioc_enum_input = video_enum_input,
1484 .vidioc_g_input = video_g_input,
1485 .vidioc_s_input = video_s_input,
1486 .vidioc_g_parm = video_g_parm,
1487 .vidioc_s_parm = video_s_parm,
1488 .vidioc_s_selection = video_s_selection,
1489 .vidioc_g_selection = video_g_selection,
1490 .vidioc_g_ctrl = video_g_ctrl,
1491 .vidioc_s_ctrl = video_s_ctrl,
1492 .vidioc_g_ext_ctrls = video_g_ext_ctrls,
1493 .vidioc_queryctrl = video_queryctrl,
1494 .vidioc_s_ext_ctrls = video_s_ext_ctrls,
1495 .vidioc_try_ext_ctrls = video_try_ext_ctrls,
1498 static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_mp = {
1499 .vidioc_querycap = video_querycap,
1500 .vidioc_enum_fmt_vid_cap = video_enum_fmt,
1501 .vidioc_enum_framesizes = video_enum_framesizes,
1502 .vidioc_enum_frameintervals = video_enum_frameintervals,
1503 .vidioc_g_fmt_vid_cap_mplane = video_g_fmt_mp,
1504 .vidioc_s_fmt_vid_cap_mplane = video_s_fmt_mp,
1505 .vidioc_try_fmt_vid_cap_mplane = video_try_fmt_mp,
1506 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1507 .vidioc_querybuf = vb2_ioctl_querybuf,
1508 .vidioc_qbuf = vb2_ioctl_qbuf,
1509 .vidioc_expbuf = vb2_ioctl_expbuf,
1510 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1511 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1512 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1513 .vidioc_streamon = vb2_ioctl_streamon,
1514 .vidioc_streamoff = vb2_ioctl_streamoff,
1515 .vidioc_enum_input = video_enum_input,
1516 .vidioc_g_input = video_g_input,
1517 .vidioc_s_input = video_s_input,
1518 .vidioc_g_parm = video_g_parm,
1519 .vidioc_s_parm = video_s_parm,
1520 .vidioc_s_selection = video_s_selection,
1521 .vidioc_g_selection = video_g_selection,
1522 .vidioc_g_ctrl = video_g_ctrl,
1523 .vidioc_s_ctrl = video_s_ctrl,
1524 .vidioc_g_ext_ctrls = video_g_ext_ctrls,
1525 .vidioc_queryctrl = video_queryctrl,
1526 .vidioc_s_ext_ctrls = video_s_ext_ctrls,
1527 .vidioc_try_ext_ctrls = video_try_ext_ctrls,
1530 static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_out = {
1531 .vidioc_querycap = video_querycap,
1532 .vidioc_enum_fmt_vid_out = video_enum_fmt,
1533 .vidioc_enum_framesizes = video_enum_framesizes,
1534 .vidioc_enum_frameintervals = video_enum_frameintervals,
1535 .vidioc_g_fmt_vid_out = video_g_fmt,
1536 .vidioc_s_fmt_vid_out = video_s_fmt,
1537 .vidioc_try_fmt_vid_out = video_try_fmt,
1538 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1539 .vidioc_querybuf = vb2_ioctl_querybuf,
1540 .vidioc_qbuf = vb2_ioctl_qbuf,
1541 .vidioc_expbuf = vb2_ioctl_expbuf,
1542 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1543 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1544 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1545 .vidioc_streamon = vb2_ioctl_streamon,
1546 .vidioc_streamoff = vb2_ioctl_streamoff,
1549 static int video_open(struct file *file)
1551 struct video_device *vdev = video_devdata(file);
1552 struct stfcamss_video *video = video_drvdata(file);
1553 struct v4l2_fh *vfh;
1556 mutex_lock(&video->lock);
1558 vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
1564 v4l2_fh_init(vfh, vdev);
1567 file->private_data = vfh;
1569 #ifdef USE_MEDIA_PIPELINE
1570 ret = v4l2_pipeline_pm_get(&vdev->entity);
1573 "Failed to power up pipeline: %d\n", ret);
1577 struct media_entity *entity;
1578 struct media_pad *pad;
1579 struct v4l2_subdev *subdev;
1582 entity = &vdev->entity;
1584 pad = &entity->pads[0];
1585 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1588 pad = media_entity_remote_pad(pad);
1589 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1592 entity = pad->entity;
1593 subdev = media_entity_to_v4l2_subdev(entity);
1595 ret = v4l2_subdev_call(subdev, core, s_power, 1);
1596 if (ret < 0 && ret != -ENOIOCTLCMD)
1601 mutex_unlock(&video->lock);
1604 #ifndef USE_MEDIA_PIPELINE
1606 entity = &vdev->entity;
1608 pad = &entity->pads[0];
1609 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1612 pad = media_entity_remote_pad(pad);
1613 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1616 entity = pad->entity;
1617 subdev = media_entity_to_v4l2_subdev(entity);
1619 v4l2_subdev_call(subdev, core, s_power, 0);
1623 v4l2_fh_release(file);
1625 mutex_unlock(&video->lock);
1629 static int video_release(struct file *file)
1631 struct video_device *vdev = video_devdata(file);
1633 vb2_fop_release(file);
1634 #ifdef USE_MEDIA_PIPELINE
1635 v4l2_pipeline_pm_put(&vdev->entity);
1637 struct media_entity *entity;
1638 struct media_pad *pad;
1639 struct v4l2_subdev *subdev;
1641 entity = &vdev->entity;
1643 pad = &entity->pads[0];
1644 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1647 pad = media_entity_remote_pad(pad);
1648 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1651 entity = pad->entity;
1652 subdev = media_entity_to_v4l2_subdev(entity);
1654 v4l2_subdev_call(subdev, core, s_power, 0);
1657 file->private_data = NULL;
1662 static const struct v4l2_file_operations stf_vid_fops = {
1663 .owner = THIS_MODULE,
1664 .unlocked_ioctl = video_ioctl2,
1666 .release = video_release,
1667 .poll = vb2_fop_poll,
1668 .mmap = vb2_fop_mmap,
1669 .read = vb2_fop_read,
1672 static void stf_video_release(struct video_device *vdev)
1674 struct stfcamss_video *video = video_get_drvdata(vdev);
1676 media_entity_cleanup(&vdev->entity);
1678 mutex_destroy(&video->q_lock);
1679 mutex_destroy(&video->lock);
1682 int stf_video_register(struct stfcamss_video *video,
1683 struct v4l2_device *v4l2_dev,
1684 const char *name, int is_mp)
1686 struct video_device *vdev;
1687 struct vb2_queue *q;
1688 struct media_pad *pad = &video->pad;
1690 enum isp_pad_id isp_pad;
1692 vdev = &video->vdev;
1694 mutex_init(&video->q_lock);
1697 q->drv_priv = video;
1698 q->mem_ops = &vb2_dma_contig_memops;
1699 q->ops = &stf_video_vb2_q_ops;
1700 //q->type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1701 // V4L2_BUF_TYPE_VIDEO_CAPTURE;
1702 q->type = video->type;
1703 q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ;
1704 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1705 q->buf_struct_size = sizeof(struct stfcamss_buffer);
1706 q->dev = video->stfcamss->dev;
1707 q->lock = &video->q_lock;
1708 q->min_buffers_needed = STFCAMSS_MIN_BUFFERS;
1709 ret = vb2_queue_init(q);
1712 "Failed to init vb2 queue: %d\n", ret);
1716 pad->flags = MEDIA_PAD_FL_SINK;
1717 ret = media_entity_pads_init(&vdev->entity, 1, pad);
1720 "Failed to init video entity: %d\n",
1725 mutex_init(&video->lock);
1727 isp_pad = stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC);
1728 if (video->id == VIN_LINE_WR) {
1729 video->formats = formats_pix_st7110_wr;
1730 video->nformats = ARRAY_SIZE(formats_pix_st7110_wr);
1731 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
1732 } else if (isp_pad == STF_ISP_PAD_SRC
1733 || isp_pad == STF_ISP_PAD_SRC_SS0
1734 || isp_pad == STF_ISP_PAD_SRC_SS1) {
1735 video->formats = formats_pix_st7110_isp;
1736 video->nformats = ARRAY_SIZE(formats_pix_st7110_isp);
1737 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
1738 } else if (isp_pad == STF_ISP_PAD_SRC_ITIW
1739 || isp_pad == STF_ISP_PAD_SRC_ITIR) {
1740 video->formats = formats_st7110_isp_iti;
1741 video->nformats = ARRAY_SIZE(formats_st7110_isp_iti);
1742 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
1743 } else { // raw/scdump/yhist
1744 video->formats = formats_raw_st7110_isp;
1745 video->nformats = ARRAY_SIZE(formats_raw_st7110_isp);
1746 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_128;
1748 video->is_mp = is_mp;
1750 ret = stf_video_init_format(video, is_mp);
1752 st_err(ST_VIDEO, "Failed to init format: %d\n", ret);
1753 goto err_vid_init_format;
1756 vdev->fops = &stf_vid_fops;
1757 if (isp_pad == STF_ISP_PAD_SRC_ITIR) {
1758 vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT;
1759 vdev->vfl_dir = VFL_DIR_TX;
1761 vdev->device_caps = is_mp ? V4L2_CAP_VIDEO_CAPTURE_MPLANE :
1762 V4L2_CAP_VIDEO_CAPTURE;
1763 vdev->vfl_dir = VFL_DIR_RX;
1765 vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
1766 if (video->type == V4L2_CAP_VIDEO_OUTPUT)
1767 vdev->ioctl_ops = &stf_vid_ioctl_ops_out;
1769 vdev->ioctl_ops = is_mp ? &stf_vid_ioctl_ops_mp : &stf_vid_ioctl_ops;
1770 vdev->release = stf_video_release;
1771 vdev->v4l2_dev = v4l2_dev;
1772 vdev->queue = &video->vb2_q;
1773 vdev->lock = &video->lock;
1774 //strlcpy(vdev->name, name, sizeof(vdev->name));
1775 strscpy(vdev->name, name, sizeof(vdev->name));
1777 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1780 "Failed to register video device: %d\n",
1785 video_set_drvdata(vdev, video);
1789 err_vid_init_format:
1790 media_entity_cleanup(&vdev->entity);
1791 mutex_destroy(&video->lock);
1793 mutex_destroy(&video->q_lock);
1797 void stf_video_unregister(struct stfcamss_video *video)
1799 vb2_video_unregister_device(&video->vdev);