diff options
| author | Koen Kooi <koen@openembedded.org> | 2009-03-17 22:51:32 +0100 |
|---|---|---|
| committer | Koen Kooi <koen@openembedded.org> | 2009-03-17 22:51:32 +0100 |
| commit | bcde4467f8ac2de9bf9a061f7a3bb3621410d9ef (patch) | |
| tree | 9c7f347420619d60fe4216e51f093556d4f48ec0 | |
| parent | 3b7b721db9da9de480a0efc2710e5592b47255fa (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/defconfig | 127 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/dm355-leopard/vfpe.patch | 143 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe1.patch | 3928 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe2.patch | 200 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe3.patch | 2558 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe4.patch | 1660 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe5.patch | 132 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe6.patch | 224 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci/vfpe7.patch | 283 | ||||
| -rw-r--r-- | recipes/linux/linux-davinci_git.bb | 12 |
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 |
