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