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\n",
876 __func__, video->active_fmt.type);
877 *f = video->active_fmt;
881 static int video_g_fmt_mp(struct file *file, void *fh, struct v4l2_format *f)
883 struct stfcamss_video *video = video_drvdata(file);
885 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
886 st_debug(ST_VIDEO, "%s, active_fmt.type = 0x%x\n",
887 __func__, video->active_fmt.type);
888 *f = video->active_fmt;
892 static int video_entity_s_fmt(struct stfcamss_video *video,
893 struct media_entity *entity,
894 struct v4l2_subdev_state *state,
895 struct v4l2_subdev_format *fmt, u32 dst_code)
897 struct v4l2_subdev *subdev;
898 struct media_pad *pad;
899 struct v4l2_mbus_framefmt *mf = &fmt->format;
900 u32 width, height, code;
906 subdev = media_entity_to_v4l2_subdev(entity);
908 if (index >= entity->num_pads)
910 pad = &entity->pads[index];
911 pad = media_entity_remote_pad(pad);
912 if (pad && is_media_entity_v4l2_subdev(pad->entity)) {
916 ret = v4l2_subdev_call(subdev, pad, set_fmt, state, fmt);
918 "\"%s\":%d pad fmt set to 0x%x %ux%u, dst_code = 0x%x\n",
919 subdev->name, fmt->pad, mf->code,
920 mf->width, mf->height, dst_code);
921 if (mf->code != code ||
922 mf->width != width || mf->height != height) {
924 "\"%s\":%d pad fmt has been"
925 " changed to 0x%x %ux%u\n",
926 subdev->name, fmt->pad, mf->code,
927 mf->width, mf->height);
930 ret = video_entity_s_fmt(video, pad->entity, state, fmt, dst_code);
933 if (ret < 0 && ret != -ENOIOCTLCMD)
940 static int video_pipeline_s_fmt(struct stfcamss_video *video,
941 struct v4l2_subdev_state *state,
942 struct v4l2_format *f)
944 struct video_device *vdev = &video->vdev;
945 struct media_entity *entity = &vdev->entity;
946 struct v4l2_subdev *subdev;
948 struct v4l2_subdev_format fmt = {
949 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
950 .reserved = {getcrop_pad_id(video->id)}
952 struct v4l2_mbus_framefmt *mf = &fmt.format;
953 struct v4l2_pix_format *pix = &f->fmt.pix;
954 struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
955 struct media_entity *sensor;
956 u32 width, height, code;
957 struct media_pad *pad;
959 /* pix to mbus format */
961 index = video_find_format(mf->code,
963 video->formats, video->nformats);
966 v4l2_fill_mbus_format_mplane(mf, pix_mp);
967 mf->code = video->formats[index].code;
969 index = video_find_format(mf->code,
971 video->formats, video->nformats);
974 v4l2_fill_mbus_format(mf, pix, video->formats[index].code);
979 sensor = stfcamss_find_sensor(entity);
981 subdev = media_entity_to_v4l2_subdev(sensor);
982 ret = v4l2_subdev_call(subdev, pad, set_fmt, state, &fmt);
984 "\"%s\":%d pad fmt set to 0x%x %ux%u\n",
985 subdev->name, fmt.pad, mf->code,
986 mf->width, mf->height);
987 if (mf->code != code ||
988 mf->width != width || mf->height != height) {
990 "\"%s\":%d pad fmt has been"
991 " changed to 0x%x %ux%u\n",
992 subdev->name, fmt.pad, mf->code,
993 mf->width, mf->height);
996 st_err(ST_VIDEO, "Can't find sensor\n");
1000 * Starting from sensor subdevice, walk within
1001 * pipeline and set format on each subdevice
1003 sensor = stfcamss_find_sensor(entity);
1004 pad = media_entity_remote_pad(&sensor->pads[0]);
1005 ret = video_entity_s_fmt(video, pad->entity, state, &fmt, code);
1007 if (ret < 0 && ret != -ENOIOCTLCMD) {
1011 index = video_find_format(mf->code,
1012 video->formats[index].pixelformat,
1013 video->formats, video->nformats);
1018 video_mbus_to_pix_mp(mf, pix_mp,
1019 &video->formats[index], video->bpl_alignment);
1021 video_mbus_to_pix(mf, pix,
1022 &video->formats[index], video->bpl_alignment);
1024 ret = __video_try_fmt(video, f, video->is_mp);
1031 static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
1033 struct stfcamss_video *video = video_drvdata(file);
1036 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
1038 if (vb2_is_busy(&video->vb2_q))
1041 ret = __video_try_fmt(video, f, false);
1045 ret = video_pipeline_s_fmt(video, NULL, f);
1049 video->active_fmt = *f;
1054 static int video_s_fmt_mp(struct file *file, void *fh, struct v4l2_format *f)
1056 struct stfcamss_video *video = video_drvdata(file);
1059 st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
1060 if (vb2_is_busy(&video->vb2_q))
1063 ret = __video_try_fmt(video, f, true);
1067 ret = video_pipeline_s_fmt(video, NULL, f);
1071 video->active_fmt = *f;
1076 static int video_try_fmt(struct file *file,
1077 void *fh, struct v4l2_format *f)
1079 struct stfcamss_video *video = video_drvdata(file);
1081 return __video_try_fmt(video, f, false);
1084 static int video_try_fmt_mp(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, true);
1092 static int video_enum_input(struct file *file, void *fh,
1093 struct v4l2_input *input)
1095 if (input->index > 0)
1098 strscpy(input->name, "camera", sizeof(input->name));
1099 input->type = V4L2_INPUT_TYPE_CAMERA;
1104 static int video_g_input(struct file *file, void *fh, unsigned int *input)
1111 static int video_s_input(struct file *file, void *fh, unsigned int input)
1113 return input == 0 ? 0 : -EINVAL;
1116 static int video_g_parm(struct file *file, void *priv,
1117 struct v4l2_streamparm *p)
1119 struct stfcamss_video *video = video_drvdata(file);
1120 struct video_device *vdev = &video->vdev;
1121 struct media_entity *entity;
1122 struct v4l2_subdev *subdev;
1123 struct media_pad *pad;
1124 int ret, is_support = 0;
1126 entity = &vdev->entity;
1128 pad = &entity->pads[0];
1129 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1132 pad = media_entity_remote_pad(pad);
1133 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1136 entity = pad->entity;
1137 subdev = media_entity_to_v4l2_subdev(entity);
1139 ret = v4l2_g_parm_cap(vdev, subdev, p);
1140 if (ret < 0 && ret != -ENOIOCTLCMD)
1146 return is_support ? 0 : ret;
1149 static int video_s_parm(struct file *file, void *priv,
1150 struct v4l2_streamparm *p)
1152 struct stfcamss_video *video = video_drvdata(file);
1153 struct video_device *vdev = &video->vdev;
1154 struct media_entity *entity;
1155 struct v4l2_subdev *subdev;
1156 struct media_pad *pad;
1157 struct v4l2_streamparm tmp_p;
1158 int ret, is_support = 0;
1160 entity = &vdev->entity;
1162 pad = &entity->pads[0];
1163 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1166 pad = media_entity_remote_pad(pad);
1167 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1170 entity = pad->entity;
1171 subdev = media_entity_to_v4l2_subdev(entity);
1174 ret = v4l2_s_parm_cap(vdev, subdev, &tmp_p);
1175 if (ret < 0 && ret != -ENOIOCTLCMD)
1183 return is_support ? 0 : ret;
1187 int video_g_pixelaspect(struct file *file, void *fh,
1188 int buf_type, struct v4l2_fract *aspect)
1193 int video_g_selection(struct file *file, void *fh,
1194 struct v4l2_selection *s)
1196 struct stfcamss_video *video = video_drvdata(file);
1197 struct video_device *vdev = &video->vdev;
1198 struct media_entity *entity;
1199 struct v4l2_subdev *subdev;
1200 struct media_pad *pad;
1201 struct v4l2_subdev_selection sel = {
1202 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1203 .pad = getcrop_pad_id(video->id),
1204 .target = s->target,
1210 st_debug(ST_VIDEO, "%s, target = 0x%x, 0x%x\n",
1211 __func__, sel.target, s->target);
1212 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1213 && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1216 entity = &vdev->entity;
1218 pad = &entity->pads[0];
1219 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1222 pad = media_entity_remote_pad(pad);
1223 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1226 entity = pad->entity;
1227 subdev = media_entity_to_v4l2_subdev(entity);
1229 ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sel);
1232 s->flags = sel.flags;
1235 if (ret != -ENOIOCTLCMD)
1242 int video_s_selection(struct file *file, void *fh,
1243 struct v4l2_selection *s)
1245 struct stfcamss_video *video = video_drvdata(file);
1246 struct video_device *vdev = &video->vdev;
1247 struct media_entity *entity;
1248 struct v4l2_subdev *subdev;
1249 struct media_pad *pad;
1250 struct v4l2_subdev_selection sel = {
1251 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1252 .pad = getcrop_pad_id(video->id),
1253 .target = s->target,
1257 struct v4l2_pix_format *format = &video->active_fmt.fmt.pix;
1258 struct v4l2_pix_format_mplane *format_mp =
1259 &video->active_fmt.fmt.pix_mp;
1262 st_debug(ST_VIDEO, "%s, target = 0x%x, 0x%x\n",
1263 __func__, sel.target, s->target);
1264 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1265 && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1268 entity = &vdev->entity;
1270 pad = &entity->pads[0];
1271 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1274 pad = media_entity_remote_pad(pad);
1275 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1278 entity = pad->entity;
1279 subdev = media_entity_to_v4l2_subdev(entity);
1281 ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sel);
1284 s->flags = sel.flags;
1285 format->width = s->r.width;
1286 format->height = s->r.height;
1287 format_mp->width = s->r.width;
1288 format_mp->height = s->r.height;
1289 ret = __video_try_fmt(video, &video->active_fmt,
1295 if (ret != -ENOIOCTLCMD)
1299 st_debug(ST_VIDEO, "ret = 0x%x, -EINVAL = 0x%x\n", ret, -EINVAL);
1304 int video_g_ctrl(struct file *file, void *fh,
1305 struct v4l2_control *ctrls)
1307 struct v4l2_subdev *subdev;
1310 subdev = get_senname(file, (char *)__func__);
1314 ret = v4l2_g_ctrl(subdev->ctrl_handler, ctrls);
1319 static int video_s_ctrl(struct file *file, void *fh,
1320 struct v4l2_control *ctrl)
1322 struct v4l2_subdev *subdev;
1323 struct v4l2_fh *vfh;
1326 subdev = get_senname(file, (char *)__func__);
1330 vfh = container_of(&subdev->ctrl_handler, struct v4l2_fh, ctrl_handler);
1331 if (!vfh->ctrl_handler)
1334 ret = v4l2_s_ctrl(vfh, subdev->ctrl_handler, ctrl);
1340 static int video_query_ext_ctrl(struct file *file, void *fh,
1341 struct v4l2_query_ext_ctrl *qec)
1343 struct v4l2_subdev *subdev;
1346 subdev = get_senname(file, (char *)__func__);
1350 ret = v4l2_query_ext_ctrl(subdev->ctrl_handler, qec);
1356 static int video_g_ext_ctrls(struct file *file, void *fh,
1357 struct v4l2_ext_controls *ctrls)
1359 struct stfcamss_video *video = video_drvdata(file);
1360 struct video_device *vdev = &video->vdev;
1361 struct v4l2_subdev *subdev;
1364 subdev = get_senname(file, (char *)__func__);
1368 ret = v4l2_g_ext_ctrls(subdev->ctrl_handler,
1369 vdev, subdev->v4l2_dev->mdev, ctrls);
1374 static int video_queryctrl(struct file *file, void *fh,
1375 struct v4l2_queryctrl *qc)
1377 struct stfcamss_video *video = video_drvdata(file);
1378 struct video_device *vdev = &video->vdev;
1379 struct media_entity *entity = &vdev->entity;
1380 struct media_entity *sensor;
1381 struct v4l2_subdev *subdev;
1384 sensor = stfcamss_find_sensor(entity);
1386 subdev = media_entity_to_v4l2_subdev(sensor);
1387 ret = v4l2_queryctrl(subdev->ctrl_handler, qc);
1389 // st_err(ST_VIDEO, "== [%s] Please configure pipeline first ==\n", __func__);
1396 static int video_s_ext_ctrls(struct file *file, void *fh,
1397 struct v4l2_ext_controls *ctrls)
1399 struct stfcamss_video *video = video_drvdata(file);
1400 struct video_device *vdev = &video->vdev;
1401 struct v4l2_subdev *subdev;
1402 struct v4l2_fh *vfh;
1405 subdev = get_senname(file, (char *)__func__);
1409 vfh = container_of(&subdev->ctrl_handler, struct v4l2_fh, ctrl_handler);
1410 if (!vfh->ctrl_handler)
1412 ret = v4l2_s_ext_ctrls(vfh, subdev->ctrl_handler,
1413 vdev, subdev->v4l2_dev->mdev, ctrls);
1418 static int video_try_ext_ctrls(struct file *file, void *fh,
1419 struct v4l2_ext_controls *ctrls)
1421 struct stfcamss_video *video = video_drvdata(file);
1422 struct video_device *vdev = &video->vdev;
1423 struct v4l2_subdev *subdev;
1424 struct v4l2_fh *vfh;
1427 subdev = get_senname(file, (char *)__func__);
1431 vfh = container_of(&subdev->ctrl_handler, struct v4l2_fh, ctrl_handler);
1432 if (!vfh->ctrl_handler)
1434 ret = v4l2_try_ext_ctrls(vfh->ctrl_handler,
1435 vdev, subdev->v4l2_dev->mdev, ctrls);
1442 static int video_querymenu(struct file *file, void *fh,
1443 struct v4l2_querymenu *qm)
1445 struct v4l2_subdev *subdev;
1448 subdev = get_senname(file, (char *)__func__);
1452 ret = v4l2_querymenu(subdev->ctrl_handler, qm);
1458 static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = {
1459 .vidioc_querycap = video_querycap,
1460 .vidioc_enum_fmt_vid_cap = video_enum_fmt,
1461 .vidioc_enum_framesizes = video_enum_framesizes,
1462 .vidioc_enum_frameintervals = video_enum_frameintervals,
1463 .vidioc_g_fmt_vid_cap = video_g_fmt,
1464 .vidioc_s_fmt_vid_cap = video_s_fmt,
1465 .vidioc_try_fmt_vid_cap = video_try_fmt,
1466 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1467 .vidioc_querybuf = vb2_ioctl_querybuf,
1468 .vidioc_qbuf = vb2_ioctl_qbuf,
1469 .vidioc_expbuf = vb2_ioctl_expbuf,
1470 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1471 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1472 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1473 .vidioc_streamon = vb2_ioctl_streamon,
1474 .vidioc_streamoff = vb2_ioctl_streamoff,
1475 .vidioc_enum_input = video_enum_input,
1476 .vidioc_g_input = video_g_input,
1477 .vidioc_s_input = video_s_input,
1478 .vidioc_g_parm = video_g_parm,
1479 .vidioc_s_parm = video_s_parm,
1480 .vidioc_s_selection = video_s_selection,
1481 .vidioc_g_selection = video_g_selection,
1482 .vidioc_g_ctrl = video_g_ctrl,
1483 .vidioc_s_ctrl = video_s_ctrl,
1484 .vidioc_g_ext_ctrls = video_g_ext_ctrls,
1485 .vidioc_queryctrl = video_queryctrl,
1486 .vidioc_s_ext_ctrls = video_s_ext_ctrls,
1487 .vidioc_try_ext_ctrls = video_try_ext_ctrls,
1490 static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_mp = {
1491 .vidioc_querycap = video_querycap,
1492 .vidioc_enum_fmt_vid_cap = video_enum_fmt,
1493 .vidioc_enum_framesizes = video_enum_framesizes,
1494 .vidioc_enum_frameintervals = video_enum_frameintervals,
1495 .vidioc_g_fmt_vid_cap_mplane = video_g_fmt_mp,
1496 .vidioc_s_fmt_vid_cap_mplane = video_s_fmt_mp,
1497 .vidioc_try_fmt_vid_cap_mplane = video_try_fmt_mp,
1498 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1499 .vidioc_querybuf = vb2_ioctl_querybuf,
1500 .vidioc_qbuf = vb2_ioctl_qbuf,
1501 .vidioc_expbuf = vb2_ioctl_expbuf,
1502 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1503 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1504 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1505 .vidioc_streamon = vb2_ioctl_streamon,
1506 .vidioc_streamoff = vb2_ioctl_streamoff,
1507 .vidioc_enum_input = video_enum_input,
1508 .vidioc_g_input = video_g_input,
1509 .vidioc_s_input = video_s_input,
1510 .vidioc_g_parm = video_g_parm,
1511 .vidioc_s_parm = video_s_parm,
1512 .vidioc_s_selection = video_s_selection,
1513 .vidioc_g_selection = video_g_selection,
1514 .vidioc_g_ctrl = video_g_ctrl,
1515 .vidioc_s_ctrl = video_s_ctrl,
1516 .vidioc_g_ext_ctrls = video_g_ext_ctrls,
1517 .vidioc_queryctrl = video_queryctrl,
1518 .vidioc_s_ext_ctrls = video_s_ext_ctrls,
1519 .vidioc_try_ext_ctrls = video_try_ext_ctrls,
1522 static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_out = {
1523 .vidioc_querycap = video_querycap,
1524 .vidioc_enum_fmt_vid_out = video_enum_fmt,
1525 .vidioc_enum_framesizes = video_enum_framesizes,
1526 .vidioc_enum_frameintervals = video_enum_frameintervals,
1527 .vidioc_g_fmt_vid_out = video_g_fmt,
1528 .vidioc_s_fmt_vid_out = video_s_fmt,
1529 .vidioc_try_fmt_vid_out = video_try_fmt,
1530 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1531 .vidioc_querybuf = vb2_ioctl_querybuf,
1532 .vidioc_qbuf = vb2_ioctl_qbuf,
1533 .vidioc_expbuf = vb2_ioctl_expbuf,
1534 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1535 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1536 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1537 .vidioc_streamon = vb2_ioctl_streamon,
1538 .vidioc_streamoff = vb2_ioctl_streamoff,
1541 static int video_open(struct file *file)
1543 struct video_device *vdev = video_devdata(file);
1544 struct stfcamss_video *video = video_drvdata(file);
1545 struct v4l2_fh *vfh;
1548 mutex_lock(&video->lock);
1550 vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
1556 v4l2_fh_init(vfh, vdev);
1559 file->private_data = vfh;
1561 #ifdef USE_MEDIA_PIPELINE
1562 ret = v4l2_pipeline_pm_get(&vdev->entity);
1565 "Failed to power up pipeline: %d\n", ret);
1569 struct media_entity *entity;
1570 struct media_pad *pad;
1571 struct v4l2_subdev *subdev;
1574 entity = &vdev->entity;
1576 pad = &entity->pads[0];
1577 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1580 pad = media_entity_remote_pad(pad);
1581 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1584 entity = pad->entity;
1585 subdev = media_entity_to_v4l2_subdev(entity);
1587 ret = v4l2_subdev_call(subdev, core, s_power, 1);
1588 if (ret < 0 && ret != -ENOIOCTLCMD)
1593 mutex_unlock(&video->lock);
1596 #ifndef USE_MEDIA_PIPELINE
1598 entity = &vdev->entity;
1600 pad = &entity->pads[0];
1601 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1604 pad = media_entity_remote_pad(pad);
1605 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1608 entity = pad->entity;
1609 subdev = media_entity_to_v4l2_subdev(entity);
1611 v4l2_subdev_call(subdev, core, s_power, 0);
1615 v4l2_fh_release(file);
1617 mutex_unlock(&video->lock);
1621 static int video_release(struct file *file)
1623 struct video_device *vdev = video_devdata(file);
1625 vb2_fop_release(file);
1626 #ifdef USE_MEDIA_PIPELINE
1627 v4l2_pipeline_pm_put(&vdev->entity);
1629 struct media_entity *entity;
1630 struct media_pad *pad;
1631 struct v4l2_subdev *subdev;
1633 entity = &vdev->entity;
1635 pad = &entity->pads[0];
1636 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1639 pad = media_entity_remote_pad(pad);
1640 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
1643 entity = pad->entity;
1644 subdev = media_entity_to_v4l2_subdev(entity);
1646 v4l2_subdev_call(subdev, core, s_power, 0);
1649 file->private_data = NULL;
1654 static const struct v4l2_file_operations stf_vid_fops = {
1655 .owner = THIS_MODULE,
1656 .unlocked_ioctl = video_ioctl2,
1658 .release = video_release,
1659 .poll = vb2_fop_poll,
1660 .mmap = vb2_fop_mmap,
1661 .read = vb2_fop_read,
1664 static void stf_video_release(struct video_device *vdev)
1666 struct stfcamss_video *video = video_get_drvdata(vdev);
1668 media_entity_cleanup(&vdev->entity);
1670 mutex_destroy(&video->q_lock);
1671 mutex_destroy(&video->lock);
1674 int stf_video_register(struct stfcamss_video *video,
1675 struct v4l2_device *v4l2_dev,
1676 const char *name, int is_mp)
1678 struct video_device *vdev;
1679 struct vb2_queue *q;
1680 struct media_pad *pad = &video->pad;
1682 enum isp_pad_id isp_pad;
1684 vdev = &video->vdev;
1686 mutex_init(&video->q_lock);
1689 q->drv_priv = video;
1690 q->mem_ops = &vb2_dma_contig_memops;
1691 q->ops = &stf_video_vb2_q_ops;
1692 //q->type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1693 // V4L2_BUF_TYPE_VIDEO_CAPTURE;
1694 q->type = video->type;
1695 q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ;
1696 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1697 q->buf_struct_size = sizeof(struct stfcamss_buffer);
1698 q->dev = video->stfcamss->dev;
1699 q->lock = &video->q_lock;
1700 q->min_buffers_needed = STFCAMSS_MIN_BUFFERS;
1701 ret = vb2_queue_init(q);
1704 "Failed to init vb2 queue: %d\n", ret);
1708 pad->flags = MEDIA_PAD_FL_SINK;
1709 ret = media_entity_pads_init(&vdev->entity, 1, pad);
1712 "Failed to init video entity: %d\n",
1717 mutex_init(&video->lock);
1719 isp_pad = stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC);
1720 if (video->id == VIN_LINE_WR) {
1721 video->formats = formats_pix_st7110_wr;
1722 video->nformats = ARRAY_SIZE(formats_pix_st7110_wr);
1723 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
1724 } else if (isp_pad == STF_ISP_PAD_SRC
1725 || isp_pad == STF_ISP_PAD_SRC_SS0
1726 || isp_pad == STF_ISP_PAD_SRC_SS1) {
1727 video->formats = formats_pix_st7110_isp;
1728 video->nformats = ARRAY_SIZE(formats_pix_st7110_isp);
1729 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
1730 } else if (isp_pad == STF_ISP_PAD_SRC_ITIW
1731 || isp_pad == STF_ISP_PAD_SRC_ITIR) {
1732 video->formats = formats_st7110_isp_iti;
1733 video->nformats = ARRAY_SIZE(formats_st7110_isp_iti);
1734 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
1735 } else { // raw/scdump/yhist
1736 video->formats = formats_raw_st7110_isp;
1737 video->nformats = ARRAY_SIZE(formats_raw_st7110_isp);
1738 video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_128;
1740 video->is_mp = is_mp;
1742 ret = stf_video_init_format(video, is_mp);
1744 st_err(ST_VIDEO, "Failed to init format: %d\n", ret);
1745 goto err_vid_init_format;
1748 vdev->fops = &stf_vid_fops;
1749 if (isp_pad == STF_ISP_PAD_SRC_ITIR) {
1750 vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT;
1751 vdev->vfl_dir = VFL_DIR_TX;
1753 vdev->device_caps = is_mp ? V4L2_CAP_VIDEO_CAPTURE_MPLANE :
1754 V4L2_CAP_VIDEO_CAPTURE;
1755 vdev->vfl_dir = VFL_DIR_RX;
1757 vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
1758 if (video->type == V4L2_CAP_VIDEO_OUTPUT)
1759 vdev->ioctl_ops = &stf_vid_ioctl_ops_out;
1761 vdev->ioctl_ops = is_mp ? &stf_vid_ioctl_ops_mp : &stf_vid_ioctl_ops;
1762 vdev->release = stf_video_release;
1763 vdev->v4l2_dev = v4l2_dev;
1764 vdev->queue = &video->vb2_q;
1765 vdev->lock = &video->lock;
1766 //strlcpy(vdev->name, name, sizeof(vdev->name));
1767 strscpy(vdev->name, name, sizeof(vdev->name));
1769 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1772 "Failed to register video device: %d\n",
1777 video_set_drvdata(vdev, video);
1781 err_vid_init_format:
1782 media_entity_cleanup(&vdev->entity);
1783 mutex_destroy(&video->lock);
1785 mutex_destroy(&video->q_lock);
1789 void stf_video_unregister(struct stfcamss_video *video)
1791 vb2_video_unregister_device(&video->vdev);