summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-davinci/vfpe1.patch
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/linux/linux-davinci/vfpe1.patch
parent3b7b721db9da9de480a0efc2710e5592b47255fa (diff)
linux-davinci git: add vfpe driver for davinci and dm355, enable it in dm355-leopard defconfig
Diffstat (limited to 'recipes/linux/linux-davinci/vfpe1.patch')
-rw-r--r--recipes/linux/linux-davinci/vfpe1.patch3928
1 files changed, 3928 insertions, 0 deletions
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