summaryrefslogtreecommitdiff
path: root/recipes
diff options
context:
space:
mode:
authorKoen Kooi <koen@openembedded.org>2009-03-17 22:51:32 +0100
committerKoen Kooi <koen@openembedded.org>2009-03-17 22:51:32 +0100
commitbcde4467f8ac2de9bf9a061f7a3bb3621410d9ef (patch)
tree9c7f347420619d60fe4216e51f093556d4f48ec0 /recipes
parent3b7b721db9da9de480a0efc2710e5592b47255fa (diff)
linux-davinci git: add vfpe driver for davinci and dm355, enable it in dm355-leopard defconfig
Diffstat (limited to 'recipes')
-rw-r--r--recipes/linux/linux-davinci/dm355-leopard/defconfig127
-rw-r--r--recipes/linux/linux-davinci/dm355-leopard/vfpe.patch143
-rw-r--r--recipes/linux/linux-davinci/vfpe1.patch3928
-rw-r--r--recipes/linux/linux-davinci/vfpe2.patch200
-rw-r--r--recipes/linux/linux-davinci/vfpe3.patch2558
-rw-r--r--recipes/linux/linux-davinci/vfpe4.patch1660
-rw-r--r--recipes/linux/linux-davinci/vfpe5.patch132
-rw-r--r--recipes/linux/linux-davinci/vfpe6.patch224
-rw-r--r--recipes/linux/linux-davinci/vfpe7.patch283
-rw-r--r--recipes/linux/linux-davinci_git.bb12
10 files changed, 9253 insertions, 14 deletions
diff --git a/recipes/linux/linux-davinci/dm355-leopard/defconfig b/recipes/linux/linux-davinci/dm355-leopard/defconfig
index 8b3f41a716..d8bd0cdc78 100644
--- a/recipes/linux/linux-davinci/dm355-leopard/defconfig
+++ b/recipes/linux/linux-davinci/dm355-leopard/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.29-rc7-davinci1
-# Tue Mar 17 20:58:19 2009
+# Tue Mar 17 22:47:40 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -941,19 +941,96 @@ CONFIG_MEDIA_TUNER_XC2028=y
CONFIG_MEDIA_TUNER_XC5000=y
CONFIG_VIDEO_V4L2=y
CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_CONTIG=y
CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_ADV_DEBUG is not set
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+CONFIG_VIDEO_TLV320AIC23B=y
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA7111 is not set
+# CONFIG_VIDEO_SAA7114 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+CONFIG_VIDEO_TVP514X=y
+CONFIG_VIDEO_TVP5150=y
+CONFIG_VIDEO_VPX3220=y
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_TVP5146 is not set
+CONFIG_VIDEO_VPFE_CAPTURE=y
+CONFIG_VIDEO_DM355_CCDC=y
# CONFIG_VIDEO_CPIA is not set
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_SOC_CAMERA is not set
+CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+CONFIG_SOC_CAMERA_MT9T031=y
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_SOC_CAMERA_PLATFORM=y
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
CONFIG_V4L_USB_DRIVERS=y
-# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_USB_GSPCA=m
# CONFIG_USB_M5602 is not set
# CONFIG_USB_STV06XX is not set
@@ -1010,9 +1087,9 @@ CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
@@ -1029,7 +1106,7 @@ CONFIG_FIRMWARE_EDID=y
# Frame buffer hardware drivers
#
# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_DAVINCI is not set
+CONFIG_FB_DAVINCI=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
@@ -1052,10 +1129,36 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
-CONFIG_SOUND=m
+CONFIG_SOUND=y
CONFIG_SOUND_OSS_CORE=y
-# CONFIG_SND is not set
-CONFIG_SOUND_PRIME=m
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+# CONFIG_SND_DAVINCI_SOC is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
diff --git a/recipes/linux/linux-davinci/dm355-leopard/vfpe.patch b/recipes/linux/linux-davinci/dm355-leopard/vfpe.patch
new file mode 100644
index 0000000000..4c644b6398
--- /dev/null
+++ b/recipes/linux/linux-davinci/dm355-leopard/vfpe.patch
@@ -0,0 +1,143 @@
+Subject:
+[PATCH 7/7] DM355 platform related changes for vpfe capture driver
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:24:34 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Add platform related changes for vpfe capture driver on DM355
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ arch/arm/mach-davinci/board-dm355-leopard.c | 91 +++++++++++++++++++++++++++-
+
+diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
+index e104650..aaa58ba 100644
+--- a/arch/arm/mach-davinci/board-dm355-leopard.c
++++ b/arch/arm/mach-davinci/board-dm355-leopard.c
+@@ -20,6 +20,8 @@
+ #include <linux/io.h>
+ #include <linux/gpio.h>
+ #include <linux/clk.h>
++#include <media/v4l2-int-device.h>
++#include <media/tvp514x.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/eeprom.h>
+
+@@ -134,12 +136,58 @@ static void dm355leopard_mmcsd_gpios(unsigned gpio)
+ dm355leopard_mmc_gpios = gpio;
+ }
+
++#define TVP5146_I2C_ADDR 0x5D
++static struct v4l2_ifparm tvp5146_ifparm = {
++ .if_type = V4L2_IF_TYPE_BT656,
++ .u = {
++ .bt656 = {
++ .frame_start_on_rising_vs = 1,
++ .bt_sync_correct = 0,
++ .swap = 0,
++ .latch_clk_inv = 0,
++ .nobt_hs_inv = 0, /* active high */
++ .nobt_vs_inv = 0, /* active high */
++ .mode = V4L2_IF_TYPE_BT656_MODE_BT_8BIT,
++ .clock_min = TVP514X_XCLK_BT656,
++ .clock_max = TVP514X_XCLK_BT656,
++ },
++ },
++};
++
++/**
++ * @brief tvp5146_g_ifparm - Returns the TVP5146 decoder interface parameters
++ *
++ * @param p - pointer to v4l2_ifparm structure
++ * @return result of operation - 0 is success
++ */
++static int tvp5146_g_ifparm(struct v4l2_ifparm *p)
++{
++ if (p == NULL)
++ return -EINVAL;
++
++ *p = tvp5146_ifparm;
++ return 0;
++}
++
++#define TVP5146_NUM_INPUTS ARRAY_SIZE(tvp5146_input_list)
++
++static struct tvp514x_platform_data tvp5146_pdata = {
++ .master = CAPTURE_DRV_NAME,
++ .ifparm = tvp5146_g_ifparm,
++ .hs_polarity = 1,
++ .vs_polarity = 1
++};
++
+ static struct i2c_board_info dm355leopard_i2c_info[] = {
+- { I2C_BOARD_INFO("dm355leopard_msp", 0x25),
++ { I2C_BOARD_INFO("dm355leopard_msp", 0x25),
+ .platform_data = dm355leopard_mmcsd_gpios,
+- /* plus irq */ },
++ },
++ {
++ I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),
++ .platform_data = &tvp5146_pdata,
++ },
++ /* { plus irq }, */
+ /* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
+- /* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
+ };
+
+ static void __init leopard_init_i2c(void)
+@@ -178,6 +226,41 @@ static struct platform_device dm355leopard_dm9000 = {
+ .num_resources = ARRAY_SIZE(dm355leopard_dm9000_rsrc),
+ };
+
++#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
++
++static struct vpfe_capture_input vpfe_capture_inputs = {
++ .num_inputs = VPFE_MAX_DEC_INPUTS,
++ .current_input = 0,
++ .inputs[0] = {
++ .dec_name = TVP514X_MODULE_NAME,
++ .input = {
++ .index = 0,
++ .name = "COMPOSITE",
++ .type = V4L2_INPUT_TYPE_CAMERA,
++ .std = TVP514X_STD_ALL,
++ },
++ .route = {
++ .input = INPUT_CVBS_VI2B,
++ .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
++ },
++ .routing_supported = 1,
++ },
++ .inputs[1] = {
++ .dec_name = TVP514X_MODULE_NAME,
++ .input = {
++ .index = 1,
++ .name = "SVIDEO",
++ .type = V4L2_INPUT_TYPE_CAMERA,
++ .std = TVP514X_STD_ALL,
++ },
++ .route = {
++ .input = INPUT_SVIDEO_VI2C_VI1C,
++ .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
++ },
++ .routing_supported = 1,
++ },
++};
++
+ static struct platform_device *davinci_leopard_devices[] __initdata = {
+ &dm355leopard_dm9000,
+ &davinci_nand_device,
+@@ -190,6 +273,8 @@ static struct davinci_uart_config uart_config __initdata = {
+ static void __init dm355_leopard_map_io(void)
+ {
+ davinci_map_common_io();
++ /* setup input configuration for VPFE input devices */
++ setup_vpfe_input_config(&vpfe_capture_inputs);
+ dm355_init();
+ }
+
diff --git a/recipes/linux/linux-davinci/vfpe1.patch b/recipes/linux/linux-davinci/vfpe1.patch
new file mode 100644
index 0000000000..8694d1b7a7
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe1.patch
@@ -0,0 +1,3928 @@
+Subject:
+[PATCH 1/7] VPFE capture driver for DM355 and DM6446
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:15:31 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+This patch is for the vpfe capture driver for DM355 &
+DM6446 from Texas instruments. VPFE stands for Video
+Processing Front End which is the basic IP on DMxxx
+family for video capture and processing. vpfe capture
+driver is a v4l2 bridge driver developed based on
+v4l2-int-device model. It interfaces slave decoder devices
+to the bridge driver using this model. V4L2 community
+has already developed a v4l2 sub device model for this
+purpose. But at this time, tvp514x, the only slave
+decoder that can work with DM355 and DM6446 VPFE, is using
+the v4l2-int-device model. So decision is taken to first
+use this model to submit the driver to the community and
+plan for a migration to sub device model when tvp514x
+driver become sub device compliant.
+
+The driver uses ccdc_hw_device interface to configure
+CCDC based on the interface requirement of the slave
+decoder device. This driver is integrated with the tvp514x
+driver available in open source kernel. The driver is
+tested using a loopback application (Will be made
+available upon request) that captures video frames from the
+capture driver and display it at the output of VPBE using
+the FBDev video output device.
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ drivers/media/video/davinci/vpfe_capture.c | 2248 ++++++++++++++++++++++++++++
+ drivers/media/video/davinci_vpfe.c | 1136 --------------
+ include/media/davinci/vpfe_capture.h | 272 ++++
+ include/media/davinci/vpfe_types.h | 71 +
+ include/media/davinci_vpfe.h | 121 --
+ 5 files changed, 2591 insertions(+), 1257 deletions(-)
+ create mode 100644 drivers/media/video/davinci/vpfe_capture.c
+ delete mode 100644 drivers/media/video/davinci_vpfe.c
+ create mode 100644 include/media/davinci/vpfe_capture.h
+ create mode 100644 include/media/davinci/vpfe_types.h
+ delete mode 100644 include/media/davinci_vpfe.h
+
+diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
+new file mode 100644
+index 0000000..decbffc
+--- /dev/null
++++ b/drivers/media/video/davinci/vpfe_capture.c
+@@ -0,0 +1,2248 @@
++/*
++ * Copyright (C) 2008-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/version.h>
++#include <media/v4l2-common.h>
++#include <linux/io.h>
++#include <mach/cpu.h>
++#include <media/davinci/vpfe_capture.h>
++#include <media/tvp514x.h>
++static int debug;
++static char *ch0_decoder = "TVP514X";
++static u32 ch0_numbuffers = 3;
++static u32 ch0_bufsize = (720 * 576 * 2);
++module_param(ch0_decoder, charp, S_IRUGO);
++module_param(ch0_numbuffers, uint, S_IRUGO);
++module_param(ch0_bufsize, uint, S_IRUGO);
++module_param(debug, int, 0);
++
++static struct vpfe_config_params config_params = {
++ .min_numbuffers = 3,
++ .numbuffers[0] = 3,
++ .min_bufsize[0] = 720 * 480 * 2,
++ .channel_bufsize[0] = 720 * 576 * 2,
++};
++
++static int vpfe_nr[] = { 0 };
++
++static struct vpfe_device vpfe_obj = { {NULL} };
++static struct device *vpfe_dev;
++
++static struct v4l2_capability vpfe_videocap = {
++ .driver = CAPTURE_DRV_NAME,
++ .card = "DaVinci EVM",
++ .bus_info = "Platform",
++ .version = VPFE_CAPTURE_VERSION_CODE,
++ .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
++};
++
++#define VPFE_PIXELASPECT_NTSC {11, 10}
++#define VPFE_PIXELASPECT_PAL {54, 59}
++
++/* standard information */
++struct vpfe_standard {
++ v4l2_std_id std_id;
++ unsigned int width;
++ unsigned int height;
++ struct v4l2_fract pixelaspect;
++ /* 0 - progressive, 1 - interlaced */
++ char frame_format;
++};
++
++struct vpfe_standard vpfe_standards[] = {
++ {V4L2_STD_NTSC, 720, 480, VPFE_PIXELASPECT_NTSC, 1},
++ {V4L2_STD_PAL, 720, 576, VPFE_PIXELASPECT_PAL, 1},
++};
++
++static int vpfe_max_standards = ARRAY_SIZE(vpfe_standards);
++
++/* Used when raw Bayer image from ccdc is directly captured to SDRAM */
++static struct vpfe_pixel_format
++ vpfe_pix_fmts[VPFE_MAX_PIX_FORMATS] = {
++ {
++ .pix_fmt = V4L2_PIX_FMT_SBGGR8,
++ .desc = "Raw Bayer GrRBGb 8bit A-Law compressed",
++ .hw_fmt = VPFE_BAYER_8BIT_PACK_ALAW,
++ },
++ {
++ .pix_fmt = V4L2_PIX_FMT_SBGGR16,
++ .desc = "Raw Bayer GrRBGb - 16bit",
++ .hw_fmt = VPFE_BAYER,
++ },
++ {
++ .pix_fmt = V4L2_PIX_FMT_SGRBG10DPCM8,
++ .desc = "Raw Bayer GrRBGb 8 bit DPCM compressed",
++ .hw_fmt = VPFE_BAYER_8BIT_PACK_DPCM,
++ },
++ {
++ .pix_fmt = V4L2_PIX_FMT_UYVY,
++ .desc = "YCbCr 4:2:2 Interleaved UYVY",
++ .hw_fmt = VPFE_UYVY,
++ },
++ {
++ .pix_fmt = V4L2_PIX_FMT_YUYV,
++ .desc = "YCbCr 4:2:2 Interleaved YUYV",
++ .hw_fmt = VPFE_YUYV,
++ },
++ {
++ .pix_fmt = V4L2_PIX_FMT_NV12,
++ .desc = "Y/CbCr 4:2:0 - Semi planar",
++ .hw_fmt = VPFE_YUV420,
++ },
++};
++
++
++static int vpfe_lookup_hw_format(u32 pix_format)
++{
++ int i, ret = -EINVAL;
++
++ for (i = 0; i < VPFE_MAX_PIX_FORMATS; i++) {
++ if (pix_format == vpfe_pix_fmts[i].pix_fmt) {
++ ret = i;
++ break;
++ }
++ }
++ return ret;
++}
++
++static int vpfe_lookup_v4l2_pix_format(enum vpfe_hw_pix_format hw_pix)
++{
++ int i, ret = -EINVAL;
++
++ for (i = 0; i < VPFE_MAX_PIX_FORMATS; i++) {
++ if (hw_pix == vpfe_pix_fmts[i].hw_fmt) {
++ ret = i;
++ break;
++ }
++ }
++ return ret;
++}
++
++
++/* Used when raw YUV image from ccdc is directly captured to SDRAM */
++static void vpfe_slave_device_unregister(struct v4l2_int_device *s)
++{
++ int index;
++ struct channel_obj *channel = s->u.slave->master->priv;
++
++ for (index = 0; index < VPFE_CAPTURE_NUM_DECODERS; index++) {
++ if ((channel->decoder[index] == s)
++ && (index == channel->current_decoder)) {
++ if (channel->common->started) {
++ /* Streaming is ON. So return busy */
++ v4l2_err(vpfe_dev->driver,
++ "Steaming ON. Cannot unregister"
++ "decoder %s\n", s->name);
++ return;
++ } else {
++ channel->decoder[index] = NULL;
++ channel->numdecoders--;
++ break;
++ }
++ }
++ }
++ if (index == VPFE_CAPTURE_NUM_DECODERS)
++ v4l2_err(vpfe_dev->driver,
++ "No matching decoder registered"
++ "decoder %s\n", s->name);
++}
++
++static int vpfe_get_stdinfo(struct channel_obj *ch, v4l2_std_id *std_id)
++{
++ int i;
++ struct video_obj *vid_ch = NULL;
++
++ vid_ch = &(ch->video);
++
++ for (i = 0; i < vpfe_max_standards; i++) {
++ if (vpfe_standards[i].std_id == *std_id) {
++ vid_ch->std_info.activepixels =
++ vpfe_standards[i].width;
++ vid_ch->std_info.activelines =
++ vpfe_standards[i].height;
++ vid_ch->std_info.frame_format =
++ vpfe_standards[i].frame_format;
++ vid_ch->index = i;
++ break;
++ }
++ }
++ if (i == vpfe_max_standards) {
++ v4l2_err(vpfe_dev->driver, "standard not supported\n");
++ return -EFAULT;
++ }
++ return 0;
++}
++
++/* vpfe_device_register: Used for registering a slave decoder
++ * device with master
++ */
++static int vpfe_slave_device_register(struct v4l2_int_device *s)
++{
++ struct channel_obj *channel = s->u.slave->master->priv;
++ struct common_obj *common = &channel->common[VPFE_VIDEO_INDEX];
++ int err = 0, index;
++ dev_notice(vpfe_dev, "register slave %s \n", s->name);
++ if (ISNULL(channel))
++ return -EINVAL;
++
++ if (!channel->numdecoders) {
++ if (!vidioc_int_dev_init(s)) {
++ channel->current_decoder = 0;
++ channel->decoder[channel->current_decoder] = s;
++ v4l2_info(vpfe_dev->driver, "Current decoder is set to"
++ " %s\n", (s->name));
++ }
++ } else {
++ /* search through the array for an empty entry */
++ for (index = 0; index < VPFE_CAPTURE_NUM_DECODERS; index++) {
++ if (ISNULL(channel->decoder[index])) {
++ channel->decoder[index] = s;
++ break;
++ }
++ }
++ if (index == VPFE_CAPTURE_NUM_DECODERS) {
++ v4l2_err(vpfe_dev->driver,
++ "decoder count reached"
++ " maximum allowed\n");
++ return -ENOMEM;
++ }
++ if (!strncmp(ch0_decoder, s->name, strlen(ch0_decoder))) {
++ if (!common->started) {
++ if (!vidioc_int_dev_init(s)) {
++ channel->current_decoder = index;
++ v4l2_info(vpfe_dev->driver,
++ "Current decoder is"
++ " set to %s\n", (s->name));
++ }
++ }
++ }
++ }
++ channel->numdecoders++;
++ return err;
++}
++
++/* vpfe capture master. All slave decoders registers
++ * with master using vpfe_device_register and deregisters
++ * using vpfe_slave_device_unregister
++ */
++static struct v4l2_int_master vpfe_master = {
++ .attach = vpfe_slave_device_register,
++ .detach = vpfe_slave_device_unregister,
++};
++
++static struct v4l2_int_device vpfe_capture = {
++ .module = THIS_MODULE,
++ .name = CAPTURE_DRV_NAME,
++ .type = v4l2_int_type_master,
++ .u = {
++ .master = &vpfe_master
++ },
++};
++
++/* Call this after storing ifparams in channel block */
++static int vpfe_set_hw_if_type(struct channel_obj *channel)
++{
++ struct vpfe_capture_input *input = channel->video.input;
++
++ switch (input->inputs[input->current_input].route.output) {
++ case OUTPUT_10BIT_422_EMBEDDED_SYNC:
++ channel->vpfe_if = VPFE_BT656;
++ break;
++ case OUTPUT_20BIT_422_SEPERATE_SYNC:
++ channel->vpfe_if = VPFE_YCBCR_SYNC_16;
++ break;
++ case OUTPUT_10BIT_422_SEPERATE_SYNC:
++ channel->vpfe_if = VPFE_YCBCR_SYNC_8;
++ default:
++ v4l2_err(vpfe_dev->driver, "decoder output"
++ " not supported, %d\n",
++ input->inputs[input->current_input].route.output);
++ return -EFAULT;
++ }
++ return ccdc_hw_dev.set_hw_if_type(channel->vpfe_if);
++}
++
++static int vpfe_get_image_format(struct v4l2_format *f)
++{
++ struct v4l2_rect image_win;
++ enum ccdc_buftype buf_type;
++ enum ccdc_frmfmt frm_fmt;
++ enum vpfe_hw_pix_format hw_pix;
++ int ret = 0;
++
++ memset(f, 0, sizeof(struct v4l2_format));
++ f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++ ccdc_hw_dev.get_image_window(&image_win);
++ f->fmt.pix.width = image_win.width;
++ f->fmt.pix.height = image_win.height;
++ ccdc_hw_dev.get_line_length(&f->fmt.pix.bytesperline);
++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
++ f->fmt.pix.height;
++ ccdc_hw_dev.get_buftype(&buf_type);
++ ccdc_hw_dev.get_pixelformat(&hw_pix);
++
++ if (hw_pix == VPFE_BAYER)
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR16;
++ else if (hw_pix == VPFE_BAYER_8BIT_PACK_ALAW)
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
++ else if (hw_pix == VPFE_UYVY)
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
++ else if (hw_pix == VPFE_YUYV)
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
++ else {
++ v4l2_err(vpfe_dev->driver, "Invalid HW pix format detected");
++ ret = -EINVAL;
++ goto out;
++ }
++ ccdc_hw_dev.get_frame_format(&frm_fmt);
++ if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++ else if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
++ if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
++ f->fmt.pix.field = V4L2_FIELD_INTERLACED;
++ else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED)
++ f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
++ else
++ ret = -EINVAL;
++ } else
++ ret = -EINVAL;
++out:
++ return ret;
++}
++
++/* vpfe_config_default_format: Update format information */
++static int vpfe_config_default_format(struct channel_obj *ch)
++{
++ struct common_obj *common = &(ch->common[VPFE_VIDEO_INDEX]);
++ struct v4l2_int_device *dec = ch->decoder[ch->current_decoder];
++ struct v4l2_rect win;
++ int err = 0;
++ struct video_obj *vid_ch = NULL;
++
++ vid_ch = &(ch->video);
++ common->crop.top = 0;
++ common->crop.left = 0;
++ /* first get format information from the decoder.
++ * if not available, get it from CCDC
++ */
++ if ((vidioc_int_g_fmt_cap(dec, &common->fmt)) < 0)
++ vpfe_get_image_format(&common->fmt);
++ else {
++ /* set up all parameters in CCDC */
++ win.top = common->crop.top;
++ win.left = common->crop.left;
++ win.width = common->fmt.fmt.pix.width;
++ win.height = common->fmt.fmt.pix.height;
++ ccdc_hw_dev.set_image_window(&win);
++ if (common->fmt.fmt.pix.field ==
++ V4L2_FIELD_INTERLACED) {
++ err |=
++ ccdc_hw_dev.set_buftype(CCDC_BUFTYPE_FLD_INTERLEAVED);
++ err |=
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_INTERLACED);
++ } else if (common->fmt.fmt.pix.field ==
++ V4L2_FIELD_SEQ_TB) {
++ err |=
++ ccdc_hw_dev.set_buftype(CCDC_BUFTYPE_FLD_SEPARATED);
++ err |=
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_INTERLACED);
++ } else if (common->fmt.fmt.pix.field ==
++ V4L2_FIELD_NONE) {
++ err |=
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_PROGRESSIVE);
++ } else {
++ v4l2_dbg(1, debug, vpfe_dev->driver,
++ "\n Decoder field not supported!");
++ err = -EINVAL;
++ goto out;
++ }
++ }
++ /* set the crop limits */
++ vid_ch->std_info.activepixels = common->fmt.fmt.pix.width;
++ vid_ch->std_info.activelines = common->fmt.fmt.pix.height;
++ if (config_params.numbuffers[ch->channel_id] == 0)
++ common->memory = V4L2_MEMORY_USERPTR;
++ else
++ common->memory = V4L2_MEMORY_MMAP;
++out:
++ return err;
++}
++
++static int vpfe_initialize_channel(struct channel_obj *channel,
++ struct v4l2_int_device *dec)
++{
++ struct common_obj *common = NULL;
++ struct video_obj *vid_ch = NULL;
++ int err = 0;
++
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ vid_ch = &(channel->video);
++ channel->out_from = VPFE_CCDC_OUT;
++ vid_ch->input->current_input = 0;
++
++ err = vidioc_int_g_ifparm(dec, &channel->ifparams);
++ if (err) {
++ v4l2_err(vpfe_dev->driver,
++ "vidioc_int_g_ifparm failed with %d\n", err);
++ return err;
++ }
++
++ err = vpfe_set_hw_if_type(channel);
++ if (err)
++ return err;
++
++ /* Initialize decoder by calling initialize function */
++ err = vidioc_int_s_power(dec, 1);
++ if (err) {
++ v4l2_err(vpfe_dev->driver,
++ "unable to power on the decoder, %s, error %d\n",
++ dec->name,
++ err);
++ return err;
++ }
++
++ err = vidioc_int_init(dec);
++ if (err) {
++ v4l2_err(vpfe_dev->driver,
++ "cannot initialize decoder - error %d\n",
++ err);
++ return err;
++ }
++
++ /* Configure the default format information */
++ err = vpfe_config_default_format(channel);
++
++ /* now open the ccdc device to initialize it */
++ ccdc_hw_dev.open(vpfe_dev);
++ channel->initialized = 1;
++ return err;
++}
++
++/* vpfe_open : It creates object of file handle structure and
++ * stores it in private_data member of filepointer
++ */
++static int vpfe_open(struct file *filep)
++{
++ int minor = iminor(filep->f_path.dentry->d_inode);
++ struct channel_obj *channel = NULL;
++ struct v4l2_int_device *dec = NULL;
++ struct common_obj *common = NULL;
++ struct vpfe_fh *fh = NULL;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "vpfe_open\n");
++
++ /* Check for valid minor number */
++ channel = vpfe_obj.dev[0];
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ if (minor != channel->video_dev->minor) {
++ v4l2_err(vpfe_dev->driver, "device not found\n");
++ return -ENODEV;
++ }
++
++ if (!channel->numdecoders) {
++ v4l2_err(vpfe_dev->driver, "No decoder registered\n");
++ return -ENODEV;
++ }
++
++ dec = channel->decoder[channel->current_decoder];
++
++ /* Allocate memory for the file handle object */
++ fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
++ if (ISNULL(fh)) {
++ v4l2_err(vpfe_dev->driver,
++ "unable to allocate memory for file handle object\n");
++ return -ENOMEM;
++ }
++ /* store pointer to fh in private_data member of filep */
++ filep->private_data = fh;
++ fh->channel = channel;
++ fh->initialized = 0;
++ /* If decoder is not initialized. initialize it */
++ if (!channel->initialized) {
++ if (vpfe_initialize_channel(channel, dec))
++ return -ENODEV;
++ fh->initialized = 1;
++ }
++ /* Increment channel usrs counter */
++ channel->usrs++;
++ /* Set io_allowed member to false */
++ fh->io_allowed[VPFE_VIDEO_INDEX] = 0;
++ /* Initialize priority of this instance to default priority */
++ fh->prio = V4L2_PRIORITY_UNSET;
++ v4l2_prio_open(&channel->prio, &fh->prio);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_open>\n");
++ return 0;
++}
++
++/*ISR for VINT0*/
++static irqreturn_t vpfe_isr(int irq, void *dev_id)
++{
++ struct timeval timevalue;
++ struct channel_obj *channel = NULL;
++ struct common_obj *common = NULL;
++ struct video_obj *vid_ch = NULL;
++ struct vpfe_device *dev = dev_id;
++ unsigned long addr;
++ int fid;
++ enum v4l2_field field;
++ channel = dev->dev[VPFE_CHANNEL0_VIDEO];
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ vid_ch = &(channel->video);
++ field = common->fmt.fmt.pix.field;
++ do_gettimeofday(&timevalue);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "\nStarting vpfe_isr...");
++
++ /* only for 6446 this will be applicable */
++ if (!(ISNULL(ccdc_hw_dev.reset)))
++ ccdc_hw_dev.reset();
++
++ if (field == V4L2_FIELD_INTERLACED ||
++ (field == V4L2_FIELD_SEQ_TB)) {
++ /* Interlaced */
++ /* check which field we are in hardware */
++ fid = ccdc_hw_dev.getfid();
++ /* switch the software maintained field id */
++ channel->field_id ^= 1;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "field id = %x:%x.\n", fid,
++ channel->field_id);
++ if (fid == channel->field_id) {
++ /* we are in-sync here,continue */
++ if (fid == 0) {
++ /* One frame is just being captured. If the
++ * next frame is available, release the current
++ * frame and move on
++ */
++ if (common->curFrm != common->nextFrm) {
++ /* Copy frame capture time value in
++ * curFrm->ts
++ */
++ common->curFrm->ts = timevalue;
++ common->curFrm->state = VIDEOBUF_DONE;
++ wake_up_interruptible(&common->curFrm->
++ done);
++ common->curFrm = common->nextFrm;
++ }
++ /* based on whether the two fields are stored
++ * interleavely or separately in memory,
++ * reconfigure the CCDC memory address
++ */
++ if (channel->out_from == VPFE_CCDC_OUT &&
++ field == V4L2_FIELD_SEQ_TB) {
++ addr =
++ videobuf_to_dma_contig(common->curFrm);
++ addr += common->field_off;
++ ccdc_hw_dev.setfbaddr(addr);
++ }
++ } else if (fid == 1) {
++ /* if one field is just being captured
++ * configure the next frame
++ * get the next frame from the empty queue
++ * if no frame is available
++ * hold on to the current buffer
++ */
++ if (channel->out_from == VPFE_CCDC_OUT &&
++ !list_empty(&common->dma_queue) &&
++ common->curFrm == common->nextFrm) {
++ common->nextFrm =
++ list_entry(common->
++ dma_queue.next,
++ struct
++ videobuf_buffer,
++ queue);
++ list_del(&common->nextFrm->queue);
++ common->nextFrm->state =
++ VIDEOBUF_ACTIVE;
++ addr = videobuf_to_dma_contig(common->
++ nextFrm);
++ ccdc_hw_dev.setfbaddr(addr);
++ }
++ }
++ } else if (fid == 0) {
++ /* recover from any hardware out-of-sync due to
++ * possible switch of video source
++ * for fid == 0, sync up the two fids
++ * for fid == 1, no action, one bad frame will
++ * go out, but it is not a big deal
++ */
++ channel->field_id = fid;
++ }
++ } else if (field == V4L2_FIELD_NONE) {
++
++ v4l2_dbg(1, debug, vpfe_dev->driver,
++ "\nframe format is progressive...");
++ if (common->curFrm != common->nextFrm) {
++ /* Copy frame capture time value in curFrm->ts */
++ common->curFrm->ts = timevalue;
++ common->curFrm->state = VIDEOBUF_DONE;
++ wake_up_interruptible(&common->curFrm->done);
++ common->curFrm = common->nextFrm;
++ }
++
++ }
++ v4l2_dbg(1, debug, vpfe_dev->driver, "interrupt returned.\n");
++ return IRQ_RETVAL(1);
++}
++
++static irqreturn_t vdint1_isr(int irq, void *dev_id)
++{
++ struct channel_obj *channel = NULL;
++ struct common_obj *common = NULL;
++ struct vpfe_device *dev = dev_id;
++ unsigned long addr;
++ channel = dev->dev[VPFE_CHANNEL0_VIDEO];
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "\nInside vdint1_isr...");
++
++ if ((common->fmt.fmt.pix.field == V4L2_FIELD_NONE) &&
++ !list_empty(&common->dma_queue) &&
++ common->curFrm == common->nextFrm) {
++ common->nextFrm =
++ list_entry(common->dma_queue.next,
++ struct videobuf_buffer, queue);
++ list_del(&common->nextFrm->queue);
++ common->nextFrm->state = VIDEOBUF_ACTIVE;
++ addr = videobuf_to_dma_contig(common->nextFrm);
++ ccdc_hw_dev.setfbaddr(addr);
++ }
++ return IRQ_RETVAL(1);
++}
++
++static int vpfe_detach_irq(struct channel_obj *channel)
++{
++ enum ccdc_frmfmt frame_format;
++ int err = 0;
++
++ /* First clear irq if already in use */
++ switch (channel->irq_type) {
++ case VPFE_USE_CCDC_IRQ:
++ ccdc_hw_dev.get_frame_format(&frame_format);
++ if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
++ free_irq(IRQ_VDINT1, &vpfe_obj);
++ channel->irq_type = VPFE_NO_IRQ;
++ break;
++ case VPFE_NO_IRQ:
++ break;
++ default:
++ return -1;
++ }
++ return err;
++}
++
++static int vpfe_attach_irq(struct channel_obj *channel)
++{
++ enum ccdc_frmfmt frame_format;
++ int err = 0;
++
++ channel->irq_type = VPFE_USE_CCDC_IRQ;
++
++ switch (channel->irq_type) {
++ case VPFE_USE_CCDC_IRQ:
++ {
++ ccdc_hw_dev.get_frame_format(&frame_format);
++ if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {
++ err =
++ request_irq(channel->ccdc_irq1,
++ vdint1_isr,
++ IRQF_DISABLED,
++ "vpfe_capture1",
++ (void *)&vpfe_obj);
++ if (err < 0)
++ return -1;
++ }
++ }
++ break;
++ default:
++ return -1;
++ }
++ return 0;
++}
++
++/* vpfe_release : This function deletes buffer queue, frees the
++ * buffers and the vpfe file handle
++ */
++static int vpfe_release(struct file *filep)
++{
++ int ret;
++ struct common_obj *common = NULL;
++ /* Get the channel object and file handle object */
++ struct vpfe_fh *fh = filep->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_release>\n");
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ /* If this is doing IO and other channels are not closed */
++ if ((channel->usrs != 1) && fh->io_allowed[VPFE_VIDEO_INDEX]) {
++ v4l2_err(vpfe_dev->driver, "Close other instances\n");
++ return -EAGAIN;
++ }
++ /* Get the lock on channel object */
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ return ret;
++ /* if this instance is doing IO */
++ if (fh->io_allowed[VPFE_VIDEO_INDEX]) {
++ /* Reset io_usrs member of channel object */
++ if (common->started) {
++ ccdc_hw_dev.enable(0);
++ if (ccdc_hw_dev.enable_out_to_sdram)
++ ccdc_hw_dev.enable_out_to_sdram(0);
++ if (vpfe_detach_irq(channel) < 0) {
++ v4l2_err(vpfe_dev->driver,
++ "Error in detaching IRQ\n");
++ mutex_unlock(&common->lock);
++ return -EFAULT;
++ }
++ }
++
++ common->io_usrs = 0;
++ /* Disable channel/vbi as per its device type and channel id */
++ common->started = 0;
++ /* Free buffers allocated */
++ common->numbuffers =
++ config_params.numbuffers[channel->channel_id];
++ }
++
++ /* Decrement channel usrs counter */
++ channel->usrs--;
++ /* unlock semaphore on channel object */
++ mutex_unlock(&common->lock);
++ /* Close the priority */
++ v4l2_prio_close(&channel->prio, &fh->prio);
++ /* If this file handle has initialize decoder device, reset it */
++ if (fh->initialized) {
++ vidioc_int_s_power(dec, 0);
++ channel->initialized = 0;
++ if (ccdc_hw_dev.close)
++ ccdc_hw_dev.close(vpfe_dev);
++ }
++ filep->private_data = NULL;
++ /* Free memory allocated to file handle object */
++ kfree(fh);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_release>\n");
++ return 0;
++}
++
++/* vpfe_mmap : It is used to map kernel space buffers
++ * into user spaces
++ */
++static int vpfe_mmap(struct file *filep, struct vm_area_struct *vma)
++{
++ /* Get the channel object and file handle object */
++ struct vpfe_fh *fh = filep->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common;
++ int err = 0;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "Start of vpfe mmap\n");
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ err = videobuf_mmap_mapper(&common->buffer_queue, vma);
++ v4l2_dbg(1, debug, vpfe_dev->driver, "End of vpfe mmap\n");
++ return err;
++}
++
++/* vpfe_poll: It is used for select/poll system call
++ */
++static unsigned int vpfe_poll(struct file *filep, poll_table *wait)
++{
++ int err = 0;
++ struct vpfe_fh *fh = filep->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_poll>");
++
++ if (common->started)
++ err = videobuf_poll_stream(filep, &common->buffer_queue, wait);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_poll>");
++ return err;
++}
++
++/* vpfe capture driver file operations */
++static struct v4l2_file_operations vpfe_fops = {
++ .owner = THIS_MODULE,
++ .open = vpfe_open,
++ .release = vpfe_release,
++ .ioctl = video_ioctl2,
++ .mmap = vpfe_mmap,
++ .poll = vpfe_poll
++};
++
++static struct vpfe_pixel_format *
++ vpfe_check_format(struct channel_obj *channel,
++ struct v4l2_pix_format *pixfmt,
++ int check)
++{
++ struct common_obj *common = &(channel->common[VPFE_VIDEO_INDEX]);
++ struct video_obj *vid_ch = &(channel->video);
++ struct vpfe_pixel_format *pix_fmt;
++ enum vpfe_hw_pix_format hw_pix;
++ int temp, found, hpitch, vpitch, bpp, min_height = 1,
++ min_width = 32, max_width, max_height;
++
++
++ temp = vpfe_lookup_hw_format(pixfmt->pixelformat);
++ if (temp < 0) {
++ if (check) {
++ v4l2_err(vpfe_dev->driver, "invalid pixel format\n");
++ return NULL;
++ }
++ /* if invalid and this is a try format, then use hw default */
++ pixfmt->pixelformat = common->fmt.fmt.pix.pixelformat;
++ /* Since this is hw default, we will find this pix format */
++ temp = vpfe_lookup_hw_format(pixfmt->pixelformat);
++
++ } else {
++ /* check if hw supports it */
++ pix_fmt = &vpfe_pix_fmts[temp];
++ temp = 0;
++ found = 0;
++ while (ccdc_hw_dev.enum_pix(&hw_pix, temp) >= 0) {
++ if (pix_fmt->hw_fmt == hw_pix) {
++ found = 1;
++ break;
++ }
++ temp++;
++ }
++ if (!found) {
++ if (check) {
++ v4l2_err(vpfe_dev->driver, "hw doesn't"
++ "support the pixel format\n");
++ return NULL;
++ }
++ /* Since this is hw default, we will find this
++ * pix format
++ */
++ pixfmt->pixelformat = common->fmt.fmt.pix.pixelformat;
++ temp = vpfe_lookup_hw_format(pixfmt->pixelformat);
++ }
++ }
++ pix_fmt = &vpfe_pix_fmts[temp];
++ if (pixfmt->field == V4L2_FIELD_ANY) {
++ /* if ANY set the field to match with decoder */
++ pixfmt->field = common->fmt.fmt.pix.field;
++ }
++
++ /* Try matching the field with the decoder scan field */
++ if (common->fmt.fmt.pix.field != pixfmt->field) {
++ if (!(VPFE_VALID_FIELD(pixfmt->field)) && check) {
++ v4l2_err(vpfe_dev->driver, "invalid field format\n");
++ return NULL;
++ }
++ if (common->fmt.fmt.pix.field == V4L2_FIELD_INTERLACED) {
++ if (pixfmt->field != V4L2_FIELD_SEQ_TB) {
++ if (check) {
++ v4l2_err(vpfe_dev->driver,
++ "invalid field format\n");
++ return NULL;
++ }
++ pixfmt->field = common->fmt.fmt.pix.field;
++ }
++ } else if (common->fmt.fmt.pix.field == V4L2_FIELD_NONE) {
++ if (check) {
++ v4l2_err(vpfe_dev->driver,
++ "invalid field format\n");
++ return NULL;
++ }
++ pixfmt->field = common->fmt.fmt.pix.field;
++ } else
++ pixfmt->field = common->fmt.fmt.pix.field;
++ }
++
++ if (pixfmt->field == V4L2_FIELD_INTERLACED)
++ min_height = 2;
++
++ max_width = vid_ch->std_info.activepixels;
++ max_height = vid_ch->std_info.activelines;
++ if ((pixfmt->pixelformat == V4L2_PIX_FMT_SBGGR8) ||
++ (pixfmt->pixelformat == V4L2_PIX_FMT_NV12) ||
++ (pixfmt->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8))
++ bpp = 1;
++ else
++ bpp = 2;
++ min_width /= bpp;
++ hpitch = pixfmt->width;
++ vpitch = pixfmt->height;
++ v4l2_info(vpfe_dev->driver, "hpitch = %d, vpitch = %d, bpp = %d\n",
++ hpitch, vpitch, bpp);
++ if (hpitch < min_width)
++ hpitch = min_width;
++ if (vpitch < min_width)
++ vpitch = min_height;
++
++ /* Check for upper limits of pitch */
++ if (hpitch > max_width)
++ hpitch = max_width;
++ if (vpitch > max_height)
++ vpitch = max_height;
++
++ /* recalculate bytesperline and sizeimage since width
++ * and height might have changed
++ */
++ pixfmt->bytesperline = (((hpitch * bpp) + 31) & ~31);
++ if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
++ pixfmt->sizeimage = pixfmt->bytesperline * vpitch +
++ ((pixfmt->bytesperline * vpitch) >> 1);
++ else
++ pixfmt->sizeimage = pixfmt->bytesperline * vpitch;
++ pixfmt->width = hpitch;
++ pixfmt->height = vpitch;
++ v4l2_info(vpfe_dev->driver, "adjusted hpitch = %d, vpitch ="
++ " %d, bpp = %d\n", hpitch, vpitch, bpp);
++ return pix_fmt;
++}
++
++static int vpfe_querycap(struct file *file, void *priv,
++ struct v4l2_capability *cap)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_QUERYCAP\n");
++ memset(cap, 0, sizeof(*cap));
++ if ((VPFE_CHANNEL0_VIDEO == channel->channel_id))
++ *cap = vpfe_videocap;
++ else
++ return -EINVAL;
++ return 0;
++}
++
++static int vpfe_g_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *fmt)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_G_FMT\n");
++ /* Fill in the information about
++ * format
++ */
++ ret = mutex_lock_interruptible(&(common->lock));
++ if (ret)
++ goto lock_out;
++ *fmt = common->fmt;
++lock_out:
++ mutex_unlock(&(common->lock));
++ return ret;
++}
++
++static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_fmtdesc *fmt)
++{
++ int ret;
++ enum vpfe_hw_pix_format hw_pix;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_ENUM_FMT\n");
++ /* Fill in the information about format */
++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ ret = ccdc_hw_dev.enum_pix(&hw_pix, fmt->index);
++ if (!ret) {
++ ret = vpfe_lookup_v4l2_pix_format(hw_pix);
++ if (ret >= 0) {
++ strcpy(fmt->description, vpfe_pix_fmts[ret].desc);
++ fmt->pixelformat = vpfe_pix_fmts[ret].pix_fmt;
++ ret = 0;
++ }
++ }
++ return ret;
++}
++
++static int vpfe_s_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *fmt)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ struct v4l2_rect win;
++ struct vpfe_pixel_format *pix_fmts;
++ int ret = 0;
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_S_FMT\n");
++ /* If streaming is started, return error */
++ if (common->started) {
++ v4l2_err(vpfe_dev->driver, "Streaming is started\n");
++ ret = -EBUSY;
++ goto out;
++ }
++ /* Check for valid frame format */
++ pix_fmts = vpfe_check_format(channel, &fmt->fmt.pix, 1);
++
++ if (ISNULL(pix_fmts)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* store the pixel format in the channel
++ * object */
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++
++ /* First detach any IRQ if currently attached */
++ if (vpfe_detach_irq(channel) < 0) {
++ v4l2_err(vpfe_dev->driver, "Error in detaching IRQ\n");
++ ret = -EFAULT;
++ goto lock_out;
++ }
++
++ common->fmt = *fmt;
++
++ /* we are using same variable for setting crop window
++ * at ccdc. For ccdc, this is same as
++ * image window
++ */
++ ccdc_hw_dev.get_image_window(&win);
++ win.width = common->fmt.fmt.pix.width;
++ win.height = common->fmt.fmt.pix.height;
++ ccdc_hw_dev.set_image_window(&win);
++
++ /* In this case, image window and crop window are
++ * the same
++ */
++ if (common->fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR16)
++ ccdc_hw_dev.set_pixelformat(VPFE_BAYER);
++ else if (common->fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
++ ccdc_hw_dev.set_pixelformat(VPFE_BAYER_8BIT_PACK_ALAW);
++ else if (common->fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
++ ccdc_hw_dev.set_pixelformat(VPFE_UYVY);
++ else if (common->fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
++ ccdc_hw_dev.set_pixelformat(VPFE_YUYV);
++ else {
++ /* invalid pix format */
++ ret = -EINVAL;
++ goto lock_out;
++ }
++ if (common->fmt.fmt.pix.field ==
++ V4L2_FIELD_INTERLACED) {
++ ccdc_hw_dev.set_buftype(CCDC_BUFTYPE_FLD_INTERLEAVED);
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_INTERLACED);
++ } else if (common->fmt.fmt.pix.field ==
++ V4L2_FIELD_SEQ_TB) {
++ ccdc_hw_dev.set_buftype(CCDC_BUFTYPE_FLD_SEPARATED);
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_INTERLACED);
++ } else if (common->fmt.fmt.pix.field == V4L2_FIELD_NONE)
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_PROGRESSIVE);
++ else {
++ v4l2_err(vpfe_dev->driver, "\n field error!");
++ ret = -EINVAL;
++ }
++lock_out:
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++static int vpfe_try_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct vpfe_pixel_format *pix_fmts;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_TRY_FMT\n");
++
++ pix_fmts = vpfe_check_format(channel, &f->fmt.pix, 0);
++ if (ISNULL(pix_fmts))
++ return -EINVAL;
++ return 0;
++}
++
++static void vpfe_config_format(struct channel_obj *ch)
++{
++ struct common_obj *common = &(ch->common[VPFE_VIDEO_INDEX]);
++ struct v4l2_rect win;
++ struct video_obj *vid_ch = NULL;
++
++ vid_ch = &(ch->video);
++ common->crop.top = 0;
++ common->crop.top = 0;
++ common->crop.width = common->fmt.fmt.pix.width =
++ vid_ch->std_info.activepixels;
++ common->crop.height = common->fmt.fmt.pix.height =
++ vid_ch->std_info.activelines;
++ win.top = common->crop.top;
++ win.left = common->crop.left;
++ win.width = common->fmt.fmt.pix.width;
++ win.height = common->fmt.fmt.pix.height;
++ ccdc_hw_dev.set_image_window(&win);
++ if (vid_ch->std_info.frame_format) {
++ common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_INTERLACED);
++ ccdc_hw_dev.set_buftype(CCDC_BUFTYPE_FLD_INTERLEAVED);
++ } else {
++ common->fmt.fmt.pix.field = V4L2_FIELD_NONE;
++ ccdc_hw_dev.set_frame_format(CCDC_FRMFMT_PROGRESSIVE);
++ }
++ ccdc_hw_dev.get_line_length(&common->fmt.fmt.pix.bytesperline);
++ common->fmt.fmt.pix.sizeimage = common->fmt.fmt.pix.bytesperline *
++ common->fmt.fmt.pix.height;
++}
++
++static int vpfe_enum_input(struct file *file, void *priv,
++ struct v4l2_input *inp)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct vpfe_capture_input *vpfe_inputs = channel->video.input;
++ int ret = -EINVAL;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_ENUMINPUT\n");
++
++ if (inp->index > vpfe_inputs->num_inputs)
++ return ret;
++
++ if (vpfe_inputs->inputs[inp->index].input.name[0]) {
++ memcpy(inp, &vpfe_inputs->inputs[inp->index].input,
++ sizeof(struct v4l2_input));
++ return 0;
++ }
++ return ret;
++}
++
++static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common =
++ &(channel->common[VPFE_VIDEO_INDEX]);
++ struct vpfe_capture_input *vpfe_inputs = channel->video.input;
++ int ret = 0;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_G_INPUT\n");
++ ret = mutex_lock_interruptible(&common->lock);
++ if (!ret)
++ *index = vpfe_inputs->current_input;
++ mutex_unlock(&common->lock);
++ return ret;
++}
++
++
++static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
++{
++ int i, ret = -EINVAL;
++ v4l2_std_id std_id;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct v4l2_int_device *new_dec, *curr_dec =
++ channel->decoder[channel->current_decoder];
++ struct common_obj *common =
++ &(channel->common[VPFE_VIDEO_INDEX]);
++ struct vpfe_capture_input *vpfe_inputs = channel->video.input;
++ char *new_dec_name;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_S_INPUT\n");
++ if (index > vpfe_inputs->num_inputs) {
++ v4l2_err(vpfe_dev->driver, "input index exceeds limit\n");
++ return ret;
++ }
++
++ if (!vpfe_inputs->inputs[index].input.name[0]) {
++ v4l2_err(vpfe_dev->driver, "input index exceeds limit\n");
++ return ret;
++ }
++
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++ /* If streaming is started return device busy
++ * error
++ */
++ if (common->started) {
++ v4l2_err(vpfe_dev->driver, "Streaming is on\n");
++ ret = -EBUSY;
++ goto lock_out;
++ }
++ new_dec_name = vpfe_inputs->inputs[index].dec_name;
++ /* switch in new decoder to be active */
++ if (strcmp(new_dec_name, curr_dec->name)) {
++ for (i = 0; i < VPFE_CAPTURE_NUM_DECODERS; i++) {
++ if (channel->decoder[i] &&
++ !strcmp(new_dec_name,
++ channel->decoder[i]->name)) {
++ new_dec = channel->decoder[i];
++ channel->current_decoder = i;
++ /* Deinitialize the previous decoder
++ * and power down
++ */
++ vidioc_int_s_power(curr_dec, 0);
++
++ ret = vidioc_int_s_power(new_dec, 1);
++ if (ret)
++ goto lock_out;
++ ret = vidioc_int_init(new_dec);
++ if (ret)
++ goto lock_out;
++ curr_dec = new_dec;
++ }
++ }
++
++ if (i == VPFE_CAPTURE_NUM_DECODERS)
++ /* couldn't find the decoder */
++ goto lock_out;
++ }
++ ret = 0;
++ /* Set the input in the decoder */
++ if (vpfe_inputs->inputs[index].routing_supported)
++ ret = vidioc_int_s_video_routing(curr_dec,
++ &vpfe_inputs->inputs[index].route);
++
++ if (ret) {
++ v4l2_err(vpfe_dev->driver,
++ "vpfe_doioctl:error in setting input in decoder \n");
++ ret = -EINVAL;
++ goto lock_out;
++ }
++
++ vpfe_inputs->current_input = index;
++ ret = vpfe_set_hw_if_type(channel);
++ if (ret)
++ goto lock_out;
++
++ ret = vpfe_config_default_format(channel);
++ if (ret)
++ goto lock_out;
++
++ /* Detect default standard */
++ ret = vidioc_int_querystd(curr_dec, &std_id);
++ if (!ret)
++ ret = vpfe_get_stdinfo(channel, &std_id);
++
++ if (ret)
++ goto lock_out;
++
++ vpfe_config_format(channel);
++lock_out:
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common =
++ &(channel->common[VPFE_VIDEO_INDEX]);
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto lock_out;
++ /* Call querystd function of decoder device */
++ ret = vidioc_int_querystd(dec, std_id);
++ /* Set format based on the standard selected */
++ if (!ret)
++ ret = vpfe_get_stdinfo(channel, std_id);
++ vpfe_config_format(channel);
++lock_out:
++ mutex_unlock(&common->lock);
++ return ret;
++}
++
++static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common =
++ &(channel->common[VPFE_VIDEO_INDEX]);
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_S_STD\n");
++
++ /* If streaming is started, return device
++ busy error */
++ if (common->started) {
++ v4l2_err(vpfe_dev->driver, "streaming is started\n");
++ ret = -EBUSY;
++ goto out;
++ }
++ /* Call decoder driver function to set the
++ standard */
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++ ret = vidioc_int_s_std(dec, std_id);
++
++ /* If it returns error, return error */
++ if (!ret)
++ ret = vpfe_get_stdinfo(channel, std_id);
++
++ if (!ret)
++ vpfe_config_format(channel);
++out:
++ mutex_unlock(&common->lock);
++ return ret;
++}
++
++static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++ int ret;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_G_STD\n");
++ ret = vidioc_int_querystd(dec, std_id);
++ if (ret)
++ goto out;
++
++ ret = vpfe_get_stdinfo(channel, std_id);
++ if (!ret)
++ vpfe_config_format(channel);
++out:
++ return ret;
++}
++/*
++ * Videobuf operations
++ */
++static int vpfe_videobuf_setup(struct videobuf_queue *vq,
++ unsigned int *count,
++ unsigned int *size)
++{
++ /* Get the file handle object and channel object */
++ struct vpfe_fh *fh = vq->priv_data;
++ struct channel_obj *channel = fh->channel;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_buffer_setup>\n");
++ *size = config_params.channel_bufsize[channel->channel_id];
++
++ if (*count < config_params.min_numbuffers)
++ *count = config_params.min_numbuffers;
++ v4l2_dbg(1, debug, vpfe_dev->driver,
++ "count=%d, size=%d\n", *count, *size);
++ return 0;
++}
++
++static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ int ret = 0;
++ /* Get the file handle object and channel object */
++ struct vpfe_fh *fh = vq->priv_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common;
++ unsigned long addr;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_buffer_prepare>\n");
++
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ if (V4L2_MEMORY_USERPTR == common->memory) {
++ /* we don't support user ptr IO */
++ v4l2_dbg(1, debug, vpfe_dev->driver,
++ "<vpfe_buffer_prepare: USERPTR IO"
++ " not supported>\n");
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* If buffer is not initialized, initialize it */
++ if (VIDEOBUF_NEEDS_INIT == vb->state) {
++ vb->width = common->width;
++ vb->height = common->height;
++ vb->size = vb->width * vb->height * 2;
++ vb->field = field;
++ }
++ addr = videobuf_to_dma_contig(vb);
++ if (vq->streaming) {
++ if (!ISALIGNED(addr)) {
++ v4l2_err(vpfe_dev->driver, "buffer_prepare:offset is"
++ "not aligned to 32 bytes\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ }
++ vb->state = VIDEOBUF_PREPARED;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_buffer_prepare>\n");
++out:
++ return ret;
++}
++
++static void vpfe_videobuf_queue(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb)
++{
++ /* Get the file handle object and channel object */
++ struct vpfe_fh *fh = vq->priv_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_buffer_queue>\n");
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ /* add the buffer to the DMA queue */
++ list_add_tail(&vb->queue, &common->dma_queue);
++ /* Change state of the buffer */
++ vb->state = VIDEOBUF_QUEUED;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_buffer_queue>\n");
++}
++
++static void vpfe_videobuf_release(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb)
++{
++ v4l2_dbg(1, debug, vpfe_dev->driver, "vpfe_videobuf_release\n");
++ videobuf_dma_contig_free(vq, vb);
++ vb->state = VIDEOBUF_NEEDS_INIT;
++}
++
++static struct videobuf_queue_ops vpfe_videobuf_qops = {
++ .buf_setup = vpfe_videobuf_setup,
++ .buf_prepare = vpfe_videobuf_prepare,
++ .buf_queue = vpfe_videobuf_queue,
++ .buf_release = vpfe_videobuf_release,
++};
++
++static int vpfe_reqbufs(struct file *file, void *priv,
++ struct v4l2_requestbuffers *p)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ enum v4l2_field field;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_buffer_queue>\n");
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "\nEnd of VIDIOC_REQBUFS ioctl");
++
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
++ ret = -EINVAL;
++ goto out;
++ }
++ if (common->io_usrs != 0) {
++ ret = -EBUSY;
++ goto out;
++ }
++
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++
++ if (common->fmt.fmt.pix.field != V4L2_FIELD_ANY)
++ field = common->fmt.fmt.pix.field;
++ else if (channel->vpfe_if == VPFE_RAW_BAYER)
++ field = V4L2_FIELD_NONE;
++ else
++ field = V4L2_FIELD_INTERLACED;
++
++ videobuf_queue_dma_contig_init(&common->buffer_queue,
++ &vpfe_videobuf_qops,
++ NULL,
++ &common->irqlock,
++ p->type,
++ field,
++ sizeof(struct videobuf_buffer),
++ fh);
++
++ fh->io_allowed[VPFE_VIDEO_INDEX] = 1;
++ common->io_usrs = 1;
++ INIT_LIST_HEAD(&common->dma_queue);
++ ret = videobuf_reqbufs(&common->buffer_queue, p);
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++static int vpfe_querybuf(struct file *file, void *priv,
++ struct v4l2_buffer *p)
++{
++
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ int ret = 0;
++ u8 buf_type_index = 0;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_QUERYBUF\n");
++ buf_type_index = VPFE_VIDEO_INDEX;
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
++ v4l2_err(vpfe_dev->driver,
++ "VIDIOC_QUERYBUF:Invalid buf type\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ common = &(channel->common[buf_type_index]);
++ if (p->memory != V4L2_MEMORY_MMAP) {
++ v4l2_err(vpfe_dev->driver,
++ "VIDIOC_QUERYBUF:Invalid memory\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ /* Call videobuf_querybuf to get information */
++ return videobuf_querybuf(&common->buffer_queue, p);
++out:
++ return ret;
++}
++
++static int vpfe_qbuf(struct file *file, void *priv,
++ struct v4l2_buffer *p)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ int buf_type_index, ret = 0;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_QBUF\n");
++ buf_type_index = VPFE_VIDEO_INDEX;
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
++ v4l2_err(vpfe_dev->driver, "VIDIOC_QBUF:Invalid buf type\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ common = &(channel->common[buf_type_index]);
++
++ /* If this file handle is not allowed to do IO,
++ * return error
++ */
++ if (!fh->io_allowed[buf_type_index]) {
++ v4l2_err(vpfe_dev->driver, "fh->io_allowed\n");
++ ret = -EACCES;
++ goto out;
++ }
++ return videobuf_qbuf(&common->buffer_queue, p);
++out:
++ return ret;
++}
++static int vpfe_dqbuf(struct file *file, void *priv,
++ struct v4l2_buffer *p)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ int buf_type_index = 0, ret = 0;
++ buf_type_index = VPFE_VIDEO_INDEX;
++ common = &(channel->common[buf_type_index]);
++
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
++ v4l2_err(vpfe_dev->driver, "VIDIOC_DQBUF:Invalid buf type\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ if (file->f_flags & O_NONBLOCK)
++ ret = videobuf_dqbuf(&common->buffer_queue, p, 1);
++ else
++ ret = videobuf_dqbuf(&common->buffer_queue, p, 0);
++out:
++ return ret;
++}
++
++/* vpfe_calculate_offsets : This function calculates buffers offset
++ * for top and bottom field
++ */
++static void vpfe_calculate_offsets(struct channel_obj *channel)
++{
++ struct common_obj *common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ struct v4l2_rect image_win;
++
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_calculate_offsets>\n");
++
++ common->field_off = 0;
++ ccdc_hw_dev.get_image_window(&image_win);
++ common->field_off = (image_win.height - 2) * image_win.width;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_calculate_offsets>\n");
++}
++
++static int vpfe_streamon(struct file *file, void *priv,
++ enum v4l2_buf_type i)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ int buf_type_index = VPFE_VIDEO_INDEX;
++ unsigned long addr;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_STREAMON\n");
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != i) {
++ v4l2_err(vpfe_dev->driver,
++ "VIDIOC_STREAMON:Invalid buf type\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ common = &(channel->common[buf_type_index]);
++ /* If file handle is not allowed IO,
++ * return error
++ */
++ if (!fh->io_allowed[buf_type_index]) {
++ v4l2_err(vpfe_dev->driver, "fh->io_allowed\n");
++ ret = -EACCES;
++ goto out;
++ }
++ /* If Streaming is already started,
++ * return error
++ */
++ if (common->started) {
++ v4l2_err(vpfe_dev->driver, "channel->started\n");
++ ret = -EBUSY;
++ goto out;
++ }
++ /* Call videobuf_streamon to start streaming
++ * in videobuf
++ */
++ ret = videobuf_streamon(&common->buffer_queue);
++ if (ret)
++ goto out;
++
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++ /* If buffer queue is empty, return error */
++ if (list_empty(&common->dma_queue)) {
++ v4l2_err(vpfe_dev->driver, "buffer queue is empty\n");
++ ret = -EIO;
++ goto lock_out;
++ }
++ /* Get the next frame from the buffer queue */
++ common->nextFrm = common->curFrm =
++ list_entry(common->dma_queue.next,
++ struct videobuf_buffer, queue);
++ /* Remove buffer from the buffer queue */
++ list_del(&common->curFrm->queue);
++ /* Mark state of the current frame to active */
++ common->curFrm->state = VIDEOBUF_ACTIVE;
++ /* Initialize field_id and started member */
++ channel->field_id = 0;
++ common->started = 1;
++
++ addr = videobuf_to_dma_contig(common->curFrm);
++
++ /* Calculate field offset */
++ vpfe_calculate_offsets(channel);
++
++ if (vpfe_attach_irq(channel) < 0) {
++ v4l2_err(vpfe_dev->driver,
++ "Error in attaching interrupt handle\n");
++ ret = -EFAULT;
++ goto lock_out;
++ }
++
++ ccdc_hw_dev.configure();
++ ccdc_hw_dev.setfbaddr((unsigned long)(addr));
++ ccdc_hw_dev.enable(1);
++ if (ccdc_hw_dev.enable_out_to_sdram)
++ ccdc_hw_dev.enable_out_to_sdram(1);
++lock_out:
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++static int vpfe_streamoff(struct file *file, void *priv,
++ enum v4l2_buf_type i)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ int buf_type_index = VPFE_VIDEO_INDEX, ret = 0;
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != i) {
++ v4l2_err(vpfe_dev->driver,
++ "VIDIOC_STREAMOFF:Invalid buf type\n");
++ return -EINVAL;
++ }
++ common = &(channel->common[buf_type_index]);
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_STREAMOFF\n");
++ /* If io is allowed for this file handle,
++ * return error
++ */
++ if (!fh->io_allowed[buf_type_index]) {
++ v4l2_err(vpfe_dev->driver, "fh->io_allowed\n");
++ ret = -EACCES;
++ goto out;
++ }
++ /* If streaming is not started, return error */
++ if (!common->started) {
++ v4l2_err(vpfe_dev->driver, "channel->started\n");
++ ret = -EINVAL;
++ goto out;
++ }
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++ common->started = 0;
++ ccdc_hw_dev.enable(0);
++ if (ccdc_hw_dev.enable_out_to_sdram)
++ ccdc_hw_dev.enable_out_to_sdram(0);
++ if (vpfe_detach_irq(channel) < 0) {
++ v4l2_err(vpfe_dev->driver,
++ "Error in detaching interrupt handler\n");
++ mutex_unlock(&common->lock);
++ ret = -EFAULT;
++ goto lock_out;
++ }
++ ret = videobuf_streamoff(&common->buffer_queue);
++lock_out:
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++static int vpfe_queryctrl(struct file *file, void *priv,
++ struct v4l2_queryctrl *qc)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_QUERYCTRL\n");
++ /* Call queryctrl function of decoder device */
++ return vidioc_int_queryctrl(dec, qc);
++}
++
++static int vpfe_g_ctrl(struct file *file, void *priv,
++ struct v4l2_control *ctrl)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++ struct common_obj *common =
++ &(channel->common[VPFE_VIDEO_INDEX]);
++ int ret = 0;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_G_CTRL\n");
++ /* Call getcontrol function of decoder device */
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ return ret;
++ ret = vidioc_int_g_ctrl(dec, ctrl);
++ mutex_unlock(&common->lock);
++ return ret;
++}
++
++static int vpfe_s_ctrl(struct file *file, void *priv,
++ struct v4l2_control *ctrl)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common =
++ &(channel->common[VPFE_VIDEO_INDEX]);
++ struct v4l2_int_device *dec =
++ channel->decoder[channel->current_decoder];
++ v4l2_dbg(1, debug, vpfe_dev->driver, "VIDIOC_S_CTRL\n");
++ /* Call setcontrol function of decoder device */
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ return ret;
++ ret = vidioc_int_s_ctrl(dec, ctrl);
++ mutex_unlock(&common->lock);
++ return ret;
++}
++
++static int vpfe_cropcap(struct file *file, void *priv,
++ struct v4l2_cropcap *crop)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct video_obj *vid_ch = NULL;
++ vid_ch = &(channel->video);
++
++ if (vid_ch->index > vpfe_max_standards)
++ return -EINVAL;
++ memset(crop, 0, sizeof(struct v4l2_cropcap));
++ crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ crop->bounds.width = crop->defrect.width =
++ vpfe_standards[vid_ch->index].width;
++ crop->bounds.height = crop->defrect.height =
++ vpfe_standards[vid_ch->index].height;
++ crop->pixelaspect = vpfe_standards[vid_ch->index].pixelaspect;
++ return 0;
++}
++
++static int vpfe_g_crop(struct file *file, void *priv,
++ struct v4l2_crop *crop)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ v4l2_dbg(1, debug, vpfe_dev->driver, "\nStarting VIDIOC_G_CROP ioctl");
++ crop->c = common->crop;
++ return 0;
++}
++
++static int vpfe_s_crop(struct file *file, void *priv,
++ struct v4l2_crop *crop)
++{
++ int ret = 0;
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ struct video_obj *vid_ch = NULL;
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ vid_ch = &(channel->video);
++ v4l2_dbg(1, debug, vpfe_dev->driver, "\nStarting VIDIOC_S_CROP ioctl");
++ if (common->started) {
++ /* make sure streaming is not started */
++ v4l2_err(vpfe_dev->driver,
++ "Cannot change crop when streaming is ON\n");
++ ret = -EBUSY;
++ goto out;
++ }
++
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++ /* make sure parameters are valid */
++ if ((crop->c.left + crop->c.width <= vid_ch->std_info.activepixels) &&
++ (crop->c.top + crop->c.height <= vid_ch->std_info.activelines)) {
++ /* adjust the width to 16 pixel boundry */
++ crop->c.width = ((crop->c.width + 15) & ~0xf);
++ ccdc_hw_dev.set_image_window(&crop->c);
++ common->fmt.fmt.pix.width = crop->c.width;
++ common->fmt.fmt.pix.height = crop->c.height;
++ ccdc_hw_dev.get_line_length(&common->fmt.fmt.pix.bytesperline);
++ common->fmt.fmt.pix.sizeimage =
++ common->fmt.fmt.pix.
++ bytesperline *
++ common->fmt.fmt.pix.height;
++ common->crop = crop->c;
++ } else {
++ v4l2_err(vpfe_dev->driver, "Error in S_CROP params\n");
++ ret = -EINVAL;
++ }
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++
++static long vpfe_param_handler(struct file *file, void *priv,
++ int cmd, void *param)
++{
++ struct vpfe_fh *fh = file->private_data;
++ struct channel_obj *channel = fh->channel;
++ struct common_obj *common = NULL;
++ int ret = 0;
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++
++ if (common->started) {
++ /* only allowed if streaming is not started */
++ v4l2_err(vpfe_dev->driver, "channel already started\n");
++ ret = -EBUSY;
++ goto out;
++ }
++ ret = mutex_lock_interruptible(&common->lock);
++ if (ret)
++ goto out;
++ switch (cmd) {
++ case VPFE_CMD_S_SOC_PARAMS:
++ {
++ ret = ccdc_hw_dev.setparams(param);
++ if (ret) {
++ v4l2_err(vpfe_dev->driver,
++ "Error in setting parameters"
++ " in CCDC \n");
++ goto lock_out;
++ }
++ if (vpfe_get_image_format(&common->fmt) < 0) {
++ v4l2_err(vpfe_dev->driver,
++ "Invalid image format at CCDC \n");
++ goto lock_out;
++ }
++ break;
++ }
++ default:
++ ret = -EINVAL;
++ }
++lock_out:
++ mutex_unlock(&common->lock);
++out:
++ return ret;
++}
++
++
++/* vpfe capture ioctl operations */
++static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
++ .vidioc_querycap = vpfe_querycap,
++ .vidioc_g_fmt_vid_cap = vpfe_g_fmt_vid_cap,
++ .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap,
++ .vidioc_s_fmt_vid_cap = vpfe_s_fmt_vid_cap,
++ .vidioc_try_fmt_vid_cap = vpfe_try_fmt_vid_cap,
++ .vidioc_enum_input = vpfe_enum_input,
++ .vidioc_g_input = vpfe_g_input,
++ .vidioc_s_input = vpfe_s_input,
++ .vidioc_querystd = vpfe_querystd,
++ .vidioc_s_std = vpfe_s_std,
++ .vidioc_g_std = vpfe_g_std,
++ .vidioc_reqbufs = vpfe_reqbufs,
++ .vidioc_querybuf = vpfe_querybuf,
++ .vidioc_qbuf = vpfe_qbuf,
++ .vidioc_dqbuf = vpfe_dqbuf,
++ .vidioc_streamon = vpfe_streamon,
++ .vidioc_streamoff = vpfe_streamoff,
++ .vidioc_queryctrl = vpfe_queryctrl,
++ .vidioc_g_ctrl = vpfe_g_ctrl,
++ .vidioc_s_ctrl = vpfe_s_ctrl,
++ .vidioc_cropcap = vpfe_cropcap,
++ .vidioc_g_crop = vpfe_g_crop,
++ .vidioc_s_crop = vpfe_s_crop,
++ .vidioc_default = vpfe_param_handler,
++};
++
++/* vpfe_probe : This function creates device entries by register
++ * itself to the V4L2 driver and initializes fields of each
++ * channel objects
++ */
++static __init int vpfe_probe(struct platform_device *device)
++{
++ struct common_obj *common = NULL;
++ int err = -ENOMEM, index = 0;
++ struct video_device *vfd = NULL;
++ struct channel_obj *channel = NULL;
++ struct video_obj *vid_ch = NULL;
++ struct resource *res1, *res2;
++ void *__iomem mem1;
++ void *__iomem mem2;
++
++ vpfe_dev = &device->dev;
++
++ /* Get the pointer to the channel object */
++ channel = vpfe_obj.dev[0];
++ /* Allocate memory for video device */
++ vfd = video_device_alloc();
++ if (ISNULL(vfd)) {
++ v4l2_err(vpfe_dev->driver,
++ "Unable to alloc video device\n");
++ return err;
++ }
++
++ /* Initialize field of video device */
++ vfd->release = video_device_release;
++ vfd->current_norm = V4L2_STD_UNKNOWN;
++ vfd->fops = &vpfe_fops;
++ vfd->ioctl_ops = &vpfe_ioctl_ops;
++ vfd->minor = -1;
++ vfd->tvnorms = V4L2_STD_UNKNOWN,
++ vfd->dev = device->dev;
++ snprintf(vfd->name, sizeof(vfd->name),
++ "%s_V%d.%d.%d",
++ CAPTURE_DRV_NAME,
++ (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff,
++ (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff,
++ (VPFE_CAPTURE_VERSION_CODE) & 0xff);
++ /* Set video_dev to the video device */
++ channel->video_dev = vfd;
++
++ channel->usrs = 0;
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ common->io_usrs = 0;
++ common->started = 0;
++ spin_lock_init(&common->irqlock);
++ common->numbuffers = 0;
++ common->field_off = 0;
++ common->curFrm = common->nextFrm = NULL;
++ memset(&common->fmt, 0, sizeof(struct v4l2_format));
++ channel->initialized = 0;
++ channel->channel_id = 0;
++ vid_ch = &(channel->video);
++ vid_ch->input = device->dev.platform_data;
++ if (!vid_ch->input) {
++ v4l2_err(vpfe_dev->driver,
++ "Unable to get inputs to vpfe\n");
++ err = -ENOENT;
++ goto probe_out_release;
++ }
++ vid_ch->index = 0;
++ channel->irq_type = VPFE_NO_IRQ;
++ /* Get VINT0 irq resource */
++ res1 = platform_get_resource(device, IORESOURCE_IRQ, 0);
++ if (!res1) {
++ err = -ENOENT;
++ v4l2_err(vpfe_dev->driver, "Unable to get interrupt for VINT0");
++ goto probe_out_release;
++ }
++ channel->ccdc_irq0 = res1->start;
++
++ /* Get VINT1 irq resource */
++ res1 = platform_get_resource(device,
++ IORESOURCE_IRQ, 1);
++ if (!res1) {
++ err = -ENOENT;
++ v4l2_err(vpfe_dev->driver,
++ "Unable to get interrupt for VINT1");
++ goto probe_out_release;
++ }
++ channel->ccdc_irq1 = res1->start;
++ channel->res1 = platform_get_resource(device, IORESOURCE_MEM, 0);
++ channel->res2 = platform_get_resource(device, IORESOURCE_MEM, 1);
++ if (!channel->res1 || !channel->res2) {
++ v4l2_err(vpfe_dev->driver,
++ "Unable to get register address map\n");
++ err = -ENOENT;
++ goto probe_out_release;
++ }
++ res1 = (struct resource *)channel->res1;
++ res2 = (struct resource *)channel->res2;
++ if (!request_mem_region(res1->start, res1->end - res1->start + 1,
++ vpfe_dev->driver->name)) {
++ err = -ENXIO;
++ v4l2_err(vpfe_dev->driver,
++ "Failed request_mem_region for ccdc base\n");
++ goto probe_out_release;
++ }
++
++ mem1 = ioremap_nocache(res1->start, res1->end - res1->start + 1);
++ if (!mem1) {
++ v4l2_err(vpfe_dev->driver, "Unable to ioremap ccdc address\n");
++ goto probe_out_release_mem1;
++ }
++
++ ccdc_hw_dev.set_ccdc_base(mem1, res1->end - res1->start + 1);
++
++ if (!request_mem_region(res2->start, res2->end - res2->start + 1,
++ vpfe_dev->driver->name)) {
++ err = -ENXIO;
++ v4l2_err(vpfe_dev->driver,
++ "Failed request_mem_region for"
++ " vpss base\n");
++ goto probe_out_unmap1;
++ }
++
++ mem2 = ioremap_nocache(res2->start, res2->end - res2->start + 1);
++ if (!mem2) {
++ v4l2_err(vpfe_dev->driver, "Unable to ioremap vpss address\n");
++ goto probe_out_release_mem2;
++ }
++
++ ccdc_hw_dev.set_vpss_base(mem2, res2->end - res2->start + 1);
++
++ err = request_irq(channel->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
++ "vpfe_capture0", (void *)&vpfe_obj);
++
++ if (0 != err) {
++ v4l2_err(vpfe_dev->driver,
++ "Unable to request interrupt\n");
++ goto probe_out_unmap2;
++ }
++
++ /* Initialize field of the channel objects */
++ channel->usrs = common->io_usrs = 0;
++ common->started = channel->initialized = 0;
++ channel->channel_id = 0;
++ common->numbuffers = config_params.numbuffers[channel->channel_id];
++ channel->numdecoders = 0;
++ channel->current_decoder = 0;
++ for (index = 0; index < VPFE_CAPTURE_NUM_DECODERS; index++)
++ channel->decoder[index] = NULL;
++
++ /* Initialize prio member of channel object */
++ v4l2_prio_init(&channel->prio);
++
++ /* register video device */
++ v4l2_dbg(1, debug, vpfe_dev->driver,
++ "trying to register vpfe device.\n");
++ v4l2_dbg(1, debug, vpfe_dev->driver,
++ "channel=%x,channel->video_dev=%x\n",
++ (int)channel, (int)&channel->video_dev);
++ channel->common[VPFE_VIDEO_INDEX].fmt.type =
++ V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = video_register_device(channel->video_dev,
++ VFL_TYPE_GRABBER, vpfe_nr[0]);
++
++ dev_notice(vpfe_dev, "video device registered\n");
++ if (err) {
++ v4l2_err(vpfe_dev->driver,
++ "Unable to register video device.\n");
++ goto probe_out_release_irq;
++ }
++
++ vpfe_capture.priv = channel;
++ err = v4l2_int_device_register(&vpfe_capture);
++ if (err) {
++ v4l2_err(vpfe_dev->driver,
++ "Unable to register int master device.\n");
++ goto probe_out;
++ }
++ dev_notice(vpfe_dev, "v4l2 int master registered\n");
++ mutex_init(&common->lock);
++ return 0;
++
++probe_out:
++ /* Get the pointer to the channel object */
++ channel = vpfe_obj.dev[0];
++ /* Unregister video device */
++ video_unregister_device(channel->video_dev);
++ v4l2_int_device_unregister(&vpfe_capture);
++
++probe_out_release_irq:
++ free_irq(channel->ccdc_irq0, (void *)&vpfe_obj);
++probe_out_unmap2:
++ iounmap(mem2);
++probe_out_unmap1:
++ iounmap(mem1);
++probe_out_release_mem1:
++ release_mem_region(res1->start, res1->end -
++ res1->start + 1);
++probe_out_release_mem2:
++ release_mem_region(res2->start,
++ res2->end -
++ res2->start + 1);
++probe_out_release:
++ video_device_release(channel->video_dev);
++ channel->video_dev = NULL;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_probe>\n");
++ return err;
++}
++
++/* vpfe_remove : It un-register channels from V4L2 driver
++ */
++static int vpfe_remove(struct platform_device *device)
++{
++ struct channel_obj *channel;
++ struct common_obj *common = NULL;
++ struct resource *res;
++ v4l2_dbg(1, debug, vpfe_dev->driver, "<vpfe_remove>\n");
++
++ /* un-register device */
++ channel = vpfe_obj.dev[0];
++ common = &(channel->common[VPFE_VIDEO_INDEX]);
++ free_irq(channel->ccdc_irq0, (void *)&vpfe_obj);
++ /* Unregister video device */
++ video_unregister_device(channel->video_dev);
++ video_device_release(channel->video_dev);
++ v4l2_int_device_unregister(&vpfe_capture);
++ channel->video_dev = NULL;
++ res = (struct resource *)channel->res1;
++ release_mem_region(res->start, res->end - res->start + 1);
++ res = (struct resource *)channel->res2;
++ release_mem_region(res->start, res->end - res->start + 1);
++ iounmap(ccdc_hw_dev.get_ccdc_base());
++ iounmap(ccdc_hw_dev.get_vpss_base());
++ v4l2_dbg(1, debug, vpfe_dev->driver, "</vpfe_remove>\n");
++ return 0;
++}
++
++static int
++vpfe_suspend(struct platform_device *dev, pm_message_t state)
++{
++ /* add suspend code here later */
++ return 0;
++}
++
++static int
++vpfe_resume(struct platform_device *dev)
++{
++ /* add resume code here later */
++ return 0;
++}
++
++static struct platform_driver vpfe_driver = {
++ .driver = {
++ .name = CAPTURE_DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = vpfe_probe,
++ .remove = __devexit_p(vpfe_remove),
++ .suspend = vpfe_suspend,
++ .resume = vpfe_resume,
++};
++
++static __init int vpfe_init(void)
++{
++ int err = 0;
++
++ /* Default number of buffers should be 3 */
++ if ((ch0_numbuffers > 0) &&
++ (ch0_numbuffers < config_params.min_numbuffers))
++ ch0_numbuffers = config_params.min_numbuffers;
++
++ /* Set buffer size to min buffers size if invalid buffer size is
++ * given
++ */
++ if (ch0_bufsize < config_params.min_bufsize[VPFE_CHANNEL0_VIDEO])
++ ch0_bufsize =
++ config_params.min_bufsize[VPFE_CHANNEL0_VIDEO];
++
++ config_params.numbuffers[VPFE_CHANNEL0_VIDEO] = ch0_numbuffers;
++
++ if (ch0_numbuffers)
++ config_params.channel_bufsize[VPFE_CHANNEL0_VIDEO]
++ = ch0_bufsize;
++
++ if (ISNULL(ccdc_hw_dev.enable) ||
++ ISNULL(ccdc_hw_dev.open) ||
++ ISNULL(ccdc_hw_dev.set_hw_if_type) ||
++ ISNULL(ccdc_hw_dev.configure) ||
++ ISNULL(ccdc_hw_dev.set_buftype) ||
++ ISNULL(ccdc_hw_dev.get_buftype) ||
++ ISNULL(ccdc_hw_dev.enum_pix) ||
++ ISNULL(ccdc_hw_dev.set_frame_format) ||
++ ISNULL(ccdc_hw_dev.get_frame_format) ||
++ ISNULL(ccdc_hw_dev.get_pixelformat) ||
++ ISNULL(ccdc_hw_dev.set_pixelformat) ||
++ ISNULL(ccdc_hw_dev.setparams) ||
++ ISNULL(ccdc_hw_dev.set_image_window) ||
++ ISNULL(ccdc_hw_dev.get_image_window) ||
++ ISNULL(ccdc_hw_dev.get_line_length) ||
++ ISNULL(ccdc_hw_dev.setfbaddr) ||
++ ISNULL(ccdc_hw_dev.getfid)) {
++ printk(KERN_ERR "vpfe_init:CCDC module interface"
++ "has missing mandatory functions\n");
++ return -ENODEV;
++ }
++
++ /* Allocate memory for channel objects */
++ vpfe_obj.dev[0] = kmalloc(sizeof(struct channel_obj), GFP_KERNEL);
++ /* If memory allocation fails, return error */
++ if (!vpfe_obj.dev[0]) {
++ err = -ENOMEM;
++ printk(KERN_ERR "vpfe_init:Memory allocation failed\n");
++ goto vpfe_init_free_channel_object;
++ }
++
++ /* Register driver to the kernel */
++ err = platform_driver_register(&vpfe_driver);
++ if (0 != err)
++ goto vpfe_init_free_channel_object;
++
++ printk(KERN_NOTICE "vpfe_capture: init successful\n");
++ return err;
++
++vpfe_init_free_channel_object:
++ kfree(vpfe_obj.dev[0]);
++ vpfe_obj.dev[0] = NULL;
++ return err;
++}
++
++/* vpfe_cleanup : This function un-registers device and driver
++ * to the kernel, frees requested irq handler and de-allocates memory
++ * allocated for channel objects.
++ */
++static void vpfe_cleanup(void)
++{
++ platform_driver_unregister(&vpfe_driver);
++ kfree(vpfe_obj.dev[0]);
++ vpfe_obj.dev[0] = NULL;
++}
++module_init(vpfe_init);
++module_exit(vpfe_cleanup);
++MODULE_AUTHOR("Texas Instruments.");
++MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/davinci_vpfe.c b/drivers/media/video/davinci_vpfe.c
+deleted file mode 100644
+index 1128eb5..0000000
+--- a/drivers/media/video/davinci_vpfe.c
++++ /dev/null
+@@ -1,1136 +0,0 @@
+-/*
+- *
+- *
+- * Copyright (C) 2006 Texas Instruments Inc
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-/* davinci_vpfe.c */
+-
+-#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/sched.h>
+-#include <linux/interrupt.h>
+-#include <linux/kdev_t.h>
+-#include <linux/string.h>
+-#include <linux/videodev.h>
+-#include <linux/wait.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/platform_device.h>
+-
+-#include <asm/irq.h>
+-#include <asm/page.h>
+-#include <asm/io.h>
+-#include <asm/dma-mapping.h>
+-
+-#include <media/davinci_vpfe.h>
+-
+-#define debug_print(x...) //printk(x)
+-
+-MODULE_LICENSE("GPL");
+-
+-static struct v4l2_rect ntsc_bounds = VPFE_WIN_NTSC;
+-static struct v4l2_rect pal_bounds = VPFE_WIN_PAL;
+-static struct v4l2_fract ntsc_aspect = VPFE_PIXELASPECT_NTSC;
+-static struct v4l2_fract pal_aspect = VPFE_PIXELASPECT_PAL;
+-static struct v4l2_rect ntscsp_bounds = VPFE_WIN_NTSC_SP;
+-static struct v4l2_rect palsp_bounds = VPFE_WIN_PAL_SP;
+-static struct v4l2_fract sp_aspect = VPFE_PIXELASPECT_NTSC_SP;
+-
+-static vpfe_obj vpfe_device = { /* the default format is NTSC */
+- .usrs = 0,
+- .io_usrs = 0,
+- .std = VPFE_STD_AUTO,
+- .vwin = VPFE_WIN_PAL,
+- .bounds = VPFE_WIN_PAL,
+- .pixelaspect = VPFE_PIXELASPECT_NTSC,
+- .pixelfmt = V4L2_PIX_FMT_UYVY,
+- .field = V4L2_FIELD_INTERLACED,
+- .numbuffers = VPFE_DEFNUM_FBUFS,
+- .ccdc_params = {
+- .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
+- .frm_fmt = CCDC_FRMFMT_INTERLACED,
+- .win = VPFE_WIN_PAL,
+- .fid_pol = CCDC_PINPOL_POSITIVE,
+- .vd_pol = CCDC_PINPOL_POSITIVE,
+- .hd_pol = CCDC_PINPOL_POSITIVE,
+- .bt656_enable = TRUE,
+- .pix_order = CCDC_PIXORDER_CBYCRY,
+- .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
+- },
+- .tvp5146_params = {
+- .mode = TVP5146_MODE_AUTO,
+- .amuxmode = TVP5146_AMUX_COMPOSITE,
+- .enablebt656sync = TRUE
+- },
+- .irqlock = SPIN_LOCK_UNLOCKED
+-};
+-
+-struct v4l2_capability vpfe_drvcap = {
+- .driver = "vpfe driver",
+- .card = "DaVinci EVM",
+- .bus_info = "Platform",
+- .version = VPFE_VERSION_CODE,
+- .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
+-};
+-
+-static int sense_std(v4l2_std_id* std_id)
+-{
+- v4l2_std_id id = 0;
+- tvp5146_mode mode;
+- int ret;
+- ret = tvp5146_ctrl(TVP5146_GET_STD, &mode);
+- if(ret < 0)
+- return ret;
+- switch (mode & 0x7) {
+- case TVP5146_MODE_NTSC:
+- id = V4L2_STD_NTSC;
+- break;
+- case TVP5146_MODE_PAL:
+- id = V4L2_STD_PAL;
+- break;
+- case TVP5146_MODE_PAL_M:
+- id = V4L2_STD_PAL_M;
+- break;
+- case TVP5146_MODE_PAL_CN:
+- id = V4L2_STD_PAL_N;
+- break;
+- case TVP5146_MODE_SECAM:
+- id = V4L2_STD_SECAM;
+- break;
+- case TVP5146_MODE_PAL_60:
+- id = V4L2_STD_PAL_60;
+- break;
+- }
+- if (mode & 0x8) { /* square pixel mode */
+- id <<= 32;
+- }
+- if (mode == TVP5146_MODE_AUTO) {
+- id = VPFE_STD_AUTO; /* auto-detection for all other modes */
+- } else if (mode == TVP5146_MODE_AUTO_SQP) {
+- id = VPFE_STD_AUTO_SQP;
+- }
+- if(id == 0)
+- return -EINVAL;
+- *std_id = id;
+- return 0;
+-}
+-
+-static irqreturn_t vpfe_isr(int irq, void *dev_id)
+-{
+- vpfe_obj *vpfe = &vpfe_device;
+- int fid;
+-
+- /* check which field we are in hardware */
+- fid = ccdc_getfid();
+- vpfe->field_id ^= 1; /* switch the software maintained field id */
+- debug_print(KERN_INFO "field id = %x:%x.\n", fid, vpfe->field_id);
+- if (fid == vpfe->field_id) { /* we are in-sync here, continue */
+- if (fid == 0) {
+- /* One frame is just being captured. If the next frame
+- is available, release the current frame and move on */
+- if (vpfe->curFrm != vpfe->nextFrm) {
+- vpfe->curFrm->state = STATE_DONE;
+- wake_up_interruptible(&vpfe->curFrm->done);
+- vpfe->curFrm = vpfe->nextFrm;
+- }
+- /* based on whether the two fields are stored interleavely */
+- /* or separately in memory, reconfigure the CCDC memory address */
+- if (vpfe->field == V4L2_FIELD_SEQ_TB) {
+- u32 addr =
+- vpfe->curFrm->boff + vpfe->field_offset;
+- ccdc_setfbaddr((unsigned long)addr);
+- }
+- } else if (fid == 1) {
+- /* if one field is just being captured */
+- /* configure the next frame */
+- /* get the next frame from the empty queue */
+- /* if no frame is available, hold on to the current buffer */
+- if (!list_empty(&vpfe->dma_queue)
+- && vpfe->curFrm == vpfe->nextFrm) {
+- vpfe->nextFrm = list_entry(vpfe->dma_queue.next,
+- struct videobuf_buffer, queue);
+- list_del(&vpfe->nextFrm->queue);
+- vpfe->nextFrm->state = STATE_ACTIVE;
+- ccdc_setfbaddr(
+- (unsigned long)vpfe->nextFrm->boff);
+- }
+- if (vpfe->mode_changed) {
+- ccdc_setwin(&vpfe->ccdc_params);
+- /* update the field offset */
+- vpfe->field_offset =
+- (vpfe->vwin.height - 2) * vpfe->vwin.width;
+- vpfe->mode_changed = FALSE;
+- }
+- }
+- } else if (fid == 0) {
+- /* recover from any hardware out-of-sync due to */
+- /* possible switch of video source */
+- /* for fid == 0, sync up the two fids */
+- /* for fid == 1, no action, one bad frame will */
+- /* go out, but it is not a big deal */
+- vpfe->field_id = fid;
+- }
+- debug_print(KERN_INFO "interrupt returned.\n");
+- return IRQ_RETVAL(1);
+-}
+-
+-/* this is the callback function called from videobuf_qbuf() function */
+-/* the buffer is prepared and queued into the dma queue */
+-static int buffer_prepare(struct videobuf_queue *q,
+- struct videobuf_buffer *vb,
+- enum v4l2_field field)
+-{
+- vpfe_obj *vpfe = &vpfe_device;
+-
+-
+- if (vb->state == STATE_NEEDS_INIT) {
+- vb->width = vpfe->vwin.width;
+- vb->height = vpfe->vwin.height;
+- vb->size = VPFE_MAX_FBUF_SIZE;
+- vb->field = field;
+- }
+- vb->state = STATE_PREPARED;
+-
+- return 0;
+-
+-}
+-static void
+-buffer_config(struct videobuf_queue *q, unsigned int count)
+-{
+- vpfe_obj *vpfe = &vpfe_device;
+- int i;
+- for(i = 0; i < count; i++) {
+- q->bufs[i]->boff = virt_to_phys(vpfe->fbuffers[i]);
+- debug_print(KERN_INFO "buffer address: %x\n", q->bufs[i]->boff);
+- }
+-}
+-
+-static int
+-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+-{
+- vpfe_obj *vpfe = &vpfe_device;
+- int i;
+- *size = VPFE_MAX_FBUF_SIZE;
+-
+-
+- for (i = VPFE_DEFNUM_FBUFS; i < *count; i++) {
+- u32 size = PAGE_SIZE << VPFE_MAX_FBUF_ORDER;
+- void *mem = (void *)__get_free_pages(GFP_KERNEL |GFP_DMA,
+- VPFE_MAX_FBUF_ORDER);
+- if (mem) {
+- unsigned long adr = (unsigned long)mem;
+- while (size > 0) {
+- /* make sure the frame buffers are never
+- swapped out of memory */
+- SetPageReserved(virt_to_page(adr));
+- adr += PAGE_SIZE;
+- size -= PAGE_SIZE;
+- }
+- vpfe->fbuffers[i] = mem;
+- } else {
+- break;
+- }
+- }
+- *count = vpfe->numbuffers = i;
+-
+- return 0;
+-}
+-
+-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+-{
+- vpfe_obj *vpfe = &vpfe_device;
+- /* add the buffer to the DMA queue */
+- list_add_tail(&vb->queue, &vpfe->dma_queue);
+- vb->state = STATE_QUEUED;
+-}
+-
+-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+-{
+- /* free the buffer if it is not one of the 3 allocated at initializaiton time */
+- if(vb->i < vpfe_device.numbuffers
+- && vb->i >= VPFE_DEFNUM_FBUFS
+- && vpfe_device.fbuffers[vb->i]){
+- free_pages((unsigned long)vpfe_device.fbuffers[vb->i],
+- VPFE_MAX_FBUF_ORDER);
+- vpfe_device.fbuffers[vb->i] = NULL;
+- }
+-}
+-
+-
+-static struct videobuf_queue_ops video_qops = {
+- .buf_setup = buffer_setup,
+- .buf_prepare = buffer_prepare,
+- .buf_queue = buffer_queue,
+- .buf_release = buffer_release,
+- .buf_config = buffer_config,
+-};
+-
+-
+-
+-
+-static int vpfe_doioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, void *arg)
+-{
+- vpfe_obj *vpfe = &vpfe_device;
+- vpfe_fh *fh = file->private_data;
+- int ret = 0;
+- switch (cmd) {
+- case VIDIOC_S_CTRL:
+- case VIDIOC_S_FMT:
+- case VIDIOC_S_STD:
+- case VIDIOC_S_CROP:
+- ret = v4l2_prio_check(&vpfe->prio, &fh->prio);
+- if (0 != ret) {
+- return ret;
+- }
+- break;
+- }
+-
+- switch (cmd) {
+- case VIDIOC_QUERYCAP:
+- {
+- struct v4l2_capability *cap =
+- (struct v4l2_capability *)arg;
+- memset(cap, 0, sizeof(*cap));
+- *cap = vpfe_drvcap;
+- break;
+- }
+- case VIDIOC_ENUM_FMT:
+- {
+- struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *)arg;
+- u32 index = fmt->index;
+- memset(fmt, 0, sizeof(*fmt));
+- fmt->index = index;
+- if (index == 0) {
+- /* only yuv4:2:2 format is supported at this point */
+- fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- strcpy(fmt->description,
+- "YCbCr4:2:2 Interleaved UYUV");
+- fmt->pixelformat = V4L2_PIX_FMT_UYVY;
+- } else if (index == 1) {
+- fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- strcpy(fmt->description,
+- "YCbCr4:2:2 Interleaved YUYV");
+- fmt->pixelformat = V4L2_PIX_FMT_YUYV;
+- } else {
+- ret = -EINVAL;
+- }
+- break;
+- }
+- case VIDIOC_G_FMT:
+- {
+- struct v4l2_format *fmt = (struct v4l2_format *)arg;
+- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+- ret = -EINVAL;
+- } else {
+- struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+- down_interruptible(&vpfe->lock);
+- pixfmt->width = vpfe->vwin.width;
+- pixfmt->height = vpfe->vwin.height;
+- pixfmt->field = vpfe->field;
+- pixfmt->pixelformat = vpfe->pixelfmt;
+- pixfmt->bytesperline = pixfmt->width * 2;
+- pixfmt->sizeimage =
+- pixfmt->bytesperline * pixfmt->height;
+- pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+- up(&vpfe->lock);
+- }
+- break;
+- }
+- case VIDIOC_S_FMT:
+- {
+- struct v4l2_format *fmt = (struct v4l2_format *)arg;
+- struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+- ccdc_params_ycbcr *params = &vpfe->ccdc_params;
+- if (vpfe->started) { /* make sure streaming is not started */
+- ret = -EBUSY;
+- break;
+- }
+-
+- down_interruptible(&vpfe->lock);
+- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+- ret = -EINVAL;
+- up(&vpfe->lock);
+- break;
+- }
+- if ((pixfmt->width + vpfe->vwin.left <=
+- vpfe->bounds.width)
+- & (pixfmt->height + vpfe->vwin.top <=
+- vpfe->bounds.height)) {
+- /* this is the case when no scaling is supported */
+- /* crop window is directed modified */
+- vpfe->vwin.height = pixfmt->height;
+- vpfe->vwin.width = pixfmt->width;
+- params->win.width = pixfmt->width;
+- params->win.height = pixfmt->height;
+- } else {
+- ret = -EINVAL;
+- up(&vpfe->lock);
+- break;
+- }
+- /* setup the CCDC parameters accordingly */
+- if (pixfmt->pixelformat == V4L2_PIX_FMT_YUYV) {
+- params->pix_order = CCDC_PIXORDER_YCBYCR;
+- vpfe->pixelfmt = pixfmt->pixelformat;
+- } else if (pixfmt->pixelformat == V4L2_PIX_FMT_UYVY) {
+- params->pix_order = CCDC_PIXORDER_CBYCRY;
+- vpfe->pixelfmt = pixfmt->pixelformat;
+- } else {
+- ret = -EINVAL; /* not supported format */
+- up(&vpfe->lock);
+- break;
+- }
+- if (pixfmt->field == V4L2_FIELD_NONE
+- || pixfmt->field == V4L2_FIELD_INTERLACED) {
+- params->buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED;
+- vpfe->field = pixfmt->field;
+- } else if (pixfmt->field == V4L2_FIELD_SEQ_TB) {
+- params->buf_type = CCDC_BUFTYPE_FLD_SEPARATED;
+- vpfe->field = pixfmt->field;
+- } else {
+- ret = -EINVAL;
+- }
+- up(&vpfe->lock);
+- break;
+- }
+- case VIDIOC_TRY_FMT:
+- {
+- struct v4l2_format *fmt = (struct v4l2_format *)arg;
+- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+- ret = -EINVAL;
+- } else {
+- struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+- if (pixfmt->width > vpfe->bounds.width
+- || pixfmt->height > vpfe->bounds.height
+- || (pixfmt->pixelformat != V4L2_PIX_FMT_UYVY
+- && pixfmt->pixelformat !=
+- V4L2_PIX_FMT_YUYV)) {
+- ret = -EINVAL;
+- }
+- }
+- break;
+- }
+- case VIDIOC_G_STD:
+- {
+- v4l2_std_id *id = (v4l2_std_id *) arg;
+- *id = vpfe->std;
+- break;
+- }
+- case VIDIOC_S_STD:
+- {
+- v4l2_std_id id = *(v4l2_std_id *) arg;
+- tvp5146_mode mode = TVP5146_MODE_INV;
+- int sqp = 0;
+-
+- if (vpfe->started) { /* make sure streaming is not started */
+- ret = -EBUSY;
+- break;
+- }
+- down_interruptible(&vpfe->lock);
+- if (id & V4L2_STD_625_50) {
+- vpfe->std = id;
+- vpfe->bounds = vpfe->vwin = pal_bounds;
+- vpfe->pixelaspect = pal_aspect;
+- vpfe->ccdc_params.win = pal_bounds;
+-
+- } else if (id & V4L2_STD_525_60) {
+- vpfe->std = id;
+- vpfe->bounds = vpfe->vwin = ntsc_bounds;
+- vpfe->pixelaspect = ntsc_aspect;
+- vpfe->ccdc_params.win = ntsc_bounds;
+- } else if (id & VPFE_STD_625_50_SQP) {
+- vpfe->std = id;
+- vpfe->bounds = vpfe->vwin = palsp_bounds;
+- vpfe->pixelaspect = sp_aspect;
+- sqp = 1;
+- id >>= 32;
+- } else if (id & VPFE_STD_525_60_SQP) {
+- vpfe->std = id;
+- sqp = 1;
+- vpfe->std = id;
+- id >>= 32;
+- vpfe->bounds = vpfe->vwin = ntscsp_bounds;
+- vpfe->pixelaspect = sp_aspect;
+- vpfe->ccdc_params.win = ntscsp_bounds;
+- } else if (id & VPFE_STD_AUTO) {
+- mode = TVP5146_MODE_AUTO;
+- vpfe->bounds = vpfe->vwin = pal_bounds;
+- vpfe->pixelaspect = pal_aspect;
+- vpfe->ccdc_params.win = pal_bounds;
+- vpfe->std = id;
+- } else if (id & VPFE_STD_AUTO_SQP) {
+- vpfe->std = id;
+- vpfe->bounds = vpfe->vwin = palsp_bounds;
+- vpfe->pixelaspect = sp_aspect;
+- sqp = 1;
+- mode = TVP5146_MODE_AUTO_SQP;
+- vpfe->pixelaspect = sp_aspect;
+- } else {
+- ret = -EINVAL;
+- }
+- if (id == V4L2_STD_PAL_60) {
+- mode = TVP5146_MODE_PAL_60;
+- } else if (id == V4L2_STD_PAL_M) {
+- mode = TVP5146_MODE_PAL_M;
+- } else if (id == V4L2_STD_PAL_Nc
+- || id == V4L2_STD_PAL_N) {
+- mode = TVP5146_MODE_PAL_CN;
+- } else if (id & V4L2_STD_PAL) {
+- mode = TVP5146_MODE_PAL;
+- } else if (id & V4L2_STD_NTSC) {
+- mode = TVP5146_MODE_NTSC;
+- } else if (id & V4L2_STD_SECAM) {
+- mode = TVP5146_MODE_SECAM;
+- }
+- vpfe->tvp5146_params.mode = mode | (sqp << 3);
+- tvp5146_ctrl(TVP5146_CONFIG, &vpfe->tvp5146_params);
+-
+- up(&vpfe->lock);
+- break;
+- }
+- case VIDIOC_ENUMSTD:
+- {
+- struct v4l2_standard *std = (struct v4l2_standard *)arg;
+- u32 index = std->index;
+- memset(std, 0, sizeof(*std));
+- std->index = index;
+- if (index == 0) {
+- std->id = V4L2_STD_525_60;
+- strcpy(std->name, "SD-525line-30fps");
+- std->framelines = 525;
+- std->frameperiod.numerator = 1001;
+- std->frameperiod.denominator = 30000;
+- } else if (index == 1) {
+- std->id = V4L2_STD_625_50;
+- strcpy(std->name, "SD-625line-25fps");
+- std->framelines = 625;
+- std->frameperiod.numerator = 1;
+- std->frameperiod.denominator = 25;
+- } else if (index == 2) {
+- std->id = VPFE_STD_625_50_SQP;
+- strcpy(std->name,
+- "SD-625line-25fps square pixel");
+- std->framelines = 625;
+- std->frameperiod.numerator = 1;
+- std->frameperiod.denominator = 25;
+- } else if (index == 3) {
+- std->id = VPFE_STD_525_60_SQP;
+- strcpy(std->name,
+- "SD-525line-25fps square pixel");
+- std->framelines = 525;
+- std->frameperiod.numerator = 1001;
+- std->frameperiod.denominator = 30000;
+- } else if (index == 4) {
+- std->id = VPFE_STD_AUTO;
+- strcpy(std->name, "automatic detect");
+- std->framelines = 625;
+- std->frameperiod.numerator = 1;
+- std->frameperiod.denominator = 1;
+- } else if (index == 5) {
+- std->id = VPFE_STD_AUTO_SQP;
+- strcpy(std->name,
+- "automatic detect square pixel");
+- std->framelines = 625;
+- std->frameperiod.numerator = 1;
+- std->frameperiod.denominator = 1;
+- } else {
+- ret = -EINVAL;
+- }
+- break;
+- }
+- case VIDIOC_ENUMINPUT:
+- {
+- u32 index=0;
+- struct v4l2_input *input = (struct v4l2_input *)arg;
+- if (input->index > 1) /* only two inputs are available */
+- ret = -EINVAL;
+- index = input->index;
+- memset(input, 0, sizeof(*input));
+- input->index = index;
+- input->type = V4L2_INPUT_TYPE_CAMERA;
+- input->std = V4L2_STD_ALL;
+- if(input->index == 0){
+- sprintf(input->name, "COMPOSITE");
+- }else if(input->index == 1) {
+- sprintf(input->name, "S-VIDEO");
+- }
+- break;
+- }
+- case VIDIOC_G_INPUT:
+- {
+- int *index = (int *)arg;
+- *index = vpfe->tvp5146_params.amuxmode;
+- break;
+- }
+- case VIDIOC_S_INPUT:
+- {
+- int *index = (int *)arg;
+- if (*index > 1 || *index < 0) {
+- ret = -EINVAL;
+- }
+- vpfe->tvp5146_params.amuxmode = *index;
+- tvp5146_ctrl(TVP5146_SET_AMUXMODE, index);
+- break;
+- }
+- case VIDIOC_CROPCAP:
+- {
+- struct v4l2_cropcap *cropcap =
+- (struct v4l2_cropcap *)arg;
+- cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- down_interruptible(&vpfe->lock);
+- cropcap->bounds = cropcap->defrect = vpfe->vwin;
+- cropcap->pixelaspect = vpfe->pixelaspect;
+- up(&vpfe->lock);
+- break;
+- }
+- case VIDIOC_G_PARM:
+- {
+- struct v4l2_streamparm *parm =
+- (struct v4l2_streamparm *)arg;
+- if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+- /* only capture is supported */
+- ret = -EINVAL;
+- } else {
+- struct v4l2_captureparm *capparm =
+- &parm->parm.capture;
+- memset(capparm, 0,
+- sizeof(struct v4l2_captureparm));
+- down_interruptible(&vpfe->lock);
+- if (vpfe->std & V4L2_STD_625_50) {
+- capparm->timeperframe.numerator = 1;
+- capparm->timeperframe.denominator = 25; /* PAL 25fps */
+- } else {
+- capparm->timeperframe.numerator = 1001;
+- capparm->timeperframe.denominator = 30000; /*NTSC 29.97fps */
+- }
+- capparm->readbuffers = vpfe->numbuffers;
+- up(&vpfe->lock);
+- }
+- break;
+- }
+- case VIDIOC_G_CTRL:
+- down_interruptible(&vpfe->lock);
+- tvp5146_ctrl(VIDIOC_G_CTRL, arg);
+- up(&vpfe->lock);
+- break;
+- case VIDIOC_S_CTRL:
+- down_interruptible(&vpfe->lock);
+- tvp5146_ctrl(VIDIOC_S_CTRL, arg);
+- up(&vpfe->lock);
+- break;
+- case VIDIOC_QUERYCTRL:
+- down_interruptible(&vpfe->lock);
+- tvp5146_ctrl(VIDIOC_QUERYCTRL, arg);
+- up(&vpfe->lock);
+- break;
+- case VIDIOC_G_CROP:
+- {
+- struct v4l2_crop *crop = arg;
+- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+- ret = -EINVAL;
+- } else {
+- crop->c = vpfe->vwin;
+- }
+- break;
+- }
+- case VIDIOC_S_CROP:
+- {
+- struct v4l2_crop *crop = arg;
+- ccdc_params_ycbcr *params = &vpfe->ccdc_params;
+- if (vpfe->started) { /* make sure streaming is not started */
+- ret = -EBUSY;
+- break;
+- }
+- /*adjust the width to 16 pixel boundry */
+- crop->c.width = ((crop->c.width + 15 )/16 ) * 16;
+-
+- /* make sure parameters are valid */
+- if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+- && (crop->c.left + crop->c.width
+- <= vpfe->bounds.left + vpfe->bounds.width)
+- && (crop->c.top + crop->c.height
+- <= vpfe->bounds.top + vpfe->bounds.height)) {
+-
+- down_interruptible(&vpfe->lock);
+- vpfe->vwin = crop->c;
+- params->win = vpfe->vwin;
+- up(&vpfe->lock);
+- } else {
+- ret = -EINVAL;
+- }
+- break;
+- }
+- case VIDIOC_QUERYSTD:
+- {
+- v4l2_std_id *id = (v4l2_std_id *) arg;
+- down_interruptible(&vpfe->lock);
+- ret = sense_std(id);
+- up(&vpfe->lock);
+- break;
+- }
+- case VIDIOC_G_PRIORITY:
+- {
+- enum v4l2_priority *p = arg;
+- *p = v4l2_prio_max(&vpfe->prio);
+- break;
+- }
+- case VIDIOC_S_PRIORITY:
+- {
+- enum v4l2_priority *p = arg;
+- ret = v4l2_prio_change(&vpfe->prio, &fh->prio, *p);
+- break;
+- }
+-
+- case VIDIOC_REQBUFS:
+- if (vpfe->io_usrs != 0) {
+- ret = -EBUSY;
+- break;
+- }
+- down_interruptible(&vpfe->lock);
+- videobuf_queue_init(&vpfe->bufqueue, &video_qops, NULL,
+- &vpfe->irqlock, V4L2_BUF_TYPE_VIDEO_CAPTURE, vpfe->field,
+- sizeof(struct videobuf_buffer), fh);
+-
+- videobuf_set_buftype(&vpfe->bufqueue, VIDEOBUF_BUF_LINEAR);
+-
+- fh->io_allowed = TRUE;
+- vpfe->io_usrs = 1;
+- INIT_LIST_HEAD(&vpfe->dma_queue);
+- ret = videobuf_reqbufs(&vpfe->bufqueue, arg);
+- up(&vpfe->lock);
+- break;
+- case VIDIOC_QUERYBUF:
+- ret = videobuf_querybuf(&vpfe->bufqueue, arg);
+- break;
+- case VIDIOC_QBUF:
+- if (!fh->io_allowed)
+- ret = -EACCES;
+- else
+- ret = videobuf_qbuf(&vpfe->bufqueue, arg);
+- break;
+- case VIDIOC_DQBUF:
+- if (!fh->io_allowed)
+- ret = -EACCES;
+- else
+- ret = videobuf_dqbuf(&vpfe->bufqueue, arg, 0);
+- break;
+- case VIDIOC_STREAMON:
+- if (!fh->io_allowed) {
+- ret = -EACCES;
+- break;
+- }
+- if(vpfe->started){
+- ret = -EBUSY;
+- break;
+- }
+- ret = videobuf_streamon(&vpfe->bufqueue);
+- if(ret) break;
+-
+- down_interruptible(&vpfe->lock);
+- /* get the current and next frame buffers */
+- /* we expect at least one buffer is in driver at this point */
+- /* if not, error is returned */
+- if (list_empty(&vpfe->dma_queue)) {
+- ret = -EIO;
+- break;
+- }
+- debug_print(KERN_INFO "cur frame %x.\n",
+- vpfe->dma_queue.next);
+- vpfe->nextFrm = vpfe->curFrm =
+- list_entry(vpfe->dma_queue.next,
+- struct videobuf_buffer, queue);
+- /* remove the buffer from the queue */
+- list_del(&vpfe->curFrm->queue);
+- vpfe->curFrm->state = STATE_ACTIVE;
+-
+- /* sense the current video input standard */
+- tvp5146_ctrl(TVP5146_CONFIG, &vpfe->tvp5146_params);
+- /* configure the ccdc and resizer as needed */
+- /* start capture by enabling CCDC and resizer */
+- ccdc_config_ycbcr(&vpfe->ccdc_params);
+- /* setup the memory address for the frame buffer */
+- ccdc_setfbaddr(((unsigned long)(vpfe->curFrm->boff)));
+- /* enable CCDC */
+- vpfe->field_id = 0;
+- vpfe->started = TRUE;
+- vpfe->mode_changed = FALSE;
+- vpfe->field_offset =
+- (vpfe->vwin.height - 2) * vpfe->vwin.width;
+- ccdc_enable(TRUE);
+- up(&vpfe->lock);
+- debug_print(KERN_INFO "started video streaming.\n");
+- break;
+- case VIDIOC_STREAMOFF:
+- {
+- if (!fh->io_allowed) {
+- ret = -EACCES;
+- break;
+- }
+- if(!vpfe->started){
+- ret = -EINVAL;
+- break;
+- }
+- /* disable CCDC */
+- down_interruptible(&vpfe->lock);
+- ccdc_enable(FALSE);
+- vpfe->started = FALSE;
+- up(&vpfe->lock);
+- ret = videobuf_streamoff(&vpfe->bufqueue);
+- break;
+- }
+- case VPFE_CMD_CONFIG_CCDC:
+- {
+- /* this can be used directly and bypass the V4L2 APIs */
+- ccdc_params_ycbcr *params = &vpfe->ccdc_params;
+- if(vpfe->started){
+- /* only allowed if streaming is not started */
+- ret = -EBUSY;
+- break;
+- }
+- down_interruptible(&vpfe->lock);
+- /* make sure the other v4l2 related fields
+- have consistant settings */
+- *params = (*(ccdc_params_ycbcr *) arg);
+- vpfe->vwin = params->win;
+- if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
+- vpfe->field = V4L2_FIELD_INTERLACED;
+- } else if (params->buf_type ==
+- CCDC_BUFTYPE_FLD_SEPARATED) {
+- vpfe->field = V4L2_FIELD_SEQ_TB;
+- }
+- if (params->pix_order == CCDC_PIXORDER_YCBYCR) {
+- vpfe->pixelfmt = V4L2_PIX_FMT_YUYV;
+- } else if (params->pix_order == CCDC_PIXORDER_CBYCRY) {
+- vpfe->pixelfmt = V4L2_PIX_FMT_UYVY;
+- }
+- up(&vpfe->lock);
+- break;
+- }
+- case VPFE_CMD_CONFIG_TVP5146:
+- /* this can be used directly and bypass the V4L2 APIs */
+- {
+- /* the settings here must be consistant with that of the CCDC's,
+- driver does not check the consistancy */
+- tvp5146_params *params = (tvp5146_params *) arg;
+- v4l2_std_id std = 0;
+- if(vpfe->started){
+- /* only allowed if streaming is not started */
+- ret = -EBUSY;
+- break;
+- }
+- down_interruptible(&vpfe->lock);
+- /*make sure the other v4l2 related fields have consistant settings */
+- switch (params->mode & 0x7) {
+- case TVP5146_MODE_NTSC:
+- std = V4L2_STD_NTSC;
+- break;
+- case TVP5146_MODE_PAL:
+- std = V4L2_STD_PAL;
+- break;
+- case TVP5146_MODE_PAL_M:
+- std = V4L2_STD_PAL_M;
+- break;
+- case TVP5146_MODE_PAL_CN:
+- std = V4L2_STD_PAL_N;
+- break;
+- case TVP5146_MODE_SECAM:
+- std = V4L2_STD_SECAM;
+- break;
+- case TVP5146_MODE_PAL_60:
+- std = V4L2_STD_PAL_60;
+- break;
+- }
+-
+- if (params->mode & 0x8) { /* square pixel mode */
+- std <<= 32;
+- }
+-
+- if (params->mode == TVP5146_MODE_AUTO) { /* auto-detection modes */
+- std = VPFE_STD_AUTO;
+- } else if (params->mode == TVP5146_MODE_AUTO_SQP) {
+- std = VPFE_STD_AUTO_SQP;
+- }
+-
+- if (std & V4L2_STD_625_50) {
+- vpfe->bounds = pal_bounds;
+- vpfe->pixelaspect = pal_aspect;
+- } else if (std & V4L2_STD_525_60) {
+- vpfe->bounds = ntsc_bounds;
+- vpfe->pixelaspect = ntsc_aspect;
+- } else if (std & VPFE_STD_625_50_SQP) {
+- vpfe->bounds = palsp_bounds;
+- vpfe->pixelaspect = sp_aspect;
+- } else if (std & VPFE_STD_525_60_SQP) {
+- vpfe->bounds = ntscsp_bounds;
+- vpfe->pixelaspect = sp_aspect;
+- }
+- vpfe->std = std;
+- tvp5146_ctrl(TVP5146_CONFIG, params);
+- vpfe->tvp5146_params = *params;
+- up(&vpfe->lock);
+- break;
+- }
+- default:
+- ret = -ENOIOCTLCMD;
+- break;
+- } /* end switch(cmd) */
+- return ret;
+-}
+-
+-static int vpfe_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
+-{
+- int ret;
+- ret = video_usercopy(inode, file, cmd, arg, vpfe_doioctl);
+- if( cmd == VIDIOC_S_FMT || cmd == VIDIOC_TRY_FMT ){
+- ret = video_usercopy(inode, file, VIDIOC_G_FMT,
+- arg, vpfe_doioctl);
+- }
+- return ret;
+-}
+-
+-static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
+-{
+- return videobuf_mmap_mapper(&vpfe_device.bufqueue, vma);
+-}
+-
+-static int vpfe_open(struct inode *inode, struct file *filep)
+-{
+- int minor = iminor(inode);
+- vpfe_obj *vpfe = NULL;
+- vpfe_fh *fh = NULL;
+-
+- debug_print(KERN_INFO "vpfe: open minor=%d\n", minor);
+-
+- /* check to make sure the minor numbers match */
+- if (vpfe_device.video_dev && vpfe_device.video_dev->minor == minor) {
+- vpfe = &vpfe_device;
+- } else { /* device not found here */
+- return -ENODEV;
+- }
+-
+- /* allocate per filehandle data */
+- if ((fh = kmalloc(sizeof(*fh), GFP_KERNEL)) == NULL) {
+- return -ENOMEM;
+- }
+- filep->private_data = fh;
+- fh->dev = vpfe;
+- fh->io_allowed = FALSE;
+- fh->prio = V4L2_PRIORITY_UNSET;
+- v4l2_prio_open(&vpfe->prio, &fh->prio);
+- vpfe->usrs++;
+-
+- return 0;
+-}
+-
+-static int vpfe_release(struct inode *inode, struct file *filep)
+-{
+- vpfe_fh *fh = filep->private_data;
+- vpfe_obj *vpfe = fh->dev;
+-
+- down_interruptible(&vpfe->lock);
+- if (fh->io_allowed) {
+- vpfe->io_usrs = 0;
+- ccdc_enable(FALSE);
+- vpfe->started = FALSE;
+- videobuf_queue_cancel(&vpfe->bufqueue);
+- vpfe->numbuffers = VPFE_DEFNUM_FBUFS;
+- }
+- vpfe->usrs--;
+- v4l2_prio_close(&vpfe->prio, &fh->prio);
+- filep->private_data = NULL;
+- kfree(fh);
+- up(&vpfe->lock);
+-
+- return 0;
+-}
+-
+-static struct file_operations vpfe_fops = {
+- .owner = THIS_MODULE,
+- .open = vpfe_open,
+- .release = vpfe_release,
+- .ioctl = vpfe_ioctl,
+- .mmap = vpfe_mmap
+-};
+-
+-static struct video_device vpfe_video_template = {
+- .name = "vpfe",
+- .type = VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,
+- .hardware = 0,
+- .fops = &vpfe_fops,
+- .minor = -1,
+-};
+-
+-static void vpfe_platform_release(struct device *device)
+-{
+- /* This is called when the reference count goes to zero. */
+-}
+-
+-static int __init vpfe_probe(struct device *device)
+-{
+- struct video_device *vfd;
+- vpfe_obj *vpfe = &vpfe_device;
+-
+- /* alloc video device */
+- if ((vfd = video_device_alloc()) == NULL) {
+- return -ENOMEM;
+- }
+- *vfd = vpfe_video_template;
+- vfd->dev = device;
+- vfd->release = video_device_release;
+- snprintf(vfd->name, sizeof(vfd->name), "DM644X_VPFE_DRIVER_V%d.%d.%d",
+- (VPFE_VERSION_CODE >> 16) & 0xff,
+- (VPFE_VERSION_CODE >> 8) & 0xff, (VPFE_VERSION_CODE) & 0xff);
+-
+- vpfe->video_dev = vfd;
+- vpfe->usrs = 0;
+- vpfe->io_usrs = 0;
+- vpfe->started = FALSE;
+- vpfe->latest_only = TRUE;
+-
+- v4l2_prio_init(&vpfe->prio);
+- init_MUTEX(&vpfe->lock);
+- /* register video device */
+- debug_print(KERN_INFO "trying to register vpfe device.\n");
+- debug_print(KERN_INFO "vpfe=%x,vpfe->video_dev=%x\n", (int)vpfe,
+- (int)&vpfe->video_dev);
+- if (video_register_device(vpfe->video_dev, VFL_TYPE_GRABBER, -1) < 0) {
+- video_device_release(vpfe->video_dev);
+- vpfe->video_dev = NULL;
+- return -1;
+- }
+-
+- debug_print(KERN_INFO "DM644X vpfe: driver version V%d.%d.%d loaded\n",
+- (VPFE_VERSION_CODE >> 16) & 0xff,
+- (VPFE_VERSION_CODE >> 8) & 0xff,
+- (VPFE_VERSION_CODE) & 0xff);
+-
+- debug_print(KERN_INFO "vpfe: registered device video%d\n",
+- vpfe->video_dev->minor & 0x1f);
+-
+- /* all done */
+- return 0;
+-}
+-
+-static int vpfe_remove(struct device *device)
+-{
+- /* un-register device */
+- video_unregister_device(vpfe_device.video_dev);
+-
+- return 0;
+-}
+-
+-#ifdef NEW
+-static struct platform_driver vpfe_driver = {
+- .driver = {
+- .name = "VPFE",
+- .owner = THIS_MODULE,
+- },
+- .probe = vpfe_probe,
+- .remove = vpfe_remove,
+-};
+-
+-#else
+-static struct device_driver vpfe_driver = {
+- .name = "vpfe",
+- .bus = &platform_bus_type,
+- .probe = vpfe_probe,
+- .remove = vpfe_remove,
+-};
+-#endif
+-
+-static struct platform_device _vpfe_device = {
+- .name = "vpfe",
+- .id = 1,
+- .dev = {
+- .release = vpfe_platform_release,
+- }
+-};
+-
+-static int vpfe_init(void)
+-{
+- int i = 0;
+- void *mem;
+- /* allocate memory at initialization time to guarentee availability */
+- for (i = 0; i < VPFE_DEFNUM_FBUFS; i++) {
+- mem = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA,
+- VPFE_MAX_FBUF_ORDER);
+- if (mem) {
+- unsigned long adr = (unsigned long)mem;
+- u32 size = PAGE_SIZE << VPFE_MAX_FBUF_ORDER;
+- while (size > 0) {
+- /* make sure the frame buffers
+- are never swapped out of memory */
+- SetPageReserved(virt_to_page(adr));
+- adr += PAGE_SIZE;
+- size -= PAGE_SIZE;
+- }
+- vpfe_device.fbuffers[i] = (u8 *) mem;
+- debug_print(KERN_INFO "memory address %d\t%x\n", i,
+- mem);
+- } else {
+- while (--i >= 0) {
+- free_pages((unsigned long)vpfe_device.fbuffers[i],
+- VPFE_MAX_FBUF_ORDER);
+- }
+- debug_print(KERN_INFO
+- "frame buffer memory allocation failed.\n");
+- return -ENOMEM;
+- }
+- }
+- if (driver_register(&vpfe_driver) != 0) {
+- debug_print(KERN_INFO "driver registration failed\n");
+- return -1;
+- }
+- if (platform_device_register(&_vpfe_device) != 0) {
+- driver_unregister(&vpfe_driver);
+- debug_print(KERN_INFO "device registration failed\n");
+- return -1;
+- }
+-
+- ccdc_reset();
+- tvp5146_ctrl(TVP5146_RESET, NULL);
+- /* configure the tvp5146 to default parameters */
+- tvp5146_ctrl(TVP5146_CONFIG, &vpfe_device.tvp5146_params);
+- /* setup interrupt handling */
+- request_irq(IRQ_VDINT0, vpfe_isr, SA_INTERRUPT,
+- "dm644xv4l2", (void *)&vpfe_device);
+-
+- printk(KERN_INFO "DaVinci v4l2 capture driver V1.0 loaded\n");
+- return 0;
+-}
+-
+-static void vpfe_cleanup(void)
+-{
+- int i = vpfe_device.numbuffers;
+- platform_device_unregister(&_vpfe_device);
+- driver_unregister(&vpfe_driver);
+- /* disable interrupt */
+- free_irq(IRQ_VDINT0, &vpfe_device);
+-
+- while (--i >= 0) {
+- free_pages((unsigned long)vpfe_device.fbuffers[i],
+- VPFE_MAX_FBUF_ORDER);
+- }
+- debug_print(KERN_INFO "vpfe: un-registered device video.\n");
+-}
+-
+-module_init(vpfe_init);
+-module_exit(vpfe_cleanup);
+diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h
+new file mode 100644
+index 0000000..c2b4e11
+--- /dev/null
++++ b/include/media/davinci/vpfe_capture.h
+@@ -0,0 +1,272 @@
++/*
++ * Copyright (C) 2008-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _VPFE_CAPTURE_H
++#define _VPFE_CAPTURE_H
++
++#ifdef __KERNEL__
++
++/* Header files */
++#include <linux/videodev2.h>
++#include <media/v4l2-ioctl.h>
++#include <media/v4l2-int-device.h>
++#include <media/videobuf-dma-contig.h>
++#include <media/davinci/ccdc_hw_device.h>
++
++#define VPFE_CAPTURE_NUM_DECODERS 5
++
++/* Macros */
++#define VPFE_MAJOR_RELEASE 0
++#define VPFE_MINOR_RELEASE 0
++#define VPFE_BUILD 1
++#define VPFE_CAPTURE_VERSION_CODE ((VPFE_MAJOR_RELEASE << 16) | \
++ (VPFE_MINOR_RELEASE << 8) | \
++ VPFE_BUILD)
++
++#define VPFE_VALID_FIELD(field) ((V4L2_FIELD_ANY == field) || \
++ (V4L2_FIELD_NONE == field) || \
++ (V4L2_FIELD_INTERLACED == field) || \
++ (V4L2_FIELD_SEQ_TB == field))
++
++#define VPFE_VALID_BUFFER_TYPE(buftype) { \
++ (V4L2_BUF_TYPE_VIDEO_CAPTURE == buftype) }
++
++#define VPFE_CAPTURE_MAX_DEVICES 1
++#define VPFE_MAX_DECODER_STD 50
++#define VPFE_TIMER_COUNT 5
++#define VPFE_SLICED_BUF_SIZE 256
++#define VPFE_SLICED_MAX_SERVICES 3
++#define VPFE_HBI_INDEX 2
++#define VPFE_VBI_INDEX 1
++#define VPFE_VIDEO_INDEX 0
++
++/* Define for device type to be passed in init */
++#define MT9T001 0
++#define TVP5146 1
++#define MT9T031 2
++#define MT9P031 3
++#define TVP7002 4
++
++#define VPFE_NUMBER_OF_OBJECTS 1
++
++/* Macros */
++#define ISALIGNED(a) (0 == (a % 32))
++#define ISEXTERNALCMD(cmd) ((VPFE_CMD_S_DECODER_PARAMS == cmd) || \
++ (VPFE_CMD_G_DECODER_PARAMS == cmd) || \
++ (VPFE_CMD_S_CCDC_PARAMS == cmd) || \
++ (VPFE_CMD_G_CCDC_PARAMS == cmd) || \
++ (VPFE_CMD_CONFIG_CCDC_YCBCR == cmd) || \
++ (VPFE_CMD_CONFIG_CCDC_RAW == cmd) || \
++ (VPFE_CMD_CONFIG_TVP5146 == cmd) || \
++ (VPFE_CMD_S_MT9T001_PARAMS == cmd) || \
++ (VPFE_CMD_G_MT9T001_PARAMS == cmd))
++
++#include <media/v4l2-dev.h>
++#define VPFE_MAX_SECOND_RESOLUTION_SIZE (640 * 480 * 2)
++#define ROUND32(x) ((((x)+31) >> 5) << 5)
++#define ISNULL(val) ((val == NULL) ? 1 : 0)
++#define VPFE_MAX_PIX_FORMATS 6
++enum vpfe_irq_use_type {
++ VPFE_USE_CCDC_IRQ,
++ VPFE_USE_IMP_IRQ,
++ VPFE_NO_IRQ
++};
++
++/* enumerated data types */
++/* Enumerated data type to give id to each device per channel */
++enum vpfe_channel_id {
++ /* Channel0 Video */
++ VPFE_CHANNEL0_VIDEO = 0,
++ /* Channel1 Video */
++ VPFE_CHANNEL1_VIDEO,
++};
++
++/* structures */
++/* Table to keep track of the standards supported in all the decoders */
++struct vpfe_decoder_std_tbl {
++ u8 dec_idx;
++ u8 std_idx;
++ v4l2_std_id std;
++};
++
++enum output_src {
++ VPFE_CCDC_OUT = 1,
++ VPFE_IMP_PREV_OUT = 2,
++ VPFE_IMP_RSZ_OUT = 4
++};
++
++struct vpfe_pixel_format {
++ unsigned int pix_fmt;
++ char *desc;
++ enum vpfe_hw_pix_format hw_fmt;
++};
++
++struct vpfe_std_info {
++ int activepixels;
++ int activelines;
++ /* current frame format */
++ int frame_format;
++};
++
++#define VPFE_MAX_DEC_INPUTS 5
++
++/* To map high level input name to decoder input */
++struct vpfe_dec_input {
++ char dec_name[32];
++ struct v4l2_input input;
++ struct v4l2_routing route;
++ int routing_supported;
++};
++
++struct vpfe_capture_input {
++ int num_inputs;
++ struct vpfe_dec_input inputs[VPFE_MAX_DEC_INPUTS];
++ int current_input;
++};
++
++struct video_obj {
++ /* Keeps track of the information about the standard */
++ struct vpfe_std_info std_info;
++ /* index into std table */
++ int index;
++ /* All inputs to the driver */
++ struct vpfe_capture_input *input;
++};
++
++struct common_obj {
++ /* Buffer specific parameters */
++ /* List of buffer pointers for storing frames */
++ u8 *fbuffers[VIDEO_MAX_FRAME];
++ /* number of buffers in fbuffers */
++ u32 numbuffers;
++ /* Pointer pointing to current v4l2_buffer */
++ struct videobuf_buffer *curFrm;
++ /* Pointer pointing to next v4l2_buffer */
++ struct videobuf_buffer *nextFrm;
++ /* This field keeps track of type of buffer exchange mechanism
++ * user has selected
++ */
++ enum v4l2_memory memory;
++ /* Used to store pixel format */
++ struct v4l2_format fmt;
++ /* Buffer queue used in video-buf */
++ struct videobuf_queue buffer_queue;
++ /* Queue of filled frames */
++ struct list_head dma_queue;
++ /* Used in video-buf */
++ spinlock_t irqlock;
++ /* channel specifc parameters */
++ /* lock used to access this structure */
++ struct mutex lock;
++ /* number of users performing IO */
++ u32 io_usrs;
++ /* Indicates whether streaming started */
++ u8 started;
++ /* offset where second field starts from the starting of the
++ * buffer for field seperated YCbCr formats
++ */
++ u32 field_off;
++ /* Indicates width of the image data */
++ u32 width;
++ /* Indicates height of the image data */
++ u32 height;
++ /* used when IMP is chained to store the crop window which
++ * is different from the image window
++ */
++ struct v4l2_rect crop;
++};
++
++struct channel_obj {
++ /* V4l2 specific parameters */
++ /* Identifies video device for this channel */
++ struct video_device *video_dev;
++ /* Used to keep track of state of the priority */
++ struct v4l2_prio_state prio;
++ /* number of open instances of the channel */
++ u32 usrs;
++ /* Indicates id of the field which is being displayed */
++ u32 field_id;
++ /* flag to indicate whether decoder is initialized */
++ u8 initialized;
++ /* Identifies channel */
++ enum vpfe_channel_id channel_id;
++ /* current interface parameters */
++ struct v4l2_ifparm ifparams;
++ /* current interface type */
++ enum vpfe_hw_if_type vpfe_if;
++ /* number of decoders registered with the master */
++ u8 numdecoders;
++ /* decoder slave ptrs */
++ struct v4l2_int_device *decoder[VPFE_CAPTURE_NUM_DECODERS];
++ /* Index of the currently selected decoder */
++ u8 current_decoder;
++ void *res1;
++ void *res2;
++ /* To track if we need to attach IPIPE IRQ or CCDC IRQ */
++ enum vpfe_irq_use_type irq_type;
++ /* CCDC IRQs used when CCDC/ISIF output to SDRAM */
++ unsigned int ccdc_irq0;
++ unsigned int ccdc_irq1;
++ enum output_src out_from;
++ struct common_obj common[VPFE_NUMBER_OF_OBJECTS];
++ struct video_obj video;
++};
++
++/* File handle structure */
++struct vpfe_fh {
++ /* pointer to channel object for opened device */
++ struct channel_obj *channel;
++ /* Indicates whether this file handle is doing IO */
++ u8 io_allowed[VPFE_NUMBER_OF_OBJECTS];
++ /* Used to keep track priority of this instance */
++ enum v4l2_priority prio;
++ /* Used to indicate channel is initialize or not */
++ u8 initialized;
++};
++
++/* vpfe device structure */
++struct vpfe_device {
++ struct channel_obj *dev[CCDC_CAPTURE_NUM_CHANNELS];
++};
++
++struct vpfe_config_params {
++ u8 min_numbuffers;
++ u8 numbuffers[CCDC_CAPTURE_NUM_CHANNELS];
++ u32 min_bufsize[CCDC_CAPTURE_NUM_CHANNELS];
++ u32 channel_bufsize[CCDC_CAPTURE_NUM_CHANNELS];
++};
++
++
++/* SoC Capture hardware interface */
++extern struct ccdc_hw_device ccdc_hw_dev;
++#define CAPTURE_DRV_NAME "vpfe-capture"
++#endif /* End of __KERNEL__ */
++
++/* IOCTLs */
++#define VPFE_CMD_LATEST_FRM_ONLY \
++ _IOW('V', BASE_VIDIOC_PRIVATE + 1, int)
++#define VPFE_CMD_G_DECODER_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 2, \
++ void *)
++#define VPFE_CMD_S_DECODER_PARAMS _IOW('V', BASE_VIDIOC_PRIVATE + 3, \
++ void *)
++#define VPFE_CMD_S_SOC_PARAMS _IOW('V', BASE_VIDIOC_PRIVATE + 4, \
++ void *)
++#define VPFE_CMD_G_SOC_PARAMS _IOW('V', BASE_VIDIOC_PRIVATE + 5, \
++ void *)
++
++#endif /* _DAVINCI_VPFE_H */
+diff --git a/include/media/davinci/vpfe_types.h b/include/media/davinci/vpfe_types.h
+new file mode 100644
+index 0000000..09d0531
+--- /dev/null
++++ b/include/media/davinci/vpfe_types.h
+@@ -0,0 +1,71 @@
++/*
++ * Copyright (C) 2008-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option)any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VPFE_TYPES_H
++#define _VPFE_TYPES_H
++
++#ifdef __KERNEL__
++
++enum vpfe_hw_if_type {
++ /* BT656 - 8 bit */
++ VPFE_BT656,
++ /* BT1120 - 16 bit */
++ VPFE_BT1120,
++ /* Raw Bayer */
++ VPFE_RAW_BAYER,
++ /* YCbCr - 8 bit with external sync */
++ VPFE_YCBCR_SYNC_8,
++ /* YCbCr - 16 bit with external sync */
++ VPFE_YCBCR_SYNC_16,
++ /* BT656 - 10 bit */
++ VPFE_BT656_10BIT
++};
++
++enum vpfe_sync_pol {
++ VPFE_SYNC_POSITIVE = 0,
++ VPFE_SYNC_NEGATIVE
++};
++
++/* Pixel format to be used across vpfe driver */
++enum vpfe_hw_pix_format {
++ VPFE_BAYER_8BIT_PACK,
++ VPFE_BAYER_8BIT_PACK_ALAW,
++ VPFE_BAYER_8BIT_PACK_DPCM,
++ VPFE_BAYER_12BIT_PACK,
++ /* 16 bit Bayer */
++ VPFE_BAYER,
++ VPFE_UYVY,
++ VPFE_YUYV,
++ VPFE_RGB565,
++ VPFE_RGB888,
++ /* YUV 420 */
++ VPFE_YUV420,
++ /* YUV 420, Y data */
++ VPFE_420_Y,
++ /* YUV 420, C data */
++ VPFE_420_C,
++};
++
++/* interface description */
++struct vpfe_hw_if_param {
++ enum vpfe_hw_if_type if_type;
++ enum vpfe_sync_pol hdpol;
++ enum vpfe_sync_pol vdpol;
++};
++
++#endif
++#endif
+diff --git a/include/media/davinci_vpfe.h b/include/media/davinci_vpfe.h
+deleted file mode 100644
+index 26e7b2c..0000000
+--- a/include/media/davinci_vpfe.h
++++ /dev/null
+@@ -1,121 +0,0 @@
+-/*
+- * Copyright (C) 2006 Texas Instruments Inc
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-/* davinci_vpfe.h */
+-
+-#ifndef DAVINCI_VPFE_H
+-#define DAVINCI_VPFE_H
+-#ifdef __KERNEL__
+-#include <media/v4l2-dev.h>
+-#endif
+-
+-#include <media/ccdc_davinci.h>
+-#include <media/tvp5146.h>
+-
+-#define TRUE 1
+-#define FALSE 0
+-
+-/* vpfe specific video standards */
+-#define VPFE_STD_625_50_SQP ((V4L2_STD_625_50)<<32)
+-#define VPFE_STD_525_60_SQP ((V4L2_STD_525_60)<<32)
+-#define VPFE_STD_AUTO ((v4l2_std_id)(0x1000000000000000ULL))
+-#define VPFE_STD_AUTO_SQP ((v4l2_std_id)(0x2000000000000000ULL))
+-
+-#define VPFE_CMD_CONFIG_CCDC _IOW('V',BASE_VIDIOC_PRIVATE + 1,ccdc_params_ycbcr)
+-#define VPFE_CMD_LATEST_FRM_ONLY _IOW('V',BASE_VIDIOC_PRIVATE + 2,int)
+-#define VPFE_CMD_CONFIG_TVP5146 _IOW('V',BASE_VIDIOC_PRIVATE + 3,tvp5146_params)
+-
+-/* settings for commonly used video formats */
+-#define VPFE_WIN_NTSC {0,0,720,480}
+-#define VPFE_WIN_PAL {0,0,720,576}
+-#define VPFE_WIN_NTSC_SP {0,0,640,480} /* ntsc square pixel */
+-#define VPFE_WIN_PAL_SP {0,0,768,576} /* pal square pixel */
+-#define VPFE_WIN_CIF {0,0,352,288}
+-#define VPFE_WIN_QCIF {0,0,176,144}
+-#define VPFE_WIN_QVGA {0,0,320,240}
+-#define VPFE_WIN_SIF {0,0,352,240}
+-
+-
+-#ifdef __KERNEL__
+-
+-#include <media/video-buf.h>
+-
+-#define VPFE_MAJOR_RELEASE 0
+-#define VPFE_MINOR_RELEASE 0
+-#define VPFE_BUILD 1
+-
+-#define VPFE_VERSION_CODE \
+- (VPFE_MAJOR_RELEASE<<16) | (VPFE_MINOR_RELEASE<<8) | VPFE_BUILD
+-
+-/* By default, the driver is setup for auto-swich mode */
+-#define VPFE_DEFAULT_STD VPFE_STD_AUTO
+-
+-#define VPFE_PIXELASPECT_NTSC {11, 10}
+-#define VPFE_PIXELASPECT_PAL {54, 59}
+-#define VPFE_PIXELASPECT_NTSC_SP {1, 1}
+-#define VPFE_PIXELASPECT_PAL_SP {1, 1}
+-#define VPFE_PIXELASPECT_DEFAULT {1, 1}
+-
+-#define VPFE_MAX_FRAME_WIDTH 768 /* account for PAL Square pixel mode */
+-#define VPFE_MAX_FRAME_HEIGHT 576 /* account for PAL */
+-/* 4:2:2 data */
+-#define VPFE_MAX_FBUF_SIZE (VPFE_MAX_FRAME_WIDTH*VPFE_MAX_FRAME_HEIGHT*2)
+-/* frame buffers allocate at driver initialization time */
+-#define VPFE_DEFNUM_FBUFS 3
+-
+-#define VPFE_MAX_FBUF_ORDER \
+- get_order(roundup_pow_of_two(VPFE_MAX_FBUF_SIZE))
+-
+-/* device object */
+-typedef struct vpfe_obj {
+- struct video_device *video_dev;
+- struct videobuf_queue bufqueue;/* queue with frame buffers */
+- struct list_head dma_queue;
+- u32 latest_only; /* indicate whether to return the most */
+- /* recent captured buffers only */
+- u32 usrs;
+- u32 io_usrs;
+- struct v4l2_prio_state prio;
+- v4l2_std_id std;
+- struct v4l2_rect vwin;
+- struct v4l2_rect bounds;
+- struct v4l2_fract pixelaspect;
+- spinlock_t irqlock;
+- struct semaphore lock;
+- enum v4l2_field field;
+- u32 pixelfmt;
+- u32 numbuffers;
+- u8* fbuffers[VIDEO_MAX_FRAME];
+- struct videobuf_buffer *curFrm;
+- struct videobuf_buffer *nextFrm;
+- int field_id;
+- int mode_changed;
+- int started;
+- int field_offset;
+- tvp5146_params tvp5146_params;
+- ccdc_params_ycbcr ccdc_params;
+-} vpfe_obj;
+-
+-/* file handle */
+-typedef struct vpfe_fh {
+- struct vpfe_obj *dev;
+- int io_allowed;
+- enum v4l2_priority prio;
+-} vpfe_fh;
+-#endif
+-
+-#endif /* DAVINCI_VPFE_H */
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci/vfpe2.patch b/recipes/linux/linux-davinci/vfpe2.patch
new file mode 100644
index 0000000000..8915ee33b6
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe2.patch
@@ -0,0 +1,200 @@
+Subject:
+[PATCH 2/7] interface for configuring CCDC and common ccdc types
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:22:39 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Adding an interface for configuring ccdc as per data format of decoder
+output. Also adds a header file for common ccdc data types.
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ include/media/davinci/ccdc_common.h | 48 +++++++++++++
+ include/media/davinci/ccdc_hw_device.h | 117 ++++++++++++++++++++++++++++++++
+ 2 files changed, 165 insertions(+), 0 deletions(-)
+ create mode 100644 include/media/davinci/ccdc_common.h
+ create mode 100644 include/media/davinci/ccdc_hw_device.h
+
+diff --git a/include/media/davinci/ccdc_common.h b/include/media/davinci/ccdc_common.h
+new file mode 100644
+index 0000000..0992af5
+--- /dev/null
++++ b/include/media/davinci/ccdc_common.h
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2008-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ **************************************************************************/
++#ifndef _CCDC_COMMON_H
++#define _CCDC_COMMON_H
++enum ccdc_pixfmt {
++ CCDC_PIXFMT_RAW = 0,
++ CCDC_PIXFMT_YCBCR_16BIT = 1,
++ CCDC_PIXFMT_YCBCR_8BIT = 2
++};
++
++enum ccdc_frmfmt {
++ CCDC_FRMFMT_PROGRESSIVE = 0,
++ CCDC_FRMFMT_INTERLACED = 1
++};
++
++/* PIXEL ORDER IN MEMORY from LSB to MSB */
++/* only applicable for 8-bit input mode */
++enum ccdc_pixorder {
++ CCDC_PIXORDER_CBYCRY = 1,
++ CCDC_PIXORDER_YCBYCR = 0
++};
++
++enum ccdc_buftype {
++ CCDC_BUFTYPE_FLD_INTERLEAVED,
++ CCDC_BUFTYPE_FLD_SEPARATED
++};
++
++enum ccdc_pinpol {
++ CCDC_PINPOL_POSITIVE = 0,
++ CCDC_PINPOL_NEGATIVE = 1
++};
++#endif
+diff --git a/include/media/davinci/ccdc_hw_device.h b/include/media/davinci/ccdc_hw_device.h
+new file mode 100644
+index 0000000..4ae9876
+--- /dev/null
++++ b/include/media/davinci/ccdc_hw_device.h
+@@ -0,0 +1,117 @@
++/*
++ * Copyright (C) 2008 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * ccdc device API
++ */
++#ifndef _CCDC_HW_DEVICE_H
++#define _CCDC_HW_DEVICE_H
++
++#ifdef __KERNEL__
++#include <linux/videodev2.h>
++#include <linux/device.h>
++#include <media/davinci/vpfe_types.h>
++#include <media/davinci/ccdc_common.h>
++/*
++ * Maximum number of capture channels supported by VPFE
++ */
++#define CCDC_CAPTURE_NUM_CHANNELS 1
++/*
++ * vpfe hw interface
++ */
++struct ccdc_hw_device {
++
++ /* vpfe device name */
++ char name[30];
++
++ /* Pointer to initialize function to initialize ccdc device */
++ int (*open) (struct device *dev);
++ /* Set of functions pointers for control related functions.
++ * Use queryctrl of decoder interface to check if it is a decoder
++ * control id. If not passed to ccdc to process it
++ */
++ /* set ccdc base address */
++ void (*set_ccdc_base)(void *base, int size);
++
++ /* set vpss base address */
++ void (*set_vpss_base)(void *base, int size);
++
++ /* get ccdc base */
++ void * (*get_ccdc_base)(void);
++
++ /* get vpss base */
++ void * (*get_vpss_base)(void);
++
++ void (*enable) (int en);
++ /*
++ * Pointer to function to enable or disable ccdc
++ */
++ u32 (*reset) (void);
++ /* reset sbl. only for 6446 */
++ void (*enable_out_to_sdram) (int en);
++ /* Pointer to function to set hw frame type */
++ int (*set_hw_if_type) (enum vpfe_hw_if_type iface);
++ /* get interface parameters */
++ int (*get_hw_if_params) (struct vpfe_hw_if_param *param);
++ /* Pointer to function to set parameters. Used
++ * for implementing VPFE_S_CCDC_PARAMS
++ */
++ int (*setparams) (void *params);
++ /* Pointer to function to get parameter. Used
++ * for implementing VPFE_G_CCDC_PARAMS
++ */
++ int (*getparams) (void *params);
++ /* Pointer to function to configure ccdc */
++ int (*configure) (void);
++
++ /* enumerate hw pix formats */
++ int (*enum_pix)(enum vpfe_hw_pix_format *hw_pix, int i);
++ /* Pointer to function to set buffer type */
++ int (*set_buftype) (enum ccdc_buftype buf_type);
++ /* Pointer to function to get buffer type */
++ int (*get_buftype) (enum ccdc_buftype *buf_type);
++ /* Pointer to function to set frame format */
++ int (*set_frame_format) (enum ccdc_frmfmt frm_fmt);
++ /* Pointer to function to get frame format */
++ int (*get_frame_format) (enum ccdc_frmfmt *frm_fmt);
++ /* Pointer to function to set buffer type */
++ int (*get_pixelformat) (enum vpfe_hw_pix_format *pixfmt);
++ /* Pointer to function to get pixel format. Uses V4L2 type */
++ int (*set_pixelformat) (enum vpfe_hw_pix_format pixfmt);
++ /* Pointer to function to set image window */
++ int (*set_image_window) (struct v4l2_rect *win);
++ /* Pointer to function to set image window */
++ int (*get_image_window) (struct v4l2_rect *win);
++ /* Pointer to function to get line length */
++ int (*get_line_length) (unsigned int *len);
++
++ /* Query SoC control IDs */
++ int (*queryctrl)(struct v4l2_queryctrl *qctrl);
++ /* Set SoC control */
++ int (*setcontrol)(struct v4l2_control *ctrl);
++ /* Get SoC control */
++ int (*getcontrol)(struct v4l2_control *ctrl);
++ /* Pointer to function to set current standard info */
++ /* Pointer to function to set frame buffer address */
++ void (*setfbaddr) (unsigned long addr);
++ /* Pointer to function to get field id */
++ int (*getfid) (void);
++ /* Pointer to deinitialize function */
++ int (*close) (struct device *dev);
++};
++
++#endif
++#endif
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci/vfpe3.patch b/recipes/linux/linux-davinci/vfpe3.patch
new file mode 100644
index 0000000000..f655b507a0
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe3.patch
@@ -0,0 +1,2558 @@
+Subject:
+[PATCH 3/7] ccdc hw module and header file for DM355
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:22:56 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Adds ccdc hw module and it's header file
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ drivers/media/video/davinci/ccdc_dm355.c | 1766 ++++++++++++++++++++++++++++++
+ drivers/media/video/davinci/ccdc_dm355.h | 758 +++++++++++++
+ 2 files changed, 2524 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/davinci/ccdc_dm355.c
+ create mode 100644 drivers/media/video/davinci/ccdc_dm355.h
+
+diff --git a/drivers/media/video/davinci/ccdc_dm355.c b/drivers/media/video/davinci/ccdc_dm355.c
+new file mode 100644
+index 0000000..b03dbaf
+--- /dev/null
++++ b/drivers/media/video/davinci/ccdc_dm355.c
+@@ -0,0 +1,1766 @@
++/*
++ * Copyright (C) 2005-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/platform_device.h>
++#include <linux/uaccess.h>
++#include <asm/page.h>
++#include <media/davinci/ccdc_hw_device.h>
++#include "ccdc_dm355.h"
++
++static struct device *dev;
++
++/*Object for CCDC raw mode */
++static struct ccdc_params_raw ccdc_hw_params_raw = {
++ .pix_fmt = CCDC_PIXFMT_RAW,
++ .frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
++ .win = CCDC_WIN_VGA,
++ .fid_pol = CCDC_PINPOL_POSITIVE,
++ .vd_pol = CCDC_PINPOL_POSITIVE,
++ .hd_pol = CCDC_PINPOL_POSITIVE,
++ .image_invert_enable = 0,
++ .data_sz = _10BITS,
++ .med_filt_thres = 0,
++ .mfilt1 = NO_MEDIAN_FILTER1,
++ .mfilt2 = NO_MEDIAN_FILTER2,
++ .ccdc_offset = 0,
++ .gain = {
++ .r_ye = 256,
++ .gb_g = 256,
++ .gr_cy = 256,
++ .b_mg = 256
++ },
++ .lpf_enable = 0,
++ .datasft = 2,
++ .alaw = {
++ .b_alaw_enable = 0,
++ .gama_wd = 2
++ },
++ .blk_clamp = {
++ .b_clamp_enable = 0,
++ .sample_pixel = 1,
++ .start_pixel = 0,
++ .dc_sub = 25
++ },
++ .blk_comp = {
++ .b_comp = 0,
++ .gb_comp = 0,
++ .gr_comp = 0,
++ .r_comp = 0
++ },
++ .vertical_dft = {
++ .ver_dft_en = 0
++ },
++ .lens_sh_corr = {
++ .lsc_enable = 0
++ },
++ .data_formatter_r = {
++ .fmt_enable = 0
++ },
++ .color_space_con = {
++ .csc_enable = 0
++ },
++ .col_pat_field0 = {
++ .olop = CCDC_GREEN_BLUE,
++ .olep = CCDC_BLUE,
++ .elop = CCDC_RED,
++ .elep = CCDC_GREEN_RED
++ },
++ .col_pat_field1 = {
++ .olop = CCDC_GREEN_BLUE,
++ .olep = CCDC_BLUE,
++ .elop = CCDC_RED,
++ .elep = CCDC_GREEN_RED
++ }
++};
++
++
++/*Object for CCDC ycbcr mode */
++static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = {
++ .win = CCDC_WIN_PAL,
++ .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
++ .frm_fmt = CCDC_FRMFMT_INTERLACED,
++ .fid_pol = CCDC_PINPOL_POSITIVE,
++ .vd_pol = CCDC_PINPOL_POSITIVE,
++ .hd_pol = CCDC_PINPOL_POSITIVE,
++ .bt656_enable = 1,
++ .pix_order = CCDC_PIXORDER_CBYCRY,
++ .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
++};
++
++static struct v4l2_queryctrl ccdc_control_info[CCDC_MAX_CONTROLS] = {
++ {
++ .id = CCDC_CID_R_GAIN,
++ .name = "R/Ye WB Gain",
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .minimum = 0,
++ .maximum = 2047,
++ .step = 1,
++ .default_value = 256
++ },
++ {
++ .id = CCDC_CID_GR_GAIN,
++ .name = "Gr/Cy WB Gain",
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .minimum = 0,
++ .maximum = 2047,
++ .step = 1,
++ .default_value = 256
++ },
++ {
++ .id = CCDC_CID_GB_GAIN,
++ .name = "Gb/G WB Gain",
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .minimum = 0,
++ .maximum = 2047,
++ .step = 1,
++ .default_value = 256
++ },
++ {
++ .id = CCDC_CID_B_GAIN,
++ .name = "B/Mg WB Gain",
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .minimum = 0,
++ .maximum = 2047,
++ .step = 1,
++ .default_value = 256
++ },
++ {
++ .id = CCDC_CID_OFFSET,
++ .name = "Offset",
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .minimum = 0,
++ .maximum = 1023,
++ .step = 1,
++ .default_value = 0
++ }
++};
++
++static struct ccdc_config_params_raw ccdc_hw_params_raw_temp;
++static enum vpfe_hw_if_type ccdc_if_type;
++static void *__iomem ccdc_base_addr;
++static int ccdc_addr_size;
++static void *__iomem vpss_base_addr;
++static int vpss_addr_size;
++
++#define CCDC_MAX_RAW_BAYER_FORMATS 2
++#define CCDC_MAX_RAW_YUV_FORMATS 2
++
++/* Raw Bayer formats */
++enum vpfe_hw_pix_format ccdc_raw_bayer_hw_formats[CCDC_MAX_RAW_BAYER_FORMATS] =
++ {VPFE_BAYER_8BIT_PACK_ALAW, VPFE_BAYER};
++
++/* Raw YUV formats */
++enum vpfe_hw_pix_format ccdc_raw_yuv_hw_formats[CCDC_MAX_RAW_YUV_FORMATS] =
++ {VPFE_UYVY, VPFE_YUYV};
++
++/* register access routines */
++static inline u32 regr(u32 offset)
++{
++ if (offset <= ccdc_addr_size)
++ return __raw_readl(ccdc_base_addr + offset);
++ else {
++ dev_err(dev, "offset exceeds ccdc register address space\n");
++ return -1;
++ }
++}
++
++static inline u32 regw(u32 val, u32 offset)
++{
++ if (offset <= ccdc_addr_size) {
++ __raw_writel(val, ccdc_base_addr + offset);
++ return val;
++ } else {
++ dev_err(dev, "offset exceeds ccdc register address space\n");
++ return -1;
++ }
++}
++
++/* register access routines */
++static inline u32 regr_bl(u32 offset)
++{
++ if (offset <= vpss_addr_size)
++ return __raw_readl(vpss_base_addr + offset);
++ else {
++ dev_err(dev, "offset exceeds vpss register address space\n");
++ return -1;
++ }
++}
++
++static inline u32 regw_bl(u32 val, u32 offset)
++{
++ if (offset <= vpss_addr_size) {
++ __raw_writel(val, vpss_base_addr + offset);
++ return val;
++ } else {
++ dev_err(dev, "offset exceeds vpss register address space\n");
++ return -1;
++ }
++}
++static void ccdc_set_ccdc_base(void *addr, int size)
++{
++ ccdc_base_addr = addr;
++ ccdc_addr_size = size;
++}
++
++static void ccdc_set_vpss_base(void *addr, int size)
++{
++ vpss_base_addr = addr;
++ vpss_addr_size = size;
++}
++
++static void *ccdc_get_ccdc_base(void)
++{
++ return (void *)ccdc_base_addr;
++}
++
++static void *ccdc_get_vpss_base(void)
++{
++ return (void *)vpss_base_addr;
++}
++
++static void ccdc_enable(int en)
++{
++ unsigned int temp;
++ temp = regr(SYNCEN);
++ temp &= (~0x1);
++ temp |= (en & 0x01);
++ regw(temp, SYNCEN);
++}
++
++static void ccdc_enable_output_to_sdram(int en)
++{
++ unsigned int temp;
++ temp = regr(SYNCEN);
++ temp &= (~(0x1 << 1));
++ temp |= (en & 0x01) << 1;
++ regw(temp, SYNCEN);
++}
++
++static void ccdc_config_gain_offset(void)
++{
++ /* configure gain */
++ regw(ccdc_hw_params_raw.gain.r_ye, RYEGAIN);
++ regw(ccdc_hw_params_raw.gain.gr_cy, GRCYGAIN);
++ regw(ccdc_hw_params_raw.gain.gb_g, GBGGAIN);
++ regw(ccdc_hw_params_raw.gain.b_mg, BMGGAIN);
++ /* configure offset */
++ regw(ccdc_hw_params_raw.ccdc_offset, OFFSET);
++}
++
++/* Query control. Only applicable for Bayer capture */
++static int ccdc_queryctrl(struct v4l2_queryctrl *qctrl)
++{
++ int i, id;
++ struct v4l2_queryctrl *control = NULL;
++
++ dev_dbg(dev, "ccdc_queryctrl: start\n");
++ if (NULL == qctrl) {
++ dev_err(dev, "ccdc_queryctrl : invalid user ptr\n");
++ return -EINVAL;
++ }
++
++ if (VPFE_RAW_BAYER != ccdc_if_type) {
++ dev_err(dev,
++ "ccdc_queryctrl : Not doing Raw Bayer Capture\n");
++ return -EINVAL;
++ }
++
++ id = qctrl->id;
++ memset(qctrl, 0, sizeof(struct v4l2_queryctrl));
++ for (i = 0; i < CCDC_MAX_CONTROLS; i++) {
++ control = &ccdc_control_info[i];
++ if (control->id == id)
++ break;
++ }
++ if (i == CCDC_MAX_CONTROLS) {
++ dev_err(dev, "ccdc_queryctrl : Invalid control ID\n");
++ return -EINVAL;
++ }
++ memcpy(qctrl, control, sizeof(struct v4l2_queryctrl));
++ dev_dbg(dev, "ccdc_queryctrl: end\n");
++ return 0;
++}
++
++static int ccdc_setcontrol(struct v4l2_control *ctrl)
++{
++ int i;
++ struct v4l2_queryctrl *control = NULL;
++ struct ccdc_gain *gain =
++ &ccdc_hw_params_raw.gain;
++
++ if (NULL == ctrl) {
++ dev_err(dev, "ccdc_setcontrol: invalid user ptr\n");
++ return -EINVAL;
++ }
++
++ if (ccdc_if_type != VPFE_RAW_BAYER) {
++ dev_err(dev,
++ "ccdc_setcontrol: Not doing Raw Bayer Capture\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; i < CCDC_MAX_CONTROLS; i++) {
++ control = &ccdc_control_info[i];
++ if (control->id == ctrl->id)
++ break;
++ }
++
++ if (i == CCDC_MAX_CONTROLS) {
++ dev_err(dev, "ccdc_queryctrl : Invalid control ID, 0x%x\n",
++ control->id);
++ return -EINVAL;
++ }
++
++ if (ctrl->value > control->maximum) {
++ dev_err(dev, "ccdc_queryctrl : Invalid control value\n");
++ return -EINVAL;
++ }
++
++ switch (ctrl->id) {
++ case CCDC_CID_R_GAIN:
++ gain->r_ye = ctrl->value & CCDC_GAIN_MASK;
++ break;
++ case CCDC_CID_GR_GAIN:
++ gain->gr_cy = ctrl->value & CCDC_GAIN_MASK;
++ break;
++ case CCDC_CID_GB_GAIN:
++ gain->gb_g = ctrl->value & CCDC_GAIN_MASK;
++ break;
++
++ case CCDC_CID_B_GAIN:
++ gain->b_mg = ctrl->value & CCDC_GAIN_MASK;
++ break;
++ default:
++ ccdc_hw_params_raw.ccdc_offset = ctrl->value & CCDC_OFFSET_MASK;
++ }
++
++ /* set it in hardware */
++ ccdc_config_gain_offset();
++ return 0;
++}
++
++static int ccdc_getcontrol(struct v4l2_control *ctrl)
++{
++ int i;
++ struct v4l2_queryctrl *control = NULL;
++
++ if (NULL == ctrl) {
++ dev_err(dev, "ccdc_setcontrol: invalid user ptr\n");
++ return -EINVAL;
++ }
++
++ if (ccdc_if_type != VPFE_RAW_BAYER) {
++ dev_err(dev,
++ "ccdc_setcontrol: Not doing Raw Bayer Capture\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; i < CCDC_MAX_CONTROLS; i++) {
++ control = &ccdc_control_info[i];
++ if (control->id == ctrl->id)
++ break;
++ }
++
++ if (i == CCDC_MAX_CONTROLS) {
++ dev_err(dev, "ccdc_queryctrl : Invalid control ID\n");
++ return -EINVAL;
++ }
++
++ switch (ctrl->id) {
++ case CCDC_CID_R_GAIN:
++ ctrl->value = ccdc_hw_params_raw.gain.r_ye;
++ break;
++ case CCDC_CID_GR_GAIN:
++ ctrl->value = ccdc_hw_params_raw.gain.gr_cy;
++ break;
++ case CCDC_CID_GB_GAIN:
++ ctrl->value = ccdc_hw_params_raw.gain.gb_g;
++ break;
++ case CCDC_CID_B_GAIN:
++ ctrl->value = ccdc_hw_params_raw.gain.b_mg;
++ break;
++ default:
++ /* offset */
++ ctrl->value = ccdc_hw_params_raw.ccdc_offset;
++ }
++ /* set it in hardware */
++ return 0;
++}
++
++static void ccdc_reset(void)
++{
++ int i, clkctrl;
++ /* disable CCDC */
++ dev_dbg(dev, "\nstarting ccdc_reset...");
++ ccdc_enable(0);
++ /* set all registers to default value */
++ for (i = 0; i <= 0x15c; i += 4)
++ regw(0, i);
++ /* no culling support */
++ regw(0xffff, CULH);
++ regw(0xff, CULV);
++ /* Set default Gain and Offset */
++ ccdc_hw_params_raw.gain.r_ye = 256;
++ ccdc_hw_params_raw.gain.gb_g = 256;
++ ccdc_hw_params_raw.gain.gr_cy = 256;
++ ccdc_hw_params_raw.gain.b_mg = 256;
++ ccdc_hw_params_raw.ccdc_offset = 0;
++ ccdc_config_gain_offset();
++ /* up to 12 bit sensor */
++ regw(0x0FFF, OUTCLIP);
++ /* CCDC input Mux select directly from sensor */
++ regw_bl(0x00, CCDCMUX);
++ dev_dbg(dev, "\nEnd of ccdc_reset...");
++}
++
++static int ccdc_open(struct device *device)
++{
++ dev = device;
++ ccdc_reset();
++ return 0;
++}
++
++/*
++ * ======== ccdc_setwin ========
++ *
++ * This function will configure the window size to
++ * be capture in CCDC reg
++ */
++static void ccdc_setwin(struct ccdc_imgwin *image_win,
++ enum ccdc_frmfmt frm_fmt, int ppc)
++{
++ int horz_start, horz_nr_pixels;
++ int vert_start, vert_nr_lines;
++ int mid_img = 0;
++ dev_dbg(dev, "\nStarting ccdc_setwin...");
++ /* configure horizonal and vertical starts and sizes */
++ horz_start = image_win->left << (ppc - 1);
++ horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1;
++
++ /*Writing the horizontal info into the registers */
++ regw(horz_start & START_PX_HOR_MASK, SPH);
++ regw(horz_nr_pixels & NUM_PX_HOR_MASK, NPH);
++ vert_start = image_win->top;
++
++ if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
++ vert_nr_lines = (image_win->height >> 1) - 1;
++ vert_start >>= 1;
++ vert_start += 1; /* Since first line doesn't have any data */
++ /* configure VDINT0 and VDINT1 */
++ regw(vert_start, VDINT0);
++ } else {
++ vert_start += 1; /* Since first line doesn't have any data */
++ vert_nr_lines = image_win->height - 1;
++ /* configure VDINT0 and VDINT1 */
++ mid_img = vert_start + (image_win->height / 2);
++ regw(vert_start, VDINT0);
++ regw(mid_img, VDINT1);
++ }
++ regw(vert_start & START_VER_ONE_MASK, SLV0);
++ regw(vert_start & START_VER_TWO_MASK, SLV1);
++ regw(vert_nr_lines & NUM_LINES_VER, NLV);
++ dev_dbg(dev, "\nEnd of ccdc_setwin...");
++}
++
++static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
++{
++ if (ccdcparam->pix_fmt != 0) {
++ dev_err(dev,
++ "Invalid value of pix_fmt, only raw supported\n");
++ return -1;
++ }
++
++ if (ccdcparam->frm_fmt != 0) {
++ dev_err(dev,
++ "Only Progressive frame format is supported\n");
++ return -1;
++ }
++
++ if (ccdcparam->fid_pol != CCDC_PINPOL_POSITIVE
++ && ccdcparam->fid_pol != CCDC_PINPOL_NEGATIVE) {
++ dev_err(dev, "Invalid value of field id polarity\n");
++ return -1;
++ }
++
++ if (ccdcparam->vd_pol != CCDC_PINPOL_POSITIVE
++ && ccdcparam->vd_pol != CCDC_PINPOL_NEGATIVE) {
++ dev_err(dev, "Invalid value of VD polarity\n");
++ return -1;
++ }
++
++ if (ccdcparam->hd_pol != CCDC_PINPOL_POSITIVE
++ && ccdcparam->hd_pol != CCDC_PINPOL_NEGATIVE) {
++ dev_err(dev, "Invalid value of HD polarity\n");
++ return -1;
++ }
++
++ if (ccdcparam->datasft < NO_SHIFT || ccdcparam->datasft > _6BIT) {
++ dev_err(dev, "Invalid value of data shift\n");
++ return -1;
++ }
++
++ if (ccdcparam->mfilt1 < NO_MEDIAN_FILTER1
++ || ccdcparam->mfilt1 > MEDIAN_FILTER1) {
++ dev_err(dev, "Invalid value of median filter1\n");
++ return -1;
++ }
++
++ if (ccdcparam->mfilt2 < NO_MEDIAN_FILTER2
++ || ccdcparam->mfilt2 > MEDIAN_FILTER2) {
++ dev_err(dev, "Invalid value of median filter2\n");
++ return -1;
++ }
++
++ if (ccdcparam->ccdc_offset < 0 || ccdcparam->ccdc_offset > 1023) {
++ dev_err(dev, "Invalid value of offset\n");
++ return -1;
++ }
++
++ if ((ccdcparam->med_filt_thres < 0)
++ || (ccdcparam->med_filt_thres > 0x3FFF)) {
++ dev_err(dev, "Invalid value of median filter thresold\n");
++ return -1;
++ }
++
++ if (ccdcparam->data_sz < _16BITS || ccdcparam->data_sz > _8BITS) {
++ dev_err(dev, "Invalid value of data size\n");
++ return -1;
++ }
++
++ if (ccdcparam->alaw.b_alaw_enable) {
++ if (ccdcparam->alaw.gama_wd < BITS_13_4
++ || ccdcparam->alaw.gama_wd > BITS_09_0) {
++ dev_err(dev, "Invalid value of ALAW\n");
++ return -1;
++ }
++ }
++
++ if (ccdcparam->blk_clamp.b_clamp_enable) {
++ if (ccdcparam->blk_clamp.sample_pixel < _1PIXELS
++ || ccdcparam->blk_clamp.sample_pixel > _16PIXELS) {
++ dev_err(dev, "Invalid value of sample pixel\n");
++ return -1;
++ }
++ if (ccdcparam->blk_clamp.sample_ln < _1LINES
++ || ccdcparam->blk_clamp.sample_ln > _16LINES) {
++ dev_err(dev, "Invalid value of sample lines\n");
++ return -1;
++ }
++
++ }
++
++ if (ccdcparam->lens_sh_corr.lsc_enable) {
++ dev_err(dev, "Lens shadding correction is not supported\n");
++ return -1;
++ }
++ return 0;
++}
++
++static int ccdc_update_raw_params(void *arg)
++{
++ struct ccdc_config_params_raw *raw =
++ (struct ccdc_config_params_raw *)arg;
++
++ ccdc_hw_params_raw.pix_fmt =
++ raw->pix_fmt;
++ ccdc_hw_params_raw.frm_fmt =
++ raw->frm_fmt;
++ ccdc_hw_params_raw.win =
++ raw->win;
++ ccdc_hw_params_raw.fid_pol =
++ raw->fid_pol;
++ ccdc_hw_params_raw.vd_pol =
++ raw->vd_pol;
++ ccdc_hw_params_raw.hd_pol =
++ raw->hd_pol;
++ ccdc_hw_params_raw.buf_type =
++ raw->buf_type;
++ ccdc_hw_params_raw.datasft =
++ raw->datasft;
++ ccdc_hw_params_raw.mfilt1 =
++ raw->mfilt1;
++ ccdc_hw_params_raw.mfilt2 =
++ raw->mfilt2;
++ ccdc_hw_params_raw.lpf_enable =
++ raw->lpf_enable;
++ ccdc_hw_params_raw.horz_flip_enable =
++ raw->horz_flip_enable;
++ ccdc_hw_params_raw.ccdc_offset =
++ raw->ccdc_offset;
++ ccdc_hw_params_raw.med_filt_thres =
++ raw->med_filt_thres;
++ ccdc_hw_params_raw.image_invert_enable =
++ raw->image_invert_enable;
++ ccdc_hw_params_raw.data_sz =
++ raw->data_sz;
++ ccdc_hw_params_raw.alaw =
++ raw->alaw;
++ ccdc_hw_params_raw.data_offset_s =
++ raw->data_offset_s;
++ ccdc_hw_params_raw.blk_clamp =
++ raw->blk_clamp;
++ ccdc_hw_params_raw.vertical_dft =
++ raw->vertical_dft;
++ ccdc_hw_params_raw.lens_sh_corr =
++ raw->lens_sh_corr;
++ ccdc_hw_params_raw.data_formatter_r =
++ raw->data_formatter_r;
++ ccdc_hw_params_raw.color_space_con =
++ raw->color_space_con;
++ ccdc_hw_params_raw.col_pat_field0 =
++ raw->col_pat_field0;
++ ccdc_hw_params_raw.col_pat_field1 =
++ raw->col_pat_field1;
++
++ return 0;
++}
++
++static int ccdc_update_ycbcr_params(void *arg)
++{
++ if (copy_from_user(&ccdc_hw_params_ycbcr,
++ (struct ccdc_params_ycbcr *)arg,
++ sizeof(struct ccdc_params_ycbcr))) {
++ dev_err(dev, "ccdc_update_ycbcr_params: error"
++ "in copying ccdc params\n");
++ return -EFAULT;
++ }
++ return 0;
++}
++
++/* Parameter operations */
++static int ccdc_setparams(void *params)
++{
++ int x;
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ x = copy_from_user(&ccdc_hw_params_raw_temp,
++ (struct ccdc_config_params_raw *)params,
++ sizeof(struct ccdc_config_params_raw));
++ if (x) {
++ dev_err(dev, "ccdc_setparams: error in copying ccdc"
++ "params, %d\n", x);
++ return -EFAULT;
++ }
++
++ if (!validate_ccdc_param(&ccdc_hw_params_raw_temp)) {
++ if (!ccdc_update_raw_params(&ccdc_hw_params_raw_temp))
++ return 0;
++ }
++ } else
++ return ccdc_update_ycbcr_params(params);
++ return -EINVAL;
++}
++
++
++/*This function will configure CCDC for YCbCr parameters*/
++static void ccdc_config_ycbcr(void)
++{
++ u32 modeset;
++ struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr;
++
++ /* first reset the CCDC */
++ /* all registers have default values after reset */
++ /* This is important since we assume default values to be set in */
++ /* a lot of registers that we didn't touch */
++ dev_dbg(dev, "\nStarting ccdc_config_ycbcr...");
++ ccdc_reset();
++
++ /* configure pixel format */
++ modeset = (params->pix_fmt & 0x3) << 12;
++
++ /* configure video frame format */
++ modeset |= (params->frm_fmt & 0x1) << 7;
++
++ /* setup BT.656 sync mode */
++ if (params->bt656_enable) {
++ regw(3, REC656IF);
++ /* configure the FID, VD, HD pin polarity */
++ /* fld,hd pol positive, vd negative, 8-bit pack mode */
++ modeset |= 0x04;
++ } else { /* y/c external sync mode */
++ modeset |= ((params->fid_pol & 0x1) << 4);
++ modeset |= ((params->hd_pol & 0x1) << 3);
++ modeset |= ((params->vd_pol & 0x1) << 2);
++ }
++
++ /* pack the data to 8-bit */
++ modeset |= 0x1 << 11;
++
++ regw(modeset, MODESET);
++
++ /* configure video window */
++ ccdc_setwin(&params->win, params->frm_fmt, 2);
++ /* configure the order of y cb cr in SD-RAM */
++ regw((params->pix_order << 11) | 0x8040, CCDCFG);
++
++ /* configure the horizontal line offset */
++ /* this is done by rounding up width to a multiple of 16 pixels */
++ /* and multiply by two to account for y:cb:cr 4:2:2 data */
++ regw(((((params->win.width * 2) + 31) & 0xffffffe0) >> 5), HSIZE);
++
++ /* configure the memory line offset */
++ if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
++ /* two fields are interleaved in memory */
++ regw(0x00000249, SDOFST);
++ }
++
++ dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n");
++}
++
++
++/*
++ * ======== ccdc_config_raw ========
++ *
++ * This function will configure CCDC for Raw mode parameters
++ */
++static void ccdc_config_raw(void)
++{
++ struct ccdc_params_raw *params = &ccdc_hw_params_raw;
++ unsigned int mode_set = 0;
++ unsigned int val = 0, val1 = 0;
++ int temp1 = 0, temp2 = 0, i = 0, fmtreg_v = 0, shift_v = 0, flag = 0;
++ int temp_gf = 0, temp_lcs = 0;
++ dev_dbg(dev, "\nStarting ccdc_config_raw...");
++ /* Reset CCDC */
++ ccdc_reset();
++
++ /*
++ * C O N F I G U R I N G T H E C C D C F G R E G I S T E R
++ */
++
++ /*Set CCD Not to swap input since input is RAW data */
++ val |= CCDC_YCINSWP_RAW;
++
++ /*set FID detection function to Latch at V-Sync */
++ val |= CCDC_CCDCFG_FIDMD_LATCH_VSYNC << CCDC_CCDCFG_FIDMD_SHIFT;
++
++ /*set WENLOG - ccdc valid area */
++ val |= CCDC_CCDCFG_WENLOG_AND << CCDC_CCDCFG_WENLOG_SHIFT;
++
++ /*set TRGSEL */
++ val |= CCDC_CCDCFG_TRGSEL_WEN << CCDC_CCDCFG_TRGSEL_SHIFT;
++
++ /*set EXTRG */
++ val |= CCDC_CCDCFG_EXTRG_DISABLE << CCDC_CCDCFG_EXTRG_SHIFT;
++
++ /* Disable latching function registers on VSYNC-busy writable
++ registers */
++
++ /* Enable latching function registers on VSYNC-shadowed registers */
++ val |= CCDC_LATCH_ON_VSYNC_DISABLE;
++ regw(val, CCDCFG);
++ /*
++ * C O N F I G U R I N G T H E M O D E S E T R E G I S T E R
++ */
++
++ /*Set VDHD direction to input */
++ mode_set |=
++ (CCDC_VDHDOUT_INPUT & CCDC_VDHDOUT_MASK) << CCDC_VDHDOUT_SHIFT;
++
++ /*Set input type to raw input */
++ mode_set |=
++ (CCDC_RAW_IP_MODE & CCDC_RAW_INPUT_MASK) << CCDC_RAW_INPUT_SHIFT;
++
++ /* Configure the vertical sync polarity(MODESET.VDPOL) */
++ mode_set = (params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT;
++
++ /* Configure the horizontal sync polarity (MODESET.HDPOL) */
++ mode_set |= (params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT;
++
++ /* Configure frame id polarity (MODESET.FLDPOL) */
++ mode_set |= (params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT;
++
++ /* Configure data polarity */
++ mode_set |=
++ (CCDC_DATAPOL_NORMAL & CCDC_DATAPOL_MASK) << CCDC_DATAPOL_SHIFT;
++
++ /* Configure External WEN Selection */
++ mode_set |= (CCDC_EXWEN_DISABLE & CCDC_EXWEN_MASK) << CCDC_EXWEN_SHIFT;
++
++ /* Configure frame format(progressive or interlace) */
++ mode_set |= (params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT;
++
++ /* Configure pixel format (Input mode) */
++ mode_set |= (params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT;
++
++ if ((params->data_sz == _8BITS) || params->alaw.b_alaw_enable)
++ mode_set |= CCDC_DATA_PACK_ENABLE;
++
++ /* Configure for LPF */
++ if (params->lpf_enable)
++ mode_set |= (params->lpf_enable & CCDC_LPF_MASK) <<
++ CCDC_LPF_SHIFT;
++ /* Configure the data shift */
++ mode_set |= (params->datasft & CCDC_DATASFT_MASK) << CCDC_DATASFT_SHIFT;
++ regw(mode_set, MODESET);
++ dev_dbg(dev, "\nWriting 0x%x to MODESET...\n", mode_set);
++
++ /* Configure the Median Filter threshold */
++ regw((params->med_filt_thres) & 0x3fff, MEDFILT);
++
++ /*
++ * C O N F I G U R E T H E G A M M A W D R E G I S T E R
++ */
++
++ val = 8;
++ val |=
++ (CCDC_CFA_MOSAIC & CCDC_GAMMAWD_CFA_MASK) << CCDC_GAMMAWD_CFA_SHIFT;
++
++ /* Enable and configure aLaw register if needed */
++ if (params->alaw.b_alaw_enable) {
++ val |= (params->alaw.gama_wd & CCDC_ALAW_GAMA_WD_MASK) << 2;
++ val |= CCDC_ALAW_ENABLE; /*set enable bit of alaw */
++ }
++
++ /* Configure Median filter1 for IPIPE capture */
++ val |= params->mfilt1 << CCDC_MFILT1_SHIFT;
++
++ /* Configure Median filter2 for SDRAM capture */
++ val |= params->mfilt2 << CCDC_MFILT2_SHIFT;
++
++ regw(val, GAMMAWD);
++ dev_dbg(dev, "\nWriting 0x%x to GAMMAWD...\n", val);
++
++ /* configure video window */
++ ccdc_setwin(&params->win, params->frm_fmt, 1);
++
++ /*
++ * O P T I C A L B L A C K A V E R A G I N G
++ */
++ val = 0;
++ if (params->blk_clamp.b_clamp_enable) {
++ val |= (params->blk_clamp.start_pixel & CCDC_BLK_ST_PXL_MASK);
++
++ /* No of line to be avg */
++ val1 |= (params->blk_clamp.sample_ln & CCDC_NUM_LINE_CALC_MASK)
++ << CCDC_NUM_LINE_CALC_SHIFT;
++ /* No of pixel/line to be avg */
++ val |=
++ (params->blk_clamp.sample_pixel & CCDC_BLK_SAMPLE_LN_MASK)
++ << CCDC_BLK_SAMPLE_LN_SHIFT;
++ /* Enable the Black clamping */
++ val |= CCDC_BLK_CLAMP_ENABLE;
++ regw(val, CLAMP);
++
++ dev_dbg(dev, "\nWriting 0x%x to CLAMP...\n", val);
++ /* If Black clamping is enable then make dcsub 0 */
++ regw(val1, DCSUB);
++ dev_dbg(dev, "\nWriting 0x00000000 to DCSUB...\n");
++
++ } else {
++ /* configure DCSub */
++ val = (params->blk_clamp.dc_sub) & CCDC_BLK_DC_SUB_MASK;
++ regw(val, DCSUB);
++
++ dev_dbg(dev, "\nWriting 0x%x to DCSUB...\n", val);
++ regw(0x0000, CLAMP);
++
++ dev_dbg(dev, "\nWriting 0x0000 to CLAMP...\n");
++ }
++
++ /*
++ * C O N F I G U R E B L A C K L E V E L C O M P E N S A T I O N
++ */
++ val = 0;
++ val = (params->blk_comp.b_comp & CCDC_BLK_COMP_MASK);
++ val |= (params->blk_comp.gb_comp & CCDC_BLK_COMP_MASK)
++ << CCDC_BLK_COMP_GB_COMP_SHIFT;
++ regw(val, BLKCMP1);
++
++ val1 = 0;
++ val1 |= (params->blk_comp.gr_comp & CCDC_BLK_COMP_MASK)
++ << CCDC_BLK_COMP_GR_COMP_SHIFT;
++ val1 |= (params->blk_comp.r_comp & CCDC_BLK_COMP_MASK)
++ << CCDC_BLK_COMP_R_COMP_SHIFT;
++ regw(val1, BLKCMP0);
++
++ dev_dbg(dev, "\nWriting 0x%x to BLKCMP1...\n", val);
++ dev_dbg(dev, "\nWriting 0x%x to BLKCMP0...\n", val1);
++
++ /* Configure Vertical Defect Correction if needed */
++ if (params->vertical_dft.ver_dft_en) {
++
++ shift_v = 0;
++ shift_v = 0 << CCDC_DFCCTL_VDFCEN_SHIFT;
++ shift_v |=
++ params->vertical_dft.gen_dft_en & CCDC_DFCCTL_GDFCEN_MASK;
++ shift_v |=
++ (params->vertical_dft.dft_corr_ctl.
++ vdfcsl & CCDC_DFCCTL_VDFCSL_MASK) <<
++ CCDC_DFCCTL_VDFCSL_SHIFT;
++ shift_v |=
++ (params->vertical_dft.dft_corr_ctl.
++ vdfcuda & CCDC_DFCCTL_VDFCUDA_MASK) <<
++ CCDC_DFCCTL_VDFCUDA_SHIFT;
++ shift_v |=
++ (params->vertical_dft.dft_corr_ctl.
++ vdflsft & CCDC_DFCCTL_VDFLSFT_MASK) <<
++ CCDC_DFCCTL_VDFLSFT_SHIFT;
++ regw(shift_v, DFCCTL);
++ regw(params->vertical_dft.dft_corr_vert[0], DFCMEM0);
++ regw(params->vertical_dft.dft_corr_horz[0], DFCMEM1);
++ regw(params->vertical_dft.dft_corr_sub1[0], DFCMEM2);
++ regw(params->vertical_dft.dft_corr_sub2[0], DFCMEM3);
++ regw(params->vertical_dft.dft_corr_sub3[0], DFCMEM4);
++
++ shift_v = 0;
++ shift_v = regr(DFCMEMCTL);
++ shift_v |= 1 << CCDC_DFCMEMCTL_DFCMARST_SHIFT;
++ shift_v |= 1;
++ regw(shift_v, DFCMEMCTL);
++
++ while (1) {
++ flag = regr(DFCMEMCTL);
++ if ((flag & 0x01) == 0x00)
++ break;
++ }
++ flag = 0;
++ shift_v = 0;
++ shift_v = regr(DFCMEMCTL);
++ shift_v |= 0 << CCDC_DFCMEMCTL_DFCMARST_SHIFT;
++ regw(shift_v, DFCMEMCTL);
++
++ for (i = 1; i < 16; i++) {
++ regw(params->vertical_dft.dft_corr_vert[i], DFCMEM0);
++ regw(params->vertical_dft.dft_corr_horz[i], DFCMEM1);
++ regw(params->vertical_dft.dft_corr_sub1[i], DFCMEM2);
++ regw(params->vertical_dft.dft_corr_sub2[i], DFCMEM3);
++ regw(params->vertical_dft.dft_corr_sub3[i], DFCMEM4);
++
++ shift_v = 0;
++ shift_v = regr(DFCMEMCTL);
++ shift_v |= 1;
++ regw(shift_v, DFCMEMCTL);
++
++ while (1) {
++ flag = regr(DFCMEMCTL);
++ if ((flag & 0x01) == 0x00)
++ break;
++ }
++ flag = 0;
++ }
++ regw(params->vertical_dft.
++ saturation_ctl & CCDC_VDC_DFCVSAT_MASK, DFCVSAT);
++
++ shift_v = 0;
++ shift_v = regr(DFCCTL);
++ shift_v |= 1 << CCDC_DFCCTL_VDFCEN_SHIFT;
++ regw(shift_v, DFCCTL);
++ }
++
++ /* Configure Lens Shading Correction if needed */
++ if (params->lens_sh_corr.lsc_enable) {
++ dev_dbg(dev, "\nlens shading Correction entered....\n");
++
++ /* first disable the LSC */
++ regw(CCDC_LSC_DISABLE, LSCCFG1);
++
++ /* UPDATE PROCEDURE FOR GAIN FACTOR TABLE 1 */
++
++ /* select table 1 */
++ regw(CCDC_LSC_TABLE1_SLC, LSCMEMCTL);
++
++ /* Reset memory address */
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_MEMADDR_RESET;
++ regw(temp_lcs, LSCMEMCTL);
++
++ /* Update gainfactor for table 1 - u8q8 */
++ temp_gf =
++ ((int)(params->lens_sh_corr.gf_table1[0].frac_no * 256))
++ & CCDC_LSC_FRAC_MASK_T1;
++ temp_gf |=
++ (((int)(params->lens_sh_corr.gf_table1[0].frac_no * 256))
++ & CCDC_LSC_FRAC_MASK_T1) << 8;
++ regw(temp_gf, LSCMEMD);
++
++ while (1) {
++ if ((regr(LSCMEMCTL) & 0x10) == 0)
++ break;
++ }
++
++ /* set the address to incremental mode */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_MEMADDR_INCR;
++ regw(temp_lcs, LSCMEMCTL);
++
++ for (i = 2; i < 255; i += 2) {
++ temp_gf = 0;
++ temp_gf = ((int)
++ (params->lens_sh_corr.gf_table1[0].frac_no *
++ 256))
++ & CCDC_LSC_FRAC_MASK_T1;
++ temp_gf |= (((int)
++ (params->lens_sh_corr.gf_table1[0].
++ frac_no * 256))
++ & CCDC_LSC_FRAC_MASK_T1) << 8;
++ regw(temp_gf, LSCMEMD);
++
++ while (1) {
++ if ((regr(LSCMEMCTL) & 0x10) == 0)
++ break;
++ }
++ }
++
++ /* UPDATE PROCEDURE FOR GAIN FACTOR TABLE 2 */
++
++ /* select table 2 */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_TABLE2_SLC;
++ regw(temp_lcs, LSCMEMCTL);
++
++ /*Reset memory address */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_MEMADDR_RESET;
++ regw(temp_lcs, LSCMEMCTL);
++
++ /*Update gainfactor for table 2 - u16q14 */
++ temp_gf =
++ (params->lens_sh_corr.gf_table2[0].
++ int_no & CCDC_LSC_INT_MASK) << 14;
++ temp_gf |=
++ ((int)(params->lens_sh_corr.gf_table2[0].frac_no) * 16384)
++ & CCDC_LSC_FRAC_MASK;
++ regw(temp_gf, LSCMEMD);
++
++ while (1) {
++ if ((regr(LSCMEMCTL) & 0x10) == 0)
++ break;
++ }
++
++ /*set the address to incremental mode */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_MEMADDR_INCR;
++ regw(temp_lcs, LSCMEMCTL);
++
++ for (i = 1; i < 128; i++) {
++ temp_gf = 0;
++ temp_gf =
++ (params->lens_sh_corr.gf_table2[i].
++ int_no & CCDC_LSC_INT_MASK) << 14;
++ temp_gf |=
++ ((int)(params->lens_sh_corr.gf_table2[0].frac_no) *
++ 16384)
++ & CCDC_LSC_FRAC_MASK;
++ regw(temp_gf, LSCMEMD);
++
++ while (1) {
++ if ((regr(LSCMEMCTL) & 0x10) == 0)
++ break;
++ }
++ }
++
++ /*UPDATE PROCEDURE FOR GAIN FACTOR TABLE 3 */
++
++ /*select table 3 */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_TABLE3_SLC;
++ regw(temp_lcs, LSCMEMCTL);
++
++ /*Reset memory address */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_MEMADDR_RESET;
++ regw(temp_lcs, LSCMEMCTL);
++
++ /*Update gainfactor for table 2 - u16q14 */
++ temp_gf =
++ (params->lens_sh_corr.gf_table3[0].
++ int_no & CCDC_LSC_INT_MASK) << 14;
++ temp_gf |=
++ ((int)(params->lens_sh_corr.gf_table3[0].frac_no) * 16384)
++ & CCDC_LSC_FRAC_MASK;
++ regw(temp_gf, LSCMEMD);
++
++ while (1) {
++ if ((regr(LSCMEMCTL) & 0x10) == 0)
++ break;
++ }
++
++ /*set the address to incremental mode */
++ temp_lcs = 0;
++ temp_lcs = regr(LSCMEMCTL);
++ temp_lcs |= CCDC_LSC_MEMADDR_INCR;
++ regw(temp_lcs, LSCMEMCTL);
++
++ for (i = 1; i < 128; i++) {
++ temp_gf = 0;
++ temp_gf =
++ (params->lens_sh_corr.gf_table3[i].
++ int_no & CCDC_LSC_INT_MASK) << 14;
++ temp_gf |=
++ ((int)(params->lens_sh_corr.gf_table3[0].frac_no) *
++ 16384)
++ & CCDC_LSC_FRAC_MASK;
++ regw(temp_gf, LSCMEMD);
++
++ while (1) {
++ if ((regr(LSCMEMCTL) & 0x10) == 0)
++ break;
++ }
++ }
++ /*Configuring the optical centre of the lens */
++ regw(params->lens_sh_corr.
++ lens_center_horz & CCDC_LSC_CENTRE_MASK, LSCH0);
++ regw(params->lens_sh_corr.
++ lens_center_vert & CCDC_LSC_CENTRE_MASK, LSCV0);
++
++ val = 0;
++ val =
++ ((int)(params->lens_sh_corr.horz_left_coef.frac_no * 128)) &
++ 0x7f;
++ val |= (params->lens_sh_corr.horz_left_coef.int_no & 0x01) << 7;
++ val |=
++ (((int)(params->lens_sh_corr.horz_right_coef.frac_no * 128))
++ & 0x7f) << 8;
++ val |=
++ (params->lens_sh_corr.horz_right_coef.int_no & 0x01) << 15;
++ regw(val, LSCKH);
++
++ val = 0;
++ val =
++ ((int)(params->lens_sh_corr.ver_up_coef.frac_no * 128)) &
++ 0x7f;
++ val |= (params->lens_sh_corr.ver_up_coef.int_no & 0x01) << 7;
++ val |=
++ (((int)(params->lens_sh_corr.ver_low_coef.frac_no * 128)) &
++ 0x7f) << 8;
++ val |= (params->lens_sh_corr.ver_low_coef.int_no & 0x01) << 15;
++ regw(val, LSCKV);
++
++ /*configuring the lsc configuration register 2 */
++ temp_lcs = 0;
++ temp_lcs |=
++ (params->lens_sh_corr.lsc_config.
++ gf_table_scaling_fact & CCDC_LSCCFG_GFTSF_MASK) <<
++ CCDC_LSCCFG_GFTSF_SHIFT;
++ temp_lcs |=
++ (params->lens_sh_corr.lsc_config.
++ gf_table_interval & CCDC_LSCCFG_GFTINV_MASK) <<
++ CCDC_LSCCFG_GFTINV_SHIFT;
++ temp_lcs |=
++ (params->lens_sh_corr.lsc_config.
++ epel & CCDC_LSC_GFTABLE_SEL_MASK) <<
++ CCDC_LSC_GFTABLE_EPEL_SHIFT;
++ temp_lcs |=
++ (params->lens_sh_corr.lsc_config.
++ opel & CCDC_LSC_GFTABLE_SEL_MASK) <<
++ CCDC_LSC_GFTABLE_OPEL_SHIFT;
++ temp_lcs |=
++ (params->lens_sh_corr.lsc_config.
++ epol & CCDC_LSC_GFTABLE_SEL_MASK) <<
++ CCDC_LSC_GFTABLE_EPOL_SHIFT;
++ temp_lcs |=
++ (params->lens_sh_corr.lsc_config.
++ opol & CCDC_LSC_GFTABLE_SEL_MASK) <<
++ CCDC_LSC_GFTABLE_OPOL_SHIFT;
++ regw(temp_lcs, LSCCFG2);
++
++ /*configuring the LSC configuration register 1 */
++ temp_lcs = 0;
++ temp_lcs |= CCDC_LSC_ENABLE;
++ temp_lcs |= (params->lens_sh_corr.lsc_config.mode &
++ CCDC_LSC_GFMODE_MASK) << CCDC_LSC_GFMODE_SHIFT;
++ regw(temp_lcs, LSCCFG1);
++ }
++
++ /* Configure data formatter if needed */
++ if (params->data_formatter_r.fmt_enable
++ && (!params->color_space_con.csc_enable)) {
++ dev_dbg(dev,
++ "\ndata formatter will be configured now....\n");
++
++ /*Configuring the FMTPLEN */
++ fmtreg_v = 0;
++ fmtreg_v |=
++ (params->data_formatter_r.plen.
++ plen0 & CCDC_FMTPLEN_P0_MASK);
++ fmtreg_v |=
++ ((params->data_formatter_r.plen.
++ plen1 & CCDC_FMTPLEN_P1_MASK)
++ << CCDC_FMTPLEN_P1_SHIFT);
++ fmtreg_v |=
++ ((params->data_formatter_r.plen.
++ plen2 & CCDC_FMTPLEN_P2_MASK)
++ << CCDC_FMTPLEN_P2_SHIFT);
++ fmtreg_v |=
++ ((params->data_formatter_r.plen.
++ plen3 & CCDC_FMTPLEN_P3_MASK)
++ << CCDC_FMTPLEN_P3_SHIFT);
++ regw(fmtreg_v, FMTPLEN);
++
++ /*Configurring the FMTSPH */
++ regw((params->data_formatter_r.fmtsph & CCDC_FMTSPH_MASK),
++ FMTSPH);
++
++ /*Configurring the FMTLNH */
++ regw((params->data_formatter_r.fmtlnh & CCDC_FMTLNH_MASK),
++ FMTLNH);
++
++ /*Configurring the FMTSLV */
++ regw((params->data_formatter_r.fmtslv & CCDC_FMTSLV_MASK),
++ FMTSLV);
++
++ /*Configurring the FMTLNV */
++ regw((params->data_formatter_r.fmtlnv & CCDC_FMTLNV_MASK),
++ FMTLNV);
++
++ /*Configurring the FMTRLEN */
++ regw((params->data_formatter_r.fmtrlen & CCDC_FMTRLEN_MASK),
++ FMTRLEN);
++
++ /*Configurring the FMTHCNT */
++ regw((params->data_formatter_r.fmthcnt & CCDC_FMTHCNT_MASK),
++ FMTHCNT);
++
++ /*Configuring the FMTADDR_PTR */
++ for (i = 0; i < 8; i++) {
++ fmtreg_v = 0;
++
++ if (params->data_formatter_r.addr_ptr[i].init >
++ (params->data_formatter_r.fmtrlen - 1)) {
++ dev_dbg(dev, "\nInvalid init parameter for"
++ "FMTADDR_PTR....\n");
++ return;
++ }
++
++ fmtreg_v =
++ (params->data_formatter_r.addr_ptr[i].
++ init & CCDC_ADP_INIT_MASK);
++ fmtreg_v |=
++ ((params->data_formatter_r.addr_ptr[i].
++ line & CCDC_ADP_LINE_MASK) <<
++ CCDC_ADP_LINE_SHIFT);
++ regw(fmtreg_v, FMT_ADDR_PTR(i));
++ }
++
++ /* Configuring the FMTPGM_VF0 */
++ fmtreg_v = 0;
++ for (i = 0; i < 16; i++)
++ fmtreg_v |= params->data_formatter_r.pgm_en[i] << i;
++ regw(fmtreg_v, FMTPGM_VF0);
++
++ /* Configuring the FMTPGM_VF1 */
++ fmtreg_v = 0;
++ for (i = 16; i < 32; i++) {
++ fmtreg_v |=
++ params->data_formatter_r.pgm_en[i] << (i - 16);
++ }
++ regw(fmtreg_v, FMTPGM_VF1);
++
++ /* Configuring the FMTPGM_AP0 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 0; i < 4; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP0);
++
++ /* Configuring the FMTPGM_AP1 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 4; i < 8; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP1);
++
++ /* Configuring the FMTPGM_AP2 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 8; i < 12; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP2);
++
++ /* Configuring the FMTPGM_AP3 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 12; i < 16; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP3);
++
++ /* Configuring the FMTPGM_AP4 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 16; i < 20; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP4);
++
++ /* Configuring the FMTPGM_AP5 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 20; i < 24; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP5);
++
++ /* Configuring the FMTPGM_AP6 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 24; i < 28; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP6);
++
++ /* Configuring the FMTPGM_AP7 */
++ fmtreg_v = 0;
++ shift_v = 0;
++ for (i = 28; i < 32; i++) {
++ fmtreg_v |=
++ ((params->data_formatter_r.pgm_ap[i].
++ pgm_aptr & CCDC_FMTPGN_APTR_MASK) << shift_v);
++ fmtreg_v |=
++ (params->data_formatter_r.pgm_ap[i].
++ pgmupdt << (shift_v + 3));
++ shift_v += 4;
++ }
++ regw(fmtreg_v, FMTPGM_AP7);
++
++ /* Configuring the FMTCFG register */
++ fmtreg_v = 0;
++ fmtreg_v = CCDC_DF_ENABLE;
++ fmtreg_v |=
++ ((params->data_formatter_r.cfg.
++ mode & CCDC_FMTCFG_FMTMODE_MASK)
++ << CCDC_FMTCFG_FMTMODE_SHIFT);
++ fmtreg_v |=
++ ((params->data_formatter_r.cfg.
++ lnum & CCDC_FMTCFG_LNUM_MASK)
++ << CCDC_FMTCFG_LNUM_SHIFT);
++ fmtreg_v |=
++ ((params->data_formatter_r.cfg.
++ addrinc & CCDC_FMTCFG_ADDRINC_MASK)
++ << CCDC_FMTCFG_ADDRINC_SHIFT);
++ regw(fmtreg_v, FMTCFG);
++
++ } else if (params->data_formatter_r.fmt_enable) {
++ dev_dbg(dev,
++ "\nCSC and Data Formatter Enabled at same time....\n");
++ }
++
++ /*
++ * C O N F I G U R E C O L O R S P A C E C O N V E R T E R
++ */
++
++ if ((params->color_space_con.csc_enable)
++ && (!params->data_formatter_r.fmt_enable)) {
++ dev_dbg(dev, "\nconfiguring the CSC Now....\n");
++
++ /* Enable the CSC sub-module */
++ regw(CCDC_CSC_ENABLE, CSCCTL);
++
++ /* Converting the co-eff as per the format of the register */
++ for (i = 0; i < 16; i++) {
++ temp1 = params->color_space_con.csc_dec_coeff[i];
++ /* Masking the data for 3 bits */
++ temp1 &= CCDC_CSC_COEFF_DEC_MASK;
++ /* Recovering the fractional part and converting to
++ * binary of 5 bits
++ */
++ temp2 =
++ (int)(params->color_space_con.csc_frac_coeff[i] *
++ (32 / 10));
++ temp2 &= CCDC_CSC_COEFF_FRAC_MASK;
++ /* shifting the decimal to the MSB */
++ temp1 = temp1 << CCDC_CSC_DEC_SHIFT;
++ temp1 |= temp2;
++ params->color_space_con.csc_dec_coeff[i] = temp1;
++ }
++ regw(params->color_space_con.csc_dec_coeff[0], CSCM0);
++ regw(params->color_space_con.
++ csc_dec_coeff[1] << CCDC_CSC_COEFF_SHIFT, CSCM0);
++ regw(params->color_space_con.csc_dec_coeff[2], CSCM1);
++ regw(params->color_space_con.
++ csc_dec_coeff[3] << CCDC_CSC_COEFF_SHIFT, CSCM1);
++ regw(params->color_space_con.csc_dec_coeff[4], CSCM2);
++ regw(params->color_space_con.
++ csc_dec_coeff[5] << CCDC_CSC_COEFF_SHIFT, CSCM2);
++ regw(params->color_space_con.csc_dec_coeff[6], CSCM3);
++ regw(params->color_space_con.
++ csc_dec_coeff[7] << CCDC_CSC_COEFF_SHIFT, CSCM3);
++ regw(params->color_space_con.csc_dec_coeff[8], CSCM4);
++ regw(params->color_space_con.
++ csc_dec_coeff[9] << CCDC_CSC_COEFF_SHIFT, CSCM4);
++ regw(params->color_space_con.csc_dec_coeff[10], CSCM5);
++ regw(params->color_space_con.
++ csc_dec_coeff[11] << CCDC_CSC_COEFF_SHIFT, CSCM5);
++ regw(params->color_space_con.csc_dec_coeff[12], CSCM6);
++ regw(params->color_space_con.
++ csc_dec_coeff[13] << CCDC_CSC_COEFF_SHIFT, CSCM6);
++ regw(params->color_space_con.csc_dec_coeff[14], CSCM7);
++ regw(params->color_space_con.
++ csc_dec_coeff[15] << CCDC_CSC_COEFF_SHIFT, CSCM7);
++
++ } else if (params->color_space_con.csc_enable) {
++ dev_dbg(dev,
++ "\nCSC and Data Formatter Enabled at same time....\n");
++ }
++
++ /* Configure the Gain & offset control */
++ ccdc_config_gain_offset();
++
++ /*
++ * C O N F I G U R E C O L O R P A T T E R N A S
++ * P E R N N 1 2 8 6 A S E N S O R
++ */
++
++ val = (params->col_pat_field0.olop);
++ val |= (params->col_pat_field0.olep << 2);
++ val |= (params->col_pat_field0.elop << 4);
++ val |= (params->col_pat_field0.elep << 6);
++ val |= (params->col_pat_field1.olop << 8);
++ val |= (params->col_pat_field1.olep << 10);
++ val |= (params->col_pat_field1.elop << 12);
++ val |= (params->col_pat_field1.elep << 14);
++ regw(val, COLPTN);
++
++ dev_dbg(dev, "\nWriting %x to COLPTN...\n", val);
++
++ /*
++ * C O N F I G U R I N G T H E H S I Z E R E G I S T E R
++ */
++ val = 0;
++ val |=
++ (params->data_offset_s.
++ horz_offset & CCDC_DATAOFST_MASK) << CCDC_DATAOFST_H_SHIFT;
++ val |=
++ (params->data_offset_s.
++ vert_offset & CCDC_DATAOFST_MASK) << CCDC_DATAOFST_V_SHIFT;
++ regw(val, DATAOFST);
++
++ /*
++ * C O N F I G U R I N G T H E H S I Z E R E G I S T E R
++ */
++ val = 0;
++ val |=
++ (params->
++ horz_flip_enable & CCDC_HSIZE_FLIP_MASK) << CCDC_HSIZE_FLIP_SHIFT;
++
++ /* If pack 8 is enable then 1 pixel will take 1 byte */
++ if ((params->data_sz == _8BITS) || params->alaw.b_alaw_enable) {
++ val |= (((params->win.width) + 31) >> 5) & 0x0fff;
++
++ dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n",
++ (((params->win.width) + 31) >> 5) & 0x0fff);
++ } else {
++ /* else one pixel will take 2 byte */
++ val |= (((params->win.width * 2) + 31) >> 5) & 0x0fff;
++
++ dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n",
++ (((params->win.width * 2) + 31) >> 5) & 0x0fff);
++ }
++ regw(val, HSIZE);
++
++ /*
++ * C O N F I G U R E S D O F S T R E G I S T E R
++ */
++
++ if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
++ if (params->image_invert_enable) {
++ /* For interlace inverse mode */
++ regw(0x4B6D, SDOFST);
++ dev_dbg(dev, "\nWriting 0x4B6D to SDOFST...\n");
++ }
++
++ else {
++ /* For interlace non inverse mode */
++ regw(0x0B6D, SDOFST);
++ dev_dbg(dev, "\nWriting 0x0B6D to SDOFST...\n");
++ }
++ } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
++ if (params->image_invert_enable) {
++ /* For progessive inverse mode */
++ regw(0x4000, SDOFST);
++ dev_dbg(dev, "\nWriting 0x4000 to SDOFST...\n");
++ }
++
++ else {
++ /* For progessive non inverse mode */
++ regw(0x0000, SDOFST);
++ dev_dbg(dev, "\nWriting 0x0000 to SDOFST...\n");
++ }
++
++ }
++
++ /*
++ * C O N F I G U R E I N T E R R U P T R E G I S T E R S
++ */
++ if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
++ val = params->win.height / 2;
++ regw(136, VDINT0);
++ regw(149, VDINT0);
++ regw(0, VDINT1);
++ } else {
++ regw(0, VDINT0);
++ regw(0, VDINT1);
++ }
++
++ dev_dbg(dev, "\nend of ccdc_config_raw...");
++}
++
++static int ccdc_configure(void)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ dev_info(dev, "calling ccdc_config_raw()\n");
++ ccdc_config_raw();
++ } else {
++ dev_info(dev, "calling ccdc_config_ycbcr()\n");
++ ccdc_config_ycbcr();
++ }
++ return 0;
++}
++
++static int ccdc_set_buftype(enum ccdc_buftype buf_type)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ ccdc_hw_params_raw.buf_type = buf_type;
++ else
++ ccdc_hw_params_ycbcr.buf_type = buf_type;
++ return 0;
++}
++static int ccdc_get_buftype(enum ccdc_buftype *buf_type)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ *buf_type = ccdc_hw_params_raw.buf_type;
++ else
++ *buf_type = ccdc_hw_params_ycbcr.buf_type;
++ return 0;
++}
++
++static int ccdc_enum_pix(enum vpfe_hw_pix_format *hw_pix, int i)
++{
++ int ret = -EINVAL;
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ if (i < CCDC_MAX_RAW_BAYER_FORMATS) {
++ *hw_pix = ccdc_raw_bayer_hw_formats[i];
++ ret = 0;
++ }
++ } else {
++ if (i < CCDC_MAX_RAW_YUV_FORMATS) {
++ *hw_pix = ccdc_raw_yuv_hw_formats[i];
++ ret = 0;
++ }
++ }
++ return ret;
++}
++
++static int ccdc_set_pixel_format(enum vpfe_hw_pix_format pixfmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW;
++ if (pixfmt == VPFE_BAYER_8BIT_PACK_ALAW)
++ ccdc_hw_params_raw.alaw.b_alaw_enable = 1;
++ else if (pixfmt != VPFE_BAYER)
++ return -1;
++ } else {
++ if (pixfmt == VPFE_YUYV)
++ ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
++ else if (pixfmt == VPFE_UYVY)
++ ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
++ else
++ return -1;
++ }
++ return 0;
++}
++static int ccdc_get_pixel_format(enum vpfe_hw_pix_format *pixfmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ if (ccdc_hw_params_raw.alaw.b_alaw_enable)
++ *pixfmt = VPFE_BAYER_8BIT_PACK_ALAW;
++ else
++ *pixfmt = VPFE_BAYER;
++ else {
++ if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
++ *pixfmt = VPFE_YUYV;
++ else
++ *pixfmt = VPFE_UYVY;
++ }
++ return 0;
++}
++static int ccdc_set_image_window(struct v4l2_rect *win)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ ccdc_hw_params_raw.win.top = win->top;
++ ccdc_hw_params_raw.win.left = win->left;
++ ccdc_hw_params_raw.win.width = win->width;
++ ccdc_hw_params_raw.win.height = win->height;
++ } else {
++ ccdc_hw_params_ycbcr.win.top = win->top;
++ ccdc_hw_params_ycbcr.win.left = win->left;
++ ccdc_hw_params_ycbcr.win.width = win->width;
++ ccdc_hw_params_ycbcr.win.height = win->height;
++ }
++ return 0;
++}
++static int ccdc_get_image_window(struct v4l2_rect *win)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ win->top = ccdc_hw_params_raw.win.top;
++ win->left = ccdc_hw_params_raw.win.left;
++ win->width = ccdc_hw_params_raw.win.width;
++ win->height = ccdc_hw_params_raw.win.height;
++ } else {
++ win->top = ccdc_hw_params_ycbcr.win.top;
++ win->left = ccdc_hw_params_ycbcr.win.left;
++ win->width = ccdc_hw_params_ycbcr.win.width;
++ win->height = ccdc_hw_params_ycbcr.win.height;
++ }
++ return 0;
++}
++static int ccdc_get_line_length(unsigned int *len)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ if ((ccdc_hw_params_raw.alaw.b_alaw_enable) ||
++ (ccdc_hw_params_raw.data_sz == _8BITS)) {
++ *len = ccdc_hw_params_raw.win.width;
++ } else {
++ *len = ccdc_hw_params_raw.win.width * 2;
++ }
++ } else {
++ *len = ccdc_hw_params_ycbcr.win.width * 2;
++ }
++ *len = ((*len + 31) & ~0x1f);
++ return 0;
++}
++
++static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ ccdc_hw_params_raw.frm_fmt = frm_fmt;
++ else
++ ccdc_hw_params_ycbcr.frm_fmt = frm_fmt;
++ return 0;
++}
++static int ccdc_get_frame_format(enum ccdc_frmfmt *frm_fmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ *frm_fmt = ccdc_hw_params_raw.frm_fmt;
++ else
++ *frm_fmt = ccdc_hw_params_ycbcr.frm_fmt;
++ return 0;
++}
++
++static int ccdc_getfid(void)
++{
++ int fid = (regr(MODESET) >> 15) & 0x1;
++ return fid;
++}
++
++/* misc operations */
++static inline void ccdc_setfbaddr(unsigned long addr)
++{
++ regw((addr >> 21) & 0x007f, STADRH);
++ regw((addr >> 5) & 0x0ffff, STADRL);
++}
++
++static int ccdc_set_hw_if_type(enum vpfe_hw_if_type iface)
++{
++ ccdc_if_type = iface;
++ return 0;
++}
++
++struct ccdc_hw_device ccdc_hw_dev = {
++ .name = "DM355 CCDC",
++ .set_ccdc_base = ccdc_set_ccdc_base,
++ .set_vpss_base = ccdc_set_vpss_base,
++ .get_ccdc_base = ccdc_get_ccdc_base,
++ .get_vpss_base = ccdc_get_vpss_base,
++ .open = ccdc_open,
++ .enable = ccdc_enable,
++ .enable_out_to_sdram = ccdc_enable_output_to_sdram,
++ .set_hw_if_type = ccdc_set_hw_if_type,
++ .setparams = ccdc_setparams,
++ .configure = ccdc_configure,
++ .set_buftype = ccdc_set_buftype,
++ .get_buftype = ccdc_get_buftype,
++ .enum_pix = ccdc_enum_pix,
++ .set_pixelformat = ccdc_set_pixel_format,
++ .get_pixelformat = ccdc_get_pixel_format,
++ .set_frame_format = ccdc_set_frame_format,
++ .get_frame_format = ccdc_get_frame_format,
++ .set_image_window = ccdc_set_image_window,
++ .get_image_window = ccdc_get_image_window,
++ .get_line_length = ccdc_get_line_length,
++ .queryctrl = ccdc_queryctrl,
++ .setcontrol = ccdc_setcontrol,
++ .getcontrol = ccdc_getcontrol,
++ .setfbaddr = ccdc_setfbaddr,
++ .getfid = ccdc_getfid,
++};
++EXPORT_SYMBOL(ccdc_hw_dev);
++
++static int dm355_ccdc_init(void)
++{
++ return 0;
++}
++
++static void dm355_ccdc_exit(void)
++{
++}
++
++subsys_initcall(dm355_ccdc_init);
++module_exit(dm355_ccdc_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/davinci/ccdc_dm355.h b/drivers/media/video/davinci/ccdc_dm355.h
+new file mode 100644
+index 0000000..a78349a
+--- /dev/null
++++ b/drivers/media/video/davinci/ccdc_dm355.h
+@@ -0,0 +1,758 @@
++/*
++ * Copyright (C) 2005-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _CCDC_DM355_H
++#define _CCDC_DM355_H
++#include <media/davinci/ccdc_common.h>
++
++/* Define to enable/disable video port */
++
++#define CCDC_WIN_PAL {0, 0, 720, 576}
++#define CCDC_WIN_VGA {0, 0, 640, 480}
++
++/* enum for No of pixel per line to be avg. in Black Clamping*/
++enum sample_length {
++ _1PIXELS,
++ _2PIXELS,
++ _4PIXELS,
++ _8PIXELS,
++ _16PIXELS
++};
++
++/* enum for No of lines in Black Clamping */
++enum sample_line {
++ _1LINES,
++ _2LINES,
++ _4LINES,
++ _8LINES,
++ _16LINES
++};
++
++/* enum for Alaw gama width */
++enum gama_width {
++ BITS_13_4,
++ BITS_12_3,
++ BITS_11_2,
++ BITS_10_1,
++ BITS_09_0
++};
++
++enum ccdc_colpats {
++ CCDC_RED,
++ CCDC_GREEN_RED,
++ CCDC_GREEN_BLUE,
++ CCDC_BLUE
++};
++
++struct ccdc_col_pat {
++ enum ccdc_colpats olop;
++ enum ccdc_colpats olep;
++ enum ccdc_colpats elop;
++ enum ccdc_colpats elep;
++};
++
++enum ccdc_datasft {
++ NO_SHIFT,
++ _1BIT,
++ _2BIT,
++ _3BIT,
++ _4BIT,
++ _5BIT,
++ _6BIT
++};
++
++enum data_size {
++ _16BITS,
++ _15BITS,
++ _14BITS,
++ _13BITS,
++ _12BITS,
++ _11BITS,
++ _10BITS,
++ _8BITS
++};
++enum ccdc_mfilt1 {
++ NO_MEDIAN_FILTER1,
++ AVERAGE_FILTER1,
++ MEDIAN_FILTER1
++};
++
++enum ccdc_mfilt2 {
++ NO_MEDIAN_FILTER2 = 0,
++ AVERAGE_FILTER2,
++ MEDIAN_FILTER2
++};
++
++struct ccdc_imgwin {
++ unsigned int top;
++ unsigned int left;
++ unsigned int width;
++ unsigned int height;
++};
++
++/* structure for ALaw */
++struct ccdc_a_law {
++ /* Enable/disable A-Law */
++ unsigned char b_alaw_enable;
++ /*Gama Width Input */
++ enum gama_width gama_wd;
++};
++
++/* structure for Black Clamping */
++struct ccdc_black_clamp {
++ /* only if bClampEnable is TRUE */
++ unsigned char b_clamp_enable;
++ /* only if bClampEnable is TRUE */
++ enum sample_length sample_pixel;
++ /* only if bClampEnable is TRUE */
++ enum sample_line sample_ln;
++ /* only if bClampEnable is TRUE */
++ unsigned short start_pixel;
++ /* only if bClampEnable is FALSE */
++ unsigned short sgain;
++ unsigned short dc_sub;
++};
++
++/* structure for Black Level Compensation */
++struct black_compensation {
++ /* Constant value to subtract from Red component */
++ unsigned char r_comp;
++ /* Constant value to subtract from Gr component */
++ unsigned char gr_comp;
++ /* Constant value to subtract from Blue component */
++ unsigned char b_comp;
++ /* Constant value to subtract from Gb component */
++ unsigned char gb_comp;
++};
++
++/*structures for lens shading correction*/
++
++/*gain factor modes*/
++enum gfmode {
++ u8q8_interpol,
++ u16q14_interpol,
++ reserved,
++ u16q14
++};
++
++enum gf_table_sel {
++ table1 = 0,
++ table2,
++ table3
++};
++
++/*LSC configuration structure*/
++struct lsccfg {
++ enum gfmode mode;
++ int gf_table_scaling_fact;
++ int gf_table_interval;
++ enum gf_table_sel epel;
++ enum gf_table_sel opel;
++ enum gf_table_sel epol;
++ enum gf_table_sel opol;
++};
++
++struct float_ccdc {
++ unsigned int int_no;
++ unsigned int frac_no;
++};
++
++/*Main structure for lens shading correction*/
++struct lens_shading_corr {
++ unsigned char lsc_enable;
++ struct lsccfg lsc_config;
++ unsigned int lens_center_horz;
++ unsigned int lens_center_vert;
++ struct float_ccdc horz_left_coef;
++ struct float_ccdc horz_right_coef;
++ struct float_ccdc ver_low_coef;
++ struct float_ccdc ver_up_coef;
++ struct float_ccdc gf_table1[256];
++ /*int_no will be always 0 since it is u8q8 */
++ struct float_ccdc gf_table2[128];
++ struct float_ccdc gf_table3[128];
++};
++
++/*structure for color space converter*/
++struct color_space_converter {
++ unsigned char csc_enable;
++ int csc_dec_coeff[16];
++ int csc_frac_coeff[16];
++};
++
++/*supporting structures for data formatter*/
++enum fmtmode {
++ split,
++ combine,
++ line_alt_mode
++};
++
++enum line_num {
++ _1line,
++ _2lines,
++ _3lines,
++ _4lines
++};
++
++enum line_pos {
++ _1stline,
++ _2ndline,
++ _3rdline,
++ _4thline
++};
++
++struct fmtplen {
++ unsigned int plen0;
++ unsigned int plen1;
++ unsigned int plen2;
++ unsigned int plen3;
++};
++
++struct fmtcfg {
++ enum fmtmode mode;
++ enum line_num lnum;
++ unsigned int addrinc;
++};
++
++struct fmtaddr_ptr {
++ unsigned int init;
++ enum line_pos line;
++};
++
++struct fmtpgm_ap {
++ unsigned int pgm_aptr;
++ unsigned char pgmupdt;
++};
++
++/* Main Structure for data formatter*/
++struct data_formatter {
++ unsigned char fmt_enable;
++ struct fmtcfg cfg;
++ struct fmtplen plen;
++ unsigned int fmtsph;
++ unsigned int fmtlnh;
++ unsigned int fmtslv;
++ unsigned int fmtlnv;
++ unsigned int fmtrlen;
++ unsigned int fmthcnt;
++ struct fmtaddr_ptr addr_ptr[8];
++ unsigned char pgm_en[32];
++ struct fmtpgm_ap pgm_ap[32];
++};
++
++/* Structures for Vertical Defect Correction*/
++enum vdf_csl {
++ normal = 0,
++ horz_interpol_sat,
++ horz_interpol
++};
++
++enum vdf_cuda {
++ whole_line_correct,
++ upper_disable
++};
++
++enum dfc_mwr {
++ write_complete,
++ write_reg
++};
++
++enum dfc_mrd {
++ read_complete,
++ read_reg
++};
++
++enum dfc_ma_rst {
++ incr_addr,
++ clr_addr
++};
++
++enum dfc_mclr {
++ clear_complete,
++ clear
++};
++
++struct dft_corr_ctl_s {
++ enum vdf_csl vdfcsl;
++ enum vdf_cuda vdfcuda;
++ unsigned int vdflsft;
++};
++
++struct dft_corr_mem_ctl_s {
++ enum dfc_mwr dfcmwr;
++ enum dfc_mrd dfcmrd;
++ enum dfc_ma_rst dfcmarst;
++ enum dfc_mclr dfcmclr;
++};
++
++/* Main Structure for vertical defect correction. Vertical defect
++ * correction can correct upto 16 defects if defects less than 16
++ * then pad the rest with 0
++ */
++struct vertical_dft_s {
++ unsigned char ver_dft_en;
++ unsigned char gen_dft_en;
++ unsigned int saturation_ctl;
++ struct dft_corr_ctl_s dft_corr_ctl;
++ struct dft_corr_mem_ctl_s dft_corr_mem_ctl;
++ unsigned int dft_corr_horz[16];
++ unsigned int dft_corr_vert[16];
++ unsigned int dft_corr_sub1[16];
++ unsigned int dft_corr_sub2[16];
++ unsigned int dft_corr_sub3[16];
++};
++
++struct data_offset {
++ unsigned char horz_offset;
++ unsigned char vert_offset;
++};
++
++/* Structure for CCDC configuration parameters for raw capture mode passed
++ * by application
++ */
++struct ccdc_config_params_raw {
++ /* pixel format */
++ enum ccdc_pixfmt pix_fmt;
++ /* progressive or interlaced frame */
++ enum ccdc_frmfmt frm_fmt;
++ /* video window */
++ struct ccdc_imgwin win;
++ /* field id polarity */
++ enum ccdc_pinpol fid_pol;
++ /* vertical sync polarity */
++ enum ccdc_pinpol vd_pol;
++ /* horizontal sync polarity */
++ enum ccdc_pinpol hd_pol;
++ /* interleaved or separated fields */
++ enum ccdc_buftype buf_type;
++ /*data shift to be applied before storing */
++ enum ccdc_datasft datasft;
++ /*median filter for sdram */
++ enum ccdc_mfilt1 mfilt1;
++ enum ccdc_mfilt2 mfilt2;
++ /*median filter for ipipe */
++ /*low pass filter enable/disable */
++ unsigned char lpf_enable;
++ unsigned char horz_flip_enable;
++ /*offset value to be applied to data */
++ /*Range is 0 to 1023 */
++ unsigned int ccdc_offset;
++ /*Threshold of median filter */
++ int med_filt_thres;
++ /* enable to store the image in inverse */
++ unsigned char image_invert_enable;
++ /* data size value from 8 to 16 bits */
++ enum data_size data_sz;
++ /*horz and vertical data offset */
++ struct data_offset data_offset_s;
++ /* Structure for Optional A-Law */
++ struct ccdc_a_law alaw;
++ /* Structure for Optical Black Clamp */
++ struct ccdc_black_clamp blk_clamp;
++ /* Structure for Black Compensation */
++ struct black_compensation blk_comp;
++ /*struture for vertical Defect Correction Module Configuration */
++ struct vertical_dft_s vertical_dft;
++ /*structure for lens shading Correction Module Configuration */
++ struct lens_shading_corr lens_sh_corr;
++ /*structure for data formatter Module Configuration */
++ struct data_formatter data_formatter_r;
++ /*structure for color space converter Module Configuration */
++ struct color_space_converter color_space_con;
++ struct ccdc_col_pat col_pat_field0;
++ struct ccdc_col_pat col_pat_field1;
++};
++
++#ifdef __KERNEL__
++#include <linux/io.h>
++/* SOC specific controls for Bayer capture. The CIDs
++ * listed here should match with that in davinci_vpfe.h
++ */
++/* White balance on Bayer RGB. U11Q8 */
++#define CCDC_CID_R_GAIN (V4L2_CID_PRIVATE_BASE + 0)
++#define CCDC_CID_GR_GAIN (V4L2_CID_PRIVATE_BASE + 1)
++#define CCDC_CID_GB_GAIN (V4L2_CID_PRIVATE_BASE + 2)
++#define CCDC_CID_B_GAIN (V4L2_CID_PRIVATE_BASE + 3)
++/* Offsets */
++#define CCDC_CID_OFFSET (V4L2_CID_PRIVATE_BASE + 4)
++#define CCDC_CID_MAX (V4L2_CID_PRIVATE_BASE + 5)
++#define CCDC_MAX_CONTROLS 5
++
++/* Gain applied to Raw Bayer data */
++struct ccdc_gain {
++ unsigned short r_ye;
++ unsigned short gr_cy;
++ unsigned short gb_g;
++ unsigned short b_mg;
++};
++
++/* Structure for CCDC configuration parameters for raw capture mode */
++struct ccdc_params_raw {
++ /* pixel format */
++ enum ccdc_pixfmt pix_fmt;
++ /* progressive or interlaced frame */
++ enum ccdc_frmfmt frm_fmt;
++ /* video window */
++ struct ccdc_imgwin win;
++ /* field id polarity */
++ enum ccdc_pinpol fid_pol;
++ /* vertical sync polarity */
++ enum ccdc_pinpol vd_pol;
++ /* horizontal sync polarity */
++ enum ccdc_pinpol hd_pol;
++ /* interleaved or separated fields */
++ enum ccdc_buftype buf_type;
++ /*data shift to be applied before storing */
++ enum ccdc_datasft datasft;
++ /*median filter for sdram */
++ enum ccdc_mfilt1 mfilt1;
++ /*median filter for ipipe */
++ enum ccdc_mfilt2 mfilt2;
++ /*low pass filter enable/disable */
++ unsigned char lpf_enable;
++ unsigned char horz_flip_enable;
++ /*offset value to be applied to data */
++ /*Range is 0 to 1023 */
++ unsigned int ccdc_offset;
++ /* Gain values */
++ struct ccdc_gain gain;
++ /*Threshold of median filter */
++ int med_filt_thres;
++ /* enable to store the image in inverse order in memory
++ * (bottom to top)
++ */
++ unsigned char image_invert_enable;
++ /* data size value from 8 to 16 bits */
++ enum data_size data_sz;
++ /* Structure for Optional A-Law */
++ struct ccdc_a_law alaw;
++ /*horz and vertical data offset */
++ struct data_offset data_offset_s;
++ /* Structure for Optical Black Clamp */
++ struct ccdc_black_clamp blk_clamp;
++ /* Structure for Black Compensation */
++ struct black_compensation blk_comp;
++ /*struture for vertical Defect Correction Module Configuration */
++ struct vertical_dft_s vertical_dft;
++ /*structure for lens shading Correction Module Configuration */
++ struct lens_shading_corr lens_sh_corr;
++ /*structure for data formatter Module Configuration */
++ struct data_formatter data_formatter_r;
++ /*structure for color space converter Module Configuration */
++ struct color_space_converter color_space_con;
++ struct ccdc_col_pat col_pat_field0;
++ struct ccdc_col_pat col_pat_field1;
++};
++
++struct ccdc_params_ycbcr {
++ /* pixel format */
++ enum ccdc_pixfmt pix_fmt;
++ /* progressive or interlaced frame */
++ enum ccdc_frmfmt frm_fmt;
++ /* video window */
++ struct ccdc_imgwin win;
++ /* field id polarity */
++ enum ccdc_pinpol fid_pol;
++ /* vertical sync polarity */
++ enum ccdc_pinpol vd_pol;
++ /* horizontal sync polarity */
++ enum ccdc_pinpol hd_pol;
++ /* enable BT.656 embedded sync mode */
++ int bt656_enable;
++ /* cb:y:cr:y or y:cb:y:cr in memory */
++ enum ccdc_pixorder pix_order;
++ /* interleaved or separated fields */
++ enum ccdc_buftype buf_type;
++};
++
++struct ccdc_supported_pix_fmt {
++ int index;
++ unsigned int pix_fmt;
++};
++
++/**************************************************************************\
++* Register OFFSET Definitions
++\**************************************************************************/
++#define SYNCEN 0x00
++#define MODESET 0x04
++#define HDWIDTH 0x08
++#define VDWIDTH 0x0c
++#define PPLN 0x10
++#define LPFR 0x14
++#define SPH 0x18
++#define NPH 0x1c
++#define SLV0 0x20
++#define SLV1 0x24
++#define NLV 0x28
++#define CULH 0x2c
++#define CULV 0x30
++#define HSIZE 0x34
++#define SDOFST 0x38
++#define STADRH 0x3c
++#define STADRL 0x40
++#define CLAMP 0x44
++#define DCSUB 0x48
++#define COLPTN 0x4c
++#define BLKCMP0 0x50
++#define BLKCMP1 0x54
++#define MEDFILT 0x58
++#define RYEGAIN 0x5c
++#define GRCYGAIN 0x60
++#define GBGGAIN 0x64
++#define BMGGAIN 0x68
++#define OFFSET 0x6c
++#define OUTCLIP 0x70
++#define VDINT0 0x74
++#define VDINT1 0x78
++#define RSV0 0x7c
++#define GAMMAWD 0x80
++#define REC656IF 0x84
++#define CCDCFG 0x88
++#define FMTCFG 0x8c
++#define FMTPLEN 0x90
++#define FMTSPH 0x94
++#define FMTLNH 0x98
++#define FMTSLV 0x9c
++#define FMTLNV 0xa0
++#define FMTRLEN 0xa4
++#define FMTHCNT 0xa8
++#define FMT_ADDR_PTR_B 0xac
++#define FMT_ADDR_PTR(i) (FMT_ADDR_PTR_B + (i*4))
++#define FMTPGM_VF0 0xcc
++#define FMTPGM_VF1 0xd0
++#define FMTPGM_AP0 0xd4
++#define FMTPGM_AP1 0xd8
++#define FMTPGM_AP2 0xdc
++#define FMTPGM_AP3 0xe0
++#define FMTPGM_AP4 0xe4
++#define FMTPGM_AP5 0xe8
++#define FMTPGM_AP6 0xec
++#define FMTPGM_AP7 0xf0
++#define LSCCFG1 0xf4
++#define LSCCFG2 0xf8
++#define LSCH0 0xfc
++#define LSCV0 0x100
++#define LSCKH 0x104
++#define LSCKV 0x108
++#define LSCMEMCTL 0x10c
++#define LSCMEMD 0x110
++#define LSCMEMQ 0x114
++#define DFCCTL 0x118
++#define DFCVSAT 0x11c
++#define DFCMEMCTL 0x120
++#define DFCMEM0 0x124
++#define DFCMEM1 0x128
++#define DFCMEM2 0x12c
++#define DFCMEM3 0x130
++#define DFCMEM4 0x134
++#define CSCCTL 0x138
++#define CSCM0 0x13c
++#define CSCM1 0x140
++#define CSCM2 0x144
++#define CSCM3 0x148
++#define CSCM4 0x14c
++#define CSCM5 0x150
++#define CSCM6 0x154
++#define CSCM7 0x158
++#define DATAOFST 0x15c
++
++#define CLKCTRL (0x04)
++
++/* offset relative to 0x1c70800 */
++#define INTSTAT (0xC)
++#define INTSEL (0x10)
++#define EVTSEL (0x14)
++#define MEMCTRL (0x18)
++#define CCDCMUX (0x1C)
++
++/**************************************************************
++* Define for various register bit mask and shifts for CCDC
++*
++**************************************************************/
++#define CCDC_RAW_IP_MODE (0x00)
++#define CCDC_VDHDOUT_INPUT (0x00)
++#define CCDC_YCINSWP_RAW (0x00 << 4)
++#define CCDC_EXWEN_DISABLE (0x00)
++#define CCDC_DATAPOL_NORMAL (0x00)
++#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC (0x00)
++#define CCDC_CCDCFG_WENLOG_AND (0x00)
++#define CCDC_CCDCFG_TRGSEL_WEN (0x00)
++#define CCDC_CCDCFG_EXTRG_DISABLE (0x00)
++#define CCDC_CFA_MOSAIC (0x00)
++
++#define CCDC_VDC_DFCVSAT_MASK (0x3fff)
++#define CCDC_DATAOFST_MASK (0x0ff)
++#define CCDC_DATAOFST_H_SHIFT (0)
++#define CCDC_DATAOFST_V_SHIFT (8)
++#define CCDC_GAMMAWD_CFA_MASK (0x01)
++#define CCDC_GAMMAWD_CFA_SHIFT (5)
++#define CCDC_FID_POL_MASK (0x01)
++#define CCDC_FID_POL_SHIFT (4)
++#define CCDC_HD_POL_MASK (0x01)
++#define CCDC_HD_POL_SHIFT (3)
++#define CCDC_VD_POL_MASK (0x01)
++#define CCDC_VD_POL_SHIFT (2)
++#define CCDC_FRM_FMT_MASK (0x01)
++#define CCDC_FRM_FMT_SHIFT (7)
++#define CCDC_DATA_SZ_MASK (0x07)
++#define CCDC_DATA_SZ_SHIFT (8)
++#define CCDC_VDHDOUT_MASK (0x01)
++#define CCDC_VDHDOUT_SHIFT (0)
++#define CCDC_EXWEN_MASK (0x01)
++#define CCDC_EXWEN_SHIFT (5)
++#define CCDC_RAW_INPUT_MASK (0x03)
++#define CCDC_RAW_INPUT_SHIFT (12)
++#define CCDC_PIX_FMT_MASK (0x03)
++#define CCDC_PIX_FMT_SHIFT (12)
++#define CCDC_DATAPOL_MASK (0x01)
++#define CCDC_DATAPOL_SHIFT (6)
++#define CCDC_WEN_ENABLE (0x01 << 1)
++#define CCDC_VDHDEN_ENABLE (0x01 << 16)
++#define CCDC_LPF_ENABLE (0x01 << 14)
++#define CCDC_ALAW_ENABLE (0x01)
++#define CCDC_ALAW_GAMA_WD_MASK (0x07)
++
++#define CCDC_FMTCFG_FMTMODE_MASK (0x03)
++#define CCDC_FMTCFG_FMTMODE_SHIFT (1)
++#define CCDC_FMTCFG_LNUM_MASK (0x03)
++#define CCDC_FMTCFG_LNUM_SHIFT (4)
++#define CCDC_FMTCFG_ADDRINC_MASK (0x07)
++#define CCDC_FMTCFG_ADDRINC_SHIFT (8)
++
++#define CCDC_CCDCFG_FIDMD_SHIFT (6)
++#define CCDC_CCDCFG_WENLOG_SHIFT (8)
++#define CCDC_CCDCFG_TRGSEL_SHIFT (9)
++#define CCDC_CCDCFG_EXTRG_SHIFT (10)
++#define CCDC_CCDCFG_MSBINVI_SHIFT (13)
++
++#define CCDC_HSIZE_FLIP_SHIFT (12)
++#define CCDC_HSIZE_FLIP_MASK (0x01)
++
++#define START_PX_HOR_MASK (0x7FFF)
++#define NUM_PX_HOR_MASK (0x7FFF)
++#define START_VER_ONE_MASK (0x7FFF)
++#define START_VER_TWO_MASK (0x7FFF)
++#define NUM_LINES_VER (0x7FFF)
++
++#define CCDC_BLK_CLAMP_ENABLE (0x01 << 15)
++#define CCDC_BLK_SGAIN_MASK (0x1F)
++#define CCDC_BLK_ST_PXL_MASK (0x1FFF)
++#define CCDC_BLK_SAMPLE_LN_MASK (0x03)
++#define CCDC_BLK_SAMPLE_LN_SHIFT (13)
++
++#define CCDC_NUM_LINE_CALC_MASK (0x03)
++#define CCDC_NUM_LINE_CALC_SHIFT (14)
++
++#define CCDC_BLK_DC_SUB_MASK (0x03FFF)
++#define CCDC_BLK_COMP_MASK (0x000000FF)
++#define CCDC_BLK_COMP_GB_COMP_SHIFT (8)
++#define CCDC_BLK_COMP_GR_COMP_SHIFT (0)
++#define CCDC_BLK_COMP_R_COMP_SHIFT (8)
++#define CCDC_LATCH_ON_VSYNC_DISABLE (0x01 << 15)
++#define CCDC_LATCH_ON_VSYNC_ENABLE (0x00 << 15)
++#define CCDC_FPC_ENABLE (0x01 << 15)
++#define CCDC_FPC_FPC_NUM_MASK (0x7FFF)
++#define CCDC_DATA_PACK_ENABLE (0x01 << 11)
++#define CCDC_FMT_HORZ_FMTLNH_MASK (0x1FFF)
++#define CCDC_FMT_HORZ_FMTSPH_MASK (0x1FFF)
++#define CCDC_FMT_HORZ_FMTSPH_SHIFT (16)
++#define CCDC_FMT_VERT_FMTLNV_MASK (0x1FFF)
++#define CCDC_FMT_VERT_FMTSLV_MASK (0x1FFF)
++#define CCDC_FMT_VERT_FMTSLV_SHIFT (16)
++#define CCDC_VP_OUT_VERT_NUM_MASK (0x3FFF)
++#define CCDC_VP_OUT_VERT_NUM_SHIFT (17)
++#define CCDC_VP_OUT_HORZ_NUM_MASK (0x1FFF)
++#define CCDC_VP_OUT_HORZ_NUM_SHIFT (4)
++#define CCDC_VP_OUT_HORZ_ST_MASK (0x000F)
++
++#define CCDC_CSC_COEFF_SHIFT (8)
++#define CCDC_CSC_COEFF_DEC_MASK (0x0007)
++#define CCDC_CSC_COEFF_FRAC_MASK (0x001F)
++#define CCDC_CSC_DEC_SHIFT (5)
++#define CCDC_CSC_ENABLE (0x01)
++#define CCDC_MFILT1_SHIFT (10)
++#define CCDC_MFILT2_SHIFT (8)
++#define CCDC_LPF_MASK (0x01)
++#define CCDC_LPF_SHIFT (14)
++#define CCDC_OFFSET_MASK (0x3FF)
++#define CCDC_DATASFT_MASK (0x07)
++#define CCDC_DATASFT_SHIFT (8)
++#define CCDC_DF_ENABLE (0x01)
++
++#define CCDC_FMTPLEN_P0_MASK (0x000F)
++#define CCDC_FMTPLEN_P1_MASK (0x000F)
++#define CCDC_FMTPLEN_P2_MASK (0x0007)
++#define CCDC_FMTPLEN_P3_MASK (0x0007)
++#define CCDC_FMTPLEN_P0_SHIFT (0)
++#define CCDC_FMTPLEN_P1_SHIFT (4)
++#define CCDC_FMTPLEN_P2_SHIFT (8)
++#define CCDC_FMTPLEN_P3_SHIFT (12)
++
++#define CCDC_FMTSPH_MASK (0x01FFF)
++#define CCDC_FMTLNH_MASK (0x01FFF)
++#define CCDC_FMTSLV_MASK (0x01FFF)
++#define CCDC_FMTLNV_MASK (0x07FFF)
++#define CCDC_FMTRLEN_MASK (0x01FFF)
++#define CCDC_FMTHCNT_MASK (0x01FFF)
++
++#define CCDC_ADP_INIT_MASK (0x01FFF)
++#define CCDC_ADP_LINE_SHIFT (13)
++#define CCDC_ADP_LINE_MASK (0x0003)
++#define CCDC_FMTPGN_APTR_MASK (0x0007)
++
++#define CCDC_DFCCTL_GDFCEN_MASK (0x01)
++#define CCDC_DFCCTL_VDFCEN_MASK (0x01)
++#define CCDC_DFCCTL_VDFCEN_SHIFT (4)
++#define CCDC_DFCCTL_VDFCSL_MASK (0x03)
++#define CCDC_DFCCTL_VDFCSL_SHIFT (5)
++#define CCDC_DFCCTL_VDFCUDA_MASK (0x01)
++#define CCDC_DFCCTL_VDFCUDA_SHIFT (7)
++#define CCDC_DFCCTL_VDFLSFT_MASK (0x03)
++#define CCDC_DFCCTL_VDFLSFT_SHIFT (8)
++#define CCDC_DFCMEMCTL_DFCMARST_MASK (0x01)
++#define CCDC_DFCMEMCTL_DFCMARST_SHIFT (2)
++#define CCDC_DFCMEMCTL_DFCMWR_MASK (0x01)
++#define CCDC_DFCMEMCTL_DFCMWR_SHIFT (0)
++
++#define CCDC_LSCCFG_GFTSF_MASK (0x07)
++#define CCDC_LSCCFG_GFTSF_SHIFT (1)
++#define CCDC_LSCCFG_GFTINV_MASK (0x0f)
++#define CCDC_LSCCFG_GFTINV_SHIFT (4)
++#define CCDC_LSC_GFTABLE_SEL_MASK (0x03)
++#define CCDC_LSC_GFTABLE_EPEL_SHIFT (8)
++#define CCDC_LSC_GFTABLE_OPEL_SHIFT (10)
++#define CCDC_LSC_GFTABLE_EPOL_SHIFT (12)
++#define CCDC_LSC_GFTABLE_OPOL_SHIFT (14)
++#define CCDC_LSC_GFMODE_MASK (0x03)
++#define CCDC_LSC_GFMODE_SHIFT (4)
++#define CCDC_LSC_DISABLE (0)
++#define CCDC_LSC_ENABLE (1)
++#define CCDC_LSC_TABLE1_SLC (0)
++#define CCDC_LSC_TABLE2_SLC (1)
++#define CCDC_LSC_TABLE3_SLC (2)
++#define CCDC_LSC_MEMADDR_RESET (1 << 2)
++#define CCDC_LSC_MEMADDR_INCR (0 << 2)
++#define CCDC_LSC_FRAC_MASK_T1 (0xFF)
++#define CCDC_LSC_INT_MASK (0x03)
++#define CCDC_LSC_FRAC_MASK (0x3FFF)
++#define CCDC_LSC_CENTRE_MASK (0x3FFF)
++#define CCDC_LSC_COEF_MASK (0x0ff)
++#define CCDC_LSC_COEFL_SHIFT (0)
++#define CCDC_LSC_COEFU_SHIFT (8)
++#define CCDC_GAIN_MASK (0x7FF)
++#endif
++#endif /* CCDC_DM355_H */
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci/vfpe4.patch b/recipes/linux/linux-davinci/vfpe4.patch
new file mode 100644
index 0000000000..2e95f9eea4
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe4.patch
@@ -0,0 +1,1660 @@
+Subject:
+[PATCH 4/7] ccdc hw module and header file for DM6446
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:23:16 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Adds ccdc hw module and it's header file
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ drivers/media/video/ccdc_davinci.c | 124 ----
+ drivers/media/video/davinci/ccdc_davinci.c | 1007 ++++++++++++++++++++++++++++
+ drivers/media/video/davinci/ccdc_davinci.h | 335 +++++++++
+ include/media/ccdc_davinci.h | 144 ----
+ 4 files changed, 1342 insertions(+), 268 deletions(-)
+ delete mode 100644 drivers/media/video/ccdc_davinci.c
+ create mode 100644 drivers/media/video/davinci/ccdc_davinci.c
+ create mode 100644 drivers/media/video/davinci/ccdc_davinci.h
+ delete mode 100644 include/media/ccdc_davinci.h
+
+diff --git a/drivers/media/video/ccdc_davinci.c b/drivers/media/video/ccdc_davinci.c
+deleted file mode 100644
+index d3cd333..0000000
+--- a/drivers/media/video/ccdc_davinci.c
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/*
+- *
+- *
+- * Copyright (C) 2006 Texas Instruments Inc
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-/* ccdc_davinci.c */
+-
+-#include <media/ccdc_davinci.h>
+-#define debug_print(x...) //printk(x)
+-void ccdc_reset()
+-{
+- int i;
+- /* disable CCDC */
+- ccdc_enable(0);
+- /* set all registers to default value */
+- for (i = 0; i <= 0x94; i += 4) {
+- regw(0, i);
+- }
+- regw(0, PCR);
+- regw(0, SYN_MODE);
+- regw(0, HD_VD_WID);
+- regw(0, PIX_LINES);
+- regw(0, HORZ_INFO);
+- regw(0, VERT_START);
+- regw(0, VERT_LINES);
+- regw(0xffff00ff, CULLING);
+- regw(0, HSIZE_OFF);
+- regw(0, SDOFST);
+- regw(0, SDR_ADDR);
+- regw(0, VDINT);
+- regw(0, REC656IF);
+- regw(0, CCDCFG);
+- regw(0, FMTCFG);
+- regw(0, VP_OUT);
+-}
+-
+-void ccdc_setwin(ccdc_params_ycbcr * params)
+-{
+- int horz_start, horz_nr_pixels;
+- int vert_start, vert_nr_lines;
+-
+- /* configure horizonal and vertical starts and sizes */
+- horz_start = params->win.left << 1;
+- horz_nr_pixels = (params->win.width <<1) - 1;
+- regw((horz_start << 16) | horz_nr_pixels, HORZ_INFO);
+-
+- vert_start = params->win.top;
+-
+- if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
+- vert_nr_lines = (params->win.height >> 1) - 1;
+- vert_start >>= 1;
+- } else {
+- vert_nr_lines = params->win.height - 1;
+- }
+- regw((vert_start << 16) | vert_start, VERT_START);
+- regw(vert_nr_lines, VERT_LINES);
+-}
+-
+-void ccdc_config_ycbcr(ccdc_params_ycbcr * params)
+-{
+- u32 syn_mode;
+-
+- /* first reset the CCDC */
+- /* all registers have default values after reset */
+- /* This is important since we assume default values to be set in */
+- /* a lot of registers that we didn't touch */
+- ccdc_reset();
+-
+- /* configure pixel format */
+- syn_mode = (params->pix_fmt & 0x3) << 12;
+-
+- /* configure video frame format */
+- syn_mode |= (params->frm_fmt & 0x1) << 7;
+-
+- /* setup BT.656 sync mode */
+- if (params->bt656_enable) {
+- regw(3, REC656IF);
+-
+- /* configure the FID, VD, HD pin polarity */
+- /* fld,hd pol positive, vd negative, 8-bit pack mode */
+- syn_mode |= 0x00000F04;
+- } else {/* y/c external sync mode */
+- syn_mode |= ((params->fid_pol & 0x1) << 4);
+- syn_mode |= ((params->hd_pol & 0x1) << 3);
+- syn_mode |= ((params->vd_pol & 0x1) << 2);
+- }
+-
+- /* configure video window */
+- ccdc_setwin(params);
+-
+- /* configure the order of y cb cr in SD-RAM */
+- regw((params->pix_order << 11) | 0x8000, CCDCFG);
+-
+- /* configure the horizontal line offset */
+- /* this is done by rounding up width to a multiple of 16 pixels */
+- /* and multiply by two to account for y:cb:cr 4:2:2 data */
+- regw(((params->win.width * 2) + 31) & 0xffffffe0, HSIZE_OFF);
+-
+- /* configure the memory line offset */
+- if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
+- /* two fields are interleaved in memory */
+- regw(0x00000249, SDOFST);
+- }
+- /* enable output to SDRAM */
+- syn_mode |= (0x1 << 17);
+- /* enable internal timing generator */
+- syn_mode |= (0x1 << 16);
+-
+- regw(syn_mode, SYN_MODE);
+-}
+diff --git a/drivers/media/video/davinci/ccdc_davinci.c b/drivers/media/video/davinci/ccdc_davinci.c
+new file mode 100644
+index 0000000..0bb596e
+--- /dev/null
++++ b/drivers/media/video/davinci/ccdc_davinci.c
+@@ -0,0 +1,1007 @@
++/*
++ * Copyright (C) 2006-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/platform_device.h>
++#include <linux/uaccess.h>
++#include <asm/page.h>
++#include <media/davinci/ccdc_hw_device.h>
++#include "ccdc_davinci.h"
++
++static struct device *dev;
++
++/* Object for CCDC raw mode */
++static struct ccdc_params_raw ccdc_hw_params_raw = {
++ .pix_fmt = CCDC_PIXFMT_RAW,
++ .frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
++ .win = CCDC_WIN_VGA,
++ .fid_pol = CCDC_PINPOL_POSITIVE,
++ .vd_pol = CCDC_PINPOL_POSITIVE,
++ .hd_pol = CCDC_PINPOL_POSITIVE,
++ .image_invert_enable = 0,
++ .data_sz = _10BITS,
++ .alaw = {
++ .b_alaw_enable = 0
++ },
++ .blk_clamp = {
++ .b_clamp_enable = 0,
++ .dc_sub = 0
++ },
++ .blk_comp = {0, 0, 0, 0},
++ .fault_pxl = {
++ .fpc_enable = 0
++ },
++};
++
++/* Object for CCDC ycbcr mode */
++static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = {
++ .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
++ .frm_fmt = CCDC_FRMFMT_INTERLACED,
++ .win = CCDC_WIN_PAL,
++ .fid_pol = CCDC_PINPOL_POSITIVE,
++ .vd_pol = CCDC_PINPOL_POSITIVE,
++ .hd_pol = CCDC_PINPOL_POSITIVE,
++ .bt656_enable = 1,
++ .pix_order = CCDC_PIXORDER_CBYCRY,
++ .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
++};
++
++#define CCDC_MAX_RAW_BAYER_FORMATS 2
++#define CCDC_MAX_RAW_YUV_FORMATS 2
++
++/* Raw Bayer formats */
++enum vpfe_hw_pix_format ccdc_raw_bayer_hw_formats[CCDC_MAX_RAW_BAYER_FORMATS] =
++ {VPFE_BAYER_8BIT_PACK_ALAW, VPFE_BAYER};
++
++/* Raw YUV formats */
++enum vpfe_hw_pix_format ccdc_raw_yuv_hw_formats[CCDC_MAX_RAW_YUV_FORMATS] =
++ {VPFE_UYVY, VPFE_YUYV};
++
++static void *__iomem ccdc_base_addr;
++static int ccdc_addr_size;
++static void *__iomem vpss_base_addr;
++static int vpss_addr_size;
++static struct ccdc_config_params_raw ccdc_hw_params_raw_temp;
++static enum vpfe_hw_if_type ccdc_if_type;
++
++/* register access routines */
++static inline u32 regr(u32 offset)
++{
++ if (offset <= ccdc_addr_size)
++ return __raw_readl(ccdc_base_addr + offset);
++ else {
++ dev_err(dev, "offset exceeds ccdc register address space\n");
++ return -1;
++ }
++}
++
++static inline u32 regw(u32 val, u32 offset)
++{
++ if (offset <= ccdc_addr_size) {
++ __raw_writel(val, ccdc_base_addr + offset);
++ return val;
++ } else {
++ dev_err(dev, "offset exceeds ccdc register address space\n");
++ return -1;
++ }
++}
++
++/* register access routines */
++static inline u32 regr_sb(u32 offset)
++{
++ if (offset <= vpss_addr_size)
++ return __raw_readl(vpss_base_addr + offset);
++ else {
++ dev_err(dev, "offset exceeds vpss register address space\n");
++ return -1;
++ }
++}
++
++static inline u32 regw_sb(u32 val, u32 offset)
++{
++ if (offset <= vpss_addr_size) {
++ __raw_writel(val, vpss_base_addr + offset);
++ return val;
++ } else {
++ dev_err(dev, "offset exceeds vpss register address space\n");
++ return -1;
++ }
++}
++
++static void ccdc_set_ccdc_base(void *addr, int size)
++{
++ ccdc_base_addr = addr;
++ ccdc_addr_size = size;
++}
++
++static void ccdc_set_vpss_base(void *addr, int size)
++{
++ vpss_base_addr = addr;
++ vpss_addr_size = size;
++}
++
++static void *ccdc_get_ccdc_base(void)
++{
++ return (void *)ccdc_base_addr;
++}
++
++static void *ccdc_get_vpss_base(void)
++{
++ return (void *)vpss_base_addr;
++}
++
++static void ccdc_enable(int flag)
++{
++ regw(flag, PCR);
++}
++
++static void ccdc_enable_vport(int flag)
++{
++ if (flag)
++ /* enable video port */
++ regw(ENABLE_VIDEO_PORT, FMTCFG);
++ else
++ regw(DISABLE_VIDEO_PORT, FMTCFG);
++}
++
++/*
++ * ======== ccdc_setwin ========
++ * This function will configure the window size
++ * to be capture in CCDC reg
++ */
++void ccdc_setwin(struct ccdc_imgwin *image_win,
++ enum ccdc_frmfmt frm_fmt,
++ int ppc)
++{
++ int horz_start, horz_nr_pixels;
++ int vert_start, vert_nr_lines;
++ int val = 0, mid_img = 0;
++ dev_dbg(dev, "\nStarting ccdc_setwin...");
++ /* configure horizonal and vertical starts and sizes */
++ /* Here, (ppc-1) will be different for raw and yuv modes */
++ horz_start = image_win->left << (ppc - 1);
++ horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
++ regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels,
++ HORZ_INFO);
++
++ vert_start = image_win->top;
++
++ if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
++ vert_nr_lines = (image_win->height >> 1) - 1;
++ vert_start >>= 1;
++ /* Since first line doesn't have any data */
++ vert_start += 1;
++ /* configure VDINT0 */
++ val = (vert_start << CCDC_VDINT_VDINT0_SHIFT);
++ regw(val, VDINT);
++
++ } else {
++ /* Since first line doesn't have any data */
++ vert_start += 1;
++ vert_nr_lines = image_win->height - 1;
++ /* configure VDINT0 and VDINT1 */
++ /* VDINT1 will be at half of image height */
++ mid_img = vert_start + (image_win->height / 2);
++ val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) |
++ (mid_img & CCDC_VDINT_VDINT1_MASK);
++ regw(val, VDINT);
++
++ }
++ regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start,
++ VERT_START);
++ regw(vert_nr_lines, VERT_LINES);
++ dev_dbg(dev, "\nEnd of ccdc_setwin...");
++}
++
++static void ccdc_readregs(void)
++{
++ unsigned int val = 0;
++
++ val = regr(ALAW);
++ dev_notice(dev, "\nReading 0x%x to ALAW...\n", val);
++ val = regr(CLAMP);
++ dev_notice(dev, "\nReading 0x%x to CLAMP...\n", val);
++ val = regr(DCSUB);
++ dev_notice(dev, "\nReading 0x%x to DCSUB...\n", val);
++ val = regr(BLKCMP);
++ dev_notice(dev, "\nReading 0x%x to BLKCMP...\n", val);
++ val = regr(FPC_ADDR);
++ dev_notice(dev, "\nReading 0x%x to FPC_ADDR...\n", val);
++ val = regr(FPC);
++ dev_notice(dev, "\nReading 0x%x to FPC...\n", val);
++ val = regr(FMTCFG);
++ dev_notice(dev, "\nReading 0x%x to FMTCFG...\n", val);
++ val = regr(COLPTN);
++ dev_notice(dev, "\nReading 0x%x to COLPTN...\n", val);
++ val = regr(FMT_HORZ);
++ dev_notice(dev, "\nReading 0x%x to FMT_HORZ...\n", val);
++ val = regr(FMT_VERT);
++ dev_notice(dev, "\nReading 0x%x to FMT_VERT...\n", val);
++ val = regr(HSIZE_OFF);
++ dev_notice(dev, "\nReading 0x%x to HSIZE_OFF...\n", val);
++ val = regr(SDOFST);
++ dev_notice(dev, "\nReading 0x%x to SDOFST...\n", val);
++ val = regr(VP_OUT);
++ dev_notice(dev, "\nReading 0x%x to VP_OUT...\n", val);
++ val = regr(SYN_MODE);
++ dev_notice(dev, "\nReading 0x%x to SYN_MODE...\n", val);
++ val = regr(HORZ_INFO);
++ dev_notice(dev, "\nReading 0x%x to HORZ_INFO...\n", val);
++ val = regr(VERT_START);
++ dev_notice(dev, "\nReading 0x%x to VERT_START...\n", val);
++ val = regr(VERT_LINES);
++ dev_notice(dev, "\nReading 0x%x to VERT_LINES...\n", val);
++}
++
++static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
++{
++ if ((ccdc_hw_params_raw.frm_fmt != CCDC_FRMFMT_INTERLACED)
++ && (ccdcparam->image_invert_enable == 1)) {
++ dev_err(dev, "\nImage invert not supported");
++ return -1;
++ }
++ if (ccdc_hw_params_raw.alaw.b_alaw_enable) {
++ if ((ccdcparam->alaw.gama_wd > BITS_09_0)
++ || (ccdcparam->alaw.gama_wd < BITS_15_6)
++ || (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) {
++ dev_err(dev, "\nInvalid data line select");
++ return -1;
++ }
++ }
++ return 0;
++}
++
++static int ccdc_update_ycbcr_params(void *arg)
++{
++ memcpy(&ccdc_hw_params_ycbcr,
++ (struct ccdc_params_ycbcr *)arg,
++ sizeof(struct ccdc_params_ycbcr));
++ return 0;
++}
++
++static int ccdc_update_raw_params(void *arg)
++{
++ unsigned int *fpc_virtaddr = NULL;
++ unsigned int *fpc_physaddr = NULL;
++ struct ccdc_params_raw *ccd_params = &ccdc_hw_params_raw;
++ struct ccdc_config_params_raw *raw_params =
++ (struct ccdc_config_params_raw *) arg;
++ ccd_params->image_invert_enable = raw_params->image_invert_enable;
++
++ dev_dbg(dev, "\nimage_invert_enable = %d",
++ ccd_params->image_invert_enable);
++
++ ccd_params->data_sz = raw_params->data_sz;
++ dev_dbg(dev, "\ndata_sz = %d", ccd_params->data_sz);
++
++ ccd_params->alaw.b_alaw_enable = raw_params->alaw.b_alaw_enable;
++ dev_dbg(dev, "\nALaw Enable = %d", ccd_params->alaw.b_alaw_enable);
++ /* copy A-Law configurations to vpfe_device, from arg
++ * passed by application */
++ if (ccd_params->alaw.b_alaw_enable) {
++ ccd_params->alaw.gama_wd = raw_params->alaw.gama_wd;
++ dev_dbg(dev, "\nALaw Gama width = %d",
++ ccd_params->alaw.gama_wd);
++ }
++
++ /* copy Optical Balck Clamping configurations to
++ * vpfe_device,from arg passed by application */
++ ccd_params->blk_clamp.b_clamp_enable
++ = raw_params->blk_clamp.b_clamp_enable;
++ dev_dbg(dev, "\nb_clamp_enable = %d",
++ ccd_params->blk_clamp.b_clamp_enable);
++ if (ccd_params->blk_clamp.b_clamp_enable) {
++ /*gain */
++ ccd_params->blk_clamp.sgain = raw_params->blk_clamp.sgain;
++ dev_dbg(dev, "\nblk_clamp.sgain = %d",
++ ccd_params->blk_clamp.sgain);
++ /*Start pixel */
++ ccd_params->blk_clamp.start_pixel
++ = raw_params->blk_clamp.start_pixel;
++ dev_dbg(dev, "\nblk_clamp.start_pixel = %d",
++ ccd_params->blk_clamp.start_pixel);
++ /*No of line to be avg */
++ ccd_params->blk_clamp.sample_ln
++ = raw_params->blk_clamp.sample_ln;
++ dev_dbg(dev, "\nblk_clamp.sample_ln = %d",
++ ccd_params->blk_clamp.sample_ln);
++ /*No of pixel/line to be avg */
++ ccd_params->blk_clamp.sample_pixel
++ = raw_params->blk_clamp.sample_pixel;
++ dev_dbg(dev, "\nblk_clamp.sample_pixel = %d",
++ ccd_params->blk_clamp.sample_pixel);
++ } else { /* configure DCSub */
++
++ ccd_params->blk_clamp.dc_sub = raw_params->blk_clamp.dc_sub;
++ dev_dbg(dev, "\nblk_clamp.dc_sub = %d",
++ ccd_params->blk_clamp.dc_sub);
++ }
++
++ /* copy BalckLevel Compansation configurations to
++ * vpfe_device,from arg passed by application
++ */
++ ccd_params->blk_comp.r_comp = raw_params->blk_comp.r_comp;
++ ccd_params->blk_comp.gr_comp = raw_params->blk_comp.gr_comp;
++ ccd_params->blk_comp.b_comp = raw_params->blk_comp.b_comp;
++ ccd_params->blk_comp.gb_comp = raw_params->blk_comp.gb_comp;
++ dev_dbg(dev, "\nblk_comp.r_comp = %d",
++ ccd_params->blk_comp.r_comp);
++ dev_dbg(dev, "\nblk_comp.gr_comp = %d",
++ ccd_params->blk_comp.gr_comp);
++ dev_dbg(dev, "\nblk_comp.b_comp = %d",
++ ccd_params->blk_comp.b_comp);
++ dev_dbg(dev, "\nblk_comp.gb_comp = %d",
++ ccd_params->blk_comp.gb_comp);
++
++ /* copy FPC configurations to vpfe_device,from
++ * arg passed by application
++ */
++ ccd_params->fault_pxl.fpc_enable = raw_params->fault_pxl.fpc_enable;
++ dev_dbg(dev, "\nfault_pxl.fpc_enable = %d",
++ ccd_params->fault_pxl.fpc_enable);
++
++ if (ccd_params->fault_pxl.fpc_enable) {
++ fpc_physaddr =
++ (unsigned int *)ccd_params->fault_pxl.fpc_table_addr;
++
++ fpc_virtaddr = (unsigned int *)
++ phys_to_virt((unsigned long)
++ fpc_physaddr);
++
++ /* Allocate memory for FPC table if current
++ * FPC table buffer is not big enough to
++ * accomodate FPC Number requested
++ */
++ if (raw_params->fault_pxl.fp_num !=
++ ccd_params->fault_pxl.fp_num) {
++ if (fpc_physaddr != NULL) {
++ free_pages((unsigned long)
++ fpc_physaddr,
++ get_order
++ (ccd_params->
++ fault_pxl.fp_num * FP_NUM_BYTES));
++
++ }
++
++ /* Allocate memory for FPC table */
++ fpc_virtaddr = (unsigned int *)
++ __get_free_pages(GFP_KERNEL |
++ GFP_DMA,
++ get_order
++ (raw_params->
++ fault_pxl.fp_num * FP_NUM_BYTES));
++
++ if (fpc_virtaddr == NULL) {
++ dev_err(dev,
++ "\nUnable to allocate memory for FPC");
++ return -1;
++ }
++ fpc_physaddr =
++ (unsigned int *)virt_to_phys((void *)fpc_virtaddr);
++ }
++
++ /* Copy number of fault pixels and FPC table */
++ ccd_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num;
++ if (copy_from_user((void *)fpc_virtaddr,
++ (void *)raw_params->
++ fault_pxl.fpc_table_addr,
++ (unsigned long)ccd_params->
++ fault_pxl.fp_num * FP_NUM_BYTES)) {
++ dev_err(dev, "\n copy_from_user failed");
++ return -1;
++ }
++
++ ccd_params->fault_pxl.fpc_table_addr =
++ (unsigned int)fpc_physaddr;
++ }
++ return 0;
++}
++
++static int ccdc_close(struct device *dev)
++{
++ unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL;
++ fpc_physaddr = (unsigned int *)
++ ccdc_hw_params_raw.fault_pxl.fpc_table_addr;
++
++ if (fpc_physaddr != NULL) {
++ fpc_virtaddr = (unsigned int *)
++ phys_to_virt((unsigned long)fpc_physaddr);
++ free_pages((unsigned long)fpc_virtaddr,
++ get_order(ccdc_hw_params_raw.fault_pxl.
++ fp_num * FP_NUM_BYTES));
++ }
++ return 0;
++}
++
++/*
++ * ======== ccdc_reset ========
++ *
++ * This function will reset all CCDc reg
++ */
++static void ccdc_reset(void)
++{
++ int i;
++
++ /* disable CCDC */
++ ccdc_enable(0);
++ /* set all registers to default value */
++ for (i = 0; i <= 0x94; i += 4)
++ regw(0, i);
++ regw(0, PCR);
++ regw(0, SYN_MODE);
++ regw(0, HD_VD_WID);
++ regw(0, PIX_LINES);
++ regw(0, HORZ_INFO);
++ regw(0, VERT_START);
++ regw(0, VERT_LINES);
++ regw(0xffff00ff, CULLING);
++ regw(0, HSIZE_OFF);
++ regw(0, SDOFST);
++ regw(0, SDR_ADDR);
++ regw(0, VDINT);
++ regw(0, REC656IF);
++ regw(0, CCDCFG);
++ regw(0, FMTCFG);
++ regw(0, VP_OUT);
++}
++
++static int ccdc_open(struct device *device)
++{
++ dev = device;
++ ccdc_reset();
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ ccdc_enable_vport(1);
++ return 0;
++}
++
++static u32 ccdc_sbl_reset(void)
++{
++ u32 sb_reset;
++ sb_reset = regr_sb(SBL_PCR_VPSS);
++ regw_sb((sb_reset & SBL_PCR_CCDC_WBL_O), SBL_PCR_VPSS);
++ return sb_reset;
++}
++
++/* Parameter operations */
++static int ccdc_setparams(void *params)
++{
++ int x;
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ x = copy_from_user(&ccdc_hw_params_raw_temp,
++ (struct ccdc_config_params_raw *)params,
++ sizeof(struct ccdc_config_params_raw));
++ if (x) {
++ dev_err(dev, "ccdc_setparams: error in copying"
++ "ccdc params, %d\n", x);
++ return -1;
++ }
++
++ if (!validate_ccdc_param(&ccdc_hw_params_raw_temp)) {
++ if (!ccdc_update_raw_params(&ccdc_hw_params_raw_temp))
++ return 0;
++ }
++ } else
++ return ccdc_update_ycbcr_params(params);
++ return -1;
++}
++
++/*
++ * ======== ccdc_config_ycbcr ========
++ * This function will configure CCDC for YCbCr parameters
++ */
++void ccdc_config_ycbcr(void)
++{
++ u32 syn_mode;
++ unsigned int val;
++ struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr;
++
++ /* first reset the CCDC */
++ /* all registers have default values after reset */
++ /* This is important since we assume default values to be set in */
++ /* a lot of registers that we didn't touch */
++ dev_dbg(dev, "\nStarting ccdc_config_ycbcr...");
++ ccdc_reset();
++
++ /* configure pixel format */
++ syn_mode = (params->pix_fmt & 0x3) << 12;
++
++ /* configure video frame format */
++ syn_mode |= (params->frm_fmt & 0x1) << 7;
++
++ /* setup BT.656 sync mode */
++ if (params->bt656_enable) {
++ regw(3, REC656IF);
++
++ /* configure the FID, VD, HD pin polarity */
++ /* fld,hd pol positive, vd negative, 8-bit pack mode */
++ syn_mode |= 0x00000F04;
++ } else {
++ /* y/c external sync mode */
++ syn_mode |= ((params->fid_pol & 0x1) << 4);
++ syn_mode |= ((params->hd_pol & 0x1) << 3);
++ syn_mode |= ((params->vd_pol & 0x1) << 2);
++ }
++
++ /* configure video window */
++ ccdc_setwin(&params->win, params->frm_fmt, 2);
++
++ /* configure the order of y cb cr in SD-RAM */
++ regw((params->pix_order << 11) | 0x8000, CCDCFG);
++
++ /* configure the horizontal line offset */
++ /* this is done by rounding up width to a multiple of 16 pixels */
++ /* and multiply by two to account for y:cb:cr 4:2:2 data */
++ regw(((params->win.width * 2) + 31) & 0xffffffe0, HSIZE_OFF);
++
++ /* configure the memory line offset */
++ if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
++ /* two fields are interleaved in memory */
++ regw(0x00000249, SDOFST);
++ /* enable output to SDRAM */
++ syn_mode |= (0x1 << 17);
++ /* enable internal timing generator */
++ syn_mode |= (0x1 << 16);
++
++ syn_mode |= CCDC_DATA_PACK_ENABLE;
++ regw(syn_mode, SYN_MODE);
++
++ val = (unsigned int)ccdc_sbl_reset();
++ dev_dbg(dev, "\nReading 0x%x from SBL...\n", val);
++ dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n");
++ ccdc_readregs();
++}
++
++/*
++ * ======== ccdc_config_raw ========
++ *
++ * This function will configure CCDC for Raw mode parameters
++ */
++void ccdc_config_raw(void)
++{
++ struct ccdc_params_raw *params = &ccdc_hw_params_raw;
++ unsigned int syn_mode = 0;
++ unsigned int val;
++ dev_dbg(dev, "\nStarting ccdc_config_raw...");
++ /* Reset CCDC */
++ ccdc_reset();
++ /* Disable latching function registers on VSYNC */
++ regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDCFG);
++
++ /* Configure the vertical sync polarity(SYN_MODE.VDPOL) */
++ syn_mode = (params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT;
++
++ /* Configure the horizontal sync polarity (SYN_MODE.HDPOL) */
++ syn_mode |= (params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT;
++
++ /* Configure frame id polarity (SYN_MODE.FLDPOL) */
++ syn_mode |= (params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT;
++
++ /* Configure frame format(progressive or interlace) */
++ syn_mode |= (params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT;
++
++ /* Configure the data size(SYNMODE.DATSIZ) */
++ syn_mode |= (params->data_sz & CCDC_DATA_SZ_MASK) << CCDC_DATA_SZ_SHIFT;
++
++ /* Configure pixel format (Input mode) */
++ syn_mode |= (params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT;
++
++ /* Configure VP2SDR bit of syn_mode = 0 */
++ syn_mode &= CCDC_VP2SDR_DISABLE;
++
++ /* Enable write enable bit */
++ syn_mode |= CCDC_WEN_ENABLE;
++
++ /* Disable output to resizer */
++ syn_mode &= CCDC_SDR2RSZ_DISABLE;
++
++ /* enable internal timing generator */
++ syn_mode |= CCDC_VDHDEN_ENABLE;
++
++ /* Enable and configure aLaw register if needed */
++ if (params->alaw.b_alaw_enable) {
++ val = (params->alaw.gama_wd & CCDC_ALAW_GAMA_WD_MASK);
++ /*set enable bit of alaw */
++ val |= CCDC_ALAW_ENABLE;
++ regw(val, ALAW);
++
++ dev_dbg(dev, "\nWriting 0x%x to ALAW...\n", val);
++ }
++
++ /* configure video window */
++ ccdc_setwin(&params->win, params->frm_fmt, PPC_RAW);
++
++ if (params->blk_clamp.b_clamp_enable) {
++ /*gain */
++ val = (params->blk_clamp.sgain) & CCDC_BLK_SGAIN_MASK;
++ /*Start pixel */
++ val |= (params->blk_clamp.start_pixel & CCDC_BLK_ST_PXL_MASK)
++ << CCDC_BLK_ST_PXL_SHIFT;
++ /*No of line to be avg */
++ val |= (params->blk_clamp.sample_ln & CCDC_BLK_SAMPLE_LINE_MASK)
++ << CCDC_BLK_SAMPLE_LINE_SHIFT;
++ /*No of pixel/line to be avg */
++ val |=
++ (params->blk_clamp.sample_pixel & CCDC_BLK_SAMPLE_LN_MASK)
++ << CCDC_BLK_SAMPLE_LN_SHIFT;
++ /*Enable the Black clamping */
++ val |= CCDC_BLK_CLAMP_ENABLE;
++ regw(val, CLAMP);
++
++ dev_dbg(dev, "\nWriting 0x%x to CLAMP...\n", val);
++ /*If Black clamping is enable then make dcsub 0 */
++ regw(DCSUB_DEFAULT_VAL, DCSUB);
++ dev_dbg(dev, "\nWriting 0x00000000 to DCSUB...\n");
++
++ } else {
++ /* configure DCSub */
++ val = (params->blk_clamp.dc_sub) & CCDC_BLK_DC_SUB_MASK;
++ regw(val, DCSUB);
++
++ dev_dbg(dev, "\nWriting 0x%x to DCSUB...\n", val);
++ regw(CLAMP_DEFAULT_VAL, CLAMP);
++
++ dev_dbg(dev, "\nWriting 0x0000 to CLAMP...\n");
++ }
++
++ /* Configure Black level compensation */
++ val = (params->blk_comp.b_comp & CCDC_BLK_COMP_MASK);
++ val |= (params->blk_comp.gb_comp & CCDC_BLK_COMP_MASK)
++ << CCDC_BLK_COMP_GB_COMP_SHIFT;
++ val |= (params->blk_comp.gr_comp & CCDC_BLK_COMP_MASK)
++ << CCDC_BLK_COMP_GR_COMP_SHIFT;
++ val |= (params->blk_comp.r_comp & CCDC_BLK_COMP_MASK)
++ << CCDC_BLK_COMP_R_COMP_SHIFT;
++
++ regw(val, BLKCMP);
++
++ dev_dbg(dev, "\nWriting 0x%x to BLKCMP...\n", val);
++ dev_dbg(dev, "\nbelow regw(val, BLKCMP)...");
++ /* Initially disable FPC */
++ val = CCDC_FPC_DISABLE;
++ regw(val, FPC);
++ /* Configure Fault pixel if needed */
++ if (params->fault_pxl.fpc_enable) {
++ regw(params->fault_pxl.fpc_table_addr, FPC_ADDR);
++
++ dev_dbg(dev, "\nWriting 0x%x to FPC_ADDR...\n",
++ (params->fault_pxl.fpc_table_addr));
++ /* Write the FPC params with FPC disable */
++ val = params->fault_pxl.fp_num & CCDC_FPC_FPC_NUM_MASK;
++ regw(val, FPC);
++
++ dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val);
++ /* read the FPC register */
++ val = regr(FPC);
++ val |= CCDC_FPC_ENABLE;
++ regw(val, FPC);
++
++ dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val);
++ }
++ /* If data size is 8 bit then pack the data */
++ if ((params->data_sz == _8BITS) || params->alaw.b_alaw_enable)
++ syn_mode |= CCDC_DATA_PACK_ENABLE;
++#if VIDEO_PORT_ENABLE
++ /* enable video port */
++ val = ENABLE_VIDEO_PORT;
++#else
++ /* disable video port */
++ val = DISABLE_VIDEO_PORT;
++#endif
++
++ if (params->data_sz == _8BITS)
++ val |= (_10BITS & CCDC_FMTCFG_VPIN_MASK)
++ << CCDC_FMTCFG_VPIN_SHIFT;
++ else
++ val |= (params->data_sz & CCDC_FMTCFG_VPIN_MASK)
++ << CCDC_FMTCFG_VPIN_SHIFT;
++
++ /* Write value in FMTCFG */
++ regw(val, FMTCFG);
++
++ dev_dbg(dev, "\nWriting 0x%x to FMTCFG...\n", val);
++
++ /* Configure the color pattern according to mt9t001 sensor */
++ regw(CCDC_COLPTN_VAL, COLPTN);
++
++ dev_dbg(dev, "\nWriting 0xBB11BB11 to COLPTN...\n");
++ /* Configure Data formatter(Video port) pixel selection
++ * (FMT_HORZ, FMT_VERT)
++ */
++ val = 0;
++ val |= ((params->win.left) & CCDC_FMT_HORZ_FMTSPH_MASK)
++ << CCDC_FMT_HORZ_FMTSPH_SHIFT;
++ val |= (((params->win.width)) & CCDC_FMT_HORZ_FMTLNH_MASK);
++ regw(val, FMT_HORZ);
++
++ dev_dbg(dev, "\nWriting 0x%x to FMT_HORZ...\n", val);
++ val = 0;
++ val |= (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK)
++ << CCDC_FMT_VERT_FMTSLV_SHIFT;
++ if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
++ val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK;
++ else
++ val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK;
++
++ dev_dbg(dev, "\nparams->win.height 0x%x ...\n",
++ params->win.height);
++ regw(val, FMT_VERT);
++
++ dev_dbg(dev, "\nWriting 0x%x to FMT_VERT...\n", val);
++
++ dev_dbg(dev, "\nbelow regw(val, FMT_VERT)...");
++
++ /* Configure Horizontal offset register */
++ /* If pack 8 is enabled then 1 pixel will take 1 byte */
++ if ((params->data_sz == _8BITS) || params->alaw.b_alaw_enable)
++ regw(((params->win.width) + CCDC_32BYTE_ALIGN_VAL)
++ & CCDC_HSIZE_OFF_MASK, HSIZE_OFF);
++
++ else
++ /* else one pixel will take 2 byte */
++ regw(((params->win.width * TWO_BYTES_PER_PIXEL)
++ + CCDC_32BYTE_ALIGN_VAL)
++ & CCDC_HSIZE_OFF_MASK, HSIZE_OFF);
++
++ /* Set value for SDOFST */
++ if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
++ if (params->image_invert_enable) {
++ /* For intelace inverse mode */
++ regw(INTERLACED_IMAGE_INVERT, SDOFST);
++ dev_dbg(dev, "\nWriting 0x4B6D to SDOFST...\n");
++ }
++
++ else {
++ /* For intelace non inverse mode */
++ regw(INTERLACED_NO_IMAGE_INVERT, SDOFST);
++ dev_dbg(dev, "\nWriting 0x0249 to SDOFST...\n");
++ }
++ } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
++ regw(PROGRESSIVE_NO_IMAGE_INVERT, SDOFST);
++ dev_dbg(dev, "\nWriting 0x0000 to SDOFST...\n");
++ }
++
++ /* Configure video port pixel selection (VPOUT) */
++ /* Here -1 is to make the height value less than FMT_VERT.FMTLNV */
++ if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
++ val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK))
++ << CCDC_VP_OUT_VERT_NUM_SHIFT;
++ else
++ val =
++ ((((params->win.
++ height >> CCDC_INTERLACED_HEIGHT_SHIFT) -
++ 1) & CCDC_VP_OUT_VERT_NUM_MASK))
++ << CCDC_VP_OUT_VERT_NUM_SHIFT;
++
++ val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK)
++ << CCDC_VP_OUT_HORZ_NUM_SHIFT;
++ val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK;
++ regw(val, VP_OUT);
++
++ dev_dbg(dev, "\nWriting 0x%x to VP_OUT...\n", val);
++ regw(syn_mode, SYN_MODE);
++ dev_dbg(dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode);
++
++ val = (unsigned int)ccdc_sbl_reset();
++ dev_dbg(dev, "\nReading 0x%x from SBL...\n", val);
++
++ dev_dbg(dev, "\nend of ccdc_config_raw...");
++ ccdc_readregs();
++}
++
++static int ccdc_configure(void)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ dev_info(dev, "calling ccdc_config_raw()\n");
++ ccdc_config_raw();
++ } else {
++ dev_info(dev, "calling ccdc_config_ycbcr()\n");
++ ccdc_config_ycbcr();
++ }
++ return 0;
++}
++
++static int ccdc_set_buftype(enum ccdc_buftype buf_type)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ ccdc_hw_params_raw.buf_type = buf_type;
++ else
++ ccdc_hw_params_ycbcr.buf_type = buf_type;
++ return 0;
++}
++
++static int ccdc_get_buftype(enum ccdc_buftype *buf_type)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ *buf_type = ccdc_hw_params_raw.buf_type;
++ else
++ *buf_type = ccdc_hw_params_ycbcr.buf_type;
++ return 0;
++}
++
++static int ccdc_enum_pix(enum vpfe_hw_pix_format *hw_pix, int i)
++{
++ int ret = -EINVAL;
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ if (i < CCDC_MAX_RAW_BAYER_FORMATS) {
++ *hw_pix = ccdc_raw_bayer_hw_formats[i];
++ ret = 0;
++ }
++ } else {
++ if (i < CCDC_MAX_RAW_YUV_FORMATS) {
++ *hw_pix = ccdc_raw_yuv_hw_formats[i];
++ ret = 0;
++ }
++ }
++ return ret;
++}
++
++static int ccdc_set_pixel_format(enum vpfe_hw_pix_format pixfmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW;
++ if (pixfmt == VPFE_BAYER_8BIT_PACK_ALAW)
++ ccdc_hw_params_raw.alaw.b_alaw_enable = 1;
++ else if (pixfmt != VPFE_BAYER)
++ return -1;
++ } else {
++ if (pixfmt == VPFE_YUYV)
++ ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
++ else if (pixfmt == VPFE_UYVY)
++ ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
++ else
++ return -1;
++ }
++ return 0;
++}
++
++static int ccdc_get_pixel_format(enum vpfe_hw_pix_format *pixfmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ if (ccdc_hw_params_raw.alaw.b_alaw_enable)
++ *pixfmt = VPFE_BAYER_8BIT_PACK_ALAW;
++ else
++ *pixfmt = VPFE_BAYER;
++ else {
++ if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
++ *pixfmt = VPFE_YUYV;
++ else
++ *pixfmt = VPFE_UYVY;
++ }
++ return 0;
++}
++
++static int ccdc_set_image_window(struct v4l2_rect *win)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ ccdc_hw_params_raw.win.top = win->top;
++ ccdc_hw_params_raw.win.left = win->left;
++ ccdc_hw_params_raw.win.width = win->width;
++ ccdc_hw_params_raw.win.height = win->height;
++ } else {
++ ccdc_hw_params_ycbcr.win.top = win->top;
++ ccdc_hw_params_ycbcr.win.left = win->left;
++ ccdc_hw_params_ycbcr.win.width = win->width;
++ ccdc_hw_params_ycbcr.win.height = win->height;
++ }
++ return 0;
++}
++
++static int ccdc_get_image_window(struct v4l2_rect *win)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ win->top = ccdc_hw_params_raw.win.top;
++ win->left = ccdc_hw_params_raw.win.left;
++ win->width = ccdc_hw_params_raw.win.width;
++ win->height = ccdc_hw_params_raw.win.height;
++ } else {
++ win->top = ccdc_hw_params_ycbcr.win.top;
++ win->left = ccdc_hw_params_ycbcr.win.left;
++ win->width = ccdc_hw_params_ycbcr.win.width;
++ win->height = ccdc_hw_params_ycbcr.win.height;
++ }
++ return 0;
++}
++
++static int ccdc_get_line_length(unsigned int *len)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER) {
++ if ((ccdc_hw_params_raw.alaw.b_alaw_enable) ||
++ (ccdc_hw_params_raw.data_sz == _8BITS))
++ *len = ccdc_hw_params_raw.win.width;
++ else
++ *len = ccdc_hw_params_raw.win.width * 2;
++ } else
++ *len = ccdc_hw_params_ycbcr.win.width * 2;
++ return 0;
++}
++
++static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ ccdc_hw_params_raw.frm_fmt = frm_fmt;
++ else
++ ccdc_hw_params_ycbcr.frm_fmt = frm_fmt;
++ return 0;
++}
++
++static int ccdc_get_frame_format(enum ccdc_frmfmt *frm_fmt)
++{
++ if (ccdc_if_type == VPFE_RAW_BAYER)
++ *frm_fmt = ccdc_hw_params_raw.frm_fmt;
++ else
++ *frm_fmt = ccdc_hw_params_ycbcr.frm_fmt;
++ return 0;
++}
++
++static int ccdc_getfid(void)
++{
++ int fid = (regr(SYN_MODE) >> 15) & 0x1;
++ return fid;
++}
++
++/* misc operations */
++static inline void ccdc_setfbaddr(unsigned long addr)
++{
++ regw(addr & 0xffffffe0, SDR_ADDR);
++}
++
++static int ccdc_set_hw_if_type(enum vpfe_hw_if_type iface)
++{
++ ccdc_if_type = iface;
++ return 0;
++}
++
++struct ccdc_hw_device ccdc_hw_dev = {
++ .name = "DM6446 CCDC",
++ .set_ccdc_base = ccdc_set_ccdc_base,
++ .set_vpss_base = ccdc_set_vpss_base,
++ .get_ccdc_base = ccdc_get_ccdc_base,
++ .get_vpss_base = ccdc_get_vpss_base,
++ .open = ccdc_open,
++ .reset = ccdc_sbl_reset,
++ .enable = ccdc_enable,
++ .set_hw_if_type = ccdc_set_hw_if_type,
++ .setparams = ccdc_setparams,
++ .configure = ccdc_configure,
++ .set_buftype = ccdc_set_buftype,
++ .get_buftype = ccdc_get_buftype,
++ .enum_pix = ccdc_enum_pix,
++ .set_pixelformat = ccdc_set_pixel_format,
++ .get_pixelformat = ccdc_get_pixel_format,
++ .set_frame_format = ccdc_set_frame_format,
++ .get_frame_format = ccdc_get_frame_format,
++ .set_image_window = ccdc_set_image_window,
++ .get_image_window = ccdc_get_image_window,
++ .get_line_length = ccdc_get_line_length,
++ .setfbaddr = ccdc_setfbaddr,
++ .getfid = ccdc_getfid,
++ .close = ccdc_close
++};
++EXPORT_SYMBOL(ccdc_hw_dev);
++
++static int davinci_ccdc_init(void)
++{
++ return 0;
++}
++
++static void davinci_ccdc_exit(void)
++{
++}
++
++subsys_initcall(davinci_ccdc_init);
++module_exit(davinci_ccdc_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/davinci/ccdc_davinci.h b/drivers/media/video/davinci/ccdc_davinci.h
+new file mode 100644
+index 0000000..188e4f1
+--- /dev/null
++++ b/drivers/media/video/davinci/ccdc_davinci.h
+@@ -0,0 +1,335 @@
++/*
++ * Copyright (C) 2006-2009 Texas Instruments Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _CCDC_DAVINCI_H
++#define _CCDC_DAVINCI_H
++#include <media/davinci/ccdc_common.h>
++
++/* enum for No of pixel per line to be avg. in Black Clamping*/
++enum sample_length {
++ _1PIXELS = 0,
++ _2PIXELS,
++ _4PIXELS,
++ _8PIXELS,
++ _16PIXELS
++};
++
++/* Define to enable/disable video port */
++#define VIDEO_PORT_ENABLE (1)
++#define FP_NUM_BYTES (4)
++/* Define for extra pixel/line and extra lines/frame */
++#define NUM_EXTRAPIXELS 8
++#define NUM_EXTRALINES 8
++
++/* settings for commonly used video formats */
++#define CCDC_WIN_PAL {0, 0, 720, 576}
++/* ntsc square pixel */
++#define CCDC_WIN_VGA {0, 0, (640 + NUM_EXTRAPIXELS), (480 + NUM_EXTRALINES)}
++
++/* enum for No of lines in Black Clamping */
++enum sample_line {
++ _1LINES = 0,
++ _2LINES,
++ _4LINES,
++ _8LINES,
++ _16LINES
++};
++
++/* enum for Alaw gama width */
++enum gama_width {
++ BITS_15_6 = 0,
++ BITS_14_5,
++ BITS_13_4,
++ BITS_12_3,
++ BITS_11_2,
++ BITS_10_1,
++ BITS_09_0
++};
++
++enum data_size {
++ _16BITS = 0,
++ _15BITS,
++ _14BITS,
++ _13BITS,
++ _12BITS,
++ _11BITS,
++ _10BITS,
++ _8BITS
++};
++
++struct ccdc_imgwin {
++ unsigned int top;
++ unsigned int left;
++ unsigned int width;
++ unsigned int height;
++};
++
++/* structure for ALaw */
++struct a_law {
++ /* Enable/disable A-Law */
++ unsigned char b_alaw_enable;
++ /*Gama Width Input */
++ enum gama_width gama_wd;
++};
++
++/* structure for Black Clamping */
++struct black_clamp {
++ unsigned char b_clamp_enable;
++ /* only if bClampEnable is TRUE */
++ enum sample_length sample_pixel;
++ /* only if bClampEnable is TRUE */
++ enum sample_line sample_ln;
++ /* only if bClampEnable is TRUE */
++ unsigned short start_pixel;
++ /* only if bClampEnable is TRUE */
++ unsigned short sgain;
++ /* only if bClampEnable is FALSE */
++ unsigned short dc_sub;
++};
++
++/* structure for Black Level Compensation */
++struct black_compensation {
++ /* Constant value to subtract from Red component */
++ char r_comp;
++ /* Constant value to subtract from Gr component */
++ char gr_comp;
++ /* Constant value to subtract from Blue component */
++ char b_comp;
++ /* Constant value to subtract from Gb component */
++ char gb_comp;
++};
++
++/* structure for fault pixel correction */
++struct fault_pixel {
++ /*Enable or Disable fault pixel correction */
++ unsigned char fpc_enable;
++ /*Number of fault pixel */
++ unsigned short fp_num;
++ /*Address of fault pixel table */
++ unsigned int fpc_table_addr;
++};
++
++/* Structure for CCDC configuration parameters for raw capture mode passed
++ * by application
++ */
++struct ccdc_config_params_raw {
++ /* pixel format */
++ enum ccdc_pixfmt pix_fmt;
++ /* progressive or interlaced frame */
++ enum ccdc_frmfmt frm_fmt;
++ /* video window */
++ struct ccdc_imgwin win;
++ /* field id polarity */
++ enum ccdc_pinpol fid_pol;
++ /* vertical sync polarity */
++ enum ccdc_pinpol vd_pol;
++ /* horizontal sync polarity */
++ enum ccdc_pinpol hd_pol;
++ /* enable to store the image in inverse order in
++ * memory(bottom to top)
++ */
++ unsigned char image_invert_enable;
++ /* data size value from 8 to 16 bits */
++ enum data_size data_sz;
++ /* Structure for Optional A-Law */
++ struct a_law alaw;
++ /* Structure for Optical Black Clamp */
++ struct black_clamp blk_clamp;
++ /* Structure for Black Compensation */
++ struct black_compensation blk_comp;
++ /* Structure for Fault Pixel Module Configuration */
++ struct fault_pixel fault_pxl;
++};
++
++struct ccdc_params_ycbcr {
++ /* pixel format */
++ enum ccdc_pixfmt pix_fmt;
++ /* progressive or interlaced frame */
++ enum ccdc_frmfmt frm_fmt;
++ /* video window */
++ struct ccdc_imgwin win;
++ /* field id polarity */
++ enum ccdc_pinpol fid_pol;
++ /* vertical sync polarity */
++ enum ccdc_pinpol vd_pol;
++ /* horizontal sync polarity */
++ enum ccdc_pinpol hd_pol;
++ /* enable BT.656 embedded sync mode */
++ int bt656_enable;
++ /* cb:y:cr:y or y:cb:y:cr in memory */
++ enum ccdc_pixorder pix_order;
++ /* interleaved or separated fields */
++ enum ccdc_buftype buf_type;
++};
++
++#ifdef __KERNEL__
++#include <linux/io.h>
++/* Structure for CCDC configuration parameters for raw capture mode */
++struct ccdc_params_raw {
++ /* pixel format */
++ enum ccdc_pixfmt pix_fmt;
++ /* progressive or interlaced frame */
++ enum ccdc_frmfmt frm_fmt;
++ /* video window */
++ struct ccdc_imgwin win;
++ /* field id polarity */
++ enum ccdc_pinpol fid_pol;
++ /* vertical sync polarity */
++ enum ccdc_pinpol vd_pol;
++ /* horizontal sync polarity */
++ enum ccdc_pinpol hd_pol;
++ /* interleaved or separated fields */
++ enum ccdc_buftype buf_type;
++ /* enable to store the image in inverse
++ * order in memory(bottom to top)
++ */
++ unsigned char image_invert_enable;
++ /* data size value from 8 to 16 bits */
++ enum data_size data_sz;
++ /* Structure for Optional A-Law */
++ struct a_law alaw;
++ /* Structure for Optical Black Clamp */
++ struct black_clamp blk_clamp;
++ /* Structure for Black Compensation */
++ struct black_compensation blk_comp;
++ /* Structure for Fault Pixel Module Configuration */
++ struct fault_pixel fault_pxl;
++};
++
++/**************************************************************************\
++* Register OFFSET Definitions
++\**************************************************************************/
++
++#define PID 0x0
++#define PCR 0x4
++#define SYN_MODE 0x8
++#define HD_VD_WID 0xc
++#define PIX_LINES 0x10
++#define HORZ_INFO 0x14
++#define VERT_START 0x18
++#define VERT_LINES 0x1c
++#define CULLING 0x20
++#define HSIZE_OFF 0x24
++#define SDOFST 0x28
++#define SDR_ADDR 0x2c
++#define CLAMP 0x30
++#define DCSUB 0x34
++#define COLPTN 0x38
++#define BLKCMP 0x3c
++#define FPC 0x40
++#define FPC_ADDR 0x44
++#define VDINT 0x48
++#define ALAW 0x4c
++#define REC656IF 0x50
++#define CCDCFG 0x54
++#define FMTCFG 0x58
++#define FMT_HORZ 0x5c
++#define FMT_VERT 0x60
++#define FMT_ADDR0 0x64
++#define FMT_ADDR1 0x68
++#define FMT_ADDR2 0x6c
++#define FMT_ADDR3 0x70
++#define FMT_ADDR4 0x74
++#define FMT_ADDR5 0x78
++#define FMT_ADDR6 0x7c
++#define FMT_ADDR7 0x80
++#define PRGEVEN_0 0x84
++#define PRGEVEN_1 0x88
++#define PRGODD_0 0x8c
++#define PRGODD_1 0x90
++#define VP_OUT 0x94
++
++
++/***************************************************************
++* Define for various register bit mask and shifts for CCDC
++****************************************************************/
++#define CCDC_FID_POL_MASK (0x01)
++#define CCDC_FID_POL_SHIFT (4)
++#define CCDC_HD_POL_MASK (0x01)
++#define CCDC_HD_POL_SHIFT (3)
++#define CCDC_VD_POL_MASK (0x01)
++#define CCDC_VD_POL_SHIFT (2)
++#define CCDC_HSIZE_OFF_MASK (0xffffffe0)
++#define CCDC_32BYTE_ALIGN_VAL (31)
++#define CCDC_FRM_FMT_MASK (0x01)
++#define CCDC_FRM_FMT_SHIFT (7)
++#define CCDC_DATA_SZ_MASK (0x07)
++#define CCDC_DATA_SZ_SHIFT (8)
++#define CCDC_PIX_FMT_MASK (0x03)
++#define CCDC_PIX_FMT_SHIFT (12)
++#define CCDC_VP2SDR_DISABLE (0xFFFBFFFF)
++#define CCDC_WEN_ENABLE (0x01 << 17)
++#define CCDC_SDR2RSZ_DISABLE (0xFFF7FFFF)
++#define CCDC_VDHDEN_ENABLE (0x01 << 16)
++#define CCDC_LPF_ENABLE (0x01 << 14)
++#define CCDC_ALAW_ENABLE (0x01 << 3)
++#define CCDC_ALAW_GAMA_WD_MASK (0x07)
++#define CCDC_BLK_CLAMP_ENABLE (0x01 << 31)
++#define CCDC_BLK_SGAIN_MASK (0x1F)
++#define CCDC_BLK_ST_PXL_MASK (0x7FFF)
++#define CCDC_BLK_ST_PXL_SHIFT (10)
++#define CCDC_BLK_SAMPLE_LN_MASK (0x07)
++#define CCDC_BLK_SAMPLE_LN_SHIFT (28)
++#define CCDC_BLK_SAMPLE_LINE_MASK (0x07)
++#define CCDC_BLK_SAMPLE_LINE_SHIFT (25)
++#define CCDC_BLK_DC_SUB_MASK (0x03FFF)
++#define CCDC_BLK_COMP_MASK (0x000000FF)
++#define CCDC_BLK_COMP_GB_COMP_SHIFT (8)
++#define CCDC_BLK_COMP_GR_COMP_SHIFT (16)
++#define CCDC_BLK_COMP_R_COMP_SHIFT (24)
++#define CCDC_LATCH_ON_VSYNC_DISABLE (0x01 << 15)
++#define CCDC_FPC_ENABLE (0x01 << 15)
++#define CCDC_FPC_DISABLE (0x0)
++#define CCDC_FPC_FPC_NUM_MASK (0x7FFF)
++#define CCDC_DATA_PACK_ENABLE (0x01<<11)
++#define CCDC_FMTCFG_VPIN_MASK (0x07)
++#define CCDC_FMTCFG_VPIN_SHIFT (12)
++#define CCDC_FMT_HORZ_FMTLNH_MASK (0x1FFF)
++#define CCDC_FMT_HORZ_FMTSPH_MASK (0x1FFF)
++#define CCDC_FMT_HORZ_FMTSPH_SHIFT (16)
++#define CCDC_FMT_VERT_FMTLNV_MASK (0x1FFF)
++#define CCDC_FMT_VERT_FMTSLV_MASK (0x1FFF)
++#define CCDC_FMT_VERT_FMTSLV_SHIFT (16)
++#define CCDC_VP_OUT_VERT_NUM_MASK (0x3FFF)
++#define CCDC_VP_OUT_VERT_NUM_SHIFT (17)
++#define CCDC_VP_OUT_HORZ_NUM_MASK (0x1FFF)
++#define CCDC_VP_OUT_HORZ_NUM_SHIFT (4)
++#define CCDC_VP_OUT_HORZ_ST_MASK (0x000F)
++#define CCDC_HORZ_INFO_SPH_SHIFT (16)
++#define CCDC_VERT_START_SLV0_SHIFT (16)
++#define CCDC_VDINT_VDINT0_SHIFT (16)
++#define CCDC_VDINT_VDINT1_MASK (0xFFFF)
++
++/* SBL register and mask defination */
++#define SBL_PCR_VPSS (4)
++#define SBL_PCR_CCDC_WBL_O (0xFF7FFFFF)
++
++#define PPC_RAW (1)
++#define DCSUB_DEFAULT_VAL (0)
++#define CLAMP_DEFAULT_VAL (0)
++#define ENABLE_VIDEO_PORT (0x00008000)
++#define DISABLE_VIDEO_PORT (0)
++#define CCDC_COLPTN_VAL (0xBB11BB11)
++#define TWO_BYTES_PER_PIXEL (2)
++#define INTERLACED_IMAGE_INVERT (0x4B6D)
++#define INTERLACED_NO_IMAGE_INVERT (0x0249)
++#define PROGRESSIVE_IMAGE_INVERT (0x4000)
++#define PROGRESSIVE_NO_IMAGE_INVERT (0)
++#define CCDC_INTERLACED_HEIGHT_SHIFT (1)
++
++#endif
++#endif /* CCDC_DAVINCI_H */
+diff --git a/include/media/ccdc_davinci.h b/include/media/ccdc_davinci.h
+deleted file mode 100644
+index 9f0a08d..0000000
+--- a/include/media/ccdc_davinci.h
++++ /dev/null
+@@ -1,144 +0,0 @@
+-/*
+- *
+- * Copyright (C) 2006 Texas Instruments Inc
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-/* ccdc_davinci.h */
+-
+-#ifndef CCDC_DAVINCI_H
+-#define CCDC_DAVINCI_H
+-#include <linux/types.h>
+-
+-#ifdef __KERNEL__
+-#include <asm/arch/hardware.h>
+-#include <asm/io.h>
+-#endif
+-
+-#include <linux/videodev.h>
+-
+-typedef enum ccdc_pixfmt {
+- CCDC_PIXFMT_RAW = 0,
+- CCDC_PIXFMT_YCBCR_16BIT = 1,
+- CCDC_PIXFMT_YCBCR_8BIT = 2
+-} ccdc_pixfmt;
+-
+-typedef enum ccdc_frmfmt {
+- CCDC_FRMFMT_PROGRESSIVE = 0,
+- CCDC_FRMFMT_INTERLACED = 1
+-} ccdc_frmfmt;
+-
+-typedef enum ccdc_pinpol {
+- CCDC_PINPOL_POSITIVE = 0,
+- CCDC_PINPOL_NEGATIVE = 1
+-} ccdc_pinpol;
+-
+-/* PIXEL ORDER IN MEMORY from LSB to MSB */
+-/* only applicable for 8-bit input mode */
+-typedef enum ccdc_pixorder {
+- CCDC_PIXORDER_CBYCRY = 1,
+- CCDC_PIXORDER_YCBYCR = 0
+-} ccdc_pixorder;
+-
+-typedef enum ccdc_buftype {
+- CCDC_BUFTYPE_FLD_INTERLEAVED,
+- CCDC_BUFTYPE_FLD_SEPARATED
+-} ccdc_buftype;
+-
+-typedef struct v4l2_rect ccdc_imgwin;
+-
+-typedef struct ccdc_params_ycbcr {
+- ccdc_pixfmt pix_fmt; /* pixel format */
+- ccdc_frmfmt frm_fmt; /* progressive or interlaced frame */
+- ccdc_imgwin win; /* video window */
+- ccdc_pinpol fid_pol; /* field id polarity */
+- ccdc_pinpol vd_pol; /* vertical sync polarity */
+- ccdc_pinpol hd_pol; /* horizontal sync polarity */
+- int bt656_enable; /* enable BT.656 embedded sync mode */
+- ccdc_pixorder pix_order;/* cb:y:cr:y or y:cb:y:cr in memory */
+- ccdc_buftype buf_type; /* interleaved or separated fields */
+-} ccdc_params_ycbcr;
+-
+-#ifdef __KERNEL__
+-/**************************************************************************\
+-* Register OFFSET Definitions
+-\**************************************************************************/
+-#define PID 0x0
+-#define PCR 0x4
+-#define SYN_MODE 0x8
+-#define HD_VD_WID 0xc
+-#define PIX_LINES 0x10
+-#define HORZ_INFO 0x14
+-#define VERT_START 0x18
+-#define VERT_LINES 0x1c
+-#define CULLING 0x20
+-#define HSIZE_OFF 0x24
+-#define SDOFST 0x28
+-#define SDR_ADDR 0x2c
+-#define CLAMP 0x30
+-#define DCSUB 0x34
+-#define COLPTN 0x38
+-#define BLKCMP 0x3c
+-#define FPC 0x40
+-#define FPC_ADDR 0x44
+-#define VDINT 0x48
+-#define ALAW 0x4c
+-#define REC656IF 0x50
+-#define CCDCFG 0x54
+-#define FMTCFG 0x58
+-#define FMT_HORZ 0x5c
+-#define FMT_VERT 0x50
+-#define FMT_ADDR0 0x64
+-#define FMT_ADDR1 0x68
+-#define FMT_ADDR2 0x6c
+-#define FMT_ADDR3 0x70
+-#define FMT_ADDR4 0x74
+-#define FMT_ADDR5 0x78
+-#define FMT_ADDR6 0x7c
+-#define FMT_ADDR7 0x80
+-#define PRGEVEN_0 0x84
+-#define PRGEVEN_1 0x88
+-#define PRGODD_0 0x8c
+-#define PRGODD_1 0x90
+-#define VP_OUT 0x94
+-
+-#define CCDC_IOBASE (0x01c70400)
+-
+-#define regw(val, reg) davinci_writel(val, (reg)+CCDC_IOBASE)
+-#define regr(reg) davinci_readl((reg)+CCDC_IOBASE)
+-
+-extern void ccdc_reset(void);
+-extern void ccdc_config_ycbcr(ccdc_params_ycbcr * params);
+-extern void ccdc_setwin(ccdc_params_ycbcr * params);
+-
+-/* inline functions that must be fast because they are called frequently */
+-static inline void ccdc_enable(int flag)
+-{
+- regw(flag, PCR);
+-}
+-
+-static inline void ccdc_setfbaddr(unsigned long paddr)
+-{
+- regw(paddr & 0xffffffe0, SDR_ADDR);
+-}
+-
+-static inline int ccdc_getfid(void)
+-{
+- int fid = (regr(SYN_MODE) >> 15) & 0x1;
+- return fid;
+-}
+-#endif
+-
+-#endif /* CCDC_DAVINCI_H */
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci/vfpe5.patch b/recipes/linux/linux-davinci/vfpe5.patch
new file mode 100644
index 0000000000..160908a1cd
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe5.patch
@@ -0,0 +1,132 @@
+Subject:
+[PATCH 5/7] Kconfig and Makefile changes for vpfe capture driver
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:23:32 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Adding updates to video Kconfig and Makefile and adding
+Makefile for building vpfe-capture files
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ drivers/media/video/Kconfig | 48 ++++++++++++++++++++++++----------
+ drivers/media/video/Makefile | 6 +---
+ drivers/media/video/davinci/Makefile | 8 +++++
+ 3 files changed, 43 insertions(+), 19 deletions(-)
+ create mode 100644 drivers/media/video/davinci/Makefile
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 1dd98d8..ea3a526 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -485,25 +485,45 @@ config VIDEO_VIVI
+ Say Y here if you want to test video apps or debug V4L devices.
+ In doubt, say N.
+
+-config VIDEO_TVP5146
+- tristate "TVP5146 video decoder"
+- depends on I2C && ARCH_DAVINCI
++config VIDEO_VPFE_CAPTURE
++ tristate "VPFE Video Capture Driver"
++ depends on VIDEO_V4L2 && ARCH_DAVINCI
++ select VIDEOBUF_DMA_CONTIG
+ help
+- Support for I2C bus based TVP5146 configuration.
++ Support for DMXXXX VPFE based frame grabber. This is the
++ common V4L2 module for following DMXXX SoCs from Texas
++ Instruments:- DM6446 & DM355.
+
+ To compile this driver as a module, choose M here: the
+- module will be called tvp5146.
++ module will be called vpfe-capture.
+
+-config VIDEO_DAVINCI
+- tristate "Davinci Video Capture"
+- depends on VIDEO_DEV && VIDEO_TVP5146 && ARCH_DAVINCI
+- select VIDEOBUF_GEN
+- select VIDEOBUF_DMA_SG
++config VIDEO_DAVINCI_CCDC
++ tristate "DM6446 CCDC HW module"
++ depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE
++ default y
+ help
+- Support for Davinci based frame grabber through CCDC.
+-
+- To compile this driver as a module, choose M here: the
+- module will be called vpfe.
++ Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
++ with decoder modules such as TVP5146 over BT656 or
++ sensor module such as MT9T001 over a raw interface. This
++ module configures the interface and CCDC/ISIF to do
++ video frame capture from slave decoders.
++
++ To compile this driver as a module, choose M here: the
++ module will be called vpfe.
++
++config VIDEO_DM355_CCDC
++ tristate "DM355 CCDC HW module"
++ depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE
++ default y
++ help
++ Enables DM355 CCD hw module. DM355 CCDC hw interfaces
++ with decoder modules such as TVP5146 over BT656 or
++ sensor module such as MT9T001 over a raw interface. This
++ module configures the interface and CCDC/ISIF to do
++ video frame capture from a slave decoders
++
++ To compile this driver as a module, choose M here: the
++ module will be called vpfe.
+
+ source "drivers/media/video/bt8xx/Kconfig"
+
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index 863b5c8..f8b6c0c 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -10,8 +10,6 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o
+
+ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
+
+-davinci-vpfe-objs := ccdc_davinci.o davinci_vpfe.o
+-
+ videodev-objs := v4l2-dev.o v4l2-ioctl.o
+
+ videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o
+@@ -29,6 +27,7 @@ endif
+
+ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+
++obj-$(CONFIG_ARCH_DAVINCI) += davinci/
+ obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
+ obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
+@@ -135,9 +134,6 @@ obj-$(CONFIG_USB_S2255) += s2255drv.o
+ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+ obj-$(CONFIG_VIDEO_CX18) += cx18/
+
+-obj-$(CONFIG_VIDEO_DAVINCI) += davinci-vpfe.o
+-obj-$(CONFIG_VIDEO_TVP5146) += tvp5146.o
+-
+ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+
+diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile
+new file mode 100644
+index 0000000..77fe038
+--- /dev/null
++++ b/drivers/media/video/davinci/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for the davinci video device drivers.
++#
++
++# Capture: DaVinci and DM355
++obj-$(CONFIG_VIDEO_DAVINCI_CCDC) += ccdc_davinci.o
++obj-$(CONFIG_VIDEO_DM355_CCDC) += ccdc_dm355.o
++obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci/vfpe6.patch b/recipes/linux/linux-davinci/vfpe6.patch
new file mode 100644
index 0000000000..b425eea5dd
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe6.patch
@@ -0,0 +1,224 @@
+Subject:
+[PATCH 6/7] platform-related-updates for vpfe capture driver on DM6446
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:24:04 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Add platform related changes for vpfe capture driver on DM6446
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ arch/arm/mach-davinci/board-dm644x-evm.c | 88 ++++++++++++++++++++++++++-
+ arch/arm/mach-davinci/dm644x.c | 42 +++++++++++++
+ arch/arm/mach-davinci/include/mach/dm644x.h | 2 +
+ 3 files changed, 130 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
+index 20ec961..5f4d9a8 100644
+--- a/arch/arm/mach-davinci/board-dm644x-evm.c
++++ b/arch/arm/mach-davinci/board-dm644x-evm.c
+@@ -27,7 +27,9 @@
+ #include <linux/io.h>
+ #include <linux/phy.h>
+ #include <linux/clk.h>
+-
++#include <linux/videodev2.h>
++#include <media/v4l2-int-device.h>
++#include <media/tvp514x.h>
+ #include <asm/setup.h>
+ #include <asm/mach-types.h>
+
+@@ -161,6 +163,41 @@ static struct platform_device davinci_fb_device = {
+ .num_resources = 0,
+ };
+
++
++#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
++static struct vpfe_capture_input vpfe_capture_inputs = {
++ .num_inputs = VPFE_MAX_DEC_INPUTS,
++ .current_input = 0,
++ .inputs[0] = {
++ .dec_name = TVP514X_MODULE_NAME,
++ .input = {
++ .index = 0,
++ .name = "COMPOSITE",
++ .type = V4L2_INPUT_TYPE_CAMERA,
++ .std = TVP514X_STD_ALL,
++ },
++ .route = {
++ .input = INPUT_CVBS_VI2B,
++ .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
++ },
++ .routing_supported = 1,
++ },
++ .inputs[1] = {
++ .dec_name = TVP514X_MODULE_NAME,
++ .input = {
++ .index = 1,
++ .name = "SVIDEO",
++ .type = V4L2_INPUT_TYPE_CAMERA,
++ .std = TVP514X_STD_ALL,
++ },
++ .route = {
++ .input = INPUT_SVIDEO_VI2C_VI1C,
++ .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
++ },
++ .routing_supported = 1,
++ },
++};
++
+ static struct platform_device rtc_dev = {
+ .name = "rtc_davinci_evm",
+ .id = -1,
+@@ -447,6 +484,48 @@ int dm6446evm_eeprom_write(void *buf, off_t off, size_t count)
+ }
+ EXPORT_SYMBOL(dm6446evm_eeprom_write);
+
++#define TVP5146_I2C_ADDR (0x5D)
++static struct v4l2_ifparm tvp5146_ifparm = {
++ .if_type = V4L2_IF_TYPE_BT656,
++ .u = {
++ .bt656 = {
++ .frame_start_on_rising_vs = 1,
++ .bt_sync_correct = 0,
++ .swap = 0,
++ .latch_clk_inv = 0,
++ .nobt_hs_inv = 0, /* active high */
++ .nobt_vs_inv = 0, /* active high */
++ .mode = V4L2_IF_TYPE_BT656_MODE_BT_8BIT,
++ .clock_min = TVP514X_XCLK_BT656,
++ .clock_max = TVP514X_XCLK_BT656,
++ },
++ },
++};
++
++/**
++ * @brief tvp5146_g_ifparm - Returns the TVP5146 decoder interface parameters
++ *
++ * @param p - pointer to v4l2_ifparm structure
++ * @return result of operation - 0 is success
++ */
++static int tvp5146_g_ifparm(struct v4l2_ifparm *p)
++{
++ if (p == NULL)
++ return -EINVAL;
++
++ *p = tvp5146_ifparm;
++ return 0;
++}
++
++#define TVP5146_NUM_INPUTS ARRAY_SIZE(tvp5146_input_list)
++
++static struct tvp514x_platform_data tvp5146_pdata = {
++ .master = CAPTURE_DRV_NAME,
++ .ifparm = tvp5146_g_ifparm,
++ .hs_polarity = 1,
++ .vs_polarity = 1
++};
++
+ /*
+ * MSP430 supports RTC, card detection, input from IR remote, and
+ * a bit more. It triggers interrupts on GPIO(7) from pressing
+@@ -557,9 +636,12 @@ static struct i2c_board_info __initdata i2c_info[] = {
+ I2C_BOARD_INFO("24c256", 0x50),
+ .platform_data = &eeprom_info,
+ },
++ {
++ I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),
++ .platform_data = &tvp5146_pdata,
++ },
+ /* ALSO:
+ * - tvl320aic33 audio codec (0x1b)
+- * - tvp5146 video decoder (0x5d)
+ */
+ };
+
+@@ -591,6 +673,8 @@ static void __init
+ davinci_evm_map_io(void)
+ {
+ davinci_map_common_io();
++ /* setup input configuration for VPFE input devices */
++ setup_vpfe_input_config(&vpfe_capture_inputs);
+ dm644x_init();
+ }
+
+diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
+index 03946fd..f46095e 100644
+--- a/arch/arm/mach-davinci/dm644x.c
++++ b/arch/arm/mach-davinci/dm644x.c
+@@ -419,6 +419,46 @@ static struct platform_device dm644x_edma_device = {
+ .resource = edma_resources,
+ };
+
++static struct resource vpfe_resources[] = {
++ {
++ .start = IRQ_VDINT0,
++ .end = IRQ_VDINT0,
++ .flags = IORESOURCE_IRQ,
++ },
++ {
++ .start = IRQ_VDINT1,
++ .end = IRQ_VDINT1,
++ .flags = IORESOURCE_IRQ,
++ },
++ {
++ .start = 0x01c70400,
++ .end = 0x01c70400 + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = 0x01c73400,
++ .end = 0x01c73400 + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static u64 vpfe_capture_dma_mask = DMA_32BIT_MASK;
++static struct platform_device vpfe_capture_dev = {
++ .name = CAPTURE_DRV_NAME,
++ .id = -1,
++ .num_resources = ARRAY_SIZE(vpfe_resources),
++ .resource = vpfe_resources,
++ .dev = {
++ .dma_mask = &vpfe_capture_dma_mask,
++ .coherent_dma_mask = DMA_32BIT_MASK,
++ },
++};
++
++void setup_vpfe_input_config(struct vpfe_capture_input *input_config)
++{
++ vpfe_capture_dev.dev.platform_data = input_config;
++}
++
+ /*----------------------------------------------------------------------*/
+
+ void __init dm644x_init(void)
+@@ -433,6 +473,8 @@ static int __init dm644x_init_devices(void)
+ return 0;
+
+ platform_device_register(&dm644x_edma_device);
++ /* Register VPFE capture device */
++ platform_device_register(&vpfe_capture_dev);
+ return 0;
+ }
+ postcore_initcall(dm644x_init_devices);
+diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h
+index 5b3d512..14f9a8a 100644
+--- a/arch/arm/mach-davinci/include/mach/dm644x.h
++++ b/arch/arm/mach-davinci/include/mach/dm644x.h
+@@ -23,7 +23,9 @@
+ #define __ASM_ARCH_DM644X_H
+
+ #include <mach/hardware.h>
++#include <media/davinci/vpfe_capture.h>
+
+ void __init dm644x_init(void);
++void setup_vpfe_input_config(struct vpfe_capture_input *input_config);
+
+ #endif /* __ASM_ARCH_DM644X_H */
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci/vfpe7.patch b/recipes/linux/linux-davinci/vfpe7.patch
new file mode 100644
index 0000000000..a6695a8cda
--- /dev/null
+++ b/recipes/linux/linux-davinci/vfpe7.patch
@@ -0,0 +1,283 @@
+Subject:
+[PATCH 7/7] DM355 platform related changes for vpfe capture driver
+From:
+m-karicheri2-l0cyMroinI0@public.gmane.org
+Date:
+Fri, 13 Mar 2009 17:24:34 -0400
+To:
+davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org, davinci_opensource_ccb-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org, psp_video-uAqBSO/uNfhBDgjK7y7TUQ@public.gmane.org
+Newsgroups:
+gmane.linux.davinci
+
+Add platform related changes for vpfe capture driver on DM355
+
+Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
+---
+ arch/arm/mach-davinci/board-dm355-evm.c | 91 +++++++++++++++++++++++++++-
+ arch/arm/mach-davinci/dm355.c | 64 +++++++++++++++++++
+ arch/arm/mach-davinci/include/mach/dm355.h | 2 +
+ arch/arm/mach-davinci/include/mach/mux.h | 9 +++
+ 4 files changed, 163 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
+index e104650..aaa58ba 100644
+--- a/arch/arm/mach-davinci/board-dm355-evm.c
++++ b/arch/arm/mach-davinci/board-dm355-evm.c
+@@ -20,6 +20,8 @@
+ #include <linux/io.h>
+ #include <linux/gpio.h>
+ #include <linux/clk.h>
++#include <media/v4l2-int-device.h>
++#include <media/tvp514x.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/eeprom.h>
+
+@@ -134,12 +136,58 @@ static void dm355evm_mmcsd_gpios(unsigned gpio)
+ dm355evm_mmc_gpios = gpio;
+ }
+
++#define TVP5146_I2C_ADDR 0x5D
++static struct v4l2_ifparm tvp5146_ifparm = {
++ .if_type = V4L2_IF_TYPE_BT656,
++ .u = {
++ .bt656 = {
++ .frame_start_on_rising_vs = 1,
++ .bt_sync_correct = 0,
++ .swap = 0,
++ .latch_clk_inv = 0,
++ .nobt_hs_inv = 0, /* active high */
++ .nobt_vs_inv = 0, /* active high */
++ .mode = V4L2_IF_TYPE_BT656_MODE_BT_8BIT,
++ .clock_min = TVP514X_XCLK_BT656,
++ .clock_max = TVP514X_XCLK_BT656,
++ },
++ },
++};
++
++/**
++ * @brief tvp5146_g_ifparm - Returns the TVP5146 decoder interface parameters
++ *
++ * @param p - pointer to v4l2_ifparm structure
++ * @return result of operation - 0 is success
++ */
++static int tvp5146_g_ifparm(struct v4l2_ifparm *p)
++{
++ if (p == NULL)
++ return -EINVAL;
++
++ *p = tvp5146_ifparm;
++ return 0;
++}
++
++#define TVP5146_NUM_INPUTS ARRAY_SIZE(tvp5146_input_list)
++
++static struct tvp514x_platform_data tvp5146_pdata = {
++ .master = CAPTURE_DRV_NAME,
++ .ifparm = tvp5146_g_ifparm,
++ .hs_polarity = 1,
++ .vs_polarity = 1
++};
++
+ static struct i2c_board_info dm355evm_i2c_info[] = {
+- { I2C_BOARD_INFO("dm355evm_msp", 0x25),
++ { I2C_BOARD_INFO("dm355evm_msp", 0x25),
+ .platform_data = dm355evm_mmcsd_gpios,
+- /* plus irq */ },
++ },
++ {
++ I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),
++ .platform_data = &tvp5146_pdata,
++ },
++ /* { plus irq }, */
+ /* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
+- /* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
+ };
+
+ static void __init evm_init_i2c(void)
+@@ -178,6 +226,41 @@ static struct platform_device dm355evm_dm9000 = {
+ .num_resources = ARRAY_SIZE(dm355evm_dm9000_rsrc),
+ };
+
++#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
++
++static struct vpfe_capture_input vpfe_capture_inputs = {
++ .num_inputs = VPFE_MAX_DEC_INPUTS,
++ .current_input = 0,
++ .inputs[0] = {
++ .dec_name = TVP514X_MODULE_NAME,
++ .input = {
++ .index = 0,
++ .name = "COMPOSITE",
++ .type = V4L2_INPUT_TYPE_CAMERA,
++ .std = TVP514X_STD_ALL,
++ },
++ .route = {
++ .input = INPUT_CVBS_VI2B,
++ .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
++ },
++ .routing_supported = 1,
++ },
++ .inputs[1] = {
++ .dec_name = TVP514X_MODULE_NAME,
++ .input = {
++ .index = 1,
++ .name = "SVIDEO",
++ .type = V4L2_INPUT_TYPE_CAMERA,
++ .std = TVP514X_STD_ALL,
++ },
++ .route = {
++ .input = INPUT_SVIDEO_VI2C_VI1C,
++ .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
++ },
++ .routing_supported = 1,
++ },
++};
++
+ static struct platform_device *davinci_evm_devices[] __initdata = {
+ &dm355evm_dm9000,
+ &davinci_nand_device,
+@@ -190,6 +273,8 @@ static struct davinci_uart_config uart_config __initdata = {
+ static void __init dm355_evm_map_io(void)
+ {
+ davinci_map_common_io();
++ /* setup input configuration for VPFE input devices */
++ setup_vpfe_input_config(&vpfe_capture_inputs);
+ dm355_init();
+ }
+
+diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
+index 5f31649..e2612dd 100644
+--- a/arch/arm/mach-davinci/dm355.c
++++ b/arch/arm/mach-davinci/dm355.c
+@@ -463,6 +463,14 @@ INT_CFG(DM355, INT_EDMA_TC1_ERR, 4, 1, 1, false)
+ EVT_CFG(DM355, EVT8_ASP1_TX, 0, 1, 0, false)
+ EVT_CFG(DM355, EVT9_ASP1_RX, 1, 1, 0, false)
+ EVT_CFG(DM355, EVT26_MMC0_RX, 2, 1, 0, false)
++
++MUX_CFG(DM355, VIN_PCLK, 0, 14, 1, 1, false)
++MUX_CFG(DM355, VIN_CAM_WEN, 0, 13, 1, 1, false)
++MUX_CFG(DM355, VIN_CAM_VD, 0, 12, 1, 1, false)
++MUX_CFG(DM355, VIN_CAM_HD, 0, 11, 1, 1, false)
++MUX_CFG(DM355, VIN_YIN_EN, 0, 10, 1, 1, false)
++MUX_CFG(DM355, VIN_CINL_EN, 0, 0, 0xff, 0x55, false)
++MUX_CFG(DM355, VIN_CINH_EN, 0, 8, 3, 3, false)
+ };
+
+ /*----------------------------------------------------------------------*/
+@@ -520,6 +528,47 @@ static struct platform_device dm355_edma_device = {
+ .resource = edma_resources,
+ };
+
++static struct resource vpfe_resources[] = {
++ {
++ .start = IRQ_VDINT0,
++ .end = IRQ_VDINT0,
++ .flags = IORESOURCE_IRQ,
++ },
++ {
++ .start = IRQ_VDINT1,
++ .end = IRQ_VDINT1,
++ .flags = IORESOURCE_IRQ,
++ },
++ /* CCDC Base address */
++ {
++ .flags = IORESOURCE_MEM,
++ .start = 0x01c70600,
++ .end = 0x01c70600 + 0x1ff,
++ },
++ /* VPSS Base address */
++ {
++ .start = 0x01c70800,
++ .end = 0x01c70800 + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static u64 vpfe_capture_dma_mask = DMA_32BIT_MASK;
++static struct platform_device vpfe_capture_dev = {
++ .name = CAPTURE_DRV_NAME,
++ .id = -1,
++ .num_resources = ARRAY_SIZE(vpfe_resources),
++ .resource = vpfe_resources,
++ .dev = {
++ .dma_mask = &vpfe_capture_dma_mask,
++ .coherent_dma_mask = DMA_32BIT_MASK,
++ },
++};
++
++void setup_vpfe_input_config(struct vpfe_capture_input *input_config)
++{
++ vpfe_capture_dev.dev.platform_data = input_config;
++}
+ /*----------------------------------------------------------------------*/
+
+ void __init dm355_init(void)
+@@ -528,13 +577,28 @@ void __init dm355_init(void)
+ davinci_mux_register(dm355_pins, ARRAY_SIZE(dm355_pins));;
+ }
+
++#define DM355_VPSSCLK_CLKCTRL_REG 0x1c70004
+ static int __init dm355_init_devices(void)
+ {
++ void __iomem *base = IO_ADDRESS(DM355_VPSSCLK_CLKCTRL_REG);
+ if (!cpu_is_davinci_dm355())
+ return 0;
+
+ davinci_cfg_reg(DM355_INT_EDMA_CC);
+ platform_device_register(&dm355_edma_device);
++ /* setup clock for vpss modules */
++ __raw_writel(0x79, base);
++ /* setup Mux configuration for vpfe input and register
++ * vpfe capture platform device
++ */
++ davinci_cfg_reg(DM355_VIN_PCLK);
++ davinci_cfg_reg(DM355_VIN_CAM_WEN);
++ davinci_cfg_reg(DM355_VIN_CAM_VD);
++ davinci_cfg_reg(DM355_VIN_CAM_HD);
++ davinci_cfg_reg(DM355_VIN_YIN_EN);
++ davinci_cfg_reg(DM355_VIN_CINL_EN);
++ davinci_cfg_reg(DM355_VIN_CINH_EN);
++ platform_device_register(&vpfe_capture_dev);
+ return 0;
+ }
+ postcore_initcall(dm355_init_devices);
+diff --git a/arch/arm/mach-davinci/include/mach/dm355.h b/arch/arm/mach-davinci/include/mach/dm355.h
+index f7100b6..0b3bd76 100644
+--- a/arch/arm/mach-davinci/include/mach/dm355.h
++++ b/arch/arm/mach-davinci/include/mach/dm355.h
+@@ -12,6 +12,7 @@
+ #define __ASM_ARCH_DM355_H
+
+ #include <mach/hardware.h>
++#include <media/davinci/vpfe_capture.h>
+
+ void __init dm355_init(void);
+
+@@ -19,5 +20,6 @@ struct spi_board_info;
+
+ void dm355_init_spi0(unsigned chipselect_mask,
+ struct spi_board_info *info, unsigned len);
++void setup_vpfe_input_config(struct vpfe_capture_input *input_config);
+
+ #endif /* __ASM_ARCH_DM355_H */
+diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
+index cd95629..4c135b0 100644
+--- a/arch/arm/mach-davinci/include/mach/mux.h
++++ b/arch/arm/mach-davinci/include/mach/mux.h
+@@ -149,6 +149,15 @@ enum davinci_dm355_index {
+ DM355_EVT8_ASP1_TX,
+ DM355_EVT9_ASP1_RX,
+ DM355_EVT26_MMC0_RX,
++
++ /* Video In Pin Mux */
++ DM355_VIN_PCLK,
++ DM355_VIN_CAM_WEN,
++ DM355_VIN_CAM_VD,
++ DM355_VIN_CAM_HD,
++ DM355_VIN_YIN_EN,
++ DM355_VIN_CINL_EN,
++ DM355_VIN_CINH_EN,
+ };
+
+ #ifdef CONFIG_DAVINCI_MUX
+-- 1.6.0.4 \ No newline at end of file
diff --git a/recipes/linux/linux-davinci_git.bb b/recipes/linux/linux-davinci_git.bb
index 779f012a4c..332aeb6e04 100644
--- a/recipes/linux/linux-davinci_git.bb
+++ b/recipes/linux/linux-davinci_git.bb
@@ -10,10 +10,17 @@ DEFAULT_PREFERENCE = "-1"
SRCREV = "486afa37130356662213cc1a2199a285b4fd72af"
PV = "2.6.29+2.6.29-rc7-${PR}+gitr${SRCREV}"
-PR = "r2"
+PR = "r3"
SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci.git;protocol=git \
file://update-mach-types.patch;patch=1 \
+ file://vfpe1.patch;patch=1 \
+ file://vfpe2.patch;patch=1 \
+ file://vfpe3.patch;patch=1 \
+ file://vfpe4.patch;patch=1 \
+ file://vfpe5.patch;patch=1 \
+ file://vfpe6.patch;patch=1 \
+ file://vfpe7.patch;patch=1 \
file://defconfig"
SRC_URI_append_davinci-sffsdr = " \
@@ -33,6 +40,7 @@ SRC_URI_append_davinci-sffsdr = " \
SRC_URI_append_dm355-leopard = " \
file://0001-dm355-leopard-add-board-file-based-on-board-dm355-e.patch;patch=1 \
- "
+ file://vfpe.patch;patch=1 \
+"
S = "${WORKDIR}/git"