4 * Copyright (C) 2005-2010 Texas Instruments.
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
10 * Leveraged code from the OMAP2 camera driver
11 * Video-for-Linux (Version 2) camera capture driver for
12 * the OMAP24xx camera controller.
14 * Author: Andy Lowe (source@mvista.com)
16 * Copyright (C) 2004 MontaVista Software, Inc.
17 * Copyright (C) 2010 Texas Instruments.
20 * 20-APR-2006 Khasim Modified VRFB based Rotation,
21 * The image data is always read from 0 degree
23 * to the virtual space of desired rotation angle
24 * 4-DEC-2006 Jian Changed to support better memory management
26 * 17-Nov-2008 Hardik Changed driver to use video_ioctl2
28 * 23-Feb-2010 Vaibhav H Modified to use new DSS2 interface
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>
43 #include <media/v4l2-device.h>
44 #include <media/v4l2-ioctl.h>
45 #include <media/v4l2-event.h>
47 #include <video/omapvrfb.h>
48 #include <video/omapfb_dss.h>
50 #include "omap_voutlib.h"
51 #include "omap_voutdef.h"
52 #include "omap_vout_vrfb.h"
54 MODULE_AUTHOR("Texas Instruments");
55 MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
56 MODULE_LICENSE("GPL");
58 /* Driver Configuration macros */
59 #define VOUT_NAME "omap_vout"
61 enum omap_vout_channels
{
66 /* Variables configurable through module params*/
67 static bool vid1_static_vrfb_alloc
;
68 static bool vid2_static_vrfb_alloc
;
71 /* Module parameters */
72 module_param(vid1_static_vrfb_alloc
, bool, S_IRUGO
);
73 MODULE_PARM_DESC(vid1_static_vrfb_alloc
,
74 "Static allocation of the VRFB buffer for video1 device");
76 module_param(vid2_static_vrfb_alloc
, bool, S_IRUGO
);
77 MODULE_PARM_DESC(vid2_static_vrfb_alloc
,
78 "Static allocation of the VRFB buffer for video2 device");
80 module_param(debug
, bool, S_IRUGO
);
81 MODULE_PARM_DESC(debug
, "Debug level (0-1)");
83 /* list of image formats supported by OMAP2 video pipelines */
84 static const struct v4l2_fmtdesc omap_formats
[] = {
86 /* Note: V4L2 defines RGB565 as:
89 * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3
91 * We interpret RGB565 as:
94 * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3
96 .pixelformat
= V4L2_PIX_FMT_RGB565
,
99 /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use
100 * this for RGB24 unpack mode, the last 8 bits are ignored
102 .pixelformat
= V4L2_PIX_FMT_RGB32
,
105 /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use
106 * this for RGB24 packed mode
109 .pixelformat
= V4L2_PIX_FMT_RGB24
,
112 .pixelformat
= V4L2_PIX_FMT_YUYV
,
115 .pixelformat
= V4L2_PIX_FMT_UYVY
,
119 #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
124 static int omap_vout_try_format(struct v4l2_pix_format
*pix
)
128 pix
->height
= clamp(pix
->height
, (u32
)VID_MIN_HEIGHT
,
129 (u32
)VID_MAX_HEIGHT
);
130 pix
->width
= clamp(pix
->width
, (u32
)VID_MIN_WIDTH
, (u32
)VID_MAX_WIDTH
);
132 for (ifmt
= 0; ifmt
< NUM_OUTPUT_FORMATS
; ifmt
++) {
133 if (pix
->pixelformat
== omap_formats
[ifmt
].pixelformat
)
137 if (ifmt
== NUM_OUTPUT_FORMATS
)
140 pix
->pixelformat
= omap_formats
[ifmt
].pixelformat
;
141 pix
->field
= V4L2_FIELD_NONE
;
143 switch (pix
->pixelformat
) {
144 case V4L2_PIX_FMT_YUYV
:
145 case V4L2_PIX_FMT_UYVY
:
147 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
150 case V4L2_PIX_FMT_RGB565
:
151 case V4L2_PIX_FMT_RGB565X
:
152 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
155 case V4L2_PIX_FMT_RGB24
:
156 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
159 case V4L2_PIX_FMT_RGB32
:
160 case V4L2_PIX_FMT_BGR32
:
161 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
165 pix
->bytesperline
= pix
->width
* bpp
;
166 pix
->sizeimage
= pix
->bytesperline
* pix
->height
;
172 * Convert V4L2 rotation to DSS rotation
173 * V4L2 understand 0, 90, 180, 270.
174 * Convert to 0, 1, 2 and 3 respectively for DSS
176 static int v4l2_rot_to_dss_rot(int v4l2_rotation
,
177 enum dss_rotation
*rotation
, bool mirror
)
181 switch (v4l2_rotation
) {
183 *rotation
= dss_rotation_90_degree
;
186 *rotation
= dss_rotation_180_degree
;
189 *rotation
= dss_rotation_270_degree
;
192 *rotation
= dss_rotation_0_degree
;
200 static int omap_vout_calculate_offset(struct omap_vout_device
*vout
)
202 struct omapvideo_info
*ovid
;
203 struct v4l2_rect
*crop
= &vout
->crop
;
204 struct v4l2_pix_format
*pix
= &vout
->pix
;
205 int *cropped_offset
= &vout
->cropped_offset
;
206 int ps
= 2, line_length
= 0;
208 ovid
= &vout
->vid_info
;
210 if (ovid
->rotation_type
== VOUT_ROT_VRFB
) {
211 omap_vout_calculate_vrfb_offset(vout
);
213 vout
->line_length
= line_length
= pix
->width
;
215 if (V4L2_PIX_FMT_YUYV
== pix
->pixelformat
||
216 V4L2_PIX_FMT_UYVY
== pix
->pixelformat
)
218 else if (V4L2_PIX_FMT_RGB32
== pix
->pixelformat
)
220 else if (V4L2_PIX_FMT_RGB24
== pix
->pixelformat
)
225 *cropped_offset
= (line_length
* ps
) *
226 crop
->top
+ crop
->left
* ps
;
229 v4l2_dbg(1, debug
, &vout
->vid_dev
->v4l2_dev
, "%s Offset:%x\n",
230 __func__
, vout
->cropped_offset
);
236 * Convert V4L2 pixel format to DSS pixel format
238 static int video_mode_to_dss_mode(struct omap_vout_device
*vout
)
240 struct omap_overlay
*ovl
;
241 struct omapvideo_info
*ovid
;
242 struct v4l2_pix_format
*pix
= &vout
->pix
;
243 enum omap_color_mode mode
;
245 ovid
= &vout
->vid_info
;
246 ovl
= ovid
->overlays
[0];
248 switch (pix
->pixelformat
) {
249 case V4L2_PIX_FMT_YUYV
:
250 mode
= OMAP_DSS_COLOR_YUV2
;
252 case V4L2_PIX_FMT_UYVY
:
253 mode
= OMAP_DSS_COLOR_UYVY
;
255 case V4L2_PIX_FMT_RGB565
:
256 mode
= OMAP_DSS_COLOR_RGB16
;
258 case V4L2_PIX_FMT_RGB24
:
259 mode
= OMAP_DSS_COLOR_RGB24P
;
261 case V4L2_PIX_FMT_RGB32
:
262 mode
= (ovl
->id
== OMAP_DSS_VIDEO1
) ?
263 OMAP_DSS_COLOR_RGB24U
: OMAP_DSS_COLOR_ARGB32
;
265 case V4L2_PIX_FMT_BGR32
:
266 mode
= OMAP_DSS_COLOR_RGBX32
;
278 static int omapvid_setup_overlay(struct omap_vout_device
*vout
,
279 struct omap_overlay
*ovl
, int posx
, int posy
, int outw
,
283 struct omap_overlay_info info
;
284 int cropheight
, cropwidth
, pixwidth
;
286 if ((ovl
->caps
& OMAP_DSS_OVL_CAP_SCALE
) == 0 &&
287 (outw
!= vout
->pix
.width
|| outh
!= vout
->pix
.height
)) {
292 vout
->dss_mode
= video_mode_to_dss_mode(vout
);
293 if (vout
->dss_mode
== -EINVAL
) {
298 /* Setup the input plane parameters according to
299 * rotation value selected.
301 if (is_rotation_90_or_270(vout
)) {
302 cropheight
= vout
->crop
.width
;
303 cropwidth
= vout
->crop
.height
;
304 pixwidth
= vout
->pix
.height
;
306 cropheight
= vout
->crop
.height
;
307 cropwidth
= vout
->crop
.width
;
308 pixwidth
= vout
->pix
.width
;
311 ovl
->get_overlay_info(ovl
, &info
);
313 info
.width
= cropwidth
;
314 info
.height
= cropheight
;
315 info
.color_mode
= vout
->dss_mode
;
316 info
.mirror
= vout
->mirror
;
319 info
.out_width
= outw
;
320 info
.out_height
= outh
;
321 info
.global_alpha
= vout
->win
.global_alpha
;
322 if (!is_rotation_enabled(vout
)) {
324 info
.rotation_type
= OMAP_DSS_ROT_DMA
;
325 info
.screen_width
= pixwidth
;
327 info
.rotation
= vout
->rotation
;
328 info
.rotation_type
= OMAP_DSS_ROT_VRFB
;
329 info
.screen_width
= 2048;
332 v4l2_dbg(1, debug
, &vout
->vid_dev
->v4l2_dev
,
333 "%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
334 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
335 "out_height=%d rotation_type=%d screen_width=%d\n", __func__
,
336 ovl
->is_enabled(ovl
), &info
.paddr
, info
.width
, info
.height
,
337 info
.color_mode
, info
.rotation
, info
.mirror
, info
.pos_x
,
338 info
.pos_y
, info
.out_width
, info
.out_height
, info
.rotation_type
,
341 ret
= ovl
->set_overlay_info(ovl
, &info
);
348 v4l2_warn(&vout
->vid_dev
->v4l2_dev
, "setup_overlay failed\n");
353 * Initialize the overlay structure
355 static int omapvid_init(struct omap_vout_device
*vout
, u32 addr
)
358 struct v4l2_window
*win
;
359 struct omap_overlay
*ovl
;
360 int posx
, posy
, outw
, outh
;
361 struct omap_video_timings
*timing
;
362 struct omapvideo_info
*ovid
= &vout
->vid_info
;
365 for (i
= 0; i
< ovid
->num_overlays
; i
++) {
366 struct omap_dss_device
*dssdev
;
368 ovl
= ovid
->overlays
[i
];
369 dssdev
= ovl
->get_device(ovl
);
374 timing
= &dssdev
->panel
.timings
;
377 outh
= win
->w
.height
;
378 switch (vout
->rotation
) {
379 case dss_rotation_90_degree
:
380 /* Invert the height and width for 90
381 * and 270 degree rotation
384 posy
= (timing
->y_res
- win
->w
.width
) - win
->w
.left
;
388 case dss_rotation_180_degree
:
389 posx
= (timing
->x_res
- win
->w
.width
) - win
->w
.left
;
390 posy
= (timing
->y_res
- win
->w
.height
) - win
->w
.top
;
393 case dss_rotation_270_degree
:
396 posx
= (timing
->x_res
- win
->w
.height
) - win
->w
.top
;
405 ret
= omapvid_setup_overlay(vout
, ovl
, posx
, posy
,
408 goto omapvid_init_err
;
413 v4l2_warn(&vout
->vid_dev
->v4l2_dev
, "apply_changes failed\n");
418 * Apply the changes set the go bit of DSS
420 static int omapvid_apply_changes(struct omap_vout_device
*vout
)
423 struct omap_overlay
*ovl
;
424 struct omapvideo_info
*ovid
= &vout
->vid_info
;
426 for (i
= 0; i
< ovid
->num_overlays
; i
++) {
427 struct omap_dss_device
*dssdev
;
429 ovl
= ovid
->overlays
[i
];
430 dssdev
= ovl
->get_device(ovl
);
433 ovl
->manager
->apply(ovl
->manager
);
439 static int omapvid_handle_interlace_display(struct omap_vout_device
*vout
,
440 unsigned int irqstatus
, u64 ts
)
444 if (vout
->first_int
) {
449 if (irqstatus
& DISPC_IRQ_EVSYNC_ODD
)
451 else if (irqstatus
& DISPC_IRQ_EVSYNC_EVEN
)
457 if (fid
!= vout
->field_id
) {
459 vout
->field_id
= fid
;
460 } else if (0 == fid
) {
461 if (vout
->cur_frm
== vout
->next_frm
)
464 vout
->cur_frm
->vbuf
.vb2_buf
.timestamp
= ts
;
465 vout
->cur_frm
->vbuf
.sequence
= vout
->sequence
++;
466 vb2_buffer_done(&vout
->cur_frm
->vbuf
.vb2_buf
, VB2_BUF_STATE_DONE
);
467 vout
->cur_frm
= vout
->next_frm
;
469 if (list_empty(&vout
->dma_queue
) ||
470 (vout
->cur_frm
!= vout
->next_frm
))
474 return vout
->field_id
;
479 static void omap_vout_isr(void *arg
, unsigned int irqstatus
)
481 int ret
, fid
, mgr_id
;
483 struct omap_overlay
*ovl
;
485 struct omapvideo_info
*ovid
;
486 struct omap_dss_device
*cur_display
;
487 struct omap_vout_device
*vout
= (struct omap_vout_device
*)arg
;
489 ovid
= &vout
->vid_info
;
490 ovl
= ovid
->overlays
[0];
492 mgr_id
= ovl
->manager
->id
;
494 /* get the display device attached to the overlay */
495 cur_display
= ovl
->get_device(ovl
);
500 spin_lock(&vout
->vbq_lock
);
503 switch (cur_display
->type
) {
504 case OMAP_DISPLAY_TYPE_DSI
:
505 case OMAP_DISPLAY_TYPE_DPI
:
506 case OMAP_DISPLAY_TYPE_DVI
:
507 if (mgr_id
== OMAP_DSS_CHANNEL_LCD
)
508 irq
= DISPC_IRQ_VSYNC
;
509 else if (mgr_id
== OMAP_DSS_CHANNEL_LCD2
)
510 irq
= DISPC_IRQ_VSYNC2
;
514 if (!(irqstatus
& irq
))
517 case OMAP_DISPLAY_TYPE_VENC
:
518 fid
= omapvid_handle_interlace_display(vout
, irqstatus
,
523 case OMAP_DISPLAY_TYPE_HDMI
:
524 if (!(irqstatus
& DISPC_IRQ_EVSYNC_EVEN
))
531 if (!vout
->first_int
&& (vout
->cur_frm
!= vout
->next_frm
)) {
532 vout
->cur_frm
->vbuf
.vb2_buf
.timestamp
= ts
;
533 vout
->cur_frm
->vbuf
.sequence
= vout
->sequence
++;
534 vb2_buffer_done(&vout
->cur_frm
->vbuf
.vb2_buf
, VB2_BUF_STATE_DONE
);
535 vout
->cur_frm
= vout
->next_frm
;
539 if (list_empty(&vout
->dma_queue
))
542 vout
->next_frm
= list_entry(vout
->dma_queue
.next
,
543 struct omap_vout_buffer
, queue
);
544 list_del(&vout
->next_frm
->queue
);
546 addr
= (unsigned long)vout
->queued_buf_addr
[vout
->next_frm
->vbuf
.vb2_buf
.index
]
547 + vout
->cropped_offset
;
549 /* First save the configuration in ovelray structure */
550 ret
= omapvid_init(vout
, addr
);
552 printk(KERN_ERR VOUT_NAME
553 "failed to set overlay info\n");
557 /* Enable the pipeline and set the Go bit */
558 ret
= omapvid_apply_changes(vout
);
560 printk(KERN_ERR VOUT_NAME
"failed to change mode\n");
563 spin_unlock(&vout
->vbq_lock
);
570 static int vidioc_querycap(struct file
*file
, void *fh
,
571 struct v4l2_capability
*cap
)
573 struct omap_vout_device
*vout
= video_drvdata(file
);
575 strscpy(cap
->driver
, VOUT_NAME
, sizeof(cap
->driver
));
576 strscpy(cap
->card
, vout
->vfd
->name
, sizeof(cap
->card
));
577 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
),
578 "platform:%s.%d", VOUT_NAME
, vout
->vid
);
582 static int vidioc_enum_fmt_vid_out(struct file
*file
, void *fh
,
583 struct v4l2_fmtdesc
*fmt
)
585 int index
= fmt
->index
;
587 if (index
>= NUM_OUTPUT_FORMATS
)
590 fmt
->flags
= omap_formats
[index
].flags
;
591 fmt
->pixelformat
= omap_formats
[index
].pixelformat
;
596 static int vidioc_g_fmt_vid_out(struct file
*file
, void *fh
,
597 struct v4l2_format
*f
)
599 struct omap_vout_device
*vout
= video_drvdata(file
);
601 f
->fmt
.pix
= vout
->pix
;
606 static int vidioc_try_fmt_vid_out(struct file
*file
, void *fh
,
607 struct v4l2_format
*f
)
609 struct omap_overlay
*ovl
;
610 struct omapvideo_info
*ovid
;
611 struct omap_video_timings
*timing
;
612 struct omap_vout_device
*vout
= video_drvdata(file
);
613 struct omap_dss_device
*dssdev
;
615 ovid
= &vout
->vid_info
;
616 ovl
= ovid
->overlays
[0];
617 /* get the display device attached to the overlay */
618 dssdev
= ovl
->get_device(ovl
);
623 timing
= &dssdev
->panel
.timings
;
625 vout
->fbuf
.fmt
.height
= timing
->y_res
;
626 vout
->fbuf
.fmt
.width
= timing
->x_res
;
628 omap_vout_try_format(&f
->fmt
.pix
);
632 static int vidioc_s_fmt_vid_out(struct file
*file
, void *fh
,
633 struct v4l2_format
*f
)
636 struct omap_overlay
*ovl
;
637 struct omapvideo_info
*ovid
;
638 struct omap_video_timings
*timing
;
639 struct omap_vout_device
*vout
= video_drvdata(file
);
640 struct omap_dss_device
*dssdev
;
642 if (vb2_is_busy(&vout
->vq
))
645 ovid
= &vout
->vid_info
;
646 ovl
= ovid
->overlays
[0];
647 dssdev
= ovl
->get_device(ovl
);
649 /* get the display device attached to the overlay */
652 goto s_fmt_vid_out_exit
;
654 timing
= &dssdev
->panel
.timings
;
656 /* We don't support RGB24-packed mode if vrfb rotation
658 if ((is_rotation_enabled(vout
)) &&
659 f
->fmt
.pix
.pixelformat
== V4L2_PIX_FMT_RGB24
) {
661 goto s_fmt_vid_out_exit
;
664 /* get the framebuffer parameters */
666 if (is_rotation_90_or_270(vout
)) {
667 vout
->fbuf
.fmt
.height
= timing
->x_res
;
668 vout
->fbuf
.fmt
.width
= timing
->y_res
;
670 vout
->fbuf
.fmt
.height
= timing
->y_res
;
671 vout
->fbuf
.fmt
.width
= timing
->x_res
;
674 /* change to smaller size is OK */
676 bpp
= omap_vout_try_format(&f
->fmt
.pix
);
677 f
->fmt
.pix
.sizeimage
= f
->fmt
.pix
.width
* f
->fmt
.pix
.height
* bpp
;
679 /* try & set the new output format */
681 vout
->pix
= f
->fmt
.pix
;
684 /* If YUYV then vrfb bpp is 2, for others its 1 */
685 if (V4L2_PIX_FMT_YUYV
== vout
->pix
.pixelformat
||
686 V4L2_PIX_FMT_UYVY
== vout
->pix
.pixelformat
)
689 /* set default crop and win */
690 omap_vout_new_format(&vout
->pix
, &vout
->fbuf
, &vout
->crop
, &vout
->win
);
698 static int vidioc_try_fmt_vid_overlay(struct file
*file
, void *fh
,
699 struct v4l2_format
*f
)
702 struct omap_vout_device
*vout
= video_drvdata(file
);
703 struct omap_overlay
*ovl
;
704 struct omapvideo_info
*ovid
;
705 struct v4l2_window
*win
= &f
->fmt
.win
;
707 ovid
= &vout
->vid_info
;
708 ovl
= ovid
->overlays
[0];
710 ret
= omap_vout_try_window(&vout
->fbuf
, win
);
712 if (!ret
&& !(ovl
->caps
& OMAP_DSS_OVL_CAP_GLOBAL_ALPHA
))
713 win
->global_alpha
= 0;
718 static int vidioc_s_fmt_vid_overlay(struct file
*file
, void *fh
,
719 struct v4l2_format
*f
)
722 struct omap_overlay
*ovl
;
723 struct omapvideo_info
*ovid
;
724 struct omap_vout_device
*vout
= video_drvdata(file
);
725 struct v4l2_window
*win
= &f
->fmt
.win
;
727 ovid
= &vout
->vid_info
;
728 ovl
= ovid
->overlays
[0];
730 ret
= omap_vout_new_window(&vout
->crop
, &vout
->win
, &vout
->fbuf
, win
);
732 enum omap_dss_trans_key_type key_type
=
733 OMAP_DSS_COLOR_KEY_GFX_DST
;
736 /* Video1 plane does not support global alpha on OMAP3 */
737 if (ovl
->caps
& OMAP_DSS_OVL_CAP_GLOBAL_ALPHA
)
738 vout
->win
.global_alpha
= win
->global_alpha
;
740 win
->global_alpha
= 0;
741 if (vout
->fbuf
.flags
& (V4L2_FBUF_FLAG_CHROMAKEY
|
742 V4L2_FBUF_FLAG_SRC_CHROMAKEY
))
746 if (vout
->fbuf
.flags
& V4L2_FBUF_FLAG_SRC_CHROMAKEY
)
747 key_type
= OMAP_DSS_COLOR_KEY_VID_SRC
;
749 if (ovl
->manager
&& ovl
->manager
->get_manager_info
&&
750 ovl
->manager
->set_manager_info
) {
751 struct omap_overlay_manager_info info
;
753 ovl
->manager
->get_manager_info(ovl
->manager
, &info
);
754 info
.trans_enabled
= enable
;
755 info
.trans_key_type
= key_type
;
756 info
.trans_key
= vout
->win
.chromakey
;
758 if (ovl
->manager
->set_manager_info(ovl
->manager
, &info
))
765 static int vidioc_g_fmt_vid_overlay(struct file
*file
, void *fh
,
766 struct v4l2_format
*f
)
768 struct omap_overlay
*ovl
;
769 struct omapvideo_info
*ovid
;
770 struct omap_vout_device
*vout
= video_drvdata(file
);
771 struct v4l2_window
*win
= &f
->fmt
.win
;
773 ovid
= &vout
->vid_info
;
774 ovl
= ovid
->overlays
[0];
776 win
->w
= vout
->win
.w
;
777 win
->field
= vout
->win
.field
;
778 win
->chromakey
= vout
->win
.chromakey
;
779 if (ovl
->caps
& OMAP_DSS_OVL_CAP_GLOBAL_ALPHA
)
780 win
->global_alpha
= vout
->win
.global_alpha
;
782 win
->global_alpha
= 0;
789 static int vidioc_g_selection(struct file
*file
, void *fh
, struct v4l2_selection
*sel
)
791 struct omap_vout_device
*vout
= video_drvdata(file
);
792 struct v4l2_pix_format
*pix
= &vout
->pix
;
794 if (sel
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
797 switch (sel
->target
) {
798 case V4L2_SEL_TGT_CROP
:
801 case V4L2_SEL_TGT_CROP_DEFAULT
:
802 omap_vout_default_crop(&vout
->pix
, &vout
->fbuf
, &sel
->r
);
804 case V4L2_SEL_TGT_CROP_BOUNDS
:
805 /* Width and height are always even */
806 sel
->r
.width
= pix
->width
& ~1;
807 sel
->r
.height
= pix
->height
& ~1;
815 static int vidioc_s_selection(struct file
*file
, void *fh
, struct v4l2_selection
*sel
)
818 struct omap_vout_device
*vout
= video_drvdata(file
);
819 struct omapvideo_info
*ovid
;
820 struct omap_overlay
*ovl
;
821 struct omap_video_timings
*timing
;
822 struct omap_dss_device
*dssdev
;
824 if (sel
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT
)
827 if (sel
->target
!= V4L2_SEL_TGT_CROP
)
830 if (vb2_is_busy(&vout
->vq
))
833 ovid
= &vout
->vid_info
;
834 ovl
= ovid
->overlays
[0];
835 /* get the display device attached to the overlay */
836 dssdev
= ovl
->get_device(ovl
);
843 timing
= &dssdev
->panel
.timings
;
845 if (is_rotation_90_or_270(vout
)) {
846 vout
->fbuf
.fmt
.height
= timing
->x_res
;
847 vout
->fbuf
.fmt
.width
= timing
->y_res
;
849 vout
->fbuf
.fmt
.height
= timing
->y_res
;
850 vout
->fbuf
.fmt
.width
= timing
->x_res
;
853 ret
= omap_vout_new_crop(&vout
->pix
, &vout
->crop
, &vout
->win
,
854 &vout
->fbuf
, &sel
->r
);
860 static int omap_vout_s_ctrl(struct v4l2_ctrl
*ctrl
)
862 struct omap_vout_device
*vout
=
863 container_of(ctrl
->handler
, struct omap_vout_device
, ctrl_handler
);
867 case V4L2_CID_ROTATE
: {
868 struct omapvideo_info
*ovid
;
869 int rotation
= ctrl
->val
;
871 ovid
= &vout
->vid_info
;
873 if (rotation
&& ovid
->rotation_type
== VOUT_ROT_NONE
) {
878 if (rotation
&& vout
->pix
.pixelformat
== V4L2_PIX_FMT_RGB24
) {
883 if (v4l2_rot_to_dss_rot(rotation
, &vout
->rotation
,
890 case V4L2_CID_BG_COLOR
:
892 struct omap_overlay
*ovl
;
893 unsigned int color
= ctrl
->val
;
894 struct omap_overlay_manager_info info
;
896 ovl
= vout
->vid_info
.overlays
[0];
898 if (!ovl
->manager
|| !ovl
->manager
->get_manager_info
) {
903 ovl
->manager
->get_manager_info(ovl
->manager
, &info
);
904 info
.default_color
= color
;
905 if (ovl
->manager
->set_manager_info(ovl
->manager
, &info
)) {
913 struct omapvideo_info
*ovid
;
914 unsigned int mirror
= ctrl
->val
;
916 ovid
= &vout
->vid_info
;
918 if (mirror
&& ovid
->rotation_type
== VOUT_ROT_NONE
) {
923 if (mirror
&& vout
->pix
.pixelformat
== V4L2_PIX_FMT_RGB24
) {
927 vout
->mirror
= mirror
;
936 static const struct v4l2_ctrl_ops omap_vout_ctrl_ops
= {
937 .s_ctrl
= omap_vout_s_ctrl
,
940 static int omap_vout_vb2_queue_setup(struct vb2_queue
*vq
,
942 unsigned int *num_planes
, unsigned int sizes
[],
943 struct device
*alloc_devs
[])
945 struct omap_vout_device
*vout
= vb2_get_drv_priv(vq
);
946 int size
= vout
->pix
.sizeimage
;
948 if (is_rotation_enabled(vout
) && vq
->num_buffers
+ *nbufs
> VRFB_NUM_BUFS
) {
949 *nbufs
= VRFB_NUM_BUFS
- vq
->num_buffers
;
955 return sizes
[0] < size
? -EINVAL
: 0;
962 static int omap_vout_vb2_prepare(struct vb2_buffer
*vb
)
964 struct omap_vout_device
*vout
= vb2_get_drv_priv(vb
->vb2_queue
);
965 struct omapvideo_info
*ovid
= &vout
->vid_info
;
966 struct omap_vout_buffer
*voutbuf
= vb2_to_omap_vout_buffer(vb
);
967 dma_addr_t buf_phy_addr
= vb2_dma_contig_plane_dma_addr(vb
, 0);
969 if (vb2_plane_size(vb
, 0) < vout
->pix
.sizeimage
) {
970 v4l2_dbg(1, debug
, &vout
->vid_dev
->v4l2_dev
,
971 "%s data will not fit into plane (%lu < %u)\n",
972 __func__
, vb2_plane_size(vb
, 0), vout
->pix
.sizeimage
);
976 vb2_set_plane_payload(vb
, 0, vout
->pix
.sizeimage
);
977 voutbuf
->vbuf
.field
= V4L2_FIELD_NONE
;
979 vout
->queued_buf_addr
[vb
->index
] = (u8
*)buf_phy_addr
;
980 if (ovid
->rotation_type
== VOUT_ROT_VRFB
)
981 return omap_vout_prepare_vrfb(vout
, vb
);
985 static void omap_vout_vb2_queue(struct vb2_buffer
*vb
)
987 struct omap_vout_device
*vout
= vb2_get_drv_priv(vb
->vb2_queue
);
988 struct omap_vout_buffer
*voutbuf
= vb2_to_omap_vout_buffer(vb
);
990 list_add_tail(&voutbuf
->queue
, &vout
->dma_queue
);
993 static int omap_vout_vb2_start_streaming(struct vb2_queue
*vq
, unsigned int count
)
995 struct omap_vout_device
*vout
= vb2_get_drv_priv(vq
);
996 struct omapvideo_info
*ovid
= &vout
->vid_info
;
997 struct omap_vout_buffer
*buf
, *tmp
;
998 u32 addr
= 0, mask
= 0;
1001 /* Get the next frame from the buffer queue */
1002 vout
->next_frm
= vout
->cur_frm
= list_entry(vout
->dma_queue
.next
,
1003 struct omap_vout_buffer
, queue
);
1004 /* Remove buffer from the buffer queue */
1005 list_del(&vout
->cur_frm
->queue
);
1006 /* Initialize field_id and started member */
1008 vout
->first_int
= 1;
1011 if (omap_vout_calculate_offset(vout
)) {
1015 if (ovid
->rotation_type
== VOUT_ROT_VRFB
)
1016 if (omap_vout_vrfb_buffer_setup(vout
, &count
, 0)) {
1021 addr
= (unsigned long)vout
->queued_buf_addr
[vout
->cur_frm
->vbuf
.vb2_buf
.index
]
1022 + vout
->cropped_offset
;
1024 mask
= DISPC_IRQ_VSYNC
| DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
1027 /* First save the configuration in overlay structure */
1028 ret
= omapvid_init(vout
, addr
);
1030 v4l2_err(&vout
->vid_dev
->v4l2_dev
,
1031 "failed to set overlay info\n");
1035 omap_dispc_register_isr(omap_vout_isr
, vout
, mask
);
1037 /* Enable the pipeline and set the Go bit */
1038 ret
= omapvid_apply_changes(vout
);
1040 v4l2_err(&vout
->vid_dev
->v4l2_dev
, "failed to change mode\n");
1042 for (j
= 0; j
< ovid
->num_overlays
; j
++) {
1043 struct omap_overlay
*ovl
= ovid
->overlays
[j
];
1044 struct omap_dss_device
*dssdev
= ovl
->get_device(ovl
);
1047 ret
= ovl
->enable(ovl
);
1055 mask
= DISPC_IRQ_VSYNC
| DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
1058 omap_dispc_unregister_isr(omap_vout_isr
, vout
, mask
);
1060 for (j
= 0; j
< ovid
->num_overlays
; j
++) {
1061 struct omap_overlay
*ovl
= ovid
->overlays
[j
];
1062 struct omap_dss_device
*dssdev
= ovl
->get_device(ovl
);
1067 /* Turn of the pipeline */
1068 if (omapvid_apply_changes(vout
))
1069 v4l2_err(&vout
->vid_dev
->v4l2_dev
,
1070 "failed to change mode in streamoff\n");
1073 vb2_buffer_done(&vout
->cur_frm
->vbuf
.vb2_buf
, VB2_BUF_STATE_QUEUED
);
1074 list_for_each_entry_safe(buf
, tmp
, &vout
->dma_queue
, queue
) {
1075 list_del(&buf
->queue
);
1076 vb2_buffer_done(&buf
->vbuf
.vb2_buf
, VB2_BUF_STATE_QUEUED
);
1081 static void omap_vout_vb2_stop_streaming(struct vb2_queue
*vq
)
1083 struct omap_vout_device
*vout
= vb2_get_drv_priv(vq
);
1084 struct omapvideo_info
*ovid
= &vout
->vid_info
;
1085 struct omap_vout_buffer
*buf
, *tmp
;
1089 mask
= DISPC_IRQ_VSYNC
| DISPC_IRQ_EVSYNC_EVEN
| DISPC_IRQ_EVSYNC_ODD
1092 omap_dispc_unregister_isr(omap_vout_isr
, vout
, mask
);
1094 for (j
= 0; j
< ovid
->num_overlays
; j
++) {
1095 struct omap_overlay
*ovl
= ovid
->overlays
[j
];
1096 struct omap_dss_device
*dssdev
= ovl
->get_device(ovl
);
1101 /* Turn of the pipeline */
1102 if (omapvid_apply_changes(vout
))
1103 v4l2_err(&vout
->vid_dev
->v4l2_dev
,
1104 "failed to change mode in streamoff\n");
1106 if (vout
->next_frm
!= vout
->cur_frm
)
1107 vb2_buffer_done(&vout
->next_frm
->vbuf
.vb2_buf
, VB2_BUF_STATE_ERROR
);
1108 vb2_buffer_done(&vout
->cur_frm
->vbuf
.vb2_buf
, VB2_BUF_STATE_ERROR
);
1109 list_for_each_entry_safe(buf
, tmp
, &vout
->dma_queue
, queue
) {
1110 list_del(&buf
->queue
);
1111 vb2_buffer_done(&buf
->vbuf
.vb2_buf
, VB2_BUF_STATE_ERROR
);
1115 static int vidioc_s_fbuf(struct file
*file
, void *fh
,
1116 const struct v4l2_framebuffer
*a
)
1119 struct omap_overlay
*ovl
;
1120 struct omapvideo_info
*ovid
;
1121 struct omap_vout_device
*vout
= video_drvdata(file
);
1122 struct omap_overlay_manager_info info
;
1123 enum omap_dss_trans_key_type key_type
= OMAP_DSS_COLOR_KEY_GFX_DST
;
1125 ovid
= &vout
->vid_info
;
1126 ovl
= ovid
->overlays
[0];
1128 /* OMAP DSS doesn't support Source and Destination color
1130 if ((a
->flags
& V4L2_FBUF_FLAG_SRC_CHROMAKEY
) &&
1131 (a
->flags
& V4L2_FBUF_FLAG_CHROMAKEY
))
1133 /* OMAP DSS Doesn't support the Destination color key
1134 and alpha blending together */
1135 if ((a
->flags
& V4L2_FBUF_FLAG_CHROMAKEY
) &&
1136 (a
->flags
& V4L2_FBUF_FLAG_LOCAL_ALPHA
))
1139 if ((a
->flags
& V4L2_FBUF_FLAG_SRC_CHROMAKEY
)) {
1140 vout
->fbuf
.flags
|= V4L2_FBUF_FLAG_SRC_CHROMAKEY
;
1141 key_type
= OMAP_DSS_COLOR_KEY_VID_SRC
;
1143 vout
->fbuf
.flags
&= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY
;
1145 if ((a
->flags
& V4L2_FBUF_FLAG_CHROMAKEY
)) {
1146 vout
->fbuf
.flags
|= V4L2_FBUF_FLAG_CHROMAKEY
;
1147 key_type
= OMAP_DSS_COLOR_KEY_GFX_DST
;
1149 vout
->fbuf
.flags
&= ~V4L2_FBUF_FLAG_CHROMAKEY
;
1151 if (a
->flags
& (V4L2_FBUF_FLAG_CHROMAKEY
|
1152 V4L2_FBUF_FLAG_SRC_CHROMAKEY
))
1156 if (ovl
->manager
&& ovl
->manager
->get_manager_info
&&
1157 ovl
->manager
->set_manager_info
) {
1159 ovl
->manager
->get_manager_info(ovl
->manager
, &info
);
1160 info
.trans_enabled
= enable
;
1161 info
.trans_key_type
= key_type
;
1162 info
.trans_key
= vout
->win
.chromakey
;
1164 if (ovl
->manager
->set_manager_info(ovl
->manager
, &info
))
1167 if (a
->flags
& V4L2_FBUF_FLAG_LOCAL_ALPHA
) {
1168 vout
->fbuf
.flags
|= V4L2_FBUF_FLAG_LOCAL_ALPHA
;
1171 vout
->fbuf
.flags
&= ~V4L2_FBUF_FLAG_LOCAL_ALPHA
;
1174 if (ovl
->manager
&& ovl
->manager
->get_manager_info
&&
1175 ovl
->manager
->set_manager_info
) {
1176 ovl
->manager
->get_manager_info(ovl
->manager
, &info
);
1177 /* enable this only if there is no zorder cap */
1178 if ((ovl
->caps
& OMAP_DSS_OVL_CAP_ZORDER
) == 0)
1179 info
.partial_alpha_enabled
= enable
;
1180 if (ovl
->manager
->set_manager_info(ovl
->manager
, &info
))
1187 static int vidioc_g_fbuf(struct file
*file
, void *fh
,
1188 struct v4l2_framebuffer
*a
)
1190 struct omap_overlay
*ovl
;
1191 struct omapvideo_info
*ovid
;
1192 struct omap_vout_device
*vout
= video_drvdata(file
);
1193 struct omap_overlay_manager_info info
;
1194 struct omap_video_timings
*timing
;
1195 struct omap_dss_device
*dssdev
;
1197 ovid
= &vout
->vid_info
;
1198 ovl
= ovid
->overlays
[0];
1199 /* get the display device attached to the overlay */
1200 dssdev
= ovl
->get_device(ovl
);
1205 timing
= &dssdev
->panel
.timings
;
1207 vout
->fbuf
.fmt
.height
= timing
->y_res
;
1208 vout
->fbuf
.fmt
.width
= timing
->x_res
;
1209 a
->fmt
.field
= V4L2_FIELD_NONE
;
1210 a
->fmt
.colorspace
= V4L2_COLORSPACE_SRGB
;
1211 a
->fmt
.pixelformat
= V4L2_PIX_FMT_RGBA32
;
1212 a
->fmt
.height
= vout
->fbuf
.fmt
.height
;
1213 a
->fmt
.width
= vout
->fbuf
.fmt
.width
;
1214 a
->fmt
.bytesperline
= vout
->fbuf
.fmt
.width
* 4;
1215 a
->fmt
.sizeimage
= a
->fmt
.height
* a
->fmt
.bytesperline
;
1216 a
->base
= vout
->fbuf
.base
;
1218 a
->flags
= vout
->fbuf
.flags
;
1219 a
->capability
= vout
->fbuf
.capability
;
1220 a
->flags
&= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY
| V4L2_FBUF_FLAG_CHROMAKEY
|
1221 V4L2_FBUF_FLAG_LOCAL_ALPHA
);
1223 if (ovl
->manager
&& ovl
->manager
->get_manager_info
) {
1224 ovl
->manager
->get_manager_info(ovl
->manager
, &info
);
1225 if (info
.trans_key_type
== OMAP_DSS_COLOR_KEY_VID_SRC
)
1226 a
->flags
|= V4L2_FBUF_FLAG_SRC_CHROMAKEY
;
1227 if (info
.trans_key_type
== OMAP_DSS_COLOR_KEY_GFX_DST
)
1228 a
->flags
|= V4L2_FBUF_FLAG_CHROMAKEY
;
1229 if (info
.partial_alpha_enabled
)
1230 a
->flags
|= V4L2_FBUF_FLAG_LOCAL_ALPHA
;
1236 static int vidioc_enum_output(struct file
*file
, void *priv_fh
,
1237 struct v4l2_output
*out
)
1241 snprintf(out
->name
, sizeof(out
->name
), "Overlay");
1242 out
->type
= V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY
;
1246 static int vidioc_g_output(struct file
*file
, void *priv_fh
, unsigned int *i
)
1252 static int vidioc_s_output(struct file
*file
, void *priv_fh
, unsigned int i
)
1254 return i
? -EINVAL
: 0;
1257 static const struct v4l2_ioctl_ops vout_ioctl_ops
= {
1258 .vidioc_querycap
= vidioc_querycap
,
1259 .vidioc_enum_fmt_vid_out
= vidioc_enum_fmt_vid_out
,
1260 .vidioc_g_fmt_vid_out
= vidioc_g_fmt_vid_out
,
1261 .vidioc_try_fmt_vid_out
= vidioc_try_fmt_vid_out
,
1262 .vidioc_s_fmt_vid_out
= vidioc_s_fmt_vid_out
,
1263 .vidioc_s_fbuf
= vidioc_s_fbuf
,
1264 .vidioc_g_fbuf
= vidioc_g_fbuf
,
1265 .vidioc_try_fmt_vid_out_overlay
= vidioc_try_fmt_vid_overlay
,
1266 .vidioc_s_fmt_vid_out_overlay
= vidioc_s_fmt_vid_overlay
,
1267 .vidioc_g_fmt_vid_out_overlay
= vidioc_g_fmt_vid_overlay
,
1268 .vidioc_g_selection
= vidioc_g_selection
,
1269 .vidioc_s_selection
= vidioc_s_selection
,
1270 .vidioc_enum_output
= vidioc_enum_output
,
1271 .vidioc_g_output
= vidioc_g_output
,
1272 .vidioc_s_output
= vidioc_s_output
,
1273 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
1274 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
1275 .vidioc_querybuf
= vb2_ioctl_querybuf
,
1276 .vidioc_qbuf
= vb2_ioctl_qbuf
,
1277 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
1278 .vidioc_expbuf
= vb2_ioctl_expbuf
,
1279 .vidioc_streamon
= vb2_ioctl_streamon
,
1280 .vidioc_streamoff
= vb2_ioctl_streamoff
,
1281 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
1282 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
1285 static const struct v4l2_file_operations omap_vout_fops
= {
1286 .owner
= THIS_MODULE
,
1287 .unlocked_ioctl
= video_ioctl2
,
1288 .poll
= vb2_fop_poll
,
1289 .mmap
= vb2_fop_mmap
,
1290 .open
= v4l2_fh_open
,
1291 .release
= vb2_fop_release
,
1294 static const struct vb2_ops omap_vout_vb2_ops
= {
1295 .queue_setup
= omap_vout_vb2_queue_setup
,
1296 .buf_queue
= omap_vout_vb2_queue
,
1297 .buf_prepare
= omap_vout_vb2_prepare
,
1298 .start_streaming
= omap_vout_vb2_start_streaming
,
1299 .stop_streaming
= omap_vout_vb2_stop_streaming
,
1300 .wait_prepare
= vb2_ops_wait_prepare
,
1301 .wait_finish
= vb2_ops_wait_finish
,
1304 /* Init functions used during driver initialization */
1305 /* Initial setup of video_data */
1306 static int __init
omap_vout_setup_video_data(struct omap_vout_device
*vout
)
1308 struct video_device
*vfd
;
1309 struct v4l2_pix_format
*pix
;
1310 struct omap_overlay
*ovl
= vout
->vid_info
.overlays
[0];
1311 struct omap_dss_device
*display
= ovl
->get_device(ovl
);
1312 struct v4l2_ctrl_handler
*hdl
;
1313 struct vb2_queue
*vq
;
1316 /* set the default pix */
1319 /* Set the default picture of QVGA */
1320 pix
->width
= QQVGA_WIDTH
;
1321 pix
->height
= QQVGA_HEIGHT
;
1323 /* Default pixel format is RGB 5-6-5 */
1324 pix
->pixelformat
= V4L2_PIX_FMT_RGB565
;
1325 pix
->field
= V4L2_FIELD_NONE
;
1326 pix
->bytesperline
= pix
->width
* 2;
1327 pix
->sizeimage
= pix
->bytesperline
* pix
->height
;
1328 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
1330 vout
->bpp
= RGB565_BPP
;
1331 vout
->fbuf
.fmt
.width
= display
->panel
.timings
.x_res
;
1332 vout
->fbuf
.fmt
.height
= display
->panel
.timings
.y_res
;
1333 vout
->cropped_offset
= 0;
1335 /* Set the data structures for the overlay parameters*/
1336 vout
->fbuf
.flags
= V4L2_FBUF_FLAG_OVERLAY
;
1337 vout
->fbuf
.capability
= V4L2_FBUF_CAP_LOCAL_ALPHA
|
1338 V4L2_FBUF_CAP_SRC_CHROMAKEY
| V4L2_FBUF_CAP_CHROMAKEY
|
1339 V4L2_FBUF_CAP_EXTERNOVERLAY
;
1340 if (ovl
->caps
& OMAP_DSS_OVL_CAP_GLOBAL_ALPHA
) {
1341 vout
->win
.global_alpha
= 255;
1342 vout
->fbuf
.capability
|= V4L2_FBUF_CAP_GLOBAL_ALPHA
;
1343 vout
->fbuf
.flags
|= V4L2_FBUF_FLAG_GLOBAL_ALPHA
;
1345 vout
->win
.global_alpha
= 0;
1347 vout
->win
.field
= V4L2_FIELD_NONE
;
1349 omap_vout_new_format(pix
, &vout
->fbuf
, &vout
->crop
, &vout
->win
);
1351 hdl
= &vout
->ctrl_handler
;
1352 v4l2_ctrl_handler_init(hdl
, 3);
1353 if (vout
->vid_info
.rotation_type
== VOUT_ROT_VRFB
) {
1354 v4l2_ctrl_new_std(hdl
, &omap_vout_ctrl_ops
,
1355 V4L2_CID_ROTATE
, 0, 270, 90, 0);
1356 v4l2_ctrl_new_std(hdl
, &omap_vout_ctrl_ops
,
1357 V4L2_CID_VFLIP
, 0, 1, 1, 0);
1359 v4l2_ctrl_new_std(hdl
, &omap_vout_ctrl_ops
,
1360 V4L2_CID_BG_COLOR
, 0, 0xffffff, 1, 0);
1365 vout
->mirror
= false;
1366 INIT_LIST_HEAD(&vout
->dma_queue
);
1367 if (vout
->vid_info
.rotation_type
== VOUT_ROT_VRFB
)
1370 /* initialize the video_device struct */
1371 vfd
= vout
->vfd
= video_device_alloc();
1374 printk(KERN_ERR VOUT_NAME
1375 ": could not allocate video device struct\n");
1376 v4l2_ctrl_handler_free(hdl
);
1379 vfd
->ctrl_handler
= hdl
;
1380 vfd
->release
= video_device_release
;
1381 vfd
->ioctl_ops
= &vout_ioctl_ops
;
1383 strscpy(vfd
->name
, VOUT_NAME
, sizeof(vfd
->name
));
1385 vfd
->fops
= &omap_vout_fops
;
1386 vfd
->v4l2_dev
= &vout
->vid_dev
->v4l2_dev
;
1387 vfd
->vfl_dir
= VFL_DIR_TX
;
1389 vfd
->device_caps
= V4L2_CAP_STREAMING
| V4L2_CAP_VIDEO_OUTPUT
|
1390 V4L2_CAP_VIDEO_OUTPUT_OVERLAY
;
1391 mutex_init(&vout
->lock
);
1394 vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
1395 vq
->io_modes
= VB2_MMAP
| VB2_DMABUF
;
1396 vq
->drv_priv
= vout
;
1397 vq
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
;
1398 vq
->buf_struct_size
= sizeof(struct omap_vout_buffer
);
1399 vq
->dev
= vfd
->v4l2_dev
->dev
;
1401 vq
->ops
= &omap_vout_vb2_ops
;
1402 vq
->mem_ops
= &vb2_dma_contig_memops
;
1403 vq
->lock
= &vout
->lock
;
1404 vq
->min_buffers_needed
= 1;
1407 ret
= vb2_queue_init(vq
);
1409 v4l2_ctrl_handler_free(hdl
);
1410 video_device_release(vfd
);
1415 /* Setup video buffers */
1416 static int __init
omap_vout_setup_video_bufs(struct platform_device
*pdev
,
1419 struct omapvideo_info
*ovid
;
1420 struct omap_vout_device
*vout
;
1421 struct v4l2_device
*v4l2_dev
= platform_get_drvdata(pdev
);
1422 struct omap2video_device
*vid_dev
=
1423 container_of(v4l2_dev
, struct omap2video_device
, v4l2_dev
);
1426 vout
= vid_dev
->vouts
[vid_num
];
1427 ovid
= &vout
->vid_info
;
1429 if (ovid
->rotation_type
== VOUT_ROT_VRFB
) {
1430 bool static_vrfb_allocation
= (vid_num
== 0) ?
1431 vid1_static_vrfb_alloc
: vid2_static_vrfb_alloc
;
1432 ret
= omap_vout_setup_vrfb_bufs(pdev
, vid_num
,
1433 static_vrfb_allocation
);
1438 /* Create video out devices */
1439 static int __init
omap_vout_create_video_devices(struct platform_device
*pdev
)
1442 struct omap_vout_device
*vout
;
1443 struct video_device
*vfd
= NULL
;
1444 struct v4l2_device
*v4l2_dev
= platform_get_drvdata(pdev
);
1445 struct omap2video_device
*vid_dev
= container_of(v4l2_dev
,
1446 struct omap2video_device
, v4l2_dev
);
1447 struct omap_overlay
*ovl
= vid_dev
->overlays
[0];
1448 struct omap_overlay_info info
;
1450 ovl
->get_overlay_info(ovl
, &info
);
1452 for (k
= 0; k
< pdev
->num_resources
; k
++) {
1454 vout
= kzalloc(sizeof(struct omap_vout_device
), GFP_KERNEL
);
1456 dev_err(&pdev
->dev
, ": could not allocate memory\n");
1461 vid_dev
->vouts
[k
] = vout
;
1462 vout
->vid_dev
= vid_dev
;
1463 /* Select video2 if only 1 overlay is controlled by V4L2 */
1464 if (pdev
->num_resources
== 1)
1465 vout
->vid_info
.overlays
[0] = vid_dev
->overlays
[k
+ 2];
1467 /* Else select video1 and video2 one by one. */
1468 vout
->vid_info
.overlays
[0] = vid_dev
->overlays
[k
+ 1];
1469 vout
->vid_info
.num_overlays
= 1;
1470 vout
->vid_info
.id
= k
+ 1;
1471 spin_lock_init(&vout
->vbq_lock
);
1473 * Set the framebuffer base, this allows applications to find
1474 * the fb corresponding to this overlay.
1476 * To be precise: fbuf.base should match smem_start of
1477 * struct fb_fix_screeninfo.
1479 vout
->fbuf
.base
= (void *)info
.paddr
;
1481 /* Set VRFB as rotation_type for omap2 and omap3 */
1482 if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
1483 vout
->vid_info
.rotation_type
= VOUT_ROT_VRFB
;
1485 /* Setup the default configuration for the video devices
1487 if (omap_vout_setup_video_data(vout
) != 0) {
1492 /* Allocate default number of buffers for the video streaming
1493 * and reserve the VRFB space for rotation
1495 if (omap_vout_setup_video_bufs(pdev
, k
) != 0) {
1500 /* Register the Video device with V4L2
1503 if (video_register_device(vfd
, VFL_TYPE_VIDEO
, -1) < 0) {
1505 ": Could not register Video for Linux device\n");
1510 video_set_drvdata(vfd
, vout
);
1512 dev_info(&pdev
->dev
,
1513 ": registered and initialized video device %d\n",
1515 if (k
== (pdev
->num_resources
- 1))
1520 if (vout
->vid_info
.rotation_type
== VOUT_ROT_VRFB
)
1521 omap_vout_release_vrfb(vout
);
1523 video_device_release(vfd
);
1531 /* Driver functions */
1532 static void omap_vout_cleanup_device(struct omap_vout_device
*vout
)
1534 struct video_device
*vfd
;
1535 struct omapvideo_info
*ovid
;
1541 ovid
= &vout
->vid_info
;
1543 if (!video_is_registered(vfd
)) {
1545 * The device was never registered, so release the
1546 * video_device struct directly.
1548 video_device_release(vfd
);
1551 * The unregister function will release the video_device
1552 * struct as well as unregistering it.
1554 video_unregister_device(vfd
);
1557 v4l2_ctrl_handler_free(&vout
->ctrl_handler
);
1558 if (ovid
->rotation_type
== VOUT_ROT_VRFB
) {
1559 omap_vout_release_vrfb(vout
);
1560 /* Free the VRFB buffer if allocated
1563 if (vout
->vrfb_static_allocation
)
1564 omap_vout_free_vrfb_buffers(vout
);
1570 static int omap_vout_remove(struct platform_device
*pdev
)
1573 struct v4l2_device
*v4l2_dev
= platform_get_drvdata(pdev
);
1574 struct omap2video_device
*vid_dev
= container_of(v4l2_dev
, struct
1575 omap2video_device
, v4l2_dev
);
1577 v4l2_device_unregister(v4l2_dev
);
1578 for (k
= 0; k
< pdev
->num_resources
; k
++)
1579 omap_vout_cleanup_device(vid_dev
->vouts
[k
]);
1581 for (k
= 0; k
< vid_dev
->num_displays
; k
++) {
1582 if (vid_dev
->displays
[k
]->state
!= OMAP_DSS_DISPLAY_DISABLED
)
1583 vid_dev
->displays
[k
]->driver
->disable(vid_dev
->displays
[k
]);
1585 omap_dss_put_device(vid_dev
->displays
[k
]);
1591 static int __init
omap_vout_probe(struct platform_device
*pdev
)
1594 struct omap_overlay
*ovl
;
1595 struct omap_dss_device
*dssdev
= NULL
;
1596 struct omap_dss_device
*def_display
;
1597 struct omap2video_device
*vid_dev
= NULL
;
1599 if (omapdss_is_initialized() == false)
1600 return -EPROBE_DEFER
;
1602 ret
= omapdss_compat_init();
1604 dev_err(&pdev
->dev
, "failed to init dss\n");
1608 if (pdev
->num_resources
== 0) {
1609 dev_err(&pdev
->dev
, "probed for an unknown device\n");
1614 vid_dev
= kzalloc(sizeof(struct omap2video_device
), GFP_KERNEL
);
1615 if (vid_dev
== NULL
) {
1620 vid_dev
->num_displays
= 0;
1621 for_each_dss_dev(dssdev
) {
1622 omap_dss_get_device(dssdev
);
1624 if (!dssdev
->driver
) {
1625 dev_warn(&pdev
->dev
, "no driver for display: %s\n",
1627 omap_dss_put_device(dssdev
);
1631 vid_dev
->displays
[vid_dev
->num_displays
++] = dssdev
;
1634 if (vid_dev
->num_displays
== 0) {
1635 dev_err(&pdev
->dev
, "no displays\n");
1640 vid_dev
->num_overlays
= omap_dss_get_num_overlays();
1641 for (i
= 0; i
< vid_dev
->num_overlays
; i
++)
1642 vid_dev
->overlays
[i
] = omap_dss_get_overlay(i
);
1644 vid_dev
->num_managers
= omap_dss_get_num_overlay_managers();
1645 for (i
= 0; i
< vid_dev
->num_managers
; i
++)
1646 vid_dev
->managers
[i
] = omap_dss_get_overlay_manager(i
);
1648 /* Get the Video1 overlay and video2 overlay.
1649 * Setup the Display attached to that overlays
1651 for (i
= 1; i
< vid_dev
->num_overlays
; i
++) {
1652 ovl
= omap_dss_get_overlay(i
);
1653 dssdev
= ovl
->get_device(ovl
);
1656 def_display
= dssdev
;
1658 dev_warn(&pdev
->dev
, "cannot find display\n");
1662 struct omap_dss_driver
*dssdrv
= def_display
->driver
;
1664 ret
= dssdrv
->enable(def_display
);
1666 /* Here we are not considering a error
1667 * as display may be enabled by frame
1670 dev_warn(&pdev
->dev
,
1671 "'%s' Display already enabled\n",
1677 if (v4l2_device_register(&pdev
->dev
, &vid_dev
->v4l2_dev
) < 0) {
1678 dev_err(&pdev
->dev
, "v4l2_device_register failed\n");
1683 ret
= omap_vout_create_video_devices(pdev
);
1687 for (i
= 0; i
< vid_dev
->num_displays
; i
++) {
1688 struct omap_dss_device
*display
= vid_dev
->displays
[i
];
1690 if (display
->driver
->update
)
1691 display
->driver
->update(display
, 0, 0,
1692 display
->panel
.timings
.x_res
,
1693 display
->panel
.timings
.y_res
);
1698 v4l2_device_unregister(&vid_dev
->v4l2_dev
);
1700 for (i
= 1; i
< vid_dev
->num_overlays
; i
++) {
1702 ovl
= omap_dss_get_overlay(i
);
1703 dssdev
= ovl
->get_device(ovl
);
1706 def_display
= dssdev
;
1708 if (def_display
&& def_display
->driver
)
1709 def_display
->driver
->disable(def_display
);
1714 omapdss_compat_uninit();
1718 static struct platform_driver omap_vout_driver
= {
1722 .remove
= omap_vout_remove
,
1725 static int __init
omap_vout_init(void)
1727 if (platform_driver_probe(&omap_vout_driver
, omap_vout_probe
) != 0) {
1728 printk(KERN_ERR VOUT_NAME
":Could not register Video driver\n");
1734 static void omap_vout_cleanup(void)
1736 platform_driver_unregister(&omap_vout_driver
);
1739 late_initcall(omap_vout_init
);
1740 module_exit(omap_vout_cleanup
);