1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/clk.h>
15#include <linux/mm.h>
16#include <linux/pagemap.h>
17#include <linux/sched.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h>
20#include <linux/module.h>
21
22#include <media/v4l2-dev.h>
23#include <media/v4l2-ioctl.h>
24#include <media/v4l2-mc.h>
25
26#include <asm/cacheflush.h>
27
28#include "iss_video.h"
29#include "iss.h"
30
31
32
33
34
35static struct iss_format_info formats[] = {
36 { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
37 MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
38 V4L2_PIX_FMT_GREY, 8, "Greyscale 8 bpp", },
39 { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10,
40 MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8,
41 V4L2_PIX_FMT_Y10, 10, "Greyscale 10 bpp", },
42 { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10,
43 MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8,
44 V4L2_PIX_FMT_Y12, 12, "Greyscale 12 bpp", },
45 { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
46 MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
47 V4L2_PIX_FMT_SBGGR8, 8, "BGGR Bayer 8 bpp", },
48 { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
49 MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
50 V4L2_PIX_FMT_SGBRG8, 8, "GBRG Bayer 8 bpp", },
51 { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
52 MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
53 V4L2_PIX_FMT_SGRBG8, 8, "GRBG Bayer 8 bpp", },
54 { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
55 MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
56 V4L2_PIX_FMT_SRGGB8, 8, "RGGB Bayer 8 bpp", },
57 { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
58 MEDIA_BUS_FMT_SGRBG10_1X10, 0,
59 V4L2_PIX_FMT_SGRBG10DPCM8, 8, "GRBG Bayer 10 bpp DPCM8", },
60 { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
61 MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8,
62 V4L2_PIX_FMT_SBGGR10, 10, "BGGR Bayer 10 bpp", },
63 { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
64 MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8,
65 V4L2_PIX_FMT_SGBRG10, 10, "GBRG Bayer 10 bpp", },
66 { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
67 MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8,
68 V4L2_PIX_FMT_SGRBG10, 10, "GRBG Bayer 10 bpp", },
69 { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
70 MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8,
71 V4L2_PIX_FMT_SRGGB10, 10, "RGGB Bayer 10 bpp", },
72 { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10,
73 MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8,
74 V4L2_PIX_FMT_SBGGR12, 12, "BGGR Bayer 12 bpp", },
75 { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10,
76 MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8,
77 V4L2_PIX_FMT_SGBRG12, 12, "GBRG Bayer 12 bpp", },
78 { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10,
79 MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8,
80 V4L2_PIX_FMT_SGRBG12, 12, "GRBG Bayer 12 bpp", },
81 { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10,
82 MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8,
83 V4L2_PIX_FMT_SRGGB12, 12, "RGGB Bayer 12 bpp", },
84 { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16,
85 MEDIA_BUS_FMT_UYVY8_1X16, 0,
86 V4L2_PIX_FMT_UYVY, 16, "YUV 4:2:2 (UYVY)", },
87 { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16,
88 MEDIA_BUS_FMT_YUYV8_1X16, 0,
89 V4L2_PIX_FMT_YUYV, 16, "YUV 4:2:2 (YUYV)", },
90 { MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8,
91 MEDIA_BUS_FMT_YUYV8_1_5X8, 0,
92 V4L2_PIX_FMT_NV12, 8, "YUV 4:2:0 (NV12)", },
93};
94
95const struct iss_format_info *
96omap4iss_video_format_info(u32 code)
97{
98 unsigned int i;
99
100 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
101 if (formats[i].code == code)
102 return &formats[i];
103 }
104
105 return NULL;
106}
107
108
109
110
111
112
113
114
115
116
117
118
119
120static unsigned int iss_video_mbus_to_pix(const struct iss_video *video,
121 const struct v4l2_mbus_framefmt *mbus,
122 struct v4l2_pix_format *pix)
123{
124 unsigned int bpl = pix->bytesperline;
125 unsigned int min_bpl;
126 unsigned int i;
127
128 memset(pix, 0, sizeof(*pix));
129 pix->width = mbus->width;
130 pix->height = mbus->height;
131
132
133
134
135
136 for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
137 if (formats[i].code == mbus->code)
138 break;
139 }
140
141 min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8;
142
143
144
145
146
147
148 if (video->bpl_max)
149 bpl = clamp(bpl, min_bpl, video->bpl_max);
150 else
151 bpl = min_bpl;
152
153 if (!video->bpl_zero_padding || bpl != min_bpl)
154 bpl = ALIGN(bpl, video->bpl_alignment);
155
156 pix->pixelformat = formats[i].pixelformat;
157 pix->bytesperline = bpl;
158 pix->sizeimage = pix->bytesperline * pix->height;
159 pix->colorspace = mbus->colorspace;
160 pix->field = mbus->field;
161
162
163 if (pix->pixelformat == V4L2_PIX_FMT_NV12)
164 pix->sizeimage += (pix->bytesperline * pix->height) / 2;
165
166 return bpl - min_bpl;
167}
168
169static void iss_video_pix_to_mbus(const struct v4l2_pix_format *pix,
170 struct v4l2_mbus_framefmt *mbus)
171{
172 unsigned int i;
173
174 memset(mbus, 0, sizeof(*mbus));
175 mbus->width = pix->width;
176 mbus->height = pix->height;
177
178
179
180
181
182 for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
183 if (formats[i].pixelformat == pix->pixelformat)
184 break;
185 }
186
187 mbus->code = formats[i].code;
188 mbus->colorspace = pix->colorspace;
189 mbus->field = pix->field;
190}
191
192static struct v4l2_subdev *
193iss_video_remote_subdev(struct iss_video *video, u32 *pad)
194{
195 struct media_pad *remote;
196
197 remote = media_entity_remote_pad(&video->pad);
198
199 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
200 return NULL;
201
202 if (pad)
203 *pad = remote->index;
204
205 return media_entity_to_v4l2_subdev(remote->entity);
206}
207
208
209static struct iss_video *
210iss_video_far_end(struct iss_video *video)
211{
212 struct media_graph graph;
213 struct media_entity *entity = &video->video.entity;
214 struct media_device *mdev = entity->graph_obj.mdev;
215 struct iss_video *far_end = NULL;
216
217 mutex_lock(&mdev->graph_mutex);
218
219 if (media_graph_walk_init(&graph, mdev)) {
220 mutex_unlock(&mdev->graph_mutex);
221 return NULL;
222 }
223
224 media_graph_walk_start(&graph, entity);
225
226 while ((entity = media_graph_walk_next(&graph))) {
227 if (entity == &video->video.entity)
228 continue;
229
230 if (!is_media_entity_v4l2_video_device(entity))
231 continue;
232
233 far_end = to_iss_video(media_entity_to_video_device(entity));
234 if (far_end->type != video->type)
235 break;
236
237 far_end = NULL;
238 }
239
240 mutex_unlock(&mdev->graph_mutex);
241
242 media_graph_walk_cleanup(&graph);
243
244 return far_end;
245}
246
247static int
248__iss_video_get_format(struct iss_video *video,
249 struct v4l2_mbus_framefmt *format)
250{
251 struct v4l2_subdev_format fmt;
252 struct v4l2_subdev *subdev;
253 u32 pad;
254 int ret;
255
256 subdev = iss_video_remote_subdev(video, &pad);
257 if (!subdev)
258 return -EINVAL;
259
260 memset(&fmt, 0, sizeof(fmt));
261 fmt.pad = pad;
262 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
263
264 mutex_lock(&video->mutex);
265 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
266 mutex_unlock(&video->mutex);
267
268 if (ret)
269 return ret;
270
271 *format = fmt.format;
272 return 0;
273}
274
275static int
276iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh)
277{
278 struct v4l2_mbus_framefmt format;
279 struct v4l2_pix_format pixfmt;
280 int ret;
281
282 ret = __iss_video_get_format(video, &format);
283 if (ret < 0)
284 return ret;
285
286 pixfmt.bytesperline = 0;
287 ret = iss_video_mbus_to_pix(video, &format, &pixfmt);
288
289 if (vfh->format.fmt.pix.pixelformat != pixfmt.pixelformat ||
290 vfh->format.fmt.pix.height != pixfmt.height ||
291 vfh->format.fmt.pix.width != pixfmt.width ||
292 vfh->format.fmt.pix.bytesperline != pixfmt.bytesperline ||
293 vfh->format.fmt.pix.sizeimage != pixfmt.sizeimage)
294 return -EINVAL;
295
296 return ret;
297}
298
299
300
301
302
303static int iss_video_queue_setup(struct vb2_queue *vq,
304 unsigned int *count, unsigned int *num_planes,
305 unsigned int sizes[],
306 struct device *alloc_devs[])
307{
308 struct iss_video_fh *vfh = vb2_get_drv_priv(vq);
309 struct iss_video *video = vfh->video;
310
311
312 *num_planes = 1;
313
314 sizes[0] = vfh->format.fmt.pix.sizeimage;
315 if (sizes[0] == 0)
316 return -EINVAL;
317
318 *count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0]));
319
320 return 0;
321}
322
323static void iss_video_buf_cleanup(struct vb2_buffer *vb)
324{
325 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
326 struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb);
327
328 if (buffer->iss_addr)
329 buffer->iss_addr = 0;
330}
331
332static int iss_video_buf_prepare(struct vb2_buffer *vb)
333{
334 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
335 struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
336 struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb);
337 struct iss_video *video = vfh->video;
338 unsigned long size = vfh->format.fmt.pix.sizeimage;
339 dma_addr_t addr;
340
341 if (vb2_plane_size(vb, 0) < size)
342 return -ENOBUFS;
343
344 addr = vb2_dma_contig_plane_dma_addr(vb, 0);
345 if (!IS_ALIGNED(addr, 32)) {
346 dev_dbg(video->iss->dev,
347 "Buffer address must be aligned to 32 bytes boundary.\n");
348 return -EINVAL;
349 }
350
351 vb2_set_plane_payload(vb, 0, size);
352 buffer->iss_addr = addr;
353 return 0;
354}
355
356static void iss_video_buf_queue(struct vb2_buffer *vb)
357{
358 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
359 struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
360 struct iss_video *video = vfh->video;
361 struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb);
362 struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
363 unsigned long flags;
364 bool empty;
365
366 spin_lock_irqsave(&video->qlock, flags);
367
368
369
370
371
372
373
374 if (unlikely(video->error)) {
375 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
376 spin_unlock_irqrestore(&video->qlock, flags);
377 return;
378 }
379
380 empty = list_empty(&video->dmaqueue);
381 list_add_tail(&buffer->list, &video->dmaqueue);
382
383 spin_unlock_irqrestore(&video->qlock, flags);
384
385 if (empty) {
386 enum iss_pipeline_state state;
387 unsigned int start;
388
389 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
390 state = ISS_PIPELINE_QUEUE_OUTPUT;
391 else
392 state = ISS_PIPELINE_QUEUE_INPUT;
393
394 spin_lock_irqsave(&pipe->lock, flags);
395 pipe->state |= state;
396 video->ops->queue(video, buffer);
397 video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED;
398
399 start = iss_pipeline_ready(pipe);
400 if (start)
401 pipe->state |= ISS_PIPELINE_STREAM;
402 spin_unlock_irqrestore(&pipe->lock, flags);
403
404 if (start)
405 omap4iss_pipeline_set_stream(pipe,
406 ISS_PIPELINE_STREAM_SINGLESHOT);
407 }
408}
409
410static const struct vb2_ops iss_video_vb2ops = {
411 .queue_setup = iss_video_queue_setup,
412 .buf_prepare = iss_video_buf_prepare,
413 .buf_queue = iss_video_buf_queue,
414 .buf_cleanup = iss_video_buf_cleanup,
415};
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
433{
434 struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
435 enum iss_pipeline_state state;
436 struct iss_buffer *buf;
437 unsigned long flags;
438
439 spin_lock_irqsave(&video->qlock, flags);
440 if (WARN_ON(list_empty(&video->dmaqueue))) {
441 spin_unlock_irqrestore(&video->qlock, flags);
442 return NULL;
443 }
444
445 buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
446 list);
447 list_del(&buf->list);
448 spin_unlock_irqrestore(&video->qlock, flags);
449
450 buf->vb.vb2_buf.timestamp = ktime_get_ns();
451
452
453
454
455
456
457
458
459 if (video == pipe->output && !pipe->do_propagation)
460 buf->vb.sequence =
461 atomic_inc_return(&pipe->frame_number);
462 else
463 buf->vb.sequence = atomic_read(&pipe->frame_number);
464
465 vb2_buffer_done(&buf->vb.vb2_buf, pipe->error ?
466 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
467 pipe->error = false;
468
469 spin_lock_irqsave(&video->qlock, flags);
470 if (list_empty(&video->dmaqueue)) {
471 spin_unlock_irqrestore(&video->qlock, flags);
472 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
473 state = ISS_PIPELINE_QUEUE_OUTPUT
474 | ISS_PIPELINE_STREAM;
475 else
476 state = ISS_PIPELINE_QUEUE_INPUT
477 | ISS_PIPELINE_STREAM;
478
479 spin_lock_irqsave(&pipe->lock, flags);
480 pipe->state &= ~state;
481 if (video->pipe.stream_state == ISS_PIPELINE_STREAM_CONTINUOUS)
482 video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN;
483 spin_unlock_irqrestore(&pipe->lock, flags);
484 return NULL;
485 }
486
487 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input) {
488 spin_lock(&pipe->lock);
489 pipe->state &= ~ISS_PIPELINE_STREAM;
490 spin_unlock(&pipe->lock);
491 }
492
493 buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
494 list);
495 spin_unlock_irqrestore(&video->qlock, flags);
496 buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
497 return buf;
498}
499
500
501
502
503
504
505
506
507void omap4iss_video_cancel_stream(struct iss_video *video)
508{
509 unsigned long flags;
510
511 spin_lock_irqsave(&video->qlock, flags);
512
513 while (!list_empty(&video->dmaqueue)) {
514 struct iss_buffer *buf;
515
516 buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
517 list);
518 list_del(&buf->list);
519 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
520 }
521
522 vb2_queue_error(video->queue);
523 video->error = true;
524
525 spin_unlock_irqrestore(&video->qlock, flags);
526}
527
528
529
530
531
532static int
533iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
534{
535 struct iss_video *video = video_drvdata(file);
536
537 strlcpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver));
538 strlcpy(cap->card, video->video.name, sizeof(cap->card));
539 strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
540
541 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
542 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
543 else
544 cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
545
546 cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
547 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
548
549 return 0;
550}
551
552static int
553iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
554{
555 struct iss_video *video = video_drvdata(file);
556 struct v4l2_mbus_framefmt format;
557 unsigned int index = f->index;
558 unsigned int i;
559 int ret;
560
561 if (f->type != video->type)
562 return -EINVAL;
563
564 ret = __iss_video_get_format(video, &format);
565 if (ret < 0)
566 return ret;
567
568 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
569 const struct iss_format_info *info = &formats[i];
570
571 if (format.code != info->code)
572 continue;
573
574 if (index == 0) {
575 f->pixelformat = info->pixelformat;
576 strlcpy(f->description, info->description,
577 sizeof(f->description));
578 return 0;
579 }
580
581 index--;
582 }
583
584 return -EINVAL;
585}
586
587static int
588iss_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
589{
590 struct iss_video_fh *vfh = to_iss_video_fh(fh);
591 struct iss_video *video = video_drvdata(file);
592
593 if (format->type != video->type)
594 return -EINVAL;
595
596 mutex_lock(&video->mutex);
597 *format = vfh->format;
598 mutex_unlock(&video->mutex);
599
600 return 0;
601}
602
603static int
604iss_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
605{
606 struct iss_video_fh *vfh = to_iss_video_fh(fh);
607 struct iss_video *video = video_drvdata(file);
608 struct v4l2_mbus_framefmt fmt;
609
610 if (format->type != video->type)
611 return -EINVAL;
612
613 mutex_lock(&video->mutex);
614
615
616
617
618
619 iss_video_pix_to_mbus(&format->fmt.pix, &fmt);
620 iss_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
621
622 vfh->format = *format;
623
624 mutex_unlock(&video->mutex);
625 return 0;
626}
627
628static int
629iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
630{
631 struct iss_video *video = video_drvdata(file);
632 struct v4l2_subdev_format fmt;
633 struct v4l2_subdev *subdev;
634 u32 pad;
635 int ret;
636
637 if (format->type != video->type)
638 return -EINVAL;
639
640 subdev = iss_video_remote_subdev(video, &pad);
641 if (!subdev)
642 return -EINVAL;
643
644 iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
645
646 fmt.pad = pad;
647 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
648 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
649 if (ret)
650 return ret;
651
652 iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
653 return 0;
654}
655
656static int
657iss_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
658{
659 struct iss_video *video = video_drvdata(file);
660 struct v4l2_subdev_format format;
661 struct v4l2_subdev *subdev;
662 struct v4l2_subdev_selection sdsel = {
663 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
664 .target = sel->target,
665 };
666 u32 pad;
667 int ret;
668
669 switch (sel->target) {
670 case V4L2_SEL_TGT_CROP:
671 case V4L2_SEL_TGT_CROP_BOUNDS:
672 case V4L2_SEL_TGT_CROP_DEFAULT:
673 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
674 return -EINVAL;
675 break;
676 case V4L2_SEL_TGT_COMPOSE:
677 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
678 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
679 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
680 return -EINVAL;
681 break;
682 default:
683 return -EINVAL;
684 }
685 subdev = iss_video_remote_subdev(video, &pad);
686 if (subdev == NULL)
687 return -EINVAL;
688
689
690
691
692
693 sdsel.pad = pad;
694 ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel);
695 if (!ret)
696 sel->r = sdsel.r;
697 if (ret != -ENOIOCTLCMD)
698 return ret;
699
700 format.pad = pad;
701 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
702 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
703 if (ret < 0)
704 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
705
706 sel->r.left = 0;
707 sel->r.top = 0;
708 sel->r.width = format.format.width;
709 sel->r.height = format.format.height;
710
711 return 0;
712}
713
714static int
715iss_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel)
716{
717 struct iss_video *video = video_drvdata(file);
718 struct v4l2_subdev *subdev;
719 struct v4l2_subdev_selection sdsel = {
720 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
721 .target = sel->target,
722 .flags = sel->flags,
723 .r = sel->r,
724 };
725 u32 pad;
726 int ret;
727
728 switch (sel->target) {
729 case V4L2_SEL_TGT_CROP:
730 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
731 return -EINVAL;
732 break;
733 case V4L2_SEL_TGT_COMPOSE:
734 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
735 return -EINVAL;
736 break;
737 default:
738 return -EINVAL;
739 }
740 subdev = iss_video_remote_subdev(video, &pad);
741 if (subdev == NULL)
742 return -EINVAL;
743
744 sdsel.pad = pad;
745 mutex_lock(&video->mutex);
746 ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel);
747 mutex_unlock(&video->mutex);
748 if (!ret)
749 sel->r = sdsel.r;
750
751 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
752}
753
754static int
755iss_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
756{
757 struct iss_video_fh *vfh = to_iss_video_fh(fh);
758 struct iss_video *video = video_drvdata(file);
759
760 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
761 video->type != a->type)
762 return -EINVAL;
763
764 memset(a, 0, sizeof(*a));
765 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
766 a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
767 a->parm.output.timeperframe = vfh->timeperframe;
768
769 return 0;
770}
771
772static int
773iss_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
774{
775 struct iss_video_fh *vfh = to_iss_video_fh(fh);
776 struct iss_video *video = video_drvdata(file);
777
778 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
779 video->type != a->type)
780 return -EINVAL;
781
782 if (a->parm.output.timeperframe.denominator == 0)
783 a->parm.output.timeperframe.denominator = 1;
784
785 vfh->timeperframe = a->parm.output.timeperframe;
786
787 return 0;
788}
789
790static int
791iss_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
792{
793 struct iss_video_fh *vfh = to_iss_video_fh(fh);
794
795 return vb2_reqbufs(&vfh->queue, rb);
796}
797
798static int
799iss_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
800{
801 struct iss_video_fh *vfh = to_iss_video_fh(fh);
802
803 return vb2_querybuf(&vfh->queue, b);
804}
805
806static int
807iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
808{
809 struct iss_video_fh *vfh = to_iss_video_fh(fh);
810
811 return vb2_qbuf(&vfh->queue, b);
812}
813
814static int
815iss_video_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *e)
816{
817 struct iss_video_fh *vfh = to_iss_video_fh(fh);
818
819 return vb2_expbuf(&vfh->queue, e);
820}
821
822static int
823iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
824{
825 struct iss_video_fh *vfh = to_iss_video_fh(fh);
826
827 return vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK);
828}
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861static int
862iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
863{
864 struct iss_video_fh *vfh = to_iss_video_fh(fh);
865 struct iss_video *video = video_drvdata(file);
866 struct media_graph graph;
867 struct media_entity *entity = &video->video.entity;
868 enum iss_pipeline_state state;
869 struct iss_pipeline *pipe;
870 struct iss_video *far_end;
871 unsigned long flags;
872 int ret;
873
874 if (type != video->type)
875 return -EINVAL;
876
877 mutex_lock(&video->stream_lock);
878
879
880
881
882
883 pipe = entity->pipe
884 ? to_iss_pipeline(entity) : &video->pipe;
885 pipe->external = NULL;
886 pipe->external_rate = 0;
887 pipe->external_bpp = 0;
888
889 ret = media_entity_enum_init(&pipe->ent_enum, entity->graph_obj.mdev);
890 if (ret)
891 goto err_graph_walk_init;
892
893 ret = media_graph_walk_init(&graph, entity->graph_obj.mdev);
894 if (ret)
895 goto err_graph_walk_init;
896
897 if (video->iss->pdata->set_constraints)
898 video->iss->pdata->set_constraints(video->iss, true);
899
900 ret = media_pipeline_start(entity, &pipe->pipe);
901 if (ret < 0)
902 goto err_media_pipeline_start;
903
904 media_graph_walk_start(&graph, entity);
905 while ((entity = media_graph_walk_next(&graph)))
906 media_entity_enum_set(&pipe->ent_enum, entity);
907
908
909
910
911
912 ret = iss_video_check_format(video, vfh);
913 if (ret < 0)
914 goto err_iss_video_check_format;
915
916 video->bpl_padding = ret;
917 video->bpl_value = vfh->format.fmt.pix.bytesperline;
918
919
920
921
922
923 far_end = iss_video_far_end(video);
924
925 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
926 state = ISS_PIPELINE_STREAM_OUTPUT | ISS_PIPELINE_IDLE_OUTPUT;
927 pipe->input = far_end;
928 pipe->output = video;
929 } else {
930 if (!far_end) {
931 ret = -EPIPE;
932 goto err_iss_video_check_format;
933 }
934
935 state = ISS_PIPELINE_STREAM_INPUT | ISS_PIPELINE_IDLE_INPUT;
936 pipe->input = video;
937 pipe->output = far_end;
938 }
939
940 spin_lock_irqsave(&pipe->lock, flags);
941 pipe->state &= ~ISS_PIPELINE_STREAM;
942 pipe->state |= state;
943 spin_unlock_irqrestore(&pipe->lock, flags);
944
945
946
947
948
949
950 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
951 pipe->max_timeperframe = vfh->timeperframe;
952
953 video->queue = &vfh->queue;
954 INIT_LIST_HEAD(&video->dmaqueue);
955 video->error = false;
956 atomic_set(&pipe->frame_number, -1);
957
958 ret = vb2_streamon(&vfh->queue, type);
959 if (ret < 0)
960 goto err_iss_video_check_format;
961
962
963
964
965
966
967 if (!pipe->input) {
968 unsigned long flags;
969
970 ret = omap4iss_pipeline_set_stream(pipe,
971 ISS_PIPELINE_STREAM_CONTINUOUS);
972 if (ret < 0)
973 goto err_omap4iss_set_stream;
974 spin_lock_irqsave(&video->qlock, flags);
975 if (list_empty(&video->dmaqueue))
976 video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN;
977 spin_unlock_irqrestore(&video->qlock, flags);
978 }
979
980 media_graph_walk_cleanup(&graph);
981
982 mutex_unlock(&video->stream_lock);
983
984 return 0;
985
986err_omap4iss_set_stream:
987 vb2_streamoff(&vfh->queue, type);
988err_iss_video_check_format:
989 media_pipeline_stop(&video->video.entity);
990err_media_pipeline_start:
991 if (video->iss->pdata->set_constraints)
992 video->iss->pdata->set_constraints(video->iss, false);
993 video->queue = NULL;
994
995 media_graph_walk_cleanup(&graph);
996
997err_graph_walk_init:
998 media_entity_enum_cleanup(&pipe->ent_enum);
999
1000 mutex_unlock(&video->stream_lock);
1001
1002 return ret;
1003}
1004
1005static int
1006iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
1007{
1008 struct iss_video_fh *vfh = to_iss_video_fh(fh);
1009 struct iss_video *video = video_drvdata(file);
1010 struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
1011 enum iss_pipeline_state state;
1012 unsigned long flags;
1013
1014 if (type != video->type)
1015 return -EINVAL;
1016
1017 mutex_lock(&video->stream_lock);
1018
1019 if (!vb2_is_streaming(&vfh->queue))
1020 goto done;
1021
1022
1023 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1024 state = ISS_PIPELINE_STREAM_OUTPUT
1025 | ISS_PIPELINE_QUEUE_OUTPUT;
1026 else
1027 state = ISS_PIPELINE_STREAM_INPUT
1028 | ISS_PIPELINE_QUEUE_INPUT;
1029
1030 spin_lock_irqsave(&pipe->lock, flags);
1031 pipe->state &= ~state;
1032 spin_unlock_irqrestore(&pipe->lock, flags);
1033
1034
1035 omap4iss_pipeline_set_stream(pipe, ISS_PIPELINE_STREAM_STOPPED);
1036 vb2_streamoff(&vfh->queue, type);
1037 video->queue = NULL;
1038
1039 media_entity_enum_cleanup(&pipe->ent_enum);
1040
1041 if (video->iss->pdata->set_constraints)
1042 video->iss->pdata->set_constraints(video->iss, false);
1043 media_pipeline_stop(&video->video.entity);
1044
1045done:
1046 mutex_unlock(&video->stream_lock);
1047 return 0;
1048}
1049
1050static int
1051iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
1052{
1053 if (input->index > 0)
1054 return -EINVAL;
1055
1056 strlcpy(input->name, "camera", sizeof(input->name));
1057 input->type = V4L2_INPUT_TYPE_CAMERA;
1058
1059 return 0;
1060}
1061
1062static int
1063iss_video_g_input(struct file *file, void *fh, unsigned int *input)
1064{
1065 *input = 0;
1066
1067 return 0;
1068}
1069
1070static int
1071iss_video_s_input(struct file *file, void *fh, unsigned int input)
1072{
1073 return input == 0 ? 0 : -EINVAL;
1074}
1075
1076static const struct v4l2_ioctl_ops iss_video_ioctl_ops = {
1077 .vidioc_querycap = iss_video_querycap,
1078 .vidioc_enum_fmt_vid_cap = iss_video_enum_format,
1079 .vidioc_g_fmt_vid_cap = iss_video_get_format,
1080 .vidioc_s_fmt_vid_cap = iss_video_set_format,
1081 .vidioc_try_fmt_vid_cap = iss_video_try_format,
1082 .vidioc_g_fmt_vid_out = iss_video_get_format,
1083 .vidioc_s_fmt_vid_out = iss_video_set_format,
1084 .vidioc_try_fmt_vid_out = iss_video_try_format,
1085 .vidioc_g_selection = iss_video_get_selection,
1086 .vidioc_s_selection = iss_video_set_selection,
1087 .vidioc_g_parm = iss_video_get_param,
1088 .vidioc_s_parm = iss_video_set_param,
1089 .vidioc_reqbufs = iss_video_reqbufs,
1090 .vidioc_querybuf = iss_video_querybuf,
1091 .vidioc_qbuf = iss_video_qbuf,
1092 .vidioc_expbuf = iss_video_expbuf,
1093 .vidioc_dqbuf = iss_video_dqbuf,
1094 .vidioc_streamon = iss_video_streamon,
1095 .vidioc_streamoff = iss_video_streamoff,
1096 .vidioc_enum_input = iss_video_enum_input,
1097 .vidioc_g_input = iss_video_g_input,
1098 .vidioc_s_input = iss_video_s_input,
1099};
1100
1101
1102
1103
1104
1105static int iss_video_open(struct file *file)
1106{
1107 struct iss_video *video = video_drvdata(file);
1108 struct iss_video_fh *handle;
1109 struct vb2_queue *q;
1110 int ret = 0;
1111
1112 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
1113 if (!handle)
1114 return -ENOMEM;
1115
1116 v4l2_fh_init(&handle->vfh, &video->video);
1117 v4l2_fh_add(&handle->vfh);
1118
1119
1120 if (!omap4iss_get(video->iss)) {
1121 ret = -EBUSY;
1122 goto done;
1123 }
1124
1125 ret = v4l2_pipeline_pm_use(&video->video.entity, 1);
1126 if (ret < 0) {
1127 omap4iss_put(video->iss);
1128 goto done;
1129 }
1130
1131 q = &handle->queue;
1132
1133 q->type = video->type;
1134 q->io_modes = VB2_MMAP | VB2_DMABUF;
1135 q->drv_priv = handle;
1136 q->ops = &iss_video_vb2ops;
1137 q->mem_ops = &vb2_dma_contig_memops;
1138 q->buf_struct_size = sizeof(struct iss_buffer);
1139 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1140 q->dev = video->iss->dev;
1141
1142 ret = vb2_queue_init(q);
1143 if (ret) {
1144 omap4iss_put(video->iss);
1145 goto done;
1146 }
1147
1148 memset(&handle->format, 0, sizeof(handle->format));
1149 handle->format.type = video->type;
1150 handle->timeperframe.denominator = 1;
1151
1152 handle->video = video;
1153 file->private_data = &handle->vfh;
1154
1155done:
1156 if (ret < 0) {
1157 v4l2_fh_del(&handle->vfh);
1158 v4l2_fh_exit(&handle->vfh);
1159 kfree(handle);
1160 }
1161
1162 return ret;
1163}
1164
1165static int iss_video_release(struct file *file)
1166{
1167 struct iss_video *video = video_drvdata(file);
1168 struct v4l2_fh *vfh = file->private_data;
1169 struct iss_video_fh *handle = to_iss_video_fh(vfh);
1170
1171
1172 iss_video_streamoff(file, vfh, video->type);
1173
1174 v4l2_pipeline_pm_use(&video->video.entity, 0);
1175
1176
1177 vb2_queue_release(&handle->queue);
1178
1179 v4l2_fh_del(vfh);
1180 v4l2_fh_exit(vfh);
1181 kfree(handle);
1182 file->private_data = NULL;
1183
1184 omap4iss_put(video->iss);
1185
1186 return 0;
1187}
1188
1189static __poll_t iss_video_poll(struct file *file, poll_table *wait)
1190{
1191 struct iss_video_fh *vfh = to_iss_video_fh(file->private_data);
1192
1193 return vb2_poll(&vfh->queue, file, wait);
1194}
1195
1196static int iss_video_mmap(struct file *file, struct vm_area_struct *vma)
1197{
1198 struct iss_video_fh *vfh = to_iss_video_fh(file->private_data);
1199
1200 return vb2_mmap(&vfh->queue, vma);
1201}
1202
1203static const struct v4l2_file_operations iss_video_fops = {
1204 .owner = THIS_MODULE,
1205 .unlocked_ioctl = video_ioctl2,
1206 .open = iss_video_open,
1207 .release = iss_video_release,
1208 .poll = iss_video_poll,
1209 .mmap = iss_video_mmap,
1210};
1211
1212
1213
1214
1215
1216static const struct iss_video_operations iss_video_dummy_ops = {
1217};
1218
1219int omap4iss_video_init(struct iss_video *video, const char *name)
1220{
1221 const char *direction;
1222 int ret;
1223
1224 switch (video->type) {
1225 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1226 direction = "output";
1227 video->pad.flags = MEDIA_PAD_FL_SINK;
1228 break;
1229 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1230 direction = "input";
1231 video->pad.flags = MEDIA_PAD_FL_SOURCE;
1232 break;
1233
1234 default:
1235 return -EINVAL;
1236 }
1237
1238 ret = media_entity_pads_init(&video->video.entity, 1, &video->pad);
1239 if (ret < 0)
1240 return ret;
1241
1242 spin_lock_init(&video->qlock);
1243 mutex_init(&video->mutex);
1244 atomic_set(&video->active, 0);
1245
1246 spin_lock_init(&video->pipe.lock);
1247 mutex_init(&video->stream_lock);
1248
1249
1250 if (!video->ops)
1251 video->ops = &iss_video_dummy_ops;
1252
1253 video->video.fops = &iss_video_fops;
1254 snprintf(video->video.name, sizeof(video->video.name),
1255 "OMAP4 ISS %s %s", name, direction);
1256 video->video.vfl_type = VFL_TYPE_GRABBER;
1257 video->video.release = video_device_release_empty;
1258 video->video.ioctl_ops = &iss_video_ioctl_ops;
1259 video->pipe.stream_state = ISS_PIPELINE_STREAM_STOPPED;
1260
1261 video_set_drvdata(&video->video, video);
1262
1263 return 0;
1264}
1265
1266void omap4iss_video_cleanup(struct iss_video *video)
1267{
1268 media_entity_cleanup(&video->video.entity);
1269 mutex_destroy(&video->stream_lock);
1270 mutex_destroy(&video->mutex);
1271}
1272
1273int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev)
1274{
1275 int ret;
1276
1277 video->video.v4l2_dev = vdev;
1278
1279 ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
1280 if (ret < 0)
1281 dev_err(video->iss->dev,
1282 "could not register video device (%d)\n", ret);
1283
1284 return ret;
1285}
1286
1287void omap4iss_video_unregister(struct iss_video *video)
1288{
1289 video_unregister_device(&video->video);
1290}
1291