4 * Qualcomm MSM Camera Subsystem - V4L2 device node
6 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
7 * Copyright (C) 2015-2017 Linaro Ltd.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 and
11 * only version 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 #include <linux/slab.h>
19 #include <media/media-entity.h>
20 #include <media/v4l2-dev.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-ioctl.h>
23 #include <media/v4l2-mc.h>
24 #include <media/videobuf2-dma-sg.h>
26 #include "camss-video.h"
35 * struct camss_format_info - ISP media bus format information
36 * @code: V4L2 media bus format code
37 * @pixelformat: V4L2 pixel format FCC identifier
38 * @planes: Number of planes
39 * @hsub: Horizontal subsampling (for each plane)
40 * @vsub: Vertical subsampling (for each plane)
41 * @bpp: Bits per pixel when stored in memory (for each plane)
43 struct camss_format_info
{
52 static const struct camss_format_info formats_rdi
[] = {
53 { MEDIA_BUS_FMT_UYVY8_2X8
, V4L2_PIX_FMT_UYVY
, 1,
54 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
55 { MEDIA_BUS_FMT_VYUY8_2X8
, V4L2_PIX_FMT_VYUY
, 1,
56 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
57 { MEDIA_BUS_FMT_YUYV8_2X8
, V4L2_PIX_FMT_YUYV
, 1,
58 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
59 { MEDIA_BUS_FMT_YVYU8_2X8
, V4L2_PIX_FMT_YVYU
, 1,
60 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
61 { MEDIA_BUS_FMT_SBGGR8_1X8
, V4L2_PIX_FMT_SBGGR8
, 1,
62 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
63 { MEDIA_BUS_FMT_SGBRG8_1X8
, V4L2_PIX_FMT_SGBRG8
, 1,
64 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
65 { MEDIA_BUS_FMT_SGRBG8_1X8
, V4L2_PIX_FMT_SGRBG8
, 1,
66 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
67 { MEDIA_BUS_FMT_SRGGB8_1X8
, V4L2_PIX_FMT_SRGGB8
, 1,
68 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
69 { MEDIA_BUS_FMT_SBGGR10_1X10
, V4L2_PIX_FMT_SBGGR10P
, 1,
70 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
71 { MEDIA_BUS_FMT_SGBRG10_1X10
, V4L2_PIX_FMT_SGBRG10P
, 1,
72 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
73 { MEDIA_BUS_FMT_SGRBG10_1X10
, V4L2_PIX_FMT_SGRBG10P
, 1,
74 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
75 { MEDIA_BUS_FMT_SRGGB10_1X10
, V4L2_PIX_FMT_SRGGB10P
, 1,
76 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
77 { MEDIA_BUS_FMT_SBGGR12_1X12
, V4L2_PIX_FMT_SBGGR12P
, 1,
78 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
79 { MEDIA_BUS_FMT_SGBRG12_1X12
, V4L2_PIX_FMT_SGBRG12P
, 1,
80 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
81 { MEDIA_BUS_FMT_SGRBG12_1X12
, V4L2_PIX_FMT_SGRBG12P
, 1,
82 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
83 { MEDIA_BUS_FMT_SRGGB12_1X12
, V4L2_PIX_FMT_SRGGB12P
, 1,
84 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
87 static const struct camss_format_info formats_pix
[] = {
88 { MEDIA_BUS_FMT_YUYV8_1_5X8
, V4L2_PIX_FMT_NV12
, 1,
89 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
90 { MEDIA_BUS_FMT_YVYU8_1_5X8
, V4L2_PIX_FMT_NV12
, 1,
91 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
92 { MEDIA_BUS_FMT_UYVY8_1_5X8
, V4L2_PIX_FMT_NV12
, 1,
93 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
94 { MEDIA_BUS_FMT_VYUY8_1_5X8
, V4L2_PIX_FMT_NV12
, 1,
95 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
96 { MEDIA_BUS_FMT_YUYV8_1_5X8
, V4L2_PIX_FMT_NV21
, 1,
97 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
98 { MEDIA_BUS_FMT_YVYU8_1_5X8
, V4L2_PIX_FMT_NV21
, 1,
99 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
100 { MEDIA_BUS_FMT_UYVY8_1_5X8
, V4L2_PIX_FMT_NV21
, 1,
101 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
102 { MEDIA_BUS_FMT_VYUY8_1_5X8
, V4L2_PIX_FMT_NV21
, 1,
103 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
104 { MEDIA_BUS_FMT_YUYV8_2X8
, V4L2_PIX_FMT_NV16
, 1,
105 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
106 { MEDIA_BUS_FMT_YVYU8_2X8
, V4L2_PIX_FMT_NV16
, 1,
107 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
108 { MEDIA_BUS_FMT_UYVY8_2X8
, V4L2_PIX_FMT_NV16
, 1,
109 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
110 { MEDIA_BUS_FMT_VYUY8_2X8
, V4L2_PIX_FMT_NV16
, 1,
111 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
112 { MEDIA_BUS_FMT_YUYV8_2X8
, V4L2_PIX_FMT_NV61
, 1,
113 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
114 { MEDIA_BUS_FMT_YVYU8_2X8
, V4L2_PIX_FMT_NV61
, 1,
115 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
116 { MEDIA_BUS_FMT_UYVY8_2X8
, V4L2_PIX_FMT_NV61
, 1,
117 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
118 { MEDIA_BUS_FMT_VYUY8_2X8
, V4L2_PIX_FMT_NV61
, 1,
119 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
122 /* -----------------------------------------------------------------------------
126 static int video_find_format(u32 code
, u32 pixelformat
,
127 const struct camss_format_info
*formats
,
128 unsigned int nformats
)
132 for (i
= 0; i
< nformats
; i
++) {
133 if (formats
[i
].code
== code
&&
134 formats
[i
].pixelformat
== pixelformat
)
138 for (i
= 0; i
< nformats
; i
++)
139 if (formats
[i
].code
== code
)
148 * video_mbus_to_pix_mp - Convert v4l2_mbus_framefmt to v4l2_pix_format_mplane
149 * @mbus: v4l2_mbus_framefmt format (input)
150 * @pix: v4l2_pix_format_mplane format (output)
151 * @f: a pointer to formats array element to be used for the conversion
152 * @alignment: bytesperline alignment value
154 * Fill the output pix structure with information from the input mbus format.
156 * Return 0 on success or a negative error code otherwise
158 static int video_mbus_to_pix_mp(const struct v4l2_mbus_framefmt
*mbus
,
159 struct v4l2_pix_format_mplane
*pix
,
160 const struct camss_format_info
*f
,
161 unsigned int alignment
)
166 memset(pix
, 0, sizeof(*pix
));
167 v4l2_fill_pix_format_mplane(pix
, mbus
);
168 pix
->pixelformat
= f
->pixelformat
;
169 pix
->num_planes
= f
->planes
;
170 for (i
= 0; i
< pix
->num_planes
; i
++) {
171 bytesperline
= pix
->width
/ f
->hsub
[i
].numerator
*
172 f
->hsub
[i
].denominator
* f
->bpp
[i
] / 8;
173 bytesperline
= ALIGN(bytesperline
, alignment
);
174 pix
->plane_fmt
[i
].bytesperline
= bytesperline
;
175 pix
->plane_fmt
[i
].sizeimage
= pix
->height
/
176 f
->vsub
[i
].numerator
* f
->vsub
[i
].denominator
*
183 static struct v4l2_subdev
*video_remote_subdev(struct camss_video
*video
,
186 struct media_pad
*remote
;
188 remote
= media_entity_remote_pad(&video
->pad
);
190 if (!remote
|| !is_media_entity_v4l2_subdev(remote
->entity
))
194 *pad
= remote
->index
;
196 return media_entity_to_v4l2_subdev(remote
->entity
);
199 static int video_get_subdev_format(struct camss_video
*video
,
200 struct v4l2_format
*format
)
202 struct v4l2_subdev_format fmt
;
203 struct v4l2_subdev
*subdev
;
207 subdev
= video_remote_subdev(video
, &pad
);
212 fmt
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
214 ret
= v4l2_subdev_call(subdev
, pad
, get_fmt
, NULL
, &fmt
);
218 ret
= video_find_format(fmt
.format
.code
,
219 format
->fmt
.pix_mp
.pixelformat
,
220 video
->formats
, video
->nformats
);
224 format
->type
= video
->type
;
226 return video_mbus_to_pix_mp(&fmt
.format
, &format
->fmt
.pix_mp
,
227 &video
->formats
[ret
], video
->bpl_alignment
);
230 /* -----------------------------------------------------------------------------
231 * Video queue operations
234 static int video_queue_setup(struct vb2_queue
*q
,
235 unsigned int *num_buffers
, unsigned int *num_planes
,
236 unsigned int sizes
[], struct device
*alloc_devs
[])
238 struct camss_video
*video
= vb2_get_drv_priv(q
);
239 const struct v4l2_pix_format_mplane
*format
=
240 &video
->active_fmt
.fmt
.pix_mp
;
244 if (*num_planes
!= format
->num_planes
)
247 for (i
= 0; i
< *num_planes
; i
++)
248 if (sizes
[i
] < format
->plane_fmt
[i
].sizeimage
)
254 *num_planes
= format
->num_planes
;
256 for (i
= 0; i
< *num_planes
; i
++)
257 sizes
[i
] = format
->plane_fmt
[i
].sizeimage
;
262 static int video_buf_init(struct vb2_buffer
*vb
)
264 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
265 struct camss_video
*video
= vb2_get_drv_priv(vb
->vb2_queue
);
266 struct camss_buffer
*buffer
= container_of(vbuf
, struct camss_buffer
,
268 const struct v4l2_pix_format_mplane
*format
=
269 &video
->active_fmt
.fmt
.pix_mp
;
270 struct sg_table
*sgt
;
273 for (i
= 0; i
< format
->num_planes
; i
++) {
274 sgt
= vb2_dma_sg_plane_desc(vb
, i
);
278 buffer
->addr
[i
] = sg_dma_address(sgt
->sgl
);
281 if (format
->pixelformat
== V4L2_PIX_FMT_NV12
||
282 format
->pixelformat
== V4L2_PIX_FMT_NV21
||
283 format
->pixelformat
== V4L2_PIX_FMT_NV16
||
284 format
->pixelformat
== V4L2_PIX_FMT_NV61
)
285 buffer
->addr
[1] = buffer
->addr
[0] +
286 format
->plane_fmt
[0].bytesperline
*
292 static int video_buf_prepare(struct vb2_buffer
*vb
)
294 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
295 struct camss_video
*video
= vb2_get_drv_priv(vb
->vb2_queue
);
296 const struct v4l2_pix_format_mplane
*format
=
297 &video
->active_fmt
.fmt
.pix_mp
;
300 for (i
= 0; i
< format
->num_planes
; i
++) {
301 if (format
->plane_fmt
[i
].sizeimage
> vb2_plane_size(vb
, i
))
304 vb2_set_plane_payload(vb
, i
, format
->plane_fmt
[i
].sizeimage
);
307 vbuf
->field
= V4L2_FIELD_NONE
;
312 static void video_buf_queue(struct vb2_buffer
*vb
)
314 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
315 struct camss_video
*video
= vb2_get_drv_priv(vb
->vb2_queue
);
316 struct camss_buffer
*buffer
= container_of(vbuf
, struct camss_buffer
,
319 video
->ops
->queue_buffer(video
, buffer
);
322 static int video_check_format(struct camss_video
*video
)
324 struct v4l2_pix_format_mplane
*pix
= &video
->active_fmt
.fmt
.pix_mp
;
325 struct v4l2_format format
;
326 struct v4l2_pix_format_mplane
*sd_pix
= &format
.fmt
.pix_mp
;
329 sd_pix
->pixelformat
= pix
->pixelformat
;
330 ret
= video_get_subdev_format(video
, &format
);
334 if (pix
->pixelformat
!= sd_pix
->pixelformat
||
335 pix
->height
!= sd_pix
->height
||
336 pix
->width
!= sd_pix
->width
||
337 pix
->num_planes
!= sd_pix
->num_planes
||
338 pix
->field
!= format
.fmt
.pix_mp
.field
)
344 static int video_start_streaming(struct vb2_queue
*q
, unsigned int count
)
346 struct camss_video
*video
= vb2_get_drv_priv(q
);
347 struct video_device
*vdev
= &video
->vdev
;
348 struct media_entity
*entity
;
349 struct media_pad
*pad
;
350 struct v4l2_subdev
*subdev
;
353 ret
= media_pipeline_start(&vdev
->entity
, &video
->pipe
);
357 ret
= video_check_format(video
);
361 entity
= &vdev
->entity
;
363 pad
= &entity
->pads
[0];
364 if (!(pad
->flags
& MEDIA_PAD_FL_SINK
))
367 pad
= media_entity_remote_pad(pad
);
368 if (!pad
|| !is_media_entity_v4l2_subdev(pad
->entity
))
371 entity
= pad
->entity
;
372 subdev
= media_entity_to_v4l2_subdev(entity
);
374 ret
= v4l2_subdev_call(subdev
, video
, s_stream
, 1);
375 if (ret
< 0 && ret
!= -ENOIOCTLCMD
)
382 media_pipeline_stop(&vdev
->entity
);
384 video
->ops
->flush_buffers(video
, VB2_BUF_STATE_QUEUED
);
389 static void video_stop_streaming(struct vb2_queue
*q
)
391 struct camss_video
*video
= vb2_get_drv_priv(q
);
392 struct video_device
*vdev
= &video
->vdev
;
393 struct media_entity
*entity
;
394 struct media_pad
*pad
;
395 struct v4l2_subdev
*subdev
;
397 entity
= &vdev
->entity
;
399 pad
= &entity
->pads
[0];
400 if (!(pad
->flags
& MEDIA_PAD_FL_SINK
))
403 pad
= media_entity_remote_pad(pad
);
404 if (!pad
|| !is_media_entity_v4l2_subdev(pad
->entity
))
407 entity
= pad
->entity
;
408 subdev
= media_entity_to_v4l2_subdev(entity
);
410 v4l2_subdev_call(subdev
, video
, s_stream
, 0);
413 media_pipeline_stop(&vdev
->entity
);
415 video
->ops
->flush_buffers(video
, VB2_BUF_STATE_ERROR
);
418 static const struct vb2_ops msm_video_vb2_q_ops
= {
419 .queue_setup
= video_queue_setup
,
420 .wait_prepare
= vb2_ops_wait_prepare
,
421 .wait_finish
= vb2_ops_wait_finish
,
422 .buf_init
= video_buf_init
,
423 .buf_prepare
= video_buf_prepare
,
424 .buf_queue
= video_buf_queue
,
425 .start_streaming
= video_start_streaming
,
426 .stop_streaming
= video_stop_streaming
,
429 /* -----------------------------------------------------------------------------
433 static int video_querycap(struct file
*file
, void *fh
,
434 struct v4l2_capability
*cap
)
436 struct camss_video
*video
= video_drvdata(file
);
438 strlcpy(cap
->driver
, "qcom-camss", sizeof(cap
->driver
));
439 strlcpy(cap
->card
, "Qualcomm Camera Subsystem", sizeof(cap
->card
));
440 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "platform:%s",
441 dev_name(video
->camss
->dev
));
446 static int video_enum_fmt(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*f
)
448 struct camss_video
*video
= video_drvdata(file
);
451 if (f
->type
!= video
->type
)
454 if (f
->index
>= video
->nformats
)
457 /* find index "i" of "k"th unique pixelformat in formats array */
459 for (i
= 0; i
< video
->nformats
; i
++) {
460 for (j
= 0; j
< i
; j
++) {
461 if (video
->formats
[i
].pixelformat
==
462 video
->formats
[j
].pixelformat
)
476 f
->pixelformat
= video
->formats
[i
].pixelformat
;
481 static int video_g_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
483 struct camss_video
*video
= video_drvdata(file
);
485 *f
= video
->active_fmt
;
490 static int __video_try_fmt(struct camss_video
*video
, struct v4l2_format
*f
)
492 struct v4l2_pix_format_mplane
*pix_mp
;
493 const struct camss_format_info
*fi
;
494 struct v4l2_plane_pix_format
*p
;
495 u32 bytesperline
[3] = { 0 };
496 u32 sizeimage
[3] = { 0 };
501 pix_mp
= &f
->fmt
.pix_mp
;
503 if (video
->line_based
)
504 for (i
= 0; i
< pix_mp
->num_planes
&& i
< 3; i
++) {
505 p
= &pix_mp
->plane_fmt
[i
];
506 bytesperline
[i
] = clamp_t(u32
, p
->bytesperline
,
508 sizeimage
[i
] = clamp_t(u32
, p
->sizeimage
,
510 bytesperline
[i
] * 4096);
513 for (j
= 0; j
< video
->nformats
; j
++)
514 if (pix_mp
->pixelformat
== video
->formats
[j
].pixelformat
)
517 if (j
== video
->nformats
)
518 j
= 0; /* default format */
520 fi
= &video
->formats
[j
];
521 width
= pix_mp
->width
;
522 height
= pix_mp
->height
;
524 memset(pix_mp
, 0, sizeof(*pix_mp
));
526 pix_mp
->pixelformat
= fi
->pixelformat
;
527 pix_mp
->width
= clamp_t(u32
, width
, 1, 8191);
528 pix_mp
->height
= clamp_t(u32
, height
, 1, 8191);
529 pix_mp
->num_planes
= fi
->planes
;
530 for (i
= 0; i
< pix_mp
->num_planes
; i
++) {
531 bpl
= pix_mp
->width
/ fi
->hsub
[i
].numerator
*
532 fi
->hsub
[i
].denominator
* fi
->bpp
[i
] / 8;
533 bpl
= ALIGN(bpl
, video
->bpl_alignment
);
534 pix_mp
->plane_fmt
[i
].bytesperline
= bpl
;
535 pix_mp
->plane_fmt
[i
].sizeimage
= pix_mp
->height
/
536 fi
->vsub
[i
].numerator
* fi
->vsub
[i
].denominator
* bpl
;
539 pix_mp
->field
= V4L2_FIELD_NONE
;
540 pix_mp
->colorspace
= V4L2_COLORSPACE_SRGB
;
542 pix_mp
->ycbcr_enc
= V4L2_MAP_YCBCR_ENC_DEFAULT(pix_mp
->colorspace
);
543 pix_mp
->quantization
= V4L2_MAP_QUANTIZATION_DEFAULT(true,
544 pix_mp
->colorspace
, pix_mp
->ycbcr_enc
);
545 pix_mp
->xfer_func
= V4L2_MAP_XFER_FUNC_DEFAULT(pix_mp
->colorspace
);
547 if (video
->line_based
)
548 for (i
= 0; i
< pix_mp
->num_planes
; i
++) {
549 p
= &pix_mp
->plane_fmt
[i
];
550 p
->bytesperline
= clamp_t(u32
, p
->bytesperline
,
552 p
->sizeimage
= clamp_t(u32
, p
->sizeimage
,
554 p
->bytesperline
* 4096);
555 lines
= p
->sizeimage
/ p
->bytesperline
;
557 if (p
->bytesperline
< bytesperline
[i
])
558 p
->bytesperline
= ALIGN(bytesperline
[i
], 8);
560 if (p
->sizeimage
< p
->bytesperline
* lines
)
561 p
->sizeimage
= p
->bytesperline
* lines
;
563 if (p
->sizeimage
< sizeimage
[i
])
564 p
->sizeimage
= sizeimage
[i
];
570 static int video_try_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
572 struct camss_video
*video
= video_drvdata(file
);
574 return __video_try_fmt(video
, f
);
577 static int video_s_fmt(struct file
*file
, void *fh
, struct v4l2_format
*f
)
579 struct camss_video
*video
= video_drvdata(file
);
582 if (vb2_is_busy(&video
->vb2_q
))
585 ret
= __video_try_fmt(video
, f
);
589 video
->active_fmt
= *f
;
594 static int video_enum_input(struct file
*file
, void *fh
,
595 struct v4l2_input
*input
)
597 if (input
->index
> 0)
600 strlcpy(input
->name
, "camera", sizeof(input
->name
));
601 input
->type
= V4L2_INPUT_TYPE_CAMERA
;
606 static int video_g_input(struct file
*file
, void *fh
, unsigned int *input
)
613 static int video_s_input(struct file
*file
, void *fh
, unsigned int input
)
615 return input
== 0 ? 0 : -EINVAL
;
618 static const struct v4l2_ioctl_ops msm_vid_ioctl_ops
= {
619 .vidioc_querycap
= video_querycap
,
620 .vidioc_enum_fmt_vid_cap_mplane
= video_enum_fmt
,
621 .vidioc_g_fmt_vid_cap_mplane
= video_g_fmt
,
622 .vidioc_s_fmt_vid_cap_mplane
= video_s_fmt
,
623 .vidioc_try_fmt_vid_cap_mplane
= video_try_fmt
,
624 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
625 .vidioc_querybuf
= vb2_ioctl_querybuf
,
626 .vidioc_qbuf
= vb2_ioctl_qbuf
,
627 .vidioc_expbuf
= vb2_ioctl_expbuf
,
628 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
629 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
630 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
631 .vidioc_streamon
= vb2_ioctl_streamon
,
632 .vidioc_streamoff
= vb2_ioctl_streamoff
,
633 .vidioc_enum_input
= video_enum_input
,
634 .vidioc_g_input
= video_g_input
,
635 .vidioc_s_input
= video_s_input
,
638 /* -----------------------------------------------------------------------------
639 * V4L2 file operations
642 static int video_open(struct file
*file
)
644 struct video_device
*vdev
= video_devdata(file
);
645 struct camss_video
*video
= video_drvdata(file
);
649 mutex_lock(&video
->lock
);
651 vfh
= kzalloc(sizeof(*vfh
), GFP_KERNEL
);
657 v4l2_fh_init(vfh
, vdev
);
660 file
->private_data
= vfh
;
662 ret
= v4l2_pipeline_pm_use(&vdev
->entity
, 1);
664 dev_err(video
->camss
->dev
, "Failed to power up pipeline: %d\n",
669 mutex_unlock(&video
->lock
);
674 v4l2_fh_release(file
);
677 mutex_unlock(&video
->lock
);
682 static int video_release(struct file
*file
)
684 struct video_device
*vdev
= video_devdata(file
);
686 vb2_fop_release(file
);
688 v4l2_pipeline_pm_use(&vdev
->entity
, 0);
690 file
->private_data
= NULL
;
695 static const struct v4l2_file_operations msm_vid_fops
= {
696 .owner
= THIS_MODULE
,
697 .unlocked_ioctl
= video_ioctl2
,
699 .release
= video_release
,
700 .poll
= vb2_fop_poll
,
701 .mmap
= vb2_fop_mmap
,
702 .read
= vb2_fop_read
,
705 /* -----------------------------------------------------------------------------
709 static void msm_video_release(struct video_device
*vdev
)
711 struct camss_video
*video
= video_get_drvdata(vdev
);
713 media_entity_cleanup(&vdev
->entity
);
715 mutex_destroy(&video
->q_lock
);
716 mutex_destroy(&video
->lock
);
718 if (atomic_dec_and_test(&video
->camss
->ref_count
))
719 camss_delete(video
->camss
);
723 * msm_video_init_format - Helper function to initialize format
724 * @video: struct camss_video
726 * Initialize pad format with default value.
728 * Return 0 on success or a negative error code otherwise
730 static int msm_video_init_format(struct camss_video
*video
)
733 struct v4l2_format format
= {
734 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
,
738 .pixelformat
= video
->formats
[0].pixelformat
,
742 ret
= __video_try_fmt(video
, &format
);
746 video
->active_fmt
= format
;
752 * msm_video_register - Register a video device node
753 * @video: struct camss_video
754 * @v4l2_dev: V4L2 device
755 * @name: name to be used for the video device node
757 * Initialize and register a video device node to a V4L2 device. Also
758 * initialize the vb2 queue.
760 * Return 0 on success or a negative error code otherwise
763 int msm_video_register(struct camss_video
*video
, struct v4l2_device
*v4l2_dev
,
764 const char *name
, int is_pix
)
766 struct media_pad
*pad
= &video
->pad
;
767 struct video_device
*vdev
;
773 mutex_init(&video
->q_lock
);
777 q
->mem_ops
= &vb2_dma_sg_memops
;
778 q
->ops
= &msm_video_vb2_q_ops
;
779 q
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
780 q
->io_modes
= VB2_DMABUF
| VB2_MMAP
| VB2_READ
;
781 q
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
;
782 q
->buf_struct_size
= sizeof(struct camss_buffer
);
783 q
->dev
= video
->camss
->dev
;
784 q
->lock
= &video
->q_lock
;
785 ret
= vb2_queue_init(q
);
787 dev_err(v4l2_dev
->dev
, "Failed to init vb2 queue: %d\n", ret
);
791 pad
->flags
= MEDIA_PAD_FL_SINK
;
792 ret
= media_entity_pads_init(&vdev
->entity
, 1, pad
);
794 dev_err(v4l2_dev
->dev
, "Failed to init video entity: %d\n",
796 goto error_media_init
;
799 mutex_init(&video
->lock
);
801 video
->formats
= formats_rdi
;
802 video
->nformats
= ARRAY_SIZE(formats_rdi
);
804 video
->formats
= formats_pix
;
805 video
->nformats
= ARRAY_SIZE(formats_pix
);
808 ret
= msm_video_init_format(video
);
810 dev_err(v4l2_dev
->dev
, "Failed to init format: %d\n", ret
);
811 goto error_video_register
;
814 vdev
->fops
= &msm_vid_fops
;
815 vdev
->device_caps
= V4L2_CAP_VIDEO_CAPTURE_MPLANE
| V4L2_CAP_STREAMING
|
817 vdev
->ioctl_ops
= &msm_vid_ioctl_ops
;
818 vdev
->release
= msm_video_release
;
819 vdev
->v4l2_dev
= v4l2_dev
;
820 vdev
->vfl_dir
= VFL_DIR_RX
;
821 vdev
->queue
= &video
->vb2_q
;
822 vdev
->lock
= &video
->lock
;
823 strlcpy(vdev
->name
, name
, sizeof(vdev
->name
));
825 ret
= video_register_device(vdev
, VFL_TYPE_GRABBER
, -1);
827 dev_err(v4l2_dev
->dev
, "Failed to register video device: %d\n",
829 goto error_video_register
;
832 video_set_drvdata(vdev
, video
);
833 atomic_inc(&video
->camss
->ref_count
);
837 error_video_register
:
838 media_entity_cleanup(&vdev
->entity
);
839 mutex_destroy(&video
->lock
);
841 vb2_queue_release(&video
->vb2_q
);
843 mutex_destroy(&video
->q_lock
);
848 void msm_video_stop_streaming(struct camss_video
*video
)
850 if (vb2_is_streaming(&video
->vb2_q
))
851 vb2_queue_release(&video
->vb2_q
);
854 void msm_video_unregister(struct camss_video
*video
)
856 atomic_inc(&video
->camss
->ref_count
);
857 video_unregister_device(&video
->vdev
);
858 atomic_dec(&video
->camss
->ref_count
);