1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/init.h>
33#include <linux/module.h>
34#include <linux/vmalloc.h>
35#include <linux/sched.h>
36#include <linux/types.h>
37#include <linux/platform_device.h>
38#include <linux/irq.h>
39#include <linux/videodev2.h>
40#include <linux/dma-mapping.h>
41#include <linux/slab.h>
42
43#include <media/videobuf-dma-contig.h>
44#include <media/v4l2-device.h>
45#include <media/v4l2-ioctl.h>
46
47#include <video/omapvrfb.h>
48#include <video/omapdss.h>
49
50#include "omap_voutlib.h"
51#include "omap_voutdef.h"
52#include "omap_vout_vrfb.h"
53
54MODULE_AUTHOR("Texas Instruments");
55MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
56MODULE_LICENSE("GPL");
57
58
59#define VOUT_NAME "omap_vout"
60
61enum omap_vout_channels {
62 OMAP_VIDEO1,
63 OMAP_VIDEO2,
64};
65
66static struct videobuf_queue_ops video_vbq_ops;
67
68static u32 video1_numbuffers = 3;
69static u32 video2_numbuffers = 3;
70static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
71static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
72static bool vid1_static_vrfb_alloc;
73static bool vid2_static_vrfb_alloc;
74static bool debug;
75
76
77module_param(video1_numbuffers, uint, S_IRUGO);
78MODULE_PARM_DESC(video1_numbuffers,
79 "Number of buffers to be allocated at init time for Video1 device.");
80
81module_param(video2_numbuffers, uint, S_IRUGO);
82MODULE_PARM_DESC(video2_numbuffers,
83 "Number of buffers to be allocated at init time for Video2 device.");
84
85module_param(video1_bufsize, uint, S_IRUGO);
86MODULE_PARM_DESC(video1_bufsize,
87 "Size of the buffer to be allocated for video1 device");
88
89module_param(video2_bufsize, uint, S_IRUGO);
90MODULE_PARM_DESC(video2_bufsize,
91 "Size of the buffer to be allocated for video2 device");
92
93module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
94MODULE_PARM_DESC(vid1_static_vrfb_alloc,
95 "Static allocation of the VRFB buffer for video1 device");
96
97module_param(vid2_static_vrfb_alloc, bool, S_IRUGO);
98MODULE_PARM_DESC(vid2_static_vrfb_alloc,
99 "Static allocation of the VRFB buffer for video2 device");
100
101module_param(debug, bool, S_IRUGO);
102MODULE_PARM_DESC(debug, "Debug level (0-1)");
103
104
105static const struct v4l2_fmtdesc omap_formats[] = {
106 {
107
108
109
110
111
112
113
114
115
116
117 .description = "RGB565, le",
118 .pixelformat = V4L2_PIX_FMT_RGB565,
119 },
120 {
121
122
123
124 .description = "RGB32, le",
125 .pixelformat = V4L2_PIX_FMT_RGB32,
126 },
127 {
128
129
130
131
132 .description = "RGB24, le",
133 .pixelformat = V4L2_PIX_FMT_RGB24,
134 },
135 {
136 .description = "YUYV (YUV 4:2:2), packed",
137 .pixelformat = V4L2_PIX_FMT_YUYV,
138 },
139 {
140 .description = "UYVY, packed",
141 .pixelformat = V4L2_PIX_FMT_UYVY,
142 },
143};
144
145#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
146
147
148
149
150static int omap_vout_try_format(struct v4l2_pix_format *pix)
151{
152 int ifmt, bpp = 0;
153
154 pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT,
155 (u32)VID_MAX_HEIGHT);
156 pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH);
157
158 for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) {
159 if (pix->pixelformat == omap_formats[ifmt].pixelformat)
160 break;
161 }
162
163 if (ifmt == NUM_OUTPUT_FORMATS)
164 ifmt = 0;
165
166 pix->pixelformat = omap_formats[ifmt].pixelformat;
167 pix->field = V4L2_FIELD_ANY;
168
169 switch (pix->pixelformat) {
170 case V4L2_PIX_FMT_YUYV:
171 case V4L2_PIX_FMT_UYVY:
172 default:
173 pix->colorspace = V4L2_COLORSPACE_JPEG;
174 bpp = YUYV_BPP;
175 break;
176 case V4L2_PIX_FMT_RGB565:
177 case V4L2_PIX_FMT_RGB565X:
178 pix->colorspace = V4L2_COLORSPACE_SRGB;
179 bpp = RGB565_BPP;
180 break;
181 case V4L2_PIX_FMT_RGB24:
182 pix->colorspace = V4L2_COLORSPACE_SRGB;
183 bpp = RGB24_BPP;
184 break;
185 case V4L2_PIX_FMT_RGB32:
186 case V4L2_PIX_FMT_BGR32:
187 pix->colorspace = V4L2_COLORSPACE_SRGB;
188 bpp = RGB32_BPP;
189 break;
190 }
191 pix->bytesperline = pix->width * bpp;
192 pix->sizeimage = pix->bytesperline * pix->height;
193
194 return bpp;
195}
196
197
198
199
200
201static unsigned long omap_vout_uservirt_to_phys(unsigned long virtp)
202{
203 unsigned long physp = 0;
204 struct vm_area_struct *vma;
205 struct mm_struct *mm = current->mm;
206
207
208 if (virtp >= PAGE_OFFSET)
209 return virt_to_phys((void *) virtp);
210
211 down_read(¤t->mm->mmap_sem);
212 vma = find_vma(mm, virtp);
213 if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
214
215
216 physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
217 up_read(¤t->mm->mmap_sem);
218 } else {
219
220 int res, nr_pages = 1;
221 struct page *pages;
222
223 res = get_user_pages(current, current->mm, virtp, nr_pages, 1,
224 0, &pages, NULL);
225 up_read(¤t->mm->mmap_sem);
226
227 if (res == nr_pages) {
228 physp = __pa(page_address(&pages[0]) +
229 (virtp & ~PAGE_MASK));
230 } else {
231 printk(KERN_WARNING VOUT_NAME
232 "get_user_pages failed\n");
233 return 0;
234 }
235 }
236
237 return physp;
238}
239
240
241
242
243void omap_vout_free_buffers(struct omap_vout_device *vout)
244{
245 int i, numbuffers;
246
247
248 numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers;
249 vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize;
250
251 for (i = 0; i < numbuffers; i++) {
252 omap_vout_free_buffer(vout->buf_virt_addr[i],
253 vout->buffer_size);
254 vout->buf_phy_addr[i] = 0;
255 vout->buf_virt_addr[i] = 0;
256 }
257}
258
259
260
261
262
263
264static int v4l2_rot_to_dss_rot(int v4l2_rotation,
265 enum dss_rotation *rotation, bool mirror)
266{
267 int ret = 0;
268
269 switch (v4l2_rotation) {
270 case 90:
271 *rotation = dss_rotation_90_degree;
272 break;
273 case 180:
274 *rotation = dss_rotation_180_degree;
275 break;
276 case 270:
277 *rotation = dss_rotation_270_degree;
278 break;
279 case 0:
280 *rotation = dss_rotation_0_degree;
281 break;
282 default:
283 ret = -EINVAL;
284 }
285 return ret;
286}
287
288static int omap_vout_calculate_offset(struct omap_vout_device *vout)
289{
290 struct omapvideo_info *ovid;
291 struct v4l2_rect *crop = &vout->crop;
292 struct v4l2_pix_format *pix = &vout->pix;
293 int *cropped_offset = &vout->cropped_offset;
294 int ps = 2, line_length = 0;
295
296 ovid = &vout->vid_info;
297
298 if (ovid->rotation_type == VOUT_ROT_VRFB) {
299 omap_vout_calculate_vrfb_offset(vout);
300 } else {
301 vout->line_length = line_length = pix->width;
302
303 if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
304 V4L2_PIX_FMT_UYVY == pix->pixelformat)
305 ps = 2;
306 else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
307 ps = 4;
308 else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
309 ps = 3;
310
311 vout->ps = ps;
312
313 *cropped_offset = (line_length * ps) *
314 crop->top + crop->left * ps;
315 }
316
317 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
318 __func__, vout->cropped_offset);
319
320 return 0;
321}
322
323
324
325
326static int video_mode_to_dss_mode(struct omap_vout_device *vout)
327{
328 struct omap_overlay *ovl;
329 struct omapvideo_info *ovid;
330 struct v4l2_pix_format *pix = &vout->pix;
331 enum omap_color_mode mode;
332
333 ovid = &vout->vid_info;
334 ovl = ovid->overlays[0];
335
336 switch (pix->pixelformat) {
337 case V4L2_PIX_FMT_YUYV:
338 mode = OMAP_DSS_COLOR_YUV2;
339 break;
340 case V4L2_PIX_FMT_UYVY:
341 mode = OMAP_DSS_COLOR_UYVY;
342 break;
343 case V4L2_PIX_FMT_RGB565:
344 mode = OMAP_DSS_COLOR_RGB16;
345 break;
346 case V4L2_PIX_FMT_RGB24:
347 mode = OMAP_DSS_COLOR_RGB24P;
348 break;
349 case V4L2_PIX_FMT_RGB32:
350 mode = (ovl->id == OMAP_DSS_VIDEO1) ?
351 OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
352 break;
353 case V4L2_PIX_FMT_BGR32:
354 mode = OMAP_DSS_COLOR_RGBX32;
355 break;
356 default:
357 mode = -EINVAL;
358 break;
359 }
360 return mode;
361}
362
363
364
365
366static int omapvid_setup_overlay(struct omap_vout_device *vout,
367 struct omap_overlay *ovl, int posx, int posy, int outw,
368 int outh, u32 addr)
369{
370 int ret = 0;
371 struct omap_overlay_info info;
372 int cropheight, cropwidth, pixwidth;
373
374 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
375 (outw != vout->pix.width || outh != vout->pix.height)) {
376 ret = -EINVAL;
377 goto setup_ovl_err;
378 }
379
380 vout->dss_mode = video_mode_to_dss_mode(vout);
381 if (vout->dss_mode == -EINVAL) {
382 ret = -EINVAL;
383 goto setup_ovl_err;
384 }
385
386
387
388
389 if (is_rotation_90_or_270(vout)) {
390 cropheight = vout->crop.width;
391 cropwidth = vout->crop.height;
392 pixwidth = vout->pix.height;
393 } else {
394 cropheight = vout->crop.height;
395 cropwidth = vout->crop.width;
396 pixwidth = vout->pix.width;
397 }
398
399 ovl->get_overlay_info(ovl, &info);
400 info.paddr = addr;
401 info.width = cropwidth;
402 info.height = cropheight;
403 info.color_mode = vout->dss_mode;
404 info.mirror = vout->mirror;
405 info.pos_x = posx;
406 info.pos_y = posy;
407 info.out_width = outw;
408 info.out_height = outh;
409 info.global_alpha = vout->win.global_alpha;
410 if (!is_rotation_enabled(vout)) {
411 info.rotation = 0;
412 info.rotation_type = OMAP_DSS_ROT_DMA;
413 info.screen_width = pixwidth;
414 } else {
415 info.rotation = vout->rotation;
416 info.rotation_type = OMAP_DSS_ROT_VRFB;
417 info.screen_width = 2048;
418 }
419
420 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
421 "%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
422 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
423 "out_height=%d rotation_type=%d screen_width=%d\n",
424 __func__, ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
425 info.color_mode, info.rotation, info.mirror, info.pos_x,
426 info.pos_y, info.out_width, info.out_height, info.rotation_type,
427 info.screen_width);
428
429 ret = ovl->set_overlay_info(ovl, &info);
430 if (ret)
431 goto setup_ovl_err;
432
433 return 0;
434
435setup_ovl_err:
436 v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n");
437 return ret;
438}
439
440
441
442
443static int omapvid_init(struct omap_vout_device *vout, u32 addr)
444{
445 int ret = 0, i;
446 struct v4l2_window *win;
447 struct omap_overlay *ovl;
448 int posx, posy, outw, outh, temp;
449 struct omap_video_timings *timing;
450 struct omapvideo_info *ovid = &vout->vid_info;
451
452 win = &vout->win;
453 for (i = 0; i < ovid->num_overlays; i++) {
454 struct omap_dss_device *dssdev;
455
456 ovl = ovid->overlays[i];
457 dssdev = ovl->get_device(ovl);
458
459 if (!dssdev)
460 return -EINVAL;
461
462 timing = &dssdev->panel.timings;
463
464 outw = win->w.width;
465 outh = win->w.height;
466 switch (vout->rotation) {
467 case dss_rotation_90_degree:
468
469
470
471 temp = outw;
472 outw = outh;
473 outh = temp;
474 posy = (timing->y_res - win->w.width) - win->w.left;
475 posx = win->w.top;
476 break;
477
478 case dss_rotation_180_degree:
479 posx = (timing->x_res - win->w.width) - win->w.left;
480 posy = (timing->y_res - win->w.height) - win->w.top;
481 break;
482
483 case dss_rotation_270_degree:
484 temp = outw;
485 outw = outh;
486 outh = temp;
487 posy = win->w.left;
488 posx = (timing->x_res - win->w.height) - win->w.top;
489 break;
490
491 default:
492 posx = win->w.left;
493 posy = win->w.top;
494 break;
495 }
496
497 ret = omapvid_setup_overlay(vout, ovl, posx, posy,
498 outw, outh, addr);
499 if (ret)
500 goto omapvid_init_err;
501 }
502 return 0;
503
504omapvid_init_err:
505 v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n");
506 return ret;
507}
508
509
510
511
512static int omapvid_apply_changes(struct omap_vout_device *vout)
513{
514 int i;
515 struct omap_overlay *ovl;
516 struct omapvideo_info *ovid = &vout->vid_info;
517
518 for (i = 0; i < ovid->num_overlays; i++) {
519 struct omap_dss_device *dssdev;
520
521 ovl = ovid->overlays[i];
522 dssdev = ovl->get_device(ovl);
523 if (!dssdev)
524 return -EINVAL;
525 ovl->manager->apply(ovl->manager);
526 }
527
528 return 0;
529}
530
531static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
532 unsigned int irqstatus, struct timeval timevalue)
533{
534 u32 fid;
535
536 if (vout->first_int) {
537 vout->first_int = 0;
538 goto err;
539 }
540
541 if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
542 fid = 1;
543 else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
544 fid = 0;
545 else
546 goto err;
547
548 vout->field_id ^= 1;
549 if (fid != vout->field_id) {
550 if (fid == 0)
551 vout->field_id = fid;
552 } else if (0 == fid) {
553 if (vout->cur_frm == vout->next_frm)
554 goto err;
555
556 vout->cur_frm->ts = timevalue;
557 vout->cur_frm->state = VIDEOBUF_DONE;
558 wake_up_interruptible(&vout->cur_frm->done);
559 vout->cur_frm = vout->next_frm;
560 } else {
561 if (list_empty(&vout->dma_queue) ||
562 (vout->cur_frm != vout->next_frm))
563 goto err;
564 }
565
566 return vout->field_id;
567err:
568 return 0;
569}
570
571static void omap_vout_isr(void *arg, unsigned int irqstatus)
572{
573 int ret, fid, mgr_id;
574 u32 addr, irq;
575 struct omap_overlay *ovl;
576 struct timeval timevalue;
577 struct omapvideo_info *ovid;
578 struct omap_dss_device *cur_display;
579 struct omap_vout_device *vout = (struct omap_vout_device *)arg;
580
581 if (!vout->streaming)
582 return;
583
584 ovid = &vout->vid_info;
585 ovl = ovid->overlays[0];
586
587 mgr_id = ovl->manager->id;
588
589
590 cur_display = ovl->get_device(ovl);
591
592 if (!cur_display)
593 return;
594
595 spin_lock(&vout->vbq_lock);
596 v4l2_get_timestamp(&timevalue);
597
598 switch (cur_display->type) {
599 case OMAP_DISPLAY_TYPE_DSI:
600 case OMAP_DISPLAY_TYPE_DPI:
601 case OMAP_DISPLAY_TYPE_DVI:
602 if (mgr_id == OMAP_DSS_CHANNEL_LCD)
603 irq = DISPC_IRQ_VSYNC;
604 else if (mgr_id == OMAP_DSS_CHANNEL_LCD2)
605 irq = DISPC_IRQ_VSYNC2;
606 else
607 goto vout_isr_err;
608
609 if (!(irqstatus & irq))
610 goto vout_isr_err;
611 break;
612 case OMAP_DISPLAY_TYPE_VENC:
613 fid = omapvid_handle_interlace_display(vout, irqstatus,
614 timevalue);
615 if (!fid)
616 goto vout_isr_err;
617 break;
618 case OMAP_DISPLAY_TYPE_HDMI:
619 if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
620 goto vout_isr_err;
621 break;
622 default:
623 goto vout_isr_err;
624 }
625
626 if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
627 vout->cur_frm->ts = timevalue;
628 vout->cur_frm->state = VIDEOBUF_DONE;
629 wake_up_interruptible(&vout->cur_frm->done);
630 vout->cur_frm = vout->next_frm;
631 }
632
633 vout->first_int = 0;
634 if (list_empty(&vout->dma_queue))
635 goto vout_isr_err;
636
637 vout->next_frm = list_entry(vout->dma_queue.next,
638 struct videobuf_buffer, queue);
639 list_del(&vout->next_frm->queue);
640
641 vout->next_frm->state = VIDEOBUF_ACTIVE;
642
643 addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
644 + vout->cropped_offset;
645
646
647 ret = omapvid_init(vout, addr);
648 if (ret) {
649 printk(KERN_ERR VOUT_NAME
650 "failed to set overlay info\n");
651 goto vout_isr_err;
652 }
653
654
655 ret = omapvid_apply_changes(vout);
656 if (ret)
657 printk(KERN_ERR VOUT_NAME "failed to change mode\n");
658
659vout_isr_err:
660 spin_unlock(&vout->vbq_lock);
661}
662
663
664
665
666
667
668
669
670
671static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
672 unsigned int *size)
673{
674 int startindex = 0, i, j;
675 u32 phy_addr = 0, virt_addr = 0;
676 struct omap_vout_device *vout = q->priv_data;
677 struct omapvideo_info *ovid = &vout->vid_info;
678 int vid_max_buf_size;
679
680 if (!vout)
681 return -EINVAL;
682
683 vid_max_buf_size = vout->vid == OMAP_VIDEO1 ? video1_bufsize :
684 video2_bufsize;
685
686 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
687 return -EINVAL;
688
689 startindex = (vout->vid == OMAP_VIDEO1) ?
690 video1_numbuffers : video2_numbuffers;
691 if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
692 *count = startindex;
693
694 if (ovid->rotation_type == VOUT_ROT_VRFB) {
695 if (omap_vout_vrfb_buffer_setup(vout, count, startindex))
696 return -ENOMEM;
697 }
698
699 if (V4L2_MEMORY_MMAP != vout->memory)
700 return 0;
701
702
703 *size = PAGE_ALIGN(vout->pix.width * vout->pix.height * vout->bpp);
704 startindex = (vout->vid == OMAP_VIDEO1) ?
705 video1_numbuffers : video2_numbuffers;
706
707
708 if (*size > vid_max_buf_size) {
709 v4l2_err(&vout->vid_dev->v4l2_dev,
710 "buffer allocation mismatch [%u] [%u]\n",
711 *size, vout->buffer_size);
712 return -ENOMEM;
713 }
714
715 for (i = startindex; i < *count; i++) {
716 vout->buffer_size = *size;
717
718 virt_addr = omap_vout_alloc_buffer(vout->buffer_size,
719 &phy_addr);
720 if (!virt_addr) {
721 if (ovid->rotation_type == VOUT_ROT_NONE) {
722 break;
723 } else {
724 if (!is_rotation_enabled(vout))
725 break;
726
727 for (j = i; j < *count; j++) {
728 omap_vout_free_buffer(
729 vout->smsshado_virt_addr[j],
730 vout->smsshado_size);
731 vout->smsshado_virt_addr[j] = 0;
732 vout->smsshado_phy_addr[j] = 0;
733 }
734 }
735 }
736 vout->buf_virt_addr[i] = virt_addr;
737 vout->buf_phy_addr[i] = phy_addr;
738 }
739 *count = vout->buffer_allocated = i;
740
741 return 0;
742}
743
744
745
746
747
748static void omap_vout_free_extra_buffers(struct omap_vout_device *vout)
749{
750 int num_buffers = 0, i;
751
752 num_buffers = (vout->vid == OMAP_VIDEO1) ?
753 video1_numbuffers : video2_numbuffers;
754
755 for (i = num_buffers; i < vout->buffer_allocated; i++) {
756 if (vout->buf_virt_addr[i])
757 omap_vout_free_buffer(vout->buf_virt_addr[i],
758 vout->buffer_size);
759
760 vout->buf_virt_addr[i] = 0;
761 vout->buf_phy_addr[i] = 0;
762 }
763 vout->buffer_allocated = num_buffers;
764}
765
766
767
768
769
770
771
772
773static int omap_vout_buffer_prepare(struct videobuf_queue *q,
774 struct videobuf_buffer *vb,
775 enum v4l2_field field)
776{
777 struct omap_vout_device *vout = q->priv_data;
778 struct omapvideo_info *ovid = &vout->vid_info;
779
780 if (VIDEOBUF_NEEDS_INIT == vb->state) {
781 vb->width = vout->pix.width;
782 vb->height = vout->pix.height;
783 vb->size = vb->width * vb->height * vout->bpp;
784 vb->field = field;
785 }
786 vb->state = VIDEOBUF_PREPARED;
787
788
789
790 if (V4L2_MEMORY_USERPTR == vb->memory) {
791 if (0 == vb->baddr)
792 return -EINVAL;
793
794 vout->queued_buf_addr[vb->i] = (u8 *)
795 omap_vout_uservirt_to_phys(vb->baddr);
796 } else {
797 unsigned long addr, dma_addr;
798 unsigned long size;
799
800 addr = (unsigned long) vout->buf_virt_addr[vb->i];
801 size = (unsigned long) vb->size;
802
803 dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void *) addr,
804 size, DMA_TO_DEVICE);
805 if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr))
806 v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single failed\n");
807
808 vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
809 }
810
811 if (ovid->rotation_type == VOUT_ROT_VRFB)
812 return omap_vout_prepare_vrfb(vout, vb);
813 else
814 return 0;
815}
816
817
818
819
820
821
822static void omap_vout_buffer_queue(struct videobuf_queue *q,
823 struct videobuf_buffer *vb)
824{
825 struct omap_vout_device *vout = q->priv_data;
826
827
828
829 list_add_tail(&vb->queue, &vout->dma_queue);
830
831 vb->state = VIDEOBUF_QUEUED;
832}
833
834
835
836
837
838static void omap_vout_buffer_release(struct videobuf_queue *q,
839 struct videobuf_buffer *vb)
840{
841 struct omap_vout_device *vout = q->priv_data;
842
843 vb->state = VIDEOBUF_NEEDS_INIT;
844
845 if (V4L2_MEMORY_MMAP != vout->memory)
846 return;
847}
848
849
850
851
852static unsigned int omap_vout_poll(struct file *file,
853 struct poll_table_struct *wait)
854{
855 struct omap_vout_device *vout = file->private_data;
856 struct videobuf_queue *q = &vout->vbq;
857
858 return videobuf_poll_stream(file, q, wait);
859}
860
861static void omap_vout_vm_open(struct vm_area_struct *vma)
862{
863 struct omap_vout_device *vout = vma->vm_private_data;
864
865 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
866 "vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
867 vout->mmap_count++;
868}
869
870static void omap_vout_vm_close(struct vm_area_struct *vma)
871{
872 struct omap_vout_device *vout = vma->vm_private_data;
873
874 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
875 "vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
876 vout->mmap_count--;
877}
878
879static struct vm_operations_struct omap_vout_vm_ops = {
880 .open = omap_vout_vm_open,
881 .close = omap_vout_vm_close,
882};
883
884static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
885{
886 int i;
887 void *pos;
888 unsigned long start = vma->vm_start;
889 unsigned long size = (vma->vm_end - vma->vm_start);
890 struct omap_vout_device *vout = file->private_data;
891 struct videobuf_queue *q = &vout->vbq;
892
893 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
894 " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__,
895 vma->vm_pgoff, vma->vm_start, vma->vm_end);
896
897
898 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
899 if (NULL == q->bufs[i])
900 continue;
901 if (V4L2_MEMORY_MMAP != q->bufs[i]->memory)
902 continue;
903 if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT))
904 break;
905 }
906
907 if (VIDEO_MAX_FRAME == i) {
908 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
909 "offset invalid [offset=0x%lx]\n",
910 (vma->vm_pgoff << PAGE_SHIFT));
911 return -EINVAL;
912 }
913
914 if (size > vout->buffer_size) {
915 v4l2_err(&vout->vid_dev->v4l2_dev,
916 "insufficient memory [%lu] [%u]\n",
917 size, vout->buffer_size);
918 return -ENOMEM;
919 }
920
921 q->bufs[i]->baddr = vma->vm_start;
922
923 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
924 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
925 vma->vm_ops = &omap_vout_vm_ops;
926 vma->vm_private_data = (void *) vout;
927 pos = (void *)vout->buf_virt_addr[i];
928 vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT;
929 while (size > 0) {
930 unsigned long pfn;
931 pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT;
932 if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
933 return -EAGAIN;
934 start += PAGE_SIZE;
935 pos += PAGE_SIZE;
936 size -= PAGE_SIZE;
937 }
938 vout->mmap_count++;
939 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
940
941 return 0;
942}
943
944static int omap_vout_release(struct file *file)
945{
946 unsigned int ret, i;
947 struct videobuf_queue *q;
948 struct omapvideo_info *ovid;
949 struct omap_vout_device *vout = file->private_data;
950
951 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
952 ovid = &vout->vid_info;
953
954 if (!vout)
955 return 0;
956
957 q = &vout->vbq;
958
959 for (i = 0; i < ovid->num_overlays; i++) {
960 struct omap_overlay *ovl = ovid->overlays[i];
961 struct omap_dss_device *dssdev = ovl->get_device(ovl);
962
963 if (dssdev)
964 ovl->disable(ovl);
965 }
966
967 ret = omapvid_apply_changes(vout);
968 if (ret)
969 v4l2_warn(&vout->vid_dev->v4l2_dev,
970 "Unable to apply changes\n");
971
972
973 omap_vout_free_extra_buffers(vout);
974
975
976
977
978 if (ovid->rotation_type == VOUT_ROT_VRFB) {
979 if (!vout->vrfb_static_allocation)
980 omap_vout_free_vrfb_buffers(vout);
981 }
982 videobuf_mmap_free(q);
983
984
985
986 if (vout->streaming) {
987 u32 mask = 0;
988
989 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
990 DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_VSYNC2;
991 omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
992 vout->streaming = false;
993
994 videobuf_streamoff(q);
995 videobuf_queue_cancel(q);
996 }
997
998 if (vout->mmap_count != 0)
999 vout->mmap_count = 0;
1000
1001 vout->opened -= 1;
1002 file->private_data = NULL;
1003
1004 if (vout->buffer_allocated)
1005 videobuf_mmap_free(q);
1006
1007 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
1008 return ret;
1009}
1010
1011static int omap_vout_open(struct file *file)
1012{
1013 struct videobuf_queue *q;
1014 struct omap_vout_device *vout = NULL;
1015
1016 vout = video_drvdata(file);
1017 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
1018
1019 if (vout == NULL)
1020 return -ENODEV;
1021
1022
1023 if (vout->opened)
1024 return -EBUSY;
1025
1026 vout->opened += 1;
1027
1028 file->private_data = vout;
1029 vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1030
1031 q = &vout->vbq;
1032 video_vbq_ops.buf_setup = omap_vout_buffer_setup;
1033 video_vbq_ops.buf_prepare = omap_vout_buffer_prepare;
1034 video_vbq_ops.buf_release = omap_vout_buffer_release;
1035 video_vbq_ops.buf_queue = omap_vout_buffer_queue;
1036 spin_lock_init(&vout->vbq_lock);
1037
1038 videobuf_queue_dma_contig_init(q, &video_vbq_ops, q->dev,
1039 &vout->vbq_lock, vout->type, V4L2_FIELD_NONE,
1040 sizeof(struct videobuf_buffer), vout, NULL);
1041
1042 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
1043 return 0;
1044}
1045
1046
1047
1048
1049static int vidioc_querycap(struct file *file, void *fh,
1050 struct v4l2_capability *cap)
1051{
1052 struct omap_vout_device *vout = fh;
1053
1054 strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
1055 strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
1056 cap->bus_info[0] = '\0';
1057 cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
1058 V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1059 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1060
1061 return 0;
1062}
1063
1064static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
1065 struct v4l2_fmtdesc *fmt)
1066{
1067 int index = fmt->index;
1068
1069 if (index >= NUM_OUTPUT_FORMATS)
1070 return -EINVAL;
1071
1072 fmt->flags = omap_formats[index].flags;
1073 strlcpy(fmt->description, omap_formats[index].description,
1074 sizeof(fmt->description));
1075 fmt->pixelformat = omap_formats[index].pixelformat;
1076
1077 return 0;
1078}
1079
1080static int vidioc_g_fmt_vid_out(struct file *file, void *fh,
1081 struct v4l2_format *f)
1082{
1083 struct omap_vout_device *vout = fh;
1084
1085 f->fmt.pix = vout->pix;
1086 return 0;
1087
1088}
1089
1090static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
1091 struct v4l2_format *f)
1092{
1093 struct omap_overlay *ovl;
1094 struct omapvideo_info *ovid;
1095 struct omap_video_timings *timing;
1096 struct omap_vout_device *vout = fh;
1097 struct omap_dss_device *dssdev;
1098
1099 ovid = &vout->vid_info;
1100 ovl = ovid->overlays[0];
1101
1102 dssdev = ovl->get_device(ovl);
1103
1104 if (!dssdev)
1105 return -EINVAL;
1106
1107 timing = &dssdev->panel.timings;
1108
1109 vout->fbuf.fmt.height = timing->y_res;
1110 vout->fbuf.fmt.width = timing->x_res;
1111
1112 omap_vout_try_format(&f->fmt.pix);
1113 return 0;
1114}
1115
1116static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
1117 struct v4l2_format *f)
1118{
1119 int ret, bpp;
1120 struct omap_overlay *ovl;
1121 struct omapvideo_info *ovid;
1122 struct omap_video_timings *timing;
1123 struct omap_vout_device *vout = fh;
1124 struct omap_dss_device *dssdev;
1125
1126 if (vout->streaming)
1127 return -EBUSY;
1128
1129 mutex_lock(&vout->lock);
1130
1131 ovid = &vout->vid_info;
1132 ovl = ovid->overlays[0];
1133 dssdev = ovl->get_device(ovl);
1134
1135
1136 if (!dssdev) {
1137 ret = -EINVAL;
1138 goto s_fmt_vid_out_exit;
1139 }
1140 timing = &dssdev->panel.timings;
1141
1142
1143
1144 if ((is_rotation_enabled(vout)) &&
1145 f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
1146 ret = -EINVAL;
1147 goto s_fmt_vid_out_exit;
1148 }
1149
1150
1151
1152 if (is_rotation_90_or_270(vout)) {
1153 vout->fbuf.fmt.height = timing->x_res;
1154 vout->fbuf.fmt.width = timing->y_res;
1155 } else {
1156 vout->fbuf.fmt.height = timing->y_res;
1157 vout->fbuf.fmt.width = timing->x_res;
1158 }
1159
1160
1161
1162 bpp = omap_vout_try_format(&f->fmt.pix);
1163 f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp;
1164
1165
1166 vout->bpp = bpp;
1167 vout->pix = f->fmt.pix;
1168 vout->vrfb_bpp = 1;
1169
1170
1171 if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat ||
1172 V4L2_PIX_FMT_UYVY == vout->pix.pixelformat)
1173 vout->vrfb_bpp = 2;
1174
1175
1176 omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
1177
1178 ret = 0;
1179
1180s_fmt_vid_out_exit:
1181 mutex_unlock(&vout->lock);
1182 return ret;
1183}
1184
1185static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
1186 struct v4l2_format *f)
1187{
1188 int ret = 0;
1189 struct omap_vout_device *vout = fh;
1190 struct omap_overlay *ovl;
1191 struct omapvideo_info *ovid;
1192 struct v4l2_window *win = &f->fmt.win;
1193
1194 ovid = &vout->vid_info;
1195 ovl = ovid->overlays[0];
1196
1197 ret = omap_vout_try_window(&vout->fbuf, win);
1198
1199 if (!ret) {
1200 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
1201 win->global_alpha = 255;
1202 else
1203 win->global_alpha = f->fmt.win.global_alpha;
1204 }
1205
1206 return ret;
1207}
1208
1209static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
1210 struct v4l2_format *f)
1211{
1212 int ret = 0;
1213 struct omap_overlay *ovl;
1214 struct omapvideo_info *ovid;
1215 struct omap_vout_device *vout = fh;
1216 struct v4l2_window *win = &f->fmt.win;
1217
1218 mutex_lock(&vout->lock);
1219 ovid = &vout->vid_info;
1220 ovl = ovid->overlays[0];
1221
1222 ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
1223 if (!ret) {
1224
1225 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
1226 vout->win.global_alpha = 255;
1227 else
1228 vout->win.global_alpha = f->fmt.win.global_alpha;
1229
1230 vout->win.chromakey = f->fmt.win.chromakey;
1231 }
1232 mutex_unlock(&vout->lock);
1233 return ret;
1234}
1235
1236static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
1237 struct v4l2_format *f)
1238{
1239 u32 key_value = 0;
1240 struct omap_overlay *ovl;
1241 struct omapvideo_info *ovid;
1242 struct omap_vout_device *vout = fh;
1243 struct omap_overlay_manager_info info;
1244 struct v4l2_window *win = &f->fmt.win;
1245
1246 ovid = &vout->vid_info;
1247 ovl = ovid->overlays[0];
1248
1249 win->w = vout->win.w;
1250 win->field = vout->win.field;
1251 win->global_alpha = vout->win.global_alpha;
1252
1253 if (ovl->manager && ovl->manager->get_manager_info) {
1254 ovl->manager->get_manager_info(ovl->manager, &info);
1255 key_value = info.trans_key;
1256 }
1257 win->chromakey = key_value;
1258 return 0;
1259}
1260
1261static int vidioc_cropcap(struct file *file, void *fh,
1262 struct v4l2_cropcap *cropcap)
1263{
1264 struct omap_vout_device *vout = fh;
1265 struct v4l2_pix_format *pix = &vout->pix;
1266
1267 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1268 return -EINVAL;
1269
1270
1271 cropcap->bounds.width = pix->width & ~1;
1272 cropcap->bounds.height = pix->height & ~1;
1273
1274 omap_vout_default_crop(&vout->pix, &vout->fbuf, &cropcap->defrect);
1275 cropcap->pixelaspect.numerator = 1;
1276 cropcap->pixelaspect.denominator = 1;
1277 return 0;
1278}
1279
1280static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
1281{
1282 struct omap_vout_device *vout = fh;
1283
1284 if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1285 return -EINVAL;
1286 crop->c = vout->crop;
1287 return 0;
1288}
1289
1290static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
1291{
1292 int ret = -EINVAL;
1293 struct omap_vout_device *vout = fh;
1294 struct omapvideo_info *ovid;
1295 struct omap_overlay *ovl;
1296 struct omap_video_timings *timing;
1297 struct omap_dss_device *dssdev;
1298
1299 if (vout->streaming)
1300 return -EBUSY;
1301
1302 mutex_lock(&vout->lock);
1303 ovid = &vout->vid_info;
1304 ovl = ovid->overlays[0];
1305
1306 dssdev = ovl->get_device(ovl);
1307
1308 if (!dssdev) {
1309 ret = -EINVAL;
1310 goto s_crop_err;
1311 }
1312
1313 timing = &dssdev->panel.timings;
1314
1315 if (is_rotation_90_or_270(vout)) {
1316 vout->fbuf.fmt.height = timing->x_res;
1317 vout->fbuf.fmt.width = timing->y_res;
1318 } else {
1319 vout->fbuf.fmt.height = timing->y_res;
1320 vout->fbuf.fmt.width = timing->x_res;
1321 }
1322
1323 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1324 ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win,
1325 &vout->fbuf, &crop->c);
1326
1327s_crop_err:
1328 mutex_unlock(&vout->lock);
1329 return ret;
1330}
1331
1332static int vidioc_queryctrl(struct file *file, void *fh,
1333 struct v4l2_queryctrl *ctrl)
1334{
1335 int ret = 0;
1336
1337 switch (ctrl->id) {
1338 case V4L2_CID_ROTATE:
1339 ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0);
1340 break;
1341 case V4L2_CID_BG_COLOR:
1342 ret = v4l2_ctrl_query_fill(ctrl, 0, 0xFFFFFF, 1, 0);
1343 break;
1344 case V4L2_CID_VFLIP:
1345 ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
1346 break;
1347 default:
1348 ctrl->name[0] = '\0';
1349 ret = -EINVAL;
1350 }
1351 return ret;
1352}
1353
1354static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl)
1355{
1356 int ret = 0;
1357 struct omap_vout_device *vout = fh;
1358
1359 switch (ctrl->id) {
1360 case V4L2_CID_ROTATE:
1361 ctrl->value = vout->control[0].value;
1362 break;
1363 case V4L2_CID_BG_COLOR:
1364 {
1365 struct omap_overlay_manager_info info;
1366 struct omap_overlay *ovl;
1367
1368 ovl = vout->vid_info.overlays[0];
1369 if (!ovl->manager || !ovl->manager->get_manager_info) {
1370 ret = -EINVAL;
1371 break;
1372 }
1373
1374 ovl->manager->get_manager_info(ovl->manager, &info);
1375 ctrl->value = info.default_color;
1376 break;
1377 }
1378 case V4L2_CID_VFLIP:
1379 ctrl->value = vout->control[2].value;
1380 break;
1381 default:
1382 ret = -EINVAL;
1383 }
1384 return ret;
1385}
1386
1387static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
1388{
1389 int ret = 0;
1390 struct omap_vout_device *vout = fh;
1391
1392 switch (a->id) {
1393 case V4L2_CID_ROTATE:
1394 {
1395 struct omapvideo_info *ovid;
1396 int rotation = a->value;
1397
1398 ovid = &vout->vid_info;
1399
1400 mutex_lock(&vout->lock);
1401 if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
1402 mutex_unlock(&vout->lock);
1403 ret = -ERANGE;
1404 break;
1405 }
1406
1407 if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
1408 mutex_unlock(&vout->lock);
1409 ret = -EINVAL;
1410 break;
1411 }
1412
1413 if (v4l2_rot_to_dss_rot(rotation, &vout->rotation,
1414 vout->mirror)) {
1415 mutex_unlock(&vout->lock);
1416 ret = -EINVAL;
1417 break;
1418 }
1419
1420 vout->control[0].value = rotation;
1421 mutex_unlock(&vout->lock);
1422 break;
1423 }
1424 case V4L2_CID_BG_COLOR:
1425 {
1426 struct omap_overlay *ovl;
1427 unsigned int color = a->value;
1428 struct omap_overlay_manager_info info;
1429
1430 ovl = vout->vid_info.overlays[0];
1431
1432 mutex_lock(&vout->lock);
1433 if (!ovl->manager || !ovl->manager->get_manager_info) {
1434 mutex_unlock(&vout->lock);
1435 ret = -EINVAL;
1436 break;
1437 }
1438
1439 ovl->manager->get_manager_info(ovl->manager, &info);
1440 info.default_color = color;
1441 if (ovl->manager->set_manager_info(ovl->manager, &info)) {
1442 mutex_unlock(&vout->lock);
1443 ret = -EINVAL;
1444 break;
1445 }
1446
1447 vout->control[1].value = color;
1448 mutex_unlock(&vout->lock);
1449 break;
1450 }
1451 case V4L2_CID_VFLIP:
1452 {
1453 struct omapvideo_info *ovid;
1454 unsigned int mirror = a->value;
1455
1456 ovid = &vout->vid_info;
1457
1458 mutex_lock(&vout->lock);
1459 if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
1460 mutex_unlock(&vout->lock);
1461 ret = -ERANGE;
1462 break;
1463 }
1464
1465 if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
1466 mutex_unlock(&vout->lock);
1467 ret = -EINVAL;
1468 break;
1469 }
1470 vout->mirror = mirror;
1471 vout->control[2].value = mirror;
1472 mutex_unlock(&vout->lock);
1473 break;
1474 }
1475 default:
1476 ret = -EINVAL;
1477 }
1478 return ret;
1479}
1480
1481static int vidioc_reqbufs(struct file *file, void *fh,
1482 struct v4l2_requestbuffers *req)
1483{
1484 int ret = 0;
1485 unsigned int i, num_buffers = 0;
1486 struct omap_vout_device *vout = fh;
1487 struct videobuf_queue *q = &vout->vbq;
1488
1489 if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1490 return -EINVAL;
1491
1492
1493 if ((V4L2_MEMORY_MMAP != req->memory) &&
1494 (V4L2_MEMORY_USERPTR != req->memory))
1495 return -EINVAL;
1496
1497 mutex_lock(&vout->lock);
1498
1499 if (vout->streaming) {
1500 ret = -EBUSY;
1501 goto reqbuf_err;
1502 }
1503
1504
1505 if (q->bufs[0] && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) {
1506 if (vout->mmap_count) {
1507 ret = -EBUSY;
1508 goto reqbuf_err;
1509 }
1510 num_buffers = (vout->vid == OMAP_VIDEO1) ?
1511 video1_numbuffers : video2_numbuffers;
1512 for (i = num_buffers; i < vout->buffer_allocated; i++) {
1513 omap_vout_free_buffer(vout->buf_virt_addr[i],
1514 vout->buffer_size);
1515 vout->buf_virt_addr[i] = 0;
1516 vout->buf_phy_addr[i] = 0;
1517 }
1518 vout->buffer_allocated = num_buffers;
1519 videobuf_mmap_free(q);
1520 } else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) {
1521 if (vout->buffer_allocated) {
1522 videobuf_mmap_free(q);
1523 for (i = 0; i < vout->buffer_allocated; i++) {
1524 kfree(q->bufs[i]);
1525 q->bufs[i] = NULL;
1526 }
1527 vout->buffer_allocated = 0;
1528 }
1529 }
1530
1531
1532 vout->memory = req->memory;
1533
1534 INIT_LIST_HEAD(&vout->dma_queue);
1535
1536
1537 ret = videobuf_reqbufs(q, req);
1538 if (ret < 0)
1539 goto reqbuf_err;
1540
1541 vout->buffer_allocated = req->count;
1542
1543reqbuf_err:
1544 mutex_unlock(&vout->lock);
1545 return ret;
1546}
1547
1548static int vidioc_querybuf(struct file *file, void *fh,
1549 struct v4l2_buffer *b)
1550{
1551 struct omap_vout_device *vout = fh;
1552
1553 return videobuf_querybuf(&vout->vbq, b);
1554}
1555
1556static int vidioc_qbuf(struct file *file, void *fh,
1557 struct v4l2_buffer *buffer)
1558{
1559 struct omap_vout_device *vout = fh;
1560 struct videobuf_queue *q = &vout->vbq;
1561
1562 if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) ||
1563 (buffer->index >= vout->buffer_allocated) ||
1564 (q->bufs[buffer->index]->memory != buffer->memory)) {
1565 return -EINVAL;
1566 }
1567 if (V4L2_MEMORY_USERPTR == buffer->memory) {
1568 if ((buffer->length < vout->pix.sizeimage) ||
1569 (0 == buffer->m.userptr)) {
1570 return -EINVAL;
1571 }
1572 }
1573
1574 if ((is_rotation_enabled(vout)) &&
1575 vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) {
1576 v4l2_warn(&vout->vid_dev->v4l2_dev,
1577 "DMA Channel not allocated for Rotation\n");
1578 return -EINVAL;
1579 }
1580
1581 return videobuf_qbuf(q, buffer);
1582}
1583
1584static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
1585{
1586 struct omap_vout_device *vout = fh;
1587 struct videobuf_queue *q = &vout->vbq;
1588
1589 int ret;
1590 u32 addr;
1591 unsigned long size;
1592 struct videobuf_buffer *vb;
1593
1594 vb = q->bufs[b->index];
1595
1596 if (!vout->streaming)
1597 return -EINVAL;
1598
1599 if (file->f_flags & O_NONBLOCK)
1600
1601 ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
1602 else
1603
1604 ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
1605
1606 addr = (unsigned long) vout->buf_phy_addr[vb->i];
1607 size = (unsigned long) vb->size;
1608 dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr,
1609 size, DMA_TO_DEVICE);
1610 return ret;
1611}
1612
1613static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
1614{
1615 int ret = 0, j;
1616 u32 addr = 0, mask = 0;
1617 struct omap_vout_device *vout = fh;
1618 struct videobuf_queue *q = &vout->vbq;
1619 struct omapvideo_info *ovid = &vout->vid_info;
1620
1621 mutex_lock(&vout->lock);
1622
1623 if (vout->streaming) {
1624 ret = -EBUSY;
1625 goto streamon_err;
1626 }
1627
1628 ret = videobuf_streamon(q);
1629 if (ret)
1630 goto streamon_err;
1631
1632 if (list_empty(&vout->dma_queue)) {
1633 ret = -EIO;
1634 goto streamon_err1;
1635 }
1636
1637
1638 vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next,
1639 struct videobuf_buffer, queue);
1640
1641 list_del(&vout->cur_frm->queue);
1642
1643 vout->cur_frm->state = VIDEOBUF_ACTIVE;
1644
1645 vout->field_id = 0;
1646
1647
1648 vout->streaming = true;
1649
1650 vout->first_int = 1;
1651
1652 if (omap_vout_calculate_offset(vout)) {
1653 ret = -EINVAL;
1654 goto streamon_err1;
1655 }
1656 addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
1657 + vout->cropped_offset;
1658
1659 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
1660 | DISPC_IRQ_VSYNC2;
1661
1662
1663 ret = omapvid_init(vout, addr);
1664 if (ret) {
1665 v4l2_err(&vout->vid_dev->v4l2_dev,
1666 "failed to set overlay info\n");
1667 goto streamon_err1;
1668 }
1669
1670 omap_dispc_register_isr(omap_vout_isr, vout, mask);
1671
1672
1673 ret = omapvid_apply_changes(vout);
1674 if (ret)
1675 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
1676
1677 for (j = 0; j < ovid->num_overlays; j++) {
1678 struct omap_overlay *ovl = ovid->overlays[j];
1679 struct omap_dss_device *dssdev = ovl->get_device(ovl);
1680
1681 if (dssdev) {
1682 ret = ovl->enable(ovl);
1683 if (ret)
1684 goto streamon_err1;
1685 }
1686 }
1687
1688 ret = 0;
1689
1690streamon_err1:
1691 if (ret)
1692 ret = videobuf_streamoff(q);
1693streamon_err:
1694 mutex_unlock(&vout->lock);
1695 return ret;
1696}
1697
1698static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
1699{
1700 u32 mask = 0;
1701 int ret = 0, j;
1702 struct omap_vout_device *vout = fh;
1703 struct omapvideo_info *ovid = &vout->vid_info;
1704
1705 if (!vout->streaming)
1706 return -EINVAL;
1707
1708 vout->streaming = false;
1709 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
1710 | DISPC_IRQ_VSYNC2;
1711
1712 omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
1713
1714 for (j = 0; j < ovid->num_overlays; j++) {
1715 struct omap_overlay *ovl = ovid->overlays[j];
1716 struct omap_dss_device *dssdev = ovl->get_device(ovl);
1717
1718 if (dssdev)
1719 ovl->disable(ovl);
1720 }
1721
1722
1723 ret = omapvid_apply_changes(vout);
1724 if (ret)
1725 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode in"
1726 " streamoff\n");
1727
1728 INIT_LIST_HEAD(&vout->dma_queue);
1729 ret = videobuf_streamoff(&vout->vbq);
1730
1731 return ret;
1732}
1733
1734static int vidioc_s_fbuf(struct file *file, void *fh,
1735 const struct v4l2_framebuffer *a)
1736{
1737 int enable = 0;
1738 struct omap_overlay *ovl;
1739 struct omapvideo_info *ovid;
1740 struct omap_vout_device *vout = fh;
1741 struct omap_overlay_manager_info info;
1742 enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
1743
1744 ovid = &vout->vid_info;
1745 ovl = ovid->overlays[0];
1746
1747
1748
1749 if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
1750 (a->flags & V4L2_FBUF_FLAG_CHROMAKEY))
1751 return -EINVAL;
1752
1753
1754 if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) &&
1755 (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA))
1756 return -EINVAL;
1757
1758 if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) {
1759 vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
1760 key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
1761 } else
1762 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY;
1763
1764 if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) {
1765 vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
1766 key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
1767 } else
1768 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY;
1769
1770 if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY |
1771 V4L2_FBUF_FLAG_SRC_CHROMAKEY))
1772 enable = 1;
1773 else
1774 enable = 0;
1775 if (ovl->manager && ovl->manager->get_manager_info &&
1776 ovl->manager->set_manager_info) {
1777
1778 ovl->manager->get_manager_info(ovl->manager, &info);
1779 info.trans_enabled = enable;
1780 info.trans_key_type = key_type;
1781 info.trans_key = vout->win.chromakey;
1782
1783 if (ovl->manager->set_manager_info(ovl->manager, &info))
1784 return -EINVAL;
1785 }
1786 if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) {
1787 vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1788 enable = 1;
1789 } else {
1790 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
1791 enable = 0;
1792 }
1793 if (ovl->manager && ovl->manager->get_manager_info &&
1794 ovl->manager->set_manager_info) {
1795 ovl->manager->get_manager_info(ovl->manager, &info);
1796
1797 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
1798 info.partial_alpha_enabled = enable;
1799 if (ovl->manager->set_manager_info(ovl->manager, &info))
1800 return -EINVAL;
1801 }
1802
1803 return 0;
1804}
1805
1806static int vidioc_g_fbuf(struct file *file, void *fh,
1807 struct v4l2_framebuffer *a)
1808{
1809 struct omap_overlay *ovl;
1810 struct omapvideo_info *ovid;
1811 struct omap_vout_device *vout = fh;
1812 struct omap_overlay_manager_info info;
1813
1814 ovid = &vout->vid_info;
1815 ovl = ovid->overlays[0];
1816
1817
1818
1819 a->flags = V4L2_FBUF_FLAG_OVERLAY;
1820 a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
1821 | V4L2_FBUF_CAP_SRC_CHROMAKEY;
1822
1823 if (ovl->manager && ovl->manager->get_manager_info) {
1824 ovl->manager->get_manager_info(ovl->manager, &info);
1825 if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC)
1826 a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
1827 if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
1828 a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
1829 }
1830 if (ovl->manager && ovl->manager->get_manager_info) {
1831 ovl->manager->get_manager_info(ovl->manager, &info);
1832 if (info.partial_alpha_enabled)
1833 a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1834 }
1835
1836 return 0;
1837}
1838
1839static const struct v4l2_ioctl_ops vout_ioctl_ops = {
1840 .vidioc_querycap = vidioc_querycap,
1841 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
1842 .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
1843 .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
1844 .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
1845 .vidioc_queryctrl = vidioc_queryctrl,
1846 .vidioc_g_ctrl = vidioc_g_ctrl,
1847 .vidioc_s_fbuf = vidioc_s_fbuf,
1848 .vidioc_g_fbuf = vidioc_g_fbuf,
1849 .vidioc_s_ctrl = vidioc_s_ctrl,
1850 .vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_overlay,
1851 .vidioc_s_fmt_vid_out_overlay = vidioc_s_fmt_vid_overlay,
1852 .vidioc_g_fmt_vid_out_overlay = vidioc_g_fmt_vid_overlay,
1853 .vidioc_cropcap = vidioc_cropcap,
1854 .vidioc_g_crop = vidioc_g_crop,
1855 .vidioc_s_crop = vidioc_s_crop,
1856 .vidioc_reqbufs = vidioc_reqbufs,
1857 .vidioc_querybuf = vidioc_querybuf,
1858 .vidioc_qbuf = vidioc_qbuf,
1859 .vidioc_dqbuf = vidioc_dqbuf,
1860 .vidioc_streamon = vidioc_streamon,
1861 .vidioc_streamoff = vidioc_streamoff,
1862};
1863
1864static const struct v4l2_file_operations omap_vout_fops = {
1865 .owner = THIS_MODULE,
1866 .poll = omap_vout_poll,
1867 .unlocked_ioctl = video_ioctl2,
1868 .mmap = omap_vout_mmap,
1869 .open = omap_vout_open,
1870 .release = omap_vout_release,
1871};
1872
1873
1874
1875static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
1876{
1877 struct video_device *vfd;
1878 struct v4l2_pix_format *pix;
1879 struct v4l2_control *control;
1880 struct omap_overlay *ovl = vout->vid_info.overlays[0];
1881 struct omap_dss_device *display = ovl->get_device(ovl);
1882
1883
1884 pix = &vout->pix;
1885
1886
1887 pix->width = QQVGA_WIDTH;
1888 pix->height = QQVGA_HEIGHT;
1889
1890
1891 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1892 pix->field = V4L2_FIELD_ANY;
1893 pix->bytesperline = pix->width * 2;
1894 pix->sizeimage = pix->bytesperline * pix->height;
1895 pix->colorspace = V4L2_COLORSPACE_JPEG;
1896
1897 vout->bpp = RGB565_BPP;
1898 vout->fbuf.fmt.width = display->panel.timings.x_res;
1899 vout->fbuf.fmt.height = display->panel.timings.y_res;
1900
1901
1902 vout->win.global_alpha = 255;
1903 vout->fbuf.flags = 0;
1904 vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
1905 V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY;
1906 vout->win.chromakey = 0;
1907
1908 omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
1909
1910
1911
1912 control = vout->control;
1913 control[0].id = V4L2_CID_ROTATE;
1914 control[0].value = 0;
1915 vout->rotation = 0;
1916 vout->mirror = false;
1917 vout->control[2].id = V4L2_CID_HFLIP;
1918 vout->control[2].value = 0;
1919 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
1920 vout->vrfb_bpp = 2;
1921
1922 control[1].id = V4L2_CID_BG_COLOR;
1923 control[1].value = 0;
1924
1925
1926 vfd = vout->vfd = video_device_alloc();
1927
1928 if (!vfd) {
1929 printk(KERN_ERR VOUT_NAME ": could not allocate"
1930 " video device struct\n");
1931 return -ENOMEM;
1932 }
1933 vfd->release = video_device_release;
1934 vfd->ioctl_ops = &vout_ioctl_ops;
1935
1936 strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
1937
1938 vfd->fops = &omap_vout_fops;
1939 vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
1940 vfd->vfl_dir = VFL_DIR_TX;
1941 mutex_init(&vout->lock);
1942
1943 vfd->minor = -1;
1944 return 0;
1945
1946}
1947
1948
1949static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
1950 int vid_num)
1951{
1952 u32 numbuffers;
1953 int ret = 0, i;
1954 struct omapvideo_info *ovid;
1955 struct omap_vout_device *vout;
1956 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
1957 struct omap2video_device *vid_dev =
1958 container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
1959
1960 vout = vid_dev->vouts[vid_num];
1961 ovid = &vout->vid_info;
1962
1963 numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers;
1964 vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize;
1965 dev_info(&pdev->dev, "Buffer Size = %d\n", vout->buffer_size);
1966
1967 for (i = 0; i < numbuffers; i++) {
1968 vout->buf_virt_addr[i] =
1969 omap_vout_alloc_buffer(vout->buffer_size,
1970 (u32 *) &vout->buf_phy_addr[i]);
1971 if (!vout->buf_virt_addr[i]) {
1972 numbuffers = i;
1973 ret = -ENOMEM;
1974 goto free_buffers;
1975 }
1976 }
1977
1978 vout->cropped_offset = 0;
1979
1980 if (ovid->rotation_type == VOUT_ROT_VRFB) {
1981 int static_vrfb_allocation = (vid_num == 0) ?
1982 vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
1983 ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
1984 static_vrfb_allocation);
1985 }
1986
1987 return ret;
1988
1989free_buffers:
1990 for (i = 0; i < numbuffers; i++) {
1991 omap_vout_free_buffer(vout->buf_virt_addr[i],
1992 vout->buffer_size);
1993 vout->buf_virt_addr[i] = 0;
1994 vout->buf_phy_addr[i] = 0;
1995 }
1996 return ret;
1997
1998}
1999
2000
2001static int __init omap_vout_create_video_devices(struct platform_device *pdev)
2002{
2003 int ret = 0, k;
2004 struct omap_vout_device *vout;
2005 struct video_device *vfd = NULL;
2006 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
2007 struct omap2video_device *vid_dev = container_of(v4l2_dev,
2008 struct omap2video_device, v4l2_dev);
2009
2010 for (k = 0; k < pdev->num_resources; k++) {
2011
2012 vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
2013 if (!vout) {
2014 dev_err(&pdev->dev, ": could not allocate memory\n");
2015 return -ENOMEM;
2016 }
2017
2018 vout->vid = k;
2019 vid_dev->vouts[k] = vout;
2020 vout->vid_dev = vid_dev;
2021
2022 if (pdev->num_resources == 1)
2023 vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
2024 else
2025
2026 vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
2027 vout->vid_info.num_overlays = 1;
2028 vout->vid_info.id = k + 1;
2029
2030
2031 if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
2032 vout->vid_info.rotation_type = VOUT_ROT_VRFB;
2033
2034
2035
2036 if (omap_vout_setup_video_data(vout) != 0) {
2037 ret = -ENOMEM;
2038 goto error;
2039 }
2040
2041
2042
2043
2044 if (omap_vout_setup_video_bufs(pdev, k) != 0) {
2045 ret = -ENOMEM;
2046 goto error1;
2047 }
2048
2049
2050
2051 vfd = vout->vfd;
2052 if (video_register_device(vfd, VFL_TYPE_GRABBER, -1) < 0) {
2053 dev_err(&pdev->dev, ": Could not register "
2054 "Video for Linux device\n");
2055 vfd->minor = -1;
2056 ret = -ENODEV;
2057 goto error2;
2058 }
2059 video_set_drvdata(vfd, vout);
2060
2061 dev_info(&pdev->dev, ": registered and initialized"
2062 " video device %d\n", vfd->minor);
2063 if (k == (pdev->num_resources - 1))
2064 return 0;
2065
2066 continue;
2067error2:
2068 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
2069 omap_vout_release_vrfb(vout);
2070 omap_vout_free_buffers(vout);
2071error1:
2072 video_device_release(vfd);
2073error:
2074 kfree(vout);
2075 return ret;
2076 }
2077
2078 return -ENODEV;
2079}
2080
2081static void omap_vout_cleanup_device(struct omap_vout_device *vout)
2082{
2083 struct video_device *vfd;
2084 struct omapvideo_info *ovid;
2085
2086 if (!vout)
2087 return;
2088
2089 vfd = vout->vfd;
2090 ovid = &vout->vid_info;
2091 if (vfd) {
2092 if (!video_is_registered(vfd)) {
2093
2094
2095
2096
2097 video_device_release(vfd);
2098 } else {
2099
2100
2101
2102
2103 video_unregister_device(vfd);
2104 }
2105 }
2106 if (ovid->rotation_type == VOUT_ROT_VRFB) {
2107 omap_vout_release_vrfb(vout);
2108
2109
2110
2111 if (vout->vrfb_static_allocation)
2112 omap_vout_free_vrfb_buffers(vout);
2113 }
2114 omap_vout_free_buffers(vout);
2115
2116 kfree(vout);
2117}
2118
2119static int omap_vout_remove(struct platform_device *pdev)
2120{
2121 int k;
2122 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
2123 struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
2124 omap2video_device, v4l2_dev);
2125
2126 v4l2_device_unregister(v4l2_dev);
2127 for (k = 0; k < pdev->num_resources; k++)
2128 omap_vout_cleanup_device(vid_dev->vouts[k]);
2129
2130 for (k = 0; k < vid_dev->num_displays; k++) {
2131 if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
2132 vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);
2133
2134 omap_dss_put_device(vid_dev->displays[k]);
2135 }
2136 kfree(vid_dev);
2137 return 0;
2138}
2139
2140static int __init omap_vout_probe(struct platform_device *pdev)
2141{
2142 int ret = 0, i;
2143 struct omap_overlay *ovl;
2144 struct omap_dss_device *dssdev = NULL;
2145 struct omap_dss_device *def_display;
2146 struct omap2video_device *vid_dev = NULL;
2147
2148 if (omapdss_is_initialized() == false)
2149 return -EPROBE_DEFER;
2150
2151 ret = omapdss_compat_init();
2152 if (ret) {
2153 dev_err(&pdev->dev, "failed to init dss\n");
2154 return ret;
2155 }
2156
2157 if (pdev->num_resources == 0) {
2158 dev_err(&pdev->dev, "probed for an unknown device\n");
2159 ret = -ENODEV;
2160 goto err_dss_init;
2161 }
2162
2163 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
2164 if (vid_dev == NULL) {
2165 ret = -ENOMEM;
2166 goto err_dss_init;
2167 }
2168
2169 vid_dev->num_displays = 0;
2170 for_each_dss_dev(dssdev) {
2171 omap_dss_get_device(dssdev);
2172
2173 if (!dssdev->driver) {
2174 dev_warn(&pdev->dev, "no driver for display: %s\n",
2175 dssdev->name);
2176 omap_dss_put_device(dssdev);
2177 continue;
2178 }
2179
2180 vid_dev->displays[vid_dev->num_displays++] = dssdev;
2181 }
2182
2183 if (vid_dev->num_displays == 0) {
2184 dev_err(&pdev->dev, "no displays\n");
2185 ret = -EINVAL;
2186 goto probe_err0;
2187 }
2188
2189 vid_dev->num_overlays = omap_dss_get_num_overlays();
2190 for (i = 0; i < vid_dev->num_overlays; i++)
2191 vid_dev->overlays[i] = omap_dss_get_overlay(i);
2192
2193 vid_dev->num_managers = omap_dss_get_num_overlay_managers();
2194 for (i = 0; i < vid_dev->num_managers; i++)
2195 vid_dev->managers[i] = omap_dss_get_overlay_manager(i);
2196
2197
2198
2199
2200 for (i = 1; i < vid_dev->num_overlays; i++) {
2201 ovl = omap_dss_get_overlay(i);
2202 dssdev = ovl->get_device(ovl);
2203
2204 if (dssdev) {
2205 def_display = dssdev;
2206 } else {
2207 dev_warn(&pdev->dev, "cannot find display\n");
2208 def_display = NULL;
2209 }
2210 if (def_display) {
2211 struct omap_dss_driver *dssdrv = def_display->driver;
2212
2213 ret = dssdrv->enable(def_display);
2214 if (ret) {
2215
2216
2217
2218
2219 dev_warn(&pdev->dev,
2220 "'%s' Display already enabled\n",
2221 def_display->name);
2222 }
2223 }
2224 }
2225
2226 if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) {
2227 dev_err(&pdev->dev, "v4l2_device_register failed\n");
2228 ret = -ENODEV;
2229 goto probe_err1;
2230 }
2231
2232 ret = omap_vout_create_video_devices(pdev);
2233 if (ret)
2234 goto probe_err2;
2235
2236 for (i = 0; i < vid_dev->num_displays; i++) {
2237 struct omap_dss_device *display = vid_dev->displays[i];
2238
2239 if (display->driver->update)
2240 display->driver->update(display, 0, 0,
2241 display->panel.timings.x_res,
2242 display->panel.timings.y_res);
2243 }
2244 return 0;
2245
2246probe_err2:
2247 v4l2_device_unregister(&vid_dev->v4l2_dev);
2248probe_err1:
2249 for (i = 1; i < vid_dev->num_overlays; i++) {
2250 def_display = NULL;
2251 ovl = omap_dss_get_overlay(i);
2252 dssdev = ovl->get_device(ovl);
2253
2254 if (dssdev)
2255 def_display = dssdev;
2256
2257 if (def_display && def_display->driver)
2258 def_display->driver->disable(def_display);
2259 }
2260probe_err0:
2261 kfree(vid_dev);
2262err_dss_init:
2263 omapdss_compat_uninit();
2264 return ret;
2265}
2266
2267static struct platform_driver omap_vout_driver = {
2268 .driver = {
2269 .name = VOUT_NAME,
2270 },
2271 .remove = omap_vout_remove,
2272};
2273
2274static int __init omap_vout_init(void)
2275{
2276 if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) {
2277 printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n");
2278 return -EINVAL;
2279 }
2280 return 0;
2281}
2282
2283static void omap_vout_cleanup(void)
2284{
2285 platform_driver_unregister(&omap_vout_driver);
2286}
2287
2288late_initcall(omap_vout_init);
2289module_exit(omap_vout_cleanup);
2290