1
2
3
4
5
6
7
8
9
10
11
12
13#include <asm/cacheflush.h>
14#include <linux/clk.h>
15#include <linux/mm.h>
16#include <linux/module.h>
17#include <linux/pagemap.h>
18#include <linux/scatterlist.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/vmalloc.h>
22
23#include <media/v4l2-dev.h>
24#include <media/v4l2-ioctl.h>
25#include <media/v4l2-mc.h>
26#include <media/videobuf2-dma-contig.h>
27
28#include "ispvideo.h"
29#include "isp.h"
30
31
32
33
34
35
36
37
38
39
40static struct isp_format_info formats[] = {
41 { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
42 MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
43 V4L2_PIX_FMT_GREY, 8, 1, },
44 { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10,
45 MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8,
46 V4L2_PIX_FMT_Y10, 10, 2, },
47 { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10,
48 MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8,
49 V4L2_PIX_FMT_Y12, 12, 2, },
50 { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
51 MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
52 V4L2_PIX_FMT_SBGGR8, 8, 1, },
53 { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
54 MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
55 V4L2_PIX_FMT_SGBRG8, 8, 1, },
56 { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
57 MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
58 V4L2_PIX_FMT_SGRBG8, 8, 1, },
59 { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
60 MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
61 V4L2_PIX_FMT_SRGGB8, 8, 1, },
62 { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
63 MEDIA_BUS_FMT_SBGGR10_1X10, 0,
64 V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, },
65 { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
66 MEDIA_BUS_FMT_SGBRG10_1X10, 0,
67 V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, },
68 { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
69 MEDIA_BUS_FMT_SGRBG10_1X10, 0,
70 V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, },
71 { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
72 MEDIA_BUS_FMT_SRGGB10_1X10, 0,
73 V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, },
74 { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
75 MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8,
76 V4L2_PIX_FMT_SBGGR10, 10, 2, },
77 { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
78 MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8,
79 V4L2_PIX_FMT_SGBRG10, 10, 2, },
80 { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
81 MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8,
82 V4L2_PIX_FMT_SGRBG10, 10, 2, },
83 { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
84 MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8,
85 V4L2_PIX_FMT_SRGGB10, 10, 2, },
86 { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10,
87 MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8,
88 V4L2_PIX_FMT_SBGGR12, 12, 2, },
89 { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10,
90 MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8,
91 V4L2_PIX_FMT_SGBRG12, 12, 2, },
92 { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10,
93 MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8,
94 V4L2_PIX_FMT_SGRBG12, 12, 2, },
95 { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10,
96 MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8,
97 V4L2_PIX_FMT_SRGGB12, 12, 2, },
98 { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16,
99 MEDIA_BUS_FMT_UYVY8_1X16, 0,
100 V4L2_PIX_FMT_UYVY, 16, 2, },
101 { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16,
102 MEDIA_BUS_FMT_YUYV8_1X16, 0,
103 V4L2_PIX_FMT_YUYV, 16, 2, },
104 { MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_UYVY8_2X8,
105 MEDIA_BUS_FMT_UYVY8_2X8, 0,
106 V4L2_PIX_FMT_UYVY, 8, 2, },
107 { MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
108 MEDIA_BUS_FMT_YUYV8_2X8, 0,
109 V4L2_PIX_FMT_YUYV, 8, 2, },
110
111
112
113 { 0, }
114};
115
116const struct isp_format_info *omap3isp_video_format_info(u32 code)
117{
118 unsigned int i;
119
120 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
121 if (formats[i].code == code)
122 return &formats[i];
123 }
124
125 return NULL;
126}
127
128
129
130
131
132
133
134
135
136
137
138
139
140static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
141 const struct v4l2_mbus_framefmt *mbus,
142 struct v4l2_pix_format *pix)
143{
144 unsigned int bpl = pix->bytesperline;
145 unsigned int min_bpl;
146 unsigned int i;
147
148 memset(pix, 0, sizeof(*pix));
149 pix->width = mbus->width;
150 pix->height = mbus->height;
151
152 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
153 if (formats[i].code == mbus->code)
154 break;
155 }
156
157 if (WARN_ON(i == ARRAY_SIZE(formats)))
158 return 0;
159
160 min_bpl = pix->width * formats[i].bpp;
161
162
163
164
165
166 if (video->bpl_max)
167 bpl = clamp(bpl, min_bpl, video->bpl_max);
168 else
169 bpl = min_bpl;
170
171 if (!video->bpl_zero_padding || bpl != min_bpl)
172 bpl = ALIGN(bpl, video->bpl_alignment);
173
174 pix->pixelformat = formats[i].pixelformat;
175 pix->bytesperline = bpl;
176 pix->sizeimage = pix->bytesperline * pix->height;
177 pix->colorspace = mbus->colorspace;
178 pix->field = mbus->field;
179
180 return bpl - min_bpl;
181}
182
183static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
184 struct v4l2_mbus_framefmt *mbus)
185{
186 unsigned int i;
187
188 memset(mbus, 0, sizeof(*mbus));
189 mbus->width = pix->width;
190 mbus->height = pix->height;
191
192
193
194
195 for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
196 if (formats[i].pixelformat == pix->pixelformat)
197 break;
198 }
199
200 mbus->code = formats[i].code;
201 mbus->colorspace = pix->colorspace;
202 mbus->field = pix->field;
203}
204
205static struct v4l2_subdev *
206isp_video_remote_subdev(struct isp_video *video, u32 *pad)
207{
208 struct media_pad *remote;
209
210 remote = media_entity_remote_pad(&video->pad);
211
212 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
213 return NULL;
214
215 if (pad)
216 *pad = remote->index;
217
218 return media_entity_to_v4l2_subdev(remote->entity);
219}
220
221
222static int isp_video_get_graph_data(struct isp_video *video,
223 struct isp_pipeline *pipe)
224{
225 struct media_graph graph;
226 struct media_entity *entity = &video->video.entity;
227 struct media_device *mdev = entity->graph_obj.mdev;
228 struct isp_video *far_end = NULL;
229 int ret;
230
231 mutex_lock(&mdev->graph_mutex);
232 ret = media_graph_walk_init(&graph, mdev);
233 if (ret) {
234 mutex_unlock(&mdev->graph_mutex);
235 return ret;
236 }
237
238 media_graph_walk_start(&graph, entity);
239
240 while ((entity = media_graph_walk_next(&graph))) {
241 struct isp_video *__video;
242
243 media_entity_enum_set(&pipe->ent_enum, entity);
244
245 if (far_end != NULL)
246 continue;
247
248 if (entity == &video->video.entity)
249 continue;
250
251 if (!is_media_entity_v4l2_video_device(entity))
252 continue;
253
254 __video = to_isp_video(media_entity_to_video_device(entity));
255 if (__video->type != video->type)
256 far_end = __video;
257 }
258
259 mutex_unlock(&mdev->graph_mutex);
260
261 media_graph_walk_cleanup(&graph);
262
263 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
264 pipe->input = far_end;
265 pipe->output = video;
266 } else {
267 if (far_end == NULL)
268 return -EPIPE;
269
270 pipe->input = video;
271 pipe->output = far_end;
272 }
273
274 return 0;
275}
276
277static int
278__isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
279{
280 struct v4l2_subdev_format fmt;
281 struct v4l2_subdev *subdev;
282 u32 pad;
283 int ret;
284
285 subdev = isp_video_remote_subdev(video, &pad);
286 if (subdev == NULL)
287 return -EINVAL;
288
289 fmt.pad = pad;
290 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
291
292 mutex_lock(&video->mutex);
293 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
294 mutex_unlock(&video->mutex);
295
296 if (ret)
297 return ret;
298
299 format->type = video->type;
300 return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
301}
302
303static int
304isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
305{
306 struct v4l2_format format;
307 int ret;
308
309 memcpy(&format, &vfh->format, sizeof(format));
310 ret = __isp_video_get_format(video, &format);
311 if (ret < 0)
312 return ret;
313
314 if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
315 vfh->format.fmt.pix.height != format.fmt.pix.height ||
316 vfh->format.fmt.pix.width != format.fmt.pix.width ||
317 vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
318 vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage ||
319 vfh->format.fmt.pix.field != format.fmt.pix.field)
320 return -EINVAL;
321
322 return 0;
323}
324
325
326
327
328
329static int isp_video_queue_setup(struct vb2_queue *queue,
330 unsigned int *count, unsigned int *num_planes,
331 unsigned int sizes[], struct device *alloc_devs[])
332{
333 struct isp_video_fh *vfh = vb2_get_drv_priv(queue);
334 struct isp_video *video = vfh->video;
335
336 *num_planes = 1;
337
338 sizes[0] = vfh->format.fmt.pix.sizeimage;
339 if (sizes[0] == 0)
340 return -EINVAL;
341
342 *count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0]));
343
344 return 0;
345}
346
347static int isp_video_buffer_prepare(struct vb2_buffer *buf)
348{
349 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf);
350 struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
351 struct isp_buffer *buffer = to_isp_buffer(vbuf);
352 struct isp_video *video = vfh->video;
353 dma_addr_t addr;
354
355
356
357
358
359
360
361 if (unlikely(video->error))
362 return -EIO;
363
364 addr = vb2_dma_contig_plane_dma_addr(buf, 0);
365 if (!IS_ALIGNED(addr, 32)) {
366 dev_dbg(video->isp->dev,
367 "Buffer address must be aligned to 32 bytes boundary.\n");
368 return -EINVAL;
369 }
370
371 vb2_set_plane_payload(&buffer->vb.vb2_buf, 0,
372 vfh->format.fmt.pix.sizeimage);
373 buffer->dma = addr;
374
375 return 0;
376}
377
378
379
380
381
382
383
384
385
386
387static void isp_video_buffer_queue(struct vb2_buffer *buf)
388{
389 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf);
390 struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
391 struct isp_buffer *buffer = to_isp_buffer(vbuf);
392 struct isp_video *video = vfh->video;
393 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
394 enum isp_pipeline_state state;
395 unsigned long flags;
396 unsigned int empty;
397 unsigned int start;
398
399 spin_lock_irqsave(&video->irqlock, flags);
400
401 if (unlikely(video->error)) {
402 vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_ERROR);
403 spin_unlock_irqrestore(&video->irqlock, flags);
404 return;
405 }
406
407 empty = list_empty(&video->dmaqueue);
408 list_add_tail(&buffer->irqlist, &video->dmaqueue);
409
410 spin_unlock_irqrestore(&video->irqlock, flags);
411
412 if (empty) {
413 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
414 state = ISP_PIPELINE_QUEUE_OUTPUT;
415 else
416 state = ISP_PIPELINE_QUEUE_INPUT;
417
418 spin_lock_irqsave(&pipe->lock, flags);
419 pipe->state |= state;
420 video->ops->queue(video, buffer);
421 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
422
423 start = isp_pipeline_ready(pipe);
424 if (start)
425 pipe->state |= ISP_PIPELINE_STREAM;
426 spin_unlock_irqrestore(&pipe->lock, flags);
427
428 if (start)
429 omap3isp_pipeline_set_stream(pipe,
430 ISP_PIPELINE_STREAM_SINGLESHOT);
431 }
432}
433
434
435
436
437
438
439
440
441
442
443
444
445static void omap3isp_video_return_buffers(struct isp_video *video,
446 enum vb2_buffer_state state)
447{
448 while (!list_empty(&video->dmaqueue)) {
449 struct isp_buffer *buf;
450
451 buf = list_first_entry(&video->dmaqueue,
452 struct isp_buffer, irqlist);
453 list_del(&buf->irqlist);
454 vb2_buffer_done(&buf->vb.vb2_buf, state);
455 }
456}
457
458static int isp_video_start_streaming(struct vb2_queue *queue,
459 unsigned int count)
460{
461 struct isp_video_fh *vfh = vb2_get_drv_priv(queue);
462 struct isp_video *video = vfh->video;
463 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
464 unsigned long flags;
465 int ret;
466
467
468
469
470
471 if (pipe->input)
472 return 0;
473
474 ret = omap3isp_pipeline_set_stream(pipe,
475 ISP_PIPELINE_STREAM_CONTINUOUS);
476 if (ret < 0) {
477 spin_lock_irqsave(&video->irqlock, flags);
478 omap3isp_video_return_buffers(video, VB2_BUF_STATE_QUEUED);
479 spin_unlock_irqrestore(&video->irqlock, flags);
480 return ret;
481 }
482
483 spin_lock_irqsave(&video->irqlock, flags);
484 if (list_empty(&video->dmaqueue))
485 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
486 spin_unlock_irqrestore(&video->irqlock, flags);
487
488 return 0;
489}
490
491static const struct vb2_ops isp_video_queue_ops = {
492 .queue_setup = isp_video_queue_setup,
493 .buf_prepare = isp_video_buffer_prepare,
494 .buf_queue = isp_video_buffer_queue,
495 .start_streaming = isp_video_start_streaming,
496};
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
515{
516 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
517 enum vb2_buffer_state vb_state;
518 struct isp_buffer *buf;
519 unsigned long flags;
520
521 spin_lock_irqsave(&video->irqlock, flags);
522 if (WARN_ON(list_empty(&video->dmaqueue))) {
523 spin_unlock_irqrestore(&video->irqlock, flags);
524 return NULL;
525 }
526
527 buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
528 irqlist);
529 list_del(&buf->irqlist);
530 spin_unlock_irqrestore(&video->irqlock, flags);
531
532 buf->vb.vb2_buf.timestamp = ktime_get_ns();
533
534
535
536
537
538
539
540 if (video == pipe->output && !pipe->do_propagation)
541 buf->vb.sequence =
542 atomic_inc_return(&pipe->frame_number);
543 else
544 buf->vb.sequence = atomic_read(&pipe->frame_number);
545
546 if (pipe->field != V4L2_FIELD_NONE)
547 buf->vb.sequence /= 2;
548
549 buf->vb.field = pipe->field;
550
551
552 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
553 vb_state = VB2_BUF_STATE_ERROR;
554 pipe->error = false;
555 } else {
556 vb_state = VB2_BUF_STATE_DONE;
557 }
558
559 vb2_buffer_done(&buf->vb.vb2_buf, vb_state);
560
561 spin_lock_irqsave(&video->irqlock, flags);
562
563 if (list_empty(&video->dmaqueue)) {
564 enum isp_pipeline_state state;
565
566 spin_unlock_irqrestore(&video->irqlock, flags);
567
568 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
569 state = ISP_PIPELINE_QUEUE_OUTPUT
570 | ISP_PIPELINE_STREAM;
571 else
572 state = ISP_PIPELINE_QUEUE_INPUT
573 | ISP_PIPELINE_STREAM;
574
575 spin_lock_irqsave(&pipe->lock, flags);
576 pipe->state &= ~state;
577 if (video->pipe.stream_state == ISP_PIPELINE_STREAM_CONTINUOUS)
578 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
579 spin_unlock_irqrestore(&pipe->lock, flags);
580 return NULL;
581 }
582
583 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
584 spin_lock(&pipe->lock);
585 pipe->state &= ~ISP_PIPELINE_STREAM;
586 spin_unlock(&pipe->lock);
587 }
588
589 buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
590 irqlist);
591
592 spin_unlock_irqrestore(&video->irqlock, flags);
593
594 return buf;
595}
596
597
598
599
600
601
602
603
604void omap3isp_video_cancel_stream(struct isp_video *video)
605{
606 unsigned long flags;
607
608 spin_lock_irqsave(&video->irqlock, flags);
609 omap3isp_video_return_buffers(video, VB2_BUF_STATE_ERROR);
610 video->error = true;
611 spin_unlock_irqrestore(&video->irqlock, flags);
612}
613
614
615
616
617
618
619
620
621
622
623
624void omap3isp_video_resume(struct isp_video *video, int continuous)
625{
626 struct isp_buffer *buf = NULL;
627
628 if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
629 mutex_lock(&video->queue_lock);
630 vb2_discard_done(video->queue);
631 mutex_unlock(&video->queue_lock);
632 }
633
634 if (!list_empty(&video->dmaqueue)) {
635 buf = list_first_entry(&video->dmaqueue,
636 struct isp_buffer, irqlist);
637 video->ops->queue(video, buf);
638 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
639 } else {
640 if (continuous)
641 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
642 }
643}
644
645
646
647
648
649static int
650isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
651{
652 struct isp_video *video = video_drvdata(file);
653
654 strscpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
655 strscpy(cap->card, video->video.name, sizeof(cap->card));
656 strscpy(cap->bus_info, "media", sizeof(cap->bus_info));
657
658 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
659 | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
660
661 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
662 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
663 else
664 cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
665
666 return 0;
667}
668
669static int
670isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
671{
672 struct isp_video_fh *vfh = to_isp_video_fh(fh);
673 struct isp_video *video = video_drvdata(file);
674
675 if (format->type != video->type)
676 return -EINVAL;
677
678 mutex_lock(&video->mutex);
679 *format = vfh->format;
680 mutex_unlock(&video->mutex);
681
682 return 0;
683}
684
685static int
686isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
687{
688 struct isp_video_fh *vfh = to_isp_video_fh(fh);
689 struct isp_video *video = video_drvdata(file);
690 struct v4l2_mbus_framefmt fmt;
691
692 if (format->type != video->type)
693 return -EINVAL;
694
695
696 switch (format->fmt.pix.field) {
697 case V4L2_FIELD_NONE:
698
699 break;
700 case V4L2_FIELD_ALTERNATE:
701
702 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
703 format->fmt.pix.field = V4L2_FIELD_NONE;
704 break;
705 case V4L2_FIELD_INTERLACED:
706
707
708
709
710 format->fmt.pix.field = V4L2_FIELD_INTERLACED_TB;
711
712 case V4L2_FIELD_INTERLACED_TB:
713 case V4L2_FIELD_INTERLACED_BT:
714
715 if (video != &video->isp->isp_ccdc.video_out)
716 format->fmt.pix.field = V4L2_FIELD_NONE;
717 break;
718 case V4L2_FIELD_TOP:
719 case V4L2_FIELD_BOTTOM:
720 case V4L2_FIELD_SEQ_TB:
721 case V4L2_FIELD_SEQ_BT:
722 default:
723
724
725
726 format->fmt.pix.field = V4L2_FIELD_NONE;
727 break;
728 }
729
730
731
732
733 isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
734 isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
735
736 mutex_lock(&video->mutex);
737 vfh->format = *format;
738 mutex_unlock(&video->mutex);
739
740 return 0;
741}
742
743static int
744isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
745{
746 struct isp_video *video = video_drvdata(file);
747 struct v4l2_subdev_format fmt;
748 struct v4l2_subdev *subdev;
749 u32 pad;
750 int ret;
751
752 if (format->type != video->type)
753 return -EINVAL;
754
755 subdev = isp_video_remote_subdev(video, &pad);
756 if (subdev == NULL)
757 return -EINVAL;
758
759 isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
760
761 fmt.pad = pad;
762 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
763 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
764 if (ret)
765 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
766
767 isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
768 return 0;
769}
770
771static int
772isp_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
773{
774 struct isp_video *video = video_drvdata(file);
775 struct v4l2_subdev_format format;
776 struct v4l2_subdev *subdev;
777 struct v4l2_subdev_selection sdsel = {
778 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
779 .target = sel->target,
780 };
781 u32 pad;
782 int ret;
783
784 switch (sel->target) {
785 case V4L2_SEL_TGT_CROP:
786 case V4L2_SEL_TGT_CROP_BOUNDS:
787 case V4L2_SEL_TGT_CROP_DEFAULT:
788 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
789 return -EINVAL;
790 break;
791 case V4L2_SEL_TGT_COMPOSE:
792 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
793 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
794 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
795 return -EINVAL;
796 break;
797 default:
798 return -EINVAL;
799 }
800 subdev = isp_video_remote_subdev(video, &pad);
801 if (subdev == NULL)
802 return -EINVAL;
803
804
805
806
807 sdsel.pad = pad;
808 ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel);
809 if (!ret)
810 sel->r = sdsel.r;
811 if (ret != -ENOIOCTLCMD)
812 return ret;
813
814 format.pad = pad;
815 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
816 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
817 if (ret < 0)
818 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
819
820 sel->r.left = 0;
821 sel->r.top = 0;
822 sel->r.width = format.format.width;
823 sel->r.height = format.format.height;
824
825 return 0;
826}
827
828static int
829isp_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel)
830{
831 struct isp_video *video = video_drvdata(file);
832 struct v4l2_subdev *subdev;
833 struct v4l2_subdev_selection sdsel = {
834 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
835 .target = sel->target,
836 .flags = sel->flags,
837 .r = sel->r,
838 };
839 u32 pad;
840 int ret;
841
842 switch (sel->target) {
843 case V4L2_SEL_TGT_CROP:
844 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
845 return -EINVAL;
846 break;
847 case V4L2_SEL_TGT_COMPOSE:
848 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
849 return -EINVAL;
850 break;
851 default:
852 return -EINVAL;
853 }
854 subdev = isp_video_remote_subdev(video, &pad);
855 if (subdev == NULL)
856 return -EINVAL;
857
858 sdsel.pad = pad;
859 mutex_lock(&video->mutex);
860 ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel);
861 mutex_unlock(&video->mutex);
862 if (!ret)
863 sel->r = sdsel.r;
864
865 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
866}
867
868static int
869isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
870{
871 struct isp_video_fh *vfh = to_isp_video_fh(fh);
872 struct isp_video *video = video_drvdata(file);
873
874 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
875 video->type != a->type)
876 return -EINVAL;
877
878 memset(a, 0, sizeof(*a));
879 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
880 a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
881 a->parm.output.timeperframe = vfh->timeperframe;
882
883 return 0;
884}
885
886static int
887isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
888{
889 struct isp_video_fh *vfh = to_isp_video_fh(fh);
890 struct isp_video *video = video_drvdata(file);
891
892 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
893 video->type != a->type)
894 return -EINVAL;
895
896 if (a->parm.output.timeperframe.denominator == 0)
897 a->parm.output.timeperframe.denominator = 1;
898
899 vfh->timeperframe = a->parm.output.timeperframe;
900
901 return 0;
902}
903
904static int
905isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
906{
907 struct isp_video_fh *vfh = to_isp_video_fh(fh);
908 struct isp_video *video = video_drvdata(file);
909 int ret;
910
911 mutex_lock(&video->queue_lock);
912 ret = vb2_reqbufs(&vfh->queue, rb);
913 mutex_unlock(&video->queue_lock);
914
915 return ret;
916}
917
918static int
919isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
920{
921 struct isp_video_fh *vfh = to_isp_video_fh(fh);
922 struct isp_video *video = video_drvdata(file);
923 int ret;
924
925 mutex_lock(&video->queue_lock);
926 ret = vb2_querybuf(&vfh->queue, b);
927 mutex_unlock(&video->queue_lock);
928
929 return ret;
930}
931
932static int
933isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
934{
935 struct isp_video_fh *vfh = to_isp_video_fh(fh);
936 struct isp_video *video = video_drvdata(file);
937 int ret;
938
939 mutex_lock(&video->queue_lock);
940 ret = vb2_qbuf(&vfh->queue, video->video.v4l2_dev->mdev, b);
941 mutex_unlock(&video->queue_lock);
942
943 return ret;
944}
945
946static int
947isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
948{
949 struct isp_video_fh *vfh = to_isp_video_fh(fh);
950 struct isp_video *video = video_drvdata(file);
951 int ret;
952
953 mutex_lock(&video->queue_lock);
954 ret = vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK);
955 mutex_unlock(&video->queue_lock);
956
957 return ret;
958}
959
960static int isp_video_check_external_subdevs(struct isp_video *video,
961 struct isp_pipeline *pipe)
962{
963 struct isp_device *isp = video->isp;
964 struct media_entity *ents[] = {
965 &isp->isp_csi2a.subdev.entity,
966 &isp->isp_csi2c.subdev.entity,
967 &isp->isp_ccp2.subdev.entity,
968 &isp->isp_ccdc.subdev.entity
969 };
970 struct media_pad *source_pad;
971 struct media_entity *source = NULL;
972 struct media_entity *sink;
973 struct v4l2_subdev_format fmt;
974 struct v4l2_ext_controls ctrls;
975 struct v4l2_ext_control ctrl;
976 unsigned int i;
977 int ret;
978
979
980 if (pipe->input != NULL)
981 return 0;
982
983 for (i = 0; i < ARRAY_SIZE(ents); i++) {
984
985 if (!media_entity_enum_test(&pipe->ent_enum, ents[i]))
986 continue;
987
988
989 source_pad = media_entity_remote_pad(&ents[i]->pads[0]);
990 if (source_pad == NULL)
991 continue;
992
993 source = source_pad->entity;
994 sink = ents[i];
995 break;
996 }
997
998 if (!source) {
999 dev_warn(isp->dev, "can't find source, failing now\n");
1000 return -EINVAL;
1001 }
1002
1003 if (!is_media_entity_v4l2_subdev(source))
1004 return 0;
1005
1006 pipe->external = media_entity_to_v4l2_subdev(source);
1007
1008 fmt.pad = source_pad->index;
1009 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1010 ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(sink),
1011 pad, get_fmt, NULL, &fmt);
1012 if (unlikely(ret < 0)) {
1013 dev_warn(isp->dev, "get_fmt returned null!\n");
1014 return ret;
1015 }
1016
1017 pipe->external_width =
1018 omap3isp_video_format_info(fmt.format.code)->width;
1019
1020 memset(&ctrls, 0, sizeof(ctrls));
1021 memset(&ctrl, 0, sizeof(ctrl));
1022
1023 ctrl.id = V4L2_CID_PIXEL_RATE;
1024
1025 ctrls.count = 1;
1026 ctrls.controls = &ctrl;
1027
1028 ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, &ctrls);
1029 if (ret < 0) {
1030 dev_warn(isp->dev, "no pixel rate control in subdev %s\n",
1031 pipe->external->name);
1032 return ret;
1033 }
1034
1035 pipe->external_rate = ctrl.value64;
1036
1037 if (media_entity_enum_test(&pipe->ent_enum,
1038 &isp->isp_ccdc.subdev.entity)) {
1039 unsigned int rate = UINT_MAX;
1040
1041
1042
1043
1044 omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
1045 if (pipe->external_rate > rate)
1046 return -ENOSPC;
1047 }
1048
1049 return 0;
1050}
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083static int
1084isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
1085{
1086 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1087 struct isp_video *video = video_drvdata(file);
1088 enum isp_pipeline_state state;
1089 struct isp_pipeline *pipe;
1090 unsigned long flags;
1091 int ret;
1092
1093 if (type != video->type)
1094 return -EINVAL;
1095
1096 mutex_lock(&video->stream_lock);
1097
1098
1099
1100
1101 pipe = video->video.entity.pipe
1102 ? to_isp_pipeline(&video->video.entity) : &video->pipe;
1103
1104 ret = media_entity_enum_init(&pipe->ent_enum, &video->isp->media_dev);
1105 if (ret)
1106 goto err_enum_init;
1107
1108
1109 pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
1110 pipe->max_rate = pipe->l3_ick;
1111
1112 ret = media_pipeline_start(&video->video.entity, &pipe->pipe);
1113 if (ret < 0)
1114 goto err_pipeline_start;
1115
1116
1117
1118
1119 ret = isp_video_check_format(video, vfh);
1120 if (ret < 0)
1121 goto err_check_format;
1122
1123 video->bpl_padding = ret;
1124 video->bpl_value = vfh->format.fmt.pix.bytesperline;
1125
1126 ret = isp_video_get_graph_data(video, pipe);
1127 if (ret < 0)
1128 goto err_check_format;
1129
1130 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1131 state = ISP_PIPELINE_STREAM_OUTPUT | ISP_PIPELINE_IDLE_OUTPUT;
1132 else
1133 state = ISP_PIPELINE_STREAM_INPUT | ISP_PIPELINE_IDLE_INPUT;
1134
1135 ret = isp_video_check_external_subdevs(video, pipe);
1136 if (ret < 0)
1137 goto err_check_format;
1138
1139 pipe->error = false;
1140
1141 spin_lock_irqsave(&pipe->lock, flags);
1142 pipe->state &= ~ISP_PIPELINE_STREAM;
1143 pipe->state |= state;
1144 spin_unlock_irqrestore(&pipe->lock, flags);
1145
1146
1147
1148
1149
1150 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1151 pipe->max_timeperframe = vfh->timeperframe;
1152
1153 video->queue = &vfh->queue;
1154 INIT_LIST_HEAD(&video->dmaqueue);
1155 atomic_set(&pipe->frame_number, -1);
1156 pipe->field = vfh->format.fmt.pix.field;
1157
1158 mutex_lock(&video->queue_lock);
1159 ret = vb2_streamon(&vfh->queue, type);
1160 mutex_unlock(&video->queue_lock);
1161 if (ret < 0)
1162 goto err_check_format;
1163
1164 mutex_unlock(&video->stream_lock);
1165
1166 return 0;
1167
1168err_check_format:
1169 media_pipeline_stop(&video->video.entity);
1170err_pipeline_start:
1171
1172
1173
1174
1175
1176
1177
1178
1179 INIT_LIST_HEAD(&video->dmaqueue);
1180 video->queue = NULL;
1181
1182 media_entity_enum_cleanup(&pipe->ent_enum);
1183
1184err_enum_init:
1185 mutex_unlock(&video->stream_lock);
1186
1187 return ret;
1188}
1189
1190static int
1191isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
1192{
1193 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1194 struct isp_video *video = video_drvdata(file);
1195 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
1196 enum isp_pipeline_state state;
1197 unsigned int streaming;
1198 unsigned long flags;
1199
1200 if (type != video->type)
1201 return -EINVAL;
1202
1203 mutex_lock(&video->stream_lock);
1204
1205
1206 mutex_lock(&video->queue_lock);
1207 streaming = vb2_is_streaming(&vfh->queue);
1208 mutex_unlock(&video->queue_lock);
1209
1210 if (!streaming)
1211 goto done;
1212
1213
1214 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1215 state = ISP_PIPELINE_STREAM_OUTPUT
1216 | ISP_PIPELINE_QUEUE_OUTPUT;
1217 else
1218 state = ISP_PIPELINE_STREAM_INPUT
1219 | ISP_PIPELINE_QUEUE_INPUT;
1220
1221 spin_lock_irqsave(&pipe->lock, flags);
1222 pipe->state &= ~state;
1223 spin_unlock_irqrestore(&pipe->lock, flags);
1224
1225
1226 omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
1227 omap3isp_video_cancel_stream(video);
1228
1229 mutex_lock(&video->queue_lock);
1230 vb2_streamoff(&vfh->queue, type);
1231 mutex_unlock(&video->queue_lock);
1232 video->queue = NULL;
1233 video->error = false;
1234
1235
1236 media_pipeline_stop(&video->video.entity);
1237
1238 media_entity_enum_cleanup(&pipe->ent_enum);
1239
1240done:
1241 mutex_unlock(&video->stream_lock);
1242 return 0;
1243}
1244
1245static int
1246isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
1247{
1248 if (input->index > 0)
1249 return -EINVAL;
1250
1251 strscpy(input->name, "camera", sizeof(input->name));
1252 input->type = V4L2_INPUT_TYPE_CAMERA;
1253
1254 return 0;
1255}
1256
1257static int
1258isp_video_g_input(struct file *file, void *fh, unsigned int *input)
1259{
1260 *input = 0;
1261
1262 return 0;
1263}
1264
1265static int
1266isp_video_s_input(struct file *file, void *fh, unsigned int input)
1267{
1268 return input == 0 ? 0 : -EINVAL;
1269}
1270
1271static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
1272 .vidioc_querycap = isp_video_querycap,
1273 .vidioc_g_fmt_vid_cap = isp_video_get_format,
1274 .vidioc_s_fmt_vid_cap = isp_video_set_format,
1275 .vidioc_try_fmt_vid_cap = isp_video_try_format,
1276 .vidioc_g_fmt_vid_out = isp_video_get_format,
1277 .vidioc_s_fmt_vid_out = isp_video_set_format,
1278 .vidioc_try_fmt_vid_out = isp_video_try_format,
1279 .vidioc_g_selection = isp_video_get_selection,
1280 .vidioc_s_selection = isp_video_set_selection,
1281 .vidioc_g_parm = isp_video_get_param,
1282 .vidioc_s_parm = isp_video_set_param,
1283 .vidioc_reqbufs = isp_video_reqbufs,
1284 .vidioc_querybuf = isp_video_querybuf,
1285 .vidioc_qbuf = isp_video_qbuf,
1286 .vidioc_dqbuf = isp_video_dqbuf,
1287 .vidioc_streamon = isp_video_streamon,
1288 .vidioc_streamoff = isp_video_streamoff,
1289 .vidioc_enum_input = isp_video_enum_input,
1290 .vidioc_g_input = isp_video_g_input,
1291 .vidioc_s_input = isp_video_s_input,
1292};
1293
1294
1295
1296
1297
1298static int isp_video_open(struct file *file)
1299{
1300 struct isp_video *video = video_drvdata(file);
1301 struct isp_video_fh *handle;
1302 struct vb2_queue *queue;
1303 int ret = 0;
1304
1305 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
1306 if (handle == NULL)
1307 return -ENOMEM;
1308
1309 v4l2_fh_init(&handle->vfh, &video->video);
1310 v4l2_fh_add(&handle->vfh);
1311
1312
1313 if (omap3isp_get(video->isp) == NULL) {
1314 ret = -EBUSY;
1315 goto done;
1316 }
1317
1318 ret = v4l2_pipeline_pm_use(&video->video.entity, 1);
1319 if (ret < 0) {
1320 omap3isp_put(video->isp);
1321 goto done;
1322 }
1323
1324 queue = &handle->queue;
1325 queue->type = video->type;
1326 queue->io_modes = VB2_MMAP | VB2_USERPTR;
1327 queue->drv_priv = handle;
1328 queue->ops = &isp_video_queue_ops;
1329 queue->mem_ops = &vb2_dma_contig_memops;
1330 queue->buf_struct_size = sizeof(struct isp_buffer);
1331 queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1332 queue->dev = video->isp->dev;
1333
1334 ret = vb2_queue_init(&handle->queue);
1335 if (ret < 0) {
1336 omap3isp_put(video->isp);
1337 goto done;
1338 }
1339
1340 memset(&handle->format, 0, sizeof(handle->format));
1341 handle->format.type = video->type;
1342 handle->timeperframe.denominator = 1;
1343
1344 handle->video = video;
1345 file->private_data = &handle->vfh;
1346
1347done:
1348 if (ret < 0) {
1349 v4l2_fh_del(&handle->vfh);
1350 v4l2_fh_exit(&handle->vfh);
1351 kfree(handle);
1352 }
1353
1354 return ret;
1355}
1356
1357static int isp_video_release(struct file *file)
1358{
1359 struct isp_video *video = video_drvdata(file);
1360 struct v4l2_fh *vfh = file->private_data;
1361 struct isp_video_fh *handle = to_isp_video_fh(vfh);
1362
1363
1364 isp_video_streamoff(file, vfh, video->type);
1365
1366 mutex_lock(&video->queue_lock);
1367 vb2_queue_release(&handle->queue);
1368 mutex_unlock(&video->queue_lock);
1369
1370 v4l2_pipeline_pm_use(&video->video.entity, 0);
1371
1372
1373 v4l2_fh_del(vfh);
1374 v4l2_fh_exit(vfh);
1375 kfree(handle);
1376 file->private_data = NULL;
1377
1378 omap3isp_put(video->isp);
1379
1380 return 0;
1381}
1382
1383static __poll_t isp_video_poll(struct file *file, poll_table *wait)
1384{
1385 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1386 struct isp_video *video = video_drvdata(file);
1387 __poll_t ret;
1388
1389 mutex_lock(&video->queue_lock);
1390 ret = vb2_poll(&vfh->queue, file, wait);
1391 mutex_unlock(&video->queue_lock);
1392
1393 return ret;
1394}
1395
1396static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
1397{
1398 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1399
1400 return vb2_mmap(&vfh->queue, vma);
1401}
1402
1403static const struct v4l2_file_operations isp_video_fops = {
1404 .owner = THIS_MODULE,
1405 .unlocked_ioctl = video_ioctl2,
1406 .open = isp_video_open,
1407 .release = isp_video_release,
1408 .poll = isp_video_poll,
1409 .mmap = isp_video_mmap,
1410};
1411
1412
1413
1414
1415
1416static const struct isp_video_operations isp_video_dummy_ops = {
1417};
1418
1419int omap3isp_video_init(struct isp_video *video, const char *name)
1420{
1421 const char *direction;
1422 int ret;
1423
1424 switch (video->type) {
1425 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1426 direction = "output";
1427 video->pad.flags = MEDIA_PAD_FL_SINK
1428 | MEDIA_PAD_FL_MUST_CONNECT;
1429 break;
1430 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1431 direction = "input";
1432 video->pad.flags = MEDIA_PAD_FL_SOURCE
1433 | MEDIA_PAD_FL_MUST_CONNECT;
1434 video->video.vfl_dir = VFL_DIR_TX;
1435 break;
1436
1437 default:
1438 return -EINVAL;
1439 }
1440
1441 ret = media_entity_pads_init(&video->video.entity, 1, &video->pad);
1442 if (ret < 0)
1443 return ret;
1444
1445 mutex_init(&video->mutex);
1446 atomic_set(&video->active, 0);
1447
1448 spin_lock_init(&video->pipe.lock);
1449 mutex_init(&video->stream_lock);
1450 mutex_init(&video->queue_lock);
1451 spin_lock_init(&video->irqlock);
1452
1453
1454 if (video->ops == NULL)
1455 video->ops = &isp_video_dummy_ops;
1456
1457 video->video.fops = &isp_video_fops;
1458 snprintf(video->video.name, sizeof(video->video.name),
1459 "OMAP3 ISP %s %s", name, direction);
1460 video->video.vfl_type = VFL_TYPE_GRABBER;
1461 video->video.release = video_device_release_empty;
1462 video->video.ioctl_ops = &isp_video_ioctl_ops;
1463 video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED;
1464
1465 video_set_drvdata(&video->video, video);
1466
1467 return 0;
1468}
1469
1470void omap3isp_video_cleanup(struct isp_video *video)
1471{
1472 media_entity_cleanup(&video->video.entity);
1473 mutex_destroy(&video->queue_lock);
1474 mutex_destroy(&video->stream_lock);
1475 mutex_destroy(&video->mutex);
1476}
1477
1478int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
1479{
1480 int ret;
1481
1482 video->video.v4l2_dev = vdev;
1483
1484 ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
1485 if (ret < 0)
1486 dev_err(video->isp->dev,
1487 "%s: could not register video device (%d)\n",
1488 __func__, ret);
1489
1490 return ret;
1491}
1492
1493void omap3isp_video_unregister(struct isp_video *video)
1494{
1495 video_unregister_device(&video->video);
1496}
1497