summaryrefslogtreecommitdiff
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
parent3b7b721db9da9de480a0efc2710e5592b47255fa (diff)
linux-davinci git: add vfpe driver for davinci and dm355, enable it in dm355-leopard defconfig
-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 V