* [PATCH] OMAP 2/3 V4L2 display driver on video planes
@ 2008-09-17 15:05 Hardik Shah
2008-09-17 15:30 ` Sakari Ailus
2008-10-03 14:33 ` Hans Verkuil
0 siblings, 2 replies; 15+ messages in thread
From: Hardik Shah @ 2008-09-17 15:05 UTC (permalink / raw)
To: linux-omap, video4linux-list, linux-fbdev-devel
From: Vaibhav Hiremath <hvaibhav@ti.com>
OMAP 2/3 V4L2 display driver sits on top of DSS library
and uses TV overlay and 2 video pipelines (video1 and video2)
to display image on TV. It exposes 2 V4L2 nodes for user
interface.
It supports standard V4L2 ioctls.
Signed-off-by: Brijesh Jadav <brijesh.j@ti.com>
Hari Nagalla <hnagalla@ti.com>
Hardik Shah <hardik.shah@ti.com>
Manju Hadli <mrh@ti.com>
R Sivaraj <sivaraj@ti.com>
Vaibhav Hiremath <hvaibhav@ti.com>
---
drivers/media/video/Kconfig | 10 +-
drivers/media/video/Makefile | 2 +
drivers/media/video/omap/Kconfig | 12 +
drivers/media/video/omap/Makefile | 2 +
drivers/media/video/omap/omap_vout.c | 3524 +++++++++++++++++++++++++++++++
drivers/media/video/omap/omap_voutdef.h | 196 ++
drivers/media/video/omap/omap_voutlib.c | 283 +++
drivers/media/video/omap/omap_voutlib.h | 34 +
include/linux/omap_vout.h | 60 +
9 files changed, 4121 insertions(+), 2 deletions(-)
create mode 100644 drivers/media/video/omap/omap_vout.c
create mode 100644 drivers/media/video/omap/omap_voutdef.h
create mode 100644 drivers/media/video/omap/omap_voutlib.c
create mode 100644 drivers/media/video/omap/omap_voutlib.h
create mode 100644 include/linux/omap_vout.h
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 2703c66..e899dd2 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -762,8 +762,6 @@ source "drivers/media/video/au0828/Kconfig"
source "drivers/media/video/ivtv/Kconfig"
-source drivers/media/video/omap/Kconfig
-
source "drivers/media/video/cx18/Kconfig"
config VIDEO_M32R_AR
@@ -802,6 +800,14 @@ config VIDEO_OMAP2
---help---
Driver for an OMAP 2 camera controller.
+config VIDEO_OMAP3
+ bool "OMAP2/OMAP3 V4L2-DSS drivers"
+ depends on VIDEO_DEV && (ARCH_OMAP24XX || ARCH_OMAP34XX)
+ default y
+ help
+ V4L2 DSS driver support for OMAP2/3 based boards.
+
+source "drivers/media/video/omap/Kconfig"
#
# USB Multimedia device configuration
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 3e580e8..10f879c 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -107,6 +107,8 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
obj-$(CONFIG_VIDEO_OMAP2) += omap24xxcam.o omap24xxcam-dma.o
+obj-$(CONFIG_VIDEO_OMAP3) += omap/
+
obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig
index c8d1f4c..06c55ae 100644
--- a/drivers/media/video/omap/Kconfig
+++ b/drivers/media/video/omap/Kconfig
@@ -5,3 +5,15 @@ config VIDEO_OMAP_CAMERA
depends on VIDEO_DEV && (ARCH_OMAP16XX || ARCH_OMAP24XX)
help
V4L2 camera driver support for OMAP1/2 based boards.
+
+config VIDEO_OMAP_VIDEOLIB
+ tristate "OMAP Video out library"
+ depends on VIDEO_OMAP3
+ default VIDEO_OMAP3
+
+config VIDEO_OMAP_VIDEOOUT
+ tristate "OMAP Video out driver"
+ select VIDEOBUF_DMA_SG
+ select VIDEOBUF_GEN
+ depends on VIDEO_OMAP3
+ default VIDEO_OMAP3
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
index 9b4a998..9a75d2a 100644
--- a/drivers/media/video/omap/Makefile
+++ b/drivers/media/video/omap/Makefile
@@ -3,6 +3,8 @@
obj-$(CONFIG_VIDEO_OMAP_CAMERA) += omapcamera.o
objs-y$(CONFIG_ARCH_OMAP16XX) += omap16xxcam.o camera_core.o
+obj-$(CONFIG_VIDEO_OMAP_VIDEOLIB) += omap_voutlib.o
+obj-$(CONFIG_VIDEO_OMAP_VIDEOOUT) += omap_vout.o
omapcamera-objs := $(objs-yy)
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
new file mode 100644
index 0000000..2b05b9b
--- /dev/null
+++ b/drivers/media/video/omap/omap_vout.c
@@ -0,0 +1,3524 @@
+/*
+ * drivers/media/video/omap/omap_vout.c
+ *
+ * Copyright (C) 2005-2006 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) 2004 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
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/videodev2.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <media/videobuf-dma-sg.h>
+#include <linux/input.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#ifdef CONFIG_PM
+#include <linux/notifier.h>
+#include <linux/pm.h>
+#endif
+#ifdef CONFIG_DPM
+#include <linux/dpm.h>
+#endif
+
+#include <mach/omap-dss.h>
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/semaphore.h>
+#include <asm/processor.h>
+#include <mach/dma.h>
+
+#include "omap_voutlib.h"
+
+/*
+ * Un-comment this to use Debug Write call
+ */
+/* #define DEBUG_ALLOW_WRITE */
+
+#include "omap_voutdef.h"
+
+unsigned long timeout;
+
+/*
+ * Uncomment this if debugging support needs to be enabled
+ */
+
+/* #define DEBUG */
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK(ARGS...) (printk(KERN_DEBUG "<%s>: ", __func__); \
+ printk(KERN_DEBUG ARGS))
+#else
+#define DPRINTK(x...)
+#endif
+
+/*
+ * -1 means rotation support is disabled
+ * 0/90/180/270 are initial rotation angles
+ */
+
+static int rotation_support = -1;
+
+/* configuration macros */
+#define VOUT_NAME "omap_vout"
+#define V1OUT_NAME "omap_vout1"
+#define V2OUT_NAME "omap_vout2"
+
+#define D1_PAL_WIDTH 720
+#define D1_PAL_HEIGHT 576
+#define QQVGA_WIDTH 160
+#define QQVGA_HEIGHT 120
+
+#define DMA_CHAN_ALLOTED 1
+#define DMA_CHAN_NOT_ALLOTED 0
+#define NUM_OF_VIDEO_CHANNELS 2
+#define VRF_SIZE (MAX_PIXELS_PER_LINE * MAX_LINES * 4)
+#define SMS_RGB_PIXSIZE 2
+#define SMS_YUYV_PIXSIZE 4
+#define VRFB_TX_TIMEOUT 1000
+
+#define VID_MAX_WIDTH D1_PAL_WIDTH /* Largest width */
+#define VID_MAX_HEIGHT D1_PAL_HEIGHT /* Largest height */
+#define VID_MIN_WIDTH 0
+#define VID_MIN_HEIGHT 0
+
+#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
+#define OMAP_VOUT_VIDEO1_SMS_START (0xE0000000)
+#define OMAP_VOUT_VIDEO2_SMS_START (0xF0000000)
+
+static struct omap_vout_device *saved_v1out, *saved_v2out;
+
+#define STREAMING_IS_ON() ((saved_v1out && saved_v1out->streaming) || \
+ (saved_v2out && saved_v2out->streaming))
+
+/*
+ * this is the layer being linked to (slave layer). possible values are:
+ * OMAP_VIDEO1: V1 is linked to V2. V1 uses V2's pix and crop.
+ * OMAP_VIDEO2: V2 is linked to V1. V2 uses V1's pix and crop.
+ * -1: no link.
+ */
+
+static int vout_linked;
+static spinlock_t vout_link_lock;
+
+static struct videobuf_queue_ops video_vbq_ops;
+
+static u32 video1_numbuffers = 3;
+static u32 video2_numbuffers = 3;
+static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
+static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
+module_param(video1_numbuffers, uint, S_IRUGO);
+module_param(video2_numbuffers, uint, S_IRUGO);
+module_param(video1_bufsize, uint, S_IRUGO);
+module_param(video2_bufsize, uint, S_IRUGO);
+
+static void omap_vout_isr(void *arg, struct pt_regs *regs,
+ unsigned int irqstatus);
+/* module parameters */
+
+/*
+ * Maximum amount of memory to use for rendering buffers.
+ * Default is enough to four (RGB24) VGA buffers.
+ */
+#define MAX_ALLOWED_VIDBUFFERS 4
+
+/* list of image formats supported by OMAP2 video pipelines */
+const static 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
+ */
+ .description = "RGB565, le",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ },
+ {
+ /* Note: V4L2 defines RGB565X as:
+ *
+ * Byte 0 Byte 1
+ * b4 b3 b2 b1 b0 g5 g4 g3 g2 g1 g0 r4 r3 r2 r1 r0
+ *
+ * We interpret RGB565X as:
+ *
+ * Byte 0 Byte 1
+ * r4 r3 r2 r1 r0 g5 g4 g3 g2 g1 g0 b4 b3 b2 b1 b0
+ */
+ .description = "RGB565, be",
+ .pixelformat = V4L2_PIX_FMT_RGB565X,
+ },
+ {
+ /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use
+ * this for RGB24 unpack mode, the last 8 bits are ignored
+ * */
+ .description = "RGB32, le",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ },
+ {
+ /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use
+ * this for RGB24 packed mode
+ *
+ */
+ .description = "RGB24, le",
+ .pixelformat = V4L2_PIX_FMT_RGB24,
+ },
+ {
+ .description = "YUYV (YUV 4:2:2), packed",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ },
+ {
+ .description = "UYVY, packed",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ },
+};
+
+#define NUM_OUTPUT_FORMATS (sizeof(omap_formats)/sizeof(omap_formats[0]))
+
+struct omap_vout_std_id_name {
+ v4l2_std_id id;
+ char name[25];
+};
+struct omap_vout_std_id_name id_name[] = {
+ {V4L2_STD_NTSC_M, "ntsc_m"},
+ {V4L2_STD_NTSC_M_JP, "ntsc_j"},
+ {V4L2_STD_NTSC_443, "ntsc_443"},
+ {V4L2_STD_PAL, "pal_bdghi"},
+ {V4L2_STD_PAL_Nc, "pal_nc"},
+ {V4L2_STD_PAL_N, "pal_n"},
+ {V4L2_STD_PAL_M, "pal_m"},
+ {V4L2_STD_PAL_60, "pal_60"},
+};
+
+/* CONFIG_PM */
+#ifdef CONFIG_PM
+#define omap_vout_suspend_lockout(s, f) \
+ if ((s)->suspended) {\
+ if ((f)->f_flags & O_NONBLOCK)\
+ return -EBUSY;\
+ wait_event_interruptible((s)->suspend_wq, \
+ (s)->suspended == 0);\
+ }
+#else
+#define omap_vout_suspend_lockout(s, f) do {(s)->suspended = 0; } while (0)
+#endif
+
+void
+omap_vout_config_vlayer(int ltype, struct v4l2_pix_format *pix,
+ struct v4l2_rect *crop, struct v4l2_window *win,
+ int rotation_deg, int mirroring)
+{
+
+ int vid_position_x, vid_position_y, ps = 2, vr_ps = 1;
+ unsigned long vid_attributes = 0;
+ struct omap_scaling_params scale_params;
+ struct omap_video_params vid_params;
+ int winheight, winwidth, cropheight, cropwidth, pixheight,
+ pixwidth;
+ int cleft, ctop;
+ int panelwidth, panelheight, row_inc_value = 0, pixel_inc_value =
+ 0;
+ int flicker_filter = 0;
+ int output_dev;
+ int v;
+ int full_range_conversion = 0;
+
+ output_dev = omap_disp_get_output_dev(ltype);
+
+ if (ltype == OMAP_VIDEO1)
+ v = 0;
+ else if (ltype == OMAP_VIDEO2)
+ v = 1;
+ else
+ return;
+
+ if ((output_dev == OMAP_OUTPUT_TV) &&
+ ((win->w.width == crop->width)
+ && (win->w.height == crop->height)))
+ flicker_filter = 1;
+
+ /* make sure the video overlay is disabled before we reconfigure it */
+ omap_disp_disable_layer(ltype);
+
+ /* configure the video attributes register */
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ if (pix->pixelformat == V4L2_PIX_FMT_YUYV) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDFORMAT_YUV2;
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDCOLORCONVENABLE;
+ } else {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDFORMAT_UYVY;
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDCOLORCONVENABLE;
+ }
+
+ if (mirroring == 1 || rotation_deg >= 0) {
+ /*
+ * ps - In VRFB space the pixel size for YUYV/UYVY
+ * is 4 bytes
+ * vr_ps - Actual pixel size for YUYV/UYVY is 2 bytes
+ */
+ ps = 4;
+ vr_ps = 2;
+ }
+ if (rotation_deg >= 0) {
+ if (mirroring == 1) {
+ vid_attributes |= (rotation_deg == 90) ?
+ ((0x3) << DISPC_VID_ATTRIBUTES_VIDROT)
+ : (rotation_deg ==
+ 270) ? ((0x1) <<
+ DISPC_VID_ATTRIBUTES_VIDROT)
+ : (rotation_deg ==
+ 0) ? (0x2 <<
+ DISPC_VID_ATTRIBUTES_VIDROT)
+ : (0 << DISPC_VID_ATTRIBUTES_VIDROT);
+ } else {
+ vid_attributes |= (rotation_deg == 90) ?
+ ((0x3) << DISPC_VID_ATTRIBUTES_VIDROT)
+ : (rotation_deg ==
+ 270) ? ((0x1) <<
+ DISPC_VID_ATTRIBUTES_VIDROT)
+ : ((rotation_deg /
+ 90) <<
+ DISPC_VID_ATTRIBUTES_VIDROT);
+ }
+ vid_attributes |= (rotation_deg == 90
+ || rotation_deg ==
+ 270) ? (1 <<
+ DISPC_VID_ATTRIBUTES_VIDROWREPEAT)
+ : (0 << DISPC_VID_ATTRIBUTES_VIDROWREPEAT);
+ }
+ if (mirroring == 1 && rotation_deg == -1) {
+ vid_attributes |=
+ (0x2 << DISPC_VID_ATTRIBUTES_VIDROT);
+ }
+
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ ps = 3; /* pixel size is 3 bytes */
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDFORMAT_RGB24P;
+ break;
+
+ /* The picture format is a bit confusing in V4L2.. as per
+ * the V4L2 spec RGB32 and BGR32 are always with alpha bit
+ * enabled.. (i.e always in packed mode) */
+ case V4L2_PIX_FMT_RGB32:
+ ps = 4; /* pixel size is 4 bytes */
+ if ((system_rev < OMAP3430_REV_ES2_0)
+ || (ltype == OMAP_VIDEO1)) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDFORMAT_RGB24;
+ } else {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDFORMAT_ARGB32;
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDENDIANNESS;
+ }
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ ps = 4; /* pixel size is 4 bytes */
+ if ((system_rev < OMAP3430_REV_ES2_0)
+ || (ltype == OMAP_VIDEO1)) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDFORMAT_RGB24;
+ } else {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDFORMAT_ARGB32;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ default:
+ ps = 2; /* pixel size is 2 bytes */
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDFORMAT_RGB16;
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDREPLICATIONENABLE;
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ ps = 2; /* pixel size is 2 bytes */
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDFORMAT_RGB16;
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDENDIANNESS;
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDREPLICATIONENABLE;
+ break;
+ }
+
+ if (output_dev == OMAP_OUTPUT_TV)
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDCHANNELOUT;
+
+ /* Enable 16 x 32 burst size */
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDBURSTSIZE_BURST16X32;
+
+ /* Set FIFO */
+ omap_disp_set_fifothreshold(v);
+
+ if (pix->colorspace == V4L2_COLORSPACE_JPEG ||
+ pix->colorspace == V4L2_COLORSPACE_SRGB) {
+ full_range_conversion = 1;
+ }
+ /* Set the color converion parameters */
+ omap_disp_set_colorconv(v, full_range_conversion);
+
+ if (rotation_deg == 90 || rotation_deg == 270) {
+ winheight = win->w.width;
+ winwidth = win->w.height;
+ cropheight = crop->width;
+ cropwidth = crop->height;
+ pixheight = pix->width;
+ pixwidth = pix->height;
+ cleft = crop->top;
+ ctop = crop->left;
+ } else {
+ winwidth = win->w.width;
+ winheight = win->w.height;
+ cropwidth = crop->width;
+ cropheight = crop->height;
+ pixheight = pix->height;
+ pixwidth = pix->width;
+ ctop = crop->top;
+ cleft = crop->left;
+ }
+
+ if (winwidth != cropwidth) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDRESIZEENABLE_HRESIZE;
+ }
+ if (winheight != cropheight) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDRESIZEENABLE_VRESIZE;
+ if (winheight < cropheight) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDVRESIZECONF;
+ } else {
+ /* Use Five tap filter for vertical up scaling */
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDVERTICALTAPS;
+ }
+ }
+
+ if (flicker_filter == 1) {
+ vid_attributes |=
+ DISPC_VID_ATTRIBUTES_VIDRESIZEENABLE_VRESIZE;
+ vid_attributes |= DISPC_VID_ATTRIBUTES_VIDVRESIZECONF;
+ }
+ omap_disp_set_vidattributes(v, vid_attributes);
+
+ scale_params.win_width = winwidth;
+ scale_params.crop_width = cropwidth;
+ scale_params.win_height = winheight;
+ scale_params.crop_height = cropheight;
+ scale_params.flicker_filter = flicker_filter;
+ scale_params.video_layer = v;
+ omap_disp_set_scaling(&scale_params);
+
+ omap_disp_get_panel_size(output_dev, &panelwidth, &panelheight);
+
+ /* configure the target window on the display */
+ switch (rotation_deg) {
+
+ case 90:
+ vid_position_y =
+ (panelheight - win->w.width) - win->w.left;
+ vid_position_x = win->w.top;
+ break;
+
+ case 180:
+ vid_position_x = (panelwidth - win->w.width) - win->w.left;
+ vid_position_y =
+ (panelheight - win->w.height) - win->w.top;
+ break;
+
+ case 270:
+ vid_position_y = win->w.left;
+ vid_position_x = (panelwidth - win->w.height) - win->w.top;
+ break;
+
+ default:
+ vid_position_x = win->w.left;
+ vid_position_y = win->w.top;
+ break;
+ }
+
+ if (output_dev == OMAP_OUTPUT_TV)
+ vid_position_y = vid_position_y / 2;
+
+ vid_params.vid_position =
+ ((vid_position_x << DISPC_VID_POSITION_VIDPOSX_SHIFT) &
+ DISPC_VID_POSITION_VIDPOSX) | ((vid_position_y <<
+ DISPC_VID_POSITION_VIDPOSY_SHIFT)
+ & DISPC_VID_POSITION_VIDPOSY);
+
+ /*
+ * If Scaling is enabled for TV then the window height should be
+ * divided by two
+ */
+ if (((output_dev == OMAP_OUTPUT_TV) &&
+ (winheight != cropheight)) || flicker_filter) {
+ vid_params.vid_size =
+ (((winwidth - 1) << DISPC_VID_SIZE_VIDSIZEX_SHIFT)
+ & DISPC_VID_SIZE_VIDSIZEX)
+ |
+ ((((winheight -
+ 1) / 2) << DISPC_VID_SIZE_VIDSIZEY_SHIFT)
+ & DISPC_VID_SIZE_VIDSIZEY);
+ } else {
+ vid_params.vid_size =
+ (((winwidth - 1) << DISPC_VID_SIZE_VIDSIZEX_SHIFT)
+ & DISPC_VID_SIZE_VIDSIZEX)
+ | (((winheight - 1) << DISPC_VID_SIZE_VIDSIZEY_SHIFT)
+ & DISPC_VID_SIZE_VIDSIZEY);
+#ifdef DMA_DECIMATE
+ vid_params.vid_size =
+ (((winwidth - 1) / 2 << DISPC_VID_SIZE_VIDSIZEX_SHIFT)
+ & DISPC_VID_SIZE_VIDSIZEX)
+ |
+ ((((winheight -
+ 1) / 2) << DISPC_VID_SIZE_VIDSIZEY_SHIFT)
+ & DISPC_VID_SIZE_VIDSIZEY);
+#endif
+ }
+
+ /* configure the source window in the framebuffer */
+ if (flicker_filter == 1) {
+ vid_params.vid_picture_size =
+ (((cropwidth -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEX_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEX)
+ | (((cropheight - 1)
+ << DISPC_VID_PICTURE_SIZE_VIDORGSIZEY_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEY);
+ } else if ((output_dev == OMAP_OUTPUT_TV)
+ && (flicker_filter == 0)) {
+ vid_params.vid_picture_size =
+ (((cropwidth -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEX_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEX) |
+ (((cropheight / 2 -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEY_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEY);
+ } else {
+ vid_params.vid_picture_size =
+ (((cropwidth -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEX_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEX) |
+ (((cropheight -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEY_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEY);
+#ifdef DMA_DECIMATE
+ vid_params.vid_picture_size =
+ (((cropwidth / 2 -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEX_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEX) |
+ (((cropheight / 2 -
+ 1) << DISPC_VID_PICTURE_SIZE_VIDORGSIZEY_SHIFT)
+ & DISPC_VID_PICTURE_SIZE_VIDORGSIZEY);
+#endif
+ }
+ vid_params.video_layer = v;
+ omap_disp_set_vid_params(&vid_params);
+
+ switch (mirroring) {
+ case 0: /* No mirroring */
+ if (rotation_deg == 90 || rotation_deg == 270) {
+ row_inc_value =
+ 1 + (MAX_PIXELS_PER_LINE - pixwidth +
+ (pixwidth - cropwidth - cleft) +
+ cleft) * ps;
+
+ } else if (rotation_deg == 180 || rotation_deg == 0) {
+ if (V4L2_PIX_FMT_YUYV == pix->pixelformat
+ || V4L2_PIX_FMT_UYVY == pix->pixelformat)
+ row_inc_value =
+ 1 + (MAX_PIXELS_PER_LINE -
+ (pixwidth / vr_ps) +
+ ((pixwidth - cropwidth -
+ cleft) / vr_ps) +
+ (cleft / vr_ps)) * ps;
+
+ else
+ row_inc_value =
+ 1 + (MAX_PIXELS_PER_LINE - pixwidth +
+ (pixwidth - cropwidth - cleft) +
+ cleft) * ps;
+#ifdef DMA_DECIMATE
+ row_inc_value =
+ row_inc_value + (MAX_PIXELS_PER_LINE * ps);
+#endif
+ } else {
+ row_inc_value =
+ 1 + (pix->width * ps) - cropwidth * ps;
+#ifdef DMA_DECIMATE
+ row_inc_value =
+ row_inc_value + ((pix->width + 1) * ps);
+#endif
+ }
+ pixel_inc_value = 1;
+#ifdef DMA_DECIMATE
+ pixel_inc_value = 1 + (1 * ps);
+#endif
+ break;
+
+ case 1: /* Mirroring */
+ if (rotation_deg == 90 || rotation_deg == 270) {
+ row_inc_value =
+ (-(MAX_PIXELS_PER_LINE + cropwidth) * ps) + 1;
+ pixel_inc_value = 1;
+ } else if (rotation_deg == 180 || rotation_deg == 0) {
+ row_inc_value =
+ (-(MAX_PIXELS_PER_LINE + (cropwidth / vr_ps)) *
+ ps) + 1;
+ pixel_inc_value = 1;
+ } else {
+ row_inc_value =
+ 2 * ((cropwidth / vr_ps) -
+ 1) * ps + 1 +
+ ((pix->width * ps) / vr_ps) -
+ (cropwidth / vr_ps) * ps;
+ pixel_inc_value = (-2 * ps) + 1;
+ }
+ break;
+ } /* Mirroring Switch */
+
+ /*
+ * For LCD row inc and pixel inc
+ */
+ omap_disp_set_dma_params(ltype, OMAP_OUTPUT_LCD,
+ 0, 0, row_inc_value, pixel_inc_value);
+
+ if (output_dev == OMAP_OUTPUT_LCD || flicker_filter == 1) {
+ omap_disp_set_row_pix_inc_values(v, row_inc_value,
+ pixel_inc_value);
+ }
+ /*
+ * For TV the row increment should be done twice as the
+ * TV operates in interlaced mode
+ */
+ else {
+ if (rotation_deg >= 0) {
+ if (mirroring == 1)
+ row_inc_value =
+ row_inc_value -
+ MAX_PIXELS_PER_LINE * ps;
+ else
+ row_inc_value =
+ row_inc_value +
+ MAX_PIXELS_PER_LINE * ps;
+ } else {
+ if (mirroring == 1)
+ row_inc_value =
+ row_inc_value +
+ pix->width * ps / vr_ps;
+ else
+ row_inc_value =
+ row_inc_value + pix->width * ps;
+ }
+ omap_disp_set_row_pix_inc_values(v, row_inc_value,
+ pixel_inc_value);
+ }
+ /*
+ * Store BA0 BA1 for TV, BA1 points to the alternate row
+ */
+ if (flicker_filter == 1) {
+ ;
+ } else if (rotation_deg >= 0) {
+ if (mirroring == 1)
+ row_inc_value =
+ row_inc_value - MAX_PIXELS_PER_LINE * ps;
+ else
+ row_inc_value =
+ row_inc_value + MAX_PIXELS_PER_LINE * ps;
+ } else {
+ if (mirroring == 1)
+ row_inc_value =
+ row_inc_value + pix->width * ps / vr_ps;
+ else
+ row_inc_value = row_inc_value + pix->width * ps;
+
+ }
+ omap_disp_set_dma_params(ltype, OMAP_OUTPUT_TV,
+ 0, 0, row_inc_value, pixel_inc_value);
+
+ omap_set_crop_layer_parameters(v, cropwidth, cropheight);
+
+ omap_disp_save_initstate(ltype);
+
+}
+
+static unsigned long
+omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
+{
+ unsigned long virt_addr, addr;
+ u32 order, size;
+ size = PAGE_ALIGN(buf_size);
+ order = get_order(size);
+ virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, 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;
+}
+
+static void
+omap_vout_free_buffer(unsigned long virtaddr, u32 phys_addr,
+ u32 buf_size)
+{
+ unsigned long addr = virtaddr;
+ u32 order, size;
+ 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);
+}
+
+static int omap_vout_try_format(struct v4l2_pix_format *pix,
+ struct v4l2_pix_format *def_pix)
+{
+ int ifmt, bpp = 0;
+
+ if (pix->width > VID_MAX_WIDTH)
+ pix->width = VID_MAX_WIDTH;
+ if (pix->height > VID_MAX_HEIGHT)
+ pix->height = VID_MAX_HEIGHT;
+
+ if (pix->width <= VID_MIN_WIDTH)
+ pix->width = def_pix->width;
+ if (pix->height <= VID_MIN_HEIGHT)
+ pix->height = def_pix->height;
+
+ 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 */ V4L2_FIELD_ANY;
+ pix->priv = 0;
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ default:
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ 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;
+}
+
+/*
+ * omap_vout_uservirt_to_phys: This inline function is used to convert user
+ * space virtual address to physical address.
+ */
+static inline u32 omap_vout_uservirt_to_phys(u32 virtp)
+{
+ unsigned long physp = 0;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+
+ vma = find_vma(mm, virtp);
+ /* For kernel direct-mapped memory, take the easy way */
+ if (virtp >= PAGE_OFFSET) {
+ physp = virt_to_phys((void *) virtp);
+ } else if ((vma) && (vma->vm_flags & VM_IO)
+ && (vma->vm_pgoff)) {
+ /* this will catch, kernel-allocated,
+ mmaped-to-usermode addresses */
+ physp =
+ (vma->vm_pgoff << PAGE_SHIFT) + (virtp -
+ vma->vm_start);
+ } else {
+ /* otherwise, use get_user_pages() for general userland pages */
+ int res, nr_pages = 1;
+ struct page *pages;
+ down_read(¤t->mm->mmap_sem);
+
+ res = get_user_pages(current, current->mm,
+ virtp, nr_pages, 1, 0, &pages, NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (res == nr_pages) {
+ physp =
+ __pa(page_address(&pages[0]) +
+ (virtp & ~PAGE_MASK));
+ } else {
+ printk("omap_vout_uservirt_to_phys:\
+ get_user_pages failed\n");
+ return 0;
+ }
+ }
+
+ return physp;
+}
+
+static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+ struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
+ t->tx_status = 1;
+ wake_up_interruptible(&t->wait);
+}
+
+static void
+omap_vout_sync(struct omap_vout_device *dest,
+ struct omap_vout_device *src)
+{
+ int rotation = -1;
+
+ if (dest->rotation >= 0)
+ rotation = dest->rotation;
+ /*
+ * once linked, dest shares src's framebuffer, pix and crop
+ */
+
+ dest->pix = src->pix;
+ dest->crop = src->crop;
+
+ if (src->streaming)
+ /* make sure the video overlay is disabled before
+ * we reconfigure it
+ */
+ omap_vout_config_vlayer(dest->vid, &dest->pix,
+ &dest->crop, &dest->win,
+ rotation, dest->mirror);
+
+}
+
+/* Buffer setup function is called by videobuf layer when REQBUF ioctl is
+ * called. This is used to setup buffers and return size and count of
+ * buffers allocated. After the call to this buffer, videobuf layer will
+ * setup buffer queue depending on the size and count of buffers
+ */
+static int
+omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+ unsigned int *size)
+{
+ struct omap_vout_fh *fh =
+ (struct omap_vout_fh *) q->priv_data;
+ struct omap_vout_device *vout = fh->vout;
+ int startindex = 0, i, j;
+ u32 phy_addr = 0, virt_addr = 0;
+
+ if (!vout)
+ return -EINVAL;
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
+ return -EINVAL;
+
+ startindex = (vout->vid == OMAP_VIDEO1) ? video1_numbuffers :
+ video2_numbuffers;
+ if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
+ *count = startindex;
+
+ if (vout->rotation != -1 && *count > 4)
+ *count = 4;
+
+ /* If rotation is enabled, allocate memory for VRFB space also */
+ if (vout->rotation >= 0) {
+ 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]) {
+ if (V4L2_MEMORY_MMAP == vout->memory
+ && i >= startindex)
+ break;
+ for (j = 0; j < i; j++) {
+ omap_vout_free_buffer(vout->
+ smsshado_virt_addr[j],
+ vout->smsshado_phy_addr[j],
+ vout->smsshado_size);
+ vout->smsshado_virt_addr[j] = 0;
+ vout->smsshado_phy_addr[j] = 0;
+ }
+ *count = 0;
+ return -ENOMEM;
+ }
+
+ memset((void *) vout->smsshado_virt_addr[i], 0,
+ vout->smsshado_size);
+
+ if (vout->rotation == 90 || vout->rotation == 270) {
+ omap_disp_set_vrfb(vout->vrfb_context[i],
+ vout->
+ smsshado_phy_addr[i],
+ vout->pix.height,
+ vout->pix.width,
+ vout->bpp *
+ vout->vrfb_bpp);
+ } else {
+ omap_disp_set_vrfb(vout->vrfb_context[i],
+ vout->
+ smsshado_phy_addr[i],
+ vout->pix.width,
+ vout->pix.height,
+ vout->bpp *
+ vout->vrfb_bpp);
+ }
+ }
+ }
+
+ if (V4L2_MEMORY_MMAP != vout->memory)
+ return 0;
+
+ *size = vout->buffer_size;
+ startindex = (vout->vid == OMAP_VIDEO1) ? video1_numbuffers :
+ video2_numbuffers;
+ for (i = startindex; i < *count; i++) {
+ vout->buffer_size = *size;
+
+ virt_addr =
+ omap_vout_alloc_buffer(vout->buffer_size,
+ &phy_addr);
+ if (!virt_addr) {
+ if (vout->rotation < 0)
+ break;
+ for (j = i; j < *count; j++) {
+ omap_vout_free_buffer(vout->
+ smsshado_virt_addr
+ [j],
+ vout->
+ smsshado_phy_addr
+ [j],
+ vout->
+ smsshado_size);
+ vout->smsshado_virt_addr[j] = 0;
+ vout->smsshado_phy_addr[j] = 0;
+ }
+ break;
+ }
+
+ vout->buf_virt_addr[i] = virt_addr;
+ vout->buf_phy_addr[i] = phy_addr;
+ }
+
+ *count = vout->buffer_allocated = i;
+ return 0;
+}
+
+/* This function will be called when VIDIOC_QBUF ioctl is called.
+ * It prepare buffers before give out for the display. This function
+ * user space virtual address into physical address if userptr memory
+ * exchange mechanism is used. If rotation is enabled, it copies entire
+ * buffer into VRFB memory space before giving it to the DSS.
+ */
+static int
+omap_vout_buffer_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct omap_vout_fh *fh =
+ (struct omap_vout_fh *) q->priv_data;
+ struct omap_vout_device *vout = fh->vout;
+ u32 dest_frame_index = 0, src_element_index = 0;
+ u32 dest_element_index = 0, src_frame_index = 0;
+ u32 elem_count = 0, frame_count = 0, pixsize = 2, mir_rot_deg = 0;
+ struct videobuf_dmabuf *dmabuf = NULL;
+
+ if (VIDEOBUF_NEEDS_INIT == vb->state) {
+ vb->width = vout->pix.width;
+ vb->height = vout->pix.height;
+ vb->size = vb->width * vb->height * vout->bpp;
+ vb->field = field;
+ }
+ vb->state = VIDEOBUF_PREPARED;
+ /* if user pointer memory mechanism is used, get the physical
+ * address of the buffer
+ */
+ if (V4L2_MEMORY_USERPTR == vb->memory) {
+ if (0 == vb->baddr)
+ return -EINVAL;
+ /* Virtual address */
+ /* priv points to struct videobuf_pci_sg_memory. But we went
+ * pointer to videobuf_dmabuf, which is member of
+ * videobuf_pci_sg_memory */
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+ dmabuf->vmalloc = (void *) vb->baddr;
+
+ /* Physical address */
+ dmabuf->bus_addr =
+ (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr);
+ }
+
+ if (vout->rotation >= 0) {
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+
+ /* 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;
+ /*
+ * DMA transfer in double index mode
+ */
+
+ /* Frame index */
+ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
+ (vout->pix.width * vout->bpp)) + 1;
+
+ /* Source and destination parameters */
+ src_element_index = 0;
+ src_frame_index = 0;
+ dest_element_index = 1;
+
+ /* Number of elements per frame */
+ elem_count = vout->pix.width * vout->bpp;
+ frame_count = vout->pix.height;
+ vout->vrfb_dma_tx.tx_status = 0;
+ omap_set_dma_transfer_params(vout->vrfb_dma_tx.dma_ch,
+ OMAP_DMA_DATA_TYPE_S32,
+ (elem_count / 4), frame_count,
+ OMAP_DMA_SYNC_ELEMENT,
+ vout->vrfb_dma_tx.dev_id,
+ 0x0);
+ /* src_port required only for OMAP1 */
+ omap_set_dma_src_params(vout->vrfb_dma_tx.dma_ch, 0,
+ OMAP_DMA_AMODE_POST_INC,
+ dmabuf->bus_addr,
+ src_element_index,
+ src_frame_index);
+
+ /*set dma source burst mode for VRFB */
+ omap_set_dma_src_burst_mode(vout->vrfb_dma_tx.dma_ch,
+ OMAP_DMA_DATA_BURST_16);
+
+ if (vout->mirror == 1) {
+ /* Following is used to select appropriate VRFB
+ * memory space for rotation with mirroring */
+ mir_rot_deg = (vout->rotation == 90) ? (270 / 90) :
+ (vout->rotation == 270) ? (90 / 90) :
+ (vout->rotation ==
+ 180) ? (0 / 90) : (180 / 90);
+ /* dest_port required only for OMAP1 */
+ omap_set_dma_dest_params(vout->vrfb_dma_tx.dma_ch, 0,
+ OMAP_DMA_AMODE_DOUBLE_IDX,
+ vout->sms_rot_phy[vb->
+ i]
+ [mir_rot_deg],
+ dest_element_index,
+ dest_frame_index);
+ } else { /* No Mirroring */
+ /* dest_port required only for OMAP1 */
+ omap_set_dma_dest_params(vout->vrfb_dma_tx.dma_ch, 0,
+ OMAP_DMA_AMODE_DOUBLE_IDX,
+ vout->sms_rot_phy[vb->
+ i]
+ [vout->rotation / 90],
+ dest_element_index,
+ dest_frame_index);
+ }
+
+ /*set dma dest burst mode for VRFB */
+ omap_set_dma_dest_burst_mode(vout->vrfb_dma_tx.dma_ch,
+ OMAP_DMA_DATA_BURST_16);
+ omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
+
+ omap_start_dma(vout->vrfb_dma_tx.dma_ch);
+ interruptible_sleep_on_timeout(&vout->vrfb_dma_tx.wait,
+ VRFB_TX_TIMEOUT);
+
+ if (vout->vrfb_dma_tx.tx_status == 0) {
+ omap_stop_dma(vout->vrfb_dma_tx.dma_ch);
+ return -EINVAL;
+ }
+ /* Store buffers physical address into an array. Addresses
+ * from this array will be used to configure DSS */
+ vout->queued_buf_addr[vb->i] =
+ (u8 *) vout->sms_rot_phy[vb->i][0];
+ } else {
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+
+ vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr;
+ }
+ return 0;
+}
+
+/* Buffer queue funtion will be called from the videobuf layer when _QBUF
+ * ioctl is called. It is used to enqueue buffer, which is ready to be
+ * displayed. */
+static void
+omap_vout_buffer_queue(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct omap_vout_fh *fh =
+ (struct omap_vout_fh *) q->priv_data;
+ struct omap_vout_device *vout = fh->vout;
+
+ /* Driver is also maintainig a queue. So enqueue buffer in the driver
+ * queue */
+ list_add_tail(&vb->queue, &vout->dma_queue);
+
+ vb->state = VIDEOBUF_PREPARED;
+}
+
+/* Buffer release function is called from videobuf layer to release buffer
+ * which are already allocated */
+static void
+omap_vout_buffer_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct omap_vout_fh *fh =
+ (struct omap_vout_fh *) q->priv_data;
+ struct omap_vout_device *vout = fh->vout;
+
+ vb->state = VIDEOBUF_NEEDS_INIT;
+
+ if (V4L2_MEMORY_MMAP != vout->memory)
+ return;
+}
+
+static int omap_vout_calculate_offset(struct omap_vout_device *vout)
+{
+ struct v4l2_pix_format *pix = &(vout->pix);
+ struct v4l2_rect *crop = &(vout->crop);
+ struct v4l2_window *win = &(vout->win);
+ int rotation_deg;
+ int mirroring = vout->mirror;
+ int vr_ps = 1, ps = 2, temp_ps = 2;
+ int offset = 0, ctop = 0, cleft = 0, line_length = 0;
+ int *cropped_offset = &(vout->cropped_offset);
+
+ if ((omap_disp_get_output_dev(vout->vid) == OMAP_OUTPUT_TV) &&
+ ((win->w.width == crop->width)
+ && (win->w.height == crop->height)))
+ vout->flicker_filter = 1;
+ else
+ vout->flicker_filter = 0;
+
+ if (1 == vout->mirror && vout->rotation >= 0) {
+ rotation_deg = (vout->rotation == 90) ? 270 :
+ (vout->rotation == 270) ? 90 : (vout->rotation ==
+ 180) ? 0 : 180;
+
+ } else if (vout->rotation >= 0) {
+ rotation_deg = vout->rotation;
+ } else {
+ rotation_deg = -1;
+ }
+
+ if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+ V4L2_PIX_FMT_UYVY == pix->pixelformat) {
+ if (rotation_deg >= 0 || mirroring == 1) {
+ /*
+ * 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 (rotation_deg >= 0) {
+ 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_deg) {
+ case 90:
+ offset = (omap_disp_get_vrfb_offset(pix->width, ps,
+ SIDE_H) -
+ (pix->width / vr_ps)) * ps * line_length;
+ temp_ps = ps / vr_ps;
+ if (mirroring == 0) {
+ *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 180:
+ offset = (omap_disp_get_vrfb_offset(pix->height, ps,
+ SIDE_H) -
+ pix->height) * ps * line_length +
+ (omap_disp_get_vrfb_offset(pix->width, ps, SIDE_W) -
+ (pix->width / vr_ps)) * ps;
+ if (mirroring == 0) {
+ *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 270:
+ offset = (omap_disp_get_vrfb_offset(pix->height, ps,
+ SIDE_W) -
+ pix->height) * ps;
+ temp_ps = ps / vr_ps;
+ if (mirroring == 0) {
+ *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 0:
+ if (mirroring == 0) {
+ *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:
+ if (mirroring == 0) {
+ *cropped_offset =
+ line_length * ps * crop->top + crop->left * ps;
+ } else {
+ *cropped_offset = (line_length * ps *
+ crop->top) / vr_ps +
+ (crop->left * ps) / vr_ps +
+ ((crop->width / vr_ps) - 1) * ps;
+ }
+ break;
+ }
+
+ if (vout->flicker_filter == 1)
+ vout->tv_field1_offset = 0;
+ else if (vout->rotation >= 0) {
+ if (vout->mirror == 1)
+ vout->tv_field1_offset =
+ -vout->line_length * vout->ps;
+ else
+ vout->tv_field1_offset =
+ vout->line_length * vout->ps;
+ } else {
+ if (vout->mirror == 1)
+ vout->tv_field1_offset =
+ vout->line_length * vout->ps / vout->vr_ps;
+ else
+ vout->tv_field1_offset =
+ vout->line_length * vout->ps;
+ }
+ return 0;
+}
+
+static int
+omap_vout_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct omap_vout_fh *fh =
+ (struct omap_vout_fh *) file->private_data;
+ struct omap_vout_device *vout = fh->vout;
+ int err = -EINVAL;
+
+ switch (cmd) {
+
+ case VIDIOC_G_OUTPUT:
+ {
+ int *output = (int *) arg;
+ return omap_disp_get_output(1, output);
+ }
+
+ case VIDIOC_S_OUTPUT:
+ {
+ unsigned int *output = arg;
+ omap_disp_get_dss();
+ err = omap_disp_set_output(1, *output);
+ omap_disp_put_dss();
+ return err;
+ }
+
+ case VIDIOC_ENUMOUTPUT:
+ {
+ struct v4l2_output *output =
+ (struct v4l2_output *) arg;
+
+ omap_disp_get_dss();
+ err = omap_disp_enum_output(1, output->index,
+ output->name);
+ if (!err)
+ output->type = V4L2_OUTPUT_TYPE_MODULATOR;
+
+ omap_disp_put_dss();
+ return err;
+ }
+
+ case VIDIOC_S_STD:
+ {
+ int i;
+ v4l2_std_id *id = (v4l2_std_id *) arg;
+ for (i = 0; i < ARRAY_SIZE(id_name); i++) {
+ if (*id == id_name[i].id) {
+ omap_disp_get_dss();
+ err = omap_disp_set_mode
+ (1, id_name[i].name);
+ omap_disp_put_dss();
+ }
+ }
+ return err;
+
+ }
+
+ case VIDIOC_G_STD:
+ {
+ int i;
+ char *s;
+ v4l2_std_id *id = (v4l2_std_id *) arg;
+ omap_disp_get_dss();
+ s = omap_disp_get_mode(1);
+ omap_disp_put_dss();
+ for (i = 0; i < ARRAY_SIZE(id_name); i++) {
+ if (!(strcmp(s, id_name[i].name))) {
+ *id = id_name[i].id;
+ err = 0;
+ }
+ }
+ return err;
+ }
+#if 0
+ case VIDIOC_ENUMOUTPUT:
+ {
+ struct v4l2_output *output =
+ (struct v4l2_output *) arg;
+ int index = output->index;
+
+ if (index > 0)
+ return -EINVAL;
+
+ memset(output, 0, sizeof(*output));
+ output->index = index;
+
+ strncpy(output->name, "video out",
+ sizeof(output->name));
+ output->type = V4L2_OUTPUT_TYPE_MODULATOR;
+ return 0;
+ }
+ case VIDIOC_G_OUTPUT:
+ {
+ unsigned int *output = arg;
+ *output = 0;
+ return 0;
+ }
+
+ case VIDIOC_S_OUTPUT:
+ {
+ unsigned int *output = arg;
+ if (*output > 0)
+ return -EINVAL;
+ return 0;
+ }
+#endif
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap =
+ (struct v4l2_capability *) arg;
+ memset(cap, 0, sizeof(*cap));
+ strncpy(cap->driver, VOUT_NAME,
+ sizeof(cap->driver));
+ strncpy(cap->card, vout->vfd->name,
+ sizeof(cap->card));
+ cap->bus_info[0] = '\0';
+ cap->capabilities =
+ V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
+#ifdef DEBUG_ALLOW_WRITE
+ cap->capabilities |= V4L2_CAP_READWRITE;
+#endif
+ return 0;
+ }
+
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *fmt = arg;
+ int index = fmt->index;
+ enum v4l2_buf_type type = fmt->type;
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->index = index;
+ fmt->type = type;
+
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ if (index >= NUM_OUTPUT_FORMATS)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ fmt->flags = omap_formats[index].flags;
+ strncpy(fmt->description,
+ omap_formats[index].description,
+ sizeof(fmt->description));
+ fmt->pixelformat =
+ omap_formats[index].pixelformat;
+
+ return 0;
+ }
+
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = (struct v4l2_format *) arg;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ {
+ struct v4l2_pix_format *pix =
+ &f->fmt.pix;
+ memset(pix, 0, sizeof(*pix));
+ *pix = vout->pix;
+ return 0;
+ }
+
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ {
+ struct v4l2_window *win =
+ &f->fmt.win;
+ memset(win, 0, sizeof(*win));
+
+ /*
+ * The API has a bit of a problem here.
+ * We're returning a v4l2_window
+ * structure, but that structure
+ * contains pointers to variable-sized
+ * objects for clipping rectangles and
+ * clipping bitmaps. We will just
+ * return NULLs for those pointers.
+ */
+
+ win->w = vout->win.w;
+ win->field = vout->win.field;
+ win->chromakey =
+ vout->win.chromakey;
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = (struct v4l2_format *) arg;
+
+ if (vout->streaming)
+ return -EBUSY;
+
+ /* We dont support RGB24-packed mode if vrfb rotation
+ * is enabled*/
+ if (vout->rotation != -1
+ && f->fmt.pix.pixelformat ==
+ V4L2_PIX_FMT_RGB24)
+ return -EINVAL;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ {
+ struct v4l2_window *win =
+ &f->fmt.win;
+ err =
+ omap_vout_try_window(&vout->
+ fbuf,
+ win);
+ return err;
+ }
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ {
+ /* don't allow to change img for the
+ * linked layer */
+ if (vout->vid == vout_linked)
+ return -EINVAL;
+ omap_disp_get_dss();
+ /* get the framebuffer parameters */
+ if (vout->rotation == 90 ||
+ vout->rotation == 270) {
+ omap_disp_get_panel_size(
+ omap_disp_get_output_dev
+ (vout->vid),
+ &(vout->fbuf.
+ fmt.height),
+ &(vout->fbuf.
+ fmt.width));
+ } else {
+ omap_disp_get_panel_size(
+ omap_disp_get_output_dev
+ (vout->vid),
+ &(vout->fbuf.
+ fmt.width),
+ &(vout->fbuf.
+ fmt.height));
+ }
+ omap_disp_put_dss();
+ omap_vout_try_format(&f->fmt.pix,
+ &vout->fbuf.fmt);
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = (struct v4l2_format *) arg;
+
+ if (vout->streaming)
+ return -EBUSY;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ /* We dont support RGB24-packed mode if vrfb rotation
+ * is enabled*/
+ if (vout->rotation != -1
+ && f->fmt.pix.pixelformat ==
+ V4L2_PIX_FMT_RGB24) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+
+ omap_disp_get_dss();
+
+ /* get the framebuffer parameters */
+ if (vout->rotation == 90 || vout->rotation == 270) {
+ omap_disp_get_panel_size
+ (omap_disp_get_output_dev(vout->vid),
+ &(vout->fbuf.fmt.height),
+ &(vout->fbuf.fmt.width));
+ } else {
+ omap_disp_get_panel_size
+ (omap_disp_get_output_dev(vout->vid),
+ &(vout->fbuf.fmt.width),
+ &(vout->fbuf.fmt.height));
+ }
+
+ omap_disp_put_dss();
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ {
+ struct v4l2_window *win =
+ &f->fmt.win;
+ err =
+ omap_vout_new_window(&vout->
+ crop,
+ &vout->
+ win,
+ &vout->
+ fbuf,
+ win);
+ up(&vout->lock);
+ return err;
+ }
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ {
+ int bpp;
+ /*
+ * don't allow to change img for
+ * the linked layer */
+ if (vout->vid == vout_linked) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ /* change to samller size is OK */
+ bpp = omap_vout_try_format(&f->fmt.pix,
+ &vout->fbuf.fmt);
+ 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);
+ up(&vout->lock);
+ return 0;
+ }
+
+ default:
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_CROPCAP:
+ {
+ struct v4l2_cropcap *cropcap =
+ (struct v4l2_cropcap *) arg;
+ enum v4l2_buf_type type = cropcap->type;
+
+ memset(cropcap, 0, sizeof(*cropcap));
+ cropcap->type = type;
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ {
+ struct v4l2_pix_format *pix =
+ &vout->pix;
+
+ /* Width and height are always even */
+ cropcap->bounds.width =
+ pix->width & ~1;
+ cropcap->bounds.height =
+ pix->height & ~1;
+
+ omap_vout_default_crop(&vout->
+ pix,
+ &vout->
+ fbuf,
+ &cropcap->
+ defrect);
+ cropcap->pixelaspect.numerator = 1;
+ cropcap->pixelaspect.denominator =
+ 1;
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_G_CROP:
+ {
+ struct v4l2_crop *crop = (struct v4l2_crop *) arg;
+
+ switch (crop->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ {
+ crop->c = vout->crop;
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_S_CROP:
+ {
+ struct v4l2_crop *crop = (struct v4l2_crop *) arg;
+ if (vout->streaming)
+ return -EBUSY;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ omap_disp_get_dss();
+
+ /* get the framebuffer parameters */
+ if (vout->rotation == 90 || vout->rotation == 270) {
+ omap_disp_get_panel_size
+ (omap_disp_get_output_dev(vout->vid),
+ &(vout->fbuf.fmt.height),
+ &(vout->fbuf.fmt.width));
+ } else {
+ omap_disp_get_panel_size
+ (omap_disp_get_output_dev(vout->vid),
+ &(vout->fbuf.fmt.width),
+ &(vout->fbuf.fmt.height));
+
+ }
+ omap_disp_put_dss();
+
+ switch (crop->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ {
+ err =
+ omap_vout_new_crop(&vout->
+ pix,
+ &vout->
+ crop,
+ &vout->
+ win,
+ &vout->
+ fbuf,
+ &crop->
+ c);
+ up(&vout->lock);
+ return err;
+ }
+ default:
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_REQBUFS:
+ {
+ struct v4l2_requestbuffers *req =
+ (struct v4l2_requestbuffers *) arg;
+ struct videobuf_queue *q = &fh->vbq;
+ unsigned int i, num_buffers = 0;
+ int ret = 0;
+ struct videobuf_dmabuf *dmabuf = NULL;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ /* don't allow to buffer request for the linked layer */
+ if (vout->vid == vout_linked) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+
+ if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ || (req->count < 0)) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ /* if memory is not mmp or userptr
+ return error */
+ if ((V4L2_MEMORY_MMAP != req->memory) &&
+ (V4L2_MEMORY_USERPTR != req->memory)) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+
+ /* Cannot be requested when streaming is on */
+ if (vout->streaming) {
+ up(&vout->lock);
+ return -EBUSY;
+ }
+
+ /* If buffers are already allocated free them */
+ if (q->bufs[0]
+ && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) {
+ if (vout->mmap_count) {
+ up(&vout->lock);
+ return -EBUSY;
+ }
+ num_buffers = (vout->vid == OMAP_VIDEO1) ?
+ video1_numbuffers : video2_numbuffers;
+ for (i = num_buffers;
+ i < vout->buffer_allocated; i++) {
+ dmabuf =
+ videobuf_to_dma(q->bufs[i]);
+ omap_vout_free_buffer((u32)
+ dmabuf->
+ vmalloc,
+ dmabuf->
+ bus_addr,
+ vout->
+ buffer_size);
+ vout->buf_virt_addr[i] = 0;
+ vout->buf_phy_addr[i] = 0;
+ }
+ vout->buffer_allocated = num_buffers;
+ videobuf_mmap_free(q);
+ } else if (q->bufs[0]
+ && (V4L2_MEMORY_USERPTR ==
+ q->bufs[0]->memory)) {
+ if (vout->buffer_allocated) {
+ videobuf_mmap_free(q);
+ for (i = 0;
+ i < vout->buffer_allocated;
+ i++) {
+ kfree(q->bufs[i]);
+ q->bufs[i] = NULL;
+ }
+ vout->buffer_allocated = 0;
+ }
+ }
+ fh->io_allowed = 1;
+
+ /*store the memory type in data structure */
+ vout->memory = req->memory;
+
+ INIT_LIST_HEAD(&vout->dma_queue);
+
+ /* call videobuf_reqbufs api */
+ ret = videobuf_reqbufs(q, req);
+ if (ret < 0) {
+ up(&vout->lock);
+ return ret;
+ }
+
+ vout->buffer_allocated = req->count;
+ for (i = 0; i < req->count; i++) {
+ dmabuf = videobuf_to_dma(q->bufs[i]);
+ dmabuf->vmalloc =
+ (void *) vout->buf_virt_addr[i];
+ dmabuf->bus_addr =
+ (dma_addr_t) vout->buf_phy_addr[i];
+
+ dmabuf->sglen = 1;
+ }
+ up(&vout->lock);
+ return 0;
+ }
+
+ case VIDIOC_QUERYBUF:
+ return videobuf_querybuf(&fh->vbq, arg);
+
+ case VIDIOC_QBUF:
+ {
+ struct v4l2_buffer *buffer =
+ (struct v4l2_buffer *) arg;
+ struct videobuf_queue *q = &fh->vbq;
+ int streaming_on = STREAMING_IS_ON(), ret = 0;
+
+ if (!fh->io_allowed)
+ return -EINVAL;
+
+ timeout = HZ / 5;
+ timeout += jiffies;
+
+ if (!streaming_on)
+ omap_disp_get_dss();
+
+ /* don't allow to queue buffer for the linked layer */
+ if (vout->vid == vout_linked) {
+ if (!streaming_on)
+ omap_disp_put_dss();
+ return -EINVAL;
+ }
+
+ if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) ||
+ (buffer->index >= vout->buffer_allocated) ||
+ (q->bufs[buffer->index]->memory !=
+ buffer->memory)) {
+ if (!streaming_on)
+ omap_disp_put_dss();
+ return -EINVAL;
+ }
+ if (V4L2_MEMORY_USERPTR == buffer->memory) {
+ if ((buffer->length < vout->pix.sizeimage)
+ || (0 == buffer->m.userptr)) {
+ if (!streaming_on)
+ omap_disp_put_dss();
+ return -EINVAL;
+ }
+ }
+
+ if (vout->rotation >= 0
+ && vout->vrfb_dma_tx.req_status ==
+ DMA_CHAN_NOT_ALLOTED) {
+ if (!streaming_on)
+ omap_disp_put_dss();
+ return -EINVAL;
+ }
+
+ ret = videobuf_qbuf(q, buffer);
+ if (!streaming_on)
+ omap_disp_put_dss();
+ return ret;
+ }
+
+ case VIDIOC_DQBUF:
+ {
+ struct videobuf_queue *q = &fh->vbq;
+ int ret = 0;
+ /* don't allow to dequeue buffer for the linked layer */
+ if (vout->vid == vout_linked)
+ return -EINVAL;
+
+ if (!vout->streaming || !fh->io_allowed)
+ return -EINVAL;
+
+ if (file->f_flags & O_NONBLOCK)
+ /* Call videobuf_dqbuf for non
+ blocking mode */
+ ret =
+ videobuf_dqbuf(q,
+ (struct v4l2_buffer *)
+ arg, 1);
+ else
+ /* Call videobuf_dqbuf for
+ blocking mode */
+ ret =
+ videobuf_dqbuf(q,
+ (struct v4l2_buffer *)
+ arg, 0);
+ return ret;
+ }
+
+ case VIDIOC_STREAMON:
+ {
+ struct videobuf_queue *q = &fh->vbq;
+ struct omap_vout_device *dest = NULL;
+ struct videobuf_dmabuf *dmabuf = NULL;
+ int ret = 0, rotation = -1, mask = 0;
+ u32 addr = 0;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ if (!fh->io_allowed) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+
+ if (vout->streaming) {
+ up(&vout->lock);
+ return -EBUSY;
+ }
+
+ ret = videobuf_streamon(q);
+ if (ret < 0) {
+ up(&vout->lock);
+ return ret;
+ }
+
+ if (list_empty(&vout->dma_queue)) {
+ up(&vout->lock);
+ return -EIO;
+ }
+ /* Get the next frame from the buffer queue */
+ vout->nextFrm = vout->curFrm =
+ list_entry(vout->dma_queue.next,
+ struct videobuf_buffer, queue);
+ /* Remove buffer from the buffer queue */
+ list_del(&vout->curFrm->queue);
+ /* Mark state of the current frame to active */
+ vout->curFrm->state = VIDEOBUF_ACTIVE;
+ /* Initialize field_id and started member */
+ vout->field_id = 0;
+
+ /* set flag here. Next QBUF will start DMA */
+ vout->streaming = fh;
+
+ vout->first_int = 1;
+
+ omap_disp_get_dss();
+ rotation =
+ (vout->rotation >= 0) ? vout->rotation : -1;
+
+ omap_vout_config_vlayer(vout->vid, &vout->pix,
+ &vout->crop, &vout->win,
+ rotation, vout->mirror);
+ omap_vout_calculate_offset(vout);
+
+ addr =
+ (unsigned long) vout->queued_buf_addr[vout->
+ curFrm->
+ i] +
+ vout->cropped_offset;
+ omap_disp_set_addr(vout->vid, addr, addr,
+ addr + vout->tv_field1_offset);
+
+ /* Configure also linked layer */
+ if (vout_linked != -1 && vout_linked != vout->vid) {
+ dest =
+ (vout_linked ==
+ OMAP_VIDEO1) ? saved_v1out :
+ saved_v2out;
+ rotation =
+ (dest->rotation >=
+ 0) ? dest->rotation : -1;
+ if (rotation > -1) {
+ if (!(vout->rotation > -1)) {
+ printk
+ ("Rotation should be \
+ enabled in linking layer\n");
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ if (rotation != vout->rotation) {
+ printk
+ ("Rotation must be same \
+ in both the layers\n");
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ }
+ omap_vout_calculate_offset(dest);
+
+ if (rotation >= 0) {
+ addr = (unsigned long)
+ vout->queued_buf_addr[vout->
+ curFrm->
+ i] +
+ dest->cropped_offset;
+ } else {
+ dmabuf =
+ videobuf_to_dma(vout->curFrm);
+ addr =
+ (unsigned long) dmabuf->
+ bus_addr +
+ dest->cropped_offset;
+ }
+
+ omap_vout_config_vlayer(dest->vid,
+ &dest->pix,
+ &dest->crop,
+ &dest->win,
+ rotation,
+ dest->mirror);
+
+ omap_disp_set_addr(dest->vid, addr, addr,
+ addr +
+ dest->
+ tv_field1_offset);
+ }
+ /* Register ISR handler */
+ mask =
+ (DISPC_IRQSTATUS_EVSYNC_ODD |
+ DISPC_IRQSTATUS_EVSYNC_EVEN |
+ DISPC_IRQSTATUS_VSYNC);
+ ret =
+ omap_disp_register_isr(omap_vout_isr, vout,
+ mask);
+ if (ret < 0) {
+ up(&vout->lock);
+ return -EIO;
+ }
+
+ omap_disp_start_video_layer(vout->vid);
+ if (vout_linked != -1 && vout_linked != vout->vid)
+ omap_disp_start_video_layer(dest->vid);
+ up(&vout->lock);
+ return 0;
+ }
+
+ case VIDIOC_STREAMOFF:
+ {
+ struct videobuf_queue *q = &fh->vbq;
+ int ret = 0;
+ if (!fh->io_allowed)
+ return -EINVAL;
+ if (!vout->streaming)
+ return -EINVAL;
+ if (vout->streaming == fh) {
+ omap_disp_disable_layer(vout->vid);
+ vout->streaming = NULL;
+
+ /* stop the slave layer */
+ if (vout_linked != -1
+ && vout_linked != vout->vid) {
+ omap_disp_disable_layer((vout->
+ vid ==
+ OMAP_VIDEO1)
+ ?
+ OMAP_VIDEO2
+ :
+ OMAP_VIDEO1);
+ }
+
+ ret = videobuf_streamoff(q);
+ omap_disp_unregister_isr
+ (omap_vout_isr);
+
+ omap_disp_put_dss();
+
+ return 0;
+ }
+
+ return -EINVAL;
+ }
+
+ case VIDIOC_S_OMAP_LINK:
+ {
+ int *link = arg;
+
+ spin_lock(&vout_link_lock);
+ if ((*link == 0) && (vout_linked == vout->vid))
+ vout_linked = -1;
+
+ omap_disp_get_dss();
+ if ((*link == 1)
+ && (vout_linked == -1
+ || vout_linked == vout->vid)) {
+ vout_linked = vout->vid;
+
+ if (vout_linked == OMAP_VIDEO2) {
+ /* sync V2 to V1 for img and crop */
+ omap_vout_sync(saved_v2out,
+ saved_v1out);
+ } else {
+ /* sync V1 to V2 */
+ omap_vout_sync(saved_v1out,
+ saved_v2out);
+ }
+ }
+
+ omap_disp_put_dss();
+
+ spin_unlock(&vout_link_lock);
+ return 0;
+ }
+
+ case VIDIOC_G_OMAP_LINK:
+ {
+ int *link = arg;
+
+ spin_lock(&vout_link_lock);
+ if (vout_linked == vout->vid)
+ *link = 1;
+ else
+ *link = 0;
+ spin_unlock(&vout_link_lock);
+ return 0;
+ }
+
+ case VIDIOC_S_OMAP_MIRROR:
+ {
+ int *mirror = arg;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ if ((*mirror == 0) && (vout->mirror == 1)) {
+ vout->mirror = 0;
+ up(&vout->lock);
+ return 0;
+ } else if ((*mirror == 1) && (vout->mirror == 0)) {
+ vout->mirror = 1;
+ up(&vout->lock);
+ return 0;
+ }
+ up(&vout->lock);
+ return -EINVAL;
+ }
+
+ case VIDIOC_G_OMAP_MIRROR:
+ {
+ int *mirror = arg;
+ *mirror = vout->mirror;
+ return 0;
+ }
+
+ case VIDIOC_S_OMAP_ROTATION:
+ {
+ int *rotation = arg;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ if ((*rotation == 0) || (*rotation == 90) ||
+ (*rotation == 180) || (*rotation == 270)
+ || (*rotation == -1)) {
+ vout->rotation =
+ (*rotation == 90) ? 270 : (*rotation ==
+ 270) ? 90 :
+ *rotation;
+ up(&vout->lock);
+ rotation_support = vout->rotation;
+ return 0;
+ } else {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_G_OMAP_ROTATION:
+ {
+ int *rotation = arg;
+ *rotation = (vout->rotation == 90) ? 270 :
+ (vout->rotation == 270) ? 90 : vout->rotation;
+ return 0;
+ }
+
+ case VIDIOC_S_OMAP_COLORKEY:
+ {
+ struct omap_vout_colorkey *colorkey =
+ (struct omap_vout_colorkey *) arg;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ if ((colorkey->output_dev != OMAP_OUTPUT_LCD &&
+ colorkey->output_dev != OMAP_OUTPUT_TV) ||
+ (colorkey->key_type != OMAP_GFX_DESTINATION
+ && colorkey->key_type != OMAP_VIDEO_SOURCE)) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ omap_disp_get_dss();
+
+ omap_disp_set_colorkey(colorkey->output_dev,
+ colorkey->key_type,
+ colorkey->key_val);
+
+ omap_disp_put_dss();
+ up(&vout->lock);
+
+ return 0;
+ }
+
+ case VIDIOC_G_OMAP_COLORKEY:
+ {
+ struct omap_vout_colorkey *colorkey =
+ (struct omap_vout_colorkey *) arg;
+
+ if (colorkey->output_dev != OMAP_OUTPUT_LCD
+ && colorkey->output_dev != OMAP_OUTPUT_TV)
+ return -EINVAL;
+
+ omap_disp_get_dss();
+
+ omap_disp_get_colorkey(colorkey->output_dev,
+ &colorkey->key_type,
+ &colorkey->key_val);
+
+ omap_disp_put_dss();
+
+ return 0;
+
+ }
+
+ case VIDIOC_S_OMAP_BGCOLOR:
+ {
+ struct omap_vout_bgcolor *bgcolor =
+ (struct omap_vout_bgcolor *) arg;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ if (bgcolor->output_dev != OMAP_OUTPUT_LCD
+ && bgcolor->output_dev != OMAP_OUTPUT_TV) {
+ up(&vout->lock);
+ return -EINVAL;
+ }
+ omap_disp_get_dss();
+
+ omap_disp_set_bg_color(bgcolor->output_dev,
+ bgcolor->color);
+
+ omap_disp_put_dss();
+
+ up(&vout->lock);
+ return 0;
+ }
+
+ case VIDIOC_G_OMAP_BGCOLOR:
+ {
+ struct omap_vout_bgcolor *bgcolor =
+ (struct omap_vout_bgcolor *) arg;
+
+ if (bgcolor->output_dev != OMAP_OUTPUT_LCD
+ && bgcolor->output_dev != OMAP_OUTPUT_TV)
+ return -EINVAL;
+
+ omap_disp_get_dss();
+
+ omap_disp_get_bg_color(bgcolor->output_dev,
+ &bgcolor->color);
+
+ omap_disp_put_dss();
+
+ return 0;
+ }
+
+ case VIDIOC_OMAP_COLORKEY_ENABLE:
+ {
+ int *output_dev = arg;
+
+ if (*output_dev != OMAP_OUTPUT_LCD
+ && *output_dev != OMAP_OUTPUT_TV)
+ return -EINVAL;
+
+ omap_disp_get_dss();
+
+ omap_disp_enable_colorkey(*output_dev);
+
+ omap_disp_put_dss();
+
+ return 0;
+ }
+
+ case VIDIOC_OMAP_COLORKEY_DISABLE:
+ {
+ int *output_dev = arg;
+
+ if (*output_dev != OMAP_OUTPUT_LCD
+ && *output_dev != OMAP_OUTPUT_TV)
+ return -EINVAL;
+
+ omap_disp_get_dss();
+
+ omap_disp_disable_colorkey(*output_dev);
+
+ omap_disp_put_dss();
+
+ return 0;
+ }
+
+ case VIDIOC_S_OMAP_COLORCONV:
+ {
+ int v;
+ int full_range_conversion = 0;
+ struct omap_vout_colconv *ccmtx =
+ (struct omap_vout_colconv *) arg;
+
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ if (vout->vid == OMAP_VIDEO1)
+ v = 0;
+ else
+ v = 1;
+
+ current_colorconv_values[v][0][0] = ccmtx->RY;
+ current_colorconv_values[v][0][1] = ccmtx->RCr;
+ current_colorconv_values[v][0][2] = ccmtx->RCb;
+ current_colorconv_values[v][1][0] = ccmtx->GY;
+ current_colorconv_values[v][1][1] = ccmtx->GCr;
+ current_colorconv_values[v][1][2] = ccmtx->GCb;
+ current_colorconv_values[v][2][0] = ccmtx->BY;
+ current_colorconv_values[v][2][1] = ccmtx->BCr;
+ current_colorconv_values[v][2][2] = ccmtx->BCb;
+ omap_disp_get_dss();
+
+ if (vout->pix.colorspace == V4L2_COLORSPACE_JPEG ||
+ vout->pix.colorspace == V4L2_COLORSPACE_SRGB) {
+ full_range_conversion = 1;
+ }
+ omap_disp_set_colorconv(v, full_range_conversion);
+ omap_disp_put_dss();
+ up(&vout->lock);
+ return 0;
+ }
+
+ case VIDIOC_G_OMAP_COLORCONV:
+ {
+ int v;
+ struct omap_vout_colconv *ccmtx =
+ (struct omap_vout_colconv *) arg;
+
+ if (vout->vid == OMAP_VIDEO1)
+ v = 0;
+ else
+ v = 1;
+
+ ccmtx->RY = current_colorconv_values[v][0][0];
+ ccmtx->RCr = current_colorconv_values[v][0][1];
+ ccmtx->RCb = current_colorconv_values[v][0][2];
+ ccmtx->GY = current_colorconv_values[v][1][0];
+ ccmtx->GCr = current_colorconv_values[v][1][1];
+ ccmtx->GCb = current_colorconv_values[v][1][2];
+ ccmtx->BY = current_colorconv_values[v][2][0];
+ ccmtx->BCr = current_colorconv_values[v][2][1];
+ ccmtx->BCb = current_colorconv_values[v][2][2];
+
+ return 0;
+ }
+
+ case VIDIOC_S_OMAP_DEFCOLORCONV:
+ {
+ if (down_interruptible(&vout->lock))
+ return -EINVAL;
+ omap_disp_get_dss();
+ switch (vout->pix.colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_SMPTE240M:
+ case V4L2_COLORSPACE_BT878:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ omap_disp_set_default_colorconv(vout->vid,
+ CC_BT601);
+ break;
+ case V4L2_COLORSPACE_REC709:
+ omap_disp_set_default_colorconv(vout->vid,
+ CC_BT709);
+ break;
+ case V4L2_COLORSPACE_JPEG:
+ case V4L2_COLORSPACE_SRGB:
+ omap_disp_set_default_colorconv(vout->vid,
+ CC_BT601_FULL);
+ break;
+ }
+
+ omap_disp_put_dss();
+ up(&vout->lock);
+ return 0;
+ }
+
+ default:
+ /* unrecognized ioctl */
+ return -ENOIOCTLCMD;
+
+ } /* End of switch(cmd) */
+
+ return 0;
+}
+
+/*
+ * file operations
+ */
+
+#ifdef DEBUG_ALLOW_WRITE
+
+static ssize_t
+omap_vout_write(struct file *file, const char *data,
+ size_t count, loff_t *ppos)
+{
+ struct omap_vout_fh *fh = file->private_data;
+ struct omap_vout_device *vout = fh->vout;
+
+ omap_disp_get_dss();
+
+ omap_vout_suspend_lockout(vout, file);
+ if ((*ppos) >= vout->pix.sizeimage) {
+ omap_disp_put_dss();
+ return 0;
+ }
+ if (count + (*ppos) > vout->pix.sizeimage)
+ count = vout->pix.sizeimage - (*ppos);
+ if (copy_from_user
+ ((void *) (vout->framebuffer_base + (*ppos)), data, count)) {
+ printk(KERN_WARNING"error in copying data");
+ }
+ *ppos += count;
+
+#if 1
+ if (*ppos == vout->pix.sizeimage)
+ mdelay(5000);
+#endif
+
+ omap_disp_put_dss();
+
+ return count;
+}
+
+#endif
+
+static void omap_vout_vm_open(struct vm_area_struct *vma)
+{
+ struct omap_vout_device *vout = vma->vm_private_data;
+ DPRINTK("vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
+ vout->mmap_count++;
+}
+
+static void omap_vout_vm_close(struct vm_area_struct *vma)
+{
+ struct omap_vout_device *vout = vma->vm_private_data;
+ DPRINTK("vm_close [vma=%08lx-%08lx]\n", vma->vm_start,
+ vma->vm_end);
+ vout->mmap_count--;
+}
+
+static struct vm_operations_struct omap_vout_vm_ops = {
+ .open = omap_vout_vm_open,
+ .close = omap_vout_vm_close,
+};
+
+static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct omap_vout_fh *fh = file->private_data;
+ struct omap_vout_device *vout = fh->vout;
+ struct videobuf_queue *q = &fh->vbq;
+ unsigned long size = (vma->vm_end - vma->vm_start);
+ unsigned long start = vma->vm_start;
+ int i;
+ void *pos;
+ struct videobuf_dmabuf *dmabuf = NULL;
+
+ DPRINTK("pgoff=0x%lx, start=0x%lx, end=0x%lx\n", vma->vm_pgoff,
+ vma->vm_start, vma->vm_end);
+
+ /* look for the buffer to map */
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+ if (V4L2_MEMORY_MMAP != q->bufs[i]->memory)
+ continue;
+ if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT))
+ break;
+ }
+
+ if (VIDEO_MAX_FRAME == i) {
+ DPRINTK("offset invalid [offset=0x%lx]\n",
+ (vma->vm_pgoff << PAGE_SHIFT));
+ return -EINVAL;
+ }
+ q->bufs[i]->baddr = vma->vm_start;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_ops = &omap_vout_vm_ops;
+ vma->vm_private_data = (void *) vout;
+ dmabuf = videobuf_to_dma(q->bufs[i]);
+ pos = dmabuf->vmalloc;
+ while (size > 0) {
+ unsigned long pfn;
+ pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT;
+ if (remap_pfn_range
+ (vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ vout->mmap_count++;
+ return 0;
+}
+
+static int
+omap_vout_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct omap_vout_fh *fh = file->private_data;
+ struct omap_vout_device *vout = fh->vout;
+
+ omap_vout_suspend_lockout(vout, file);
+ return video_usercopy(inode, file, cmd, arg,
+ omap_vout_do_ioctl);
+}
+
+static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
+{
+ int num_buffers = 0, i;
+ num_buffers = (vout->vid == OMAP_VIDEO1) ?
+ video1_numbuffers : video2_numbuffers;
+ for (i = num_buffers; i < vout->buffer_allocated; i++) {
+ if (vout->buf_virt_addr[i]) {
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
+ vout->buf_phy_addr[i],
+ vout->buffer_size);
+ }
+ vout->buf_virt_addr[i] = 0;
+ vout->buf_phy_addr[i] = 0;
+ }
+ for (i = 0; i < 4; i++) {
+ if (vout->smsshado_virt_addr[i]) {
+ omap_vout_free_buffer(vout->
+ smsshado_virt_addr[i],
+ vout->
+ smsshado_phy_addr[i],
+ vout->smsshado_size);
+ vout->smsshado_virt_addr[i] = 0;
+ vout->smsshado_phy_addr[i] = 0;
+ }
+ }
+ vout->buffer_allocated = num_buffers;
+}
+
+static int omap_vout_release(struct inode *inode, struct file *file)
+{
+ struct omap_vout_fh *fh = file->private_data;
+ struct omap_vout_device *vout;
+ struct videobuf_queue *q;
+
+ DPRINTK("entering\n");
+
+ vout = fh->vout;
+ if (fh == 0)
+ return 0;
+ if (!vout)
+ return 0;
+ q = &fh->vbq;
+
+ omap_disp_get_dss();
+ omap_vout_suspend_lockout(vout, file);
+
+ /*
+ * Check if the hidden buffer transfer is happening with DMA
+ * if yes then stop it
+ */
+
+ if (vout->rotation >= 0) {
+ if (vout->vrfb_dma_tx.tx_status == 0) {
+ /*
+ * DMA will be stopped once here and again after
+ * wakeup to avoid race conditions due to time
+ * taken to wakeup the sleeping process
+ */
+
+ omap_stop_dma(vout->vrfb_dma_tx.dma_ch);
+ wake_up_interruptible(&vout->vrfb_dma_tx.wait);
+ }
+ }
+
+ omap_disp_disable_layer(vout->vid);
+
+ if ((vout_linked != -1) && (vout->vid != vout_linked))
+ omap_disp_disable_layer((vout->vid == OMAP_VIDEO1) ?
+ OMAP_VIDEO2 : OMAP_VIDEO1);
+
+ if (fh->io_allowed) {
+ videobuf_streamoff(q);
+ videobuf_queue_cancel(q);
+ /* Free all buffers */
+ omap_vout_free_allbuffers(vout);
+ videobuf_mmap_free(q);
+ }
+#ifdef DEBUG_ALLOW_WRITE
+ if (vout->framebuffer_base) {
+
+ dma_free_coherent(NULL, vout->framebuffer_size, (void *)
+ vout->framebuffer_base,
+ vout->framebuffer_base_phys);
+ vout->framebuffer_base = 0;
+ }
+ vout->framebuffer_base_phys = 0;
+#endif
+
+ if (vout->streaming == fh) {
+ omap_disp_unregister_isr(omap_vout_isr);
+ vout->streaming = NULL;
+ }
+
+ if (vout->mmap_count != 0) {
+ vout->mmap_count = 0;
+ printk("mmap count is not zero!\n");
+ }
+
+ omap_disp_release_layer(vout->vid);
+ omap_disp_put_dss();
+ vout->opened -= 1;
+ file->private_data = NULL;
+
+ if (vout->buffer_allocated)
+ videobuf_mmap_free(q);
+
+ kfree(fh);
+
+ /* need to remove the link when the either slave or master is gone */
+ spin_lock(&vout_link_lock);
+ if (vout_linked != -1)
+ vout_linked = -1;
+ spin_unlock(&vout_link_lock);
+
+ return 0;
+}
+
+static int omap_vout_open(struct inode *inode, struct file *file)
+{
+ int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct omap_vout_device *vout = NULL;
+ struct omap_vout_fh *fh;
+ struct videobuf_queue *q;
+#ifdef DEBUG_ALLOW_WRITE
+ int rotation = -1;
+#endif
+ /*int i; */
+
+ DPRINTK("entering\n");
+
+ if (saved_v1out && saved_v1out->vfd
+ && (saved_v1out->vfd->minor == minor)) {
+ vout = saved_v1out;
+ }
+
+ if (vout == NULL) {
+ if (saved_v2out && saved_v2out->vfd
+ && (saved_v2out->vfd->minor == minor)) {
+ vout = saved_v2out;
+ }
+ }
+
+ if (vout == NULL)
+ return -ENODEV;
+
+ /* for now, we only support single open */
+ if (vout->opened)
+ return -EBUSY;
+
+ vout->opened += 1;
+ if (!omap_disp_request_layer(vout->vid)) {
+ vout->opened -= 1;
+ return -ENODEV;
+ }
+
+ omap_disp_get_dss();
+ omap_vout_suspend_lockout(vout, file);
+ /* allocate per-filehandle data */
+ fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ omap_disp_release_layer(vout->vid);
+ omap_disp_put_dss();
+ vout->opened -= 1;
+ return -ENOMEM;
+ }
+ memset(fh, 0, sizeof(*fh));
+
+ file->private_data = fh;
+ fh->vout = vout;
+ fh->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+#ifdef DEBUG_ALLOW_WRITE
+ vout->framebuffer_size = VID_MAX_HEIGHT * VID_MAX_HEIGHT * 2;
+ vout->framebuffer_base = dma_alloc_coherent(NULL,
+ vout->framebuffer_size,
+ (dma_addr_t *) &vout->
+ framebuffer_base_phys,
+ GFP_KERNEL | GFP_DMA);
+
+ if (!vout->framebuffer_base) {
+ kfree(fh);
+ omap_disp_release_layer(vout->vid);
+ omap_disp_put_dss();
+ vout->opened -= 1;
+ return -ENOMEM;
+ }
+ rotation = (vout->rotation >= 0) ? vout->rotation : -1;
+ memset((void *) vout->framebuffer_base, 0, vout->framebuffer_size);
+
+ omap_vout_config_vlayer(dest->vid, &dest->pix, &dest->crop,
+ &dest->win, rotation, dest->mirror);
+ omap_disp_start_vlayer(vout->vid, &vout->pix, &vout->crop,
+ vout->framebuffer_base_phys, rotation,
+ vout->mirror);
+#endif
+
+ q = &fh->vbq;
+ video_vbq_ops.buf_setup = omap_vout_buffer_setup;
+ video_vbq_ops.buf_prepare = omap_vout_buffer_prepare;
+ video_vbq_ops.buf_release = omap_vout_buffer_release;
+ video_vbq_ops.buf_queue = omap_vout_buffer_queue;
+ spin_lock_init(&vout->vbq_lock);
+
+ videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock,
+ fh->type, V4L2_FIELD_NONE, sizeof
+ (struct videobuf_buffer), fh);
+
+ omap_disp_put_dss();
+
+ return 0;
+}
+
+static struct file_operations omap_vout_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+#ifdef DEBUG_ALLOW_WRITE
+ .write = omap_vout_write,
+#endif
+ .ioctl = omap_vout_ioctl,
+ .mmap = omap_vout_mmap,
+ .open = omap_vout_open,
+ .release = omap_vout_release,
+};
+
+#ifdef CONFIG_PM
+static int
+omap_vout_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct omap_vout_device *vout = platform_get_drvdata(dev);
+
+ /* lock-out applications during suspend */
+ if (vout->suspended == 1)
+ return 0;
+ if (vout->opened) {
+ /* stall vid DMA */
+ if (vout->streaming) {
+ omap_disp_disable_layer(vout->vid);
+ /*
+ * Check if the hidden buffer transfer is happening
+ * with DMA if yes then stop it
+ */
+
+ if (vout->rotation >= 0) {
+ if (vout->vrfb_dma_tx.tx_status == 0) {
+ /*
+ * DMA will be stopped once here
+ * and again after wakeup to
+ * avoid race conditions due to time
+ * taken to wakeup the sleeping
+ * process */
+ omap_stop_dma(vout->vrfb_dma_tx.
+ dma_ch);
+ wake_up_interruptible(&vout->
+ vrfb_dma_tx.
+ wait);
+ }
+ }
+ }
+ vout->suspended = 1;
+ omap_disp_put_dss();
+ }
+
+ return 0;
+}
+
+static int omap_vout_resume(struct platform_device *dev)
+{
+ struct omap_vout_device *vout = platform_get_drvdata(dev);
+ if (vout->suspended == 0)
+ return 0;
+ if (vout->opened) {
+ omap_disp_get_dss();
+
+ /* resume vid DMA */
+ if (vout->streaming)
+ omap_disp_enable_layer(vout->vid);
+
+ /* wake up applications waiting on suspend queue */
+ vout->suspended = 0;
+ wake_up(&vout->suspend_wq);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_DPM
+
+static struct constraints omap_vout_constraints = {
+ .count = 2,
+ .param = {
+ {DPM_MD_V, OMAP_V_MIN, OMAP_V_MAX},
+ {DPM_MD_SLEEP_MODE, PM_SUSPEND_STANDBY, PM_SUSPEND_MEM},
+ },
+};
+
+static int
+omap_vout_scale(int vid, struct notifier_block *op, unsigned long level)
+{
+ struct omap_vout_device *vout;
+ vout = (vid == OMAP_VIDEO1) ? saved_v1out : saved_v2out;
+ if (!vout->opened)
+ return 0;
+ switch (level) {
+ case SCALE_PRECHANGE:
+ if (vout->streaming) {
+ omap_disp_disable_layer(vout->vid);
+ if (vout->rotation >= 0) {
+ if (vout->vrfb_dma_tx.tx_status == 0) {
+ omap_stop_dma(vout->vrfb_dma_tx.
+ dma_ch);
+ }
+ }
+ }
+ break;
+ case SCALE_POSTCHANGE:
+ if (vout->streaming) {
+ omap_disp_enable_layer(vout->vid);
+ if (vout->rotation >= 0) {
+ if (vout->vrfb_dma_tx.tx_status == 0) {
+ omap_start_dma(vout->vrfb_dma_tx.
+ dma_ch);
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int
+omap_v1out_scale(struct notifier_block *op,
+ unsigned long level, void *ptr)
+{
+ return omap_vout_scale(OMAP_VIDEO1, op, level);
+}
+
+static int
+omap_v2out_scale(struct notifier_block *op,
+ unsigned long level, void *ptr)
+{
+ return omap_vout_scale(OMAP_VIDEO2, op, level);
+}
+
+static struct notifier_block omap_v1out_pre_scale = {
+ .notifier_call = omap_v1out_scale,
+};
+
+static struct notifier_block omap_v1out_post_scale = {
+ .notifier_call = omap_v1out_scale,
+};
+
+static struct notifier_block omap_v2out_pre_scale = {
+ .notifier_call = omap_v2out_scale,
+};
+
+static struct notifier_block omap_v2out_post_scale = {
+ .notifier_call = omap_v2out_scale,
+};
+
+#endif
+#endif /* PM */
+
+static int omap_vout_probe(struct platform_device *dev)
+{
+ return 0;
+}
+static void omap_vout_platform_release(struct device *device)
+{
+ /* This is called when the reference count goes to zero */
+}
+
+static struct platform_device omap_v1out_dev = {
+ .name = V1OUT_NAME,
+ .id = 11,
+ /*.devid = OMAP_V1OUT_DEVID, */
+ /*.busid = OMAP_BUS_L3, */
+ .dev = {
+#ifdef CONFIG_DPM
+ .constraints = &omap_vout_constraints,
+#endif
+ .release = omap_vout_platform_release,
+ },
+};
+
+static struct platform_device omap_v2out_dev = {
+ .name = V2OUT_NAME,
+ .id = 12,
+ /*.devid = OMAP_V2OUT_DEVID, */
+ /*.busid = OMAP_BUS_L3, */
+ .dev = {
+#ifdef CONFIG_DPM
+ .constraints = &omap_vout_constraints,
+#endif
+ .release = omap_vout_platform_release,
+ },
+};
+
+static struct platform_driver omap_v1out_driver = {
+ .driver = {
+ .name = V1OUT_NAME,
+ },
+ /*.devid = OMAP_V1OUT_DEVID, */
+ /*.id = 11, */
+ /*.busid = OMAP_BUS_L3, */
+ /*.clocks = 0, */
+ .probe = omap_vout_probe,
+#ifdef CONFIG_PM
+ .suspend = omap_vout_suspend,
+ .resume = omap_vout_resume,
+#endif
+};
+
+static struct platform_driver omap_v2out_driver = {
+ .driver = {
+ .name = V2OUT_NAME,
+ },
+ /*.id = 12, */
+ /*.devid = OMAP_V2OUT_DEVID, */
+ /*.busid = OMAP_BUS_L3, */
+ /*.clocks = 0, */
+ .probe = omap_vout_probe,
+#ifdef CONFIG_PM
+ .suspend = omap_vout_suspend,
+ .resume = omap_vout_resume,
+#endif
+};
+
+void
+omap_vout_isr(void *arg, struct pt_regs *regs, unsigned int irqstatus)
+{
+ struct timeval timevalue;
+ unsigned int out_dev;
+ struct omap_vout_device *vout =
+ (struct omap_vout_device *) arg, *dest = NULL;
+ struct videobuf_dmabuf *dmabuf = NULL;
+ u32 addr, fid;
+
+ if (!vout->streaming)
+ return;
+
+ spin_lock(&vout->vbq_lock);
+ do_gettimeofday(&timevalue);
+ out_dev = omap_disp_get_output_dev(vout->vid);
+ if (out_dev == OMAP_OUTPUT_LCD) {
+ if (!(irqstatus & DISPC_IRQSTATUS_VSYNC))
+ return;
+ if (!vout->first_int && (vout->curFrm != vout->nextFrm)) {
+ vout->curFrm->ts = timevalue;
+ vout->curFrm->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->curFrm->done);
+ vout->curFrm = vout->nextFrm;
+ }
+ vout->first_int = 0;
+ if (list_empty(&vout->dma_queue)) {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ vout->nextFrm = list_entry(vout->dma_queue.next,
+ struct videobuf_buffer, queue);
+ list_del(&vout->nextFrm->queue);
+
+ vout->nextFrm->state = VIDEOBUF_ACTIVE;
+
+ addr = (unsigned long)
+ vout->queued_buf_addr[vout->nextFrm->i] +
+ vout->cropped_offset;
+ omap_disp_set_addr(vout->vid, addr, addr,
+ addr + vout->tv_field1_offset);
+ if (vout_linked != -1 && vout_linked != vout->vid) {
+ dmabuf = videobuf_to_dma(vout->nextFrm);
+ dest =
+ (vout_linked ==
+ OMAP_VIDEO1) ? saved_v1out : saved_v2out;
+ if (dest->rotation > -1)
+ addr = (unsigned long)
+ vout->queued_buf_addr[vout->nextFrm->
+ i] +
+ dest->cropped_offset;
+ else
+ addr =
+ dmabuf->bus_addr +
+ dest->cropped_offset;
+ omap_disp_set_addr(dest->vid, addr, addr,
+ addr + dest->tv_field1_offset);
+ }
+ } else {
+ if (vout->first_int) {
+ vout->first_int = 0;
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ if (irqstatus & DISPC_IRQSTATUS_EVSYNC_ODD)
+ fid = 1;
+ else if (irqstatus & DISPC_IRQSTATUS_EVSYNC_EVEN)
+ fid = 0;
+ else {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ vout->field_id ^= 1;
+ if (fid != vout->field_id) {
+ if (0 == fid)
+ vout->field_id = fid;
+
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ if (0 == fid) {
+ if (vout->curFrm == vout->nextFrm) {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ vout->curFrm->ts = timevalue;
+ vout->curFrm->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->curFrm->done);
+ vout->curFrm = vout->nextFrm;
+ } else if (1 == fid) {
+ if (list_empty(&vout->dma_queue) ||
+ (vout->curFrm != vout->nextFrm)) {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+
+ vout->nextFrm = list_entry(vout->dma_queue.next,
+ struct videobuf_buffer,
+ queue);
+
+ list_del(&vout->nextFrm->queue);
+
+ vout->nextFrm->state = VIDEOBUF_ACTIVE;
+
+ addr = (unsigned long)
+ vout->queued_buf_addr[vout->nextFrm->i] +
+ vout->cropped_offset;
+ omap_disp_set_addr(vout->vid, addr, addr,
+ addr + vout->tv_field1_offset);
+ if (vout_linked != -1 && vout_linked != vout->vid) {
+ dmabuf = videobuf_to_dma(vout->nextFrm);
+ dest = (vout_linked == OMAP_VIDEO1) ?
+ saved_v1out : saved_v2out;
+ if (dest->rotation > -1)
+ addr = (unsigned long)
+ vout->queued_buf_addr
+ [vout->nextFrm->i] +
+ dest->cropped_offset;
+ else
+ addr =
+ dmabuf->bus_addr +
+ dest->cropped_offset;
+ omap_disp_set_addr(dest->vid, addr, addr,
+ addr +
+ dest->
+ tv_field1_offset);
+ }
+ }
+ }
+ spin_unlock(&vout->vbq_lock);
+}
+
+static void omap_vout_cleanup_device(int vid)
+{
+ struct video_device *vfd;
+ struct omap_vout_device *vout;
+ int i, j, numbuffers;
+
+ vout = (vid == OMAP_VIDEO1) ? saved_v1out : saved_v2out;
+ if (!vout)
+ return;
+ vfd = vout->vfd;
+
+ if (vfd) {
+ if (vfd->minor == -1) {
+ /*
+ * 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);
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ release_mem_region(vout->sms_rot_phy[i][j],
+ VRF_SIZE);
+ }
+ }
+
+ /* Allocate memory for the buffes */
+ numbuffers =
+ (vid == OMAP_VIDEO1) ? video1_numbuffers : video2_numbuffers;
+ vout->buffer_size =
+ (vid == OMAP_VIDEO1) ? video1_bufsize : video2_bufsize;
+ for (i = 0; i < numbuffers; i++) {
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
+ vout->buf_phy_addr[i],
+ vout->buffer_size);
+ vout->buf_phy_addr[i] = 0;
+ vout->buf_virt_addr[i] = 0;
+ }
+
+ if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
+ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+ omap_free_dma(vout->vrfb_dma_tx.dma_ch);
+ }
+ platform_device_unregister((vid == OMAP_VIDEO1) ?
+ &omap_v1out_dev :
+ &omap_v2out_dev);
+ platform_driver_unregister((vid ==
+ OMAP_VIDEO1) ? &omap_v1out_driver :
+ &omap_v2out_driver);
+
+#ifdef CONFIG_DPM
+ if (vid == OMAP_VIDEO1) {
+ dpm_unregister_scale(&omap_v1out_pre_scale,
+ SCALE_PRECHANGE);
+ dpm_unregister_scale(&omap_v1out_post_scale,
+ SCALE_POSTCHANGE);
+ } else {
+ dpm_unregister_scale(&omap_v2out_pre_scale,
+ SCALE_PRECHANGE);
+ dpm_unregister_scale(&omap_v2out_pre_scale,
+ SCALE_POSTCHANGE);
+ }
+#endif
+
+ kfree(vout);
+
+ if (vid == OMAP_VIDEO1)
+ saved_v1out = NULL;
+ else
+ saved_v2out = NULL;
+}
+
+static struct omap_vout_device *omap_vout_init_device(int vid)
+{
+ int r, i, j;
+ struct omap_vout_device *vout;
+ struct video_device *vfd;
+ struct v4l2_pix_format *pix;
+ struct platform_driver *this_driver;
+ struct platform_device *this_dev;
+ u32 sms_start_addr, numbuffers;
+ int index_i, index_j, image_width, image_height;
+
+ vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
+ if (!vout) {
+ printk(KERN_ERR VOUT_NAME ": could not allocate memory\n");
+ return NULL;
+ }
+
+ memset(vout, 0, sizeof(struct omap_vout_device));
+ vout->vid = vid;
+ vout->rotation = rotation_support;
+
+ /* set the default pix */
+ pix = &vout->pix;
+ pix->width = QQVGA_WIDTH;
+ pix->height = QQVGA_HEIGHT;
+
+ pix->pixelformat = V4L2_PIX_FMT_RGB565;
+ pix->field = V4L2_FIELD_ANY;
+ pix->bytesperline = pix->width * 2;
+ pix->sizeimage = pix->bytesperline * pix->height;
+ pix->priv = 0;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ vout->bpp = RGB565_BPP;
+ vout->vrfb_bpp = 1;
+
+ /* get the screen parameters */
+ omap_disp_get_panel_size(omap_disp_get_output_dev(vout->vid),
+ &(vout->fbuf.fmt.width),
+ &(vout->fbuf.fmt.height));
+
+ /* set default crop and win */
+ omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
+
+ /* 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");
+ kfree(vout);
+ return NULL;
+ }
+ vfd->release = video_device_release;
+
+ strncpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
+ vfd->vfl_type = VID_TYPE_OVERLAY | VID_TYPE_CHROMAKEY;
+ /* need to register for a VID_HARDWARE_* ID in videodev.h */
+ vfd->fops = &omap_vout_fops;
+ video_set_drvdata(vfd, vout);
+ vfd->minor = -1;
+
+ sms_start_addr =
+ (vid ==
+ OMAP_VIDEO1) ? OMAP_VOUT_VIDEO1_SMS_START :
+ OMAP_VOUT_VIDEO2_SMS_START;
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ vout->sms_rot_phy[i][j] = sms_start_addr;
+ if (!request_mem_region(vout->sms_rot_phy[i][j],
+ VRF_SIZE, vfd->name)) {
+ printk(KERN_ERR
+ "Cannot reserve smsm IO %x\n",
+ vout->sms_rot_phy[i][j]);
+ index_i = i;
+ index_j = j;
+ goto rotation_free;
+ }
+ sms_start_addr += 0x1000000;
+ }
+ }
+ index_i = 4;
+ index_j = 0;
+
+ /* Allocate memory for the buffes */
+ numbuffers =
+ (vid == OMAP_VIDEO1) ? video1_numbuffers : video2_numbuffers;
+ vout->buffer_size =
+ (vid == OMAP_VIDEO1) ? video1_bufsize : video2_bufsize;
+ printk(KERN_INFO "Buffer Size = %d\n", vout->buffer_size);
+ for (i = 0; i < numbuffers; i++) {
+ vout->buf_virt_addr[i] =
+ omap_vout_alloc_buffer(vout->buffer_size,
+ (u32 *) &vout->
+ buf_phy_addr[i]);
+ if (!vout->buf_virt_addr[i]) {
+ numbuffers = i;
+ goto free_buffer_memory;
+ }
+ }
+
+ vout->suspended = 0;
+ init_waitqueue_head(&vout->suspend_wq);
+ init_MUTEX(&vout->lock);
+
+ if (video_register_device(vfd, VFL_TYPE_GRABBER, vid) < 0) {
+ printk(KERN_ERR VOUT_NAME ": could not register Video for \
+ Linux device\n");
+ vfd->minor = -1;
+ goto free_buffer_memory;
+ }
+
+ this_driver = (vid == OMAP_VIDEO1) ?
+ &omap_v1out_driver : &omap_v2out_driver;
+ this_dev =
+ (vid ==
+ OMAP_VIDEO1) ? &omap_v1out_dev : &omap_v2out_dev;
+ if (platform_driver_register(this_driver) != 0) {
+ printk(KERN_ERR VOUT_NAME ": could not register \
+ Video driver\n");
+ omap_vout_cleanup_device(vid);
+ return NULL;
+ }
+ if (platform_device_register(this_dev) != 0) {
+ printk(KERN_ERR VOUT_NAME ": could not register \
+ Video device\n");
+ omap_vout_cleanup_device(vid);
+ return NULL;
+ }
+ /* set driver specific data to use in power mgmt functions */
+ platform_set_drvdata(this_dev, vout);
+
+ if (vid == OMAP_VIDEO1) {
+ vout->vrfb_context[0] = 4;
+ vout->vrfb_context[1] = 5;
+ vout->vrfb_context[2] = 6;
+ vout->vrfb_context[3] = 7;
+ } else {
+ vout->vrfb_context[0] = 8;
+ vout->vrfb_context[1] = 9;
+ vout->vrfb_context[2] = 10;
+ vout->vrfb_context[3] = 11;
+ }
+ vout->cropped_offset = 0;
+
+#ifdef CONFIG_DPM
+ /* Scaling is enabled only when DPM is enabled */
+ if (vid == OMAP_VIDEO1) {
+ dpm_register_scale(&omap_v1out_pre_scale,
+ SCALE_PRECHANGE);
+ dpm_register_scale(&omap_v1out_post_scale,
+ SCALE_POSTCHANGE);
+ } else {
+ dpm_register_scale(&omap_v2out_pre_scale,
+ SCALE_PRECHANGE);
+ dpm_register_scale(&omap_v2out_post_scale,
+ SCALE_POSTCHANGE);
+ }
+#endif
+ /* 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
+ */
+ vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
+ vout->vrfb_dma_tx.dma_ch = -1;
+ vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
+ r = omap_request_dma(vout->vrfb_dma_tx.dev_id,
+ "VRFB DMA TX", omap_vout_vrfb_dma_tx_callback,
+ (void *) &vout->vrfb_dma_tx,
+ &vout->vrfb_dma_tx.dma_ch);
+ if (r < 0)
+ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+
+ init_waitqueue_head(&vout->vrfb_dma_tx.wait);
+
+ /*if rotation support */
+ printk(KERN_INFO VOUT_NAME ": registered device video%d [v4l2]\n",
+ vfd->minor);
+ return vout;
+
+free_buffer_memory:
+ for (i = 0; i < numbuffers; i++) {
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
+ vout->buf_phy_addr[i],
+ vout->buffer_size);
+ vout->buf_virt_addr[i] = 0;
+ vout->buf_phy_addr[i] = 0;
+ }
+
+rotation_free:
+ for (i = 0; i < index_i; i++) {
+ for (j = 0; j < 4; j++) {
+ release_mem_region(vout->sms_rot_phy[i][j],
+ VRF_SIZE);
+ }
+ }
+ for (j = 0; j < index_j; j++) {
+ release_mem_region(vout->sms_rot_phy[index_i][j],
+ VRF_SIZE);
+ }
+ video_device_release(vfd);
+ kfree(vout);
+ return NULL;
+}
+
+static int __init omap_vout_init(void)
+{
+ omap_disp_get_dss();
+ saved_v1out = omap_vout_init_device(OMAP_VIDEO1);
+ if (saved_v1out == NULL) {
+ omap_disp_put_dss();
+ return -ENODEV;
+ }
+ omap_disp_save_initstate(OMAP_DSS_DISPC_GENERIC);
+ omap_disp_save_initstate(OMAP_VIDEO1);
+
+ saved_v2out = omap_vout_init_device(OMAP_VIDEO2);
+ if (saved_v2out == NULL) {
+ omap_vout_cleanup_device(OMAP_VIDEO1);
+ omap_disp_put_dss();
+ return -ENODEV;
+ }
+ omap_disp_save_initstate(OMAP_DSS_DISPC_GENERIC);
+ omap_disp_save_initstate(OMAP_VIDEO2);
+ omap_disp_put_dss();
+
+ vout_linked = -1;
+ spin_lock_init(&vout_link_lock);
+ return 0;
+}
+
+static void omap_vout_cleanup(void)
+{
+ omap_disp_get_dss();
+ omap_vout_cleanup_device(OMAP_VIDEO1);
+ omap_vout_cleanup_device(OMAP_VIDEO2);
+ omap_disp_put_dss();
+}
+
+#ifndef MODULE
+/*
+ * omap_vout_setup - process command line options
+ * @options: string of options
+ *
+ * NOTE: This function is a __setup and __init function.
+ *
+ * Returns zero.
+ */
+int __init omap_vout_setup(char *options)
+{
+ char *this_opt;
+ int i;
+
+ if (!options || !*options)
+ return 0;
+
+ DPRINTK("Options \"%s\"\n", options);
+ i = strlen(VOUT_NAME);
+ if (!strncmp(options, VOUT_NAME, i) && options[i] == ':') {
+ this_opt = options + i + 1;
+ if (!this_opt || !*this_opt)
+ return 0;
+
+ if (!strncmp(this_opt, "rotation=", 9)) {
+ int deg = simple_strtoul(this_opt + 9, NULL, 0);
+ switch (deg) {
+ case 0:
+ case 90:
+ case 180:
+ case 270:
+ rotation_support =
+ (deg == 90) ? 270 : (deg ==
+ 270) ? 90 : deg;
+ break;
+ default:
+ rotation_support = -1;
+ break;
+ }
+ printk(KERN_INFO VOUT_NAME ": Rotation %s\n",
+ (rotation_support ==
+ -1) ? "none (supported: \"rotation=\
+ [-1|0|90|180|270]\")" : this_opt + 9);
+ } else
+ printk(KERN_INFO VOUT_NAME ": Invalid parameter \
+ \"%s\" " "(supported: \
+ \"rotation = [-1|0|90|180|270]\")\n", this_opt);
+ return 0;
+ }
+
+ /*
+ * If we get here no fb was specified.
+ * We consider the argument to be a global video mode option.
+ */
+ /* TODO - remove when FB is configured */
+ return 0;
+}
+
+__setup("videoout=", omap_vout_setup);
+#endif
+
+MODULE_AUTHOR("Texas Instruments.");
+MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
+MODULE_LICENSE("GPL");
+/* TODO -- Enabling it results in build erros, why?? */
+/*
+module_param(render_mem, uint, \
+ VID_MAX_WIDTH * VID_MAX_HEIGHT * 4 * MAX_ALLOWED_VIDBUFFERS);
+MODULE_PARM_DESC (render_mem,
+ "Maximum rendering memory size (default 1.2MB)");
+*/
+/*module_init (omap_vout_init);*/
+late_initcall(omap_vout_init);
+module_exit(omap_vout_cleanup);
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
new file mode 100644
index 0000000..6506ab1
--- /dev/null
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -0,0 +1,196 @@
+/*
+ * drivers/media/video/omap/omap_voutdef.h
+ *
+ * Copyright (C) 2005 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 <linux/omap_vout.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
+
+/*
+ * This structure is used to store the DMA transfer parameters
+ * for VRFB hidden buffer
+ */
+struct vid_vrfb_dma {
+ int dev_id;
+ int dma_ch;
+ int req_status;
+ int tx_status;
+ wait_queue_head_t wait;
+};
+
+/* per-device data structure */
+struct omap_vout_device {
+ struct device dev;
+ struct video_device *vfd;
+ int vid;
+ int opened;
+
+ /* Power management suspend lockout stuff */
+ int suspended;
+ wait_queue_head_t suspend_wq;
+
+#ifdef DEBUG_ALLOW_WRITE
+ unsigned long framebuffer_base;
+ unsigned long framebuffer_base_phys;
+ unsigned long framebuffer_size;
+#endif
+
+ /* we don't allow to change image fmt/size once buffer has
+ * been allocated
+ */
+ int buffer_allocated;
+ /* allow to reuse previosuly allocated buffer which is big enough */
+ int buffer_size;
+ /* keep buffer info accross opens */
+ unsigned long buf_virt_addr[VIDEO_MAX_FRAME];
+ unsigned long buf_phy_addr[VIDEO_MAX_FRAME];
+ unsigned int buf_memory_type;
+
+ /* we don't allow to request new buffer when old buffers are
+ * still mmaped
+ */
+ int mmap_count;
+
+ spinlock_t vbq_lock; /* spinlock for videobuf queues */
+ unsigned long field_count; /* field counter for videobuf_buffer */
+
+ /* non-NULL means streaming is in progress. */
+ struct omap_vout_fh *streaming;
+
+ 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 semaphore lock;
+
+ /* rotation variablse goes here */
+ unsigned long sms_rot_virt[4]; /* virtual addresss for four angles */
+ /* four angles */
+ dma_addr_t sms_rot_phy[4][4];
+
+ int mirror;
+ int rotation;
+
+ int bpp; /* bytes per pixel */
+ int vrfb_bpp; /* bytes per pixel with respect to VRFB */
+ unsigned int tile_aligned_psize;
+
+ struct vid_vrfb_dma vrfb_dma_tx;
+ unsigned int smsshado_phy_addr[4];
+ unsigned int smsshado_virt_addr[4];
+ unsigned int vrfb_context[4];
+ unsigned int smsshado_size;
+ unsigned char pos;
+
+ int flicker_filter;
+ int ps, vr_ps, line_length, first_int, field_id;
+ enum v4l2_memory memory;
+ struct videobuf_buffer *curFrm, *nextFrm;
+ struct list_head dma_queue;
+ u8 *queued_buf_addr[32];
+ u32 cropped_offset;
+ s32 tv_field1_offset;
+
+};
+
+/* per-filehandle data structure */
+struct omap_vout_fh {
+ struct omap_vout_device *vout;
+ enum v4l2_buf_type type;
+ struct videobuf_queue vbq;
+ int io_allowed;
+};
+
+#ifdef CONFIG_ARCH_OMAP34XX
+
+/*******************************************************************/
+/* auxiliary display buffer type */
+struct aux_disp_buf {
+ int index;
+ void *data;
+};
+
+struct aux_disp_queue_hdr {
+ int queue_depth;
+ int queued;
+ int dequeued;
+ int processed;
+ struct aux_disp_buf *aux_disp_queue;
+};
+
+/* auxiliary device data structure */
+struct omap3_aux_disp_device {
+ struct device dev;
+ struct video_device *vfd;
+ int opened;
+
+ /* Power management suspend lockout stuff */
+ int suspended;
+ wait_queue_head_t suspend_wq;
+
+#ifdef DEBUG_ALLOW_WRITE
+ unsigned long framebuffer_base;
+ unsigned long framebuffer_base_phys;
+ unsigned long framebuffer_size;
+#endif
+
+ /* we don't allow to change image fmt/size once buffer
+ * has been allocated
+ */
+ int buffer_allocated;
+ /* allow to reuse previosuly allocated buffer which is big enough */
+ int buffer_size;
+ /* keep buffer info accross opens */
+ unsigned long buf_virt_addr[VIDEO_MAX_FRAME];
+ unsigned long buf_phy_addr[VIDEO_MAX_FRAME];
+ unsigned int buf_memory_type;
+
+ /* we don't allow to request new buffer when old buffers
+ * are still mmaped
+ */
+ int mmap_count;
+
+ spinlock_t vbq_lock; /* spinlock for videobuf queues */
+ unsigned long field_count; /* field counter for videobuf_buffer */
+
+ /* non-NULL means streaming is in progress. */
+ struct omap_vout_fh *streaming;
+
+ struct v4l2_pix_format pix;
+ struct v4l2_rect crop;
+ struct v4l2_window win;
+ struct v4l2_framebuffer fbuf;
+
+ int mirror;
+ int rotation;
+
+ int bpp; /* bytes per pixel */
+ struct aux_disp_queue_hdr aux_queue_hdr;
+};
+
+/* per-filehandle data structure */
+struct omap3_aux_disp_fh {
+ struct omap3_aux_disp_device *vout;
+ enum v4l2_buf_type type;
+ struct videobuf_queue vbq;
+};
+#endif
+
+#endif /* ifndef OMAP_VOUTDEF_H */
diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c
new file mode 100644
index 0000000..bb7e7dd
--- /dev/null
+++ b/drivers/media/video/omap/omap_voutlib.c
@@ -0,0 +1,283 @@
+/*
+ * drivers/media/video/omap/omap_voutlib.c
+ *
+ * Copyright (C) 2005 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) 2004 Texas Instruments.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/videodev2.h>
+#include <linux/semaphore.h>
+
+#include <mach/omap-dss.h>
+
+/* 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 succesful, 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*/V4L2_FIELD_ANY;
+ 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 succesful, 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 limitations */
+ if ((crop->height/win->w.height) >= 2) {
+ /* The maximum vertical downsizing ratio is 2:1 */
+ crop->height = win->w.height * 2;
+ }
+ if ((crop->width/win->w.width) >= 2) {
+ /* The maximum horizontal downsizing ratio is 2:1 */
+ 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;
+ }
+ 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 succesful, 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 (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 * crop->height) / win->w.height;
+ if (vresize > 2048)
+ vresize = 2048;
+ else if (vresize == 0)
+ vresize = 1;
+ 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 * crop->width) / win->w.width;
+ if (hresize > 2048)
+ hresize = 2048;
+ else if (hresize == 0)
+ hresize = 1;
+ 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;
+ }
+
+ /* Check for resizing constraints */
+ if ((try_crop.height/win->w.height) >= 2) {
+ /* The maximum vertical downsizing ratio is 2:1 */
+ try_crop.height = win->w.height * 2;
+ }
+ if ((try_crop.width/win->w.width) >= 2) {
+ /* The maximum horizontal downsizing ratio is 2:1 */
+ 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;
+ }
+
+ /* 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);
+
+MODULE_AUTHOR("Texas Instruments.");
+MODULE_DESCRIPTION("OMAP Video library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h
new file mode 100644
index 0000000..3655630
--- /dev/null
+++ b/drivers/media/video/omap/omap_voutlib.h
@@ -0,0 +1,34 @@
+/*
+ * drivers/media/video/omap/omap_voutlib.h
+ *
+ * Copyright (C) 2005 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
+
+extern void omap_vout_default_crop(struct v4l2_pix_format *pix,
+ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
+
+extern 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);
+
+extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+ struct v4l2_window *new_win);
+
+extern int omap_vout_new_window(struct v4l2_rect *crop,
+ struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
+ struct v4l2_window *new_win);
+
+extern void omap_vout_new_format(struct v4l2_pix_format *pix,
+ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
+ struct v4l2_window *win);
+#endif /* #ifndef OMAP_LIB_H */
+
diff --git a/include/linux/omap_vout.h b/include/linux/omap_vout.h
new file mode 100644
index 0000000..bf08c76
--- /dev/null
+++ b/include/linux/omap_vout.h
@@ -0,0 +1,60 @@
+/*
+ * include/linux/omap_vout.h
+ *
+ * Copyright (C) 2005 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_H
+#define OMAP_VOUT_H
+
+/* This is for user apps */
+#define OMAP_VOUT_OUTPUT_LCD 4
+#define OMAP_VOUT_OUTPUT_TV 5
+#define OMAP_VOUT_GFX_DESTINATION 100
+#define OMAP_VOUT_VIDEO_SOURCE 101
+
+struct omap_vout_colorkey {
+ unsigned int output_dev;
+ unsigned int key_type;
+ unsigned int key_val;
+};
+
+struct omap_vout_bgcolor {
+ unsigned int color;
+ unsigned int output_dev;
+};
+
+struct omap_vout_colconv {
+ short int RY, RCr, RCb;
+ short int GY, GCr, GCb;
+ short int BY, BCr, BCb;
+};
+
+/* non-standard V4L2 ioctls that are specific to OMAP */
+#define VIDIOC_S_OMAP_MIRROR _IOW('V', 1, int)
+#define VIDIOC_G_OMAP_MIRROR _IOR('V', 2, int)
+#define VIDIOC_S_OMAP_ROTATION _IOW('V', 3, int)
+#define VIDIOC_G_OMAP_ROTATION _IOR('V', 4, int)
+#define VIDIOC_S_OMAP_LINK _IOW('V', 5, int)
+#define VIDIOC_G_OMAP_LINK _IOR('V', 6, int)
+#define VIDIOC_S_OMAP_COLORKEY _IOW('V', 7,\
+ struct omap_vout_colorkey)
+#define VIDIOC_G_OMAP_COLORKEY _IOW('V', 8,\
+ struct omap_vout_colorkey)
+#define VIDIOC_S_OMAP_BGCOLOR _IOW('V', 9,\
+ struct omap_vout_bgcolor)
+#define VIDIOC_G_OMAP_BGCOLOR _IOW('V', 10,\
+ struct omap_vout_bgcolor)
+#define VIDIOC_OMAP_COLORKEY_ENABLE _IOW('V', 11, int)
+#define VIDIOC_OMAP_COLORKEY_DISABLE _IOW('V', 12, int)
+#define VIDIOC_S_OMAP_DEFCOLORCONV _IOW('V', 13, int)
+#define VIDIOC_S_OMAP_COLORCONV _IOW('V', 14,\
+ struct omap_vout_colconv)
+#define VIDIOC_G_OMAP_COLORCONV _IOR('V', 15,\
+ struct omap_vout_colconv)
+
+#endif /* #ifndef OMAP_VOUT_H */
--
1.5.6
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-09-17 15:05 [PATCH] OMAP 2/3 V4L2 display driver on video planes Hardik Shah
@ 2008-09-17 15:30 ` Sakari Ailus
2008-09-17 15:42 ` Hiremath, Vaibhav
2008-10-03 14:33 ` Hans Verkuil
1 sibling, 1 reply; 15+ messages in thread
From: Sakari Ailus @ 2008-09-17 15:30 UTC (permalink / raw)
To: ext Hardik Shah; +Cc: linux-omap, video4linux-list, linux-fbdev-devel
Hi, Hardik!
ext Hardik Shah wrote:
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 2703c66..e899dd2 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -762,8 +762,6 @@ source "drivers/media/video/au0828/Kconfig"
>
> source "drivers/media/video/ivtv/Kconfig"
>
> -source drivers/media/video/omap/Kconfig
> -
> source "drivers/media/video/cx18/Kconfig"
>
> config VIDEO_M32R_AR
> @@ -802,6 +800,14 @@ config VIDEO_OMAP2
> ---help---
> Driver for an OMAP 2 camera controller.
>
> +config VIDEO_OMAP3
This is the same configuration option as we are using for the OMAP 3
camera driver at the moment.
Could you, for example, call this VIDEO_OMAP3_VIDEOOUT?
CONFIG_VIDEO_OMAP2 enables the OMAP 2 camera driver.
> diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> index 3e580e8..10f879c 100644
> --- a/drivers/media/video/Makefile
> +++ b/drivers/media/video/Makefile
> @@ -107,6 +107,8 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
> obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
>
> obj-$(CONFIG_VIDEO_OMAP2) += omap24xxcam.o omap24xxcam-dma.o
> +obj-$(CONFIG_VIDEO_OMAP3) += omap/
It's just two C source code files --- how about putting them into the
parent directory? The omap directory has just one driver in it, the OMAP
1 camera driver. I think at some point it was intended to be moved to
the parent directory although this hasn't happened.
Best regards,
--
Sakari Ailus
sakari.ailus@nokia.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-09-17 15:30 ` Sakari Ailus
@ 2008-09-17 15:42 ` Hiremath, Vaibhav
0 siblings, 0 replies; 15+ messages in thread
From: Hiremath, Vaibhav @ 2008-09-17 15:42 UTC (permalink / raw)
To: Sakari Ailus, Shah, Hardik
Cc: video4linux-list@redhat.com, linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net
Hi Ailus,
Thanks,
Vaibhav Hiremath
Senior Software Engg.
Platform Support Products
Texas Instruments Inc
Ph: +91-80-25099927
> -----Original Message-----
> From: video4linux-list-bounces@redhat.com [mailto:video4linux-list-bounces@redhat.com] On Behalf Of
> Sakari Ailus
> Sent: Wednesday, September 17, 2008 9:00 PM
> To: Shah, Hardik
> Cc: video4linux-list@redhat.com; linux-omap@vger.kernel.org; linux-fbdev-devel@lists.sourceforge.net
> Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
>
> Hi, Hardik!
>
> ext Hardik Shah wrote:
> > diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> > index 2703c66..e899dd2 100644
> > --- a/drivers/media/video/Kconfig
> > +++ b/drivers/media/video/Kconfig
> > @@ -762,8 +762,6 @@ source "drivers/media/video/au0828/Kconfig"
> >
> > source "drivers/media/video/ivtv/Kconfig"
> >
> > -source drivers/media/video/omap/Kconfig
> > -
> > source "drivers/media/video/cx18/Kconfig"
> >
> > config VIDEO_M32R_AR
> > @@ -802,6 +800,14 @@ config VIDEO_OMAP2
> > ---help---
> > Driver for an OMAP 2 camera controller.
> >
> > +config VIDEO_OMAP3
>
> This is the same configuration option as we are using for the OMAP 3
> camera driver at the moment.
>
> Could you, for example, call this VIDEO_OMAP3_VIDEOOUT?
>
> CONFIG_VIDEO_OMAP2 enables the OMAP 2 camera driver.
>
I am aware of camera config options, but since now V4l started supporting
output devices (like display) widely, we should have some meaningful
config options here. I propose something following -
config VIDEO_OMAP3
bool "OMAP2/OMAP3 V4L2 drivers"
depends on VIDEO_DEV && (ARCH_OMAP24XX || ARCH_OMAP34XX)
default y
help
V4L2 DSS driver support for OMAP2/3 based boards.
source "drivers/media/video/omap/Kconfig"
config VIDEO_OMAP3_CAMERA
tristate "OMAP 3 Camera support"
select VIDEOBUF_GEN
select VIDEOBUF_DMA_SG
select VIDEO_OMAP3_ISP
depends on VIDEO_V4L2 && ARCH_OMAP34XX && VIDEO_OMAP3
default VIDEO_OMAP3
---help---
Driver for an OMAP 3 camera controller.
source "drivers/media/video/isp/Kconfig"
> > diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> > index 3e580e8..10f879c 100644
> > --- a/drivers/media/video/Makefile
> > +++ b/drivers/media/video/Makefile
> > @@ -107,6 +107,8 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
> > obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
> >
> > obj-$(CONFIG_VIDEO_OMAP2) += omap24xxcam.o omap24xxcam-dma.o
> > +obj-$(CONFIG_VIDEO_OMAP3) += omap/
>
> It's just two C source code files --- how about putting them into the
> parent directory? The omap directory has just one driver in it, the OMAP
> 1 camera driver. I think at some point it was intended to be moved to
> the parent directory although this hasn't happened.
>
But with addition of V4L2 display patch the number of files got increased, now we
have 4 files for display driver. I would prefer other way, move OMAP specific files
to omap directory.
> Best regards,
>
> --
> Sakari Ailus
> sakari.ailus@nokia.com
>
> --
> video4linux-list mailing list
> Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
> https://www.redhat.com/mailman/listinfo/video4linux-list
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-09-17 15:05 [PATCH] OMAP 2/3 V4L2 display driver on video planes Hardik Shah
2008-09-17 15:30 ` Sakari Ailus
@ 2008-10-03 14:33 ` Hans Verkuil
2008-10-03 14:40 ` Shah, Hardik
1 sibling, 1 reply; 15+ messages in thread
From: Hans Verkuil @ 2008-10-03 14:33 UTC (permalink / raw)
To: video4linux-list; +Cc: Hardik Shah, linux-omap, linux-fbdev-devel
On Wednesday 17 September 2008 17:05:42 Hardik Shah wrote:
> From: Vaibhav Hiremath <hvaibhav@ti.com>
>
> OMAP 2/3 V4L2 display driver sits on top of DSS library
> and uses TV overlay and 2 video pipelines (video1 and video2)
> to display image on TV. It exposes 2 V4L2 nodes for user
> interface.
> It supports standard V4L2 ioctls.
>
> Signed-off-by: Brijesh Jadav <brijesh.j@ti.com>
> Hari Nagalla <hnagalla@ti.com>
> Hardik Shah <hardik.shah@ti.com>
> Manju Hadli <mrh@ti.com>
> R Sivaraj <sivaraj@ti.com>
> Vaibhav Hiremath <hvaibhav@ti.com>
I've taken a quick look and I have a two main comments:
1) Please use video_ioctl2 rather than setting up your own ioctl
callback. New drivers should use it.
2) Can you describe what the non-standard v4l2 ioctls are used for? I
suspect that some of these can be done differently. Something like a
chromakey is already available in v4l2 (through VIDIOC_G/S_FBUF and
VIDIOC_G/S_FMT), things like mirror is available as a control, and
rotation should perhaps be a control as well. Ditto for background
color. These are just ideas, it depends on how it is used exactly.
3) Some of the lines are broken up rather badly probably to respect the
80 column maximum. Note that the 80 column maximum is a recommendation,
and that readability is more important. So IMHO it's better to have a
slightly longer line and break it up at a more logical place. However,
switching to video_ioctl2 will automatically reduce the indentation, so
this might not be that much of an issue anymore.
It is possible to setup a mercurial repository on linuxtv.org? I thought
that Manju has an account by now. This is useful as well for all the
other omap camera patches. I've seen omap patches popping up all over
the place for the past six months (if not longer) but it needs to be a
bit more organized if you want it to be merged. Setting up v4l-dvb
repositories containing the new patches is a good way of streamlining
the process.
Obviously the process is more complicated for you since the omap stuff
relies on various subsystems and platform code. Perhaps someone within
TI should be coordinating this?
Regards,
Hans
> ---
> drivers/media/video/Kconfig | 10 +-
> drivers/media/video/Makefile | 2 +
> drivers/media/video/omap/Kconfig | 12 +
> drivers/media/video/omap/Makefile | 2 +
> drivers/media/video/omap/omap_vout.c | 3524
> +++++++++++++++++++++++++++++++
> drivers/media/video/omap/omap_voutdef.h | 196 ++
> drivers/media/video/omap/omap_voutlib.c | 283 +++
> drivers/media/video/omap/omap_voutlib.h | 34 +
> include/linux/omap_vout.h | 60 +
> 9 files changed, 4121 insertions(+), 2 deletions(-)
> create mode 100644 drivers/media/video/omap/omap_vout.c
> create mode 100644 drivers/media/video/omap/omap_voutdef.h
> create mode 100644 drivers/media/video/omap/omap_voutlib.c
> create mode 100644 drivers/media/video/omap/omap_voutlib.h
> create mode 100644 include/linux/omap_vout.h
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-03 14:33 ` Hans Verkuil
@ 2008-10-03 14:40 ` Shah, Hardik
2008-10-05 11:19 ` Mauro Carvalho Chehab
0 siblings, 1 reply; 15+ messages in thread
From: Shah, Hardik @ 2008-10-03 14:40 UTC (permalink / raw)
To: Hans Verkuil, video4linux-list@redhat.com
Cc: linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net
> -----Original Message-----
> From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
> Sent: Friday, October 03, 2008 8:04 PM
> To: video4linux-list@redhat.com
> Cc: Shah, Hardik; linux-omap@vger.kernel.org; linux-fbdev-devel@lists.sourceforge.net
> Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
>
> On Wednesday 17 September 2008 17:05:42 Hardik Shah wrote:
> > From: Vaibhav Hiremath <hvaibhav@ti.com>
> >
> > OMAP 2/3 V4L2 display driver sits on top of DSS library
> > and uses TV overlay and 2 video pipelines (video1 and video2)
> > to display image on TV. It exposes 2 V4L2 nodes for user
> > interface.
> > It supports standard V4L2 ioctls.
> >
> > Signed-off-by: Brijesh Jadav <brijesh.j@ti.com>
> > Hari Nagalla <hnagalla@ti.com>
> > Hardik Shah <hardik.shah@ti.com>
> > Manju Hadli <mrh@ti.com>
> > R Sivaraj <sivaraj@ti.com>
> > Vaibhav Hiremath <hvaibhav@ti.com>
>
> I've taken a quick look and I have a two main comments:
>
> 1) Please use video_ioctl2 rather than setting up your own ioctl
> callback. New drivers should use it.
>
> 2) Can you describe what the non-standard v4l2 ioctls are used for? I
> suspect that some of these can be done differently. Something like a
> chromakey is already available in v4l2 (through VIDIOC_G/S_FBUF and
> VIDIOC_G/S_FMT), things like mirror is available as a control, and
> rotation should perhaps be a control as well. Ditto for background
> color. These are just ideas, it depends on how it is used exactly.
[Shah, Hardik] Hans I will revisit the code and will provide you with the sufficient information.
>
> 3) Some of the lines are broken up rather badly probably to respect the
> 80 column maximum. Note that the 80 column maximum is a recommendation,
> and that readability is more important. So IMHO it's better to have a
> slightly longer line and break it up at a more logical place. However,
> switching to video_ioctl2 will automatically reduce the indentation, so
> this might not be that much of an issue anymore.
[Shah, Hardik] 80 column was implemented to make the checkpatch pass. Point noted and will take care of this.
>
> It is possible to setup a mercurial repository on linuxtv.org? I thought
> that Manju has an account by now. This is useful as well for all the
> other omap camera patches. I've seen omap patches popping up all over
> the place for the past six months (if not longer) but it needs to be a
> bit more organized if you want it to be merged. Setting up v4l-dvb
> repositories containing the new patches is a good way of streamlining
> the process.
>
> Obviously the process is more complicated for you since the omap stuff
> relies on various subsystems and platform code. Perhaps someone within
> TI should be coordinating this?
[Shah, Hardik] we are in process of coordinating this.
>
> Regards,
>
> Hans
>
> > ---
> > drivers/media/video/Kconfig | 10 +-
> > drivers/media/video/Makefile | 2 +
> > drivers/media/video/omap/Kconfig | 12 +
> > drivers/media/video/omap/Makefile | 2 +
> > drivers/media/video/omap/omap_vout.c | 3524
> > +++++++++++++++++++++++++++++++
> > drivers/media/video/omap/omap_voutdef.h | 196 ++
> > drivers/media/video/omap/omap_voutlib.c | 283 +++
> > drivers/media/video/omap/omap_voutlib.h | 34 +
> > include/linux/omap_vout.h | 60 +
> > 9 files changed, 4121 insertions(+), 2 deletions(-)
> > create mode 100644 drivers/media/video/omap/omap_vout.c
> > create mode 100644 drivers/media/video/omap/omap_voutdef.h
> > create mode 100644 drivers/media/video/omap/omap_voutlib.c
> > create mode 100644 drivers/media/video/omap/omap_voutlib.h
> > create mode 100644 include/linux/omap_vout.h
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-03 14:40 ` Shah, Hardik
@ 2008-10-05 11:19 ` Mauro Carvalho Chehab
2008-10-05 11:57 ` Robert William Fuller
2008-10-06 6:06 ` Shah, Hardik
0 siblings, 2 replies; 15+ messages in thread
From: Mauro Carvalho Chehab @ 2008-10-05 11:19 UTC (permalink / raw)
To: Shah, Hardik
Cc: Hans Verkuil, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net
On Fri, 3 Oct 2008 20:10:36 +0530
"Shah, Hardik" <hardik.shah@ti.com> wrote:
> > 2) Can you describe what the non-standard v4l2 ioctls are used for? I
> > suspect that some of these can be done differently. Something like a
> > chromakey is already available in v4l2 (through VIDIOC_G/S_FBUF and
> > VIDIOC_G/S_FMT), things like mirror is available as a control, and
> > rotation should perhaps be a control as well. Ditto for background
> > color. These are just ideas, it depends on how it is used exactly.
> [Shah, Hardik] Hans I will revisit the code and will provide you with the sufficient information.
I don't like the idea of having private ioctls. This generally means that only
a very restricted subset of userspace apps that are aware of the that API will
work. This is really bad.
So, I prefer to discuss the need for newer ioctls and add it into the standard
whenever make some sense (ok, maybe you might have some ioctls that are really
very specific for your app and that won't break userspace apps - I've acked
with 2 private ioctls on uvc driver in the past due to that).
> > 3) Some of the lines are broken up rather badly probably to respect the
> > 80 column maximum. Note that the 80 column maximum is a recommendation,
> > and that readability is more important. So IMHO it's better to have a
> > slightly longer line and break it up at a more logical place. However,
> > switching to video_ioctl2 will automatically reduce the indentation, so
> > this might not be that much of an issue anymore.
> [Shah, Hardik] 80 column was implemented to make the checkpatch pass. Point noted and will take care of this.
The 80 column rule isn't there for nothing.
It is a sort of checking if some common bad practices aren't used inside the
drivers, like having lots of indentation levels inside the functions, or long
("Pascal like") names for vars.
So, if you are having several points where you're violating the rule, probably
your code is very complex or you are using long names instead of short ones. On
the fisrt case, try to break the complex stuff into smaller and simpler static
functions. The compiler will deal with those functions like inline, so this
won't cost cpu cycles, but it will make easier for people to understand what
you're doing.
> > It is possible to setup a mercurial repository on linuxtv.org? I thought
> > that Manju has an account by now.
I don't remember if I created an account for Manju. If not, please ping me. I
prefer to not setup an account for every single developer, since LinuxTV
machine is not meant to be a host server.
Perhaps the better would be for you to have one public machine where you all
can work and merge your work. I'm OK on pulling and seeing patches outside LinuxTV.
> > This is useful as well for all the
> > other omap camera patches. I've seen omap patches popping up all over
> > the place for the past six months (if not longer) but it needs to be a
> > bit more organized if you want it to be merged. Setting up v4l-dvb
> > repositories containing the new patches is a good way of streamlining
> > the process.
> >
> > Obviously the process is more complicated for you since the omap stuff
> > relies on various subsystems and platform code. Perhaps someone within
> > TI should be coordinating this?
> [Shah, Hardik] we are in process of coordinating this.
One option in the future is to base your work on a git tree. I've changed a lot
the proccess of submitting patches upstream, to avoid having to rebase my tree
(Yet, I had to do two rebases during 2.6.27 cycle). If I can keep my tree
without rebase, the developers may rely on it and start sending me git pull
requests also. Let's see if I can do this for 2.6.28.
I think we should start discussing using git trees as the reference for
v4l/dvb development, and start moving developers tree to git. This would solve
the issues with complex projects like OMAP, where you need to touch not only on
V4L/DVB subsystem.
This topic deserves some more discussion,
Cheers,
Mauro.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-05 11:19 ` Mauro Carvalho Chehab
@ 2008-10-05 11:57 ` Robert William Fuller
2008-10-05 12:05 ` Mauro Carvalho Chehab
2008-10-07 21:48 ` [Linux-fbdev-devel] " Krzysztof Helt
2008-10-06 6:06 ` Shah, Hardik
1 sibling, 2 replies; 15+ messages in thread
From: Robert William Fuller @ 2008-10-05 11:57 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Shah, Hardik, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net
Mauro Carvalho Chehab wrote:
> On Fri, 3 Oct 2008 20:10:36 +0530
> "Shah, Hardik" <hardik.shah@ti.com> wrote:
>>> 3) Some of the lines are broken up rather badly probably to respect the
>>> 80 column maximum. Note that the 80 column maximum is a recommendation,
>>> and that readability is more important. So IMHO it's better to have a
>>> slightly longer line and break it up at a more logical place. However,
>>> switching to video_ioctl2 will automatically reduce the indentation, so
>>> this might not be that much of an issue anymore.
>> [Shah, Hardik] 80 column was implemented to make the checkpatch pass. Point noted and will take care of this.
>
> The 80 column rule isn't there for nothing.
The 80 column rule is retarded. None of this code needs to fit on punch
cards, nor is it COBOL. There are legitimate reasons to have lines
longer than 80 columns. No matter how simple a program is, it is likely
to have an expression that is longer than 80 characters. Most people's
displays are wider than 80 columns these days. Vertical real estate is
at a greater premium than horizontal real estate these days with wider
aspect ratio monitors, which better approximate the human field of
vision. Why make people scan more than one line for a single expression?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-05 11:57 ` Robert William Fuller
@ 2008-10-05 12:05 ` Mauro Carvalho Chehab
2008-10-07 21:48 ` [Linux-fbdev-devel] " Krzysztof Helt
1 sibling, 0 replies; 15+ messages in thread
From: Mauro Carvalho Chehab @ 2008-10-05 12:05 UTC (permalink / raw)
To: Robert William Fuller
Cc: Shah, Hardik, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net
On Sun, 05 Oct 2008 07:57:20 -0400
Robert William Fuller <hydrologiccycle@gmail.com> wrote:
> > The 80 column rule isn't there for nothing.
> There are legitimate reasons to have lines longer than 80 columns.
True. That's why this is a warning.
Cheers,
Mauro.
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-05 11:19 ` Mauro Carvalho Chehab
2008-10-05 11:57 ` Robert William Fuller
@ 2008-10-06 6:06 ` Shah, Hardik
2008-10-06 6:29 ` Hans Verkuil
1 sibling, 1 reply; 15+ messages in thread
From: Shah, Hardik @ 2008-10-06 6:06 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Hans Verkuil, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net, Hadli, Manjunath
Hi,
> -----Original Message-----
> From: Mauro Carvalho Chehab [mailto:mchehab@infradead.org]
> Sent: Sunday, October 05, 2008 4:50 PM
> To: Shah, Hardik
> Cc: Hans Verkuil; video4linux-list@redhat.com; linux-omap@vger.kernel.org; linux-fbdev-
> devel@lists.sourceforge.net
> Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
>
> On Fri, 3 Oct 2008 20:10:36 +0530
> "Shah, Hardik" <hardik.shah@ti.com> wrote:
>
>
> I don't like the idea of having private ioctls. This generally means that only
> a very restricted subset of userspace apps that are aware of the that API will
> work. This is really bad.
>
> So, I prefer to discuss the need for newer ioctls and add it into the standard
> whenever make some sense (ok, maybe you might have some ioctls that are really
> very specific for your app and that won't break userspace apps - I've acked
> with 2 private ioctls on uvc driver in the past due to that).
>
[Shah, Hardik] Following are the custom IOCTLs used in the V4L2 display driver of DSS.
1. VIDIOC_S/G_OMAP2_MIRROR: This ioctl is used to enable the mirroring of the image. Hardware supports mirroring. As pointed out by Hans it will be better to move it to VIDIOC_S_CTRL ioctl. we can add the new control id for the mirroring.
2. VIDIOC_S/G_OMAP2_ROTATION: Rotation is used to enable the rotation of the image. This also can be moved to the VIDIOC_S_CTRL ioctl. Need to add new control id for the rotation also.
3. VIDIOC_S/G_OMAP2_LINK: This feature is software provided. OMAP DSS is having two video pipelines. Using this feature user can link the two video pipelines. This means the streaming of the video on one pipeline will be linked to the other pipeline with the same parameters as the original pipeline. Same image can be streamed on both the pipelines, one of the pipeline's output going to TV and other one to LCD. I believe this feature is very specific to OMAP, and should remain as the custom ioctl.
4. VIDIOC_S/G_OMAP2_COLORKEY: Color keying allows the pixels with the defined color on the video pipelines to be replaced with the pixels on the graphics pipelines. I believe similar feature must be available on almost all next generation of video hardware. We can add new ioctl for this feature in V4L2 framework. I think VIDIOC_S_FBUF ioctl is used for setting up the buffer parameters on per buffer basis. So IMHO this ioctl is not a natural fit for the above functionality. Please provide your comments on same.
5. VIDIOC_S/G_OMAP2_BGCOLOR: This ioctl is used to set the Background color on either TV or LCD. It takes two inputs, first is the output device second is the color to be set. I think this can be added to the standard ioctl list but is it ok to have the output device as one of the parameters in the input structure? Instead we can set the background color for the current output.
6. VIDIOC_OMAP2_COLORKEY_ENABLE/DISABLE. This ioctl is used to enable or the disable the color keying feature described above. This can be added as the one of the control using VIDIOC_S_CTRL ioctl.
7. VIDIOC_S/G_OMAP2_COLORCONV: This is a hardware feature. Video pipelines of the DSS are capable of getting the buffer in the YUV/UYVY format. But internally DSS operates on RGB format. So hardware has a capability to convert the YUV format to RGB format. This is done using the color conversion matrix in the hardware. It accepts the structure as input which has 9 unsigned short variables representing the coefficients for color conversion. I think this feature will also be present in many new devices. So we can have the standard ioctl for this.
8. VIDIOC_S_OMAP2_DEFCOLORCONV: This ioctl just programs the default color conversion matrix defined by the driver. This we can have as one of the controls using VIDIOC_S_CTRL ioctl.
Please let me know your view/thoughts on above custom ioctls added in the driver.
>
> So, if you are having several points where you're violating the rule, probably
> your code is very complex or you are using long names instead of short ones. On
> the fisrt case, try to break the complex stuff into smaller and simpler static
> functions. The compiler will deal with those functions like inline, so this
> won't cost cpu cycles, but it will make easier for people to understand what
> you're doing.
>
[Shah, Hardik] I will revisit the code and structure it properly.
>
> Perhaps the better would be for you to have one public machine where you all
> can work and merge your work. I'm OK on pulling and seeing patches outside LinuxTV.
>
> > [Shah, Hardik] we are in process of coordinating this.
>
> One option in the future is to base your work on a git tree. I've changed a lot
> the proccess of submitting patches upstream, to avoid having to rebase my tree
> (Yet, I had to do two rebases during 2.6.27 cycle). If I can keep my tree
> without rebase, the developers may rely on it and start sending me git pull
> requests also. Let's see if I can do this for 2.6.28.
>
> I think we should start discussing using git trees as the reference for
> v4l/dvb development, and start moving developers tree to git. This would solve
> the issues with complex projects like OMAP, where you need to touch not only on
> V4L/DVB subsystem.
>
> This topic deserves some more discussion,
[Shah, Hardik] Right now Manju is on travel. I will confirm with him once he comes back.
> Cheers,
> Mauro.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-06 6:06 ` Shah, Hardik
@ 2008-10-06 6:29 ` Hans Verkuil
2008-10-06 8:41 ` Måns Rullgård
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Hans Verkuil @ 2008-10-06 6:29 UTC (permalink / raw)
To: Shah, Hardik
Cc: video4linux-list@redhat.com, linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net, Mauro Carvalho Chehab
On Monday 06 October 2008 08:06:30 Shah, Hardik wrote:
> Hi,
>
> > -----Original Message-----
> > From: Mauro Carvalho Chehab [mailto:mchehab@infradead.org]
> > Sent: Sunday, October 05, 2008 4:50 PM
> > To: Shah, Hardik
> > Cc: Hans Verkuil; video4linux-list@redhat.com;
> > linux-omap@vger.kernel.org; linux-fbdev-
> > devel@lists.sourceforge.net
> > Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
> >
> > On Fri, 3 Oct 2008 20:10:36 +0530
> > "Shah, Hardik" <hardik.shah@ti.com> wrote:
> >
> >
> >
> > I don't like the idea of having private ioctls. This generally
> > means that only a very restricted subset of userspace apps that are
> > aware of the that API will work. This is really bad.
> >
> > So, I prefer to discuss the need for newer ioctls and add it into
> > the standard whenever make some sense (ok, maybe you might have
> > some ioctls that are really very specific for your app and that
> > won't break userspace apps - I've acked with 2 private ioctls on
> > uvc driver in the past due to that).
>
> [Shah, Hardik] Following are the custom IOCTLs used in the V4L2
> display driver of DSS.
>
> 1. VIDIOC_S/G_OMAP2_MIRROR: This ioctl is used to enable the
> mirroring of the image. Hardware supports mirroring. As pointed out
> by Hans it will be better to move it to VIDIOC_S_CTRL ioctl. we can
> add the new control id for the mirroring.
HFLIP and VFLIP user controls already exist.
> 2. VIDIOC_S/G_OMAP2_ROTATION: Rotation is used to enable the
> rotation of the image. This also can be moved to the VIDIOC_S_CTRL
> ioctl. Need to add new control id for the rotation also.
A new standard user control can be added for this.
> 3. VIDIOC_S/G_OMAP2_LINK: This feature is software provided. OMAP
> DSS is having two video pipelines. Using this feature user can link
> the two video pipelines. This means the streaming of the video on one
> pipeline will be linked to the other pipeline with the same
> parameters as the original pipeline. Same image can be streamed on
> both the pipelines, one of the pipeline's output going to TV and
> other one to LCD. I believe this feature is very specific to OMAP,
> and should remain as the custom ioctl.
I agree.
> 4. VIDIOC_S/G_OMAP2_COLORKEY: Color keying allows the pixels with
> the defined color on the video pipelines to be replaced with the
> pixels on the graphics pipelines. I believe similar feature must be
> available on almost all next generation of video hardware. We can add
> new ioctl for this feature in V4L2 framework. I think VIDIOC_S_FBUF
> ioctl is used for setting up the buffer parameters on per buffer
> basis. So IMHO this ioctl is not a natural fit for the above
> functionality. Please provide your comments on same.
Do I understand correctly that if the color in the *video* streams
matches the colorkey, then it is replaced by the color in the
*framebuffer* (aka menu/overlay)? Usually it is the other way around:
if the framebuffer (menu) has chromakey pixels, then those pixels are
replaced by pixels from the video stream. That's what the current API
does.
> 5. VIDIOC_S/G_OMAP2_BGCOLOR: This ioctl is used to set the Background
> color on either TV or LCD. It takes two inputs, first is the output
> device second is the color to be set. I think this can be added to
> the standard ioctl list but is it ok to have the output device as one
> of the parameters in the input structure? Instead we can set the
> background color for the current output.
Setting the background color for the current output is the more logical
choice. It would also be a nice addition for e.g. the ivtv driver where
a similar functionality exists (currently unused).
I assume that background color refers to the part of the display not
covered by a menu or video?
> 6. VIDIOC_OMAP2_COLORKEY_ENABLE/DISABLE. This ioctl is used to
> enable or the disable the color keying feature described above. This
> can be added as the one of the control using VIDIOC_S_CTRL ioctl.
Depends on the answer to 4).
> 7. VIDIOC_S/G_OMAP2_COLORCONV: This is a hardware feature. Video
> pipelines of the DSS are capable of getting the buffer in the
> YUV/UYVY format. But internally DSS operates on RGB format. So
> hardware has a capability to convert the YUV format to RGB format.
> This is done using the color conversion matrix in the hardware. It
> accepts the structure as input which has 9 unsigned short variables
> representing the coefficients for color conversion. I think this
> feature will also be present in many new devices. So we can have the
> standard ioctl for this.
I think so too, it's pretty much a standard operation.
> 8. VIDIOC_S_OMAP2_DEFCOLORCONV: This ioctl just programs the
> default color conversion matrix defined by the driver. This we can
> have as one of the controls using VIDIOC_S_CTRL ioctl.
I don't understand the need for this one. In what way does it differ
from OMAP2_COLORCONV?
> Please let me know your view/thoughts on above custom ioctls added in
> the driver.
My pleasure,
Hans
>
> > So, if you are having several points where you're violating the
> > rule, probably your code is very complex or you are using long
> > names instead of short ones. On the fisrt case, try to break the
> > complex stuff into smaller and simpler static functions. The
> > compiler will deal with those functions like inline, so this won't
> > cost cpu cycles, but it will make easier for people to understand
> > what you're doing.
>
> [Shah, Hardik] I will revisit the code and structure it properly.
>
> > Perhaps the better would be for you to have one public machine
> > where you all can work and merge your work. I'm OK on pulling and
> > seeing patches outside LinuxTV.
> >
> > > [Shah, Hardik] we are in process of coordinating this.
> >
> > One option in the future is to base your work on a git tree. I've
> > changed a lot the proccess of submitting patches upstream, to avoid
> > having to rebase my tree (Yet, I had to do two rebases during
> > 2.6.27 cycle). If I can keep my tree without rebase, the developers
> > may rely on it and start sending me git pull requests also. Let's
> > see if I can do this for 2.6.28.
> >
> > I think we should start discussing using git trees as the reference
> > for v4l/dvb development, and start moving developers tree to git.
> > This would solve the issues with complex projects like OMAP, where
> > you need to touch not only on V4L/DVB subsystem.
> >
> > This topic deserves some more discussion,
>
> [Shah, Hardik] Right now Manju is on travel. I will confirm with him
> once he comes back.
>
> > Cheers,
> > Mauro.
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-06 6:29 ` Hans Verkuil
@ 2008-10-06 8:41 ` Måns Rullgård
2008-10-06 8:50 ` Shah, Hardik
2008-10-24 9:50 ` Shah, Hardik
2 siblings, 0 replies; 15+ messages in thread
From: Måns Rullgård @ 2008-10-06 8:41 UTC (permalink / raw)
To: video4linux-list; +Cc: linux-omap, linux-fbdev-devel
Hans Verkuil <hverkuil@xs4all.nl> writes:
> On Monday 06 October 2008 08:06:30 Shah, Hardik wrote:
>> 4. VIDIOC_S/G_OMAP2_COLORKEY: Color keying allows the pixels with
>> the defined color on the video pipelines to be replaced with the
>> pixels on the graphics pipelines. I believe similar feature must be
>> available on almost all next generation of video hardware. We can add
>> new ioctl for this feature in V4L2 framework. I think VIDIOC_S_FBUF
>> ioctl is used for setting up the buffer parameters on per buffer
>> basis. So IMHO this ioctl is not a natural fit for the above
>> functionality. Please provide your comments on same.
>
> Do I understand correctly that if the color in the *video* streams
> matches the colorkey, then it is replaced by the color in the
> *framebuffer* (aka menu/overlay)? Usually it is the other way around:
> if the framebuffer (menu) has chromakey pixels, then those pixels are
> replaced by pixels from the video stream. That's what the current API
> does.
The OMAP3 hardware supports both type of keying, but not
simultaneously.
--
Måns Rullgård
mans@mansr.com
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-06 6:29 ` Hans Verkuil
2008-10-06 8:41 ` Måns Rullgård
@ 2008-10-06 8:50 ` Shah, Hardik
2008-10-06 11:22 ` [Linux-fbdev-devel] " Geert Uytterhoeven
2008-10-24 9:50 ` Shah, Hardik
2 siblings, 1 reply; 15+ messages in thread
From: Shah, Hardik @ 2008-10-06 8:50 UTC (permalink / raw)
To: Hans Verkuil
Cc: Mauro Carvalho Chehab, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net, Hadli, Manjunath
Hi,
> -----Original Message-----
> From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
> Sent: Monday, October 06, 2008 11:59 AM
> To: Shah, Hardik
> Cc: Mauro Carvalho Chehab; video4linux-list@redhat.com; linux-omap@vger.kernel.org; linux-fbdev-
> devel@lists.sourceforge.net; Hadli, Manjunath
> Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
>
> On Monday 06 October 2008 08:06:30 Shah, Hardik wrote:
> > Hi,
> >
> > > -----Original Message-----
> > > From: Mauro Carvalho Chehab [mailto:mchehab@infradead.org]
> > > Sent: Sunday, October 05, 2008 4:50 PM
> > > To: Shah, Hardik
> > > Cc: Hans Verkuil; video4linux-list@redhat.com;
> > > linux-omap@vger.kernel.org; linux-fbdev-
> > > devel@lists.sourceforge.net
> > > Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
> > >
> > > On Fri, 3 Oct 2008 20:10:36 +0530
> > > "Shah, Hardik" <hardik.shah@ti.com> wrote:
> > >
> > >
> > >
> > > I don't like the idea of having private ioctls. This generally
> > > means that only a very restricted subset of userspace apps that are
> > > aware of the that API will work. This is really bad.
> > >
> > > So, I prefer to discuss the need for newer ioctls and add it into
> > > the standard whenever make some sense (ok, maybe you might have
> > > some ioctls that are really very specific for your app and that
> > > won't break userspace apps - I've acked with 2 private ioctls on
> > > uvc driver in the past due to that).
> >
> > [Shah, Hardik] Following are the custom IOCTLs used in the V4L2
> > display driver of DSS.
> >
> > 1. VIDIOC_S/G_OMAP2_MIRROR: This ioctl is used to enable the
> > mirroring of the image. Hardware supports mirroring. As pointed out
> > by Hans it will be better to move it to VIDIOC_S_CTRL ioctl. we can
> > add the new control id for the mirroring.
>
> HFLIP and VFLIP user controls already exist.
>
> > 2. VIDIOC_S/G_OMAP2_ROTATION: Rotation is used to enable the
> > rotation of the image. This also can be moved to the VIDIOC_S_CTRL
> > ioctl. Need to add new control id for the rotation also.
>
> A new standard user control can be added for this.
>
> > 3. VIDIOC_S/G_OMAP2_LINK: This feature is software provided. OMAP
> > DSS is having two video pipelines. Using this feature user can link
> > the two video pipelines. This means the streaming of the video on one
> > pipeline will be linked to the other pipeline with the same
> > parameters as the original pipeline. Same image can be streamed on
> > both the pipelines, one of the pipeline's output going to TV and
> > other one to LCD. I believe this feature is very specific to OMAP,
> > and should remain as the custom ioctl.
>
> I agree.
>
> > 4. VIDIOC_S/G_OMAP2_COLORKEY: Color keying allows the pixels with
> > the defined color on the video pipelines to be replaced with the
> > pixels on the graphics pipelines. I believe similar feature must be
> > available on almost all next generation of video hardware. We can add
> > new ioctl for this feature in V4L2 framework. I think VIDIOC_S_FBUF
> > ioctl is used for setting up the buffer parameters on per buffer
> > basis. So IMHO this ioctl is not a natural fit for the above
> > functionality. Please provide your comments on same.
>
> Do I understand correctly that if the color in the *video* streams
> matches the colorkey, then it is replaced by the color in the
> *framebuffer* (aka menu/overlay)? Usually it is the other way around:
> if the framebuffer (menu) has chromakey pixels, then those pixels are
> replaced by pixels from the video stream. That's what the current API
> does
[Shah, Hardik] This is a hardware provided feature. It can be both ways as hardware supports both the features. It means replacing the graphics pipelines pixels with video pipeline pixels and other way is also true. When both graphics and video pipelines are going to the same output device and when the colorkeying is enabled then the pixels of the video pipelines of specific color are replaced by the pixels of the graphics pipeline. This is done automatically done by the overlay manager aka compositor. Graphics pipeline can be controlled by frame buffer interface or V4L2 interface.
In driver we only need to enable the color keying and state that whether it is a source color keying or destination color keying along with the color code.
>
> > 5. VIDIOC_S/G_OMAP2_BGCOLOR: This ioctl is used to set the Background
> > color on either TV or LCD. It takes two inputs, first is the output
> > device second is the color to be set. I think this can be added to
> > the standard ioctl list but is it ok to have the output device as one
> > of the parameters in the input structure? Instead we can set the
> > background color for the current output.
>
> Setting the background color for the current output is the more logical
> choice. It would also be a nice addition for e.g. the ivtv driver where
> a similar functionality exists (currently unused).
>
> I assume that background color refers to the part of the display not
> covered by a menu or video?
[Shah, Hardik] Yes background color refers to the whole display screen. Its not covered by menu or video.
>
> > 6. VIDIOC_OMAP2_COLORKEY_ENABLE/DISABLE. This ioctl is used to
> > enable or the disable the color keying feature described above. This
> > can be added as the one of the control using VIDIOC_S_CTRL ioctl.
>
> Depends on the answer to 4).
>
> > 7. VIDIOC_S/G_OMAP2_COLORCONV: This is a hardware feature. Video
> > pipelines of the DSS are capable of getting the buffer in the
> > YUV/UYVY format. But internally DSS operates on RGB format. So
> > hardware has a capability to convert the YUV format to RGB format.
> > This is done using the color conversion matrix in the hardware. It
> > accepts the structure as input which has 9 unsigned short variables
> > representing the coefficients for color conversion. I think this
> > feature will also be present in many new devices. So we can have the
> > standard ioctl for this.
>
> I think so too, it's pretty much a standard operation.
>
> > 8. VIDIOC_S_OMAP2_DEFCOLORCONV: This ioctl just programs the
> > default color conversion matrix defined by the driver. This we can
> > have as one of the controls using VIDIOC_S_CTRL ioctl.
>
> I don't understand the need for this one. In what way does it differ
> from OMAP2_COLORCONV?
[Shah, Hardik] This gives the extra control to user application, where the color conversion matrix programmed was not showing up the correct colors onto display, and now user wants to restore back the default color conv matrix.
This we can also support by passing NULL argument to the VIDIOC_S_OMAP2_COLORCONV ioctl to program the default color conv. matrix.
>
> > Please let me know your view/thoughts on above custom ioctls added in
> > the driver.
>
> My pleasure,
>
> Hans
>
> >
> > > So, if you are having several points where you're violating the
> > > rule, probably your code is very complex or you are using long
> > > names instead of short ones. On the fisrt case, try to break the
> > > complex stuff into smaller and simpler static functions. The
> > > compiler will deal with those functions like inline, so this won't
> > > cost cpu cycles, but it will make easier for people to understand
> > > what you're doing.
> >
> > [Shah, Hardik] I will revisit the code and structure it properly.
> >
> > > Perhaps the better would be for you to have one public machine
> > > where you all can work and merge your work. I'm OK on pulling and
> > > seeing patches outside LinuxTV.
> > >
> > > > [Shah, Hardik] we are in process of coordinating this.
> > >
> > > One option in the future is to base your work on a git tree. I've
> > > changed a lot the proccess of submitting patches upstream, to avoid
> > > having to rebase my tree (Yet, I had to do two rebases during
> > > 2.6.27 cycle). If I can keep my tree without rebase, the developers
> > > may rely on it and start sending me git pull requests also. Let's
> > > see if I can do this for 2.6.28.
> > >
> > > I think we should start discussing using git trees as the reference
> > > for v4l/dvb development, and start moving developers tree to git.
> > > This would solve the issues with complex projects like OMAP, where
> > > you need to touch not only on V4L/DVB subsystem.
> > >
> > > This topic deserves some more discussion,
> >
> > [Shah, Hardik] Right now Manju is on travel. I will confirm with him
> > once he comes back.
> >
> > > Cheers,
> > > Mauro.
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-06 8:50 ` Shah, Hardik
@ 2008-10-06 11:22 ` Geert Uytterhoeven
0 siblings, 0 replies; 15+ messages in thread
From: Geert Uytterhoeven @ 2008-10-06 11:22 UTC (permalink / raw)
To: Shah, Hardik
Cc: Hans Verkuil, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net, Hadli, Manjunath,
Mauro Carvalho Chehab
On Mon, 6 Oct 2008, Shah, Hardik wrote:
> > -----Original Message-----
> > From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
> > On Monday 06 October 2008 08:06:30 Shah, Hardik wrote:
> > > > -----Original Message-----
> > > > From: Mauro Carvalho Chehab [mailto:mchehab@infradead.org]
> > > 4. VIDIOC_S/G_OMAP2_COLORKEY: Color keying allows the pixels with
> > > the defined color on the video pipelines to be replaced with the
> > > pixels on the graphics pipelines. I believe similar feature must be
> > > available on almost all next generation of video hardware. We can add
> > > new ioctl for this feature in V4L2 framework. I think VIDIOC_S_FBUF
> > > ioctl is used for setting up the buffer parameters on per buffer
> > > basis. So IMHO this ioctl is not a natural fit for the above
> > > functionality. Please provide your comments on same.
> >
> > Do I understand correctly that if the color in the *video* streams
> > matches the colorkey, then it is replaced by the color in the
> > *framebuffer* (aka menu/overlay)? Usually it is the other way around:
> > if the framebuffer (menu) has chromakey pixels, then those pixels are
> > replaced by pixels from the video stream. That's what the current API
> > does
> [Shah, Hardik] This is a hardware provided feature. It can be both ways as
> hardware supports both the features. It means replacing the graphics
> pipelines pixels with video pipeline pixels and other way is also true.
> When both graphics and video pipelines are going to the same output device
> and when the colorkeying is enabled then the pixels of the video pipelines
> of specific color are replaced by the pixels of the graphics pipeline.
> This is done automatically done by the overlay manager aka compositor.
> Graphics pipeline can be controlled by frame buffer interface or V4L2
> interface.
> In driver we only need to enable the color keying and state that whether
> it is a source color keying or destination color keying along with the
> color code.
As video input usually contains noise: is it an exact color match, or a
range? IIRC, I saw a similar feature on a different chip some years ago,
and there the color key was a (YCbCr) range.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-05 11:57 ` Robert William Fuller
2008-10-05 12:05 ` Mauro Carvalho Chehab
@ 2008-10-07 21:48 ` Krzysztof Helt
1 sibling, 0 replies; 15+ messages in thread
From: Krzysztof Helt @ 2008-10-07 21:48 UTC (permalink / raw)
To: Robert William Fuller
Cc: Mauro Carvalho Chehab, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net
On Sun, 05 Oct 2008 07:57:20 -0400
Robert William Fuller <hydrologiccycle@gmail.com> wrote:
>
> The 80 column rule is retarded. None of this code needs to fit on punch
> cards, nor is it COBOL. There are legitimate reasons to have lines
> longer than 80 columns. No matter how simple a program is, it is likely
> to have an expression that is longer than 80 characters. Most people's
> displays are wider than 80 columns these days. Vertical real estate is
> at a greater premium than horizontal real estate these days with wider
> aspect ratio monitors, which better approximate the human field of
> vision. Why make people scan more than one line for a single expression?
>
A printed page is still 80 column with very readable characters.
The human vision may be better approximated by wide screen
monitors but human reading vision not. That's why nobody publish
a printed newspaper or a book in a "wide-page" format. Even more,
one can hardly find a newspaper which has no columns (each line
as wide as a whole page).
My two cents,
Krzysztof
----------------------------------------------------------------------
Dzwon taniej na zagraniczne komorki!
Sprawdz >> http://link.interia.pl/f1f26
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] OMAP 2/3 V4L2 display driver on video planes
2008-10-06 6:29 ` Hans Verkuil
2008-10-06 8:41 ` Måns Rullgård
2008-10-06 8:50 ` Shah, Hardik
@ 2008-10-24 9:50 ` Shah, Hardik
2 siblings, 0 replies; 15+ messages in thread
From: Shah, Hardik @ 2008-10-24 9:50 UTC (permalink / raw)
To: Hans Verkuil
Cc: Mauro Carvalho Chehab, video4linux-list@redhat.com,
linux-omap@vger.kernel.org,
linux-fbdev-devel@lists.sourceforge.net, Hadli, Manjunath
> -----Original Message-----
> From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
> Sent: Monday, October 06, 2008 11:59 AM
> To: Shah, Hardik
> Cc: Mauro Carvalho Chehab; video4linux-list@redhat.com; linux-
> omap@vger.kernel.org; linux-fbdev-devel@lists.sourceforge.net; Hadli,
> Manjunath
> Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
>
> On Monday 06 October 2008 08:06:30 Shah, Hardik wrote:
> > Hi,
> >
> > > -----Original Message-----
> > > From: Mauro Carvalho Chehab [mailto:mchehab@infradead.org]
> > > Sent: Sunday, October 05, 2008 4:50 PM
> > > To: Shah, Hardik
> > > Cc: Hans Verkuil; video4linux-list@redhat.com;
> > > linux-omap@vger.kernel.org; linux-fbdev-
> > > devel@lists.sourceforge.net
> > > Subject: Re: [PATCH] OMAP 2/3 V4L2 display driver on video planes
> > >
> > > On Fri, 3 Oct 2008 20:10:36 +0530
> > > "Shah, Hardik" <hardik.shah@ti.com> wrote:
> > >
> > >
> > >
> > > I don't like the idea of having private ioctls. This generally
> > > means that only a very restricted subset of userspace apps that are
> > > aware of the that API will work. This is really bad.
> > >
> > > So, I prefer to discuss the need for newer ioctls and add it into
> > > the standard whenever make some sense (ok, maybe you might have
> > > some ioctls that are really very specific for your app and that
> > > won't break userspace apps - I've acked with 2 private ioctls on
> > > uvc driver in the past due to that).
> >
> > [Shah, Hardik] Following are the custom IOCTLs used in the V4L2
> > display driver of DSS.
> >
> > 1. VIDIOC_S/G_OMAP2_MIRROR: This ioctl is used to enable the
> > mirroring of the image. Hardware supports mirroring. As pointed out
> > by Hans it will be better to move it to VIDIOC_S_CTRL ioctl. we can
> > add the new control id for the mirroring.
>
> HFLIP and VFLIP user controls already exist.
>
> > 2. VIDIOC_S/G_OMAP2_ROTATION: Rotation is used to enable the
> > rotation of the image. This also can be moved to the VIDIOC_S_CTRL
> > ioctl. Need to add new control id for the rotation also.
>
> A new standard user control can be added for this.
>
> > 3. VIDIOC_S/G_OMAP2_LINK: This feature is software provided. OMAP
> > DSS is having two video pipelines. Using this feature user can link
> > the two video pipelines. This means the streaming of the video on one
> > pipeline will be linked to the other pipeline with the same
> > parameters as the original pipeline. Same image can be streamed on
> > both the pipelines, one of the pipeline's output going to TV and
> > other one to LCD. I believe this feature is very specific to OMAP,
> > and should remain as the custom ioctl.
>
> I agree.
>
> > 4. VIDIOC_S/G_OMAP2_COLORKEY: Color keying allows the pixels with
> > the defined color on the video pipelines to be replaced with the
> > pixels on the graphics pipelines. I believe similar feature must be
> > available on almost all next generation of video hardware. We can add
> > new ioctl for this feature in V4L2 framework. I think VIDIOC_S_FBUF
> > ioctl is used for setting up the buffer parameters on per buffer
> > basis. So IMHO this ioctl is not a natural fit for the above
> > functionality. Please provide your comments on same.
>
> Do I understand correctly that if the color in the *video* streams
> matches the colorkey, then it is replaced by the color in the
> *framebuffer* (aka menu/overlay)? Usually it is the other way around:
> if the framebuffer (menu) has chromakey pixels, then those pixels are
> replaced by pixels from the video stream. That's what the current API
> does.
>
> > 5. VIDIOC_S/G_OMAP2_BGCOLOR: This ioctl is used to set the Background
> > color on either TV or LCD. It takes two inputs, first is the output
> > device second is the color to be set. I think this can be added to
> > the standard ioctl list but is it ok to have the output device as one
> > of the parameters in the input structure? Instead we can set the
> > background color for the current output.
>
> Setting the background color for the current output is the more logical
> choice. It would also be a nice addition for e.g. the ivtv driver where
> a similar functionality exists (currently unused).
>
> I assume that background color refers to the part of the display not
> covered by a menu or video?
>
> > 6. VIDIOC_OMAP2_COLORKEY_ENABLE/DISABLE. This ioctl is used to
> > enable or the disable the color keying feature described above. This
> > can be added as the one of the control using VIDIOC_S_CTRL ioctl.
>
> Depends on the answer to 4).
>
> > 7. VIDIOC_S/G_OMAP2_COLORCONV: This is a hardware feature. Video
> > pipelines of the DSS are capable of getting the buffer in the
> > YUV/UYVY format. But internally DSS operates on RGB format. So
> > hardware has a capability to convert the YUV format to RGB format.
> > This is done using the color conversion matrix in the hardware. It
> > accepts the structure as input which has 9 unsigned short variables
> > representing the coefficients for color conversion. I think this
> > feature will also be present in many new devices. So we can have the
> > standard ioctl for this.
>
> I think so too, it's pretty much a standard operation.
>
> > 8. VIDIOC_S_OMAP2_DEFCOLORCONV: This ioctl just programs the
> > default color conversion matrix defined by the driver. This we can
> > have as one of the controls using VIDIOC_S_CTRL ioctl.
>
> I don't understand the need for this one. In what way does it differ
> from OMAP2_COLORCONV?
>
> > Please let me know your view/thoughts on above custom ioctls added in
> > the driver.
>
> My pleasure,
>
> Hans
>
> >
> > > So, if you are having several points where you're violating the
> > > rule, probably your code is very complex or you are using long
> > > names instead of short ones. On the fisrt case, try to break the
> > > complex stuff into smaller and simpler static functions. The
> > > compiler will deal with those functions like inline, so this won't
> > > cost cpu cycles, but it will make easier for people to understand
> > > what you're doing.
> >
> > [Shah, Hardik] I will revisit the code and structure it properly.
> >
> > > Perhaps the better would be for you to have one public machine
> > > where you all can work and merge your work. I'm OK on pulling and
> > > seeing patches outside LinuxTV.
> > >
> > > > [Shah, Hardik] we are in process of coordinating this.
> > >
> > > One option in the future is to base your work on a git tree. I've
> > > changed a lot the proccess of submitting patches upstream, to avoid
> > > having to rebase my tree (Yet, I had to do two rebases during
> > > 2.6.27 cycle). If I can keep my tree without rebase, the developers
> > > may rely on it and start sending me git pull requests also. Let's
> > > see if I can do this for 2.6.28.
> > >
> > > I think we should start discussing using git trees as the reference
> > > for v4l/dvb development, and start moving developers tree to git.
> > > This would solve the issues with complex projects like OMAP, where
> > > you need to touch not only on V4L/DVB subsystem.
> > >
> > > This topic deserves some more discussion,
> >
Hi All,
I will be posting the version 2 of the DSS library and V4L2 display driver
with almost all the comments from the community taken care of.
It will be series of 4 patches containing
OMAP 2/3 DSS Library
OMAP3 EVM TV encoder Driver.
New IOCTLS added to V4L2 Framework (Already posted on V4L2 mailing list)
OMAP 2/3 V4L2 Display driver on the Video planes of DSS hardware.
We are enhancing the DSS library. This is the first post containing the
features like power management, video pipeline, Digital overlay manager,
clock management support.
Further plan is to add graphics pipeline, LCD overlay manager, RFBI, DSI,
support and frame buffer interface for graphics pipeline
Please let us know your comments on further enhancements of the DSS Library
and V4L2 display driver.
Thanks and Regards,
Hardik Shah
> >
> > > Cheers,
> > > Mauro.
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2008-10-24 9:50 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-17 15:05 [PATCH] OMAP 2/3 V4L2 display driver on video planes Hardik Shah
2008-09-17 15:30 ` Sakari Ailus
2008-09-17 15:42 ` Hiremath, Vaibhav
2008-10-03 14:33 ` Hans Verkuil
2008-10-03 14:40 ` Shah, Hardik
2008-10-05 11:19 ` Mauro Carvalho Chehab
2008-10-05 11:57 ` Robert William Fuller
2008-10-05 12:05 ` Mauro Carvalho Chehab
2008-10-07 21:48 ` [Linux-fbdev-devel] " Krzysztof Helt
2008-10-06 6:06 ` Shah, Hardik
2008-10-06 6:29 ` Hans Verkuil
2008-10-06 8:41 ` Måns Rullgård
2008-10-06 8:50 ` Shah, Hardik
2008-10-06 11:22 ` [Linux-fbdev-devel] " Geert Uytterhoeven
2008-10-24 9:50 ` Shah, Hardik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).