lists.zerezo.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Patch 10/16] OMAP3 camera driver ISP basic blocks



From: Mohit Jalori <mjalori@xxxxxx>

ARM: OMAP: OMAP34XXCAM: Camera Driver.

Adding OMAP 3 Camera Driver with basic ISP blocks.

Signed-off-by: Mohit Jalori <mjalori@xxxxxx>
---
 drivers/media/video/Kconfig          |   10
 drivers/media/video/Makefile         |    2
 drivers/media/video/omap34xxcam.c    | 1605 +++++++++++++++++++++++++++++++
 drivers/media/video/omap34xxcam.h    |  189 +++
 drivers/media/video/isp/Makefile     |    4
 drivers/media/video/isp/Kconfig      |    1
 drivers/media/video/isp/isp.c        | 1802 +++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/isp.h        |  326 ++++++
 drivers/media/video/isp/ispccdc.c    | 1296 +++++++++++++++++++++++++
 drivers/media/video/isp/ispccdc.h    |  202 +++
 drivers/media/video/isp/ispmmu.c     |  742 ++++++++++++++
 drivers/media/video/isp/ispmmu.h     |  117 ++
 drivers/media/video/isp/ispreg.h     | 1281 ++++++++++++++++++++++++
 include/asm-arm/arch-omap/isp_user.h |  151 ++
 14 files changed, 7728 insertions(+)

--- a/drivers/media/video/Kconfig	2008-06-29 17:44:21.000000000 -0500
+++ b/drivers/media/video/Kconfig	2008-06-29 16:57:48.000000000 -0500
@@ -792,6 +792,16 @@ config VIDEO_CAFE_CCIC
 	  CMOS camera controller.  This is the controller found on first-
 	  generation OLPC systems.
 
+config VIDEO_OMAP3
+        tristate "OMAP 3 Camera support"
+	select VIDEOBUF_GEN
+	select VIDEOBUF_DMA_SG
+	depends on VIDEO_V4L2 && ARCH_OMAP34XX
+	---help---
+	  Driver for an OMAP 3 camera controller.
+
+source "drivers/media/video/isp/Kconfig"
+
 config VIDEO_OMAP2
 	tristate "OMAP 2 Camera support (EXPERIMENTAL)"
 	select VIDEOBUF_GEN
--- a/drivers/media/video/Makefile	2008-06-29 17:44:21.000000000 -0500
+++ b/drivers/media/video/Makefile	2008-06-29 16:57:48.000000000 -0500
@@ -105,6 +105,8 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_cc
 obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
 
 obj-$(CONFIG_VIDEO_OMAP2) += omap24xxcam.o omap24xxcam-dma.o
+obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o isp/
+
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 obj-$(CONFIG_VIDEO_OV9640)	+= ov9640.o
 
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/omap34xxcam.c	2008-06-29 17:07:06.000000000 -0500
@@ -0,0 +1,1605 @@
+/*
+ * drivers/media/video/omap34xxcam.c
+ *
+ * Video-for-Linux (Version 2) Camera capture driver for OMAP34xx ISP.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ * Copyright (C) 2008 Nokia.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@xxxxxx>
+ * 	Mohit Jalori <mjalori@xxxxxx>
+ * 	Sakari Ailus <sakari.ailus@xxxxxxxxx>
+ * 	Tuukka Toivonen <tuukka.o.toivonen@xxxxxxxxx>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/pci.h>		/* needed for videobufs */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-common.h>
+
+#include "omap34xxcam.h"
+#include "isp/isp.h"
+#include "isp/ispmmu.h"
+#include "isp/ispreg.h"
+#include "isp/ispccdc.h"
+
+#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
+
+/* global variables */
+static struct omap34xxcam_device *omap34xxcam;
+
+/* module parameters */
+static int capture_mem = 2592 * 1944 * 2 * 2;
+static int omap34xxcam_device_register(struct v4l2_int_device *s);
+static void omap34xxcam_device_unregister(struct v4l2_int_device *s);
+static int omap34xxcam_remove(struct platform_device *pdev);
+struct omap34xxcam_fh *camfh_saved;
+
+/*
+ *
+ * Sensor handling.
+ *
+ */
+
+/**
+ * omap34xxcam_slave_enable - Enable all slaves on device
+ * @vdev: per-video device data structure
+ *
+ * Power-up and configure camera sensor and sensor interface. On
+ * successful return (0), it's ready for capturing now.
+ */
+static int omap34xxcam_slave_power_set(struct omap34xxcam_videodev *vdev,
+				       enum v4l2_power power)
+{
+	int rval = 0, i = OMAP34XXCAM_SLAVE_FLASH + 1;
+
+	if (power == V4L2_POWER_OFF)
+		goto out;
+
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		if (!vdev->slave[i])
+			continue;
+
+		rval = vidioc_int_s_power(vdev->slave[i], power);
+
+		if (rval) {
+			power = V4L2_POWER_OFF;
+			goto out;
+		}
+	}
+
+	return 0;
+
+out:
+	for (i--; i >= 0; i--) {
+		if (!vdev->slave[i])
+			continue;
+
+		vidioc_int_s_power(vdev->slave[i], power);
+	}
+
+	return rval;
+}
+
+/**
+ * omap34xxcam_update_vbq - Updates VBQ with completed input buffer
+ * @vb: ptr. to standard V4L2 video buffer structure
+ *
+ * Updates video buffer queue with completed buffer passed as
+ * input parameter.  Also updates ISP H3A timestamp and field count
+ * statistics.
+ */
+int omap34xxcam_update_vbq(struct videobuf_buffer *vb)
+{
+	struct omap34xxcam_fh *fh = camfh_saved;
+	struct omap34xxcam_videodev *vdev = fh->vdev;
+	int rval = 0;
+
+	do_gettimeofday(&vb->ts);
+	vb->field_count = atomic_add_return(2, &fh->field_count);
+	vb->state = VIDEOBUF_DONE;
+
+	if (vdev->streaming)
+		rval = 1;
+
+	wake_up(&vb->done);
+
+	return rval;
+}
+
+/**
+ * omap34xxcam_vbq_setup - Calcs size and num of buffs allowed in queue
+ * @vbq: ptr. to standard V4L2 video buffer queue structure
+ * @cnt: ptr to location to hold the count of buffers to be in the queue
+ * @size: ptr to location to hold the size of a frame
+ *
+ * Calculates the number of buffers of current image size that can be
+ * supported by the available capture memory.
+ */
+static int omap34xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
+				 unsigned int *size)
+{
+	struct omap34xxcam_fh *fh = vbq->priv_data;
+	struct v4l2_format format;
+
+	if (*cnt <= 0)
+		*cnt = VIDEO_MAX_FRAME;	/* supply a default number of buffers */
+
+	if (*cnt > VIDEO_MAX_FRAME)
+		*cnt = VIDEO_MAX_FRAME;
+
+	isp_g_fmt_cap(&format);
+	*size = format.fmt.pix.sizeimage;
+
+	/* accessing fh->cam->capture_mem is ok, it's constant */
+	while (*size * *cnt > fh->vdev->capture_mem)
+		(*cnt)--;
+
+	return 0;
+}
+
+/**
+ * omap34xxcam_vbq_release - Free resources for input VBQ and VB
+ * @vbq: ptr. to standard V4L2 video buffer queue structure
+ * @vb: ptr to standard V4L2 video buffer structure
+ *
+ * Unmap and free all memory associated with input VBQ and VB, also
+ * unmap the address in ISP MMU.  Reset the VB state.
+ */
+static void omap34xxcam_vbq_release(struct videobuf_queue *vbq,
+				    struct videobuf_buffer *vb)
+{
+	if (!vbq->streaming) {
+		isp_vbq_release(vbq, vb);
+		videobuf_dma_unmap(vbq, videobuf_to_dma(vb));
+		videobuf_dma_free(videobuf_to_dma(vb));
+		vb->state = VIDEOBUF_NEEDS_INIT;
+	}
+	return;
+}
+
+/**
+ * omap34xxcam_vbq_prepare - V4L2 video ops buf_prepare handler
+ * @vbq: ptr. to standard V4L2 video buffer queue structure
+ * @vb: ptr to standard V4L2 video buffer structure
+ * @field: standard V4L2 field enum
+ *
+ * Verifies there is sufficient locked memory for the requested
+ * buffer, or if there is not, allocates, locks and initializes
+ * it.
+ */
+static int omap34xxcam_vbq_prepare(struct videobuf_queue *vbq,
+				   struct videobuf_buffer *vb,
+				   enum v4l2_field field)
+{
+	struct v4l2_format format;
+	unsigned int size;
+	int err = 0;
+
+	isp_g_fmt_cap(&format);
+	size = format.fmt.pix.sizeimage;
+	/*
+	 * Accessing pix here is okay since it's constant while
+	 * streaming is on (and we only get called then).
+	 */
+	if (vb->baddr) {
+		/* This is a userspace buffer. */
+		if (size > vb->bsize)
+			/* The buffer isn't big enough. */
+			err = -EINVAL;
+		else {
+			vb->size = size;
+			vb->bsize = vb->size;
+		}
+	} else {
+		if (vb->state != VIDEOBUF_NEEDS_INIT) {
+			/*
+			 * We have a kernel bounce buffer that has
+			 * already been allocated.
+			 */
+			if (size > vb->size) {
+				/*
+				 * The image size has been changed to
+				 * a larger size since this buffer was
+				 * allocated, so we need to free and
+				 * reallocate it.
+				 */
+				omap34xxcam_vbq_release(vbq, vb);
+				vb->size = size;
+			}
+		} else {
+			/* We need to allocate a new kernel bounce buffer. */
+			vb->size = size;
+		}
+	}
+
+	if (err)
+		return err;
+
+	vb->width = format.fmt.pix.width;
+	vb->height = format.fmt.pix.height;
+	vb->field = field;
+
+	if (vb->state == VIDEOBUF_NEEDS_INIT) {
+		err = videobuf_iolock(vbq, vb, NULL);
+		if (!err) {
+			/* isp_addr will be stored locally inside isp code */
+			err = isp_vbq_prepare(vbq, vb, field);
+		}
+	}
+
+	if (!err)
+		vb->state = VIDEOBUF_PREPARED;
+	else
+		omap34xxcam_vbq_release(vbq, vb);
+
+	return err;
+
+}
+
+/**
+ * omap34xxcam_vbq_queue - V4L2 video ops buf_queue handler
+ * @vbq: ptr. to standard V4L2 video buffer queue structure
+ * @vb: ptr to standard V4L2 video buffer structure
+ *
+ * Maps the video buffer to sgdma and through the isp, sets
+ * the isp buffer done callback and sets the video buffer state
+ * to active.
+ */
+static void omap34xxcam_vbq_queue(struct videobuf_queue *vbq,
+				  struct videobuf_buffer *vb)
+{
+	struct omap34xxcam_fh *fh = vbq->priv_data;
+	struct omap34xxcam_videodev *vdev = fh->vdev;
+	enum videobuf_state state = vb->state;
+	isp_vbq_callback_ptr func_ptr;
+	int err = 0;
+
+	camfh_saved = fh;
+
+	func_ptr = omap34xxcam_update_vbq;
+	vb->state = VIDEOBUF_ACTIVE;
+
+	err = isp_sgdma_queue(videobuf_to_dma(vb),
+				vb, 0, &vdev->cam->dma_notify, func_ptr);
+	if (err) {
+		dev_dbg(vdev->cam->dev, "vbq queue failed\n");
+		vb->state = state;
+	}
+
+}
+
+static struct videobuf_queue_ops omap34xxcam_vbq_ops = {
+	.buf_setup = omap34xxcam_vbq_setup,
+	.buf_prepare = omap34xxcam_vbq_prepare,
+	.buf_queue = omap34xxcam_vbq_queue,
+	.buf_release = omap34xxcam_vbq_release,
+};
+
+/*
+ *
+ * IOCTL interface.
+ *
+ */
+
+/**
+ * vidioc_querycap - V4L2 query capabilities IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @cap: ptr to standard V4L2 capability structure
+ *
+ * Fill in the V4L2 capabliity structure for the camera device
+ */
+static int vidioc_querycap(struct file *file, void *fh,
+			   struct v4l2_capability *cap)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+
+	strlcpy(cap->driver, CAM_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, vdev->vfd->name, sizeof(cap->card));
+	cap->version = OMAP34XXCAM_VERSION;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+	return 0;
+}
+
+/**
+ * vidioc_enum_fmt_cap - V4L2 enumerate format capabilities IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @f: ptr to standard V4L2 format description structure
+ *
+ * Fills in enumerate format capabilities information for sensor (if SOC
+ * sensor attached) or ISP (if raw sensor attached).
+ */
+static int vidioc_enum_fmt_cap(struct file *file, void *fh,
+			       struct v4l2_fmtdesc *f)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, f);
+	else
+		rval = isp_enum_fmt_cap(f);
+
+	return rval;
+}
+
+/**
+ * vidioc_g_fmt_cap - V4L2 get format capabilities IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @f: ptr to standard V4L2 format structure
+ *
+ * Fills in format capabilities for sensor (if SOC sensor attached) or ISP
+ * (if raw sensor attached).
+ */
+static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+
+	mutex_lock(&vdev->mutex);
+	f->fmt.pix = ofh->pix;
+	mutex_unlock(&vdev->mutex);
+
+	return 0;
+}
+
+/**
+ * vidioc_s_fmt_cap - V4L2 set format capabilities IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @f: ptr to standard V4L2 format structure
+ *
+ * Attempts to set input format with the sensor driver (first) and then the
+ * ISP.  Returns the return code from vidioc_g_fmt_cap().
+ */
+static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_pix_format pix_tmp;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		rval = -EBUSY;
+		goto out;
+	}
+
+	pix_tmp.width = f->fmt.pix.width;
+	pix_tmp.height = f->fmt.pix.height;
+	pix_tmp.pixelformat = f->fmt.pix.pixelformat;
+	/* Always negotiate with the sensor first */
+	rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, f);
+	if (rval)
+		goto out;
+
+	/* Negotiate with OMAP3 ISP */
+	rval = isp_s_fmt_cap(pix, &pix_tmp);
+out:
+	mutex_unlock(&vdev->mutex);
+
+	if (!rval) {
+		mutex_lock(&ofh->vbq.vb_lock);
+		*pix = ofh->pix = pix_tmp;
+		mutex_unlock(&ofh->vbq.vb_lock);
+	}
+
+	return rval;
+}
+
+/**
+ * vidioc_try_fmt_cap - V4L2 try format capabilities IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @f: ptr to standard V4L2 format structure
+ *
+ * Checks if the given format is supported by the sensor driver and
+ * by the ISP.
+ */
+static int vidioc_try_fmt_cap(struct file *file, void *fh,
+			      struct v4l2_format *f)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_pix_format pix_tmp;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	pix_tmp.width = f->fmt.pix.width;
+	pix_tmp.height = f->fmt.pix.height;
+	pix_tmp.pixelformat = f->fmt.pix.pixelformat;
+	rval = vidioc_int_try_fmt_cap(vdev->vdev_sensor, f);
+	if (rval)
+		goto out;
+
+	rval = isp_try_fmt_cap(pix, &pix_tmp);
+	*pix = pix_tmp;
+
+out:
+	mutex_unlock(&vdev->mutex);
+	return rval;
+}
+
+/**
+ * vidioc_reqbufs - V4L2 request buffers IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @b: ptr to standard V4L2 request buffers structure
+ *
+ * Attempts to get a buffer from the buffer queue associated with the
+ * fh through the video buffer library API.
+ */
+static int vidioc_reqbufs(struct file *file, void *fh,
+			  struct v4l2_requestbuffers *b)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		mutex_unlock(&vdev->mutex);
+		return -EBUSY;
+	}
+
+	mutex_unlock(&vdev->mutex);
+
+	rval = videobuf_reqbufs(&ofh->vbq, b);
+
+	/*
+	 * Either videobuf_reqbufs failed or the buffers are not
+	 * memory-mapped (which would need special attention).
+	 */
+	if (rval < 0 || b->memory != V4L2_MEMORY_MMAP)
+		goto out;
+
+out:
+	return rval;
+}
+
+/**
+ * vidioc_querybuf - V4L2 query buffer IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @b: ptr to standard V4L2 buffer structure
+ *
+ * Attempts to fill in the v4l2_buffer structure for the buffer queue
+ * associated with the fh through the video buffer library API.
+ */
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct omap34xxcam_fh *ofh = fh;
+
+	return videobuf_querybuf(&ofh->vbq, b);
+}
+
+/**
+ * vidioc_qbuf - V4L2 queue buffer IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @b: ptr to standard V4L2 buffer structure
+ *
+ * Attempts to queue the v4l2_buffer on the buffer queue
+ * associated with the fh through the video buffer library API.
+ */
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct omap34xxcam_fh *ofh = fh;
+
+	return videobuf_qbuf(&ofh->vbq, b);
+}
+
+/**
+ * vidioc_dqbuf - V4L2 dequeue buffer IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @b: ptr to standard V4L2 buffer structure
+ *
+ * Attempts to dequeue the v4l2_buffer from the buffer queue
+ * associated with the fh through the video buffer library API.  If the
+ * buffer is a user space buffer, then this function will also requeue it,
+ * as user does not expect to do this.
+ */
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct omap34xxcam_fh *ofh = fh;
+
+	return videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
+}
+
+/**
+ * vidioc_streamon - V4L2 streamon IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @i: V4L2 buffer type
+ *
+ * Attempts to start streaming by enabling the sensor interface and turning
+ * on video buffer streaming through the video buffer library API.  Upon
+ * success the function returns 0, otherwise an error code is returned.
+ */
+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct omap34xxcam_device *cam = vdev->cam;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		rval = -EBUSY;
+		goto out;
+	}
+
+	rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_RESUME);
+	if (rval) {
+		dev_dbg(vdev->cam->dev, "omap34xxcam_slave_power_set failed\n");
+		goto out;
+	}
+	/* Configure sensor and start streaming */
+	rval = vidioc_int_init(vdev->vdev_sensor);
+	if (rval) {
+		dev_dbg(vdev->cam->dev, "vidioc_int_init failed\n");
+		goto out;
+	}
+
+	cam->dma_notify = 1;
+	isp_sgdma_init();
+	rval = videobuf_streamon(&ofh->vbq);
+	if (!rval)
+		vdev->streaming = file;
+
+out:
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_streamoff - V4L2 streamoff IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @i: V4L2 buffer type
+ *
+ * Attempts to stop streaming by flushing all scheduled work, waiting on
+ * any queued buffers to complete and then stopping the ISP and turning
+ * off video buffer streaming through the video buffer library API.  Upon
+ * success the function returns 0, otherwise an error code is returned.
+ */
+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct videobuf_queue *q = &ofh->vbq;
+	int rval;
+
+	isp_stop();
+	rval = videobuf_streamoff(q);
+	if (!rval) {
+		mutex_lock(&vdev->mutex);
+		vdev->streaming = NULL;
+		mutex_unlock(&vdev->mutex);
+	}
+
+	omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY);
+
+	return rval;
+}
+
+/**
+ * vidioc_enum_input - V4L2 enumerate input IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @inp: V4L2 input type information structure
+ *
+ * Fills in v4l2_input structure.  Returns 0.
+ */
+static int vidioc_enum_input(struct file *file, void *fh,
+			     struct v4l2_input *inp)
+{
+	if (inp->index > 0)
+		return -EINVAL;
+
+	strlcpy(inp->name, "camera", sizeof(inp->name));
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+
+	return 0;
+}
+
+/**
+ * vidioc_g_input - V4L2 get input IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @i: address to hold index of input supported
+ *
+ * Sets index to 0.
+ */
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	*i = 0;
+
+	return 0;
+}
+
+/**
+ * vidioc_s_input - V4L2 set input IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @i: index of input selected
+ *
+ * 0 is only index supported.
+ */
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+	if (i > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * vidioc_queryctrl - V4L2 query control IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 query control ioctl structure
+ *
+ * If the requested control is supported, returns the control information
+ * in the v4l2_queryctrl structure.  Otherwise, returns -EINVAL if the
+ * control is not supported.  If the sensor being used is a "smart sensor",
+ * this request is passed to the sensor driver, otherwise the ISP is
+ * queried and if it does not support the requested control, the request
+ * is forwarded to the "raw" sensor driver to see if it supports it.
+ */
+static int vidioc_queryctrl(struct file *file, void *fh,
+			    struct v4l2_queryctrl *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = vidioc_int_queryctrl(vdev->vdev_sensor, a);
+	} else {
+		rval = isp_queryctrl(a);
+		if (rval) {
+			/* ISP does not support, check sensor */
+			rval = vidioc_int_queryctrl(vdev->vdev_sensor, a);
+		}
+	}
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_g_ctrl - V4L2 get control IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 control structure
+ *
+ * If the sensor being used is a "smart sensor",
+ * this request is passed to the sensor driver, otherwise the ISP is
+ * queried and if it does not support the requested control, the request
+ * is forwarded to the "raw" sensor driver to see if it supports it.
+ * If one of these supports the control, the current value of the control
+ * is returned in the v4l2_control structure.  Otherwise, -EINVAL is
+ * returned if the control is not supported.
+ */
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = vidioc_int_g_ctrl(vdev->vdev_sensor, a);
+	} else {
+		rval = isp_g_ctrl(a);
+		/* If control not supported on ISP, try sensor */
+		if (rval)
+			rval = vidioc_int_g_ctrl(vdev->vdev_sensor, a);
+	}
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_s_ctrl - V4L2 set control IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 control structure
+ *
+ * If the sensor being used is a "smart sensor", this request is passed to
+ * the sensor driver.  Otherwise, the ISP is queried and if it does not
+ * support the requested control, the request is forwarded to the "raw"
+ * sensor driver to see if it supports it.
+ * If one of these supports the control, the current value of the control
+ * is returned in the v4l2_control structure.  Otherwise, -EINVAL is
+ * returned if the control is not supported.
+ */
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = vidioc_int_s_ctrl(vdev->vdev_sensor, a);
+	} else {
+		rval = isp_s_ctrl(a);
+		/* If control not supported on ISP, try sensor */
+		if (rval)
+			rval = vidioc_int_s_ctrl(vdev->vdev_sensor, a);
+	}
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_g_parm - V4L2 get parameters IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 stream parameters structure
+ *
+ * If request is for video capture buffer type, handles request by
+ * forwarding to sensor driver.
+ */
+static int vidioc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	rval = vidioc_int_g_parm(vdev->vdev_sensor, a);
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_s_parm - V4L2 set parameters IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 stream parameters structure
+ *
+ * If request is for video capture buffer type, handles request by
+ * first getting current stream parameters from sensor, then forwarding
+ * request to set new parameters to sensor driver.  It then attempts to
+ * enable the sensor interface with the new parameters.  If this fails, it
+ * reverts back to the previous parameters.
+ */
+static int vidioc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct v4l2_streamparm old_streamparm;
+	int rval;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		rval = -EBUSY;
+		goto out;
+	}
+
+	old_streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	rval = vidioc_int_g_parm(vdev->vdev_sensor, &old_streamparm);
+	if (rval)
+		goto out;
+
+	rval = vidioc_int_s_parm(vdev->vdev_sensor, a);
+	if (rval)
+		goto out;
+
+out:
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_cropcap - V4L2 crop capture IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 crop capture structure
+ *
+ * If using a "smart" sensor, just forwards request to the sensor driver,
+ * otherwise fills in the v4l2_cropcap values locally.
+ */
+static int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct v4l2_cropcap *cropcap = a;
+	int rval;
+
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = vidioc_int_cropcap(vdev->vdev_sensor, a);
+	} else {
+		cropcap->bounds.left = cropcap->bounds.top = 0;
+		cropcap->bounds.width = ofh->pix.width;
+		cropcap->bounds.height = ofh->pix.height;
+		cropcap->defrect = cropcap->bounds;
+		cropcap->pixelaspect.numerator = 1;
+		cropcap->pixelaspect.denominator = 1;
+		rval = 0;
+	}
+	return rval;
+}
+
+/**
+ * vidioc_g_crop - V4L2 get capture crop IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 crop structure
+ *
+ * If using a "smart" sensor, just forwards request to the sensor driver,
+ * otherwise calls the isp functions to fill in current crop values.
+ */
+static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval = 0;
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		rval = vidioc_int_g_crop(vdev->vdev_sensor, a);
+	else
+		rval = isp_g_crop(a);
+
+	return rval;
+}
+
+/**
+ * vidioc_s_crop - V4L2 set capture crop IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 crop structure
+ *
+ * If using a "smart" sensor, just forwards request to the sensor driver,
+ * otherwise calls the isp functions to set the current crop values.
+ */
+static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	struct v4l2_pix_format *pix = &ofh->pix;
+	int rval = 0;
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		rval = vidioc_int_s_crop(vdev->vdev_sensor, a);
+	else
+		rval = isp_s_crop(a, pix);
+
+	return rval;
+}
+
+/*
+ *
+ * File operations.
+ *
+ */
+
+/**
+ * omap34xxcam_poll - file operations poll handler
+ * @file: ptr. to system file structure
+ * @wait: system poll table structure
+ *
+ */
+static unsigned int omap34xxcam_poll(struct file *file,
+				     struct poll_table_struct *wait)
+{
+	struct omap34xxcam_fh *fh = file->private_data;
+	struct omap34xxcam_videodev *vdev = fh->vdev;
+	struct videobuf_buffer *vb;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming != file) {
+		mutex_unlock(&vdev->mutex);
+		return POLLERR;
+	}
+	mutex_unlock(&vdev->mutex);
+
+	mutex_lock(&fh->vbq.vb_lock);
+	if (list_empty(&fh->vbq.stream)) {
+		mutex_unlock(&fh->vbq.vb_lock);
+		return POLLERR;
+	}
+	vb = list_entry(fh->vbq.stream.next, struct videobuf_buffer, stream);
+	mutex_unlock(&fh->vbq.vb_lock);
+
+	poll_wait(file, &vb->done, wait);
+
+	if (vb->state == VIDEOBUF_DONE || vb->state == VIDEOBUF_ERROR)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+/**
+ * omap34xxcam_mmap - file operations mmap handler
+ * @file: ptr. to system file structure
+ * @vma: system virt. mem. area structure
+ *
+ * Maps a virtual memory area via the video buffer API
+ */
+static int omap34xxcam_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct omap34xxcam_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(&fh->vbq, vma);
+}
+
+/**
+ * omap34xxcam_open - file operations open handler
+ * @inode: ptr. to system inode structure
+ * @file: ptr. to system file structure
+ *
+ * Allocates and initializes the per-filehandle data (omap34xxcam_fh),
+ * enables the sensor, opens/initializes the ISP interface and the
+ * video buffer queue.  Note that this function will allow multiple
+ * file handles to be open simultaneously, however only the first
+ * handle opened will initialize the ISP.  It is the application
+ * responsibility to only use one handle for streaming and the others
+ * for control only.
+ * This function returns 0 upon success and -ENODEV upon error.
+ */
+static int omap34xxcam_open(struct inode *inode, struct file *file)
+{
+	struct omap34xxcam_videodev *vdev = NULL;
+	struct omap34xxcam_device *cam = omap34xxcam;
+	struct omap34xxcam_fh *fh;
+	struct v4l2_format format;
+	int i;
+
+	for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
+		if (cam->vdevs[i].vfd
+		    && cam->vdevs[i].vfd->minor == iminor(inode)) {
+			vdev = &cam->vdevs[i];
+			break;
+		}
+	}
+
+	if (!vdev || !vdev->vfd)
+		return -ENODEV;
+
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (fh == NULL)
+		return -ENOMEM;
+
+	mutex_lock(&vdev->mutex);
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		if (vdev->slave[i]
+		    && !try_module_get(vdev->slave[i]->module)) {
+			mutex_unlock(&vdev->mutex);
+			goto out_try_module_get;
+		}
+	}
+
+	if (atomic_inc_return(&vdev->users) == 1) {
+		isp_get();
+		isp_open();
+		if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON)) {
+			mutex_unlock(&vdev->mutex);
+			goto out_try_module_get;
+		}
+		if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY)) {
+			mutex_unlock(&vdev->mutex);
+			goto out_try_module_get;
+		}
+	}
+
+	mutex_unlock(&vdev->mutex);
+	fh->vdev = vdev;
+	mutex_lock(&vdev->mutex);
+
+	/* FIXME: Check that we have sensor now... */
+	if (vdev->vdev_sensor_config.sensor_isp)
+		vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format);
+	else
+		isp_g_fmt_cap(&format);
+
+	mutex_unlock(&vdev->mutex);
+	/* FIXME: how about fh->pix when there are more users? */
+	fh->pix = format.fmt.pix;
+
+	file->private_data = fh;
+
+	spin_lock_init(&fh->vbq_lock);
+
+	videobuf_queue_sg_init(&fh->vbq, &omap34xxcam_vbq_ops, NULL,
+				&fh->vbq_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				V4L2_FIELD_NONE,
+				sizeof(struct videobuf_buffer), fh);
+
+	return 0;
+
+out_try_module_get:
+	for (i--; i >= 0; i--)
+		if (vdev->slave[i])
+			module_put(vdev->slave[i]->module);
+
+	isp_close();
+	isp_put();
+	kfree(fh);
+
+	return -ENODEV;
+}
+
+/**
+ * omap34xxcam_release - file operations release handler
+ * @inode: ptr. to system inode structure
+ * @file: ptr. to system file structure
+ *
+ * Complement of omap34xxcam_open.  This function will flush any scheduled
+ * work, disable the sensor, close the ISP interface, stop the
+ * video buffer queue from streaming and free the per-filehandle data
+ * (omap34xxcam_fh).  Note that because multiple open file handles
+ * are allowed, this function will only close the ISP and disable the
+ * sensor when the last open file handle (by count) is closed.
+ * This function returns 0.
+ */
+static int omap34xxcam_release(struct inode *inode, struct file *file)
+{
+	struct omap34xxcam_fh *fh = file->private_data;
+	struct omap34xxcam_videodev *vdev = fh->vdev;
+	int i;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming == file) {
+		isp_stop();
+		videobuf_streamoff(&fh->vbq);
+		omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY);
+		vdev->streaming = NULL;
+	}
+
+	if (atomic_dec_return(&vdev->users) == 0) {
+		omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF);
+		isp_close();
+		isp_put();
+	}
+	mutex_unlock(&vdev->mutex);
+
+	file->private_data = NULL;
+
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++)
+		if (vdev->slave[i])
+			module_put(vdev->slave[i]->module);
+
+	kfree(fh);
+
+	return 0;
+}
+
+/**
+ * omap34xxcam_handle_private - private IOCTL handler
+ * @inode: ptr. to system inode structure
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @cmd: ioctl cmd value
+ * @arg: ioctl arg value
+ *
+ * If the sensor being used is a "smart sensor", this request is returned to
+ * caller with -EINVAL err code.  Otherwise if the control id is the private
+ * VIDIOC_PRIVATE_ISP_AEWB_REQ to update the analog gain or exposure,
+ * then this request is forwared directly to the sensor to incorporate the
+ * feedback. The request is then passed on to the ISP private IOCTL handler,
+ * isp_handle_private()
+ */
+static int omap34xxcam_handle_private(struct file *file, void *fh,
+							int cmd, void *arg)
+{
+	struct omap34xxcam_fh *ofh = file->private_data;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = -EINVAL;
+	} else {
+		switch (cmd) {
+		default:
+			rval = isp_handle_private(cmd, arg);
+		}
+	}
+
+	mutex_unlock(&vdev->mutex);
+	return rval;
+}
+
+/**
+ * omap34xxcam_unlocked_ioctl - unlocked (unserialized) IOCTL handler
+ * @file: ptr. to system file structure
+ * @cmd: ioctl cmd value
+ * @arg: ioctl arg value
+ *
+ * Unlocked (unserialized) ioctl handler for the camera driver.
+ * Checks if the IOCTL is in the private ioctl range, and if so
+ * calls the local private ioctl handler omap34xxcam_handle_private(),
+ * otherwise it calls the V4L2 provided ioctl handler (video_ioctl2).
+ */
+static long omap34xxcam_unlocked_ioctl(struct file *file, unsigned int cmd,
+							unsigned long arg)
+{
+	return (long)video_ioctl2(file->f_dentry->d_inode, file, cmd, arg);
+}
+
+static struct file_operations omap34xxcam_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.unlocked_ioctl = omap34xxcam_unlocked_ioctl,
+	.poll = omap34xxcam_poll,
+	.mmap = omap34xxcam_mmap,
+	.open = omap34xxcam_open,
+	.release = omap34xxcam_release,
+};
+
+/**
+ * omap34xxcam_device_unregister - V4L2 detach handler
+ * @s: ptr. to standard V4L2 device information structure
+ *
+ * Detach sensor and unregister and release the video device.
+ */
+static void omap34xxcam_device_unregister(struct v4l2_int_device *s)
+{
+	struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
+	struct omap34xxcam_hw_config hwc;
+
+	BUG_ON(vidioc_int_g_priv(s, &hwc) < 0);
+
+	if (vdev->slave[hwc.dev_type]) {
+		vdev->slave[hwc.dev_type] = NULL;
+		vdev->slaves--;
+	}
+
+	if (vdev->slaves == 0 && vdev->vfd) {
+		if (vdev->vfd->minor == -1) {
+			/*
+			 * The device was never registered, so release the
+			 * video_device struct directly.
+			 */
+			video_device_release(vdev->vfd);
+		} else {
+			/*
+			 * The unregister function will release the
+			 * video_device struct as well as
+			 * unregistering it.
+			 */
+			video_unregister_device(vdev->vfd);
+		}
+		vdev->vfd = NULL;
+	}
+
+}
+
+/**
+ * omap34xxcam_device_register - V4L2 attach handler
+ * @s: ptr. to standard V4L2 device information structure
+ *
+ * Allocates and initializes the V4L2 video_device structure, initializes
+ * the sensor, and finally registers the device with V4L2 based on the
+ * video_device structure.
+ *
+ * Returns 0 on success, otherwise an appropriate error code on
+ * failure.
+ */
+static int omap34xxcam_device_register(struct v4l2_int_device *s)
+{
+	struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
+	struct omap34xxcam_device *cam = vdev->cam;
+	struct omap34xxcam_hw_config hwc;
+	struct video_device *vfd;
+	int rval, i;
+
+	/* We need to check rval just once. The place is here. */
+	if (vidioc_int_g_priv(s, &hwc))
+		return -ENODEV;
+
+	dev_info(cam->dev, "vdev index %d, slave index %d\n",
+		 vdev->index, hwc.dev_index);
+
+	if (vdev->index != hwc.dev_index)
+		return -ENODEV;
+
+	if (hwc.dev_type < 0 || hwc.dev_type > OMAP34XXCAM_SLAVE_FLASH)
+		return -EINVAL;
+
+	if (vdev->slave[hwc.dev_type])
+		return -EBUSY;
+
+	mutex_lock(&vdev->mutex);
+	if (atomic_read(&vdev->users)) {
+		dev_info(cam->dev, "we're open (%d), can't register\n",
+			 atomic_read(&vdev->users));
+		mutex_unlock(&vdev->mutex);
+		return -EBUSY;
+	}
+
+	/* Are we the first slave? */
+	if (vdev->slaves == 0) {
+
+		/* initialize the video_device struct */
+		vfd = vdev->vfd = video_device_alloc();
+		if (!vfd) {
+			dev_err(cam->dev,
+				"could not allocate video device struct\n");
+			return -ENOMEM;
+		}
+		vfd->release = video_device_release;
+
+		vfd->dev = cam->dev;
+
+		vfd->type		 = VID_TYPE_CAPTURE;
+		vfd->fops		 = &omap34xxcam_fops;
+		vfd->priv		 = vdev;
+
+		vfd->vidioc_querycap	 = vidioc_querycap;
+		vfd->vidioc_enum_fmt_cap = vidioc_enum_fmt_cap;
+		vfd->vidioc_g_fmt_cap	 = vidioc_g_fmt_cap;
+		vfd->vidioc_s_fmt_cap	 = vidioc_s_fmt_cap;
+		vfd->vidioc_try_fmt_cap	 = vidioc_try_fmt_cap;
+		vfd->vidioc_reqbufs	 = vidioc_reqbufs;
+		vfd->vidioc_querybuf	 = vidioc_querybuf;
+		vfd->vidioc_qbuf	 = vidioc_qbuf;
+		vfd->vidioc_dqbuf	 = vidioc_dqbuf;
+		vfd->vidioc_streamon	 = vidioc_streamon;
+		vfd->vidioc_streamoff	 = vidioc_streamoff;
+		vfd->vidioc_enum_input	 = vidioc_enum_input;
+		vfd->vidioc_g_input	 = vidioc_g_input;
+		vfd->vidioc_s_input	 = vidioc_s_input;
+		vfd->vidioc_queryctrl	 = vidioc_queryctrl;
+		vfd->vidioc_g_ctrl	 = vidioc_g_ctrl;
+		vfd->vidioc_s_ctrl	 = vidioc_s_ctrl;
+		vfd->vidioc_g_parm	 = vidioc_g_parm;
+		vfd->vidioc_s_parm	 = vidioc_s_parm;
+		vfd->vidioc_cropcap	 = vidioc_cropcap;
+		vfd->vidioc_g_crop	 = vidioc_g_crop;
+		vfd->vidioc_s_crop	 = vidioc_s_crop;
+		vfd->vidioc_default	 = omap34xxcam_handle_private;
+
+		if (video_register_device(vfd, VFL_TYPE_GRABBER,
+					  hwc.dev_minor) < 0) {
+			dev_err(cam->dev,
+				"could not register V4L device\n");
+			vfd->minor = -1;
+			rval = -EBUSY;
+			goto err;
+		}
+		dev_info(cam->dev,
+			 "registered device video%d\n", vfd->minor);
+	} else {
+		vfd = vdev->vfd;
+	}
+
+	vdev->slaves++;
+	vdev->slave[hwc.dev_type] = s;
+	vdev->slave_config[hwc.dev_type] = hwc;
+	dev_info(cam->dev, "registering device %s (%d) to video%d\n",
+		 s->name, hwc.dev_type, vfd->minor);
+
+	isp_get();
+	rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON);
+	omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF);
+	isp_put();
+
+	if (rval)
+		goto err;
+	strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name));
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		strlcat(vfd->name, "/", sizeof(vfd->name));
+		if (!vdev->slave[i])
+			continue;
+		strlcat(vfd->name, vdev->slave[i]->name, sizeof(vfd->name));
+	}
+
+	mutex_unlock(&vdev->mutex);
+
+	dev_info(cam->dev, "video%d is now %s\n", vfd->minor, vfd->name);
+	return 0;
+
+err:
+	if (s == vdev->slave[hwc.dev_type]) {
+		vdev->slave[hwc.dev_type] = NULL;
+		vdev->slaves--;
+	}
+
+	mutex_unlock(&vdev->mutex);
+	omap34xxcam_device_unregister(s);
+
+	return rval;
+}
+
+static struct v4l2_int_master omap34xxcam_master = {
+	.attach = omap34xxcam_device_register,
+	.detach = omap34xxcam_device_unregister,
+};
+
+/*
+ *
+ * Driver Suspend/Resume
+ *
+ */
+
+#ifdef CONFIG_PM
+/**
+ * omap34xxcam_suspend - platform driver PM suspend handler
+ * @pdev: ptr. to platform level device information structure
+ * @state: power state
+ *
+ * If applicable, stop capture and disable sensor.
+ *
+ * Returns 0 always
+ */
+static int omap34xxcam_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct omap34xxcam_videodev *vdev = platform_get_drvdata(pdev);
+
+	if (atomic_read(&vdev->users) == 0)
+		return 0;
+
+	if (vdev->streaming) {
+		isp_stop();
+		omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF);
+	}
+
+	return 0;
+}
+
+/**
+ * omap34xxcam_resume - platform driver PM resume handler
+ * @pdev: ptr. to platform level device information structure
+ *
+ * If applicable, resume capture and enable sensor.
+ *
+ * Returns 0 always
+ */
+static int omap34xxcam_resume(struct platform_device *pdev)
+{
+	struct omap34xxcam_videodev *vdev = platform_get_drvdata(pdev);
+
+	if (atomic_read(&vdev->users) == 0)
+		return 0;
+
+	if (vdev->streaming) {
+		omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON);
+		isp_start();
+	}
+
+	return 0;
+}
+#endif
+
+/*
+ *
+ * Driver initialisation and deinitialisation.
+ *
+ */
+
+/**
+ * omap34xxcam_probe - platform driver probe handler
+ * @pdev: ptr. to platform level device information structure
+ *
+ * Allocates and initializes camera device information structure
+ * (omap34xxcam_device), maps the device registers and gets the
+ * device IRQ.  Registers the device as a V4L2 client.
+ *
+ * Returns 0 on success or -ENODEV on failure.
+ */
+static int omap34xxcam_probe(struct platform_device *pdev)
+{
+	struct omap34xxcam_device *cam;
+	struct resource *mem;
+	struct isp_sysc isp_sysconfig;
+	int irq;
+	int i;
+
+	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
+	if (!cam) {
+		dev_err(&pdev->dev, "could not allocate memory\n");
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, cam);
+
+	cam->dev = &pdev->dev;
+	/*
+	 * Impose a lower limit on the amount of memory allocated for
+	 * capture. We require at least enough memory to double-buffer
+	 * QVGA (300KB).
+	 */
+	if (capture_mem < 320 * 240 * 2 * 2)
+		capture_mem = 320 * 240 * 2 * 2;
+
+	/* request the mem region for the camera registers */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(cam->dev, "no mem resource?\n");
+		goto err;
+	}
+
+	if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
+				pdev->name)) {
+		dev_err(cam->dev,
+			"cannot reserve camera register I/O region\n");
+		goto err;
+
+	}
+	cam->mmio_base_phys = mem->start;
+	cam->mmio_size = (mem->end - mem->start) + 1;
+
+	/* map the region */
+	cam->mmio_base = (unsigned long)
+			ioremap_nocache(cam->mmio_base_phys, cam->mmio_size);
+	if (!cam->mmio_base) {
+		dev_err(cam->dev, "cannot map camera register I/O region\n");
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(cam->dev, "no irq for camera?\n");
+		goto err;
+	}
+
+	isp_get();
+	isp_sysconfig.reset = 0;
+	isp_sysconfig.idle_mode = 1;
+	isp_power_settings(isp_sysconfig);
+
+	for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
+		struct omap34xxcam_videodev *vdev = &cam->vdevs[i];
+		struct v4l2_int_device *m = &vdev->master;
+
+		m->module       = THIS_MODULE;
+		strlcpy(m->name, CAM_NAME, sizeof(m->name));
+		m->type         = v4l2_int_type_master;
+		m->u.master     = &omap34xxcam_master;
+		m->priv		= vdev;
+
+		if (v4l2_int_device_register(m))
+			goto err;
+
+		mutex_init(&vdev->mutex);
+		vdev->index             = i;
+		vdev->cam               = cam;
+		vdev->capture_mem       = capture_mem;
+	}
+
+	omap34xxcam = cam;
+	isp_put();
+
+	return 0;
+
+err:
+	omap34xxcam_remove(pdev);
+	isp_put();
+	return -ENODEV;
+}
+
+/**
+ * omap34xxcam_remove - platform driver remove handler
+ * @pdev: ptr. to platform level device information structure
+ *
+ * Unregister device with V4L2, unmap camera registers, and
+ * free camera device information structure (omap34xxcam_device).
+ *
+ * Returns 0 always.
+ */
+static int omap34xxcam_remove(struct platform_device *pdev)
+{
+	struct omap34xxcam_device *cam = platform_get_drvdata(pdev);
+	int i;
+
+	if (!cam)
+		return 0;
+
+	omap34xxcam = NULL;
+
+	isp_put();
+
+	for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
+		if (cam->vdevs[i].cam == NULL)
+			continue;
+
+		v4l2_int_device_unregister(&cam->vdevs[i].master);
+		cam->vdevs[i].cam = NULL;
+	}
+
+	if (cam->mmio_base) {
+		iounmap((void *)cam->mmio_base);
+		cam->mmio_base = 0;
+	}
+
+	if (cam->mmio_base_phys) {
+		release_mem_region(cam->mmio_base_phys, cam->mmio_size);
+		cam->mmio_base_phys = 0;
+	}
+
+	kfree(cam);
+
+	return 0;
+}
+
+static struct platform_driver omap34xxcam_driver = {
+	.probe = omap34xxcam_probe,
+	.remove = omap34xxcam_remove,
+#ifdef CONFIG_PM
+	.suspend = omap34xxcam_suspend,
+	.resume = omap34xxcam_resume,
+#endif
+	.driver = {
+		   .name = CAM_NAME,
+		   },
+};
+
+/*
+ *
+ * Module initialisation and deinitialisation
+ *
+ */
+
+/**
+ * omap34xxcam_init - module_init function
+ *
+ * Calls platfrom driver to register probe, remove,
+ * suspend and resume functions.
+ *
+ */
+static int __init omap34xxcam_init(void)
+{
+	return platform_driver_register(&omap34xxcam_driver);
+}
+
+/**
+ * omap34xxcam_cleanup - module_exit function
+ *
+ * Calls platfrom driver to unregister probe, remove,
+ * suspend and resume functions.
+ *
+ */
+static void __exit omap34xxcam_cleanup(void)
+{
+	platform_driver_unregister(&omap34xxcam_driver);
+}
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("OMAP34xx Video for Linux camera driver");
+MODULE_LICENSE("GPL");
+
+late_initcall(omap34xxcam_init);
+module_exit(omap34xxcam_cleanup);
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/omap34xxcam.h	2008-06-29 16:57:48.000000000 -0500
@@ -0,0 +1,189 @@
+/*
+ * drivers/media/video/omap34xxcam.h
+ *
+ * Video-for-Linux (Version 2) Camera capture driver for OMAP34xx ISP.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ * Copyright (C) 2008 Nokia.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@xxxxxx>
+ * 	Mohit Jalori <mjalori@xxxxxx>
+ * 	Sakari Ailus <sakari.ailus@xxxxxxxxx>
+ * 	Tuukka Toivonen <tuukka.o.toivonen@xxxxxxxxx>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef OMAP34XXCAM_H
+#define OMAP34XXCAM_H
+
+#include <media/v4l2-int-device.h>
+#include "isp/isp.h"
+
+#define CAM_NAME "omap34xxcam"
+
+#define OMAP_ISP_AF     	(1 << 4)
+#define OMAP_ISP_HIST   	(1 << 5)
+#define OMAP34XXCAM_XCLK_NONE	-1
+#define OMAP34XXCAM_XCLK_A	0
+#define OMAP34XXCAM_XCLK_B	1
+
+#define OMAP34XXCAM_SLAVE_SENSOR	0
+#define OMAP34XXCAM_SLAVE_LENS		1
+#define OMAP34XXCAM_SLAVE_FLASH		2 /* This is the last slave! */
+
+#define OMAP34XXCAM_VIDEODEVS		4
+
+struct omap34xxcam_device;
+struct omap34xxcam_videodev;
+
+struct omap34xxcam_sensor_config {
+	int xclk;
+	int sensor_isp;
+};
+
+struct omap34xxcam_lens_config {
+};
+
+struct omap34xxcam_flash_config {
+};
+
+/**
+ * struct omap34xxcam_hw_config - struct for vidioc_int_g_priv ioctl
+ * @xclk: OMAP34XXCAM_XCLK_A or OMAP34XXCAM_XCLK_B
+ * @sensor_isp: Is sensor smart/SOC or raw
+ * @s_pix_sparm: Access function to set pix and sparm.
+ * Pix will override sparm
+ */
+struct omap34xxcam_hw_config {
+	int dev_index; /* Index in omap34xxcam_sensors */
+	int dev_minor; /* Video device minor number */
+	int dev_type; /* OMAP34XXCAM_SLAVE_* */
+	union {
+		struct omap34xxcam_sensor_config sensor;
+		struct omap34xxcam_lens_config lens;
+		struct omap34xxcam_flash_config flash;
+	} u;
+};
+
+/**
+ * struct omap34xxcam_videodev - per /dev/video* structure
+ * @mutex: serialises access to this structure
+ * @cam: pointer to cam hw structure
+ * @master: we are v4l2_int_device master
+ * @sensor: sensor device
+ * @lens: lens device
+ * @flash: flash device
+ * @slaves: how many slaves we have at the moment
+ * @vfd: our video device
+ * @capture_mem: maximum kernel-allocated capture memory
+ * @if_u: sensor interface stuff
+ * @index: index of this structure in cam->vdevs
+ * @users: how many users we have
+ * @sensor_config: ISP-speicific sensor configuration
+ * @lens_config: ISP-speicific lens configuration
+ * @flash_config: ISP-speicific flash configuration
+ * @streaming: streaming file handle, if streaming is enabled
+ */
+struct omap34xxcam_videodev {
+	struct mutex mutex;
+
+	struct omap34xxcam_device *cam;
+	struct v4l2_int_device master;
+
+#define vdev_sensor slave[OMAP34XXCAM_SLAVE_SENSOR]
+#define vdev_lens slave[OMAP34XXCAM_SLAVE_LENS]
+#define vdev_flash slave[OMAP34XXCAM_SLAVE_FLASH]
+	struct v4l2_int_device *slave[OMAP34XXCAM_SLAVE_FLASH + 1];
+
+	/* number of slaves attached */
+	int slaves;
+
+	/*** video device parameters ***/
+	struct video_device *vfd;
+	int capture_mem;
+
+	/*** general driver state information ***/
+	/*
+	 * Sensor interface parameters: interface type, CC_CTRL
+	 * register value and interface specific data.
+	 */
+	u32 xclk;
+	/* index to omap34xxcam_videodevs of this structure */
+	int index;
+	atomic_t users;
+
+#define vdev_sensor_config slave_config[OMAP34XXCAM_SLAVE_SENSOR].u.sensor
+#define vdev_lens_config slave_config[OMAP34XXCAM_SLAVE_LENS].u.lens
+#define vdev_flash_config slave_config[OMAP34XXCAM_SLAVE_FLASH].u.flash
+	struct omap34xxcam_hw_config slave_config[OMAP34XXCAM_SLAVE_FLASH + 1];
+
+	/*** capture data ***/
+	/* file handle, if streaming is on */
+	struct file *streaming;
+};
+
+/**
+ * struct omap34xxcam_device - per-device data structure
+ * @mutex: mutex serialises access to this structure
+ * @sgdma_in_queue: Number or sgdma requests in scatter-gather queue,
+ * protected by the lock above.
+ * @sgdma: ISP sgdma subsystem information structure
+ * @dma_notify: DMA notify flag
+ * @irq: irq number platform HW resource
+ * @mmio_base: register map memory base (platform HW resource)
+ * @mmio_base_phys: register map memory base physical address
+ * @mmio_size: register map memory size
+ * @dev: device structure
+ * @vdevs: /dev/video specific structures
+ * @fck: camera module fck clock information
+ * @ick: camera module ick clock information
+ */
+struct omap34xxcam_device {
+	struct mutex mutex;
+	int sgdma_in_queue;
+	struct isp_sgdma sgdma;
+	int dma_notify;
+
+	/*** platform HW resource ***/
+	unsigned int irq;
+	unsigned long mmio_base;
+	unsigned long mmio_base_phys;
+	unsigned long mmio_size;
+
+	/*** interfaces and device ***/
+	struct device *dev;
+	struct omap34xxcam_videodev vdevs[OMAP34XXCAM_VIDEODEVS];
+
+	/*** camera module clocks ***/
+	struct clk *fck;
+	struct clk *ick;
+	bool sensor_if_enabled;
+};
+
+/**
+ * struct omap34xxcam_fh - per-filehandle data structure
+ * @vbq_lock: spinlock for the videobuf queue
+ * @vbq: V4L2 video buffer queue structure
+ * @pix: V4L2 pixel format structure (serialise pix by vbq->lock)
+ * @field_count: field counter for videobuf_buffer
+ * @vdev: our /dev/video specific structure
+ */
+struct omap34xxcam_fh {
+	spinlock_t vbq_lock;
+	struct videobuf_queue vbq;
+	struct v4l2_pix_format pix;
+	atomic_t field_count;
+	/* accessing cam here doesn't need serialisation: it's constant */
+	struct omap34xxcam_videodev *vdev;
+};
+
+#endif /* ifndef OMAP34XXCAM_H */
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/isp/Makefile	2008-06-29 17:44:40.000000000 -0500
@@ -0,0 +1,4 @@
+# Makefile for OMAP3 ISP driver
+
+obj-$(CONFIG_VIDEO_OMAP3) += \
+	isp.o ispccdc.o ispmmu.o \
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/isp/Kconfig	2008-06-29 17:07:00.000000000 -0500
@@ -0,0 +1 @@
+# Kconfig for OMAP3 ISP driver
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/isp/isp.c	2008-06-29 17:44:57.000000000 -0500
@@ -0,0 +1,1802 @@
+/*
+ * drivers/media/video/isp/isp.c
+ *
+ * Driver Library for ISP Control module in TI's OMAP3430 Camera ISP
+ * ISP interface and IRQ related APIs are defined here.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ * Copyright (C) 2008 Nokia.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@xxxxxx>
+ * 	Mohit Jalori <mjalori@xxxxxx>
+ * 	Sakari Ailus <sakari.ailus@xxxxxxxxx>
+ * 	Tuukka Toivonen <tuukka.o.toivonen@xxxxxxxxx>
+ *	Toni Leinonen <toni.leinonen@xxxxxxxxx>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <asm/irq.h>
+#include <linux/bitops.h>
+#include <linux/scatterlist.h>
+#include <asm/mach-types.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/io.h>
+#include <linux/device.h>
+#include <linux/videodev2.h>
+
+#include "isp.h"
+#include "ispmmu.h"
+#include "ispreg.h"
+#include "ispccdc.h"
+
+/* List of image formats supported via OMAP ISP */
+const static struct v4l2_fmtdesc isp_formats[] = {
+	{
+		.description = "UYVY, packed",
+		.pixelformat = V4L2_PIX_FMT_UYVY,
+	},
+	{
+		.description = "YUYV (YUV 4:2:2), packed",
+		.pixelformat = V4L2_PIX_FMT_YUYV,
+	},
+	{
+		.description = "Bayer10 (GrR/BGb)",
+		.pixelformat = V4L2_PIX_FMT_SGRBG10,
+	},
+};
+
+/* ISP Crop capabilities */
+static struct v4l2_rect ispcroprect;
+static struct v4l2_rect cur_rect;
+
+/**
+ * struct vcontrol - Video control structure.
+ * @qc: V4L2 Query control structure.
+ * @current_value: Current value of the control.
+ */
+static struct vcontrol {
+	struct v4l2_queryctrl qc;
+	int current_value;
+} video_control[] = { };
+
+/**
+ * struct ispirq - Structure for containing callbacks to be called in ISP ISR.
+ * @isp_callbk: Array which stores callback functions, indexed by the type of
+ *              callback (8 possible types).
+ * @isp_callbk_arg1: Pointer to array containing pointers to the first argument
+ *                   to be passed to the requested callback function.
+ * @isp_callbk_arg2: Pointer to array containing pointers to the second
+ *                   argument to be passed to the requested callback function.
+ *
+ * This structure is used to contain all the callback functions related for
+ * each callback type (CBK_CCDC_VD0, CBK_CCDC_VD1, CBK_PREV_DONE,
+ * CBK_RESZ_DONE, CBK_MMU_ERR, CBK_H3A_AWB_DONE, CBK_HIST_DONE, CBK_HS_VS,
+ * CBK_LSC_ISR).
+ */
+static struct ispirq {
+	isp_callback_t isp_callbk[9];
+	isp_vbq_callback_ptr isp_callbk_arg1[9];
+	void *isp_callbk_arg2[9];
+} ispirq_obj;
+
+/**
+ * struct isp - Structure for storing ISP Control module information
+ * @lock: Spinlock to sync between isr and processes.
+ * @isp_temp_buf_lock: Temporary spinlock for buffer control.
+ * @isp_mutex: Semaphore used to get access to the ISP.
+ * @if_status: Type of interface used in ISP.
+ * @interfacetype: (Not used).
+ * @ref_count: Reference counter.
+ * @cam_ick: Pointer to ISP Interface clock.
+ * @cam_fck: Pointer to ISP Functional clock.
+ *
+ * This structure is used to store the OMAP ISP Control Information.
+ */
+static struct isp {
+	spinlock_t lock;
+	spinlock_t isp_temp_buf_lock;
+	struct mutex isp_mutex;
+	u8 if_status;
+	u8 interfacetype;
+	int ref_count;
+	struct clk *cam_ick;
+	struct clk *cam_mclk;
+} isp_obj;
+
+struct isp_sgdma ispsg;
+
+/**
+ * struct ispmodule - Structure for storing ISP sub-module information.
+ * @isp_pipeline: Bit mask for submodules enabled within the ISP.
+ * @isp_temp_state: State of current buffers.
+ * @applyCrop: Flag to do a crop operation when video buffer queue ISR is done
+ * @pix: Structure containing the format and layout of the output image.
+ * @ccdc_input_width: ISP CCDC module input image width.
+ * @ccdc_input_height: ISP CCDC module input image height.
+ * @ccdc_output_width: ISP CCDC module output image width.
+ * @ccdc_output_height: ISP CCDC module output image height.
+ * @preview_input_width: ISP Preview module input image width.
+ * @preview_input_height: ISP Preview module input image height.
+ * @preview_output_width: ISP Preview module output image width.
+ * @preview_output_height: ISP Preview module output image height.
+ * @resizer_input_width: ISP Resizer module input image width.
+ * @resizer_input_height: ISP Resizer module input image height.
+ * @resizer_output_width: ISP Resizer module output image width.
+ * @resizer_output_height: ISP Resizer module output image height.
+ */
+struct ispmodule {
+	unsigned int isp_pipeline;
+	int isp_temp_state;
+	int applyCrop;
+	struct v4l2_pix_format pix;
+	unsigned int ccdc_input_width;
+	unsigned int ccdc_input_height;
+	unsigned int ccdc_output_width;
+	unsigned int ccdc_output_height;
+	unsigned int preview_input_width;
+	unsigned int preview_input_height;
+	unsigned int preview_output_width;
+	unsigned int preview_output_height;
+	unsigned int resizer_input_width;
+	unsigned int resizer_input_height;
+	unsigned int resizer_output_width;
+	unsigned int resizer_output_height;
+};
+
+static struct ispmodule ispmodule_obj = {
+	.isp_pipeline = OMAP_ISP_CCDC,
+	.isp_temp_state = ISP_BUF_INIT,
+	.applyCrop = 0,
+	.pix = {
+		.width = ISP_OUTPUT_WIDTH_DEFAULT,
+		.height = ISP_OUTPUT_HEIGHT_DEFAULT,
+		.pixelformat = V4L2_PIX_FMT_UYVY,
+		.field = V4L2_FIELD_NONE,
+		.bytesperline = ISP_OUTPUT_WIDTH_DEFAULT * ISP_BYTES_PER_PIXEL,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0,
+	},
+};
+
+/* Structure for saving/restoring ISP module registers */
+static struct isp_reg isp_reg_list[] = {
+	{ISP_SYSCONFIG, 0},
+	{ISP_IRQ0ENABLE, 0},
+	{ISP_IRQ1ENABLE, 0},
+	{ISP_TCTRL_GRESET_LENGTH, 0},
+	{ISP_TCTRL_PSTRB_REPLAY, 0},
+	{ISP_CTRL, 0},
+	{ISP_TCTRL_CTRL, 0},
+	{ISP_TCTRL_FRAME, 0},
+	{ISP_TCTRL_PSTRB_DELAY, 0},
+	{ISP_TCTRL_STRB_DELAY, 0},
+	{ISP_TCTRL_SHUT_DELAY, 0},
+	{ISP_TCTRL_PSTRB_LENGTH, 0},
+	{ISP_TCTRL_STRB_LENGTH, 0},
+	{ISP_TCTRL_SHUT_LENGTH, 0},
+	{ISP_CBUFF_SYSCONFIG, 0},
+	{ISP_CBUFF_IRQENABLE, 0},
+	{ISP_CBUFF0_CTRL, 0},
+	{ISP_CBUFF1_CTRL, 0},
+	{ISP_CBUFF0_START, 0},
+	{ISP_CBUFF1_START, 0},
+	{ISP_CBUFF0_END, 0},
+	{ISP_CBUFF1_END, 0},
+	{ISP_CBUFF0_WINDOWSIZE, 0},
+	{ISP_CBUFF1_WINDOWSIZE, 0},
+	{ISP_CBUFF0_THRESHOLD, 0},
+	{ISP_CBUFF1_THRESHOLD, 0},
+	{ISP_TOK_TERM, 0}
+};
+
+/*
+ *
+ * V4L2 Handling
+ *
+ */
+
+/**
+ * find_vctrl - Returns the index of the ctrl array of the requested ctrl ID.
+ * @id: Requested control ID.
+ *
+ * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
+ * domain.
+ **/
+static int find_vctrl(int id)
+{
+	int i;
+
+	if (id < V4L2_CID_BASE)
+		return -EDOM;
+
+	for (i = (ARRAY_SIZE(video_control) - 1); i >= 0; i--)
+		if (video_control[i].qc.id == id)
+			break;
+
+	if (i < 0)
+		i = -EINVAL;
+
+	return i;
+}
+
+/**
+ * isp_open - Reserve ISP submodules for operation
+ **/
+void isp_open(void)
+{
+	ispccdc_request();
+	return;
+}
+EXPORT_SYMBOL(isp_open);
+
+/**
+ * isp_close - Free ISP submodules
+ **/
+void isp_close(void)
+{
+	ispccdc_free();
+	return;
+}
+EXPORT_SYMBOL(isp_close);
+
+/* Flag to check first time of isp_get */
+static int off_mode;
+
+/**
+ * isp_set_sgdma_callback - Set Scatter-Gather DMA Callback.
+ * @sgdma_state: Pointer to structure with the SGDMA state for each videobuffer
+ * @func_ptr: Callback function pointer for SG-DMA management
+ **/
+static int isp_set_sgdma_callback(struct isp_sgdma_state *sgdma_state,
+						isp_vbq_callback_ptr func_ptr)
+{
+	if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC) {
+		isp_set_callback(CBK_CCDC_VD0, sgdma_state->callback, func_ptr,
+							sgdma_state->arg);
+		isp_set_callback(CBK_CCDC_VD1, sgdma_state->callback, func_ptr,
+							sgdma_state->arg);
+		isp_set_callback(CBK_LSC_ISR, NULL, NULL, NULL);
+	}
+
+	isp_set_callback(CBK_HS_VS, sgdma_state->callback, func_ptr,
+							sgdma_state->arg);
+	return 0;
+}
+
+/**
+ * isp_set_callback - Sets the callback for the ISP module done events.
+ * @type: Type of the event for which callback is requested.
+ * @callback: Method to be called as callback in the ISR context.
+ * @arg1: First argument to be passed when callback is called in ISR.
+ * @arg2: Second argument to be passed when callback is called in ISR.
+ *
+ * This function sets a callback function for a done event in the ISP
+ * module, and enables the corresponding interrupt.
+ **/
+int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
+						isp_vbq_callback_ptr arg1,
+						void *arg2)
+{
+	unsigned long irqflags = 0;
+
+	if (callback == NULL) {
+		DPRINTK_ISPCTRL("ISP_ERR : Null Callback\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&isp_obj.lock, irqflags);
+	ispirq_obj.isp_callbk[type] = callback;
+	ispirq_obj.isp_callbk_arg1[type] = arg1;
+	ispirq_obj.isp_callbk_arg2[type] = arg2;
+	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+
+	switch (type) {
+	case CBK_HS_VS:
+		omap_writel(IRQ0ENABLE_HS_VS_IRQ, ISP_IRQ0STATUS);
+		omap_writel(omap_readl(ISP_IRQ0ENABLE) | IRQ0ENABLE_HS_VS_IRQ,
+							ISP_IRQ0ENABLE);
+		break;
+	case CBK_MMU_ERR:
+		omap_writel(omap_readl(ISP_IRQ0ENABLE) |
+					IRQ0ENABLE_MMU_ERR_IRQ,
+					ISP_IRQ0ENABLE);
+
+		omap_writel(omap_readl(ISPMMU_IRQENABLE) |
+					IRQENABLE_MULTIHITFAULT |
+					IRQENABLE_TWFAULT |
+					IRQENABLE_EMUMISS |
+					IRQENABLE_TRANSLNFAULT |
+					IRQENABLE_TLBMISS,
+					ISPMMU_IRQENABLE);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_set_callback);
+
+/**
+ * isp_unset_callback - Clears the callback for the ISP module done events.
+ * @type: Type of the event for which callback to be cleared.
+ *
+ * This function clears a callback function for a done event in the ISP
+ * module, and disables the corresponding interrupt.
+ **/
+int isp_unset_callback(enum isp_callback_type type)
+{
+	unsigned long irqflags = 0;
+
+	spin_lock_irqsave(&isp_obj.lock, irqflags);
+	ispirq_obj.isp_callbk[type] = NULL;
+	ispirq_obj.isp_callbk_arg1[type] = NULL;
+	ispirq_obj.isp_callbk_arg2[type] = NULL;
+	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+
+	switch (type) {
+	case CBK_CCDC_VD0:
+		omap_writel((omap_readl(ISP_IRQ0ENABLE)) &
+						~IRQ0ENABLE_CCDC_VD0_IRQ,
+						ISP_IRQ0ENABLE);
+		break;
+	case CBK_CCDC_VD1:
+		omap_writel((omap_readl(ISP_IRQ0ENABLE)) &
+						~IRQ0ENABLE_CCDC_VD1_IRQ,
+						ISP_IRQ0ENABLE);
+		break;
+	case CBK_MMU_ERR:
+		omap_writel(omap_readl(ISPMMU_IRQENABLE) &
+						~(IRQENABLE_MULTIHITFAULT |
+						IRQENABLE_TWFAULT |
+						IRQENABLE_EMUMISS |
+						IRQENABLE_TRANSLNFAULT |
+						IRQENABLE_TLBMISS),
+						ISPMMU_IRQENABLE);
+		break;
+	case CBK_HS_VS:
+		omap_writel((omap_readl(ISP_IRQ0ENABLE)) &
+						~IRQ0ENABLE_HS_VS_IRQ,
+						ISP_IRQ0ENABLE);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_unset_callback);
+
+/**
+ * isp_request_interface - Requests an ISP interface type (parallel or serial).
+ * @if_t: Type of requested ISP interface (parallel or serial).
+ *
+ * This function requests for allocation of an ISP interface type.
+ **/
+int isp_request_interface(enum isp_interface_type if_t)
+{
+	if (isp_obj.if_status & if_t) {
+		DPRINTK_ISPCTRL("ISP_ERR : Requested Interface already \
+			allocated\n");
+		goto err_ebusy;
+	}
+	if ((isp_obj.if_status == (ISP_PARLL | ISP_CSIA))
+			|| isp_obj.if_status == (ISP_CSIA | ISP_CSIB)) {
+		DPRINTK_ISPCTRL("ISP_ERR : No Free interface now\n");
+		goto err_ebusy;
+	}
+
+	if (((isp_obj.if_status == ISP_PARLL) && (if_t == ISP_CSIA)) ||
+				((isp_obj.if_status == ISP_CSIA) &&
+				(if_t == ISP_PARLL)) ||
+				((isp_obj.if_status == ISP_CSIA) &&
+				(if_t == ISP_CSIB)) ||
+				((isp_obj.if_status == ISP_CSIB) &&
+				(if_t == ISP_CSIA)) ||
+				(isp_obj.if_status == 0)) {
+		isp_obj.if_status |= if_t;
+		return 0;
+	} else {
+		DPRINTK_ISPCTRL("ISP_ERR : Invalid Combination Serial- \
+			Parallel interface\n");
+		return -EINVAL;
+	}
+
+err_ebusy:
+	return -EBUSY;
+}
+EXPORT_SYMBOL(isp_request_interface);
+
+/**
+ * isp_free_interface - Frees an ISP interface type (parallel or serial).
+ * @if_t: Type of ISP interface to be freed (parallel or serial).
+ *
+ * This function frees the allocation of an ISP interface type.
+ **/
+int isp_free_interface(enum isp_interface_type if_t)
+{
+	isp_obj.if_status &= ~if_t;
+	return 0;
+}
+EXPORT_SYMBOL(isp_free_interface);
+
+/**
+ * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
+ * @xclk: Desired frequency of the clock in Hz.
+ * @xclksel: XCLK to configure (0 = A, 1 = B).
+ *
+ * Configures the specified MCLK divisor in the ISP timing control register
+ * (TCTRL_CTRL) to generate the desired xclk clock value.
+ *
+ * Divisor = CM_CAM_MCLK_HZ / xclk
+ *
+ * Returns the final frequency that is actually being generated
+ **/
+u32 isp_set_xclk(u32 xclk, u8 xclksel)
+{
+	u32 divisor;
+	u32 currentxclk;
+
+	if (xclk >= CM_CAM_MCLK_HZ) {
+		divisor = ISPTCTRL_CTRL_DIV_BYPASS;
+		currentxclk = CM_CAM_MCLK_HZ;
+	} else if (xclk >= 2) {
+		divisor = CM_CAM_MCLK_HZ / xclk;
+		if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
+			divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
+		currentxclk = CM_CAM_MCLK_HZ / divisor;
+	} else {
+		divisor = xclk;
+		currentxclk = 0;
+	}
+
+	switch (xclksel) {
+	case 0:
+		omap_writel((omap_readl(ISP_TCTRL_CTRL) &
+				~ISPTCTRL_CTRL_DIVA_MASK) |
+				(divisor << ISPTCTRL_CTRL_DIVA_SHIFT),
+				ISP_TCTRL_CTRL);
+		DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclka set to %d Hz\n",
+								currentxclk);
+		break;
+	case 1:
+		omap_writel((omap_readl(ISP_TCTRL_CTRL) &
+				~ISPTCTRL_CTRL_DIVB_MASK) |
+				(divisor << ISPTCTRL_CTRL_DIVB_SHIFT),
+				ISP_TCTRL_CTRL);
+		DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclkb set to %d Hz\n",
+								currentxclk);
+		break;
+	default:
+		DPRINTK_ISPCTRL("ISP_ERR: isp_set_xclk(): Invalid requested "
+						"xclk. Must be 0 (A) or 1 (B)."
+						"\n");
+		return -EINVAL;
+	}
+
+	return currentxclk;
+}
+EXPORT_SYMBOL(isp_set_xclk);
+
+/**
+ * isp_get_xclk - Returns the frequency in Hz of the desired cam_xclk.
+ * @xclksel: XCLK to retrieve (0 = A, 1 = B).
+ *
+ * This function returns the External Clock (XCLKA or XCLKB) value generated
+ * by the ISP.
+ **/
+u32 isp_get_xclk(u8 xclksel)
+{
+	u32 xclkdiv;
+	u32 xclk;
+
+	switch (xclksel) {
+	case 0:
+		xclkdiv = omap_readl(ISP_TCTRL_CTRL) & ISPTCTRL_CTRL_DIVA_MASK;
+		xclkdiv = xclkdiv >> ISPTCTRL_CTRL_DIVA_SHIFT;
+		break;
+	case 1:
+		xclkdiv = omap_readl(ISP_TCTRL_CTRL) & ISPTCTRL_CTRL_DIVB_MASK;
+		xclkdiv = xclkdiv >> ISPTCTRL_CTRL_DIVB_SHIFT;
+		break;
+	default:
+		DPRINTK_ISPCTRL("ISP_ERR: isp_get_xclk(): Invalid requested "
+						"xclk. Must be 0 (A) or 1 (B)."
+						"\n");
+		return -EINVAL;
+	}
+
+	switch (xclkdiv) {
+	case 0:
+	case 1:
+		xclk = 0;
+		break;
+	case 0x1f:
+		xclk = CM_CAM_MCLK_HZ;
+		break;
+	default:
+		xclk = CM_CAM_MCLK_HZ / xclkdiv;
+		break;
+	}
+
+	return xclk;
+}
+EXPORT_SYMBOL(isp_get_xclk);
+
+/**
+ * isp_power_settings - Sysconfig settings, for Power Management.
+ * @isp_sysconfig: Structure containing the power settings for ISP to configure
+ *
+ * Sets the power settings for the ISP, and SBL bus.
+ **/
+void isp_power_settings(struct isp_sysc isp_sysconfig)
+{
+	if (isp_sysconfig.idle_mode) {
+		omap_writel(ISP_SYSCONFIG_AUTOIDLE |
+				(ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY <<
+				ISP_SYSCONFIG_MIDLEMODE_SHIFT),
+				ISP_SYSCONFIG);
+
+		omap_writel(ISPMMU_AUTOIDLE | (ISPMMU_SIDLEMODE_SMARTIDLE <<
+						ISPMMU_SIDLEMODE_SHIFT),
+						ISPMMU_SYSCONFIG);
+		if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) {
+			omap_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					ISP_CSIA_SYSCONFIG);
+			omap_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					ISP_CSIB_SYSCONFIG);
+		}
+		omap_writel(ISPCTRL_SBL_AUTOIDLE, ISP_CTRL);
+
+	} else {
+		omap_writel(ISP_SYSCONFIG_AUTOIDLE |
+				(ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY <<
+				ISP_SYSCONFIG_MIDLEMODE_SHIFT),
+				ISP_SYSCONFIG);
+
+		omap_writel(ISPMMU_AUTOIDLE |
+			(ISPMMU_SIDLEMODE_NOIDLE << ISPMMU_SIDLEMODE_SHIFT),
+							ISPMMU_SYSCONFIG);
+		if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) {
+			omap_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_FORCESTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					ISP_CSIA_SYSCONFIG);
+
+			omap_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_FORCESTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					ISP_CSIB_SYSCONFIG);
+		}
+
+		omap_writel(ISPCTRL_SBL_AUTOIDLE, ISP_CTRL);
+	}
+}
+EXPORT_SYMBOL(isp_power_settings);
+
+#define BIT_SET(var, shift, mask, val)		\
+	do {					\
+		var = (var & ~(mask << shift))	\
+			| (val << shift);	\
+	} while (0)
+
+static int isp_init_csi(struct isp_interface_config *config)
+{
+	u32 i = 0, val, reg;
+	int format;
+
+	switch (config->u.csi.format) {
+	case V4L2_PIX_FMT_SGRBG10:
+		format = 0x16;		/* RAW10+VP */
+		break;
+	case V4L2_PIX_FMT_SGRBG10DPCM8:
+		format = 0x12;		/* RAW8+DPCM10+VP */
+		break;
+	default:
+		printk(KERN_ERR "isp_init_csi: bad csi format\n");
+		return -EINVAL;
+	}
+
+	/* Reset the CSI and wait for reset to complete */
+	omap_writel(omap_readl(ISPCSI1_SYSCONFIG) | BIT(1), ISPCSI1_SYSCONFIG);
+	while (!(omap_readl(ISPCSI1_SYSSTATUS) & BIT(0))) {
+		udelay(10);
+		if (i++ > 10)
+			break;
+	}
+	if (!(omap_readl(ISPCSI1_SYSSTATUS) & BIT(0))) {
+		printk(KERN_WARNING
+			"omap3_isp: timeout waiting for csi reset\n");
+	}
+
+	/* CONTROL_CSIRXFE */
+	omap_writel(
+		/* CSIb receiver data/clock or data/strobe mode */
+		(config->u.csi.signalling << 10)
+		| BIT(12)	/* Enable differential transceiver */
+		| BIT(13)	/* Disable reset */
+#ifdef TERM_RESISTOR
+		| BIT(8)	/* Enable internal CSIb resistor (no effect) */
+#endif
+/*		| BIT(7) */	/* Strobe/clock inversion (no effect) */
+	, CONTROL_CSIRXFE);
+
+#ifdef TERM_RESISTOR
+	/* Set CONTROL_CSI */
+	val = omap_readl(CONTROL_CSI);
+	val &= ~(0x1F<<16);
+	val |= BIT(31) | (TERM_RESISTOR<<16);
+	omap_writel(val, CONTROL_CSI);
+#endif
+
+	/* ISPCSI1_CTRL */
+	val = omap_readl(ISPCSI1_CTRL);
+	val &= ~BIT(11);	/* Enable VP only off ->
+				extract embedded data to interconnect */
+	BIT_SET(val, 8, 0x3, config->u.csi.vpclk);	/* Video port clock */
+/*	val |= BIT(3);	*/	/* Wait for FEC before disabling interface */
+	val |= BIT(2);		/* I/O cell output is parallel
+				(no effect, but errata says should be enabled
+				for class 1/2) */
+	val |= BIT(12);		/* VP clock polarity to falling edge
+				(needed or bad picture!) */
+
+	/* Data/strobe physical layer */
+	BIT_SET(val, 1, 1, config->u.csi.signalling);
+	BIT_SET(val, 10, 1, config->u.csi.strobe_clock_inv);
+	val |= BIT(4);		/* Magic bit to enable CSI1 and strobe mode */
+	omap_writel(val, ISPCSI1_CTRL);
+
+	/* ISPCSI1_LCx_CTRL logical channel #0 */
+	reg = ISPCSI1_LCx_CTRL(0);	/* reg = ISPCSI1_CTRL1; */
+	val = omap_readl(reg);
+	/* Format = RAW10+VP or RAW8+DPCM10+VP*/
+	BIT_SET(val, 3, 0x1f, format);
+	/* Enable setting of frame regions of interest */
+	BIT_SET(val, 1, 1, 1);
+	BIT_SET(val, 2, 1, config->u.csi.crc);
+	omap_writel(val, reg);
+
+	/* ISPCSI1_DAT_START for logical channel #0 */
+	reg = ISPCSI1_LCx_DAT_START(0);		/* reg = ISPCSI1_DAT_START; */
+	val = omap_readl(reg);
+	BIT_SET(val, 16, 0xfff, config->u.csi.data_start);
+	omap_writel(val, reg);
+
+	/* ISPCSI1_DAT_SIZE for logical channel #0 */
+	reg = ISPCSI1_LCx_DAT_SIZE(0);		/* reg = ISPCSI1_DAT_SIZE; */
+	val = omap_readl(reg);
+	BIT_SET(val, 16, 0xfff, config->u.csi.data_size);
+	omap_writel(val, reg);
+
+	/* Clear status bits for logical channel #0 */
+	omap_writel(0xFFF & ~BIT(6), ISPCSI1_LC01_IRQSTATUS);
+
+	/* Enable CSI1 */
+	val = omap_readl(ISPCSI1_CTRL);
+	val |=  BIT(0) | BIT(4);
+	omap_writel(val, ISPCSI1_CTRL);
+
+	if (!(omap_readl(ISPCSI1_CTRL) & BIT(4))) {
+		printk(KERN_WARNING "OMAP3 CSI1 bus not available\n");
+		if (config->u.csi.signalling)	/* Strobe mode requires CSI1 */
+			return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * isp_configure_interface - Configures ISP Control I/F related parameters.
+ * @config: Pointer to structure containing the desired configuration for the
+ * 	ISP.
+ *
+ * Configures ISP control register (ISP_CTRL) with the values specified inside
+ * the config structure. Controls:
+ * - Selection of parallel or serial input to the preview hardware.
+ * - Data lane shifter.
+ * - Pixel clock polarity.
+ * - 8 to 16-bit bridge at the input of CCDC module.
+ * - HS or VS synchronization signal detection
+ **/
+int isp_configure_interface(struct isp_interface_config *config)
+{
+	u32 ispctrl_val = omap_readl(ISP_CTRL);
+	u32 ispccdc_vdint_val;
+	int r;
+
+	ispctrl_val &= ISPCTRL_SHIFT_MASK;
+	ispctrl_val |= (config->dataline_shift << ISPCTRL_SHIFT_SHIFT);
+	ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
+
+	ispctrl_val &= (ISPCTRL_PAR_SER_CLK_SEL_MASK);
+	switch (config->ccdc_par_ser) {
+	case ISP_PARLL:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
+		ispctrl_val |= (config->u.par.par_clk_pol
+						<< ISPCTRL_PAR_CLK_POL_SHIFT);
+		ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
+		ispctrl_val |= (config->u.par.par_bridge
+						<< ISPCTRL_PAR_BRIDGE_SHIFT);
+		break;
+	case ISP_CSIB:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
+		r = isp_init_csi(config);
+		if (r)
+			return r;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ispctrl_val &= ~(ISPCTRL_SYNC_DETECT_VSRISE);
+	ispctrl_val |= (config->hsvs_syncdetect);
+
+	omap_writel(ispctrl_val, ISP_CTRL);
+
+	ispccdc_vdint_val = omap_readl(ISPCCDC_VDINT);
+	ispccdc_vdint_val &= ~(ISPCCDC_VDINT_0_MASK << ISPCCDC_VDINT_0_SHIFT);
+	ispccdc_vdint_val &= ~(ISPCCDC_VDINT_1_MASK << ISPCCDC_VDINT_1_SHIFT);
+	omap_writel((config->vdint0_timing << ISPCCDC_VDINT_0_SHIFT) |
+						(config->vdint1_timing <<
+						ISPCCDC_VDINT_1_SHIFT),
+						ISPCCDC_VDINT);
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_configure_interface);
+
+/**
+ * isp_CCDC_VD01_enable - Enables VD0 and VD1 IRQs.
+ *
+ * Sets VD0 and VD1 bits in IRQ0STATUS to reset the flag, and sets them in
+ * IRQ0ENABLE to enable the corresponding IRQs.
+ **/
+void isp_CCDC_VD01_enable(void)
+{
+	omap_writel(IRQ0STATUS_CCDC_VD0_IRQ | IRQ0STATUS_CCDC_VD1_IRQ,
+							ISP_IRQ0STATUS);
+	omap_writel(omap_readl(ISP_IRQ0ENABLE) | IRQ0ENABLE_CCDC_VD0_IRQ |
+						IRQ0ENABLE_CCDC_VD1_IRQ,
+						ISP_IRQ0ENABLE);
+}
+
+/**
+ * isp_CCDC_VD01_disable - Disables VD0 and VD1 IRQs.
+ *
+ * Clears VD0 and VD1 bits in IRQ0ENABLE register.
+ **/
+void isp_CCDC_VD01_disable(void)
+{
+	omap_writel(omap_readl(ISP_IRQ0ENABLE) & ~(IRQ0ENABLE_CCDC_VD0_IRQ |
+						IRQ0ENABLE_CCDC_VD1_IRQ),
+						ISP_IRQ0ENABLE);
+}
+
+/**
+ * omap34xx_isp_isr - Interrupt Service Routine for Camera ISP module.
+ * @irq: Not used currently.
+ * @ispirq_disp: Pointer to the object that is passed while request_irq is
+ *               called. This is the ispirq_obj object containing info on the
+ *               callback.
+ *
+ * Handles the corresponding callback if plugged in.
+ *
+ * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
+ * IRQ wasn't handled.
+ **/
+static irqreturn_t omap34xx_isp_isr(int irq, void *ispirq_disp)
+{
+	struct ispirq *irqdis = (struct ispirq *)ispirq_disp;
+	u32 irqstatus = 0;
+	unsigned long irqflags = 0;
+	u8 is_irqhandled = 0;
+
+	irqstatus = omap_readl(ISP_IRQ0STATUS);
+
+	spin_lock_irqsave(&isp_obj.lock, irqflags);
+
+	if ((irqstatus & MMU_ERR) == MMU_ERR) {
+		if (irqdis->isp_callbk[CBK_MMU_ERR])
+			irqdis->isp_callbk[CBK_MMU_ERR](irqstatus,
+				irqdis->isp_callbk_arg1[CBK_MMU_ERR],
+				irqdis->isp_callbk_arg2[CBK_MMU_ERR]);
+		is_irqhandled = 1;
+		goto out;
+	}
+
+	if ((irqstatus & CCDC_VD1) == CCDC_VD1) {
+		if (irqdis->isp_callbk[CBK_CCDC_VD1])
+				irqdis->isp_callbk[CBK_CCDC_VD1](CCDC_VD1,
+				irqdis->isp_callbk_arg1[CBK_CCDC_VD1],
+				irqdis->isp_callbk_arg2[CBK_CCDC_VD1]);
+		is_irqhandled = 1;
+	}
+
+	if ((irqstatus & CCDC_VD0) == CCDC_VD0) {
+		if (irqdis->isp_callbk[CBK_CCDC_VD0])
+			irqdis->isp_callbk[CBK_CCDC_VD0](CCDC_VD0,
+				irqdis->isp_callbk_arg1[CBK_CCDC_VD0],
+				irqdis->isp_callbk_arg2[CBK_CCDC_VD0]);
+		is_irqhandled = 1;
+	}
+
+	if ((irqstatus & HS_VS) == HS_VS) {
+		if (irqdis->isp_callbk[CBK_HS_VS])
+			irqdis->isp_callbk[CBK_HS_VS](HS_VS,
+				irqdis->isp_callbk_arg1[CBK_HS_VS],
+				irqdis->isp_callbk_arg2[CBK_HS_VS]);
+		is_irqhandled = 1;
+	}
+
+	if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
+		u32 ispcsi1_irqstatus;
+
+		ispcsi1_irqstatus = omap_readl(ISPCSI1_LC01_IRQSTATUS);
+		DPRINTK_ISPCTRL("%x\n", ispcsi1_irqstatus);
+	}
+
+out:
+	omap_writel(irqstatus, ISP_IRQ0STATUS);
+	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+
+	if (is_irqhandled)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+/* Device name, needed for resource tracking layer */
+struct device_driver camera_drv = {
+	.name = "camera"
+};
+
+struct device camera_dev = {
+	.driver = &camera_drv,
+};
+
+/**
+ * isp_set_pipeline - Set bit mask for submodules enabled within the ISP.
+ * @soc_type: Sensor to use: 1 - Smart sensor, 0 - Raw sensor.
+ *
+ * Sets Previewer and Resizer in the bit mask only if its a Raw sensor.
+ **/
+void isp_set_pipeline(int soc_type)
+{
+	ispmodule_obj.isp_pipeline |= OMAP_ISP_CCDC;
+
+	if (!soc_type)
+		ispmodule_obj.isp_pipeline |= (OMAP_ISP_PREVIEW |
+							OMAP_ISP_RESIZER);
+
+	return;
+}
+
+/**
+ * omapisp_unset_callback - Unsets all the callbacks associated with ISP module
+ **/
+void omapisp_unset_callback()
+{
+	isp_unset_callback(CBK_HS_VS);
+
+	if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC) {
+		isp_unset_callback(CBK_CCDC_VD0);
+		isp_unset_callback(CBK_CCDC_VD1);
+		isp_unset_callback(CBK_LSC_ISR);
+	}
+	omap_writel(omap_readl(ISP_IRQ0STATUS) | ISP_INT_CLR, ISP_IRQ0STATUS);
+}
+
+/**
+ * isp_start - Starts ISP submodule
+ *
+ * Start the needed isp components assuming these components
+ * are configured correctly.
+ **/
+void isp_start(void)
+{
+	return;
+}
+
+/**
+ * isp_stop - Stops isp submodules
+ **/
+void isp_stop()
+{
+	int timeout;
+
+	spin_lock(&isp_obj.isp_temp_buf_lock);
+	ispmodule_obj.isp_temp_state = ISP_FREE_RUNNING;
+	spin_unlock(&isp_obj.isp_temp_buf_lock);
+	omapisp_unset_callback();
+
+	if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC) {
+		ispccdc_enable(0);
+		timeout = 0;
+		while (ispccdc_busy() && (timeout < 20)) {
+			timeout++;
+			mdelay(10);
+		}
+	}
+	if (ispccdc_busy()) {
+		isp_save_ctx();
+		omap_writel(omap_readl(ISP_SYSCONFIG) |
+			ISP_SYSCONFIG_SOFTRESET, ISP_SYSCONFIG);
+		timeout = 0;
+		while ((!(omap_readl(ISP_SYSSTATUS) & 0x1)) && timeout < 20) {
+			timeout++;
+			mdelay(1);
+		}
+	isp_restore_ctx();
+	}
+}
+
+/**
+ * isp_set_buf - Sets output address for submodules.
+ * @sgdma_state: Pointer to structure with the SGDMA state for each videobuffer
+ **/
+void isp_set_buf(struct isp_sgdma_state *sgdma_state)
+{
+	if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC)
+		ispccdc_set_outaddr(sgdma_state->isp_addr);
+
+}
+
+/**
+ * isp_calc_pipeline - Sets pipeline depending of input and output pixel format
+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
+ **/
+void isp_calc_pipeline(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output)
+{
+	ispmodule_obj.isp_pipeline = OMAP_ISP_CCDC;
+	if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10) &&
+		(pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10)) {
+		ispmodule_obj.isp_pipeline |= (OMAP_ISP_PREVIEW |
+							OMAP_ISP_RESIZER);
+		ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP);
+	} else {
+		if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10)
+			ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_MEM);
+		else
+			ispccdc_config_datapath(CCDC_YUV_SYNC,
+							CCDC_OTHERS_MEM);
+	}
+	return;
+}
+
+/**
+ * isp_config_pipeline - Configures the image size and ycpos for ISP submodules
+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
+ *
+ * The configuration of ycpos depends on the output pixel format for both the
+ * Preview and Resizer submodules.
+ **/
+void isp_config_pipeline(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output)
+{
+	ispccdc_config_size(ispmodule_obj.ccdc_input_width,
+			ispmodule_obj.ccdc_input_height,
+			ispmodule_obj.ccdc_output_width,
+			ispmodule_obj.ccdc_output_height);
+
+	return;
+}
+
+/**
+ * isp_vbq_done - Callback for interrupt completion
+ * @status: IRQ0STATUS register value. Passed by the ISR, or the caller.
+ * @arg1: Pointer to callback function for SG-DMA management.
+ * @arg2: Pointer to videobuffer structure managed by ISP.
+ **/
+void isp_vbq_done(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
+{
+	struct videobuf_buffer *vb = (struct videobuf_buffer *) arg2;
+	int notify = 0;
+	int rval = 0;
+	unsigned long flags;
+
+	switch (status) {
+	case CCDC_VD0:
+		ispccdc_config_shadow_registers();
+		if ((ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) ||
+			(ispmodule_obj.isp_pipeline & OMAP_ISP_PREVIEW))
+			return;
+		else {
+			spin_lock(&isp_obj.isp_temp_buf_lock);
+			if (ispmodule_obj.isp_temp_state != ISP_BUF_INIT) {
+				spin_unlock(&isp_obj.isp_temp_buf_lock);
+				return;
+
+			} else {
+				spin_unlock(&isp_obj.isp_temp_buf_lock);
+				break;
+			}
+		}
+		break;
+	case CCDC_VD1:
+		if ((ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) ||
+			(ispmodule_obj.isp_pipeline & OMAP_ISP_PREVIEW))
+			return;
+		spin_lock(&isp_obj.isp_temp_buf_lock);
+		if (ispmodule_obj.isp_temp_state == ISP_BUF_INIT) {
+			spin_unlock(&isp_obj.isp_temp_buf_lock);
+			ispccdc_enable(0);
+			return;
+		}
+		spin_unlock(&isp_obj.isp_temp_buf_lock);
+		return;
+		break;
+	case HS_VS:
+		spin_lock(&isp_obj.isp_temp_buf_lock);
+		if (ispmodule_obj.isp_temp_state == ISP_BUF_TRAN) {
+			isp_CCDC_VD01_enable();
+			ispmodule_obj.isp_temp_state = ISP_BUF_INIT;
+		}
+		spin_unlock(&isp_obj.isp_temp_buf_lock);
+		return;
+	default:
+		break;
+	}
+
+	spin_lock_irqsave(&ispsg.lock, flags);
+	ispsg.free_sgdma++;
+	if (ispsg.free_sgdma > NUM_SG_DMA)
+		ispsg.free_sgdma = NUM_SG_DMA;
+	spin_unlock_irqrestore(&ispsg.lock, flags);
+
+	rval = arg1(vb);
+
+	if (rval)
+		isp_sgdma_process(&ispsg, 1, &notify, arg1);
+
+	return;
+}
+
+/**
+ * isp_sgdma_init - Initializes Scatter Gather DMA status and operations.
+ **/
+void isp_sgdma_init()
+{
+	int sg;
+
+	ispsg.free_sgdma = NUM_SG_DMA;
+	ispsg.next_sgdma = 0;
+	for (sg = 0; sg < NUM_SG_DMA; sg++) {
+		ispsg.sg_state[sg].status = 0;
+		ispsg.sg_state[sg].callback = NULL;
+		ispsg.sg_state[sg].arg = NULL;
+	}
+}
+
+/**
+ * isp_sgdma_process - Sets operations and config for specified SG DMA
+ * @sgdma: SG-DMA function to work on.
+ * @irq: Flag to specify if an IRQ is associated with the DMA completion.
+ * @dma_notify: Pointer to flag that says when the ISP has to be started.
+ * @func_ptr: Callback function pointer for SG-DMA setup.
+ **/
+void isp_sgdma_process(struct isp_sgdma *sgdma, int irq, int *dma_notify,
+						isp_vbq_callback_ptr func_ptr)
+{
+	struct isp_sgdma_state *sgdma_state;
+	unsigned long flags;
+	spin_lock_irqsave(&sgdma->lock, flags);
+
+	if (NUM_SG_DMA > sgdma->free_sgdma) {
+		sgdma_state = sgdma->sg_state +
+			(sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA;
+		if (!irq) {
+			if (*dma_notify) {
+				isp_set_sgdma_callback(sgdma_state, func_ptr);
+				isp_set_buf(sgdma_state);
+				ispccdc_enable(1);
+				isp_start();
+				*dma_notify = 0;
+				ispmodule_obj.isp_temp_state = ISP_BUF_TRAN;
+			} else {
+				if (ispmodule_obj.isp_temp_state ==
+							ISP_FREE_RUNNING) {
+					isp_set_sgdma_callback(sgdma_state,
+								func_ptr);
+					isp_set_buf(sgdma_state);
+					ispccdc_enable(1);
+					ispmodule_obj.isp_temp_state =
+								ISP_BUF_TRAN;
+				}
+			}
+		} else {
+			isp_set_sgdma_callback(sgdma_state, func_ptr);
+			isp_set_buf(sgdma_state);
+			ispccdc_enable(1);
+			ispmodule_obj.isp_temp_state = ISP_BUF_INIT;
+
+			if (*dma_notify) {
+				isp_start();
+				*dma_notify = 0;
+			}
+		}
+	} else {
+		spin_lock(&isp_obj.isp_temp_buf_lock);
+		isp_CCDC_VD01_disable();
+		ispmodule_obj.isp_temp_state = ISP_FREE_RUNNING;
+		spin_unlock(&isp_obj.isp_temp_buf_lock);
+	}
+	spin_unlock_irqrestore(&sgdma->lock, flags);
+	return;
+}
+
+/**
+ * isp_sgdma_queue - Queues a Scatter-Gather DMA videobuffer.
+ * @vdma: Pointer to structure containing the desired DMA video buffer
+ *        transfer parameters.
+ * @vb: Pointer to structure containing the target videobuffer.
+ * @irq: Flag to specify if an IRQ is associated with the DMA completion.
+ * @dma_notify: Pointer to flag that says when the ISP has to be started.
+ * @func_ptr: Callback function pointer for SG-DMA setup.
+ *
+ * Returns 0 if successful, -EINVAL if invalid SG linked list setup, or -EBUSY
+ * if the ISP SG-DMA is not free.
+ **/
+int isp_sgdma_queue(struct videobuf_dmabuf *vdma, struct videobuf_buffer *vb,
+						int irq, int *dma_notify,
+						isp_vbq_callback_ptr func_ptr)
+{
+	unsigned long flags;
+	struct isp_sgdma_state *sg_state;
+	const struct scatterlist *sglist = vdma->sglist;
+	int sglen = vdma->sglen;
+
+	if ((sglen < 0) || ((sglen > 0) & !sglist))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ispsg.lock, flags);
+
+	if (!ispsg.free_sgdma) {
+		spin_unlock_irqrestore(&ispsg.lock, flags);
+		return -EBUSY;
+	}
+
+	sg_state = ispsg.sg_state + ispsg.next_sgdma;
+	sg_state->isp_addr = ispsg.isp_addr_capture[vb->i];
+	sg_state->status = 0;
+	sg_state->callback = isp_vbq_done;
+	sg_state->arg = vb;
+
+	ispsg.next_sgdma = (ispsg.next_sgdma + 1) % NUM_SG_DMA;
+	ispsg.free_sgdma--;
+
+	spin_unlock_irqrestore(&ispsg.lock, flags);
+
+	isp_sgdma_process(&ispsg, irq, dma_notify, func_ptr);
+
+	return 0;
+}
+
+/**
+ * isp_vbq_prepare - Videobuffer queue prepare.
+ * @vbq: Pointer to videobuf_queue structure.
+ * @vb: Pointer to videobuf_buffer structure.
+ * @field: Requested Field order for the videobuffer.
+ *
+ * Returns 0 if successful, or -EIO if the ispmmu was unable to map a
+ * scatter-gather linked list data space.
+ **/
+int isp_vbq_prepare(struct videobuf_queue *vbq, struct videobuf_buffer *vb,
+							enum v4l2_field field)
+{
+	unsigned int isp_addr;
+	struct videobuf_dmabuf	*vdma;
+
+	int err = 0;
+
+	vdma = videobuf_to_dma(vb);
+
+	isp_addr = ispmmu_map_sg(vdma->sglist, vdma->sglen);
+
+	if (!isp_addr)
+		err = -EIO;
+	else
+		ispsg.isp_addr_capture[vb->i] = isp_addr;
+
+	return err;
+}
+
+/**
+ * isp_vbq_release - Videobuffer queue release.
+ * @vbq: Pointer to videobuf_queue structure.
+ * @vb: Pointer to videobuf_buffer structure.
+ **/
+void isp_vbq_release(struct videobuf_queue *vbq, struct videobuf_buffer *vb)
+{
+	ispmmu_unmap(ispsg.isp_addr_capture[vb->i]);
+	ispsg.isp_addr_capture[vb->i] = (dma_addr_t) NULL;
+	return;
+}
+
+/**
+ * isp_queryctrl - Query V4L2 control from existing controls in ISP.
+ * @a: Pointer to v4l2_queryctrl structure. It only needs the id field filled.
+ *
+ * Returns 0 if successful, or -EINVAL if not found in ISP.
+ **/
+int isp_queryctrl(struct v4l2_queryctrl *a)
+{
+	int i;
+
+	i = find_vctrl(a->id);
+	if (i == -EINVAL)
+		a->flags = V4L2_CTRL_FLAG_DISABLED;
+
+	if (i < 0)
+		return -EINVAL;
+
+	*a = video_control[i].qc;
+	return 0;
+}
+
+/**
+ * isp_g_ctrl - Gets value of the desired V4L2 control.
+ * @a: V4L2 control to read actual value from.
+ *
+ * Return 0 if successful, or -EINVAL if chosen control is not found.
+ **/
+int isp_g_ctrl(struct v4l2_control *a)
+{
+	int rval = 0;
+
+	switch (a->id) {
+	default:
+		rval = -EINVAL;
+		break;
+	}
+
+	return rval;
+}
+
+/**
+ * isp_s_ctrl - Sets value of the desired V4L2 control.
+ * @a: V4L2 control to read actual value from.
+ *
+ * Return 0 if successful, -EINVAL if chosen control is not found or value
+ * is out of bounds, -EFAULT if copy_from_user or copy_to_user operation fails
+ * from camera abstraction layer related controls or the transfered user space
+ * pointer via the value field is not set properly.
+ **/
+int isp_s_ctrl(struct v4l2_control *a)
+{
+	int rval = 0;
+
+	switch (a->id) {
+	default:
+		rval = -EINVAL;
+		break;
+	}
+
+	return rval;
+}
+
+/**
+ * isp_handle_private - Handle all private ioctls for isp module.
+ * @cmd: ioctl cmd value
+ * @arg: ioctl arg value
+ *
+ * Return 0 if successful, -EINVAL if chosen cmd value is not handled or value
+ * is out of bounds, -EFAULT if ioctl arg value is not valid.
+ * Function simply routes the input ioctl cmd id to the appropriate handler in
+ * the isp module.
+ **/
+int isp_handle_private(int cmd, void *arg)
+{
+	int rval = 0;
+
+	switch (cmd) {
+	default:
+		rval = -EINVAL;
+		break;
+	}
+
+	return rval;
+}
+
+/**
+ * isp_enum_fmt_cap - Gets more information of chosen format index and type
+ * @f: Pointer to structure containing index and type of format to read from.
+ *
+ * Returns 0 if successful, or -EINVAL if format index or format type is
+ * invalid.
+ **/
+int isp_enum_fmt_cap(struct v4l2_fmtdesc *f)
+{
+	int index = f->index;
+	enum v4l2_buf_type type = f->type;
+	int rval = -EINVAL;
+
+	if (index >= NUM_ISP_CAPTURE_FORMATS)
+		goto err;
+
+	memset(f, 0, sizeof(*f));
+	f->index = index;
+	f->type = type;
+
+	switch (f->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		rval = 0;
+		break;
+	default:
+		goto err;
+	}
+
+	f->flags = isp_formats[index].flags;
+	strncpy(f->description, isp_formats[index].description,
+						sizeof(f->description));
+	f->pixelformat = isp_formats[index].pixelformat;
+err:
+	return rval;
+}
+EXPORT_SYMBOL(isp_enum_fmt_cap);
+
+/**
+ * isp_g_fmt_cap - Gets current output image format.
+ * @f: Pointer to V4L2 format structure to be filled with current output format
+ **/
+void isp_g_fmt_cap(struct v4l2_format *f)
+{
+	f->fmt.pix = ispmodule_obj.pix;
+	return;
+}
+
+/**
+ * isp_s_fmt_cap - Sets I/O formats and crop and configures pipeline in ISP
+ * @f: Pointer to V4L2 format structure to be filled with current output format
+ *
+ * Returns 0 if successful, or return value of either isp_try_size or
+ * isp_try_fmt if there is an error.
+ **/
+int isp_s_fmt_cap(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output)
+{
+	int crop_scaling_w, crop_scaling_h = 0;
+	int rval = 0;
+
+	isp_calc_pipeline(pix_input, pix_output);
+	rval = isp_try_size(pix_input, pix_output);
+
+	if (rval)
+		goto out;
+
+	rval = isp_try_fmt(pix_input, pix_output);
+	if (rval)
+		goto out;
+
+	if (ispcroprect.width != pix_output->width) {
+		crop_scaling_w = 1;
+		ispcroprect.left = 0;
+		ispcroprect.width = pix_output->width;
+	}
+
+	if (ispcroprect.height != pix_output->height) {
+		crop_scaling_h = 1;
+		ispcroprect.top = 0;
+		ispcroprect.height = pix_output->height;
+	}
+
+	isp_config_pipeline(pix_input, pix_output);
+
+	if (crop_scaling_h || crop_scaling_w)
+		isp_config_crop(pix_output);
+
+out:
+	return rval;
+}
+EXPORT_SYMBOL(isp_s_fmt_cap);
+
+/**
+ * isp_config_crop - Configures crop parameters in isp resizer.
+ * @croppix: Pointer to V4L2 pixel format structure containing crop parameters
+ **/
+void isp_config_crop(struct v4l2_pix_format *croppix)
+{
+	u8 crop_scaling_w;
+	u8 crop_scaling_h;
+	struct v4l2_pix_format *pix = croppix;
+
+	crop_scaling_w = (ispmodule_obj.preview_output_width * 10) /
+								pix->width;
+	crop_scaling_h = (ispmodule_obj.preview_output_height * 10) /
+								pix->height;
+
+	cur_rect.left = (ispcroprect.left * crop_scaling_w) / 10;
+	cur_rect.top = (ispcroprect.top * crop_scaling_h) / 10;
+	cur_rect.width = (ispcroprect.width * crop_scaling_w) / 10;
+	cur_rect.height = (ispcroprect.height * crop_scaling_h) / 10;
+
+	return;
+}
+
+/**
+ * isp_g_crop - Gets crop rectangle size and position.
+ * @a: Pointer to V4L2 crop structure to be filled.
+ *
+ * Always returns 0.
+ **/
+int isp_g_crop(struct v4l2_crop *a)
+{
+	struct v4l2_crop *crop = a;
+
+	crop->c = ispcroprect;
+	return 0;
+}
+
+/**
+ * isp_s_crop - Sets crop rectangle size and position and queues crop operation
+ * @a: Pointer to V4L2 crop structure with desired parameters.
+ * @pix: Pointer to V4L2 pixel format structure with desired parameters.
+ *
+ * Returns 0 if successful, or -EINVAL if crop parameters are out of bounds.
+ **/
+int isp_s_crop(struct v4l2_crop *a, struct v4l2_pix_format *pix)
+{
+	struct v4l2_crop *crop = a;
+	int rval = 0;
+
+	if ((crop->c.left + crop->c.width) > pix->width) {
+		rval = -EINVAL;
+		goto out;
+	}
+
+	if ((crop->c.top + crop->c.height) > pix->height) {
+		rval = -EINVAL;
+		goto out;
+	}
+
+	ispcroprect.left = crop->c.left;
+	ispcroprect.top = crop->c.top;
+	ispcroprect.width = crop->c.width;
+	ispcroprect.height = crop->c.height;
+
+	isp_config_crop(pix);
+
+	ispmodule_obj.applyCrop = 1;
+out:
+	return rval;
+}
+
+/**
+ * isp_try_fmt_cap - Tries desired input/output image formats
+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
+ *
+ * Returns 0 if successful, or return value of either isp_try_size or
+ * isp_try_fmt if there is an error.
+ **/
+int isp_try_fmt_cap(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output)
+{
+	int rval = 0;
+
+	isp_calc_pipeline(pix_input, pix_output);
+	rval = isp_try_size(pix_input, pix_output);
+
+	if (rval)
+		goto out;
+
+	rval = isp_try_fmt(pix_input, pix_output);
+
+	if (rval)
+		goto out;
+
+out:
+	return rval;
+}
+EXPORT_SYMBOL(isp_try_fmt_cap);
+
+/**
+ * isp_try_size - Tries size configuration for I/O images of each ISP submodule
+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
+ *
+ * Returns 0 if successful, or return value of ispccdc_try_size,
+ * isppreview_try_size, or ispresizer_try_size (depending on the pipeline
+ * configuration) if there is an error.
+ **/
+int isp_try_size(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output)
+{
+	int rval = 0;
+	ispmodule_obj.ccdc_input_width = pix_input->width;
+	ispmodule_obj.ccdc_input_height = pix_input->height;
+	ispmodule_obj.resizer_output_width = pix_output->width;
+	ispmodule_obj.resizer_output_height = pix_output->height;
+
+	if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC) {
+		rval = ispccdc_try_size(ispmodule_obj.ccdc_input_width,
+					ispmodule_obj.ccdc_input_height,
+					&ispmodule_obj.ccdc_output_width,
+					&ispmodule_obj.ccdc_output_height);
+		pix_output->width = ispmodule_obj.ccdc_output_width;
+		pix_output->height = ispmodule_obj.ccdc_output_height;
+	}
+
+	return rval;
+}
+EXPORT_SYMBOL(isp_try_size);
+
+/**
+ * isp_try_fmt - Validates input/output format parameters.
+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
+ *
+ * Always returns 0.
+ **/
+int isp_try_fmt(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output)
+{
+	int ifmt;
+
+	for (ifmt = 0; ifmt < NUM_ISP_CAPTURE_FORMATS; ifmt++) {
+		if (pix_output->pixelformat == isp_formats[ifmt].pixelformat)
+			break;
+	}
+	if (ifmt == NUM_ISP_CAPTURE_FORMATS)
+		ifmt = 1;
+	pix_output->pixelformat = isp_formats[ifmt].pixelformat;
+	pix_output->field = V4L2_FIELD_NONE;
+	pix_output->bytesperline = pix_output->width * ISP_BYTES_PER_PIXEL;
+	pix_output->sizeimage = pix_output->bytesperline * pix_output->height;
+	pix_output->priv = 0;
+	switch (pix_output->pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+		pix_output->colorspace = V4L2_COLORSPACE_JPEG;
+		break;
+	default:
+		pix_output->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	}
+
+	ispmodule_obj.pix.pixelformat = pix_output->pixelformat;
+	ispmodule_obj.pix.width = pix_output->width;
+	ispmodule_obj.pix.height = pix_output->height;
+	ispmodule_obj.pix.field = pix_output->field;
+	ispmodule_obj.pix.bytesperline = pix_output->bytesperline;
+	ispmodule_obj.pix.sizeimage = pix_output->sizeimage;
+	ispmodule_obj.pix.priv = pix_output->priv;
+	ispmodule_obj.pix.colorspace = pix_output->colorspace;
+
+	return 0;
+}
+/**
+ * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
+ *
+ * Routine for saving the context of each module in the ISP.
+ * CCDC, HIST, H3A, PREV, RESZ and MMU.
+ **/
+void isp_save_ctx(void)
+{
+	isp_save_context(isp_reg_list);
+	ispccdc_save_context();
+	ispmmu_save_context();
+}
+EXPORT_SYMBOL(isp_save_ctx);
+
+/**
+ * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
+ *
+ * Routine for restoring the context of each module in the ISP.
+ * CCDC, HIST, H3A, PREV, RESZ and MMU.
+ **/
+void isp_restore_ctx(void)
+{
+	isp_restore_context(isp_reg_list);
+	ispccdc_restore_context();
+	ispmmu_restore_context();
+}
+EXPORT_SYMBOL(isp_restore_ctx);
+
+/**
+ * isp_get - Adquires the ISP resource.
+ *
+ * Initializes the clocks for the first acquire.
+ **/
+int isp_get(void)
+{
+	int ret_err = 0;
+	DPRINTK_ISPCTRL("isp_get: old %d\n", isp_obj.ref_count);
+	mutex_lock(&(isp_obj.isp_mutex));
+	if (isp_obj.ref_count == 0) {
+		isp_obj.cam_ick = clk_get(&camera_dev, "cam_ick");
+		if (IS_ERR(isp_obj.cam_ick)) {
+			DPRINTK_ISPCTRL("ISP_ERR: clk_get for "
+							"cam_ick failed\n");
+			ret_err = PTR_ERR(isp_obj.cam_ick);
+			goto out_clk_get_ick;
+		}
+		isp_obj.cam_mclk = clk_get(&camera_dev, "cam_mclk");
+		if (IS_ERR(isp_obj.cam_mclk)) {
+			DPRINTK_ISPCTRL("ISP_ERR: clk_get for "
+							"cam_mclk failed\n");
+			ret_err = PTR_ERR(isp_obj.cam_mclk);
+			goto out_clk_get_mclk;
+		}
+		ret_err = clk_enable(isp_obj.cam_ick);
+		if (ret_err) {
+			DPRINTK_ISPCTRL("ISP_ERR: clk_en for ick failed\n");
+			goto out_clk_enable_ick;
+		}
+		ret_err = clk_enable(isp_obj.cam_mclk);
+		if (ret_err) {
+			DPRINTK_ISPCTRL("ISP_ERR: clk_en for mclk failed\n");
+			goto out_clk_enable_mclk;
+		}
+		if (off_mode == 1)
+			isp_restore_ctx();
+	}
+	isp_obj.ref_count++;
+	mutex_unlock(&(isp_obj.isp_mutex));
+
+
+	DPRINTK_ISPCTRL("isp_get: new %d\n", isp_obj.ref_count);
+	return isp_obj.ref_count;
+
+out_clk_enable_mclk:
+	clk_disable(isp_obj.cam_ick);
+out_clk_enable_ick:
+	clk_put(isp_obj.cam_mclk);
+out_clk_get_mclk:
+	clk_put(isp_obj.cam_ick);
+out_clk_get_ick:
+
+	mutex_unlock(&(isp_obj.isp_mutex));
+
+	return ret_err;
+}
+EXPORT_SYMBOL(isp_get);
+
+/**
+ * isp_put - Releases the ISP resource.
+ *
+ * Releases the clocks also for the last release.
+ **/
+int isp_put(void)
+{
+	DPRINTK_ISPCTRL("isp_put: old %d\n", isp_obj.ref_count);
+	mutex_lock(&(isp_obj.isp_mutex));
+	if (isp_obj.ref_count)
+		if (--isp_obj.ref_count == 0) {
+			isp_save_ctx();
+			off_mode = 1;
+
+			clk_disable(isp_obj.cam_ick);
+			clk_disable(isp_obj.cam_mclk);
+			clk_put(isp_obj.cam_ick);
+			clk_put(isp_obj.cam_mclk);
+		}
+	mutex_unlock(&(isp_obj.isp_mutex));
+	DPRINTK_ISPCTRL("isp_put: new %d\n", isp_obj.ref_count);
+	return isp_obj.ref_count;
+}
+EXPORT_SYMBOL(isp_put);
+
+/**
+ * isp_save_context - Saves the values of the ISP module registers.
+ * @reg_list: Structure containing pairs of register address and value to
+ *            modify on OMAP.
+ **/
+void isp_save_context(struct isp_reg *reg_list)
+{
+	struct isp_reg *next = reg_list;
+
+	for (; next->reg != ISP_TOK_TERM; next++)
+		next->val = omap_readl(next->reg);
+}
+EXPORT_SYMBOL(isp_save_context);
+
+/**
+ * isp_restore_context - Restores the values of the ISP module registers.
+ * @reg_list: Structure containing pairs of register address and value to
+ *            modify on OMAP.
+ **/
+void isp_restore_context(struct isp_reg *reg_list)
+{
+	struct isp_reg *next = reg_list;
+
+	for (; next->reg != ISP_TOK_TERM; next++)
+		omap_writel(next->val, next->reg);
+}
+EXPORT_SYMBOL(isp_restore_context);
+
+/**
+ * isp_init - ISP module initialization.
+ **/
+static int __init isp_init(void)
+{
+	DPRINTK_ISPCTRL("+isp_init for Omap 3430 Camera ISP\n");
+	isp_obj.ref_count = 0;
+
+	mutex_init(&(isp_obj.isp_mutex));
+	spin_lock_init(&isp_obj.isp_temp_buf_lock);
+
+	if (request_irq(INT_34XX_CAM_IRQ, omap34xx_isp_isr, IRQF_SHARED,
+				"Omap 34xx Camera ISP", &ispirq_obj)) {
+		DPRINTK_ISPCTRL("Could not install ISR\n");
+		return -EINVAL;
+	} else {
+		spin_lock_init(&isp_obj.lock);
+		DPRINTK_ISPCTRL("-isp_init for Omap 3430 Camera ISP\n");
+		return 0;
+	}
+}
+
+/**
+ * isp_cleanup - ISP module cleanup.
+ **/
+static void __exit isp_cleanup(void)
+{
+	free_irq(INT_34XX_CAM_IRQ, &ispirq_obj);
+}
+
+/**
+ * isp_print_status - Prints the values of the ISP Control Module registers
+ *
+ * Also prints other debug information stored in the ISP module structure.
+ **/
+void isp_print_status(void)
+{
+	if (!is_ispctrl_debug_enabled())
+		return;
+
+	DPRINTK_ISPCTRL("###CM_FCLKEN_CAM=0x%x\n", omap_readl(CM_FCLKEN_CAM));
+	DPRINTK_ISPCTRL("###CM_ICLKEN_CAM=0x%x\n", omap_readl(CM_ICLKEN_CAM));
+	DPRINTK_ISPCTRL("###CM_CLKSEL_CAM=0x%x\n", omap_readl(CM_CLKSEL_CAM));
+	DPRINTK_ISPCTRL("###CM_AUTOIDLE_CAM=0x%x\n",
+						omap_readl(CM_AUTOIDLE_CAM));
+	DPRINTK_ISPCTRL("###CM_CLKEN_PLL[18:16] should be 0x7, = 0x%x\n",
+						omap_readl(CM_CLKEN_PLL));
+	DPRINTK_ISPCTRL("###CM_CLKSEL2_PLL[18:8] should be 0x2D, [6:0] should "
+				"be 1 = 0x%x\n", omap_readl(CM_CLKSEL2_PLL));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_HS=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_HS));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_XCLKA=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_XCLKA));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_D1=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_D1));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_D3=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_D3));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_D5=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_D5));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_D7=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_D7));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_D9=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_D9));
+	DPRINTK_ISPCTRL("###CTRL_PADCONF_CAM_D11=0x%x\n",
+					omap_readl(CTRL_PADCONF_CAM_D11));
+}
+EXPORT_SYMBOL(isp_print_status);
+
+module_init(isp_init);
+module_exit(isp_cleanup);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("ISP Control Module Library");
+MODULE_LICENSE("GPL");
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/isp/isp.h	2008-06-29 16:57:48.000000000 -0500
@@ -0,0 +1,326 @@
+/*
+ * drivers/media/video/isp/isp.h
+ *
+ * Top level public header file for ISP Control module in
+ * TI's OMAP3430 Camera ISP
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ * Copyright (C) 2008 Nokia.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@xxxxxx>
+ * 	Mohit Jalori <mjalori@xxxxxx>
+ * 	Sakari Ailus <sakari.ailus@xxxxxxxxx>
+ * 	Tuukka Toivonen <tuukka.o.toivonen@xxxxxxxxx>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef OMAP_ISP_TOP_H
+#define OMAP_ISP_TOP_H
+#include <media/videobuf-dma-sg.h>
+#include <linux/videodev2.h>
+#define OMAP_ISP_CCDC		(1 << 0)
+#define OMAP_ISP_PREVIEW	(1 << 1)
+#define OMAP_ISP_RESIZER	(1 << 2)
+#define OMAP_ISP_AEWB		(1 << 3)
+#define OMAP_ISP_AF		(1 << 4)
+#define OMAP_ISP_HIST		(1 << 5)
+
+/* Our ISP specific controls */
+#define V4L2_CID_PRIVATE_ISP_COLOR_FX		(V4L2_CID_PRIVATE_BASE + 0)
+
+/* ISP Private IOCTLs */
+#define VIDIOC_PRIVATE_ISP_CCDC_CFG	\
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct ispccdc_update_config)
+#define VIDIOC_PRIVATE_ISP_PRV_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct ispprv_update_config)
+#define VIDIOC_PRIVATE_ISP_AEWB_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct isph3a_aewb_config)
+#define VIDIOC_PRIVATE_ISP_AEWB_REQ \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct isph3a_aewb_data)
+#define VIDIOC_PRIVATE_ISP_HIST_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct isp_hist_config)
+#define VIDIOC_PRIVATE_ISP_HIST_REQ \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct isp_hist_data)
+#define VIDIOC_PRIVATE_ISP_AF_CFG \
+	_IO('V', BASE_VIDIOC_PRIVATE + 8)
+#define VIDIOC_PRIVATE_ISP_AF_REQ \
+	_IO('V', BASE_VIDIOC_PRIVATE + 9)
+
+#define ISP_TOK_TERM		0xFFFFFFFF	/*
+						 * terminating token for ISP
+						 * modules reg list
+						 */
+#define NUM_SG_DMA		(VIDEO_MAX_FRAME + 2)
+
+#define ISP_BUF_INIT		0
+#define ISP_FREE_RUNNING	1
+#define ISP_BUF_TRAN		2
+
+#ifndef CONFIG_ARCH_OMAP3410
+#define USE_ISP_PREVIEW
+#define USE_ISP_RESZ
+#define is_isppreview_enabled()		1
+#define is_ispresizer_enabled()		1
+#else
+#define is_isppreview_enabled()		0
+#define is_ispresizer_enabled()		0
+#endif
+
+#ifdef OMAP_ISPCTRL_DEBUG
+#define is_ispctrl_debug_enabled()		1
+#else
+#define is_ispctrl_debug_enabled()		0
+#endif
+
+#define ISP_XCLKA_DEFAULT		0x12
+#define ISP_OUTPUT_WIDTH_DEFAULT	176
+#define ISP_OUTPUT_HEIGHT_DEFAULT	144
+#define ISP_BYTES_PER_PIXEL		2
+#define NUM_ISP_CAPTURE_FORMATS 	(sizeof(isp_formats) /\
+							sizeof(isp_formats[0]))
+
+typedef int (*isp_vbq_callback_ptr) (struct videobuf_buffer *vb);
+typedef void (*isp_callback_t) (unsigned long status,
+					isp_vbq_callback_ptr arg1, void *arg2);
+
+enum isp_interface_type {
+	ISP_PARLL = 1,
+	ISP_CSIA = 2,
+	ISP_CSIB = 4
+};
+
+enum isp_irqevents {
+	CCDC_VD0 = 0x100,
+	CCDC_VD1 = 0x200,
+	CCDC_VD2 = 0x400,
+	CCDC_ERR = 0x800,
+	H3A_AWB_DONE = 0x2000,
+	HIST_DONE = 0x10000,
+	PREV_DONE = 0x100000,
+	LSC_DONE = 0x20000,
+	LSC_PRE_COMP = 0x40000,
+	LSC_PRE_ERR = 0x80000,
+	RESZ_DONE = 0x1000000,
+	SBL_OVF = 0x2000000,
+	MMU_ERR = 0x10000000,
+	OCP_ERR = 0x20000000,
+	HS_VS = 0x80000000
+};
+
+enum isp_callback_type {
+	CBK_CCDC_VD0,
+	CBK_CCDC_VD1,
+	CBK_PREV_DONE,
+	CBK_RESZ_DONE,
+	CBK_MMU_ERR,
+	CBK_H3A_AWB_DONE,
+	CBK_HIST_DONE,
+	CBK_HS_VS,
+	CBK_LSC_ISR
+};
+
+/**
+ * struct isp_reg - Structure for ISP register values.
+ * @reg: 32-bit Register address.
+ * @val: 32-bit Register value.
+ */
+struct isp_reg {
+	u32 reg;
+	u32 val;
+};
+
+/**
+ * struct isp_sgdma_state - SG-DMA state for each videobuffer + 2 overlays
+ * @isp_addr: ISP space address mapped by ISP MMU.
+ * @status: DMA return code mapped by ISP MMU.
+ * @callback: Pointer to ISP callback function.
+ * @arg: Pointer to argument passed to the specified callback function.
+ */
+struct isp_sgdma_state {
+	dma_addr_t isp_addr;
+	u32 status;
+	isp_callback_t callback;
+	void *arg;
+};
+
+/**
+ * struct isp_sgdma - ISP Scatter Gather DMA status.
+ * @isp_addr_capture: Array of ISP space addresses mapped by the ISP MMU.
+ * @lock: Spinlock used to check free_sgdma field.
+ * @free_sgdma: Number of free SG-DMA slots.
+ * @next_sgdma: Index of next SG-DMA slot to use.
+ */
+struct isp_sgdma {
+	dma_addr_t isp_addr_capture[VIDEO_MAX_FRAME];
+	spinlock_t lock;
+	int free_sgdma;
+	int next_sgdma;
+	struct isp_sgdma_state sg_state[NUM_SG_DMA];
+};
+
+/**
+ * struct isp_interface_config - ISP interface configuration.
+ * @ccdc_par_ser: ISP interface type. 0 - Parallel, 1 - CSIA, 2 - CSIB to CCDC.
+ * @par_bridge: CCDC Bridge input control. Parallel interface.
+ *                  0 - Disable, 1 - Enable, first byte->cam_d(bits 7 to 0)
+ *                  2 - Enable, first byte -> cam_d(bits 15 to 8)
+ * @par_clk_pol: Pixel clock polarity on the parallel interface.
+ *                    0 - Non Inverted, 1 - Inverted
+ * @dataline_shift: Data lane shifter.
+ *                      0 - No Shift, 1 - CAMEXT[13 to 2]->CAM[11 to 0]
+ *                      2 - CAMEXT[13 to 4]->CAM[9 to 0]
+ *                      3 - CAMEXT[13 to 6]->CAM[7 to 0]
+ * @hsvs_syncdetect: HS or VS synchronization signal detection.
+ *                       0 - HS Falling, 1 - HS rising
+ *                       2 - VS falling, 3 - VS rising
+ * @vdint0_timing: VD0 Interrupt timing.
+ * @vdint1_timing: VD1 Interrupt timing.
+ * @strobe: Strobe related parameter.
+ * @prestrobe: PreStrobe related parameter.
+ * @shutter: Shutter related parameter.
+ */
+struct isp_interface_config {
+	enum isp_interface_type ccdc_par_ser;
+	u8 dataline_shift;
+	u32 hsvs_syncdetect;
+	u16 vdint0_timing;
+	u16 vdint1_timing;
+	int strobe;
+	int prestrobe;
+	int shutter;
+	union {
+		struct par {
+			unsigned par_bridge:2;
+			unsigned par_clk_pol:1;
+		} par;
+		struct csi {
+			unsigned crc:1;
+			unsigned mode:1;
+			unsigned edge:1;
+			unsigned signalling:1;
+			unsigned strobe_clock_inv:1;
+			unsigned vs_edge:1;
+			unsigned channel:3;
+			unsigned vpclk:2;	/* Video port output clock */
+			unsigned int data_start;
+			unsigned int data_size;
+			u32 format;		/* V4L2_PIX_FMT_* */
+		} csi;
+	} u;
+};
+
+/**
+ * struct isp_sysc - ISP Power switches to set.
+ * @reset: Flag for setting ISP reset.
+ * @idle_mode: Flag for setting ISP idle mode.
+ */
+struct isp_sysc {
+	char reset;
+	char idle_mode;
+};
+
+void isp_open(void);
+
+void isp_close(void);
+
+void isp_start(void);
+
+void isp_stop(void);
+
+void isp_sgdma_init(void);
+
+void isp_vbq_done(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2);
+
+void isp_sgdma_process(struct isp_sgdma *sgdma, int irq, int *dma_notify,
+						isp_vbq_callback_ptr func_ptr);
+
+int isp_sgdma_queue(struct videobuf_dmabuf *vdma, struct videobuf_buffer *vb,
+						int irq, int *dma_notify,
+						isp_vbq_callback_ptr func_ptr);
+
+int isp_vbq_prepare(struct videobuf_queue *vbq, struct videobuf_buffer *vb,
+							enum v4l2_field field);
+
+void isp_vbq_release(struct videobuf_queue *vbq, struct videobuf_buffer *vb);
+
+int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
+					isp_vbq_callback_ptr arg1, void *arg2);
+
+void omapisp_unset_callback(void);
+
+int isp_unset_callback(enum isp_callback_type type);
+
+u32 isp_set_xclk(u32 xclk, u8 xclksel);
+
+u32 isp_get_xclk(u8 xclksel);
+
+int isp_request_interface(enum isp_interface_type if_t);
+
+int isp_free_interface(enum isp_interface_type if_t);
+
+void isp_power_settings(struct isp_sysc);
+
+int isp_configure_interface(struct isp_interface_config *config);
+
+void isp_CCDC_VD01_disable(void);
+
+void isp_CCDC_VD01_enable(void);
+
+int isp_get(void);
+
+int isp_put(void);
+
+void isp_set_pipeline(int soc_type);
+
+void isp_config_pipeline(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output);
+
+int isp_queryctrl(struct v4l2_queryctrl *a);
+
+int isp_g_ctrl(struct v4l2_control *a);
+
+int isp_s_ctrl(struct v4l2_control *a);
+
+int isp_enum_fmt_cap(struct v4l2_fmtdesc *f);
+
+int isp_try_fmt_cap(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output);
+
+void isp_g_fmt_cap(struct v4l2_format *f);
+
+int isp_s_fmt_cap(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output);
+
+int isp_g_crop(struct v4l2_crop *a);
+
+int isp_s_crop(struct v4l2_crop *a, struct v4l2_pix_format *pix);
+
+void isp_config_crop(struct v4l2_pix_format *pix);
+
+int isp_try_size(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output);
+
+int isp_try_fmt(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output);
+
+int isp_handle_private(int cmd, void *arg);
+
+void isp_save_context(struct isp_reg *);
+
+void isp_restore_context(struct isp_reg *);
+
+void isp_save_ctx(void);
+
+void isp_restore_ctx(void);
+
+void isp_print_status(void);
+
+#endif	/* OMAP_ISP_TOP_H */
--- /dev/null	2004-06-24 13:05:26.000000000 -0500
+++ b/drivers/media/video/isp/ispccdc.c	2008-06-29 17:44:57.000000000 -0500
@@ -0,0 +1,1296 @@
+/*
+ * drivers/media/video/isp/ispccdc.c
+ *
+ * Driver Library for CCDC module in TI's OMAP3430 Camera ISP
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Senthilvadivu Guruswamy <svadivu@xxxxxx>
+ *	Pallavi Kulkarni <p-kulkarni@xxxxxx>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <asm/mach-types.h>
+#include <asm/arch/clock.h>
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispccdc.h"
+#include "ispmmu.h"
+
+static u32 *fpc_table_add;
+static unsigned long fpc_table_add_m;
+
+/**
+ * struct isp_ccdc - Structure for the CCDC module to store its own information
+ * @ccdc_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
+ * @ccdcout_w: CCDC output width.
+ * @ccdcout_h: CCDC output height.
+ * @ccdcin_w: CCDC input width.
+ * @ccdcin_h: CCDC input height.
+ * @ccdcin_woffset: CCDC input horizontal offset.
+ * @ccdcin_hoffset: CCDC input vertical offset.
+ * @crop_w: Crop width.
+ * @crop_h: Crop weight.
+ * @ccdc_inpfmt: CCDC input format.
+ * @ccdc_outfmt: CCDC output format.
+ * @vpout_en: Video port output enable.
+ * @wen: Data write enable.
+ * @exwen: External data write enable.
+ * @refmt_en: Reformatter enable.
+ * @ccdcslave: CCDC slave mode enable.
+ * @syncif_ipmod: Image
+ * @obclamp_en: Data input format.
+ * @mutexlock: Mutex used to get access to the CCDC.
+ */
+static struct isp_ccdc {
+	u8 ccdc_inuse;
+	u32 ccdcout_w;
+	u32 ccdcout_h;
+	u32 ccdcin_w;
+	u32 ccdcin_h;
+	u32 ccdcin_woffset;
+	u32 ccdcin_hoffset;
+	u32 crop_w;
+	u32 crop_h;
+	u8 ccdc_inpfmt;
+	u8 ccdc_outfmt;
+	u8 vpout_en;
+	u8 wen;
+	u8 exwen;
+	u8 refmt_en;
+	u8 ccdcslave;
+	u8 syncif_ipmod;
+	u8 obclamp_en;
+	u8 lsc_en;
+	struct mutex mutexlock;
+} ispccdc_obj;
+
+/* Structure for saving/restoring CCDC module registers*/
+static struct isp_reg ispccdc_reg_list[] = {
+	{ISPCCDC_SYN_MODE, 0},
+	{ISPCCDC_HD_VD_WID, 0},
+	{ISPCCDC_PIX_LINES, 0},
+	{ISPCCDC_HORZ_INFO, 0},
+	{ISPCCDC_VERT_START, 0},
+	{ISPCCDC_VERT_LINES, 0},
+	{ISPCCDC_CULLING, 0},
+	{ISPCCDC_HSIZE_OFF, 0},
+	{ISPCCDC_SDOFST, 0},
+	{ISPCCDC_SDR_ADDR, 0},
+	{ISPCCDC_CLAMP, 0},
+	{ISPCCDC_DCSUB, 0},
+	{ISPCCDC_COLPTN, 0},
+	{ISPCCDC_BLKCMP, 0},
+	{ISPCCDC_FPC, 0},
+	{ISPCCDC_FPC_ADDR, 0},
+	{ISPCCDC_VDINT, 0},
+	{ISPCCDC_ALAW, 0},
+	{ISPCCDC_REC656IF, 0},
+	{ISPCCDC_CFG, 0},
+	{ISPCCDC_FMTCFG, 0},
+	{ISPCCDC_FMT_HORZ, 0},
+	{ISPCCDC_FMT_VERT, 0},
+	{ISPCCDC_FMT_ADDR0, 0},
+	{ISPCCDC_FMT_ADDR1, 0},
+	{ISPCCDC_FMT_ADDR2, 0},
+	{ISPCCDC_FMT_ADDR3, 0},
+	{ISPCCDC_FMT_ADDR4, 0},
+	{ISPCCDC_FMT_ADDR5, 0},
+	{ISPCCDC_FMT_ADDR6, 0},
+	{ISPCCDC_FMT_ADDR7, 0},
+	{ISPCCDC_PRGEVEN0, 0},
+	{ISPCCDC_PRGEVEN1, 0},
+	{ISPCCDC_PRGODD0, 0},
+	{ISPCCDC_PRGODD1, 0},
+	{ISPCCDC_VP_OUT, 0},
+	{ISPCCDC_LSC_CONFIG, 0},
+	{ISPCCDC_LSC_INITIAL, 0},
+	{ISPCCDC_LSC_TABLE_BASE, 0},
+	{ISPCCDC_LSC_TABLE_OFFSET, 0},
+	{ISP_TOK_TERM, 0}
+};
+
+/**
+ * omap34xx_isp_ccdc_config - Sets CCDC configuration from userspace
+ * @userspace_add: Structure containing CCDC configuration sent from userspace.
+ *
+ * Returns 0 if successful, -EINVAL if the pointer to the configuration
+ * structure is null, or the copy_from_user function fails to copy user space
+ * memory to kernel space memory.
+ **/
+int omap34xx_isp_ccdc_config(void *userspace_add)
+{
+	struct ispccdc_bclamp bclamp_t;
+	struct ispccdc_blcomp blcomp_t;
+	struct ispccdc_fpc fpc_t;
+	struct ispccdc_culling cull_t;
+	struct ispccdc_update_config *ccdc_struct;
+
+	if (userspace_add == NULL)
+		return -EINVAL;
+
+	ccdc_struct = (struct ispccdc_update_config *) userspace_add;
+
+	if ((ISP_ABS_CCDC_ALAW & ccdc_struct->flag) == ISP_ABS_CCDC_ALAW) {
+		if ((ISP_ABS_CCDC_ALAW & ccdc_struct->update) ==
+							ISP_ABS_CCDC_ALAW)
+			ispccdc_config_alaw(ccdc_struct->alawip);
+		ispccdc_enable_alaw(1);
+	} else if ((ISP_ABS_CCDC_ALAW & ccdc_struct->update) ==
+							ISP_ABS_CCDC_ALAW)
+		ispccdc_enable_alaw(0);
+
+	if ((ISP_ABS_CCDC_LPF & ccdc_struct->flag) == ISP_ABS_CCDC_LPF)
+		ispccdc_enable_lpf(1);
+	else
+		ispccdc_enable_lpf(0);
+
+	if ((ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) ==
+		ISP_ABS_CCDC_BLCLAMP) {
+		if ((ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) ==
+			ISP_ABS_CCDC_BLCLAMP) {
+			if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
+						(ccdc_struct->bclamp),
+						sizeof(struct ispccdc_bclamp)))
+				goto copy_from_user_err;
+
+			ispccdc_config_black_clamp(bclamp_t);
+		}
+		ispccdc_enable_black_clamp(1);
+	} else if ((ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) ==
+							ISP_ABS_CCDC_BLCLAMP)
+			ispccdc_enable_black_clamp(0);
+
+	if ((ISP_ABS_CCDC_BCOMP & ccdc_struct->update) == ISP_ABS_CCDC_BCOMP) {
+		if (copy_from_user(&blcomp_t, (struct ispccdc_blcomp *)
+							(ccdc_struct->blcomp),
+							sizeof(blcomp_t)))
+			goto copy_from_user_err;
+
+		ispccdc_config_black_comp(blcomp_t);
+	}
+
+	if ((ISP_ABS_CCDC_FPC & ccdc_struct->flag) == ISP_ABS_CCDC_FPC) {
+		if ((ISP_ABS_CCDC_FPC & ccdc_struct->update) ==
+							ISP_ABS_CCDC_FPC) {
+			if (copy_from_user(&fpc_t, (struct ispccdc_fpc *)
+							(ccdc_struct->fpc),
+							sizeof(fpc_t)))
+				goto copy_from_user_err;
+			fpc_table_add = kmalloc((64 + (fpc_t.fpnum * 4)),
+							GFP_KERNEL | GFP_DMA);
+			if (!fpc_table_add) {
+				printk(KERN_ERR "Cannot allocate memory for"
+								" FPC table");
+				return -ENOMEM;
+			}
+			while (((int)fpc_table_add & 0xFFFFFFC0) !=
+							(int)fpc_table_add)
+				fpc_table_add++;
+
+			fpc_table_add_m = ispmmu_map(virt_to_phys
+							(fpc_table_add),
+							(fpc_t.fpnum) * 4);
+
+			if (copy_from_user(fpc_table_add, (u32 *)fpc_t.fpcaddr,
+							fpc_t.fpnum * 4))
+				goto copy_from_user_err;
+
+			fpc_t.fpcaddr = fpc_table_add_m;
+			ispccdc_config_fpc(fpc_t);
+		}
+		ispccdc_enable_fpc(1);
+	} else if ((ISP_ABS_CCDC_FPC & ccdc_struct->update) ==
+							ISP_ABS_CCDC_FPC)
+			ispccdc_enable_fpc(0);
+
+	if ((ISP_ABS_CCDC_CULL & ccdc_struct->update) == ISP_ABS_CCDC_CULL) {
+		if (copy_from_user(&cull_t, (struct ispccdc_culling *)
+							(ccdc_struct->cull),
+							sizeof(cull_t)))
+			goto copy_from_user_err;
+		ispccdc_config_culling(cull_t);
+	}
+
+	if ((ISP_ABS_CCDC_COLPTN & ccdc_struct->update) == ISP_ABS_CCDC_COLPTN)
+		ispccdc_config_imgattr(ccdc_struct->colptn);
+
+	return 0;
+
+copy_from_user_err:
+	printk(KERN_ERR "CCDC Config:Copy From User Error");
+	return -EINVAL ;
+}
+
+/**
+ * ispccdc_request - Reserves the CCDC module.
+ *
+ * Reserves the CCDC module and assures that is used only once at a time.
+ *
+ * Returns 0 if successful, or -EBUSY if CCDC module is busy.
+ **/
+int ispccdc_request(void)
+{
+	mutex_lock(&ispccdc_obj.mutexlock);
+	if (ispccdc_obj.ccdc_inuse) {
+		mutex_unlock(&ispccdc_obj.mutexlock);
+		DPRINTK_ISPCCDC("ISP_ERR : CCDC Module Busy");
+		return -EBUSY;
+	}
+
+	ispccdc_obj.ccdc_inuse = 1;
+	mutex_unlock(&ispccdc_obj.mutexlock);
+	omap_writel((omap_readl(ISP_CTRL)) | ISPCTRL_CCDC_RAM_EN |
+							ISPCTRL_CCDC_CLK_EN |
+							ISPCTRL_SBL_WR1_RAM_EN,
+							ISP_CTRL);
+	omap_writel((omap_readl(ISPCCDC_CFG)) | ISPCCDC_CFG_VDLC, ISPCCDC_CFG);
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_request);
+
+/**
+ * ispccdc_free - Frees the CCDC module.
+ *
+ * Frees the CCDC module so it can be used by another process.
+ *
+ * Returns 0 if successful, or -EINVAL if module has been already freed.
+ **/
+int ispccdc_free(void)
+{
+	mutex_lock(&ispccdc_obj.mutexlock);
+	if (!ispccdc_obj.ccdc_inuse) {
+		mutex_unlock(&ispccdc_obj.mutexlock);
+		DPRINTK_ISPCCDC("ISP_ERR: CCDC Module already freed\n");
+		return -EINVAL;
+	}
+
+	ispccdc_obj.ccdc_inuse = 0;
+	mutex_unlock(&ispccdc_obj.mutexlock);
+	omap_writel((omap_readl(ISP_CTRL)) & ~(ISPCTRL_CCDC_CLK_EN |
+						ISPCTRL_CCDC_RAM_EN |
+						ISPCTRL_SBL_WR1_RAM_EN),
+						ISP_CTRL);
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_free);
+
+/**
+ * ispccdc_config_crop - Configures crop parameters for the ISP CCDC.
+ * @left: Left offset of the crop area.
+ * @top: Top offset of the crop area.
+ * @height: Height of the crop area.
+ * @width: Width of the crop area.
+ *
+ * The following restrictions are applied for the crop settings. If incoming
+ * values do not follow these restrictions then we map the settings to the
+ * closest acceptable crop value.
+ * 1) Left offset is always odd. This can be avoided if we enable byte swap
+ *    option for incoming data into CCDC.
+ * 2) Top offset is always even.
+ * 3) Crop height is always even.
+ * 4) Crop width is always a multiple of 16 pixels
+ **/
+void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width)
+{
+	ispccdc_obj.ccdcin_woffset = left + ((left + 1) % 2);
+	ispccdc_obj.ccdcin_hoffset = top + (top % 2);
+
+	ispccdc_obj.crop_w = width - (width % 16);
+	ispccdc_obj.crop_h = height + (height % 2);
+
+	DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
+						ispccdc_obj.ccdcin_woffset,
+						ispccdc_obj.ccdcin_hoffset,
+						ispccdc_obj.crop_w,
+						ispccdc_obj.crop_h);
+}
+
+/**
+ * ispccdc_config_datapath - Specifies the input and output modules for CCDC.
+ * @input: Indicates the module that inputs the image to the CCDC.
+ * @output: Indicates the module to which the CCDC outputs the image.
+ *
+ * Configures the default configuration for the CCDC to work with.
+ *
+ * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
+ * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
+ *
+ * The valid values for the output are CCDC_YUV_RSZ (0), CCDC_YUV_MEM_RSZ (1),
+ * CCDC_OTHERS_VP (2), CCDC_OTHERS_MEM (3), CCDC_OTHERS_VP_MEM (4).
+ *
+ * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input
+ * or output values.
+ **/
+int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output)
+{
+	u32 syn_mode = 0;
+	struct ispccdc_vp vpcfg;
+	struct ispccdc_syncif syncif;
+	struct ispccdc_bclamp blkcfg;
+
+	u32 colptn = (ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT) |
+		(ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT) |
+		(ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT) |
+		(ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT) |
+		(ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT) |
+		(ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT) |
+		(ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT) |
+		(ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT) |
+		(ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT) |
+		(ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT) |
+		(ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT) |
+		(ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT) |
+		(ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT) |
+		(ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT) |
+		(ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT) |
+		(ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT);
+
+	/* CCDC does not convert the image format */
+	if (((input == CCDC_RAW) || (input == CCDC_OTHERS)) &&
+						(output == CCDC_YUV_R