All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver
@ 2009-06-11 17:00 m-karicheri2
  2009-06-11 17:00 ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 m-karicheri2
  2009-06-11 20:24 ` [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver David Brownell
  0 siblings, 2 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

Resending to have all patches together since I had to resend couple of
them earlier and had to fix few issues...

VPFE Capture driver for DaVinci Media SOCs :- DM355 and DM6446

This is the version v2 of the patch series. This is the reworked
version of the driver based on comments received against the last
version of the patch.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
These patches add support for VPFE (Video Processing Front End) based
video capture on DM355 and DM6446 EVMs. For more details on the hardware
configuration and capabilities, please refer the vpfe_capture.c header.
This patch set consists of following:-

Patch 1: VPFE Capture bridge driver
Patch 2: CCDC hw device header file
Patch 3: DM355 CCDC hw module
Patch 4: DM644x CCDC hw module
Patch 5: ccdc types used across CCDC modules
Patch 6: Makefile and config files for the driver
Patch 7: DM355 platform and board setup
Patch 8: DM644x platform and board setup
Patch 9: Remove outdated driver files from davinci git tree
Patch 10: common vpss hw module for video drivers

NOTE:

Dependent on the TVP514x decoder driver patch for migrating the
driver to sub device model from Vaibhav Hiremath

Following tests are performed.
	1) Capture and display video (PAL & NTSC) from tvp5146 decoder.
	   Displayed using fbdev device driver available on davinci git tree
	2) Tested with driver built statically and dynamically

Muralidhara Karicheri

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-11 17:00 [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver m-karicheri2
@ 2009-06-11 17:00 ` m-karicheri2
  2009-06-11 17:00   ` [PATCH 2/10 - v2] ccdc hw device header file for vpfe capture m-karicheri2
                     ` (2 more replies)
  2009-06-11 20:24 ` [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver David Brownell
  1 sibling, 3 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

Re-sending since previous one missed a file (vpfe_types.h)

VPFE Capture bridge driver

This is version, v2 of vpfe capture bridge driver for doing video
capture on DM355 and DM6446 evms. The ccdc hw modules register with the
driver and are used for configuring the CCD Controller for a specific
decoder interface. The driver also registers the sub devices required
for a specific evm. More than one sub devices can be registered.
This allows driver to switch dynamically to capture video from
any sub device that is registered. Currently only one sub device
(tvp5146) is supported. But in future this driver is expected
to do capture from sensor devices such as Micron's MT9T001,MT9T031
and MT9P031 etc. The driver currently supports MMAP based IO.

Following are the updates based on review comments:-
	1) minor number is allocated dynamically
	2) updates to QUERYCAP handling
	3) eliminated intermediate vpfe pixel format
	4) refactored few functions
	5) reworked isr routines for reducing indentation
	6) reworked vpfe_check_format and added a documentation
	   for algorithm
	7) fixed memory leak in probe()

TODO list :
	1) load sub device from bridge driver. Hans has enhanced
	the v4l2-subdevice framework to do this. Will be updated
	soon to pick this.
	
		
Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 drivers/media/video/davinci/vpfe_capture.c | 2252 ++++++++++++++++++++++++++++
 include/media/davinci/vpfe_capture.h       |  183 +++
 include/media/davinci/vpfe_types.h         |   51 +
 3 files changed, 2486 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/vpfe_capture.c
 create mode 100644 include/media/davinci/vpfe_capture.h
 create mode 100644 include/media/davinci/vpfe_types.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..003450b
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -0,0 +1,2252 @@
+/*
+ * 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
+ *
+ * Driver name : VPFE Capture driver
+ *    VPFE Capture driver allows applications to capture and stream video
+ *    frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
+ *    TVP5146 or  Raw Bayer RGB image data from an image sensor
+ *    such as Microns' MT9T001, MT9T031 etc.
+ *
+ *    These SoCs have, in common, a Video Processing Subsystem (VPSS) that
+ *    consists of a Video Processing Front End (VPFE) for capturing
+ *    video/raw image data and Video Processing Back End (VPBE) for displaying
+ *    YUV data through an in-built analog encoder or Digital LCD port. This
+ *    driver is for capture through VPFE. A typical EVM using these SoCs have
+ *    following high level configuration.
+ *
+ *
+ *    decoder(TVP5146/		YUV/
+ * 	     MT9T001)   -->  Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
+ *    				data input              |      |
+ *							V      |
+ *						      SDRAM    |
+ *							       V
+ *							   Image Processor
+ *							       |
+ *							       V
+ *							     SDRAM
+ *    The data flow happens from a decoder connected to the VPFE over a
+ *    YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
+ *    and to the input of VPFE through an optional MUX (if more inputs are
+ *    to be interfaced on the EVM). The input data is first passed through
+ *    CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
+ *    does very little or no processing on YUV data and does pre-process Raw
+ *    Bayer RGB data through modules such as Defect Pixel Correction (DFC)
+ *    Color Space Conversion (CSC), data gain/offset etc. After this, data
+ *    can be written to SDRAM or can be connected to the image processing
+ *    block such as IPIPE (on DM355 only).
+ *
+ *    Features supported
+ *  		- MMAP IO
+ *		- Capture using TVP5146 over BT.656
+ *		- support for interfacing decoders using sub device model
+ *		- Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV
+ *		  data capture to SDRAM.
+ *    TODO list
+ *		- Support multiple REQBUF after open
+ *		- Support for de-allocating buffers through REQBUF
+ *		- Support for Raw Bayer RGB capture
+ *		- Support for chaining Image Processor
+ *		- Support for static allocation of buffers
+ *		- Support for USERPTR IO
+ *		- Support for STREAMON before QBUF
+ */
+#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 <media/davinci/vpfe_capture.h>
+#include <media/tvp514x.h>
+#include <linux/i2c.h>
+#include "ccdc_hw_device.h"
+
+static int debug;
+static u32 numbuffers = 3;
+static u32 bufsize = (720 * 576 * 2);
+
+module_param(numbuffers, uint, S_IRUGO);
+module_param(bufsize, uint, S_IRUGO);
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(numbuffers, "buffer count (default:3)");
+MODULE_PARM_DESC(bufsize, "buffer size (default:720 x 576 x 2)");
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+
+/* standard information */
+struct vpfe_standard {
+	v4l2_std_id std_id;
+	unsigned int width;
+	unsigned int height;
+	struct v4l2_fract pixelaspect;
+	/* 0 - progressive, 1 - interlaced */
+	int frame_format;
+};
+
+/* ccdc configuration */
+struct ccdc_config {
+	/* This make sure vpfe is probed and ready to go */
+	int vpfe_probed;
+	/* name of ccdc device */
+	char name[32];
+	/* for storing mem maps for CCDC */
+	int ccdc_addr_size;
+	void *__iomem ccdc_addr;
+};
+
+/* data structures */
+static struct vpfe_config_params config_params = {
+	.min_numbuffers = 3,
+	.numbuffers = 3,
+	.min_bufsize = 720 * 480 * 2,
+	.device_bufsize = 720 * 576 * 2,
+};
+
+/* ccdc device registered */
+static struct ccdc_hw_device *ccdc_dev;
+/* lock for accessing ccdc information */
+static DEFINE_MUTEX(ccdc_lock);
+/* ccdc configuration */
+static struct ccdc_config *ccdc_cfg;
+
+#define VPFE_PIXELASPECT_NTSC       {11, 10}
+#define VPFE_PIXELASPECT_PAL        {54, 59}
+
+const struct vpfe_standard vpfe_standards[] = {
+	{V4L2_STD_NTSC,	720, 480, VPFE_PIXELASPECT_NTSC, 1},
+	{V4L2_STD_PAL,	720, 576, VPFE_PIXELASPECT_PAL, 1},
+};
+
+/* Used when raw Bayer image from ccdc is directly captured to SDRAM */
+static const struct vpfe_pixel_format vpfe_pix_fmts[] = {
+	{
+		.fmtdesc = {
+			.index = 0,
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.description = "Bayer GrRBGb 8bit A-Law compr.",
+			.pixelformat = V4L2_PIX_FMT_SBGGR8,
+		},
+		.bpp = 1,
+	},
+	{
+		.fmtdesc = {
+			.index = 1,
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.description = "Bayer GrRBGb - 16bit",
+			.pixelformat = V4L2_PIX_FMT_SBGGR16,
+		},
+		.bpp = 2,
+	},
+	{
+		.fmtdesc = {
+			.index = 2,
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.description = "Bayer GrRBGb 8bit DPCM compr.",
+			.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
+		},
+		.bpp = 1,
+	},
+	{
+		.fmtdesc = {
+			.index = 3,
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.description = "YCbCr 4:2:2 Interleaved UYVY",
+			.pixelformat = V4L2_PIX_FMT_UYVY,
+		},
+		.bpp = 2,
+	},
+	{
+		.fmtdesc = {
+			.index = 4,
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.description = "YCbCr 4:2:2 Interleaved YUYV",
+			.pixelformat = V4L2_PIX_FMT_YUYV,
+		},
+		.bpp = 2,
+	},
+	{
+		.fmtdesc = {
+			.index = 5,
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.description = "Y/CbCr 4:2:0 - Semi planar",
+			.pixelformat = V4L2_PIX_FMT_NV12,
+		},
+		.bpp = 1,
+	},
+};
+
+/*
+ * vpfe_lookup_pix_format()
+ * lookup an entry in the vpfe pix format table based on pix_format
+ */
+static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) {
+		if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat)
+			return &vpfe_pix_fmts[i];
+	}
+	return NULL;
+}
+
+/*
+ * vpfe_register_ccdc_device. CCDC module calls this to
+ * register with vpfe capture
+ */
+int vpfe_register_ccdc_device(struct ccdc_hw_device *dev)
+{
+	int ret = 0;
+	printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name);
+
+	BUG_ON(!dev->hw_ops.open);
+	BUG_ON(!dev->hw_ops.enable);
+	BUG_ON(!dev->hw_ops.set_hw_if_params);
+	BUG_ON(!dev->hw_ops.configure);
+	BUG_ON(!dev->hw_ops.set_buftype);
+	BUG_ON(!dev->hw_ops.get_buftype);
+	BUG_ON(!dev->hw_ops.enum_pix);
+	BUG_ON(!dev->hw_ops.set_frame_format);
+	BUG_ON(!dev->hw_ops.get_frame_format);
+	BUG_ON(!dev->hw_ops.get_pixel_format);
+	BUG_ON(!dev->hw_ops.set_pixel_format);
+	BUG_ON(!dev->hw_ops.set_params);
+	BUG_ON(!dev->hw_ops.set_image_window);
+	BUG_ON(!dev->hw_ops.get_image_window);
+	BUG_ON(!dev->hw_ops.get_line_length);
+	BUG_ON(!dev->hw_ops.setfbaddr);
+	BUG_ON(!dev->hw_ops.getfid);
+
+	mutex_lock(&ccdc_lock);
+	if (NULL == ccdc_cfg) {
+		/*
+		 * TODO. Will this ever happen? if so, we need to fix it.
+		 * Proabably we need to add the request to a linked list and
+		 * walk through it during vpfe probe
+		 */
+		printk(KERN_ERR "vpfe capture not initialized\n");
+		ret = -1;
+		goto unlock;
+	}
+
+	if (strcmp(dev->name, ccdc_cfg->name)) {
+		/* ignore this ccdc */
+		ret = -1;
+		goto unlock;
+	}
+
+	if (ccdc_dev) {
+		printk(KERN_ERR "ccdc already registered\n");
+		ret = -1;
+		goto unlock;
+	}
+
+	ccdc_dev = dev;
+	dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr,
+				  ccdc_cfg->ccdc_addr_size);
+unlock:
+	mutex_unlock(&ccdc_lock);
+	return ret;
+}
+EXPORT_SYMBOL(vpfe_register_ccdc_device);
+
+/*
+ * vpfe_unregister_ccdc_device. CCDC module calls this to
+ * unregister with vpfe capture
+ */
+void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev)
+{
+	if (NULL == dev) {
+		printk(KERN_ERR "invalid ccdc device ptr\n");
+		return;
+	}
+
+	printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n",
+		dev->name);
+
+	if (strcmp(dev->name, ccdc_cfg->name)) {
+		/* ignore this ccdc */
+		return;
+	}
+
+	mutex_lock(&ccdc_lock);
+	ccdc_dev = NULL;
+	mutex_unlock(&ccdc_lock);
+	return;
+}
+EXPORT_SYMBOL(vpfe_unregister_ccdc_device);
+
+/* Set interface params based on client interface */
+static int vpfe_set_hw_if_params(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_subdev_info *subdev = vpfe_dev->current_subdev;
+	struct v4l2_routing *route =
+		&(subdev->routes[vpfe_dev->current_input]);
+
+	switch (route->output) {
+	case OUTPUT_10BIT_422_EMBEDDED_SYNC:
+		vpfe_dev->vpfe_if_params.if_type = VPFE_BT656;
+		break;
+	case OUTPUT_20BIT_422_SEPERATE_SYNC:
+		vpfe_dev->vpfe_if_params.if_type = VPFE_YCBCR_SYNC_16;
+		break;
+	case OUTPUT_10BIT_422_SEPERATE_SYNC:
+		vpfe_dev->vpfe_if_params.if_type = VPFE_YCBCR_SYNC_8;
+		break;
+	default:
+		v4l2_err(&vpfe_dev->v4l2_dev, "decoder output"
+			" not supported, %d\n", route->output);
+		return -EINVAL;
+	}
+
+	/* set if client specific interface param is available */
+	if (subdev->pdata) {
+		/* each client will have different interface requirements */
+		if (!strcmp(subdev->name, "tvp5146")) {
+			struct tvp514x_platform_data *pdata = subdev->pdata;
+
+			if (pdata->hs_polarity)
+				vpfe_dev->vpfe_if_params.hdpol =
+					VPFE_PINPOL_POSITIVE;
+			else
+				vpfe_dev->vpfe_if_params.hdpol =
+					VPFE_PINPOL_NEGATIVE;
+
+			if (pdata->vs_polarity)
+				vpfe_dev->vpfe_if_params.vdpol =
+					VPFE_PINPOL_POSITIVE;
+			else
+				vpfe_dev->vpfe_if_params.hdpol =
+					VPFE_PINPOL_NEGATIVE;
+		} else {
+			v4l2_err(&vpfe_dev->v4l2_dev, "No interface params"
+				" defined for subdevice, %d\n", route->output);
+			return -EFAULT;
+		}
+	}
+	return ccdc_dev->hw_ops.set_hw_if_params(&vpfe_dev->vpfe_if_params);
+}
+
+/*
+ * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings
+ */
+static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev,
+				 struct v4l2_format *f)
+{
+	struct v4l2_rect image_win;
+	enum ccdc_buftype buf_type;
+	enum ccdc_frmfmt frm_fmt;
+
+	memset(f, 0, sizeof(*f));
+	f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	ccdc_dev->hw_ops.get_image_window(&image_win);
+	f->fmt.pix.width = image_win.width;
+	f->fmt.pix.height = image_win.height;
+	f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length();
+	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+				f->fmt.pix.height;
+	buf_type = ccdc_dev->hw_ops.get_buftype();
+	f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format();
+	frm_fmt = ccdc_dev->hw_ops.get_frame_format();
+	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 {
+			v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type");
+			return -EINVAL;
+		}
+	} else {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * vpfe_config_ccdc_image_format()
+ * For a pix format, configure ccdc to setup the capture
+ */
+static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev)
+{
+	enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
+	int ret = 0;
+
+	if (ccdc_dev->hw_ops.set_pixel_format(
+			vpfe_dev->fmt.fmt.pix.pixelformat) < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"couldn't set pix format in ccdc\n");
+		return -EINVAL;
+	}
+	/* configure the image window */
+	ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop);
+
+	switch (vpfe_dev->fmt.fmt.pix.field) {
+	case V4L2_FIELD_INTERLACED:
+		/* do nothing, since it is default */
+		ret = ccdc_dev->hw_ops.set_buftype(
+				CCDC_BUFTYPE_FLD_INTERLEAVED);
+		break;
+	case V4L2_FIELD_NONE:
+		frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
+		/* buffer type only applicable for interlaced scan */
+		break;
+	case V4L2_FIELD_SEQ_TB:
+		ret = ccdc_dev->hw_ops.set_buftype(
+				CCDC_BUFTYPE_FLD_SEPARATED);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set the frame format */
+	if (!ret)
+		ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt);
+	return ret;
+}
+/*
+ * vpfe_config_image_format()
+ * For a given standard, this functions sets up the default
+ * pix format & crop values in the vpfe device and ccdc.  It first
+ * starts with defaults based values from the standard table.
+ * It then checks if sub device support g_fmt and then override the
+ * values based on that.Sets crop values to match with scan resolution
+ * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
+ * values in ccdc
+ */
+static int vpfe_config_image_format(struct vpfe_device *vpfe_dev,
+				    const v4l2_std_id *std_id)
+{
+	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
+	int i, ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
+		if (vpfe_standards[i].std_id == *std_id) {
+			vpfe_dev->std_info.active_pixels =
+					vpfe_standards[i].width;
+			vpfe_dev->std_info.active_lines =
+					vpfe_standards[i].height;
+			vpfe_dev->std_info.frame_format =
+					vpfe_standards[i].frame_format;
+			vpfe_dev->std_index = i;
+			break;
+		}
+	}
+
+	if (i ==  ARRAY_SIZE(vpfe_standards)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n");
+		return -EINVAL;
+	}
+
+	vpfe_dev->crop.top = 0;
+	vpfe_dev->crop.left = 0;
+	vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels;
+	vpfe_dev->crop.height = vpfe_dev->std_info.active_lines;
+	vpfe_dev->fmt.fmt.pix.width = vpfe_dev->crop.width;
+	vpfe_dev->fmt.fmt.pix.height = vpfe_dev->crop.height;
+
+	/* first field and frame format based on standard frame format */
+	if (vpfe_dev->std_info.frame_format) {
+		vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+		/* assume V4L2_PIX_FMT_UYVY as default */
+		vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+	} else {
+		vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_NONE;
+		/* assume V4L2_PIX_FMT_SBGGR8 */
+		vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+	}
+
+	/* if sub device supports g_fmt, override the defaults */
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+			sub_dev->grp_id,
+			video, g_fmt, &vpfe_dev->fmt);
+
+	if (ret && ret != -ENOIOCTLCMD) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"error in getting g_fmt from sub device\n");
+		return ret;
+	}
+
+	/* Sets the values in CCDC */
+	ret = vpfe_config_ccdc_image_format(vpfe_dev);
+	if (ret)
+		return ret;
+
+	/* Update the values of sizeimage and bytesperline */
+	if (!ret) {
+		vpfe_dev->fmt.fmt.pix.bytesperline =
+			ccdc_dev->hw_ops.get_line_length();
+		vpfe_dev->fmt.fmt.pix.sizeimage =
+			vpfe_dev->fmt.fmt.pix.bytesperline *
+			vpfe_dev->fmt.fmt.pix.height;
+	}
+	return ret;
+}
+
+static int vpfe_initialize_device(struct vpfe_device *vpfe_dev)
+{
+	int ret = 0;
+
+	/* set first input of current subdevice as the current input */
+	vpfe_dev->current_input = 0;
+
+	/* set default standard */
+	vpfe_dev->std_index = 0;
+
+	/* Configure the default format information */
+	ret = vpfe_config_image_format(vpfe_dev,
+				&vpfe_standards[vpfe_dev->std_index].std_id);
+	if (ret)
+		return ret;
+
+	/* now open the ccdc device to initialize it */
+	mutex_lock(&ccdc_lock);
+	if (NULL == ccdc_dev) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n");
+		ret = -ENODEV;
+		goto unlock;
+	}
+
+	if (!try_module_get(ccdc_dev->owner)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n");
+		ret = -ENODEV;
+		goto unlock;
+	}
+	ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev);
+	if (!ret)
+		vpfe_dev->initialized = 1;
+unlock:
+	mutex_unlock(&ccdc_lock);
+	return ret;
+}
+
+/*
+ * vpfe_open : It creates object of file handle structure and
+ * stores it in private_data  member of filepointer
+ */
+static int vpfe_open(struct file *file)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_fh *fh;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");
+
+	if (!vpfe_dev->cfg->num_subdevs) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");
+		return -ENODEV;
+	}
+
+	/* Allocate memory for the file handle object */
+	fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
+	if (NULL == fh) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"unable to allocate memory for file handle object\n");
+		return -ENOMEM;
+	}
+	/* store pointer to fh in private_data member of file */
+	file->private_data = fh;
+	fh->vpfe_dev = vpfe_dev;
+	mutex_lock(&vpfe_dev->lock);
+	/* If decoder is not initialized. initialize it */
+	if (!vpfe_dev->initialized) {
+		if (vpfe_initialize_device(vpfe_dev)) {
+			mutex_unlock(&vpfe_dev->lock);
+			return -ENODEV;
+		}
+	}
+	/* Increment device usrs counter */
+	vpfe_dev->usrs++;
+	/* Set io_allowed member to false */
+	fh->io_allowed = 0;
+	/* Initialize priority of this instance to default priority */
+	fh->prio = V4L2_PRIORITY_UNSET;
+	v4l2_prio_open(&vpfe_dev->prio, &fh->prio);
+	mutex_unlock(&vpfe_dev->lock);
+	return 0;
+}
+
+static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)
+{
+	unsigned long addr;
+	vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
+					struct videobuf_buffer, queue);
+	list_del(&vpfe_dev->next_frm->queue);
+	vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
+	addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
+	ccdc_dev->hw_ops.setfbaddr(addr);
+}
+
+static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev)
+{
+	struct timeval timevalue;
+
+	do_gettimeofday(&timevalue);
+	vpfe_dev->cur_frm->ts = timevalue;
+	vpfe_dev->cur_frm->state = VIDEOBUF_DONE;
+	vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage;
+	wake_up_interruptible(&vpfe_dev->cur_frm->done);
+	vpfe_dev->cur_frm = vpfe_dev->next_frm;
+}
+
+/* ISR for VINT0*/
+static irqreturn_t vpfe_isr(int irq, void *dev_id)
+{
+	struct vpfe_device *vpfe_dev = dev_id;
+	enum v4l2_field field;
+	unsigned long addr;
+	int fid;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...");
+	field = vpfe_dev->fmt.fmt.pix.field;
+
+	/* if streaming not started, don't do anything */
+	if (!vpfe_dev->started)
+		return IRQ_RETVAL(1);
+
+	/* only for 6446 this will be applicable */
+	if (NULL != ccdc_dev->hw_ops.reset)
+		ccdc_dev->hw_ops.reset();
+
+	if (field == V4L2_FIELD_NONE) {
+		/* handle progressive frame capture */
+		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+			"frame format is progressive...\n");
+		if (vpfe_dev->cur_frm != vpfe_dev->next_frm)
+			vpfe_process_buffer_complete(vpfe_dev);
+		return IRQ_RETVAL(1);
+	}
+
+	/* interlaced or TB capture check which field we are in hardware */
+	fid = ccdc_dev->hw_ops.getfid();
+
+	/* switch the software maintained field id */
+	vpfe_dev->field_id ^= 1;
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n",
+		fid, vpfe_dev->field_id);
+	if (fid == vpfe_dev->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_dev->cur_frm != vpfe_dev->next_frm)
+				vpfe_process_buffer_complete(vpfe_dev);
+			/*
+			 * based on whether the two fields are stored
+			 * interleavely or separately in memory, reconfigure
+			 * the CCDC memory address
+			 */
+			if (field == V4L2_FIELD_SEQ_TB) {
+				addr =
+				  videobuf_to_dma_contig(vpfe_dev->cur_frm);
+				addr += vpfe_dev->field_off;
+				ccdc_dev->hw_ops.setfbaddr(addr);
+			}
+			return IRQ_RETVAL(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
+		 */
+		spin_lock(&vpfe_dev->dma_queue_lock);
+		if (!list_empty(&vpfe_dev->dma_queue) &&
+		    vpfe_dev->cur_frm == vpfe_dev->next_frm)
+			vpfe_schedule_next_buffer(vpfe_dev);
+		spin_unlock(&vpfe_dev->dma_queue_lock);
+	} else if (fid == 0) {
+		/*
+		 * out of sync. Recover from any hardware out-of-sync.
+		 * May loose one frame
+		 */
+		vpfe_dev->field_id = fid;
+	}
+	return IRQ_RETVAL(1);
+}
+
+/* vdint1_isr - isr handler for VINT1 interrupt */
+static irqreturn_t vdint1_isr(int irq, void *dev_id)
+{
+	struct vpfe_device *vpfe_dev = dev_id;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...");
+
+	/* if streaming not started, don't do anything */
+	if (!vpfe_dev->started)
+		return IRQ_RETVAL(1);
+
+	spin_lock(&vpfe_dev->dma_queue_lock);
+	if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) &&
+	    !list_empty(&vpfe_dev->dma_queue) &&
+	    vpfe_dev->cur_frm == vpfe_dev->next_frm)
+		vpfe_schedule_next_buffer(vpfe_dev);
+	spin_unlock(&vpfe_dev->dma_queue_lock);
+	return IRQ_RETVAL(1);
+}
+
+static void vpfe_detach_irq(struct vpfe_device *vpfe_dev)
+{
+	enum ccdc_frmfmt frame_format;
+
+	frame_format = ccdc_dev->hw_ops.get_frame_format();
+	if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
+		free_irq(IRQ_VDINT1, vpfe_dev);
+}
+
+static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
+{
+	enum ccdc_frmfmt frame_format;
+
+	frame_format = ccdc_dev->hw_ops.get_frame_format();
+	if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {
+		return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr,
+				    IRQF_DISABLED, "vpfe_capture1",
+				    vpfe_dev);
+	}
+	return 0;
+}
+
+/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */
+static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev)
+{
+	vpfe_dev->started = 0;
+	ccdc_dev->hw_ops.enable(0);
+	if (ccdc_dev->hw_ops.enable_out_to_sdram)
+		ccdc_dev->hw_ops.enable_out_to_sdram(0);
+}
+
+/*
+ * vpfe_release : This function deletes buffer queue, frees the
+ * buffers and the vpfe file  handle
+ */
+static int vpfe_release(struct file *file)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_fh *fh = file->private_data;
+	struct vpfe_subdev_info *subdev;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
+
+	/* Get the device lock */
+	mutex_lock(&vpfe_dev->lock);
+	/* if this instance is doing IO */
+	if (fh->io_allowed) {
+		if (vpfe_dev->started) {
+			subdev = vpfe_dev->current_subdev;
+			ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+							 subdev->grp_id,
+							 video, s_stream, 0);
+			if (ret && (ret != -ENOIOCTLCMD))
+				v4l2_err(&vpfe_dev->v4l2_dev,
+				"stream off failed in subdev\n");
+			vpfe_stop_ccdc_capture(vpfe_dev);
+			vpfe_detach_irq(vpfe_dev);
+			videobuf_streamoff(&vpfe_dev->buffer_queue);
+		}
+		vpfe_dev->io_usrs = 0;
+		vpfe_dev->numbuffers = config_params.numbuffers;
+	}
+
+	/* Decrement device usrs counter */
+	vpfe_dev->usrs--;
+	/* Close the priority */
+	v4l2_prio_close(&vpfe_dev->prio, &fh->prio);
+	/* If this is the last file handle */
+	if (!vpfe_dev->usrs) {
+		vpfe_dev->initialized = 0;
+		if (ccdc_dev->hw_ops.close)
+			ccdc_dev->hw_ops.close(vpfe_dev->pdev);
+		module_put(ccdc_dev->owner);
+	}
+	mutex_unlock(&vpfe_dev->lock);
+	file->private_data = NULL;
+	/* Free memory allocated to file handle object */
+	kfree(fh);
+	return 0;
+}
+
+/*
+ * vpfe_mmap : It is used to map kernel space buffers
+ * into user spaces
+ */
+static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	/* Get the device object and file handle object */
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
+
+	return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma);
+}
+
+/*
+ * vpfe_poll: It is used for select/poll system call
+ */
+static unsigned int vpfe_poll(struct file *file, poll_table *wait)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
+
+	if (vpfe_dev->started)
+		return videobuf_poll_stream(file,
+					    &vpfe_dev->buffer_queue, wait);
+	return 0;
+}
+
+/* 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
+};
+
+/*
+ * vpfe_check_format()
+ * This function adjust the input pixel format as per hardware
+ * capabilities and update the same in pixfmt.
+ * Following algorithm used :-
+ *
+ *	If given pixformat is not in the vpfe list of pix formats or not
+ *	supported by the hardware, current value of pixformat in the device
+ *	is used
+ *	If given field is not supported, then current field is used. If field
+ *	is different from current, then it is matched with that from sub device.
+ *	Minimum height is 2 lines for interlaced or tb field and 1 line for
+ *	progressive. Maximum height is clamped to active active lines of scan
+ *	Minimum width is 32 bytes in memory and width is clamped to active
+ *	pixels of scan.
+ *	bytesperline is a multiple of 32.
+ */
+static const struct vpfe_pixel_format *
+	vpfe_check_format(struct vpfe_device *vpfe_dev,
+			  struct v4l2_pix_format *pixfmt)
+{
+	u32 min_height = 1, min_width = 32, max_width, max_height;
+	const struct vpfe_pixel_format *vpfe_pix_fmt;
+	u32 pix;
+	int temp, found;
+
+	vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
+	if (NULL == vpfe_pix_fmt) {
+		/*
+		 * use current pixel format in the vpfe device. We
+		 * will find this pix format in the table
+		 */
+		pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
+		vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
+	}
+
+	/* check if hw supports it */
+	temp = 0;
+	found = 0;
+	while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) {
+		if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) {
+			found = 1;
+			break;
+		}
+		temp++;
+	}
+
+	if (!found) {
+		/* use current pixel format */
+		pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
+		/*
+		 * Since this is currently used in the vpfe device, we
+		 * will find this pix format in the table
+		 */
+		vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
+	}
+
+	/* check what field format is supported */
+	if (pixfmt->field == V4L2_FIELD_ANY) {
+		/* if field is any, use current value as default */
+		pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
+	}
+
+	/*
+	 * if field is not same as current field in the vpfe device
+	 * try matching the field with the sub device field
+	 */
+	if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) {
+		/*
+		 * If field value is not in the supported fields, use current
+		 * field used in the device as default
+		 */
+		switch (pixfmt->field) {
+		case V4L2_FIELD_INTERLACED:
+		case V4L2_FIELD_SEQ_TB:
+			/* if sub device is supporting progressive, use that */
+			if (!vpfe_dev->std_info.frame_format)
+				pixfmt->field = V4L2_FIELD_NONE;
+			break;
+		case V4L2_FIELD_NONE:
+			if (vpfe_dev->std_info.frame_format)
+				pixfmt->field = V4L2_FIELD_INTERLACED;
+			break;
+
+		default:
+			/* use current field as default */
+			pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
+		}
+	}
+
+	/* Now adjust image resolutions supported */
+	if (pixfmt->field == V4L2_FIELD_INTERLACED ||
+	    pixfmt->field == V4L2_FIELD_SEQ_TB)
+		min_height = 2;
+
+	max_width = vpfe_dev->std_info.active_pixels;
+	max_height = vpfe_dev->std_info.active_lines;
+	min_width /= vpfe_pix_fmt->bpp;
+
+	v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n",
+		  pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp);
+
+	pixfmt->width = clamp((pixfmt->width), min_width, max_width);
+	pixfmt->height = clamp((pixfmt->height), min_height, max_height);
+
+	/* If interlaced, adjust height to be a multiple of 2 */
+	if (pixfmt->field == V4L2_FIELD_INTERLACED)
+		pixfmt->height &= (~1);
+	/*
+	 * recalculate bytesperline and sizeimage since width
+	 * and height might have changed
+	 */
+	pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31)
+				& ~31);
+	if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
+		pixfmt->sizeimage =
+			pixfmt->bytesperline * pixfmt->height +
+			((pixfmt->bytesperline * pixfmt->height) >> 1);
+	else
+		pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+
+	v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="
+		 " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
+		 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,
+		 pixfmt->bytesperline, pixfmt->sizeimage);
+	return vpfe_pix_fmt;
+}
+
+static int vpfe_querycap(struct file *file, void  *priv,
+			       struct v4l2_capability *cap)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
+
+	cap->version = VPFE_CAPTURE_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
+	strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
+	return 0;
+}
+
+static int vpfe_g_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *fmt)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n");
+	/* Fill in the information about format */
+	*fmt = vpfe_dev->fmt;
+	return ret;
+}
+
+static int vpfe_enum_fmt_vid_cap(struct file *file, void  *priv,
+				   struct v4l2_fmtdesc *fmt)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	const struct vpfe_pixel_format *pix_fmt;
+	int temp_index;
+	u32 pix;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n");
+
+	if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0)
+		return -EINVAL;
+
+	/* Fill in the information about format */
+	pix_fmt = vpfe_lookup_pix_format(pix);
+	if (NULL != pix_fmt) {
+		temp_index = fmt->index;
+		*fmt = pix_fmt->fmtdesc;
+		fmt->index = temp_index;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int vpfe_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *fmt)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	const struct vpfe_pixel_format *pix_fmts;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");
+
+	/* If streaming is started, return error */
+	if (vpfe_dev->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
+		return -EBUSY;
+	}
+
+	/* Check for valid frame format */
+	pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);
+
+	if (NULL == pix_fmts)
+		return -EINVAL;
+
+	/* store the pixel format in the device  object */
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	/* First detach any IRQ if currently attached */
+	vpfe_detach_irq(vpfe_dev);
+	vpfe_dev->fmt = *fmt;
+	/* set image capture parameters in the ccdc */
+	ret = vpfe_config_ccdc_image_format(vpfe_dev);
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+static int vpfe_try_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	const struct vpfe_pixel_format *pix_fmts;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");
+
+	pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);
+	if (NULL == pix_fmts)
+		return -EINVAL;
+	return 0;
+}
+
+/*
+ * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a
+ * given app input index
+ */
+static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev,
+					int *subdev_index,
+					int *subdev_input_index,
+					int app_input_index)
+{
+	struct vpfe_config *cfg = vpfe_dev->cfg;
+	struct vpfe_subdev_info *sub_dev;
+	int i, j = 0;
+
+	for (i = 0; i < cfg->num_subdevs; i++) {
+		sub_dev = &cfg->sub_devs[i];
+		if (app_input_index < (j + sub_dev->num_inputs)) {
+			*subdev_index = i;
+			*subdev_input_index = app_input_index - j;
+			return 0;
+		}
+		j += sub_dev->num_inputs;
+	}
+	return -EINVAL;
+}
+
+/*
+ * vpfe_get_app_input - Get app input index for a given subdev input index
+ * driver stores the input index of the current sub device and translate it
+ * when application request the current input
+ */
+static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev,
+				    int *app_input_index)
+{
+	struct vpfe_config *cfg = vpfe_dev->cfg;
+	struct vpfe_subdev_info *sub_dev;
+	int i, j = 0;
+
+	for (i = 0; i < cfg->num_subdevs; i++) {
+		sub_dev = &cfg->sub_devs[i];
+		if (!strcmp(sub_dev->name, vpfe_dev->current_subdev->name)) {
+			if (vpfe_dev->current_input >= sub_dev->num_inputs)
+				return -1;
+			*app_input_index = j + vpfe_dev->current_input;
+			return 0;
+		}
+		j += sub_dev->num_inputs;
+	}
+	return -EINVAL;
+}
+
+static int vpfe_enum_input(struct file *file, void *priv,
+				 struct v4l2_input *inp)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *sub_dev;
+	int subdev, index ;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
+
+	if (vpfe_get_subdev_input_index(vpfe_dev,
+					&subdev,
+					&index,
+					inp->index) < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"
+			 " for the subdev\n");
+		return -EINVAL;
+	}
+	sub_dev = &vpfe_dev->cfg->sub_devs[subdev];
+	memcpy(inp, &sub_dev->inputs[index],
+		sizeof(struct v4l2_input));
+	return 0;
+}
+
+static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
+
+	return vpfe_get_app_input_index(vpfe_dev, index);
+}
+
+
+static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *sub_dev;
+	int subdev_index, inp_index;
+	struct v4l2_routing *route;
+	u32 input = 0, output = 0;
+	int ret = -EINVAL;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	/*
+	 * If streaming is started return device busy
+	 * error
+	 */
+	if (vpfe_dev->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
+		ret = -EBUSY;
+		goto unlock_out;
+	}
+
+	if (vpfe_get_subdev_input_index(vpfe_dev,
+					&subdev_index,
+					&inp_index,
+					index) < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");
+		goto unlock_out;
+	}
+
+	sub_dev = &vpfe_dev->cfg->sub_devs[subdev_index];
+	route = &sub_dev->routes[inp_index];
+	if (route && sub_dev->can_route) {
+		input = route->input;
+		output = route->output;
+	}
+
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+					 sub_dev->grp_id,
+					 video, s_routing, input,
+					 output, 0);
+
+	if (ret) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"vpfe_doioctl:error in setting input in decoder \n");
+		ret = -EINVAL;
+		goto unlock_out;
+	}
+	vpfe_dev->current_subdev = sub_dev;
+	vpfe_dev->current_input = index;
+	vpfe_dev->std_index = 0;
+
+	ret = vpfe_set_hw_if_params(vpfe_dev);
+	if (ret)
+		goto unlock_out;
+
+	/* set the default image parameters in the device */
+	ret = vpfe_config_image_format(vpfe_dev,
+				&vpfe_standards[vpfe_dev->std_index].std_id);
+	if (ret)
+		goto unlock_out;
+
+unlock_out:
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *subdev;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	subdev = vpfe_dev->current_subdev;
+	if (ret)
+		return ret;
+	/* Call querystd function of decoder device */
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+					 subdev->grp_id,
+					 video, querystd, std_id);
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *subdev;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
+
+	/* Call decoder driver function to set the standard */
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	subdev = vpfe_dev->current_subdev;
+	/* If streaming is started, return device busy error */
+	if (vpfe_dev->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
+		ret = -EBUSY;
+		goto unlock_out;
+	}
+
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
+					 core, s_std, *std_id);
+	if (ret < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
+		goto unlock_out;
+	}
+	ret = vpfe_config_image_format(vpfe_dev, std_id);
+
+unlock_out:
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
+
+	*std_id = vpfe_standards[vpfe_dev->std_index].std_id;
+	return 0;
+}
+/*
+ *  Videobuf operations
+ */
+static int vpfe_videobuf_setup(struct videobuf_queue *vq,
+				unsigned int *count,
+				unsigned int *size)
+{
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
+	*size = config_params.device_bufsize;
+
+	if (*count < config_params.min_numbuffers)
+		*count = config_params.min_numbuffers;
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+		"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)
+{
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
+
+	/* If buffer is not initialized, initialize it */
+	if (VIDEOBUF_NEEDS_INIT == vb->state) {
+		vb->width = vpfe_dev->fmt.fmt.pix.width;
+		vb->height = vpfe_dev->fmt.fmt.pix.height;
+		vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
+		vb->field = field;
+	}
+	vb->state = VIDEOBUF_PREPARED;
+	return 0;
+}
+
+static void vpfe_videobuf_queue(struct videobuf_queue *vq,
+				struct videobuf_buffer *vb)
+{
+	/* Get the file handle object and device object */
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
+	unsigned long flags;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n");
+
+	/* add the buffer to the DMA queue */
+	spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
+	list_add_tail(&vb->queue, &vpfe_dev->dma_queue);
+	spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
+
+	/* Change state of the buffer */
+	vb->state = VIDEOBUF_QUEUED;
+}
+
+static void vpfe_videobuf_release(struct videobuf_queue *vq,
+				  struct videobuf_buffer *vb)
+{
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
+	unsigned long flags;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");
+
+	/*
+	 * We need to flush the buffer from the dma queue since
+	 * they are de-allocated
+	 */
+	spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
+	INIT_LIST_HEAD(&vpfe_dev->dma_queue);
+	spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
+	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,
+};
+
+/*
+ * vpfe_reqbufs. currently support REQBUF only once opening
+ * the device.
+ */
+static int vpfe_reqbufs(struct file *file, void *priv,
+			struct v4l2_requestbuffers *req_buf)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_fh *fh = file->private_data;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	if (V4L2_MEMORY_USERPTR == req_buf->memory) {
+		/* we don't support user ptr IO */
+		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
+			 " USERPTR IO not supported>\n");
+		return  -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	if (vpfe_dev->io_usrs != 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
+		ret = -EBUSY;
+		goto unlock_out;
+	}
+
+	vpfe_dev->memory = req_buf->memory;
+	videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue,
+				&vpfe_videobuf_qops,
+				NULL,
+				&vpfe_dev->irqlock,
+				req_buf->type,
+				vpfe_dev->fmt.fmt.pix.field,
+				sizeof(struct videobuf_buffer),
+				fh);
+
+	fh->io_allowed = 1;
+	vpfe_dev->io_usrs = 1;
+	INIT_LIST_HEAD(&vpfe_dev->dma_queue);
+	ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf);
+unlock_out:
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+static int vpfe_querybuf(struct file *file, void *priv,
+			 struct v4l2_buffer *buf)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return  -EINVAL;
+	}
+
+	if (vpfe_dev->memory != V4L2_MEMORY_MMAP) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
+		return -EINVAL;
+	}
+	/* Call videobuf_querybuf to get information */
+	return videobuf_querybuf(&vpfe_dev->buffer_queue, buf);
+}
+
+static int vpfe_qbuf(struct file *file, void *priv,
+		     struct v4l2_buffer *p)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_fh *fh = file->private_data;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * If this file handle is not allowed to do IO,
+	 * return error
+	 */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+		return -EACCES;
+	}
+	return videobuf_qbuf(&vpfe_dev->buffer_queue, p);
+}
+
+static int vpfe_dqbuf(struct file *file, void *priv,
+		      struct v4l2_buffer *buf)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+	return videobuf_dqbuf(&vpfe_dev->buffer_queue,
+				      buf, file->f_flags & O_NONBLOCK);
+}
+
+/*
+ * vpfe_calculate_offsets : This function calculates buffers offset
+ * for top and bottom field
+ */
+static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev)
+{
+	struct v4l2_rect image_win;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n");
+
+	ccdc_dev->hw_ops.get_image_window(&image_win);
+	vpfe_dev->field_off = image_win.height * image_win.width;
+}
+
+/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */
+static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev)
+{
+	ccdc_dev->hw_ops.enable(1);
+	if (ccdc_dev->hw_ops.enable_out_to_sdram)
+		ccdc_dev->hw_ops.enable_out_to_sdram(1);
+	vpfe_dev->started = 1;
+}
+
+/*
+ * vpfe_streamon. Assume the DMA queue is not empty.
+ * application is expected to call QBUF before calling
+ * this ioctl. If not, driver returns error
+ */
+static int vpfe_streamon(struct file *file, void *priv,
+			 enum v4l2_buf_type buf_type)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_fh *fh = file->private_data;
+	struct vpfe_subdev_info *subdev;
+	unsigned long addr;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+
+	/* If file handle is not allowed IO, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+		return -EACCES;
+	}
+
+	subdev = vpfe_dev->current_subdev;
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
+					video, s_stream, 1);
+
+	if (ret && (ret != -ENOIOCTLCMD)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n");
+		return -EINVAL;
+	}
+
+	/* If buffer queue is empty, return error */
+	if (list_empty(&vpfe_dev->buffer_queue.stream)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
+		return EIO;
+	}
+
+	/* Call videobuf_streamon to start streaming * in videobuf */
+	ret = videobuf_streamon(&vpfe_dev->buffer_queue);
+	if (ret)
+		return ret;
+
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		goto streamoff;
+	/* Get the next frame from the buffer queue */
+	vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
+					struct videobuf_buffer, queue);
+	vpfe_dev->cur_frm = vpfe_dev->next_frm;
+	/* Remove buffer from the buffer queue */
+	list_del(&vpfe_dev->cur_frm->queue);
+	/* Mark state of the current frame to active */
+	vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
+	/* Initialize field_id and started member */
+	vpfe_dev->field_id = 0;
+	addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
+
+	/* Calculate field offset */
+	vpfe_calculate_offsets(vpfe_dev);
+
+	if (vpfe_attach_irq(vpfe_dev) < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			 "Error in attaching interrupt handle\n");
+		ret = -EFAULT;
+		goto unlock_out;
+	}
+	if (ccdc_dev->hw_ops.configure() < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			 "Error in configuring ccdc\n");
+		ret = -EINVAL;
+		goto unlock_out;
+	}
+	ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr));
+	vpfe_start_ccdc_capture(vpfe_dev);
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+unlock_out:
+	mutex_unlock(&vpfe_dev->lock);
+streamoff:
+	ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
+	return ret;
+}
+
+static int vpfe_streamoff(struct file *file, void *priv,
+			  enum v4l2_buf_type i)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_fh *fh = file->private_data;
+	struct vpfe_subdev_info *subdev;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != i) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+
+	/* If io is allowed for this file handle, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+		return -EACCES;
+	}
+
+	/* If streaming is not started, return error */
+	if (!vpfe_dev->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "device started\n");
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	vpfe_stop_ccdc_capture(vpfe_dev);
+	vpfe_detach_irq(vpfe_dev);
+
+	subdev = vpfe_dev->current_subdev;
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
+					video, s_stream, 0);
+
+	if (ret && (ret != -ENOIOCTLCMD))
+		v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n");
+	ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+static int vpfe_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *qc)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_queryctrl\n");
+
+	if (qc->id >= V4L2_CID_PRIVATE_BASE) {
+		/* It is ccdc CID */
+		if (ccdc_dev->hw_ops.queryctrl)
+			return ccdc_dev->hw_ops.queryctrl(qc);
+	}
+	/* pass it to sub device */
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
+					  core, queryctrl, qc);
+}
+
+static int vpfe_g_ctrl(struct file *file, void *priv,
+			struct v4l2_control *ctrl)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_ctrl\n");
+
+	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
+		/* It is ccdc CID */
+		if (ccdc_dev->hw_ops.get_control)
+			return ccdc_dev->hw_ops.get_control(ctrl);
+	}
+
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
+					  core, g_ctrl, ctrl);
+}
+
+static int vpfe_s_ctrl(struct file *file, void *priv,
+			     struct v4l2_control *ctrl)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_ctrl\n");
+
+	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
+		/* It is internal ccdc CID */
+		if (ccdc_dev->hw_ops.set_control)
+			return ccdc_dev->hw_ops.set_control(ctrl);
+	}
+
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
+					  core, s_ctrl, ctrl);
+}
+
+static int vpfe_cropcap(struct file *file, void *priv,
+			      struct v4l2_cropcap *crop)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n");
+
+	if (vpfe_dev->std_index > ARRAY_SIZE(vpfe_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[vpfe_dev->std_index].width;
+	crop->bounds.height = crop->defrect.height =
+		vpfe_standards[vpfe_dev->std_index].height;
+	crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect;
+	return 0;
+}
+
+static int vpfe_g_crop(struct file *file, void *priv,
+			     struct v4l2_crop *crop)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n");
+
+	crop->c = vpfe_dev->crop;
+	return 0;
+}
+
+static int vpfe_s_crop(struct file *file, void *priv,
+			     struct v4l2_crop *crop)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
+
+	if (vpfe_dev->started) {
+		/* make sure streaming is not started */
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"Cannot change crop when streaming is ON\n");
+		return -EBUSY;
+	}
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	if (crop->c.top < 0 || crop->c.left < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"doesn't support negative values for top & left\n");
+		ret = -EINVAL;
+		goto unlock_out;
+	}
+
+	/* adjust the width to 16 pixel boundry */
+	crop->c.width = ((crop->c.width + 15) & ~0xf);
+
+	/* make sure parameters are valid */
+	if ((crop->c.left + crop->c.width >
+		vpfe_dev->std_info.active_pixels) ||
+	    (crop->c.top + crop->c.height >
+		vpfe_dev->std_info.active_lines)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
+		ret = -EINVAL;
+		goto unlock_out;
+	}
+	ccdc_dev->hw_ops.set_image_window(&crop->c);
+	vpfe_dev->fmt.fmt.pix.width = crop->c.width;
+	vpfe_dev->fmt.fmt.pix.height = crop->c.height;
+	vpfe_dev->fmt.fmt.pix.bytesperline =
+		ccdc_dev->hw_ops.get_line_length();
+	vpfe_dev->fmt.fmt.pix.sizeimage =
+		vpfe_dev->fmt.fmt.pix.bytesperline *
+		vpfe_dev->fmt.fmt.pix.height;
+	vpfe_dev->crop = crop->c;
+unlock_out:
+	mutex_unlock(&vpfe_dev->lock);
+	return ret;
+}
+
+
+static long vpfe_param_handler(struct file *file, void *priv,
+		int cmd, void *param)
+{
+	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
+
+	if (vpfe_dev->started) {
+		/* only allowed if streaming is not started */
+		v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n");
+		return -EBUSY;
+	}
+
+	ret = mutex_lock_interruptible(&vpfe_dev->lock);
+	if (ret)
+		return ret;
+
+	switch (cmd) {
+	case VPFE_CMD_S_CCDC_RAW_PARAMS:
+		ret = ccdc_dev->hw_ops.set_params(param);
+		if (ret) {
+			v4l2_err(&vpfe_dev->v4l2_dev,
+				"Error in setting parameters"
+				" in CCDC \n");
+			goto unlock_out;
+		}
+		if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) {
+			v4l2_err(&vpfe_dev->v4l2_dev,
+				"Invalid image format at CCDC \n");
+			goto unlock_out;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+unlock_out:
+	mutex_unlock(&vpfe_dev->lock);
+	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,
+};
+
+static struct vpfe_device *vpfe_initialize(void)
+{
+	struct vpfe_device *vpfe_dev;
+
+	/* Default number of buffers should be 3 */
+	if ((numbuffers > 0) &&
+	    (numbuffers < config_params.min_numbuffers))
+		numbuffers = config_params.min_numbuffers;
+
+	/*
+	 * Set buffer size to min buffers size if invalid buffer size is
+	 * given
+	 */
+	if (bufsize < config_params.min_bufsize)
+		bufsize = config_params.min_bufsize;
+
+	config_params.numbuffers = numbuffers;
+
+	if (numbuffers)
+		config_params.device_bufsize = bufsize;
+
+	/* Allocate memory for device objects */
+	vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);
+
+	return vpfe_dev;
+}
+
+static void vpfe_disable_clock(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
+
+	clk_disable(vpfe_cfg->vpssclk);
+	clk_put(vpfe_cfg->vpssclk);
+	clk_disable(vpfe_cfg->slaveclk);
+	clk_put(vpfe_cfg->slaveclk);
+	v4l2_info(vpfe_dev->pdev->driver,
+		 "vpfe vpss master & slave clocks disabled\n");
+}
+
+static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
+	int ret = -ENOENT;
+
+	vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master");
+	if (NULL == vpfe_cfg->vpssclk) {
+		v4l2_err(vpfe_dev->pdev->driver, "No clock defined for"
+			 "vpss_master\n");
+		return ret;
+	}
+
+	if (clk_enable(vpfe_cfg->vpssclk)) {
+		v4l2_err(vpfe_dev->pdev->driver,
+			"vpfe vpss master clock not enabled");
+		goto out;
+	}
+	v4l2_info(vpfe_dev->pdev->driver,
+		 "vpfe vpss master clock enabled\n");
+
+	vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave");
+	if (NULL == vpfe_cfg->slaveclk) {
+		v4l2_err(vpfe_dev->pdev->driver,
+			"No clock defined for vpss slave\n");
+		goto out;
+	}
+
+	if (clk_enable(vpfe_cfg->slaveclk)) {
+		v4l2_err(vpfe_dev->pdev->driver,
+			 "vpfe vpss slave clock not enabled");
+		goto out;
+	}
+	v4l2_info(vpfe_dev->pdev->driver,
+		 "vpfe vpss slave clock enabled\n");
+	return 0;
+out:
+	if (vpfe_cfg->vpssclk)
+		clk_put(vpfe_cfg->vpssclk);
+	if (vpfe_cfg->slaveclk)
+		clk_put(vpfe_cfg->slaveclk);
+
+	return -1;
+}
+
+/*
+ * vpfe_probe : This function creates device entries by register
+ * itself to the V4L2 driver and initializes fields of each
+ * device objects
+ */
+static __init int vpfe_probe(struct platform_device *pdev)
+{
+	struct vpfe_config *vpfe_cfg;
+	struct resource *res1;
+	struct vpfe_device *vpfe_dev;
+	struct i2c_adapter *i2c_adap;
+	struct i2c_client *client;
+	struct video_device *vfd;
+	int ret = -ENOMEM, i, j;
+	int num_subdevs = 0;
+
+	/* Get the pointer to the device object */
+	vpfe_dev = vpfe_initialize();
+
+	if (!vpfe_dev) {
+		v4l2_err(pdev->dev.driver,
+			"Failed to allocate memory for vpfe_dev\n");
+		return ret;
+	}
+
+	vpfe_dev->pdev = &pdev->dev;
+
+	if (NULL == pdev->dev.platform_data) {
+		v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+
+	vpfe_cfg = pdev->dev.platform_data;
+	vpfe_dev->cfg = vpfe_cfg;
+	if (NULL == vpfe_cfg->ccdc ||
+	    NULL == vpfe_cfg->card_name ||
+	    NULL == vpfe_cfg->sub_devs) {
+		v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+
+	/* enable vpss clocks */
+	ret = vpfe_enable_clock(vpfe_dev);
+	if (ret)
+		goto probe_free_dev_mem;
+
+	mutex_lock(&ccdc_lock);
+	/* Allocate memory for ccdc configuration */
+	ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);
+	if (NULL == ccdc_cfg) {
+		v4l2_err(pdev->dev.driver, "Memory allocation failed for"
+			"ccdc_cfg");
+		goto probe_disable_clock;
+	}
+
+	strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);
+	/* Get VINT0 irq resource */
+	res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res1) {
+		v4l2_err(pdev->dev.driver, "Unable to get interrupt for VINT0");
+		ret = -ENOENT;
+		goto probe_disable_clock;
+	}
+	vpfe_dev->ccdc_irq0 = res1->start;
+
+	/* Get VINT1 irq resource */
+	res1 = platform_get_resource(pdev,
+				IORESOURCE_IRQ, 1);
+	if (!res1) {
+		v4l2_err(pdev->dev.driver, "Unable to get interrupt for VINT1");
+		ret = -ENOENT;
+		goto probe_disable_clock;
+	}
+	vpfe_dev->ccdc_irq1 = res1->start;
+
+	/* Get address base of CCDC */
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res1) {
+		v4l2_err(pdev->dev.driver,
+			"Unable to get register address map\n");
+		ret = -ENOENT;
+		goto probe_disable_clock;
+	}
+
+	ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1;
+	if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size,
+				pdev->dev.driver->name)) {
+		v4l2_err(pdev->dev.driver,
+			"Failed request_mem_region for ccdc base\n");
+		ret = -ENXIO;
+		goto probe_disable_clock;
+	}
+	ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start,
+					     ccdc_cfg->ccdc_addr_size);
+	if (!ccdc_cfg->ccdc_addr) {
+		v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n");
+		ret = -ENXIO;
+		goto probe_out_release_mem1;
+	}
+
+	ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
+			  "vpfe_capture0", vpfe_dev);
+
+	if (0 != ret) {
+		v4l2_err(pdev->dev.driver, "Unable to request interrupt\n");
+		goto probe_out_unmap1;
+	}
+
+	/* Allocate memory for video device */
+	vfd = video_device_alloc();
+	if (NULL == vfd) {
+		ret = ENOMEM;
+		v4l2_err(pdev->dev.driver,
+			"Unable to alloc video device\n");
+		goto probe_out_release_irq;
+	}
+
+	/* 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		= 0;
+	vfd->current_norm	= V4L2_STD_PAL;
+	vfd->v4l2_dev 		= &vpfe_dev->v4l2_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 */
+	vpfe_dev->video_dev	= vfd;
+
+	ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
+	if (ret) {
+		v4l2_err(pdev->dev.driver,
+			"Unable to register v4l2 device.\n");
+		goto probe_out_video_release;
+	}
+	v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
+	spin_lock_init(&vpfe_dev->irqlock);
+	spin_lock_init(&vpfe_dev->dma_queue_lock);
+	mutex_init(&vpfe_dev->lock);
+
+	/* Initialize field of the device objects */
+	vpfe_dev->numbuffers = config_params.numbuffers;
+
+	/* Initialize prio member of device object */
+	v4l2_prio_init(&vpfe_dev->prio);
+	/* register video device */
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+		"trying to register vpfe device.\n");
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+		"video_dev=%x\n", (int)&vpfe_dev->video_dev);
+	vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ret = video_register_device(vpfe_dev->video_dev,
+				    VFL_TYPE_GRABBER, -1);
+
+	if (ret) {
+		v4l2_err(pdev->dev.driver,
+			"Unable to register video device.\n");
+		goto probe_out_v4l2_unregister;
+	}
+
+	v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n");
+	/* set the driver data in platform device */
+	platform_set_drvdata(pdev, vpfe_dev);
+	/* set driver private data */
+	video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);
+	i2c_adap = i2c_get_adapter(1);
+	vpfe_cfg = pdev->dev.platform_data;
+	num_subdevs = vpfe_cfg->num_subdevs;
+	vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
+				GFP_KERNEL);
+	if (NULL == vpfe_dev->sd) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"unable to allocate memory for subdevice pointers\n");
+		ret = -ENOMEM;
+		goto probe_out_video_unregister;
+	}
+
+	for (i = 0; i < num_subdevs; i++) {
+		struct vpfe_subdev_info *sub_dev = &vpfe_cfg->sub_devs[i];
+		struct v4l2_input *inps;
+
+		list_for_each_entry(client, &i2c_adap->clients, list) {
+			if (!strcmp(client->name, sub_dev->name))
+				break;
+		}
+
+		if (NULL == client) {
+			v4l2_err(&vpfe_dev->v4l2_dev, "No Subdevice found\n");
+			ret =  -ENODEV;
+			goto probe_sd_out;
+		}
+
+		/* Get subdevice data from the client */
+		vpfe_dev->sd[i] = i2c_get_clientdata(client);
+		sub_dev->pdata = client->dev.platform_data;
+		if (NULL == vpfe_dev->sd[i] || NULL == sub_dev->pdata) {
+			v4l2_err(&vpfe_dev->v4l2_dev,
+				"No Subdevice or platform client data\n");
+			ret =  -ENODEV;
+			goto probe_sd_out;
+		}
+
+		vpfe_dev->sd[i]->grp_id = sub_dev->grp_id;
+		ret = v4l2_device_register_subdev(&vpfe_dev->v4l2_dev,
+						  vpfe_dev->sd[i]);
+		if (ret) {
+			ret =  -ENODEV;
+			v4l2_err(&vpfe_dev->v4l2_dev,
+				"Error registering v4l2 sub-device\n");
+			goto probe_sd_out;
+		}
+		v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 sub device %s"
+			  " registered\n", client->name);
+
+		/* update tvnorms from the sub devices */
+		for (j = 0; j < sub_dev->num_inputs; j++) {
+			inps = &sub_dev->inputs[j];
+			vfd->tvnorms |= inps->std;
+		}
+	}
+	/* We have at least one sub device to work with */
+	vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0];
+	mutex_unlock(&ccdc_lock);
+	return 0;
+
+probe_sd_out:
+	for (j = i; j >= 0; j--)
+		v4l2_device_unregister_subdev(vpfe_dev->sd[j]);
+	kfree(vpfe_dev->sd);
+probe_out_video_unregister:
+	video_unregister_device(vpfe_dev->video_dev);
+probe_out_v4l2_unregister:
+	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
+probe_out_video_release:
+	video_device_release(vpfe_dev->video_dev);
+probe_out_release_irq:
+	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+probe_out_unmap1:
+	iounmap(ccdc_cfg->ccdc_addr);
+probe_out_release_mem1:
+	release_mem_region(res1->start, res1->end - res1->start + 1);
+probe_disable_clock:
+	vpfe_disable_clock(vpfe_dev);
+	mutex_unlock(&ccdc_lock);
+	kfree(ccdc_cfg);
+probe_free_dev_mem:
+	kfree(vpfe_dev);
+	return ret;
+}
+
+/*
+ * vpfe_remove : It un-register device from V4L2 driver
+ */
+static int vpfe_remove(struct platform_device *pdev)
+{
+	struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
+	struct resource *res;
+	int j;
+
+	v4l2_info(pdev->dev.driver, "vpfe_remove\n");
+
+	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+	/* Unregister video device */
+	for (j = 0; j < vpfe_dev->cfg->num_subdevs; j++)
+		v4l2_device_unregister_subdev(vpfe_dev->sd[j]);
+	kfree(vpfe_dev->sd);
+	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
+	video_unregister_device(vpfe_dev->video_dev);
+	mutex_lock(&ccdc_lock);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+	iounmap(ccdc_cfg->ccdc_addr);
+	mutex_unlock(&ccdc_lock);
+	vpfe_disable_clock(vpfe_dev);
+	kfree(vpfe_dev);
+	kfree(ccdc_cfg);
+	return 0;
+}
+
+static int
+vpfe_suspend(struct platform_device *dev, pm_message_t state)
+{
+	/* add suspend code here later */
+	return -1;
+}
+
+static int
+vpfe_resume(struct platform_device *dev)
+{
+	/* add resume code here later */
+	return -1;
+}
+
+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)
+{
+	printk(KERN_NOTICE "vpfe_init\n");
+	/* Register driver to the kernel */
+	return platform_driver_register(&vpfe_driver);
+}
+
+/*
+ * vpfe_cleanup : This function un-registers device driver
+ */
+static void vpfe_cleanup(void)
+{
+	platform_driver_unregister(&vpfe_driver);
+}
+
+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/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h
new file mode 100644
index 0000000..c08dc92
--- /dev/null
+++ b/include/media/davinci/vpfe_capture.h
@@ -0,0 +1,183 @@
+/*
+ * 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 <media/v4l2-dev.h>
+#include <linux/videodev2.h>
+#include <linux/clk.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf-dma-contig.h>
+#include <media/davinci/vpfe_types.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 CAPTURE_DRV_NAME		"vpfe-capture"
+
+struct vpfe_pixel_format {
+	struct v4l2_fmtdesc fmtdesc;
+	/* bytes per pixel */
+	int bpp;
+};
+
+struct vpfe_std_info {
+	int active_pixels;
+	int active_lines;
+	/* current frame format */
+	int frame_format;
+};
+
+struct vpfe_subdev_info {
+	/* Sub device name */
+	char name[32];
+	/* Sub device group id */
+	int grp_id;
+	/* Number of inputs supported */
+	int num_inputs;
+	/* inputs available at the sub device */
+	struct v4l2_input *inputs;
+	/* Sub dev routing information for each input */
+	struct v4l2_routing *routes;
+	/* check if sub dev supports routing */
+	int can_route;
+	/* sub device private data */
+	void *pdata;
+};
+
+struct vpfe_config {
+	/* Number of sub devices connected to vpfe */
+	int num_subdevs;
+	/* information about each subdev */
+	struct vpfe_subdev_info *sub_devs;
+	/* evm card info */
+	char *card_name;
+	/* ccdc name */
+	char *ccdc;
+	/* vpfe clock */
+	struct clk *vpssclk;
+	struct clk *slaveclk;
+};
+
+struct vpfe_device {
+	/* V4l2 specific parameters */
+	/* Identifies video device for this channel */
+	struct video_device *video_dev;
+	/* sub devices */
+	struct v4l2_subdev **sd;
+	/* vpfe cfg */
+	struct vpfe_config *cfg;
+	/* V4l2 device */
+	struct v4l2_device v4l2_dev;
+	/* parent device */
+	struct device *pdev;
+	/* 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;
+	/* current interface type */
+	struct vpfe_hw_if_param vpfe_if_params;
+	/* ptr to currently selected sub device */
+	struct vpfe_subdev_info *current_subdev;
+	/* current input at the sub device */
+	int current_input;
+	/* Keeps track of the information about the standard */
+	struct vpfe_std_info std_info;
+	/* std index into std table */
+	int std_index;
+	/* CCDC IRQs used when CCDC/ISIF output to SDRAM */
+	unsigned int ccdc_irq0;
+	unsigned int ccdc_irq1;
+	/* number of buffers in fbuffers */
+	u32 numbuffers;
+	/* List of buffer pointers for storing frames */
+	u8 *fbuffers[VIDEO_MAX_FRAME];
+	/* Pointer pointing to current v4l2_buffer */
+	struct videobuf_buffer *cur_frm;
+	/* Pointer pointing to next v4l2_buffer */
+	struct videobuf_buffer *next_frm;
+	/*
+	 * 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;
+	/*
+	 * used when IMP is chained to store the crop window which
+	 * is different from the image window
+	 */
+	struct v4l2_rect crop;
+	/* 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;
+	/* IRQ lock for DMA queue */
+	spinlock_t dma_queue_lock;
+	/* 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;
+};
+
+/* File handle structure */
+struct vpfe_fh {
+	struct vpfe_device *vpfe_dev;
+	/* Indicates whether this file handle is doing IO */
+	u8 io_allowed;
+	/* Used to keep track priority of this instance */
+	enum v4l2_priority prio;
+};
+
+struct vpfe_config_params {
+	u8 min_numbuffers;
+	u8 numbuffers;
+	u32 min_bufsize;
+	u32 device_bufsize;
+};
+
+#endif				/* End of __KERNEL__ */
+/* IOCTLs */
+#define VPFE_CMD_S_CCDC_RAW_PARAMS _IOW('V', BASE_VIDIOC_PRIVATE + 1, \
+					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..76fb74b
--- /dev/null
+++ b/include/media/davinci/vpfe_types.h
@@ -0,0 +1,51 @@
+/*
+ * 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_pin_pol {
+	VPFE_PINPOL_POSITIVE,
+	VPFE_PINPOL_NEGATIVE
+};
+
+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
+};
+
+/* interface description */
+struct vpfe_hw_if_param {
+	enum vpfe_hw_if_type if_type;
+	enum vpfe_pin_pol hdpol;
+	enum vpfe_pin_pol vdpol;
+};
+
+#endif
+#endif
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 2/10 - v2] ccdc hw device header file for vpfe capture
  2009-06-11 17:00 ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 m-karicheri2
@ 2009-06-11 17:00   ` m-karicheri2
  2009-06-11 17:00     ` [PATCH 3/10 - v2] dm355 ccdc module for vpfe capture driver m-karicheri2
  2009-06-11 22:41   ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 Alexey Klimov
  2009-06-14 14:10   ` Hans Verkuil
  2 siblings, 1 reply; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

CCDC hw device header file

Adds ccdc hw device header for vpfe capture driver

Incorporated review comments against previous patch

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 drivers/media/video/davinci/ccdc_hw_device.h |  110 ++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/ccdc_hw_device.h

diff --git a/drivers/media/video/davinci/ccdc_hw_device.h b/drivers/media/video/davinci/ccdc_hw_device.h
new file mode 100644
index 0000000..86b9b35
--- /dev/null
+++ b/drivers/media/video/davinci/ccdc_hw_device.h
@@ -0,0 +1,110 @@
+/*
+ * 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
+ *
+ * ccdc device API
+ */
+#ifndef _CCDC_HW_DEVICE_H
+#define _CCDC_HW_DEVICE_H
+
+#ifdef __KERNEL__
+#include <linux/videodev2.h>
+#include <linux/device.h>
+#include <media/davinci/vpfe_types.h>
+#include <media/davinci/ccdc_types.h>
+
+/*
+ * ccdc hw operations
+ */
+struct ccdc_hw_ops {
+	/* Pointer to initialize function to initialize ccdc device */
+	int (*open) (struct device *dev);
+	/* Pointer to deinitialize function */
+	int (*close) (struct device *dev);
+	/* set ccdc base address */
+	void (*set_ccdc_base)(void *base, int size);
+	/* Pointer to function to enable or disable ccdc */
+	void (*enable) (int en);
+	/* reset sbl. only for 6446 */
+	void (*reset) (void);
+	/* enable output to sdram */
+	void (*enable_out_to_sdram) (int en);
+	/* Pointer to function to set hw parameters */
+	int (*set_hw_if_params) (struct vpfe_hw_if_param *param);
+	/* get interface parameters */
+	int (*get_hw_if_params) (struct vpfe_hw_if_param *param);
+	/*
+	 * Pointer to function to set parameters. Used
+	 * for implementing VPFE_S_CCDC_PARAMS
+	 */
+	int (*set_params) (void *params);
+	/*
+	 * Pointer to function to get parameter. Used
+	 * for implementing VPFE_G_CCDC_PARAMS
+	 */
+	int (*get_params) (void *params);
+	/* Pointer to function to configure ccdc */
+	int (*configure) (void);
+
+	/* Pointer to function to set buffer type */
+	int (*set_buftype) (enum ccdc_buftype buf_type);
+	/* Pointer to function to get buffer type */
+	enum ccdc_buftype (*get_buftype) (void);
+	/* Pointer to function to set frame format */
+	int (*set_frame_format) (enum ccdc_frmfmt frm_fmt);
+	/* Pointer to function to get frame format */
+	enum ccdc_frmfmt (*get_frame_format) (void);
+	/* enumerate hw pix formats */
+	int (*enum_pix)(u32 *hw_pix, int i);
+	/* Pointer to function to set buffer type */
+	u32 (*get_pixel_format) (void);
+	/* Pointer to function to get pixel format. */
+	int (*set_pixel_format) (u32 pixfmt);
+	/* Pointer to function to set image window */
+	int (*set_image_window) (struct v4l2_rect *win);
+	/* Pointer to function to set image window */
+	void (*get_image_window) (struct v4l2_rect *win);
+	/* Pointer to function to get line length */
+	unsigned int (*get_line_length) (void);
+
+	/* Query CCDC control IDs */
+	int (*queryctrl)(struct v4l2_queryctrl *qctrl);
+	/* Set CCDC control */
+	int (*set_control)(struct v4l2_control *ctrl);
+	/* Get CCDC control */
+	int (*get_control)(struct v4l2_control *ctrl);
+
+	/* Pointer to function to set frame buffer address */
+	void (*setfbaddr) (unsigned long addr);
+	/* Pointer to function to get field id */
+	int (*getfid) (void);
+};
+
+struct ccdc_hw_device {
+	/* ccdc device name */
+	char name[32];
+	/* module owner */
+	struct module *owner;
+	/* hw ops */
+	struct ccdc_hw_ops hw_ops;
+};
+
+/* Used by CCDC module to register & unregister with vpfe capture driver */
+int vpfe_register_ccdc_device(struct ccdc_hw_device *dev);
+void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev);
+
+#endif
+#endif
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 3/10 - v2] dm355 ccdc module for vpfe capture driver
  2009-06-11 17:00   ` [PATCH 2/10 - v2] ccdc hw device header file for vpfe capture m-karicheri2
@ 2009-06-11 17:00     ` m-karicheri2
  2009-06-11 17:00       ` [PATCH 4/10 - v2] dm644x " m-karicheri2
  0 siblings, 1 reply; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

DM355 CCDC hw module

Adds ccdc hw module for DM355 CCDC. This registers with the bridge
driver a set of hw_ops for configuring the CCDC for a specific
decoder device connected to vpfe.

Following are some of the major comments addressed :-
	1) removed vpss configration from this module to a standalone
	   vpss module that can be used by other video drivers as well
	2) replaced magic numbers with #defines
	3) cleaned up and refractored ccdc_config_raw()
	4) embedded config part of the variables inside
	   ccdc_params_raw to help in memcpy.
	5) avoided generic names for ccdc types in include file by
	   prefixing with  ccdc_

Reviewed By "Hans Verkuil". 
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 drivers/media/video/davinci/dm355_ccdc.c      | 1161 +++++++++++++++++++++++++
 drivers/media/video/davinci/dm355_ccdc_regs.h |  310 +++++++
 include/media/davinci/dm355_ccdc.h            |  336 +++++++
 3 files changed, 1807 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/dm355_ccdc.c
 create mode 100644 drivers/media/video/davinci/dm355_ccdc_regs.h
 create mode 100644 include/media/davinci/dm355_ccdc.h

diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c
new file mode 100644
index 0000000..1e7152e
--- /dev/null
+++ b/drivers/media/video/davinci/dm355_ccdc.c
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (C) 2005-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * CCDC hardware module for DM355
+ * ------------------------------
+ *
+ * This module is for configuring DM355 CCD controller of VPFE to capture
+ * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules
+ * such as Defect Pixel Correction, Color Space Conversion etc to
+ * pre-process the Bayer RGB data, before writing it to SDRAM. This
+ * module also allows application to configure individual
+ * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL.
+ * To do so, application include dm355_ccdc.h and vpfe_capture.h header
+ * files. The setparams() API is called by vpfe_capture driver
+ * to configure module parameters
+ *
+ * TODO: 1) Raw bayer parameter settings and bayer capture
+ * 	 2) Split module parameter structure to module specific ioctl structs
+ *	 3) add support for lense shading correction
+ *	 4) investigate if enum used for user space type definition
+ * 	    to be replaced by #defines or integer
+ */
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+#include <media/davinci/dm355_ccdc.h>
+#include <media/davinci/vpss.h>
+#include "dm355_ccdc_regs.h"
+#include "ccdc_hw_device.h"
+
+static struct device *dev;
+
+/* Object for CCDC raw mode */
+static struct ccdc_params_raw ccdc_hw_params_raw = {
+	.pix_fmt = CCDC_PIXFMT_RAW,
+	.frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
+	.win = CCDC_WIN_VGA,
+	.fid_pol = VPFE_PINPOL_POSITIVE,
+	.vd_pol = VPFE_PINPOL_POSITIVE,
+	.hd_pol = VPFE_PINPOL_POSITIVE,
+	.gain = {
+		.r_ye = 256,
+		.gb_g = 256,
+		.gr_cy = 256,
+		.b_mg = 256
+	},
+	.config_params = {
+		.datasft = 2,
+		.data_sz = CCDC_DATA_10BITS,
+		.mfilt1 = CCDC_NO_MEDIAN_FILTER1,
+		.mfilt2 = CCDC_NO_MEDIAN_FILTER2,
+		.alaw = {
+			.gama_wd = 2,
+		},
+		.blk_clamp = {
+			.sample_pixel = 1,
+			.dc_sub = 25
+		},
+		.col_pat_field0 = {
+			.olop = CCDC_GREEN_BLUE,
+			.olep = CCDC_BLUE,
+			.elop = CCDC_RED,
+			.elep = CCDC_GREEN_RED
+		},
+		.col_pat_field1 = {
+			.olop = CCDC_GREEN_BLUE,
+			.olep = CCDC_BLUE,
+			.elop = CCDC_RED,
+			.elep = CCDC_GREEN_RED
+		},
+	},
+};
+
+
+/* Object for CCDC ycbcr mode */
+static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = {
+	.win = CCDC_WIN_PAL,
+	.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
+	.frm_fmt = CCDC_FRMFMT_INTERLACED,
+	.fid_pol = VPFE_PINPOL_POSITIVE,
+	.vd_pol = VPFE_PINPOL_POSITIVE,
+	.hd_pol = VPFE_PINPOL_POSITIVE,
+	.bt656_enable = 1,
+	.pix_order = CCDC_PIXORDER_CBYCRY,
+	.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
+};
+
+static struct v4l2_queryctrl ccdc_control_info[] = {
+	{
+		.id = CCDC_CID_R_GAIN,
+		.name = "R/Ye WB Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = 2047,
+		.step = 1,
+		.default_value = 256
+	},
+	{
+		.id = CCDC_CID_GR_GAIN,
+		.name = "Gr/Cy WB Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = 2047,
+		.step = 1,
+		.default_value = 256
+	},
+	{
+		.id = CCDC_CID_GB_GAIN,
+		.name = "Gb/G WB Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = 2047,
+		.step = 1,
+		.default_value = 256
+	},
+	{
+		.id = CCDC_CID_B_GAIN,
+		.name = "B/Mg WB Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = 2047,
+		.step = 1,
+		.default_value = 256
+	},
+	{
+		.id = CCDC_CID_OFFSET,
+		.name = "Offset",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = 1023,
+		.step = 1,
+		.default_value = 0
+	}
+};
+
+static enum vpfe_hw_if_type ccdc_if_type;
+static void *__iomem ccdc_base_addr;
+static int ccdc_addr_size;
+
+/* Raw Bayer formats */
+static u32 ccdc_raw_bayer_pix_formats[] =
+		{V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
+
+/* Raw YUV formats */
+static u32 ccdc_raw_yuv_pix_formats[] =
+		{V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
+
+/* register access routines */
+static inline u32 regr(u32 offset)
+{
+	return __raw_readl(ccdc_base_addr + offset);
+}
+
+static inline void regw(u32 val, u32 offset)
+{
+	__raw_writel(val, ccdc_base_addr + offset);
+}
+
+static void ccdc_set_ccdc_base(void *addr, int size)
+{
+	ccdc_base_addr = addr;
+	ccdc_addr_size = size;
+}
+
+static void ccdc_enable(int en)
+{
+	unsigned int temp;
+	temp = regr(SYNCEN);
+	temp &= (~CCDC_SYNCEN_VDHDEN_MASK);
+	temp |= (en & CCDC_SYNCEN_VDHDEN_MASK);
+	regw(temp, SYNCEN);
+}
+
+static void ccdc_enable_output_to_sdram(int en)
+{
+	unsigned int temp;
+	temp = regr(SYNCEN);
+	temp &= (~(CCDC_SYNCEN_WEN_MASK));
+	temp |= ((en << CCDC_SYNCEN_WEN_SHIFT) & CCDC_SYNCEN_WEN_MASK);
+	regw(temp, SYNCEN);
+}
+
+static void ccdc_config_gain_offset(void)
+{
+	/* configure gain */
+	regw(ccdc_hw_params_raw.gain.r_ye, RYEGAIN);
+	regw(ccdc_hw_params_raw.gain.gr_cy, GRCYGAIN);
+	regw(ccdc_hw_params_raw.gain.gb_g, GBGGAIN);
+	regw(ccdc_hw_params_raw.gain.b_mg, BMGGAIN);
+	/* configure offset */
+	regw(ccdc_hw_params_raw.ccdc_offset, OFFSET);
+}
+
+/* Query control. Only applicable for Bayer capture */
+static int ccdc_queryctrl(struct v4l2_queryctrl *qctrl)
+{
+	struct v4l2_queryctrl *control = NULL;
+	int i, id;
+
+	dev_dbg(dev, "ccdc_queryctrl: start\n");
+
+	if (VPFE_RAW_BAYER != ccdc_if_type) {
+		dev_dbg(dev,
+		       "ccdc_queryctrl : Not doing Raw Bayer Capture\n");
+		return -EINVAL;
+	}
+
+	id = qctrl->id;
+	memset(qctrl, 0, sizeof(struct v4l2_queryctrl));
+	for (i = 0; i < ARRAY_SIZE(ccdc_control_info); i++) {
+		control = &ccdc_control_info[i];
+		if (control->id == id)
+			break;
+	}
+	if (i == ARRAY_SIZE(ccdc_control_info)) {
+		dev_dbg(dev, "ccdc_queryctrl : Invalid control ID\n");
+		return -EINVAL;
+	}
+	memcpy(qctrl, control, sizeof(*qctrl));
+	dev_dbg(dev, "ccdc_queryctrl: end\n");
+	return 0;
+}
+
+static int ccdc_set_control(struct v4l2_control *ctrl)
+{
+	int i;
+	struct v4l2_queryctrl *control = NULL;
+	struct ccdc_gain *gain =
+	    &ccdc_hw_params_raw.gain;
+
+	if (ccdc_if_type != VPFE_RAW_BAYER) {
+		dev_dbg(dev,
+		       "ccdc_set_control: Not doing Raw Bayer Capture\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ccdc_control_info); i++) {
+		control = &ccdc_control_info[i];
+		if (control->id == ctrl->id)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(ccdc_control_info)) {
+		dev_dbg(dev, "ccdc_queryctrl : Invalid control ID, 0x%x\n",
+		       control->id);
+		return -EINVAL;
+	}
+
+	if (ctrl->value > control->maximum ||
+	    ctrl->value < control->minimum) {
+		dev_dbg(dev, "ccdc_queryctrl : Invalid control value\n");
+		return -EINVAL;
+	}
+
+	switch (ctrl->id) {
+	case CCDC_CID_R_GAIN:
+		gain->r_ye = ctrl->value & CCDC_GAIN_MASK;
+		regw(gain->r_ye, RYEGAIN);
+		break;
+	case CCDC_CID_GR_GAIN:
+		gain->gr_cy = ctrl->value & CCDC_GAIN_MASK;
+		regw(gain->gr_cy, GRCYGAIN);
+		break;
+	case CCDC_CID_GB_GAIN:
+		gain->gb_g = ctrl->value  & CCDC_GAIN_MASK;
+		regw(gain->gb_g, GBGGAIN);
+		break;
+	case CCDC_CID_B_GAIN:
+		gain->b_mg = ctrl->value  & CCDC_GAIN_MASK;
+		regw(gain->b_mg, BMGGAIN);
+		break;
+	default:
+		/*
+		 * Since we validate the control ids earlier, the default
+		 * will be offset
+		 */
+		ccdc_hw_params_raw.ccdc_offset = ctrl->value & CCDC_OFFSET_MASK;
+		regw(ccdc_hw_params_raw.ccdc_offset, OFFSET);
+	}
+	return 0;
+}
+
+static int ccdc_get_control(struct v4l2_control *ctrl)
+{
+	int i;
+	struct v4l2_queryctrl *control = NULL;
+
+	if (ccdc_if_type != VPFE_RAW_BAYER) {
+		dev_dbg(dev,
+		       "ccdc_get_control: Not doing Raw Bayer Capture\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ccdc_control_info); i++) {
+		control = &ccdc_control_info[i];
+		if (control->id == ctrl->id)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(ccdc_control_info)) {
+		dev_dbg(dev, "ccdc_get_control: Invalid control ID\n");
+		return -EINVAL;
+	}
+
+	switch (ctrl->id) {
+	case CCDC_CID_R_GAIN:
+		ctrl->value = ccdc_hw_params_raw.gain.r_ye;
+		break;
+	case CCDC_CID_GR_GAIN:
+		ctrl->value = ccdc_hw_params_raw.gain.gr_cy;
+		break;
+	case CCDC_CID_GB_GAIN:
+		ctrl->value = ccdc_hw_params_raw.gain.gb_g;
+		break;
+	case CCDC_CID_B_GAIN:
+		ctrl->value = ccdc_hw_params_raw.gain.b_mg;
+		break;
+	default:
+		/*
+		 * Since we validate the control ids earlier, the default
+		 * will be offset
+		 */
+		ctrl->value = ccdc_hw_params_raw.ccdc_offset;
+	}
+	return 0;
+}
+
+/*
+ * ccdc_restore_defaults()
+ * This function restore power on defaults in the ccdc registers
+ */
+static int ccdc_restore_defaults(void)
+{
+	int i;
+
+	dev_dbg(dev, "\nstarting ccdc_restore_defaults...");
+	/* set all registers to zero */
+	for (i = 0; i <= CCDC_REG_LAST; i += 4)
+		regw(0, i);
+
+	/* now override the values with power on defaults in registers */
+	regw(MODESET_DEFAULT, MODESET);
+	/* no culling support */
+	regw(CULH_DEFAULT, CULH);
+	regw(CULV_DEFAULT, CULV);
+	/* Set default Gain and Offset */
+	ccdc_hw_params_raw.gain.r_ye = GAIN_DEFAULT;
+	ccdc_hw_params_raw.gain.gb_g = GAIN_DEFAULT;
+	ccdc_hw_params_raw.gain.gr_cy = GAIN_DEFAULT;
+	ccdc_hw_params_raw.gain.b_mg = GAIN_DEFAULT;
+	ccdc_config_gain_offset();
+	regw(OUTCLIP_DEFAULT, OUTCLIP);
+	regw(LSCCFG2_DEFAULT, LSCCFG2);
+	/* select ccdc input */
+	if (vpss_select_ccdc_source(VPSS_CCDCIN)) {
+		dev_dbg(dev, "\ncouldn't select ccdc input source");
+		return -EFAULT;
+	}
+	/* select ccdc clock */
+	if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) {
+		dev_dbg(dev, "\ncouldn't enable ccdc clock");
+		return -EFAULT;
+	}
+	dev_dbg(dev, "\nEnd of ccdc_restore_defaults...");
+	return 0;
+}
+
+static int ccdc_open(struct device *device)
+{
+	dev = device;
+	return ccdc_restore_defaults();
+}
+
+static int ccdc_close(struct device *device)
+{
+	/* disable clock */
+	vpss_enable_clock(VPSS_CCDC_CLOCK, 0);
+	/* do nothing for now */
+	return 0;
+}
+/*
+ * ccdc_setwin()
+ * This function will configure the window size to
+ * be capture in CCDC reg.
+ */
+static void ccdc_setwin(struct v4l2_rect *image_win,
+			enum ccdc_frmfmt frm_fmt, int ppc)
+{
+	int horz_start, horz_nr_pixels;
+	int vert_start, vert_nr_lines;
+	int mid_img = 0;
+
+	dev_dbg(dev, "\nStarting ccdc_setwin...");
+
+	/*
+	 * ppc - per pixel count. indicates how many pixels per cell
+	 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
+	 * raw capture this is 1
+	 */
+	horz_start = image_win->left << (ppc - 1);
+	horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1;
+
+	/* Writing the horizontal info into the registers */
+	regw(horz_start, SPH);
+	regw(horz_nr_pixels, NPH);
+	vert_start = image_win->top;
+
+	if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		vert_nr_lines = (image_win->height >> 1) - 1;
+		vert_start >>= 1;
+		/* Since first line doesn't have any data */
+		vert_start += 1;
+		/* configure VDINT0 and VDINT1 */
+		regw(vert_start, VDINT0);
+	} else {
+		/* Since first line doesn't have any data */
+		vert_start += 1;
+		vert_nr_lines = image_win->height - 1;
+		/* configure VDINT0 and VDINT1 */
+		mid_img = vert_start + (image_win->height / 2);
+		regw(vert_start, VDINT0);
+		regw(mid_img, VDINT1);
+	}
+	regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0);
+	regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1);
+	regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV);
+	dev_dbg(dev, "\nEnd of ccdc_setwin...");
+}
+
+static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
+{
+	if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT ||
+	    ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) {
+		dev_dbg(dev, "Invalid value of data shift\n");
+		return -EINVAL;
+	}
+
+	if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 ||
+	    ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) {
+		dev_dbg(dev, "Invalid value of median filter1\n");
+		return -EINVAL;
+	}
+
+	if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 ||
+	    ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) {
+		dev_dbg(dev, "Invalid value of median filter2\n");
+		return -EINVAL;
+	}
+
+	if ((ccdcparam->med_filt_thres < 0) ||
+	   (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) {
+		dev_dbg(dev, "Invalid value of median filter thresold\n");
+		return -EINVAL;
+	}
+
+	if (ccdcparam->data_sz < CCDC_DATA_16BITS ||
+	    ccdcparam->data_sz > CCDC_DATA_8BITS) {
+		dev_dbg(dev, "Invalid value of data size\n");
+		return -EINVAL;
+	}
+
+	if (ccdcparam->alaw.enable) {
+		if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 ||
+		    ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) {
+			dev_dbg(dev, "Invalid value of ALAW\n");
+			return -EINVAL;
+		}
+	}
+
+	if (ccdcparam->blk_clamp.b_clamp_enable) {
+		if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS ||
+		    ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) {
+			dev_dbg(dev, "Invalid value of sample pixel\n");
+			return -EINVAL;
+		}
+		if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES ||
+		    ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) {
+			dev_dbg(dev, "Invalid value of sample lines\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+/* Parameter operations */
+static int ccdc_set_params(void __user *params)
+{
+	struct ccdc_config_params_raw ccdc_raw_params;
+	int x;
+
+	/* only raw module parameters can be set through the IOCTL */
+	if (ccdc_if_type != VPFE_RAW_BAYER)
+		return -EINVAL;
+
+	x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
+	if (x) {
+		dev_dbg(dev, "ccdc_set_params: error in copying ccdc"
+			"params, %d\n", x);
+		return -EFAULT;
+	}
+
+	if (!validate_ccdc_param(&ccdc_raw_params)) {
+		memcpy(&ccdc_hw_params_raw.config_params,
+			&ccdc_raw_params,
+			sizeof(ccdc_raw_params));
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/* This function will configure CCDC for YCbCr video capture */
+static void ccdc_config_ycbcr(void)
+{
+	struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr;
+	u32 temp;
+
+	/* first set the CCDC power on defaults values in all registers */
+	dev_dbg(dev, "\nStarting ccdc_config_ycbcr...");
+	ccdc_restore_defaults();
+
+	/* configure pixel format & video frame format */
+	temp = (((params->pix_fmt & CCDC_INPUT_MODE_MASK) <<
+		CCDC_INPUT_MODE_SHIFT) |
+		((params->frm_fmt & CCDC_FRM_FMT_MASK) <<
+		CCDC_FRM_FMT_SHIFT));
+
+	/* setup BT.656 sync mode */
+	if (params->bt656_enable) {
+		regw(CCDC_REC656IF_BT656_EN, REC656IF);
+		/*
+		 * configure the FID, VD, HD pin polarity fld,hd pol positive,
+		 * vd negative, 8-bit pack mode
+		 */
+		temp |= CCDC_VD_POL_NEGATIVE;
+	} else {		/* y/c external sync mode */
+		temp |= (((params->fid_pol & CCDC_FID_POL_MASK) <<
+			CCDC_FID_POL_SHIFT) |
+			((params->hd_pol & CCDC_HD_POL_MASK) <<
+			CCDC_HD_POL_SHIFT) |
+			((params->vd_pol & CCDC_VD_POL_MASK) <<
+			CCDC_VD_POL_SHIFT));
+	}
+
+	/* pack the data to 8-bit */
+	temp |= CCDC_DATA_PACK_ENABLE;
+
+	regw(temp, MODESET);
+
+	/* configure video window */
+	ccdc_setwin(&params->win, params->frm_fmt, 2);
+
+	/* configure the order of y cb cr in SD-RAM */
+	temp = (params->pix_order << CCDC_Y8POS_SHIFT);
+	temp |= CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC;
+	regw(temp, CCDCFG);
+
+	/*
+	 * configure the horizontal line offset. This is done by rounding up
+	 * width to a multiple of 16 pixels and multiply by two to account for
+	 * y:cb:cr 4:2:2 data
+	 */
+	regw(((params->win.width * 2 + 31) >> 5), HSIZE);
+
+	/* configure the memory line offset */
+	if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
+		/* two fields are interleaved in memory */
+		regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST);
+	}
+
+	dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n");
+}
+
+/*
+ * ccdc_config_black_clamp()
+ * configure parameters for Optical Black Clamp
+ */
+static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp)
+{
+	u32 val;
+
+	if (!bclamp->b_clamp_enable) {
+		/* configure DCSub */
+		regw(bclamp->dc_sub & CCDC_BLK_DC_SUB_MASK, DCSUB);
+		regw(0x0000, CLAMP);
+		return;
+	}
+	/* Enable the Black clamping, set sample lines and pixels */
+	val = (bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) |
+	      ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) <<
+		CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE;
+	regw(val, CLAMP);
+
+	/* If Black clamping is enable then make dcsub 0 */
+	val = (bclamp->sample_ln & CCDC_NUM_LINE_CALC_MASK)
+			<< CCDC_NUM_LINE_CALC_SHIFT;
+	regw(val, DCSUB);
+}
+
+/*
+ * ccdc_config_black_compense()
+ * configure parameters for Black Compensation
+ */
+static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp)
+{
+	u32 val;
+
+	val = (bcomp->b & CCDC_BLK_COMP_MASK) |
+		((bcomp->gb & CCDC_BLK_COMP_MASK) <<
+		CCDC_BLK_COMP_GB_COMP_SHIFT);
+	regw(val, BLKCMP1);
+
+	val = ((bcomp->gr & CCDC_BLK_COMP_MASK) <<
+		CCDC_BLK_COMP_GR_COMP_SHIFT) |
+		((bcomp->r & CCDC_BLK_COMP_MASK) <<
+		CCDC_BLK_COMP_R_COMP_SHIFT);
+	regw(val, BLKCMP0);
+}
+
+/*
+ * ccdc_write_dfc_entry()
+ * write an entry in the dfc table.
+ */
+int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc)
+{
+/* TODO This is to be re-visited and adjusted */
+#define DFC_WRITE_WAIT_COUNT	1000
+	u32 val, count = DFC_WRITE_WAIT_COUNT;
+
+	regw(dfc->dft_corr_vert[index], DFCMEM0);
+	regw(dfc->dft_corr_horz[index], DFCMEM1);
+	regw(dfc->dft_corr_sub1[index], DFCMEM2);
+	regw(dfc->dft_corr_sub2[index], DFCMEM3);
+	regw(dfc->dft_corr_sub3[index], DFCMEM4);
+	/* set WR bit to write */
+	val = regr(DFCMEMCTL) | CCDC_DFCMEMCTL_DFCMWR_MASK;
+	regw(val, DFCMEMCTL);
+
+	/*
+	 * Assume, it is very short. If we get an error, we need to
+	 * adjust this value
+	 */
+	while (regr(DFCMEMCTL) & CCDC_DFCMEMCTL_DFCMWR_MASK)
+		count--;
+	/*
+	 * TODO We expect the count to be non-zero to be successful. Adjust
+	 * the count if write requires more time
+	 */
+
+	if (count) {
+		dev_err(dev, "defect table write timeout !!!\n");
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * ccdc_config_vdfc()
+ * configure parameters for Vertical Defect Correction
+ */
+static int ccdc_config_vdfc(struct ccdc_vertical_dft *dfc)
+{
+	u32 val;
+	int i;
+
+	/* Configure General Defect Correction. The table used is from IPIPE */
+	val = dfc->gen_dft_en & CCDC_DFCCTL_GDFCEN_MASK;
+
+	/* Configure Vertical Defect Correction if needed */
+	if (!dfc->ver_dft_en) {
+		/* Enable only General Defect Correction */
+		regw(val, DFCCTL);
+		return 0;
+	}
+
+	if (dfc->table_size > CCDC_DFT_TABLE_SIZE)
+		return -EINVAL;
+
+	val |= CCDC_DFCCTL_VDFC_DISABLE;
+	val |= (dfc->dft_corr_ctl.vdfcsl & CCDC_DFCCTL_VDFCSL_MASK) <<
+		CCDC_DFCCTL_VDFCSL_SHIFT;
+	val |= (dfc->dft_corr_ctl.vdfcuda & CCDC_DFCCTL_VDFCUDA_MASK) <<
+		CCDC_DFCCTL_VDFCUDA_SHIFT;
+	val |= (dfc->dft_corr_ctl.vdflsft & CCDC_DFCCTL_VDFLSFT_MASK) <<
+		CCDC_DFCCTL_VDFLSFT_SHIFT;
+	regw(val , DFCCTL);
+
+	/* clear address ptr to offset 0 */
+	val = CCDC_DFCMEMCTL_DFCMARST_MASK << CCDC_DFCMEMCTL_DFCMARST_SHIFT;
+
+	/* write defect table entries */
+	for (i = 0; i < dfc->table_size; i++) {
+		/* increment address for non zero index */
+		if (i != 0)
+			val = CCDC_DFCMEMCTL_INC_ADDR;
+		regw(val, DFCMEMCTL);
+		if (ccdc_write_dfc_entry(i, dfc) < 0)
+			return -EFAULT;
+	}
+
+	/* update saturation level and enable dfc */
+	regw(dfc->saturation_ctl & CCDC_VDC_DFCVSAT_MASK, DFCVSAT);
+	val = regr(DFCCTL) | (CCDC_DFCCTL_VDFCEN_MASK <<
+			CCDC_DFCCTL_VDFCEN_SHIFT);
+	regw(val, DFCCTL);
+	return 0;
+}
+
+/*
+ * ccdc_config_csc()
+ * configure parameters for color space conversion
+ * Each register CSCM0-7 has two values in S8Q5 format.
+ */
+static void ccdc_config_csc(struct ccdc_csc *csc)
+{
+	u32 val1, val2;
+	int i;
+
+	if (!csc->enable)
+		return;
+
+	/* Enable the CSC sub-module */
+	regw(CCDC_CSC_ENABLE, CSCCTL);
+
+	/* Converting the co-eff as per the format of the register */
+	for (i = 0; i < CCDC_CSC_COEFF_TABLE_SIZE; i++) {
+		if ((i % 2) == 0) {
+			/* CSCM - LSB */
+			val1 = (csc->coeff[i].integer &
+				CCDC_CSC_COEF_INTEG_MASK)
+				<< CCDC_CSC_COEF_INTEG_SHIFT;
+			/*
+			 * convert decimal part to binary. Use 2 decimal
+			 * precision, user values range from .00 - 0.99
+			 */
+			val1 |= (((csc->coeff[i].decimal &
+				CCDC_CSC_COEF_DECIMAL_MASK) *
+				CCDC_CSC_DEC_MAX) / 100);
+		} else {
+
+			/* CSCM - MSB */
+			val2 = (csc->coeff[i].integer &
+				CCDC_CSC_COEF_INTEG_MASK)
+				<< CCDC_CSC_COEF_INTEG_SHIFT;
+			val2 |= (((csc->coeff[i].decimal &
+				 CCDC_CSC_COEF_DECIMAL_MASK) *
+				 CCDC_CSC_DEC_MAX) / 100);
+			val2 <<= CCDC_CSCM_MSB_SHIFT;
+			val2 |= val1;
+			regw(val2, (CSCM0 + ((i - 1) << 1)));
+		}
+	}
+}
+
+/*
+ * ccdc_config_color_patterns()
+ * configure parameters for color patterns
+ */
+static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0,
+				       struct ccdc_col_pat *pat1)
+{
+	u32 val;
+
+	val = (pat0->olop | (pat0->olep << 2) | (pat0->elop << 4) |
+		(pat0->elep << 6) | (pat1->olop << 8) | (pat1->olep << 10) |
+		(pat1->elop << 12) | (pat1->elep << 14));
+	regw(val, COLPTN);
+}
+
+/* This function will configure CCDC for Raw mode image capture */
+static int ccdc_config_raw(void)
+{
+	struct ccdc_params_raw *params = &ccdc_hw_params_raw;
+	struct ccdc_config_params_raw *config_params =
+		&ccdc_hw_params_raw.config_params;
+	unsigned int val;
+
+	dev_dbg(dev, "\nStarting ccdc_config_raw...");
+
+	/* restore power on defaults to register */
+	ccdc_restore_defaults();
+
+	/* CCDCFG register:
+	 * set CCD Not to swap input since input is RAW data
+	 * set FID detection function to Latch at V-Sync
+	 * set WENLOG - ccdc valid area to AND
+	 * set TRGSEL to WENBIT
+	 * set EXTRG to DISABLE
+	 * disable latching function on VSYNC - shadowed registers
+	 */
+	regw(CCDC_YCINSWP_RAW | CCDC_CCDCFG_FIDMD_LATCH_VSYNC |
+	     CCDC_CCDCFG_WENLOG_AND | CCDC_CCDCFG_TRGSEL_WEN |
+	     CCDC_CCDCFG_EXTRG_DISABLE | CCDC_LATCH_ON_VSYNC_DISABLE, CCDCFG);
+
+	/*
+	 * Set VDHD direction to input,  input type to raw input
+	 * normal data polarity, do not use external WEN
+	 */
+	val = (CCDC_VDHDOUT_INPUT | CCDC_RAW_IP_MODE | CCDC_DATAPOL_NORMAL |
+		CCDC_EXWEN_DISABLE);
+
+	/*
+	 * Configure the vertical sync polarity (MODESET.VDPOL), horizontal
+	 * sync polarity (MODESET.HDPOL), field id polarity (MODESET.FLDPOL),
+	 * frame format(progressive or interlace), & pixel format (Input mode)
+	 */
+	val |= (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
+		((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
+		((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
+		((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
+		((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT));
+
+	/* set pack for alaw compression */
+	if ((config_params->data_sz == CCDC_DATA_8BITS) ||
+	     config_params->alaw.enable)
+		val |= CCDC_DATA_PACK_ENABLE;
+
+	/* Configure for LPF */
+	if (config_params->lpf_enable)
+		val |= (config_params->lpf_enable & CCDC_LPF_MASK) <<
+			CCDC_LPF_SHIFT;
+
+	/* Configure the data shift */
+	val |= (config_params->datasft & CCDC_DATASFT_MASK) <<
+		CCDC_DATASFT_SHIFT;
+	regw(val , MODESET);
+	dev_dbg(dev, "\nWriting 0x%x to MODESET...\n", val);
+
+	/* Configure the Median Filter threshold */
+	regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT);
+
+	/* Configure GAMMAWD register. defaur 11-2, and Mosaic cfa pattern */
+	val = CCDC_GAMMA_BITS_11_2 << CCDC_GAMMAWD_INPUT_SHIFT |
+		CCDC_CFA_MOSAIC;
+
+	/* Enable and configure aLaw register if needed */
+	if (config_params->alaw.enable) {
+		val |= (CCDC_ALAW_ENABLE |
+			((config_params->alaw.gama_wd &
+			CCDC_ALAW_GAMA_WD_MASK) <<
+			CCDC_GAMMAWD_INPUT_SHIFT));
+	}
+
+	/* Configure Median filter1 & filter2 */
+	val |= ((config_params->mfilt1 << CCDC_MFILT1_SHIFT) |
+		(config_params->mfilt2 << CCDC_MFILT2_SHIFT));
+
+	regw(val, GAMMAWD);
+	dev_dbg(dev, "\nWriting 0x%x to GAMMAWD...\n", val);
+
+	/* configure video window */
+	ccdc_setwin(&params->win, params->frm_fmt, 1);
+
+	/* Optical Clamp Averaging */
+	ccdc_config_black_clamp(&config_params->blk_clamp);
+
+	/* Black level compensation */
+	ccdc_config_black_compense(&config_params->blk_comp);
+
+	/* Vertical Defect Correction if needed */
+	if (ccdc_config_vdfc(&config_params->vertical_dft) < 0)
+		return -EFAULT;
+
+	/* color space conversion */
+	ccdc_config_csc(&config_params->csc);
+
+	/* color pattern */
+	ccdc_config_color_patterns(&config_params->col_pat_field0,
+				   &config_params->col_pat_field1);
+
+	/* Configure the Gain  & offset control */
+	ccdc_config_gain_offset();
+
+	dev_dbg(dev, "\nWriting %x to COLPTN...\n", val);
+
+	/* Configure DATAOFST  register */
+	val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) <<
+		CCDC_DATAOFST_H_SHIFT;
+	val |= (config_params->data_offset.vert_offset & CCDC_DATAOFST_MASK) <<
+		CCDC_DATAOFST_V_SHIFT;
+	regw(val, DATAOFST);
+
+	/* configuring HSIZE register */
+	val = (params->horz_flip_enable & CCDC_HSIZE_FLIP_MASK) <<
+		CCDC_HSIZE_FLIP_SHIFT;
+
+	/* If pack 8 is enable then 1 pixel will take 1 byte */
+	if ((config_params->data_sz == CCDC_DATA_8BITS) ||
+	     config_params->alaw.enable) {
+		val |= (((params->win.width) + 31) >> 5) &
+			CCDC_HSIZE_VAL_MASK;
+
+		/* adjust to multiple of 32 */
+		dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n",
+		       (((params->win.width) + 31) >> 5) &
+			CCDC_HSIZE_VAL_MASK);
+	} else {
+		/* else one pixel will take 2 byte */
+		val |= (((params->win.width * 2) + 31) >> 5) &
+			CCDC_HSIZE_VAL_MASK;
+
+		dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n",
+		       (((params->win.width * 2) + 31) >> 5) &
+			CCDC_HSIZE_VAL_MASK);
+	}
+	regw(val, HSIZE);
+
+	/* Configure SDOFST register */
+	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		if (params->image_invert_enable) {
+			/* For interlace inverse mode */
+			regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST);
+			dev_dbg(dev, "\nWriting %x to SDOFST...\n",
+				CCDC_SDOFST_INTERLACE_INVERSE);
+		} else {
+			/* For interlace non inverse mode */
+			regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST);
+			dev_dbg(dev, "\nWriting %x to SDOFST...\n",
+				CCDC_SDOFST_INTERLACE_NORMAL);
+		}
+	} else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
+		if (params->image_invert_enable) {
+			/* For progessive inverse mode */
+			regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST);
+			dev_dbg(dev, "\nWriting %x to SDOFST...\n",
+				CCDC_SDOFST_PROGRESSIVE_INVERSE);
+		} else {
+			/* For progessive non inverse mode */
+			regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST);
+			dev_dbg(dev, "\nWriting %x to SDOFST...\n",
+				CCDC_SDOFST_PROGRESSIVE_NORMAL);
+		}
+	}
+	dev_dbg(dev, "\nend of ccdc_config_raw...");
+	return 0;
+}
+
+static int ccdc_configure(void)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		return ccdc_config_raw();
+	else
+		ccdc_config_ycbcr();
+	return 0;
+}
+
+static int ccdc_set_buftype(enum ccdc_buftype buf_type)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_hw_params_raw.buf_type = buf_type;
+	else
+		ccdc_hw_params_ycbcr.buf_type = buf_type;
+	return 0;
+}
+static enum ccdc_buftype ccdc_get_buftype(void)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		return ccdc_hw_params_raw.buf_type;
+	return ccdc_hw_params_ycbcr.buf_type;
+}
+
+static int ccdc_enum_pix(u32 *pix, int i)
+{
+	int ret = -EINVAL;
+	if (ccdc_if_type == VPFE_RAW_BAYER) {
+		if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
+			*pix = ccdc_raw_bayer_pix_formats[i];
+			ret = 0;
+		}
+	} else {
+		if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
+			*pix = ccdc_raw_yuv_pix_formats[i];
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
+static int ccdc_set_pixel_format(u32 pixfmt)
+{
+	struct ccdc_a_law *alaw =
+		&ccdc_hw_params_raw.config_params.alaw;
+
+	if (ccdc_if_type == VPFE_RAW_BAYER) {
+		ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW;
+		if (pixfmt == V4L2_PIX_FMT_SBGGR8)
+			alaw->enable = 1;
+		else if (pixfmt != V4L2_PIX_FMT_SBGGR16)
+			return -EINVAL;
+	} else {
+		if (pixfmt == V4L2_PIX_FMT_YUYV)
+			ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
+		else if (pixfmt == V4L2_PIX_FMT_UYVY)
+			ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		else
+			return -EINVAL;
+	}
+	return 0;
+}
+static u32 ccdc_get_pixel_format(void)
+{
+	struct ccdc_a_law *alaw =
+		&ccdc_hw_params_raw.config_params.alaw;
+	u32 pixfmt;
+
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		if (alaw->enable)
+			pixfmt = V4L2_PIX_FMT_SBGGR8;
+		else
+			pixfmt = V4L2_PIX_FMT_SBGGR16;
+	else {
+		if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
+			pixfmt = V4L2_PIX_FMT_YUYV;
+		else
+			pixfmt = V4L2_PIX_FMT_UYVY;
+	}
+	return pixfmt;
+}
+static int ccdc_set_image_window(struct v4l2_rect *win)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_hw_params_raw.win = *win;
+	else
+		ccdc_hw_params_ycbcr.win = *win;
+	return 0;
+}
+
+static void ccdc_get_image_window(struct v4l2_rect *win)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		*win = ccdc_hw_params_raw.win;
+	else
+		*win = ccdc_hw_params_ycbcr.win;
+}
+
+static unsigned int ccdc_get_line_length(void)
+{
+	struct ccdc_config_params_raw *config_params =
+		&ccdc_hw_params_raw.config_params;
+	unsigned int len;
+
+	if (ccdc_if_type == VPFE_RAW_BAYER) {
+		if ((config_params->alaw.enable) ||
+		    (config_params->data_sz == CCDC_DATA_8BITS))
+			len = ccdc_hw_params_raw.win.width;
+		else
+			len = ccdc_hw_params_raw.win.width * 2;
+	} else
+		len = ccdc_hw_params_ycbcr.win.width * 2;
+	return ALIGN(len, 32);
+}
+
+static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_hw_params_raw.frm_fmt = frm_fmt;
+	else
+		ccdc_hw_params_ycbcr.frm_fmt = frm_fmt;
+	return 0;
+}
+
+static enum ccdc_frmfmt ccdc_get_frame_format(void)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		return ccdc_hw_params_raw.frm_fmt;
+	else
+		return ccdc_hw_params_ycbcr.frm_fmt;
+}
+
+static int ccdc_getfid(void)
+{
+	return  (regr(MODESET) >> 15) & 1;
+}
+
+/* misc operations */
+static inline void ccdc_setfbaddr(unsigned long addr)
+{
+	regw((addr >> 21) & 0x007f, STADRH);
+	regw((addr >> 5) & 0x0ffff, STADRL);
+}
+
+static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
+{
+	ccdc_if_type = params->if_type;
+
+	switch (params->if_type) {
+	case VPFE_BT656:
+	case VPFE_YCBCR_SYNC_16:
+	case VPFE_YCBCR_SYNC_8:
+		ccdc_hw_params_ycbcr.vd_pol = params->vdpol;
+		ccdc_hw_params_ycbcr.hd_pol = params->hdpol;
+		break;
+	default:
+		/* TODO add support for raw bayer here */
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct ccdc_hw_device ccdc_hw_dev = {
+	.name = "DM355 CCDC",
+	.owner = THIS_MODULE,
+	.hw_ops = {
+		.open = ccdc_open,
+		.close = ccdc_close,
+		.set_ccdc_base = ccdc_set_ccdc_base,
+		.enable = ccdc_enable,
+		.enable_out_to_sdram = ccdc_enable_output_to_sdram,
+		.set_hw_if_params = ccdc_set_hw_if_params,
+		.set_params = ccdc_set_params,
+		.configure = ccdc_configure,
+		.set_buftype = ccdc_set_buftype,
+		.get_buftype = ccdc_get_buftype,
+		.enum_pix = ccdc_enum_pix,
+		.set_pixel_format = ccdc_set_pixel_format,
+		.get_pixel_format = ccdc_get_pixel_format,
+		.set_frame_format = ccdc_set_frame_format,
+		.get_frame_format = ccdc_get_frame_format,
+		.set_image_window = ccdc_set_image_window,
+		.get_image_window = ccdc_get_image_window,
+		.get_line_length = ccdc_get_line_length,
+		.queryctrl = ccdc_queryctrl,
+		.set_control = ccdc_set_control,
+		.get_control = ccdc_get_control,
+		.setfbaddr = ccdc_setfbaddr,
+		.getfid = ccdc_getfid,
+	},
+};
+
+static int dm355_ccdc_init(void)
+{
+	printk(KERN_NOTICE "dm355_ccdc_init\n");
+	if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0)
+		return -1;
+	printk(KERN_NOTICE "%s is registered with vpfe.\n",
+		ccdc_hw_dev.name);
+	return 0;
+}
+
+static void dm355_ccdc_exit(void)
+{
+	vpfe_unregister_ccdc_device(&ccdc_hw_dev);
+}
+
+module_init(dm355_ccdc_init);
+module_exit(dm355_ccdc_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/dm355_ccdc_regs.h b/drivers/media/video/davinci/dm355_ccdc_regs.h
new file mode 100644
index 0000000..d6d2ef0
--- /dev/null
+++ b/drivers/media/video/davinci/dm355_ccdc_regs.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2005-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _DM355_CCDC_REGS_H
+#define _DM355_CCDC_REGS_H
+
+/**************************************************************************\
+* Register OFFSET Definitions
+\**************************************************************************/
+#define SYNCEN				0x00
+#define MODESET				0x04
+#define HDWIDTH				0x08
+#define VDWIDTH				0x0c
+#define PPLN				0x10
+#define LPFR				0x14
+#define SPH				0x18
+#define NPH				0x1c
+#define SLV0				0x20
+#define SLV1				0x24
+#define NLV				0x28
+#define CULH				0x2c
+#define CULV				0x30
+#define HSIZE				0x34
+#define SDOFST				0x38
+#define STADRH				0x3c
+#define STADRL				0x40
+#define CLAMP				0x44
+#define DCSUB				0x48
+#define COLPTN				0x4c
+#define BLKCMP0				0x50
+#define BLKCMP1				0x54
+#define MEDFILT				0x58
+#define RYEGAIN				0x5c
+#define GRCYGAIN			0x60
+#define GBGGAIN				0x64
+#define BMGGAIN				0x68
+#define OFFSET				0x6c
+#define OUTCLIP				0x70
+#define VDINT0				0x74
+#define VDINT1				0x78
+#define RSV0				0x7c
+#define GAMMAWD				0x80
+#define REC656IF			0x84
+#define CCDCFG				0x88
+#define FMTCFG				0x8c
+#define FMTPLEN				0x90
+#define FMTSPH				0x94
+#define FMTLNH				0x98
+#define FMTSLV				0x9c
+#define FMTLNV				0xa0
+#define FMTRLEN				0xa4
+#define FMTHCNT				0xa8
+#define FMT_ADDR_PTR_B			0xac
+#define FMT_ADDR_PTR(i)			(FMT_ADDR_PTR_B + (i * 4))
+#define FMTPGM_VF0			0xcc
+#define FMTPGM_VF1			0xd0
+#define FMTPGM_AP0			0xd4
+#define FMTPGM_AP1			0xd8
+#define FMTPGM_AP2			0xdc
+#define FMTPGM_AP3                      0xe0
+#define FMTPGM_AP4                      0xe4
+#define FMTPGM_AP5                      0xe8
+#define FMTPGM_AP6                      0xec
+#define FMTPGM_AP7                      0xf0
+#define LSCCFG1                         0xf4
+#define LSCCFG2                         0xf8
+#define LSCH0                           0xfc
+#define LSCV0                           0x100
+#define LSCKH                           0x104
+#define LSCKV                           0x108
+#define LSCMEMCTL                       0x10c
+#define LSCMEMD                         0x110
+#define LSCMEMQ                         0x114
+#define DFCCTL                          0x118
+#define DFCVSAT                         0x11c
+#define DFCMEMCTL                       0x120
+#define DFCMEM0                         0x124
+#define DFCMEM1                         0x128
+#define DFCMEM2                         0x12c
+#define DFCMEM3                         0x130
+#define DFCMEM4                         0x134
+#define CSCCTL                          0x138
+#define CSCM0                           0x13c
+#define CSCM1                           0x140
+#define CSCM2                           0x144
+#define CSCM3                           0x148
+#define CSCM4                           0x14c
+#define CSCM5                           0x150
+#define CSCM6                           0x154
+#define CSCM7                           0x158
+#define DATAOFST			0x15c
+#define CCDC_REG_LAST			DATAOFST
+/**************************************************************
+*	Define for various register bit mask and shifts for CCDC
+*
+**************************************************************/
+#define CCDC_RAW_IP_MODE			0
+#define CCDC_VDHDOUT_INPUT			0
+#define CCDC_YCINSWP_RAW			(0 << 4)
+#define CCDC_EXWEN_DISABLE 			0
+#define CCDC_DATAPOL_NORMAL			0
+#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC		0
+#define CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC	(1 << 6)
+#define CCDC_CCDCFG_WENLOG_AND			0
+#define CCDC_CCDCFG_TRGSEL_WEN			0
+#define CCDC_CCDCFG_EXTRG_DISABLE		0
+#define CCDC_CFA_MOSAIC				0
+#define CCDC_Y8POS_SHIFT			11
+
+#define CCDC_VDC_DFCVSAT_MASK			0x3fff
+#define CCDC_DATAOFST_MASK			0x0ff
+#define CCDC_DATAOFST_H_SHIFT			0
+#define CCDC_DATAOFST_V_SHIFT			8
+#define CCDC_GAMMAWD_CFA_MASK			1
+#define CCDC_GAMMAWD_CFA_SHIFT			5
+#define CCDC_GAMMAWD_INPUT_SHIFT		2
+#define CCDC_FID_POL_MASK			1
+#define CCDC_FID_POL_SHIFT			4
+#define CCDC_HD_POL_MASK			1
+#define CCDC_HD_POL_SHIFT			3
+#define CCDC_VD_POL_MASK			1
+#define CCDC_VD_POL_SHIFT			2
+#define CCDC_VD_POL_NEGATIVE			(1 << 2)
+#define CCDC_FRM_FMT_MASK			1
+#define CCDC_FRM_FMT_SHIFT			7
+#define CCDC_DATA_SZ_MASK			7
+#define CCDC_DATA_SZ_SHIFT			8
+#define CCDC_VDHDOUT_MASK			1
+#define CCDC_VDHDOUT_SHIFT			0
+#define CCDC_EXWEN_MASK				1
+#define CCDC_EXWEN_SHIFT			5
+#define CCDC_INPUT_MODE_MASK			3
+#define CCDC_INPUT_MODE_SHIFT			12
+#define CCDC_PIX_FMT_MASK			3
+#define CCDC_PIX_FMT_SHIFT			12
+#define CCDC_DATAPOL_MASK			1
+#define CCDC_DATAPOL_SHIFT			6
+#define CCDC_WEN_ENABLE				(1 << 1)
+#define CCDC_VDHDEN_ENABLE			(1 << 16)
+#define CCDC_LPF_ENABLE				(1 << 14)
+#define CCDC_ALAW_ENABLE			1
+#define CCDC_ALAW_GAMA_WD_MASK			7
+#define CCDC_REC656IF_BT656_EN			3
+
+#define CCDC_FMTCFG_FMTMODE_MASK 		3
+#define CCDC_FMTCFG_FMTMODE_SHIFT		1
+#define CCDC_FMTCFG_LNUM_MASK			3
+#define CCDC_FMTCFG_LNUM_SHIFT			4
+#define CCDC_FMTCFG_ADDRINC_MASK		7
+#define CCDC_FMTCFG_ADDRINC_SHIFT		8
+
+#define CCDC_CCDCFG_FIDMD_SHIFT			6
+#define	CCDC_CCDCFG_WENLOG_SHIFT		8
+#define CCDC_CCDCFG_TRGSEL_SHIFT		9
+#define CCDC_CCDCFG_EXTRG_SHIFT			10
+#define CCDC_CCDCFG_MSBINVI_SHIFT		13
+
+#define CCDC_HSIZE_FLIP_SHIFT			12
+#define CCDC_HSIZE_FLIP_MASK			1
+#define CCDC_HSIZE_VAL_MASK			0xFFF
+#define CCDC_SDOFST_FIELD_INTERLEAVED		0x249
+#define CCDC_SDOFST_INTERLACE_INVERSE		0x4B6D
+#define CCDC_SDOFST_INTERLACE_NORMAL		0x0B6D
+#define CCDC_SDOFST_PROGRESSIVE_INVERSE		0x4000
+#define CCDC_SDOFST_PROGRESSIVE_NORMAL		0
+#define CCDC_START_PX_HOR_MASK			0x7FFF
+#define CCDC_NUM_PX_HOR_MASK			0x7FFF
+#define CCDC_START_VER_ONE_MASK			0x7FFF
+#define CCDC_START_VER_TWO_MASK			0x7FFF
+#define CCDC_NUM_LINES_VER			0x7FFF
+
+#define CCDC_BLK_CLAMP_ENABLE			(1 << 15)
+#define CCDC_BLK_SGAIN_MASK			0x1F
+#define CCDC_BLK_ST_PXL_MASK			0x1FFF
+#define CCDC_BLK_SAMPLE_LN_MASK			3
+#define CCDC_BLK_SAMPLE_LN_SHIFT		13
+
+#define CCDC_NUM_LINE_CALC_MASK			3
+#define CCDC_NUM_LINE_CALC_SHIFT		14
+
+#define CCDC_BLK_DC_SUB_MASK			0x3FFF
+#define CCDC_BLK_COMP_MASK			0xFF
+#define CCDC_BLK_COMP_GB_COMP_SHIFT		8
+#define CCDC_BLK_COMP_GR_COMP_SHIFT		0
+#define CCDC_BLK_COMP_R_COMP_SHIFT		8
+#define CCDC_LATCH_ON_VSYNC_DISABLE		(1 << 15)
+#define CCDC_LATCH_ON_VSYNC_ENABLE		(0 << 15)
+#define CCDC_FPC_ENABLE				(1 << 15)
+#define CCDC_FPC_FPC_NUM_MASK 			0x7FFF
+#define CCDC_DATA_PACK_ENABLE			(1 << 11)
+#define CCDC_FMT_HORZ_FMTLNH_MASK		0x1FFF
+#define CCDC_FMT_HORZ_FMTSPH_MASK		0x1FFF
+#define CCDC_FMT_HORZ_FMTSPH_SHIFT		16
+#define CCDC_FMT_VERT_FMTLNV_MASK		0x1FFF
+#define CCDC_FMT_VERT_FMTSLV_MASK		0x1FFF
+#define CCDC_FMT_VERT_FMTSLV_SHIFT		16
+#define CCDC_VP_OUT_VERT_NUM_MASK		0x3FFF
+#define CCDC_VP_OUT_VERT_NUM_SHIFT		17
+#define CCDC_VP_OUT_HORZ_NUM_MASK		0x1FFF
+#define CCDC_VP_OUT_HORZ_NUM_SHIFT		4
+#define CCDC_VP_OUT_HORZ_ST_MASK		0xF
+
+#define CCDC_CSC_COEF_INTEG_MASK		7
+#define CCDC_CSC_COEF_DECIMAL_MASK		0x1f
+#define CCDC_CSC_COEF_INTEG_SHIFT		5
+#define CCDC_CSCM_MSB_SHIFT			8
+#define CCDC_CSC_ENABLE				1
+#define CCDC_CSC_DEC_MAX			32
+
+#define CCDC_MFILT1_SHIFT			10
+#define CCDC_MFILT2_SHIFT			8
+#define CCDC_MED_FILT_THRESH			0x3FFF
+#define CCDC_LPF_MASK				1
+#define CCDC_LPF_SHIFT				14
+#define CCDC_OFFSET_MASK			0x3FF
+#define CCDC_DATASFT_MASK			7
+#define CCDC_DATASFT_SHIFT			8
+
+#define CCDC_DF_ENABLE				1
+
+#define CCDC_FMTPLEN_P0_MASK			0xF
+#define CCDC_FMTPLEN_P1_MASK			0xF
+#define CCDC_FMTPLEN_P2_MASK			7
+#define CCDC_FMTPLEN_P3_MASK			7
+#define CCDC_FMTPLEN_P0_SHIFT			0
+#define CCDC_FMTPLEN_P1_SHIFT			4
+#define CCDC_FMTPLEN_P2_SHIFT			8
+#define CCDC_FMTPLEN_P3_SHIFT			12
+
+#define CCDC_FMTSPH_MASK			0x1FFF
+#define CCDC_FMTLNH_MASK			0x1FFF
+#define CCDC_FMTSLV_MASK			0x1FFF
+#define CCDC_FMTLNV_MASK			0x7FFF
+#define CCDC_FMTRLEN_MASK			0x1FFF
+#define CCDC_FMTHCNT_MASK			0x1FFF
+
+#define CCDC_ADP_INIT_MASK			0x1FFF
+#define CCDC_ADP_LINE_SHIFT			13
+#define CCDC_ADP_LINE_MASK			3
+#define CCDC_FMTPGN_APTR_MASK			7
+
+#define CCDC_DFCCTL_GDFCEN_MASK			1
+#define CCDC_DFCCTL_VDFCEN_MASK			1
+#define CCDC_DFCCTL_VDFC_DISABLE		(0 << 4)
+#define CCDC_DFCCTL_VDFCEN_SHIFT		4
+#define CCDC_DFCCTL_VDFCSL_MASK			3
+#define CCDC_DFCCTL_VDFCSL_SHIFT		5
+#define CCDC_DFCCTL_VDFCUDA_MASK		1
+#define CCDC_DFCCTL_VDFCUDA_SHIFT		7
+#define CCDC_DFCCTL_VDFLSFT_MASK		3
+#define CCDC_DFCCTL_VDFLSFT_SHIFT		8
+#define CCDC_DFCMEMCTL_DFCMARST_MASK		1
+#define CCDC_DFCMEMCTL_DFCMARST_SHIFT		2
+#define CCDC_DFCMEMCTL_DFCMWR_MASK		1
+#define CCDC_DFCMEMCTL_DFCMWR_SHIFT		0
+#define CCDC_DFCMEMCTL_INC_ADDR			(0 << 2)
+
+#define CCDC_LSCCFG_GFTSF_MASK			7
+#define CCDC_LSCCFG_GFTSF_SHIFT			1
+#define CCDC_LSCCFG_GFTINV_MASK			0xf
+#define CCDC_LSCCFG_GFTINV_SHIFT		4
+#define CCDC_LSC_GFTABLE_SEL_MASK		3
+#define CCDC_LSC_GFTABLE_EPEL_SHIFT		8
+#define CCDC_LSC_GFTABLE_OPEL_SHIFT		10
+#define CCDC_LSC_GFTABLE_EPOL_SHIFT		12
+#define CCDC_LSC_GFTABLE_OPOL_SHIFT		14
+#define CCDC_LSC_GFMODE_MASK			3
+#define CCDC_LSC_GFMODE_SHIFT			4
+#define CCDC_LSC_DISABLE			0
+#define CCDC_LSC_ENABLE				1
+#define CCDC_LSC_TABLE1_SLC			0
+#define CCDC_LSC_TABLE2_SLC			1
+#define CCDC_LSC_TABLE3_SLC			2
+#define CCDC_LSC_MEMADDR_RESET			(1 << 2)
+#define CCDC_LSC_MEMADDR_INCR			(0 << 2)
+#define CCDC_LSC_FRAC_MASK_T1			0xFF
+#define CCDC_LSC_INT_MASK			3
+#define CCDC_LSC_FRAC_MASK			0x3FFF
+#define CCDC_LSC_CENTRE_MASK			0x3FFF
+#define CCDC_LSC_COEF_MASK			0xff
+#define CCDC_LSC_COEFL_SHIFT			0
+#define CCDC_LSC_COEFU_SHIFT			8
+#define CCDC_GAIN_MASK				0x7FF
+#define CCDC_SYNCEN_VDHDEN_MASK			(1 << 0)
+#define CCDC_SYNCEN_WEN_MASK			(1 << 1)
+#define CCDC_SYNCEN_WEN_SHIFT			1
+
+/* Power on Defaults in hardware */
+#define MODESET_DEFAULT				0x200
+#define CULH_DEFAULT				0xFFFF
+#define CULV_DEFAULT				0xFF
+#define GAIN_DEFAULT				256
+#define OUTCLIP_DEFAULT				0x3FFF
+#define LSCCFG2_DEFAULT				0xE
+
+#endif
diff --git a/include/media/davinci/dm355_ccdc.h b/include/media/davinci/dm355_ccdc.h
new file mode 100644
index 0000000..b0ce1af
--- /dev/null
+++ b/include/media/davinci/dm355_ccdc.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2005-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _DM355_CCDC_H
+#define _DM355_CCDC_H
+#include <media/davinci/ccdc_types.h>
+#include <media/davinci/vpfe_types.h>
+
+/* enum for No of pixel per line to be avg. in Black Clamping */
+enum ccdc_sample_length {
+	CCDC_SAMPLE_1PIXELS,
+	CCDC_SAMPLE_2PIXELS,
+	CCDC_SAMPLE_4PIXELS,
+	CCDC_SAMPLE_8PIXELS,
+	CCDC_SAMPLE_16PIXELS
+};
+
+/* enum for No of lines in Black Clamping */
+enum ccdc_sample_line {
+	CCDC_SAMPLE_1LINES,
+	CCDC_SAMPLE_2LINES,
+	CCDC_SAMPLE_4LINES,
+	CCDC_SAMPLE_8LINES,
+	CCDC_SAMPLE_16LINES
+};
+
+/* enum for Alaw gama width */
+enum ccdc_gamma_width {
+	CCDC_GAMMA_BITS_13_4,
+	CCDC_GAMMA_BITS_12_3,
+	CCDC_GAMMA_BITS_11_2,
+	CCDC_GAMMA_BITS_10_1,
+	CCDC_GAMMA_BITS_09_0
+};
+
+enum ccdc_colpats {
+	CCDC_RED,
+	CCDC_GREEN_RED,
+	CCDC_GREEN_BLUE,
+	CCDC_BLUE
+};
+
+struct ccdc_col_pat {
+	enum ccdc_colpats olop;
+	enum ccdc_colpats olep;
+	enum ccdc_colpats elop;
+	enum ccdc_colpats elep;
+};
+
+enum ccdc_datasft {
+	CCDC_DATA_NO_SHIFT,
+	CCDC_DATA_SHIFT_1BIT,
+	CCDC_DATA_SHIFT_2BIT,
+	CCDC_DATA_SHIFT_3BIT,
+	CCDC_DATA_SHIFT_4BIT,
+	CCDC_DATA_SHIFT_5BIT,
+	CCDC_DATA_SHIFT_6BIT
+};
+
+enum ccdc_data_size {
+	CCDC_DATA_16BITS,
+	CCDC_DATA_15BITS,
+	CCDC_DATA_14BITS,
+	CCDC_DATA_13BITS,
+	CCDC_DATA_12BITS,
+	CCDC_DATA_11BITS,
+	CCDC_DATA_10BITS,
+	CCDC_DATA_8BITS
+};
+enum ccdc_mfilt1 {
+	CCDC_NO_MEDIAN_FILTER1,
+	CCDC_AVERAGE_FILTER1,
+	CCDC_MEDIAN_FILTER1
+};
+
+enum ccdc_mfilt2 {
+	CCDC_NO_MEDIAN_FILTER2,
+	CCDC_AVERAGE_FILTER2,
+	CCDC_MEDIAN_FILTER2
+};
+
+/* structure for ALaw */
+struct ccdc_a_law {
+	/* Enable/disable A-Law */
+	unsigned char enable;
+	/* Gama Width Input */
+	enum ccdc_gamma_width gama_wd;
+};
+
+/* structure for Black Clamping */
+struct ccdc_black_clamp {
+	/* only if bClampEnable is TRUE */
+	unsigned char b_clamp_enable;
+	/* only if bClampEnable is TRUE */
+	enum ccdc_sample_length sample_pixel;
+	/* only if bClampEnable is TRUE */
+	enum ccdc_sample_line sample_ln;
+	/* only if bClampEnable is TRUE */
+	unsigned short start_pixel;
+	/* only if bClampEnable is FALSE */
+	unsigned short sgain;
+	unsigned short dc_sub;
+};
+
+/* structure for Black Level Compensation */
+struct ccdc_black_compensation {
+	/* Constant value to subtract from Red component */
+	unsigned char r;
+	/* Constant value to subtract from Gr component */
+	unsigned char gr;
+	/* Constant value to subtract from Blue component */
+	unsigned char b;
+	/* Constant value to subtract from Gb component */
+	unsigned char gb;
+};
+
+struct ccdc_float {
+	int integer;
+	unsigned int decimal;
+};
+
+#define CCDC_CSC_COEFF_TABLE_SIZE	16
+/* structure for color space converter */
+struct ccdc_csc {
+	unsigned char enable;
+	/*
+	 * S8Q5. Use 2 decimal precision, user values range from -3.00 to 3.99.
+	 * example - to use 1.03, set integer part as 1, and decimal part as 3
+	 * to use -1.03, set integer part as -1 and decimal part as 3
+	 */
+	struct ccdc_float coeff[CCDC_CSC_COEFF_TABLE_SIZE];
+};
+
+/* Structures for Vertical Defect Correction*/
+enum ccdc_vdf_csl {
+	CCDC_VDF_NORMAL,
+	CCDC_VDF_HORZ_INTERPOL_SAT,
+	CCDC_VDF_HORZ_INTERPOL
+};
+
+enum ccdc_vdf_cuda {
+	CCDC_VDF_WHOLE_LINE_CORRECT,
+	CCDC_VDF_UPPER_DISABLE
+};
+
+enum ccdc_dfc_mwr {
+	CCDC_DFC_MWR_WRITE_COMPLETE,
+	CCDC_DFC_WRITE_REG
+};
+
+enum ccdc_dfc_mrd {
+	CCDC_DFC_READ_COMPLETE,
+	CCDC_DFC_READ_REG
+};
+
+enum ccdc_dfc_ma_rst {
+	CCDC_DFC_INCR_ADDR,
+	CCDC_DFC_CLR_ADDR
+};
+
+enum ccdc_dfc_mclr {
+	CCDC_DFC_CLEAR_COMPLETE,
+	CCDC_DFC_CLEAR
+};
+
+struct ccdc_dft_corr_ctl {
+	enum ccdc_vdf_csl vdfcsl;
+	enum ccdc_vdf_cuda vdfcuda;
+	unsigned int vdflsft;
+};
+
+struct ccdc_dft_corr_mem_ctl {
+	enum ccdc_dfc_mwr dfcmwr;
+	enum ccdc_dfc_mrd dfcmrd;
+	enum ccdc_dfc_ma_rst dfcmarst;
+	enum ccdc_dfc_mclr dfcmclr;
+};
+
+#define CCDC_DFT_TABLE_SIZE	16
+/*
+ * Main Structure for vertical defect correction. Vertical defect
+ * correction can correct upto 16 defects if defects less than 16
+ * then pad the rest with 0
+ */
+struct ccdc_vertical_dft {
+	unsigned char ver_dft_en;
+	unsigned char gen_dft_en;
+	unsigned int saturation_ctl;
+	struct ccdc_dft_corr_ctl dft_corr_ctl;
+	struct ccdc_dft_corr_mem_ctl dft_corr_mem_ctl;
+	int table_size;
+	unsigned int dft_corr_horz[CCDC_DFT_TABLE_SIZE];
+	unsigned int dft_corr_vert[CCDC_DFT_TABLE_SIZE];
+	unsigned int dft_corr_sub1[CCDC_DFT_TABLE_SIZE];
+	unsigned int dft_corr_sub2[CCDC_DFT_TABLE_SIZE];
+	unsigned int dft_corr_sub3[CCDC_DFT_TABLE_SIZE];
+};
+
+struct ccdc_data_offset {
+	unsigned char horz_offset;
+	unsigned char vert_offset;
+};
+
+/*
+ * Structure for CCDC configuration parameters for raw capture mode passed
+ * by application
+ */
+struct ccdc_config_params_raw {
+	/* data shift to be applied before storing */
+	enum ccdc_datasft datasft;
+	/* data size value from 8 to 16 bits */
+	enum ccdc_data_size data_sz;
+	/* median filter for sdram */
+	enum ccdc_mfilt1 mfilt1;
+	enum ccdc_mfilt2 mfilt2;
+	/* low pass filter enable/disable */
+	unsigned char lpf_enable;
+	/* Threshold of median filter */
+	int med_filt_thres;
+	/*
+	 * horz and vertical data offset. Appliable for defect correction
+	 * and lsc
+	 */
+	struct ccdc_data_offset data_offset;
+	/* Structure for Optional A-Law */
+	struct ccdc_a_law alaw;
+	/* Structure for Optical Black Clamp */
+	struct ccdc_black_clamp blk_clamp;
+	/* Structure for Black Compensation */
+	struct ccdc_black_compensation blk_comp;
+	/* struture for vertical Defect Correction Module Configuration */
+	struct ccdc_vertical_dft vertical_dft;
+	/* structure for color space converter Module Configuration */
+	struct ccdc_csc csc;
+	/* color patters for bayer capture */
+	struct ccdc_col_pat col_pat_field0;
+	struct ccdc_col_pat col_pat_field1;
+};
+
+#ifdef __KERNEL__
+#include <linux/io.h>
+
+#define CCDC_WIN_PAL	{0, 0, 720, 576}
+#define CCDC_WIN_VGA	{0, 0, 640, 480}
+
+/*
+ * CCDC specific controls for Bayer capture. The CIDs
+ * listed here should match with that in davinci_vpfe.h
+ */
+
+/* White balance on Bayer RGB. U11Q8 */
+#define CCDC_CID_R_GAIN		(V4L2_CID_PRIVATE_BASE + 0)
+#define CCDC_CID_GR_GAIN	(V4L2_CID_PRIVATE_BASE + 1)
+#define CCDC_CID_GB_GAIN 	(V4L2_CID_PRIVATE_BASE + 2)
+#define CCDC_CID_B_GAIN 	(V4L2_CID_PRIVATE_BASE + 3)
+/* Offsets */
+#define CCDC_CID_OFFSET 	(V4L2_CID_PRIVATE_BASE + 4)
+#define CCDC_CID_MAX		(V4L2_CID_PRIVATE_BASE + 5)
+#define CCDC_MAX_CONTROLS 5
+
+struct ccdc_params_ycbcr {
+	/* pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* progressive or interlaced frame */
+	enum ccdc_frmfmt frm_fmt;
+	/* video window */
+	struct v4l2_rect win;
+	/* field id polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* vertical sync polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* horizontal sync polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* enable BT.656 embedded sync mode */
+	int bt656_enable;
+	/* cb:y:cr:y or y:cb:y:cr in memory */
+	enum ccdc_pixorder pix_order;
+	/* interleaved or separated fields  */
+	enum ccdc_buftype buf_type;
+};
+
+/* Gain applied to Raw Bayer data */
+struct ccdc_gain {
+	unsigned short r_ye;
+	unsigned short gr_cy;
+	unsigned short gb_g;
+	unsigned short b_mg;
+};
+
+/* Structure for CCDC configuration parameters for raw capture mode */
+struct ccdc_params_raw {
+	/* pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* progressive or interlaced frame */
+	enum ccdc_frmfmt frm_fmt;
+	/* video window */
+	struct v4l2_rect win;
+	/* field id polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* vertical sync polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* horizontal sync polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* interleaved or separated fields */
+	enum ccdc_buftype buf_type;
+	/* Gain values */
+	struct ccdc_gain gain;
+	/* offset */
+	unsigned int ccdc_offset;
+	/* horizontal flip enable */
+	unsigned char horz_flip_enable;
+	/*
+	 * enable to store the image in inverse order in memory
+	 * (bottom to top)
+	 */
+	unsigned char image_invert_enable;
+	/* Configurable part of raw data */
+	struct ccdc_config_params_raw config_params;
+};
+
+#endif
+#endif				/* DM355_CCDC_H */
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 4/10 - v2] dm644x ccdc module for vpfe capture driver
  2009-06-11 17:00     ` [PATCH 3/10 - v2] dm355 ccdc module for vpfe capture driver m-karicheri2
@ 2009-06-11 17:00       ` m-karicheri2
  2009-06-11 17:00         ` [PATCH 5/10 - v2] ccdc types used across ccdc modules " m-karicheri2
  0 siblings, 1 reply; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

DM644x CCDC hw module

This is the hw module for DM644x CCDC. This registers with the
vpfe capture driver and provides a set of hw_ops to configure
CCDC for a specific decoder device connected to the VPFE

Following are some of the major comments addressed :-
	1) removed vpss configration from this module to a standalone
	   vpss module that can be used by other video drivers as well
	2) replaced magic numbers with #defines
	3) cleaned up and refractored ccdc_config_raw()
	4) embedded config part of the variables inside
	   ccdc_params_raw to help in memcpy.
	5) avoided generic names for ccdc types in include file by
	   prefixing with  ccdc_

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 drivers/media/video/davinci/dm644x_ccdc.c      |  876 ++++++++++++++++++++++++
 drivers/media/video/davinci/dm644x_ccdc_regs.h |  145 ++++
 include/media/davinci/dm644x_ccdc.h            |  184 +++++
 3 files changed, 1205 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/dm644x_ccdc.c
 create mode 100644 drivers/media/video/davinci/dm644x_ccdc_regs.h
 create mode 100644 include/media/davinci/dm644x_ccdc.h

diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c
new file mode 100644
index 0000000..4f81f69
--- /dev/null
+++ b/drivers/media/video/davinci/dm644x_ccdc.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2006-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * CCDC hardware module for DM6446
+ * ------------------------------
+ *
+ * This module is for configuring CCD controller of DM6446 VPFE to capture
+ * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules
+ * such as Defect Pixel Correction, Color Space Conversion etc to
+ * pre-process the Raw Bayer RGB data, before writing it to SDRAM. This
+ * module also allows application to configure individual
+ * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL.
+ * To do so, application includes dm644x_ccdc.h and vpfe_capture.h header
+ * files.  The setparams() API is called by vpfe_capture driver
+ * to configure module parameters. This file is named DM644x so that other
+ * variants such DM6443 may be supported using the same module.
+ *
+ * TODO: Test Raw bayer parameter settings and bayer capture
+ * 	 Split module parameter structure to module specific ioctl structs
+ * 	 investigate if enum used for user space type definition
+ * 	 to be replaced by #defines or integer
+ */
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+#include <media/davinci/dm644x_ccdc.h>
+#include <media/davinci/vpss.h>
+#include "dm644x_ccdc_regs.h"
+#include "ccdc_hw_device.h"
+
+static struct device *dev;
+
+/* Object for CCDC raw mode */
+static struct ccdc_params_raw ccdc_hw_params_raw = {
+	.pix_fmt = CCDC_PIXFMT_RAW,
+	.frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
+	.win = CCDC_WIN_VGA,
+	.fid_pol = VPFE_PINPOL_POSITIVE,
+	.vd_pol = VPFE_PINPOL_POSITIVE,
+	.hd_pol = VPFE_PINPOL_POSITIVE,
+	.config_params = {
+		.data_sz = CCDC_DATA_10BITS,
+	},
+};
+
+/* Object for CCDC ycbcr mode */
+static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = {
+	.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
+	.frm_fmt = CCDC_FRMFMT_INTERLACED,
+	.win = CCDC_WIN_PAL,
+	.fid_pol = VPFE_PINPOL_POSITIVE,
+	.vd_pol = VPFE_PINPOL_POSITIVE,
+	.hd_pol = VPFE_PINPOL_POSITIVE,
+	.bt656_enable = 1,
+	.pix_order = CCDC_PIXORDER_CBYCRY,
+	.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
+};
+
+#define CCDC_MAX_RAW_YUV_FORMATS	2
+
+/* Raw Bayer formats */
+static u32 ccdc_raw_bayer_pix_formats[] =
+	{V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
+
+/* Raw YUV formats */
+static u32 ccdc_raw_yuv_pix_formats[] =
+	{V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
+
+static void *__iomem ccdc_base_addr;
+static int ccdc_addr_size;
+static enum vpfe_hw_if_type ccdc_if_type;
+
+/* register access routines */
+static inline u32 regr(u32 offset)
+{
+	return __raw_readl(ccdc_base_addr + offset);
+}
+
+static inline void regw(u32 val, u32 offset)
+{
+	__raw_writel(val, ccdc_base_addr + offset);
+}
+
+static void ccdc_set_ccdc_base(void *addr, int size)
+{
+	ccdc_base_addr = addr;
+	ccdc_addr_size = size;
+}
+
+static void ccdc_enable(int flag)
+{
+	regw(flag, CCDC_PCR);
+}
+
+static void ccdc_enable_vport(int flag)
+{
+	if (flag)
+		/* enable video port */
+		regw(CCDC_ENABLE_VIDEO_PORT, CCDC_FMTCFG);
+	else
+		regw(CCDC_DISABLE_VIDEO_PORT, CCDC_FMTCFG);
+}
+
+/*
+ * ccdc_setwin()
+ * This function will configure the window size
+ * to be capture in CCDC reg
+ */
+void ccdc_setwin(struct v4l2_rect *image_win,
+		enum ccdc_frmfmt frm_fmt,
+		int ppc)
+{
+	int horz_start, horz_nr_pixels;
+	int vert_start, vert_nr_lines;
+	int val = 0, mid_img = 0;
+
+	dev_dbg(dev, "\nStarting ccdc_setwin...");
+	/*
+	 * ppc - per pixel count. indicates how many pixels per cell
+	 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
+	 * raw capture this is 1
+	 */
+	horz_start = image_win->left << (ppc - 1);
+	horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
+	regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels,
+	     CCDC_HORZ_INFO);
+
+	vert_start = image_win->top;
+
+	if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		vert_nr_lines = (image_win->height >> 1) - 1;
+		vert_start >>= 1;
+		/* Since first line doesn't have any data */
+		vert_start += 1;
+		/* configure VDINT0 */
+		val = (vert_start << CCDC_VDINT_VDINT0_SHIFT);
+		regw(val, CCDC_VDINT);
+
+	} else {
+		/* Since first line doesn't have any data */
+		vert_start += 1;
+		vert_nr_lines = image_win->height - 1;
+		/*
+		 * configure VDINT0 and VDINT1. VDINT1 will be at half
+		 * of image height
+		 */
+		mid_img = vert_start + (image_win->height / 2);
+		val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) |
+		    (mid_img & CCDC_VDINT_VDINT1_MASK);
+		regw(val, CCDC_VDINT);
+
+	}
+	regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start,
+	     CCDC_VERT_START);
+	regw(vert_nr_lines, CCDC_VERT_LINES);
+	dev_dbg(dev, "\nEnd of ccdc_setwin...");
+}
+
+static void ccdc_readregs(void)
+{
+	unsigned int val = 0;
+
+	val = regr(CCDC_ALAW);
+	dev_notice(dev, "\nReading 0x%x to ALAW...\n", val);
+	val = regr(CCDC_CLAMP);
+	dev_notice(dev, "\nReading 0x%x to CLAMP...\n", val);
+	val = regr(CCDC_DCSUB);
+	dev_notice(dev, "\nReading 0x%x to DCSUB...\n", val);
+	val = regr(CCDC_BLKCMP);
+	dev_notice(dev, "\nReading 0x%x to BLKCMP...\n", val);
+	val = regr(CCDC_FPC_ADDR);
+	dev_notice(dev, "\nReading 0x%x to FPC_ADDR...\n", val);
+	val = regr(CCDC_FPC);
+	dev_notice(dev, "\nReading 0x%x to FPC...\n", val);
+	val = regr(CCDC_FMTCFG);
+	dev_notice(dev, "\nReading 0x%x to FMTCFG...\n", val);
+	val = regr(CCDC_COLPTN);
+	dev_notice(dev, "\nReading 0x%x to COLPTN...\n", val);
+	val = regr(CCDC_FMT_HORZ);
+	dev_notice(dev, "\nReading 0x%x to FMT_HORZ...\n", val);
+	val = regr(CCDC_FMT_VERT);
+	dev_notice(dev, "\nReading 0x%x to FMT_VERT...\n", val);
+	val = regr(CCDC_HSIZE_OFF);
+	dev_notice(dev, "\nReading 0x%x to HSIZE_OFF...\n", val);
+	val = regr(CCDC_SDOFST);
+	dev_notice(dev, "\nReading 0x%x to SDOFST...\n", val);
+	val = regr(CCDC_VP_OUT);
+	dev_notice(dev, "\nReading 0x%x to VP_OUT...\n", val);
+	val = regr(CCDC_SYN_MODE);
+	dev_notice(dev, "\nReading 0x%x to SYN_MODE...\n", val);
+	val = regr(CCDC_HORZ_INFO);
+	dev_notice(dev, "\nReading 0x%x to HORZ_INFO...\n", val);
+	val = regr(CCDC_VERT_START);
+	dev_notice(dev, "\nReading 0x%x to VERT_START...\n", val);
+	val = regr(CCDC_VERT_LINES);
+	dev_notice(dev, "\nReading 0x%x to VERT_LINES...\n", val);
+}
+
+static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
+{
+	if (ccdcparam->alaw.enable) {
+		if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) ||
+		    (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) ||
+		    (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) {
+			dev_dbg(dev, "\nInvalid data line select");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params)
+{
+	struct ccdc_config_params_raw *config_params =
+		&ccdc_hw_params_raw.config_params;
+	unsigned int *fpc_virtaddr = NULL;
+	unsigned int *fpc_physaddr = NULL;
+
+	memcpy(config_params, raw_params, sizeof(*raw_params));
+	/*
+	 * allocate memory for fault pixel table and copy the user
+	 * values to the table
+	 */
+	if (!config_params->fault_pxl.enable)
+		return 0;
+
+	fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr;
+	fpc_virtaddr = (unsigned int *)phys_to_virt(
+				(unsigned long)fpc_physaddr);
+	/*
+	 * Allocate memory for FPC table if current
+	 * FPC table buffer is not big enough to
+	 * accomodate FPC Number requested
+	 */
+	if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) {
+		if (fpc_physaddr != NULL) {
+			free_pages((unsigned long)fpc_physaddr,
+				   get_order
+				   (config_params->fault_pxl.fp_num *
+				   FP_NUM_BYTES));
+		}
+
+		/* Allocate memory for FPC table */
+		fpc_virtaddr =
+			(unsigned int *)__get_free_pages(GFP_KERNEL | GFP_DMA,
+							 get_order(raw_params->
+							 fault_pxl.fp_num *
+							 FP_NUM_BYTES));
+
+		if (fpc_virtaddr == NULL) {
+			dev_dbg(dev,
+				"\nUnable to allocate memory for FPC");
+			return -EFAULT;
+		}
+		fpc_physaddr =
+		    (unsigned int *)virt_to_phys((void *)fpc_virtaddr);
+	}
+
+	/* Copy number of fault pixels and FPC table */
+	config_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num;
+	if (copy_from_user(fpc_virtaddr,
+			(void __user *)raw_params->fault_pxl.fpc_table_addr,
+			config_params->fault_pxl.fp_num * FP_NUM_BYTES)) {
+		dev_dbg(dev, "\n copy_from_user failed");
+		return -EFAULT;
+	}
+	config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr;
+	return 0;
+}
+
+static int ccdc_close(struct device *dev)
+{
+	struct ccdc_config_params_raw *config_params =
+		&ccdc_hw_params_raw.config_params;
+	unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL;
+
+	fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr;
+
+	if (fpc_physaddr != NULL) {
+		fpc_virtaddr = (unsigned int *)
+		    phys_to_virt((unsigned long)fpc_physaddr);
+		free_pages((unsigned long)fpc_virtaddr,
+			   get_order(config_params->fault_pxl.fp_num *
+			   FP_NUM_BYTES));
+	}
+	return 0;
+}
+
+/*
+ * ccdc_restore_defaults()
+ * This function will write defaults to all CCDC registers
+ */
+static void ccdc_restore_defaults(void)
+{
+	int i;
+
+	/* disable CCDC */
+	ccdc_enable(0);
+	/* set all registers to default value */
+	for (i = 4; i <= 0x94; i += 4)
+		regw(0,  i);
+	regw(CCDC_NO_CULLING, CCDC_CULLING);
+	regw(CCDC_GAMMA_BITS_11_2, CCDC_ALAW);
+}
+
+static int ccdc_open(struct device *device)
+{
+	dev = device;
+	ccdc_restore_defaults();
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_enable_vport(1);
+	return 0;
+}
+
+static void ccdc_sbl_reset(void)
+{
+	vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O);
+}
+
+/* Parameter operations */
+static int ccdc_set_params(void __user *params)
+{
+	struct ccdc_config_params_raw ccdc_raw_params;
+	int x;
+
+	if (ccdc_if_type != VPFE_RAW_BAYER)
+		return -EINVAL;
+
+	x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
+	if (x) {
+		dev_dbg(dev, "ccdc_set_params: error in copying"
+			   "ccdc params, %d\n", x);
+		return -EFAULT;
+	}
+
+	if (!validate_ccdc_param(&ccdc_raw_params)) {
+		if (!ccdc_update_raw_params(&ccdc_raw_params))
+			return 0;
+	}
+	return -EINVAL;
+}
+
+/*
+ * ccdc_config_ycbcr()
+ * This function will configure CCDC for YCbCr video capture
+ */
+void ccdc_config_ycbcr(void)
+{
+	struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr;
+	u32 syn_mode;
+
+	dev_dbg(dev, "\nStarting ccdc_config_ycbcr...");
+	/*
+	 * first restore the CCDC registers to default values
+	 * This is important since we assume default values to be set in
+	 * a lot of registers that we didn't touch
+	 */
+	ccdc_restore_defaults();
+
+	/*
+	 * configure pixel format, frame format, configure video frame
+	 * format, enable output to SDRAM, enable internal timing generator
+	 * and 8bit pack mode
+	 */
+	syn_mode = (((params->pix_fmt & CCDC_SYN_MODE_INPMOD_MASK) <<
+		    CCDC_SYN_MODE_INPMOD_SHIFT) |
+		    ((params->frm_fmt & CCDC_SYN_FLDMODE_MASK) <<
+		    CCDC_SYN_FLDMODE_SHIFT) | CCDC_VDHDEN_ENABLE |
+		    CCDC_WEN_ENABLE | CCDC_DATA_PACK_ENABLE);
+
+	/* setup BT.656 sync mode */
+	if (params->bt656_enable) {
+		regw(CCDC_REC656IF_BT656_EN, CCDC_REC656IF);
+
+		/*
+		 * configure the FID, VD, HD pin polarity,
+		 * fld,hd pol positive, vd negative, 8-bit data
+		 */
+		syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE | CCDC_SYN_MODE_8BITS;
+	} else {
+		/* y/c external sync mode */
+		syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) <<
+			     CCDC_FID_POL_SHIFT) |
+			     ((params->hd_pol & CCDC_HD_POL_MASK) <<
+			     CCDC_HD_POL_SHIFT) |
+			     ((params->vd_pol & CCDC_VD_POL_MASK) <<
+			     CCDC_VD_POL_SHIFT));
+	}
+	regw(syn_mode, CCDC_SYN_MODE);
+
+	/* configure video window */
+	ccdc_setwin(&params->win, params->frm_fmt, 2);
+
+	/*
+	 * configure the order of y cb cr in SDRAM, and disable latch
+	 * internal register on vsync
+	 */
+	regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) |
+		 CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
+
+	/*
+	 * configure the horizontal line offset. This should be a
+	 * on 32 byte bondary. So clear LSB 5 bits
+	 */
+	regw(((params->win.width * 2  + 31) & ~0x1f), CCDC_HSIZE_OFF);
+
+	/* configure the memory line offset */
+	if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
+		/* two fields are interleaved in memory */
+		regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST);
+
+	ccdc_sbl_reset();
+	dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n");
+	ccdc_readregs();
+}
+
+static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp)
+{
+	u32 val;
+
+	if (!bclamp->enable) {
+		/* configure DCSub */
+		val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK;
+		regw(val, CCDC_DCSUB);
+		dev_dbg(dev, "\nWriting 0x%x to DCSUB...\n", val);
+		regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP);
+		dev_dbg(dev, "\nWriting 0x0000 to CLAMP...\n");
+		return;
+	}
+	/*
+	 * Configure gain,  Start pixel, No of line to be avg,
+	 * No of pixel/line to be avg, & Enable the Black clamping
+	 */
+	val = ((bclamp->sgain & CCDC_BLK_SGAIN_MASK) |
+	       ((bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) <<
+		CCDC_BLK_ST_PXL_SHIFT) |
+	       ((bclamp->sample_ln & CCDC_BLK_SAMPLE_LINE_MASK) <<
+		CCDC_BLK_SAMPLE_LINE_SHIFT) |
+	       ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) <<
+		CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE);
+	regw(val, CCDC_CLAMP);
+	dev_dbg(dev, "\nWriting 0x%x to CLAMP...\n", val);
+	/* If Black clamping is enable then make dcsub 0 */
+	regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB);
+	dev_dbg(dev, "\nWriting 0x00000000 to DCSUB...\n");
+}
+
+static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp)
+{
+	u32 val;
+
+	val = ((bcomp->b & CCDC_BLK_COMP_MASK) |
+	      ((bcomp->gb & CCDC_BLK_COMP_MASK) <<
+	       CCDC_BLK_COMP_GB_COMP_SHIFT) |
+	      ((bcomp->gr & CCDC_BLK_COMP_MASK) <<
+	       CCDC_BLK_COMP_GR_COMP_SHIFT) |
+	      ((bcomp->r & CCDC_BLK_COMP_MASK) <<
+	       CCDC_BLK_COMP_R_COMP_SHIFT));
+	regw(val, CCDC_BLKCMP);
+}
+
+static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc)
+{
+	u32 val;
+
+	/* Initially disable FPC */
+	val = CCDC_FPC_DISABLE;
+	regw(val, CCDC_FPC);
+
+	if (!fpc->enable)
+		return;
+
+	/* Configure Fault pixel if needed */
+	regw(fpc->fpc_table_addr, CCDC_FPC_ADDR);
+	dev_dbg(dev, "\nWriting 0x%x to FPC_ADDR...\n",
+		       (fpc->fpc_table_addr));
+	/* Write the FPC params with FPC disable */
+	val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK;
+	regw(val, CCDC_FPC);
+
+	dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val);
+	/* read the FPC register */
+	val = regr(CCDC_FPC) | CCDC_FPC_ENABLE;
+	regw(val, CCDC_FPC);
+	dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val);
+}
+
+/*
+ * ccdc_config_raw()
+ * This function will configure CCDC for Raw capture mode
+ */
+void ccdc_config_raw(void)
+{
+	struct ccdc_params_raw *params = &ccdc_hw_params_raw;
+	struct ccdc_config_params_raw *config_params =
+		&ccdc_hw_params_raw.config_params;
+	unsigned int syn_mode = 0;
+	unsigned int val;
+
+	dev_dbg(dev, "\nStarting ccdc_config_raw...");
+
+	/*      Reset CCDC */
+	ccdc_restore_defaults();
+
+	/* Disable latching function registers on VSYNC  */
+	regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
+
+	/*
+	 * Configure the vertical sync polarity(SYN_MODE.VDPOL),
+	 * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity
+	 * (SYN_MODE.FLDPOL), frame format(progressive or interlace),
+	 * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output
+	 * SDRAM, enable internal timing generator
+	 */
+	syn_mode =
+		(((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
+		((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
+		((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
+		((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
+		((config_params->data_sz & CCDC_DATA_SZ_MASK) <<
+		CCDC_DATA_SZ_SHIFT) |
+		((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT) |
+		CCDC_WEN_ENABLE | CCDC_VDHDEN_ENABLE);
+
+	/* Enable and configure aLaw register if needed */
+	if (config_params->alaw.enable) {
+		val = ((config_params->alaw.gama_wd &
+		      CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE);
+		regw(val, CCDC_ALAW);
+		dev_dbg(dev, "\nWriting 0x%x to ALAW...\n", val);
+	}
+
+	/* Configure video window */
+	ccdc_setwin(&params->win, params->frm_fmt, CCDC_PPC_RAW);
+
+	/* Configure Black Clamp */
+	ccdc_config_black_clamp(&config_params->blk_clamp);
+
+	/* Configure Black level compensation */
+	ccdc_config_black_compense(&config_params->blk_comp);
+
+	/* Configure Fault Pixel Correction */
+	ccdc_config_fpc(&config_params->fault_pxl);
+
+	/* If data size is 8 bit then pack the data */
+	if ((config_params->data_sz == CCDC_DATA_8BITS) ||
+	     config_params->alaw.enable)
+		syn_mode |= CCDC_DATA_PACK_ENABLE;
+
+#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE
+	/* enable video port */
+	val = CCDC_ENABLE_VIDEO_PORT;
+#else
+	/* disable video port */
+	val = CCDC_DISABLE_VIDEO_PORT;
+#endif
+
+	if (config_params->data_sz == CCDC_DATA_8BITS)
+		val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
+		    << CCDC_FMTCFG_VPIN_SHIFT;
+	else
+		val |= (config_params->data_sz & CCDC_FMTCFG_VPIN_MASK)
+		    << CCDC_FMTCFG_VPIN_SHIFT;
+	/* Write value in FMTCFG */
+	regw(val, CCDC_FMTCFG);
+
+	dev_dbg(dev, "\nWriting 0x%x to FMTCFG...\n", val);
+	/* Configure the color pattern according to mt9t001 sensor */
+	regw(CCDC_COLPTN_VAL, CCDC_COLPTN);
+
+	dev_dbg(dev, "\nWriting 0xBB11BB11 to COLPTN...\n");
+	/*
+	 * Configure Data formatter(Video port) pixel selection
+	 * (FMT_HORZ, FMT_VERT)
+	 */
+	val = ((params->win.left & CCDC_FMT_HORZ_FMTSPH_MASK) <<
+	      CCDC_FMT_HORZ_FMTSPH_SHIFT) |
+	      (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK);
+	regw(val, CCDC_FMT_HORZ);
+
+	dev_dbg(dev, "\nWriting 0x%x to FMT_HORZ...\n", val);
+	val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK)
+	    << CCDC_FMT_VERT_FMTSLV_SHIFT;
+	if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
+		val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK;
+	else
+		val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK;
+
+	dev_dbg(dev, "\nparams->win.height  0x%x ...\n",
+	       params->win.height);
+	regw(val, CCDC_FMT_VERT);
+
+	dev_dbg(dev, "\nWriting 0x%x to FMT_VERT...\n", val);
+
+	dev_dbg(dev, "\nbelow regw(val, FMT_VERT)...");
+
+	/*
+	 * Configure Horizontal offset register. If pack 8 is enabled then
+	 * 1 pixel will take 1 byte
+	 */
+	if ((config_params->data_sz == CCDC_DATA_8BITS) ||
+	    config_params->alaw.enable)
+		regw((params->win.width + CCDC_32BYTE_ALIGN_VAL) &
+		    CCDC_HSIZE_OFF_MASK, CCDC_HSIZE_OFF);
+	else
+		/* else one pixel will take 2 byte */
+		regw(((params->win.width * CCDC_TWO_BYTES_PER_PIXEL) +
+		    CCDC_32BYTE_ALIGN_VAL) & CCDC_HSIZE_OFF_MASK,
+		    CCDC_HSIZE_OFF);
+
+	/* Set value for SDOFST */
+	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		if (params->image_invert_enable) {
+			/* For intelace inverse mode */
+			regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST);
+			dev_dbg(dev, "\nWriting 0x4B6D to SDOFST...\n");
+		}
+
+		else {
+			/* For intelace non inverse mode */
+			regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST);
+			dev_dbg(dev, "\nWriting 0x0249 to SDOFST...\n");
+		}
+	} else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
+		regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST);
+		dev_dbg(dev, "\nWriting 0x0000 to SDOFST...\n");
+	}
+
+	/*
+	 * Configure video port pixel selection (VPOUT)
+	 * Here -1 is to make the height value less than FMT_VERT.FMTLNV
+	 */
+	if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
+		val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK))
+		    << CCDC_VP_OUT_VERT_NUM_SHIFT;
+	else
+		val =
+		    ((((params->win.height >> CCDC_INTERLACED_HEIGHT_SHIFT) -
+		     1) & CCDC_VP_OUT_VERT_NUM_MASK)) <<
+		    CCDC_VP_OUT_VERT_NUM_SHIFT;
+
+	val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK)
+	    << CCDC_VP_OUT_HORZ_NUM_SHIFT;
+	val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK;
+	regw(val, CCDC_VP_OUT);
+
+	dev_dbg(dev, "\nWriting 0x%x to VP_OUT...\n", val);
+	regw(syn_mode, CCDC_SYN_MODE);
+	dev_dbg(dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode);
+
+	ccdc_sbl_reset();
+	dev_dbg(dev, "\nend of ccdc_config_raw...");
+	ccdc_readregs();
+}
+
+static int ccdc_configure(void)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_config_raw();
+	else
+		ccdc_config_ycbcr();
+	return 0;
+}
+
+static int ccdc_set_buftype(enum ccdc_buftype buf_type)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_hw_params_raw.buf_type = buf_type;
+	else
+		ccdc_hw_params_ycbcr.buf_type = buf_type;
+	return 0;
+}
+
+static enum ccdc_buftype ccdc_get_buftype(void)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		return ccdc_hw_params_raw.buf_type;
+	return ccdc_hw_params_ycbcr.buf_type;
+}
+
+static int ccdc_enum_pix(u32 *pix, int i)
+{
+	int ret = -EINVAL;
+	if (ccdc_if_type == VPFE_RAW_BAYER) {
+		if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
+			*pix = ccdc_raw_bayer_pix_formats[i];
+			ret = 0;
+		}
+	} else {
+		if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
+			*pix = ccdc_raw_yuv_pix_formats[i];
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
+static int ccdc_set_pixel_format(u32 pixfmt)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER) {
+		ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW;
+		if (pixfmt == V4L2_PIX_FMT_SBGGR8)
+			ccdc_hw_params_raw.config_params.alaw.enable = 1;
+		else if (pixfmt != V4L2_PIX_FMT_SBGGR16)
+			return -EINVAL;
+	} else {
+		if (pixfmt == V4L2_PIX_FMT_YUYV)
+			ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
+		else if (pixfmt == V4L2_PIX_FMT_UYVY)
+			ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		else
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static u32 ccdc_get_pixel_format(void)
+{
+	struct ccdc_a_law *alaw =
+		&ccdc_hw_params_raw.config_params.alaw;
+	u32 pixfmt;
+
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		if (alaw->enable)
+			pixfmt = V4L2_PIX_FMT_SBGGR8;
+		else
+			pixfmt = V4L2_PIX_FMT_SBGGR16;
+	else {
+		if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
+			pixfmt = V4L2_PIX_FMT_YUYV;
+		else
+			pixfmt = V4L2_PIX_FMT_UYVY;
+	}
+	return pixfmt;
+}
+
+static int ccdc_set_image_window(struct v4l2_rect *win)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_hw_params_raw.win = *win;
+	else
+		ccdc_hw_params_ycbcr.win = *win;
+	return 0;
+}
+
+static void ccdc_get_image_window(struct v4l2_rect *win)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		*win = ccdc_hw_params_raw.win;
+	else
+		*win = ccdc_hw_params_ycbcr.win;
+}
+
+static unsigned int ccdc_get_line_length(void)
+{
+	struct ccdc_config_params_raw *config_params =
+		&ccdc_hw_params_raw.config_params;
+	unsigned int len;
+
+	if (ccdc_if_type == VPFE_RAW_BAYER) {
+		if ((config_params->alaw.enable) ||
+		    (config_params->data_sz == CCDC_DATA_8BITS))
+			len = ccdc_hw_params_raw.win.width;
+		else
+			len = ccdc_hw_params_raw.win.width * 2;
+	} else
+		len = ccdc_hw_params_ycbcr.win.width * 2;
+	return ALIGN(len, 32);
+}
+
+static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		ccdc_hw_params_raw.frm_fmt = frm_fmt;
+	else
+		ccdc_hw_params_ycbcr.frm_fmt = frm_fmt;
+	return 0;
+}
+
+static enum ccdc_frmfmt ccdc_get_frame_format(void)
+{
+	if (ccdc_if_type == VPFE_RAW_BAYER)
+		return ccdc_hw_params_raw.frm_fmt;
+	else
+		return ccdc_hw_params_ycbcr.frm_fmt;
+}
+
+static int ccdc_getfid(void)
+{
+	return (regr(CCDC_SYN_MODE) >> 15) & 1;
+}
+
+/* misc operations */
+static inline void ccdc_setfbaddr(unsigned long addr)
+{
+	regw(addr & 0xffffffe0, CCDC_SDR_ADDR);
+}
+
+static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
+{
+	ccdc_if_type = params->if_type;
+
+	switch (params->if_type) {
+	case VPFE_BT656:
+	case VPFE_YCBCR_SYNC_16:
+	case VPFE_YCBCR_SYNC_8:
+		ccdc_hw_params_ycbcr.vd_pol = params->vdpol;
+		ccdc_hw_params_ycbcr.hd_pol = params->hdpol;
+		break;
+	default:
+		/* TODO add support for raw bayer here */
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct ccdc_hw_device ccdc_hw_dev = {
+	.name = "DM6446 CCDC",
+	.owner = THIS_MODULE,
+	.hw_ops = {
+		.open = ccdc_open,
+		.close = ccdc_close,
+		.set_ccdc_base = ccdc_set_ccdc_base,
+		.reset = ccdc_sbl_reset,
+		.enable = ccdc_enable,
+		.set_hw_if_params = ccdc_set_hw_if_params,
+		.set_params = ccdc_set_params,
+		.configure = ccdc_configure,
+		.set_buftype = ccdc_set_buftype,
+		.get_buftype = ccdc_get_buftype,
+		.enum_pix = ccdc_enum_pix,
+		.set_pixel_format = ccdc_set_pixel_format,
+		.get_pixel_format = ccdc_get_pixel_format,
+		.set_frame_format = ccdc_set_frame_format,
+		.get_frame_format = ccdc_get_frame_format,
+		.set_image_window = ccdc_set_image_window,
+		.get_image_window = ccdc_get_image_window,
+		.get_line_length = ccdc_get_line_length,
+		.setfbaddr = ccdc_setfbaddr,
+		.getfid = ccdc_getfid,
+	},
+};
+
+static int dm644x_ccdc_init(void)
+{
+	printk(KERN_NOTICE "dm644x_ccdc_init\n");
+	if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0)
+		return -1;
+	printk(KERN_NOTICE "%s is registered with vpfe.\n",
+		ccdc_hw_dev.name);
+	return 0;
+}
+
+static void dm644x_ccdc_exit(void)
+{
+	vpfe_unregister_ccdc_device(&ccdc_hw_dev);
+}
+
+module_init(dm644x_ccdc_init);
+module_exit(dm644x_ccdc_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/video/davinci/dm644x_ccdc_regs.h
new file mode 100644
index 0000000..6e5d053
--- /dev/null
+++ b/drivers/media/video/davinci/dm644x_ccdc_regs.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2006-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _DM644X_CCDC_REGS_H
+#define _DM644X_CCDC_REGS_H
+
+/**************************************************************************\
+* Register OFFSET Definitions
+\**************************************************************************/
+#define CCDC_PID				0x0
+#define CCDC_PCR				0x4
+#define CCDC_SYN_MODE				0x8
+#define CCDC_HD_VD_WID				0xc
+#define CCDC_PIX_LINES				0x10
+#define CCDC_HORZ_INFO				0x14
+#define CCDC_VERT_START				0x18
+#define CCDC_VERT_LINES				0x1c
+#define CCDC_CULLING				0x20
+#define CCDC_HSIZE_OFF				0x24
+#define CCDC_SDOFST				0x28
+#define CCDC_SDR_ADDR				0x2c
+#define CCDC_CLAMP				0x30
+#define CCDC_DCSUB				0x34
+#define CCDC_COLPTN				0x38
+#define CCDC_BLKCMP				0x3c
+#define CCDC_FPC				0x40
+#define CCDC_FPC_ADDR				0x44
+#define CCDC_VDINT				0x48
+#define CCDC_ALAW				0x4c
+#define CCDC_REC656IF				0x50
+#define CCDC_CCDCFG				0x54
+#define CCDC_FMTCFG				0x58
+#define CCDC_FMT_HORZ				0x5c
+#define CCDC_FMT_VERT				0x60
+#define CCDC_FMT_ADDR0				0x64
+#define CCDC_FMT_ADDR1				0x68
+#define CCDC_FMT_ADDR2				0x6c
+#define CCDC_FMT_ADDR3				0x70
+#define CCDC_FMT_ADDR4				0x74
+#define CCDC_FMT_ADDR5				0x78
+#define CCDC_FMT_ADDR6				0x7c
+#define CCDC_FMT_ADDR7				0x80
+#define CCDC_PRGEVEN_0				0x84
+#define CCDC_PRGEVEN_1				0x88
+#define CCDC_PRGODD_0				0x8c
+#define CCDC_PRGODD_1				0x90
+#define CCDC_VP_OUT				0x94
+
+
+/***************************************************************
+*	Define for various register bit mask and shifts for CCDC
+****************************************************************/
+#define CCDC_FID_POL_MASK			1
+#define CCDC_FID_POL_SHIFT			4
+#define CCDC_HD_POL_MASK			1
+#define CCDC_HD_POL_SHIFT			3
+#define CCDC_VD_POL_MASK			1
+#define CCDC_VD_POL_SHIFT			2
+#define CCDC_HSIZE_OFF_MASK			0xffffffe0
+#define CCDC_32BYTE_ALIGN_VAL			31
+#define CCDC_FRM_FMT_MASK			0x1
+#define CCDC_FRM_FMT_SHIFT			7
+#define CCDC_DATA_SZ_MASK			7
+#define CCDC_DATA_SZ_SHIFT			8
+#define CCDC_PIX_FMT_MASK			3
+#define CCDC_PIX_FMT_SHIFT			12
+#define CCDC_VP2SDR_DISABLE			0xFFFBFFFF
+#define CCDC_WEN_ENABLE				(1 << 17)
+#define CCDC_SDR2RSZ_DISABLE			0xFFF7FFFF
+#define CCDC_VDHDEN_ENABLE			(1 << 16)
+#define CCDC_LPF_ENABLE				(1 << 14)
+#define CCDC_ALAW_ENABLE			(1 << 3)
+#define CCDC_ALAW_GAMA_WD_MASK			7
+#define CCDC_BLK_CLAMP_ENABLE			(1 << 31)
+#define CCDC_BLK_SGAIN_MASK			0x1F
+#define CCDC_BLK_ST_PXL_MASK			0x7FFF
+#define CCDC_BLK_ST_PXL_SHIFT			10
+#define CCDC_BLK_SAMPLE_LN_MASK			7
+#define CCDC_BLK_SAMPLE_LN_SHIFT		28
+#define CCDC_BLK_SAMPLE_LINE_MASK		7
+#define CCDC_BLK_SAMPLE_LINE_SHIFT		25
+#define CCDC_BLK_DC_SUB_MASK			0x03FFF
+#define CCDC_BLK_COMP_MASK			0xFF
+#define CCDC_BLK_COMP_GB_COMP_SHIFT		8
+#define CCDC_BLK_COMP_GR_COMP_SHIFT		16
+#define CCDC_BLK_COMP_R_COMP_SHIFT		24
+#define CCDC_LATCH_ON_VSYNC_DISABLE		(1 << 15)
+#define CCDC_FPC_ENABLE				(1 << 15)
+#define CCDC_FPC_DISABLE			0
+#define CCDC_FPC_FPC_NUM_MASK 			0x7FFF
+#define CCDC_DATA_PACK_ENABLE			(1 << 11)
+#define CCDC_FMTCFG_VPIN_MASK			7
+#define CCDC_FMTCFG_VPIN_SHIFT			12
+#define CCDC_FMT_HORZ_FMTLNH_MASK		0x1FFF
+#define CCDC_FMT_HORZ_FMTSPH_MASK		0x1FFF
+#define CCDC_FMT_HORZ_FMTSPH_SHIFT		16
+#define CCDC_FMT_VERT_FMTLNV_MASK		0x1FFF
+#define CCDC_FMT_VERT_FMTSLV_MASK		0x1FFF
+#define CCDC_FMT_VERT_FMTSLV_SHIFT		16
+#define CCDC_VP_OUT_VERT_NUM_MASK		0x3FFF
+#define CCDC_VP_OUT_VERT_NUM_SHIFT		17
+#define CCDC_VP_OUT_HORZ_NUM_MASK		0x1FFF
+#define CCDC_VP_OUT_HORZ_NUM_SHIFT		4
+#define CCDC_VP_OUT_HORZ_ST_MASK		0xF
+#define CCDC_HORZ_INFO_SPH_SHIFT		16
+#define CCDC_VERT_START_SLV0_SHIFT		16
+#define CCDC_VDINT_VDINT0_SHIFT			16
+#define CCDC_VDINT_VDINT1_MASK			0xFFFF
+#define CCDC_PPC_RAW				1
+#define CCDC_DCSUB_DEFAULT_VAL			0
+#define CCDC_CLAMP_DEFAULT_VAL			0
+#define CCDC_ENABLE_VIDEO_PORT			0x8000
+#define CCDC_DISABLE_VIDEO_PORT			0
+#define CCDC_COLPTN_VAL				0xBB11BB11
+#define CCDC_TWO_BYTES_PER_PIXEL		2
+#define CCDC_INTERLACED_IMAGE_INVERT		0x4B6D
+#define CCDC_INTERLACED_NO_IMAGE_INVERT		0x0249
+#define CCDC_PROGRESSIVE_IMAGE_INVERT		0x4000
+#define CCDC_PROGRESSIVE_NO_IMAGE_INVERT	0
+#define CCDC_INTERLACED_HEIGHT_SHIFT		1
+#define CCDC_SYN_MODE_INPMOD_SHIFT		12
+#define CCDC_SYN_MODE_INPMOD_MASK		3
+#define CCDC_SYN_MODE_8BITS			(7 << 8)
+#define CCDC_SYN_FLDMODE_MASK			1
+#define CCDC_SYN_FLDMODE_SHIFT			7
+#define CCDC_REC656IF_BT656_EN			3
+#define CCDC_SYN_MODE_VD_POL_NEGATIVE		(1 << 2)
+#define CCDC_CCDCFG_Y8POS_SHIFT			11
+#define CCDC_SDOFST_FIELD_INTERLEAVED		0x249
+#define CCDC_NO_CULLING				0xffff00ff
+#endif
diff --git a/include/media/davinci/dm644x_ccdc.h b/include/media/davinci/dm644x_ccdc.h
new file mode 100644
index 0000000..3e178eb
--- /dev/null
+++ b/include/media/davinci/dm644x_ccdc.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2006-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _DM644X_CCDC_H
+#define _DM644X_CCDC_H
+#include <media/davinci/ccdc_types.h>
+#include <media/davinci/vpfe_types.h>
+
+/* enum for No of pixel per line to be avg. in Black Clamping*/
+enum ccdc_sample_length {
+	CCDC_SAMPLE_1PIXELS,
+	CCDC_SAMPLE_2PIXELS,
+	CCDC_SAMPLE_4PIXELS,
+	CCDC_SAMPLE_8PIXELS,
+	CCDC_SAMPLE_16PIXELS
+};
+
+/* enum for No of lines in Black Clamping */
+enum ccdc_sample_line {
+	CCDC_SAMPLE_1LINES,
+	CCDC_SAMPLE_2LINES,
+	CCDC_SAMPLE_4LINES,
+	CCDC_SAMPLE_8LINES,
+	CCDC_SAMPLE_16LINES
+};
+
+/* enum for Alaw gama width */
+enum ccdc_gama_width {
+	CCDC_GAMMA_BITS_15_6,
+	CCDC_GAMMA_BITS_14_5,
+	CCDC_GAMMA_BITS_13_4,
+	CCDC_GAMMA_BITS_12_3,
+	CCDC_GAMMA_BITS_11_2,
+	CCDC_GAMMA_BITS_10_1,
+	CCDC_GAMMA_BITS_09_0
+};
+
+enum ccdc_data_size {
+	CCDC_DATA_16BITS,
+	CCDC_DATA_15BITS,
+	CCDC_DATA_14BITS,
+	CCDC_DATA_13BITS,
+	CCDC_DATA_12BITS,
+	CCDC_DATA_11BITS,
+	CCDC_DATA_10BITS,
+	CCDC_DATA_8BITS
+};
+
+/* structure for ALaw */
+struct ccdc_a_law {
+	/* Enable/disable A-Law */
+	unsigned char enable;
+	/* Gama Width Input */
+	enum ccdc_gama_width gama_wd;
+};
+
+/* structure for Black Clamping */
+struct ccdc_black_clamp {
+	unsigned char enable;
+	/* only if bClampEnable is TRUE */
+	enum ccdc_sample_length sample_pixel;
+	/* only if bClampEnable is TRUE */
+	enum ccdc_sample_line sample_ln;
+	/* only if bClampEnable is TRUE */
+	unsigned short start_pixel;
+	/* only if bClampEnable is TRUE */
+	unsigned short sgain;
+	/* only if bClampEnable is FALSE */
+	unsigned short dc_sub;
+};
+
+/* structure for Black Level Compensation */
+struct ccdc_black_compensation {
+	/* Constant value to subtract from Red component */
+	char r;
+	/* Constant value to subtract from Gr component */
+	char gr;
+	/* Constant value to subtract from Blue component */
+	char b;
+	/* Constant value to subtract from Gb component */
+	char gb;
+};
+
+/* structure for fault pixel correction */
+struct ccdc_fault_pixel {
+	/* Enable or Disable fault pixel correction */
+	unsigned char enable;
+	/* Number of fault pixel */
+	unsigned short fp_num;
+	/* Address of fault pixel table */
+	unsigned int fpc_table_addr;
+};
+
+/* Structure for CCDC configuration parameters for raw capture mode passed
+ * by application
+ */
+struct ccdc_config_params_raw {
+	/* data size value from 8 to 16 bits */
+	enum ccdc_data_size data_sz;
+	/* Structure for Optional A-Law */
+	struct ccdc_a_law alaw;
+	/* Structure for Optical Black Clamp */
+	struct ccdc_black_clamp blk_clamp;
+	/* Structure for Black Compensation */
+	struct ccdc_black_compensation blk_comp;
+	/* Structure for Fault Pixel Module Configuration */
+	struct ccdc_fault_pixel fault_pxl;
+};
+
+
+#ifdef __KERNEL__
+#include <linux/io.h>
+/* Define to enable/disable video port */
+#define FP_NUM_BYTES		4
+/* Define for extra pixel/line and extra lines/frame */
+#define NUM_EXTRAPIXELS		8
+#define NUM_EXTRALINES		8
+
+/* settings for commonly used video formats */
+#define CCDC_WIN_PAL     {0, 0, 720, 576}
+/* ntsc square pixel */
+#define CCDC_WIN_VGA	{0, 0, (640 + NUM_EXTRAPIXELS), (480 + NUM_EXTRALINES)}
+
+/* Structure for CCDC configuration parameters for raw capture mode */
+struct ccdc_params_raw {
+	/* pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* progressive or interlaced frame */
+	enum ccdc_frmfmt frm_fmt;
+	/* video window */
+	struct v4l2_rect win;
+	/* field id polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* vertical sync polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* horizontal sync polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* interleaved or separated fields */
+	enum ccdc_buftype buf_type;
+	/*
+	 * enable to store the image in inverse
+	 * order in memory(bottom to top)
+	 */
+	unsigned char image_invert_enable;
+	/* configurable paramaters */
+	struct ccdc_config_params_raw config_params;
+};
+
+struct ccdc_params_ycbcr {
+	/* pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* progressive or interlaced frame */
+	enum ccdc_frmfmt frm_fmt;
+	/* video window */
+	struct v4l2_rect win;
+	/* field id polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* vertical sync polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* horizontal sync polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* enable BT.656 embedded sync mode */
+	int bt656_enable;
+	/* cb:y:cr:y or y:cb:y:cr in memory */
+	enum ccdc_pixorder pix_order;
+	/* interleaved or separated fields  */
+	enum ccdc_buftype buf_type;
+};
+#endif
+#endif				/* _DM644X_CCDC_H */
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 5/10 - v2] ccdc types used across ccdc modules for vpfe capture driver
  2009-06-11 17:00       ` [PATCH 4/10 - v2] dm644x " m-karicheri2
@ 2009-06-11 17:00         ` m-karicheri2
  2009-06-11 17:00           ` [PATCH 6/10 - v2] Makefile and config files " m-karicheri2
  0 siblings, 1 reply; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

common types used across CCDC modules

No change from last version

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 include/media/davinci/ccdc_types.h |   43 ++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)
 create mode 100644 include/media/davinci/ccdc_types.h

diff --git a/include/media/davinci/ccdc_types.h b/include/media/davinci/ccdc_types.h
new file mode 100644
index 0000000..5773874
--- /dev/null
+++ b/include/media/davinci/ccdc_types.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ **************************************************************************/
+#ifndef _CCDC_TYPES_H
+#define _CCDC_TYPES_H
+enum ccdc_pixfmt {
+	CCDC_PIXFMT_RAW,
+	CCDC_PIXFMT_YCBCR_16BIT,
+	CCDC_PIXFMT_YCBCR_8BIT
+};
+
+enum ccdc_frmfmt {
+	CCDC_FRMFMT_PROGRESSIVE,
+	CCDC_FRMFMT_INTERLACED
+};
+
+/* PIXEL ORDER IN MEMORY from LSB to MSB */
+/* only applicable for 8-bit input mode  */
+enum ccdc_pixorder {
+	CCDC_PIXORDER_YCBYCR,
+	CCDC_PIXORDER_CBYCRY,
+};
+
+enum ccdc_buftype {
+	CCDC_BUFTYPE_FLD_INTERLEAVED,
+	CCDC_BUFTYPE_FLD_SEPARATED
+};
+#endif
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 6/10 - v2] Makefile and config files for vpfe capture driver
  2009-06-11 17:00         ` [PATCH 5/10 - v2] ccdc types used across ccdc modules " m-karicheri2
@ 2009-06-11 17:00           ` m-karicheri2
  2009-06-11 17:00             ` [PATCH 7/10 - v2] DM355 platform changes " m-karicheri2
  0 siblings, 1 reply; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

Makefile and config files for the driver

This adds Makefile and Kconfig changes to build vpfe capture driver.

Added configuration variable for vpss driver based on last review

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 drivers/media/video/Kconfig          |   49 ++++++++++++++++++++++++++++++++++
 drivers/media/video/Makefile         |    1 +
 drivers/media/video/davinci/Makefile |    9 ++++++
 3 files changed, 59 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/Makefile

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 9d48da2..ee6806c 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -479,6 +479,55 @@ config VIDEO_VIVI
 	  Say Y here if you want to test video apps or debug V4L devices.
 	  In doubt, say N.
 
+config VIDEO_VPSS_SYSTEM
+	tristate "VPSS System module driver"
+	depends on ARCH_DAVINCI
+	help
+	  Support for vpss system module for video driver
+	default y
+
+config VIDEO_VPFE_CAPTURE
+	tristate "VPFE Video Capture Driver"
+	depends on VIDEO_V4L2 && ARCH_DAVINCI
+	select VIDEOBUF_DMA_CONTIG
+	help
+	  Support for DMXXXX VPFE based frame grabber. This is the
+	  common V4L2 module for following DMXXX SoCs from Texas
+	  Instruments:- DM6446 & DM355.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vpfe-capture.
+
+config VIDEO_DM6446_CCDC
+	tristate "DM6446 CCDC HW module"
+	depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE
+	select VIDEO_VPSS_SYSTEM
+	default y
+	help
+	   Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
+	   with decoder modules such as TVP5146 over BT656 or
+	   sensor module such as MT9T001 over a raw interface. This
+	   module configures the interface and CCDC/ISIF to do
+	   video frame capture from slave decoders.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called vpfe.
+
+config VIDEO_DM355_CCDC
+	tristate "DM355 CCDC HW module"
+	depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE
+	select VIDEO_VPSS_SYSTEM
+	default y
+	help
+	   Enables DM355 CCD hw module. DM355 CCDC hw interfaces
+	   with decoder modules such as TVP5146 over BT656 or
+	   sensor module such as MT9T001 over a raw interface. This
+	   module configures the interface and CCDC/ISIF to do
+	   video frame capture from a slave decoders
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called vpfe.
+
 source "drivers/media/video/bt8xx/Kconfig"
 
 config VIDEO_PMS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 3f1a035..bc8ac8e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -147,6 +147,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
 obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
 obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc_camera_platform.o
 obj-$(CONFIG_SOC_CAMERA_TW9910)		+= tw9910.o
+obj-$(CONFIG_ARCH_DAVINCI)        += davinci/
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828/
 
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile
new file mode 100644
index 0000000..b84a405
--- /dev/null
+++ b/drivers/media/video/davinci/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the davinci video device drivers.
+#
+
+# Capture: DM6446 and DM355
+obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o
+obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
+obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o
+obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 7/10 - v2] DM355 platform changes for vpfe capture driver
  2009-06-11 17:00           ` [PATCH 6/10 - v2] Makefile and config files " m-karicheri2
@ 2009-06-11 17:00             ` m-karicheri2
  2009-06-11 17:00               ` [PATCH 8/10 - v2] DM6446 " m-karicheri2
                                 ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

DM355 platform and board setup

This has platform and board setup changes to support vpfe capture
driver for DM355 EVMs.

Added registration of vpss platform driver based on last review

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to Davinci GIT Tree

 arch/arm/mach-davinci/board-dm355-evm.c    |   72 +++++++++++++++++++++++-
 arch/arm/mach-davinci/dm355.c              |   83 ++++++++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/dm355.h |    2 +
 arch/arm/mach-davinci/include/mach/mux.h   |    9 +++
 4 files changed, 163 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 5ac2f56..cf87e21 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -20,6 +20,8 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
+#include <linux/videodev2.h>
+#include <media/tvp514x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
 
@@ -134,12 +136,23 @@ static void dm355evm_mmcsd_gpios(unsigned gpio)
 	dm355evm_mmc_gpios = gpio;
 }
 
+#define TVP5146_I2C_ADDR		0x5D
+static struct tvp514x_platform_data tvp5146_pdata = {
+	.clk_polarity = 0,
+	.hs_polarity = 1,
+	.vs_polarity = 1
+};
+
 static struct i2c_board_info dm355evm_i2c_info[] = {
-	{ I2C_BOARD_INFO("dm355evm_msp", 0x25),
+	{	I2C_BOARD_INFO("dm355evm_msp", 0x25),
 		.platform_data = dm355evm_mmcsd_gpios,
-		/* plus irq */ },
+	},
+	{
+		I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),
+		.platform_data = &tvp5146_pdata,
+	},
+	/* { plus irq  }, */
 	/* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
-	/* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
 };
 
 static void __init evm_init_i2c(void)
@@ -178,6 +191,57 @@ static struct platform_device dm355evm_dm9000 = {
 	.num_resources	= ARRAY_SIZE(dm355evm_dm9000_rsrc),
 };
 
+#define TVP514X_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
+/* Inputs available at the TVP5146 */
+static struct v4l2_input tvp5146_inputs[] = {
+	{
+		.index = 0,
+		.name = "COMPOSITE",
+		.type = V4L2_INPUT_TYPE_CAMERA,
+		.std = TVP514X_STD_ALL,
+	},
+	{
+		.index = 1,
+		.name = "SVIDEO",
+		.type = V4L2_INPUT_TYPE_CAMERA,
+		.std = TVP514X_STD_ALL,
+	},
+};
+
+/*
+ * this is the route info for connecting each input to decoder
+ * ouput that goes to vpfe. There is a one to one correspondence
+ * with tvp5146_inputs
+ */
+static struct v4l2_routing tvp5146_routes[] = {
+	{
+		.input = INPUT_CVBS_VI2B,
+		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+	},
+	{
+		.input = INPUT_SVIDEO_VI2C_VI1C,
+		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+	},
+};
+
+static struct vpfe_subdev_info vpfe_sub_devs[] = {
+	{
+		.name = "tvp5146",
+		.grp_id = 0,
+		.num_inputs = ARRAY_SIZE(tvp5146_inputs),
+		.inputs = tvp5146_inputs,
+		.routes = tvp5146_routes,
+		.can_route = 1,
+	}
+};
+
+static struct vpfe_config vpfe_cfg = {
+	.num_subdevs = ARRAY_SIZE(vpfe_sub_devs),
+	.sub_devs = vpfe_sub_devs,
+	.card_name = "DM355 EVM",
+	.ccdc = "DM355 CCDC",
+};
+
 static struct platform_device *davinci_evm_devices[] __initdata = {
 	&dm355evm_dm9000,
 	&davinci_nand_device,
@@ -189,6 +253,8 @@ static struct davinci_uart_config uart_config __initdata = {
 
 static void __init dm355_evm_map_io(void)
 {
+	/* setup input configuration for VPFE input devices */
+	dm355_set_vpfe_config(&vpfe_cfg);
 	dm355_init();
 }
 
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 9baeed3..3263af8 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -481,6 +481,14 @@ INT_CFG(DM355,  INT_EDMA_TC1_ERR,     4,    1,    1,     false)
 EVT_CFG(DM355,  EVT8_ASP1_TX,	      0,    1,    0,     false)
 EVT_CFG(DM355,  EVT9_ASP1_RX,	      1,    1,    0,     false)
 EVT_CFG(DM355,  EVT26_MMC0_RX,	      2,    1,    0,     false)
+
+MUX_CFG(DM355,	VIN_PCLK,	0,   14,    1,    1,	 false)
+MUX_CFG(DM355,	VIN_CAM_WEN,	0,   13,    1,    1,	 false)
+MUX_CFG(DM355,	VIN_CAM_VD,	0,   12,    1,    1,	 false)
+MUX_CFG(DM355,	VIN_CAM_HD,	0,   11,    1,    1,	 false)
+MUX_CFG(DM355,	VIN_YIN_EN,	0,   10,    1,    1,	 false)
+MUX_CFG(DM355,	VIN_CINL_EN,	0,   0,   0xff, 0x55,	 false)
+MUX_CFG(DM355,	VIN_CINH_EN,	0,   8,     3,    3,	 false)
 #endif
 };
 
@@ -623,6 +631,67 @@ static struct platform_device dm355_edma_device = {
 	.resource		= edma_resources,
 };
 
+static struct resource dm355_vpss_resources[] = {
+	{
+		/* VPSS BL Base address */
+		.name		= "vpss",
+		.start          = 0x01c70800,
+		.end            = 0x01c70800 + 0xff,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		/* VPSS CLK Base address */
+		.name		= "vpss",
+		.start          = 0x01c70000,
+		.end            = 0x01c70000 + 0xf,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm355_vpss_device = {
+	.name			= "vpss",
+	.id			= -1,
+	.dev.platform_data	= "dm355_vpss",
+	.num_resources		= ARRAY_SIZE(dm355_vpss_resources),
+	.resource		= dm355_vpss_resources,
+};
+
+static struct resource vpfe_resources[] = {
+	{
+		.start          = IRQ_VDINT0,
+		.end            = IRQ_VDINT0,
+		.flags          = IORESOURCE_IRQ,
+	},
+	{
+		.start          = IRQ_VDINT1,
+		.end            = IRQ_VDINT1,
+		.flags          = IORESOURCE_IRQ,
+	},
+	/* CCDC Base address */
+	{
+		.flags          = IORESOURCE_MEM,
+		.start          = 0x01c70600,
+		.end            = 0x01c70600 + 0x1ff,
+	},
+};
+
+static u64 vpfe_capture_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device vpfe_capture_dev = {
+	.name		= CAPTURE_DRV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(vpfe_resources),
+	.resource	= vpfe_resources,
+	.dev = {
+		.dma_mask		= &vpfe_capture_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void dm355_set_vpfe_config(struct vpfe_config *cfg)
+{
+	vpfe_capture_dev.dev.platform_data = cfg;
+}
+
 /*----------------------------------------------------------------------*/
 
 static struct map_desc dm355_io_desc[] = {
@@ -744,6 +813,20 @@ static int __init dm355_init_devices(void)
 
 	davinci_cfg_reg(DM355_INT_EDMA_CC);
 	platform_device_register(&dm355_edma_device);
+	platform_device_register(&dm355_vpss_device);
+	/*
+	 * setup Mux configuration for vpfe input and register
+	 * vpfe capture platform device
+	 */
+	davinci_cfg_reg(DM355_VIN_PCLK);
+	davinci_cfg_reg(DM355_VIN_CAM_WEN);
+	davinci_cfg_reg(DM355_VIN_CAM_VD);
+	davinci_cfg_reg(DM355_VIN_CAM_HD);
+	davinci_cfg_reg(DM355_VIN_YIN_EN);
+	davinci_cfg_reg(DM355_VIN_CINL_EN);
+	davinci_cfg_reg(DM355_VIN_CINH_EN);
+	platform_device_register(&vpfe_capture_dev);
+
 	return 0;
 }
 postcore_initcall(dm355_init_devices);
diff --git a/arch/arm/mach-davinci/include/mach/dm355.h b/arch/arm/mach-davinci/include/mach/dm355.h
index 54903b7..e28713c 100644
--- a/arch/arm/mach-davinci/include/mach/dm355.h
+++ b/arch/arm/mach-davinci/include/mach/dm355.h
@@ -12,11 +12,13 @@
 #define __ASM_ARCH_DM355_H
 
 #include <mach/hardware.h>
+#include <media/davinci/vpfe_capture.h>
 
 struct spi_board_info;
 
 void __init dm355_init(void);
 void dm355_init_spi0(unsigned chipselect_mask,
 		struct spi_board_info *info, unsigned len);
+void dm355_set_vpfe_config(struct vpfe_config *cfg);
 
 #endif /* __ASM_ARCH_DM355_H */
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index 2737845..f288063 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -154,6 +154,15 @@ enum davinci_dm355_index {
 	DM355_EVT8_ASP1_TX,
 	DM355_EVT9_ASP1_RX,
 	DM355_EVT26_MMC0_RX,
+
+	/* Video In Pin Mux */
+	DM355_VIN_PCLK,
+	DM355_VIN_CAM_WEN,
+	DM355_VIN_CAM_VD,
+	DM355_VIN_CAM_HD,
+	DM355_VIN_YIN_EN,
+	DM355_VIN_CINL_EN,
+	DM355_VIN_CINH_EN,
 };
 
 #ifdef CONFIG_DAVINCI_MUX
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 8/10 - v2] DM6446 platform changes for vpfe capture driver
  2009-06-11 17:00             ` [PATCH 7/10 - v2] DM355 platform changes " m-karicheri2
@ 2009-06-11 17:00               ` m-karicheri2
  2009-06-11 17:00                 ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 m-karicheri2
  2009-06-14 14:24                 ` [PATCH 8/10 - v2] DM6446 platform changes for vpfe capture driver Hans Verkuil
  2009-06-11 20:23               ` [PATCH 7/10 - v2] DM355 " David Brownell
  2009-06-14 14:22               ` Hans Verkuil
  2 siblings, 2 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

DM644x platform and board setup

This adds plarform and board setup changes required to support
vpfe capture driver on DM644x

Added registration of vpss platform driver based on last comment

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to Davinci GIT Tree

 arch/arm/mach-davinci/board-dm644x-evm.c    |   68 ++++++++++++++++++++++++++-
 arch/arm/mach-davinci/dm644x.c              |   56 ++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/dm644x.h |    2 +
 3 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index d9d4045..13b73a7 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -28,7 +28,8 @@
 #include <linux/io.h>
 #include <linux/phy.h>
 #include <linux/clk.h>
-
+#include <linux/videodev2.h>
+#include <media/tvp514x.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
@@ -195,6 +196,57 @@ static struct platform_device davinci_fb_device = {
 	.num_resources = 0,
 };
 
+#define TVP514X_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
+/* Inputs available at the TVP5146 */
+static struct v4l2_input tvp5146_inputs[] = {
+	{
+		.index = 0,
+		.name = "COMPOSITE",
+		.type = V4L2_INPUT_TYPE_CAMERA,
+		.std = TVP514X_STD_ALL,
+	},
+	{
+		.index = 1,
+		.name = "SVIDEO",
+		.type = V4L2_INPUT_TYPE_CAMERA,
+		.std = TVP514X_STD_ALL,
+	},
+};
+
+/*
+ * this is the route info for connecting each input to decoder
+ * ouput that goes to vpfe. There is a one to one correspondence
+ * with tvp5146_inputs
+ */
+static struct v4l2_routing tvp5146_routes[] = {
+	{
+		.input = INPUT_CVBS_VI2B,
+		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+	},
+	{
+		.input = INPUT_SVIDEO_VI2C_VI1C,
+		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+	},
+};
+
+static struct vpfe_subdev_info vpfe_sub_devs[] = {
+	{
+		.name = "tvp5146",
+		.grp_id = 0,
+		.num_inputs = ARRAY_SIZE(tvp5146_inputs),
+		.inputs = tvp5146_inputs,
+		.routes = tvp5146_routes,
+		.can_route = 1,
+	},
+};
+
+static struct vpfe_config vpfe_cfg = {
+	.num_subdevs = ARRAY_SIZE(vpfe_sub_devs),
+	.sub_devs = vpfe_sub_devs,
+	.card_name = "DM6446 EVM",
+	.ccdc = "DM6446 CCDC",
+};
+
 static struct platform_device rtc_dev = {
 	.name           = "rtc_davinci_evm",
 	.id             = -1,
@@ -447,6 +499,13 @@ static struct at24_platform_data eeprom_info = {
 	.context	= (void *)0x7f00,
 };
 
+#define TVP5146_I2C_ADDR		(0x5D)
+static struct tvp514x_platform_data tvp5146_pdata = {
+	.clk_polarity = 0,
+	.hs_polarity = 1,
+	.vs_polarity = 1
+};
+
 /*
  * MSP430 supports RTC, card detection, input from IR remote, and
  * a bit more.  It triggers interrupts on GPIO(7) from pressing
@@ -558,9 +617,12 @@ static struct i2c_board_info __initdata i2c_info[] =  {
 		I2C_BOARD_INFO("24c256", 0x50),
 		.platform_data	= &eeprom_info,
 	},
+	{
+		I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),
+		.platform_data = &tvp5146_pdata,
+	},
 	/* ALSO:
 	 * - tvl320aic33 audio codec (0x1b)
-	 * - tvp5146 video decoder (0x5d)
 	 */
 };
 
@@ -591,6 +653,8 @@ static struct davinci_uart_config uart_config __initdata = {
 static void __init
 davinci_evm_map_io(void)
 {
+	/* setup input configuration for VPFE input devices */
+	dm644x_set_vpfe_config(&vpfe_cfg);
 	dm644x_init();
 }
 
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 1b3aec8..444c4df 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -549,6 +549,59 @@ static struct platform_device dm644x_edma_device = {
 	.resource		= edma_resources,
 };
 
+static struct resource dm644x_vpss_resources[] = {
+	{
+		/* VPSS Base address */
+		.name		= "vpss",
+		.start          = 0x01c73400,
+		.end            = 0x01c73400 + 0xff,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm644x_vpss_device = {
+	.name			= "vpss",
+	.id			= -1,
+	.dev.platform_data	= "dm644x_vpss",
+	.num_resources		= ARRAY_SIZE(dm644x_vpss_resources),
+	.resource		= dm644x_vpss_resources,
+};
+
+static struct resource vpfe_resources[] = {
+	{
+		.start          = IRQ_VDINT0,
+		.end            = IRQ_VDINT0,
+		.flags          = IORESOURCE_IRQ,
+	},
+	{
+		.start          = IRQ_VDINT1,
+		.end            = IRQ_VDINT1,
+		.flags          = IORESOURCE_IRQ,
+	},
+	{
+		.start          = 0x01c70400,
+		.end            = 0x01c70400 + 0xff,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+static u64 vpfe_capture_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device vpfe_capture_dev = {
+	.name		= CAPTURE_DRV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(vpfe_resources),
+	.resource	= vpfe_resources,
+	.dev = {
+		.dma_mask		= &vpfe_capture_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void dm644x_set_vpfe_config(struct vpfe_config *cfg)
+{
+	vpfe_capture_dev.dev.platform_data = cfg;
+}
+
 /*----------------------------------------------------------------------*/
 
 static struct map_desc dm644x_io_desc[] = {
@@ -678,6 +731,9 @@ static int __init dm644x_init_devices(void)
 
 	platform_device_register(&dm644x_edma_device);
 	platform_device_register(&dm644x_emac_device);
+	platform_device_register(&dm644x_vpss_device);
+	platform_device_register(&vpfe_capture_dev);
+
 	return 0;
 }
 postcore_initcall(dm644x_init_devices);
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h
index 15d42b9..0066db3 100644
--- a/arch/arm/mach-davinci/include/mach/dm644x.h
+++ b/arch/arm/mach-davinci/include/mach/dm644x.h
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <mach/hardware.h>
 #include <mach/emac.h>
+#include <media/davinci/vpfe_capture.h>
 
 #define DM644X_EMAC_BASE		(0x01C80000)
 #define DM644X_EMAC_CNTRL_OFFSET	(0x0000)
@@ -34,5 +35,6 @@
 #define DM644X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 void __init dm644x_init(void);
+void dm644x_set_vpfe_config(struct vpfe_config *cfg);
 
 #endif /* __ASM_ARCH_DM644X_H */
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 9/10 - v2] remove outdated video driver files of dm6446
  2009-06-11 17:00               ` [PATCH 8/10 - v2] DM6446 " m-karicheri2
@ 2009-06-11 17:00                 ` m-karicheri2
  2009-06-11 17:00                   ` [PATCH 10/10 - v2] common vpss module for video drivers m-karicheri2
  2009-06-11 20:23                   ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 Kevin Hilman
  2009-06-14 14:24                 ` [PATCH 8/10 - v2] DM6446 platform changes for vpfe capture driver Hans Verkuil
  1 sibling, 2 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

Remove outdated driver files from davinci git tree

No change from last patch

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to Davinci GIT Tree

 drivers/media/video/ccdc_davinci.c |  124 ----
 drivers/media/video/davinci_vpfe.c | 1136 ------------------------------------
 include/media/ccdc_davinci.h       |  144 -----
 include/media/davinci_vpfe.h       |  121 ----
 4 files changed, 0 insertions(+), 1525 deletions(-)
 delete mode 100644 drivers/media/video/ccdc_davinci.c
 delete mode 100644 drivers/media/video/davinci_vpfe.c
 delete mode 100644 include/media/ccdc_davinci.h
 delete mode 100644 include/media/davinci_vpfe.h

diff --git a/drivers/media/video/ccdc_davinci.c b/drivers/media/video/ccdc_davinci.c
deleted file mode 100644
index d3cd333..0000000
--- a/drivers/media/video/ccdc_davinci.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *
- *
- * Copyright (C) 2006 Texas Instruments Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/* ccdc_davinci.c */
-
-#include <media/ccdc_davinci.h>
-#define debug_print(x...)	//printk(x)
-void ccdc_reset()
-{
-	int i;
-	/* disable CCDC */
-	ccdc_enable(0);
-	/* set all registers to default value */
-	for (i = 0; i <= 0x94; i += 4) {
-		regw(0, i);
-	}
-	regw(0, PCR);
-	regw(0, SYN_MODE);
-	regw(0, HD_VD_WID);
-	regw(0, PIX_LINES);
-	regw(0, HORZ_INFO);
-	regw(0, VERT_START);
-	regw(0, VERT_LINES);
-	regw(0xffff00ff, CULLING);
-	regw(0, HSIZE_OFF);
-	regw(0, SDOFST);
-	regw(0, SDR_ADDR);
-	regw(0, VDINT);
-	regw(0, REC656IF);
-	regw(0, CCDCFG);
-	regw(0, FMTCFG);
-	regw(0, VP_OUT);
-}
-
-void ccdc_setwin(ccdc_params_ycbcr * params)
-{
-	int horz_start, horz_nr_pixels;
-	int vert_start, vert_nr_lines;
-
-	/* configure horizonal and vertical starts and sizes */
-	horz_start = params->win.left << 1;
-	horz_nr_pixels = (params->win.width <<1) - 1;
-	regw((horz_start << 16) | horz_nr_pixels, HORZ_INFO);
-
-	vert_start = params->win.top;
-
-	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
-		vert_nr_lines = (params->win.height >> 1) - 1;
-		vert_start >>= 1;
-	} else {
-		vert_nr_lines = params->win.height - 1;
-	}
-	regw((vert_start << 16) | vert_start, VERT_START);
-	regw(vert_nr_lines, VERT_LINES);
-}
-
-void ccdc_config_ycbcr(ccdc_params_ycbcr * params)
-{
-	u32 syn_mode;
-
-	/* first reset the CCDC                                          */
-	/* all registers have default values after reset                 */
-	/* This is important since we assume default values to be set in */
-	/* a lot of registers that we didn't touch                       */
-	ccdc_reset();
-
-	/* configure pixel format */
-	syn_mode = (params->pix_fmt & 0x3) << 12;
-
-	/* configure video frame format */
-	syn_mode |= (params->frm_fmt & 0x1) << 7;
-
-	/* setup BT.656 sync mode */
-	if (params->bt656_enable) {
-		regw(3, REC656IF);
-
-		/* configure the FID, VD, HD pin polarity */
-		/* fld,hd pol positive, vd negative, 8-bit pack mode */
-		syn_mode |= 0x00000F04;
-	} else {/* y/c external sync mode */
-		syn_mode |= ((params->fid_pol & 0x1) << 4);
-		syn_mode |= ((params->hd_pol & 0x1) << 3);
-		syn_mode |= ((params->vd_pol & 0x1) << 2);
-	}
-
-	/* configure video window */
-	ccdc_setwin(params);
-
-	/* configure the order of y cb cr in SD-RAM */
-	regw((params->pix_order << 11) | 0x8000, CCDCFG);
-
-	/* configure the horizontal line offset */
-	/* this is done by rounding up width to a multiple of 16 pixels */
-	/* and multiply by two to account for y:cb:cr 4:2:2 data */
-	regw(((params->win.width * 2) + 31) & 0xffffffe0, HSIZE_OFF);
-
-	/* configure the memory line offset */
-	if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
-		/* two fields are interleaved in memory */
-		regw(0x00000249, SDOFST);
-	}
-	/* enable output to SDRAM */
-	syn_mode |= (0x1 << 17);
-	/* enable internal timing generator */
-	syn_mode |= (0x1 << 16);
-
-	regw(syn_mode, SYN_MODE);
-}
diff --git a/drivers/media/video/davinci_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/ccdc_davinci.h b/include/media/ccdc_davinci.h
deleted file mode 100644
index 9f0a08d..0000000
--- a/include/media/ccdc_davinci.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- * Copyright (C) 2006 Texas Instruments Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/* ccdc_davinci.h */
-
-#ifndef CCDC_DAVINCI_H
-#define CCDC_DAVINCI_H
-#include <linux/types.h>
-
-#ifdef __KERNEL__
-#include <asm/arch/hardware.h>
-#include <asm/io.h>
-#endif
-
-#include <linux/videodev.h>
-
-typedef enum ccdc_pixfmt {
-	CCDC_PIXFMT_RAW = 0,
-	CCDC_PIXFMT_YCBCR_16BIT = 1,
-	CCDC_PIXFMT_YCBCR_8BIT = 2
-} ccdc_pixfmt;
-
-typedef enum ccdc_frmfmt {
-	CCDC_FRMFMT_PROGRESSIVE = 0,
-	CCDC_FRMFMT_INTERLACED = 1
-} ccdc_frmfmt;
-
-typedef enum ccdc_pinpol {
-	CCDC_PINPOL_POSITIVE = 0,
-	CCDC_PINPOL_NEGATIVE = 1
-} ccdc_pinpol;
-
-/* PIXEL ORDER IN MEMORY from LSB to MSB */
-/* only applicable for 8-bit input mode  */
-typedef enum ccdc_pixorder {
-	CCDC_PIXORDER_CBYCRY = 1,
-	CCDC_PIXORDER_YCBYCR = 0
-} ccdc_pixorder;
-
-typedef enum ccdc_buftype {
-	CCDC_BUFTYPE_FLD_INTERLEAVED,
-	CCDC_BUFTYPE_FLD_SEPARATED
-} ccdc_buftype;
-
-typedef struct v4l2_rect ccdc_imgwin;
-
-typedef struct ccdc_params_ycbcr {
-	ccdc_pixfmt pix_fmt;	/* pixel format                     */
-	ccdc_frmfmt frm_fmt;	/* progressive or interlaced frame  */
-	ccdc_imgwin win;	/* video window                     */
-	ccdc_pinpol fid_pol;	/* field id polarity                */
-	ccdc_pinpol vd_pol;	/* vertical sync polarity           */
-	ccdc_pinpol hd_pol;	/* horizontal sync polarity         */
-	int bt656_enable;	/* enable BT.656 embedded sync mode */
-	ccdc_pixorder pix_order;/* cb:y:cr:y or y:cb:y:cr in memory */
-	ccdc_buftype buf_type;	/* interleaved or separated fields  */
-} ccdc_params_ycbcr;
-
-#ifdef __KERNEL__
-/**************************************************************************\
-* Register OFFSET Definitions
-\**************************************************************************/
-#define PID                             0x0
-#define PCR                             0x4
-#define SYN_MODE                        0x8
-#define HD_VD_WID                       0xc
-#define PIX_LINES                       0x10
-#define HORZ_INFO                       0x14
-#define VERT_START                      0x18
-#define VERT_LINES                      0x1c
-#define CULLING                         0x20
-#define HSIZE_OFF                       0x24
-#define SDOFST                          0x28
-#define SDR_ADDR                        0x2c
-#define CLAMP                           0x30
-#define DCSUB                           0x34
-#define COLPTN                          0x38
-#define BLKCMP                          0x3c
-#define FPC                             0x40
-#define FPC_ADDR                        0x44
-#define VDINT                           0x48
-#define ALAW                            0x4c
-#define REC656IF                        0x50
-#define CCDCFG                          0x54
-#define FMTCFG                          0x58
-#define FMT_HORZ                        0x5c
-#define FMT_VERT                        0x50
-#define FMT_ADDR0                       0x64
-#define FMT_ADDR1                       0x68
-#define FMT_ADDR2                       0x6c
-#define FMT_ADDR3                       0x70
-#define FMT_ADDR4                       0x74
-#define FMT_ADDR5                       0x78
-#define FMT_ADDR6                       0x7c
-#define FMT_ADDR7                       0x80
-#define PRGEVEN_0                       0x84
-#define PRGEVEN_1                       0x88
-#define PRGODD_0                        0x8c
-#define PRGODD_1                        0x90
-#define VP_OUT                          0x94
-
-#define CCDC_IOBASE                     (0x01c70400)
-
-#define regw(val, reg)    davinci_writel(val, (reg)+CCDC_IOBASE)
-#define regr(reg)         davinci_readl((reg)+CCDC_IOBASE)
-
-extern void ccdc_reset(void);
-extern void ccdc_config_ycbcr(ccdc_params_ycbcr * params);
-extern void ccdc_setwin(ccdc_params_ycbcr * params);
-
-/* inline functions that must be fast because they are called frequently */
-static inline void ccdc_enable(int flag)
-{
-	regw(flag, PCR);
-}
-
-static inline void ccdc_setfbaddr(unsigned long paddr)
-{
-	regw(paddr & 0xffffffe0, SDR_ADDR);
-}
-
-static inline int ccdc_getfid(void)
-{
-	int fid = (regr(SYN_MODE) >> 15) & 0x1;
-	return fid;
-}
-#endif
-
-#endif /* CCDC_DAVINCI_H */
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


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 10/10 - v2] common vpss module for video drivers
  2009-06-11 17:00                 ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 m-karicheri2
@ 2009-06-11 17:00                   ` m-karicheri2
  2009-06-11 23:23                     ` Alexey Klimov
  2009-06-14 14:26                     ` Hans Verkuil
  2009-06-11 20:23                   ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 Kevin Hilman
  1 sibling, 2 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-11 17:00 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

common voss module for video drivers

This is a new module added for vpss library functions that are
used for configuring vpss system module. All video drivers will
include vpss.h header file and call functions defined in this
module to configure vpss system module.


Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
 drivers/media/video/davinci/vpss.c |  290 ++++++++++++++++++++++++++++++++++++
 include/media/davinci/vpss.h       |   69 +++++++++
 2 files changed, 359 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/vpss.c
 create mode 100644 include/media/davinci/vpss.h

diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
new file mode 100644
index 0000000..def021e
--- /dev/null
+++ b/drivers/media/video/davinci/vpss.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * common vpss driver for all video drivers.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <media/davinci/vpss.h>
+
+/* DM644x defines */
+#define DM644X_SBL_PCR_VPSS		(4)
+
+/* vpss BL register offsets */
+#define DM355_VPSSBL_CCDCMUX		0x1c
+/* vpss CLK register offsets */
+#define DM355_VPSSCLK_CLKCTRL		0x04
+/* masks and shifts */
+#define VPSS_HSSISEL_SHIFT		4
+
+/*
+ * vpss operations. Depends on platform. Not all functions are available
+ * on all platforms. The api, first check if a functio is available before
+ * invoking it. In the probe, the function ptrs are intialized based on
+ * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
+ */
+struct vpss_hw_ops {
+	/* enable clock */
+	int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
+	/* select input to ccdc */
+	void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
+	/* clear wbl overlflow bit */
+	int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
+};
+
+/* vpss configuration */
+struct vpss_oper_config {
+	__iomem void *vpss_bl_regs_base;
+	__iomem void *vpss_regs_base;
+	struct resource		*r1;
+	resource_size_t		len1;
+	struct resource		*r2;
+	resource_size_t		len2;
+	char vpss_name[32];
+	spinlock_t vpss_lock;
+	struct vpss_hw_ops hw_ops;
+};
+
+static struct vpss_oper_config oper_cfg;
+
+/* register access routines */
+static inline u32 bl_regr(u32 offset)
+{
+	return __raw_readl(oper_cfg.vpss_bl_regs_base + offset);
+}
+
+static inline void bl_regw(u32 val, u32 offset)
+{
+	__raw_writel(val, oper_cfg.vpss_bl_regs_base + offset);
+}
+
+static inline u32 vpss_regr(u32 offset)
+{
+	return __raw_readl(oper_cfg.vpss_regs_base + offset);
+}
+
+static inline void vpss_regw(u32 val, u32 offset)
+{
+	__raw_writel(val, oper_cfg.vpss_regs_base + offset);
+}
+
+static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
+{
+	bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
+}
+
+int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
+{
+	if (!oper_cfg.hw_ops.select_ccdc_source)
+		return -1;
+
+	dm355_select_ccdc_source(src_sel);
+	return 0;
+}
+EXPORT_SYMBOL(vpss_select_ccdc_source);
+
+static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
+{
+	u32 mask = 1, val;
+
+	if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
+	    wbl_sel > VPSS_PCR_CCDC_WBL_O)
+		return -1;
+
+	/* writing a 0 clear the overflow */
+	mask = ~(mask << wbl_sel);
+	val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
+	bl_regw(val, DM644X_SBL_PCR_VPSS);
+	return 0;
+}
+
+int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
+{
+	if (!oper_cfg.hw_ops.clear_wbl_overflow)
+		return -1;
+
+	return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
+}
+EXPORT_SYMBOL(vpss_clear_wbl_overflow);
+
+/*
+ *  dm355_enable_clock - Enable VPSS Clock
+ *  @clock_sel: CLock to be enabled/disabled
+ *  @en: enable/disable flag
+ *
+ *  This is called to enable or disable a vpss clock
+ */
+static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
+{
+	unsigned long flags;
+	u32 utemp, mask = 0x1, shift = 0;
+
+	switch (clock_sel) {
+	case VPSS_VPBE_CLOCK:
+		/* nothing since lsb */
+		break;
+	case VPSS_VENC_CLOCK_SEL:
+		shift = 2;
+		break;
+	case VPSS_CFALD_CLOCK:
+		shift = 3;
+		break;
+	case VPSS_H3A_CLOCK:
+		shift = 4;
+		break;
+	case VPSS_IPIPE_CLOCK:
+		shift = 5;
+		break;
+	case VPSS_CCDC_CLOCK:
+		shift = 6;
+		break;
+	default:
+		printk(KERN_ERR "dm355_enable_clock:"
+				" Invalid selector: %d\n", clock_sel);
+		return -1;
+	}
+
+	spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
+	utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
+	if (!en)
+		utemp &= ~(mask << shift);
+	else
+		utemp |= (mask << shift);
+
+	vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
+	spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
+	return 0;
+}
+
+int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
+{
+	if (!oper_cfg.hw_ops.enable_clock)
+		return -1;
+
+	return oper_cfg.hw_ops.enable_clock(clock_sel, en);
+}
+EXPORT_SYMBOL(vpss_enable_clock);
+
+static int __init vpss_probe(struct platform_device *pdev)
+{
+	int			status;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "vpss, no platform data\n");
+		return -ENOENT;
+	}
+
+	strcpy(oper_cfg.vpss_name, pdev->dev.platform_data);
+	dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name);
+	oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!oper_cfg.r1)
+		return -ENOENT;
+
+	oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1;
+
+	oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1,
+					 oper_cfg.r1->name);
+	if (!oper_cfg.r1)
+		return -EBUSY;
+
+	oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1);
+	if (!oper_cfg.vpss_bl_regs_base) {
+		status = -EBUSY;
+		goto fail1;
+	}
+
+	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
+		oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!oper_cfg.r2) {
+			status = -ENOENT;
+			goto fail2;
+		}
+		oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1;
+		oper_cfg.r2 = request_mem_region(oper_cfg.r2->start,
+						 oper_cfg.len2,
+						 oper_cfg.r2->name);
+		if (!oper_cfg.r2) {
+			status = -EBUSY;
+			goto fail2;
+		}
+
+		oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start,
+						  oper_cfg.len2);
+		if (!oper_cfg.vpss_regs_base) {
+			status = -EBUSY;
+			goto fail3;
+		}
+	}
+
+	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
+		oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
+		oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
+	} else if (!strcmp(oper_cfg.vpss_name, "dm644x_vpss"))
+		oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
+	else
+		return -ENODEV;
+	spin_lock_init(&oper_cfg.vpss_lock);
+	dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name);
+	return 0;
+fail3:
+	release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
+fail2:
+	iounmap(oper_cfg.vpss_bl_regs_base);
+fail1:
+	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
+	return status;
+}
+
+static int vpss_remove(struct platform_device *pdev)
+{
+	iounmap(oper_cfg.vpss_bl_regs_base);
+	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
+	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
+		iounmap(oper_cfg.vpss_regs_base);
+		release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
+	}
+	return 0;
+}
+
+static struct platform_driver vpss_driver = {
+	.driver = {
+		.name	= "vpss",
+		.owner = THIS_MODULE,
+	},
+	.remove = __devexit_p(vpss_remove),
+	.probe = vpss_probe,
+};
+
+static void vpss_exit(void)
+{
+	platform_driver_unregister(&vpss_driver);
+}
+
+static int __init vpss_init(void)
+{
+	return platform_driver_register(&vpss_driver);
+}
+subsys_initcall(vpss_init);
+module_exit(vpss_exit);
+MODULE_LICENSE("GPL");
diff --git a/include/media/davinci/vpss.h b/include/media/davinci/vpss.h
new file mode 100644
index 0000000..fcdff74
--- /dev/null
+++ b/include/media/davinci/vpss.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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
+ *
+ * vpss - video processing subsystem module header file.
+ *
+ * Include this header file if a driver needs to configure vpss system
+ * module. It exports a set of library functions  for video drivers to
+ * configure vpss system module functions such as clock enable/disable,
+ * vpss interrupt mux to arm, and other common vpss system module
+ * functions.
+ */
+#ifndef _VPSS_H
+#define _VPSS_H
+
+/* selector for ccdc input selection on DM355 */
+enum vpss_ccdc_source_sel {
+	VPSS_CCDCIN,
+	VPSS_HSSIIN
+};
+
+/* Used for enable/diable VPSS Clock */
+enum vpss_clock_sel {
+	/* DM355/DM365 */
+	VPSS_CCDC_CLOCK,
+	VPSS_IPIPE_CLOCK,
+	VPSS_H3A_CLOCK,
+	VPSS_CFALD_CLOCK,
+	/*
+	 * When using VPSS_VENC_CLOCK_SEL in vpss_enable_clock() api
+	 * following applies:-
+	 * en = 0 selects ENC_CLK
+	 * en = 1 selects ENC_CLK/2
+	 */
+	VPSS_VENC_CLOCK_SEL,
+	VPSS_VPBE_CLOCK,
+};
+
+/* select input to ccdc on dm355 */
+int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel);
+/* enable/disable a vpss clock, 0 - success, -1 - failure */
+int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en);
+
+/* wbl reset for dm644x */
+enum vpss_wbl_sel {
+	VPSS_PCR_AEW_WBL_0 = 16,
+	VPSS_PCR_AF_WBL_0,
+	VPSS_PCR_RSZ4_WBL_0,
+	VPSS_PCR_RSZ3_WBL_0,
+	VPSS_PCR_RSZ2_WBL_0,
+	VPSS_PCR_RSZ1_WBL_0,
+	VPSS_PCR_PREV_WBL_0,
+	VPSS_PCR_CCDC_WBL_O,
+};
+int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel);
+#endif
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 9/10 - v2] remove outdated video driver files of dm6446
  2009-06-11 17:00                 ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 m-karicheri2
  2009-06-11 17:00                   ` [PATCH 10/10 - v2] common vpss module for video drivers m-karicheri2
@ 2009-06-11 20:23                   ` Kevin Hilman
  2009-06-12 15:07                     ` Karicheri, Muralidharan
  1 sibling, 1 reply; 34+ messages in thread
From: Kevin Hilman @ 2009-06-11 20:23 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

m-karicheri2@ti.com writes:

> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
>
> Remove outdated driver files from davinci git tree

Can you add another patch that removes the old Kconfig/Makfile entries
as well (of course, this only applied to davinci git and not mainline.)

Also, can't we drop the Kconfig/Makefile stuff for tvp5146.c also?

Thanks,

Kevin

> No change from last patch
>
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
>
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
> Applies to Davinci GIT Tree
>
>  drivers/media/video/ccdc_davinci.c |  124 ----
>  drivers/media/video/davinci_vpfe.c | 1136 ------------------------------------
>  include/media/ccdc_davinci.h       |  144 -----
>  include/media/davinci_vpfe.h       |  121 ----
>  4 files changed, 0 insertions(+), 1525 deletions(-)
>  delete mode 100644 drivers/media/video/ccdc_davinci.c
>  delete mode 100644 drivers/media/video/davinci_vpfe.c
>  delete mode 100644 include/media/ccdc_davinci.h
>  delete mode 100644 include/media/davinci_vpfe.h
>
> diff --git a/drivers/media/video/ccdc_davinci.c b/drivers/media/video/ccdc_davinci.c
> deleted file mode 100644
> index d3cd333..0000000
> --- a/drivers/media/video/ccdc_davinci.c
> +++ /dev/null
> @@ -1,124 +0,0 @@
> -/*
> - *
> - *
> - * Copyright (C) 2006 Texas Instruments Inc
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> - */
> -/* ccdc_davinci.c */
> -
> -#include <media/ccdc_davinci.h>
> -#define debug_print(x...)	//printk(x)
> -void ccdc_reset()
> -{
> -	int i;
> -	/* disable CCDC */
> -	ccdc_enable(0);
> -	/* set all registers to default value */
> -	for (i = 0; i <= 0x94; i += 4) {
> -		regw(0, i);
> -	}
> -	regw(0, PCR);
> -	regw(0, SYN_MODE);
> -	regw(0, HD_VD_WID);
> -	regw(0, PIX_LINES);
> -	regw(0, HORZ_INFO);
> -	regw(0, VERT_START);
> -	regw(0, VERT_LINES);
> -	regw(0xffff00ff, CULLING);
> -	regw(0, HSIZE_OFF);
> -	regw(0, SDOFST);
> -	regw(0, SDR_ADDR);
> -	regw(0, VDINT);
> -	regw(0, REC656IF);
> -	regw(0, CCDCFG);
> -	regw(0, FMTCFG);
> -	regw(0, VP_OUT);
> -}
> -
> -void ccdc_setwin(ccdc_params_ycbcr * params)
> -{
> -	int horz_start, horz_nr_pixels;
> -	int vert_start, vert_nr_lines;
> -
> -	/* configure horizonal and vertical starts and sizes */
> -	horz_start = params->win.left << 1;
> -	horz_nr_pixels = (params->win.width <<1) - 1;
> -	regw((horz_start << 16) | horz_nr_pixels, HORZ_INFO);
> -
> -	vert_start = params->win.top;
> -
> -	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
> -		vert_nr_lines = (params->win.height >> 1) - 1;
> -		vert_start >>= 1;
> -	} else {
> -		vert_nr_lines = params->win.height - 1;
> -	}
> -	regw((vert_start << 16) | vert_start, VERT_START);
> -	regw(vert_nr_lines, VERT_LINES);
> -}
> -
> -void ccdc_config_ycbcr(ccdc_params_ycbcr * params)
> -{
> -	u32 syn_mode;
> -
> -	/* first reset the CCDC                                          */
> -	/* all registers have default values after reset                 */
> -	/* This is important since we assume default values to be set in */
> -	/* a lot of registers that we didn't touch                       */
> -	ccdc_reset();
> -
> -	/* configure pixel format */
> -	syn_mode = (params->pix_fmt & 0x3) << 12;
> -
> -	/* configure video frame format */
> -	syn_mode |= (params->frm_fmt & 0x1) << 7;
> -
> -	/* setup BT.656 sync mode */
> -	if (params->bt656_enable) {
> -		regw(3, REC656IF);
> -
> -		/* configure the FID, VD, HD pin polarity */
> -		/* fld,hd pol positive, vd negative, 8-bit pack mode */
> -		syn_mode |= 0x00000F04;
> -	} else {/* y/c external sync mode */
> -		syn_mode |= ((params->fid_pol & 0x1) << 4);
> -		syn_mode |= ((params->hd_pol & 0x1) << 3);
> -		syn_mode |= ((params->vd_pol & 0x1) << 2);
> -	}
> -
> -	/* configure video window */
> -	ccdc_setwin(params);
> -
> -	/* configure the order of y cb cr in SD-RAM */
> -	regw((params->pix_order << 11) | 0x8000, CCDCFG);
> -
> -	/* configure the horizontal line offset */
> -	/* this is done by rounding up width to a multiple of 16 pixels */
> -	/* and multiply by two to account for y:cb:cr 4:2:2 data */
> -	regw(((params->win.width * 2) + 31) & 0xffffffe0, HSIZE_OFF);
> -
> -	/* configure the memory line offset */
> -	if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
> -		/* two fields are interleaved in memory */
> -		regw(0x00000249, SDOFST);
> -	}
> -	/* enable output to SDRAM */
> -	syn_mode |= (0x1 << 17);
> -	/* enable internal timing generator */
> -	syn_mode |= (0x1 << 16);
> -
> -	regw(syn_mode, SYN_MODE);
> -}
> diff --git a/drivers/media/video/davinci_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/ccdc_davinci.h b/include/media/ccdc_davinci.h
> deleted file mode 100644
> index 9f0a08d..0000000
> --- a/include/media/ccdc_davinci.h
> +++ /dev/null
> @@ -1,144 +0,0 @@
> -/*
> - *
> - * Copyright (C) 2006 Texas Instruments Inc
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> - */
> -/* ccdc_davinci.h */
> -
> -#ifndef CCDC_DAVINCI_H
> -#define CCDC_DAVINCI_H
> -#include <linux/types.h>
> -
> -#ifdef __KERNEL__
> -#include <asm/arch/hardware.h>
> -#include <asm/io.h>
> -#endif
> -
> -#include <linux/videodev.h>
> -
> -typedef enum ccdc_pixfmt {
> -	CCDC_PIXFMT_RAW = 0,
> -	CCDC_PIXFMT_YCBCR_16BIT = 1,
> -	CCDC_PIXFMT_YCBCR_8BIT = 2
> -} ccdc_pixfmt;
> -
> -typedef enum ccdc_frmfmt {
> -	CCDC_FRMFMT_PROGRESSIVE = 0,
> -	CCDC_FRMFMT_INTERLACED = 1
> -} ccdc_frmfmt;
> -
> -typedef enum ccdc_pinpol {
> -	CCDC_PINPOL_POSITIVE = 0,
> -	CCDC_PINPOL_NEGATIVE = 1
> -} ccdc_pinpol;
> -
> -/* PIXEL ORDER IN MEMORY from LSB to MSB */
> -/* only applicable for 8-bit input mode  */
> -typedef enum ccdc_pixorder {
> -	CCDC_PIXORDER_CBYCRY = 1,
> -	CCDC_PIXORDER_YCBYCR = 0
> -} ccdc_pixorder;
> -
> -typedef enum ccdc_buftype {
> -	CCDC_BUFTYPE_FLD_INTERLEAVED,
> -	CCDC_BUFTYPE_FLD_SEPARATED
> -} ccdc_buftype;
> -
> -typedef struct v4l2_rect ccdc_imgwin;
> -
> -typedef struct ccdc_params_ycbcr {
> -	ccdc_pixfmt pix_fmt;	/* pixel format                     */
> -	ccdc_frmfmt frm_fmt;	/* progressive or interlaced frame  */
> -	ccdc_imgwin win;	/* video window                     */
> -	ccdc_pinpol fid_pol;	/* field id polarity                */
> -	ccdc_pinpol vd_pol;	/* vertical sync polarity           */
> -	ccdc_pinpol hd_pol;	/* horizontal sync polarity         */
> -	int bt656_enable;	/* enable BT.656 embedded sync mode */
> -	ccdc_pixorder pix_order;/* cb:y:cr:y or y:cb:y:cr in memory */
> -	ccdc_buftype buf_type;	/* interleaved or separated fields  */
> -} ccdc_params_ycbcr;
> -
> -#ifdef __KERNEL__
> -/**************************************************************************\
> -* Register OFFSET Definitions
> -\**************************************************************************/
> -#define PID                             0x0
> -#define PCR                             0x4
> -#define SYN_MODE                        0x8
> -#define HD_VD_WID                       0xc
> -#define PIX_LINES                       0x10
> -#define HORZ_INFO                       0x14
> -#define VERT_START                      0x18
> -#define VERT_LINES                      0x1c
> -#define CULLING                         0x20
> -#define HSIZE_OFF                       0x24
> -#define SDOFST                          0x28
> -#define SDR_ADDR                        0x2c
> -#define CLAMP                           0x30
> -#define DCSUB                           0x34
> -#define COLPTN                          0x38
> -#define BLKCMP                          0x3c
> -#define FPC                             0x40
> -#define FPC_ADDR                        0x44
> -#define VDINT                           0x48
> -#define ALAW                            0x4c
> -#define REC656IF                        0x50
> -#define CCDCFG                          0x54
> -#define FMTCFG                          0x58
> -#define FMT_HORZ                        0x5c
> -#define FMT_VERT                        0x50
> -#define FMT_ADDR0                       0x64
> -#define FMT_ADDR1                       0x68
> -#define FMT_ADDR2                       0x6c
> -#define FMT_ADDR3                       0x70
> -#define FMT_ADDR4                       0x74
> -#define FMT_ADDR5                       0x78
> -#define FMT_ADDR6                       0x7c
> -#define FMT_ADDR7                       0x80
> -#define PRGEVEN_0                       0x84
> -#define PRGEVEN_1                       0x88
> -#define PRGODD_0                        0x8c
> -#define PRGODD_1                        0x90
> -#define VP_OUT                          0x94
> -
> -#define CCDC_IOBASE                     (0x01c70400)
> -
> -#define regw(val, reg)    davinci_writel(val, (reg)+CCDC_IOBASE)
> -#define regr(reg)         davinci_readl((reg)+CCDC_IOBASE)
> -
> -extern void ccdc_reset(void);
> -extern void ccdc_config_ycbcr(ccdc_params_ycbcr * params);
> -extern void ccdc_setwin(ccdc_params_ycbcr * params);
> -
> -/* inline functions that must be fast because they are called frequently */
> -static inline void ccdc_enable(int flag)
> -{
> -	regw(flag, PCR);
> -}
> -
> -static inline void ccdc_setfbaddr(unsigned long paddr)
> -{
> -	regw(paddr & 0xffffffe0, SDR_ADDR);
> -}
> -
> -static inline int ccdc_getfid(void)
> -{
> -	int fid = (regr(SYN_MODE) >> 15) & 0x1;
> -	return fid;
> -}
> -#endif
> -
> -#endif /* CCDC_DAVINCI_H */
> 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
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 7/10 - v2] DM355 platform changes for vpfe capture driver
  2009-06-11 17:00             ` [PATCH 7/10 - v2] DM355 platform changes " m-karicheri2
  2009-06-11 17:00               ` [PATCH 8/10 - v2] DM6446 " m-karicheri2
@ 2009-06-11 20:23               ` David Brownell
  2009-06-14 14:22               ` Hans Verkuil
  2 siblings, 0 replies; 34+ messages in thread
From: David Brownell @ 2009-06-11 20:23 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: m-karicheri2, linux-media, Muralidharan Karicheri

On Thursday 11 June 2009, m-karicheri2@ti.com wrote:
> +               I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),

Minor nit:  just use "0x5d" instead of defining TVP5146_I2C_ADDR.
Fix in a v3, iff you make one.


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver
  2009-06-11 17:00 [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver m-karicheri2
  2009-06-11 17:00 ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 m-karicheri2
@ 2009-06-11 20:24 ` David Brownell
  2009-06-12 15:58   ` Karicheri, Muralidharan
  1 sibling, 1 reply; 34+ messages in thread
From: David Brownell @ 2009-06-11 20:24 UTC (permalink / raw)
  To: m-karicheri2
  Cc: davinci-linux-open-source, linux-media, Muralidharan Karicheri

On Thursday 11 June 2009, m-karicheri2@ti.com wrote:
> VPFE Capture driver for DaVinci Media SOCs :- DM355 and DM6446
> 
> This is the version v2 of the patch series. This is the reworked
> version of the driver based on comments received against the last
> version of the patch.

I'll be glad to see this get to mainline ... it's seeming closer
and closer!

What's the merge plan though?  I had hopes for 2.6.31.real-soon
but several of the later patches comment

  > Applies to Davinci GIT Tree

which implies "not -next".  DM355 patches are in the "-next" tree.

Is this just an oversight (tracking -next can be a PITA!) or is
there some other dependency?

- dave


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-11 17:00 ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 m-karicheri2
  2009-06-11 17:00   ` [PATCH 2/10 - v2] ccdc hw device header file for vpfe capture m-karicheri2
@ 2009-06-11 22:41   ` Alexey Klimov
  2009-06-15 17:41     ` Karicheri, Muralidharan
  2009-06-14 14:10   ` Hans Verkuil
  2 siblings, 1 reply; 34+ messages in thread
From: Alexey Klimov @ 2009-06-11 22:41 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

Hello,

Very small suggestion, please see below.

On Thu, Jun 11, 2009 at 9:00 PM, <m-karicheri2@ti.com> wrote:
> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
>
> Re-sending since previous one missed a file (vpfe_types.h)
>
> VPFE Capture bridge driver
>
> This is version, v2 of vpfe capture bridge driver for doing video
> capture on DM355 and DM6446 evms. The ccdc hw modules register with the
> driver and are used for configuring the CCD Controller for a specific
> decoder interface. The driver also registers the sub devices required
> for a specific evm. More than one sub devices can be registered.
> This allows driver to switch dynamically to capture video from
> any sub device that is registered. Currently only one sub device
> (tvp5146) is supported. But in future this driver is expected
> to do capture from sensor devices such as Micron's MT9T001,MT9T031
> and MT9P031 etc. The driver currently supports MMAP based IO.
>
> Following are the updates based on review comments:-
>        1) minor number is allocated dynamically
>        2) updates to QUERYCAP handling
>        3) eliminated intermediate vpfe pixel format
>        4) refactored few functions
>        5) reworked isr routines for reducing indentation
>        6) reworked vpfe_check_format and added a documentation
>           for algorithm
>        7) fixed memory leak in probe()
>
> TODO list :
>        1) load sub device from bridge driver. Hans has enhanced
>        the v4l2-subdevice framework to do this. Will be updated
>        soon to pick this.
>
>
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
>
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
> Applies to v4l-dvb repository
>
>  drivers/media/video/davinci/vpfe_capture.c | 2252 ++++++++++++++++++++++++++++
>  include/media/davinci/vpfe_capture.h       |  183 +++
>  include/media/davinci/vpfe_types.h         |   51 +
>  3 files changed, 2486 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.c
>  create mode 100644 include/media/davinci/vpfe_capture.h
>  create mode 100644 include/media/davinci/vpfe_types.h


<snip>

> +/* 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
> +};
> +
> +/*
> + * vpfe_check_format()
> + * This function adjust the input pixel format as per hardware
> + * capabilities and update the same in pixfmt.
> + * Following algorithm used :-
> + *
> + *     If given pixformat is not in the vpfe list of pix formats or not
> + *     supported by the hardware, current value of pixformat in the device
> + *     is used
> + *     If given field is not supported, then current field is used. If field
> + *     is different from current, then it is matched with that from sub device.
> + *     Minimum height is 2 lines for interlaced or tb field and 1 line for
> + *     progressive. Maximum height is clamped to active active lines of scan
> + *     Minimum width is 32 bytes in memory and width is clamped to active
> + *     pixels of scan.
> + *     bytesperline is a multiple of 32.
> + */
> +static const struct vpfe_pixel_format *
> +       vpfe_check_format(struct vpfe_device *vpfe_dev,
> +                         struct v4l2_pix_format *pixfmt)
> +{
> +       u32 min_height = 1, min_width = 32, max_width, max_height;
> +       const struct vpfe_pixel_format *vpfe_pix_fmt;
> +       u32 pix;
> +       int temp, found;
> +
> +       vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
> +       if (NULL == vpfe_pix_fmt) {
> +               /*
> +                * use current pixel format in the vpfe device. We
> +                * will find this pix format in the table
> +                */
> +               pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
> +               vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
> +       }
> +
> +       /* check if hw supports it */
> +       temp = 0;
> +       found = 0;
> +       while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) {
> +               if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) {
> +                       found = 1;
> +                       break;
> +               }
> +               temp++;
> +       }
> +
> +       if (!found) {
> +               /* use current pixel format */
> +               pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
> +               /*
> +                * Since this is currently used in the vpfe device, we
> +                * will find this pix format in the table
> +                */
> +               vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
> +       }
> +
> +       /* check what field format is supported */
> +       if (pixfmt->field == V4L2_FIELD_ANY) {
> +               /* if field is any, use current value as default */
> +               pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
> +       }
> +
> +       /*
> +        * if field is not same as current field in the vpfe device
> +        * try matching the field with the sub device field
> +        */
> +       if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) {
> +               /*
> +                * If field value is not in the supported fields, use current
> +                * field used in the device as default
> +                */
> +               switch (pixfmt->field) {
> +               case V4L2_FIELD_INTERLACED:
> +               case V4L2_FIELD_SEQ_TB:
> +                       /* if sub device is supporting progressive, use that */
> +                       if (!vpfe_dev->std_info.frame_format)
> +                               pixfmt->field = V4L2_FIELD_NONE;
> +                       break;
> +               case V4L2_FIELD_NONE:
> +                       if (vpfe_dev->std_info.frame_format)
> +                               pixfmt->field = V4L2_FIELD_INTERLACED;
> +                       break;
> +
> +               default:
> +                       /* use current field as default */
> +                       pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
> +               }
> +       }
> +
> +       /* Now adjust image resolutions supported */
> +       if (pixfmt->field == V4L2_FIELD_INTERLACED ||
> +           pixfmt->field == V4L2_FIELD_SEQ_TB)
> +               min_height = 2;
> +
> +       max_width = vpfe_dev->std_info.active_pixels;
> +       max_height = vpfe_dev->std_info.active_lines;
> +       min_width /= vpfe_pix_fmt->bpp;
> +
> +       v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n",
> +                 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp);
> +
> +       pixfmt->width = clamp((pixfmt->width), min_width, max_width);
> +       pixfmt->height = clamp((pixfmt->height), min_height, max_height);
> +
> +       /* If interlaced, adjust height to be a multiple of 2 */
> +       if (pixfmt->field == V4L2_FIELD_INTERLACED)
> +               pixfmt->height &= (~1);
> +       /*
> +        * recalculate bytesperline and sizeimage since width
> +        * and height might have changed
> +        */
> +       pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31)
> +                               & ~31);
> +       if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
> +               pixfmt->sizeimage =
> +                       pixfmt->bytesperline * pixfmt->height +
> +                       ((pixfmt->bytesperline * pixfmt->height) >> 1);
> +       else
> +               pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
> +
> +       v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="
> +                " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
> +                pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,
> +                pixfmt->bytesperline, pixfmt->sizeimage);
> +       return vpfe_pix_fmt;
> +}
> +
> +static int vpfe_querycap(struct file *file, void  *priv,
> +                              struct v4l2_capability *cap)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
> +
> +       cap->version = VPFE_CAPTURE_VERSION_CODE;
> +       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
> +       strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
> +       strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
> +       strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
> +       return 0;
> +}
> +
> +static int vpfe_g_fmt_vid_cap(struct file *file, void *priv,
> +                               struct v4l2_format *fmt)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       int ret = 0;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n");
> +       /* Fill in the information about format */
> +       *fmt = vpfe_dev->fmt;
> +       return ret;
> +}
> +
> +static int vpfe_enum_fmt_vid_cap(struct file *file, void  *priv,
> +                                  struct v4l2_fmtdesc *fmt)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       const struct vpfe_pixel_format *pix_fmt;
> +       int temp_index;
> +       u32 pix;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n");
> +
> +       if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0)
> +               return -EINVAL;
> +
> +       /* Fill in the information about format */
> +       pix_fmt = vpfe_lookup_pix_format(pix);
> +       if (NULL != pix_fmt) {
> +               temp_index = fmt->index;
> +               *fmt = pix_fmt->fmtdesc;
> +               fmt->index = temp_index;
> +               return 0;
> +       }
> +       return -EINVAL;
> +}
> +
> +static int vpfe_s_fmt_vid_cap(struct file *file, void *priv,
> +                               struct v4l2_format *fmt)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       const struct vpfe_pixel_format *pix_fmts;
> +       int ret = 0;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");
> +
> +       /* If streaming is started, return error */
> +       if (vpfe_dev->started) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
> +               return -EBUSY;
> +       }
> +
> +       /* Check for valid frame format */
> +       pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);
> +
> +       if (NULL == pix_fmts)
> +               return -EINVAL;
> +
> +       /* store the pixel format in the device  object */
> +       ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +       if (ret)
> +               return ret;
> +
> +       /* First detach any IRQ if currently attached */
> +       vpfe_detach_irq(vpfe_dev);
> +       vpfe_dev->fmt = *fmt;
> +       /* set image capture parameters in the ccdc */
> +       ret = vpfe_config_ccdc_image_format(vpfe_dev);
> +       mutex_unlock(&vpfe_dev->lock);
> +       return ret;
> +}
> +
> +static int vpfe_try_fmt_vid_cap(struct file *file, void *priv,
> +                                 struct v4l2_format *f)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       const struct vpfe_pixel_format *pix_fmts;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");
> +
> +       pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);
> +       if (NULL == pix_fmts)
> +               return -EINVAL;
> +       return 0;
> +}
> +
> +/*
> + * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a
> + * given app input index
> + */
> +static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev,
> +                                       int *subdev_index,
> +                                       int *subdev_input_index,
> +                                       int app_input_index)
> +{
> +       struct vpfe_config *cfg = vpfe_dev->cfg;
> +       struct vpfe_subdev_info *sub_dev;
> +       int i, j = 0;
> +
> +       for (i = 0; i < cfg->num_subdevs; i++) {
> +               sub_dev = &cfg->sub_devs[i];
> +               if (app_input_index < (j + sub_dev->num_inputs)) {
> +                       *subdev_index = i;
> +                       *subdev_input_index = app_input_index - j;
> +                       return 0;
> +               }
> +               j += sub_dev->num_inputs;
> +       }
> +       return -EINVAL;
> +}
> +
> +/*
> + * vpfe_get_app_input - Get app input index for a given subdev input index
> + * driver stores the input index of the current sub device and translate it
> + * when application request the current input
> + */
> +static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev,
> +                                   int *app_input_index)
> +{
> +       struct vpfe_config *cfg = vpfe_dev->cfg;
> +       struct vpfe_subdev_info *sub_dev;
> +       int i, j = 0;
> +
> +       for (i = 0; i < cfg->num_subdevs; i++) {
> +               sub_dev = &cfg->sub_devs[i];
> +               if (!strcmp(sub_dev->name, vpfe_dev->current_subdev->name)) {
> +                       if (vpfe_dev->current_input >= sub_dev->num_inputs)
> +                               return -1;
> +                       *app_input_index = j + vpfe_dev->current_input;
> +                       return 0;
> +               }
> +               j += sub_dev->num_inputs;
> +       }
> +       return -EINVAL;
> +}
> +
> +static int vpfe_enum_input(struct file *file, void *priv,
> +                                struct v4l2_input *inp)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_subdev_info *sub_dev;
> +       int subdev, index ;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
> +
> +       if (vpfe_get_subdev_input_index(vpfe_dev,
> +                                       &subdev,
> +                                       &index,
> +                                       inp->index) < 0) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"
> +                        " for the subdev\n");
> +               return -EINVAL;
> +       }
> +       sub_dev = &vpfe_dev->cfg->sub_devs[subdev];
> +       memcpy(inp, &sub_dev->inputs[index],
> +               sizeof(struct v4l2_input));
> +       return 0;
> +}
> +
> +static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
> +
> +       return vpfe_get_app_input_index(vpfe_dev, index);
> +}
> +
> +
> +static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_subdev_info *sub_dev;
> +       int subdev_index, inp_index;
> +       struct v4l2_routing *route;
> +       u32 input = 0, output = 0;
> +       int ret = -EINVAL;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
> +
> +       ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +       if (ret)
> +               return ret;
> +
> +       /*
> +        * If streaming is started return device busy
> +        * error
> +        */
> +       if (vpfe_dev->started) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
> +               ret = -EBUSY;
> +               goto unlock_out;
> +       }
> +
> +       if (vpfe_get_subdev_input_index(vpfe_dev,
> +                                       &subdev_index,
> +                                       &inp_index,
> +                                       index) < 0) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");
> +               goto unlock_out;
> +       }
> +
> +       sub_dev = &vpfe_dev->cfg->sub_devs[subdev_index];
> +       route = &sub_dev->routes[inp_index];
> +       if (route && sub_dev->can_route) {
> +               input = route->input;
> +               output = route->output;
> +       }
> +
> +       ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
> +                                        sub_dev->grp_id,
> +                                        video, s_routing, input,
> +                                        output, 0);
> +
> +       if (ret) {
> +               v4l2_err(&vpfe_dev->v4l2_dev,
> +                       "vpfe_doioctl:error in setting input in decoder \n");
> +               ret = -EINVAL;
> +               goto unlock_out;
> +       }
> +       vpfe_dev->current_subdev = sub_dev;
> +       vpfe_dev->current_input = index;
> +       vpfe_dev->std_index = 0;
> +
> +       ret = vpfe_set_hw_if_params(vpfe_dev);
> +       if (ret)
> +               goto unlock_out;
> +
> +       /* set the default image parameters in the device */
> +       ret = vpfe_config_image_format(vpfe_dev,
> +                               &vpfe_standards[vpfe_dev->std_index].std_id);
> +       if (ret)
> +               goto unlock_out;

Why you check ret value and go to label below?
Probably you can remove if-check and goto here.

> +
> +unlock_out:
> +       mutex_unlock(&vpfe_dev->lock);
> +       return ret;
> +}
> +
> +static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_subdev_info *subdev;
> +       int ret = 0;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
> +
> +       ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +       subdev = vpfe_dev->current_subdev;
> +       if (ret)
> +               return ret;
> +       /* Call querystd function of decoder device */
> +       ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
> +                                        subdev->grp_id,
> +                                        video, querystd, std_id);
> +       mutex_unlock(&vpfe_dev->lock);
> +       return ret;
> +}
> +
> +static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_subdev_info *subdev;
> +       int ret = 0;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
> +
> +       /* Call decoder driver function to set the standard */
> +       ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +       if (ret)
> +               return ret;
> +
> +       subdev = vpfe_dev->current_subdev;
> +       /* If streaming is started, return device busy error */
> +       if (vpfe_dev->started) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
> +               ret = -EBUSY;
> +               goto unlock_out;
> +       }
> +
> +       ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
> +                                        core, s_std, *std_id);
> +       if (ret < 0) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
> +               goto unlock_out;
> +       }
> +       ret = vpfe_config_image_format(vpfe_dev, std_id);
> +
> +unlock_out:
> +       mutex_unlock(&vpfe_dev->lock);
> +       return ret;
> +}
> +
> +static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
> +
> +       *std_id = vpfe_standards[vpfe_dev->std_index].std_id;
> +       return 0;
> +}
> +/*
> + *  Videobuf operations
> + */
> +static int vpfe_videobuf_setup(struct videobuf_queue *vq,
> +                               unsigned int *count,
> +                               unsigned int *size)
> +{
> +       struct vpfe_fh *fh = vq->priv_data;
> +       struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
> +       *size = config_params.device_bufsize;
> +
> +       if (*count < config_params.min_numbuffers)
> +               *count = config_params.min_numbuffers;
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +               "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)
> +{
> +       struct vpfe_fh *fh = vq->priv_data;
> +       struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
> +
> +       /* If buffer is not initialized, initialize it */
> +       if (VIDEOBUF_NEEDS_INIT == vb->state) {
> +               vb->width = vpfe_dev->fmt.fmt.pix.width;
> +               vb->height = vpfe_dev->fmt.fmt.pix.height;
> +               vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
> +               vb->field = field;
> +       }
> +       vb->state = VIDEOBUF_PREPARED;
> +       return 0;
> +}
> +
> +static void vpfe_videobuf_queue(struct videobuf_queue *vq,
> +                               struct videobuf_buffer *vb)
> +{
> +       /* Get the file handle object and device object */
> +       struct vpfe_fh *fh = vq->priv_data;
> +       struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +       unsigned long flags;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n");
> +
> +       /* add the buffer to the DMA queue */
> +       spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
> +       list_add_tail(&vb->queue, &vpfe_dev->dma_queue);
> +       spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
> +
> +       /* Change state of the buffer */
> +       vb->state = VIDEOBUF_QUEUED;
> +}
> +
> +static void vpfe_videobuf_release(struct videobuf_queue *vq,
> +                                 struct videobuf_buffer *vb)
> +{
> +       struct vpfe_fh *fh = vq->priv_data;
> +       struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +       unsigned long flags;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");
> +
> +       /*
> +        * We need to flush the buffer from the dma queue since
> +        * they are de-allocated
> +        */
> +       spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
> +       INIT_LIST_HEAD(&vpfe_dev->dma_queue);
> +       spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
> +       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,
> +};
> +
> +/*
> + * vpfe_reqbufs. currently support REQBUF only once opening
> + * the device.
> + */
> +static int vpfe_reqbufs(struct file *file, void *priv,
> +                       struct v4l2_requestbuffers *req_buf)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_fh *fh = file->private_data;
> +       int ret = 0;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
> +
> +       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
> +               return -EINVAL;
> +       }
> +
> +       if (V4L2_MEMORY_USERPTR == req_buf->memory) {
> +               /* we don't support user ptr IO */
> +               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
> +                        " USERPTR IO not supported>\n");
> +               return  -EINVAL;
> +       }
> +
> +       ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +       if (ret)
> +               return ret;
> +
> +       if (vpfe_dev->io_usrs != 0) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
> +               ret = -EBUSY;
> +               goto unlock_out;
> +       }
> +
> +       vpfe_dev->memory = req_buf->memory;
> +       videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue,
> +                               &vpfe_videobuf_qops,
> +                               NULL,
> +                               &vpfe_dev->irqlock,
> +                               req_buf->type,
> +                               vpfe_dev->fmt.fmt.pix.field,
> +                               sizeof(struct videobuf_buffer),
> +                               fh);
> +
> +       fh->io_allowed = 1;
> +       vpfe_dev->io_usrs = 1;
> +       INIT_LIST_HEAD(&vpfe_dev->dma_queue);
> +       ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf);
> +unlock_out:
> +       mutex_unlock(&vpfe_dev->lock);
> +       return ret;
> +}
> +
> +static int vpfe_querybuf(struct file *file, void *priv,
> +                        struct v4l2_buffer *buf)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
> +
> +       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +               return  -EINVAL;
> +       }
> +
> +       if (vpfe_dev->memory != V4L2_MEMORY_MMAP) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
> +               return -EINVAL;
> +       }
> +       /* Call videobuf_querybuf to get information */
> +       return videobuf_querybuf(&vpfe_dev->buffer_queue, buf);
> +}
> +
> +static int vpfe_qbuf(struct file *file, void *priv,
> +                    struct v4l2_buffer *p)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_fh *fh = file->private_data;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
> +
> +       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * If this file handle is not allowed to do IO,
> +        * return error
> +        */
> +       if (!fh->io_allowed) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
> +               return -EACCES;
> +       }
> +       return videobuf_qbuf(&vpfe_dev->buffer_queue, p);
> +}
> +
> +static int vpfe_dqbuf(struct file *file, void *priv,
> +                     struct v4l2_buffer *buf)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
> +
> +       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +               return -EINVAL;
> +       }
> +       return videobuf_dqbuf(&vpfe_dev->buffer_queue,
> +                                     buf, file->f_flags & O_NONBLOCK);
> +}
> +
> +/*
> + * vpfe_calculate_offsets : This function calculates buffers offset
> + * for top and bottom field
> + */
> +static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev)
> +{
> +       struct v4l2_rect image_win;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n");
> +
> +       ccdc_dev->hw_ops.get_image_window(&image_win);
> +       vpfe_dev->field_off = image_win.height * image_win.width;
> +}
> +
> +/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */
> +static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev)
> +{
> +       ccdc_dev->hw_ops.enable(1);
> +       if (ccdc_dev->hw_ops.enable_out_to_sdram)
> +               ccdc_dev->hw_ops.enable_out_to_sdram(1);
> +       vpfe_dev->started = 1;
> +}
> +
> +/*
> + * vpfe_streamon. Assume the DMA queue is not empty.
> + * application is expected to call QBUF before calling
> + * this ioctl. If not, driver returns error
> + */
> +static int vpfe_streamon(struct file *file, void *priv,
> +                        enum v4l2_buf_type buf_type)
> +{
> +       struct vpfe_device *vpfe_dev = video_drvdata(file);
> +       struct vpfe_fh *fh = file->private_data;
> +       struct vpfe_subdev_info *subdev;
> +       unsigned long addr;
> +       int ret = 0;
> +
> +       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
> +
> +       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +               return -EINVAL;
> +       }
> +
> +       /* If file handle is not allowed IO, return error */
> +       if (!fh->io_allowed) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
> +               return -EACCES;
> +       }
> +
> +       subdev = vpfe_dev->current_subdev;
> +       ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
> +                                       video, s_stream, 1);
> +
> +       if (ret && (ret != -ENOIOCTLCMD)) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n");
> +               return -EINVAL;
> +       }
> +
> +       /* If buffer queue is empty, return error */
> +       if (list_empty(&vpfe_dev->buffer_queue.stream)) {
> +               v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
> +               return EIO;

return -EIO?

-- 
Best regards, Klimov Alexey

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 10/10 - v2] common vpss module for video drivers
  2009-06-11 17:00                   ` [PATCH 10/10 - v2] common vpss module for video drivers m-karicheri2
@ 2009-06-11 23:23                     ` Alexey Klimov
  2009-06-15 17:42                       ` Karicheri, Muralidharan
  2009-06-14 14:26                     ` Hans Verkuil
  1 sibling, 1 reply; 34+ messages in thread
From: Alexey Klimov @ 2009-06-11 23:23 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

Hello,

On Thu, Jun 11, 2009 at 9:00 PM, <m-karicheri2@ti.com> wrote:
> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
>
> common voss module for video drivers
>
> This is a new module added for vpss library functions that are
> used for configuring vpss system module. All video drivers will
> include vpss.h header file and call functions defined in this
> module to configure vpss system module.
>
>
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
>
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
>  drivers/media/video/davinci/vpss.c |  290 ++++++++++++++++++++++++++++++++++++
>  include/media/davinci/vpss.h       |   69 +++++++++
>  2 files changed, 359 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/vpss.c
>  create mode 100644 include/media/davinci/vpss.h
>
> diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
> new file mode 100644
> index 0000000..def021e
> --- /dev/null
> +++ b/drivers/media/video/davinci/vpss.c
> @@ -0,0 +1,290 @@
> +/*
> + * Copyright (C) 2009 Texas Instruments.
> + *
> + * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * common vpss driver for all video drivers.
> + */
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/compiler.h>
> +#include <linux/io.h>
> +#include <mach/hardware.h>
> +#include <media/davinci/vpss.h>
> +
> +/* DM644x defines */
> +#define DM644X_SBL_PCR_VPSS            (4)
> +
> +/* vpss BL register offsets */
> +#define DM355_VPSSBL_CCDCMUX           0x1c
> +/* vpss CLK register offsets */
> +#define DM355_VPSSCLK_CLKCTRL          0x04
> +/* masks and shifts */
> +#define VPSS_HSSISEL_SHIFT             4
> +
> +/*
> + * vpss operations. Depends on platform. Not all functions are available
> + * on all platforms. The api, first check if a functio is available before
> + * invoking it. In the probe, the function ptrs are intialized based on
> + * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
> + */
> +struct vpss_hw_ops {
> +       /* enable clock */
> +       int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
> +       /* select input to ccdc */
> +       void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
> +       /* clear wbl overlflow bit */
> +       int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
> +};
> +
> +/* vpss configuration */
> +struct vpss_oper_config {
> +       __iomem void *vpss_bl_regs_base;
> +       __iomem void *vpss_regs_base;
> +       struct resource         *r1;
> +       resource_size_t         len1;
> +       struct resource         *r2;
> +       resource_size_t         len2;
> +       char vpss_name[32];
> +       spinlock_t vpss_lock;
> +       struct vpss_hw_ops hw_ops;
> +};
> +
> +static struct vpss_oper_config oper_cfg;
> +
> +/* register access routines */
> +static inline u32 bl_regr(u32 offset)
> +{
> +       return __raw_readl(oper_cfg.vpss_bl_regs_base + offset);
> +}
> +
> +static inline void bl_regw(u32 val, u32 offset)
> +{
> +       __raw_writel(val, oper_cfg.vpss_bl_regs_base + offset);
> +}
> +
> +static inline u32 vpss_regr(u32 offset)
> +{
> +       return __raw_readl(oper_cfg.vpss_regs_base + offset);
> +}
> +
> +static inline void vpss_regw(u32 val, u32 offset)
> +{
> +       __raw_writel(val, oper_cfg.vpss_regs_base + offset);
> +}
> +
> +static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
> +{
> +       bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
> +}
> +
> +int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
> +{
> +       if (!oper_cfg.hw_ops.select_ccdc_source)
> +               return -1;
> +
> +       dm355_select_ccdc_source(src_sel);
> +       return 0;
> +}
> +EXPORT_SYMBOL(vpss_select_ccdc_source);
> +
> +static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
> +{
> +       u32 mask = 1, val;
> +
> +       if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
> +           wbl_sel > VPSS_PCR_CCDC_WBL_O)
> +               return -1;
> +
> +       /* writing a 0 clear the overflow */
> +       mask = ~(mask << wbl_sel);
> +       val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
> +       bl_regw(val, DM644X_SBL_PCR_VPSS);
> +       return 0;
> +}
> +
> +int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
> +{
> +       if (!oper_cfg.hw_ops.clear_wbl_overflow)
> +               return -1;
> +
> +       return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
> +}
> +EXPORT_SYMBOL(vpss_clear_wbl_overflow);
> +
> +/*
> + *  dm355_enable_clock - Enable VPSS Clock
> + *  @clock_sel: CLock to be enabled/disabled
> + *  @en: enable/disable flag
> + *
> + *  This is called to enable or disable a vpss clock
> + */
> +static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
> +{
> +       unsigned long flags;
> +       u32 utemp, mask = 0x1, shift = 0;
> +
> +       switch (clock_sel) {
> +       case VPSS_VPBE_CLOCK:
> +               /* nothing since lsb */
> +               break;
> +       case VPSS_VENC_CLOCK_SEL:
> +               shift = 2;
> +               break;
> +       case VPSS_CFALD_CLOCK:
> +               shift = 3;
> +               break;
> +       case VPSS_H3A_CLOCK:
> +               shift = 4;
> +               break;
> +       case VPSS_IPIPE_CLOCK:
> +               shift = 5;
> +               break;
> +       case VPSS_CCDC_CLOCK:
> +               shift = 6;
> +               break;
> +       default:
> +               printk(KERN_ERR "dm355_enable_clock:"
> +                               " Invalid selector: %d\n", clock_sel);
> +               return -1;
> +       }
> +
> +       spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
> +       utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
> +       if (!en)
> +               utemp &= ~(mask << shift);
> +       else
> +               utemp |= (mask << shift);
> +
> +       vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
> +       spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
> +       return 0;
> +}
> +
> +int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
> +{
> +       if (!oper_cfg.hw_ops.enable_clock)
> +               return -1;
> +
> +       return oper_cfg.hw_ops.enable_clock(clock_sel, en);
> +}
> +EXPORT_SYMBOL(vpss_enable_clock);
> +
> +static int __init vpss_probe(struct platform_device *pdev)
> +{
> +       int                     status;
> +
> +       if (!pdev->dev.platform_data) {
> +               dev_err(&pdev->dev, "vpss, no platform data\n");
> +               return -ENOENT;
> +       }
> +
> +       strcpy(oper_cfg.vpss_name, pdev->dev.platform_data);
> +       dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name);
> +       oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!oper_cfg.r1)
> +               return -ENOENT;
> +
> +       oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1;
> +
> +       oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1,
> +                                        oper_cfg.r1->name);
> +       if (!oper_cfg.r1)
> +               return -EBUSY;
> +
> +       oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1);
> +       if (!oper_cfg.vpss_bl_regs_base) {
> +               status = -EBUSY;
> +               goto fail1;
> +       }
> +
> +       if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +               oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +               if (!oper_cfg.r2) {
> +                       status = -ENOENT;
> +                       goto fail2;
> +               }
> +               oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1;
> +               oper_cfg.r2 = request_mem_region(oper_cfg.r2->start,
> +                                                oper_cfg.len2,
> +                                                oper_cfg.r2->name);
> +               if (!oper_cfg.r2) {
> +                       status = -EBUSY;
> +                       goto fail2;
> +               }
> +
> +               oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start,
> +                                                 oper_cfg.len2);
> +               if (!oper_cfg.vpss_regs_base) {
> +                       status = -EBUSY;
> +                       goto fail3;
> +               }
> +       }
> +
> +       if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +               oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
> +               oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
> +       } else if (!strcmp(oper_cfg.vpss_name, "dm644x_vpss"))
> +               oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
> +       else
> +               return -ENODEV;

Do you need clean up procedure if you return error here? I mean -
calls to release_mem_region, release_mem_region, etc

> +       spin_lock_init(&oper_cfg.vpss_lock);
> +       dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name);
> +       return 0;
> +fail3:
> +       release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
> +fail2:
> +       iounmap(oper_cfg.vpss_bl_regs_base);
> +fail1:
> +       release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
> +       return status;
> +}


-- 
Best regards, Klimov Alexey

^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 9/10 - v2] remove outdated video driver files of dm6446
  2009-06-11 20:23                   ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 Kevin Hilman
@ 2009-06-12 15:07                     ` Karicheri, Muralidharan
  0 siblings, 0 replies; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-12 15:07 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

Kevin,

Sure, I discussed that with Denys yesterday and would send you one.

Murali Karicheri
Software Design Engineer
Texas Instruments Inc.
Germantown, MD 20874
Phone : 301-515-3736
email: m-karicheri2@ti.com

>-----Original Message-----
>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>Sent: Thursday, June 11, 2009 4:23 PM
>To: Karicheri, Muralidharan
>Cc: linux-media@vger.kernel.org; davinci-linux-open-
>source@linux.davincidsp.com; Muralidharan Karicheri
>Subject: Re: [PATCH 9/10 - v2] remove outdated video driver files of dm6446
>
>m-karicheri2@ti.com writes:
>
>> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
>>
>> Remove outdated driver files from davinci git tree
>
>Can you add another patch that removes the old Kconfig/Makfile entries
>as well (of course, this only applied to davinci git and not mainline.)
>
>Also, can't we drop the Kconfig/Makefile stuff for tvp5146.c also?
>
>Thanks,
>
>Kevin
>
>> No change from last patch
>>
>> Reviewed By "Hans Verkuil".
>> Reviewed By "Laurent Pinchart".
>>
>> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
>> ---
>> Applies to Davinci GIT Tree
>>
>>  drivers/media/video/ccdc_davinci.c |  124 ----
>>  drivers/media/video/davinci_vpfe.c | 1136 ------------------------------
>------
>>  include/media/ccdc_davinci.h       |  144 -----
>>  include/media/davinci_vpfe.h       |  121 ----
>>  4 files changed, 0 insertions(+), 1525 deletions(-)
>>  delete mode 100644 drivers/media/video/ccdc_davinci.c
>>  delete mode 100644 drivers/media/video/davinci_vpfe.c
>>  delete mode 100644 include/media/ccdc_davinci.h
>>  delete mode 100644 include/media/davinci_vpfe.h
>>
>> diff --git a/drivers/media/video/ccdc_davinci.c
>b/drivers/media/video/ccdc_davinci.c
>> deleted file mode 100644
>> index d3cd333..0000000
>> --- a/drivers/media/video/ccdc_davinci.c
>> +++ /dev/null
>> @@ -1,124 +0,0 @@
>> -/*
>> - *
>> - *
>> - * Copyright (C) 2006 Texas Instruments Inc
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or
>> - * (at your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> - * GNU General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>USA
>> - */
>> -/* ccdc_davinci.c */
>> -
>> -#include <media/ccdc_davinci.h>
>> -#define debug_print(x...)   //printk(x)
>> -void ccdc_reset()
>> -{
>> -    int i;
>> -    /* disable CCDC */
>> -    ccdc_enable(0);
>> -    /* set all registers to default value */
>> -    for (i = 0; i <= 0x94; i += 4) {
>> -            regw(0, i);
>> -    }
>> -    regw(0, PCR);
>> -    regw(0, SYN_MODE);
>> -    regw(0, HD_VD_WID);
>> -    regw(0, PIX_LINES);
>> -    regw(0, HORZ_INFO);
>> -    regw(0, VERT_START);
>> -    regw(0, VERT_LINES);
>> -    regw(0xffff00ff, CULLING);
>> -    regw(0, HSIZE_OFF);
>> -    regw(0, SDOFST);
>> -    regw(0, SDR_ADDR);
>> -    regw(0, VDINT);
>> -    regw(0, REC656IF);
>> -    regw(0, CCDCFG);
>> -    regw(0, FMTCFG);
>> -    regw(0, VP_OUT);
>> -}
>> -
>> -void ccdc_setwin(ccdc_params_ycbcr * params)
>> -{
>> -    int horz_start, horz_nr_pixels;
>> -    int vert_start, vert_nr_lines;
>> -
>> -    /* configure horizonal and vertical starts and sizes */
>> -    horz_start = params->win.left << 1;
>> -    horz_nr_pixels = (params->win.width <<1) - 1;
>> -    regw((horz_start << 16) | horz_nr_pixels, HORZ_INFO);
>> -
>> -    vert_start = params->win.top;
>> -
>> -    if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
>> -            vert_nr_lines = (params->win.height >> 1) - 1;
>> -            vert_start >>= 1;
>> -    } else {
>> -            vert_nr_lines = params->win.height - 1;
>> -    }
>> -    regw((vert_start << 16) | vert_start, VERT_START);
>> -    regw(vert_nr_lines, VERT_LINES);
>> -}
>> -
>> -void ccdc_config_ycbcr(ccdc_params_ycbcr * params)
>> -{
>> -    u32 syn_mode;
>> -
>> -    /* first reset the CCDC                                          */
>> -    /* all registers have default values after reset                 */
>> -    /* This is important since we assume default values to be set in */
>> -    /* a lot of registers that we didn't touch                       */
>> -    ccdc_reset();
>> -
>> -    /* configure pixel format */
>> -    syn_mode = (params->pix_fmt & 0x3) << 12;
>> -
>> -    /* configure video frame format */
>> -    syn_mode |= (params->frm_fmt & 0x1) << 7;
>> -
>> -    /* setup BT.656 sync mode */
>> -    if (params->bt656_enable) {
>> -            regw(3, REC656IF);
>> -
>> -            /* configure the FID, VD, HD pin polarity */
>> -            /* fld,hd pol positive, vd negative, 8-bit pack mode */
>> -            syn_mode |= 0x00000F04;
>> -    } else {/* y/c external sync mode */
>> -            syn_mode |= ((params->fid_pol & 0x1) << 4);
>> -            syn_mode |= ((params->hd_pol & 0x1) << 3);
>> -            syn_mode |= ((params->vd_pol & 0x1) << 2);
>> -    }
>> -
>> -    /* configure video window */
>> -    ccdc_setwin(params);
>> -
>> -    /* configure the order of y cb cr in SD-RAM */
>> -    regw((params->pix_order << 11) | 0x8000, CCDCFG);
>> -
>> -    /* configure the horizontal line offset */
>> -    /* this is done by rounding up width to a multiple of 16 pixels */
>> -    /* and multiply by two to account for y:cb:cr 4:2:2 data */
>> -    regw(((params->win.width * 2) + 31) & 0xffffffe0, HSIZE_OFF);
>> -
>> -    /* configure the memory line offset */
>> -    if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
>> -            /* two fields are interleaved in memory */
>> -            regw(0x00000249, SDOFST);
>> -    }
>> -    /* enable output to SDRAM */
>> -    syn_mode |= (0x1 << 17);
>> -    /* enable internal timing generator */
>> -    syn_mode |= (0x1 << 16);
>> -
>> -    regw(syn_mode, SYN_MODE);
>> -}
>> diff --git a/drivers/media/video/davinci_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/ccdc_davinci.h b/include/media/ccdc_davinci.h
>> deleted file mode 100644
>> index 9f0a08d..0000000
>> --- a/include/media/ccdc_davinci.h
>> +++ /dev/null
>> @@ -1,144 +0,0 @@
>> -/*
>> - *
>> - * Copyright (C) 2006 Texas Instruments Inc
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or
>> - * (at your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> - * GNU General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>USA
>> - */
>> -/* ccdc_davinci.h */
>> -
>> -#ifndef CCDC_DAVINCI_H
>> -#define CCDC_DAVINCI_H
>> -#include <linux/types.h>
>> -
>> -#ifdef __KERNEL__
>> -#include <asm/arch/hardware.h>
>> -#include <asm/io.h>
>> -#endif
>> -
>> -#include <linux/videodev.h>
>> -
>> -typedef enum ccdc_pixfmt {
>> -    CCDC_PIXFMT_RAW = 0,
>> -    CCDC_PIXFMT_YCBCR_16BIT = 1,
>> -    CCDC_PIXFMT_YCBCR_8BIT = 2
>> -} ccdc_pixfmt;
>> -
>> -typedef enum ccdc_frmfmt {
>> -    CCDC_FRMFMT_PROGRESSIVE = 0,
>> -    CCDC_FRMFMT_INTERLACED = 1
>> -} ccdc_frmfmt;
>> -
>> -typedef enum ccdc_pinpol {
>> -    CCDC_PINPOL_POSITIVE = 0,
>> -    CCDC_PINPOL_NEGATIVE = 1
>> -} ccdc_pinpol;
>> -
>> -/* PIXEL ORDER IN MEMORY from LSB to MSB */
>> -/* only applicable for 8-bit input mode  */
>> -typedef enum ccdc_pixorder {
>> -    CCDC_PIXORDER_CBYCRY = 1,
>> -    CCDC_PIXORDER_YCBYCR = 0
>> -} ccdc_pixorder;
>> -
>> -typedef enum ccdc_buftype {
>> -    CCDC_BUFTYPE_FLD_INTERLEAVED,
>> -    CCDC_BUFTYPE_FLD_SEPARATED
>> -} ccdc_buftype;
>> -
>> -typedef struct v4l2_rect ccdc_imgwin;
>> -
>> -typedef struct ccdc_params_ycbcr {
>> -    ccdc_pixfmt pix_fmt;    /* pixel format                     */
>> -    ccdc_frmfmt frm_fmt;    /* progressive or interlaced frame  */
>> -    ccdc_imgwin win;        /* video window                     */
>> -    ccdc_pinpol fid_pol;    /* field id polarity                */
>> -    ccdc_pinpol vd_pol;     /* vertical sync polarity           */
>> -    ccdc_pinpol hd_pol;     /* horizontal sync polarity         */
>> -    int bt656_enable;       /* enable BT.656 embedded sync mode */
>> -    ccdc_pixorder pix_order;/* cb:y:cr:y or y:cb:y:cr in memory */
>> -    ccdc_buftype buf_type;  /* interleaved or separated fields  */
>> -} ccdc_params_ycbcr;
>> -
>> -#ifdef __KERNEL__
>> -
>/**************************************************************************
>\
>> -* Register OFFSET Definitions
>> -
>\**************************************************************************
>/
>> -#define PID                             0x0
>> -#define PCR                             0x4
>> -#define SYN_MODE                        0x8
>> -#define HD_VD_WID                       0xc
>> -#define PIX_LINES                       0x10
>> -#define HORZ_INFO                       0x14
>> -#define VERT_START                      0x18
>> -#define VERT_LINES                      0x1c
>> -#define CULLING                         0x20
>> -#define HSIZE_OFF                       0x24
>> -#define SDOFST                          0x28
>> -#define SDR_ADDR                        0x2c
>> -#define CLAMP                           0x30
>> -#define DCSUB                           0x34
>> -#define COLPTN                          0x38
>> -#define BLKCMP                          0x3c
>> -#define FPC                             0x40
>> -#define FPC_ADDR                        0x44
>> -#define VDINT                           0x48
>> -#define ALAW                            0x4c
>> -#define REC656IF                        0x50
>> -#define CCDCFG                          0x54
>> -#define FMTCFG                          0x58
>> -#define FMT_HORZ                        0x5c
>> -#define FMT_VERT                        0x50
>> -#define FMT_ADDR0                       0x64
>> -#define FMT_ADDR1                       0x68
>> -#define FMT_ADDR2                       0x6c
>> -#define FMT_ADDR3                       0x70
>> -#define FMT_ADDR4                       0x74
>> -#define FMT_ADDR5                       0x78
>> -#define FMT_ADDR6                       0x7c
>> -#define FMT_ADDR7                       0x80
>> -#define PRGEVEN_0                       0x84
>> -#define PRGEVEN_1                       0x88
>> -#define PRGODD_0                        0x8c
>> -#define PRGODD_1                        0x90
>> -#define VP_OUT                          0x94
>> -
>> -#define CCDC_IOBASE                     (0x01c70400)
>> -
>> -#define regw(val, reg)    davinci_writel(val, (reg)+CCDC_IOBASE)
>> -#define regr(reg)         davinci_readl((reg)+CCDC_IOBASE)
>> -
>> -extern void ccdc_reset(void);
>> -extern void ccdc_config_ycbcr(ccdc_params_ycbcr * params);
>> -extern void ccdc_setwin(ccdc_params_ycbcr * params);
>> -
>> -/* inline functions that must be fast because they are called frequently
>*/
>> -static inline void ccdc_enable(int flag)
>> -{
>> -    regw(flag, PCR);
>> -}
>> -
>> -static inline void ccdc_setfbaddr(unsigned long paddr)
>> -{
>> -    regw(paddr & 0xffffffe0, SDR_ADDR);
>> -}
>> -
>> -static inline int ccdc_getfid(void)
>> -{
>> -    int fid = (regr(SYN_MODE) >> 15) & 0x1;
>> -    return fid;
>> -}
>> -#endif
>> -
>> -#endif /* CCDC_DAVINCI_H */
>> 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
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver
  2009-06-11 20:24 ` [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver David Brownell
@ 2009-06-12 15:58   ` Karicheri, Muralidharan
  0 siblings, 0 replies; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-12 15:58 UTC (permalink / raw)
  To: David Brownell
  Cc: davinci-linux-open-source, linux-media, Muralidharan Karicheri



>>
>> This is the version v2 of the patch series. This is the reworked
>> version of the driver based on comments received against the last
>> version of the patch.
>
>I'll be glad to see this get to mainline ... it's seeming closer
>and closer!
>
>What's the merge plan though?  I had hopes for 2.6.31.real-soon
>but several of the later patches comment
>
Not sure if it can go in 2.6.31, but this has less comments to 
address then I can send a updated version next week. 2.6.32 is
the targeted release.
>  > Applies to Davinci GIT Tree
>
>which implies "not -next".  DM355 patches are in the "-next" tree.
>
>Is this just an oversight (tracking -next can be a PITA!) or is
>there some other dependency?
>
One dependency is the tvp514x sub device patch migration patch from Vaibhav. This is put for review, but couldn't see any comments.

I have split the patches such that v4l2 part can applies independently followed by platform part. All of the platform part has "Applies to Davinci GIT tree" in the patch description and v4l2 part has "Applies to v4l-dvb". The v4l2 part can go with out the platform changes, but platform part is dependent on the v4l2 part.

I am not sure if I have answered your question.
>-
>


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-11 17:00 ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 m-karicheri2
  2009-06-11 17:00   ` [PATCH 2/10 - v2] ccdc hw device header file for vpfe capture m-karicheri2
  2009-06-11 22:41   ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 Alexey Klimov
@ 2009-06-14 14:10   ` Hans Verkuil
  2009-06-15 21:47     ` Karicheri, Muralidharan
  2 siblings, 1 reply; 34+ messages in thread
From: Hans Verkuil @ 2009-06-14 14:10 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

On Thursday 11 June 2009 19:00:40 m-karicheri2@ti.com wrote:
> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
> 
> Re-sending since previous one missed a file (vpfe_types.h)
> 
> VPFE Capture bridge driver
> 
> This is version, v2 of vpfe capture bridge driver for doing video
> capture on DM355 and DM6446 evms. The ccdc hw modules register with the
> driver and are used for configuring the CCD Controller for a specific
> decoder interface. The driver also registers the sub devices required
> for a specific evm. More than one sub devices can be registered.
> This allows driver to switch dynamically to capture video from
> any sub device that is registered. Currently only one sub device
> (tvp5146) is supported. But in future this driver is expected
> to do capture from sensor devices such as Micron's MT9T001,MT9T031
> and MT9P031 etc. The driver currently supports MMAP based IO.
> 
> Following are the updates based on review comments:-
> 	1) minor number is allocated dynamically
> 	2) updates to QUERYCAP handling
> 	3) eliminated intermediate vpfe pixel format
> 	4) refactored few functions
> 	5) reworked isr routines for reducing indentation
> 	6) reworked vpfe_check_format and added a documentation
> 	   for algorithm
> 	7) fixed memory leak in probe()
> 
> TODO list :
> 	1) load sub device from bridge driver. Hans has enhanced
> 	the v4l2-subdevice framework to do this. Will be updated
> 	soon to pick this.
> 	
> 		
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
> 
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
> Applies to v4l-dvb repository
> 
>  drivers/media/video/davinci/vpfe_capture.c | 2252 ++++++++++++++++++++++++++++
>  include/media/davinci/vpfe_capture.h       |  183 +++
>  include/media/davinci/vpfe_types.h         |   51 +
>  3 files changed, 2486 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.c
>  create mode 100644 include/media/davinci/vpfe_capture.h
>  create mode 100644 include/media/davinci/vpfe_types.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..003450b
> --- /dev/null
> +++ b/drivers/media/video/davinci/vpfe_capture.c
> @@ -0,0 +1,2252 @@
> +/*
> + * 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
> + *
> + * Driver name : VPFE Capture driver
> + *    VPFE Capture driver allows applications to capture and stream video
> + *    frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
> + *    TVP5146 or  Raw Bayer RGB image data from an image sensor
> + *    such as Microns' MT9T001, MT9T031 etc.
> + *
> + *    These SoCs have, in common, a Video Processing Subsystem (VPSS) that
> + *    consists of a Video Processing Front End (VPFE) for capturing
> + *    video/raw image data and Video Processing Back End (VPBE) for displaying
> + *    YUV data through an in-built analog encoder or Digital LCD port. This
> + *    driver is for capture through VPFE. A typical EVM using these SoCs have
> + *    following high level configuration.
> + *
> + *
> + *    decoder(TVP5146/		YUV/
> + * 	     MT9T001)   -->  Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
> + *    				data input              |      |
> + *							V      |
> + *						      SDRAM    |
> + *							       V
> + *							   Image Processor
> + *							       |
> + *							       V
> + *							     SDRAM
> + *    The data flow happens from a decoder connected to the VPFE over a
> + *    YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
> + *    and to the input of VPFE through an optional MUX (if more inputs are
> + *    to be interfaced on the EVM). The input data is first passed through
> + *    CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
> + *    does very little or no processing on YUV data and does pre-process Raw
> + *    Bayer RGB data through modules such as Defect Pixel Correction (DFC)
> + *    Color Space Conversion (CSC), data gain/offset etc. After this, data
> + *    can be written to SDRAM or can be connected to the image processing
> + *    block such as IPIPE (on DM355 only).
> + *
> + *    Features supported
> + *  		- MMAP IO
> + *		- Capture using TVP5146 over BT.656
> + *		- support for interfacing decoders using sub device model
> + *		- Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV
> + *		  data capture to SDRAM.
> + *    TODO list
> + *		- Support multiple REQBUF after open
> + *		- Support for de-allocating buffers through REQBUF
> + *		- Support for Raw Bayer RGB capture
> + *		- Support for chaining Image Processor
> + *		- Support for static allocation of buffers
> + *		- Support for USERPTR IO
> + *		- Support for STREAMON before QBUF
> + */
> +#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 <media/davinci/vpfe_capture.h>
> +#include <media/tvp514x.h>
> +#include <linux/i2c.h>
> +#include "ccdc_hw_device.h"
> +
> +static int debug;
> +static u32 numbuffers = 3;
> +static u32 bufsize = (720 * 576 * 2);
> +
> +module_param(numbuffers, uint, S_IRUGO);
> +module_param(bufsize, uint, S_IRUGO);
> +module_param(debug, int, 0644);
> +
> +MODULE_PARM_DESC(numbuffers, "buffer count (default:3)");
> +MODULE_PARM_DESC(bufsize, "buffer size (default:720 x 576 x 2)");

'buffer size' -> 'buffer size in bytes'

> +MODULE_PARM_DESC(debug, "Debug level 0-1");
> +
> +
> +/* standard information */
> +struct vpfe_standard {
> +	v4l2_std_id std_id;
> +	unsigned int width;
> +	unsigned int height;
> +	struct v4l2_fract pixelaspect;
> +	/* 0 - progressive, 1 - interlaced */
> +	int frame_format;
> +};
> +
> +/* ccdc configuration */
> +struct ccdc_config {
> +	/* This make sure vpfe is probed and ready to go */
> +	int vpfe_probed;
> +	/* name of ccdc device */
> +	char name[32];
> +	/* for storing mem maps for CCDC */
> +	int ccdc_addr_size;
> +	void *__iomem ccdc_addr;
> +};
> +
> +/* data structures */
> +static struct vpfe_config_params config_params = {
> +	.min_numbuffers = 3,
> +	.numbuffers = 3,
> +	.min_bufsize = 720 * 480 * 2,
> +	.device_bufsize = 720 * 576 * 2,
> +};
> +
> +/* ccdc device registered */
> +static struct ccdc_hw_device *ccdc_dev;
> +/* lock for accessing ccdc information */
> +static DEFINE_MUTEX(ccdc_lock);
> +/* ccdc configuration */
> +static struct ccdc_config *ccdc_cfg;
> +
> +#define VPFE_PIXELASPECT_NTSC       {11, 10}
> +#define VPFE_PIXELASPECT_PAL        {54, 59}
> +
> +const struct vpfe_standard vpfe_standards[] = {
> +	{V4L2_STD_NTSC,	720, 480, VPFE_PIXELASPECT_NTSC, 1},
> +	{V4L2_STD_PAL,	720, 576, VPFE_PIXELASPECT_PAL, 1},

These VPFE_PIXELASPECT_ macros are used only here. So why not specify them
directly?

I also suggest using V4L2_STD_525_60 and V4L2_STD_625_50 instead of STD_NTSC
and STD_PAL.

> +};
> +
> +/* Used when raw Bayer image from ccdc is directly captured to SDRAM */
> +static const struct vpfe_pixel_format vpfe_pix_fmts[] = {
> +	{
> +		.fmtdesc = {
> +			.index = 0,
> +			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +			.description = "Bayer GrRBGb 8bit A-Law compr.",
> +			.pixelformat = V4L2_PIX_FMT_SBGGR8,
> +		},
> +		.bpp = 1,
> +	},
> +	{
> +		.fmtdesc = {
> +			.index = 1,
> +			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +			.description = "Bayer GrRBGb - 16bit",
> +			.pixelformat = V4L2_PIX_FMT_SBGGR16,
> +		},
> +		.bpp = 2,
> +	},
> +	{
> +		.fmtdesc = {
> +			.index = 2,
> +			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +			.description = "Bayer GrRBGb 8bit DPCM compr.",
> +			.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
> +		},
> +		.bpp = 1,
> +	},
> +	{
> +		.fmtdesc = {
> +			.index = 3,
> +			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +			.description = "YCbCr 4:2:2 Interleaved UYVY",
> +			.pixelformat = V4L2_PIX_FMT_UYVY,
> +		},
> +		.bpp = 2,
> +	},
> +	{
> +		.fmtdesc = {
> +			.index = 4,
> +			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +			.description = "YCbCr 4:2:2 Interleaved YUYV",
> +			.pixelformat = V4L2_PIX_FMT_YUYV,
> +		},
> +		.bpp = 2,
> +	},
> +	{
> +		.fmtdesc = {
> +			.index = 5,
> +			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +			.description = "Y/CbCr 4:2:0 - Semi planar",
> +			.pixelformat = V4L2_PIX_FMT_NV12,
> +		},
> +		.bpp = 1,
> +	},
> +};
> +
> +/*
> + * vpfe_lookup_pix_format()
> + * lookup an entry in the vpfe pix format table based on pix_format
> + */
> +static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) {
> +		if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat)
> +			return &vpfe_pix_fmts[i];
> +	}
> +	return NULL;
> +}
> +
> +/*
> + * vpfe_register_ccdc_device. CCDC module calls this to
> + * register with vpfe capture
> + */
> +int vpfe_register_ccdc_device(struct ccdc_hw_device *dev)
> +{
> +	int ret = 0;
> +	printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name);
> +
> +	BUG_ON(!dev->hw_ops.open);
> +	BUG_ON(!dev->hw_ops.enable);
> +	BUG_ON(!dev->hw_ops.set_hw_if_params);
> +	BUG_ON(!dev->hw_ops.configure);
> +	BUG_ON(!dev->hw_ops.set_buftype);
> +	BUG_ON(!dev->hw_ops.get_buftype);
> +	BUG_ON(!dev->hw_ops.enum_pix);
> +	BUG_ON(!dev->hw_ops.set_frame_format);
> +	BUG_ON(!dev->hw_ops.get_frame_format);
> +	BUG_ON(!dev->hw_ops.get_pixel_format);
> +	BUG_ON(!dev->hw_ops.set_pixel_format);
> +	BUG_ON(!dev->hw_ops.set_params);
> +	BUG_ON(!dev->hw_ops.set_image_window);
> +	BUG_ON(!dev->hw_ops.get_image_window);
> +	BUG_ON(!dev->hw_ops.get_line_length);
> +	BUG_ON(!dev->hw_ops.setfbaddr);
> +	BUG_ON(!dev->hw_ops.getfid);
> +
> +	mutex_lock(&ccdc_lock);
> +	if (NULL == ccdc_cfg) {
> +		/*
> +		 * TODO. Will this ever happen? if so, we need to fix it.
> +		 * Proabably we need to add the request to a linked list and
> +		 * walk through it during vpfe probe
> +		 */
> +		printk(KERN_ERR "vpfe capture not initialized\n");
> +		ret = -1;
> +		goto unlock;
> +	}
> +
> +	if (strcmp(dev->name, ccdc_cfg->name)) {
> +		/* ignore this ccdc */
> +		ret = -1;
> +		goto unlock;
> +	}
> +
> +	if (ccdc_dev) {
> +		printk(KERN_ERR "ccdc already registered\n");
> +		ret = -1;
> +		goto unlock;
> +	}
> +
> +	ccdc_dev = dev;
> +	dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr,
> +				  ccdc_cfg->ccdc_addr_size);
> +unlock:
> +	mutex_unlock(&ccdc_lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL(vpfe_register_ccdc_device);
> +
> +/*
> + * vpfe_unregister_ccdc_device. CCDC module calls this to
> + * unregister with vpfe capture
> + */
> +void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev)
> +{
> +	if (NULL == dev) {
> +		printk(KERN_ERR "invalid ccdc device ptr\n");
> +		return;
> +	}
> +
> +	printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n",
> +		dev->name);
> +
> +	if (strcmp(dev->name, ccdc_cfg->name)) {
> +		/* ignore this ccdc */
> +		return;
> +	}
> +
> +	mutex_lock(&ccdc_lock);
> +	ccdc_dev = NULL;
> +	mutex_unlock(&ccdc_lock);
> +	return;
> +}
> +EXPORT_SYMBOL(vpfe_unregister_ccdc_device);
> +
> +/* Set interface params based on client interface */
> +static int vpfe_set_hw_if_params(struct vpfe_device *vpfe_dev)
> +{
> +	struct vpfe_subdev_info *subdev = vpfe_dev->current_subdev;
> +	struct v4l2_routing *route =
> +		&(subdev->routes[vpfe_dev->current_input]);
> +
> +	switch (route->output) {
> +	case OUTPUT_10BIT_422_EMBEDDED_SYNC:
> +		vpfe_dev->vpfe_if_params.if_type = VPFE_BT656;
> +		break;
> +	case OUTPUT_20BIT_422_SEPERATE_SYNC:
> +		vpfe_dev->vpfe_if_params.if_type = VPFE_YCBCR_SYNC_16;
> +		break;
> +	case OUTPUT_10BIT_422_SEPERATE_SYNC:
> +		vpfe_dev->vpfe_if_params.if_type = VPFE_YCBCR_SYNC_8;
> +		break;
> +	default:
> +		v4l2_err(&vpfe_dev->v4l2_dev, "decoder output"
> +			" not supported, %d\n", route->output);
> +		return -EINVAL;
> +	}
> +
> +	/* set if client specific interface param is available */
> +	if (subdev->pdata) {
> +		/* each client will have different interface requirements */
> +		if (!strcmp(subdev->name, "tvp5146")) {
> +			struct tvp514x_platform_data *pdata = subdev->pdata;
> +
> +			if (pdata->hs_polarity)
> +				vpfe_dev->vpfe_if_params.hdpol =
> +					VPFE_PINPOL_POSITIVE;
> +			else
> +				vpfe_dev->vpfe_if_params.hdpol =
> +					VPFE_PINPOL_NEGATIVE;
> +
> +			if (pdata->vs_polarity)
> +				vpfe_dev->vpfe_if_params.vdpol =
> +					VPFE_PINPOL_POSITIVE;
> +			else
> +				vpfe_dev->vpfe_if_params.hdpol =
> +					VPFE_PINPOL_NEGATIVE;

This won't work. Instead this should be data associated with the platform_data.
I.e. the platform_data for the dm355/dm6446 contains not only the subdev
information, but for each subdev also the information on how to setup the vpfe
polarities. You cannot derive that information from what subdevs are used since
the board designer might have added e.g. inverters or something like that. Such
information can only come from the platform_data.

> +		} else {
> +			v4l2_err(&vpfe_dev->v4l2_dev, "No interface params"
> +				" defined for subdevice, %d\n", route->output);
> +			return -EFAULT;
> +		}
> +	}
> +	return ccdc_dev->hw_ops.set_hw_if_params(&vpfe_dev->vpfe_if_params);
> +}
> +
> +/*
> + * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings
> + */
> +static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev,
> +				 struct v4l2_format *f)
> +{
> +	struct v4l2_rect image_win;
> +	enum ccdc_buftype buf_type;
> +	enum ccdc_frmfmt frm_fmt;
> +
> +	memset(f, 0, sizeof(*f));
> +	f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
> +	ccdc_dev->hw_ops.get_image_window(&image_win);
> +	f->fmt.pix.width = image_win.width;
> +	f->fmt.pix.height = image_win.height;
> +	f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length();
> +	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
> +				f->fmt.pix.height;
> +	buf_type = ccdc_dev->hw_ops.get_buftype();
> +	f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format();
> +	frm_fmt = ccdc_dev->hw_ops.get_frame_format();
> +	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 {
> +			v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type");
> +			return -EINVAL;
> +		}
> +	} else {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt");
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +/*
> + * vpfe_config_ccdc_image_format()
> + * For a pix format, configure ccdc to setup the capture
> + */
> +static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev)
> +{
> +	enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
> +	int ret = 0;
> +
> +	if (ccdc_dev->hw_ops.set_pixel_format(
> +			vpfe_dev->fmt.fmt.pix.pixelformat) < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"couldn't set pix format in ccdc\n");
> +		return -EINVAL;
> +	}
> +	/* configure the image window */
> +	ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop);
> +
> +	switch (vpfe_dev->fmt.fmt.pix.field) {
> +	case V4L2_FIELD_INTERLACED:
> +		/* do nothing, since it is default */
> +		ret = ccdc_dev->hw_ops.set_buftype(
> +				CCDC_BUFTYPE_FLD_INTERLEAVED);
> +		break;
> +	case V4L2_FIELD_NONE:
> +		frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
> +		/* buffer type only applicable for interlaced scan */
> +		break;
> +	case V4L2_FIELD_SEQ_TB:
> +		ret = ccdc_dev->hw_ops.set_buftype(
> +				CCDC_BUFTYPE_FLD_SEPARATED);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	/* set the frame format */
> +	if (!ret)
> +		ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt);
> +	return ret;
> +}
> +/*
> + * vpfe_config_image_format()
> + * For a given standard, this functions sets up the default
> + * pix format & crop values in the vpfe device and ccdc.  It first
> + * starts with defaults based values from the standard table.
> + * It then checks if sub device support g_fmt and then override the
> + * values based on that.Sets crop values to match with scan resolution
> + * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
> + * values in ccdc
> + */
> +static int vpfe_config_image_format(struct vpfe_device *vpfe_dev,
> +				    const v4l2_std_id *std_id)
> +{
> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
> +	int i, ret = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
> +		if (vpfe_standards[i].std_id == *std_id) {

std_id is a bitmask, so you probably want to do '& *std_id' here.

> +			vpfe_dev->std_info.active_pixels =
> +					vpfe_standards[i].width;
> +			vpfe_dev->std_info.active_lines =
> +					vpfe_standards[i].height;
> +			vpfe_dev->std_info.frame_format =
> +					vpfe_standards[i].frame_format;
> +			vpfe_dev->std_index = i;
> +			break;
> +		}
> +	}
> +
> +	if (i ==  ARRAY_SIZE(vpfe_standards)) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	vpfe_dev->crop.top = 0;
> +	vpfe_dev->crop.left = 0;
> +	vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels;
> +	vpfe_dev->crop.height = vpfe_dev->std_info.active_lines;
> +	vpfe_dev->fmt.fmt.pix.width = vpfe_dev->crop.width;
> +	vpfe_dev->fmt.fmt.pix.height = vpfe_dev->crop.height;
> +
> +	/* first field and frame format based on standard frame format */
> +	if (vpfe_dev->std_info.frame_format) {
> +		vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
> +		/* assume V4L2_PIX_FMT_UYVY as default */
> +		vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
> +	} else {
> +		vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_NONE;
> +		/* assume V4L2_PIX_FMT_SBGGR8 */
> +		vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
> +	}
> +
> +	/* if sub device supports g_fmt, override the defaults */
> +	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
> +			sub_dev->grp_id,
> +			video, g_fmt, &vpfe_dev->fmt);
> +
> +	if (ret && ret != -ENOIOCTLCMD) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"error in getting g_fmt from sub device\n");
> +		return ret;
> +	}
> +
> +	/* Sets the values in CCDC */
> +	ret = vpfe_config_ccdc_image_format(vpfe_dev);
> +	if (ret)
> +		return ret;
> +
> +	/* Update the values of sizeimage and bytesperline */
> +	if (!ret) {
> +		vpfe_dev->fmt.fmt.pix.bytesperline =
> +			ccdc_dev->hw_ops.get_line_length();
> +		vpfe_dev->fmt.fmt.pix.sizeimage =
> +			vpfe_dev->fmt.fmt.pix.bytesperline *
> +			vpfe_dev->fmt.fmt.pix.height;
> +	}
> +	return ret;
> +}
> +
> +static int vpfe_initialize_device(struct vpfe_device *vpfe_dev)
> +{
> +	int ret = 0;
> +
> +	/* set first input of current subdevice as the current input */
> +	vpfe_dev->current_input = 0;
> +
> +	/* set default standard */
> +	vpfe_dev->std_index = 0;
> +
> +	/* Configure the default format information */
> +	ret = vpfe_config_image_format(vpfe_dev,
> +				&vpfe_standards[vpfe_dev->std_index].std_id);
> +	if (ret)
> +		return ret;
> +
> +	/* now open the ccdc device to initialize it */
> +	mutex_lock(&ccdc_lock);
> +	if (NULL == ccdc_dev) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n");
> +		ret = -ENODEV;
> +		goto unlock;
> +	}
> +
> +	if (!try_module_get(ccdc_dev->owner)) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n");
> +		ret = -ENODEV;
> +		goto unlock;
> +	}
> +	ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev);
> +	if (!ret)
> +		vpfe_dev->initialized = 1;
> +unlock:
> +	mutex_unlock(&ccdc_lock);
> +	return ret;
> +}
> +
> +/*
> + * vpfe_open : It creates object of file handle structure and
> + * stores it in private_data  member of filepointer
> + */
> +static int vpfe_open(struct file *file)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_fh *fh;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");
> +
> +	if (!vpfe_dev->cfg->num_subdevs) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");
> +		return -ENODEV;
> +	}

Why would this be an error? I might have an FPGA connected instead or some
other non-i2c device that doesn't require any setup from this driver.

> +
> +	/* Allocate memory for the file handle object */
> +	fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
> +	if (NULL == fh) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"unable to allocate memory for file handle object\n");
> +		return -ENOMEM;
> +	}
> +	/* store pointer to fh in private_data member of file */
> +	file->private_data = fh;
> +	fh->vpfe_dev = vpfe_dev;
> +	mutex_lock(&vpfe_dev->lock);
> +	/* If decoder is not initialized. initialize it */
> +	if (!vpfe_dev->initialized) {
> +		if (vpfe_initialize_device(vpfe_dev)) {
> +			mutex_unlock(&vpfe_dev->lock);
> +			return -ENODEV;
> +		}
> +	}
> +	/* Increment device usrs counter */
> +	vpfe_dev->usrs++;
> +	/* Set io_allowed member to false */
> +	fh->io_allowed = 0;
> +	/* Initialize priority of this instance to default priority */
> +	fh->prio = V4L2_PRIORITY_UNSET;
> +	v4l2_prio_open(&vpfe_dev->prio, &fh->prio);
> +	mutex_unlock(&vpfe_dev->lock);
> +	return 0;
> +}
> +
> +static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)
> +{
> +	unsigned long addr;

Add newline.

> +	vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
> +					struct videobuf_buffer, queue);
> +	list_del(&vpfe_dev->next_frm->queue);
> +	vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
> +	addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
> +	ccdc_dev->hw_ops.setfbaddr(addr);
> +}
> +
> +static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev)
> +{
> +	struct timeval timevalue;
> +
> +	do_gettimeofday(&timevalue);
> +	vpfe_dev->cur_frm->ts = timevalue;
> +	vpfe_dev->cur_frm->state = VIDEOBUF_DONE;
> +	vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage;
> +	wake_up_interruptible(&vpfe_dev->cur_frm->done);
> +	vpfe_dev->cur_frm = vpfe_dev->next_frm;
> +}
> +
> +/* ISR for VINT0*/
> +static irqreturn_t vpfe_isr(int irq, void *dev_id)
> +{
> +	struct vpfe_device *vpfe_dev = dev_id;
> +	enum v4l2_field field;
> +	unsigned long addr;
> +	int fid;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...");
> +	field = vpfe_dev->fmt.fmt.pix.field;
> +
> +	/* if streaming not started, don't do anything */
> +	if (!vpfe_dev->started)
> +		return IRQ_RETVAL(1);

Why not return IRQ_NONE or IRQ_HANDLED directly?

> +
> +	/* only for 6446 this will be applicable */
> +	if (NULL != ccdc_dev->hw_ops.reset)
> +		ccdc_dev->hw_ops.reset();
> +
> +	if (field == V4L2_FIELD_NONE) {
> +		/* handle progressive frame capture */
> +		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +			"frame format is progressive...\n");
> +		if (vpfe_dev->cur_frm != vpfe_dev->next_frm)
> +			vpfe_process_buffer_complete(vpfe_dev);
> +		return IRQ_RETVAL(1);

Ditto, and repeated below as well.

> +	}
> +
> +	/* interlaced or TB capture check which field we are in hardware */
> +	fid = ccdc_dev->hw_ops.getfid();
> +
> +	/* switch the software maintained field id */
> +	vpfe_dev->field_id ^= 1;
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n",
> +		fid, vpfe_dev->field_id);
> +	if (fid == vpfe_dev->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_dev->cur_frm != vpfe_dev->next_frm)
> +				vpfe_process_buffer_complete(vpfe_dev);
> +			/*
> +			 * based on whether the two fields are stored
> +			 * interleavely or separately in memory, reconfigure
> +			 * the CCDC memory address
> +			 */
> +			if (field == V4L2_FIELD_SEQ_TB) {
> +				addr =
> +				  videobuf_to_dma_contig(vpfe_dev->cur_frm);
> +				addr += vpfe_dev->field_off;
> +				ccdc_dev->hw_ops.setfbaddr(addr);
> +			}
> +			return IRQ_RETVAL(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
> +		 */
> +		spin_lock(&vpfe_dev->dma_queue_lock);
> +		if (!list_empty(&vpfe_dev->dma_queue) &&
> +		    vpfe_dev->cur_frm == vpfe_dev->next_frm)
> +			vpfe_schedule_next_buffer(vpfe_dev);
> +		spin_unlock(&vpfe_dev->dma_queue_lock);
> +	} else if (fid == 0) {
> +		/*
> +		 * out of sync. Recover from any hardware out-of-sync.
> +		 * May loose one frame
> +		 */
> +		vpfe_dev->field_id = fid;
> +	}
> +	return IRQ_RETVAL(1);
> +}
> +
> +/* vdint1_isr - isr handler for VINT1 interrupt */
> +static irqreturn_t vdint1_isr(int irq, void *dev_id)
> +{
> +	struct vpfe_device *vpfe_dev = dev_id;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...");
> +
> +	/* if streaming not started, don't do anything */
> +	if (!vpfe_dev->started)
> +		return IRQ_RETVAL(1);
> +
> +	spin_lock(&vpfe_dev->dma_queue_lock);
> +	if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) &&
> +	    !list_empty(&vpfe_dev->dma_queue) &&
> +	    vpfe_dev->cur_frm == vpfe_dev->next_frm)
> +		vpfe_schedule_next_buffer(vpfe_dev);
> +	spin_unlock(&vpfe_dev->dma_queue_lock);
> +	return IRQ_RETVAL(1);
> +}
> +
> +static void vpfe_detach_irq(struct vpfe_device *vpfe_dev)
> +{
> +	enum ccdc_frmfmt frame_format;
> +
> +	frame_format = ccdc_dev->hw_ops.get_frame_format();
> +	if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
> +		free_irq(IRQ_VDINT1, vpfe_dev);
> +}
> +
> +static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
> +{
> +	enum ccdc_frmfmt frame_format;
> +
> +	frame_format = ccdc_dev->hw_ops.get_frame_format();
> +	if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {
> +		return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr,
> +				    IRQF_DISABLED, "vpfe_capture1",
> +				    vpfe_dev);
> +	}
> +	return 0;
> +}
> +
> +/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */
> +static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev)
> +{
> +	vpfe_dev->started = 0;
> +	ccdc_dev->hw_ops.enable(0);
> +	if (ccdc_dev->hw_ops.enable_out_to_sdram)
> +		ccdc_dev->hw_ops.enable_out_to_sdram(0);
> +}
> +
> +/*
> + * vpfe_release : This function deletes buffer queue, frees the
> + * buffers and the vpfe file  handle
> + */
> +static int vpfe_release(struct file *file)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_fh *fh = file->private_data;
> +	struct vpfe_subdev_info *subdev;
> +	int ret;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
> +
> +	/* Get the device lock */
> +	mutex_lock(&vpfe_dev->lock);
> +	/* if this instance is doing IO */
> +	if (fh->io_allowed) {
> +		if (vpfe_dev->started) {
> +			subdev = vpfe_dev->current_subdev;
> +			ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
> +							 subdev->grp_id,
> +							 video, s_stream, 0);
> +			if (ret && (ret != -ENOIOCTLCMD))
> +				v4l2_err(&vpfe_dev->v4l2_dev,
> +				"stream off failed in subdev\n");
> +			vpfe_stop_ccdc_capture(vpfe_dev);
> +			vpfe_detach_irq(vpfe_dev);
> +			videobuf_streamoff(&vpfe_dev->buffer_queue);
> +		}
> +		vpfe_dev->io_usrs = 0;
> +		vpfe_dev->numbuffers = config_params.numbuffers;
> +	}
> +
> +	/* Decrement device usrs counter */
> +	vpfe_dev->usrs--;
> +	/* Close the priority */
> +	v4l2_prio_close(&vpfe_dev->prio, &fh->prio);
> +	/* If this is the last file handle */
> +	if (!vpfe_dev->usrs) {
> +		vpfe_dev->initialized = 0;
> +		if (ccdc_dev->hw_ops.close)
> +			ccdc_dev->hw_ops.close(vpfe_dev->pdev);
> +		module_put(ccdc_dev->owner);
> +	}
> +	mutex_unlock(&vpfe_dev->lock);
> +	file->private_data = NULL;
> +	/* Free memory allocated to file handle object */
> +	kfree(fh);
> +	return 0;
> +}
> +
> +/*
> + * vpfe_mmap : It is used to map kernel space buffers
> + * into user spaces
> + */
> +static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	/* Get the device object and file handle object */
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
> +
> +	return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma);
> +}
> +
> +/*
> + * vpfe_poll: It is used for select/poll system call
> + */
> +static unsigned int vpfe_poll(struct file *file, poll_table *wait)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
> +
> +	if (vpfe_dev->started)
> +		return videobuf_poll_stream(file,
> +					    &vpfe_dev->buffer_queue, wait);
> +	return 0;
> +}
> +
> +/* 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
> +};

Should be a const struct. I also recommend using .unlocked_ioctl instead of
.ioctl. The .ioctl variant means that the ioctl is called with the big kernel
lock held, and for new drivers it is much better to ensure proper locking so
that the BKL isn't necessary.

> +
> +/*
> + * vpfe_check_format()
> + * This function adjust the input pixel format as per hardware
> + * capabilities and update the same in pixfmt.
> + * Following algorithm used :-
> + *
> + *	If given pixformat is not in the vpfe list of pix formats or not
> + *	supported by the hardware, current value of pixformat in the device
> + *	is used
> + *	If given field is not supported, then current field is used. If field
> + *	is different from current, then it is matched with that from sub device.
> + *	Minimum height is 2 lines for interlaced or tb field and 1 line for
> + *	progressive. Maximum height is clamped to active active lines of scan
> + *	Minimum width is 32 bytes in memory and width is clamped to active
> + *	pixels of scan.
> + *	bytesperline is a multiple of 32.
> + */
> +static const struct vpfe_pixel_format *
> +	vpfe_check_format(struct vpfe_device *vpfe_dev,
> +			  struct v4l2_pix_format *pixfmt)
> +{
> +	u32 min_height = 1, min_width = 32, max_width, max_height;
> +	const struct vpfe_pixel_format *vpfe_pix_fmt;
> +	u32 pix;
> +	int temp, found;
> +
> +	vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
> +	if (NULL == vpfe_pix_fmt) {
> +		/*
> +		 * use current pixel format in the vpfe device. We
> +		 * will find this pix format in the table
> +		 */
> +		pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
> +		vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
> +	}
> +
> +	/* check if hw supports it */
> +	temp = 0;
> +	found = 0;
> +	while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) {
> +		if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) {
> +			found = 1;
> +			break;
> +		}
> +		temp++;
> +	}
> +
> +	if (!found) {
> +		/* use current pixel format */
> +		pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
> +		/*
> +		 * Since this is currently used in the vpfe device, we
> +		 * will find this pix format in the table
> +		 */
> +		vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
> +	}
> +
> +	/* check what field format is supported */
> +	if (pixfmt->field == V4L2_FIELD_ANY) {
> +		/* if field is any, use current value as default */
> +		pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
> +	}
> +
> +	/*
> +	 * if field is not same as current field in the vpfe device
> +	 * try matching the field with the sub device field
> +	 */
> +	if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) {
> +		/*
> +		 * If field value is not in the supported fields, use current
> +		 * field used in the device as default
> +		 */
> +		switch (pixfmt->field) {
> +		case V4L2_FIELD_INTERLACED:
> +		case V4L2_FIELD_SEQ_TB:
> +			/* if sub device is supporting progressive, use that */
> +			if (!vpfe_dev->std_info.frame_format)
> +				pixfmt->field = V4L2_FIELD_NONE;
> +			break;
> +		case V4L2_FIELD_NONE:
> +			if (vpfe_dev->std_info.frame_format)
> +				pixfmt->field = V4L2_FIELD_INTERLACED;
> +			break;
> +
> +		default:
> +			/* use current field as default */
> +			pixfmt->field = vpfe_dev->fmt.fmt.pix.field;

Add a break here.

> +		}
> +	}
> +
> +	/* Now adjust image resolutions supported */
> +	if (pixfmt->field == V4L2_FIELD_INTERLACED ||
> +	    pixfmt->field == V4L2_FIELD_SEQ_TB)
> +		min_height = 2;
> +
> +	max_width = vpfe_dev->std_info.active_pixels;
> +	max_height = vpfe_dev->std_info.active_lines;
> +	min_width /= vpfe_pix_fmt->bpp;
> +
> +	v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n",
> +		  pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp);
> +
> +	pixfmt->width = clamp((pixfmt->width), min_width, max_width);
> +	pixfmt->height = clamp((pixfmt->height), min_height, max_height);
> +
> +	/* If interlaced, adjust height to be a multiple of 2 */
> +	if (pixfmt->field == V4L2_FIELD_INTERLACED)
> +		pixfmt->height &= (~1);
> +	/*
> +	 * recalculate bytesperline and sizeimage since width
> +	 * and height might have changed
> +	 */
> +	pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31)
> +				& ~31);
> +	if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
> +		pixfmt->sizeimage =
> +			pixfmt->bytesperline * pixfmt->height +
> +			((pixfmt->bytesperline * pixfmt->height) >> 1);
> +	else
> +		pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
> +
> +	v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="
> +		 " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
> +		 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,
> +		 pixfmt->bytesperline, pixfmt->sizeimage);
> +	return vpfe_pix_fmt;
> +}
> +
> +static int vpfe_querycap(struct file *file, void  *priv,
> +			       struct v4l2_capability *cap)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
> +
> +	cap->version = VPFE_CAPTURE_VERSION_CODE;
> +	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
> +	strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
> +	strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));

Perhaps use "VPFE" instead of the very non-descript 'Platform'?

> +	strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
> +	return 0;
> +}
> +
> +static int vpfe_g_fmt_vid_cap(struct file *file, void *priv,
> +				struct v4l2_format *fmt)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n");
> +	/* Fill in the information about format */
> +	*fmt = vpfe_dev->fmt;
> +	return ret;
> +}
> +
> +static int vpfe_enum_fmt_vid_cap(struct file *file, void  *priv,
> +				   struct v4l2_fmtdesc *fmt)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	const struct vpfe_pixel_format *pix_fmt;
> +	int temp_index;
> +	u32 pix;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n");
> +
> +	if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0)
> +		return -EINVAL;
> +
> +	/* Fill in the information about format */
> +	pix_fmt = vpfe_lookup_pix_format(pix);
> +	if (NULL != pix_fmt) {
> +		temp_index = fmt->index;
> +		*fmt = pix_fmt->fmtdesc;
> +		fmt->index = temp_index;
> +		return 0;
> +	}
> +	return -EINVAL;
> +}
> +
> +static int vpfe_s_fmt_vid_cap(struct file *file, void *priv,
> +				struct v4l2_format *fmt)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	const struct vpfe_pixel_format *pix_fmts;
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");
> +
> +	/* If streaming is started, return error */
> +	if (vpfe_dev->started) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
> +		return -EBUSY;
> +	}
> +
> +	/* Check for valid frame format */
> +	pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);
> +
> +	if (NULL == pix_fmts)
> +		return -EINVAL;
> +
> +	/* store the pixel format in the device  object */
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	/* First detach any IRQ if currently attached */
> +	vpfe_detach_irq(vpfe_dev);
> +	vpfe_dev->fmt = *fmt;
> +	/* set image capture parameters in the ccdc */
> +	ret = vpfe_config_ccdc_image_format(vpfe_dev);
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +static int vpfe_try_fmt_vid_cap(struct file *file, void *priv,
> +				  struct v4l2_format *f)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	const struct vpfe_pixel_format *pix_fmts;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");
> +
> +	pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);
> +	if (NULL == pix_fmts)
> +		return -EINVAL;
> +	return 0;
> +}
> +
> +/*
> + * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a
> + * given app input index
> + */
> +static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev,
> +					int *subdev_index,
> +					int *subdev_input_index,
> +					int app_input_index)
> +{
> +	struct vpfe_config *cfg = vpfe_dev->cfg;
> +	struct vpfe_subdev_info *sub_dev;
> +	int i, j = 0;
> +
> +	for (i = 0; i < cfg->num_subdevs; i++) {
> +		sub_dev = &cfg->sub_devs[i];
> +		if (app_input_index < (j + sub_dev->num_inputs)) {
> +			*subdev_index = i;
> +			*subdev_input_index = app_input_index - j;
> +			return 0;
> +		}
> +		j += sub_dev->num_inputs;
> +	}
> +	return -EINVAL;
> +}
> +
> +/*
> + * vpfe_get_app_input - Get app input index for a given subdev input index
> + * driver stores the input index of the current sub device and translate it
> + * when application request the current input
> + */
> +static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev,
> +				    int *app_input_index)
> +{
> +	struct vpfe_config *cfg = vpfe_dev->cfg;
> +	struct vpfe_subdev_info *sub_dev;
> +	int i, j = 0;
> +
> +	for (i = 0; i < cfg->num_subdevs; i++) {
> +		sub_dev = &cfg->sub_devs[i];
> +		if (!strcmp(sub_dev->name, vpfe_dev->current_subdev->name)) {
> +			if (vpfe_dev->current_input >= sub_dev->num_inputs)
> +				return -1;
> +			*app_input_index = j + vpfe_dev->current_input;
> +			return 0;
> +		}
> +		j += sub_dev->num_inputs;
> +	}
> +	return -EINVAL;
> +}
> +
> +static int vpfe_enum_input(struct file *file, void *priv,
> +				 struct v4l2_input *inp)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *sub_dev;
> +	int subdev, index ;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
> +
> +	if (vpfe_get_subdev_input_index(vpfe_dev,
> +					&subdev,
> +					&index,
> +					inp->index) < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"
> +			 " for the subdev\n");
> +		return -EINVAL;
> +	}
> +	sub_dev = &vpfe_dev->cfg->sub_devs[subdev];
> +	memcpy(inp, &sub_dev->inputs[index],
> +		sizeof(struct v4l2_input));
> +	return 0;
> +}
> +
> +static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
> +
> +	return vpfe_get_app_input_index(vpfe_dev, index);
> +}
> +
> +
> +static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *sub_dev;
> +	int subdev_index, inp_index;
> +	struct v4l2_routing *route;

Don't use this v4l2_routing struct: it will disappear as soon as the
v4l2-int-device interface disappears.

> +	u32 input = 0, output = 0;
> +	int ret = -EINVAL;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * If streaming is started return device busy
> +	 * error
> +	 */
> +	if (vpfe_dev->started) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
> +		ret = -EBUSY;
> +		goto unlock_out;
> +	}
> +
> +	if (vpfe_get_subdev_input_index(vpfe_dev,
> +					&subdev_index,
> +					&inp_index,
> +					index) < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");
> +		goto unlock_out;
> +	}
> +
> +	sub_dev = &vpfe_dev->cfg->sub_devs[subdev_index];
> +	route = &sub_dev->routes[inp_index];
> +	if (route && sub_dev->can_route) {
> +		input = route->input;
> +		output = route->output;
> +	}
> +
> +	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
> +					 sub_dev->grp_id,
> +					 video, s_routing, input,
> +					 output, 0);
> +
> +	if (ret) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"vpfe_doioctl:error in setting input in decoder \n");
> +		ret = -EINVAL;
> +		goto unlock_out;
> +	}
> +	vpfe_dev->current_subdev = sub_dev;
> +	vpfe_dev->current_input = index;
> +	vpfe_dev->std_index = 0;
> +
> +	ret = vpfe_set_hw_if_params(vpfe_dev);
> +	if (ret)
> +		goto unlock_out;
> +
> +	/* set the default image parameters in the device */
> +	ret = vpfe_config_image_format(vpfe_dev,
> +				&vpfe_standards[vpfe_dev->std_index].std_id);
> +	if (ret)
> +		goto unlock_out;

This goto is not needed.

> +
> +unlock_out:
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *subdev;
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	subdev = vpfe_dev->current_subdev;
> +	if (ret)
> +		return ret;
> +	/* Call querystd function of decoder device */
> +	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
> +					 subdev->grp_id,
> +					 video, querystd, std_id);
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *subdev;

Suggestion: instead of using the name 'subdev' for a vpfe_subdev_info pointer,
it is better to use something like 'sdinfo' or 'sdi' or perhaps just plain
'info'. Every time I read 'subdev' I think it refers to a v4l2_subdev struct.

> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
> +
> +	/* Call decoder driver function to set the standard */
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	subdev = vpfe_dev->current_subdev;
> +	/* If streaming is started, return device busy error */
> +	if (vpfe_dev->started) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
> +		ret = -EBUSY;
> +		goto unlock_out;
> +	}
> +
> +	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
> +					 core, s_std, *std_id);
> +	if (ret < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
> +		goto unlock_out;
> +	}
> +	ret = vpfe_config_image_format(vpfe_dev, std_id);
> +
> +unlock_out:
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
> +
> +	*std_id = vpfe_standards[vpfe_dev->std_index].std_id;
> +	return 0;
> +}
> +/*
> + *  Videobuf operations
> + */
> +static int vpfe_videobuf_setup(struct videobuf_queue *vq,
> +				unsigned int *count,
> +				unsigned int *size)
> +{
> +	struct vpfe_fh *fh = vq->priv_data;
> +	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
> +	*size = config_params.device_bufsize;
> +
> +	if (*count < config_params.min_numbuffers)
> +		*count = config_params.min_numbuffers;
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +		"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)
> +{
> +	struct vpfe_fh *fh = vq->priv_data;
> +	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
> +
> +	/* If buffer is not initialized, initialize it */
> +	if (VIDEOBUF_NEEDS_INIT == vb->state) {
> +		vb->width = vpfe_dev->fmt.fmt.pix.width;
> +		vb->height = vpfe_dev->fmt.fmt.pix.height;
> +		vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
> +		vb->field = field;
> +	}
> +	vb->state = VIDEOBUF_PREPARED;
> +	return 0;
> +}
> +
> +static void vpfe_videobuf_queue(struct videobuf_queue *vq,
> +				struct videobuf_buffer *vb)
> +{
> +	/* Get the file handle object and device object */
> +	struct vpfe_fh *fh = vq->priv_data;
> +	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +	unsigned long flags;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n");
> +
> +	/* add the buffer to the DMA queue */
> +	spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
> +	list_add_tail(&vb->queue, &vpfe_dev->dma_queue);
> +	spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
> +
> +	/* Change state of the buffer */
> +	vb->state = VIDEOBUF_QUEUED;
> +}
> +
> +static void vpfe_videobuf_release(struct videobuf_queue *vq,
> +				  struct videobuf_buffer *vb)
> +{
> +	struct vpfe_fh *fh = vq->priv_data;
> +	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> +	unsigned long flags;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");
> +
> +	/*
> +	 * We need to flush the buffer from the dma queue since
> +	 * they are de-allocated
> +	 */
> +	spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
> +	INIT_LIST_HEAD(&vpfe_dev->dma_queue);
> +	spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
> +	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,
> +};
> +
> +/*
> + * vpfe_reqbufs. currently support REQBUF only once opening
> + * the device.
> + */
> +static int vpfe_reqbufs(struct file *file, void *priv,
> +			struct v4l2_requestbuffers *req_buf)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_fh *fh = file->private_data;
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
> +
> +	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
> +		return -EINVAL;
> +	}
> +
> +	if (V4L2_MEMORY_USERPTR == req_buf->memory) {
> +		/* we don't support user ptr IO */
> +		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
> +			 " USERPTR IO not supported>\n");
> +		return  -EINVAL;
> +	}
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	if (vpfe_dev->io_usrs != 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
> +		ret = -EBUSY;
> +		goto unlock_out;
> +	}
> +
> +	vpfe_dev->memory = req_buf->memory;
> +	videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue,
> +				&vpfe_videobuf_qops,
> +				NULL,
> +				&vpfe_dev->irqlock,
> +				req_buf->type,
> +				vpfe_dev->fmt.fmt.pix.field,
> +				sizeof(struct videobuf_buffer),
> +				fh);
> +
> +	fh->io_allowed = 1;
> +	vpfe_dev->io_usrs = 1;
> +	INIT_LIST_HEAD(&vpfe_dev->dma_queue);
> +	ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf);
> +unlock_out:
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +static int vpfe_querybuf(struct file *file, void *priv,
> +			 struct v4l2_buffer *buf)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
> +
> +	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +		return  -EINVAL;
> +	}
> +
> +	if (vpfe_dev->memory != V4L2_MEMORY_MMAP) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
> +		return -EINVAL;
> +	}
> +	/* Call videobuf_querybuf to get information */
> +	return videobuf_querybuf(&vpfe_dev->buffer_queue, buf);
> +}
> +
> +static int vpfe_qbuf(struct file *file, void *priv,
> +		     struct v4l2_buffer *p)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_fh *fh = file->private_data;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
> +
> +	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * If this file handle is not allowed to do IO,
> +	 * return error
> +	 */
> +	if (!fh->io_allowed) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
> +		return -EACCES;
> +	}
> +	return videobuf_qbuf(&vpfe_dev->buffer_queue, p);
> +}
> +
> +static int vpfe_dqbuf(struct file *file, void *priv,
> +		      struct v4l2_buffer *buf)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
> +
> +	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +		return -EINVAL;
> +	}
> +	return videobuf_dqbuf(&vpfe_dev->buffer_queue,
> +				      buf, file->f_flags & O_NONBLOCK);
> +}
> +
> +/*
> + * vpfe_calculate_offsets : This function calculates buffers offset
> + * for top and bottom field
> + */
> +static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev)
> +{
> +	struct v4l2_rect image_win;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n");
> +
> +	ccdc_dev->hw_ops.get_image_window(&image_win);
> +	vpfe_dev->field_off = image_win.height * image_win.width;
> +}
> +
> +/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */
> +static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev)
> +{
> +	ccdc_dev->hw_ops.enable(1);
> +	if (ccdc_dev->hw_ops.enable_out_to_sdram)
> +		ccdc_dev->hw_ops.enable_out_to_sdram(1);
> +	vpfe_dev->started = 1;
> +}
> +
> +/*
> + * vpfe_streamon. Assume the DMA queue is not empty.
> + * application is expected to call QBUF before calling
> + * this ioctl. If not, driver returns error
> + */
> +static int vpfe_streamon(struct file *file, void *priv,
> +			 enum v4l2_buf_type buf_type)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_fh *fh = file->private_data;
> +	struct vpfe_subdev_info *subdev;
> +	unsigned long addr;
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
> +
> +	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +		return -EINVAL;
> +	}
> +
> +	/* If file handle is not allowed IO, return error */
> +	if (!fh->io_allowed) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
> +		return -EACCES;
> +	}
> +
> +	subdev = vpfe_dev->current_subdev;
> +	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
> +					video, s_stream, 1);
> +
> +	if (ret && (ret != -ENOIOCTLCMD)) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n");
> +		return -EINVAL;
> +	}
> +
> +	/* If buffer queue is empty, return error */
> +	if (list_empty(&vpfe_dev->buffer_queue.stream)) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
> +		return EIO;
> +	}
> +
> +	/* Call videobuf_streamon to start streaming * in videobuf */
> +	ret = videobuf_streamon(&vpfe_dev->buffer_queue);
> +	if (ret)
> +		return ret;
> +
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		goto streamoff;
> +	/* Get the next frame from the buffer queue */
> +	vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
> +					struct videobuf_buffer, queue);
> +	vpfe_dev->cur_frm = vpfe_dev->next_frm;
> +	/* Remove buffer from the buffer queue */
> +	list_del(&vpfe_dev->cur_frm->queue);
> +	/* Mark state of the current frame to active */
> +	vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
> +	/* Initialize field_id and started member */
> +	vpfe_dev->field_id = 0;
> +	addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
> +
> +	/* Calculate field offset */
> +	vpfe_calculate_offsets(vpfe_dev);
> +
> +	if (vpfe_attach_irq(vpfe_dev) < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			 "Error in attaching interrupt handle\n");
> +		ret = -EFAULT;
> +		goto unlock_out;
> +	}
> +	if (ccdc_dev->hw_ops.configure() < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			 "Error in configuring ccdc\n");
> +		ret = -EINVAL;
> +		goto unlock_out;
> +	}
> +	ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr));
> +	vpfe_start_ccdc_capture(vpfe_dev);
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +unlock_out:
> +	mutex_unlock(&vpfe_dev->lock);
> +streamoff:
> +	ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
> +	return ret;
> +}
> +
> +static int vpfe_streamoff(struct file *file, void *priv,
> +			  enum v4l2_buf_type i)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_fh *fh = file->private_data;
> +	struct vpfe_subdev_info *subdev;
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
> +
> +	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != i) {

'i'? 'buf_type' is a much better name!

> +		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
> +		return -EINVAL;
> +	}
> +
> +	/* If io is allowed for this file handle, return error */
> +	if (!fh->io_allowed) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
> +		return -EACCES;
> +	}
> +
> +	/* If streaming is not started, return error */
> +	if (!vpfe_dev->started) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "device started\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	vpfe_stop_ccdc_capture(vpfe_dev);
> +	vpfe_detach_irq(vpfe_dev);
> +
> +	subdev = vpfe_dev->current_subdev;
> +	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, subdev->grp_id,
> +					video, s_stream, 0);
> +
> +	if (ret && (ret != -ENOIOCTLCMD))
> +		v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n");
> +	ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +static int vpfe_queryctrl(struct file *file, void *priv,
> +				struct v4l2_queryctrl *qc)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_queryctrl\n");
> +
> +	if (qc->id >= V4L2_CID_PRIVATE_BASE) {
> +		/* It is ccdc CID */
> +		if (ccdc_dev->hw_ops.queryctrl)
> +			return ccdc_dev->hw_ops.queryctrl(qc);
> +	}
> +	/* pass it to sub device */
> +	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
> +					  core, queryctrl, qc);
> +}
> +
> +static int vpfe_g_ctrl(struct file *file, void *priv,
> +			struct v4l2_control *ctrl)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_ctrl\n");
> +
> +	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
> +		/* It is ccdc CID */
> +		if (ccdc_dev->hw_ops.get_control)
> +			return ccdc_dev->hw_ops.get_control(ctrl);
> +	}

Don't use these PRIVATE_BASE controls. See also this post regarding
the current situation regarding private controls:

http://www.mail-archive.com/linux-omap%40vger.kernel.org/msg07999.html

> +
> +	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
> +					  core, g_ctrl, ctrl);
> +}
> +
> +static int vpfe_s_ctrl(struct file *file, void *priv,
> +			     struct v4l2_control *ctrl)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_ctrl\n");
> +
> +	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
> +		/* It is internal ccdc CID */
> +		if (ccdc_dev->hw_ops.set_control)
> +			return ccdc_dev->hw_ops.set_control(ctrl);
> +	}
> +
> +	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
> +					  core, s_ctrl, ctrl);
> +}
> +
> +static int vpfe_cropcap(struct file *file, void *priv,
> +			      struct v4l2_cropcap *crop)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n");
> +
> +	if (vpfe_dev->std_index > ARRAY_SIZE(vpfe_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[vpfe_dev->std_index].width;
> +	crop->bounds.height = crop->defrect.height =
> +		vpfe_standards[vpfe_dev->std_index].height;
> +	crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect;
> +	return 0;
> +}
> +
> +static int vpfe_g_crop(struct file *file, void *priv,
> +			     struct v4l2_crop *crop)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n");
> +
> +	crop->c = vpfe_dev->crop;
> +	return 0;
> +}
> +
> +static int vpfe_s_crop(struct file *file, void *priv,
> +			     struct v4l2_crop *crop)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
> +
> +	if (vpfe_dev->started) {
> +		/* make sure streaming is not started */
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"Cannot change crop when streaming is ON\n");
> +		return -EBUSY;
> +	}
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	if (crop->c.top < 0 || crop->c.left < 0) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"doesn't support negative values for top & left\n");
> +		ret = -EINVAL;
> +		goto unlock_out;
> +	}
> +
> +	/* adjust the width to 16 pixel boundry */
> +	crop->c.width = ((crop->c.width + 15) & ~0xf);
> +
> +	/* make sure parameters are valid */
> +	if ((crop->c.left + crop->c.width >
> +		vpfe_dev->std_info.active_pixels) ||
> +	    (crop->c.top + crop->c.height >
> +		vpfe_dev->std_info.active_lines)) {
> +		v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
> +		ret = -EINVAL;
> +		goto unlock_out;
> +	}
> +	ccdc_dev->hw_ops.set_image_window(&crop->c);
> +	vpfe_dev->fmt.fmt.pix.width = crop->c.width;
> +	vpfe_dev->fmt.fmt.pix.height = crop->c.height;
> +	vpfe_dev->fmt.fmt.pix.bytesperline =
> +		ccdc_dev->hw_ops.get_line_length();
> +	vpfe_dev->fmt.fmt.pix.sizeimage =
> +		vpfe_dev->fmt.fmt.pix.bytesperline *
> +		vpfe_dev->fmt.fmt.pix.height;
> +	vpfe_dev->crop = crop->c;
> +unlock_out:
> +	mutex_unlock(&vpfe_dev->lock);
> +	return ret;
> +}
> +
> +
> +static long vpfe_param_handler(struct file *file, void *priv,
> +		int cmd, void *param)
> +{
> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> +	int ret = 0;
> +
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
> +
> +	if (vpfe_dev->started) {
> +		/* only allowed if streaming is not started */
> +		v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n");
> +		return -EBUSY;
> +	}
> +
> +	ret = mutex_lock_interruptible(&vpfe_dev->lock);
> +	if (ret)
> +		return ret;
> +
> +	switch (cmd) {
> +	case VPFE_CMD_S_CCDC_RAW_PARAMS:
> +		ret = ccdc_dev->hw_ops.set_params(param);
> +		if (ret) {
> +			v4l2_err(&vpfe_dev->v4l2_dev,
> +				"Error in setting parameters"
> +				" in CCDC \n");
> +			goto unlock_out;
> +		}
> +		if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) {
> +			v4l2_err(&vpfe_dev->v4l2_dev,
> +				"Invalid image format at CCDC \n");
> +			goto unlock_out;
> +		}
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +unlock_out:
> +	mutex_unlock(&vpfe_dev->lock);
> +	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,
> +};
> +
> +static struct vpfe_device *vpfe_initialize(void)
> +{
> +	struct vpfe_device *vpfe_dev;
> +
> +	/* Default number of buffers should be 3 */
> +	if ((numbuffers > 0) &&
> +	    (numbuffers < config_params.min_numbuffers))
> +		numbuffers = config_params.min_numbuffers;
> +
> +	/*
> +	 * Set buffer size to min buffers size if invalid buffer size is
> +	 * given
> +	 */
> +	if (bufsize < config_params.min_bufsize)
> +		bufsize = config_params.min_bufsize;
> +
> +	config_params.numbuffers = numbuffers;
> +
> +	if (numbuffers)
> +		config_params.device_bufsize = bufsize;
> +
> +	/* Allocate memory for device objects */
> +	vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);
> +
> +	return vpfe_dev;
> +}
> +
> +static void vpfe_disable_clock(struct vpfe_device *vpfe_dev)
> +{
> +	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
> +
> +	clk_disable(vpfe_cfg->vpssclk);
> +	clk_put(vpfe_cfg->vpssclk);
> +	clk_disable(vpfe_cfg->slaveclk);
> +	clk_put(vpfe_cfg->slaveclk);
> +	v4l2_info(vpfe_dev->pdev->driver,
> +		 "vpfe vpss master & slave clocks disabled\n");
> +}
> +
> +static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
> +{
> +	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
> +	int ret = -ENOENT;
> +
> +	vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master");
> +	if (NULL == vpfe_cfg->vpssclk) {
> +		v4l2_err(vpfe_dev->pdev->driver, "No clock defined for"
> +			 "vpss_master\n");
> +		return ret;
> +	}
> +
> +	if (clk_enable(vpfe_cfg->vpssclk)) {
> +		v4l2_err(vpfe_dev->pdev->driver,
> +			"vpfe vpss master clock not enabled");
> +		goto out;
> +	}
> +	v4l2_info(vpfe_dev->pdev->driver,
> +		 "vpfe vpss master clock enabled\n");
> +
> +	vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave");
> +	if (NULL == vpfe_cfg->slaveclk) {
> +		v4l2_err(vpfe_dev->pdev->driver,
> +			"No clock defined for vpss slave\n");
> +		goto out;
> +	}
> +
> +	if (clk_enable(vpfe_cfg->slaveclk)) {
> +		v4l2_err(vpfe_dev->pdev->driver,
> +			 "vpfe vpss slave clock not enabled");
> +		goto out;
> +	}
> +	v4l2_info(vpfe_dev->pdev->driver,
> +		 "vpfe vpss slave clock enabled\n");
> +	return 0;
> +out:
> +	if (vpfe_cfg->vpssclk)
> +		clk_put(vpfe_cfg->vpssclk);
> +	if (vpfe_cfg->slaveclk)
> +		clk_put(vpfe_cfg->slaveclk);
> +
> +	return -1;
> +}
> +
> +/*
> + * vpfe_probe : This function creates device entries by register
> + * itself to the V4L2 driver and initializes fields of each
> + * device objects
> + */
> +static __init int vpfe_probe(struct platform_device *pdev)
> +{
> +	struct vpfe_config *vpfe_cfg;
> +	struct resource *res1;
> +	struct vpfe_device *vpfe_dev;
> +	struct i2c_adapter *i2c_adap;
> +	struct i2c_client *client;
> +	struct video_device *vfd;
> +	int ret = -ENOMEM, i, j;
> +	int num_subdevs = 0;
> +
> +	/* Get the pointer to the device object */
> +	vpfe_dev = vpfe_initialize();
> +
> +	if (!vpfe_dev) {
> +		v4l2_err(pdev->dev.driver,
> +			"Failed to allocate memory for vpfe_dev\n");
> +		return ret;
> +	}
> +
> +	vpfe_dev->pdev = &pdev->dev;
> +
> +	if (NULL == pdev->dev.platform_data) {
> +		v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
> +		ret = -ENOENT;
> +		goto probe_free_dev_mem;
> +	}
> +
> +	vpfe_cfg = pdev->dev.platform_data;
> +	vpfe_dev->cfg = vpfe_cfg;
> +	if (NULL == vpfe_cfg->ccdc ||
> +	    NULL == vpfe_cfg->card_name ||
> +	    NULL == vpfe_cfg->sub_devs) {
> +		v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
> +		ret = -ENOENT;
> +		goto probe_free_dev_mem;
> +	}
> +
> +	/* enable vpss clocks */
> +	ret = vpfe_enable_clock(vpfe_dev);
> +	if (ret)
> +		goto probe_free_dev_mem;
> +
> +	mutex_lock(&ccdc_lock);
> +	/* Allocate memory for ccdc configuration */
> +	ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);
> +	if (NULL == ccdc_cfg) {
> +		v4l2_err(pdev->dev.driver, "Memory allocation failed for"
> +			"ccdc_cfg");
> +		goto probe_disable_clock;
> +	}
> +
> +	strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);
> +	/* Get VINT0 irq resource */
> +	res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!res1) {
> +		v4l2_err(pdev->dev.driver, "Unable to get interrupt for VINT0");
> +		ret = -ENOENT;
> +		goto probe_disable_clock;
> +	}
> +	vpfe_dev->ccdc_irq0 = res1->start;
> +
> +	/* Get VINT1 irq resource */
> +	res1 = platform_get_resource(pdev,
> +				IORESOURCE_IRQ, 1);
> +	if (!res1) {
> +		v4l2_err(pdev->dev.driver, "Unable to get interrupt for VINT1");
> +		ret = -ENOENT;
> +		goto probe_disable_clock;
> +	}
> +	vpfe_dev->ccdc_irq1 = res1->start;
> +
> +	/* Get address base of CCDC */
> +	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res1) {
> +		v4l2_err(pdev->dev.driver,
> +			"Unable to get register address map\n");
> +		ret = -ENOENT;
> +		goto probe_disable_clock;
> +	}
> +
> +	ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1;
> +	if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size,
> +				pdev->dev.driver->name)) {
> +		v4l2_err(pdev->dev.driver,
> +			"Failed request_mem_region for ccdc base\n");
> +		ret = -ENXIO;
> +		goto probe_disable_clock;
> +	}
> +	ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start,
> +					     ccdc_cfg->ccdc_addr_size);
> +	if (!ccdc_cfg->ccdc_addr) {
> +		v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n");
> +		ret = -ENXIO;
> +		goto probe_out_release_mem1;
> +	}
> +
> +	ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
> +			  "vpfe_capture0", vpfe_dev);
> +
> +	if (0 != ret) {
> +		v4l2_err(pdev->dev.driver, "Unable to request interrupt\n");
> +		goto probe_out_unmap1;
> +	}
> +
> +	/* Allocate memory for video device */
> +	vfd = video_device_alloc();
> +	if (NULL == vfd) {
> +		ret = ENOMEM;
> +		v4l2_err(pdev->dev.driver,
> +			"Unable to alloc video device\n");
> +		goto probe_out_release_irq;
> +	}
> +
> +	/* 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		= 0;
> +	vfd->current_norm	= V4L2_STD_PAL;
> +	vfd->v4l2_dev 		= &vpfe_dev->v4l2_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 */
> +	vpfe_dev->video_dev	= vfd;
> +
> +	ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
> +	if (ret) {
> +		v4l2_err(pdev->dev.driver,
> +			"Unable to register v4l2 device.\n");
> +		goto probe_out_video_release;
> +	}
> +	v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
> +	spin_lock_init(&vpfe_dev->irqlock);
> +	spin_lock_init(&vpfe_dev->dma_queue_lock);
> +	mutex_init(&vpfe_dev->lock);
> +
> +	/* Initialize field of the device objects */
> +	vpfe_dev->numbuffers = config_params.numbuffers;
> +
> +	/* Initialize prio member of device object */
> +	v4l2_prio_init(&vpfe_dev->prio);
> +	/* register video device */
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +		"trying to register vpfe device.\n");
> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +		"video_dev=%x\n", (int)&vpfe_dev->video_dev);
> +	vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	ret = video_register_device(vpfe_dev->video_dev,
> +				    VFL_TYPE_GRABBER, -1);
> +
> +	if (ret) {
> +		v4l2_err(pdev->dev.driver,
> +			"Unable to register video device.\n");
> +		goto probe_out_v4l2_unregister;
> +	}
> +
> +	v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n");
> +	/* set the driver data in platform device */
> +	platform_set_drvdata(pdev, vpfe_dev);
> +	/* set driver private data */
> +	video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);
> +	i2c_adap = i2c_get_adapter(1);
> +	vpfe_cfg = pdev->dev.platform_data;
> +	num_subdevs = vpfe_cfg->num_subdevs;
> +	vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
> +				GFP_KERNEL);
> +	if (NULL == vpfe_dev->sd) {
> +		v4l2_err(&vpfe_dev->v4l2_dev,
> +			"unable to allocate memory for subdevice pointers\n");
> +		ret = -ENOMEM;
> +		goto probe_out_video_unregister;
> +	}
> +
> +	for (i = 0; i < num_subdevs; i++) {
> +		struct vpfe_subdev_info *sub_dev = &vpfe_cfg->sub_devs[i];
> +		struct v4l2_input *inps;
> +
> +		list_for_each_entry(client, &i2c_adap->clients, list) {
> +			if (!strcmp(client->name, sub_dev->name))
> +				break;
> +		}
> +
> +		if (NULL == client) {
> +			v4l2_err(&vpfe_dev->v4l2_dev, "No Subdevice found\n");
> +			ret =  -ENODEV;
> +			goto probe_sd_out;
> +		}
> +
> +		/* Get subdevice data from the client */
> +		vpfe_dev->sd[i] = i2c_get_clientdata(client);
> +		sub_dev->pdata = client->dev.platform_data;
> +		if (NULL == vpfe_dev->sd[i] || NULL == sub_dev->pdata) {
> +			v4l2_err(&vpfe_dev->v4l2_dev,
> +				"No Subdevice or platform client data\n");
> +			ret =  -ENODEV;
> +			goto probe_sd_out;
> +		}
> +
> +		vpfe_dev->sd[i]->grp_id = sub_dev->grp_id;
> +		ret = v4l2_device_register_subdev(&vpfe_dev->v4l2_dev,
> +						  vpfe_dev->sd[i]);
> +		if (ret) {
> +			ret =  -ENODEV;
> +			v4l2_err(&vpfe_dev->v4l2_dev,
> +				"Error registering v4l2 sub-device\n");
> +			goto probe_sd_out;
> +		}
> +		v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 sub device %s"
> +			  " registered\n", client->name);
> +
> +		/* update tvnorms from the sub devices */
> +		for (j = 0; j < sub_dev->num_inputs; j++) {
> +			inps = &sub_dev->inputs[j];
> +			vfd->tvnorms |= inps->std;
> +		}
> +	}
> +	/* We have at least one sub device to work with */
> +	vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0];
> +	mutex_unlock(&ccdc_lock);
> +	return 0;
> +
> +probe_sd_out:
> +	for (j = i; j >= 0; j--)
> +		v4l2_device_unregister_subdev(vpfe_dev->sd[j]);
> +	kfree(vpfe_dev->sd);
> +probe_out_video_unregister:
> +	video_unregister_device(vpfe_dev->video_dev);
> +probe_out_v4l2_unregister:
> +	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
> +probe_out_video_release:
> +	video_device_release(vpfe_dev->video_dev);
> +probe_out_release_irq:
> +	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
> +probe_out_unmap1:
> +	iounmap(ccdc_cfg->ccdc_addr);
> +probe_out_release_mem1:
> +	release_mem_region(res1->start, res1->end - res1->start + 1);
> +probe_disable_clock:
> +	vpfe_disable_clock(vpfe_dev);
> +	mutex_unlock(&ccdc_lock);
> +	kfree(ccdc_cfg);
> +probe_free_dev_mem:
> +	kfree(vpfe_dev);
> +	return ret;
> +}
> +
> +/*
> + * vpfe_remove : It un-register device from V4L2 driver
> + */
> +static int vpfe_remove(struct platform_device *pdev)
> +{
> +	struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
> +	struct resource *res;
> +	int j;
> +
> +	v4l2_info(pdev->dev.driver, "vpfe_remove\n");
> +
> +	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
> +	/* Unregister video device */
> +	for (j = 0; j < vpfe_dev->cfg->num_subdevs; j++)
> +		v4l2_device_unregister_subdev(vpfe_dev->sd[j]);
> +	kfree(vpfe_dev->sd);
> +	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
> +	video_unregister_device(vpfe_dev->video_dev);
> +	mutex_lock(&ccdc_lock);
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	release_mem_region(res->start, res->end - res->start + 1);
> +	iounmap(ccdc_cfg->ccdc_addr);
> +	mutex_unlock(&ccdc_lock);
> +	vpfe_disable_clock(vpfe_dev);
> +	kfree(vpfe_dev);
> +	kfree(ccdc_cfg);
> +	return 0;
> +}
> +
> +static int
> +vpfe_suspend(struct platform_device *dev, pm_message_t state)
> +{
> +	/* add suspend code here later */
> +	return -1;
> +}
> +
> +static int
> +vpfe_resume(struct platform_device *dev)
> +{
> +	/* add resume code here later */
> +	return -1;
> +}
> +
> +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)
> +{
> +	printk(KERN_NOTICE "vpfe_init\n");
> +	/* Register driver to the kernel */
> +	return platform_driver_register(&vpfe_driver);
> +}
> +
> +/*
> + * vpfe_cleanup : This function un-registers device driver
> + */
> +static void vpfe_cleanup(void)
> +{
> +	platform_driver_unregister(&vpfe_driver);
> +}
> +
> +module_init(vpfe_init);
> +module_exit(vpfe_cleanup);
> +MODULE_AUTHOR("Texas Instruments.");

A dot at the end? I think it should be just plain 'Texas Instruments'.

> +MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
> +MODULE_LICENSE("GPL");

Move these MODULE macros to the top of the source.

> diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h
> new file mode 100644
> index 0000000..c08dc92
> --- /dev/null
> +++ b/include/media/davinci/vpfe_capture.h
> @@ -0,0 +1,183 @@
> +/*
> + * 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 <media/v4l2-dev.h>
> +#include <linux/videodev2.h>
> +#include <linux/clk.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-device.h>
> +#include <media/videobuf-dma-contig.h>
> +#include <media/davinci/vpfe_types.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 CAPTURE_DRV_NAME		"vpfe-capture"
> +
> +struct vpfe_pixel_format {
> +	struct v4l2_fmtdesc fmtdesc;
> +	/* bytes per pixel */
> +	int bpp;
> +};
> +
> +struct vpfe_std_info {
> +	int active_pixels;
> +	int active_lines;
> +	/* current frame format */
> +	int frame_format;
> +};
> +
> +struct vpfe_subdev_info {
> +	/* Sub device name */
> +	char name[32];
> +	/* Sub device group id */
> +	int grp_id;
> +	/* Number of inputs supported */
> +	int num_inputs;
> +	/* inputs available at the sub device */
> +	struct v4l2_input *inputs;
> +	/* Sub dev routing information for each input */
> +	struct v4l2_routing *routes;
> +	/* check if sub dev supports routing */
> +	int can_route;
> +	/* sub device private data */
> +	void *pdata;
> +};
> +
> +struct vpfe_config {
> +	/* Number of sub devices connected to vpfe */
> +	int num_subdevs;
> +	/* information about each subdev */
> +	struct vpfe_subdev_info *sub_devs;
> +	/* evm card info */
> +	char *card_name;
> +	/* ccdc name */
> +	char *ccdc;
> +	/* vpfe clock */
> +	struct clk *vpssclk;
> +	struct clk *slaveclk;
> +};
> +
> +struct vpfe_device {
> +	/* V4l2 specific parameters */
> +	/* Identifies video device for this channel */
> +	struct video_device *video_dev;
> +	/* sub devices */
> +	struct v4l2_subdev **sd;
> +	/* vpfe cfg */
> +	struct vpfe_config *cfg;
> +	/* V4l2 device */
> +	struct v4l2_device v4l2_dev;
> +	/* parent device */
> +	struct device *pdev;
> +	/* 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;
> +	/* current interface type */
> +	struct vpfe_hw_if_param vpfe_if_params;
> +	/* ptr to currently selected sub device */
> +	struct vpfe_subdev_info *current_subdev;
> +	/* current input at the sub device */
> +	int current_input;
> +	/* Keeps track of the information about the standard */
> +	struct vpfe_std_info std_info;
> +	/* std index into std table */
> +	int std_index;
> +	/* CCDC IRQs used when CCDC/ISIF output to SDRAM */
> +	unsigned int ccdc_irq0;
> +	unsigned int ccdc_irq1;
> +	/* number of buffers in fbuffers */
> +	u32 numbuffers;
> +	/* List of buffer pointers for storing frames */
> +	u8 *fbuffers[VIDEO_MAX_FRAME];
> +	/* Pointer pointing to current v4l2_buffer */
> +	struct videobuf_buffer *cur_frm;
> +	/* Pointer pointing to next v4l2_buffer */
> +	struct videobuf_buffer *next_frm;
> +	/*
> +	 * 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;
> +	/*
> +	 * used when IMP is chained to store the crop window which
> +	 * is different from the image window
> +	 */
> +	struct v4l2_rect crop;
> +	/* 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;
> +	/* IRQ lock for DMA queue */
> +	spinlock_t dma_queue_lock;
> +	/* 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;
> +};
> +
> +/* File handle structure */
> +struct vpfe_fh {
> +	struct vpfe_device *vpfe_dev;
> +	/* Indicates whether this file handle is doing IO */
> +	u8 io_allowed;
> +	/* Used to keep track priority of this instance */
> +	enum v4l2_priority prio;
> +};
> +
> +struct vpfe_config_params {
> +	u8 min_numbuffers;
> +	u8 numbuffers;
> +	u32 min_bufsize;
> +	u32 device_bufsize;
> +};
> +
> +#endif				/* End of __KERNEL__ */
> +/* IOCTLs */
> +#define VPFE_CMD_S_CCDC_RAW_PARAMS _IOW('V', BASE_VIDIOC_PRIVATE + 1, \
> +					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..76fb74b
> --- /dev/null
> +++ b/include/media/davinci/vpfe_types.h
> @@ -0,0 +1,51 @@
> +/*
> + * 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_pin_pol {
> +	VPFE_PINPOL_POSITIVE,
> +	VPFE_PINPOL_NEGATIVE
> +};
> +
> +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
> +};
> +
> +/* interface description */
> +struct vpfe_hw_if_param {
> +	enum vpfe_hw_if_type if_type;
> +	enum vpfe_pin_pol hdpol;
> +	enum vpfe_pin_pol vdpol;
> +};
> +
> +#endif
> +#endif

Regards,

	Hans


-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 7/10 - v2] DM355 platform changes for vpfe capture driver
  2009-06-11 17:00             ` [PATCH 7/10 - v2] DM355 platform changes " m-karicheri2
  2009-06-11 17:00               ` [PATCH 8/10 - v2] DM6446 " m-karicheri2
  2009-06-11 20:23               ` [PATCH 7/10 - v2] DM355 " David Brownell
@ 2009-06-14 14:22               ` Hans Verkuil
  2009-06-14 19:42                 ` David Brownell
  2009-06-15 22:24                 ` Karicheri, Muralidharan
  2 siblings, 2 replies; 34+ messages in thread
From: Hans Verkuil @ 2009-06-14 14:22 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

On Thursday 11 June 2009 19:00:46 m-karicheri2@ti.com wrote:
> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
> 
> DM355 platform and board setup
> 
> This has platform and board setup changes to support vpfe capture
> driver for DM355 EVMs.
> 
> Added registration of vpss platform driver based on last review
> 
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
> 
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
> Applies to Davinci GIT Tree
> 
>  arch/arm/mach-davinci/board-dm355-evm.c    |   72 +++++++++++++++++++++++-
>  arch/arm/mach-davinci/dm355.c              |   83 ++++++++++++++++++++++++++++
>  arch/arm/mach-davinci/include/mach/dm355.h |    2 +
>  arch/arm/mach-davinci/include/mach/mux.h   |    9 +++
>  4 files changed, 163 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
> index 5ac2f56..cf87e21 100644
> --- a/arch/arm/mach-davinci/board-dm355-evm.c
> +++ b/arch/arm/mach-davinci/board-dm355-evm.c
> @@ -20,6 +20,8 @@
>  #include <linux/io.h>
>  #include <linux/gpio.h>
>  #include <linux/clk.h>
> +#include <linux/videodev2.h>
> +#include <media/tvp514x.h>
>  #include <linux/spi/spi.h>
>  #include <linux/spi/eeprom.h>
>  
> @@ -134,12 +136,23 @@ static void dm355evm_mmcsd_gpios(unsigned gpio)
>  	dm355evm_mmc_gpios = gpio;
>  }
>  
> +#define TVP5146_I2C_ADDR		0x5D
> +static struct tvp514x_platform_data tvp5146_pdata = {
> +	.clk_polarity = 0,
> +	.hs_polarity = 1,
> +	.vs_polarity = 1
> +};
> +
>  static struct i2c_board_info dm355evm_i2c_info[] = {
> -	{ I2C_BOARD_INFO("dm355evm_msp", 0x25),
> +	{	I2C_BOARD_INFO("dm355evm_msp", 0x25),
>  		.platform_data = dm355evm_mmcsd_gpios,
> -		/* plus irq */ },
> +	},
> +	{
> +		I2C_BOARD_INFO("tvp5146", TVP5146_I2C_ADDR),
> +		.platform_data = &tvp5146_pdata,
> +	},
> +	/* { plus irq  }, */
>  	/* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */

Huh? What's this? I only know the tlv320aic23b and that's an audio driver.

> -	/* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
>  };
>  
>  static void __init evm_init_i2c(void)
> @@ -178,6 +191,57 @@ static struct platform_device dm355evm_dm9000 = {
>  	.num_resources	= ARRAY_SIZE(dm355evm_dm9000_rsrc),
>  };
>  
> +#define TVP514X_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
> +/* Inputs available at the TVP5146 */
> +static struct v4l2_input tvp5146_inputs[] = {
> +	{
> +		.index = 0,
> +		.name = "COMPOSITE",

Please, don't use all-caps. Just use "Composite" and "S-Video". 

> +		.type = V4L2_INPUT_TYPE_CAMERA,
> +		.std = TVP514X_STD_ALL,
> +	},
> +	{
> +		.index = 1,
> +		.name = "SVIDEO",
> +		.type = V4L2_INPUT_TYPE_CAMERA,
> +		.std = TVP514X_STD_ALL,
> +	},
> +};
> +
> +/*
> + * this is the route info for connecting each input to decoder
> + * ouput that goes to vpfe. There is a one to one correspondence
> + * with tvp5146_inputs
> + */
> +static struct v4l2_routing tvp5146_routes[] = {

As mentioned elsewhere: v4l2_routing will disappear, so please don't use it.

> +	{
> +		.input = INPUT_CVBS_VI2B,
> +		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
> +	},
> +	{
> +		.input = INPUT_SVIDEO_VI2C_VI1C,
> +		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
> +	},
> +};
> +
> +static struct vpfe_subdev_info vpfe_sub_devs[] = {
> +	{
> +		.name = "tvp5146",
> +		.grp_id = 0,
> +		.num_inputs = ARRAY_SIZE(tvp5146_inputs),
> +		.inputs = tvp5146_inputs,
> +		.routes = tvp5146_routes,
> +		.can_route = 1,
> +	}
> +};

A general remark: currently you link your inputs directly to a subdev. This
approach has two disadvantages:

1) It doesn't work if there are no subdevs at all (e.g. because everything
goes through an fpga).

2) It fixes the reported order of the inputs to the order of the subdevs.

I think it is better to have a separate array of input descriptions that
refer to a subdev when an input is associated with that subdev. It's more
flexible that way, and I actually think that the vpfe driver will be
simplified as well.

> +
> +static struct vpfe_config vpfe_cfg = {
> +	.num_subdevs = ARRAY_SIZE(vpfe_sub_devs),
> +	.sub_devs = vpfe_sub_devs,
> +	.card_name = "DM355 EVM",
> +	.ccdc = "DM355 CCDC",
> +};
> +
>  static struct platform_device *davinci_evm_devices[] __initdata = {
>  	&dm355evm_dm9000,
>  	&davinci_nand_device,
> @@ -189,6 +253,8 @@ static struct davinci_uart_config uart_config __initdata = {
>  
>  static void __init dm355_evm_map_io(void)
>  {
> +	/* setup input configuration for VPFE input devices */
> +	dm355_set_vpfe_config(&vpfe_cfg);
>  	dm355_init();
>  }
>  
> diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
> index 9baeed3..3263af8 100644
> --- a/arch/arm/mach-davinci/dm355.c
> +++ b/arch/arm/mach-davinci/dm355.c
> @@ -481,6 +481,14 @@ INT_CFG(DM355,  INT_EDMA_TC1_ERR,     4,    1,    1,     false)
>  EVT_CFG(DM355,  EVT8_ASP1_TX,	      0,    1,    0,     false)
>  EVT_CFG(DM355,  EVT9_ASP1_RX,	      1,    1,    0,     false)
>  EVT_CFG(DM355,  EVT26_MMC0_RX,	      2,    1,    0,     false)
> +
> +MUX_CFG(DM355,	VIN_PCLK,	0,   14,    1,    1,	 false)
> +MUX_CFG(DM355,	VIN_CAM_WEN,	0,   13,    1,    1,	 false)
> +MUX_CFG(DM355,	VIN_CAM_VD,	0,   12,    1,    1,	 false)
> +MUX_CFG(DM355,	VIN_CAM_HD,	0,   11,    1,    1,	 false)
> +MUX_CFG(DM355,	VIN_YIN_EN,	0,   10,    1,    1,	 false)
> +MUX_CFG(DM355,	VIN_CINL_EN,	0,   0,   0xff, 0x55,	 false)
> +MUX_CFG(DM355,	VIN_CINH_EN,	0,   8,     3,    3,	 false)
>  #endif
>  };
>  
> @@ -623,6 +631,67 @@ static struct platform_device dm355_edma_device = {
>  	.resource		= edma_resources,
>  };
>  
> +static struct resource dm355_vpss_resources[] = {
> +	{
> +		/* VPSS BL Base address */
> +		.name		= "vpss",
> +		.start          = 0x01c70800,
> +		.end            = 0x01c70800 + 0xff,
> +		.flags          = IORESOURCE_MEM,
> +	},
> +	{
> +		/* VPSS CLK Base address */
> +		.name		= "vpss",
> +		.start          = 0x01c70000,
> +		.end            = 0x01c70000 + 0xf,
> +		.flags          = IORESOURCE_MEM,
> +	},
> +};
> +
> +static struct platform_device dm355_vpss_device = {
> +	.name			= "vpss",
> +	.id			= -1,
> +	.dev.platform_data	= "dm355_vpss",
> +	.num_resources		= ARRAY_SIZE(dm355_vpss_resources),
> +	.resource		= dm355_vpss_resources,
> +};
> +
> +static struct resource vpfe_resources[] = {
> +	{
> +		.start          = IRQ_VDINT0,
> +		.end            = IRQ_VDINT0,
> +		.flags          = IORESOURCE_IRQ,
> +	},
> +	{
> +		.start          = IRQ_VDINT1,
> +		.end            = IRQ_VDINT1,
> +		.flags          = IORESOURCE_IRQ,
> +	},
> +	/* CCDC Base address */
> +	{
> +		.flags          = IORESOURCE_MEM,
> +		.start          = 0x01c70600,
> +		.end            = 0x01c70600 + 0x1ff,
> +	},
> +};
> +
> +static u64 vpfe_capture_dma_mask = DMA_BIT_MASK(32);
> +static struct platform_device vpfe_capture_dev = {
> +	.name		= CAPTURE_DRV_NAME,
> +	.id		= -1,
> +	.num_resources	= ARRAY_SIZE(vpfe_resources),
> +	.resource	= vpfe_resources,
> +	.dev = {
> +		.dma_mask		= &vpfe_capture_dma_mask,
> +		.coherent_dma_mask	= DMA_BIT_MASK(32),
> +	},
> +};
> +
> +void dm355_set_vpfe_config(struct vpfe_config *cfg)
> +{
> +	vpfe_capture_dev.dev.platform_data = cfg;
> +}
> +
>  /*----------------------------------------------------------------------*/
>  
>  static struct map_desc dm355_io_desc[] = {
> @@ -744,6 +813,20 @@ static int __init dm355_init_devices(void)
>  
>  	davinci_cfg_reg(DM355_INT_EDMA_CC);
>  	platform_device_register(&dm355_edma_device);
> +	platform_device_register(&dm355_vpss_device);
> +	/*
> +	 * setup Mux configuration for vpfe input and register
> +	 * vpfe capture platform device
> +	 */
> +	davinci_cfg_reg(DM355_VIN_PCLK);
> +	davinci_cfg_reg(DM355_VIN_CAM_WEN);
> +	davinci_cfg_reg(DM355_VIN_CAM_VD);
> +	davinci_cfg_reg(DM355_VIN_CAM_HD);
> +	davinci_cfg_reg(DM355_VIN_YIN_EN);
> +	davinci_cfg_reg(DM355_VIN_CINL_EN);
> +	davinci_cfg_reg(DM355_VIN_CINH_EN);
> +	platform_device_register(&vpfe_capture_dev);
> +
>  	return 0;
>  }
>  postcore_initcall(dm355_init_devices);
> diff --git a/arch/arm/mach-davinci/include/mach/dm355.h b/arch/arm/mach-davinci/include/mach/dm355.h
> index 54903b7..e28713c 100644
> --- a/arch/arm/mach-davinci/include/mach/dm355.h
> +++ b/arch/arm/mach-davinci/include/mach/dm355.h
> @@ -12,11 +12,13 @@
>  #define __ASM_ARCH_DM355_H
>  
>  #include <mach/hardware.h>
> +#include <media/davinci/vpfe_capture.h>
>  
>  struct spi_board_info;
>  
>  void __init dm355_init(void);
>  void dm355_init_spi0(unsigned chipselect_mask,
>  		struct spi_board_info *info, unsigned len);
> +void dm355_set_vpfe_config(struct vpfe_config *cfg);
>  
>  #endif /* __ASM_ARCH_DM355_H */
> diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
> index 2737845..f288063 100644
> --- a/arch/arm/mach-davinci/include/mach/mux.h
> +++ b/arch/arm/mach-davinci/include/mach/mux.h
> @@ -154,6 +154,15 @@ enum davinci_dm355_index {
>  	DM355_EVT8_ASP1_TX,
>  	DM355_EVT9_ASP1_RX,
>  	DM355_EVT26_MMC0_RX,
> +
> +	/* Video In Pin Mux */
> +	DM355_VIN_PCLK,
> +	DM355_VIN_CAM_WEN,
> +	DM355_VIN_CAM_VD,
> +	DM355_VIN_CAM_HD,
> +	DM355_VIN_YIN_EN,
> +	DM355_VIN_CINL_EN,
> +	DM355_VIN_CINH_EN,
>  };
>  
>  #ifdef CONFIG_DAVINCI_MUX

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 8/10 - v2] DM6446 platform changes for vpfe capture driver
  2009-06-11 17:00               ` [PATCH 8/10 - v2] DM6446 " m-karicheri2
  2009-06-11 17:00                 ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 m-karicheri2
@ 2009-06-14 14:24                 ` Hans Verkuil
  1 sibling, 0 replies; 34+ messages in thread
From: Hans Verkuil @ 2009-06-14 14:24 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

On Thursday 11 June 2009 19:00:47 m-karicheri2@ti.com wrote:
> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
> 
> DM644x platform and board setup
> 
> This adds plarform and board setup changes required to support
> vpfe capture driver on DM644x
> 
> Added registration of vpss platform driver based on last comment
> 
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
> 
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
> Applies to Davinci GIT Tree
> 
>  arch/arm/mach-davinci/board-dm644x-evm.c    |   68 ++++++++++++++++++++++++++-
>  arch/arm/mach-davinci/dm644x.c              |   56 ++++++++++++++++++++++
>  arch/arm/mach-davinci/include/mach/dm644x.h |    2 +
>  3 files changed, 124 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
> index d9d4045..13b73a7 100644
> --- a/arch/arm/mach-davinci/board-dm644x-evm.c
> +++ b/arch/arm/mach-davinci/board-dm644x-evm.c
> @@ -28,7 +28,8 @@
>  #include <linux/io.h>
>  #include <linux/phy.h>
>  #include <linux/clk.h>
> -
> +#include <linux/videodev2.h>
> +#include <media/tvp514x.h>
>  #include <asm/setup.h>
>  #include <asm/mach-types.h>
>  
> @@ -195,6 +196,57 @@ static struct platform_device davinci_fb_device = {
>  	.num_resources = 0,
>  };
>  
> +#define TVP514X_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
> +/* Inputs available at the TVP5146 */
> +static struct v4l2_input tvp5146_inputs[] = {
> +	{
> +		.index = 0,
> +		.name = "COMPOSITE",
> +		.type = V4L2_INPUT_TYPE_CAMERA,
> +		.std = TVP514X_STD_ALL,
> +	},
> +	{
> +		.index = 1,
> +		.name = "SVIDEO",
> +		.type = V4L2_INPUT_TYPE_CAMERA,
> +		.std = TVP514X_STD_ALL,
> +	},

No all-caps.

> +};
> +
> +/*
> + * this is the route info for connecting each input to decoder
> + * ouput that goes to vpfe. There is a one to one correspondence
> + * with tvp5146_inputs
> + */
> +static struct v4l2_routing tvp5146_routes[] = {
> +	{
> +		.input = INPUT_CVBS_VI2B,
> +		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
> +	},
> +	{
> +		.input = INPUT_SVIDEO_VI2C_VI1C,
> +		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
> +	},
> +};
> +
> +static struct vpfe_subdev_info vpfe_sub_devs[] = {
> +	{
> +		.name = "tvp5146",
> +		.grp_id = 0,
> +		.num_inputs = ARRAY_SIZE(tvp5146_inputs),
> +		.inputs = tvp5146_inputs,
> +		.routes = tvp5146_routes,
> +		.can_route = 1,
> +	},
> +};

Same remark as for patch 7: suggest using a separate input array.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 10/10 - v2] common vpss module for video drivers
  2009-06-11 17:00                   ` [PATCH 10/10 - v2] common vpss module for video drivers m-karicheri2
  2009-06-11 23:23                     ` Alexey Klimov
@ 2009-06-14 14:26                     ` Hans Verkuil
  1 sibling, 0 replies; 34+ messages in thread
From: Hans Verkuil @ 2009-06-14 14:26 UTC (permalink / raw)
  To: m-karicheri2
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

On Thursday 11 June 2009 19:00:49 m-karicheri2@ti.com wrote:
> From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>
> 
> common voss module for video drivers
> 
> This is a new module added for vpss library functions that are
> used for configuring vpss system module. All video drivers will
> include vpss.h header file and call functions defined in this
> module to configure vpss system module.
> 
> 
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
> 
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
>  drivers/media/video/davinci/vpss.c |  290 ++++++++++++++++++++++++++++++++++++
>  include/media/davinci/vpss.h       |   69 +++++++++
>  2 files changed, 359 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/vpss.c
>  create mode 100644 include/media/davinci/vpss.h
> 
> diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
> new file mode 100644
> index 0000000..def021e
> --- /dev/null
> +++ b/drivers/media/video/davinci/vpss.c
> @@ -0,0 +1,290 @@
> +/*
> + * Copyright (C) 2009 Texas Instruments.
> + *
> + * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * common vpss driver for all video drivers.
> + */
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/compiler.h>
> +#include <linux/io.h>
> +#include <mach/hardware.h>
> +#include <media/davinci/vpss.h>
> +
> +/* DM644x defines */
> +#define DM644X_SBL_PCR_VPSS		(4)
> +
> +/* vpss BL register offsets */
> +#define DM355_VPSSBL_CCDCMUX		0x1c
> +/* vpss CLK register offsets */
> +#define DM355_VPSSCLK_CLKCTRL		0x04
> +/* masks and shifts */
> +#define VPSS_HSSISEL_SHIFT		4
> +
> +/*
> + * vpss operations. Depends on platform. Not all functions are available
> + * on all platforms. The api, first check if a functio is available before
> + * invoking it. In the probe, the function ptrs are intialized based on
> + * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
> + */
> +struct vpss_hw_ops {
> +	/* enable clock */
> +	int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
> +	/* select input to ccdc */
> +	void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
> +	/* clear wbl overlflow bit */
> +	int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
> +};
> +
> +/* vpss configuration */
> +struct vpss_oper_config {
> +	__iomem void *vpss_bl_regs_base;
> +	__iomem void *vpss_regs_base;
> +	struct resource		*r1;
> +	resource_size_t		len1;
> +	struct resource		*r2;
> +	resource_size_t		len2;
> +	char vpss_name[32];
> +	spinlock_t vpss_lock;
> +	struct vpss_hw_ops hw_ops;
> +};
> +
> +static struct vpss_oper_config oper_cfg;
> +
> +/* register access routines */
> +static inline u32 bl_regr(u32 offset)
> +{
> +	return __raw_readl(oper_cfg.vpss_bl_regs_base + offset);
> +}
> +
> +static inline void bl_regw(u32 val, u32 offset)
> +{
> +	__raw_writel(val, oper_cfg.vpss_bl_regs_base + offset);
> +}
> +
> +static inline u32 vpss_regr(u32 offset)
> +{
> +	return __raw_readl(oper_cfg.vpss_regs_base + offset);
> +}
> +
> +static inline void vpss_regw(u32 val, u32 offset)
> +{
> +	__raw_writel(val, oper_cfg.vpss_regs_base + offset);
> +}
> +
> +static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
> +{
> +	bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
> +}
> +
> +int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
> +{
> +	if (!oper_cfg.hw_ops.select_ccdc_source)
> +		return -1;
> +
> +	dm355_select_ccdc_source(src_sel);
> +	return 0;
> +}
> +EXPORT_SYMBOL(vpss_select_ccdc_source);
> +
> +static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
> +{
> +	u32 mask = 1, val;
> +
> +	if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
> +	    wbl_sel > VPSS_PCR_CCDC_WBL_O)
> +		return -1;
> +
> +	/* writing a 0 clear the overflow */
> +	mask = ~(mask << wbl_sel);
> +	val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
> +	bl_regw(val, DM644X_SBL_PCR_VPSS);
> +	return 0;
> +}
> +
> +int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
> +{
> +	if (!oper_cfg.hw_ops.clear_wbl_overflow)
> +		return -1;
> +
> +	return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
> +}
> +EXPORT_SYMBOL(vpss_clear_wbl_overflow);
> +
> +/*
> + *  dm355_enable_clock - Enable VPSS Clock
> + *  @clock_sel: CLock to be enabled/disabled
> + *  @en: enable/disable flag
> + *
> + *  This is called to enable or disable a vpss clock
> + */
> +static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
> +{
> +	unsigned long flags;
> +	u32 utemp, mask = 0x1, shift = 0;
> +
> +	switch (clock_sel) {
> +	case VPSS_VPBE_CLOCK:
> +		/* nothing since lsb */
> +		break;
> +	case VPSS_VENC_CLOCK_SEL:
> +		shift = 2;
> +		break;
> +	case VPSS_CFALD_CLOCK:
> +		shift = 3;
> +		break;
> +	case VPSS_H3A_CLOCK:
> +		shift = 4;
> +		break;
> +	case VPSS_IPIPE_CLOCK:
> +		shift = 5;
> +		break;
> +	case VPSS_CCDC_CLOCK:
> +		shift = 6;
> +		break;
> +	default:
> +		printk(KERN_ERR "dm355_enable_clock:"
> +				" Invalid selector: %d\n", clock_sel);
> +		return -1;
> +	}
> +
> +	spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
> +	utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
> +	if (!en)
> +		utemp &= ~(mask << shift);
> +	else
> +		utemp |= (mask << shift);
> +
> +	vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
> +	spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
> +	return 0;
> +}
> +
> +int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
> +{
> +	if (!oper_cfg.hw_ops.enable_clock)
> +		return -1;
> +
> +	return oper_cfg.hw_ops.enable_clock(clock_sel, en);
> +}
> +EXPORT_SYMBOL(vpss_enable_clock);
> +
> +static int __init vpss_probe(struct platform_device *pdev)
> +{
> +	int			status;
> +
> +	if (!pdev->dev.platform_data) {
> +		dev_err(&pdev->dev, "vpss, no platform data\n");
> +		return -ENOENT;
> +	}
> +
> +	strcpy(oper_cfg.vpss_name, pdev->dev.platform_data);
> +	dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name);
> +	oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!oper_cfg.r1)
> +		return -ENOENT;
> +
> +	oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1;
> +
> +	oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1,
> +					 oper_cfg.r1->name);
> +	if (!oper_cfg.r1)
> +		return -EBUSY;
> +
> +	oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1);
> +	if (!oper_cfg.vpss_bl_regs_base) {
> +		status = -EBUSY;
> +		goto fail1;
> +	}
> +
> +	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +		oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +		if (!oper_cfg.r2) {
> +			status = -ENOENT;
> +			goto fail2;
> +		}
> +		oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1;
> +		oper_cfg.r2 = request_mem_region(oper_cfg.r2->start,
> +						 oper_cfg.len2,
> +						 oper_cfg.r2->name);
> +		if (!oper_cfg.r2) {
> +			status = -EBUSY;
> +			goto fail2;
> +		}
> +
> +		oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start,
> +						  oper_cfg.len2);
> +		if (!oper_cfg.vpss_regs_base) {
> +			status = -EBUSY;
> +			goto fail3;
> +		}
> +	}
> +
> +	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +		oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
> +		oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
> +	} else if (!strcmp(oper_cfg.vpss_name, "dm644x_vpss"))
> +		oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
> +	else
> +		return -ENODEV;
> +	spin_lock_init(&oper_cfg.vpss_lock);
> +	dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name);
> +	return 0;
> +fail3:
> +	release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
> +fail2:
> +	iounmap(oper_cfg.vpss_bl_regs_base);
> +fail1:
> +	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
> +	return status;
> +}
> +
> +static int vpss_remove(struct platform_device *pdev)
> +{
> +	iounmap(oper_cfg.vpss_bl_regs_base);
> +	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
> +	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +		iounmap(oper_cfg.vpss_regs_base);
> +		release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
> +	}
> +	return 0;
> +}
> +
> +static struct platform_driver vpss_driver = {
> +	.driver = {
> +		.name	= "vpss",
> +		.owner = THIS_MODULE,
> +	},
> +	.remove = __devexit_p(vpss_remove),
> +	.probe = vpss_probe,
> +};
> +
> +static void vpss_exit(void)
> +{
> +	platform_driver_unregister(&vpss_driver);
> +}
> +
> +static int __init vpss_init(void)
> +{
> +	return platform_driver_register(&vpss_driver);
> +}
> +subsys_initcall(vpss_init);
> +module_exit(vpss_exit);
> +MODULE_LICENSE("GPL");

MODULE_AUTHOR? MODULE_DESCRIPTION? Also suggest moving these to the top of
the source.

> diff --git a/include/media/davinci/vpss.h b/include/media/davinci/vpss.h
> new file mode 100644
> index 0000000..fcdff74
> --- /dev/null
> +++ b/include/media/davinci/vpss.h
> @@ -0,0 +1,69 @@
> +/*
> + * Copyright (C) 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
> + *
> + * vpss - video processing subsystem module header file.
> + *
> + * Include this header file if a driver needs to configure vpss system
> + * module. It exports a set of library functions  for video drivers to
> + * configure vpss system module functions such as clock enable/disable,
> + * vpss interrupt mux to arm, and other common vpss system module
> + * functions.
> + */
> +#ifndef _VPSS_H
> +#define _VPSS_H
> +
> +/* selector for ccdc input selection on DM355 */
> +enum vpss_ccdc_source_sel {
> +	VPSS_CCDCIN,
> +	VPSS_HSSIIN
> +};
> +
> +/* Used for enable/diable VPSS Clock */
> +enum vpss_clock_sel {
> +	/* DM355/DM365 */
> +	VPSS_CCDC_CLOCK,
> +	VPSS_IPIPE_CLOCK,
> +	VPSS_H3A_CLOCK,
> +	VPSS_CFALD_CLOCK,
> +	/*
> +	 * When using VPSS_VENC_CLOCK_SEL in vpss_enable_clock() api
> +	 * following applies:-
> +	 * en = 0 selects ENC_CLK
> +	 * en = 1 selects ENC_CLK/2
> +	 */
> +	VPSS_VENC_CLOCK_SEL,
> +	VPSS_VPBE_CLOCK,
> +};
> +
> +/* select input to ccdc on dm355 */
> +int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel);
> +/* enable/disable a vpss clock, 0 - success, -1 - failure */
> +int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en);
> +
> +/* wbl reset for dm644x */
> +enum vpss_wbl_sel {
> +	VPSS_PCR_AEW_WBL_0 = 16,
> +	VPSS_PCR_AF_WBL_0,
> +	VPSS_PCR_RSZ4_WBL_0,
> +	VPSS_PCR_RSZ3_WBL_0,
> +	VPSS_PCR_RSZ2_WBL_0,
> +	VPSS_PCR_RSZ1_WBL_0,
> +	VPSS_PCR_PREV_WBL_0,
> +	VPSS_PCR_CCDC_WBL_O,
> +};
> +int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel);
> +#endif

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 7/10 - v2] DM355 platform changes for vpfe capture driver
  2009-06-14 14:22               ` Hans Verkuil
@ 2009-06-14 19:42                 ` David Brownell
  2009-06-15 22:24                 ` Karicheri, Muralidharan
  1 sibling, 0 replies; 34+ messages in thread
From: David Brownell @ 2009-06-14 19:42 UTC (permalink / raw)
  To: davinci-linux-open-source, Hans Verkuil
  Cc: m-karicheri2, Muralidharan Karicheri, linux-media

On Sunday 14 June 2009, Hans Verkuil wrote:
> >       /* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
> 
> Huh? What's this? I only know the tlv320aic23b and that's an audio driver.

AIC33 is another audio codec chip:

  http://focus.ti.com/docs/prod/folders/print/tlv320aic33.html

One can't list audio codecs with other board-specific data until
the ASoC initialization gets re-worked to allow it.  That's why
it's commented out of the list-of-i2c-devices-on-the-board.




^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-11 22:41   ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 Alexey Klimov
@ 2009-06-15 17:41     ` Karicheri, Muralidharan
  0 siblings, 0 replies; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-15 17:41 UTC (permalink / raw)
  To: Alexey Klimov
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

>> +       /* set the default image parameters in the device */
>> +       ret = vpfe_config_image_format(vpfe_dev,
>> +                               &vpfe_standards[vpfe_dev-
>>std_index].std_id);
>> +       if (ret)
>> +               goto unlock_out;
>
>Why you check ret value and go to label below?
>Probably you can remove if-check and goto here.
>
Ok.
>> +
>> +unlock_out:
>> +       mutex_unlock(&vpfe_dev->lock);
;
>
>return -EIO?
>
Ok.
>--
>Best regards, Klimov Alexey


^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 10/10 - v2] common vpss module for video drivers
  2009-06-11 23:23                     ` Alexey Klimov
@ 2009-06-15 17:42                       ` Karicheri, Muralidharan
  0 siblings, 0 replies; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-15 17:42 UTC (permalink / raw)
  To: Alexey Klimov
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri


=
>dm644x_clear_wbl_overflow;
>> +       else
>> +               return -ENODEV;
>
>Do you need clean up procedure if you return error here? I mean -
>calls to release_mem_region, release_mem_region, etc
>
Oops! I need to add that. Thanks.
>> +       spin_lock_init(&oper_cfg.vpss_lock);
>> +       dev_info(&pdev->dev, "%s vpss probe success\n",
>oper_cfg.vpss_name);
>> +       return 0;
>> +fail3:
>> +       release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
>> +fail2:
>> +       iounmap(oper_cfg.vpss_bl_regs_base);
>> +fail1:
>> +       release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
>> +       return status;
>> +}
>
>
>--
>Best regards, Klimov Alexey


^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-14 14:10   ` Hans Verkuil
@ 2009-06-15 21:47     ` Karicheri, Muralidharan
  2009-06-15 22:29       ` Hans Verkuil
  0 siblings, 1 reply; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-15 21:47 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

Hans,

I am not clear about some of your comments. Please see below with a [MK] prefix.

>> +static int debug;
>> +static u32 numbuffers = 3;
>> +static u32 bufsize = (720 * 576 * 2);
>> +
>> +module_param(numbuffers, uint, S_IRUGO);
>> +module_param(bufsize, uint, S_IRUGO);
>> +module_param(debug, int, 0644);
>> +
>> +
>> +/* Set interface params based on client interface */
>> +static int vpfe_set_hw_if_params(struct vpfe_device *vpfe_dev)
>> +{
>> +	struct vpfe_subdev_info *subdev = vpfe_dev->current_subdev;
>> +	struct v4l2_routing *route =
>> +		&(subdev->routes[vpfe_dev->current_input]);
>> +
>> +	switch (route->output) {
>> +	case OUTPUT_10BIT_422_EMBEDDED_SYNC:
>> +		vpfe_dev->vpfe_if_params.if_type = VPFE_BT656;
>> +		break;
>> +	case OUTPUT_20BIT_422_SEPERATE_SYNC:
>> +		vpfe_dev->vpfe_if_params.if_type = VPFE_YCBCR_SYNC_16;
>> +		break;
>> +	case OUTPUT_10BIT_422_SEPERATE_SYNC:
>> +		vpfe_dev->vpfe_if_params.if_type = VPFE_YCBCR_SYNC_8;
>> +		break;
>> +	default:
>> +		v4l2_err(&vpfe_dev->v4l2_dev, "decoder output"
>> +			" not supported, %d\n", route->output);
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* set if client specific interface param is available */
>> +	if (subdev->pdata) {
>> +		/* each client will have different interface requirements */
>> +		if (!strcmp(subdev->name, "tvp5146")) {
>> +			struct tvp514x_platform_data *pdata = subdev->pdata;
>> +
>> +			if (pdata->hs_polarity)
>> +				vpfe_dev->vpfe_if_params.hdpol =
>> +					VPFE_PINPOL_POSITIVE;
>> +			else
>> +				vpfe_dev->vpfe_if_params.hdpol =
>> +					VPFE_PINPOL_NEGATIVE;
>> +
>> +			if (pdata->vs_polarity)
>> +				vpfe_dev->vpfe_if_params.vdpol =
>> +					VPFE_PINPOL_POSITIVE;
>> +			else
>> +				vpfe_dev->vpfe_if_params.hdpol =
>> +					VPFE_PINPOL_NEGATIVE;
>
>This won't work. Instead this should be data associated with the
>platform_data.
>I.e. the platform_data for the dm355/dm6446 contains not only the subdev
>information, but for each subdev also the information on how to setup the
>vpfe
>polarities. You cannot derive that information from what subdevs are used
>since
>the board designer might have added e.g. inverters or something like that.
>Such
>information can only come from the platform_data.
>
[MK] I know this code is not correct. But I was waiting for the discussion on my bus parameter patch to make this change. Currently TVP514x driver that you have reviewed configure output bus based on route->output parameter set by s_route(). This doesn't make sense. The input param make sense since application can choose between Composite and S-Video inputs. There is only one bus going out of the sub device to vpfe. So the output selection @ sub device is redundant. I think the output is part of as the bus parameter structure I added in the bus parameter patch which is under review. It can be read by TVP514x from the platform data (using the structure added by my patch) and can be overridden by s_bus(). Do you expect the bridge driver and sub devices having platform data for bus type (For example, BT.656)? It appears to be required only for sub device and bridge driver can configure the ccdc based on sub device bus type.  But for polarities I need to define them for both sides. comments?

>> +		} else {
>> +			v4l2_err(&vpfe_dev->v4l2_dev, "No interface params"
>> +				" defined for subdevice, %d\n", route->output);
>> +			return -EFAULT;
>> +		}
>> +	}
>> +	return ccdc_dev->hw_ops.set_hw_if_params(&vpfe_dev->vpfe_if_params);
>> +}
>> +
>> +/*
>> +
>> +	struct vpfe_fh *fh;
>> +
>> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");
>> +
>> +	if (!vpfe_dev->cfg->num_subdevs) {
>> +		v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");
>> +		return -ENODEV;
>> +	}
>
>Why would this be an error? I might have an FPGA connected instead or some
>other non-i2c device that doesn't require any setup from this driver.
>
[MK] What you mean by this? Are you saying an FPGA logic will implement the decoder hardware? That is quite possible, so also it could be non-i2c. But my understanding was that sub device can be anything that basically implement the sub device API and need not always be an i2c device. So for FPGA or some other bus based device, the bridge device doesn't care how the command to change input, detect standard etc are communicated by the sub device driver to its hardware. It could be writing into some FPGA register or sending a proprietary protocol command. Is my understanding correct? In that case each of the above (FPGA or non-i2c) is a sub device and at least one sub device should be available before application can do any useful operation with the capture device. So the check is required. Am I missing something here?

>
>> +
>> +unlock_out:
>> +	mutex_unlock(&vpfe_dev->lock);
>> +	return ret;
>> +}
>> +
>> +
>> +static int vpfe_queryctrl(struct file *file, void *priv,
>> +				struct v4l2_queryctrl *qc)
>> +{
>> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
>> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
>> +
>> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_queryctrl\n");
>> +
>> +	if (qc->id >= V4L2_CID_PRIVATE_BASE) {
>> +		/* It is ccdc CID */
>> +		if (ccdc_dev->hw_ops.queryctrl)
>> +			return ccdc_dev->hw_ops.queryctrl(qc);
>> +	}
>> +	/* pass it to sub device */
>> +	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev-
>>grp_id,
>> +					  core, queryctrl, qc);
>> +}
>> +
>> +static int vpfe_g_ctrl(struct file *file, void *priv,
>> +			struct v4l2_control *ctrl)
>> +{
>> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
>> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
>> +
>> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_ctrl\n");
>> +
>> +	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
>> +		/* It is ccdc CID */
>> +		if (ccdc_dev->hw_ops.get_control)
>> +			return ccdc_dev->hw_ops.get_control(ctrl);
>> +	}
>
>Don't use these PRIVATE_BASE controls. See also this post regarding
>the current situation regarding private controls:
>
>http://www.mail-archive.com/linux-omap%40vger.kernel.org/msg07999.html
>
[MK] Looks like it is better to add it to TBD and address it when I add camera interface support.
>--
>Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom


^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 7/10 - v2] DM355 platform changes for vpfe capture driver
  2009-06-14 14:22               ` Hans Verkuil
  2009-06-14 19:42                 ` David Brownell
@ 2009-06-15 22:24                 ` Karicheri, Muralidharan
  2009-06-15 22:40                   ` Hans Verkuil
  1 sibling, 1 reply; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-15 22:24 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

Hans,

Please see my response below.

>> +	/* { plus irq  }, */
>>  	/* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
>
>Huh? What's this? I only know the tlv320aic23b and that's an audio driver.
>
[MK] Thanks to David for answering this.
>> -	/* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
>>  };
>>
>>  static void __init evm_init_i2c(void)
>> @@ -178,6 +191,57 @@ static struct platform_device dm355evm_dm9000 = {
>>  	.num_resources	= ARRAY_SIZE(dm355evm_dm9000_rsrc),
>>  };
>>
>> +#define TVP514X_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
>> +/* Inputs available at the TVP5146 */
>> +static struct v4l2_input tvp5146_inputs[] = {
>> +	{
>> +		.index = 0,
>> +		.name = "COMPOSITE",
>
>Please, don't use all-caps. Just use "Composite" and "S-Video".
>
[MK] Ok
>> +		.type = V4L2_INPUT_TYPE_CAMERA,
>> +		.std = TVP514X_STD_ALL,
>> +	},
>> +	{
>> +		.index = 1,
>> +		.name = "SVIDEO",
>> +		.type = V4L2_INPUT_TYPE_CAMERA,
>> +		.std = TVP514X_STD_ALL,
>> +	},
>> +};
>> +
>> +/*
>> + * this is the route info for connecting each input to decoder
>> + * ouput that goes to vpfe. There is a one to one correspondence
>> + * with tvp5146_inputs
>> + */
>> +static struct v4l2_routing tvp5146_routes[] = {
>
>As mentioned elsewhere: v4l2_routing will disappear, so please don't use it.
>
[MK] Will change.
>> +	{
>> +		.input = INPUT_CVBS_VI2B,
>> +		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
>> +	},
>> +	{
>> +		.input = INPUT_SVIDEO_VI2C_VI1C,
>> +		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
>> +	},
>> +};
>> +
>> +static struct vpfe_subdev_info vpfe_sub_devs[] = {
>> +	{
>> +		.name = "tvp5146",
>> +		.grp_id = 0,
>> +		.num_inputs = ARRAY_SIZE(tvp5146_inputs),
>> +		.inputs = tvp5146_inputs,
>> +		.routes = tvp5146_routes,
>> +		.can_route = 1,
>> +	}
>> +};
>
>A general remark: currently you link your inputs directly to a subdev. This
>approach has two disadvantages:
>
>1) It doesn't work if there are no subdevs at all (e.g. because everything
>goes through an fpga).
>
[MK] Not sure what you mean here. If there is an FPGA, there should be something to make a selection between FPGA vs the rest of the decoders. FPGA will have an input and there should be some way it reports the detected standard etc. So why can't it be implemented by a sub device (may be less configuration since most of the logic is in FPGA).  
>2) It fixes the reported order of the inputs to the order of the subdevs.
>
[MK]Is that an issue? I don't see why.
>I think it is better to have a separate array of input descriptions that
>refer to a subdev when an input is associated with that subdev. 
[MK] Are suggesting an link from input array entry into sub device entry input index? How do you translate the input from application to a sub device or FPGA input? What if there are two "composite" inputs on two different sub devices?

>flexible that way, and I actually think that the vpfe driver will be
>simplified as well.
[MK], Not sure at this point.

Murali
m-karicher2@ti.com

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-15 21:47     ` Karicheri, Muralidharan
@ 2009-06-15 22:29       ` Hans Verkuil
  2009-06-16 14:26         ` Karicheri, Muralidharan
  0 siblings, 1 reply; 34+ messages in thread
From: Hans Verkuil @ 2009-06-15 22:29 UTC (permalink / raw)
  To: Karicheri, Muralidharan; +Cc: linux-media, davinci-linux-open-source

On Monday 15 June 2009 23:47:07 Karicheri, Muralidharan wrote:
> Hans,
>
> I am not clear about some of your comments. Please see below with a [MK]
> prefix.
>

<snip>

> >> +	/* set if client specific interface param is available */
> >> +	if (subdev->pdata) {
> >> +		/* each client will have different interface requirements */
> >> +		if (!strcmp(subdev->name, "tvp5146")) {
> >> +			struct tvp514x_platform_data *pdata = subdev->pdata;
> >> +
> >> +			if (pdata->hs_polarity)
> >> +				vpfe_dev->vpfe_if_params.hdpol =
> >> +					VPFE_PINPOL_POSITIVE;
> >> +			else
> >> +				vpfe_dev->vpfe_if_params.hdpol =
> >> +					VPFE_PINPOL_NEGATIVE;
> >> +
> >> +			if (pdata->vs_polarity)
> >> +				vpfe_dev->vpfe_if_params.vdpol =
> >> +					VPFE_PINPOL_POSITIVE;
> >> +			else
> >> +				vpfe_dev->vpfe_if_params.hdpol =
> >> +					VPFE_PINPOL_NEGATIVE;
> >
> >This won't work. Instead this should be data associated with the
> >platform_data.
> >I.e. the platform_data for the dm355/dm6446 contains not only the subdev
> >information, but for each subdev also the information on how to setup
> > the vpfe
> >polarities. You cannot derive that information from what subdevs are
> > used since
> >the board designer might have added e.g. inverters or something like
> > that. Such
> >information can only come from the platform_data.
>
> [MK] I know this code is not correct. But I was waiting for the
> discussion on my bus parameter patch to make this change. Currently
> TVP514x driver that you have reviewed configure output bus based on
> route->output parameter set by s_route(). This doesn't make sense. The
> input param make sense since application can choose between Composite and
> S-Video inputs. There is only one bus going out of the sub device to
> vpfe. So the output selection @ sub device is redundant. I think the
> output is part of as the bus parameter structure I added in the bus
> parameter patch which is under review. It can be read by TVP514x from the
> platform data (using the structure added by my patch) and can be
> overridden by s_bus(). Do you expect the bridge driver and sub devices
> having platform data for bus type (For example, BT.656)? It appears to be
> required only for sub device and bridge driver can configure the ccdc
> based on sub device bus type.  But for polarities I need to define them
> for both sides. comments?

Part of the current functionality of s_route will be taken over by s_bus. 
But right now this is all we have. Usually the output argument of s_route 
is used by audio devices that have multiple output pins. Most video devices 
have only one output so it does not normally apply to those. But without an 
s_bus function it is (ab)used to set things like bus parameters. One can 
argue that those parameters define the output of the chip but it will 
definitely be nicer to set this with a proper s_bus call.

Polarities have to be set for each side, that's correct. The other 
parameters are common for both. Although I can think of scenarios where the 
bus width can differ between host and subdev (e.g. subdev sends data on 8 
pins and the host captures on 10 with the least significant two pins pulled 
low). But that's probably really paranoid of me :-)

>
> >> +		} else {
> >> +			v4l2_err(&vpfe_dev->v4l2_dev, "No interface params"
> >> +				" defined for subdevice, %d\n", route->output);
> >> +			return -EFAULT;
> >> +		}
> >> +	}
> >> +	return ccdc_dev->hw_ops.set_hw_if_params(&vpfe_dev->vpfe_if_params);
> >> +}
> >> +
> >> +/*
> >> +
> >> +	struct vpfe_fh *fh;
> >> +
> >> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");
> >> +
> >> +	if (!vpfe_dev->cfg->num_subdevs) {
> >> +		v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");
> >> +		return -ENODEV;
> >> +	}
> >
> >Why would this be an error? I might have an FPGA connected instead or
> > some other non-i2c device that doesn't require any setup from this
> > driver.
>
> [MK] What you mean by this? Are you saying an FPGA logic will implement
> the decoder hardware? That is quite possible, so also it could be
> non-i2c. But my understanding was that sub device can be anything that
> basically implement the sub device API and need not always be an i2c
> device. So for FPGA or some other bus based device, the bridge device
> doesn't care how the command to change input, detect standard etc are
> communicated by the sub device driver to its hardware. It could be
> writing into some FPGA register or sending a proprietary protocol
> command. Is my understanding correct? In that case each of the above
> (FPGA or non-i2c) is a sub device and at least one sub device should be
> available before application can do any useful operation with the capture
> device. So the check is required. Am I missing something here?

First of all, this isn't a blocking issue at all. This is more a 
nice-to-have.

The reason I mentioned it is because of how we use this (or the dm646x to be 
precise) at my work: the dm646x is connected to our FPGA so we had to make 
dummy encoder/decoder drivers to allow it to work with that driver. What 
made that somewhat annoying is that those dummy drivers really didn't do 
anything since the FPGA isn't programmed from the linux kernel at all. So 
we have basically dead code in our kernel just to satisfy a dm646x driver 
requirement.

And you are right: a subdev is bus independent, so it is perfectly possible 
to make a dummy subdev instead. The key phrase was really 'doesn't require 
any setup'. It would be nice to be able to use this driver 'standalone' 
without requiring a subdev. Something to think about.

And apologies for my poor review comment, that was phrased rather badly.

>
> >> +
> >> +unlock_out:
> >> +	mutex_unlock(&vpfe_dev->lock);
> >> +	return ret;
> >> +}
> >> +
> >> +
> >> +static int vpfe_queryctrl(struct file *file, void *priv,
> >> +				struct v4l2_queryctrl *qc)
> >> +{
> >> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> >> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
> >> +
> >> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_queryctrl\n");
> >> +
> >> +	if (qc->id >= V4L2_CID_PRIVATE_BASE) {
> >> +		/* It is ccdc CID */
> >> +		if (ccdc_dev->hw_ops.queryctrl)
> >> +			return ccdc_dev->hw_ops.queryctrl(qc);
> >> +	}
> >> +	/* pass it to sub device */
> >> +	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev-
> >>grp_id,
> >> +					  core, queryctrl, qc);
> >> +}
> >> +
> >> +static int vpfe_g_ctrl(struct file *file, void *priv,
> >> +			struct v4l2_control *ctrl)
> >> +{
> >> +	struct vpfe_device *vpfe_dev = video_drvdata(file);
> >> +	struct vpfe_subdev_info *sub_dev = vpfe_dev->current_subdev;
> >> +
> >> +	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_ctrl\n");
> >> +
> >> +	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
> >> +		/* It is ccdc CID */
> >> +		if (ccdc_dev->hw_ops.get_control)
> >> +			return ccdc_dev->hw_ops.get_control(ctrl);
> >> +	}
> >
> >Don't use these PRIVATE_BASE controls. See also this post regarding
> >the current situation regarding private controls:
> >
> >http://www.mail-archive.com/linux-omap%40vger.kernel.org/msg07999.html
>
> [MK] Looks like it is better to add it to TBD and address it when I add
> camera interface support.

OK, but please make sure it is revisited. Improving the control handling 
code in the v4l2 framework is very high on my TODO list since it is getting 
really annoying to implement in drivers. And the inconsistent driver 
support isn't helping applications either.

I really hope I'll have time for it in the next few weeks.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 7/10 - v2] DM355 platform changes for vpfe capture driver
  2009-06-15 22:24                 ` Karicheri, Muralidharan
@ 2009-06-15 22:40                   ` Hans Verkuil
  0 siblings, 0 replies; 34+ messages in thread
From: Hans Verkuil @ 2009-06-15 22:40 UTC (permalink / raw)
  To: Karicheri, Muralidharan
  Cc: linux-media, davinci-linux-open-source, Muralidharan Karicheri

On Tuesday 16 June 2009 00:24:34 Karicheri, Muralidharan wrote:
> Hans,
>
> Please see my response below.

<snip>

> >A general remark: currently you link your inputs directly to a subdev.
> > This approach has two disadvantages:
> >
> >1) It doesn't work if there are no subdevs at all (e.g. because
> > everything goes through an fpga).
>
> [MK] Not sure what you mean here. If there is an FPGA, there should be
> something to make a selection between FPGA vs the rest of the decoders.
> FPGA will have an input and there should be some way it reports the
> detected standard etc. So why can't it be implemented by a sub device
> (may be less configuration since most of the logic is in FPGA).

Hopefully my previous reply explains what I meant. I wasn't clear here 
either.

> >2) It fixes the reported order of the inputs to the order of the
> > subdevs.
>
> [MK]Is that an issue? I don't see why.

It's a minor issue. But applications typically enumerate inputs to present a 
list to the user which inputs there are. And if there are a lot then it can 
be useful to have them in a specific order. Either to group the inputs 
based on some criterium or to reflect the labeling on the box. It's a 
nice-to-have, I admit.

> >I think it is better to have a separate array of input descriptions that
> >refer to a subdev when an input is associated with that subdev.
>
> [MK] Are suggesting an link from input array entry into sub device entry
> input index?

Yes.

> How do you translate the input from application to a sub 
> device or FPGA input? What if there are two "composite" inputs on two
> different sub devices?

A "Composite 1" input would point to subdev 1 and the "Composite 2" input 
would point to subdev 2. Or do you mean something else? (I'm not sure I 
entirely understand your question)

>
> >flexible that way, and I actually think that the vpfe driver will be
> >simplified as well.
>
> [MK], Not sure at this point.

The advantage is that the ENUMINPUT and S/G_INPUT functions can do a simple 
lookup in the input array and immediately find the subdev index. Rather 
than iterating over all subdevs and counting the number of inputs in order 
to find which input belongs to which subdev.

This is probably a stronger argument than my others are :-)

Regards,

	Hans

>
> Murali
> m-karicher2@ti.com
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-15 22:29       ` Hans Verkuil
@ 2009-06-16 14:26         ` Karicheri, Muralidharan
  2009-06-17  6:39           ` Hans Verkuil
  0 siblings, 1 reply; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-16 14:26 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, davinci-linux-open-source

Hans,

Thanks for the response.

<snip>

>Polarities have to be set for each side, that's correct. The other
>parameters are common for both. Although I can think of scenarios where the
>bus width can differ between host and subdev (e.g. subdev sends data on 8
>pins and the host captures on 10 with the least significant two pins pulled
>low). But that's probably really paranoid of me :-)

[MK] You are right on width. The MT9T001/31 sensor has 10 bits and MT9P031 has 12 bits, but on DM355 we the vpfe will take in only 10 bits and on DM365 it takes 12 bits. But this is applicable only on the host (vpfe) side though (at least in this case) , not on sub device side.

<snip>

>First of all, this isn't a blocking issue at all. This is more a
>nice-to-have.
>
>The reason I mentioned it is because of how we use this (or the dm646x to
>be
>precise) at my work: the dm646x is connected to our FPGA so we had to make
>dummy encoder/decoder drivers to allow it to work with that driver. What
>made that somewhat annoying is that those dummy drivers really didn't do
>anything since the FPGA isn't programmed from the linux kernel at all. So
>we have basically dead code in our kernel just to satisfy a dm646x driver
>requirement.
>
>And you are right: a subdev is bus independent, so it is perfectly possible
>to make a dummy subdev instead. The key phrase was really 'doesn't require
>any setup'. It would be nice to be able to use this driver 'standalone'
>without requiring a subdev. Something to think about.
>
>And apologies for my poor review comment, that was phrased rather badly.
>
[MK] This is the first version of the driver and I assure you that there are opportunities to improve the driver as we add more features. Since many of the other activities like adding camera interface, supporting resizer/previewer are dependent on this, it is important for us to get this to the kernel tree as quickly as possible. So I would prefer to keep it as is now and change it part of later patches. If this can go in 2.6.31, that will be really great.

>>

<snip>

>> >Don't use these PRIVATE_BASE controls. See also this post regarding
>> >the current situation regarding private controls:
>> >
>> >http://www.mail-archive.com/linux-omap%40vger.kernel.org/msg07999.html
>>
>> [MK] Looks like it is better to add it to TBD and address it when I add
>> camera interface support.
>
>OK, but please make sure it is revisited. Improving the control handling
>code in the v4l2 framework is very high on my TODO list since it is getting
>really annoying to implement in drivers. And the inconsistent driver
>support isn't helping applications either.
>
[MK] Sure. I will add it to the TODO list and address it later.
>I really hope I'll have time for it in the next few weeks.
>
>Regards,
>
>	Hans
>
>--
>Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-16 14:26         ` Karicheri, Muralidharan
@ 2009-06-17  6:39           ` Hans Verkuil
  2009-06-17 15:02             ` Karicheri, Muralidharan
  0 siblings, 1 reply; 34+ messages in thread
From: Hans Verkuil @ 2009-06-17  6:39 UTC (permalink / raw)
  To: Karicheri, Muralidharan; +Cc: linux-media, davinci-linux-open-source

On Tuesday 16 June 2009 16:26:05 Karicheri, Muralidharan wrote:
> Hans,
>
> Thanks for the response.
>
> <snip>
>
> >Polarities have to be set for each side, that's correct. The other
> >parameters are common for both. Although I can think of scenarios where
> > the bus width can differ between host and subdev (e.g. subdev sends
> > data on 8 pins and the host captures on 10 with the least significant
> > two pins pulled low). But that's probably really paranoid of me :-)
>
> [MK] You are right on width. The MT9T001/31 sensor has 10 bits and
> MT9P031 has 12 bits, but on DM355 we the vpfe will take in only 10 bits
> and on DM365 it takes 12 bits. But this is applicable only on the host
> (vpfe) side though (at least in this case) , not on sub device side.

Can you post your latest proposal for the s_bus op?

I propose a few changes: the name of the struct should be something like 
v4l2_bus_settings, the master/slave bit should be renamed to something 
like 'host_is_master', and we should have two widths: subdev_width and 
host_width.

That way the same structure can be used for both host and subdev, unless 
some of the polarities are inverted. In that case you need to make two 
structs, one for host and one for the subdev.

It is possible to add info on inverters to the struct, but unless inverters 
are used a lot more frequently than I expect I am inclined not to do that 
at this time.

> <snip>
>
> >First of all, this isn't a blocking issue at all. This is more a
> >nice-to-have.
> >
> >The reason I mentioned it is because of how we use this (or the dm646x
> > to be
> >precise) at my work: the dm646x is connected to our FPGA so we had to
> > make dummy encoder/decoder drivers to allow it to work with that
> > driver. What made that somewhat annoying is that those dummy drivers
> > really didn't do anything since the FPGA isn't programmed from the
> > linux kernel at all. So we have basically dead code in our kernel just
> > to satisfy a dm646x driver requirement.
> >
> >And you are right: a subdev is bus independent, so it is perfectly
> > possible to make a dummy subdev instead. The key phrase was really
> > 'doesn't require any setup'. It would be nice to be able to use this
> > driver 'standalone' without requiring a subdev. Something to think
> > about.
> >
> >And apologies for my poor review comment, that was phrased rather badly.
>
> [MK] This is the first version of the driver and I assure you that there
> are opportunities to improve the driver as we add more features. Since
> many of the other activities like adding camera interface, supporting
> resizer/previewer are dependent on this, it is important for us to get
> this to the kernel tree as quickly as possible. So I would prefer to keep
> it as is now and change it part of later patches. If this can go in
> 2.6.31, that will be really great.

It's no problem to keep this as is.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-17  6:39           ` Hans Verkuil
@ 2009-06-17 15:02             ` Karicheri, Muralidharan
  2009-06-17 19:05               ` Hans Verkuil
  0 siblings, 1 reply; 34+ messages in thread
From: Karicheri, Muralidharan @ 2009-06-17 15:02 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, davinci-linux-open-source

>>
>> <snip>
>
>Can you post your latest proposal for the s_bus op?
>
>I propose a few changes: the name of the struct should be something like
>v4l2_bus_settings, the master/slave bit should be renamed to something
>like 'host_is_master', and we should have two widths: subdev_width and
>host_width.
>
>That way the same structure can be used for both host and subdev, unless
>some of the polarities are inverted. In that case you need to make two
>structs, one for host and one for the subdev.
>
>It is possible to add info on inverters to the struct, but unless inverters
>are used a lot more frequently than I expect I am inclined not to do that
>at this time.
>
[MK]Today I am planning to send my v3 version of the vpfe capture patch and also tvp514x patch since Vaibhav is pre-occupied with some other activities. I have discussed the changes with Vaibhav for this driver.

For s_bus, I will try if I can send a patch today. BTW, do you expect me to add one bool for active high, one for active low etc as done in SoC camera ?

Murali 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446
  2009-06-17 15:02             ` Karicheri, Muralidharan
@ 2009-06-17 19:05               ` Hans Verkuil
  0 siblings, 0 replies; 34+ messages in thread
From: Hans Verkuil @ 2009-06-17 19:05 UTC (permalink / raw)
  To: Karicheri, Muralidharan; +Cc: linux-media, davinci-linux-open-source

On Wednesday 17 June 2009 17:02:01 Karicheri, Muralidharan wrote:
> >> <snip>
> >
> >Can you post your latest proposal for the s_bus op?
> >
> >I propose a few changes: the name of the struct should be something like
> >v4l2_bus_settings, the master/slave bit should be renamed to something
> >like 'host_is_master', and we should have two widths: subdev_width and
> >host_width.
> >
> >That way the same structure can be used for both host and subdev, unless
> >some of the polarities are inverted. In that case you need to make two
> >structs, one for host and one for the subdev.
> >
> >It is possible to add info on inverters to the struct, but unless
> > inverters are used a lot more frequently than I expect I am inclined
> > not to do that at this time.
>
> [MK]Today I am planning to send my v3 version of the vpfe capture patch
> and also tvp514x patch since Vaibhav is pre-occupied with some other
> activities. I have discussed the changes with Vaibhav for this driver.
>
> For s_bus, I will try if I can send a patch today. BTW, do you expect me
> to add one bool for active high, one for active low etc as done in SoC
> camera ?

Since I remain opposed to autonegotiation, there is IMO no need for this.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 10/10 - v2] common vpss module for video drivers
@ 2009-06-09 18:51 m-karicheri2
  0 siblings, 0 replies; 34+ messages in thread
From: m-karicheri2 @ 2009-06-09 18:51 UTC (permalink / raw)
  To: linux-media
  Cc: davinci-linux-open-source, Muralidharan Karicheri,
	Muralidharan Karicheri

From: Muralidharan Karicheri <a0868495@gt516km11.gt.design.ti.com>

Reviewed By "Hans Verkuil".
Reviewed By "Laurent Pinchart".

This is a new module added for vpss library functions that are
used configuring vpss system module. All video drivers will
include vpss.h header and call functions defined in this module
to configure vpss system module.
 
Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
Applies to v4l-dvb repository

 drivers/media/video/davinci/vpss.c |  291 ++++++++++++++++++++++++++++++++++++
 include/media/davinci/vpss.h       |   69 +++++++++
 2 files changed, 360 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/vpss.c
 create mode 100644 include/media/davinci/vpss.h

diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
new file mode 100644
index 0000000..9480256
--- /dev/null
+++ b/drivers/media/video/davinci/vpss.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * common vpss driver for all video drivers.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/io.h>
+#include <mach/cpu.h>
+#include <mach/hardware.h>
+#include <media/davinci/vpss.h>
+
+/* DM644x defines */
+#define DM644X_SBL_PCR_VPSS		(4)
+
+/* vpss BL register offsets */
+#define DM355_VPSSBL_CCDCMUX		0x1c
+/* vpss CLK register offsets */
+#define DM355_VPSSCLK_CLKCTRL		0x04
+/* masks and shifts */
+#define VPSS_HSSISEL_SHIFT		4
+
+/*
+ * vpss operations. Depends on platform. Not all functions are available
+ * on all platforms. The api, first check if a functio is available before
+ * invoking it. In the probe, the function ptrs are intialized based on
+ * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
+ */
+struct vpss_hw_ops {
+	/* enable clock */
+	int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
+	/* select input to ccdc */
+	void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
+	/* clear wbl overlflow bit */
+	int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
+};
+
+/* vpss configuration */
+struct vpss_oper_config {
+	__iomem void *vpss_bl_regs_base;
+	__iomem void *vpss_regs_base;
+	struct resource		*r1;
+	resource_size_t		len1;
+	struct resource		*r2;
+	resource_size_t		len2;
+	char vpss_name[32];
+	spinlock_t vpss_lock;
+	struct vpss_hw_ops hw_ops;
+};
+
+static struct vpss_oper_config oper_cfg;
+
+/* register access routines */
+static inline u32 bl_regr(u32 offset)
+{
+	return __raw_readl(oper_cfg.vpss_bl_regs_base + offset);
+}
+
+static inline void bl_regw(u32 val, u32 offset)
+{
+	__raw_writel(val, oper_cfg.vpss_bl_regs_base + offset);
+}
+
+static inline u32 vpss_regr(u32 offset)
+{
+	return __raw_readl(oper_cfg.vpss_regs_base + offset);
+}
+
+static inline void vpss_regw(u32 val, u32 offset)
+{
+	__raw_writel(val, oper_cfg.vpss_regs_base + offset);
+}
+
+static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
+{
+	bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
+}
+
+int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
+{
+	if (!oper_cfg.hw_ops.select_ccdc_source)
+		return -1;
+
+	dm355_select_ccdc_source(src_sel);
+	return 0;
+}
+EXPORT_SYMBOL(vpss_select_ccdc_source);
+
+static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
+{
+	u32 mask = 1, val;
+
+	if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
+	    wbl_sel > VPSS_PCR_CCDC_WBL_O)
+		return -1;
+
+	/* writing a 0 clear the overflow */
+	mask = ~(mask << wbl_sel);
+	val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
+	bl_regw(val, DM644X_SBL_PCR_VPSS);
+	return 0;
+}
+
+int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
+{
+	if (!oper_cfg.hw_ops.clear_wbl_overflow)
+		return -1;
+
+	return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
+}
+EXPORT_SYMBOL(vpss_clear_wbl_overflow);
+
+/*
+ *  dm355_enable_clock - Enable VPSS Clock
+ *  @clock_sel: CLock to be enabled/disabled
+ *  @en: enable/disable flag
+ *
+ *  This is called to enable or disable a vpss clock
+ */
+static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
+{
+	unsigned long flags;
+	u32 utemp, mask = 0x1, shift = 0;
+
+	switch (clock_sel) {
+	case VPSS_VPBE_CLOCK:
+		/* nothing since lsb */
+		break;
+	case VPSS_VENC_CLOCK_SEL:
+		shift = 2;
+		break;
+	case VPSS_CFALD_CLOCK:
+		shift = 3;
+		break;
+	case VPSS_H3A_CLOCK:
+		shift = 4;
+		break;
+	case VPSS_IPIPE_CLOCK:
+		shift = 5;
+		break;
+	case VPSS_CCDC_CLOCK:
+		shift = 6;
+		break;
+	default:
+		printk(KERN_ERR "dm355_enable_clock:"
+				" Invalid selector: %d\n", clock_sel);
+		return -1;
+	}
+
+	spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
+	utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
+	if (!en)
+		utemp &= ~(mask << shift);
+	else
+		utemp |= (mask << shift);
+
+	vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
+	spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
+	return 0;
+}
+
+int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
+{
+	if (!oper_cfg.hw_ops.enable_clock)
+		return -1;
+
+	return oper_cfg.hw_ops.enable_clock(clock_sel, en);
+}
+EXPORT_SYMBOL(vpss_enable_clock);
+
+static int __init vpss_probe(struct platform_device *pdev)
+{
+	int			status;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "vpss, no platform data\n");
+		return -ENOENT;
+	}
+
+	strcpy(oper_cfg.vpss_name, pdev->dev.platform_data);
+	dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name);
+	oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!oper_cfg.r1)
+		return -ENOENT;
+
+	oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1;
+
+	oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1,
+					 oper_cfg.r1->name);
+	if (!oper_cfg.r1)
+		return -EBUSY;
+
+	oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1);
+	if (!oper_cfg.vpss_bl_regs_base) {
+		status = -EBUSY;
+		goto fail1;
+	}
+
+	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
+		oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!oper_cfg.r2) {
+			status = -ENOENT;
+			goto fail2;
+		}
+		oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1;
+		oper_cfg.r2 = request_mem_region(oper_cfg.r2->start,
+						 oper_cfg.len2,
+						 oper_cfg.r2->name);
+		if (!oper_cfg.r2) {
+			status = -EBUSY;
+			goto fail2;
+		}
+
+		oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start,
+						  oper_cfg.len2);
+		if (!oper_cfg.vpss_regs_base) {
+			status = -EBUSY;
+			goto fail3;
+		}
+	}
+
+	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
+		oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
+		oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
+	} else if (!strcmp(oper_cfg.vpss_name, "dm644x_vpss"))
+		oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
+	else
+		return -ENODEV;
+	spin_lock_init(&oper_cfg.vpss_lock);
+	dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name);
+	return 0;
+fail3:
+	release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
+fail2:
+	iounmap(oper_cfg.vpss_bl_regs_base);
+fail1:
+	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
+	return status;
+}
+
+static int vpss_remove(struct platform_device *pdev)
+{
+	iounmap(oper_cfg.vpss_bl_regs_base);
+	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
+	if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
+		iounmap(oper_cfg.vpss_regs_base);
+		release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
+	}
+	return 0;
+}
+
+static struct platform_driver vpss_driver = {
+	.driver = {
+		.name	= "vpss",
+		.owner = THIS_MODULE,
+	},
+	.remove = __devexit_p(vpss_remove),
+	.probe = vpss_probe,
+};
+
+static void vpss_exit(void)
+{
+	platform_driver_unregister(&vpss_driver);
+}
+
+static int __init vpss_init(void)
+{
+	return platform_driver_register(&vpss_driver);
+}
+subsys_initcall(vpss_init);
+module_exit(vpss_exit);
+MODULE_LICENSE("GPL");
diff --git a/include/media/davinci/vpss.h b/include/media/davinci/vpss.h
new file mode 100644
index 0000000..fcdff74
--- /dev/null
+++ b/include/media/davinci/vpss.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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
+ *
+ * vpss - video processing subsystem module header file.
+ *
+ * Include this header file if a driver needs to configure vpss system
+ * module. It exports a set of library functions  for video drivers to
+ * configure vpss system module functions such as clock enable/disable,
+ * vpss interrupt mux to arm, and other common vpss system module
+ * functions.
+ */
+#ifndef _VPSS_H
+#define _VPSS_H
+
+/* selector for ccdc input selection on DM355 */
+enum vpss_ccdc_source_sel {
+	VPSS_CCDCIN,
+	VPSS_HSSIIN
+};
+
+/* Used for enable/diable VPSS Clock */
+enum vpss_clock_sel {
+	/* DM355/DM365 */
+	VPSS_CCDC_CLOCK,
+	VPSS_IPIPE_CLOCK,
+	VPSS_H3A_CLOCK,
+	VPSS_CFALD_CLOCK,
+	/*
+	 * When using VPSS_VENC_CLOCK_SEL in vpss_enable_clock() api
+	 * following applies:-
+	 * en = 0 selects ENC_CLK
+	 * en = 1 selects ENC_CLK/2
+	 */
+	VPSS_VENC_CLOCK_SEL,
+	VPSS_VPBE_CLOCK,
+};
+
+/* select input to ccdc on dm355 */
+int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel);
+/* enable/disable a vpss clock, 0 - success, -1 - failure */
+int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en);
+
+/* wbl reset for dm644x */
+enum vpss_wbl_sel {
+	VPSS_PCR_AEW_WBL_0 = 16,
+	VPSS_PCR_AF_WBL_0,
+	VPSS_PCR_RSZ4_WBL_0,
+	VPSS_PCR_RSZ3_WBL_0,
+	VPSS_PCR_RSZ2_WBL_0,
+	VPSS_PCR_RSZ1_WBL_0,
+	VPSS_PCR_PREV_WBL_0,
+	VPSS_PCR_CCDC_WBL_O,
+};
+int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel);
+#endif
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2009-06-17 19:05 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-11 17:00 [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver m-karicheri2
2009-06-11 17:00 ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 m-karicheri2
2009-06-11 17:00   ` [PATCH 2/10 - v2] ccdc hw device header file for vpfe capture m-karicheri2
2009-06-11 17:00     ` [PATCH 3/10 - v2] dm355 ccdc module for vpfe capture driver m-karicheri2
2009-06-11 17:00       ` [PATCH 4/10 - v2] dm644x " m-karicheri2
2009-06-11 17:00         ` [PATCH 5/10 - v2] ccdc types used across ccdc modules " m-karicheri2
2009-06-11 17:00           ` [PATCH 6/10 - v2] Makefile and config files " m-karicheri2
2009-06-11 17:00             ` [PATCH 7/10 - v2] DM355 platform changes " m-karicheri2
2009-06-11 17:00               ` [PATCH 8/10 - v2] DM6446 " m-karicheri2
2009-06-11 17:00                 ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 m-karicheri2
2009-06-11 17:00                   ` [PATCH 10/10 - v2] common vpss module for video drivers m-karicheri2
2009-06-11 23:23                     ` Alexey Klimov
2009-06-15 17:42                       ` Karicheri, Muralidharan
2009-06-14 14:26                     ` Hans Verkuil
2009-06-11 20:23                   ` [PATCH 9/10 - v2] remove outdated video driver files of dm6446 Kevin Hilman
2009-06-12 15:07                     ` Karicheri, Muralidharan
2009-06-14 14:24                 ` [PATCH 8/10 - v2] DM6446 platform changes for vpfe capture driver Hans Verkuil
2009-06-11 20:23               ` [PATCH 7/10 - v2] DM355 " David Brownell
2009-06-14 14:22               ` Hans Verkuil
2009-06-14 19:42                 ` David Brownell
2009-06-15 22:24                 ` Karicheri, Muralidharan
2009-06-15 22:40                   ` Hans Verkuil
2009-06-11 22:41   ` [PATCH 1/10 - v2] vpfe capture bridge driver for DM355 and DM6446 Alexey Klimov
2009-06-15 17:41     ` Karicheri, Muralidharan
2009-06-14 14:10   ` Hans Verkuil
2009-06-15 21:47     ` Karicheri, Muralidharan
2009-06-15 22:29       ` Hans Verkuil
2009-06-16 14:26         ` Karicheri, Muralidharan
2009-06-17  6:39           ` Hans Verkuil
2009-06-17 15:02             ` Karicheri, Muralidharan
2009-06-17 19:05               ` Hans Verkuil
2009-06-11 20:24 ` [PATCH 0/10 - v2] ARM: DaVinci: Video: DM355/DM6446 VPFE Capture driver David Brownell
2009-06-12 15:58   ` Karicheri, Muralidharan
  -- strict thread matches above, loose matches on Subject: below --
2009-06-09 18:51 [PATCH 10/10 - v2] common vpss module for video drivers m-karicheri2

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.