Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / media / platform / qcom / camss-8x16 / camss-video.c
blobffaa2849e0c148511a518b95b487bc3d24c2a379
1 /*
2 * camss-video.c
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"
27 #include "camss.h"
29 struct fract {
30 u8 numerator;
31 u8 denominator;
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 {
44 u32 code;
45 u32 pixelformat;
46 u8 planes;
47 struct fract hsub[3];
48 struct fract vsub[3];
49 unsigned int bpp[3];
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 /* -----------------------------------------------------------------------------
123 * Helper functions
126 static int video_find_format(u32 code, u32 pixelformat,
127 const struct camss_format_info *formats,
128 unsigned int nformats)
130 int i;
132 for (i = 0; i < nformats; i++) {
133 if (formats[i].code == code &&
134 formats[i].pixelformat == pixelformat)
135 return i;
138 for (i = 0; i < nformats; i++)
139 if (formats[i].code == code)
140 return i;
142 WARN_ON(1);
144 return -EINVAL;
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)
163 unsigned int i;
164 u32 bytesperline;
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 *
177 bytesperline;
180 return 0;
183 static struct v4l2_subdev *video_remote_subdev(struct camss_video *video,
184 u32 *pad)
186 struct media_pad *remote;
188 remote = media_entity_remote_pad(&video->pad);
190 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
191 return NULL;
193 if (pad)
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;
204 u32 pad;
205 int ret;
207 subdev = video_remote_subdev(video, &pad);
208 if (subdev == NULL)
209 return -EPIPE;
211 fmt.pad = pad;
212 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
214 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
215 if (ret)
216 return ret;
218 ret = video_find_format(fmt.format.code,
219 format->fmt.pix_mp.pixelformat,
220 video->formats, video->nformats);
221 if (ret < 0)
222 return ret;
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;
241 unsigned int i;
243 if (*num_planes) {
244 if (*num_planes != format->num_planes)
245 return -EINVAL;
247 for (i = 0; i < *num_planes; i++)
248 if (sizes[i] < format->plane_fmt[i].sizeimage)
249 return -EINVAL;
251 return 0;
254 *num_planes = format->num_planes;
256 for (i = 0; i < *num_planes; i++)
257 sizes[i] = format->plane_fmt[i].sizeimage;
259 return 0;
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,
267 vb);
268 const struct v4l2_pix_format_mplane *format =
269 &video->active_fmt.fmt.pix_mp;
270 struct sg_table *sgt;
271 unsigned int i;
273 for (i = 0; i < format->num_planes; i++) {
274 sgt = vb2_dma_sg_plane_desc(vb, i);
275 if (!sgt)
276 return -EFAULT;
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 *
287 format->height;
289 return 0;
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;
298 unsigned int i;
300 for (i = 0; i < format->num_planes; i++) {
301 if (format->plane_fmt[i].sizeimage > vb2_plane_size(vb, i))
302 return -EINVAL;
304 vb2_set_plane_payload(vb, i, format->plane_fmt[i].sizeimage);
307 vbuf->field = V4L2_FIELD_NONE;
309 return 0;
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,
317 vb);
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;
327 int ret;
329 sd_pix->pixelformat = pix->pixelformat;
330 ret = video_get_subdev_format(video, &format);
331 if (ret < 0)
332 return ret;
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)
339 return -EPIPE;
341 return 0;
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;
351 int ret;
353 ret = media_pipeline_start(&vdev->entity, &video->pipe);
354 if (ret < 0)
355 return ret;
357 ret = video_check_format(video);
358 if (ret < 0)
359 goto error;
361 entity = &vdev->entity;
362 while (1) {
363 pad = &entity->pads[0];
364 if (!(pad->flags & MEDIA_PAD_FL_SINK))
365 break;
367 pad = media_entity_remote_pad(pad);
368 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
369 break;
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)
376 goto error;
379 return 0;
381 error:
382 media_pipeline_stop(&vdev->entity);
384 video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
386 return ret;
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;
398 while (1) {
399 pad = &entity->pads[0];
400 if (!(pad->flags & MEDIA_PAD_FL_SINK))
401 break;
403 pad = media_entity_remote_pad(pad);
404 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
405 break;
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 /* -----------------------------------------------------------------------------
430 * V4L2 ioctls
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));
443 return 0;
446 static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
448 struct camss_video *video = video_drvdata(file);
449 int i, j, k;
451 if (f->type != video->type)
452 return -EINVAL;
454 if (f->index >= video->nformats)
455 return -EINVAL;
457 /* find index "i" of "k"th unique pixelformat in formats array */
458 k = -1;
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)
463 break;
466 if (j == i)
467 k++;
469 if (k == f->index)
470 break;
473 if (k < f->index)
474 return -EINVAL;
476 f->pixelformat = video->formats[i].pixelformat;
478 return 0;
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;
487 return 0;
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 };
497 u32 width, height;
498 u32 bpl, lines;
499 int i, j;
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,
507 1, 65528);
508 sizeimage[i] = clamp_t(u32, p->sizeimage,
509 bytesperline[i],
510 bytesperline[i] * 4096);
513 for (j = 0; j < video->nformats; j++)
514 if (pix_mp->pixelformat == video->formats[j].pixelformat)
515 break;
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;
541 pix_mp->flags = 0;
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,
551 1, 65528);
552 p->sizeimage = clamp_t(u32, p->sizeimage,
553 p->bytesperline,
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];
567 return 0;
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);
580 int ret;
582 if (vb2_is_busy(&video->vb2_q))
583 return -EBUSY;
585 ret = __video_try_fmt(video, f);
586 if (ret < 0)
587 return ret;
589 video->active_fmt = *f;
591 return 0;
594 static int video_enum_input(struct file *file, void *fh,
595 struct v4l2_input *input)
597 if (input->index > 0)
598 return -EINVAL;
600 strlcpy(input->name, "camera", sizeof(input->name));
601 input->type = V4L2_INPUT_TYPE_CAMERA;
603 return 0;
606 static int video_g_input(struct file *file, void *fh, unsigned int *input)
608 *input = 0;
610 return 0;
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);
646 struct v4l2_fh *vfh;
647 int ret;
649 mutex_lock(&video->lock);
651 vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
652 if (vfh == NULL) {
653 ret = -ENOMEM;
654 goto error_alloc;
657 v4l2_fh_init(vfh, vdev);
658 v4l2_fh_add(vfh);
660 file->private_data = vfh;
662 ret = v4l2_pipeline_pm_use(&vdev->entity, 1);
663 if (ret < 0) {
664 dev_err(video->camss->dev, "Failed to power up pipeline: %d\n",
665 ret);
666 goto error_pm_use;
669 mutex_unlock(&video->lock);
671 return 0;
673 error_pm_use:
674 v4l2_fh_release(file);
676 error_alloc:
677 mutex_unlock(&video->lock);
679 return ret;
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;
692 return 0;
695 static const struct v4l2_file_operations msm_vid_fops = {
696 .owner = THIS_MODULE,
697 .unlocked_ioctl = video_ioctl2,
698 .open = video_open,
699 .release = video_release,
700 .poll = vb2_fop_poll,
701 .mmap = vb2_fop_mmap,
702 .read = vb2_fop_read,
705 /* -----------------------------------------------------------------------------
706 * CAMSS video core
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)
732 int ret;
733 struct v4l2_format format = {
734 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
735 .fmt.pix_mp = {
736 .width = 1920,
737 .height = 1080,
738 .pixelformat = video->formats[0].pixelformat,
742 ret = __video_try_fmt(video, &format);
743 if (ret < 0)
744 return ret;
746 video->active_fmt = format;
748 return 0;
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;
768 struct vb2_queue *q;
769 int ret;
771 vdev = &video->vdev;
773 mutex_init(&video->q_lock);
775 q = &video->vb2_q;
776 q->drv_priv = video;
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);
786 if (ret < 0) {
787 dev_err(v4l2_dev->dev, "Failed to init vb2 queue: %d\n", ret);
788 goto error_vb2_init;
791 pad->flags = MEDIA_PAD_FL_SINK;
792 ret = media_entity_pads_init(&vdev->entity, 1, pad);
793 if (ret < 0) {
794 dev_err(v4l2_dev->dev, "Failed to init video entity: %d\n",
795 ret);
796 goto error_media_init;
799 mutex_init(&video->lock);
801 video->formats = formats_rdi;
802 video->nformats = ARRAY_SIZE(formats_rdi);
803 if (is_pix) {
804 video->formats = formats_pix;
805 video->nformats = ARRAY_SIZE(formats_pix);
808 ret = msm_video_init_format(video);
809 if (ret < 0) {
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 |
816 V4L2_CAP_READWRITE;
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);
826 if (ret < 0) {
827 dev_err(v4l2_dev->dev, "Failed to register video device: %d\n",
828 ret);
829 goto error_video_register;
832 video_set_drvdata(vdev, video);
833 atomic_inc(&video->camss->ref_count);
835 return 0;
837 error_video_register:
838 media_entity_cleanup(&vdev->entity);
839 mutex_destroy(&video->lock);
840 error_media_init:
841 vb2_queue_release(&video->vb2_q);
842 error_vb2_init:
843 mutex_destroy(&video->q_lock);
845 return ret;
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);