1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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/videobuf-core.h>
25#include <media/videobuf2-dma-sg.h>
26
27#include "camss-video.h"
28#include "camss.h"
29
30struct fract {
31 u8 numerator;
32 u8 denominator;
33};
34
35
36
37
38
39
40
41
42
43
44struct camss_format_info {
45 u32 code;
46 u32 pixelformat;
47 u8 planes;
48 struct fract hsub[3];
49 struct fract vsub[3];
50 unsigned int bpp[3];
51};
52
53static const struct camss_format_info formats_rdi[] = {
54 { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1,
55 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
56 { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1,
57 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
58 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
59 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
60 { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1,
61 { { 1, 1 } }, { { 1, 1 } }, { 16 } },
62 { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1,
63 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
64 { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1,
65 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
66 { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1,
67 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
68 { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1,
69 { { 1, 1 } }, { { 1, 1 } }, { 8 } },
70 { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1,
71 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
72 { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1,
73 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
74 { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1,
75 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
76 { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1,
77 { { 1, 1 } }, { { 1, 1 } }, { 10 } },
78 { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1,
79 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
80 { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1,
81 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
82 { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1,
83 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
84 { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1,
85 { { 1, 1 } }, { { 1, 1 } }, { 12 } },
86};
87
88static const struct camss_format_info formats_pix[] = {
89 { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1,
90 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
91 { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1,
92 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
93 { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
94 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
95 { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
96 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
97 { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1,
98 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
99 { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1,
100 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
101 { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
102 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
103 { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
104 { { 1, 1 } }, { { 2, 3 } }, { 8 } },
105 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1,
106 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
107 { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1,
108 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
109 { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1,
110 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
111 { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1,
112 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
113 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1,
114 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
115 { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1,
116 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
117 { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1,
118 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
119 { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1,
120 { { 1, 1 } }, { { 1, 2 } }, { 8 } },
121};
122
123
124
125
126
127static int video_find_format(u32 code, u32 pixelformat,
128 const struct camss_format_info *formats,
129 unsigned int nformats)
130{
131 int i;
132
133 for (i = 0; i < nformats; i++) {
134 if (formats[i].code == code &&
135 formats[i].pixelformat == pixelformat)
136 return i;
137 }
138
139 for (i = 0; i < nformats; i++)
140 if (formats[i].code == code)
141 return i;
142
143 WARN_ON(1);
144
145 return -EINVAL;
146}
147
148
149
150
151
152
153
154
155
156
157
158
159static int video_mbus_to_pix_mp(const struct v4l2_mbus_framefmt *mbus,
160 struct v4l2_pix_format_mplane *pix,
161 const struct camss_format_info *f,
162 unsigned int alignment)
163{
164 unsigned int i;
165 u32 bytesperline;
166
167 memset(pix, 0, sizeof(*pix));
168 v4l2_fill_pix_format_mplane(pix, mbus);
169 pix->pixelformat = f->pixelformat;
170 pix->num_planes = f->planes;
171 for (i = 0; i < pix->num_planes; i++) {
172 bytesperline = pix->width / f->hsub[i].numerator *
173 f->hsub[i].denominator * f->bpp[i] / 8;
174 bytesperline = ALIGN(bytesperline, alignment);
175 pix->plane_fmt[i].bytesperline = bytesperline;
176 pix->plane_fmt[i].sizeimage = pix->height /
177 f->vsub[i].numerator * f->vsub[i].denominator *
178 bytesperline;
179 }
180
181 return 0;
182}
183
184static struct v4l2_subdev *video_remote_subdev(struct camss_video *video,
185 u32 *pad)
186{
187 struct media_pad *remote;
188
189 remote = media_entity_remote_pad(&video->pad);
190
191 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
192 return NULL;
193
194 if (pad)
195 *pad = remote->index;
196
197 return media_entity_to_v4l2_subdev(remote->entity);
198}
199
200static int video_get_subdev_format(struct camss_video *video,
201 struct v4l2_format *format)
202{
203 struct v4l2_subdev_format fmt;
204 struct v4l2_subdev *subdev;
205 u32 pad;
206 int ret;
207
208 subdev = video_remote_subdev(video, &pad);
209 if (subdev == NULL)
210 return -EPIPE;
211
212 fmt.pad = pad;
213 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
214
215 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
216 if (ret)
217 return ret;
218
219 ret = video_find_format(fmt.format.code,
220 format->fmt.pix_mp.pixelformat,
221 video->formats, video->nformats);
222 if (ret < 0)
223 return ret;
224
225 format->type = video->type;
226
227 return video_mbus_to_pix_mp(&fmt.format, &format->fmt.pix_mp,
228 &video->formats[ret], video->bpl_alignment);
229}
230
231
232
233
234
235static int video_queue_setup(struct vb2_queue *q,
236 unsigned int *num_buffers, unsigned int *num_planes,
237 unsigned int sizes[], struct device *alloc_devs[])
238{
239 struct camss_video *video = vb2_get_drv_priv(q);
240 const struct v4l2_pix_format_mplane *format =
241 &video->active_fmt.fmt.pix_mp;
242 unsigned int i;
243
244 if (*num_planes) {
245 if (*num_planes != format->num_planes)
246 return -EINVAL;
247
248 for (i = 0; i < *num_planes; i++)
249 if (sizes[i] < format->plane_fmt[i].sizeimage)
250 return -EINVAL;
251
252 return 0;
253 }
254
255 *num_planes = format->num_planes;
256
257 for (i = 0; i < *num_planes; i++)
258 sizes[i] = format->plane_fmt[i].sizeimage;
259
260 return 0;
261}
262
263static int video_buf_init(struct vb2_buffer *vb)
264{
265 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
266 struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
267 struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer,
268 vb);
269 const struct v4l2_pix_format_mplane *format =
270 &video->active_fmt.fmt.pix_mp;
271 struct sg_table *sgt;
272 unsigned int i;
273
274 for (i = 0; i < format->num_planes; i++) {
275 sgt = vb2_dma_sg_plane_desc(vb, i);
276 if (!sgt)
277 return -EFAULT;
278
279 buffer->addr[i] = sg_dma_address(sgt->sgl);
280 }
281
282 if (format->pixelformat == V4L2_PIX_FMT_NV12 ||
283 format->pixelformat == V4L2_PIX_FMT_NV21 ||
284 format->pixelformat == V4L2_PIX_FMT_NV16 ||
285 format->pixelformat == V4L2_PIX_FMT_NV61)
286 buffer->addr[1] = buffer->addr[0] +
287 format->plane_fmt[0].bytesperline *
288 format->height;
289
290 return 0;
291}
292
293static int video_buf_prepare(struct vb2_buffer *vb)
294{
295 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
296 struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
297 const struct v4l2_pix_format_mplane *format =
298 &video->active_fmt.fmt.pix_mp;
299 unsigned int i;
300
301 for (i = 0; i < format->num_planes; i++) {
302 if (format->plane_fmt[i].sizeimage > vb2_plane_size(vb, i))
303 return -EINVAL;
304
305 vb2_set_plane_payload(vb, i, format->plane_fmt[i].sizeimage);
306 }
307
308 vbuf->field = V4L2_FIELD_NONE;
309
310 return 0;
311}
312
313static void video_buf_queue(struct vb2_buffer *vb)
314{
315 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
316 struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
317 struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer,
318 vb);
319
320 video->ops->queue_buffer(video, buffer);
321}
322
323static int video_check_format(struct camss_video *video)
324{
325 struct v4l2_pix_format_mplane *pix = &video->active_fmt.fmt.pix_mp;
326 struct v4l2_format format;
327 struct v4l2_pix_format_mplane *sd_pix = &format.fmt.pix_mp;
328 int ret;
329
330 sd_pix->pixelformat = pix->pixelformat;
331 ret = video_get_subdev_format(video, &format);
332 if (ret < 0)
333 return ret;
334
335 if (pix->pixelformat != sd_pix->pixelformat ||
336 pix->height != sd_pix->height ||
337 pix->width != sd_pix->width ||
338 pix->num_planes != sd_pix->num_planes ||
339 pix->field != format.fmt.pix_mp.field)
340 return -EPIPE;
341
342 return 0;
343}
344
345static int video_start_streaming(struct vb2_queue *q, unsigned int count)
346{
347 struct camss_video *video = vb2_get_drv_priv(q);
348 struct video_device *vdev = &video->vdev;
349 struct media_entity *entity;
350 struct media_pad *pad;
351 struct v4l2_subdev *subdev;
352 int ret;
353
354 ret = media_pipeline_start(&vdev->entity, &video->pipe);
355 if (ret < 0)
356 return ret;
357
358 ret = video_check_format(video);
359 if (ret < 0)
360 goto error;
361
362 entity = &vdev->entity;
363 while (1) {
364 pad = &entity->pads[0];
365 if (!(pad->flags & MEDIA_PAD_FL_SINK))
366 break;
367
368 pad = media_entity_remote_pad(pad);
369 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
370 break;
371
372 entity = pad->entity;
373 subdev = media_entity_to_v4l2_subdev(entity);
374
375 ret = v4l2_subdev_call(subdev, video, s_stream, 1);
376 if (ret < 0 && ret != -ENOIOCTLCMD)
377 goto error;
378 }
379
380 return 0;
381
382error:
383 media_pipeline_stop(&vdev->entity);
384
385 video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
386
387 return ret;
388}
389
390static void video_stop_streaming(struct vb2_queue *q)
391{
392 struct camss_video *video = vb2_get_drv_priv(q);
393 struct video_device *vdev = &video->vdev;
394 struct media_entity *entity;
395 struct media_pad *pad;
396 struct v4l2_subdev *subdev;
397
398 entity = &vdev->entity;
399 while (1) {
400 pad = &entity->pads[0];
401 if (!(pad->flags & MEDIA_PAD_FL_SINK))
402 break;
403
404 pad = media_entity_remote_pad(pad);
405 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
406 break;
407
408 entity = pad->entity;
409 subdev = media_entity_to_v4l2_subdev(entity);
410
411 v4l2_subdev_call(subdev, video, s_stream, 0);
412 }
413
414 media_pipeline_stop(&vdev->entity);
415
416 video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
417}
418
419static const struct vb2_ops msm_video_vb2_q_ops = {
420 .queue_setup = video_queue_setup,
421 .wait_prepare = vb2_ops_wait_prepare,
422 .wait_finish = vb2_ops_wait_finish,
423 .buf_init = video_buf_init,
424 .buf_prepare = video_buf_prepare,
425 .buf_queue = video_buf_queue,
426 .start_streaming = video_start_streaming,
427 .stop_streaming = video_stop_streaming,
428};
429
430
431
432
433
434static int video_querycap(struct file *file, void *fh,
435 struct v4l2_capability *cap)
436{
437 struct camss_video *video = video_drvdata(file);
438
439 strlcpy(cap->driver, "qcom-camss", sizeof(cap->driver));
440 strlcpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card));
441 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
442 dev_name(video->camss->dev));
443
444 return 0;
445}
446
447static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
448{
449 struct camss_video *video = video_drvdata(file);
450 int i, j, k;
451
452 if (f->type != video->type)
453 return -EINVAL;
454
455 if (f->index >= video->nformats)
456 return -EINVAL;
457
458
459 k = -1;
460 for (i = 0; i < video->nformats; i++) {
461 for (j = 0; j < i; j++) {
462 if (video->formats[i].pixelformat ==
463 video->formats[j].pixelformat)
464 break;
465 }
466
467 if (j == i)
468 k++;
469
470 if (k == f->index)
471 break;
472 }
473
474 if (k < f->index)
475 return -EINVAL;
476
477 f->pixelformat = video->formats[i].pixelformat;
478
479 return 0;
480}
481
482static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
483{
484 struct camss_video *video = video_drvdata(file);
485
486 *f = video->active_fmt;
487
488 return 0;
489}
490
491static int __video_try_fmt(struct camss_video *video, struct v4l2_format *f)
492{
493 struct v4l2_pix_format_mplane *pix_mp;
494 const struct camss_format_info *fi;
495 struct v4l2_plane_pix_format *p;
496 u32 bytesperline[3] = { 0 };
497 u32 sizeimage[3] = { 0 };
498 u32 width, height;
499 u32 bpl, lines;
500 int i, j;
501
502 pix_mp = &f->fmt.pix_mp;
503
504 if (video->line_based)
505 for (i = 0; i < pix_mp->num_planes && i < 3; i++) {
506 p = &pix_mp->plane_fmt[i];
507 bytesperline[i] = clamp_t(u32, p->bytesperline,
508 1, 65528);
509 sizeimage[i] = clamp_t(u32, p->sizeimage,
510 bytesperline[i],
511 bytesperline[i] * 4096);
512 }
513
514 for (j = 0; j < video->nformats; j++)
515 if (pix_mp->pixelformat == video->formats[j].pixelformat)
516 break;
517
518 if (j == video->nformats)
519 j = 0;
520
521 fi = &video->formats[j];
522 width = pix_mp->width;
523 height = pix_mp->height;
524
525 memset(pix_mp, 0, sizeof(*pix_mp));
526
527 pix_mp->pixelformat = fi->pixelformat;
528 pix_mp->width = clamp_t(u32, width, 1, 8191);
529 pix_mp->height = clamp_t(u32, height, 1, 8191);
530 pix_mp->num_planes = fi->planes;
531 for (i = 0; i < pix_mp->num_planes; i++) {
532 bpl = pix_mp->width / fi->hsub[i].numerator *
533 fi->hsub[i].denominator * fi->bpp[i] / 8;
534 bpl = ALIGN(bpl, video->bpl_alignment);
535 pix_mp->plane_fmt[i].bytesperline = bpl;
536 pix_mp->plane_fmt[i].sizeimage = pix_mp->height /
537 fi->vsub[i].numerator * fi->vsub[i].denominator * bpl;
538 }
539
540 pix_mp->field = V4L2_FIELD_NONE;
541 pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
542 pix_mp->flags = 0;
543 pix_mp->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix_mp->colorspace);
544 pix_mp->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
545 pix_mp->colorspace, pix_mp->ycbcr_enc);
546 pix_mp->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix_mp->colorspace);
547
548 if (video->line_based)
549 for (i = 0; i < pix_mp->num_planes; i++) {
550 p = &pix_mp->plane_fmt[i];
551 p->bytesperline = clamp_t(u32, p->bytesperline,
552 1, 65528);
553 p->sizeimage = clamp_t(u32, p->sizeimage,
554 p->bytesperline,
555 p->bytesperline * 4096);
556 lines = p->sizeimage / p->bytesperline;
557
558 if (p->bytesperline < bytesperline[i])
559 p->bytesperline = ALIGN(bytesperline[i], 8);
560
561 if (p->sizeimage < p->bytesperline * lines)
562 p->sizeimage = p->bytesperline * lines;
563
564 if (p->sizeimage < sizeimage[i])
565 p->sizeimage = sizeimage[i];
566 }
567
568 return 0;
569}
570
571static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
572{
573 struct camss_video *video = video_drvdata(file);
574
575 return __video_try_fmt(video, f);
576}
577
578static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
579{
580 struct camss_video *video = video_drvdata(file);
581 int ret;
582
583 if (vb2_is_busy(&video->vb2_q))
584 return -EBUSY;
585
586 ret = __video_try_fmt(video, f);
587 if (ret < 0)
588 return ret;
589
590 video->active_fmt = *f;
591
592 return 0;
593}
594
595static int video_enum_input(struct file *file, void *fh,
596 struct v4l2_input *input)
597{
598 if (input->index > 0)
599 return -EINVAL;
600
601 strlcpy(input->name, "camera", sizeof(input->name));
602 input->type = V4L2_INPUT_TYPE_CAMERA;
603
604 return 0;
605}
606
607static int video_g_input(struct file *file, void *fh, unsigned int *input)
608{
609 *input = 0;
610
611 return 0;
612}
613
614static int video_s_input(struct file *file, void *fh, unsigned int input)
615{
616 return input == 0 ? 0 : -EINVAL;
617}
618
619static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = {
620 .vidioc_querycap = video_querycap,
621 .vidioc_enum_fmt_vid_cap_mplane = video_enum_fmt,
622 .vidioc_g_fmt_vid_cap_mplane = video_g_fmt,
623 .vidioc_s_fmt_vid_cap_mplane = video_s_fmt,
624 .vidioc_try_fmt_vid_cap_mplane = video_try_fmt,
625 .vidioc_reqbufs = vb2_ioctl_reqbufs,
626 .vidioc_querybuf = vb2_ioctl_querybuf,
627 .vidioc_qbuf = vb2_ioctl_qbuf,
628 .vidioc_expbuf = vb2_ioctl_expbuf,
629 .vidioc_dqbuf = vb2_ioctl_dqbuf,
630 .vidioc_create_bufs = vb2_ioctl_create_bufs,
631 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
632 .vidioc_streamon = vb2_ioctl_streamon,
633 .vidioc_streamoff = vb2_ioctl_streamoff,
634 .vidioc_enum_input = video_enum_input,
635 .vidioc_g_input = video_g_input,
636 .vidioc_s_input = video_s_input,
637};
638
639
640
641
642
643static int video_open(struct file *file)
644{
645 struct video_device *vdev = video_devdata(file);
646 struct camss_video *video = video_drvdata(file);
647 struct v4l2_fh *vfh;
648 int ret;
649
650 mutex_lock(&video->lock);
651
652 vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
653 if (vfh == NULL) {
654 ret = -ENOMEM;
655 goto error_alloc;
656 }
657
658 v4l2_fh_init(vfh, vdev);
659 v4l2_fh_add(vfh);
660
661 file->private_data = vfh;
662
663 ret = v4l2_pipeline_pm_use(&vdev->entity, 1);
664 if (ret < 0) {
665 dev_err(video->camss->dev, "Failed to power up pipeline: %d\n",
666 ret);
667 goto error_pm_use;
668 }
669
670 mutex_unlock(&video->lock);
671
672 return 0;
673
674error_pm_use:
675 v4l2_fh_release(file);
676
677error_alloc:
678 mutex_unlock(&video->lock);
679
680 return ret;
681}
682
683static int video_release(struct file *file)
684{
685 struct video_device *vdev = video_devdata(file);
686
687 vb2_fop_release(file);
688
689 v4l2_pipeline_pm_use(&vdev->entity, 0);
690
691 file->private_data = NULL;
692
693 return 0;
694}
695
696static const struct v4l2_file_operations msm_vid_fops = {
697 .owner = THIS_MODULE,
698 .unlocked_ioctl = video_ioctl2,
699 .open = video_open,
700 .release = video_release,
701 .poll = vb2_fop_poll,
702 .mmap = vb2_fop_mmap,
703 .read = vb2_fop_read,
704};
705
706
707
708
709
710static void msm_video_release(struct video_device *vdev)
711{
712 struct camss_video *video = video_get_drvdata(vdev);
713
714 media_entity_cleanup(&vdev->entity);
715
716 mutex_destroy(&video->q_lock);
717 mutex_destroy(&video->lock);
718
719 if (atomic_dec_and_test(&video->camss->ref_count))
720 camss_delete(video->camss);
721}
722
723
724
725
726
727
728
729
730
731static int msm_video_init_format(struct camss_video *video)
732{
733 int ret;
734 struct v4l2_format format = {
735 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
736 .fmt.pix_mp = {
737 .width = 1920,
738 .height = 1080,
739 .pixelformat = video->formats[0].pixelformat,
740 },
741 };
742
743 ret = __video_try_fmt(video, &format);
744 if (ret < 0)
745 return ret;
746
747 video->active_fmt = format;
748
749 return 0;
750}
751
752
753
754
755
756
757
758
759
760
761
762
763
764int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev,
765 const char *name, int is_pix)
766{
767 struct media_pad *pad = &video->pad;
768 struct video_device *vdev;
769 struct vb2_queue *q;
770 int ret;
771
772 vdev = &video->vdev;
773
774 mutex_init(&video->q_lock);
775
776 q = &video->vb2_q;
777 q->drv_priv = video;
778 q->mem_ops = &vb2_dma_sg_memops;
779 q->ops = &msm_video_vb2_q_ops;
780 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
781 q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ;
782 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
783 q->buf_struct_size = sizeof(struct camss_buffer);
784 q->dev = video->camss->dev;
785 q->lock = &video->q_lock;
786 ret = vb2_queue_init(q);
787 if (ret < 0) {
788 dev_err(v4l2_dev->dev, "Failed to init vb2 queue: %d\n", ret);
789 goto error_vb2_init;
790 }
791
792 pad->flags = MEDIA_PAD_FL_SINK;
793 ret = media_entity_pads_init(&vdev->entity, 1, pad);
794 if (ret < 0) {
795 dev_err(v4l2_dev->dev, "Failed to init video entity: %d\n",
796 ret);
797 goto error_media_init;
798 }
799
800 mutex_init(&video->lock);
801
802 video->formats = formats_rdi;
803 video->nformats = ARRAY_SIZE(formats_rdi);
804 if (is_pix) {
805 video->formats = formats_pix;
806 video->nformats = ARRAY_SIZE(formats_pix);
807 }
808
809 ret = msm_video_init_format(video);
810 if (ret < 0) {
811 dev_err(v4l2_dev->dev, "Failed to init format: %d\n", ret);
812 goto error_video_register;
813 }
814
815 vdev->fops = &msm_vid_fops;
816 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING |
817 V4L2_CAP_READWRITE;
818 vdev->ioctl_ops = &msm_vid_ioctl_ops;
819 vdev->release = msm_video_release;
820 vdev->v4l2_dev = v4l2_dev;
821 vdev->vfl_dir = VFL_DIR_RX;
822 vdev->queue = &video->vb2_q;
823 vdev->lock = &video->lock;
824 strlcpy(vdev->name, name, sizeof(vdev->name));
825
826 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
827 if (ret < 0) {
828 dev_err(v4l2_dev->dev, "Failed to register video device: %d\n",
829 ret);
830 goto error_video_register;
831 }
832
833 video_set_drvdata(vdev, video);
834 atomic_inc(&video->camss->ref_count);
835
836 return 0;
837
838error_video_register:
839 media_entity_cleanup(&vdev->entity);
840 mutex_destroy(&video->lock);
841error_media_init:
842 vb2_queue_release(&video->vb2_q);
843error_vb2_init:
844 mutex_destroy(&video->q_lock);
845
846 return ret;
847}
848
849void msm_video_stop_streaming(struct camss_video *video)
850{
851 if (vb2_is_streaming(&video->vb2_q))
852 vb2_queue_release(&video->vb2_q);
853}
854
855void msm_video_unregister(struct camss_video *video)
856{
857 atomic_inc(&video->camss->ref_count);
858 video_unregister_device(&video->vdev);
859 atomic_dec(&video->camss->ref_count);
860}
861