media: platform: rename omap/ to ti/omap/
authorMauro Carvalho Chehab <mchehab@kernel.org>
Sun, 13 Mar 2022 10:18:20 +0000 (11:18 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 18 Mar 2022 04:58:34 +0000 (05:58 +0100)
As the end goal is to have platform drivers split by vendor,
rename omap/ to ti/omap/.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
18 files changed:
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/omap/Kconfig [deleted file]
drivers/media/platform/omap/Makefile [deleted file]
drivers/media/platform/omap/omap_vout.c [deleted file]
drivers/media/platform/omap/omap_vout_vrfb.c [deleted file]
drivers/media/platform/omap/omap_vout_vrfb.h [deleted file]
drivers/media/platform/omap/omap_voutdef.h [deleted file]
drivers/media/platform/omap/omap_voutlib.c [deleted file]
drivers/media/platform/omap/omap_voutlib.h [deleted file]
drivers/media/platform/ti/omap/Kconfig [new file with mode: 0644]
drivers/media/platform/ti/omap/Makefile [new file with mode: 0644]
drivers/media/platform/ti/omap/omap_vout.c [new file with mode: 0644]
drivers/media/platform/ti/omap/omap_vout_vrfb.c [new file with mode: 0644]
drivers/media/platform/ti/omap/omap_vout_vrfb.h [new file with mode: 0644]
drivers/media/platform/ti/omap/omap_voutdef.h [new file with mode: 0644]
drivers/media/platform/ti/omap/omap_voutlib.c [new file with mode: 0644]
drivers/media/platform/ti/omap/omap_voutlib.h [new file with mode: 0644]

index c452684..4a8d287 100644 (file)
@@ -81,7 +81,6 @@ source "drivers/media/platform/mediatek/mtk-vcodec/Kconfig"
 source "drivers/media/platform/mediatek/mtk-vpu/Kconfig"
 source "drivers/media/platform/nvidia/tegra-vde/Kconfig"
 source "drivers/media/platform/nxp/Kconfig"
-source "drivers/media/platform/omap/Kconfig"
 source "drivers/media/platform/qcom/Kconfig"
 source "drivers/media/platform/renesas/Kconfig"
 source "drivers/media/platform/rockchip/Kconfig"
@@ -97,6 +96,7 @@ source "drivers/media/platform/st/stm32/Kconfig"
 source "drivers/media/platform/ti-vpe/Kconfig"
 source "drivers/media/platform/ti/am437x/Kconfig"
 source "drivers/media/platform/ti/davinci/Kconfig"
+source "drivers/media/platform/ti/omap/Kconfig"
 source "drivers/media/platform/ti/omap3isp/Kconfig"
 source "drivers/media/platform/via/Kconfig"
 source "drivers/media/platform/xilinx/Kconfig"
index cf86573..9c532bd 100644 (file)
@@ -21,7 +21,6 @@ obj-y += mediatek/mtk-vcodec/
 obj-y += mediatek/mtk-vpu/
 obj-y += nvidia/tegra-vde/
 obj-y += nxp/
-obj-y += omap/
 obj-y += qcom/camss/
 obj-y += qcom/venus/
 obj-y += renesas/
@@ -42,6 +41,7 @@ obj-y += st/stm32/
 obj-y += ti-vpe/
 obj-y += ti/am437x/
 obj-y += ti/davinci/
+obj-y += ti/omap/
 obj-y += ti/omap3isp/
 obj-y += via/
 obj-y += xilinx/
diff --git a/drivers/media/platform/omap/Kconfig b/drivers/media/platform/omap/Kconfig
deleted file mode 100644 (file)
index 789d5e5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_OMAP2_VOUT_VRFB
-       bool
-       default y
-       depends on VIDEO_OMAP2_VOUT && (OMAP2_VRFB || COMPILE_TEST)
-
-config VIDEO_OMAP2_VOUT
-       tristate "OMAP2/OMAP3 V4L2-Display driver"
-       depends on V4L_PLATFORM_DRIVERS
-       depends on MMU
-       depends on FB_OMAP2 || (COMPILE_TEST && FB_OMAP2=n)
-       depends on ARCH_OMAP2 || ARCH_OMAP3 || COMPILE_TEST
-       depends on VIDEO_V4L2
-       select VIDEOBUF2_DMA_CONTIG
-       select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
-       help
-         V4L2 Display driver support for OMAP2/3 based boards.
diff --git a/drivers/media/platform/omap/Makefile b/drivers/media/platform/omap/Makefile
deleted file mode 100644 (file)
index b17a0ac..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the omap video device drivers.
-#
-
-# OMAP2/3 Display driver
-omap-vout-y += omap_vout.o omap_voutlib.o
-omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o
-obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
deleted file mode 100644 (file)
index 3e0d9af..0000000
+++ /dev/null
@@ -1,1742 +0,0 @@
-/*
- * omap_vout.c
- *
- * Copyright (C) 2005-2010 Texas Instruments.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- * Leveraged code from the OMAP2 camera driver
- * Video-for-Linux (Version 2) camera capture driver for
- * the OMAP24xx camera controller.
- *
- * Author: Andy Lowe (source@mvista.com)
- *
- * Copyright (C) 2004 MontaVista Software, Inc.
- * Copyright (C) 2010 Texas Instruments.
- *
- * History:
- * 20-APR-2006 Khasim          Modified VRFB based Rotation,
- *                             The image data is always read from 0 degree
- *                             view and written
- *                             to the virtual space of desired rotation angle
- * 4-DEC-2006  Jian            Changed to support better memory management
- *
- * 17-Nov-2008 Hardik          Changed driver to use video_ioctl2
- *
- * 23-Feb-2010 Vaibhav H       Modified to use new DSS2 interface
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/videodev2.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-
-#include <video/omapvrfb.h>
-#include <video/omapfb_dss.h>
-
-#include "omap_voutlib.h"
-#include "omap_voutdef.h"
-#include "omap_vout_vrfb.h"
-
-MODULE_AUTHOR("Texas Instruments");
-MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
-MODULE_LICENSE("GPL");
-
-/* Driver Configuration macros */
-#define VOUT_NAME              "omap_vout"
-
-enum omap_vout_channels {
-       OMAP_VIDEO1,
-       OMAP_VIDEO2,
-};
-
-/* Variables configurable through module params*/
-static bool vid1_static_vrfb_alloc;
-static bool vid2_static_vrfb_alloc;
-static bool debug;
-
-/* Module parameters */
-module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
-MODULE_PARM_DESC(vid1_static_vrfb_alloc,
-       "Static allocation of the VRFB buffer for video1 device");
-
-module_param(vid2_static_vrfb_alloc, bool, S_IRUGO);
-MODULE_PARM_DESC(vid2_static_vrfb_alloc,
-       "Static allocation of the VRFB buffer for video2 device");
-
-module_param(debug, bool, S_IRUGO);
-MODULE_PARM_DESC(debug, "Debug level (0-1)");
-
-/* list of image formats supported by OMAP2 video pipelines */
-static const struct v4l2_fmtdesc omap_formats[] = {
-       {
-               /* Note:  V4L2 defines RGB565 as:
-                *
-                *      Byte 0                    Byte 1
-                *      g2 g1 g0 r4 r3 r2 r1 r0   b4 b3 b2 b1 b0 g5 g4 g3
-                *
-                * We interpret RGB565 as:
-                *
-                *      Byte 0                    Byte 1
-                *      g2 g1 g0 b4 b3 b2 b1 b0   r4 r3 r2 r1 r0 g5 g4 g3
-                */
-               .pixelformat = V4L2_PIX_FMT_RGB565,
-       },
-       {
-               /* Note:  V4L2 defines RGB32 as: RGB-8-8-8-8  we use
-                *  this for RGB24 unpack mode, the last 8 bits are ignored
-                * */
-               .pixelformat = V4L2_PIX_FMT_RGB32,
-       },
-       {
-               /* Note:  V4L2 defines RGB24 as: RGB-8-8-8  we use
-                *        this for RGB24 packed mode
-                *
-                */
-               .pixelformat = V4L2_PIX_FMT_RGB24,
-       },
-       {
-               .pixelformat = V4L2_PIX_FMT_YUYV,
-       },
-       {
-               .pixelformat = V4L2_PIX_FMT_UYVY,
-       },
-};
-
-#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
-
-/*
- * Try format
- */
-static int omap_vout_try_format(struct v4l2_pix_format *pix)
-{
-       int ifmt, bpp = 0;
-
-       pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT,
-                                               (u32)VID_MAX_HEIGHT);
-       pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH);
-
-       for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) {
-               if (pix->pixelformat == omap_formats[ifmt].pixelformat)
-                       break;
-       }
-
-       if (ifmt == NUM_OUTPUT_FORMATS)
-               ifmt = 0;
-
-       pix->pixelformat = omap_formats[ifmt].pixelformat;
-       pix->field = V4L2_FIELD_NONE;
-
-       switch (pix->pixelformat) {
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_UYVY:
-       default:
-               pix->colorspace = V4L2_COLORSPACE_SRGB;
-               bpp = YUYV_BPP;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_RGB565X:
-               pix->colorspace = V4L2_COLORSPACE_SRGB;
-               bpp = RGB565_BPP;
-               break;
-       case V4L2_PIX_FMT_RGB24:
-               pix->colorspace = V4L2_COLORSPACE_SRGB;
-               bpp = RGB24_BPP;
-               break;
-       case V4L2_PIX_FMT_RGB32:
-       case V4L2_PIX_FMT_BGR32:
-               pix->colorspace = V4L2_COLORSPACE_SRGB;
-               bpp = RGB32_BPP;
-               break;
-       }
-       pix->bytesperline = pix->width * bpp;
-       pix->sizeimage = pix->bytesperline * pix->height;
-
-       return bpp;
-}
-
-/*
- * Convert V4L2 rotation to DSS rotation
- *     V4L2 understand 0, 90, 180, 270.
- *     Convert to 0, 1, 2 and 3 respectively for DSS
- */
-static int v4l2_rot_to_dss_rot(int v4l2_rotation,
-                       enum dss_rotation *rotation, bool mirror)
-{
-       int ret = 0;
-
-       switch (v4l2_rotation) {
-       case 90:
-               *rotation = dss_rotation_90_degree;
-               break;
-       case 180:
-               *rotation = dss_rotation_180_degree;
-               break;
-       case 270:
-               *rotation = dss_rotation_270_degree;
-               break;
-       case 0:
-               *rotation = dss_rotation_0_degree;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-       return ret;
-}
-
-static int omap_vout_calculate_offset(struct omap_vout_device *vout)
-{
-       struct omapvideo_info *ovid;
-       struct v4l2_rect *crop = &vout->crop;
-       struct v4l2_pix_format *pix = &vout->pix;
-       int *cropped_offset = &vout->cropped_offset;
-       int ps = 2, line_length = 0;
-
-       ovid = &vout->vid_info;
-
-       if (ovid->rotation_type == VOUT_ROT_VRFB) {
-               omap_vout_calculate_vrfb_offset(vout);
-       } else {
-               vout->line_length = line_length = pix->width;
-
-               if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
-                       V4L2_PIX_FMT_UYVY == pix->pixelformat)
-                       ps = 2;
-               else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
-                       ps = 4;
-               else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
-                       ps = 3;
-
-               vout->ps = ps;
-
-               *cropped_offset = (line_length * ps) *
-                       crop->top + crop->left * ps;
-       }
-
-       v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
-                       __func__, vout->cropped_offset);
-
-       return 0;
-}
-
-/*
- * Convert V4L2 pixel format to DSS pixel format
- */
-static int video_mode_to_dss_mode(struct omap_vout_device *vout)
-{
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct v4l2_pix_format *pix = &vout->pix;
-       enum omap_color_mode mode;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-
-       switch (pix->pixelformat) {
-       case V4L2_PIX_FMT_YUYV:
-               mode = OMAP_DSS_COLOR_YUV2;
-               break;
-       case V4L2_PIX_FMT_UYVY:
-               mode = OMAP_DSS_COLOR_UYVY;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-               mode = OMAP_DSS_COLOR_RGB16;
-               break;
-       case V4L2_PIX_FMT_RGB24:
-               mode = OMAP_DSS_COLOR_RGB24P;
-               break;
-       case V4L2_PIX_FMT_RGB32:
-               mode = (ovl->id == OMAP_DSS_VIDEO1) ?
-                       OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
-               break;
-       case V4L2_PIX_FMT_BGR32:
-               mode = OMAP_DSS_COLOR_RGBX32;
-               break;
-       default:
-               mode = -EINVAL;
-               break;
-       }
-       return mode;
-}
-
-/*
- * Setup the overlay
- */
-static int omapvid_setup_overlay(struct omap_vout_device *vout,
-               struct omap_overlay *ovl, int posx, int posy, int outw,
-               int outh, dma_addr_t addr)
-{
-       int ret = 0;
-       struct omap_overlay_info info;
-       int cropheight, cropwidth, pixwidth;
-
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
-                       (outw != vout->pix.width || outh != vout->pix.height)) {
-               ret = -EINVAL;
-               goto setup_ovl_err;
-       }
-
-       vout->dss_mode = video_mode_to_dss_mode(vout);
-       if (vout->dss_mode == -EINVAL) {
-               ret = -EINVAL;
-               goto setup_ovl_err;
-       }
-
-       /* Setup the input plane parameters according to
-        * rotation value selected.
-        */
-       if (is_rotation_90_or_270(vout)) {
-               cropheight = vout->crop.width;
-               cropwidth = vout->crop.height;
-               pixwidth = vout->pix.height;
-       } else {
-               cropheight = vout->crop.height;
-               cropwidth = vout->crop.width;
-               pixwidth = vout->pix.width;
-       }
-
-       ovl->get_overlay_info(ovl, &info);
-       info.paddr = addr;
-       info.width = cropwidth;
-       info.height = cropheight;
-       info.color_mode = vout->dss_mode;
-       info.mirror = vout->mirror;
-       info.pos_x = posx;
-       info.pos_y = posy;
-       info.out_width = outw;
-       info.out_height = outh;
-       info.global_alpha = vout->win.global_alpha;
-       if (!is_rotation_enabled(vout)) {
-               info.rotation = 0;
-               info.rotation_type = OMAP_DSS_ROT_DMA;
-               info.screen_width = pixwidth;
-       } else {
-               info.rotation = vout->rotation;
-               info.rotation_type = OMAP_DSS_ROT_VRFB;
-               info.screen_width = 2048;
-       }
-
-       v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
-               "%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
-               "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
-               "out_height=%d rotation_type=%d screen_width=%d\n", __func__,
-               ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
-               info.color_mode, info.rotation, info.mirror, info.pos_x,
-               info.pos_y, info.out_width, info.out_height, info.rotation_type,
-               info.screen_width);
-
-       ret = ovl->set_overlay_info(ovl, &info);
-       if (ret)
-               goto setup_ovl_err;
-
-       return 0;
-
-setup_ovl_err:
-       v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n");
-       return ret;
-}
-
-/*
- * Initialize the overlay structure
- */
-static int omapvid_init(struct omap_vout_device *vout, dma_addr_t addr)
-{
-       int ret = 0, i;
-       struct v4l2_window *win;
-       struct omap_overlay *ovl;
-       int posx, posy, outw, outh;
-       struct omap_video_timings *timing;
-       struct omapvideo_info *ovid = &vout->vid_info;
-
-       win = &vout->win;
-       for (i = 0; i < ovid->num_overlays; i++) {
-               struct omap_dss_device *dssdev;
-
-               ovl = ovid->overlays[i];
-               dssdev = ovl->get_device(ovl);
-
-               if (!dssdev)
-                       return -EINVAL;
-
-               timing = &dssdev->panel.timings;
-
-               outw = win->w.width;
-               outh = win->w.height;
-               switch (vout->rotation) {
-               case dss_rotation_90_degree:
-                       /* Invert the height and width for 90
-                        * and 270 degree rotation
-                        */
-                       swap(outw, outh);
-                       posy = (timing->y_res - win->w.width) - win->w.left;
-                       posx = win->w.top;
-                       break;
-
-               case dss_rotation_180_degree:
-                       posx = (timing->x_res - win->w.width) - win->w.left;
-                       posy = (timing->y_res - win->w.height) - win->w.top;
-                       break;
-
-               case dss_rotation_270_degree:
-                       swap(outw, outh);
-                       posy = win->w.left;
-                       posx = (timing->x_res - win->w.height) - win->w.top;
-                       break;
-
-               default:
-                       posx = win->w.left;
-                       posy = win->w.top;
-                       break;
-               }
-
-               ret = omapvid_setup_overlay(vout, ovl, posx, posy,
-                               outw, outh, addr);
-               if (ret)
-                       goto omapvid_init_err;
-       }
-       return 0;
-
-omapvid_init_err:
-       v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n");
-       return ret;
-}
-
-/*
- * Apply the changes set the go bit of DSS
- */
-static int omapvid_apply_changes(struct omap_vout_device *vout)
-{
-       int i;
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid = &vout->vid_info;
-
-       for (i = 0; i < ovid->num_overlays; i++) {
-               struct omap_dss_device *dssdev;
-
-               ovl = ovid->overlays[i];
-               dssdev = ovl->get_device(ovl);
-               if (!dssdev)
-                       return -EINVAL;
-               ovl->manager->apply(ovl->manager);
-       }
-
-       return 0;
-}
-
-static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
-               unsigned int irqstatus, u64 ts)
-{
-       u32 fid;
-
-       if (vout->first_int) {
-               vout->first_int = 0;
-               goto err;
-       }
-
-       if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
-               fid = 1;
-       else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
-               fid = 0;
-       else
-               goto err;
-
-       vout->field_id ^= 1;
-       if (fid != vout->field_id) {
-               if (fid == 0)
-                       vout->field_id = fid;
-       } else if (0 == fid) {
-               if (vout->cur_frm == vout->next_frm)
-                       goto err;
-
-               vout->cur_frm->vbuf.vb2_buf.timestamp = ts;
-               vout->cur_frm->vbuf.sequence = vout->sequence++;
-               vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
-               vout->cur_frm = vout->next_frm;
-       } else {
-               if (list_empty(&vout->dma_queue) ||
-                               (vout->cur_frm != vout->next_frm))
-                       goto err;
-       }
-
-       return vout->field_id;
-err:
-       return 0;
-}
-
-static void omap_vout_isr(void *arg, unsigned int irqstatus)
-{
-       int ret, fid, mgr_id;
-       dma_addr_t addr;
-       u32 irq;
-       struct omap_overlay *ovl;
-       u64 ts;
-       struct omapvideo_info *ovid;
-       struct omap_dss_device *cur_display;
-       struct omap_vout_device *vout = (struct omap_vout_device *)arg;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-
-       mgr_id = ovl->manager->id;
-
-       /* get the display device attached to the overlay */
-       cur_display = ovl->get_device(ovl);
-
-       if (!cur_display)
-               return;
-
-       spin_lock(&vout->vbq_lock);
-       ts = ktime_get_ns();
-
-       switch (cur_display->type) {
-       case OMAP_DISPLAY_TYPE_DSI:
-       case OMAP_DISPLAY_TYPE_DPI:
-       case OMAP_DISPLAY_TYPE_DVI:
-               if (mgr_id == OMAP_DSS_CHANNEL_LCD)
-                       irq = DISPC_IRQ_VSYNC;
-               else if (mgr_id == OMAP_DSS_CHANNEL_LCD2)
-                       irq = DISPC_IRQ_VSYNC2;
-               else
-                       goto vout_isr_err;
-
-               if (!(irqstatus & irq))
-                       goto vout_isr_err;
-               break;
-       case OMAP_DISPLAY_TYPE_VENC:
-               fid = omapvid_handle_interlace_display(vout, irqstatus,
-                               ts);
-               if (!fid)
-                       goto vout_isr_err;
-               break;
-       case OMAP_DISPLAY_TYPE_HDMI:
-               if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
-                       goto vout_isr_err;
-               break;
-       default:
-               goto vout_isr_err;
-       }
-
-       if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
-               vout->cur_frm->vbuf.vb2_buf.timestamp = ts;
-               vout->cur_frm->vbuf.sequence = vout->sequence++;
-               vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
-               vout->cur_frm = vout->next_frm;
-       }
-
-       vout->first_int = 0;
-       if (list_empty(&vout->dma_queue))
-               goto vout_isr_err;
-
-       vout->next_frm = list_entry(vout->dma_queue.next,
-                       struct omap_vout_buffer, queue);
-       list_del(&vout->next_frm->queue);
-
-       addr = vout->queued_buf_addr[vout->next_frm->vbuf.vb2_buf.index]
-               + vout->cropped_offset;
-
-       /* First save the configuration in ovelray structure */
-       ret = omapvid_init(vout, addr);
-       if (ret) {
-               printk(KERN_ERR VOUT_NAME
-                       "failed to set overlay info\n");
-               goto vout_isr_err;
-       }
-
-       /* Enable the pipeline and set the Go bit */
-       ret = omapvid_apply_changes(vout);
-       if (ret)
-               printk(KERN_ERR VOUT_NAME "failed to change mode\n");
-
-vout_isr_err:
-       spin_unlock(&vout->vbq_lock);
-}
-
-
-/*
- * V4L2 ioctls
- */
-static int vidioc_querycap(struct file *file, void *fh,
-               struct v4l2_capability *cap)
-{
-       struct omap_vout_device *vout = video_drvdata(file);
-
-       strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
-       strscpy(cap->card, vout->vfd->name, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info),
-                "platform:%s.%d", VOUT_NAME, vout->vid);
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
-                       struct v4l2_fmtdesc *fmt)
-{
-       int index = fmt->index;
-
-       if (index >= NUM_OUTPUT_FORMATS)
-               return -EINVAL;
-
-       fmt->flags = omap_formats[index].flags;
-       fmt->pixelformat = omap_formats[index].pixelformat;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_out(struct file *file, void *fh,
-                       struct v4l2_format *f)
-{
-       struct omap_vout_device *vout = video_drvdata(file);
-
-       f->fmt.pix = vout->pix;
-       return 0;
-
-}
-
-static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
-                       struct v4l2_format *f)
-{
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct omap_video_timings *timing;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct omap_dss_device *dssdev;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-       /* get the display device attached to the overlay */
-       dssdev = ovl->get_device(ovl);
-
-       if (!dssdev)
-               return -EINVAL;
-
-       timing = &dssdev->panel.timings;
-
-       vout->fbuf.fmt.height = timing->y_res;
-       vout->fbuf.fmt.width = timing->x_res;
-
-       omap_vout_try_format(&f->fmt.pix);
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
-                       struct v4l2_format *f)
-{
-       int ret, bpp;
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct omap_video_timings *timing;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct omap_dss_device *dssdev;
-
-       if (vb2_is_busy(&vout->vq))
-               return -EBUSY;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-       dssdev = ovl->get_device(ovl);
-
-       /* get the display device attached to the overlay */
-       if (!dssdev) {
-               ret = -EINVAL;
-               goto s_fmt_vid_out_exit;
-       }
-       timing = &dssdev->panel.timings;
-
-       /* We don't support RGB24-packed mode if vrfb rotation
-        * is enabled*/
-       if ((is_rotation_enabled(vout)) &&
-                       f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
-               ret = -EINVAL;
-               goto s_fmt_vid_out_exit;
-       }
-
-       /* get the framebuffer parameters */
-
-       if (is_rotation_90_or_270(vout)) {
-               vout->fbuf.fmt.height = timing->x_res;
-               vout->fbuf.fmt.width = timing->y_res;
-       } else {
-               vout->fbuf.fmt.height = timing->y_res;
-               vout->fbuf.fmt.width = timing->x_res;
-       }
-
-       /* change to smaller size is OK */
-
-       bpp = omap_vout_try_format(&f->fmt.pix);
-       f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp;
-
-       /* try & set the new output format */
-       vout->bpp = bpp;
-       vout->pix = f->fmt.pix;
-       vout->vrfb_bpp = 1;
-
-       /* If YUYV then vrfb bpp is 2, for  others its 1 */
-       if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat ||
-                       V4L2_PIX_FMT_UYVY == vout->pix.pixelformat)
-               vout->vrfb_bpp = 2;
-
-       /* set default crop and win */
-       omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
-
-       ret = 0;
-
-s_fmt_vid_out_exit:
-       return ret;
-}
-
-static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
-                       struct v4l2_format *f)
-{
-       int ret = 0;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct v4l2_window *win = &f->fmt.win;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-
-       ret = omap_vout_try_window(&vout->fbuf, win);
-
-       if (!ret && !(ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA))
-               win->global_alpha = 0;
-
-       return ret;
-}
-
-static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
-                       struct v4l2_format *f)
-{
-       int ret = 0;
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct v4l2_window *win = &f->fmt.win;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-
-       ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
-       if (!ret) {
-               enum omap_dss_trans_key_type key_type =
-                       OMAP_DSS_COLOR_KEY_GFX_DST;
-               int enable;
-
-               /* Video1 plane does not support global alpha on OMAP3 */
-               if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
-                       vout->win.global_alpha = win->global_alpha;
-               else
-                       win->global_alpha = 0;
-               if (vout->fbuf.flags & (V4L2_FBUF_FLAG_CHROMAKEY |
-                                       V4L2_FBUF_FLAG_SRC_CHROMAKEY))
-                       enable = 1;
-               else
-                       enable = 0;
-               if (vout->fbuf.flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)
-                       key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
-
-               if (ovl->manager && ovl->manager->get_manager_info &&
-                   ovl->manager->set_manager_info) {
-                       struct omap_overlay_manager_info info;
-
-                       ovl->manager->get_manager_info(ovl->manager, &info);
-                       info.trans_enabled = enable;
-                       info.trans_key_type = key_type;
-                       info.trans_key = vout->win.chromakey;
-
-                       if (ovl->manager->set_manager_info(ovl->manager, &info))
-                               return -EINVAL;
-               }
-       }
-       return ret;
-}
-
-static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
-                       struct v4l2_format *f)
-{
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct v4l2_window *win = &f->fmt.win;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-
-       win->w = vout->win.w;
-       win->field = vout->win.field;
-       win->chromakey = vout->win.chromakey;
-       if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
-               win->global_alpha = vout->win.global_alpha;
-       else
-               win->global_alpha = 0;
-       win->clips = NULL;
-       win->clipcount = 0;
-       win->bitmap = NULL;
-       return 0;
-}
-
-static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection *sel)
-{
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct v4l2_pix_format *pix = &vout->pix;
-
-       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return -EINVAL;
-
-       switch (sel->target) {
-       case V4L2_SEL_TGT_CROP:
-               sel->r = vout->crop;
-               break;
-       case V4L2_SEL_TGT_CROP_DEFAULT:
-               omap_vout_default_crop(&vout->pix, &vout->fbuf, &sel->r);
-               break;
-       case V4L2_SEL_TGT_CROP_BOUNDS:
-               /* Width and height are always even */
-               sel->r.width = pix->width & ~1;
-               sel->r.height = pix->height & ~1;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_s_selection(struct file *file, void *fh, struct v4l2_selection *sel)
-{
-       int ret = -EINVAL;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct omapvideo_info *ovid;
-       struct omap_overlay *ovl;
-       struct omap_video_timings *timing;
-       struct omap_dss_device *dssdev;
-
-       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return -EINVAL;
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       if (vb2_is_busy(&vout->vq))
-               return -EBUSY;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-       /* get the display device attached to the overlay */
-       dssdev = ovl->get_device(ovl);
-
-       if (!dssdev) {
-               ret = -EINVAL;
-               goto s_crop_err;
-       }
-
-       timing = &dssdev->panel.timings;
-
-       if (is_rotation_90_or_270(vout)) {
-               vout->fbuf.fmt.height = timing->x_res;
-               vout->fbuf.fmt.width = timing->y_res;
-       } else {
-               vout->fbuf.fmt.height = timing->y_res;
-               vout->fbuf.fmt.width = timing->x_res;
-       }
-
-       ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win,
-                                &vout->fbuf, &sel->r);
-
-s_crop_err:
-       return ret;
-}
-
-static int omap_vout_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct omap_vout_device *vout =
-               container_of(ctrl->handler, struct omap_vout_device, ctrl_handler);
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_ROTATE: {
-               struct omapvideo_info *ovid;
-               int rotation = ctrl->val;
-
-               ovid = &vout->vid_info;
-
-               if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
-                       ret = -ERANGE;
-                       break;
-               }
-
-               if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               if (v4l2_rot_to_dss_rot(rotation, &vout->rotation,
-                                                       vout->mirror)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               break;
-       }
-       case V4L2_CID_BG_COLOR:
-       {
-               struct omap_overlay *ovl;
-               unsigned int color = ctrl->val;
-               struct omap_overlay_manager_info info;
-
-               ovl = vout->vid_info.overlays[0];
-
-               if (!ovl->manager || !ovl->manager->get_manager_info) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               ovl->manager->get_manager_info(ovl->manager, &info);
-               info.default_color = color;
-               if (ovl->manager->set_manager_info(ovl->manager, &info)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               break;
-       }
-       case V4L2_CID_VFLIP:
-       {
-               struct omapvideo_info *ovid;
-               unsigned int mirror = ctrl->val;
-
-               ovid = &vout->vid_info;
-
-               if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
-                       ret = -ERANGE;
-                       break;
-               }
-
-               if (mirror  && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
-                       ret = -EINVAL;
-                       break;
-               }
-               vout->mirror = mirror;
-               break;
-       }
-       default:
-               return -EINVAL;
-       }
-       return ret;
-}
-
-static const struct v4l2_ctrl_ops omap_vout_ctrl_ops = {
-       .s_ctrl = omap_vout_s_ctrl,
-};
-
-static int omap_vout_vb2_queue_setup(struct vb2_queue *vq,
-                                    unsigned int *nbufs,
-                                    unsigned int *num_planes, unsigned int sizes[],
-                                    struct device *alloc_devs[])
-{
-       struct omap_vout_device *vout = vb2_get_drv_priv(vq);
-       int size = vout->pix.sizeimage;
-
-       if (is_rotation_enabled(vout) && vq->num_buffers + *nbufs > VRFB_NUM_BUFS) {
-               *nbufs = VRFB_NUM_BUFS - vq->num_buffers;
-               if (*nbufs == 0)
-                       return -EINVAL;
-       }
-
-       if (*num_planes)
-               return sizes[0] < size ? -EINVAL : 0;
-
-       *num_planes = 1;
-       sizes[0] = size;
-       return 0;
-}
-
-static int omap_vout_vb2_prepare(struct vb2_buffer *vb)
-{
-       struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue);
-       struct omapvideo_info *ovid = &vout->vid_info;
-       struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb);
-       dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-
-       if (vb2_plane_size(vb, 0) < vout->pix.sizeimage) {
-               v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
-                        "%s data will not fit into plane (%lu < %u)\n",
-                       __func__, vb2_plane_size(vb, 0), vout->pix.sizeimage);
-               return -EINVAL;
-       }
-
-       vb2_set_plane_payload(vb, 0, vout->pix.sizeimage);
-       voutbuf->vbuf.field = V4L2_FIELD_NONE;
-
-       vout->queued_buf_addr[vb->index] = buf_phy_addr;
-       if (ovid->rotation_type == VOUT_ROT_VRFB)
-               return omap_vout_prepare_vrfb(vout, vb);
-       return 0;
-}
-
-static void omap_vout_vb2_queue(struct vb2_buffer *vb)
-{
-       struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue);
-       struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb);
-
-       list_add_tail(&voutbuf->queue, &vout->dma_queue);
-}
-
-static int omap_vout_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-       struct omap_vout_device *vout = vb2_get_drv_priv(vq);
-       struct omapvideo_info *ovid = &vout->vid_info;
-       struct omap_vout_buffer *buf, *tmp;
-       dma_addr_t addr = 0;
-       u32 mask = 0;
-       int ret, j;
-
-       /* Get the next frame from the buffer queue */
-       vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next,
-                       struct omap_vout_buffer, queue);
-       /* Remove buffer from the buffer queue */
-       list_del(&vout->cur_frm->queue);
-       /* Initialize field_id and started member */
-       vout->field_id = 0;
-       vout->first_int = 1;
-       vout->sequence = 0;
-
-       if (omap_vout_calculate_offset(vout)) {
-               ret = -EINVAL;
-               goto out;
-       }
-       if (ovid->rotation_type == VOUT_ROT_VRFB)
-               if (omap_vout_vrfb_buffer_setup(vout, &count, 0)) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-       addr = vout->queued_buf_addr[vout->cur_frm->vbuf.vb2_buf.index]
-               + vout->cropped_offset;
-
-       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
-               | DISPC_IRQ_VSYNC2;
-
-       /* First save the configuration in overlay structure */
-       ret = omapvid_init(vout, addr);
-       if (ret) {
-               v4l2_err(&vout->vid_dev->v4l2_dev,
-                               "failed to set overlay info\n");
-               goto streamon_err1;
-       }
-
-       omap_dispc_register_isr(omap_vout_isr, vout, mask);
-
-       /* Enable the pipeline and set the Go bit */
-       ret = omapvid_apply_changes(vout);
-       if (ret)
-               v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
-
-       for (j = 0; j < ovid->num_overlays; j++) {
-               struct omap_overlay *ovl = ovid->overlays[j];
-               struct omap_dss_device *dssdev = ovl->get_device(ovl);
-
-               if (dssdev) {
-                       ret = ovl->enable(ovl);
-                       if (ret)
-                               goto streamon_err1;
-               }
-       }
-       return 0;
-
-streamon_err1:
-       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
-               | DISPC_IRQ_VSYNC2;
-
-       omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
-
-       for (j = 0; j < ovid->num_overlays; j++) {
-               struct omap_overlay *ovl = ovid->overlays[j];
-               struct omap_dss_device *dssdev = ovl->get_device(ovl);
-
-               if (dssdev)
-                       ovl->disable(ovl);
-       }
-       /* Turn of the pipeline */
-       if (omapvid_apply_changes(vout))
-               v4l2_err(&vout->vid_dev->v4l2_dev,
-                        "failed to change mode in streamoff\n");
-
-out:
-       vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
-       list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) {
-               list_del(&buf->queue);
-               vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
-       }
-       return ret;
-}
-
-static void omap_vout_vb2_stop_streaming(struct vb2_queue *vq)
-{
-       struct omap_vout_device *vout = vb2_get_drv_priv(vq);
-       struct omapvideo_info *ovid = &vout->vid_info;
-       struct omap_vout_buffer *buf, *tmp;
-       u32 mask = 0;
-       int j;
-
-       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
-               | DISPC_IRQ_VSYNC2;
-
-       omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
-
-       for (j = 0; j < ovid->num_overlays; j++) {
-               struct omap_overlay *ovl = ovid->overlays[j];
-               struct omap_dss_device *dssdev = ovl->get_device(ovl);
-
-               if (dssdev)
-                       ovl->disable(ovl);
-       }
-       /* Turn of the pipeline */
-       if (omapvid_apply_changes(vout))
-               v4l2_err(&vout->vid_dev->v4l2_dev,
-                        "failed to change mode in streamoff\n");
-
-       if (vout->next_frm != vout->cur_frm)
-               vb2_buffer_done(&vout->next_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
-       vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
-       list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) {
-               list_del(&buf->queue);
-               vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
-       }
-}
-
-static int vidioc_s_fbuf(struct file *file, void *fh,
-                               const struct v4l2_framebuffer *a)
-{
-       int enable = 0;
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct omap_overlay_manager_info info;
-       enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-
-       /* OMAP DSS doesn't support Source and Destination color
-          key together */
-       if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
-                       (a->flags & V4L2_FBUF_FLAG_CHROMAKEY))
-               return -EINVAL;
-       /* OMAP DSS Doesn't support the Destination color key
-          and alpha blending together */
-       if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) &&
-                       (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA))
-               return -EINVAL;
-
-       if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) {
-               vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
-               key_type =  OMAP_DSS_COLOR_KEY_VID_SRC;
-       } else
-               vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY;
-
-       if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) {
-               vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
-               key_type =  OMAP_DSS_COLOR_KEY_GFX_DST;
-       } else
-               vout->fbuf.flags &=  ~V4L2_FBUF_FLAG_CHROMAKEY;
-
-       if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY |
-                               V4L2_FBUF_FLAG_SRC_CHROMAKEY))
-               enable = 1;
-       else
-               enable = 0;
-       if (ovl->manager && ovl->manager->get_manager_info &&
-                       ovl->manager->set_manager_info) {
-
-               ovl->manager->get_manager_info(ovl->manager, &info);
-               info.trans_enabled = enable;
-               info.trans_key_type = key_type;
-               info.trans_key = vout->win.chromakey;
-
-               if (ovl->manager->set_manager_info(ovl->manager, &info))
-                       return -EINVAL;
-       }
-       if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) {
-               vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
-               enable = 1;
-       } else {
-               vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
-               enable = 0;
-       }
-       if (ovl->manager && ovl->manager->get_manager_info &&
-                       ovl->manager->set_manager_info) {
-               ovl->manager->get_manager_info(ovl->manager, &info);
-               /* enable this only if there is no zorder cap */
-               if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
-                       info.partial_alpha_enabled = enable;
-               if (ovl->manager->set_manager_info(ovl->manager, &info))
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int vidioc_g_fbuf(struct file *file, void *fh,
-               struct v4l2_framebuffer *a)
-{
-       struct omap_overlay *ovl;
-       struct omapvideo_info *ovid;
-       struct omap_vout_device *vout = video_drvdata(file);
-       struct omap_overlay_manager_info info;
-       struct omap_video_timings *timing;
-       struct omap_dss_device *dssdev;
-
-       ovid = &vout->vid_info;
-       ovl = ovid->overlays[0];
-       /* get the display device attached to the overlay */
-       dssdev = ovl->get_device(ovl);
-
-       if (!dssdev)
-               return -EINVAL;
-
-       timing = &dssdev->panel.timings;
-
-       vout->fbuf.fmt.height = timing->y_res;
-       vout->fbuf.fmt.width = timing->x_res;
-       a->fmt.field = V4L2_FIELD_NONE;
-       a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
-       a->fmt.pixelformat = V4L2_PIX_FMT_RGBA32;
-       a->fmt.height = vout->fbuf.fmt.height;
-       a->fmt.width = vout->fbuf.fmt.width;
-       a->fmt.bytesperline = vout->fbuf.fmt.width * 4;
-       a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline;
-       a->base = vout->fbuf.base;
-
-       a->flags = vout->fbuf.flags;
-       a->capability = vout->fbuf.capability;
-       a->flags &= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY | V4L2_FBUF_FLAG_CHROMAKEY |
-                     V4L2_FBUF_FLAG_LOCAL_ALPHA);
-
-       if (ovl->manager && ovl->manager->get_manager_info) {
-               ovl->manager->get_manager_info(ovl->manager, &info);
-               if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC)
-                       a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
-               if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
-                       a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
-               if (info.partial_alpha_enabled)
-                       a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
-       }
-
-       return 0;
-}
-
-static int vidioc_enum_output(struct file *file, void *priv_fh,
-                             struct v4l2_output *out)
-{
-       if (out->index)
-               return -EINVAL;
-       snprintf(out->name, sizeof(out->name), "Overlay");
-       out->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-       return 0;
-}
-
-static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i)
-{
-       return i ? -EINVAL : 0;
-}
-
-static const struct v4l2_ioctl_ops vout_ioctl_ops = {
-       .vidioc_querycap                        = vidioc_querycap,
-       .vidioc_enum_fmt_vid_out                = vidioc_enum_fmt_vid_out,
-       .vidioc_g_fmt_vid_out                   = vidioc_g_fmt_vid_out,
-       .vidioc_try_fmt_vid_out                 = vidioc_try_fmt_vid_out,
-       .vidioc_s_fmt_vid_out                   = vidioc_s_fmt_vid_out,
-       .vidioc_s_fbuf                          = vidioc_s_fbuf,
-       .vidioc_g_fbuf                          = vidioc_g_fbuf,
-       .vidioc_try_fmt_vid_out_overlay         = vidioc_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_out_overlay           = vidioc_s_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_out_overlay           = vidioc_g_fmt_vid_overlay,
-       .vidioc_g_selection                     = vidioc_g_selection,
-       .vidioc_s_selection                     = vidioc_s_selection,
-       .vidioc_enum_output                     = vidioc_enum_output,
-       .vidioc_g_output                        = vidioc_g_output,
-       .vidioc_s_output                        = vidioc_s_output,
-       .vidioc_reqbufs                         = vb2_ioctl_reqbufs,
-       .vidioc_create_bufs                     = vb2_ioctl_create_bufs,
-       .vidioc_querybuf                        = vb2_ioctl_querybuf,
-       .vidioc_qbuf                            = vb2_ioctl_qbuf,
-       .vidioc_dqbuf                           = vb2_ioctl_dqbuf,
-       .vidioc_expbuf                          = vb2_ioctl_expbuf,
-       .vidioc_streamon                        = vb2_ioctl_streamon,
-       .vidioc_streamoff                       = vb2_ioctl_streamoff,
-       .vidioc_subscribe_event                 = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event               = v4l2_event_unsubscribe,
-};
-
-static const struct v4l2_file_operations omap_vout_fops = {
-       .owner          = THIS_MODULE,
-       .unlocked_ioctl = video_ioctl2,
-       .poll           = vb2_fop_poll,
-       .mmap           = vb2_fop_mmap,
-       .open           = v4l2_fh_open,
-       .release        = vb2_fop_release,
-};
-
-static const struct vb2_ops omap_vout_vb2_ops = {
-       .queue_setup            = omap_vout_vb2_queue_setup,
-       .buf_queue              = omap_vout_vb2_queue,
-       .buf_prepare            = omap_vout_vb2_prepare,
-       .start_streaming        = omap_vout_vb2_start_streaming,
-       .stop_streaming         = omap_vout_vb2_stop_streaming,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-};
-
-/* Init functions used during driver initialization */
-/* Initial setup of video_data */
-static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
-{
-       struct video_device *vfd;
-       struct v4l2_pix_format *pix;
-       struct omap_overlay *ovl = vout->vid_info.overlays[0];
-       struct omap_dss_device *display = ovl->get_device(ovl);
-       struct v4l2_ctrl_handler *hdl;
-       struct vb2_queue *vq;
-       int ret;
-
-       /* set the default pix */
-       pix = &vout->pix;
-
-       /* Set the default picture of QVGA  */
-       pix->width = QQVGA_WIDTH;
-       pix->height = QQVGA_HEIGHT;
-
-       /* Default pixel format is RGB 5-6-5 */
-       pix->pixelformat = V4L2_PIX_FMT_RGB565;
-       pix->field = V4L2_FIELD_NONE;
-       pix->bytesperline = pix->width * 2;
-       pix->sizeimage = pix->bytesperline * pix->height;
-       pix->colorspace = V4L2_COLORSPACE_SRGB;
-
-       vout->bpp = RGB565_BPP;
-       vout->fbuf.fmt.width  =  display->panel.timings.x_res;
-       vout->fbuf.fmt.height =  display->panel.timings.y_res;
-       vout->cropped_offset = 0;
-
-       /* Set the data structures for the overlay parameters*/
-       vout->fbuf.flags = V4L2_FBUF_FLAG_OVERLAY;
-       vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
-               V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY |
-               V4L2_FBUF_CAP_EXTERNOVERLAY;
-       if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) {
-               vout->win.global_alpha = 255;
-               vout->fbuf.capability |= V4L2_FBUF_CAP_GLOBAL_ALPHA;
-               vout->fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
-       } else {
-               vout->win.global_alpha = 0;
-       }
-       vout->win.field = V4L2_FIELD_NONE;
-
-       omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
-
-       hdl = &vout->ctrl_handler;
-       v4l2_ctrl_handler_init(hdl, 3);
-       if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) {
-               v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
-                                 V4L2_CID_ROTATE, 0, 270, 90, 0);
-               v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
-                                 V4L2_CID_VFLIP, 0, 1, 1, 0);
-       }
-       v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
-                         V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0);
-       if (hdl->error)
-               return hdl->error;
-
-       vout->rotation = 0;
-       vout->mirror = false;
-       INIT_LIST_HEAD(&vout->dma_queue);
-       if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
-               vout->vrfb_bpp = 2;
-
-       /* initialize the video_device struct */
-       vfd = vout->vfd = video_device_alloc();
-
-       if (!vfd) {
-               printk(KERN_ERR VOUT_NAME
-                      ": could not allocate video device struct\n");
-               v4l2_ctrl_handler_free(hdl);
-               return -ENOMEM;
-       }
-       vfd->ctrl_handler = hdl;
-       vfd->release = video_device_release;
-       vfd->ioctl_ops = &vout_ioctl_ops;
-
-       strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
-
-       vfd->fops = &omap_vout_fops;
-       vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
-       vfd->vfl_dir = VFL_DIR_TX;
-       vfd->minor = -1;
-       vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
-                          V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
-       mutex_init(&vout->lock);
-
-       vq = &vout->vq;
-       vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       vq->io_modes = VB2_MMAP | VB2_DMABUF;
-       vq->drv_priv = vout;
-       vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-       vq->buf_struct_size = sizeof(struct omap_vout_buffer);
-       vq->dev = vfd->v4l2_dev->dev;
-
-       vq->ops = &omap_vout_vb2_ops;
-       vq->mem_ops = &vb2_dma_contig_memops;
-       vq->lock = &vout->lock;
-       vq->min_buffers_needed = 1;
-       vfd->queue = vq;
-
-       ret = vb2_queue_init(vq);
-       if (ret) {
-               v4l2_ctrl_handler_free(hdl);
-               video_device_release(vfd);
-       }
-       return ret;
-}
-
-/* Setup video buffers */
-static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
-               int vid_num)
-{
-       struct omapvideo_info *ovid;
-       struct omap_vout_device *vout;
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
-       struct omap2video_device *vid_dev =
-               container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
-       int ret = 0;
-
-       vout = vid_dev->vouts[vid_num];
-       ovid = &vout->vid_info;
-
-       if (ovid->rotation_type == VOUT_ROT_VRFB) {
-               bool static_vrfb_allocation = (vid_num == 0) ?
-                       vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
-               ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
-                               static_vrfb_allocation);
-       }
-       return ret;
-}
-
-/* Create video out devices */
-static int __init omap_vout_create_video_devices(struct platform_device *pdev)
-{
-       int ret = 0, k;
-       struct omap_vout_device *vout;
-       struct video_device *vfd = NULL;
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
-       struct omap2video_device *vid_dev = container_of(v4l2_dev,
-                       struct omap2video_device, v4l2_dev);
-       struct omap_overlay *ovl = vid_dev->overlays[0];
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       for (k = 0; k < pdev->num_resources; k++) {
-
-               vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
-               if (!vout) {
-                       dev_err(&pdev->dev, ": could not allocate memory\n");
-                       return -ENOMEM;
-               }
-
-               vout->vid = k;
-               vid_dev->vouts[k] = vout;
-               vout->vid_dev = vid_dev;
-               /* Select video2 if only 1 overlay is controlled by V4L2 */
-               if (pdev->num_resources == 1)
-                       vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
-               else
-                       /* Else select video1 and video2 one by one. */
-                       vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
-               vout->vid_info.num_overlays = 1;
-               vout->vid_info.id = k + 1;
-               spin_lock_init(&vout->vbq_lock);
-               /*
-                * Set the framebuffer base, this allows applications to find
-                * the fb corresponding to this overlay.
-                *
-                * To be precise: fbuf.base should match smem_start of
-                * struct fb_fix_screeninfo.
-                */
-               vout->fbuf.base = (void *)(uintptr_t)info.paddr;
-
-               /* Set VRFB as rotation_type for omap2 and omap3 */
-               if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
-                       vout->vid_info.rotation_type = VOUT_ROT_VRFB;
-
-               /* Setup the default configuration for the video devices
-                */
-               if (omap_vout_setup_video_data(vout) != 0) {
-                       ret = -ENOMEM;
-                       goto error;
-               }
-
-               /* Allocate default number of buffers for the video streaming
-                * and reserve the VRFB space for rotation
-                */
-               if (omap_vout_setup_video_bufs(pdev, k) != 0) {
-                       ret = -ENOMEM;
-                       goto error1;
-               }
-
-               /* Register the Video device with V4L2
-                */
-               vfd = vout->vfd;
-               if (video_register_device(vfd, VFL_TYPE_VIDEO, -1) < 0) {
-                       dev_err(&pdev->dev,
-                               ": Could not register Video for Linux device\n");
-                       vfd->minor = -1;
-                       ret = -ENODEV;
-                       goto error2;
-               }
-               video_set_drvdata(vfd, vout);
-
-               dev_info(&pdev->dev,
-                        ": registered and initialized video device %d\n",
-                        vfd->minor);
-               if (k == (pdev->num_resources - 1))
-                       return 0;
-
-               continue;
-error2:
-               if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
-                       omap_vout_release_vrfb(vout);
-error1:
-               video_device_release(vfd);
-error:
-               kfree(vout);
-               return ret;
-       }
-
-       return -ENODEV;
-}
-/* Driver functions */
-static void omap_vout_cleanup_device(struct omap_vout_device *vout)
-{
-       struct video_device *vfd;
-       struct omapvideo_info *ovid;
-
-       if (!vout)
-               return;
-
-       vfd = vout->vfd;
-       ovid = &vout->vid_info;
-       if (vfd) {
-               if (!video_is_registered(vfd)) {
-                       /*
-                        * The device was never registered, so release the
-                        * video_device struct directly.
-                        */
-                       video_device_release(vfd);
-               } else {
-                       /*
-                        * The unregister function will release the video_device
-                        * struct as well as unregistering it.
-                        */
-                       video_unregister_device(vfd);
-               }
-       }
-       v4l2_ctrl_handler_free(&vout->ctrl_handler);
-       if (ovid->rotation_type == VOUT_ROT_VRFB) {
-               omap_vout_release_vrfb(vout);
-               /* Free the VRFB buffer if allocated
-                * init time
-                */
-               if (vout->vrfb_static_allocation)
-                       omap_vout_free_vrfb_buffers(vout);
-       }
-
-       kfree(vout);
-}
-
-static int omap_vout_remove(struct platform_device *pdev)
-{
-       int k;
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
-       struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
-                       omap2video_device, v4l2_dev);
-
-       v4l2_device_unregister(v4l2_dev);
-       for (k = 0; k < pdev->num_resources; k++)
-               omap_vout_cleanup_device(vid_dev->vouts[k]);
-
-       for (k = 0; k < vid_dev->num_displays; k++) {
-               if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
-                       vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);
-
-               omap_dss_put_device(vid_dev->displays[k]);
-       }
-       kfree(vid_dev);
-       return 0;
-}
-
-static int __init omap_vout_probe(struct platform_device *pdev)
-{
-       int ret = 0, i;
-       struct omap_overlay *ovl;
-       struct omap_dss_device *dssdev = NULL;
-       struct omap_dss_device *def_display;
-       struct omap2video_device *vid_dev = NULL;
-
-       if (omapdss_is_initialized() == false)
-               return -EPROBE_DEFER;
-
-       ret = omapdss_compat_init();
-       if (ret) {
-               dev_err(&pdev->dev, "failed to init dss\n");
-               return ret;
-       }
-
-       if (pdev->num_resources == 0) {
-               dev_err(&pdev->dev, "probed for an unknown device\n");
-               ret = -ENODEV;
-               goto err_dss_init;
-       }
-
-       vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
-       if (vid_dev == NULL) {
-               ret = -ENOMEM;
-               goto err_dss_init;
-       }
-
-       vid_dev->num_displays = 0;
-       for_each_dss_dev(dssdev) {
-               omap_dss_get_device(dssdev);
-
-               if (!dssdev->driver) {
-                       dev_warn(&pdev->dev, "no driver for display: %s\n",
-                                       dssdev->name);
-                       omap_dss_put_device(dssdev);
-                       continue;
-               }
-
-               vid_dev->displays[vid_dev->num_displays++] = dssdev;
-       }
-
-       if (vid_dev->num_displays == 0) {
-               dev_err(&pdev->dev, "no displays\n");
-               ret = -EINVAL;
-               goto probe_err0;
-       }
-
-       vid_dev->num_overlays = omap_dss_get_num_overlays();
-       for (i = 0; i < vid_dev->num_overlays; i++)
-               vid_dev->overlays[i] = omap_dss_get_overlay(i);
-
-       vid_dev->num_managers = omap_dss_get_num_overlay_managers();
-       for (i = 0; i < vid_dev->num_managers; i++)
-               vid_dev->managers[i] = omap_dss_get_overlay_manager(i);
-
-       /* Get the Video1 overlay and video2 overlay.
-        * Setup the Display attached to that overlays
-        */
-       for (i = 1; i < vid_dev->num_overlays; i++) {
-               ovl = omap_dss_get_overlay(i);
-               dssdev = ovl->get_device(ovl);
-
-               if (dssdev) {
-                       def_display = dssdev;
-               } else {
-                       dev_warn(&pdev->dev, "cannot find display\n");
-                       def_display = NULL;
-               }
-               if (def_display) {
-                       struct omap_dss_driver *dssdrv = def_display->driver;
-
-                       ret = dssdrv->enable(def_display);
-                       if (ret) {
-                               /* Here we are not considering a error
-                                *  as display may be enabled by frame
-                                *  buffer driver
-                                */
-                               dev_warn(&pdev->dev,
-                                       "'%s' Display already enabled\n",
-                                       def_display->name);
-                       }
-               }
-       }
-
-       if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) {
-               dev_err(&pdev->dev, "v4l2_device_register failed\n");
-               ret = -ENODEV;
-               goto probe_err1;
-       }
-
-       ret = omap_vout_create_video_devices(pdev);
-       if (ret)
-               goto probe_err2;
-
-       for (i = 0; i < vid_dev->num_displays; i++) {
-               struct omap_dss_device *display = vid_dev->displays[i];
-
-               if (display->driver->update)
-                       display->driver->update(display, 0, 0,
-                                       display->panel.timings.x_res,
-                                       display->panel.timings.y_res);
-       }
-       return 0;
-
-probe_err2:
-       v4l2_device_unregister(&vid_dev->v4l2_dev);
-probe_err1:
-       for (i = 1; i < vid_dev->num_overlays; i++) {
-               def_display = NULL;
-               ovl = omap_dss_get_overlay(i);
-               dssdev = ovl->get_device(ovl);
-
-               if (dssdev)
-                       def_display = dssdev;
-
-               if (def_display && def_display->driver)
-                       def_display->driver->disable(def_display);
-       }
-probe_err0:
-       kfree(vid_dev);
-err_dss_init:
-       omapdss_compat_uninit();
-       return ret;
-}
-
-static struct platform_driver omap_vout_driver = {
-       .driver = {
-               .name = VOUT_NAME,
-       },
-       .remove = omap_vout_remove,
-};
-
-static int __init omap_vout_init(void)
-{
-       if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) {
-               printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void omap_vout_cleanup(void)
-{
-       platform_driver_unregister(&omap_vout_driver);
-}
-
-late_initcall(omap_vout_init);
-module_exit(omap_vout_cleanup);
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
deleted file mode 100644 (file)
index 0cfa016..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * omap_vout_vrfb.c
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-
-#include <linux/sched.h>
-#include <linux/platform_device.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-device.h>
-
-#include <video/omapvrfb.h>
-
-#include "omap_voutdef.h"
-#include "omap_voutlib.h"
-#include "omap_vout_vrfb.h"
-
-#define OMAP_DMA_NO_DEVICE     0
-
-/*
- * Function for allocating video buffers
- */
-static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
-               unsigned int *count, int startindex)
-{
-       int i, j;
-
-       for (i = 0; i < *count; i++) {
-               if (!vout->smsshado_virt_addr[i]) {
-                       vout->smsshado_virt_addr[i] =
-                               omap_vout_alloc_buffer(vout->smsshado_size,
-                                               &vout->smsshado_phy_addr[i]);
-               }
-               if (!vout->smsshado_virt_addr[i] && startindex != -1) {
-                       if (vout->vq.memory == V4L2_MEMORY_MMAP && i >= startindex)
-                               break;
-               }
-               if (!vout->smsshado_virt_addr[i]) {
-                       for (j = 0; j < i; j++) {
-                               omap_vout_free_buffer(
-                                               vout->smsshado_virt_addr[j],
-                                               vout->smsshado_size);
-                               vout->smsshado_virt_addr[j] = 0;
-                               vout->smsshado_phy_addr[j] = 0;
-                       }
-                       *count = 0;
-                       return -ENOMEM;
-               }
-               memset((void *)(long)vout->smsshado_virt_addr[i], 0,
-                      vout->smsshado_size);
-       }
-       return 0;
-}
-
-/*
- * Wakes up the application once the DMA transfer to VRFB space is completed.
- */
-static void omap_vout_vrfb_dma_tx_callback(void *data)
-{
-       struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
-
-       t->tx_status = 1;
-       wake_up_interruptible(&t->wait);
-}
-
-/*
- * Free VRFB buffers
- */
-void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
-{
-       int j;
-
-       for (j = 0; j < VRFB_NUM_BUFS; j++) {
-               if (vout->smsshado_virt_addr[j]) {
-                       omap_vout_free_buffer(vout->smsshado_virt_addr[j],
-                                             vout->smsshado_size);
-                       vout->smsshado_virt_addr[j] = 0;
-                       vout->smsshado_phy_addr[j] = 0;
-               }
-       }
-}
-
-int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
-                             bool static_vrfb_allocation)
-{
-       int ret = 0, i, j;
-       struct omap_vout_device *vout;
-       struct video_device *vfd;
-       dma_cap_mask_t mask;
-       int image_width, image_height;
-       int vrfb_num_bufs = VRFB_NUM_BUFS;
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
-       struct omap2video_device *vid_dev =
-               container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
-
-       vout = vid_dev->vouts[vid_num];
-       vfd = vout->vfd;
-
-       for (i = 0; i < VRFB_NUM_BUFS; i++) {
-               if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
-                       dev_info(&pdev->dev, ": VRFB allocation failed\n");
-                       for (j = 0; j < i; j++)
-                               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
-                       return -ENOMEM;
-               }
-       }
-
-       /* Calculate VRFB memory size */
-       /* allocate for worst case size */
-       image_width = VID_MAX_WIDTH / TILE_SIZE;
-       if (VID_MAX_WIDTH % TILE_SIZE)
-               image_width++;
-
-       image_width = image_width * TILE_SIZE;
-       image_height = VID_MAX_HEIGHT / TILE_SIZE;
-
-       if (VID_MAX_HEIGHT % TILE_SIZE)
-               image_height++;
-
-       image_height = image_height * TILE_SIZE;
-       vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
-
-       /*
-        * Request and Initialize DMA, for DMA based VRFB transfer
-        */
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_INTERLEAVE, mask);
-       vout->vrfb_dma_tx.chan = dma_request_chan_by_mask(&mask);
-       if (IS_ERR(vout->vrfb_dma_tx.chan)) {
-               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
-       } else {
-               size_t xt_size = sizeof(struct dma_interleaved_template) +
-                                sizeof(struct data_chunk);
-
-               vout->vrfb_dma_tx.xt = kzalloc(xt_size, GFP_KERNEL);
-               if (!vout->vrfb_dma_tx.xt) {
-                       dma_release_channel(vout->vrfb_dma_tx.chan);
-                       vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
-               }
-       }
-
-       if (vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED)
-               dev_info(&pdev->dev,
-                        ": failed to allocate DMA Channel for video%d\n",
-                        vfd->minor);
-
-       init_waitqueue_head(&vout->vrfb_dma_tx.wait);
-
-       /*
-        * statically allocated the VRFB buffer is done through
-        * command line arguments
-        */
-       if (static_vrfb_allocation) {
-               if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
-                       ret =  -ENOMEM;
-                       goto release_vrfb_ctx;
-               }
-               vout->vrfb_static_allocation = true;
-       }
-       return 0;
-
-release_vrfb_ctx:
-       for (j = 0; j < VRFB_NUM_BUFS; j++)
-               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
-       return ret;
-}
-
-/*
- * Release the VRFB context once the module exits
- */
-void omap_vout_release_vrfb(struct omap_vout_device *vout)
-{
-       int i;
-
-       for (i = 0; i < VRFB_NUM_BUFS; i++)
-               omap_vrfb_release_ctx(&vout->vrfb_context[i]);
-
-       if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
-               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
-               kfree(vout->vrfb_dma_tx.xt);
-               dmaengine_terminate_sync(vout->vrfb_dma_tx.chan);
-               dma_release_channel(vout->vrfb_dma_tx.chan);
-       }
-}
-
-/*
- * Allocate the buffers for the VRFB space.  Data is copied from V4L2
- * buffers to the VRFB buffers using the DMA engine.
- */
-int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
-                         unsigned int *count, unsigned int startindex)
-{
-       int i;
-       bool yuv_mode;
-
-       if (!is_rotation_enabled(vout))
-               return 0;
-
-       /* If rotation is enabled, allocate memory for VRFB space also */
-       *count = *count > VRFB_NUM_BUFS ? VRFB_NUM_BUFS : *count;
-
-       /* Allocate the VRFB buffers only if the buffers are not
-        * allocated during init time.
-        */
-       if (!vout->vrfb_static_allocation)
-               if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
-                       return -ENOMEM;
-
-       if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
-                       vout->dss_mode == OMAP_DSS_COLOR_UYVY)
-               yuv_mode = true;
-       else
-               yuv_mode = false;
-
-       for (i = 0; i < *count; i++)
-               omap_vrfb_setup(&vout->vrfb_context[i],
-                               vout->smsshado_phy_addr[i], vout->pix.width,
-                               vout->pix.height, vout->bpp, yuv_mode);
-
-       return 0;
-}
-
-int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
-                          struct vb2_buffer *vb)
-{
-       struct dma_async_tx_descriptor *tx;
-       enum dma_ctrl_flags flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
-       struct dma_chan *chan = vout->vrfb_dma_tx.chan;
-       struct dma_interleaved_template *xt = vout->vrfb_dma_tx.xt;
-       dma_cookie_t cookie;
-       dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-       enum dma_status status;
-       enum dss_rotation rotation;
-       size_t dst_icg;
-       u32 pixsize;
-
-       if (!is_rotation_enabled(vout))
-               return 0;
-
-       /* If rotation is enabled, copy input buffer into VRFB
-        * memory space using DMA. We are copying input buffer
-        * into VRFB memory space of desired angle and DSS will
-        * read image VRFB memory for 0 degree angle
-        */
-
-       pixsize = vout->bpp * vout->vrfb_bpp;
-       dst_icg = MAX_PIXELS_PER_LINE * pixsize - vout->pix.width * vout->bpp;
-
-       xt->src_start = buf_phy_addr;
-       xt->dst_start = vout->vrfb_context[vb->index].paddr[0];
-
-       xt->numf = vout->pix.height;
-       xt->frame_size = 1;
-       xt->sgl[0].size = vout->pix.width * vout->bpp;
-       xt->sgl[0].icg = dst_icg;
-
-       xt->dir = DMA_MEM_TO_MEM;
-       xt->src_sgl = false;
-       xt->src_inc = true;
-       xt->dst_sgl = true;
-       xt->dst_inc = true;
-
-       tx = dmaengine_prep_interleaved_dma(chan, xt, flags);
-       if (tx == NULL) {
-               pr_err("%s: DMA interleaved prep error\n", __func__);
-               return -EINVAL;
-       }
-
-       tx->callback = omap_vout_vrfb_dma_tx_callback;
-       tx->callback_param = &vout->vrfb_dma_tx;
-
-       cookie = dmaengine_submit(tx);
-       if (dma_submit_error(cookie)) {
-               pr_err("%s: dmaengine_submit failed (%d)\n", __func__, cookie);
-               return -EINVAL;
-       }
-
-       vout->vrfb_dma_tx.tx_status = 0;
-       dma_async_issue_pending(chan);
-
-       wait_event_interruptible_timeout(vout->vrfb_dma_tx.wait,
-                                        vout->vrfb_dma_tx.tx_status == 1,
-                                        VRFB_TX_TIMEOUT);
-
-       status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
-
-       if (vout->vrfb_dma_tx.tx_status == 0) {
-               pr_err("%s: Timeout while waiting for DMA\n", __func__);
-               dmaengine_terminate_sync(chan);
-               return -EINVAL;
-       } else if (status != DMA_COMPLETE) {
-               pr_err("%s: DMA completion %s status\n", __func__,
-                      status == DMA_ERROR ? "error" : "busy");
-               dmaengine_terminate_sync(chan);
-               return -EINVAL;
-       }
-
-       /* Store buffers physical address into an array. Addresses
-        * from this array will be used to configure DSS */
-       rotation = calc_rotation(vout);
-       vout->queued_buf_addr[vb->index] =
-               vout->vrfb_context[vb->index].paddr[rotation];
-       return 0;
-}
-
-/*
- * Calculate the buffer offsets from which the streaming should
- * start. This offset calculation is mainly required because of
- * the VRFB 32 pixels alignment with rotation.
- */
-void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout)
-{
-       enum dss_rotation rotation;
-       bool mirroring = vout->mirror;
-       struct v4l2_rect *crop = &vout->crop;
-       struct v4l2_pix_format *pix = &vout->pix;
-       int *cropped_offset = &vout->cropped_offset;
-       int vr_ps = 1, ps = 2, temp_ps = 2;
-       int offset = 0, ctop = 0, cleft = 0, line_length = 0;
-
-       rotation = calc_rotation(vout);
-
-       if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
-                       V4L2_PIX_FMT_UYVY == pix->pixelformat) {
-               if (is_rotation_enabled(vout)) {
-                       /*
-                        * ps    - Actual pixel size for YUYV/UYVY for
-                        *         VRFB/Mirroring is 4 bytes
-                        * vr_ps - Virtually pixel size for YUYV/UYVY is
-                        *         2 bytes
-                        */
-                       ps = 4;
-                       vr_ps = 2;
-               } else {
-                       ps = 2; /* otherwise the pixel size is 2 byte */
-               }
-       } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
-               ps = 4;
-       } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
-               ps = 3;
-       }
-       vout->ps = ps;
-       vout->vr_ps = vr_ps;
-
-       if (is_rotation_enabled(vout)) {
-               line_length = MAX_PIXELS_PER_LINE;
-               ctop = (pix->height - crop->height) - crop->top;
-               cleft = (pix->width - crop->width) - crop->left;
-       } else {
-               line_length = pix->width;
-       }
-       vout->line_length = line_length;
-       switch (rotation) {
-       case dss_rotation_90_degree:
-               offset = vout->vrfb_context[0].yoffset *
-                       vout->vrfb_context[0].bytespp;
-               temp_ps = ps / vr_ps;
-               if (!mirroring) {
-                       *cropped_offset = offset + line_length *
-                               temp_ps * cleft + crop->top * temp_ps;
-               } else {
-                       *cropped_offset = offset + line_length * temp_ps *
-                               cleft + crop->top * temp_ps + (line_length *
-                               ((crop->width / (vr_ps)) - 1) * ps);
-               }
-               break;
-       case dss_rotation_180_degree:
-               offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
-                       vout->vrfb_context[0].bytespp) +
-                       (vout->vrfb_context[0].xoffset *
-                       vout->vrfb_context[0].bytespp));
-               if (!mirroring) {
-                       *cropped_offset = offset + (line_length * ps * ctop) +
-                               (cleft / vr_ps) * ps;
-
-               } else {
-                       *cropped_offset = offset + (line_length * ps * ctop) +
-                               (cleft / vr_ps) * ps + (line_length *
-                               (crop->height - 1) * ps);
-               }
-               break;
-       case dss_rotation_270_degree:
-               offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
-                       vout->vrfb_context[0].bytespp;
-               temp_ps = ps / vr_ps;
-               if (!mirroring) {
-                       *cropped_offset = offset + line_length *
-                           temp_ps * crop->left + ctop * ps;
-               } else {
-                       *cropped_offset = offset + line_length *
-                               temp_ps * crop->left + ctop * ps +
-                               (line_length * ((crop->width / vr_ps) - 1) *
-                                ps);
-               }
-               break;
-       case dss_rotation_0_degree:
-               if (!mirroring) {
-                       *cropped_offset = (line_length * ps) *
-                               crop->top + (crop->left / vr_ps) * ps;
-               } else {
-                       *cropped_offset = (line_length * ps) *
-                               crop->top + (crop->left / vr_ps) * ps +
-                               (line_length * (crop->height - 1) * ps);
-               }
-               break;
-       default:
-               *cropped_offset = (line_length * ps * crop->top) /
-                       vr_ps + (crop->left * ps) / vr_ps +
-                       ((crop->width / vr_ps) - 1) * ps;
-               break;
-       }
-}
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.h b/drivers/media/platform/omap/omap_vout_vrfb.h
deleted file mode 100644 (file)
index 40bc9e5..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * omap_vout_vrfb.h
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-
-#ifndef OMAP_VOUT_VRFB_H
-#define OMAP_VOUT_VRFB_H
-
-#ifdef CONFIG_VIDEO_OMAP2_VOUT_VRFB
-void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout);
-int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
-                       bool static_vrfb_allocation);
-void omap_vout_release_vrfb(struct omap_vout_device *vout);
-int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
-                       unsigned int *count, unsigned int startindex);
-int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
-                       struct vb2_buffer *vb);
-void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout);
-#else
-static inline void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) { };
-static inline int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
-                       bool static_vrfb_allocation)
-               { return 0; };
-static inline void omap_vout_release_vrfb(struct omap_vout_device *vout) { };
-static inline int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
-                       unsigned int *count, unsigned int startindex)
-               { return 0; };
-static inline int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
-                       struct vb2_buffer *vb)
-               { return 0; };
-static inline void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout) { };
-#endif
-
-#endif
diff --git a/drivers/media/platform/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h
deleted file mode 100644 (file)
index b586193..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * omap_voutdef.h
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef OMAP_VOUTDEF_H
-#define OMAP_VOUTDEF_H
-
-#include <media/videobuf2-dma-contig.h>
-#include <media/v4l2-ctrls.h>
-#include <video/omapfb_dss.h>
-#include <video/omapvrfb.h>
-#include <linux/dmaengine.h>
-
-#define YUYV_BPP        2
-#define RGB565_BPP      2
-#define RGB24_BPP       3
-#define RGB32_BPP       4
-#define TILE_SIZE       32
-#define YUYV_VRFB_BPP   2
-#define RGB_VRFB_BPP    1
-#define MAX_CID                3
-#define MAC_VRFB_CTXS  4
-#define MAX_VOUT_DEV   2
-#define MAX_OVLS       3
-#define MAX_DISPLAYS   10
-#define MAX_MANAGERS   3
-
-#define QQVGA_WIDTH            160
-#define QQVGA_HEIGHT           120
-
-/* Max Resolution supported by the driver */
-#define VID_MAX_WIDTH          1280    /* Largest width */
-#define VID_MAX_HEIGHT         720     /* Largest height */
-
-/* Minimum requirement is 2x2 for DSS */
-#define VID_MIN_WIDTH          2
-#define VID_MIN_HEIGHT         2
-
-/* 2048 x 2048 is max res supported by OMAP display controller */
-#define MAX_PIXELS_PER_LINE     2048
-
-#define VRFB_TX_TIMEOUT         1000
-#define VRFB_NUM_BUFS          4
-
-/* Max buffer size tobe allocated during init */
-#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
-
-enum dma_channel_state {
-       DMA_CHAN_NOT_ALLOTED,
-       DMA_CHAN_ALLOTED,
-};
-
-/* Enum for Rotation
- * DSS understands rotation in 0, 1, 2, 3 context
- * while V4L2 driver understands it as 0, 90, 180, 270
- */
-enum dss_rotation {
-       dss_rotation_0_degree   = 0,
-       dss_rotation_90_degree  = 1,
-       dss_rotation_180_degree = 2,
-       dss_rotation_270_degree = 3,
-};
-
-/* Enum for choosing rotation type for vout
- * DSS2 doesn't understand no rotation as an
- * option while V4L2 driver doesn't support
- * rotation in the case where VRFB is not built in
- * the kernel
- */
-enum vout_rotaion_type {
-       VOUT_ROT_NONE   = 0,
-       VOUT_ROT_VRFB   = 1,
-};
-
-/*
- * This structure is used to store the DMA transfer parameters
- * for VRFB hidden buffer
- */
-struct vid_vrfb_dma {
-       struct dma_chan *chan;
-       struct dma_interleaved_template *xt;
-
-       int req_status;
-       int tx_status;
-       wait_queue_head_t wait;
-};
-
-struct omapvideo_info {
-       int id;
-       int num_overlays;
-       struct omap_overlay *overlays[MAX_OVLS];
-       enum vout_rotaion_type rotation_type;
-};
-
-struct omap2video_device {
-       struct mutex  mtx;
-
-       int state;
-
-       struct v4l2_device v4l2_dev;
-       struct omap_vout_device *vouts[MAX_VOUT_DEV];
-
-       int num_displays;
-       struct omap_dss_device *displays[MAX_DISPLAYS];
-       int num_overlays;
-       struct omap_overlay *overlays[MAX_OVLS];
-       int num_managers;
-       struct omap_overlay_manager *managers[MAX_MANAGERS];
-};
-
-/* buffer for one video frame */
-struct omap_vout_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct vb2_v4l2_buffer          vbuf;
-       struct list_head                queue;
-};
-
-static inline struct omap_vout_buffer *vb2_to_omap_vout_buffer(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-
-       return container_of(vbuf, struct omap_vout_buffer, vbuf);
-}
-
-/* per-device data structure */
-struct omap_vout_device {
-
-       struct omapvideo_info vid_info;
-       struct video_device *vfd;
-       struct omap2video_device *vid_dev;
-       struct v4l2_ctrl_handler ctrl_handler;
-       int vid;
-
-       /* allow to reuse previously allocated buffer which is big enough */
-       int buffer_size;
-       enum omap_color_mode dss_mode;
-
-       u32 sequence;
-
-       struct v4l2_pix_format pix;
-       struct v4l2_rect crop;
-       struct v4l2_window win;
-       struct v4l2_framebuffer fbuf;
-
-       /* Lock to protect the shared data structures in ioctl */
-       struct mutex lock;
-
-       enum dss_rotation rotation;
-       bool mirror;
-       int flicker_filter;
-
-       int bpp; /* bytes per pixel */
-       int vrfb_bpp; /* bytes per pixel with respect to VRFB */
-
-       struct vid_vrfb_dma vrfb_dma_tx;
-       unsigned int smsshado_phy_addr[MAC_VRFB_CTXS];
-       unsigned int smsshado_virt_addr[MAC_VRFB_CTXS];
-       struct vrfb vrfb_context[MAC_VRFB_CTXS];
-       bool vrfb_static_allocation;
-       unsigned int smsshado_size;
-       unsigned char pos;
-
-       int ps, vr_ps, line_length, first_int, field_id;
-       struct omap_vout_buffer *cur_frm, *next_frm;
-       spinlock_t vbq_lock;            /* spinlock for dma_queue */
-       struct list_head dma_queue;
-       dma_addr_t queued_buf_addr[VIDEO_MAX_FRAME];
-       u32 cropped_offset;
-       s32 tv_field1_offset;
-       void *isr_handle;
-       struct vb2_queue vq;
-
-};
-
-/*
- * Return true if rotation is 90 or 270
- */
-static inline int is_rotation_90_or_270(const struct omap_vout_device *vout)
-{
-       return (vout->rotation == dss_rotation_90_degree ||
-                       vout->rotation == dss_rotation_270_degree);
-}
-
-/*
- * Return true if rotation is enabled
- */
-static inline int is_rotation_enabled(const struct omap_vout_device *vout)
-{
-       return vout->rotation || vout->mirror;
-}
-
-/*
- * Reverse the rotation degree if mirroring is enabled
- */
-static inline int calc_rotation(const struct omap_vout_device *vout)
-{
-       if (!vout->mirror)
-               return vout->rotation;
-
-       switch (vout->rotation) {
-       case dss_rotation_90_degree:
-               return dss_rotation_270_degree;
-       case dss_rotation_270_degree:
-               return dss_rotation_90_degree;
-       case dss_rotation_180_degree:
-               return dss_rotation_0_degree;
-       default:
-               return dss_rotation_180_degree;
-       }
-}
-
-void omap_vout_free_buffers(struct omap_vout_device *vout);
-#endif /* ifndef OMAP_VOUTDEF_H */
diff --git a/drivers/media/platform/omap/omap_voutlib.c b/drivers/media/platform/omap/omap_voutlib.c
deleted file mode 100644 (file)
index 480a7e9..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * omap_voutlib.c
- *
- * Copyright (C) 2005-2010 Texas Instruments.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- * Based on the OMAP2 camera driver
- * Video-for-Linux (Version 2) camera capture driver for
- * the OMAP24xx camera controller.
- *
- * Author: Andy Lowe (source@mvista.com)
- *
- * Copyright (C) 2004 MontaVista Software, Inc.
- * Copyright (C) 2010 Texas Instruments.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-
-#include <linux/dma-mapping.h>
-
-#include <video/omapfb_dss.h>
-
-#include "omap_voutlib.h"
-
-MODULE_AUTHOR("Texas Instruments");
-MODULE_DESCRIPTION("OMAP Video library");
-MODULE_LICENSE("GPL");
-
-/* Return the default overlay cropping rectangle in crop given the image
- * size in pix and the video display size in fbuf.  The default
- * cropping rectangle is the largest rectangle no larger than the capture size
- * that will fit on the display.  The default cropping rectangle is centered in
- * the image.  All dimensions and offsets are rounded down to even numbers.
- */
-void omap_vout_default_crop(struct v4l2_pix_format *pix,
-                 struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop)
-{
-       crop->width = (pix->width < fbuf->fmt.width) ?
-               pix->width : fbuf->fmt.width;
-       crop->height = (pix->height < fbuf->fmt.height) ?
-               pix->height : fbuf->fmt.height;
-       crop->width &= ~1;
-       crop->height &= ~1;
-       crop->left = ((pix->width - crop->width) >> 1) & ~1;
-       crop->top = ((pix->height - crop->height) >> 1) & ~1;
-}
-EXPORT_SYMBOL_GPL(omap_vout_default_crop);
-
-/* Given a new render window in new_win, adjust the window to the
- * nearest supported configuration.  The adjusted window parameters are
- * returned in new_win.
- * Returns zero if successful, or -EINVAL if the requested window is
- * impossible and cannot reasonably be adjusted.
- */
-int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
-                       struct v4l2_window *new_win)
-{
-       struct v4l2_rect try_win;
-
-       /* make a working copy of the new_win rectangle */
-       try_win = new_win->w;
-
-       /* adjust the preview window so it fits on the display by clipping any
-        * offscreen areas
-        */
-       if (try_win.left < 0) {
-               try_win.width += try_win.left;
-               try_win.left = 0;
-       }
-       if (try_win.top < 0) {
-               try_win.height += try_win.top;
-               try_win.top = 0;
-       }
-       try_win.width = (try_win.width < fbuf->fmt.width) ?
-               try_win.width : fbuf->fmt.width;
-       try_win.height = (try_win.height < fbuf->fmt.height) ?
-               try_win.height : fbuf->fmt.height;
-       if (try_win.left + try_win.width > fbuf->fmt.width)
-               try_win.width = fbuf->fmt.width - try_win.left;
-       if (try_win.top + try_win.height > fbuf->fmt.height)
-               try_win.height = fbuf->fmt.height - try_win.top;
-       try_win.width &= ~1;
-       try_win.height &= ~1;
-
-       if (try_win.width <= 0 || try_win.height <= 0)
-               return -EINVAL;
-
-       /* We now have a valid preview window, so go with it */
-       new_win->w = try_win;
-       new_win->field = V4L2_FIELD_NONE;
-       new_win->clips = NULL;
-       new_win->clipcount = 0;
-       new_win->bitmap = NULL;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(omap_vout_try_window);
-
-/* Given a new render window in new_win, adjust the window to the
- * nearest supported configuration.  The image cropping window in crop
- * will also be adjusted if necessary.  Preference is given to keeping the
- * the window as close to the requested configuration as possible.  If
- * successful, new_win, vout->win, and crop are updated.
- * Returns zero if successful, or -EINVAL if the requested preview window is
- * impossible and cannot reasonably be adjusted.
- */
-int omap_vout_new_window(struct v4l2_rect *crop,
-               struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
-               struct v4l2_window *new_win)
-{
-       int err;
-
-       err = omap_vout_try_window(fbuf, new_win);
-       if (err)
-               return err;
-
-       /* update our preview window */
-       win->w = new_win->w;
-       win->field = new_win->field;
-       win->chromakey = new_win->chromakey;
-
-       /* Adjust the cropping window to allow for resizing limitation */
-       if (omap_vout_dss_omap24xx()) {
-               /* For 24xx limit is 8x to 1/2x scaling. */
-               if ((crop->height/win->w.height) >= 2)
-                       crop->height = win->w.height * 2;
-
-               if ((crop->width/win->w.width) >= 2)
-                       crop->width = win->w.width * 2;
-
-               if (crop->width > 768) {
-                       /* The OMAP2420 vertical resizing line buffer is 768
-                        * pixels wide. If the cropped image is wider than
-                        * 768 pixels then it cannot be vertically resized.
-                        */
-                       if (crop->height != win->w.height)
-                               crop->width = 768;
-               }
-       } else if (omap_vout_dss_omap34xx()) {
-               /* For 34xx limit is 8x to 1/4x scaling. */
-               if ((crop->height/win->w.height) >= 4)
-                       crop->height = win->w.height * 4;
-
-               if ((crop->width/win->w.width) >= 4)
-                       crop->width = win->w.width * 4;
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(omap_vout_new_window);
-
-/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
- * the nearest supported configuration.  The image render window in win will
- * also be adjusted if necessary.  The preview window is adjusted such that the
- * horizontal and vertical rescaling ratios stay constant.  If the render
- * window would fall outside the display boundaries, the cropping rectangle
- * will also be adjusted to maintain the rescaling ratios.  If successful, crop
- * and win are updated.
- * Returns zero if successful, or -EINVAL if the requested cropping rectangle is
- * impossible and cannot reasonably be adjusted.
- */
-int omap_vout_new_crop(struct v4l2_pix_format *pix,
-             struct v4l2_rect *crop, struct v4l2_window *win,
-             struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop)
-{
-       struct v4l2_rect try_crop;
-       unsigned long vresize, hresize;
-
-       /* make a working copy of the new_crop rectangle */
-       try_crop = *new_crop;
-
-       /* adjust the cropping rectangle so it fits in the image */
-       if (try_crop.left < 0) {
-               try_crop.width += try_crop.left;
-               try_crop.left = 0;
-       }
-       if (try_crop.top < 0) {
-               try_crop.height += try_crop.top;
-               try_crop.top = 0;
-       }
-       try_crop.width = (try_crop.width < pix->width) ?
-               try_crop.width : pix->width;
-       try_crop.height = (try_crop.height < pix->height) ?
-               try_crop.height : pix->height;
-       if (try_crop.left + try_crop.width > pix->width)
-               try_crop.width = pix->width - try_crop.left;
-       if (try_crop.top + try_crop.height > pix->height)
-               try_crop.height = pix->height - try_crop.top;
-
-       try_crop.width &= ~1;
-       try_crop.height &= ~1;
-
-       if (try_crop.width <= 0 || try_crop.height <= 0)
-               return -EINVAL;
-
-       if (omap_vout_dss_omap24xx()) {
-               if (try_crop.height != win->w.height) {
-                       /* If we're resizing vertically, we can't support a
-                        * crop width wider than 768 pixels.
-                        */
-                       if (try_crop.width > 768)
-                               try_crop.width = 768;
-               }
-       }
-       /* vertical resizing */
-       vresize = (1024 * try_crop.height) / win->w.height;
-       if (omap_vout_dss_omap24xx() && (vresize > 2048))
-               vresize = 2048;
-       else if (omap_vout_dss_omap34xx() && (vresize > 4096))
-               vresize = 4096;
-
-       win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
-       if (win->w.height == 0)
-               win->w.height = 2;
-       if (win->w.height + win->w.top > fbuf->fmt.height) {
-               /* We made the preview window extend below the bottom of the
-                * display, so clip it to the display boundary and resize the
-                * cropping height to maintain the vertical resizing ratio.
-                */
-               win->w.height = (fbuf->fmt.height - win->w.top) & ~1;
-               if (try_crop.height == 0)
-                       try_crop.height = 2;
-       }
-       /* horizontal resizing */
-       hresize = (1024 * try_crop.width) / win->w.width;
-       if (omap_vout_dss_omap24xx() && (hresize > 2048))
-               hresize = 2048;
-       else if (omap_vout_dss_omap34xx() && (hresize > 4096))
-               hresize = 4096;
-
-       win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
-       if (win->w.width == 0)
-               win->w.width = 2;
-       if (win->w.width + win->w.left > fbuf->fmt.width) {
-               /* We made the preview window extend past the right side of the
-                * display, so clip it to the display boundary and resize the
-                * cropping width to maintain the horizontal resizing ratio.
-                */
-               win->w.width = (fbuf->fmt.width - win->w.left) & ~1;
-               if (try_crop.width == 0)
-                       try_crop.width = 2;
-       }
-       if (omap_vout_dss_omap24xx()) {
-               if ((try_crop.height/win->w.height) >= 2)
-                       try_crop.height = win->w.height * 2;
-
-               if ((try_crop.width/win->w.width) >= 2)
-                       try_crop.width = win->w.width * 2;
-
-               if (try_crop.width > 768) {
-                       /* The OMAP2420 vertical resizing line buffer is
-                        * 768 pixels wide.  If the cropped image is wider
-                        * than 768 pixels then it cannot be vertically resized.
-                        */
-                       if (try_crop.height != win->w.height)
-                               try_crop.width = 768;
-               }
-       } else if (omap_vout_dss_omap34xx()) {
-               if ((try_crop.height/win->w.height) >= 4)
-                       try_crop.height = win->w.height * 4;
-
-               if ((try_crop.width/win->w.width) >= 4)
-                       try_crop.width = win->w.width * 4;
-       }
-       /* update our cropping rectangle and we're done */
-       *crop = try_crop;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(omap_vout_new_crop);
-
-/* Given a new format in pix and fbuf,  crop and win
- * structures are initialized to default values. crop
- * is initialized to the largest window size that will fit on the display.  The
- * crop window is centered in the image. win is initialized to
- * the same size as crop and is centered on the display.
- * All sizes and offsets are constrained to be even numbers.
- */
-void omap_vout_new_format(struct v4l2_pix_format *pix,
-               struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
-               struct v4l2_window *win)
-{
-       /* crop defines the preview source window in the image capture
-        * buffer
-        */
-       omap_vout_default_crop(pix, fbuf, crop);
-
-       /* win defines the preview target window on the display */
-       win->w.width = crop->width;
-       win->w.height = crop->height;
-       win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1;
-       win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1;
-}
-EXPORT_SYMBOL_GPL(omap_vout_new_format);
-
-/*
- * Allocate buffers
- */
-unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
-{
-       u32 order, size;
-       unsigned long virt_addr, addr;
-
-       size = PAGE_ALIGN(buf_size);
-       order = get_order(size);
-       virt_addr = __get_free_pages(GFP_KERNEL, order);
-       addr = virt_addr;
-
-       if (virt_addr) {
-               while (size > 0) {
-                       SetPageReserved(virt_to_page(addr));
-                       addr += PAGE_SIZE;
-                       size -= PAGE_SIZE;
-               }
-       }
-       *phys_addr = (u32) virt_to_phys((void *) virt_addr);
-       return virt_addr;
-}
-
-/*
- * Free buffers
- */
-void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
-{
-       u32 order, size;
-       unsigned long addr = virtaddr;
-
-       size = PAGE_ALIGN(buf_size);
-       order = get_order(size);
-
-       while (size > 0) {
-               ClearPageReserved(virt_to_page(addr));
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       free_pages((unsigned long) virtaddr, order);
-}
-
-bool omap_vout_dss_omap24xx(void)
-{
-       return omapdss_get_version() == OMAPDSS_VER_OMAP24xx;
-}
-
-bool omap_vout_dss_omap34xx(void)
-{
-       switch (omapdss_get_version()) {
-       case OMAPDSS_VER_OMAP34xx_ES1:
-       case OMAPDSS_VER_OMAP34xx_ES3:
-       case OMAPDSS_VER_OMAP3630:
-       case OMAPDSS_VER_AM35xx:
-               return true;
-       default:
-               return false;
-       }
-}
diff --git a/drivers/media/platform/omap/omap_voutlib.h b/drivers/media/platform/omap/omap_voutlib.h
deleted file mode 100644 (file)
index f9d1c07..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * omap_voutlib.h
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-
-#ifndef OMAP_VOUTLIB_H
-#define OMAP_VOUTLIB_H
-
-void omap_vout_default_crop(struct v4l2_pix_format *pix,
-               struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
-
-int omap_vout_new_crop(struct v4l2_pix_format *pix,
-               struct v4l2_rect *crop, struct v4l2_window *win,
-               struct v4l2_framebuffer *fbuf,
-               const struct v4l2_rect *new_crop);
-
-int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
-               struct v4l2_window *new_win);
-
-int omap_vout_new_window(struct v4l2_rect *crop,
-               struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
-               struct v4l2_window *new_win);
-
-void omap_vout_new_format(struct v4l2_pix_format *pix,
-               struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
-               struct v4l2_window *win);
-unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
-void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
-
-bool omap_vout_dss_omap24xx(void);
-bool omap_vout_dss_omap34xx(void);
-#endif /* #ifndef OMAP_VOUTLIB_H */
-
diff --git a/drivers/media/platform/ti/omap/Kconfig b/drivers/media/platform/ti/omap/Kconfig
new file mode 100644 (file)
index 0000000..789d5e5
--- /dev/null
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config VIDEO_OMAP2_VOUT_VRFB
+       bool
+       default y
+       depends on VIDEO_OMAP2_VOUT && (OMAP2_VRFB || COMPILE_TEST)
+
+config VIDEO_OMAP2_VOUT
+       tristate "OMAP2/OMAP3 V4L2-Display driver"
+       depends on V4L_PLATFORM_DRIVERS
+       depends on MMU
+       depends on FB_OMAP2 || (COMPILE_TEST && FB_OMAP2=n)
+       depends on ARCH_OMAP2 || ARCH_OMAP3 || COMPILE_TEST
+       depends on VIDEO_V4L2
+       select VIDEOBUF2_DMA_CONTIG
+       select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
+       help
+         V4L2 Display driver support for OMAP2/3 based boards.
diff --git a/drivers/media/platform/ti/omap/Makefile b/drivers/media/platform/ti/omap/Makefile
new file mode 100644 (file)
index 0000000..b17a0ac
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for the omap video device drivers.
+#
+
+# OMAP2/3 Display driver
+omap-vout-y += omap_vout.o omap_voutlib.o
+omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o
+obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
diff --git a/drivers/media/platform/ti/omap/omap_vout.c b/drivers/media/platform/ti/omap/omap_vout.c
new file mode 100644 (file)
index 0000000..3e0d9af
--- /dev/null
@@ -0,0 +1,1742 @@
+/*
+ * omap_vout.c
+ *
+ * Copyright (C) 2005-2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * Leveraged code from the OMAP2 camera driver
+ * Video-for-Linux (Version 2) camera capture driver for
+ * the OMAP24xx camera controller.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * History:
+ * 20-APR-2006 Khasim          Modified VRFB based Rotation,
+ *                             The image data is always read from 0 degree
+ *                             view and written
+ *                             to the virtual space of desired rotation angle
+ * 4-DEC-2006  Jian            Changed to support better memory management
+ *
+ * 17-Nov-2008 Hardik          Changed driver to use video_ioctl2
+ *
+ * 23-Feb-2010 Vaibhav H       Modified to use new DSS2 interface
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/videodev2.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+
+#include <video/omapvrfb.h>
+#include <video/omapfb_dss.h>
+
+#include "omap_voutlib.h"
+#include "omap_voutdef.h"
+#include "omap_vout_vrfb.h"
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
+MODULE_LICENSE("GPL");
+
+/* Driver Configuration macros */
+#define VOUT_NAME              "omap_vout"
+
+enum omap_vout_channels {
+       OMAP_VIDEO1,
+       OMAP_VIDEO2,
+};
+
+/* Variables configurable through module params*/
+static bool vid1_static_vrfb_alloc;
+static bool vid2_static_vrfb_alloc;
+static bool debug;
+
+/* Module parameters */
+module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
+MODULE_PARM_DESC(vid1_static_vrfb_alloc,
+       "Static allocation of the VRFB buffer for video1 device");
+
+module_param(vid2_static_vrfb_alloc, bool, S_IRUGO);
+MODULE_PARM_DESC(vid2_static_vrfb_alloc,
+       "Static allocation of the VRFB buffer for video2 device");
+
+module_param(debug, bool, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/* list of image formats supported by OMAP2 video pipelines */
+static const struct v4l2_fmtdesc omap_formats[] = {
+       {
+               /* Note:  V4L2 defines RGB565 as:
+                *
+                *      Byte 0                    Byte 1
+                *      g2 g1 g0 r4 r3 r2 r1 r0   b4 b3 b2 b1 b0 g5 g4 g3
+                *
+                * We interpret RGB565 as:
+                *
+                *      Byte 0                    Byte 1
+                *      g2 g1 g0 b4 b3 b2 b1 b0   r4 r3 r2 r1 r0 g5 g4 g3
+                */
+               .pixelformat = V4L2_PIX_FMT_RGB565,
+       },
+       {
+               /* Note:  V4L2 defines RGB32 as: RGB-8-8-8-8  we use
+                *  this for RGB24 unpack mode, the last 8 bits are ignored
+                * */
+               .pixelformat = V4L2_PIX_FMT_RGB32,
+       },
+       {
+               /* Note:  V4L2 defines RGB24 as: RGB-8-8-8  we use
+                *        this for RGB24 packed mode
+                *
+                */
+               .pixelformat = V4L2_PIX_FMT_RGB24,
+       },
+       {
+               .pixelformat = V4L2_PIX_FMT_YUYV,
+       },
+       {
+               .pixelformat = V4L2_PIX_FMT_UYVY,
+       },
+};
+
+#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
+
+/*
+ * Try format
+ */
+static int omap_vout_try_format(struct v4l2_pix_format *pix)
+{
+       int ifmt, bpp = 0;
+
+       pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT,
+                                               (u32)VID_MAX_HEIGHT);
+       pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH);
+
+       for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) {
+               if (pix->pixelformat == omap_formats[ifmt].pixelformat)
+                       break;
+       }
+
+       if (ifmt == NUM_OUTPUT_FORMATS)
+               ifmt = 0;
+
+       pix->pixelformat = omap_formats[ifmt].pixelformat;
+       pix->field = V4L2_FIELD_NONE;
+
+       switch (pix->pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_UYVY:
+       default:
+               pix->colorspace = V4L2_COLORSPACE_SRGB;
+               bpp = YUYV_BPP;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_RGB565X:
+               pix->colorspace = V4L2_COLORSPACE_SRGB;
+               bpp = RGB565_BPP;
+               break;
+       case V4L2_PIX_FMT_RGB24:
+               pix->colorspace = V4L2_COLORSPACE_SRGB;
+               bpp = RGB24_BPP;
+               break;
+       case V4L2_PIX_FMT_RGB32:
+       case V4L2_PIX_FMT_BGR32:
+               pix->colorspace = V4L2_COLORSPACE_SRGB;
+               bpp = RGB32_BPP;
+               break;
+       }
+       pix->bytesperline = pix->width * bpp;
+       pix->sizeimage = pix->bytesperline * pix->height;
+
+       return bpp;
+}
+
+/*
+ * Convert V4L2 rotation to DSS rotation
+ *     V4L2 understand 0, 90, 180, 270.
+ *     Convert to 0, 1, 2 and 3 respectively for DSS
+ */
+static int v4l2_rot_to_dss_rot(int v4l2_rotation,
+                       enum dss_rotation *rotation, bool mirror)
+{
+       int ret = 0;
+
+       switch (v4l2_rotation) {
+       case 90:
+               *rotation = dss_rotation_90_degree;
+               break;
+       case 180:
+               *rotation = dss_rotation_180_degree;
+               break;
+       case 270:
+               *rotation = dss_rotation_270_degree;
+               break;
+       case 0:
+               *rotation = dss_rotation_0_degree;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int omap_vout_calculate_offset(struct omap_vout_device *vout)
+{
+       struct omapvideo_info *ovid;
+       struct v4l2_rect *crop = &vout->crop;
+       struct v4l2_pix_format *pix = &vout->pix;
+       int *cropped_offset = &vout->cropped_offset;
+       int ps = 2, line_length = 0;
+
+       ovid = &vout->vid_info;
+
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               omap_vout_calculate_vrfb_offset(vout);
+       } else {
+               vout->line_length = line_length = pix->width;
+
+               if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+                       V4L2_PIX_FMT_UYVY == pix->pixelformat)
+                       ps = 2;
+               else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
+                       ps = 4;
+               else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
+                       ps = 3;
+
+               vout->ps = ps;
+
+               *cropped_offset = (line_length * ps) *
+                       crop->top + crop->left * ps;
+       }
+
+       v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
+                       __func__, vout->cropped_offset);
+
+       return 0;
+}
+
+/*
+ * Convert V4L2 pixel format to DSS pixel format
+ */
+static int video_mode_to_dss_mode(struct omap_vout_device *vout)
+{
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct v4l2_pix_format *pix = &vout->pix;
+       enum omap_color_mode mode;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
+       switch (pix->pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+               mode = OMAP_DSS_COLOR_YUV2;
+               break;
+       case V4L2_PIX_FMT_UYVY:
+               mode = OMAP_DSS_COLOR_UYVY;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               mode = OMAP_DSS_COLOR_RGB16;
+               break;
+       case V4L2_PIX_FMT_RGB24:
+               mode = OMAP_DSS_COLOR_RGB24P;
+               break;
+       case V4L2_PIX_FMT_RGB32:
+               mode = (ovl->id == OMAP_DSS_VIDEO1) ?
+                       OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
+               break;
+       case V4L2_PIX_FMT_BGR32:
+               mode = OMAP_DSS_COLOR_RGBX32;
+               break;
+       default:
+               mode = -EINVAL;
+               break;
+       }
+       return mode;
+}
+
+/*
+ * Setup the overlay
+ */
+static int omapvid_setup_overlay(struct omap_vout_device *vout,
+               struct omap_overlay *ovl, int posx, int posy, int outw,
+               int outh, dma_addr_t addr)
+{
+       int ret = 0;
+       struct omap_overlay_info info;
+       int cropheight, cropwidth, pixwidth;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
+                       (outw != vout->pix.width || outh != vout->pix.height)) {
+               ret = -EINVAL;
+               goto setup_ovl_err;
+       }
+
+       vout->dss_mode = video_mode_to_dss_mode(vout);
+       if (vout->dss_mode == -EINVAL) {
+               ret = -EINVAL;
+               goto setup_ovl_err;
+       }
+
+       /* Setup the input plane parameters according to
+        * rotation value selected.
+        */
+       if (is_rotation_90_or_270(vout)) {
+               cropheight = vout->crop.width;
+               cropwidth = vout->crop.height;
+               pixwidth = vout->pix.height;
+       } else {
+               cropheight = vout->crop.height;
+               cropwidth = vout->crop.width;
+               pixwidth = vout->pix.width;
+       }
+
+       ovl->get_overlay_info(ovl, &info);
+       info.paddr = addr;
+       info.width = cropwidth;
+       info.height = cropheight;
+       info.color_mode = vout->dss_mode;
+       info.mirror = vout->mirror;
+       info.pos_x = posx;
+       info.pos_y = posy;
+       info.out_width = outw;
+       info.out_height = outh;
+       info.global_alpha = vout->win.global_alpha;
+       if (!is_rotation_enabled(vout)) {
+               info.rotation = 0;
+               info.rotation_type = OMAP_DSS_ROT_DMA;
+               info.screen_width = pixwidth;
+       } else {
+               info.rotation = vout->rotation;
+               info.rotation_type = OMAP_DSS_ROT_VRFB;
+               info.screen_width = 2048;
+       }
+
+       v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+               "%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
+               "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
+               "out_height=%d rotation_type=%d screen_width=%d\n", __func__,
+               ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
+               info.color_mode, info.rotation, info.mirror, info.pos_x,
+               info.pos_y, info.out_width, info.out_height, info.rotation_type,
+               info.screen_width);
+
+       ret = ovl->set_overlay_info(ovl, &info);
+       if (ret)
+               goto setup_ovl_err;
+
+       return 0;
+
+setup_ovl_err:
+       v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n");
+       return ret;
+}
+
+/*
+ * Initialize the overlay structure
+ */
+static int omapvid_init(struct omap_vout_device *vout, dma_addr_t addr)
+{
+       int ret = 0, i;
+       struct v4l2_window *win;
+       struct omap_overlay *ovl;
+       int posx, posy, outw, outh;
+       struct omap_video_timings *timing;
+       struct omapvideo_info *ovid = &vout->vid_info;
+
+       win = &vout->win;
+       for (i = 0; i < ovid->num_overlays; i++) {
+               struct omap_dss_device *dssdev;
+
+               ovl = ovid->overlays[i];
+               dssdev = ovl->get_device(ovl);
+
+               if (!dssdev)
+                       return -EINVAL;
+
+               timing = &dssdev->panel.timings;
+
+               outw = win->w.width;
+               outh = win->w.height;
+               switch (vout->rotation) {
+               case dss_rotation_90_degree:
+                       /* Invert the height and width for 90
+                        * and 270 degree rotation
+                        */
+                       swap(outw, outh);
+                       posy = (timing->y_res - win->w.width) - win->w.left;
+                       posx = win->w.top;
+                       break;
+
+               case dss_rotation_180_degree:
+                       posx = (timing->x_res - win->w.width) - win->w.left;
+                       posy = (timing->y_res - win->w.height) - win->w.top;
+                       break;
+
+               case dss_rotation_270_degree:
+                       swap(outw, outh);
+                       posy = win->w.left;
+                       posx = (timing->x_res - win->w.height) - win->w.top;
+                       break;
+
+               default:
+                       posx = win->w.left;
+                       posy = win->w.top;
+                       break;
+               }
+
+               ret = omapvid_setup_overlay(vout, ovl, posx, posy,
+                               outw, outh, addr);
+               if (ret)
+                       goto omapvid_init_err;
+       }
+       return 0;
+
+omapvid_init_err:
+       v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n");
+       return ret;
+}
+
+/*
+ * Apply the changes set the go bit of DSS
+ */
+static int omapvid_apply_changes(struct omap_vout_device *vout)
+{
+       int i;
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid = &vout->vid_info;
+
+       for (i = 0; i < ovid->num_overlays; i++) {
+               struct omap_dss_device *dssdev;
+
+               ovl = ovid->overlays[i];
+               dssdev = ovl->get_device(ovl);
+               if (!dssdev)
+                       return -EINVAL;
+               ovl->manager->apply(ovl->manager);
+       }
+
+       return 0;
+}
+
+static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
+               unsigned int irqstatus, u64 ts)
+{
+       u32 fid;
+
+       if (vout->first_int) {
+               vout->first_int = 0;
+               goto err;
+       }
+
+       if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
+               fid = 1;
+       else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
+               fid = 0;
+       else
+               goto err;
+
+       vout->field_id ^= 1;
+       if (fid != vout->field_id) {
+               if (fid == 0)
+                       vout->field_id = fid;
+       } else if (0 == fid) {
+               if (vout->cur_frm == vout->next_frm)
+                       goto err;
+
+               vout->cur_frm->vbuf.vb2_buf.timestamp = ts;
+               vout->cur_frm->vbuf.sequence = vout->sequence++;
+               vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
+               vout->cur_frm = vout->next_frm;
+       } else {
+               if (list_empty(&vout->dma_queue) ||
+                               (vout->cur_frm != vout->next_frm))
+                       goto err;
+       }
+
+       return vout->field_id;
+err:
+       return 0;
+}
+
+static void omap_vout_isr(void *arg, unsigned int irqstatus)
+{
+       int ret, fid, mgr_id;
+       dma_addr_t addr;
+       u32 irq;
+       struct omap_overlay *ovl;
+       u64 ts;
+       struct omapvideo_info *ovid;
+       struct omap_dss_device *cur_display;
+       struct omap_vout_device *vout = (struct omap_vout_device *)arg;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
+       mgr_id = ovl->manager->id;
+
+       /* get the display device attached to the overlay */
+       cur_display = ovl->get_device(ovl);
+
+       if (!cur_display)
+               return;
+
+       spin_lock(&vout->vbq_lock);
+       ts = ktime_get_ns();
+
+       switch (cur_display->type) {
+       case OMAP_DISPLAY_TYPE_DSI:
+       case OMAP_DISPLAY_TYPE_DPI:
+       case OMAP_DISPLAY_TYPE_DVI:
+               if (mgr_id == OMAP_DSS_CHANNEL_LCD)
+                       irq = DISPC_IRQ_VSYNC;
+               else if (mgr_id == OMAP_DSS_CHANNEL_LCD2)
+                       irq = DISPC_IRQ_VSYNC2;
+               else
+                       goto vout_isr_err;
+
+               if (!(irqstatus & irq))
+                       goto vout_isr_err;
+               break;
+       case OMAP_DISPLAY_TYPE_VENC:
+               fid = omapvid_handle_interlace_display(vout, irqstatus,
+                               ts);
+               if (!fid)
+                       goto vout_isr_err;
+               break;
+       case OMAP_DISPLAY_TYPE_HDMI:
+               if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
+                       goto vout_isr_err;
+               break;
+       default:
+               goto vout_isr_err;
+       }
+
+       if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
+               vout->cur_frm->vbuf.vb2_buf.timestamp = ts;
+               vout->cur_frm->vbuf.sequence = vout->sequence++;
+               vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
+               vout->cur_frm = vout->next_frm;
+       }
+
+       vout->first_int = 0;
+       if (list_empty(&vout->dma_queue))
+               goto vout_isr_err;
+
+       vout->next_frm = list_entry(vout->dma_queue.next,
+                       struct omap_vout_buffer, queue);
+       list_del(&vout->next_frm->queue);
+
+       addr = vout->queued_buf_addr[vout->next_frm->vbuf.vb2_buf.index]
+               + vout->cropped_offset;
+
+       /* First save the configuration in ovelray structure */
+       ret = omapvid_init(vout, addr);
+       if (ret) {
+               printk(KERN_ERR VOUT_NAME
+                       "failed to set overlay info\n");
+               goto vout_isr_err;
+       }
+
+       /* Enable the pipeline and set the Go bit */
+       ret = omapvid_apply_changes(vout);
+       if (ret)
+               printk(KERN_ERR VOUT_NAME "failed to change mode\n");
+
+vout_isr_err:
+       spin_unlock(&vout->vbq_lock);
+}
+
+
+/*
+ * V4L2 ioctls
+ */
+static int vidioc_querycap(struct file *file, void *fh,
+               struct v4l2_capability *cap)
+{
+       struct omap_vout_device *vout = video_drvdata(file);
+
+       strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
+       strscpy(cap->card, vout->vfd->name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                "platform:%s.%d", VOUT_NAME, vout->vid);
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
+                       struct v4l2_fmtdesc *fmt)
+{
+       int index = fmt->index;
+
+       if (index >= NUM_OUTPUT_FORMATS)
+               return -EINVAL;
+
+       fmt->flags = omap_formats[index].flags;
+       fmt->pixelformat = omap_formats[index].pixelformat;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_out(struct file *file, void *fh,
+                       struct v4l2_format *f)
+{
+       struct omap_vout_device *vout = video_drvdata(file);
+
+       f->fmt.pix = vout->pix;
+       return 0;
+
+}
+
+static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
+                       struct v4l2_format *f)
+{
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct omap_video_timings *timing;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct omap_dss_device *dssdev;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+       /* get the display device attached to the overlay */
+       dssdev = ovl->get_device(ovl);
+
+       if (!dssdev)
+               return -EINVAL;
+
+       timing = &dssdev->panel.timings;
+
+       vout->fbuf.fmt.height = timing->y_res;
+       vout->fbuf.fmt.width = timing->x_res;
+
+       omap_vout_try_format(&f->fmt.pix);
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
+                       struct v4l2_format *f)
+{
+       int ret, bpp;
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct omap_video_timings *timing;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct omap_dss_device *dssdev;
+
+       if (vb2_is_busy(&vout->vq))
+               return -EBUSY;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+       dssdev = ovl->get_device(ovl);
+
+       /* get the display device attached to the overlay */
+       if (!dssdev) {
+               ret = -EINVAL;
+               goto s_fmt_vid_out_exit;
+       }
+       timing = &dssdev->panel.timings;
+
+       /* We don't support RGB24-packed mode if vrfb rotation
+        * is enabled*/
+       if ((is_rotation_enabled(vout)) &&
+                       f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+               ret = -EINVAL;
+               goto s_fmt_vid_out_exit;
+       }
+
+       /* get the framebuffer parameters */
+
+       if (is_rotation_90_or_270(vout)) {
+               vout->fbuf.fmt.height = timing->x_res;
+               vout->fbuf.fmt.width = timing->y_res;
+       } else {
+               vout->fbuf.fmt.height = timing->y_res;
+               vout->fbuf.fmt.width = timing->x_res;
+       }
+
+       /* change to smaller size is OK */
+
+       bpp = omap_vout_try_format(&f->fmt.pix);
+       f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp;
+
+       /* try & set the new output format */
+       vout->bpp = bpp;
+       vout->pix = f->fmt.pix;
+       vout->vrfb_bpp = 1;
+
+       /* If YUYV then vrfb bpp is 2, for  others its 1 */
+       if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat ||
+                       V4L2_PIX_FMT_UYVY == vout->pix.pixelformat)
+               vout->vrfb_bpp = 2;
+
+       /* set default crop and win */
+       omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
+
+       ret = 0;
+
+s_fmt_vid_out_exit:
+       return ret;
+}
+
+static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
+                       struct v4l2_format *f)
+{
+       int ret = 0;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct v4l2_window *win = &f->fmt.win;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
+       ret = omap_vout_try_window(&vout->fbuf, win);
+
+       if (!ret && !(ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA))
+               win->global_alpha = 0;
+
+       return ret;
+}
+
+static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
+                       struct v4l2_format *f)
+{
+       int ret = 0;
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct v4l2_window *win = &f->fmt.win;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
+       ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
+       if (!ret) {
+               enum omap_dss_trans_key_type key_type =
+                       OMAP_DSS_COLOR_KEY_GFX_DST;
+               int enable;
+
+               /* Video1 plane does not support global alpha on OMAP3 */
+               if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
+                       vout->win.global_alpha = win->global_alpha;
+               else
+                       win->global_alpha = 0;
+               if (vout->fbuf.flags & (V4L2_FBUF_FLAG_CHROMAKEY |
+                                       V4L2_FBUF_FLAG_SRC_CHROMAKEY))
+                       enable = 1;
+               else
+                       enable = 0;
+               if (vout->fbuf.flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)
+                       key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
+
+               if (ovl->manager && ovl->manager->get_manager_info &&
+                   ovl->manager->set_manager_info) {
+                       struct omap_overlay_manager_info info;
+
+                       ovl->manager->get_manager_info(ovl->manager, &info);
+                       info.trans_enabled = enable;
+                       info.trans_key_type = key_type;
+                       info.trans_key = vout->win.chromakey;
+
+                       if (ovl->manager->set_manager_info(ovl->manager, &info))
+                               return -EINVAL;
+               }
+       }
+       return ret;
+}
+
+static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
+                       struct v4l2_format *f)
+{
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct v4l2_window *win = &f->fmt.win;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
+       win->w = vout->win.w;
+       win->field = vout->win.field;
+       win->chromakey = vout->win.chromakey;
+       if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
+               win->global_alpha = vout->win.global_alpha;
+       else
+               win->global_alpha = 0;
+       win->clips = NULL;
+       win->clipcount = 0;
+       win->bitmap = NULL;
+       return 0;
+}
+
+static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection *sel)
+{
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct v4l2_pix_format *pix = &vout->pix;
+
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return -EINVAL;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+               sel->r = vout->crop;
+               break;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               omap_vout_default_crop(&vout->pix, &vout->fbuf, &sel->r);
+               break;
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               /* Width and height are always even */
+               sel->r.width = pix->width & ~1;
+               sel->r.height = pix->height & ~1;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_s_selection(struct file *file, void *fh, struct v4l2_selection *sel)
+{
+       int ret = -EINVAL;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct omapvideo_info *ovid;
+       struct omap_overlay *ovl;
+       struct omap_video_timings *timing;
+       struct omap_dss_device *dssdev;
+
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return -EINVAL;
+
+       if (sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
+
+       if (vb2_is_busy(&vout->vq))
+               return -EBUSY;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+       /* get the display device attached to the overlay */
+       dssdev = ovl->get_device(ovl);
+
+       if (!dssdev) {
+               ret = -EINVAL;
+               goto s_crop_err;
+       }
+
+       timing = &dssdev->panel.timings;
+
+       if (is_rotation_90_or_270(vout)) {
+               vout->fbuf.fmt.height = timing->x_res;
+               vout->fbuf.fmt.width = timing->y_res;
+       } else {
+               vout->fbuf.fmt.height = timing->y_res;
+               vout->fbuf.fmt.width = timing->x_res;
+       }
+
+       ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win,
+                                &vout->fbuf, &sel->r);
+
+s_crop_err:
+       return ret;
+}
+
+static int omap_vout_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct omap_vout_device *vout =
+               container_of(ctrl->handler, struct omap_vout_device, ctrl_handler);
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_ROTATE: {
+               struct omapvideo_info *ovid;
+               int rotation = ctrl->val;
+
+               ovid = &vout->vid_info;
+
+               if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
+                       ret = -ERANGE;
+                       break;
+               }
+
+               if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (v4l2_rot_to_dss_rot(rotation, &vout->rotation,
+                                                       vout->mirror)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       }
+       case V4L2_CID_BG_COLOR:
+       {
+               struct omap_overlay *ovl;
+               unsigned int color = ctrl->val;
+               struct omap_overlay_manager_info info;
+
+               ovl = vout->vid_info.overlays[0];
+
+               if (!ovl->manager || !ovl->manager->get_manager_info) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               ovl->manager->get_manager_info(ovl->manager, &info);
+               info.default_color = color;
+               if (ovl->manager->set_manager_info(ovl->manager, &info)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       }
+       case V4L2_CID_VFLIP:
+       {
+               struct omapvideo_info *ovid;
+               unsigned int mirror = ctrl->val;
+
+               ovid = &vout->vid_info;
+
+               if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
+                       ret = -ERANGE;
+                       break;
+               }
+
+               if (mirror  && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+                       ret = -EINVAL;
+                       break;
+               }
+               vout->mirror = mirror;
+               break;
+       }
+       default:
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static const struct v4l2_ctrl_ops omap_vout_ctrl_ops = {
+       .s_ctrl = omap_vout_s_ctrl,
+};
+
+static int omap_vout_vb2_queue_setup(struct vb2_queue *vq,
+                                    unsigned int *nbufs,
+                                    unsigned int *num_planes, unsigned int sizes[],
+                                    struct device *alloc_devs[])
+{
+       struct omap_vout_device *vout = vb2_get_drv_priv(vq);
+       int size = vout->pix.sizeimage;
+
+       if (is_rotation_enabled(vout) && vq->num_buffers + *nbufs > VRFB_NUM_BUFS) {
+               *nbufs = VRFB_NUM_BUFS - vq->num_buffers;
+               if (*nbufs == 0)
+                       return -EINVAL;
+       }
+
+       if (*num_planes)
+               return sizes[0] < size ? -EINVAL : 0;
+
+       *num_planes = 1;
+       sizes[0] = size;
+       return 0;
+}
+
+static int omap_vout_vb2_prepare(struct vb2_buffer *vb)
+{
+       struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue);
+       struct omapvideo_info *ovid = &vout->vid_info;
+       struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb);
+       dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       if (vb2_plane_size(vb, 0) < vout->pix.sizeimage) {
+               v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+                        "%s data will not fit into plane (%lu < %u)\n",
+                       __func__, vb2_plane_size(vb, 0), vout->pix.sizeimage);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, vout->pix.sizeimage);
+       voutbuf->vbuf.field = V4L2_FIELD_NONE;
+
+       vout->queued_buf_addr[vb->index] = buf_phy_addr;
+       if (ovid->rotation_type == VOUT_ROT_VRFB)
+               return omap_vout_prepare_vrfb(vout, vb);
+       return 0;
+}
+
+static void omap_vout_vb2_queue(struct vb2_buffer *vb)
+{
+       struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue);
+       struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb);
+
+       list_add_tail(&voutbuf->queue, &vout->dma_queue);
+}
+
+static int omap_vout_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct omap_vout_device *vout = vb2_get_drv_priv(vq);
+       struct omapvideo_info *ovid = &vout->vid_info;
+       struct omap_vout_buffer *buf, *tmp;
+       dma_addr_t addr = 0;
+       u32 mask = 0;
+       int ret, j;
+
+       /* Get the next frame from the buffer queue */
+       vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next,
+                       struct omap_vout_buffer, queue);
+       /* Remove buffer from the buffer queue */
+       list_del(&vout->cur_frm->queue);
+       /* Initialize field_id and started member */
+       vout->field_id = 0;
+       vout->first_int = 1;
+       vout->sequence = 0;
+
+       if (omap_vout_calculate_offset(vout)) {
+               ret = -EINVAL;
+               goto out;
+       }
+       if (ovid->rotation_type == VOUT_ROT_VRFB)
+               if (omap_vout_vrfb_buffer_setup(vout, &count, 0)) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+       addr = vout->queued_buf_addr[vout->cur_frm->vbuf.vb2_buf.index]
+               + vout->cropped_offset;
+
+       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+               | DISPC_IRQ_VSYNC2;
+
+       /* First save the configuration in overlay structure */
+       ret = omapvid_init(vout, addr);
+       if (ret) {
+               v4l2_err(&vout->vid_dev->v4l2_dev,
+                               "failed to set overlay info\n");
+               goto streamon_err1;
+       }
+
+       omap_dispc_register_isr(omap_vout_isr, vout, mask);
+
+       /* Enable the pipeline and set the Go bit */
+       ret = omapvid_apply_changes(vout);
+       if (ret)
+               v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
+
+       for (j = 0; j < ovid->num_overlays; j++) {
+               struct omap_overlay *ovl = ovid->overlays[j];
+               struct omap_dss_device *dssdev = ovl->get_device(ovl);
+
+               if (dssdev) {
+                       ret = ovl->enable(ovl);
+                       if (ret)
+                               goto streamon_err1;
+               }
+       }
+       return 0;
+
+streamon_err1:
+       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+               | DISPC_IRQ_VSYNC2;
+
+       omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
+
+       for (j = 0; j < ovid->num_overlays; j++) {
+               struct omap_overlay *ovl = ovid->overlays[j];
+               struct omap_dss_device *dssdev = ovl->get_device(ovl);
+
+               if (dssdev)
+                       ovl->disable(ovl);
+       }
+       /* Turn of the pipeline */
+       if (omapvid_apply_changes(vout))
+               v4l2_err(&vout->vid_dev->v4l2_dev,
+                        "failed to change mode in streamoff\n");
+
+out:
+       vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
+       list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) {
+               list_del(&buf->queue);
+               vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
+       }
+       return ret;
+}
+
+static void omap_vout_vb2_stop_streaming(struct vb2_queue *vq)
+{
+       struct omap_vout_device *vout = vb2_get_drv_priv(vq);
+       struct omapvideo_info *ovid = &vout->vid_info;
+       struct omap_vout_buffer *buf, *tmp;
+       u32 mask = 0;
+       int j;
+
+       mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
+               | DISPC_IRQ_VSYNC2;
+
+       omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
+
+       for (j = 0; j < ovid->num_overlays; j++) {
+               struct omap_overlay *ovl = ovid->overlays[j];
+               struct omap_dss_device *dssdev = ovl->get_device(ovl);
+
+               if (dssdev)
+                       ovl->disable(ovl);
+       }
+       /* Turn of the pipeline */
+       if (omapvid_apply_changes(vout))
+               v4l2_err(&vout->vid_dev->v4l2_dev,
+                        "failed to change mode in streamoff\n");
+
+       if (vout->next_frm != vout->cur_frm)
+               vb2_buffer_done(&vout->next_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
+       vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
+       list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) {
+               list_del(&buf->queue);
+               vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
+       }
+}
+
+static int vidioc_s_fbuf(struct file *file, void *fh,
+                               const struct v4l2_framebuffer *a)
+{
+       int enable = 0;
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct omap_overlay_manager_info info;
+       enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
+       /* OMAP DSS doesn't support Source and Destination color
+          key together */
+       if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
+                       (a->flags & V4L2_FBUF_FLAG_CHROMAKEY))
+               return -EINVAL;
+       /* OMAP DSS Doesn't support the Destination color key
+          and alpha blending together */
+       if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) &&
+                       (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA))
+               return -EINVAL;
+
+       if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) {
+               vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
+               key_type =  OMAP_DSS_COLOR_KEY_VID_SRC;
+       } else
+               vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY;
+
+       if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) {
+               vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+               key_type =  OMAP_DSS_COLOR_KEY_GFX_DST;
+       } else
+               vout->fbuf.flags &=  ~V4L2_FBUF_FLAG_CHROMAKEY;
+
+       if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY |
+                               V4L2_FBUF_FLAG_SRC_CHROMAKEY))
+               enable = 1;
+       else
+               enable = 0;
+       if (ovl->manager && ovl->manager->get_manager_info &&
+                       ovl->manager->set_manager_info) {
+
+               ovl->manager->get_manager_info(ovl->manager, &info);
+               info.trans_enabled = enable;
+               info.trans_key_type = key_type;
+               info.trans_key = vout->win.chromakey;
+
+               if (ovl->manager->set_manager_info(ovl->manager, &info))
+                       return -EINVAL;
+       }
+       if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) {
+               vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+               enable = 1;
+       } else {
+               vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
+               enable = 0;
+       }
+       if (ovl->manager && ovl->manager->get_manager_info &&
+                       ovl->manager->set_manager_info) {
+               ovl->manager->get_manager_info(ovl->manager, &info);
+               /* enable this only if there is no zorder cap */
+               if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+                       info.partial_alpha_enabled = enable;
+               if (ovl->manager->set_manager_info(ovl->manager, &info))
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vidioc_g_fbuf(struct file *file, void *fh,
+               struct v4l2_framebuffer *a)
+{
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
+       struct omap_vout_device *vout = video_drvdata(file);
+       struct omap_overlay_manager_info info;
+       struct omap_video_timings *timing;
+       struct omap_dss_device *dssdev;
+
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+       /* get the display device attached to the overlay */
+       dssdev = ovl->get_device(ovl);
+
+       if (!dssdev)
+               return -EINVAL;
+
+       timing = &dssdev->panel.timings;
+
+       vout->fbuf.fmt.height = timing->y_res;
+       vout->fbuf.fmt.width = timing->x_res;
+       a->fmt.field = V4L2_FIELD_NONE;
+       a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
+       a->fmt.pixelformat = V4L2_PIX_FMT_RGBA32;
+       a->fmt.height = vout->fbuf.fmt.height;
+       a->fmt.width = vout->fbuf.fmt.width;
+       a->fmt.bytesperline = vout->fbuf.fmt.width * 4;
+       a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline;
+       a->base = vout->fbuf.base;
+
+       a->flags = vout->fbuf.flags;
+       a->capability = vout->fbuf.capability;
+       a->flags &= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY | V4L2_FBUF_FLAG_CHROMAKEY |
+                     V4L2_FBUF_FLAG_LOCAL_ALPHA);
+
+       if (ovl->manager && ovl->manager->get_manager_info) {
+               ovl->manager->get_manager_info(ovl->manager, &info);
+               if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC)
+                       a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
+               if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
+                       a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+               if (info.partial_alpha_enabled)
+                       a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+       }
+
+       return 0;
+}
+
+static int vidioc_enum_output(struct file *file, void *priv_fh,
+                             struct v4l2_output *out)
+{
+       if (out->index)
+               return -EINVAL;
+       snprintf(out->name, sizeof(out->name), "Overlay");
+       out->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
+       return 0;
+}
+
+static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i)
+{
+       return i ? -EINVAL : 0;
+}
+
+static const struct v4l2_ioctl_ops vout_ioctl_ops = {
+       .vidioc_querycap                        = vidioc_querycap,
+       .vidioc_enum_fmt_vid_out                = vidioc_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_out                   = vidioc_g_fmt_vid_out,
+       .vidioc_try_fmt_vid_out                 = vidioc_try_fmt_vid_out,
+       .vidioc_s_fmt_vid_out                   = vidioc_s_fmt_vid_out,
+       .vidioc_s_fbuf                          = vidioc_s_fbuf,
+       .vidioc_g_fbuf                          = vidioc_g_fbuf,
+       .vidioc_try_fmt_vid_out_overlay         = vidioc_try_fmt_vid_overlay,
+       .vidioc_s_fmt_vid_out_overlay           = vidioc_s_fmt_vid_overlay,
+       .vidioc_g_fmt_vid_out_overlay           = vidioc_g_fmt_vid_overlay,
+       .vidioc_g_selection                     = vidioc_g_selection,
+       .vidioc_s_selection                     = vidioc_s_selection,
+       .vidioc_enum_output                     = vidioc_enum_output,
+       .vidioc_g_output                        = vidioc_g_output,
+       .vidioc_s_output                        = vidioc_s_output,
+       .vidioc_reqbufs                         = vb2_ioctl_reqbufs,
+       .vidioc_create_bufs                     = vb2_ioctl_create_bufs,
+       .vidioc_querybuf                        = vb2_ioctl_querybuf,
+       .vidioc_qbuf                            = vb2_ioctl_qbuf,
+       .vidioc_dqbuf                           = vb2_ioctl_dqbuf,
+       .vidioc_expbuf                          = vb2_ioctl_expbuf,
+       .vidioc_streamon                        = vb2_ioctl_streamon,
+       .vidioc_streamoff                       = vb2_ioctl_streamoff,
+       .vidioc_subscribe_event                 = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event               = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_file_operations omap_vout_fops = {
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = video_ioctl2,
+       .poll           = vb2_fop_poll,
+       .mmap           = vb2_fop_mmap,
+       .open           = v4l2_fh_open,
+       .release        = vb2_fop_release,
+};
+
+static const struct vb2_ops omap_vout_vb2_ops = {
+       .queue_setup            = omap_vout_vb2_queue_setup,
+       .buf_queue              = omap_vout_vb2_queue,
+       .buf_prepare            = omap_vout_vb2_prepare,
+       .start_streaming        = omap_vout_vb2_start_streaming,
+       .stop_streaming         = omap_vout_vb2_stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+};
+
+/* Init functions used during driver initialization */
+/* Initial setup of video_data */
+static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
+{
+       struct video_device *vfd;
+       struct v4l2_pix_format *pix;
+       struct omap_overlay *ovl = vout->vid_info.overlays[0];
+       struct omap_dss_device *display = ovl->get_device(ovl);
+       struct v4l2_ctrl_handler *hdl;
+       struct vb2_queue *vq;
+       int ret;
+
+       /* set the default pix */
+       pix = &vout->pix;
+
+       /* Set the default picture of QVGA  */
+       pix->width = QQVGA_WIDTH;
+       pix->height = QQVGA_HEIGHT;
+
+       /* Default pixel format is RGB 5-6-5 */
+       pix->pixelformat = V4L2_PIX_FMT_RGB565;
+       pix->field = V4L2_FIELD_NONE;
+       pix->bytesperline = pix->width * 2;
+       pix->sizeimage = pix->bytesperline * pix->height;
+       pix->colorspace = V4L2_COLORSPACE_SRGB;
+
+       vout->bpp = RGB565_BPP;
+       vout->fbuf.fmt.width  =  display->panel.timings.x_res;
+       vout->fbuf.fmt.height =  display->panel.timings.y_res;
+       vout->cropped_offset = 0;
+
+       /* Set the data structures for the overlay parameters*/
+       vout->fbuf.flags = V4L2_FBUF_FLAG_OVERLAY;
+       vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
+               V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY |
+               V4L2_FBUF_CAP_EXTERNOVERLAY;
+       if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) {
+               vout->win.global_alpha = 255;
+               vout->fbuf.capability |= V4L2_FBUF_CAP_GLOBAL_ALPHA;
+               vout->fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+       } else {
+               vout->win.global_alpha = 0;
+       }
+       vout->win.field = V4L2_FIELD_NONE;
+
+       omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
+
+       hdl = &vout->ctrl_handler;
+       v4l2_ctrl_handler_init(hdl, 3);
+       if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) {
+               v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
+                                 V4L2_CID_ROTATE, 0, 270, 90, 0);
+               v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
+                                 V4L2_CID_VFLIP, 0, 1, 1, 0);
+       }
+       v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
+                         V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0);
+       if (hdl->error)
+               return hdl->error;
+
+       vout->rotation = 0;
+       vout->mirror = false;
+       INIT_LIST_HEAD(&vout->dma_queue);
+       if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
+               vout->vrfb_bpp = 2;
+
+       /* initialize the video_device struct */
+       vfd = vout->vfd = video_device_alloc();
+
+       if (!vfd) {
+               printk(KERN_ERR VOUT_NAME
+                      ": could not allocate video device struct\n");
+               v4l2_ctrl_handler_free(hdl);
+               return -ENOMEM;
+       }
+       vfd->ctrl_handler = hdl;
+       vfd->release = video_device_release;
+       vfd->ioctl_ops = &vout_ioctl_ops;
+
+       strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
+
+       vfd->fops = &omap_vout_fops;
+       vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
+       vfd->vfl_dir = VFL_DIR_TX;
+       vfd->minor = -1;
+       vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+                          V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+       mutex_init(&vout->lock);
+
+       vq = &vout->vq;
+       vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       vq->drv_priv = vout;
+       vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       vq->buf_struct_size = sizeof(struct omap_vout_buffer);
+       vq->dev = vfd->v4l2_dev->dev;
+
+       vq->ops = &omap_vout_vb2_ops;
+       vq->mem_ops = &vb2_dma_contig_memops;
+       vq->lock = &vout->lock;
+       vq->min_buffers_needed = 1;
+       vfd->queue = vq;
+
+       ret = vb2_queue_init(vq);
+       if (ret) {
+               v4l2_ctrl_handler_free(hdl);
+               video_device_release(vfd);
+       }
+       return ret;
+}
+
+/* Setup video buffers */
+static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
+               int vid_num)
+{
+       struct omapvideo_info *ovid;
+       struct omap_vout_device *vout;
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+       struct omap2video_device *vid_dev =
+               container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
+       int ret = 0;
+
+       vout = vid_dev->vouts[vid_num];
+       ovid = &vout->vid_info;
+
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               bool static_vrfb_allocation = (vid_num == 0) ?
+                       vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
+               ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
+                               static_vrfb_allocation);
+       }
+       return ret;
+}
+
+/* Create video out devices */
+static int __init omap_vout_create_video_devices(struct platform_device *pdev)
+{
+       int ret = 0, k;
+       struct omap_vout_device *vout;
+       struct video_device *vfd = NULL;
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+       struct omap2video_device *vid_dev = container_of(v4l2_dev,
+                       struct omap2video_device, v4l2_dev);
+       struct omap_overlay *ovl = vid_dev->overlays[0];
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       for (k = 0; k < pdev->num_resources; k++) {
+
+               vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
+               if (!vout) {
+                       dev_err(&pdev->dev, ": could not allocate memory\n");
+                       return -ENOMEM;
+               }
+
+               vout->vid = k;
+               vid_dev->vouts[k] = vout;
+               vout->vid_dev = vid_dev;
+               /* Select video2 if only 1 overlay is controlled by V4L2 */
+               if (pdev->num_resources == 1)
+                       vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
+               else
+                       /* Else select video1 and video2 one by one. */
+                       vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
+               vout->vid_info.num_overlays = 1;
+               vout->vid_info.id = k + 1;
+               spin_lock_init(&vout->vbq_lock);
+               /*
+                * Set the framebuffer base, this allows applications to find
+                * the fb corresponding to this overlay.
+                *
+                * To be precise: fbuf.base should match smem_start of
+                * struct fb_fix_screeninfo.
+                */
+               vout->fbuf.base = (void *)(uintptr_t)info.paddr;
+
+               /* Set VRFB as rotation_type for omap2 and omap3 */
+               if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
+                       vout->vid_info.rotation_type = VOUT_ROT_VRFB;
+
+               /* Setup the default configuration for the video devices
+                */
+               if (omap_vout_setup_video_data(vout) != 0) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+
+               /* Allocate default number of buffers for the video streaming
+                * and reserve the VRFB space for rotation
+                */
+               if (omap_vout_setup_video_bufs(pdev, k) != 0) {
+                       ret = -ENOMEM;
+                       goto error1;
+               }
+
+               /* Register the Video device with V4L2
+                */
+               vfd = vout->vfd;
+               if (video_register_device(vfd, VFL_TYPE_VIDEO, -1) < 0) {
+                       dev_err(&pdev->dev,
+                               ": Could not register Video for Linux device\n");
+                       vfd->minor = -1;
+                       ret = -ENODEV;
+                       goto error2;
+               }
+               video_set_drvdata(vfd, vout);
+
+               dev_info(&pdev->dev,
+                        ": registered and initialized video device %d\n",
+                        vfd->minor);
+               if (k == (pdev->num_resources - 1))
+                       return 0;
+
+               continue;
+error2:
+               if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
+                       omap_vout_release_vrfb(vout);
+error1:
+               video_device_release(vfd);
+error:
+               kfree(vout);
+               return ret;
+       }
+
+       return -ENODEV;
+}
+/* Driver functions */
+static void omap_vout_cleanup_device(struct omap_vout_device *vout)
+{
+       struct video_device *vfd;
+       struct omapvideo_info *ovid;
+
+       if (!vout)
+               return;
+
+       vfd = vout->vfd;
+       ovid = &vout->vid_info;
+       if (vfd) {
+               if (!video_is_registered(vfd)) {
+                       /*
+                        * The device was never registered, so release the
+                        * video_device struct directly.
+                        */
+                       video_device_release(vfd);
+               } else {
+                       /*
+                        * The unregister function will release the video_device
+                        * struct as well as unregistering it.
+                        */
+                       video_unregister_device(vfd);
+               }
+       }
+       v4l2_ctrl_handler_free(&vout->ctrl_handler);
+       if (ovid->rotation_type == VOUT_ROT_VRFB) {
+               omap_vout_release_vrfb(vout);
+               /* Free the VRFB buffer if allocated
+                * init time
+                */
+               if (vout->vrfb_static_allocation)
+                       omap_vout_free_vrfb_buffers(vout);
+       }
+
+       kfree(vout);
+}
+
+static int omap_vout_remove(struct platform_device *pdev)
+{
+       int k;
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+       struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
+                       omap2video_device, v4l2_dev);
+
+       v4l2_device_unregister(v4l2_dev);
+       for (k = 0; k < pdev->num_resources; k++)
+               omap_vout_cleanup_device(vid_dev->vouts[k]);
+
+       for (k = 0; k < vid_dev->num_displays; k++) {
+               if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
+                       vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);
+
+               omap_dss_put_device(vid_dev->displays[k]);
+       }
+       kfree(vid_dev);
+       return 0;
+}
+
+static int __init omap_vout_probe(struct platform_device *pdev)
+{
+       int ret = 0, i;
+       struct omap_overlay *ovl;
+       struct omap_dss_device *dssdev = NULL;
+       struct omap_dss_device *def_display;
+       struct omap2video_device *vid_dev = NULL;
+
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
+
+       ret = omapdss_compat_init();
+       if (ret) {
+               dev_err(&pdev->dev, "failed to init dss\n");
+               return ret;
+       }
+
+       if (pdev->num_resources == 0) {
+               dev_err(&pdev->dev, "probed for an unknown device\n");
+               ret = -ENODEV;
+               goto err_dss_init;
+       }
+
+       vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
+       if (vid_dev == NULL) {
+               ret = -ENOMEM;
+               goto err_dss_init;
+       }
+
+       vid_dev->num_displays = 0;
+       for_each_dss_dev(dssdev) {
+               omap_dss_get_device(dssdev);
+
+               if (!dssdev->driver) {
+                       dev_warn(&pdev->dev, "no driver for display: %s\n",
+                                       dssdev->name);
+                       omap_dss_put_device(dssdev);
+                       continue;
+               }
+
+               vid_dev->displays[vid_dev->num_displays++] = dssdev;
+       }
+
+       if (vid_dev->num_displays == 0) {
+               dev_err(&pdev->dev, "no displays\n");
+               ret = -EINVAL;
+               goto probe_err0;
+       }
+
+       vid_dev->num_overlays = omap_dss_get_num_overlays();
+       for (i = 0; i < vid_dev->num_overlays; i++)
+               vid_dev->overlays[i] = omap_dss_get_overlay(i);
+
+       vid_dev->num_managers = omap_dss_get_num_overlay_managers();
+       for (i = 0; i < vid_dev->num_managers; i++)
+               vid_dev->managers[i] = omap_dss_get_overlay_manager(i);
+
+       /* Get the Video1 overlay and video2 overlay.
+        * Setup the Display attached to that overlays
+        */
+       for (i = 1; i < vid_dev->num_overlays; i++) {
+               ovl = omap_dss_get_overlay(i);
+               dssdev = ovl->get_device(ovl);
+
+               if (dssdev) {
+                       def_display = dssdev;
+               } else {
+                       dev_warn(&pdev->dev, "cannot find display\n");
+                       def_display = NULL;
+               }
+               if (def_display) {
+                       struct omap_dss_driver *dssdrv = def_display->driver;
+
+                       ret = dssdrv->enable(def_display);
+                       if (ret) {
+                               /* Here we are not considering a error
+                                *  as display may be enabled by frame
+                                *  buffer driver
+                                */
+                               dev_warn(&pdev->dev,
+                                       "'%s' Display already enabled\n",
+                                       def_display->name);
+                       }
+               }
+       }
+
+       if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) {
+               dev_err(&pdev->dev, "v4l2_device_register failed\n");
+               ret = -ENODEV;
+               goto probe_err1;
+       }
+
+       ret = omap_vout_create_video_devices(pdev);
+       if (ret)
+               goto probe_err2;
+
+       for (i = 0; i < vid_dev->num_displays; i++) {
+               struct omap_dss_device *display = vid_dev->displays[i];
+
+               if (display->driver->update)
+                       display->driver->update(display, 0, 0,
+                                       display->panel.timings.x_res,
+                                       display->panel.timings.y_res);
+       }
+       return 0;
+
+probe_err2:
+       v4l2_device_unregister(&vid_dev->v4l2_dev);
+probe_err1:
+       for (i = 1; i < vid_dev->num_overlays; i++) {
+               def_display = NULL;
+               ovl = omap_dss_get_overlay(i);
+               dssdev = ovl->get_device(ovl);
+
+               if (dssdev)
+                       def_display = dssdev;
+
+               if (def_display && def_display->driver)
+                       def_display->driver->disable(def_display);
+       }
+probe_err0:
+       kfree(vid_dev);
+err_dss_init:
+       omapdss_compat_uninit();
+       return ret;
+}
+
+static struct platform_driver omap_vout_driver = {
+       .driver = {
+               .name = VOUT_NAME,
+       },
+       .remove = omap_vout_remove,
+};
+
+static int __init omap_vout_init(void)
+{
+       if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) {
+               printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void omap_vout_cleanup(void)
+{
+       platform_driver_unregister(&omap_vout_driver);
+}
+
+late_initcall(omap_vout_init);
+module_exit(omap_vout_cleanup);
diff --git a/drivers/media/platform/ti/omap/omap_vout_vrfb.c b/drivers/media/platform/ti/omap/omap_vout_vrfb.c
new file mode 100644 (file)
index 0000000..0cfa016
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * omap_vout_vrfb.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+
+#include <video/omapvrfb.h>
+
+#include "omap_voutdef.h"
+#include "omap_voutlib.h"
+#include "omap_vout_vrfb.h"
+
+#define OMAP_DMA_NO_DEVICE     0
+
+/*
+ * Function for allocating video buffers
+ */
+static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
+               unsigned int *count, int startindex)
+{
+       int i, j;
+
+       for (i = 0; i < *count; i++) {
+               if (!vout->smsshado_virt_addr[i]) {
+                       vout->smsshado_virt_addr[i] =
+                               omap_vout_alloc_buffer(vout->smsshado_size,
+                                               &vout->smsshado_phy_addr[i]);
+               }
+               if (!vout->smsshado_virt_addr[i] && startindex != -1) {
+                       if (vout->vq.memory == V4L2_MEMORY_MMAP && i >= startindex)
+                               break;
+               }
+               if (!vout->smsshado_virt_addr[i]) {
+                       for (j = 0; j < i; j++) {
+                               omap_vout_free_buffer(
+                                               vout->smsshado_virt_addr[j],
+                                               vout->smsshado_size);
+                               vout->smsshado_virt_addr[j] = 0;
+                               vout->smsshado_phy_addr[j] = 0;
+                       }
+                       *count = 0;
+                       return -ENOMEM;
+               }
+               memset((void *)(long)vout->smsshado_virt_addr[i], 0,
+                      vout->smsshado_size);
+       }
+       return 0;
+}
+
+/*
+ * Wakes up the application once the DMA transfer to VRFB space is completed.
+ */
+static void omap_vout_vrfb_dma_tx_callback(void *data)
+{
+       struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
+
+       t->tx_status = 1;
+       wake_up_interruptible(&t->wait);
+}
+
+/*
+ * Free VRFB buffers
+ */
+void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
+{
+       int j;
+
+       for (j = 0; j < VRFB_NUM_BUFS; j++) {
+               if (vout->smsshado_virt_addr[j]) {
+                       omap_vout_free_buffer(vout->smsshado_virt_addr[j],
+                                             vout->smsshado_size);
+                       vout->smsshado_virt_addr[j] = 0;
+                       vout->smsshado_phy_addr[j] = 0;
+               }
+       }
+}
+
+int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
+                             bool static_vrfb_allocation)
+{
+       int ret = 0, i, j;
+       struct omap_vout_device *vout;
+       struct video_device *vfd;
+       dma_cap_mask_t mask;
+       int image_width, image_height;
+       int vrfb_num_bufs = VRFB_NUM_BUFS;
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+       struct omap2video_device *vid_dev =
+               container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
+
+       vout = vid_dev->vouts[vid_num];
+       vfd = vout->vfd;
+
+       for (i = 0; i < VRFB_NUM_BUFS; i++) {
+               if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
+                       dev_info(&pdev->dev, ": VRFB allocation failed\n");
+                       for (j = 0; j < i; j++)
+                               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+                       return -ENOMEM;
+               }
+       }
+
+       /* Calculate VRFB memory size */
+       /* allocate for worst case size */
+       image_width = VID_MAX_WIDTH / TILE_SIZE;
+       if (VID_MAX_WIDTH % TILE_SIZE)
+               image_width++;
+
+       image_width = image_width * TILE_SIZE;
+       image_height = VID_MAX_HEIGHT / TILE_SIZE;
+
+       if (VID_MAX_HEIGHT % TILE_SIZE)
+               image_height++;
+
+       image_height = image_height * TILE_SIZE;
+       vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
+
+       /*
+        * Request and Initialize DMA, for DMA based VRFB transfer
+        */
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_INTERLEAVE, mask);
+       vout->vrfb_dma_tx.chan = dma_request_chan_by_mask(&mask);
+       if (IS_ERR(vout->vrfb_dma_tx.chan)) {
+               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+       } else {
+               size_t xt_size = sizeof(struct dma_interleaved_template) +
+                                sizeof(struct data_chunk);
+
+               vout->vrfb_dma_tx.xt = kzalloc(xt_size, GFP_KERNEL);
+               if (!vout->vrfb_dma_tx.xt) {
+                       dma_release_channel(vout->vrfb_dma_tx.chan);
+                       vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+               }
+       }
+
+       if (vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED)
+               dev_info(&pdev->dev,
+                        ": failed to allocate DMA Channel for video%d\n",
+                        vfd->minor);
+
+       init_waitqueue_head(&vout->vrfb_dma_tx.wait);
+
+       /*
+        * statically allocated the VRFB buffer is done through
+        * command line arguments
+        */
+       if (static_vrfb_allocation) {
+               if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
+                       ret =  -ENOMEM;
+                       goto release_vrfb_ctx;
+               }
+               vout->vrfb_static_allocation = true;
+       }
+       return 0;
+
+release_vrfb_ctx:
+       for (j = 0; j < VRFB_NUM_BUFS; j++)
+               omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+       return ret;
+}
+
+/*
+ * Release the VRFB context once the module exits
+ */
+void omap_vout_release_vrfb(struct omap_vout_device *vout)
+{
+       int i;
+
+       for (i = 0; i < VRFB_NUM_BUFS; i++)
+               omap_vrfb_release_ctx(&vout->vrfb_context[i]);
+
+       if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
+               vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+               kfree(vout->vrfb_dma_tx.xt);
+               dmaengine_terminate_sync(vout->vrfb_dma_tx.chan);
+               dma_release_channel(vout->vrfb_dma_tx.chan);
+       }
+}
+
+/*
+ * Allocate the buffers for the VRFB space.  Data is copied from V4L2
+ * buffers to the VRFB buffers using the DMA engine.
+ */
+int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+                         unsigned int *count, unsigned int startindex)
+{
+       int i;
+       bool yuv_mode;
+
+       if (!is_rotation_enabled(vout))
+               return 0;
+
+       /* If rotation is enabled, allocate memory for VRFB space also */
+       *count = *count > VRFB_NUM_BUFS ? VRFB_NUM_BUFS : *count;
+
+       /* Allocate the VRFB buffers only if the buffers are not
+        * allocated during init time.
+        */
+       if (!vout->vrfb_static_allocation)
+               if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
+                       return -ENOMEM;
+
+       if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
+                       vout->dss_mode == OMAP_DSS_COLOR_UYVY)
+               yuv_mode = true;
+       else
+               yuv_mode = false;
+
+       for (i = 0; i < *count; i++)
+               omap_vrfb_setup(&vout->vrfb_context[i],
+                               vout->smsshado_phy_addr[i], vout->pix.width,
+                               vout->pix.height, vout->bpp, yuv_mode);
+
+       return 0;
+}
+
+int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
+                          struct vb2_buffer *vb)
+{
+       struct dma_async_tx_descriptor *tx;
+       enum dma_ctrl_flags flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+       struct dma_chan *chan = vout->vrfb_dma_tx.chan;
+       struct dma_interleaved_template *xt = vout->vrfb_dma_tx.xt;
+       dma_cookie_t cookie;
+       dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+       enum dma_status status;
+       enum dss_rotation rotation;
+       size_t dst_icg;
+       u32 pixsize;
+
+       if (!is_rotation_enabled(vout))
+               return 0;
+
+       /* If rotation is enabled, copy input buffer into VRFB
+        * memory space using DMA. We are copying input buffer
+        * into VRFB memory space of desired angle and DSS will
+        * read image VRFB memory for 0 degree angle
+        */
+
+       pixsize = vout->bpp * vout->vrfb_bpp;
+       dst_icg = MAX_PIXELS_PER_LINE * pixsize - vout->pix.width * vout->bpp;
+
+       xt->src_start = buf_phy_addr;
+       xt->dst_start = vout->vrfb_context[vb->index].paddr[0];
+
+       xt->numf = vout->pix.height;
+       xt->frame_size = 1;
+       xt->sgl[0].size = vout->pix.width * vout->bpp;
+       xt->sgl[0].icg = dst_icg;
+
+       xt->dir = DMA_MEM_TO_MEM;
+       xt->src_sgl = false;
+       xt->src_inc = true;
+       xt->dst_sgl = true;
+       xt->dst_inc = true;
+
+       tx = dmaengine_prep_interleaved_dma(chan, xt, flags);
+       if (tx == NULL) {
+               pr_err("%s: DMA interleaved prep error\n", __func__);
+               return -EINVAL;
+       }
+
+       tx->callback = omap_vout_vrfb_dma_tx_callback;
+       tx->callback_param = &vout->vrfb_dma_tx;
+
+       cookie = dmaengine_submit(tx);
+       if (dma_submit_error(cookie)) {
+               pr_err("%s: dmaengine_submit failed (%d)\n", __func__, cookie);
+               return -EINVAL;
+       }
+
+       vout->vrfb_dma_tx.tx_status = 0;
+       dma_async_issue_pending(chan);
+
+       wait_event_interruptible_timeout(vout->vrfb_dma_tx.wait,
+                                        vout->vrfb_dma_tx.tx_status == 1,
+                                        VRFB_TX_TIMEOUT);
+
+       status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+
+       if (vout->vrfb_dma_tx.tx_status == 0) {
+               pr_err("%s: Timeout while waiting for DMA\n", __func__);
+               dmaengine_terminate_sync(chan);
+               return -EINVAL;
+       } else if (status != DMA_COMPLETE) {
+               pr_err("%s: DMA completion %s status\n", __func__,
+                      status == DMA_ERROR ? "error" : "busy");
+               dmaengine_terminate_sync(chan);
+               return -EINVAL;
+       }
+
+       /* Store buffers physical address into an array. Addresses
+        * from this array will be used to configure DSS */
+       rotation = calc_rotation(vout);
+       vout->queued_buf_addr[vb->index] =
+               vout->vrfb_context[vb->index].paddr[rotation];
+       return 0;
+}
+
+/*
+ * Calculate the buffer offsets from which the streaming should
+ * start. This offset calculation is mainly required because of
+ * the VRFB 32 pixels alignment with rotation.
+ */
+void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout)
+{
+       enum dss_rotation rotation;
+       bool mirroring = vout->mirror;
+       struct v4l2_rect *crop = &vout->crop;
+       struct v4l2_pix_format *pix = &vout->pix;
+       int *cropped_offset = &vout->cropped_offset;
+       int vr_ps = 1, ps = 2, temp_ps = 2;
+       int offset = 0, ctop = 0, cleft = 0, line_length = 0;
+
+       rotation = calc_rotation(vout);
+
+       if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+                       V4L2_PIX_FMT_UYVY == pix->pixelformat) {
+               if (is_rotation_enabled(vout)) {
+                       /*
+                        * ps    - Actual pixel size for YUYV/UYVY for
+                        *         VRFB/Mirroring is 4 bytes
+                        * vr_ps - Virtually pixel size for YUYV/UYVY is
+                        *         2 bytes
+                        */
+                       ps = 4;
+                       vr_ps = 2;
+               } else {
+                       ps = 2; /* otherwise the pixel size is 2 byte */
+               }
+       } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
+               ps = 4;
+       } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
+               ps = 3;
+       }
+       vout->ps = ps;
+       vout->vr_ps = vr_ps;
+
+       if (is_rotation_enabled(vout)) {
+               line_length = MAX_PIXELS_PER_LINE;
+               ctop = (pix->height - crop->height) - crop->top;
+               cleft = (pix->width - crop->width) - crop->left;
+       } else {
+               line_length = pix->width;
+       }
+       vout->line_length = line_length;
+       switch (rotation) {
+       case dss_rotation_90_degree:
+               offset = vout->vrfb_context[0].yoffset *
+                       vout->vrfb_context[0].bytespp;
+               temp_ps = ps / vr_ps;
+               if (!mirroring) {
+                       *cropped_offset = offset + line_length *
+                               temp_ps * cleft + crop->top * temp_ps;
+               } else {
+                       *cropped_offset = offset + line_length * temp_ps *
+                               cleft + crop->top * temp_ps + (line_length *
+                               ((crop->width / (vr_ps)) - 1) * ps);
+               }
+               break;
+       case dss_rotation_180_degree:
+               offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
+                       vout->vrfb_context[0].bytespp) +
+                       (vout->vrfb_context[0].xoffset *
+                       vout->vrfb_context[0].bytespp));
+               if (!mirroring) {
+                       *cropped_offset = offset + (line_length * ps * ctop) +
+                               (cleft / vr_ps) * ps;
+
+               } else {
+                       *cropped_offset = offset + (line_length * ps * ctop) +
+                               (cleft / vr_ps) * ps + (line_length *
+                               (crop->height - 1) * ps);
+               }
+               break;
+       case dss_rotation_270_degree:
+               offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
+                       vout->vrfb_context[0].bytespp;
+               temp_ps = ps / vr_ps;
+               if (!mirroring) {
+                       *cropped_offset = offset + line_length *
+                           temp_ps * crop->left + ctop * ps;
+               } else {
+                       *cropped_offset = offset + line_length *
+                               temp_ps * crop->left + ctop * ps +
+                               (line_length * ((crop->width / vr_ps) - 1) *
+                                ps);
+               }
+               break;
+       case dss_rotation_0_degree:
+               if (!mirroring) {
+                       *cropped_offset = (line_length * ps) *
+                               crop->top + (crop->left / vr_ps) * ps;
+               } else {
+                       *cropped_offset = (line_length * ps) *
+                               crop->top + (crop->left / vr_ps) * ps +
+                               (line_length * (crop->height - 1) * ps);
+               }
+               break;
+       default:
+               *cropped_offset = (line_length * ps * crop->top) /
+                       vr_ps + (crop->left * ps) / vr_ps +
+                       ((crop->width / vr_ps) - 1) * ps;
+               break;
+       }
+}
diff --git a/drivers/media/platform/ti/omap/omap_vout_vrfb.h b/drivers/media/platform/ti/omap/omap_vout_vrfb.h
new file mode 100644 (file)
index 0000000..40bc9e5
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * omap_vout_vrfb.h
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef OMAP_VOUT_VRFB_H
+#define OMAP_VOUT_VRFB_H
+
+#ifdef CONFIG_VIDEO_OMAP2_VOUT_VRFB
+void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout);
+int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
+                       bool static_vrfb_allocation);
+void omap_vout_release_vrfb(struct omap_vout_device *vout);
+int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+                       unsigned int *count, unsigned int startindex);
+int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
+                       struct vb2_buffer *vb);
+void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout);
+#else
+static inline void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) { };
+static inline int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
+                       bool static_vrfb_allocation)
+               { return 0; };
+static inline void omap_vout_release_vrfb(struct omap_vout_device *vout) { };
+static inline int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+                       unsigned int *count, unsigned int startindex)
+               { return 0; };
+static inline int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
+                       struct vb2_buffer *vb)
+               { return 0; };
+static inline void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout) { };
+#endif
+
+#endif
diff --git a/drivers/media/platform/ti/omap/omap_voutdef.h b/drivers/media/platform/ti/omap/omap_voutdef.h
new file mode 100644 (file)
index 0000000..b586193
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * omap_voutdef.h
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef OMAP_VOUTDEF_H
+#define OMAP_VOUTDEF_H
+
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-ctrls.h>
+#include <video/omapfb_dss.h>
+#include <video/omapvrfb.h>
+#include <linux/dmaengine.h>
+
+#define YUYV_BPP        2
+#define RGB565_BPP      2
+#define RGB24_BPP       3
+#define RGB32_BPP       4
+#define TILE_SIZE       32
+#define YUYV_VRFB_BPP   2
+#define RGB_VRFB_BPP    1
+#define MAX_CID                3
+#define MAC_VRFB_CTXS  4
+#define MAX_VOUT_DEV   2
+#define MAX_OVLS       3
+#define MAX_DISPLAYS   10
+#define MAX_MANAGERS   3
+
+#define QQVGA_WIDTH            160
+#define QQVGA_HEIGHT           120
+
+/* Max Resolution supported by the driver */
+#define VID_MAX_WIDTH          1280    /* Largest width */
+#define VID_MAX_HEIGHT         720     /* Largest height */
+
+/* Minimum requirement is 2x2 for DSS */
+#define VID_MIN_WIDTH          2
+#define VID_MIN_HEIGHT         2
+
+/* 2048 x 2048 is max res supported by OMAP display controller */
+#define MAX_PIXELS_PER_LINE     2048
+
+#define VRFB_TX_TIMEOUT         1000
+#define VRFB_NUM_BUFS          4
+
+/* Max buffer size tobe allocated during init */
+#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
+
+enum dma_channel_state {
+       DMA_CHAN_NOT_ALLOTED,
+       DMA_CHAN_ALLOTED,
+};
+
+/* Enum for Rotation
+ * DSS understands rotation in 0, 1, 2, 3 context
+ * while V4L2 driver understands it as 0, 90, 180, 270
+ */
+enum dss_rotation {
+       dss_rotation_0_degree   = 0,
+       dss_rotation_90_degree  = 1,
+       dss_rotation_180_degree = 2,
+       dss_rotation_270_degree = 3,
+};
+
+/* Enum for choosing rotation type for vout
+ * DSS2 doesn't understand no rotation as an
+ * option while V4L2 driver doesn't support
+ * rotation in the case where VRFB is not built in
+ * the kernel
+ */
+enum vout_rotaion_type {
+       VOUT_ROT_NONE   = 0,
+       VOUT_ROT_VRFB   = 1,
+};
+
+/*
+ * This structure is used to store the DMA transfer parameters
+ * for VRFB hidden buffer
+ */
+struct vid_vrfb_dma {
+       struct dma_chan *chan;
+       struct dma_interleaved_template *xt;
+
+       int req_status;
+       int tx_status;
+       wait_queue_head_t wait;
+};
+
+struct omapvideo_info {
+       int id;
+       int num_overlays;
+       struct omap_overlay *overlays[MAX_OVLS];
+       enum vout_rotaion_type rotation_type;
+};
+
+struct omap2video_device {
+       struct mutex  mtx;
+
+       int state;
+
+       struct v4l2_device v4l2_dev;
+       struct omap_vout_device *vouts[MAX_VOUT_DEV];
+
+       int num_displays;
+       struct omap_dss_device *displays[MAX_DISPLAYS];
+       int num_overlays;
+       struct omap_overlay *overlays[MAX_OVLS];
+       int num_managers;
+       struct omap_overlay_manager *managers[MAX_MANAGERS];
+};
+
+/* buffer for one video frame */
+struct omap_vout_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_v4l2_buffer          vbuf;
+       struct list_head                queue;
+};
+
+static inline struct omap_vout_buffer *vb2_to_omap_vout_buffer(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+       return container_of(vbuf, struct omap_vout_buffer, vbuf);
+}
+
+/* per-device data structure */
+struct omap_vout_device {
+
+       struct omapvideo_info vid_info;
+       struct video_device *vfd;
+       struct omap2video_device *vid_dev;
+       struct v4l2_ctrl_handler ctrl_handler;
+       int vid;
+
+       /* allow to reuse previously allocated buffer which is big enough */
+       int buffer_size;
+       enum omap_color_mode dss_mode;
+
+       u32 sequence;
+
+       struct v4l2_pix_format pix;
+       struct v4l2_rect crop;
+       struct v4l2_window win;
+       struct v4l2_framebuffer fbuf;
+
+       /* Lock to protect the shared data structures in ioctl */
+       struct mutex lock;
+
+       enum dss_rotation rotation;
+       bool mirror;
+       int flicker_filter;
+
+       int bpp; /* bytes per pixel */
+       int vrfb_bpp; /* bytes per pixel with respect to VRFB */
+
+       struct vid_vrfb_dma vrfb_dma_tx;
+       unsigned int smsshado_phy_addr[MAC_VRFB_CTXS];
+       unsigned int smsshado_virt_addr[MAC_VRFB_CTXS];
+       struct vrfb vrfb_context[MAC_VRFB_CTXS];
+       bool vrfb_static_allocation;
+       unsigned int smsshado_size;
+       unsigned char pos;
+
+       int ps, vr_ps, line_length, first_int, field_id;
+       struct omap_vout_buffer *cur_frm, *next_frm;
+       spinlock_t vbq_lock;            /* spinlock for dma_queue */
+       struct list_head dma_queue;
+       dma_addr_t queued_buf_addr[VIDEO_MAX_FRAME];
+       u32 cropped_offset;
+       s32 tv_field1_offset;
+       void *isr_handle;
+       struct vb2_queue vq;
+
+};
+
+/*
+ * Return true if rotation is 90 or 270
+ */
+static inline int is_rotation_90_or_270(const struct omap_vout_device *vout)
+{
+       return (vout->rotation == dss_rotation_90_degree ||
+                       vout->rotation == dss_rotation_270_degree);
+}
+
+/*
+ * Return true if rotation is enabled
+ */
+static inline int is_rotation_enabled(const struct omap_vout_device *vout)
+{
+       return vout->rotation || vout->mirror;
+}
+
+/*
+ * Reverse the rotation degree if mirroring is enabled
+ */
+static inline int calc_rotation(const struct omap_vout_device *vout)
+{
+       if (!vout->mirror)
+               return vout->rotation;
+
+       switch (vout->rotation) {
+       case dss_rotation_90_degree:
+               return dss_rotation_270_degree;
+       case dss_rotation_270_degree:
+               return dss_rotation_90_degree;
+       case dss_rotation_180_degree:
+               return dss_rotation_0_degree;
+       default:
+               return dss_rotation_180_degree;
+       }
+}
+
+void omap_vout_free_buffers(struct omap_vout_device *vout);
+#endif /* ifndef OMAP_VOUTDEF_H */
diff --git a/drivers/media/platform/ti/omap/omap_voutlib.c b/drivers/media/platform/ti/omap/omap_voutlib.c
new file mode 100644 (file)
index 0000000..480a7e9
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * omap_voutlib.c
+ *
+ * Copyright (C) 2005-2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * Based on the OMAP2 camera driver
+ * Video-for-Linux (Version 2) camera capture driver for
+ * the OMAP24xx camera controller.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <linux/dma-mapping.h>
+
+#include <video/omapfb_dss.h>
+
+#include "omap_voutlib.h"
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("OMAP Video library");
+MODULE_LICENSE("GPL");
+
+/* Return the default overlay cropping rectangle in crop given the image
+ * size in pix and the video display size in fbuf.  The default
+ * cropping rectangle is the largest rectangle no larger than the capture size
+ * that will fit on the display.  The default cropping rectangle is centered in
+ * the image.  All dimensions and offsets are rounded down to even numbers.
+ */
+void omap_vout_default_crop(struct v4l2_pix_format *pix,
+                 struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop)
+{
+       crop->width = (pix->width < fbuf->fmt.width) ?
+               pix->width : fbuf->fmt.width;
+       crop->height = (pix->height < fbuf->fmt.height) ?
+               pix->height : fbuf->fmt.height;
+       crop->width &= ~1;
+       crop->height &= ~1;
+       crop->left = ((pix->width - crop->width) >> 1) & ~1;
+       crop->top = ((pix->height - crop->height) >> 1) & ~1;
+}
+EXPORT_SYMBOL_GPL(omap_vout_default_crop);
+
+/* Given a new render window in new_win, adjust the window to the
+ * nearest supported configuration.  The adjusted window parameters are
+ * returned in new_win.
+ * Returns zero if successful, or -EINVAL if the requested window is
+ * impossible and cannot reasonably be adjusted.
+ */
+int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+                       struct v4l2_window *new_win)
+{
+       struct v4l2_rect try_win;
+
+       /* make a working copy of the new_win rectangle */
+       try_win = new_win->w;
+
+       /* adjust the preview window so it fits on the display by clipping any
+        * offscreen areas
+        */
+       if (try_win.left < 0) {
+               try_win.width += try_win.left;
+               try_win.left = 0;
+       }
+       if (try_win.top < 0) {
+               try_win.height += try_win.top;
+               try_win.top = 0;
+       }
+       try_win.width = (try_win.width < fbuf->fmt.width) ?
+               try_win.width : fbuf->fmt.width;
+       try_win.height = (try_win.height < fbuf->fmt.height) ?
+               try_win.height : fbuf->fmt.height;
+       if (try_win.left + try_win.width > fbuf->fmt.width)
+               try_win.width = fbuf->fmt.width - try_win.left;
+       if (try_win.top + try_win.height > fbuf->fmt.height)
+               try_win.height = fbuf->fmt.height - try_win.top;
+       try_win.width &= ~1;
+       try_win.height &= ~1;
+
+       if (try_win.width <= 0 || try_win.height <= 0)
+               return -EINVAL;
+
+       /* We now have a valid preview window, so go with it */
+       new_win->w = try_win;
+       new_win->field = V4L2_FIELD_NONE;
+       new_win->clips = NULL;
+       new_win->clipcount = 0;
+       new_win->bitmap = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_vout_try_window);
+
+/* Given a new render window in new_win, adjust the window to the
+ * nearest supported configuration.  The image cropping window in crop
+ * will also be adjusted if necessary.  Preference is given to keeping the
+ * the window as close to the requested configuration as possible.  If
+ * successful, new_win, vout->win, and crop are updated.
+ * Returns zero if successful, or -EINVAL if the requested preview window is
+ * impossible and cannot reasonably be adjusted.
+ */
+int omap_vout_new_window(struct v4l2_rect *crop,
+               struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
+               struct v4l2_window *new_win)
+{
+       int err;
+
+       err = omap_vout_try_window(fbuf, new_win);
+       if (err)
+               return err;
+
+       /* update our preview window */
+       win->w = new_win->w;
+       win->field = new_win->field;
+       win->chromakey = new_win->chromakey;
+
+       /* Adjust the cropping window to allow for resizing limitation */
+       if (omap_vout_dss_omap24xx()) {
+               /* For 24xx limit is 8x to 1/2x scaling. */
+               if ((crop->height/win->w.height) >= 2)
+                       crop->height = win->w.height * 2;
+
+               if ((crop->width/win->w.width) >= 2)
+                       crop->width = win->w.width * 2;
+
+               if (crop->width > 768) {
+                       /* The OMAP2420 vertical resizing line buffer is 768
+                        * pixels wide. If the cropped image is wider than
+                        * 768 pixels then it cannot be vertically resized.
+                        */
+                       if (crop->height != win->w.height)
+                               crop->width = 768;
+               }
+       } else if (omap_vout_dss_omap34xx()) {
+               /* For 34xx limit is 8x to 1/4x scaling. */
+               if ((crop->height/win->w.height) >= 4)
+                       crop->height = win->w.height * 4;
+
+               if ((crop->width/win->w.width) >= 4)
+                       crop->width = win->w.width * 4;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_vout_new_window);
+
+/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
+ * the nearest supported configuration.  The image render window in win will
+ * also be adjusted if necessary.  The preview window is adjusted such that the
+ * horizontal and vertical rescaling ratios stay constant.  If the render
+ * window would fall outside the display boundaries, the cropping rectangle
+ * will also be adjusted to maintain the rescaling ratios.  If successful, crop
+ * and win are updated.
+ * Returns zero if successful, or -EINVAL if the requested cropping rectangle is
+ * impossible and cannot reasonably be adjusted.
+ */
+int omap_vout_new_crop(struct v4l2_pix_format *pix,
+             struct v4l2_rect *crop, struct v4l2_window *win,
+             struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop)
+{
+       struct v4l2_rect try_crop;
+       unsigned long vresize, hresize;
+
+       /* make a working copy of the new_crop rectangle */
+       try_crop = *new_crop;
+
+       /* adjust the cropping rectangle so it fits in the image */
+       if (try_crop.left < 0) {
+               try_crop.width += try_crop.left;
+               try_crop.left = 0;
+       }
+       if (try_crop.top < 0) {
+               try_crop.height += try_crop.top;
+               try_crop.top = 0;
+       }
+       try_crop.width = (try_crop.width < pix->width) ?
+               try_crop.width : pix->width;
+       try_crop.height = (try_crop.height < pix->height) ?
+               try_crop.height : pix->height;
+       if (try_crop.left + try_crop.width > pix->width)
+               try_crop.width = pix->width - try_crop.left;
+       if (try_crop.top + try_crop.height > pix->height)
+               try_crop.height = pix->height - try_crop.top;
+
+       try_crop.width &= ~1;
+       try_crop.height &= ~1;
+
+       if (try_crop.width <= 0 || try_crop.height <= 0)
+               return -EINVAL;
+
+       if (omap_vout_dss_omap24xx()) {
+               if (try_crop.height != win->w.height) {
+                       /* If we're resizing vertically, we can't support a
+                        * crop width wider than 768 pixels.
+                        */
+                       if (try_crop.width > 768)
+                               try_crop.width = 768;
+               }
+       }
+       /* vertical resizing */
+       vresize = (1024 * try_crop.height) / win->w.height;
+       if (omap_vout_dss_omap24xx() && (vresize > 2048))
+               vresize = 2048;
+       else if (omap_vout_dss_omap34xx() && (vresize > 4096))
+               vresize = 4096;
+
+       win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
+       if (win->w.height == 0)
+               win->w.height = 2;
+       if (win->w.height + win->w.top > fbuf->fmt.height) {
+               /* We made the preview window extend below the bottom of the
+                * display, so clip it to the display boundary and resize the
+                * cropping height to maintain the vertical resizing ratio.
+                */
+               win->w.height = (fbuf->fmt.height - win->w.top) & ~1;
+               if (try_crop.height == 0)
+                       try_crop.height = 2;
+       }
+       /* horizontal resizing */
+       hresize = (1024 * try_crop.width) / win->w.width;
+       if (omap_vout_dss_omap24xx() && (hresize > 2048))
+               hresize = 2048;
+       else if (omap_vout_dss_omap34xx() && (hresize > 4096))
+               hresize = 4096;
+
+       win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
+       if (win->w.width == 0)
+               win->w.width = 2;
+       if (win->w.width + win->w.left > fbuf->fmt.width) {
+               /* We made the preview window extend past the right side of the
+                * display, so clip it to the display boundary and resize the
+                * cropping width to maintain the horizontal resizing ratio.
+                */
+               win->w.width = (fbuf->fmt.width - win->w.left) & ~1;
+               if (try_crop.width == 0)
+                       try_crop.width = 2;
+       }
+       if (omap_vout_dss_omap24xx()) {
+               if ((try_crop.height/win->w.height) >= 2)
+                       try_crop.height = win->w.height * 2;
+
+               if ((try_crop.width/win->w.width) >= 2)
+                       try_crop.width = win->w.width * 2;
+
+               if (try_crop.width > 768) {
+                       /* The OMAP2420 vertical resizing line buffer is
+                        * 768 pixels wide.  If the cropped image is wider
+                        * than 768 pixels then it cannot be vertically resized.
+                        */
+                       if (try_crop.height != win->w.height)
+                               try_crop.width = 768;
+               }
+       } else if (omap_vout_dss_omap34xx()) {
+               if ((try_crop.height/win->w.height) >= 4)
+                       try_crop.height = win->w.height * 4;
+
+               if ((try_crop.width/win->w.width) >= 4)
+                       try_crop.width = win->w.width * 4;
+       }
+       /* update our cropping rectangle and we're done */
+       *crop = try_crop;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_vout_new_crop);
+
+/* Given a new format in pix and fbuf,  crop and win
+ * structures are initialized to default values. crop
+ * is initialized to the largest window size that will fit on the display.  The
+ * crop window is centered in the image. win is initialized to
+ * the same size as crop and is centered on the display.
+ * All sizes and offsets are constrained to be even numbers.
+ */
+void omap_vout_new_format(struct v4l2_pix_format *pix,
+               struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
+               struct v4l2_window *win)
+{
+       /* crop defines the preview source window in the image capture
+        * buffer
+        */
+       omap_vout_default_crop(pix, fbuf, crop);
+
+       /* win defines the preview target window on the display */
+       win->w.width = crop->width;
+       win->w.height = crop->height;
+       win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1;
+       win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1;
+}
+EXPORT_SYMBOL_GPL(omap_vout_new_format);
+
+/*
+ * Allocate buffers
+ */
+unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
+{
+       u32 order, size;
+       unsigned long virt_addr, addr;
+
+       size = PAGE_ALIGN(buf_size);
+       order = get_order(size);
+       virt_addr = __get_free_pages(GFP_KERNEL, order);
+       addr = virt_addr;
+
+       if (virt_addr) {
+               while (size > 0) {
+                       SetPageReserved(virt_to_page(addr));
+                       addr += PAGE_SIZE;
+                       size -= PAGE_SIZE;
+               }
+       }
+       *phys_addr = (u32) virt_to_phys((void *) virt_addr);
+       return virt_addr;
+}
+
+/*
+ * Free buffers
+ */
+void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
+{
+       u32 order, size;
+       unsigned long addr = virtaddr;
+
+       size = PAGE_ALIGN(buf_size);
+       order = get_order(size);
+
+       while (size > 0) {
+               ClearPageReserved(virt_to_page(addr));
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+       free_pages((unsigned long) virtaddr, order);
+}
+
+bool omap_vout_dss_omap24xx(void)
+{
+       return omapdss_get_version() == OMAPDSS_VER_OMAP24xx;
+}
+
+bool omap_vout_dss_omap34xx(void)
+{
+       switch (omapdss_get_version()) {
+       case OMAPDSS_VER_OMAP34xx_ES1:
+       case OMAPDSS_VER_OMAP34xx_ES3:
+       case OMAPDSS_VER_OMAP3630:
+       case OMAPDSS_VER_AM35xx:
+               return true;
+       default:
+               return false;
+       }
+}
diff --git a/drivers/media/platform/ti/omap/omap_voutlib.h b/drivers/media/platform/ti/omap/omap_voutlib.h
new file mode 100644 (file)
index 0000000..f9d1c07
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * omap_voutlib.h
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef OMAP_VOUTLIB_H
+#define OMAP_VOUTLIB_H
+
+void omap_vout_default_crop(struct v4l2_pix_format *pix,
+               struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
+
+int omap_vout_new_crop(struct v4l2_pix_format *pix,
+               struct v4l2_rect *crop, struct v4l2_window *win,
+               struct v4l2_framebuffer *fbuf,
+               const struct v4l2_rect *new_crop);
+
+int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+               struct v4l2_window *new_win);
+
+int omap_vout_new_window(struct v4l2_rect *crop,
+               struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
+               struct v4l2_window *new_win);
+
+void omap_vout_new_format(struct v4l2_pix_format *pix,
+               struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
+               struct v4l2_window *win);
+unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
+void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
+
+bool omap_vout_dss_omap24xx(void);
+bool omap_vout_dss_omap34xx(void);
+#endif /* #ifndef OMAP_VOUTLIB_H */
+