All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/9] OMAP3 ISP and camera drivers
@ 2009-03-03 10:06 Sakari Ailus
  2009-03-03 10:06 ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Sakari Ailus
                   ` (3 more replies)
  0 siblings, 4 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media, linux-omap
  Cc: Aguirre Rodriguez, Sergio Alberto, Toivonen Tuukka Olli Artturi,
	Hiroshi DOYU, DongSoo Kim

Hi,

So here's the patchset for OMAP 3 ISP and camera drivers plus the
associated V4L changes. Sergio Aguirre has been posting a related
patchset earlier, containing also sensor and lens driver used on SDP. 
This patchset is agains the linux-omap tree:

<URL:http://www.muru.com/linux/omap/README_OMAP_GIT>

So I and Sergio have synchronised our versions of the ISP and camera
drivers and this is the end result. There is still a lot of work to do,
though. You can find some comments in individual patch descriptions. If 
the todo list for a patch is empty it doesn't mean there wouldn't be 
anything left to do. ;)

There's at least one major change to Sergio Aguirre's earlier patches 
which is that the ISP driver now uses the IOMMU from Hiroshi Doyu. 
Hiroshi is away for some time now so there are just some hacks on top of 
Hiroshi's older iommu patches to use with current linux-omap.

This patchset does not contain the resizer or preview wrappers from TI 
but they have been left intentionally out. A proper interface (V4L) 
should be used for those and the camera driver should be somehow 
involved --- the wrappers are just duplicating much of the camera 
driver's functionality.

I don't have any sensor or lens drivers to publish at this time.

This patchset should work with the SDP and OMAPZoom boards although you
need the associated sensor drivers + the board code from Sergio Aguirre 
to use it. You'll also need the IOMMU patchset from Hiroshi Doyu. 
Everything except the sensor / board stuff is available here:

<URL:http://www.gitorious.org/projects/omap3camera>

In short, on linux-omap:

$ git pull http://git.gitorious.org/omap3camera/mainline.git v4l \
   iommu omap3camera base

Hiroshi's original iommu tree is here (branch iommu):

<URL:http://git.gitorious.org/lk/mainline.git>

Some of the camera and ISP driver development history is available, too. 
See the first link.

Any feedback is appreciated.

Sincerely,

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com


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

* [PATCH 1/9] omap3isp: Add ISP main driver and register definitions
  2009-03-03 10:06 [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
@ 2009-03-03 10:06 ` Sakari Ailus
  2009-03-03 10:06   ` [PATCH 2/9] omap3isp: Add ISP MMU wrapper Sakari Ailus
  2009-03-03 11:56   ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Alexey Klimov
  2009-03-03 13:09 ` [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

TODO:

- Release resoures in isp_probe() if something fails.

- Implement a sensible generic interface so that the ISP can offer a
  v4l2_subdev (like the v4l2-int-device slaves) interface towards the
  camera driver.

- Handle CSI1 and CSI2 error cases (currently unhandled?).

- Fix H3A / HIST interrupt enabling / disabling.

- Clean up the private ioctls.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/Makefile     |    2 +
 drivers/media/video/isp/Makefile |   12 +
 drivers/media/video/isp/isp.c    | 2418 ++++++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/isp.h    |  318 +++++
 drivers/media/video/isp/ispreg.h | 1673 ++++++++++++++++++++++++++
 5 files changed, 4423 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/Makefile
 create mode 100644 drivers/media/video/isp/isp.c
 create mode 100644 drivers/media/video/isp/isp.h
 create mode 100644 drivers/media/video/isp/ispreg.h

diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 72f6d03..e654270 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -106,6 +106,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
 obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
 
+obj-y				+= isp/
+
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
new file mode 100644
index 0000000..f14d617
--- /dev/null
+++ b/drivers/media/video/isp/Makefile
@@ -0,0 +1,12 @@
+# Makefile for OMAP3 ISP driver
+
+ifdef CONFIG_ARCH_OMAP3410
+isp-mod-objs += \
+	isp.o ispccdc.o
+else
+isp-mod-objs += \
+	isp.o ispccdc.o ispmmu.o \
+	isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
+endif
+
+obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
new file mode 100644
index 0000000..12a545c
--- /dev/null
+++ b/drivers/media/video/isp/isp.c
@@ -0,0 +1,2418 @@
+/*
+ * isp.c
+ *
+ * Driver Library for ISP Control module in TI's OMAP3 Camera ISP
+ * ISP interface and IRQ related APIs are defined here.
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2009 Nokia.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@ti.com>
+ * 	Mohit Jalori <mjalori@ti.com>
+ * 	Sergio Aguirre <saaguirre@ti.com>
+ * 	Sakari Ailus <sakari.ailus@nokia.com>
+ * 	Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *	Toni Leinonen <toni.leinonen@nokia.com>
+ *
+ * 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 <asm/cacheflush.h>
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+
+#include "isp.h"
+#include "ispmmu.h"
+#include "ispreg.h"
+#include "ispccdc.h"
+#include "isph3a.h"
+#include "isphist.h"
+#include "isp_af.h"
+#include "isppreview.h"
+#include "ispresizer.h"
+#include "ispcsi2.h"
+
+static struct isp_device *omap3isp;
+
+static int isp_try_size(struct v4l2_pix_format *pix_input,
+					struct v4l2_pix_format *pix_output);
+
+static void isp_save_ctx(void);
+
+static void isp_restore_ctx(void);
+
+static void isp_buf_init(void);
+
+/* 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[] = {
+	{
+		{
+			.id = V4L2_CID_BRIGHTNESS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Brightness",
+			.minimum = ISPPRV_BRIGHT_LOW,
+			.maximum = ISPPRV_BRIGHT_HIGH,
+			.step = ISPPRV_BRIGHT_STEP,
+			.default_value = ISPPRV_BRIGHT_DEF,
+		},
+		.current_value = ISPPRV_BRIGHT_DEF,
+	},
+	{
+		{
+			.id = V4L2_CID_CONTRAST,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Contrast",
+			.minimum = ISPPRV_CONTRAST_LOW,
+			.maximum = ISPPRV_CONTRAST_HIGH,
+			.step = ISPPRV_CONTRAST_STEP,
+			.default_value = ISPPRV_CONTRAST_DEF,
+		},
+		.current_value = ISPPRV_CONTRAST_DEF,
+	},
+	{
+		{
+			.id = V4L2_CID_COLORFX,
+			.type = V4L2_CTRL_TYPE_MENU,
+			.name = "Color Effects",
+			.minimum = V4L2_COLORFX_NONE,
+			.maximum = V4L2_COLORFX_SEPIA,
+			.step = 1,
+			.default_value = V4L2_COLORFX_NONE,
+		},
+		.current_value = V4L2_COLORFX_NONE,
+	}
+};
+
+static struct v4l2_querymenu video_menu[] = {
+	{
+		.id = V4L2_CID_COLORFX,
+		.index = 0,
+		.name = "None",
+	},
+	{
+		.id = V4L2_CID_COLORFX,
+		.index = 1,
+		.name = "B&W",
+	},
+	{
+		.id = V4L2_CID_COLORFX,
+		.index = 2,
+		.name = "Sepia",
+	},
+};
+
+struct isp_buf {
+	dma_addr_t isp_addr;
+	void (*complete)(struct videobuf_buffer *vb, void *priv);
+	struct videobuf_buffer *vb;
+	void *priv;
+	u32 vb_state;
+};
+
+#define ISP_BUFS_IS_FULL(bufs) \
+	(((bufs)->queue + 1) % NUM_BUFS == (bufs)->done)
+#define ISP_BUFS_IS_EMPTY(bufs)		((bufs)->queue == (bufs)->done)
+#define ISP_BUFS_IS_LAST(bufs) \
+	((bufs)->queue == ((bufs)->done + 1) % NUM_BUFS)
+#define ISP_BUFS_QUEUED(bufs) \
+	((((bufs)->done - (bufs)->queue + NUM_BUFS)) % NUM_BUFS)
+#define ISP_BUF_DONE(bufs)		((bufs)->buf + (bufs)->done)
+#define ISP_BUF_NEXT_DONE(bufs)	\
+	((bufs)->buf + ((bufs)->done + 1) % NUM_BUFS)
+#define ISP_BUF_QUEUE(bufs)		((bufs)->buf + (bufs)->queue)
+#define ISP_BUF_MARK_DONE(bufs) \
+	(bufs)->done = ((bufs)->done + 1) % NUM_BUFS;
+#define ISP_BUF_MARK_QUEUED(bufs) \
+	(bufs)->queue = ((bufs)->queue + 1) % NUM_BUFS;
+
+struct isp_bufs {
+	dma_addr_t isp_addr_capture[VIDEO_MAX_FRAME];
+	spinlock_t lock;	/* For handling current buffer */
+	/* queue full: (ispsg.queue + 1) % NUM_BUFS == ispsg.done
+	   queue empty: ispsg.queue == ispsg.done */
+	struct isp_buf buf[NUM_BUFS];
+	/* Next slot to queue a buffer. */
+	int queue;
+	/* Buffer that is being processed. */
+	int done;
+	/* Wait for this many hs_vs before anything else. */
+	int wait_hs_vs;
+};
+
+/**
+ * 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).
+ */
+struct isp_irq {
+	isp_callback_t isp_callbk[CBK_END];
+	isp_vbq_callback_ptr isp_callbk_arg1[CBK_END];
+	void *isp_callbk_arg2[CBK_END];
+};
+
+/**
+ * struct ispmodule - Structure for storing ISP sub-module information.
+ * @isp_pipeline: Bit mask for submodules enabled within the ISP.
+ * @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 isp_module {
+	unsigned int isp_pipeline;
+	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;
+};
+
+#define RAW_CAPTURE(isp) \
+	(!((isp)->module.isp_pipeline & OMAP_ISP_PREVIEW))
+
+/**
+ * struct isp - Structure for storing ISP Control module information
+ * @lock: Spinlock to sync between isr and processes.
+ * @isp_mutex: Semaphore used to get access to the ISP.
+ * @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;	/* For handling registered ISP callbacks */
+	struct mutex isp_mutex;	/* For handling ref_count field */
+	int ref_count;
+	struct clk *cam_ick;
+	struct clk *cam_mclk;
+	struct clk *csi2_fck;
+	struct isp_interface_config *config;
+	dma_addr_t tmp_buf;
+	size_t tmp_buf_size;
+	unsigned long tmp_buf_offset;
+	 struct isp_bufs bufs;
+	 struct isp_irq irq;
+	 struct isp_module module;
+} isp_obj;
+
+/* Structure for saving/restoring ISP module registers */
+static struct isp_reg isp_reg_list[] = {
+	{OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_GRESET_LENGTH, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_REPLAY, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_FRAME, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_DELAY, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_DELAY, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_DELAY, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_LENGTH, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_LENGTH, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_LENGTH, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_SYSCONFIG, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_IRQENABLE, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_CTRL, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_CTRL, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_START, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_START, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_END, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_END, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_WINDOWSIZE, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_WINDOWSIZE, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_THRESHOLD, 0},
+	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_THRESHOLD, 0},
+	{0, ISP_TOK_TERM, 0}
+};
+
+u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset)
+{
+	return __raw_readl(omap3isp->mmio_base[isp_mmio_range] + reg_offset);
+}
+EXPORT_SYMBOL(isp_reg_readl);
+
+void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
+								u32 reg_offset)
+{
+	__raw_writel(reg_value,
+			omap3isp->mmio_base[isp_mmio_range] + reg_offset);
+}
+EXPORT_SYMBOL(isp_reg_writel);
+
+/*
+ *
+ * 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;
+}
+
+static int find_next_vctrl(int id)
+{
+	int i;
+	u32 best = (u32)-1;
+
+	for (i = 0; i < ARRAY_SIZE(video_control); i++) {
+		if (video_control[i].qc.id > id &&
+						(best == (u32)-1 ||
+						video_control[i].qc.id <
+						video_control[best].qc.id)) {
+			best = i;
+		}
+	}
+
+	if (best == (u32)-1)
+		return -EINVAL;
+
+	return best;
+}
+
+/**
+ * find_vmenu - Returns index of the menu array of the requested ctrl option.
+ * @id: Requested control ID.
+ * @index: Requested menu option index.
+ *
+ * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
+ * domain.
+ **/
+static int find_vmenu(int id, int index)
+{
+	int i;
+
+	if (id < V4L2_CID_BASE)
+		return -EDOM;
+
+	for (i = (ARRAY_SIZE(video_menu) - 1); i >= 0; i--) {
+		if ((video_menu[i].id != id) || (video_menu[i].index != index))
+			continue;
+		return i;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * isp_release_resources - Free ISP submodules
+ **/
+static void isp_release_resources(void)
+{
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
+		ispccdc_free();
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW)
+		isppreview_free();
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER)
+		ispresizer_free();
+	return;
+}
+
+static int isp_wait(int (*busy)(void), int wait_for_busy, int max_wait)
+{
+	int wait = 0;
+
+	if (max_wait == 0)
+		max_wait = 10000; /* 10 ms */
+
+	while ((wait_for_busy && !busy())
+	       || (!wait_for_busy && busy())) {
+		rmb();
+		udelay(1);
+		wait++;
+		if (wait > max_wait) {
+			printk(KERN_ALERT "%s: wait is too much\n", __func__);
+			return -EBUSY;
+		}
+	}
+	DPRINTK_ISPCTRL(KERN_ALERT "%s: wait %d\n", __func__, wait);
+
+	return 0;
+}
+
+static int ispccdc_sbl_wait_idle(int max_wait)
+{
+	return isp_wait(ispccdc_sbl_busy, 0, max_wait);
+}
+
+static void isp_enable_interrupts(int is_raw)
+{
+	isp_reg_writel(-1, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+		    IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
+		    IRQ0ENABLE_HS_VS_IRQ |
+		    IRQ0ENABLE_CCDC_VD0_IRQ |
+		    IRQ0ENABLE_CCDC_VD1_IRQ);
+
+	if (is_raw)
+		return;
+
+	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+		    IRQ0ENABLE_PRV_DONE_IRQ |
+		    IRQ0ENABLE_RSZ_DONE_IRQ);
+
+	return;
+}
+
+static void isp_disable_interrupts(void)
+{
+	isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+		    ~(IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
+			IRQ0ENABLE_HS_VS_IRQ |
+			IRQ0ENABLE_CCDC_VD0_IRQ |
+			IRQ0ENABLE_CCDC_VD1_IRQ |
+			IRQ0ENABLE_PRV_DONE_IRQ |
+			IRQ0ENABLE_RSZ_DONE_IRQ));
+}
+
+/**
+ * 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);
+	isp_obj.irq.isp_callbk[type] = callback;
+	isp_obj.irq.isp_callbk_arg1[type] = arg1;
+	isp_obj.irq.isp_callbk_arg2[type] = arg2;
+	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+
+	switch (type) {
+	case CBK_H3A_AWB_DONE:
+		isp_reg_writel(IRQ0ENABLE_H3A_AWB_DONE_IRQ,
+					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						IRQ0ENABLE_H3A_AWB_DONE_IRQ);
+		break;
+	case CBK_H3A_AF_DONE:
+		isp_reg_writel(IRQ0ENABLE_H3A_AF_DONE_IRQ,
+					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						IRQ0ENABLE_H3A_AF_DONE_IRQ);
+		break;
+	case CBK_HIST_DONE:
+		isp_reg_writel(IRQ0ENABLE_HIST_DONE_IRQ,
+					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						IRQ0ENABLE_HIST_DONE_IRQ);
+		break;
+	case CBK_PREV_DONE:
+		isp_reg_writel(IRQ0ENABLE_PRV_DONE_IRQ,
+					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						IRQ0ENABLE_PRV_DONE_IRQ);
+		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);
+	isp_obj.irq.isp_callbk[type] = NULL;
+	isp_obj.irq.isp_callbk_arg1[type] = NULL;
+	isp_obj.irq.isp_callbk_arg2[type] = NULL;
+	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+
+	switch (type) {
+	case CBK_H3A_AWB_DONE:
+		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						~IRQ0ENABLE_H3A_AWB_DONE_IRQ);
+		break;
+	case CBK_H3A_AF_DONE:
+		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						~IRQ0ENABLE_H3A_AF_DONE_IRQ);
+		break;
+	case CBK_HIST_DONE:
+		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						~IRQ0ENABLE_HIST_DONE_IRQ);
+		break;
+	case CBK_CSIA:
+		isp_csi2_irq_set(0);
+		break;
+	case CBK_CSIB:
+		isp_reg_writel(IRQ0ENABLE_CSIB_IRQ, OMAP3_ISP_IOMEM_MAIN,
+							ISP_IRQ0STATUS);
+		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						IRQ0ENABLE_CSIB_IRQ);
+		break;
+	case CBK_PREV_DONE:
+		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+						~IRQ0ENABLE_PRV_DONE_IRQ);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_unset_callback);
+
+/**
+ * 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:
+		isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
+					~ISPTCTRL_CTRL_DIVA_MASK,
+					divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
+		DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclka set to %d Hz\n",
+								currentxclk);
+		break;
+	case 1:
+		isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
+					~ISPTCTRL_CTRL_DIVB_MASK,
+					divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
+		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_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.
+ **/
+static void isp_power_settings(int idle)
+{
+	if (idle) {
+		isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
+				(ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY <<
+				ISP_SYSCONFIG_MIDLEMODE_SHIFT),
+				OMAP3_ISP_IOMEM_MAIN,
+				ISP_SYSCONFIG);
+		if (omap_rev() == OMAP3430_REV_ES1_0) {
+			isp_reg_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					OMAP3_ISP_IOMEM_CSI2A,
+					ISP_CSIA_SYSCONFIG);
+			isp_reg_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					OMAP3_ISP_IOMEM_CCP2,
+					ISP_CSIB_SYSCONFIG);
+		}
+		isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
+								ISP_CTRL);
+
+	} else {
+		isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
+				(ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY <<
+				ISP_SYSCONFIG_MIDLEMODE_SHIFT),
+				OMAP3_ISP_IOMEM_MAIN,
+				ISP_SYSCONFIG);
+		if (omap_rev() == OMAP3430_REV_ES1_0) {
+			isp_reg_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_FORCESTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					OMAP3_ISP_IOMEM_CSI2A,
+					ISP_CSIA_SYSCONFIG);
+
+			isp_reg_writel(ISPCSI1_AUTOIDLE |
+					(ISPCSI1_MIDLEMODE_FORCESTANDBY <<
+					ISPCSI1_MIDLEMODE_SHIFT),
+					OMAP3_ISP_IOMEM_CCP2,
+					ISP_CSIB_SYSCONFIG);
+		}
+
+		isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
+								ISP_CTRL);
+	}
+}
+
+#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 */
+	isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSCONFIG) |
+							BIT(1),
+							OMAP3_ISP_IOMEM_CCP2,
+							ISPCSI1_SYSCONFIG);
+	while (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
+								BIT(0))) {
+		udelay(10);
+		if (i++ > 10)
+			break;
+	}
+	if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
+								BIT(0))) {
+		printk(KERN_WARNING
+			"omap3_isp: timeout waiting for csi reset\n");
+	}
+
+	/* ISPCSI1_CTRL */
+	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, 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 */
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
+
+	/* ISPCSI1_LCx_CTRL logical channel #0 */
+	reg = ISPCSI1_LCx_CTRL(0);	/* reg = ISPCSI1_CTRL1; */
+	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, 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);
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
+
+	/* ISPCSI1_DAT_START for logical channel #0 */
+	reg = ISPCSI1_LCx_DAT_START(0);		/* reg = ISPCSI1_DAT_START; */
+	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
+	BIT_SET(val, 16, 0xfff, config->u.csi.data_start);
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
+
+	/* ISPCSI1_DAT_SIZE for logical channel #0 */
+	reg = ISPCSI1_LCx_DAT_SIZE(0);		/* reg = ISPCSI1_DAT_SIZE; */
+	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
+	BIT_SET(val, 16, 0xfff, config->u.csi.data_size);
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
+
+	/* Clear status bits for logical channel #0 */
+	isp_reg_writel(0xFFF & ~BIT(6), OMAP3_ISP_IOMEM_CCP2,
+						ISPCSI1_LC01_IRQSTATUS);
+
+	/* Enable CSI1 */
+	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
+	val |=  BIT(0) | BIT(4);
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
+
+	if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, 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 = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
+	int r;
+
+	isp_obj.config = config;
+
+	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);
+
+	isp_buf_init();
+
+	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_CSIA:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
+		ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
+
+		isp_csi2_ctx_config_format(0, config->u.csi.format);
+		isp_csi2_ctx_update(0, false);
+
+		if (config->u.csi.crc)
+			isp_csi2_ctrl_config_ecc_enable(true);
+
+		isp_csi2_ctrl_config_vp_out_ctrl(config->u.csi.vpclk);
+		isp_csi2_ctrl_config_vp_only_enable(true);
+		isp_csi2_ctrl_config_vp_clk_enable(true);
+		isp_csi2_ctrl_update(false);
+
+		isp_csi2_irq_complexio1_set(1);
+		isp_csi2_irq_status_set(1);
+		isp_csi2_irq_set(1);
+
+		isp_csi2_enable(1);
+		mdelay(3);
+		break;
+	case ISP_CSIB:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
+		r = isp_init_csi(config);
+		if (r)
+			return r;
+		break;
+	case ISP_NONE:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	ispctrl_val &= ~(ISPCTRL_SYNC_DETECT_VSRISE);
+	ispctrl_val |= (config->hsvs_syncdetect);
+
+	isp_reg_writel(ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
+
+	/* Set sensor specific fields in CCDC and Previewer module.*/
+	isppreview_set_skip(config->prev_sph, config->prev_slv);
+	ispccdc_set_wenlog(config->wenlog);
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_configure_interface);
+
+static int isp_buf_process(struct isp_bufs *bufs);
+
+/**
+ * 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 isp_obj.irq 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 *_isp)
+{
+	struct isp *isp = _isp;
+	struct isp_irq *irqdis = &isp->irq;
+	struct isp_bufs *bufs = &isp->bufs;
+	unsigned long flags;
+	u32 irqstatus = 0;
+	unsigned long irqflags = 0;
+	int wait_hs_vs = 0;
+
+	irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+	isp_reg_writel(irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+
+	spin_lock_irqsave(&bufs->lock, flags);
+	wait_hs_vs = bufs->wait_hs_vs;
+	if (irqstatus & HS_VS && bufs->wait_hs_vs)
+		bufs->wait_hs_vs--;
+	spin_unlock_irqrestore(&bufs->lock, flags);
+
+	spin_lock_irqsave(&isp_obj.lock, irqflags);
+	/*
+	 * We need to wait for the first HS_VS interrupt from CCDC.
+	 * Otherwise our frame (and everything else) might be bad.
+	 */
+	if (wait_hs_vs)
+		goto out_ignore_buff;
+
+	if ((irqstatus & CCDC_VD0) == CCDC_VD0) {
+		if (RAW_CAPTURE(&isp_obj))
+			isp_buf_process(bufs);
+	}
+
+	if ((irqstatus & PREV_DONE) == PREV_DONE) {
+		if (irqdis->isp_callbk[CBK_PREV_DONE])
+			irqdis->isp_callbk[CBK_PREV_DONE](PREV_DONE,
+				irqdis->isp_callbk_arg1[CBK_PREV_DONE],
+				irqdis->isp_callbk_arg2[CBK_PREV_DONE]);
+		else if (!RAW_CAPTURE(&isp_obj) && !ispresizer_busy()) {
+			if (isp_obj.module.applyCrop) {
+				ispresizer_applycrop();
+				if (!ispresizer_busy())
+					isp_obj.module.applyCrop = 0;
+			}
+			if (!isppreview_busy()) {
+				ispresizer_enable(1);
+				if (isppreview_busy()) {
+					/* FIXME: locking! */
+					ISP_BUF_DONE(bufs)->vb_state =
+						VIDEOBUF_ERROR;
+					printk(KERN_ERR "%s: can't stop"
+					       " preview\n", __func__);
+				}
+			}
+			if (!isppreview_busy())
+				isppreview_config_shadow_registers();
+			if (!isppreview_busy())
+				isph3a_update_wb();
+		}
+	}
+
+	if ((irqstatus & RESZ_DONE) == RESZ_DONE) {
+		if (!RAW_CAPTURE(&isp_obj)) {
+			if (!ispresizer_busy())
+				ispresizer_config_shadow_registers();
+			isp_buf_process(bufs);
+		}
+	}
+
+	if ((irqstatus & H3A_AWB_DONE) == H3A_AWB_DONE) {
+		if (irqdis->isp_callbk[CBK_H3A_AWB_DONE])
+			irqdis->isp_callbk[CBK_H3A_AWB_DONE](H3A_AWB_DONE,
+				irqdis->isp_callbk_arg1[CBK_H3A_AWB_DONE],
+				irqdis->isp_callbk_arg2[CBK_H3A_AWB_DONE]);
+	}
+
+	if ((irqstatus & HIST_DONE) == HIST_DONE) {
+		if (irqdis->isp_callbk[CBK_HIST_DONE])
+			irqdis->isp_callbk[CBK_HIST_DONE](HIST_DONE,
+				irqdis->isp_callbk_arg1[CBK_HIST_DONE],
+				irqdis->isp_callbk_arg2[CBK_HIST_DONE]);
+	}
+
+	if ((irqstatus & H3A_AF_DONE) == H3A_AF_DONE) {
+		if (irqdis->isp_callbk[CBK_H3A_AF_DONE])
+			irqdis->isp_callbk[CBK_H3A_AF_DONE](H3A_AF_DONE,
+				irqdis->isp_callbk_arg1[CBK_H3A_AF_DONE],
+				irqdis->isp_callbk_arg2[CBK_H3A_AF_DONE]);
+	}
+
+
+out_ignore_buff:
+	if (irqstatus & LSC_PRE_ERR) {
+		struct isp_buf *buf = ISP_BUF_DONE(bufs);
+		ispccdc_enable_lsc(0);
+		ispccdc_enable_lsc(1);
+		/* Mark buffer faulty. */
+		buf->vb_state = VIDEOBUF_ERROR;
+		printk(KERN_ERR "%s: lsc prefetch error\n", __func__);
+	}
+
+	if ((irqstatus & CSIA) == CSIA) {
+		struct isp_buf *buf = ISP_BUF_DONE(bufs);
+		isp_csi2_isr();
+		buf->vb_state = VIDEOBUF_ERROR;
+	}
+
+	if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
+		u32 ispcsi1_irqstatus;
+
+		ispcsi1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2,
+						ISPCSI1_LC01_IRQSTATUS);
+		DPRINTK_ISPCTRL("%x\n", ispcsi1_irqstatus);
+	}
+
+	if (irqdis->isp_callbk[CBK_CATCHALL]) {
+		irqdis->isp_callbk[CBK_CATCHALL](irqstatus,
+			irqdis->isp_callbk_arg1[CBK_CATCHALL],
+			irqdis->isp_callbk_arg2[CBK_CATCHALL]);
+	}
+
+	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+
+#if 1
+	{
+		static const struct {
+			int num;
+			char *name;
+		} bits[] = {
+			{ 31, "HS_VS_IRQ" },
+			{ 30, "SEC_ERR_IRQ" },
+			{ 29, "OCP_ERR_IRQ" },
+			{ 28, "MMU_ERR_IRQ" },
+			{ 27, "res27" },
+			{ 26, "res26" },
+			{ 25, "OVF_IRQ" },
+			{ 24, "RSZ_DONE_IRQ" },
+			{ 23, "res23" },
+			{ 22, "res22" },
+			{ 21, "CBUFF_IRQ" },
+			{ 20, "PRV_DONE_IRQ" },
+			{ 19, "CCDC_LSC_PREFETCH_ERROR" },
+			{ 18, "CCDC_LSC_PREFETCH_COMPLETED" },
+			{ 17, "CCDC_LSC_DONE" },
+			{ 16, "HIST_DONE_IRQ" },
+			{ 15, "res15" },
+			{ 14, "res14" },
+			{ 13, "H3A_AWB_DONE_IRQ" },
+			{ 12, "H3A_AF_DONE_IRQ" },
+			{ 11, "CCDC_ERR_IRQ" },
+			{ 10, "CCDC_VD2_IRQ" },
+			{  9, "CCDC_VD1_IRQ" },
+			{  8, "CCDC_VD0_IRQ" },
+			{  7, "res7" },
+			{  6, "res6" },
+			{  5, "res5" },
+			{  4, "CSIB_IRQ" },
+			{  3, "CSIB_LCM_IRQ" },
+			{  2, "res2" },
+			{  1, "res1" },
+			{  0, "CSIA_IRQ" },
+		};
+		int i;
+		for (i = 0; i < ARRAY_SIZE(bits); i++) {
+			if ((1 << bits[i].num) & irqstatus)
+				DPRINTK_ISPCTRL("%s ", bits[i].name);
+		}
+		DPRINTK_ISPCTRL("\n");
+	}
+#endif
+
+	return IRQ_HANDLED;
+}
+
+/* Device name, needed for resource tracking layer */
+struct device_driver camera_drv = {
+	.name = "camera"
+};
+
+struct device camera_dev = {
+	.driver = &camera_drv,
+};
+
+/**
+ *  isp_tmp_buf_free - To free allocated 10MB memory
+ *
+ **/
+static void isp_tmp_buf_free(void)
+{
+	if (isp_obj.tmp_buf) {
+		ispmmu_vfree(isp_obj.tmp_buf);
+		isp_obj.tmp_buf = 0;
+		isp_obj.tmp_buf_size = 0;
+	}
+}
+
+/**
+ *  isp_tmp_buf_alloc - To allocate a 10MB memory
+ *
+ **/
+static u32 isp_tmp_buf_alloc(size_t size)
+{
+	isp_tmp_buf_free();
+
+	printk(KERN_INFO "%s: allocating %d bytes\n", __func__, size);
+
+	isp_obj.tmp_buf = ispmmu_vmalloc(size);
+	if (IS_ERR((void *)isp_obj.tmp_buf)) {
+		printk(KERN_ERR "ispmmu_vmap mapping failed ");
+		return -ENOMEM;
+	}
+	isp_obj.tmp_buf_size = size;
+
+	isppreview_set_outaddr(isp_obj.tmp_buf);
+	ispresizer_set_inaddr(isp_obj.tmp_buf);
+
+	return 0;
+}
+
+/**
+ * isp_start - Starts ISP submodule
+ *
+ * Start the needed isp components assuming these components
+ * are configured correctly.
+ **/
+void isp_start(void)
+{
+	if ((isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) &&
+						is_isppreview_enabled())
+		isppreview_enable(1);
+
+	return;
+}
+EXPORT_SYMBOL(isp_start);
+
+#define ISP_STATISTICS_BUSY				\
+	()
+#define ISP_STOP_TIMEOUT	msecs_to_jiffies(1000)
+/**
+ * isp_stop - Stops isp submodules
+ **/
+void isp_stop()
+{
+	unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
+	int reset = 0;
+
+	isp_disable_interrupts();
+
+	/*
+	 * We need to stop all the modules after CCDC first or they'll
+	 * never stop since they may not get a full frame from CCDC.
+	 */
+	isp_af_enable(0);
+	isph3a_aewb_enable(0);
+	isp_hist_enable(0);
+	isppreview_enable(0);
+	ispresizer_enable(0);
+
+	timeout = jiffies + ISP_STOP_TIMEOUT;
+	while (isp_af_busy()
+	       || isph3a_aewb_busy()
+	       || isp_hist_busy()
+	       || isppreview_busy()
+	       || ispresizer_busy()) {
+		if (time_after(jiffies, timeout)) {
+			printk(KERN_ERR "%s: can't stop non-ccdc modules\n",
+			       __func__);
+			reset = 1;
+			break;
+		}
+		msleep(1);
+	}
+
+	/* Let's stop CCDC now. */
+	ispccdc_enable_lsc(0);
+	ispccdc_enable(0);
+
+	timeout = jiffies + ISP_STOP_TIMEOUT;
+	while (ispccdc_busy()) {
+		if (time_after(jiffies, timeout)) {
+			printk(KERN_ERR "%s: can't stop ccdc\n", __func__);
+			reset = 1;
+			break;
+		}
+		msleep(1);
+	}
+
+	isp_buf_init();
+
+	if (!reset)
+		return;
+
+	isp_save_ctx();
+	isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
+		       | ISP_SYSCONFIG_SOFTRESET,
+		       OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
+	timeout = 0;
+	while (!(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS) & 0x1)) {
+		if (timeout++ > 10000) {
+			printk(KERN_ALERT "%s: cannot reset ISP\n", __func__);
+			break;
+		}
+		udelay(1);
+	}
+	isp_restore_ctx();
+}
+EXPORT_SYMBOL(isp_stop);
+
+static void isp_set_buf(struct isp_buf *buf)
+{
+	if ((isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) &&
+						is_ispresizer_enabled())
+		ispresizer_set_outaddr(buf->isp_addr);
+	else if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
+		ispccdc_set_outaddr(buf->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.
+ **/
+static u32 isp_calc_pipeline(struct v4l2_pix_format *pix_input,
+			     struct v4l2_pix_format *pix_output)
+{
+	isp_release_resources();
+	if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
+	     || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
+	    && pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10) {
+		isp_obj.module.isp_pipeline = OMAP_ISP_CCDC | OMAP_ISP_PREVIEW |
+							OMAP_ISP_RESIZER;
+		ispccdc_request();
+		isppreview_request();
+		ispresizer_request();
+		ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP);
+		isppreview_config_datapath(PRV_RAW_CCDC, PREVIEW_MEM);
+		ispresizer_config_datapath(RSZ_MEM_YUV);
+	} else {
+		isp_obj.module.isp_pipeline = OMAP_ISP_CCDC;
+		ispccdc_request();
+		if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
+		    || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
+			ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP_MEM);
+		else
+			ispccdc_config_datapath(CCDC_YUV_SYNC,
+							CCDC_OTHERS_MEM);
+	}
+	return 0;
+}
+
+/**
+ * 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.
+ **/
+static void isp_config_pipeline(struct v4l2_pix_format *pix_input,
+				struct v4l2_pix_format *pix_output)
+{
+	ispccdc_config_size(isp_obj.module.ccdc_input_width,
+			isp_obj.module.ccdc_input_height,
+			isp_obj.module.ccdc_output_width,
+			isp_obj.module.ccdc_output_height);
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
+		isppreview_config_size(isp_obj.module.preview_input_width,
+			isp_obj.module.preview_input_height,
+			isp_obj.module.preview_output_width,
+			isp_obj.module.preview_output_height);
+	}
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
+		ispresizer_config_size(isp_obj.module.resizer_input_width,
+					isp_obj.module.resizer_input_height,
+					isp_obj.module.resizer_output_width,
+					isp_obj.module.resizer_output_height);
+	}
+
+	if (pix_output->pixelformat == V4L2_PIX_FMT_UYVY) {
+		isppreview_config_ycpos(YCPOS_YCrYCb);
+		if (is_ispresizer_enabled())
+			ispresizer_config_ycpos(0);
+	} else {
+		isppreview_config_ycpos(YCPOS_CrYCbY);
+		if (is_ispresizer_enabled())
+			ispresizer_config_ycpos(1);
+	}
+
+	return;
+}
+
+static void isp_buf_init(void)
+{
+	struct isp_bufs *bufs = &isp_obj.bufs;
+	int sg;
+
+	bufs->queue = 0;
+	bufs->done = 0;
+	bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
+	for (sg = 0; sg < NUM_BUFS; sg++) {
+		bufs->buf[sg].complete = NULL;
+		bufs->buf[sg].vb = NULL;
+		bufs->buf[sg].priv = NULL;
+	}
+}
+
+/**
+ * isp_vbq_sync - Walks the pages table and flushes the cache for
+ *                each page.
+ **/
+static int isp_vbq_sync(struct videobuf_buffer *vb, int when)
+{
+	flush_cache_all();
+
+	return 0;
+}
+
+static int isp_buf_process(struct isp_bufs *bufs)
+{
+	struct isp_buf *buf = NULL;
+	unsigned long flags;
+	int last;
+
+	spin_lock_irqsave(&bufs->lock, flags);
+
+	if (ISP_BUFS_IS_EMPTY(bufs))
+		goto out;
+
+	if (RAW_CAPTURE(&isp_obj) && ispccdc_sbl_wait_idle(1000)) {
+		printk(KERN_ERR "ccdc %d won't become idle!\n",
+		       RAW_CAPTURE(&isp_obj));
+		goto out;
+	}
+
+	/* We had at least one buffer in queue. */
+	buf = ISP_BUF_DONE(bufs);
+	last = ISP_BUFS_IS_LAST(bufs);
+
+	if (!last) {
+		/* Set new buffer address. */
+		isp_set_buf(ISP_BUF_NEXT_DONE(bufs));
+	} else {
+		/* Tell ISP not to write any of our buffers. */
+		isp_disable_interrupts();
+		if (RAW_CAPTURE(&isp_obj))
+			ispccdc_enable(0);
+		else
+			ispresizer_enable(0);
+		/*
+		 * We must wait for the HS_VS since before that the
+		 * CCDC may trigger interrupts even if it's not
+		 * receiving a frame.
+		 */
+		bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
+	}
+	if ((RAW_CAPTURE(&isp_obj) && ispccdc_busy())
+	    || (!RAW_CAPTURE(&isp_obj) && ispresizer_busy())) {
+		/*
+		 * Next buffer available: for the transfer to succeed, the
+		 * CCDC (RAW capture) or resizer (YUV capture) must be idle
+		 * for the duration of transfer setup. Bad things happen
+		 * otherwise!
+		 *
+		 * Next buffer not available: if we fail to stop the
+		 * ISP the buffer is probably going to be bad.
+		 */
+		/* Mark this buffer faulty. */
+		buf->vb_state = VIDEOBUF_ERROR;
+		/* Mark next faulty, too, in case we have one. */
+		if (!last) {
+			ISP_BUF_NEXT_DONE(bufs)->vb_state =
+				VIDEOBUF_ERROR;
+			printk(KERN_ALERT "OUCH!!!\n");
+		} else {
+			printk(KERN_ALERT "Ouch!\n");
+		}
+	}
+
+	/* Mark the current buffer as done. */
+	ISP_BUF_MARK_DONE(bufs);
+
+	DPRINTK_ISPCTRL(KERN_ALERT "%s: finish %d mmu %p\n", __func__,
+	       (bufs->done - 1 + NUM_BUFS) % NUM_BUFS,
+	       (bufs->buf+((bufs->done - 1 + NUM_BUFS) % NUM_BUFS))->isp_addr);
+
+out:
+	spin_unlock_irqrestore(&bufs->lock, flags);
+
+	if (buf != NULL) {
+		/*
+		 * We want to dequeue a buffer from the video buffer
+		 * queue. Let's do it!
+		 */
+		isp_vbq_sync(buf->vb, DMA_FROM_DEVICE);
+		buf->vb->state = buf->vb_state;
+		buf->complete(buf->vb, buf->priv);
+	}
+
+	return 0;
+}
+
+int isp_buf_queue(struct videobuf_buffer *vb,
+		  void (*complete)(struct videobuf_buffer *vb, void *priv),
+		  void *priv)
+{
+	unsigned long flags;
+	struct isp_buf *buf;
+	struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+	const struct scatterlist *sglist = dma->sglist;
+	struct isp_bufs *bufs = &isp_obj.bufs;
+	int sglen = dma->sglen;
+
+	BUG_ON(sglen < 0 || !sglist);
+
+	isp_vbq_sync(vb, DMA_TO_DEVICE);
+
+	spin_lock_irqsave(&bufs->lock, flags);
+
+	BUG_ON(ISP_BUFS_IS_FULL(bufs));
+
+	buf = ISP_BUF_QUEUE(bufs);
+
+	buf->isp_addr = bufs->isp_addr_capture[vb->i];
+	buf->complete = complete;
+	buf->vb = vb;
+	buf->priv = priv;
+	buf->vb_state = VIDEOBUF_DONE;
+
+	if (ISP_BUFS_IS_EMPTY(bufs)) {
+		isp_enable_interrupts(RAW_CAPTURE(&isp_obj));
+		isp_set_buf(buf);
+		ispccdc_enable(1);
+		isp_start();
+	}
+
+	ISP_BUF_MARK_QUEUED(bufs);
+
+	spin_unlock_irqrestore(&bufs->lock, flags);
+
+	DPRINTK_ISPCTRL(KERN_ALERT "%s: queue %d vb %d, mmu %p\n", __func__,
+	       (bufs->queue - 1 + NUM_BUFS) % NUM_BUFS, vb->i,
+	       buf->isp_addr);
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_buf_queue);
+
+int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
+		  unsigned int *size)
+{
+	int rval = 0;
+	size_t tmp_size = PAGE_ALIGN(isp_obj.module.preview_output_width
+				     * isp_obj.module.preview_output_height
+				     * ISP_BYTES_PER_PIXEL);
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW
+	    && isp_obj.tmp_buf_size < tmp_size)
+		rval = isp_tmp_buf_alloc(tmp_size);
+
+	return rval;
+}
+EXPORT_SYMBOL(isp_vbq_setup);
+
+/**
+ * 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;
+	struct isp_bufs *bufs = &isp_obj.bufs;
+
+	int err = 0;
+
+	vdma = videobuf_to_dma(vb);
+
+	isp_addr = ispmmu_vmap(vdma->sglist, vdma->sglen);
+
+	if (IS_ERR_VALUE(isp_addr))
+		err = -EIO;
+	else
+		bufs->isp_addr_capture[vb->i] = isp_addr;
+
+	return err;
+}
+EXPORT_SYMBOL(isp_vbq_prepare);
+
+/**
+ * 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)
+{
+	struct isp_bufs *bufs = &isp_obj.bufs;
+
+	ispmmu_vunmap(bufs->isp_addr_capture[vb->i]);
+	bufs->isp_addr_capture[vb->i] = (dma_addr_t)NULL;
+	return;
+}
+EXPORT_SYMBOL(isp_vbq_release);
+
+/**
+ * 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;
+
+	if (a->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+		a->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
+		i = find_next_vctrl(a->id);
+	} else {
+		i = find_vctrl(a->id);
+	}
+
+	if (i < 0)
+		return -EINVAL;
+
+	*a = video_control[i].qc;
+	return 0;
+}
+EXPORT_SYMBOL(isp_queryctrl);
+
+/**
+ * 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_querymenu(struct v4l2_querymenu *a)
+{
+	int i;
+
+	i = find_vmenu(a->id, a->index);
+
+	if (i < 0)
+		return -EINVAL;
+
+	*a = video_menu[i];
+	return 0;
+}
+EXPORT_SYMBOL(isp_querymenu);
+
+/**
+ * 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)
+{
+	u8 current_value;
+	int rval = 0;
+
+	if (!isp_obj.ref_count)
+		return -EINVAL;
+
+	switch (a->id) {
+	case V4L2_CID_BRIGHTNESS:
+		isppreview_query_brightness(&current_value);
+		a->value = current_value / ISPPRV_BRIGHT_UNITS;
+		break;
+	case V4L2_CID_CONTRAST:
+		isppreview_query_contrast(&current_value);
+		a->value = current_value / ISPPRV_CONTRAST_UNITS;
+		break;
+	case V4L2_CID_COLORFX:
+		isppreview_get_color(&current_value);
+		a->value = current_value;
+		break;
+	default:
+		rval = -EINVAL;
+		break;
+	}
+
+	return rval;
+}
+EXPORT_SYMBOL(isp_g_ctrl);
+
+/**
+ * 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;
+	u8 new_value = a->value;
+
+	if (!isp_obj.ref_count)
+		return -EINVAL;
+
+	switch (a->id) {
+	case V4L2_CID_BRIGHTNESS:
+		if (new_value > ISPPRV_BRIGHT_HIGH)
+			rval = -EINVAL;
+		else
+			isppreview_update_brightness(&new_value);
+		break;
+	case V4L2_CID_CONTRAST:
+		if (new_value > ISPPRV_CONTRAST_HIGH)
+			rval = -EINVAL;
+		else
+			isppreview_update_contrast(&new_value);
+		break;
+	case V4L2_CID_COLORFX:
+		if (new_value > V4L2_COLORFX_SEPIA)
+			rval = -EINVAL;
+		else
+			isppreview_set_color(&new_value);
+		break;
+	default:
+		rval = -EINVAL;
+		break;
+	}
+
+	return rval;
+}
+EXPORT_SYMBOL(isp_s_ctrl);
+
+/**
+ * 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;
+
+	if (!isp_obj.ref_count)
+		return -EINVAL;
+
+	switch (cmd) {
+	case VIDIOC_PRIVATE_ISP_CCDC_CFG:
+		rval = omap34xx_isp_ccdc_config(arg);
+		break;
+	case VIDIOC_PRIVATE_ISP_PRV_CFG:
+		rval = omap34xx_isp_preview_config(arg);
+		break;
+	case VIDIOC_PRIVATE_ISP_AEWB_CFG: {
+		struct isph3a_aewb_config *params;
+		params = (struct isph3a_aewb_config *)arg;
+		rval = isph3a_aewb_configure(params);
+		}
+		break;
+	case VIDIOC_PRIVATE_ISP_AEWB_REQ: {
+		struct isph3a_aewb_data *data;
+		data = (struct isph3a_aewb_data *)arg;
+		rval = isph3a_aewb_request_statistics(data);
+		}
+		break;
+	case VIDIOC_PRIVATE_ISP_HIST_CFG: {
+		struct isp_hist_config *params;
+		params = (struct isp_hist_config *)arg;
+		rval = isp_hist_configure(params);
+		}
+		break;
+	case VIDIOC_PRIVATE_ISP_HIST_REQ: {
+		struct isp_hist_data *data;
+		data = (struct isp_hist_data *)arg;
+		rval = isp_hist_request_statistics(data);
+		}
+		break;
+	case VIDIOC_PRIVATE_ISP_AF_CFG: {
+		struct af_configuration *params;
+		params = (struct af_configuration *)arg;
+		rval = isp_af_configure(params);
+		}
+		break;
+	case VIDIOC_PRIVATE_ISP_AF_REQ: {
+		struct isp_af_data *data;
+		data = (struct isp_af_data *)arg;
+		rval = isp_af_request_statistics(data);
+		}
+		break;
+	default:
+		rval = -EINVAL;
+		break;
+	}
+	return rval;
+}
+EXPORT_SYMBOL(isp_handle_private);
+
+/**
+ * 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_pix_format *pix)
+{
+	*pix = isp_obj.module.pix;
+	return;
+}
+EXPORT_SYMBOL(isp_g_fmt_cap);
+
+/**
+ * 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 = 0, crop_scaling_h = 0;
+	int rval = 0;
+
+	if (!isp_obj.ref_count)
+		return -EINVAL;
+
+	rval = isp_calc_pipeline(pix_input, pix_output);
+	if (rval)
+		goto out;
+
+	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 ((isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) &&
+	    (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;
+	unsigned long org_left, num_pix, new_top;
+
+	struct v4l2_pix_format *pix = croppix;
+
+	crop_scaling_w = (isp_obj.module.preview_output_width * 10) /
+								pix->width;
+	crop_scaling_h = (isp_obj.module.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;
+
+	org_left = cur_rect.left;
+	while (((int)cur_rect.left & 0xFFFFFFF0) != (int)cur_rect.left)
+		(int)cur_rect.left--;
+
+	num_pix = org_left - cur_rect.left;
+	new_top = (int)(num_pix * 3) / 4;
+	cur_rect.top = cur_rect.top - new_top;
+	cur_rect.height = (2 * new_top) + cur_rect.height;
+
+	cur_rect.width = cur_rect.width + (2 * num_pix);
+	while (((int)cur_rect.width & 0xFFFFFFF0) != (int)cur_rect.width)
+		(int)cur_rect.width--;
+
+	isp_obj.tmp_buf_offset = ((cur_rect.left * 2) +
+		((isp_obj.module.preview_output_width) * 2 * cur_rect.top));
+
+	ispresizer_trycrop(cur_rect.left, cur_rect.top, cur_rect.width,
+					cur_rect.height,
+					isp_obj.module.resizer_output_width,
+					isp_obj.module.resizer_output_height);
+
+	return;
+}
+EXPORT_SYMBOL(isp_config_crop);
+
+/**
+ * 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;
+}
+EXPORT_SYMBOL(isp_g_crop);
+
+/**
+ * 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 (!isp_obj.ref_count)
+		return -EINVAL;
+
+	if (crop->c.left < 0)
+		crop->c.left = 0;
+	if (crop->c.width < 0)
+		crop->c.width = 0;
+	if (crop->c.top < 0)
+		crop->c.top = 0;
+	if (crop->c.height < 0)
+		crop->c.height = 0;
+
+	if (crop->c.left >= pix->width)
+		crop->c.left = pix->width - 1;
+	if (crop->c.top >= pix->height)
+		crop->c.top = pix->height - 1;
+
+	if (crop->c.left + crop->c.width > pix->width)
+		crop->c.width = pix->width - crop->c.left;
+	if (crop->c.top + crop->c.height > pix->height)
+		crop->c.height = pix->height - crop->c.top;
+
+	ispcroprect.left = crop->c.left;
+	ispcroprect.top = crop->c.top;
+	ispcroprect.width = crop->c.width;
+	ispcroprect.height = crop->c.height;
+
+	isp_config_crop(pix);
+
+	isp_obj.module.applyCrop = 1;
+
+	return rval;
+}
+EXPORT_SYMBOL(isp_s_crop);
+
+/**
+ * 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;
+
+	rval = isp_calc_pipeline(pix_input, pix_output);
+	if (rval)
+		goto out;
+
+	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.
+ **/
+static int isp_try_size(struct v4l2_pix_format *pix_input,
+			struct v4l2_pix_format *pix_output)
+{
+	int rval = 0;
+
+	if ((pix_output->width <= ISPRSZ_MIN_OUTPUT) ||
+				(pix_output->height <= ISPRSZ_MIN_OUTPUT))
+		return -EINVAL;
+
+	if ((pix_output->width >= ISPRSZ_MAX_OUTPUT) ||
+				(pix_output->height > ISPRSZ_MAX_OUTPUT))
+		return -EINVAL;
+
+	isp_obj.module.ccdc_input_width = pix_input->width;
+	isp_obj.module.ccdc_input_height = pix_input->height;
+	isp_obj.module.resizer_output_width = pix_output->width;
+	isp_obj.module.resizer_output_height = pix_output->height;
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC) {
+		rval = ispccdc_try_size(isp_obj.module.ccdc_input_width,
+					isp_obj.module.ccdc_input_height,
+					&isp_obj.module.ccdc_output_width,
+					&isp_obj.module.ccdc_output_height);
+		if (rval) {
+			printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
+					" supported\n", pix_input->width,
+					pix_input->height);
+			return rval;
+		}
+		pix_output->width = isp_obj.module.ccdc_output_width;
+		pix_output->height = isp_obj.module.ccdc_output_height;
+	}
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
+		isp_obj.module.preview_input_width =
+					isp_obj.module.ccdc_output_width;
+		isp_obj.module.preview_input_height =
+					isp_obj.module.ccdc_output_height;
+		rval = isppreview_try_size(isp_obj.module.preview_input_width,
+					isp_obj.module.preview_input_height,
+					&isp_obj.module.preview_output_width,
+					&isp_obj.module.preview_output_height);
+		if (rval) {
+			printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
+					" supported\n", pix_input->width,
+					pix_input->height);
+			return rval;
+		}
+		pix_output->width = isp_obj.module.preview_output_width;
+		pix_output->height = isp_obj.module.preview_output_height;
+	}
+
+	if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
+		isp_obj.module.resizer_input_width =
+					isp_obj.module.preview_output_width;
+		isp_obj.module.resizer_input_height =
+					isp_obj.module.preview_output_height;
+		rval = ispresizer_try_size(&isp_obj.module.resizer_input_width,
+					&isp_obj.module.resizer_input_height,
+					&isp_obj.module.resizer_output_width,
+					&isp_obj.module.resizer_output_height);
+		if (rval) {
+			printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
+					" supported\n", pix_input->width,
+					pix_input->height);
+			return rval;
+		}
+		pix_output->width = isp_obj.module.resizer_output_width;
+		pix_output->height = isp_obj.module.resizer_output_height;
+	}
+
+	return rval;
+}
+
+/**
+ * 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 =
+		PAGE_ALIGN(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;
+	}
+
+	isp_obj.module.pix.pixelformat = pix_output->pixelformat;
+	isp_obj.module.pix.width = pix_output->width;
+	isp_obj.module.pix.height = pix_output->height;
+	isp_obj.module.pix.field = pix_output->field;
+	isp_obj.module.pix.bytesperline = pix_output->bytesperline;
+	isp_obj.module.pix.sizeimage = pix_output->sizeimage;
+	isp_obj.module.pix.priv = pix_output->priv;
+	isp_obj.module.pix.colorspace = pix_output->colorspace;
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_try_fmt);
+
+/**
+ * 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.
+ **/
+static void isp_save_ctx(void)
+{
+	isp_save_context(isp_reg_list);
+	ispccdc_save_context();
+	ispmmu_save_context();
+	isphist_save_context();
+	isph3a_save_context();
+	isppreview_save_context();
+	ispresizer_save_context();
+}
+
+/**
+ * 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.
+ **/
+static void isp_restore_ctx(void)
+{
+	isp_restore_context(isp_reg_list);
+	ispccdc_restore_context();
+	ispmmu_restore_context();
+	isphist_restore_context();
+	isph3a_restore_context();
+	isppreview_restore_context();
+	ispresizer_restore_context();
+}
+
+/**
+ * isp_get - Adquires the ISP resource.
+ *
+ * Initializes the clocks for the first acquire.
+ **/
+int isp_get(void)
+{
+	static int has_context = 0;
+	int ret_err = 0;
+
+	if (omap3isp == NULL)
+		return -EBUSY;
+
+	DPRINTK_ISPCTRL("isp_get: old %d\n", isp_obj.ref_count);
+	mutex_lock(&(isp_obj.isp_mutex));
+	if (isp_obj.ref_count == 0) {
+		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;
+		}
+		ret_err = clk_enable(isp_obj.csi2_fck);
+		if (ret_err) {
+			DPRINTK_ISPCTRL("ISP_ERR: clk_en for csi2_fclk"
+								" failed\n");
+			goto out_clk_enable_csi2_fclk;
+		}
+
+		/* We don't want to restore context before saving it! */
+		if (has_context)
+			isp_restore_ctx();
+		else
+			has_context = 1;
+	} else {
+		mutex_unlock(&isp_obj.isp_mutex);
+		return -EBUSY;
+	}
+	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_csi2_fclk:
+	clk_disable(isp_obj.cam_mclk);
+out_clk_enable_mclk:
+	clk_disable(isp_obj.cam_ick);
+out_clk_enable_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)
+{
+	if (omap3isp == NULL)
+		return -EBUSY;
+
+	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();
+			isp_tmp_buf_free();
+			isp_release_resources();
+			isp_obj.module.isp_pipeline = 0;
+			clk_disable(isp_obj.cam_ick);
+			clk_disable(isp_obj.cam_mclk);
+			clk_disable(isp_obj.csi2_fck);
+			memset(&ispcroprect, 0, sizeof(ispcroprect));
+			memset(&cur_rect, 0, sizeof(cur_rect));
+		}
+	}
+	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 = isp_reg_readl(next->mmio_range, 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++)
+		isp_reg_writel(next->val, next->mmio_range, next->reg);
+}
+EXPORT_SYMBOL(isp_restore_context);
+
+static int isp_remove(struct platform_device *pdev)
+{
+	struct isp_device *isp = platform_get_drvdata(pdev);
+	int i;
+
+	isp_csi2_cleanup();
+	isp_af_exit();
+	isp_resizer_cleanup();
+	isp_preview_cleanup();
+	ispmmu_cleanup();
+	isph3a_aewb_cleanup();
+	isp_hist_cleanup();
+	isp_ccdc_cleanup();
+
+	if (!isp)
+		return 0;
+
+	clk_put(isp_obj.cam_ick);
+	clk_put(isp_obj.cam_mclk);
+	clk_put(isp_obj.csi2_fck);
+
+	free_irq(isp->irq, &isp_obj);
+
+	for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
+		if (isp->mmio_base[i]) {
+			iounmap((void *)isp->mmio_base[i]);
+			isp->mmio_base[i] = 0;
+		}
+
+		if (isp->mmio_base_phys[i]) {
+			release_mem_region(isp->mmio_base_phys[i],
+						isp->mmio_size[i]);
+			isp->mmio_base_phys[i] = 0;
+		}
+	}
+
+	omap3isp = NULL;
+
+	kfree(isp);
+
+	return 0;
+}
+
+static int isp_probe(struct platform_device *pdev)
+{
+	struct isp_device *isp;
+	int ret_err = 0;
+	int i;
+
+	isp = kzalloc(sizeof(*isp), GFP_KERNEL);
+	if (!isp) {
+		dev_err(&pdev->dev, "could not allocate memory\n");
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, isp);
+
+	isp->dev = &pdev->dev;
+
+	for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
+		struct resource *mem;
+		/* request the mem region for the camera registers */
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!mem) {
+			dev_err(isp->dev, "no mem resource?\n");
+			return -ENODEV;
+		}
+
+		if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
+					pdev->name)) {
+			dev_err(isp->dev,
+				"cannot reserve camera register I/O region\n");
+			return -ENODEV;
+
+		}
+		isp->mmio_base_phys[i] = mem->start;
+		isp->mmio_size[i] = (mem->end - mem->start) + 1;
+
+		/* map the region */
+		isp->mmio_base[i] = (unsigned long)
+				ioremap_nocache(isp->mmio_base_phys[i],
+				isp->mmio_size[i]);
+		if (!isp->mmio_base[i]) {
+			dev_err(isp->dev,
+				"cannot map camera register I/O region\n");
+			return -ENODEV;
+		}
+	}
+
+	isp->irq = platform_get_irq(pdev, 0);
+	if (isp->irq <= 0) {
+		dev_err(isp->dev, "no irq for camera?\n");
+		return -ENODEV;
+	}
+
+	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");
+		return PTR_ERR(isp_obj.cam_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;
+	}
+	isp_obj.csi2_fck = clk_get(&camera_dev, "csi2_96m_fck");
+	if (IS_ERR(isp_obj.csi2_fck)) {
+		DPRINTK_ISPCTRL("ISP_ERR: clk_get for csi2_fclk"
+				" failed\n");
+		ret_err = PTR_ERR(isp_obj.csi2_fck);
+		goto out_clk_get_csi2_fclk;
+	}
+
+	if (request_irq(isp->irq, omap34xx_isp_isr, IRQF_SHARED,
+				"Omap 3 Camera ISP", &isp_obj)) {
+		DPRINTK_ISPCTRL("Could not install ISR\n");
+		ret_err = -EINVAL;
+		goto out_request_irq;
+	}
+
+	isp_obj.ref_count = 0;
+
+	mutex_init(&(isp_obj.isp_mutex));
+	spin_lock_init(&isp_obj.lock);
+	spin_lock_init(&isp_obj.bufs.lock);
+
+	omap3isp = isp;
+
+	ret_err = ispmmu_init();
+	if (ret_err)
+		goto out_ispmmu_init;
+
+	isp_ccdc_init();
+	isp_hist_init();
+	isph3a_aewb_init();
+	isp_preview_init();
+	isp_resizer_init();
+	isp_af_init();
+	isp_csi2_init();
+
+	isp_get();
+	isp_power_settings(1);
+	isp_put();
+
+	isph3a_notify(1);
+	isp_af_notify(1);
+
+	return 0;
+
+out_ispmmu_init:
+	omap3isp = NULL;
+	free_irq(isp->irq, &isp_obj);
+out_request_irq:
+	clk_put(isp_obj.csi2_fck);
+out_clk_get_csi2_fclk:
+	clk_put(isp_obj.cam_mclk);
+out_clk_get_mclk:
+	clk_put(isp_obj.cam_ick);
+
+	return ret_err;
+}
+
+static struct platform_driver omap3isp_driver = {
+	.probe = isp_probe,
+	.remove = isp_remove,
+	.driver = {
+		   .name = "omap3isp",
+		   },
+};
+
+/**
+ * isp_init - ISP module initialization.
+ **/
+static int __init isp_init(void)
+{
+	return platform_driver_register(&omap3isp_driver);
+}
+
+/**
+ * isp_cleanup - ISP module cleanup.
+ **/
+static void __exit isp_cleanup(void)
+{
+	platform_driver_unregister(&omap3isp_driver);
+}
+
+/**
+ * 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("###ISP_CTRL=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
+	DPRINTK_ISPCTRL("###ISP_TCTRL_CTRL=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
+	DPRINTK_ISPCTRL("###ISP_SYSCONFIG=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG));
+	DPRINTK_ISPCTRL("###ISP_SYSSTATUS=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS));
+	DPRINTK_ISPCTRL("###ISP_IRQ0ENABLE=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
+	DPRINTK_ISPCTRL("###ISP_IRQ0STATUS=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
+}
+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");
diff --git a/drivers/media/video/isp/isp.h b/drivers/media/video/isp/isp.h
new file mode 100644
index 0000000..bfbbc5f
--- /dev/null
+++ b/drivers/media/video/isp/isp.h
@@ -0,0 +1,318 @@
+/*
+ * isp.h
+ *
+ * Top level public header file for ISP Control module in
+ * TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2009 Nokia.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@ti.com>
+ * 	Mohit Jalori <mjalori@ti.com>
+ * 	Sergio Aguirre <saaguirre@ti.com>
+ * 	Sakari Ailus <sakari.ailus@nokia.com>
+ * 	Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *
+ * 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 <mach/cpu.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)
+
+#define ISP_TOK_TERM		0xFFFFFFFF	/*
+						 * terminating token for ISP
+						 * modules reg list
+						 */
+#define NUM_BUFS		VIDEO_MAX_FRAME
+
+#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
+
+#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_mem_resources {
+	OMAP3_ISP_IOMEM_MAIN,
+	OMAP3_ISP_IOMEM_CBUFF,
+	OMAP3_ISP_IOMEM_CCP2,
+	OMAP3_ISP_IOMEM_CCDC,
+	OMAP3_ISP_IOMEM_HIST,
+	OMAP3_ISP_IOMEM_H3A,
+	OMAP3_ISP_IOMEM_PREV,
+	OMAP3_ISP_IOMEM_RESZ,
+	OMAP3_ISP_IOMEM_SBL,
+	OMAP3_ISP_IOMEM_CSI2A,
+	OMAP3_ISP_IOMEM_CSI2PHY
+};
+
+struct isp_device {
+	struct device *dev;
+
+	/*** platform HW resources ***/
+	unsigned int irq;
+
+#define mmio_base_main mmio_base[OMAP3_ISP_IOMEM_MAIN]
+#define mmio_cbuff_main mmio_base[OMAP3_ISP_IOMEM_CBUFF]
+#define mmio_ccp2_main mmio_base[OMAP3_ISP_IOMEM_CCP2]
+#define mmio_ccdc_main mmio_base[OMAP3_ISP_IOMEM_CCDC]
+#define mmio_hist_main mmio_base[OMAP3_ISP_IOMEM_HIST]
+#define mmio_h3a_main mmio_base[OMAP3_ISP_IOMEM_H3A]
+#define mmio_prev_main mmio_base[OMAP3_ISP_IOMEM_PREV]
+#define mmio_resz_main mmio_base[OMAP3_ISP_IOMEM_RESZ]
+#define mmio_sbl_main mmio_base[OMAP3_ISP_IOMEM_SBL]
+#define mmio_csi2_main mmio_base[OMAP3_ISP_IOMEM_CSI2A]
+#define mmio_csi2phy_main mmio_base[OMAP3_ISP_IOMEM_CSI2PHY]
+	unsigned long mmio_base[OMAP3_ISP_IOMEM_CSI2PHY + 1];
+	unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_CSI2PHY + 1];
+	unsigned long mmio_size[OMAP3_ISP_IOMEM_CSI2PHY + 1];
+};
+
+enum isp_interface_type {
+	ISP_PARLL = 1,
+	ISP_CSIA = 2,
+	ISP_CSIB = 4,
+	ISP_NONE = 8 /* memory input to preview / resizer */
+};
+
+enum isp_irqevents {
+	CSIA = 0x01,
+	CSIB = 0x10,
+	CCDC_VD0 = 0x100,
+	CCDC_VD1 = 0x200,
+	CCDC_VD2 = 0x400,
+	CCDC_ERR = 0x800,
+	H3A_AWB_DONE = 0x2000,
+	H3A_AF_DONE = 0x1000,
+	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,
+	CBK_H3A_AF_DONE,
+	CBK_CATCHALL,
+	CBK_CSIA,
+	CBK_CSIB,
+	CBK_END,
+};
+
+/**
+ * struct isp_reg - Structure for ISP register values.
+ * @reg: 32-bit Register address.
+ * @val: 32-bit Register value.
+ */
+struct isp_reg {
+	enum isp_mem_resources mmio_range;
+	u32 reg;
+	u32 val;
+};
+
+/**
+ * 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
+ * @strobe: Strobe related parameter.
+ * @prestrobe: PreStrobe related parameter.
+ * @shutter: Shutter related parameter.
+ * @hskip: Horizontal Start Pixel performed in Preview module.
+ * @vskip: Vertical Start Line performed in Preview module.
+ * @wenlog: Store the value for the sensor specific wenlog field.
+ * @wait_hs_vs: Wait for this many hs_vs before anything else in the beginning.
+ */
+struct isp_interface_config {
+	enum isp_interface_type ccdc_par_ser;
+	u8 dataline_shift;
+	u32 hsvs_syncdetect;
+	int strobe;
+	int prestrobe;
+	int shutter;
+	u32 prev_sph;
+	u32 prev_slv;
+	u32 wenlog;
+	int wait_hs_vs;
+	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;
+};
+
+u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset);
+
+void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
+						u32 reg_offset);
+
+static inline void isp_reg_and(enum isp_mem_resources mmio_range, u32 reg,
+						u32 and_bits)
+{
+	u32 v = isp_reg_readl(mmio_range, reg);
+
+	isp_reg_writel(v & and_bits, mmio_range, reg);
+}
+
+static inline void isp_reg_or(enum isp_mem_resources mmio_range, u32 reg,
+						u32 or_bits)
+{
+	u32 v = isp_reg_readl(mmio_range, reg);
+
+	isp_reg_writel(v | or_bits, mmio_range, reg);
+}
+
+static inline void isp_reg_and_or(enum isp_mem_resources mmio_range, u32 reg,
+						u32 and_bits, u32 or_bits)
+{
+	u32 v = isp_reg_readl(mmio_range, reg);
+
+	isp_reg_writel((v & and_bits) | or_bits, mmio_range, reg);
+}
+
+void isp_start(void);
+
+void isp_stop(void);
+
+int isp_buf_queue(struct videobuf_buffer *vb,
+		  void (*complete)(struct videobuf_buffer *vb, void *priv),
+		  void *priv);
+
+int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
+		  unsigned int *size);
+
+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);
+
+int isp_unset_callback(enum isp_callback_type type);
+
+u32 isp_set_xclk(u32 xclk, u8 xclksel);
+
+int isp_configure_interface(struct isp_interface_config *config);
+
+int isp_get(void);
+
+int isp_put(void);
+
+int isp_queryctrl(struct v4l2_queryctrl *a);
+
+int isp_querymenu(struct v4l2_querymenu *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_pix_format *pix);
+
+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_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_print_status(void);
+
+int __init isp_ccdc_init(void);
+int __init isp_hist_init(void);
+int __init isph3a_aewb_init(void);
+int __init isp_preview_init(void);
+int __init isp_resizer_init(void);
+int __init isp_af_init(void);
+int __init isp_csi2_init(void);
+
+void isp_ccdc_cleanup(void);
+void isp_hist_cleanup(void);
+void isph3a_aewb_cleanup(void);
+void isp_preview_cleanup(void);
+void isp_hist_cleanup(void);
+void isp_resizer_cleanup(void);
+void isp_af_exit(void);
+void isp_csi2_cleanup(void);
+
+#endif	/* OMAP_ISP_TOP_H */
diff --git a/drivers/media/video/isp/ispreg.h b/drivers/media/video/isp/ispreg.h
new file mode 100644
index 0000000..e6ef8c4
--- /dev/null
+++ b/drivers/media/video/isp/ispreg.h
@@ -0,0 +1,1673 @@
+/*
+ * ispreg.h
+ *
+ * Header file for all the ISP module in TI's OMAP3 Camera ISP.
+ * It has the OMAP HW register definitions.
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2009 Nokia.
+ *
+ * Contributors:
+ * 	Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *	Thara Gopinath <thara@ti.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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 __ISPREG_H__
+#define __ISPREG_H__
+
+#include <mach/omap34xx.h>
+
+/* Note: Uncomment below defines as needed for enabling module specific debug
+ * messages
+ */
+
+/*
+#define OMAP_ISPCTRL_DEBUG
+#define OMAP_ISPCCDC_DEBUG
+#define OMAP_ISPPREV_DEBUG
+#define OMAP_ISPRESZ_DEBUG
+#define OMAP_ISPMMU_DEBUG
+#define OMAP_ISPH3A_DEBUG
+#define OMAP_ISP_AF_DEBUG
+#define OMAP_ISPHIST_DEBUG
+*/
+
+#ifdef OMAP_ISPCTRL_DEBUG
+#define DPRINTK_ISPCTRL(format, ...)\
+	printk(KERN_INFO "ISPCTRL: " format, ## __VA_ARGS__)
+#define is_ispctrl_debug_enabled()		1
+#else
+#define DPRINTK_ISPCTRL(format, ...)
+#define is_ispctrl_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISPCCDC_DEBUG
+#define DPRINTK_ISPCCDC(format, ...)\
+	printk(KERN_INFO "ISPCCDC: " format, ## __VA_ARGS__)
+#define is_ispccdc_debug_enabled()		1
+#else
+#define DPRINTK_ISPCCDC(format, ...)
+#define is_ispccdc_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISPPREV_DEBUG
+#define DPRINTK_ISPPREV(format, ...)\
+	printk(KERN_INFO "ISPPREV: " format, ## __VA_ARGS__)
+#define is_ispprev_debug_enabled()		1
+#else
+#define DPRINTK_ISPPREV(format, ...)
+#define is_ispprev_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISPRESZ_DEBUG
+#define DPRINTK_ISPRESZ(format, ...)\
+	printk(KERN_INFO "ISPRESZ: " format, ## __VA_ARGS__)
+#define is_ispresz_debug_enabled()		1
+#else
+#define DPRINTK_ISPRESZ(format, ...)
+#define is_ispresz_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISPMMU_DEBUG
+#define DPRINTK_ISPMMU(format, ...)\
+	printk(KERN_INFO "ISPMMU: " format, ## __VA_ARGS__)
+#define is_ispmmu_debug_enabled()		1
+#else
+#define DPRINTK_ISPMMU(format, ...)
+#define is_ispmmu_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISPH3A_DEBUG
+#define DPRINTK_ISPH3A(format, ...)\
+	printk(KERN_INFO "ISPH3A: " format, ## __VA_ARGS__)
+#define is_isph3a_debug_enabled()		1
+#else
+#define DPRINTK_ISPH3A(format, ...)
+#define is_isph3a_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISP_AF_DEBUG
+#define DPRINTK_ISP_AF(format, ...)\
+	printk(KERN_INFO "ISP_AF: " format, ## __VA_ARGS__)
+#define is_isp_af_debug_enabled()		1
+#else
+#define DPRINTK_ISP_AF(format, ...)
+#define is_isp_af_debug_enabled()		0
+#endif
+
+#ifdef OMAP_ISPHIST_DEBUG
+#define DPRINTK_ISPHIST(format, ...)\
+	printk(KERN_INFO "ISPHIST: " format, ## __VA_ARGS__)
+#define is_isphist_debug_enabled()		1
+#else
+#define DPRINTK_ISPHIST(format, ...)
+#define is_isphist_debug_enabled()		0
+#endif
+
+#define ISP_32B_BOUNDARY_BUF		0xFFFFFFE0
+#define ISP_32B_BOUNDARY_OFFSET		0x0000FFE0
+
+#define CM_CAM_MCLK_HZ			216000000
+
+/* ISP Submodules offset */
+
+#define OMAP3ISP_REG_BASE		OMAP3430_ISP_BASE
+#define OMAP3ISP_REG(offset)		(OMAP3ISP_REG_BASE + (offset))
+
+#define OMAP3ISP_CBUFF_REG_OFFSET	0x0100
+#define OMAP3ISP_CBUFF_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_CBUFF_REG_OFFSET)
+#define OMAP3ISP_CBUFF_REG(offset)	(OMAP3ISP_CBUFF_REG_BASE + (offset))
+
+#define OMAP3ISP_CCP2_REG_OFFSET	0x0400
+#define OMAP3ISP_CCP2_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_CCP2_REG_OFFSET)
+#define OMAP3ISP_CCP2_REG(offset)	(OMAP3ISP_CCP2_REG_BASE + (offset))
+
+#define OMAP3ISP_CCDC_REG_OFFSET	0x0600
+#define OMAP3ISP_CCDC_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_CCDC_REG_OFFSET)
+#define OMAP3ISP_CCDC_REG(offset)	(OMAP3ISP_CCDC_REG_BASE + (offset))
+
+#define OMAP3ISP_HIST_REG_OFFSET	0x0A00
+#define OMAP3ISP_HIST_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_HIST_REG_OFFSET)
+#define OMAP3ISP_HIST_REG(offset)	(OMAP3ISP_HIST_REG_BASE + (offset))
+
+#define OMAP3ISP_H3A_REG_OFFSET		0x0C00
+#define OMAP3ISP_H3A_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_H3A_REG_OFFSET)
+#define OMAP3ISP_H3A_REG(offset)	(OMAP3ISP_H3A_REG_BASE + (offset))
+
+#define OMAP3ISP_PREV_REG_OFFSET	0x0E00
+#define OMAP3ISP_PREV_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_PREV_REG_OFFSET)
+#define OMAP3ISP_PREV_REG(offset)	(OMAP3ISP_PREV_REG_BASE + (offset))
+
+#define OMAP3ISP_RESZ_REG_OFFSET	0x1000
+#define OMAP3ISP_RESZ_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_RESZ_REG_OFFSET)
+#define OMAP3ISP_RESZ_REG(offset)	(OMAP3ISP_RESZ_REG_BASE + (offset))
+
+#define OMAP3ISP_SBL_REG_OFFSET		0x1200
+#define OMAP3ISP_SBL_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_SBL_REG_OFFSET)
+#define OMAP3ISP_SBL_REG(offset)	(OMAP3ISP_SBL_REG_BASE + (offset))
+
+#define OMAP3ISP_MMU_REG_OFFSET		0x1400
+#define OMAP3ISP_MMU_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_MMU_REG_OFFSET)
+#define OMAP3ISP_MMU_REG(offset)	(OMAP3ISP_MMU_REG_BASE + (offset))
+
+#define OMAP3ISP_CSI2A_REG_OFFSET	0x1800
+#define OMAP3ISP_CSI2A_REG_BASE		(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_CSI2A_REG_OFFSET)
+#define OMAP3ISP_CSI2A_REG(offset)	(OMAP3ISP_CSI2A_REG_BASE + (offset))
+
+#define OMAP3ISP_CSI2PHY_REG_OFFSET	0x1970
+#define OMAP3ISP_CSI2PHY_REG_BASE	(OMAP3ISP_REG_BASE + \
+						OMAP3ISP_CSI2PHY_REG_OFFSET)
+#define OMAP3ISP_CSI2PHY_REG(offset)	(OMAP3ISP_CSI2PHY_REG_BASE + (offset))
+
+/* ISP module register offset */
+
+#define ISP_REVISION			(0x000)
+#define ISP_SYSCONFIG			(0x004)
+#define ISP_SYSSTATUS			(0x008)
+#define ISP_IRQ0ENABLE			(0x00C)
+#define ISP_IRQ0STATUS			(0x010)
+#define ISP_IRQ1ENABLE			(0x014)
+#define ISP_IRQ1STATUS			(0x018)
+#define ISP_TCTRL_GRESET_LENGTH		(0x030)
+#define ISP_TCTRL_PSTRB_REPLAY		(0x034)
+#define ISP_CTRL			(0x040)
+#define ISP_SECURE			(0x044)
+#define ISP_TCTRL_CTRL			(0x050)
+#define ISP_TCTRL_FRAME			(0x054)
+#define ISP_TCTRL_PSTRB_DELAY		(0x058)
+#define ISP_TCTRL_STRB_DELAY		(0x05C)
+#define ISP_TCTRL_SHUT_DELAY		(0x060)
+#define ISP_TCTRL_PSTRB_LENGTH		(0x064)
+#define ISP_TCTRL_STRB_LENGTH		(0x068)
+#define ISP_TCTRL_SHUT_LENGTH		(0x06C)
+#define ISP_PING_PONG_ADDR		(0x070)
+#define ISP_PING_PONG_MEM_RANGE		(0x074)
+#define ISP_PING_PONG_BUF_SIZE		(0x078)
+
+/* CSI1 receiver registers (ES2.0) */
+#define ISPCSI1_REVISION		(0x000)
+#define ISPCSI1_SYSCONFIG		(0x004)
+#define ISPCSI1_SYSSTATUS		(0x008)
+#define ISPCSI1_LC01_IRQENABLE		(0x00C)
+#define ISPCSI1_LC01_IRQSTATUS		(0x010)
+#define ISPCSI1_LC23_IRQENABLE		(0x014)
+#define ISPCSI1_LC23_IRQSTATUS		(0x018)
+#define ISPCSI1_LCM_IRQENABLE		(0x02C)
+#define ISPCSI1_LCM_IRQSTATUS		(0x030)
+#define ISPCSI1_CTRL			(0x040)
+#define ISPCSI1_DBG			(0x044)
+#define ISPCSI1_GNQ			(0x048)
+#define ISPCSI1_LCx_CTRL(x)		((0x050)+0x30*(x))
+#define ISPCSI1_LCx_CODE(x)		((0x054)+0x30*(x))
+#define ISPCSI1_LCx_STAT_START(x)	((0x058)+0x30*(x))
+#define ISPCSI1_LCx_STAT_SIZE(x)	((0x05C)+0x30*(x))
+#define ISPCSI1_LCx_SOF_ADDR(x)		((0x060)+0x30*(x))
+#define ISPCSI1_LCx_EOF_ADDR(x)		((0x064)+0x30*(x))
+#define ISPCSI1_LCx_DAT_START(x)	((0x068)+0x30*(x))
+#define ISPCSI1_LCx_DAT_SIZE(x)		((0x06C)+0x30*(x))
+#define ISPCSI1_LCx_DAT_PING_ADDR(x)	((0x070)+0x30*(x))
+#define ISPCSI1_LCx_DAT_PONG_ADDR(x)	((0x074)+0x30*(x))
+#define ISPCSI1_LCx_DAT_OFST(x)		((0x078)+0x30*(x))
+#define ISPCSI1_LCM_CTRL		(0x1D0)
+#define ISPCSI1_LCM_VSIZE		(0x1D4)
+#define ISPCSI1_LCM_HSIZE		(0x1D8)
+#define ISPCSI1_LCM_PREFETCH		(0x1DC)
+#define ISPCSI1_LCM_SRC_ADDR		(0x1E0)
+#define ISPCSI1_LCM_SRC_OFST		(0x1E4)
+#define ISPCSI1_LCM_DST_ADDR		(0x1E8)
+#define ISPCSI1_LCM_DST_OFST		(0x1EC)
+#define ISP_CSIB_SYSCONFIG		ISPCSI1_SYSCONFIG
+#define ISP_CSIA_SYSCONFIG		ISPCSI2_SYSCONFIG
+
+/* ISP_CBUFF Registers */
+
+#define ISP_CBUFF_SYSCONFIG		(0x010)
+#define ISP_CBUFF_IRQENABLE		(0x01C)
+
+#define ISP_CBUFF0_CTRL			(0x020)
+#define ISP_CBUFF1_CTRL			(0x024)
+
+#define ISP_CBUFF0_START		(0x040)
+#define ISP_CBUFF1_START		(0x044)
+
+#define ISP_CBUFF0_END			(0x050)
+#define ISP_CBUFF1_END			(0x054)
+
+#define ISP_CBUFF0_WINDOWSIZE		(0x060)
+#define ISP_CBUFF1_WINDOWSIZE		(0x064)
+
+#define ISP_CBUFF0_THRESHOLD		(0x070)
+#define ISP_CBUFF1_THRESHOLD		(0x074)
+
+/* CCDC module register offset */
+
+#define ISPCCDC_PID			(0x000)
+#define ISPCCDC_PCR			(0x004)
+#define ISPCCDC_SYN_MODE		(0x008)
+#define ISPCCDC_HD_VD_WID		(0x00C)
+#define ISPCCDC_PIX_LINES		(0x010)
+#define ISPCCDC_HORZ_INFO		(0x014)
+#define ISPCCDC_VERT_START		(0x018)
+#define ISPCCDC_VERT_LINES		(0x01C)
+#define ISPCCDC_CULLING			(0x020)
+#define ISPCCDC_HSIZE_OFF		(0x024)
+#define ISPCCDC_SDOFST			(0x028)
+#define ISPCCDC_SDR_ADDR		(0x02C)
+#define ISPCCDC_CLAMP			(0x030)
+#define ISPCCDC_DCSUB			(0x034)
+#define ISPCCDC_COLPTN			(0x038)
+#define ISPCCDC_BLKCMP			(0x03C)
+#define ISPCCDC_FPC			(0x040)
+#define ISPCCDC_FPC_ADDR		(0x044)
+#define ISPCCDC_VDINT			(0x048)
+#define ISPCCDC_ALAW			(0x04C)
+#define ISPCCDC_REC656IF		(0x050)
+#define ISPCCDC_CFG			(0x054)
+#define ISPCCDC_FMTCFG			(0x058)
+#define ISPCCDC_FMT_HORZ		(0x05C)
+#define ISPCCDC_FMT_VERT		(0x060)
+#define ISPCCDC_FMT_ADDR0		(0x064)
+#define ISPCCDC_FMT_ADDR1		(0x068)
+#define ISPCCDC_FMT_ADDR2		(0x06C)
+#define ISPCCDC_FMT_ADDR3		(0x070)
+#define ISPCCDC_FMT_ADDR4		(0x074)
+#define ISPCCDC_FMT_ADDR5		(0x078)
+#define ISPCCDC_FMT_ADDR6		(0x07C)
+#define ISPCCDC_FMT_ADDR7		(0x080)
+#define ISPCCDC_PRGEVEN0		(0x084)
+#define ISPCCDC_PRGEVEN1		(0x088)
+#define ISPCCDC_PRGODD0			(0x08C)
+#define ISPCCDC_PRGODD1			(0x090)
+#define ISPCCDC_VP_OUT			(0x094)
+
+#define ISPCCDC_LSC_CONFIG		(0x098)
+#define ISPCCDC_LSC_INITIAL		(0x09C)
+#define ISPCCDC_LSC_TABLE_BASE		(0x0A0)
+#define ISPCCDC_LSC_TABLE_OFFSET	(0x0A4)
+
+/* SBL */
+#define ISPSBL_CCDC_WR_0		(0x028)
+#define ISPSBL_CCDC_WR_0_DATA_READY	(1 << 21)
+#define ISPSBL_CCDC_WR_1		(0x02C)
+#define ISPSBL_CCDC_WR_2		(0x030)
+#define ISPSBL_CCDC_WR_3		(0x034)
+
+/* Histogram registers */
+#define ISPHIST_PID			(0x000)
+#define ISPHIST_PCR			(0x004)
+#define ISPHIST_CNT			(0x008)
+#define ISPHIST_WB_GAIN			(0x00C)
+#define ISPHIST_R0_HORZ			(0x010)
+#define ISPHIST_R0_VERT			(0x014)
+#define ISPHIST_R1_HORZ			(0x018)
+#define ISPHIST_R1_VERT			(0x01C)
+#define ISPHIST_R2_HORZ			(0x020)
+#define ISPHIST_R2_VERT			(0x024)
+#define ISPHIST_R3_HORZ			(0x028)
+#define ISPHIST_R3_VERT			(0x02C)
+#define ISPHIST_ADDR			(0x030)
+#define ISPHIST_DATA			(0x034)
+#define ISPHIST_RADD			(0x038)
+#define ISPHIST_RADD_OFF		(0x03C)
+#define ISPHIST_H_V_INFO		(0x040)
+
+/* H3A module registers */
+#define ISPH3A_PID			(0x000)
+#define ISPH3A_PCR			(0x004)
+#define ISPH3A_AEWWIN1			(0x04C)
+#define ISPH3A_AEWINSTART		(0x050)
+#define ISPH3A_AEWINBLK			(0x054)
+#define ISPH3A_AEWSUBWIN		(0x058)
+#define ISPH3A_AEWBUFST			(0x05C)
+#define ISPH3A_AFPAX1			(0x008)
+#define ISPH3A_AFPAX2			(0x00C)
+#define ISPH3A_AFPAXSTART		(0x010)
+#define ISPH3A_AFIIRSH			(0x014)
+#define ISPH3A_AFBUFST			(0x018)
+#define ISPH3A_AFCOEF010		(0x01C)
+#define ISPH3A_AFCOEF032		(0x020)
+#define ISPH3A_AFCOEF054		(0x024)
+#define ISPH3A_AFCOEF076		(0x028)
+#define ISPH3A_AFCOEF098		(0x02C)
+#define ISPH3A_AFCOEF0010		(0x030)
+#define ISPH3A_AFCOEF110		(0x034)
+#define ISPH3A_AFCOEF132		(0x038)
+#define ISPH3A_AFCOEF154		(0x03C)
+#define ISPH3A_AFCOEF176		(0x040)
+#define ISPH3A_AFCOEF198		(0x044)
+#define ISPH3A_AFCOEF1010		(0x048)
+
+#define ISPPRV_PCR			(0x004)
+#define ISPPRV_HORZ_INFO		(0x008)
+#define ISPPRV_VERT_INFO		(0x00C)
+#define ISPPRV_RSDR_ADDR		(0x010)
+#define ISPPRV_RADR_OFFSET		(0x014)
+#define ISPPRV_DSDR_ADDR		(0x018)
+#define ISPPRV_DRKF_OFFSET		(0x01C)
+#define ISPPRV_WSDR_ADDR		(0x020)
+#define ISPPRV_WADD_OFFSET		(0x024)
+#define ISPPRV_AVE			(0x028)
+#define ISPPRV_HMED			(0x02C)
+#define ISPPRV_NF			(0x030)
+#define ISPPRV_WB_DGAIN			(0x034)
+#define ISPPRV_WBGAIN			(0x038)
+#define ISPPRV_WBSEL			(0x03C)
+#define ISPPRV_CFA			(0x040)
+#define ISPPRV_BLKADJOFF		(0x044)
+#define ISPPRV_RGB_MAT1			(0x048)
+#define ISPPRV_RGB_MAT2			(0x04C)
+#define ISPPRV_RGB_MAT3			(0x050)
+#define ISPPRV_RGB_MAT4			(0x054)
+#define ISPPRV_RGB_MAT5			(0x058)
+#define ISPPRV_RGB_OFF1			(0x05C)
+#define ISPPRV_RGB_OFF2			(0x060)
+#define ISPPRV_CSC0			(0x064)
+#define ISPPRV_CSC1			(0x068)
+#define ISPPRV_CSC2			(0x06C)
+#define ISPPRV_CSC_OFFSET		(0x070)
+#define ISPPRV_CNT_BRT			(0x074)
+#define ISPPRV_CSUP			(0x078)
+#define ISPPRV_SETUP_YC			(0x07C)
+#define ISPPRV_SET_TBL_ADDR		(0x080)
+#define ISPPRV_SET_TBL_DATA		(0x084)
+#define ISPPRV_CDC_THR0			(0x090)
+#define ISPPRV_CDC_THR1			(ISPPRV_CDC_THR0 + (0x4))
+#define ISPPRV_CDC_THR2			(ISPPRV_CDC_THR0 + (0x4) * 2)
+#define ISPPRV_CDC_THR3			(ISPPRV_CDC_THR0 + (0x4) * 3)
+
+#define ISPPRV_REDGAMMA_TABLE_ADDR	0x0000
+#define ISPPRV_GREENGAMMA_TABLE_ADDR	0x0400
+#define ISPPRV_BLUEGAMMA_TABLE_ADDR	0x0800
+#define ISPPRV_NF_TABLE_ADDR		0x0C00
+#define ISPPRV_YENH_TABLE_ADDR		0x1000
+#define ISPPRV_CFA_TABLE_ADDR		0x1400
+
+#define ISPPRV_MAXOUTPUT_WIDTH		1280
+#define ISPPRV_MAXOUTPUT_WIDTH_ES2	3300
+#define ISPRSZ_MIN_OUTPUT		64
+#define ISPRSZ_MAX_OUTPUT		3312
+
+/* Resizer module register offset */
+#define ISPRSZ_PID			(0x000)
+#define ISPRSZ_PCR			(0x004)
+#define ISPRSZ_CNT			(0x008)
+#define ISPRSZ_OUT_SIZE			(0x00C)
+#define ISPRSZ_IN_START			(0x010)
+#define ISPRSZ_IN_SIZE			(0x014)
+#define ISPRSZ_SDR_INADD		(0x018)
+#define ISPRSZ_SDR_INOFF		(0x01C)
+#define ISPRSZ_SDR_OUTADD		(0x020)
+#define ISPRSZ_SDR_OUTOFF		(0x024)
+#define ISPRSZ_HFILT10			(0x028)
+#define ISPRSZ_HFILT32			(0x02C)
+#define ISPRSZ_HFILT54			(0x030)
+#define ISPRSZ_HFILT76			(0x034)
+#define ISPRSZ_HFILT98			(0x038)
+#define ISPRSZ_HFILT1110		(0x03C)
+#define ISPRSZ_HFILT1312		(0x040)
+#define ISPRSZ_HFILT1514		(0x044)
+#define ISPRSZ_HFILT1716		(0x048)
+#define ISPRSZ_HFILT1918		(0x04C)
+#define ISPRSZ_HFILT2120		(0x050)
+#define ISPRSZ_HFILT2322		(0x054)
+#define ISPRSZ_HFILT2524		(0x058)
+#define ISPRSZ_HFILT2726		(0x05C)
+#define ISPRSZ_HFILT2928		(0x060)
+#define ISPRSZ_HFILT3130		(0x064)
+#define ISPRSZ_VFILT10			(0x068)
+#define ISPRSZ_VFILT32			(0x06C)
+#define ISPRSZ_VFILT54			(0x070)
+#define ISPRSZ_VFILT76			(0x074)
+#define ISPRSZ_VFILT98			(0x078)
+#define ISPRSZ_VFILT1110		(0x07C)
+#define ISPRSZ_VFILT1312		(0x080)
+#define ISPRSZ_VFILT1514		(0x084)
+#define ISPRSZ_VFILT1716		(0x088)
+#define ISPRSZ_VFILT1918		(0x08C)
+#define ISPRSZ_VFILT2120		(0x090)
+#define ISPRSZ_VFILT2322		(0x094)
+#define ISPRSZ_VFILT2524		(0x098)
+#define ISPRSZ_VFILT2726		(0x09C)
+#define ISPRSZ_VFILT2928		(0x0A0)
+#define ISPRSZ_VFILT3130		(0x0A4)
+#define ISPRSZ_YENH			(0x0A8)
+
+/* MMU module registers */
+#define ISPMMU_REVISION			(0x000)
+#define ISPMMU_SYSCONFIG		(0x010)
+#define ISPMMU_SYSSTATUS		(0x014)
+#define ISPMMU_IRQSTATUS		(0x018)
+#define ISPMMU_IRQENABLE		(0x01C)
+#define ISPMMU_WALKING_ST		(0x040)
+#define ISPMMU_CNTL			(0x044)
+#define ISPMMU_FAULT_AD			(0x048)
+#define ISPMMU_TTB			(0x04C)
+#define ISPMMU_LOCK			(0x050)
+#define ISPMMU_LD_TLB			(0x054)
+#define ISPMMU_CAM			(0x058)
+#define ISPMMU_RAM			(0x05C)
+#define ISPMMU_GFLUSH			(0x060)
+#define ISPMMU_FLUSH_ENTRY		(0x064)
+#define ISPMMU_READ_CAM			(0x068)
+#define ISPMMU_READ_RAM			(0x06c)
+#define ISPMMU_EMU_FAULT_AD		(0x070)
+
+#define ISP_INT_CLR			0xFF113F11
+#define ISPPRV_PCR_EN			1
+#define ISPPRV_PCR_BUSY			(1 << 1)
+#define ISPPRV_PCR_SOURCE		(1 << 2)
+#define ISPPRV_PCR_ONESHOT		(1 << 3)
+#define ISPPRV_PCR_WIDTH		(1 << 4)
+#define ISPPRV_PCR_INVALAW		(1 << 5)
+#define ISPPRV_PCR_DRKFEN		(1 << 6)
+#define ISPPRV_PCR_DRKFCAP		(1 << 7)
+#define ISPPRV_PCR_HMEDEN		(1 << 8)
+#define ISPPRV_PCR_NFEN			(1 << 9)
+#define ISPPRV_PCR_CFAEN		(1 << 10)
+#define ISPPRV_PCR_CFAFMT_SHIFT		11
+#define ISPPRV_PCR_CFAFMT_MASK		0x7800
+#define ISPPRV_PCR_CFAFMT_BAYER		(0 << 11)
+#define ISPPRV_PCR_CFAFMT_SONYVGA	(1 << 11)
+#define ISPPRV_PCR_CFAFMT_RGBFOVEON	(2 << 11)
+#define ISPPRV_PCR_CFAFMT_DNSPL		(3 << 11)
+#define ISPPRV_PCR_CFAFMT_HONEYCOMB	(4 << 11)
+#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON	(5 << 11)
+#define ISPPRV_PCR_YNENHEN		(1 << 15)
+#define ISPPRV_PCR_SUPEN		(1 << 16)
+#define ISPPRV_PCR_YCPOS_SHIFT		17
+#define ISPPRV_PCR_YCPOS_YCrYCb		(0 << 17)
+#define ISPPRV_PCR_YCPOS_YCbYCr		(1 << 17)
+#define ISPPRV_PCR_YCPOS_CbYCrY		(2 << 17)
+#define ISPPRV_PCR_YCPOS_CrYCbY		(3 << 17)
+#define ISPPRV_PCR_RSZPORT		(1 << 19)
+#define ISPPRV_PCR_SDRPORT		(1 << 20)
+#define ISPPRV_PCR_SCOMP_EN		(1 << 21)
+#define ISPPRV_PCR_SCOMP_SFT_SHIFT	(22)
+#define ISPPRV_PCR_SCOMP_SFT_MASK	(~(7 << 22))
+#define ISPPRV_PCR_GAMMA_BYPASS		(1 << 26)
+#define ISPPRV_PCR_DCOREN		(1 << 27)
+#define ISPPRV_PCR_DCCOUP		(1 << 28)
+#define ISPPRV_PCR_DRK_FAIL		(1 << 31)
+
+#define ISPPRV_HORZ_INFO_EPH_SHIFT	0
+#define ISPPRV_HORZ_INFO_EPH_MASK	0x3fff
+#define ISPPRV_HORZ_INFO_SPH_SHIFT	16
+#define ISPPRV_HORZ_INFO_SPH_MASK	0x3fff0
+
+#define ISPPRV_VERT_INFO_ELV_SHIFT	0
+#define ISPPRV_VERT_INFO_ELV_MASK	0x3fff
+#define ISPPRV_VERT_INFO_SLV_SHIFT	16
+#define ISPPRV_VERT_INFO_SLV_MASK	0x3fff0
+
+#define ISPPRV_AVE_EVENDIST_SHIFT	2
+#define ISPPRV_AVE_EVENDIST_1		0x0
+#define ISPPRV_AVE_EVENDIST_2		0x1
+#define ISPPRV_AVE_EVENDIST_3		0x2
+#define ISPPRV_AVE_EVENDIST_4		0x3
+#define ISPPRV_AVE_ODDDIST_SHIFT	4
+#define ISPPRV_AVE_ODDDIST_1		0x0
+#define ISPPRV_AVE_ODDDIST_2		0x1
+#define ISPPRV_AVE_ODDDIST_3		0x2
+#define ISPPRV_AVE_ODDDIST_4		0x3
+
+#define ISPPRV_HMED_THRESHOLD_SHIFT	0
+#define ISPPRV_HMED_EVENDIST		(1 << 8)
+#define ISPPRV_HMED_ODDDIST		(1 << 9)
+
+#define ISPPRV_WBGAIN_COEF0_SHIFT	0
+#define ISPPRV_WBGAIN_COEF1_SHIFT	8
+#define ISPPRV_WBGAIN_COEF2_SHIFT	16
+#define ISPPRV_WBGAIN_COEF3_SHIFT	24
+
+#define ISPPRV_WBSEL_COEF0		0x0
+#define ISPPRV_WBSEL_COEF1		0x1
+#define ISPPRV_WBSEL_COEF2		0x2
+#define ISPPRV_WBSEL_COEF3		0x3
+
+#define ISPPRV_WBSEL_N0_0_SHIFT		0
+#define ISPPRV_WBSEL_N0_1_SHIFT		2
+#define ISPPRV_WBSEL_N0_2_SHIFT		4
+#define ISPPRV_WBSEL_N0_3_SHIFT		6
+#define ISPPRV_WBSEL_N1_0_SHIFT		8
+#define ISPPRV_WBSEL_N1_1_SHIFT		10
+#define ISPPRV_WBSEL_N1_2_SHIFT		12
+#define ISPPRV_WBSEL_N1_3_SHIFT		14
+#define ISPPRV_WBSEL_N2_0_SHIFT		16
+#define ISPPRV_WBSEL_N2_1_SHIFT		18
+#define ISPPRV_WBSEL_N2_2_SHIFT		20
+#define ISPPRV_WBSEL_N2_3_SHIFT		22
+#define ISPPRV_WBSEL_N3_0_SHIFT		24
+#define ISPPRV_WBSEL_N3_1_SHIFT		26
+#define ISPPRV_WBSEL_N3_2_SHIFT		28
+#define ISPPRV_WBSEL_N3_3_SHIFT		30
+
+#define ISPPRV_CFA_GRADTH_HOR_SHIFT	0
+#define ISPPRV_CFA_GRADTH_VER_SHIFT	8
+
+#define ISPPRV_BLKADJOFF_B_SHIFT	0
+#define ISPPRV_BLKADJOFF_G_SHIFT	8
+#define ISPPRV_BLKADJOFF_R_SHIFT	16
+
+#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT	0
+#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT	16
+
+#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT	0
+#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT	16
+
+#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT	0
+#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT	16
+
+#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT	0
+#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT	16
+
+#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT	0
+
+#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT	0
+#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT	16
+
+#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT	0
+
+#define ISPPRV_CSC0_RY_SHIFT		0
+#define ISPPRV_CSC0_GY_SHIFT		10
+#define ISPPRV_CSC0_BY_SHIFT		20
+
+#define ISPPRV_CSC1_RCB_SHIFT		0
+#define ISPPRV_CSC1_GCB_SHIFT		10
+#define ISPPRV_CSC1_BCB_SHIFT		20
+
+#define ISPPRV_CSC2_RCR_SHIFT		0
+#define ISPPRV_CSC2_GCR_SHIFT		10
+#define ISPPRV_CSC2_BCR_SHIFT		20
+
+#define ISPPRV_CSC_OFFSET_CR_SHIFT	0
+#define ISPPRV_CSC_OFFSET_CB_SHIFT	8
+#define ISPPRV_CSC_OFFSET_Y_SHIFT	16
+
+#define ISPPRV_CNT_BRT_BRT_SHIFT	0
+#define ISPPRV_CNT_BRT_CNT_SHIFT	8
+
+#define ISPPRV_CONTRAST_MAX		0x10
+#define ISPPRV_CONTRAST_MIN		0xFF
+#define ISPPRV_BRIGHT_MIN		0x00
+#define ISPPRV_BRIGHT_MAX		0xFF
+
+#define ISPPRV_CSUP_CSUPG_SHIFT		0
+#define ISPPRV_CSUP_THRES_SHIFT		8
+#define ISPPRV_CSUP_HPYF_SHIFT		16
+
+#define ISPPRV_SETUP_YC_MINC_SHIFT	0
+#define ISPPRV_SETUP_YC_MAXC_SHIFT	8
+#define ISPPRV_SETUP_YC_MINY_SHIFT	16
+#define ISPPRV_SETUP_YC_MAXY_SHIFT	24
+#define ISPPRV_YC_MAX			0xFF
+#define ISPPRV_YC_MIN			0x0
+
+/* Define bit fields within selected registers */
+#define ISP_REVISION_SHIFT			0
+
+#define ISP_SYSCONFIG_AUTOIDLE			0
+#define ISP_SYSCONFIG_SOFTRESET			(1 << 1)
+#define ISP_SYSCONFIG_MIDLEMODE_SHIFT		12
+#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY	0x0
+#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY	0x1
+#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY	0x2
+
+#define ISP_SYSSTATUS_RESETDONE			0
+
+#define IRQ0ENABLE_CSIA_IRQ			1
+#define IRQ0ENABLE_CSIA_LC1_IRQ			(1 << 1)
+#define IRQ0ENABLE_CSIA_LC2_IRQ			(1 << 2)
+#define IRQ0ENABLE_CSIA_LC3_IRQ			(1 << 3)
+#define IRQ0ENABLE_CSIB_IRQ			(1 << 4)
+#define IRQ0ENABLE_CSIB_LC1_IRQ			(1 << 5)
+#define IRQ0ENABLE_CSIB_LC2_IRQ			(1 << 6)
+#define IRQ0ENABLE_CSIB_LC3_IRQ			(1 << 7)
+#define IRQ0ENABLE_CCDC_VD0_IRQ			(1 << 8)
+#define IRQ0ENABLE_CCDC_VD1_IRQ			(1 << 9)
+#define IRQ0ENABLE_CCDC_VD2_IRQ			(1 << 10)
+#define IRQ0ENABLE_CCDC_ERR_IRQ			(1 << 11)
+#define IRQ0ENABLE_H3A_AF_DONE_IRQ		(1 << 12)
+#define IRQ0ENABLE_H3A_AWB_DONE_IRQ		(1 << 13)
+#define IRQ0ENABLE_HIST_DONE_IRQ		(1 << 16)
+#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ		(1 << 17)
+#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ	(1 << 18)
+#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ	(1 << 19)
+#define IRQ0ENABLE_PRV_DONE_IRQ			(1 << 20)
+#define IRQ0ENABLE_RSZ_DONE_IRQ			(1 << 24)
+#define IRQ0ENABLE_OVF_IRQ			(1 << 25)
+#define IRQ0ENABLE_PING_IRQ			(1 << 26)
+#define IRQ0ENABLE_PONG_IRQ			(1 << 27)
+#define IRQ0ENABLE_MMU_ERR_IRQ			(1 << 28)
+#define IRQ0ENABLE_OCP_ERR_IRQ			(1 << 29)
+#define IRQ0ENABLE_SEC_ERR_IRQ			(1 << 30)
+#define IRQ0ENABLE_HS_VS_IRQ			(1 << 31)
+
+#define IRQ0STATUS_CSIA_IRQ			1
+#define IRQ0STATUS_CSIA_LC1_IRQ			(1 << 1)
+#define IRQ0STATUS_CSIA_LC2_IRQ			(1 << 2)
+#define IRQ0STATUS_CSIA_LC3_IRQ			(1 << 3)
+#define IRQ0STATUS_CSIB_IRQ			(1 << 4)
+#define IRQ0STATUS_CSIB_LC1_IRQ			(1 << 5)
+#define IRQ0STATUS_CSIB_LC2_IRQ			(1 << 6)
+#define IRQ0STATUS_CSIB_LC3_IRQ			(1 << 7)
+#define IRQ0STATUS_CCDC_VD0_IRQ			(1 << 8)
+#define IRQ0STATUS_CCDC_VD1_IRQ			(1 << 9)
+#define IRQ0STATUS_CCDC_VD2_IRQ			(1 << 10)
+#define IRQ0STATUS_CCDC_ERR_IRQ			(1 << 11)
+#define IRQ0STATUS_H3A_AF_DONE_IRQ		(1 << 12)
+#define IRQ0STATUS_H3A_AWB_DONE_IRQ		(1 << 13)
+#define IRQ0STATUS_HIST_DONE_IRQ		(1 << 16)
+#define IRQ0STATUS_PRV_DONE_IRQ			(1 << 20)
+#define IRQ0STATUS_RSZ_DONE_IRQ			(1 << 24)
+#define IRQ0STATUS_OVF_IRQ			(1 << 25)
+#define IRQ0STATUS_PING_IRQ			(1 << 26)
+#define IRQ0STATUS_PONG_IRQ			(1 << 27)
+#define IRQ0STATUS_MMU_ERR_IRQ			(1 << 28)
+#define IRQ0STATUS_OCP_ERR_IRQ			(1 << 29)
+#define IRQ0STATUS_SEC_ERR_IRQ			(1 << 30)
+#define IRQ0STATUS_HS_VS_IRQ			(1 << 31)
+
+#define TCTRL_GRESET_LEN			0
+
+#define TCTRL_PSTRB_REPLAY_DELAY		0
+#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT	25
+
+#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL	0x0
+#define ISPCTRL_PAR_SER_CLK_SEL_CSIA		0x1
+#define ISPCTRL_PAR_SER_CLK_SEL_CSIB		0x2
+#define ISPCTRL_PAR_SER_CLK_SEL_MASK		0xFFFFFFFC
+
+#define ISPCTRL_PAR_BRIDGE_SHIFT		2
+#define ISPCTRL_PAR_BRIDGE_DISABLE		(0x0 << 2)
+#define ISPCTRL_PAR_BRIDGE_LENDIAN		(0x2 << 2)
+#define ISPCTRL_PAR_BRIDGE_BENDIAN		(0x3 << 2)
+
+#define ISPCTRL_PAR_CLK_POL_SHIFT		4
+#define ISPCTRL_PAR_CLK_POL_INV			(1 << 4)
+#define ISPCTRL_PING_PONG_EN			(1 << 5)
+#define ISPCTRL_SHIFT_SHIFT			6
+#define ISPCTRL_SHIFT_0				(0x0 << 6)
+#define ISPCTRL_SHIFT_2				(0x1 << 6)
+#define ISPCTRL_SHIFT_4				(0x2 << 6)
+#define ISPCTRL_SHIFT_MASK			(~(0x3 << 6))
+
+#define ISPCTRL_CCDC_CLK_EN			(1 << 8)
+#define ISPCTRL_SCMP_CLK_EN			(1 << 9)
+#define ISPCTRL_H3A_CLK_EN			(1 << 10)
+#define ISPCTRL_HIST_CLK_EN			(1 << 11)
+#define ISPCTRL_PREV_CLK_EN			(1 << 12)
+#define ISPCTRL_RSZ_CLK_EN			(1 << 13)
+#define ISPCTRL_SYNC_DETECT_SHIFT		14
+#define ISPCTRL_SYNC_DETECT_HSFALL	(0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_HSRISE	(0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_VSFALL	(0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_VSRISE	(0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_MASK	(0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
+
+#define ISPCTRL_CCDC_RAM_EN		(1 << 16)
+#define ISPCTRL_PREV_RAM_EN		(1 << 17)
+#define ISPCTRL_SBL_RD_RAM_EN		(1 << 18)
+#define ISPCTRL_SBL_WR1_RAM_EN		(1 << 19)
+#define ISPCTRL_SBL_WR0_RAM_EN		(1 << 20)
+#define ISPCTRL_SBL_AUTOIDLE		(1 << 21)
+#define ISPCTRL_SBL_SHARED_RPORTB	(1 << 28)
+#define ISPCTRL_JPEG_FLUSH		(1 << 30)
+#define ISPCTRL_CCDC_FLUSH		(1 << 31)
+
+#define ISPSECURE_SECUREMODE		0
+
+#define ISPTCTRL_CTRL_DIV_LOW		0x0
+#define ISPTCTRL_CTRL_DIV_HIGH		0x1
+#define ISPTCTRL_CTRL_DIV_BYPASS	0x1F
+
+#define ISPTCTRL_CTRL_DIVA_SHIFT	0
+#define ISPTCTRL_CTRL_DIVA_MASK		(0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
+
+#define ISPTCTRL_CTRL_DIVB_SHIFT	5
+#define ISPTCTRL_CTRL_DIVB_MASK		(0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
+
+#define ISPTCTRL_CTRL_DIVC_SHIFT	10
+#define ISPTCTRL_CTRL_DIVC_NOCLOCK	(0x0 << 10)
+
+#define ISPTCTRL_CTRL_SHUTEN		(1 << 21)
+#define ISPTCTRL_CTRL_PSTRBEN		(1 << 22)
+#define ISPTCTRL_CTRL_STRBEN		(1 << 23)
+#define ISPTCTRL_CTRL_SHUTPOL		(1 << 24)
+#define ISPTCTRL_CTRL_STRBPSTRBPOL	(1 << 26)
+
+#define ISPTCTRL_CTRL_INSEL_SHIFT	27
+#define ISPTCTRL_CTRL_INSEL_PARALLEL	(0x0 << 27)
+#define ISPTCTRL_CTRL_INSEL_CSIA	(0x1 << 27)
+#define ISPTCTRL_CTRL_INSEL_CSIB	(0x2 << 27)
+
+#define ISPTCTRL_CTRL_GRESETEn		(1 << 29)
+#define ISPTCTRL_CTRL_GRESETPOL		(1 << 30)
+#define ISPTCTRL_CTRL_GRESETDIR		(1 << 31)
+
+#define ISPTCTRL_FRAME_SHUT_SHIFT		0
+#define ISPTCTRL_FRAME_PSTRB_SHIFT		6
+#define ISPTCTRL_FRAME_STRB_SHIFT		12
+
+#define ISPCCDC_PID_PREV_SHIFT			0
+#define ISPCCDC_PID_CID_SHIFT			8
+#define ISPCCDC_PID_TID_SHIFT			16
+
+#define ISPCCDC_PCR_EN				1
+#define ISPCCDC_PCR_BUSY			(1 << 1)
+
+#define ISPCCDC_SYN_MODE_VDHDOUT		0x1
+#define ISPCCDC_SYN_MODE_FLDOUT			(1 << 1)
+#define ISPCCDC_SYN_MODE_VDPOL			(1 << 2)
+#define ISPCCDC_SYN_MODE_HDPOL			(1 << 3)
+#define ISPCCDC_SYN_MODE_FLDPOL			(1 << 4)
+#define ISPCCDC_SYN_MODE_EXWEN			(1 << 5)
+#define ISPCCDC_SYN_MODE_DATAPOL		(1 << 6)
+#define ISPCCDC_SYN_MODE_FLDMODE		(1 << 7)
+#define ISPCCDC_SYN_MODE_DATSIZ_MASK		0xFFFFF8FF
+#define ISPCCDC_SYN_MODE_DATSIZ_8_16		(0x0 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_12		(0x4 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_11		(0x5 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_10		(0x6 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_8		(0x7 << 8)
+#define ISPCCDC_SYN_MODE_PACK8			(1 << 11)
+#define ISPCCDC_SYN_MODE_INPMOD_MASK		0xFFFFCFFF
+#define ISPCCDC_SYN_MODE_INPMOD_RAW		(0 << 12)
+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16		(1 << 12)
+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8		(2 << 12)
+#define ISPCCDC_SYN_MODE_LPF			(1 << 14)
+#define ISPCCDC_SYN_MODE_FLDSTAT		(1 << 15)
+#define ISPCCDC_SYN_MODE_VDHDEN			(1 << 16)
+#define ISPCCDC_SYN_MODE_WEN			(1 << 17)
+#define ISPCCDC_SYN_MODE_VP2SDR			(1 << 18)
+#define ISPCCDC_SYN_MODE_SDR2RSZ		(1 << 19)
+
+#define ISPCCDC_HD_VD_WID_VDW_SHIFT		0
+#define ISPCCDC_HD_VD_WID_HDW_SHIFT		16
+
+#define ISPCCDC_PIX_LINES_HLPRF_SHIFT		0
+#define ISPCCDC_PIX_LINES_PPLN_SHIFT		16
+
+#define ISPCCDC_HORZ_INFO_NPH_SHIFT		0
+#define ISPCCDC_HORZ_INFO_NPH_MASK		0xFFFF8000
+#define ISPCCDC_HORZ_INFO_SPH_MASK		0x1000FFFF
+#define ISPCCDC_HORZ_INFO_SPH_SHIFT		16
+
+#define ISPCCDC_VERT_START_SLV0_SHIFT		16
+#define ISPCCDC_VERT_START_SLV0_MASK		0x1000FFFF
+#define ISPCCDC_VERT_START_SLV1_SHIFT		0
+
+#define ISPCCDC_VERT_LINES_NLV_MASK		0xFFFF8000
+#define ISPCCDC_VERT_LINES_NLV_SHIFT		0
+
+#define ISPCCDC_CULLING_CULV_SHIFT		0
+#define ISPCCDC_CULLING_CULHODD_SHIFT		16
+#define ISPCCDC_CULLING_CULHEVN_SHIFT		24
+
+#define ISPCCDC_HSIZE_OFF_SHIFT			0
+
+#define ISPCCDC_SDOFST_FINV			(1 << 14)
+#define ISPCCDC_SDOFST_FOFST_1L			0
+#define ISPCCDC_SDOFST_FOFST_4L			(3 << 12)
+#define ISPCCDC_SDOFST_LOFST3_SHIFT		0
+#define ISPCCDC_SDOFST_LOFST2_SHIFT		3
+#define ISPCCDC_SDOFST_LOFST1_SHIFT		6
+#define ISPCCDC_SDOFST_LOFST0_SHIFT		9
+#define EVENEVEN				1
+#define ODDEVEN					2
+#define EVENODD					3
+#define ODDODD					4
+
+#define ISPCCDC_CLAMP_OBGAIN_SHIFT		0
+#define ISPCCDC_CLAMP_OBST_SHIFT		10
+#define ISPCCDC_CLAMP_OBSLN_SHIFT		25
+#define ISPCCDC_CLAMP_OBSLEN_SHIFT		28
+#define ISPCCDC_CLAMP_CLAMPEN			(1 << 31)
+
+#define ISPCCDC_COLPTN_R_Ye			0x0
+#define ISPCCDC_COLPTN_Gr_Cy			0x1
+#define ISPCCDC_COLPTN_Gb_G			0x2
+#define ISPCCDC_COLPTN_B_Mg			0x3
+#define ISPCCDC_COLPTN_CP0PLC0_SHIFT		0
+#define ISPCCDC_COLPTN_CP0PLC1_SHIFT		2
+#define ISPCCDC_COLPTN_CP0PLC2_SHIFT		4
+#define ISPCCDC_COLPTN_CP0PLC3_SHIFT		6
+#define ISPCCDC_COLPTN_CP1PLC0_SHIFT		8
+#define ISPCCDC_COLPTN_CP1PLC1_SHIFT		10
+#define ISPCCDC_COLPTN_CP1PLC2_SHIFT		12
+#define ISPCCDC_COLPTN_CP1PLC3_SHIFT		14
+#define ISPCCDC_COLPTN_CP2PLC0_SHIFT		16
+#define ISPCCDC_COLPTN_CP2PLC1_SHIFT		18
+#define ISPCCDC_COLPTN_CP2PLC2_SHIFT		20
+#define ISPCCDC_COLPTN_CP2PLC3_SHIFT		22
+#define ISPCCDC_COLPTN_CP3PLC0_SHIFT		24
+#define ISPCCDC_COLPTN_CP3PLC1_SHIFT		26
+#define ISPCCDC_COLPTN_CP3PLC2_SHIFT		28
+#define ISPCCDC_COLPTN_CP3PLC3_SHIFT		30
+
+#define ISPCCDC_BLKCMP_B_MG_SHIFT		0
+#define ISPCCDC_BLKCMP_GB_G_SHIFT		8
+#define ISPCCDC_BLKCMP_GR_CY_SHIFT		16
+#define ISPCCDC_BLKCMP_R_YE_SHIFT		24
+
+#define ISPCCDC_FPC_FPNUM_SHIFT			0
+#define ISPCCDC_FPC_FPCEN			(1 << 15)
+#define ISPCCDC_FPC_FPERR			(1 << 16)
+
+#define ISPCCDC_VDINT_1_SHIFT			0
+#define ISPCCDC_VDINT_0_SHIFT			16
+#define ISPCCDC_VDINT_0_MASK			0x7FFF
+#define ISPCCDC_VDINT_1_MASK			0x7FFF
+
+#define ISPCCDC_ALAW_GWDI_SHIFT			0
+#define ISPCCDC_ALAW_CCDTBL			(1 << 3)
+
+#define ISPCCDC_REC656IF_R656ON			1
+#define ISPCCDC_REC656IF_ECCFVH			(1 << 1)
+
+#define ISPCCDC_CFG_BW656			(1 << 5)
+#define ISPCCDC_CFG_FIDMD_SHIFT			6
+#define ISPCCDC_CFG_WENLOG			(1 << 8)
+#define ISPCCDC_CFG_WENLOG_AND			(0 << 8)
+#define ISPCCDC_CFG_WENLOG_OR		(1 << 8)
+#define ISPCCDC_CFG_Y8POS			(1 << 11)
+#define ISPCCDC_CFG_BSWD			(1 << 12)
+#define ISPCCDC_CFG_MSBINVI			(1 << 13)
+#define ISPCCDC_CFG_VDLC			(1 << 15)
+
+#define ISPCCDC_FMTCFG_FMTEN			0x1
+#define ISPCCDC_FMTCFG_LNALT			(1 << 1)
+#define ISPCCDC_FMTCFG_LNUM_SHIFT		2
+#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT		4
+#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT		8
+#define ISPCCDC_FMTCFG_VPIN_MASK		0xFFFF8000
+#define ISPCCDC_FMTCFG_VPIN_12_3		(0x3 << 12)
+#define ISPCCDC_FMTCFG_VPIN_11_2		(0x4 << 12)
+#define ISPCCDC_FMTCFG_VPIN_10_1		(0x5 << 12)
+#define ISPCCDC_FMTCFG_VPIN_9_0			(0x6 << 12)
+#define ISPCCDC_FMTCFG_VPEN			(1 << 15)
+
+#define ISPCCDC_FMTCF_VPIF_FRQ_MASK		0xFFF8FFFF
+#define ISPCCDC_FMTCF_VPIF_FRQ_BY2		(0x0 << 16)
+#define ISPCCDC_FMTCF_VPIF_FRQ_BY3		(0x1 << 16)
+#define ISPCCDC_FMTCF_VPIF_FRQ_BY4		(0x2 << 16)
+#define ISPCCDC_FMTCF_VPIF_FRQ_BY5		(0x3 << 16)
+#define ISPCCDC_FMTCF_VPIF_FRQ_BY6		(0x4 << 16)
+
+#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT		0
+#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT		16
+
+#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT		0
+#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT		16
+
+#define ISPCCDC_FMT_HORZ_FMTSPH_MASK		0x1FFF0000
+#define ISPCCDC_FMT_HORZ_FMTLNH_MASK		0x1FFF
+
+#define ISPCCDC_FMT_VERT_FMTSLV_MASK		0x1FFF0000
+#define ISPCCDC_FMT_VERT_FMTLNV_MASK		0x1FFF
+
+#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT		0
+#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT		4
+#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT		17
+
+#define ISPRSZ_PID_PREV_SHIFT			0
+#define ISPRSZ_PID_CID_SHIFT			8
+#define ISPRSZ_PID_TID_SHIFT			16
+
+#define ISPRSZ_PCR_ENABLE			0x5
+#define ISPRSZ_PCR_BUSY				(1 << 1)
+
+#define ISPRSZ_CNT_HRSZ_SHIFT			0
+#define ISPRSZ_CNT_HRSZ_MASK			0x3FF
+#define ISPRSZ_CNT_VRSZ_SHIFT			10
+#define ISPRSZ_CNT_VRSZ_MASK			0xFFC00
+#define ISPRSZ_CNT_HSTPH_SHIFT			20
+#define ISPRSZ_CNT_HSTPH_MASK			0x700000
+#define ISPRSZ_CNT_VSTPH_SHIFT			23
+#define	ISPRSZ_CNT_VSTPH_MASK			0x3800000
+#define	ISPRSZ_CNT_CBILIN_MASK			0x20000000
+#define	ISPRSZ_CNT_INPTYP_MASK			0x08000000
+#define	ISPRSZ_CNT_PIXFMT_MASK			0x04000000
+#define ISPRSZ_CNT_YCPOS			(1 << 26)
+#define ISPRSZ_CNT_INPTYP			(1 << 27)
+#define ISPRSZ_CNT_INPSRC			(1 << 28)
+#define ISPRSZ_CNT_CBILIN			(1 << 29)
+
+#define ISPRSZ_OUT_SIZE_HORZ_SHIFT		0
+#define ISPRSZ_OUT_SIZE_HORZ_MASK		0x7FF
+#define ISPRSZ_OUT_SIZE_VERT_SHIFT		16
+#define ISPRSZ_OUT_SIZE_VERT_MASK		0x7FF0000
+
+
+#define ISPRSZ_IN_START_HORZ_ST_SHIFT		0
+#define ISPRSZ_IN_START_HORZ_ST_MASK		0x1FFF
+#define ISPRSZ_IN_START_VERT_ST_SHIFT		16
+#define ISPRSZ_IN_START_VERT_ST_MASK		0x1FFF0000
+
+
+#define ISPRSZ_IN_SIZE_HORZ_SHIFT		0
+#define ISPRSZ_IN_SIZE_HORZ_MASK		0x1FFF
+#define ISPRSZ_IN_SIZE_VERT_SHIFT		16
+#define ISPRSZ_IN_SIZE_VERT_MASK		0x1FFF0000
+
+#define ISPRSZ_SDR_INADD_ADDR_SHIFT		0
+#define ISPRSZ_SDR_INADD_ADDR_MASK		0xFFFFFFFF
+
+#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT		0
+#define ISPRSZ_SDR_INOFF_OFFSET_MASK		0xFFFF
+
+#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT		0
+#define ISPRSZ_SDR_OUTADD_ADDR_MASK		0xFFFFFFFF
+
+
+#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT		0
+#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK		0xFFFF
+
+#define ISPRSZ_HFILT10_COEF0_SHIFT		0
+#define ISPRSZ_HFILT10_COEF0_MASK		0x3FF
+#define ISPRSZ_HFILT10_COEF1_SHIFT		16
+#define ISPRSZ_HFILT10_COEF1_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT32_COEF2_SHIFT		0
+#define ISPRSZ_HFILT32_COEF2_MASK		0x3FF
+#define ISPRSZ_HFILT32_COEF3_SHIFT		16
+#define ISPRSZ_HFILT32_COEF3_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT54_COEF4_SHIFT		0
+#define ISPRSZ_HFILT54_COEF4_MASK		0x3FF
+#define ISPRSZ_HFILT54_COEF5_SHIFT		16
+#define ISPRSZ_HFILT54_COEF5_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT76_COEFF6_SHIFT		0
+#define ISPRSZ_HFILT76_COEFF6_MASK		0x3FF
+#define ISPRSZ_HFILT76_COEFF7_SHIFT		16
+#define ISPRSZ_HFILT76_COEFF7_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT98_COEFF8_SHIFT		0
+#define ISPRSZ_HFILT98_COEFF8_MASK		0x3FF
+#define ISPRSZ_HFILT98_COEFF9_SHIFT		16
+#define ISPRSZ_HFILT98_COEFF9_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1110_COEF10_SHIFT		0
+#define ISPRSZ_HFILT1110_COEF10_MASK		0x3FF
+#define ISPRSZ_HFILT1110_COEF11_SHIFT		16
+#define ISPRSZ_HFILT1110_COEF11_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1312_COEFF12_SHIFT		0
+#define ISPRSZ_HFILT1312_COEFF12_MASK		0x3FF
+#define ISPRSZ_HFILT1312_COEFF13_SHIFT		16
+#define ISPRSZ_HFILT1312_COEFF13_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1514_COEFF14_SHIFT		0
+#define ISPRSZ_HFILT1514_COEFF14_MASK		0x3FF
+#define ISPRSZ_HFILT1514_COEFF15_SHIFT		16
+#define ISPRSZ_HFILT1514_COEFF15_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1716_COEF16_SHIFT		0
+#define ISPRSZ_HFILT1716_COEF16_MASK		0x3FF
+#define ISPRSZ_HFILT1716_COEF17_SHIFT		16
+#define ISPRSZ_HFILT1716_COEF17_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1918_COEF18_SHIFT		0
+#define ISPRSZ_HFILT1918_COEF18_MASK		0x3FF
+#define ISPRSZ_HFILT1918_COEF19_SHIFT		16
+#define ISPRSZ_HFILT1918_COEF19_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2120_COEF20_SHIFT		0
+#define ISPRSZ_HFILT2120_COEF20_MASK		0x3FF
+#define ISPRSZ_HFILT2120_COEF21_SHIFT		16
+#define ISPRSZ_HFILT2120_COEF21_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2322_COEF22_SHIFT		0
+#define ISPRSZ_HFILT2322_COEF22_MASK		0x3FF
+#define ISPRSZ_HFILT2322_COEF23_SHIFT		16
+#define ISPRSZ_HFILT2322_COEF23_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2524_COEF24_SHIFT		0
+#define ISPRSZ_HFILT2524_COEF24_MASK		0x3FF
+#define ISPRSZ_HFILT2524_COEF25_SHIFT		16
+#define ISPRSZ_HFILT2524_COEF25_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2726_COEF26_SHIFT		0
+#define ISPRSZ_HFILT2726_COEF26_MASK		0x3FF
+#define ISPRSZ_HFILT2726_COEF27_SHIFT		16
+#define ISPRSZ_HFILT2726_COEF27_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2928_COEF28_SHIFT		0
+#define ISPRSZ_HFILT2928_COEF28_MASK		0x3FF
+#define ISPRSZ_HFILT2928_COEF29_SHIFT		16
+#define ISPRSZ_HFILT2928_COEF29_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT3130_COEF30_SHIFT		0
+#define ISPRSZ_HFILT3130_COEF30_MASK		0x3FF
+#define ISPRSZ_HFILT3130_COEF31_SHIFT		16
+#define ISPRSZ_HFILT3130_COEF31_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT10_COEF0_SHIFT		0
+#define ISPRSZ_VFILT10_COEF0_MASK		0x3FF
+#define ISPRSZ_VFILT10_COEF1_SHIFT		16
+#define ISPRSZ_VFILT10_COEF1_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT32_COEF2_SHIFT		0
+#define ISPRSZ_VFILT32_COEF2_MASK		0x3FF
+#define ISPRSZ_VFILT32_COEF3_SHIFT		16
+#define ISPRSZ_VFILT32_COEF3_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT54_COEF4_SHIFT		0
+#define ISPRSZ_VFILT54_COEF4_MASK		0x3FF
+#define ISPRSZ_VFILT54_COEF5_SHIFT		16
+#define ISPRSZ_VFILT54_COEF5_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT76_COEFF6_SHIFT		0
+#define ISPRSZ_VFILT76_COEFF6_MASK		0x3FF
+#define ISPRSZ_VFILT76_COEFF7_SHIFT		16
+#define ISPRSZ_VFILT76_COEFF7_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT98_COEFF8_SHIFT		0
+#define ISPRSZ_VFILT98_COEFF8_MASK		0x3FF
+#define ISPRSZ_VFILT98_COEFF9_SHIFT		16
+#define ISPRSZ_VFILT98_COEFF9_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1110_COEF10_SHIFT		0
+#define ISPRSZ_VFILT1110_COEF10_MASK		0x3FF
+#define ISPRSZ_VFILT1110_COEF11_SHIFT		16
+#define ISPRSZ_VFILT1110_COEF11_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1312_COEFF12_SHIFT		0
+#define ISPRSZ_VFILT1312_COEFF12_MASK		0x3FF
+#define ISPRSZ_VFILT1312_COEFF13_SHIFT		16
+#define ISPRSZ_VFILT1312_COEFF13_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1514_COEFF14_SHIFT		0
+#define ISPRSZ_VFILT1514_COEFF14_MASK		0x3FF
+#define ISPRSZ_VFILT1514_COEFF15_SHIFT		16
+#define ISPRSZ_VFILT1514_COEFF15_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1716_COEF16_SHIFT		0
+#define ISPRSZ_VFILT1716_COEF16_MASK		0x3FF
+#define ISPRSZ_VFILT1716_COEF17_SHIFT		16
+#define ISPRSZ_VFILT1716_COEF17_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1918_COEF18_SHIFT		0
+#define ISPRSZ_VFILT1918_COEF18_MASK		0x3FF
+#define ISPRSZ_VFILT1918_COEF19_SHIFT		16
+#define ISPRSZ_VFILT1918_COEF19_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2120_COEF20_SHIFT		0
+#define ISPRSZ_VFILT2120_COEF20_MASK		0x3FF
+#define ISPRSZ_VFILT2120_COEF21_SHIFT		16
+#define ISPRSZ_VFILT2120_COEF21_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2322_COEF22_SHIFT		0
+#define ISPRSZ_VFILT2322_COEF22_MASK		0x3FF
+#define ISPRSZ_VFILT2322_COEF23_SHIFT		16
+#define ISPRSZ_VFILT2322_COEF23_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2524_COEF24_SHIFT		0
+#define ISPRSZ_VFILT2524_COEF24_MASK		0x3FF
+#define ISPRSZ_VFILT2524_COEF25_SHIFT		16
+#define ISPRSZ_VFILT2524_COEF25_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2726_COEF26_SHIFT		0
+#define ISPRSZ_VFILT2726_COEF26_MASK		0x3FF
+#define ISPRSZ_VFILT2726_COEF27_SHIFT		16
+#define ISPRSZ_VFILT2726_COEF27_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2928_COEF28_SHIFT		0
+#define ISPRSZ_VFILT2928_COEF28_MASK		0x3FF
+#define ISPRSZ_VFILT2928_COEF29_SHIFT		16
+#define ISPRSZ_VFILT2928_COEF29_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT3130_COEF30_SHIFT		0
+#define ISPRSZ_VFILT3130_COEF30_MASK		0x3FF
+#define ISPRSZ_VFILT3130_COEF31_SHIFT		16
+#define ISPRSZ_VFILT3130_COEF31_MASK		0x3FF0000
+
+#define ISPRSZ_YENH_CORE_SHIFT			0
+#define ISPRSZ_YENH_CORE_MASK			0xFF
+#define ISPRSZ_YENH_SLOP_SHIFT			8
+#define ISPRSZ_YENH_SLOP_MASK			0xF00
+#define ISPRSZ_YENH_GAIN_SHIFT			12
+#define ISPRSZ_YENH_GAIN_MASK			0xF000
+#define ISPRSZ_YENH_ALGO_SHIFT			16
+#define ISPRSZ_YENH_ALGO_MASK			0x30000
+
+#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT		1
+#define ISPH3A_PCR_AF_MED_TH_SHIFT		3
+#define ISPH3A_PCR_AF_RGBPOS_SHIFT		11
+#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT		22
+#define ISPH3A_PCR_AEW_AVE2LMT_MASK		0xFFC00000
+#define ISPH3A_PCR_BUSYAF			(1 << 15)
+#define ISPH3A_PCR_BUSYAEAWB			(1 << 18)
+
+#define ISPH3A_AEWWIN1_WINHC_SHIFT		0
+#define ISPH3A_AEWWIN1_WINHC_MASK		0x3F
+#define ISPH3A_AEWWIN1_WINVC_SHIFT		6
+#define ISPH3A_AEWWIN1_WINVC_MASK		0x1FC0
+#define ISPH3A_AEWWIN1_WINW_SHIFT		13
+#define ISPH3A_AEWWIN1_WINW_MASK		0xFE000
+#define ISPH3A_AEWWIN1_WINH_SHIFT		24
+#define ISPH3A_AEWWIN1_WINH_MASK		0x7F000000
+
+#define ISPH3A_AEWINSTART_WINSH_SHIFT		0
+#define ISPH3A_AEWINSTART_WINSH_MASK		0x0FFF
+#define ISPH3A_AEWINSTART_WINSV_SHIFT		16
+#define ISPH3A_AEWINSTART_WINSV_MASK		0x0FFF0000
+
+#define ISPH3A_AEWINBLK_WINH_SHIFT		0
+#define ISPH3A_AEWINBLK_WINH_MASK		0x7F
+#define ISPH3A_AEWINBLK_WINSV_SHIFT		16
+#define ISPH3A_AEWINBLK_WINSV_MASK		0x0FFF0000
+
+#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT		0
+#define ISPH3A_AEWSUBWIN_AEWINCH_MASK		0x0F
+#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT		8
+#define ISPH3A_AEWSUBWIN_AEWINCV_MASK		0x0F00
+
+#define ISPHIST_PCR_ENABLE_SHIFT	0
+#define ISPHIST_PCR_ENABLE_MASK		0x01
+#define ISPHIST_PCR_BUSY		0x02
+
+#define ISPHIST_CNT_DATASIZE_SHIFT	8
+#define ISPHIST_CNT_DATASIZE_MASK	0x0100
+#define ISPHIST_CNT_CLEAR_SHIFT		7
+#define ISPHIST_CNT_CLEAR_MASK		0x080
+#define ISPHIST_CNT_CFA_SHIFT		6
+#define ISPHIST_CNT_CFA_MASK		0x040
+#define ISPHIST_CNT_BINS_SHIFT		4
+#define ISPHIST_CNT_BINS_MASK		0x030
+#define ISPHIST_CNT_SOURCE_SHIFT	3
+#define ISPHIST_CNT_SOURCE_MASK		0x08
+#define ISPHIST_CNT_SHIFT_SHIFT		0
+#define ISPHIST_CNT_SHIFT_MASK		0x07
+
+#define ISPHIST_WB_GAIN_WG00_SHIFT	24
+#define ISPHIST_WB_GAIN_WG00_MASK	0xFF000000
+#define ISPHIST_WB_GAIN_WG01_SHIFT	16
+#define ISPHIST_WB_GAIN_WG01_MASK	0xFF0000
+#define ISPHIST_WB_GAIN_WG02_SHIFT	8
+#define ISPHIST_WB_GAIN_WG02_MASK	0xFF00
+#define ISPHIST_WB_GAIN_WG03_SHIFT	0
+#define ISPHIST_WB_GAIN_WG03_MASK	0xFF
+
+#define ISPHIST_REGHORIZ_HSTART_SHIFT		16	/*
+							* REGION 0 to 3 HORZ
+							* and VERT
+							*/
+#define ISPHIST_REGHORIZ_HSTART_MASK		0x3FFF0000
+#define ISPHIST_REGHORIZ_HEND_SHIFT		0
+#define ISPHIST_REGHORIZ_HEND_MASK		0x3FFF
+#define ISPHIST_REGVERT_VSTART_SHIFT		16
+#define ISPHIST_REGVERT_VSTART_MASK		0x3FFF0000
+#define ISPHIST_REGVERT_VEND_SHIFT		0
+#define ISPHIST_REGVERT_VEND_MASK		0x3FFF
+
+#define ISPHIST_REGHORIZ_MASK			0x3FFF3FFF
+#define ISPHIST_REGVERT_MASK			0x3FFF3FFF
+
+#define ISPHIST_ADDR_SHIFT			0
+#define ISPHIST_ADDR_MASK			0x3FF
+
+#define ISPHIST_DATA_SHIFT			0
+#define ISPHIST_DATA_MASK			0xFFFFF
+
+#define ISPHIST_RADD_SHIFT			0
+#define ISPHIST_RADD_MASK			0xFFFFFFFF
+
+#define ISPHIST_RADD_OFF_SHIFT			0
+#define ISPHIST_RADD_OFF_MASK			0xFFFF
+
+#define ISPHIST_HV_INFO_HSIZE_SHIFT		16
+#define ISPHIST_HV_INFO_HSIZE_MASK		0x3FFF0000
+#define ISPHIST_HV_INFO_VSIZE_SHIFT		0
+#define ISPHIST_HV_INFO_VSIZE_MASK		0x3FFF
+
+#define ISPHIST_HV_INFO_MASK			0x3FFF3FFF
+
+#define ISPCCDC_LSC_GAIN_MODE_N_MASK		0x700
+#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT		8
+#define ISPCCDC_LSC_GAIN_MODE_M_MASK		0x3800
+#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT		12
+#define ISPCCDC_LSC_GAIN_FORMAT_MASK		0xE
+#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT		1
+#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK	(1<<6)
+
+#define ISPCCDC_LSC_INITIAL_X_MASK		0x3F
+#define ISPCCDC_LSC_INITIAL_X_SHIFT		0
+#define ISPCCDC_LSC_INITIAL_Y_MASK		0x3F0000
+#define ISPCCDC_LSC_INITIAL_Y_SHIFT		16
+
+#define ISPMMU_REVISION_REV_MINOR_MASK		0xF
+#define ISPMMU_REVISION_REV_MAJOR_SHIFT		0x4
+
+#define IRQENABLE_MULTIHITFAULT			(1<<4)
+#define IRQENABLE_TWFAULT			(1<<3)
+#define IRQENABLE_EMUMISS			(1<<2)
+#define IRQENABLE_TRANSLNFAULT			(1<<1)
+#define IRQENABLE_TLBMISS			(1)
+
+#define ISPMMU_MMUCNTL_MMU_EN			(1<<1)
+#define ISPMMU_MMUCNTL_TWL_EN			(1<<2)
+#define ISPMMU_MMUCNTL_EMUTLBUPDATE		(1<<3)
+#define ISPMMU_AUTOIDLE				0x1
+#define ISPMMU_SIDLEMODE_FORCEIDLE		0
+#define ISPMMU_SIDLEMODE_NOIDLE			1
+#define ISPMMU_SIDLEMODE_SMARTIDLE		2
+#define ISPMMU_SIDLEMODE_SHIFT			3
+
+#define ISPCSI1_AUTOIDLE			0x1
+#define ISPCSI1_MIDLEMODE_SHIFT			12
+#define ISPCSI1_MIDLEMODE_FORCESTANDBY		0x0
+#define ISPCSI1_MIDLEMODE_NOSTANDBY		0x1
+#define ISPCSI1_MIDLEMODE_SMARTSTANDBY		0x2
+
+/* CSI2 receiver registers (ES2.0) */
+#define ISPCSI2_REVISION			(0x000)
+#define ISPCSI2_SYSCONFIG			(0x010)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT	12
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK \
+				(0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE \
+				(0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO \
+				(0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART \
+				(0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT	1
+#define ISPCSI2_SYSCONFIG_SOFT_RESET_MASK \
+				(0x1 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
+#define ISPCSI2_SYSCONFIG_SOFT_RESET_NORMAL \
+				(0x0 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
+#define ISPCSI2_SYSCONFIG_SOFT_RESET_RESET \
+				(0x1 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT	0
+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK \
+				(0x1 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_FREE \
+				(0x0 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_AUTO \
+				(0x1 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
+#define ISPCSI2_SYSSTATUS			(0x014)
+#define ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT	0
+#define ISPCSI2_SYSSTATUS_RESET_DONE_MASK \
+				(0x1 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
+#define ISPCSI2_SYSSTATUS_RESET_DONE_ONGOING \
+				(0x0 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
+#define ISPCSI2_SYSSTATUS_RESET_DONE_DONE \
+				(0x1 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
+#define ISPCSI2_IRQSTATUS				(0x018)
+#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ			(1 << 14)
+#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ		(1 << 13)
+#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ		(1 << 12)
+#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ		(1 << 11)
+#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ		(1 << 10)
+#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ		(1 << 9)
+#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ			(1 << 8)
+#define ISPCSI2_IRQSTATUS_CONTEXT(n)			(1 << (n))
+
+#define ISPCSI2_IRQENABLE			(0x01C)
+#define ISPCSI2_CTRL				(0x040)
+#define ISPCSI2_CTRL_VP_CLK_EN_SHIFT	15
+#define ISPCSI2_CTRL_VP_CLK_EN_MASK	(0x1 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
+#define ISPCSI2_CTRL_VP_CLK_EN_DISABLE	(0x0 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
+#define ISPCSI2_CTRL_VP_CLK_EN_ENABLE	(0x1 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
+
+#define ISPCSI2_CTRL_VP_ONLY_EN_SHIFT	11
+#define ISPCSI2_CTRL_VP_ONLY_EN_MASK	(0x1 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
+#define ISPCSI2_CTRL_VP_ONLY_EN_DISABLE	(0x0 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
+#define ISPCSI2_CTRL_VP_ONLY_EN_ENABLE	(0x1 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
+
+#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT		8
+#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK		(0x3 << \
+						ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
+#define ISPCSI2_CTRL_VP_OUT_CTRL_DISABLE	(0x0 << \
+						ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
+#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV2		(0x1 << \
+						ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
+#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV3		(0x2 << \
+						ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
+#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV4		(0x3 << \
+						ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
+
+#define ISPCSI2_CTRL_DBG_EN_SHIFT	7
+#define ISPCSI2_CTRL_DBG_EN_MASK	(0x1 << ISPCSI2_CTRL_DBG_EN_SHIFT)
+#define ISPCSI2_CTRL_DBG_EN_DISABLE	(0x0 << ISPCSI2_CTRL_DBG_EN_SHIFT)
+#define ISPCSI2_CTRL_DBG_EN_ENABLE	(0x1 << ISPCSI2_CTRL_DBG_EN_SHIFT)
+
+#define ISPCSI2_CTRL_BURST_SIZE_SHIFT		5
+#define ISPCSI2_CTRL_BURST_SIZE_MASK		(0x3 << \
+						ISPCSI2_CTRL_BURST_SIZE_SHIFT)
+#define ISPCSI2_CTRL_BURST_SIZE_MYSTERY_VAL		(0x2 << \
+						ISPCSI2_CTRL_BURST_SIZE_SHIFT)
+
+#define ISPCSI2_CTRL_FRAME_SHIFT	3
+#define ISPCSI2_CTRL_FRAME_MASK		(0x1 << ISPCSI2_CTRL_FRAME_SHIFT)
+#define ISPCSI2_CTRL_FRAME_DISABLE_IMM	(0x0 << ISPCSI2_CTRL_FRAME_SHIFT)
+#define ISPCSI2_CTRL_FRAME_DISABLE_FEC	(0x1 << ISPCSI2_CTRL_FRAME_SHIFT)
+
+#define ISPCSI2_CTRL_ECC_EN_SHIFT	2
+#define ISPCSI2_CTRL_ECC_EN_MASK	(0x1 << ISPCSI2_CTRL_ECC_EN_SHIFT)
+#define ISPCSI2_CTRL_ECC_EN_DISABLE	(0x0 << ISPCSI2_CTRL_ECC_EN_SHIFT)
+#define ISPCSI2_CTRL_ECC_EN_ENABLE	(0x1 << ISPCSI2_CTRL_ECC_EN_SHIFT)
+
+#define ISPCSI2_CTRL_SECURE_SHIFT	1
+#define ISPCSI2_CTRL_SECURE_MASK	(0x1 << ISPCSI2_CTRL_SECURE_SHIFT)
+#define ISPCSI2_CTRL_SECURE_DISABLE	(0x0 << ISPCSI2_CTRL_SECURE_SHIFT)
+#define ISPCSI2_CTRL_SECURE_ENABLE	(0x1 << ISPCSI2_CTRL_SECURE_SHIFT)
+
+#define ISPCSI2_CTRL_IF_EN_SHIFT	0
+#define ISPCSI2_CTRL_IF_EN_MASK		(0x1 << ISPCSI2_CTRL_IF_EN_SHIFT)
+#define ISPCSI2_CTRL_IF_EN_DISABLE	(0x0 << ISPCSI2_CTRL_IF_EN_SHIFT)
+#define ISPCSI2_CTRL_IF_EN_ENABLE	(0x1 << ISPCSI2_CTRL_IF_EN_SHIFT)
+
+#define ISPCSI2_DBG_H				(0x044)
+#define ISPCSI2_GNQ				(0x048)
+#define ISPCSI2_COMPLEXIO_CFG1			(0x050)
+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT		29
+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_MASK \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_ONGOING \
+			(0x0 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_DONE \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT		27
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK \
+			(0x3 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF \
+			(0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW \
+			(0x2 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT		25
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK \
+			(0x3 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF \
+			(0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW \
+			(0x2 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT		24
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE \
+			(0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
+
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n) 	(3 + ((n) * 4))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(n) (0x1 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_PN(n) (0x0 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_NP(n) (0x1 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
+
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n)	((n) * 4)
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(n)	(0x7 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_NC(n)	(0x0 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_1(n)	(0x1 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_2(n)	(0x2 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_3(n)	(0x3 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_4(n)	(0x4 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_5(n)	(0x5 << \
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
+
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT		3
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_PN \
+			(0x0 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_NP \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
+
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT		0
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK \
+			(0x7 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_1 \
+			(0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_2 \
+			(0x2 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_3 \
+			(0x3 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_4 \
+			(0x4 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_5 \
+			(0x5 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
+
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS			(0x054)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEALLULPMEXIT	(1 << 26)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEALLULPMENTER	(1 << 25)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM5		(1 << 24)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM4		(1 << 23)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM3		(1 << 22)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM2		(1 << 21)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM1		(1 << 20)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL5	(1 << 19)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL4	(1 << 18)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL3	(1 << 17)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL2	(1 << 16)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL1	(1 << 15)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC5		(1 << 14)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC4		(1 << 13)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC3		(1 << 12)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC2		(1 << 11)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC1		(1 << 10)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS5	(1 << 9)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS4	(1 << 8)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS3	(1 << 7)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS2	(1 << 6)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS1	(1 << 5)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS5		(1 << 4)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS4		(1 << 3)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS3		(1 << 2)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS2		(1 << 1)
+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS1		1
+
+#define ISPCSI2_SHORT_PACKET		(0x05C)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE			(0x060)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT	(1 << 26)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER	(1 << 25)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5		(1 << 24)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4		(1 << 23)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3		(1 << 22)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2		(1 << 21)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1		(1 << 20)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5	(1 << 19)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4	(1 << 18)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3	(1 << 17)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2	(1 << 16)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1	(1 << 15)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5		(1 << 14)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4		(1 << 13)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3		(1 << 12)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2		(1 << 11)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1		(1 << 10)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5	(1 << 9)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4	(1 << 8)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3	(1 << 7)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2	(1 << 6)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1	(1 << 5)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5		(1 << 4)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4		(1 << 3)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3		(1 << 2)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2		(1 << 1)
+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1		1
+#define ISPCSI2_DBG_P			(0x068)
+#define ISPCSI2_TIMING			(0x06C)
+
+
+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n)	((16 * ((n) - 1)) + 15)
+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(n)	(0x1 << \
+				ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE(n)	(0x0 << \
+				ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(n)	(0x1 << \
+				ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n)	((16 * ((n) - 1)) + 14)
+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(n)	(0x1 << \
+				ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE(n)	(0x0 << \
+				ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(n)	(0x1 << \
+				ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n)	((16 * ((n) - 1)) + 13)
+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(n)		(0x1 << \
+				ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE(n)	(0x0 << \
+				ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(n)		(0x1 << \
+				ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n)	(16 * ((n) - 1))
+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n)	(0x1FFF << \
+				ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
+
+#define ISPCSI2_CTX_CTRL1(n)		((0x070) + 0x20 * (n))
+#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT		8
+#define ISPCSI2_CTX_CTRL1_COUNT_MASK		(0xFF << \
+						ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT		7
+#define ISPCSI2_CTX_CTRL1_EOF_EN_MASK		(0x1 << \
+						ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE	(0x0 << \
+						ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE		(0x1 << \
+						ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT		6
+#define ISPCSI2_CTX_CTRL1_EOL_EN_MASK		(0x1 << \
+						ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE	(0x0 << \
+						ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE		(0x1 << \
+						ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_CS_EN_SHIFT		5
+#define ISPCSI2_CTX_CTRL1_CS_EN_MASK		(0x1 << \
+						ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_CS_EN_DISABLE		(0x0 << \
+						ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_CS_EN_ENABLE		(0x1 << \
+						ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT		4
+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_MASK		(0x1 << \
+					ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_DISABLE	(0x0 << \
+					ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_ENABLE	(0x1 << \
+					ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_PING_PONG_SHIFT	3
+#define ISPCSI2_CTX_CTRL1_PING_PONG_MASK	(0x1 << \
+					ISPCSI2_CTX_CTRL1_PING_PONG_SHIFT)
+#define ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT		0
+#define ISPCSI2_CTX_CTRL1_CTX_EN_MASK		(0x1 << \
+						ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE	(0x0 << \
+						ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
+#define ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE		(0x1 << \
+						ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
+
+#define ISPCSI2_CTX_CTRL2(n)		((0x074) + 0x20 * (n))
+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT	11
+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK	(0x3 << \
+					ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
+#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT	0
+#define ISPCSI2_CTX_CTRL2_FORMAT_MASK	(0x3FF << \
+					ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
+
+#define ISPCSI2_CTX_DAT_OFST(n)		((0x078) + 0x20 * (n))
+#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT	5
+#define ISPCSI2_CTX_DAT_OFST_OFST_MASK	(0x7FF << \
+						ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
+
+#define ISPCSI2_CTX_DAT_PING_ADDR(n)	((0x07C) + 0x20 * (n))
+#define ISPCSI2_CTX_DAT_PONG_ADDR(n)	((0x080) + 0x20 * (n))
+#define ISPCSI2_CTX_IRQENABLE(n)	((0x084) + 0x20 * (n))
+#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ		(1 << 8)
+#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ		(1 << 7)
+#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ		(1 << 6)
+#define ISPCSI2_CTX_IRQENABLE_CS_IRQ			(1 << 5)
+#define ISPCSI2_CTX_IRQENABLE_LE_IRQ			(1 << 3)
+#define ISPCSI2_CTX_IRQENABLE_LS_IRQ			(1 << 2)
+#define ISPCSI2_CTX_IRQENABLE_FE_IRQ			(1 << 1)
+#define ISPCSI2_CTX_IRQENABLE_FS_IRQ			1
+#define ISPCSI2_CTX_IRQSTATUS(n)	((0x088) + 0x20 * (n))
+#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ		(1 << 8)
+#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ		(1 << 7)
+#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ		(1 << 6)
+#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ			(1 << 5)
+#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ			(1 << 3)
+#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ			(1 << 2)
+#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ			(1 << 1)
+#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ			1
+
+#define ISPCSI2_CTX_CTRL3(n)		((0x08C) + 0x20 * (n))
+#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT	5
+#define ISPCSI2_CTX_CTRL3_ALPHA_MASK	(0x3FFF << \
+						ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
+
+#define ISPCSI2PHY_CFG0				(0x000)
+#define ISPCSI2PHY_CFG0_THS_TERM_SHIFT		8
+#define ISPCSI2PHY_CFG0_THS_TERM_MASK \
+				(0xFF << ISPCSI2PHY_CFG0_THS_TERM_SHIFT)
+#define ISPCSI2PHY_CFG0_THS_TERM_RESETVAL \
+				(0x04 << ISPCSI2PHY_CFG0_THS_TERM_SHIFT)
+#define ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT		0
+#define ISPCSI2PHY_CFG0_THS_SETTLE_MASK \
+				(0xFF << ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT)
+#define ISPCSI2PHY_CFG0_THS_SETTLE_RESETVAL \
+				(0x27 << ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT)
+#define ISPCSI2PHY_CFG1				(0x004)
+#define ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT		18
+#define ISPCSI2PHY_CFG1_TCLK_TERM_MASK \
+				(0x7F << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
+#define ISPCSI2PHY_CFG1_TCLK_TERM__RESETVAL \
+				(0x00 << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
+#define ISPCSI2PHY_CFG1_RESERVED1_SHIFT		10
+#define ISPCSI2PHY_CFG1_RESERVED1_MASK \
+				(0xFF << ISPCSI2PHY_CFG1_RESERVED1_SHIFT)
+#define ISPCSI2PHY_CFG1_RESERVED1__RESETVAL \
+				(0xB8 << ISPCSI2PHY_CFG1_RESERVED1_SHIFT)
+#define ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT		8
+#define ISPCSI2PHY_CFG1_TCLK_MISS_MASK \
+				(0x3 << ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT)
+#define ISPCSI2PHY_CFG1_TCLK_MISS__RESETVAL \
+				(0x1 << ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT)
+#define ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT		0
+#define ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK \
+				(0xFF << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
+#define ISPCSI2PHY_CFG1_TCLK_SETTLE__RESETVAL \
+				(0x0E << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
+#define ISPCSI2PHY_CFG1__RESETVAL	(ISPCSI2PHY_CFG1_TCLK_TERM__RESETVAL | \
+					ISPCSI2PHY_CFG1_RESERVED1__RESETVAL | \
+					ISPCSI2PHY_CFG1_TCLK_MISS__RESETVAL | \
+					ISPCSI2PHY_CFG1_TCLK_SETTLE__RESETVAL)
+#define ISPCSI2PHY_CFG1__EDITABLE_MASK	(ISPCSI2PHY_CFG1_TCLK_TERM_MASK | \
+					ISPCSI2PHY_CFG1_RESERVED1_MASK | \
+					ISPCSI2PHY_CFG1_TCLK_MISS_MASK | \
+					ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK)
+
+#endif	/* __ISPREG_H__ */
-- 
1.5.6.5


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

* [PATCH 2/9] omap3isp: Add ISP MMU wrapper
  2009-03-03 10:06 ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Sakari Ailus
@ 2009-03-03 10:06   ` Sakari Ailus
  2009-03-03 10:06     ` [PATCH 3/9] omap3isp: Add userspace header Sakari Ailus
  2009-03-03 11:56   ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Alexey Klimov
  1 sibling, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

TODO:

- The ISP driver should start using the IOMMU directly without this wrapper.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/isp/ispmmu.c |  141 ++++++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/ispmmu.h |   36 ++++++++++
 2 files changed, 177 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/ispmmu.c
 create mode 100644 drivers/media/video/isp/ispmmu.h

diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c
new file mode 100644
index 0000000..f872c71
--- /dev/null
+++ b/drivers/media/video/isp/ispmmu.c
@@ -0,0 +1,141 @@
+/*
+ * omap iommu wrapper for TI's OMAP3430 Camera ISP
+ *
+ * Copyright (C) 2008--2009 Nokia.
+ *
+ * Contributors:
+ *	Hiroshi Doyu <hiroshi.doyu@nokia.com>
+ *	Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * 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 "ispmmu.h"
+#include "isp.h"
+
+#include <mach/iommu.h>
+#include <mach/iovmm.h>
+
+#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
+
+static struct iommu *isp_iommu;
+
+dma_addr_t ispmmu_vmalloc(size_t bytes)
+{
+	return (dma_addr_t)iommu_vmalloc(isp_iommu, 0, bytes, IOMMU_FLAG);
+}
+
+void ispmmu_vfree(const dma_addr_t da)
+{
+	iommu_vfree(isp_iommu, (u32)da);
+}
+
+dma_addr_t ispmmu_kmap(u32 pa, int size)
+{
+	void *da;
+
+	da = (void *)iommu_kmap(isp_iommu, 0, pa, size, IOMMU_FLAG);
+	if (IS_ERR(da))
+		return PTR_ERR(da);
+
+	return (dma_addr_t)da;
+}
+
+void ispmmu_kunmap(dma_addr_t da)
+{
+	iommu_kunmap(isp_iommu, (u32)da);
+}
+
+dma_addr_t ispmmu_vmap(const struct scatterlist *sglist,
+		       int sglen)
+{
+	int err;
+	void *da;
+	struct sg_table *sgt;
+	unsigned int i;
+	struct scatterlist *sg, *src = (struct scatterlist *)sglist;
+
+	/*
+	 * convert isp sglist to iommu sgt
+	 * FIXME: should be fixed in the upper layer?
+	 */
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return -ENOMEM;
+	err = sg_alloc_table(sgt, sglen, GFP_KERNEL);
+	if (err)
+		goto err_sg_alloc;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i)
+		sg_set_buf(sg, phys_to_virt(sg_dma_address(src + i)),
+			   sg_dma_len(src + i));
+
+	da = (void *)iommu_vmap(isp_iommu, 0, sgt, IOMMU_FLAG);
+	if (IS_ERR(da))
+		goto err_vmap;
+
+	return (dma_addr_t)da;
+
+err_vmap:
+	sg_free_table(sgt);
+err_sg_alloc:
+	kfree(sgt);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(ispmmu_vmap);
+
+void ispmmu_vunmap(dma_addr_t da)
+{
+	struct sg_table *sgt;
+
+	sgt = iommu_vunmap(isp_iommu, (u32)da);
+	if (!sgt)
+		return;
+	sg_free_table(sgt);
+	kfree(sgt);
+}
+EXPORT_SYMBOL_GPL(ispmmu_vunmap);
+
+void ispmmu_save_context(void)
+{
+	if (isp_iommu)
+		iommu_save_ctx(isp_iommu);
+}
+
+void ispmmu_restore_context(void)
+{
+	if (isp_iommu)
+		iommu_restore_ctx(isp_iommu);
+}
+
+int __init ispmmu_init(void)
+{
+	int err = 0;
+
+	isp_get();
+	isp_iommu = iommu_get("isp");
+	if (IS_ERR(isp_iommu)) {
+		err = PTR_ERR(isp_iommu);
+		isp_iommu = NULL;
+	}
+	isp_put();
+
+	return err;
+}
+
+void ispmmu_cleanup(void)
+{
+	isp_get();
+	if (isp_iommu)
+		iommu_put(isp_iommu);
+	isp_put();
+	isp_iommu = NULL;
+}
diff --git a/drivers/media/video/isp/ispmmu.h b/drivers/media/video/isp/ispmmu.h
new file mode 100644
index 0000000..0bc5bcb
--- /dev/null
+++ b/drivers/media/video/isp/ispmmu.h
@@ -0,0 +1,36 @@
+/*
+ * omap iommu wrapper for TI's OMAP3430 Camera ISP
+ *
+ * Copyright (C) 2008--2009 Nokia.
+ *
+ * Contributors:
+ *	Hiroshi Doyu <hiroshi.doyu@nokia.com>
+ *	Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * 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_MMU_H
+#define OMAP_ISP_MMU_H
+
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+
+dma_addr_t ispmmu_vmalloc(size_t bytes);
+void ispmmu_vfree(const dma_addr_t da);
+dma_addr_t ispmmu_kmap(u32 pa, int size);
+void ispmmu_kunmap(dma_addr_t da);
+dma_addr_t ispmmu_vmap(const struct scatterlist *sglist, int sglen);
+void ispmmu_vunmap(dma_addr_t da);
+void ispmmu_save_context(void);
+void ispmmu_restore_context(void);
+int ispmmu_init(void);
+void ispmmu_cleanup(void);
+
+#endif /* OMAP_ISP_MMU_H */
-- 
1.5.6.5


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

* [PATCH 3/9] omap3isp: Add userspace header
  2009-03-03 10:06   ` [PATCH 2/9] omap3isp: Add ISP MMU wrapper Sakari Ailus
@ 2009-03-03 10:06     ` Sakari Ailus
  2009-03-03 10:06       ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Sakari Ailus
  2009-03-06 12:51       ` [PATCH 3/9] omap3isp: Add userspace header Hans Verkuil
  0 siblings, 2 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 arch/arm/plat-omap/include/mach/isp_user.h |  676 ++++++++++++++++++++++++++++
 1 files changed, 676 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/mach/isp_user.h

diff --git a/arch/arm/plat-omap/include/mach/isp_user.h b/arch/arm/plat-omap/include/mach/isp_user.h
new file mode 100644
index 0000000..b819e26
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/isp_user.h
@@ -0,0 +1,676 @@
+/*
+ * isp_user.h
+ *
+ * Include file for OMAP ISP module in TI's OMAP3.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Mohit Jalori <mjalori@ti.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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_USER_H
+#define OMAP_ISP_USER_H
+
+/* 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 \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct af_configuration)
+#define VIDIOC_PRIVATE_ISP_AF_REQ \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct isp_af_data)
+
+/* AE/AWB related structures and flags*/
+
+/* Flags for update field */
+#define REQUEST_STATISTICS	(1 << 0)
+#define SET_COLOR_GAINS		(1 << 1)
+#define SET_DIGITAL_GAIN	(1 << 2)
+#define SET_EXPOSURE		(1 << 3)
+#define SET_ANALOG_GAIN		(1 << 4)
+
+#define MAX_FRAME_COUNT		0x0FFF
+#define MAX_FUTURE_FRAMES	10
+
+#define MAX_SATURATION_LIM	1023
+#define MIN_WIN_H		2
+#define MAX_WIN_H		256
+#define MIN_WIN_W		6
+#define MAX_WIN_W		256
+#define MAX_WINVC		128
+#define MAX_WINHC		36
+#define MAX_WINSTART		4095
+#define MIN_SUB_INC		2
+#define MAX_SUB_INC		32
+
+/* Range Constants */
+#define AF_IIRSH_MIN			0
+#define AF_IIRSH_MAX			4094
+#define AF_PAXEL_HORIZONTAL_COUNT_MIN	0
+#define AF_PAXEL_HORIZONTAL_COUNT_MAX	35
+#define AF_PAXEL_VERTICAL_COUNT_MIN	0
+#define AF_PAXEL_VERTICAL_COUNT_MAX	127
+#define AF_PAXEL_INCREMENT_MIN		0
+#define AF_PAXEL_INCREMENT_MAX		14
+#define AF_PAXEL_HEIGHT_MIN		0
+#define AF_PAXEL_HEIGHT_MAX		127
+#define AF_PAXEL_WIDTH_MIN		0
+#define AF_PAXEL_WIDTH_MAX		127
+#define AF_PAXEL_HZSTART_MIN		2
+#define AF_PAXEL_HZSTART_MAX		4094
+
+#define AF_PAXEL_VTSTART_MIN		0
+#define AF_PAXEL_VTSTART_MAX		4095
+#define AF_THRESHOLD_MAX		255
+#define AF_COEF_MAX			4095
+#define AF_PAXEL_SIZE			48
+
+/**
+ * struct isph3a_aewb_config - AE AWB configuration reset values.
+ * saturation_limit: Saturation limit.
+ * @win_height: Window Height. Range 2 - 256, even values only.
+ * @win_width: Window Width. Range 6 - 256, even values only.
+ * @ver_win_count: Vertical Window Count. Range 1 - 128.
+ * @hor_win_count: Horizontal Window Count. Range 1 - 36.
+ * @ver_win_start: Vertical Window Start. Range 0 - 4095.
+ * @hor_win_start: Horizontal Window Start. Range 0 - 4095.
+ * @blk_ver_win_start: Black Vertical Windows Start. Range 0 - 4095.
+ * @blk_win_height: Black Window Height. Range 2 - 256, even values only.
+ * @subsample_ver_inc: Subsample Vertical points increment Range 2 - 32, even
+ *                     values only.
+ * @subsample_hor_inc: Subsample Horizontal points increment Range 2 - 32, even
+ *                     values only.
+ * @alaw_enable: AEW ALAW EN flag.
+ * @aewb_enable: AE AWB stats generation EN flag.
+ */
+struct isph3a_aewb_config {
+	__u16 saturation_limit;
+	__u16 win_height;
+	__u16 win_width;
+	__u16 ver_win_count;
+	__u16 hor_win_count;
+	__u16 ver_win_start;
+	__u16 hor_win_start;
+	__u16 blk_ver_win_start;
+	__u16 blk_win_height;
+	__u16 subsample_ver_inc;
+	__u16 subsample_hor_inc;
+	__u8 alaw_enable;
+	__u8 aewb_enable;
+};
+
+/**
+ * struct isph3a_aewb_data - Structure of data sent to or received from user
+ * @h3a_aewb_statistics_buf: Pointer to pass to user.
+ * @shutter: Shutter speed.
+ * @gain: Sensor analog Gain.
+ * @shutter_cap: Shutter speed for capture.
+ * @gain_cap: Sensor Gain for capture.
+ * @dgain: White balance digital gain.
+ * @wb_gain_b: White balance color gain blue.
+ * @wb_gain_r: White balance color gain red.
+ * @wb_gain_gb: White balance color gain green blue.
+ * @wb_gain_gr: White balance color gain green red.
+ * @frame_number: Frame number of requested stats.
+ * @curr_frame: Current frame number being processed.
+ * @update: Bitwise flags to update parameters.
+ * @ts: Timestamp of returned framestats.
+ * @field_count: Sequence number of returned framestats.
+ */
+struct isph3a_aewb_data {
+	void *h3a_aewb_statistics_buf;
+	__u32 shutter;
+	__u16 gain;
+	__u32 shutter_cap;
+	__u16 gain_cap;
+	__u16 dgain;
+	__u16 wb_gain_b;
+	__u16 wb_gain_r;
+	__u16 wb_gain_gb;
+	__u16 wb_gain_gr;
+	__u16 frame_number;
+	__u16 curr_frame;
+	__u8 update;
+	struct timeval ts;
+	__u32 config_counter;
+	unsigned long field_count;
+};
+
+
+/* Histogram related structs */
+/* Flags for number of bins */
+#define BINS_32			0x0
+#define BINS_64			0x1
+#define BINS_128		0x2
+#define BINS_256		0x3
+
+struct isp_hist_config {
+	__u8 hist_source;		/* CCDC or Memory */
+	__u8 input_bit_width;	/* Needed o know the size per pixel */
+	__u8 hist_frames;		/* Num of frames to be processed and
+				 * accumulated
+				 */
+	__u8 hist_h_v_info;	/* frame-input width and height if source is
+				 * memory
+				 */
+	__u16 hist_radd;		/* frame-input address in memory */
+	__u16 hist_radd_off;	/* line-offset for frame-input */
+	__u16 hist_bins;	/* number of bins: 32, 64, 128, or 256 */
+	__u16 wb_gain_R;	/* White Balance Field-to-Pattern Assignments */
+	__u16 wb_gain_RG;	/* White Balance Field-to-Pattern Assignments */
+	__u16 wb_gain_B;	/* White Balance Field-to-Pattern Assignments */
+	__u16 wb_gain_BG;	/* White Balance Field-to-Pattern Assignments */
+	__u8 num_regions;		/* number of regions to be configured */
+	__u16 reg0_hor;		/* Region 0 size and position */
+	__u16 reg0_ver;		/* Region 0 size and position */
+	__u16 reg1_hor;		/* Region 1 size and position */
+	__u16 reg1_ver;		/* Region 1 size and position */
+	__u16 reg2_hor;		/* Region 2 size and position */
+	__u16 reg2_ver;		/* Region 2 size and position */
+	__u16 reg3_hor;		/* Region 3 size and position */
+	__u16 reg3_ver;		/* Region 3 size and position */
+};
+
+struct isp_hist_data {
+	__u32 *hist_statistics_buf;	/* Pointer to pass to user */
+};
+
+/* Auto Focus related structs */
+
+#define AF_NUMBER_OF_COEF		11
+
+/* Flags for update field */
+#define REQUEST_STATISTICS		(1 << 0)
+#define LENS_DESIRED_POSITION	(1 << 1)
+#define LENS_CURRENT_POSITION	(1 << 2)
+
+/**
+ * struct isp_af_xtrastats - Extra statistics related to AF generated stats.
+ * @ts: Timestamp when the frame gets delivered to the user.
+ * @field_count: Field count of the frame delivered to the user.
+ * @lens_position: Lens position when the stats are being generated.
+ */
+struct isp_af_xtrastats {
+	struct timeval ts;
+	unsigned long field_count;
+	__u16 lens_position; /* deprecated */
+};
+
+/**
+ * struct isp_af_data - AF statistics data to transfer between driver and user.
+ * @af_statistics_buf: Pointer to pass to user.
+ * @lens_current_position: Read value of lens absolute position.
+ * @desired_lens_direction: Lens desired location.
+ * @update: Bitwise flags to update parameters.
+ * @frame_number: Data for which frame is desired/given.
+ * @curr_frame: Current frame number being processed by AF module.
+ * @xtrastats: Extra statistics structure.
+ */
+struct isp_af_data {
+	void *af_statistics_buf;
+	__u16 lens_current_position; /* deprecated */
+	__u16 desired_lens_direction; /* deprecated */
+	__u16 update;
+	__u16 frame_number;
+	__u16 curr_frame;
+	__u32 config_counter;
+	struct isp_af_xtrastats xtrastats;
+};
+
+/* enum used for status of specific feature */
+enum af_alaw_enable {
+	H3A_AF_ALAW_DISABLE = 0,
+	H3A_AF_ALAW_ENABLE = 1
+};
+
+enum af_hmf_enable {
+	H3A_AF_HMF_DISABLE = 0,
+	H3A_AF_HMF_ENABLE = 1
+};
+
+enum af_config_flag {
+	H3A_AF_CFG_DISABLE = 0,
+	H3A_AF_CFG_ENABLE = 1
+};
+
+enum af_mode {
+	ACCUMULATOR_SUMMED = 0,
+	ACCUMULATOR_PEAK = 1
+};
+
+/* Red, Green, and blue pixel location in the AF windows */
+enum rgbpos {
+	GR_GB_BAYER = 0,	/* GR and GB as Bayer pattern */
+	RG_GB_BAYER = 1,	/* RG and GB as Bayer pattern */
+	GR_BG_BAYER = 2,	/* GR and BG as Bayer pattern */
+	RG_BG_BAYER = 3,	/* RG and BG as Bayer pattern */
+	GG_RB_CUSTOM = 4,	/* GG and RB as custom pattern */
+	RB_GG_CUSTOM = 5	/* RB and GG as custom pattern */
+};
+
+/* Contains the information regarding the Horizontal Median Filter */
+struct af_hmf {
+	enum af_hmf_enable enable;	/* Status of Horizontal Median Filter */
+	unsigned int threshold;	/* Threshhold Value for Horizontal Median
+				 * Filter
+				 */
+};
+
+/* Contains the information regarding the IIR Filters */
+struct af_iir {
+	unsigned int hz_start_pos;	/* IIR Start Register Value */
+	int coeff_set0[AF_NUMBER_OF_COEF];	/*
+						 * IIR Filter Coefficient for
+						 * Set 0
+						 */
+	int coeff_set1[AF_NUMBER_OF_COEF];	/*
+						 * IIR Filter Coefficient for
+						 * Set 1
+						 */
+};
+
+/* Contains the information regarding the Paxels Structure in AF Engine */
+struct af_paxel {
+	unsigned int width;	/* Width of the Paxel */
+	unsigned int height;	/* Height of the Paxel */
+	unsigned int hz_start;	/* Horizontal Start Position */
+	unsigned int vt_start;	/* Vertical Start Position */
+	unsigned int hz_cnt;	/* Horizontal Count */
+	unsigned int vt_cnt;	/* vertical Count */
+	unsigned int line_incr;	/* Line Increment */
+};
+/* Contains the parameters required for hardware set up of AF Engine */
+struct af_configuration {
+	enum af_alaw_enable alaw_enable;	/*ALWAW status */
+	struct af_hmf hmf_config;	/*HMF configurations */
+	enum rgbpos rgb_pos;		/*RGB Positions */
+	struct af_iir iir_config;	/*IIR filter configurations */
+	struct af_paxel paxel_config;	/*Paxel parameters */
+	enum af_mode mode;		/*Accumulator mode */
+	enum af_config_flag af_config; /*Flag indicates Engine is configured */
+};
+
+/* ISP CCDC structs */
+
+/* Abstraction layer CCDC configurations */
+#define ISP_ABS_CCDC_ALAW		(1 << 0)
+#define ISP_ABS_CCDC_LPF 		(1 << 1)
+#define ISP_ABS_CCDC_BLCLAMP		(1 << 2)
+#define ISP_ABS_CCDC_BCOMP		(1 << 3)
+#define ISP_ABS_CCDC_FPC		(1 << 4)
+#define ISP_ABS_CCDC_CULL		(1 << 5)
+#define ISP_ABS_CCDC_COLPTN		(1 << 6)
+#define ISP_ABS_CCDC_CONFIG_LSC		(1 << 7)
+#define ISP_ABS_TBL_LSC			(1 << 8)
+
+#define RGB_MAX				3
+
+/* Enumeration constants for Alaw input width */
+enum alaw_ipwidth {
+	ALAW_BIT12_3 = 0x3,
+	ALAW_BIT11_2 = 0x4,
+	ALAW_BIT10_1 = 0x5,
+	ALAW_BIT9_0 = 0x6
+};
+
+/* Enumeration constants for Video Port */
+enum vpin {
+	BIT12_3 = 3,
+	BIT11_2 = 4,
+	BIT10_1 = 5,
+	BIT9_0 = 6
+};
+
+enum vpif_freq {
+	PIXCLKBY2,
+	PIXCLKBY3_5,
+	PIXCLKBY4_5,
+	PIXCLKBY5_5,
+	PIXCLKBY6_5
+};
+
+/**
+ * struct ispccdc_lsc_config - Structure for LSC configuration.
+ * @offset: Table Offset of the gain table.
+ * @gain_mode_n: Vertical dimension of a paxel in LSC configuration.
+ * @gain_mode_m: Horizontal dimension of a paxel in LSC configuration.
+ * @gain_format: Gain table format.
+ * @fmtsph: Start pixel horizontal from start of the HS sync pulse.
+ * @fmtlnh: Number of pixels in horizontal direction to use for the data
+ *          reformatter.
+ * @fmtslv: Start line from start of VS sync pulse for the data reformatter.
+ * @fmtlnv: Number of lines in vertical direction for the data reformatter.
+ * @initial_x: X position, in pixels, of the first active pixel in reference
+ *             to the first active paxel. Must be an even number.
+ * @initial_y: Y position, in pixels, of the first active pixel in reference
+ *             to the first active paxel. Must be an even number.
+ * @size: Size of LSC gain table. Filled when loaded from userspace.
+ */
+struct ispccdc_lsc_config {
+	__u16 offset;
+	__u8 gain_mode_n;
+	__u8 gain_mode_m;
+	__u8 gain_format;
+	__u16 fmtsph;
+	__u16 fmtlnh;
+	__u16 fmtslv;
+	__u16 fmtlnv;
+	__u8 initial_x;
+	__u8 initial_y;
+	__u32 size;
+};
+
+/**
+ * struct ispccdc_bclamp - Structure for Optical & Digital black clamp subtract
+ * @obgain: Optical black average gain.
+ * @obstpixel: Start Pixel w.r.t. HS pulse in Optical black sample.
+ * @oblines: Optical Black Sample lines.
+ * @oblen: Optical Black Sample Length.
+ * @dcsubval: Digital Black Clamp subtract value.
+ */
+struct ispccdc_bclamp {
+	__u8 obgain;
+	__u8 obstpixel;
+	__u8 oblines;
+	__u8 oblen;
+	__u16 dcsubval;
+};
+
+/**
+ * ispccdc_fpc - Structure for FPC
+ * @fpnum: Number of faulty pixels to be corrected in the frame.
+ * @fpcaddr: Memory address of the FPC Table
+ */
+struct ispccdc_fpc {
+	__u16 fpnum;
+	__u32 fpcaddr;
+};
+
+/**
+ * ispccdc_blcomp - Structure for Black Level Compensation parameters.
+ * @b_mg: B/Mg pixels. 2's complement. -128 to +127.
+ * @gb_g: Gb/G pixels. 2's complement. -128 to +127.
+ * @gr_cy: Gr/Cy pixels. 2's complement. -128 to +127.
+ * @r_ye: R/Ye pixels. 2's complement. -128 to +127.
+ */
+struct ispccdc_blcomp {
+	__u8 b_mg;
+	__u8 gb_g;
+	__u8 gr_cy;
+	__u8 r_ye;
+};
+
+/**
+ * struct ispccdc_vp - Structure for Video Port parameters
+ * @bitshift_sel: Video port input select. 3 - bits 12-3, 4 - bits 11-2,
+ *                5 - bits 10-1, 6 - bits 9-0.
+ * @freq_sel: Video port data ready frequency. 1 - 1/3.5, 2 - 1/4.5,
+ *            3 - 1/5.5, 4 - 1/6.5.
+ */
+struct ispccdc_vp {
+	enum vpin bitshift_sel;
+	enum vpif_freq freq_sel;
+};
+
+/**
+ * ispccdc_culling - Structure for Culling parameters.
+ * @v_pattern: Vertical culling pattern.
+ * @h_odd: Horizontal Culling pattern for odd lines.
+ * @h_even: Horizontal Culling pattern for even lines.
+ */
+struct ispccdc_culling {
+	__u8 v_pattern;
+	__u16 h_odd;
+	__u16 h_even;
+};
+
+/**
+ * ispccdc_update_config - Structure for CCDC configuration.
+ * @update: Specifies which CCDC registers should be updated.
+ * @flag: Specifies which CCDC functions should be enabled.
+ * @alawip: Enable/Disable A-Law compression.
+ * @bclamp: Black clamp control register.
+ * @blcomp: Black level compensation value for RGrGbB Pixels. 2's complement.
+ * @fpc: Number of faulty pixels corrected in the frame, address of FPC table.
+ * @cull: Cull control register.
+ * @colptn: Color pattern of the sensor.
+ * @lsc: Pointer to LSC gain table.
+ */
+struct ispccdc_update_config {
+	__u16 update;
+	__u16 flag;
+	enum alaw_ipwidth alawip;
+	struct ispccdc_bclamp *bclamp;
+	struct ispccdc_blcomp *blcomp;
+	struct ispccdc_fpc *fpc;
+	struct ispccdc_lsc_config *lsc_cfg;
+	struct ispccdc_culling *cull;
+	__u32 colptn;
+	__u8 *lsc;
+};
+
+/* Preview configuration */
+
+/*Abstraction layer preview configurations*/
+#define ISP_ABS_PREV_LUMAENH		(1 << 0)
+#define ISP_ABS_PREV_INVALAW		(1 << 1)
+#define ISP_ABS_PREV_HRZ_MED		(1 << 2)
+#define ISP_ABS_PREV_CFA		(1 << 3)
+#define ISP_ABS_PREV_CHROMA_SUPP	(1 << 4)
+#define ISP_ABS_PREV_WB			(1 << 5)
+#define ISP_ABS_PREV_BLKADJ		(1 << 6)
+#define ISP_ABS_PREV_RGB2RGB		(1 << 7)
+#define ISP_ABS_PREV_COLOR_CONV		(1 << 8)
+#define ISP_ABS_PREV_YC_LIMIT		(1 << 9)
+#define ISP_ABS_PREV_DEFECT_COR		(1 << 10)
+#define ISP_ABS_PREV_GAMMABYPASS	(1 << 11)
+#define ISP_ABS_TBL_NF 			(1 << 12)
+#define ISP_ABS_TBL_REDGAMMA		(1 << 13)
+#define ISP_ABS_TBL_GREENGAMMA		(1 << 14)
+#define ISP_ABS_TBL_BLUEGAMMA		(1 << 15)
+
+#define ISPPRV_NF_TBL_SIZE		64
+#define ISPPRV_CFA_TBL_SIZE		576
+#define ISPPRV_GAMMA_TBL_SIZE		1024
+#define ISPPRV_YENH_TBL_SIZE		128
+
+/**
+ * struct ispprev_hmed - Structure for Horizontal Median Filter.
+ * @odddist: Distance between consecutive pixels of same color in the odd line.
+ * @evendist: Distance between consecutive pixels of same color in the even
+ *            line.
+ * @thres: Horizontal median filter threshold.
+ */
+struct ispprev_hmed {
+	__u8 odddist;
+	__u8 evendist;
+	__u8 thres;
+};
+
+/*
+ * Enumeration for CFA Formats supported by preview
+ */
+enum cfa_fmt {
+	CFAFMT_BAYER, CFAFMT_SONYVGA, CFAFMT_RGBFOVEON,
+	CFAFMT_DNSPL, CFAFMT_HONEYCOMB, CFAFMT_RRGGBBFOVEON
+};
+
+/**
+ * struct ispprev_cfa - Structure for CFA Inpterpolation.
+ * @cfafmt: CFA Format Enum value supported by preview.
+ * @cfa_gradthrs_vert: CFA Gradient Threshold - Vertical.
+ * @cfa_gradthrs_horz: CFA Gradient Threshold - Horizontal.
+ * @cfa_table: Pointer to the CFA table.
+ */
+struct ispprev_cfa {
+	enum cfa_fmt cfafmt;
+	__u8 cfa_gradthrs_vert;
+	__u8 cfa_gradthrs_horz;
+	__u32 *cfa_table;
+};
+
+/**
+ * struct ispprev_csup - Structure for Chrominance Suppression.
+ * @gain: Gain.
+ * @thres: Threshold.
+ * @hypf_en: Flag to enable/disable the High Pass Filter.
+ */
+struct ispprev_csup {
+	__u8 gain;
+	__u8 thres;
+	__u8 hypf_en;
+};
+
+/**
+ * struct ispprev_wbal - Structure for White Balance.
+ * @dgain: Digital gain (U10Q8).
+ * @coef3: White balance gain - COEF 3 (U8Q5).
+ * @coef2: White balance gain - COEF 2 (U8Q5).
+ * @coef1: White balance gain - COEF 1 (U8Q5).
+ * @coef0: White balance gain - COEF 0 (U8Q5).
+ */
+struct ispprev_wbal {
+	__u16 dgain;
+	__u8 coef3;
+	__u8 coef2;
+	__u8 coef1;
+	__u8 coef0;
+};
+
+/**
+ * struct ispprev_blkadj - Structure for Black Adjustment.
+ * @red: Black level offset adjustment for Red in 2's complement format
+ * @green: Black level offset adjustment for Green in 2's complement format
+ * @blue: Black level offset adjustment for Blue in 2's complement format
+ */
+struct ispprev_blkadj {
+	/*Black level offset adjustment for Red in 2's complement format */
+	__u8 red;
+	/*Black level offset adjustment for Green in 2's complement format */
+	__u8 green;
+	/* Black level offset adjustment for Blue in 2's complement format */
+	__u8 blue;
+};
+
+/**
+ * struct ispprev_rgbtorgb - Structure for RGB to RGB Blending.
+ * @matrix: Blending values(S12Q8 format)
+ *              [RR] [GR] [BR]
+ *              [RG] [GG] [BG]
+ *              [RB] [GB] [BB]
+ * @offset: Blending offset value for R,G,B in 2's complement integer format.
+ */
+struct ispprev_rgbtorgb {
+	__u16 matrix[3][3];
+	__u16 offset[3];
+};
+
+/**
+ * struct ispprev_csc - Structure for Color Space Conversion from RGB-YCbYCr
+ * @matrix: Color space conversion coefficients(S10Q8)
+ *              [CSCRY]  [CSCGY]  [CSCBY]
+ *              [CSCRCB] [CSCGCB] [CSCBCB]
+ *              [CSCRCR] [CSCGCR] [CSCBCR]
+ * @offset: CSC offset values for Y offset, CB offset and CR offset respectively
+ */
+struct ispprev_csc {
+	__u16 matrix[RGB_MAX][RGB_MAX];
+	__s16 offset[RGB_MAX];
+};
+
+/**
+ * struct ispprev_yclimit - Structure for Y, C Value Limit.
+ * @minC: Minimum C value
+ * @maxC: Maximum C value
+ * @minY: Minimum Y value
+ * @maxY: Maximum Y value
+ */
+struct ispprev_yclimit {
+	__u8 minC;
+	__u8 maxC;
+	__u8 minY;
+	__u8 maxY;
+};
+
+/**
+ * struct ispprev_dcor - Structure for Defect correction.
+ * @couplet_mode_en: Flag to enable or disable the couplet dc Correction in NF
+ * @detect_correct: Thresholds for correction bit 0:10 detect 16:25 correct
+ */
+struct ispprev_dcor {
+	__u8 couplet_mode_en;
+	__u32 detect_correct[4];
+};
+
+/**
+ * struct ispprev_nf - Structure for Noise Filter
+ * @spread: Spread value to be used in Noise Filter
+ * @table: Pointer to the Noise Filter table
+ */
+struct ispprev_nf {
+	__u8 spread;
+	__u32 table[ISPPRV_NF_TBL_SIZE];
+};
+
+/**
+ * struct ispprv_update_config - Structure for Preview Configuration (user).
+ * @update: Specifies which ISP Preview registers should be updated.
+ * @flag: Specifies which ISP Preview functions should be enabled.
+ * @yen: Pointer to luma enhancement table.
+ * @shading_shift: 3bit value of shift used in shading compensation.
+ * @prev_hmed: Pointer to structure containing the odd and even distance.
+ *             between the pixels in the image along with the filter threshold.
+ * @prev_cfa: Pointer to structure containing the CFA interpolation table, CFA.
+ *            format in the image, vertical and horizontal gradient threshold.
+ * @csup: Pointer to Structure for Chrominance Suppression coefficients.
+ * @prev_wbal: Pointer to structure for White Balance.
+ * @prev_blkadj: Pointer to structure for Black Adjustment.
+ * @rgb2rgb: Pointer to structure for RGB to RGB Blending.
+ * @prev_csc: Pointer to structure for Color Space Conversion from RGB-YCbYCr.
+ * @yclimit: Pointer to structure for Y, C Value Limit.
+ * @prev_dcor: Pointer to structure for defect correction.
+ * @prev_nf: Pointer to structure for Noise Filter
+ * @red_gamma: Pointer to red gamma correction table.
+ * @green_gamma: Pointer to green gamma correction table.
+ * @blue_gamma: Pointer to blue gamma correction table.
+ */
+struct ispprv_update_config {
+	__u16 update;
+	__u16 flag;
+	void *yen;
+	__u32 shading_shift;
+	struct ispprev_hmed *prev_hmed;
+	struct ispprev_cfa *prev_cfa;
+	struct ispprev_csup *csup;
+	struct ispprev_wbal *prev_wbal;
+	struct ispprev_blkadj *prev_blkadj;
+	struct ispprev_rgbtorgb *rgb2rgb;
+	struct ispprev_csc *prev_csc;
+	struct ispprev_yclimit *yclimit;
+	struct ispprev_dcor *prev_dcor;
+	struct ispprev_nf *prev_nf;
+	__u32 *red_gamma;
+	__u32 *green_gamma;
+	__u32 *blue_gamma;
+};
+
+#endif /* OMAP_ISP_USER_H */
-- 
1.5.6.5


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

* [PATCH 4/9] omap3isp: Add ISP frontend (CCDC)
  2009-03-03 10:06     ` [PATCH 3/9] omap3isp: Add userspace header Sakari Ailus
@ 2009-03-03 10:06       ` Sakari Ailus
  2009-03-03 10:06         ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Sakari Ailus
  2009-03-03 12:07         ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Alexey Klimov
  2009-03-06 12:51       ` [PATCH 3/9] omap3isp: Add userspace header Hans Verkuil
  1 sibling, 2 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/isp/ispccdc.c | 1568 +++++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/ispccdc.h |  203 +++++
 2 files changed, 1771 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/ispccdc.c
 create mode 100644 drivers/media/video/isp/ispccdc.h

diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c
new file mode 100644
index 0000000..80ab762
--- /dev/null
+++ b/drivers/media/video/isp/ispccdc.c
@@ -0,0 +1,1568 @@
+/*
+ * ispccdc.c
+ *
+ * Driver Library for CCDC module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Senthilvadivu Guruswamy <svadivu@ti.com>
+ *	Pallavi Kulkarni <p-kulkarni@ti.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispccdc.h"
+#include "ispmmu.h"
+
+#define LSC_TABLE_INIT_SIZE	50052
+
+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; /* For checking/modifying ccdc_inuse */
+	u32 wenlog;
+} ispccdc_obj;
+
+static struct ispccdc_lsc_config lsc_config;
+static u8 *lsc_gain_table;
+static unsigned long lsc_ispmmu_addr;
+static int lsc_initialized;
+static u8 ccdc_use_lsc;
+static u8 *lsc_gain_table_tmp;
+
+/* Structure for saving/restoring CCDC module registers*/
+static struct isp_reg ispccdc_reg_list[] = {
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HD_VD_WID, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PIX_LINES, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR0, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR1, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR2, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR3, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR4, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR5, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR6, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR7, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN0, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN1, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD0, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD1, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE, 0},
+	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_OFFSET, 0},
+	{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 = userspace_add;
+
+	if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) {
+		if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
+			ispccdc_config_alaw(ccdc_struct->alawip);
+		ispccdc_enable_alaw(1);
+	} else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
+		ispccdc_enable_alaw(0);
+
+	if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
+		ispccdc_enable_lpf(1);
+	else
+		ispccdc_enable_lpf(0);
+
+	if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) {
+		if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
+			if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
+						(ccdc_struct->bclamp),
+						sizeof(struct ispccdc_bclamp)))
+				goto copy_from_user_err;
+
+			ispccdc_enable_black_clamp(1);
+			ispccdc_config_black_clamp(bclamp_t);
+		} else
+			ispccdc_enable_black_clamp(1);
+	} else {
+		if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
+			if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
+						(ccdc_struct->bclamp),
+						sizeof(struct ispccdc_bclamp)))
+				goto copy_from_user_err;
+
+			ispccdc_enable_black_clamp(0);
+			ispccdc_config_black_clamp(bclamp_t);
+		}
+	}
+
+	if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) {
+		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) {
+		if (ISP_ABS_CCDC_FPC & ccdc_struct->update) {
+			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_kmap(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)
+			ispccdc_enable_fpc(0);
+
+	if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
+		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 (is_isplsc_activated()) {
+		if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) {
+			if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
+				if (copy_from_user(&lsc_config,
+						(struct ispccdc_lsc_config *)
+						(ccdc_struct->lsc_cfg),
+						sizeof(struct
+						ispccdc_lsc_config)))
+					goto copy_from_user_err;
+				ispccdc_config_lsc(&lsc_config);
+			}
+			ccdc_use_lsc = 1;
+		} else if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
+				ispccdc_enable_lsc(0);
+				ccdc_use_lsc = 0;
+		}
+		if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
+			if (copy_from_user(lsc_gain_table,
+				(ccdc_struct->lsc), lsc_config.size))
+				goto copy_from_user_err;
+			ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
+		}
+	}
+
+	if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
+		ispccdc_config_imgattr(ccdc_struct->colptn);
+
+	return 0;
+
+copy_from_user_err:
+	printk(KERN_ERR "CCDC Config:Copy From User Error");
+	return -EINVAL ;
+}
+EXPORT_SYMBOL(omap34xx_isp_ccdc_config);
+
+/**
+ * Set the value to be used for CCDC_CFG.WENLOG.
+ *  w - Value of wenlog.
+ */
+void ispccdc_set_wenlog(u32 wenlog)
+{
+	ispccdc_obj.wenlog = wenlog;
+}
+EXPORT_SYMBOL(ispccdc_set_wenlog);
+
+/**
+ * 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);
+	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_CCDC_RAM_EN |
+							ISPCTRL_CCDC_CLK_EN |
+							ISPCTRL_SBL_WR1_RAM_EN);
+	isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
+	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);
+	isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+			~(ISPCTRL_CCDC_CLK_EN |
+			ISPCTRL_CCDC_RAM_EN |
+			ISPCTRL_SBL_WR1_RAM_EN));
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_free);
+
+/**
+ * ispccdc_free_lsc - Frees Lens Shading Compensation table
+ *
+ * Always returns 0.
+ **/
+static int ispccdc_free_lsc(void)
+{
+	if (!lsc_ispmmu_addr)
+		return 0;
+
+	ispccdc_enable_lsc(0);
+	lsc_initialized = 0;
+	isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
+	ispmmu_kunmap(lsc_ispmmu_addr);
+	kfree(lsc_gain_table);
+	return 0;
+}
+
+/**
+ * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table
+ * @table_size: LSC gain table size.
+ *
+ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
+ * table_size is zero.
+ **/
+static int ispccdc_allocate_lsc(u32 table_size)
+{
+	if (table_size == 0)
+		return -EINVAL;
+
+	if ((lsc_config.size >= table_size) && lsc_gain_table)
+		return 0;
+
+	ispccdc_free_lsc();
+
+	lsc_gain_table = kmalloc(table_size, GFP_KERNEL | GFP_DMA);
+
+	if (!lsc_gain_table) {
+		printk(KERN_ERR "Cannot allocate memory for gain tables \n");
+		return -ENOMEM;
+	}
+
+	lsc_ispmmu_addr = ispmmu_kmap(virt_to_phys(lsc_gain_table), table_size);
+	if (lsc_ispmmu_addr <= 0) {
+		printk(KERN_ERR "Cannot map memory for gain tables \n");
+		kfree(lsc_gain_table);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ * ispccdc_program_lsc - Program Lens Shading Compensation table.
+ * @table_size: LSC gain table size.
+ *
+ * Returns 0 if successful, or -EINVAL if there's no mapped address for the
+ * table yet.
+ **/
+static int ispccdc_program_lsc(void)
+{
+	if (!lsc_ispmmu_addr)
+		return -EINVAL;
+
+	if (lsc_initialized)
+		return 0;
+
+	isp_reg_writel(lsc_ispmmu_addr, OMAP3_ISP_IOMEM_CCDC,
+						ISPCCDC_LSC_TABLE_BASE);
+	lsc_initialized = 1;
+	return 0;
+}
+
+/**
+ * ispccdc_load_lsc - Load Lens Shading Compensation table.
+ * @table_addr: LSC gain table MMU Mapped address.
+ * @table_size: LSC gain table size.
+ *
+ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
+ * table_size is zero.
+ **/
+int ispccdc_load_lsc(u8 *table_addr, u32 table_size)
+{
+	int ret;
+
+	if (!is_isplsc_activated())
+		return 0;
+
+	if (!table_addr)
+		return -EINVAL;
+
+	ret = ispccdc_allocate_lsc(table_size);
+	if (ret)
+		return ret;
+
+	if (table_addr != lsc_gain_table)
+		memcpy(lsc_gain_table, table_addr, table_size);
+	ret = ispccdc_program_lsc();
+	if (ret)
+		return ret;
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_load_lsc);
+
+/**
+ * ispccdc_config_lsc - Configures the lens shading compensation module
+ * @lsc_cfg: LSC configuration structure
+ **/
+void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg)
+{
+	int reg;
+
+	if (!is_isplsc_activated())
+		return;
+
+	ispccdc_enable_lsc(0);
+	isp_reg_writel(lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_LSC_TABLE_OFFSET);
+
+	reg = 0;
+	reg |= (lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT);
+	reg |= (lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT);
+	reg |= (lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT);
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
+
+	reg = 0;
+	reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
+	reg |= (lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT);
+	reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
+	reg |= (lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT);
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL);
+}
+EXPORT_SYMBOL(ispccdc_config_lsc);
+
+/**
+ * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module.
+ * @enable: 0 Disables LSC, 1 Enables LSC.
+ **/
+void ispccdc_enable_lsc(u8 enable)
+{
+	if (!is_isplsc_activated())
+		return;
+
+	if (enable) {
+		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+			ISPCTRL_SBL_SHARED_RPORTB | ISPCTRL_SBL_RD_RAM_EN);
+
+		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0x1);
+
+		ispccdc_obj.lsc_en = 1;
+	} else {
+		isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0xFFFE);
+		ispccdc_obj.lsc_en = 0;
+	}
+}
+EXPORT_SYMBOL(ispccdc_enable_lsc);
+
+
+/**
+ * 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 % 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_RSZ)) {
+		DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC I/O Combination\n");
+		return -EINVAL;
+	}
+
+	syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	switch (output) {
+	case CCDC_YUV_RSZ:
+		syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
+		syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
+		break;
+
+	case CCDC_YUV_MEM_RSZ:
+		syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
+		ispccdc_obj.wen = 1;
+		syn_mode |= ISPCCDC_SYN_MODE_WEN;
+		break;
+
+	case CCDC_OTHERS_VP:
+		syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
+		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
+		syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
+		vpcfg.bitshift_sel = BIT9_0;
+		vpcfg.freq_sel = PIXCLKBY2;
+		ispccdc_config_vp(vpcfg);
+		ispccdc_enable_vp(1);
+		break;
+
+	case CCDC_OTHERS_MEM:
+		syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
+		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
+		syn_mode |= ISPCCDC_SYN_MODE_WEN;
+		syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
+		isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+							~ISPCCDC_CFG_WENLOG);
+		vpcfg.bitshift_sel = BIT11_2;
+		vpcfg.freq_sel = PIXCLKBY2;
+		ispccdc_config_vp(vpcfg);
+		ispccdc_enable_vp(0);
+		break;
+
+	case CCDC_OTHERS_VP_MEM:
+		syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
+		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
+		syn_mode |= ISPCCDC_SYN_MODE_WEN;
+		syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
+
+		isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+							~ISPCCDC_CFG_WENLOG,
+							ispccdc_obj.wenlog);
+		vpcfg.bitshift_sel = BIT9_0;
+		vpcfg.freq_sel = PIXCLKBY2;
+		ispccdc_config_vp(vpcfg);
+		ispccdc_enable_vp(1);
+		break;
+	default:
+		DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output");
+		return -EINVAL;
+	};
+
+	isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	switch (input) {
+	case CCDC_RAW:
+		syncif.ccdc_mastermode = 0;
+		syncif.datapol = 0;
+		syncif.datsz = DAT10;
+		syncif.fldmode = 0;
+		syncif.fldout = 0;
+		syncif.fldpol = 0;
+		syncif.fldstat = 0;
+		syncif.hdpol = 0;
+		syncif.ipmod = RAW;
+		syncif.vdpol = 0;
+		ispccdc_config_sync_if(syncif);
+		ispccdc_config_imgattr(colptn);
+		blkcfg.dcsubval = 64;
+		ispccdc_config_black_clamp(blkcfg);
+		if (is_isplsc_activated()) {
+			ispccdc_config_lsc(&lsc_config);
+			ispccdc_load_lsc(lsc_gain_table_tmp,
+							LSC_TABLE_INIT_SIZE);
+		}
+
+		break;
+	case CCDC_YUV_SYNC:
+		syncif.ccdc_mastermode = 0;
+		syncif.datapol = 0;
+		syncif.datsz = DAT8;
+		syncif.fldmode = 0;
+		syncif.fldout = 0;
+		syncif.fldpol = 0;
+		syncif.fldstat = 0;
+		syncif.hdpol = 0;
+		syncif.ipmod = YUV16;
+		syncif.vdpol = 1;
+		ispccdc_config_imgattr(0);
+		ispccdc_config_sync_if(syncif);
+		blkcfg.dcsubval = 0;
+		ispccdc_config_black_clamp(blkcfg);
+		break;
+	case CCDC_YUV_BT:
+		break;
+	case CCDC_OTHERS:
+		break;
+	default:
+		DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input");
+		return -EINVAL;
+	}
+
+	ispccdc_obj.ccdc_inpfmt = input;
+	ispccdc_obj.ccdc_outfmt = output;
+	ispccdc_print_status();
+	isp_print_status();
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_config_datapath);
+
+/**
+ * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC.
+ * @syncif: Structure containing the sync parameters like field state, CCDC in
+ *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
+ *          signals.
+ **/
+void ispccdc_config_sync_if(struct ispccdc_syncif syncif)
+{
+	u32 syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
+
+	if (syncif.fldstat)
+		syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
+
+	syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
+	ispccdc_obj.syncif_ipmod = syncif.ipmod;
+
+	switch (syncif.ipmod) {
+	case RAW:
+		break;
+	case YUV16:
+		syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
+		break;
+	case YUV8:
+		syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
+		break;
+	};
+
+	syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
+	switch (syncif.datsz) {
+	case DAT8:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
+		break;
+	case DAT10:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
+		break;
+	case DAT11:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
+		break;
+	case DAT12:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
+		break;
+	};
+
+	if (syncif.fldmode)
+		syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
+
+	if (syncif.datapol)
+		syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
+
+	if (syncif.fldpol)
+		syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
+
+	if (syncif.hdpol)
+		syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
+
+	if (syncif.vdpol)
+		syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
+
+	if (syncif.ccdc_mastermode) {
+		syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
+		isp_reg_writel((syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT)
+						| (syncif.vs_width <<
+						ISPCCDC_HD_VD_WID_VDW_SHIFT),
+						OMAP3_ISP_IOMEM_CCDC,
+						ISPCCDC_HD_VD_WID);
+
+		isp_reg_writel(syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
+			| syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
+			OMAP3_ISP_IOMEM_CCDC,
+			ISPCCDC_PIX_LINES);
+	} else
+		syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
+						ISPCCDC_SYN_MODE_VDHDOUT);
+
+	isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	if (!(syncif.bt_r656_en)) {
+		isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
+						~ISPCCDC_REC656IF_R656ON);
+	}
+}
+EXPORT_SYMBOL(ispccdc_config_sync_if);
+
+/**
+ * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC.
+ * @bclamp: Structure containing the optical black average gain, optical black
+ *          sample length, sample lines, and the start pixel position of the
+ *          samples w.r.t the HS pulse.
+ * Configures the clamp parameters in CCDC. Either if its being used the
+ * optical black clamp, or the digital clamp. If its a digital clamp, then
+ * assures to put a valid DC substraction level.
+ *
+ * Returns always 0 when completed.
+ **/
+int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp)
+{
+	u32 bclamp_val = 0;
+
+	if (ispccdc_obj.obclamp_en) {
+		bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
+		bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
+		bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
+		bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
+		isp_reg_writel(bclamp_val, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_CLAMP);
+	} else {
+		if (omap_rev() < OMAP3430_REV_ES2_0)
+			if ((ispccdc_obj.syncif_ipmod == YUV16) ||
+					(ispccdc_obj.syncif_ipmod == YUV8) ||
+					(isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_REC656IF) &
+					ISPCCDC_REC656IF_R656ON))
+				bclamp.dcsubval = 0;
+		isp_reg_writel(bclamp.dcsubval, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_DCSUB);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_config_black_clamp);
+
+/**
+ * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp.
+ * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp.
+ *
+ * Enables or disables the optical black clamp. When disabled, the digital
+ * clamp operates.
+ **/
+void ispccdc_enable_black_clamp(u8 enable)
+{
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
+					~ISPCCDC_CLAMP_CLAMPEN,
+					enable ? ISPCCDC_CLAMP_CLAMPEN : 0);
+	ispccdc_obj.obclamp_en = enable;
+}
+EXPORT_SYMBOL(ispccdc_enable_black_clamp);
+
+/**
+ * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
+ * @fpc: Structure containing the number of faulty pixels corrected in the
+ *       frame, address of the FPC table.
+ *
+ * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
+ * boundary.
+ **/
+int ispccdc_config_fpc(struct ispccdc_fpc fpc)
+{
+	u32 fpc_val = 0;
+
+	fpc_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
+
+	if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
+		isp_reg_writel(fpc_val & (~ISPCCDC_FPC_FPCEN),
+					OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
+		isp_reg_writel(fpc.fpcaddr,
+				OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
+	} else {
+		DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
+		return -EINVAL;
+	}
+	isp_reg_writel(fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_config_fpc);
+
+/**
+ * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
+ * @enable: 0 Disables FPC, 1 Enables FPC.
+ **/
+void ispccdc_enable_fpc(u8 enable)
+{
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
+					~ISPCCDC_FPC_FPCEN,
+					enable ? ISPCCDC_FPC_FPCEN : 0);
+}
+EXPORT_SYMBOL(ispccdc_enable_fpc);
+
+/**
+ * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
+ * @blcomp: Structure containing the black level compensation value for RGrGbB
+ *          pixels. in 2's complement.
+ **/
+void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp)
+{
+	u32 blcomp_val = 0;
+
+	blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
+	blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
+	blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
+	blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
+
+	isp_reg_writel(blcomp_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
+}
+EXPORT_SYMBOL(ispccdc_config_black_comp);
+
+/**
+ * ispccdc_config_vp - Configures the Video Port Configuration parameters.
+ * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
+ *         format.
+ **/
+void ispccdc_config_vp(struct ispccdc_vp vpcfg)
+{
+	u32 fmtcfg_vp = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
+
+	fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCF_VPIF_FRQ_MASK;
+
+	switch (vpcfg.bitshift_sel) {
+	case BIT9_0:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
+		break;
+	case BIT10_1:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
+		break;
+	case BIT11_2:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
+		break;
+	case BIT12_3:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
+		break;
+	};
+	switch (vpcfg.freq_sel) {
+	case PIXCLKBY2:
+		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY2;
+		break;
+	case PIXCLKBY3_5:
+		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY3;
+		break;
+	case PIXCLKBY4_5:
+		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY4;
+		break;
+	case PIXCLKBY5_5:
+		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY5;
+		break;
+	case PIXCLKBY6_5:
+		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY6;
+		break;
+	};
+	isp_reg_writel(fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
+}
+EXPORT_SYMBOL(ispccdc_config_vp);
+
+/**
+ * ispccdc_enable_vp - Enables the Video Port.
+ * @enable: 0 Disables VP, 1 Enables VP
+ **/
+void ispccdc_enable_vp(u8 enable)
+{
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
+					~ISPCCDC_FMTCFG_VPEN,
+					enable ? ISPCCDC_FMTCFG_VPEN : 0);
+}
+EXPORT_SYMBOL(ispccdc_enable_vp);
+
+/**
+ * ispccdc_config_reformatter - Configures the Reformatter.
+ * @refmt: Structure containing the memory address to format and the bit fields
+ *         for the reformatter registers.
+ *
+ * Configures the Reformatter register values if line alternating is disabled.
+ * Else, just enabling line alternating is enough.
+ **/
+void ispccdc_config_reformatter(struct ispccdc_refmt refmt)
+{
+	u32 fmtcfg_val = 0;
+
+	fmtcfg_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
+
+	if (refmt.lnalt)
+		fmtcfg_val |= ISPCCDC_FMTCFG_LNALT;
+	else {
+		fmtcfg_val &= ~ISPCCDC_FMTCFG_LNALT;
+		fmtcfg_val &= 0xFFFFF003;
+		fmtcfg_val |= refmt.lnum << ISPCCDC_FMTCFG_LNUM_SHIFT;
+		fmtcfg_val |= refmt.plen_even <<
+						ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT;
+		fmtcfg_val |= refmt.plen_odd << ISPCCDC_FMTCFG_PLEN_ODD_SHIFT;
+
+		isp_reg_writel(refmt.prgeven0, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_PRGEVEN0);
+		isp_reg_writel(refmt.prgeven1, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_PRGEVEN1);
+		isp_reg_writel(refmt.prgodd0, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_PRGODD0);
+		isp_reg_writel(refmt.prgodd1, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_PRGODD1);
+		isp_reg_writel(refmt.fmtaddr0, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR0);
+		isp_reg_writel(refmt.fmtaddr1, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR1);
+		isp_reg_writel(refmt.fmtaddr2, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR2);
+		isp_reg_writel(refmt.fmtaddr3, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR3);
+		isp_reg_writel(refmt.fmtaddr4, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR4);
+		isp_reg_writel(refmt.fmtaddr5, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR5);
+		isp_reg_writel(refmt.fmtaddr6, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR6);
+		isp_reg_writel(refmt.fmtaddr7, OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_FMT_ADDR7);
+	}
+	isp_reg_writel(fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
+}
+EXPORT_SYMBOL(ispccdc_config_reformatter);
+
+/**
+ * ispccdc_enable_reformatter - Enables the Reformatter.
+ * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter
+ **/
+void ispccdc_enable_reformatter(u8 enable)
+{
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
+					~ISPCCDC_FMTCFG_FMTEN,
+					enable ? ISPCCDC_FMTCFG_FMTEN : 0);
+	ispccdc_obj.refmt_en = enable;
+}
+EXPORT_SYMBOL(ispccdc_enable_reformatter);
+
+/**
+ * ispccdc_config_culling - Configures the culling parameters.
+ * @cull: Structure containing the vertical culling pattern, and horizontal
+ *        culling pattern for odd and even lines.
+ **/
+void ispccdc_config_culling(struct ispccdc_culling cull)
+{
+	u32 culling_val = 0;
+
+	culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
+	culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
+	culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;
+
+	isp_reg_writel(culling_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING);
+}
+EXPORT_SYMBOL(ispccdc_config_culling);
+
+/**
+ * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
+ * @enable: 0 Disables LPF, 1 Enables LPF
+ **/
+void ispccdc_enable_lpf(u8 enable)
+{
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
+					~ISPCCDC_SYN_MODE_LPF,
+					enable ? ISPCCDC_SYN_MODE_LPF : 0);
+}
+EXPORT_SYMBOL(ispccdc_enable_lpf);
+
+/**
+ * ispccdc_config_alaw - Configures the input width for A-law.
+ * @ipwidth: Input width for A-law
+ **/
+void ispccdc_config_alaw(enum alaw_ipwidth ipwidth)
+{
+	isp_reg_writel(ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
+					OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
+}
+EXPORT_SYMBOL(ispccdc_config_alaw);
+
+/**
+ * ispccdc_enable_alaw - Enables the A-law compression.
+ * @enable: 0 - Disables A-law, 1 - Enables A-law
+ **/
+void ispccdc_enable_alaw(u8 enable)
+{
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
+					~ISPCCDC_ALAW_CCDTBL,
+					enable ? ISPCCDC_ALAW_CCDTBL : 0);
+}
+EXPORT_SYMBOL(ispccdc_enable_alaw);
+
+/**
+ * ispccdc_config_imgattr - Configures the sensor image specific attributes.
+ * @colptn: Color pattern of the sensor.
+ **/
+void ispccdc_config_imgattr(u32 colptn)
+{
+	isp_reg_writel(colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
+}
+EXPORT_SYMBOL(ispccdc_config_imgattr);
+
+/**
+ * ispccdc_config_shadow_registers - Programs the shadow registers for CCDC.
+ * Currently nothing to program in shadow, but kept for future use.
+ **/
+void ispccdc_config_shadow_registers(void)
+{
+	return;
+}
+EXPORT_SYMBOL(ispccdc_config_shadow_registers);
+
+/**
+ * ispccdc_try_size - Checks if requested Input/output dimensions are valid
+ * @input_w: input width for the CCDC in number of pixels per line
+ * @input_h: input height for the CCDC in number of lines
+ * @output_w: output width from the CCDC in number of pixels per line
+ * @output_h: output height for the CCDC in number of lines
+ *
+ * Calculates the number of pixels cropped if the reformater is disabled,
+ * Fills up the output width and height variables in the isp_ccdc structure.
+ *
+ * Returns 0 if successful, or -EINVAL if the input width is less than 2 pixels
+ **/
+int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
+{
+	if (input_w < 32 || input_h < 32) {
+		DPRINTK_ISPCCDC("ISP_ERR: CCDC cannot handle input width less"
+				" than 32 pixels or height less than 32\n");
+		return -EINVAL;
+	}
+
+	if (ispccdc_obj.crop_w)
+		*output_w = ispccdc_obj.crop_w;
+	else
+		*output_w = input_w;
+
+	if (ispccdc_obj.crop_h)
+		*output_h = ispccdc_obj.crop_h;
+	else
+		*output_h = input_h;
+
+	if ((!ispccdc_obj.refmt_en) && ((ispccdc_obj.ccdc_outfmt !=
+		CCDC_OTHERS_MEM) && ispccdc_obj.ccdc_outfmt !=
+					CCDC_OTHERS_VP_MEM))
+		*output_h -= 1;
+
+	if ((ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) ||
+						(ispccdc_obj.ccdc_outfmt ==
+						CCDC_OTHERS_VP_MEM)) {
+		if (*output_w % 16) {
+			*output_w -= (*output_w % 16);
+			*output_w += 16;
+		}
+	}
+
+	ispccdc_obj.ccdcout_w = *output_w;
+	ispccdc_obj.ccdcout_h = *output_h;
+	ispccdc_obj.ccdcin_w = input_w;
+	ispccdc_obj.ccdcin_h = input_h;
+
+	DPRINTK_ISPCCDC("try size: ccdcin_w=%u,ccdcin_h=%u,ccdcout_w=%u,"
+							" ccdcout_h=%u\n",
+							ispccdc_obj.ccdcin_w,
+							ispccdc_obj.ccdcin_h,
+							ispccdc_obj.ccdcout_w,
+							ispccdc_obj.ccdcout_h);
+
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_try_size);
+
+/**
+ * ispccdc_config_size - Configure the dimensions of the CCDC input/output
+ * @input_w: input width for the CCDC in number of pixels per line
+ * @input_h: input height for the CCDC in number of lines
+ * @output_w: output width from the CCDC in number of pixels per line
+ * @output_h: output height for the CCDC in number of lines
+ *
+ * Configures the appropriate values stored in the isp_ccdc structure to
+ * HORZ/VERT_INFO registers and the VP_OUT depending on whether the image
+ * is stored in memory or given to the another module in the ISP pipeline.
+ *
+ * Returns 0 if successful, or -EINVAL if try_size was not called before to
+ * validate the requested dimensions.
+ **/
+int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
+{
+	DPRINTK_ISPCCDC("config size: input_w=%u, input_h=%u, output_w=%u,"
+							" output_h=%u\n",
+							input_w, input_h,
+							output_w, output_h);
+	if ((output_w != ispccdc_obj.ccdcout_w) || (output_h !=
+						ispccdc_obj.ccdcout_h)) {
+		DPRINTK_ISPCCDC("ISP_ERR : ispccdc_try_size should"
+					" be called before config size\n");
+		return -EINVAL;
+	}
+
+	if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP) {
+		isp_reg_writel((ispccdc_obj.ccdcin_woffset <<
+					ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
+					(ispccdc_obj.ccdcin_w <<
+					ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_FMT_HORZ);
+		isp_reg_writel((ispccdc_obj.ccdcin_hoffset <<
+					ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
+					(ispccdc_obj.ccdcin_h <<
+					ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_FMT_VERT);
+		isp_reg_writel((ispccdc_obj.ccdcout_w <<
+					ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
+					(ispccdc_obj.ccdcout_h - 1) <<
+					ISPCCDC_VP_OUT_VERT_NUM_SHIFT,
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VP_OUT);
+		isp_reg_writel((((ispccdc_obj.ccdcout_h - 25) &
+					ISPCCDC_VDINT_0_MASK) <<
+					ISPCCDC_VDINT_0_SHIFT) |
+					((50 & ISPCCDC_VDINT_1_MASK) <<
+					ISPCCDC_VDINT_1_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VDINT);
+
+	} else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) {
+		isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
+		if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
+			isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
+					| ((ispccdc_obj.ccdcout_w - 1)
+					<< ISPCCDC_HORZ_INFO_NPH_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_HORZ_INFO);
+		} else {
+			isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
+					| ((ispccdc_obj.ccdcout_w - 1)
+					<< ISPCCDC_HORZ_INFO_NPH_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_HORZ_INFO);
+		}
+		isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
+							OMAP3_ISP_IOMEM_CCDC,
+							ISPCCDC_VERT_START);
+		isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
+						ISPCCDC_VERT_LINES_NLV_SHIFT,
+						OMAP3_ISP_IOMEM_CCDC,
+						ISPCCDC_VERT_LINES);
+
+		ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
+		isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
+					ISPCCDC_VDINT_0_MASK) <<
+					ISPCCDC_VDINT_0_SHIFT) |
+					((100 & ISPCCDC_VDINT_1_MASK) <<
+					ISPCCDC_VDINT_1_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VDINT);
+	} else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
+		isp_reg_writel((0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
+					(ispccdc_obj.ccdcin_w <<
+					ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_FMT_HORZ);
+		isp_reg_writel((0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
+					((ispccdc_obj.ccdcin_h) <<
+					ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_FMT_VERT);
+		isp_reg_writel((ispccdc_obj.ccdcout_w
+					<< ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
+					((ispccdc_obj.ccdcout_h - 1) <<
+					ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VP_OUT);
+		isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
+					((ispccdc_obj.ccdcout_w - 1) <<
+					ISPCCDC_HORZ_INFO_NPH_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_HORZ_INFO);
+		isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VERT_START);
+		isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
+					ISPCCDC_VERT_LINES_NLV_SHIFT,
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VERT_LINES);
+		ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
+		isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
+					ISPCCDC_VDINT_0_MASK) <<
+					ISPCCDC_VDINT_0_SHIFT) |
+					((100 & ISPCCDC_VDINT_1_MASK) <<
+					ISPCCDC_VDINT_1_SHIFT),
+					OMAP3_ISP_IOMEM_CCDC,
+					ISPCCDC_VDINT);
+	}
+
+	if (is_isplsc_activated()) {
+		if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
+			ispccdc_config_lsc(&lsc_config);
+			ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_config_size);
+
+/**
+ * ispccdc_config_outlineoffset - Configures the output line offset
+ * @offset: Must be twice the Output width and aligned on 32 byte boundary
+ * @oddeven: Specifies the odd/even line pattern to be chosen to store the
+ *           output.
+ * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
+ *
+ * - Configures the output line offset when stored in memory
+ * - Sets the odd/even line pattern to store the output
+ *    (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
+ * - Configures the number of even and odd line fields in case of rearranging
+ * the lines.
+ *
+ * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
+ * boundary.
+ **/
+int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines)
+{
+	if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
+		isp_reg_writel((offset & 0xFFFF), OMAP3_ISP_IOMEM_CCDC,
+						ISPCCDC_HSIZE_OFF);
+	} else {
+		DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
+								" boundary");
+		return -EINVAL;
+	}
+
+	isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+						~ISPCCDC_SDOFST_FINV);
+
+	isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+						~ISPCCDC_SDOFST_FOFST_4L);
+
+	switch (oddeven) {
+	case EVENEVEN:
+		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
+		break;
+	case ODDEVEN:
+		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
+		break;
+	case EVENODD:
+		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
+		break;
+	case ODDODD:
+		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ispccdc_config_outlineoffset);
+
+/**
+ * ispccdc_set_outaddr - Sets the memory address where the output will be saved
+ * @addr: 32-bit memory address aligned on 32 byte boundary.
+ *
+ * Sets the memory address where the output will be saved.
+ *
+ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
+ * boundary.
+ **/
+int ispccdc_set_outaddr(u32 addr)
+{
+	if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
+		isp_reg_writel(addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
+		return 0;
+	} else {
+		DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
+								" boundary");
+		return -EINVAL;
+	}
+
+}
+EXPORT_SYMBOL(ispccdc_set_outaddr);
+
+/**
+ * ispccdc_enable - Enables the CCDC module.
+ * @enable: 0 Disables CCDC, 1 Enables CCDC
+ *
+ * Client should configure all the sub modules in CCDC before this.
+ **/
+void ispccdc_enable(u8 enable)
+{
+	if (ccdc_use_lsc && !ispccdc_obj.lsc_en &&
+				(ispccdc_obj.ccdc_inpfmt == CCDC_RAW) &&
+				enable)
+		ispccdc_enable_lsc(1);
+
+	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR, ~ISPCCDC_PCR_EN,
+						enable ? ISPCCDC_PCR_EN : 0);
+}
+EXPORT_SYMBOL(ispccdc_enable);
+
+/*
+ * Returns zero if the CCDC is idle and the image has been written to
+ * memory, too.
+ */
+int ispccdc_sbl_busy(void)
+{
+	return ispccdc_busy()
+		| (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
+				ISPSBL_CCDC_WR_0_DATA_READY)
+		| (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
+				ISPSBL_CCDC_WR_0_DATA_READY)
+		| (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
+				ISPSBL_CCDC_WR_0_DATA_READY)
+		| (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
+				ISPSBL_CCDC_WR_0_DATA_READY);
+}
+EXPORT_SYMBOL(ispccdc_sbl_busy);
+
+/**
+ * ispccdc_busy - Gets busy state of the CCDC.
+ **/
+int ispccdc_busy(void)
+{
+	return isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
+							ISPCCDC_PCR_BUSY;
+}
+EXPORT_SYMBOL(ispccdc_busy);
+
+/**
+ * ispccdc_save_context - Saves the values of the CCDC module registers
+ **/
+void ispccdc_save_context(void)
+{
+	DPRINTK_ISPCCDC("Saving context\n");
+	isp_save_context(ispccdc_reg_list);
+}
+EXPORT_SYMBOL(ispccdc_save_context);
+
+/**
+ * ispccdc_restore_context - Restores the values of the CCDC module registers
+ **/
+void ispccdc_restore_context(void)
+{
+	DPRINTK_ISPCCDC("Restoring context\n");
+	isp_restore_context(ispccdc_reg_list);
+}
+EXPORT_SYMBOL(ispccdc_restore_context);
+
+/**
+ * ispccdc_print_status - Prints the values of the CCDC Module registers
+ *
+ * Also prints other debug information stored in the CCDC module.
+ **/
+void ispccdc_print_status(void)
+{
+	if (!is_ispccdc_debug_enabled())
+		return;
+
+	DPRINTK_ISPCCDC("Module in use =%d\n", ispccdc_obj.ccdc_inuse);
+	DPRINTK_ISPCCDC("Accepted CCDC Input (width = %d,Height = %d)\n",
+							ispccdc_obj.ccdcin_w,
+							ispccdc_obj.ccdcin_h);
+	DPRINTK_ISPCCDC("Accepted CCDC Output (width = %d,Height = %d)\n",
+							ispccdc_obj.ccdcout_w,
+							ispccdc_obj.ccdcout_h);
+	DPRINTK_ISPCCDC("###CCDC PCR=0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR));
+	DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
+	switch (ispccdc_obj.ccdc_inpfmt) {
+	case CCDC_RAW:
+		DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
+		break;
+	case CCDC_YUV_SYNC:
+		DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
+		break;
+	case CCDC_YUV_BT:
+		DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
+		break;
+	}
+
+	switch (ispccdc_obj.ccdc_outfmt) {
+	case CCDC_OTHERS_VP:
+		DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
+		break;
+	case CCDC_OTHERS_MEM:
+		DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
+		break;
+	case CCDC_YUV_RSZ:
+		DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
+		break;
+	}
+
+	DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
+	DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
+	DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
+	DPRINTK_ISPCCDC("###CCDC SYN_MODE=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
+	DPRINTK_ISPCCDC("###CCDC HORZ_INFO=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
+	DPRINTK_ISPCCDC("###CCDC VERT_START=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START));
+	DPRINTK_ISPCCDC("###CCDC VERT_LINES=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES));
+	DPRINTK_ISPCCDC("###CCDC CULLING=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING));
+	DPRINTK_ISPCCDC("###CCDC HSIZE_OFF=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
+	DPRINTK_ISPCCDC("###CCDC SDOFST=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST));
+	DPRINTK_ISPCCDC("###CCDC SDR_ADDR=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
+	DPRINTK_ISPCCDC("###CCDC CLAMP=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP));
+	DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN));
+	DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
+	DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT));
+	DPRINTK_ISPCCDC("###CCDC_SDR_ADDR= 0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
+	DPRINTK_ISPCCDC("###CCDC FMTCFG=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
+	DPRINTK_ISPCCDC("###CCDC FMT_HORZ=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ));
+	DPRINTK_ISPCCDC("###CCDC FMT_VERT=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT));
+	DPRINTK_ISPCCDC("###CCDC LSC_CONFIG=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG));
+	DPRINTK_ISPCCDC("###CCDC LSC_INIT=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL));
+	DPRINTK_ISPCCDC("###CCDC LSC_TABLE BASE=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE));
+	DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_OFFSET));
+}
+EXPORT_SYMBOL(ispccdc_print_status);
+
+/**
+ * isp_ccdc_init - CCDC module initialization.
+ *
+ * Always returns 0
+ **/
+int __init isp_ccdc_init(void)
+{
+	ispccdc_obj.ccdc_inuse = 0;
+	ispccdc_config_crop(0, 0, 0, 0);
+	mutex_init(&ispccdc_obj.mutexlock);
+
+	if (is_isplsc_activated()) {
+		lsc_gain_table_tmp = kmalloc(LSC_TABLE_INIT_SIZE, GFP_KERNEL |
+								GFP_DMA);
+		memset(lsc_gain_table_tmp, 0x40, LSC_TABLE_INIT_SIZE);
+		lsc_config.initial_x = 0;
+		lsc_config.initial_y = 0;
+		lsc_config.gain_mode_n = 0x6;
+		lsc_config.gain_mode_m = 0x6;
+		lsc_config.gain_format = 0x4;
+		lsc_config.offset = 0x60;
+		lsc_config.size = LSC_TABLE_INIT_SIZE;
+		ccdc_use_lsc = 1;
+	}
+
+	return 0;
+}
+
+/**
+ * isp_ccdc_cleanup - CCDC module cleanup.
+ **/
+void isp_ccdc_cleanup(void)
+{
+	if (is_isplsc_activated()) {
+		ispccdc_free_lsc();
+		kfree(lsc_gain_table_tmp);
+	}
+
+	if (fpc_table_add_m != 0) {
+		ispmmu_kunmap(fpc_table_add_m);
+		kfree(fpc_table_add);
+	}
+}
diff --git a/drivers/media/video/isp/ispccdc.h b/drivers/media/video/isp/ispccdc.h
new file mode 100644
index 0000000..c1403cf
--- /dev/null
+++ b/drivers/media/video/isp/ispccdc.h
@@ -0,0 +1,203 @@
+/*
+ * ispccdc.h
+ *
+ * Driver header file for CCDC module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Senthilvadivu Guruswamy <svadivu@ti.com>
+ *	Pallavi Kulkarni <p-kulkarni@ti.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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_CCDC_H
+#define OMAP_ISP_CCDC_H
+
+#include <mach/isp_user.h>
+
+#define is_isplsc_activated()		1
+
+/* Enumeration constants for CCDC input output format */
+enum ccdc_input {
+	CCDC_RAW,
+	CCDC_YUV_SYNC,
+	CCDC_YUV_BT,
+	CCDC_OTHERS
+};
+
+enum ccdc_output {
+	CCDC_YUV_RSZ,
+	CCDC_YUV_MEM_RSZ,
+	CCDC_OTHERS_VP,
+	CCDC_OTHERS_MEM,
+	CCDC_OTHERS_VP_MEM
+};
+
+/* Enumeration constants for the sync interface parameters */
+enum inpmode {
+	RAW,
+	YUV16,
+	YUV8
+};
+enum datasize {
+	DAT8,
+	DAT10,
+	DAT11,
+	DAT12
+};
+
+
+/**
+ * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
+ * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
+ * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
+ * @ipmod: Input mode.
+ * @datsz: Data size.
+ * @fldmode: 0 - Progressive, 1 - Interlaced.
+ * @datapol: 0 - Positive, 1 - Negative.
+ * @fldpol: 0 - Positive, 1 - Negative.
+ * @hdpol: 0 - Positive, 1 - Negative.
+ * @vdpol: 0 - Positive, 1 - Negative.
+ * @fldout: 0 - Input, 1 - Output.
+ * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
+ * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
+ * @ppln: Number of pixels per line, used for HS/VS Output.
+ * @hlprf: Number of half lines per frame, used for HS/VS Output.
+ * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
+ */
+struct ispccdc_syncif {
+	u8 ccdc_mastermode;
+	u8 fldstat;
+	enum inpmode ipmod;
+	enum datasize datsz;
+	u8 fldmode;
+	u8 datapol;
+	u8 fldpol;
+	u8 hdpol;
+	u8 vdpol;
+	u8 fldout;
+	u8 hs_width;
+	u8 vs_width;
+	u8 ppln;
+	u8 hlprf;
+	u8 bt_r656_en;
+};
+
+/**
+ * ispccdc_refmt - Structure for Reformatter parameters
+ * @lnalt: Line alternating mode enable. 0 - Enable, 1 - Disable.
+ * @lnum: Number of output lines from 1 input line. 1 to 4 lines.
+ * @plen_even: Number of program entries in even line minus 1.
+ * @plen_odd: Number of program entries in odd line minus 1.
+ * @prgeven0: Program entries 0-7 for even lines register
+ * @prgeven1: Program entries 8-15 for even lines register
+ * @prgodd0: Program entries 0-7 for odd lines register
+ * @prgodd1: Program entries 8-15 for odd lines register
+ * @fmtaddr0: Output line in which the original pixel is to be placed
+ * @fmtaddr1: Output line in which the original pixel is to be placed
+ * @fmtaddr2: Output line in which the original pixel is to be placed
+ * @fmtaddr3: Output line in which the original pixel is to be placed
+ * @fmtaddr4: Output line in which the original pixel is to be placed
+ * @fmtaddr5: Output line in which the original pixel is to be placed
+ * @fmtaddr6: Output line in which the original pixel is to be placed
+ * @fmtaddr7: Output line in which the original pixel is to be placed
+ */
+struct ispccdc_refmt {
+	u8 lnalt;
+	u8 lnum;
+	u8 plen_even;
+	u8 plen_odd;
+	u32 prgeven0;
+	u32 prgeven1;
+	u32 prgodd0;
+	u32 prgodd1;
+	u32 fmtaddr0;
+	u32 fmtaddr1;
+	u32 fmtaddr2;
+	u32 fmtaddr3;
+	u32 fmtaddr4;
+	u32 fmtaddr5;
+	u32 fmtaddr6;
+	u32 fmtaddr7;
+};
+
+int ispccdc_request(void);
+
+int ispccdc_free(void);
+
+int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output);
+
+void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width);
+
+void ispccdc_config_sync_if(struct ispccdc_syncif syncif);
+
+int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp);
+
+void ispccdc_enable_black_clamp(u8 enable);
+
+int ispccdc_config_fpc(struct ispccdc_fpc fpc);
+
+void ispccdc_enable_fpc(u8 enable);
+
+void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp);
+
+void ispccdc_config_vp(struct ispccdc_vp vp);
+
+void ispccdc_enable_vp(u8 enable);
+
+void ispccdc_config_reformatter(struct ispccdc_refmt refmt);
+
+void ispccdc_enable_reformatter(u8 enable);
+
+void ispccdc_config_culling(struct ispccdc_culling culling);
+
+void ispccdc_enable_lpf(u8 enable);
+
+void ispccdc_config_alaw(enum alaw_ipwidth ipwidth);
+
+void ispccdc_enable_alaw(u8 enable);
+
+int ispccdc_load_lsc(u8 *table_addr, u32 table_size);
+
+void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg);
+
+void ispccdc_enable_lsc(u8 enable);
+
+void ispccdc_config_imgattr(u32 colptn);
+
+void ispccdc_config_shadow_registers(void);
+
+int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h);
+
+int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h);
+
+int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines);
+
+int ispccdc_set_outaddr(u32 addr);
+
+void ispccdc_enable(u8 enable);
+
+int ispccdc_sbl_busy(void);
+
+int ispccdc_busy(void);
+
+void ispccdc_save_context(void);
+
+void ispccdc_restore_context(void);
+
+void ispccdc_print_status(void);
+
+int omap34xx_isp_ccdc_config(void *userspace_add);
+
+void ispccdc_set_wenlog(u32 wenlog);
+
+#endif		/* OMAP_ISP_CCDC_H */
-- 
1.5.6.5


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

* [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ)
  2009-03-03 10:06       ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Sakari Ailus
@ 2009-03-03 10:06         ` Sakari Ailus
  2009-03-03 10:06           ` [PATCH 6/9] omap3isp: Add statistics collection modules (H3A and HIST) Sakari Ailus
  2009-03-03 12:23           ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Alexey Klimov
  2009-03-03 12:07         ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Alexey Klimov
  1 sibling, 2 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/isp/isppreview.c | 1896 ++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/isppreview.h |  350 +++++++
 drivers/media/video/isp/ispresizer.c |  897 ++++++++++++++++
 drivers/media/video/isp/ispresizer.h |  154 +++
 4 files changed, 3297 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/isppreview.c
 create mode 100644 drivers/media/video/isp/isppreview.h
 create mode 100644 drivers/media/video/isp/ispresizer.c
 create mode 100644 drivers/media/video/isp/ispresizer.h

diff --git a/drivers/media/video/isp/isppreview.c b/drivers/media/video/isp/isppreview.c
new file mode 100644
index 0000000..242b578
--- /dev/null
+++ b/drivers/media/video/isp/isppreview.c
@@ -0,0 +1,1896 @@
+/*
+ * isppreview.c
+ *
+ * Driver Library for Preview module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Senthilvadivu Guruswamy <svadivu@ti.com>
+ *	Pallavi Kulkarni <p-kulkarni@ti.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "isppreview.h"
+
+static struct ispprev_nf prev_nf_t;
+static struct prev_params *params;
+static int rg_update, gg_update, bg_update, nf_enable, nf_update;
+
+/* Structure for saving/restoring preview module registers */
+static struct isp_reg ispprev_reg_list[] = {
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_DRKF_OFFSET, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_NF, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3, 0x0000},
+	{OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 0x0000},
+	{0, ISP_TOK_TERM, 0x0000}
+};
+
+
+/* Default values in Office Flourescent Light for RGBtoRGB Blending */
+static struct ispprev_rgbtorgb flr_rgb2rgb = {
+	{	/* RGB-RGB Matrix */
+		{0x01E2, 0x0F30, 0x0FEE},
+		{0x0F9B, 0x01AC, 0x0FB9},
+		{0x0FE0, 0x0EC0, 0x0260}
+	},	/* RGB Offset */
+	{0x0000, 0x0000, 0x0000}
+};
+
+/* Default values in Office Flourescent Light for RGB to YUV Conversion*/
+static struct ispprev_csc flr_prev_csc[] = {
+	{
+		{	/* CSC Coef Matrix */
+			{66, 129, 25},
+			{-38, -75, 112},
+			{112, -94 , -18}
+		},	/* CSC Offset */
+		{0x0, 0x0, 0x0}
+	},
+	{
+		{	/* CSC Coef Matrix BW */
+			{66, 129, 25},
+			{0, 0, 0},
+			{0, 0, 0}
+		},	/* CSC Offset */
+		{0x0, 0x0, 0x0}
+	},
+	{
+		{	/* CSC Coef Matrix Sepia */
+			{19, 38, 7},
+			{0, 0, 0},
+			{0, 0, 0}
+		},	/* CSC Offset */
+		{0x0, 0xE7, 0x14}
+	}
+};
+
+
+/* Default values in Office Flourescent Light for CFA Gradient*/
+#define FLR_CFA_GRADTHRS_HORZ	0x28
+#define FLR_CFA_GRADTHRS_VERT	0x28
+
+/* Default values in Office Flourescent Light for Chroma Suppression*/
+#define FLR_CSUP_GAIN		0x0D
+#define FLR_CSUP_THRES		0xEB
+
+/* Default values in Office Flourescent Light for Noise Filter*/
+#define FLR_NF_STRGTH		0x03
+
+/* Default values in Office Flourescent Light for White Balance*/
+#define FLR_WBAL_DGAIN		0x100
+#define FLR_WBAL_COEF0		0x20
+#define FLR_WBAL_COEF1		0x29
+#define FLR_WBAL_COEF2		0x2d
+#define FLR_WBAL_COEF3		0x20
+
+#define FLR_WBAL_COEF0_ES1	0x20
+#define FLR_WBAL_COEF1_ES1	0x23
+#define FLR_WBAL_COEF2_ES1	0x39
+#define FLR_WBAL_COEF3_ES1	0x20
+
+/* Default values in Office Flourescent Light for Black Adjustment*/
+#define FLR_BLKADJ_BLUE		0x0
+#define FLR_BLKADJ_GREEN	0x0
+#define FLR_BLKADJ_RED		0x0
+
+static int update_color_matrix;
+
+/**
+ * struct isp_prev - Structure for storing ISP Preview module information
+ * @prev_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
+ * @prevout_w: Preview output width.
+ * @prevout_h: Preview output height.
+ * @previn_w: Preview input width.
+ * @previn_h: Preview input height.
+ * @prev_inpfmt: Preview input format.
+ * @prev_outfmt: Preview output format.
+ * @hmed_en: Horizontal median filter enable.
+ * @nf_en: Noise filter enable.
+ * @dcor_en: Defect correction enable.
+ * @cfa_en: Color Filter Array (CFA) interpolation enable.
+ * @csup_en: Chrominance suppression enable.
+ * @yenh_en: Luma enhancement enable.
+ * @fmtavg: Number of horizontal pixels to average in input formatter. The
+ *          input width should be a multiple of this number.
+ * @brightness: Brightness in preview module.
+ * @contrast: Contrast in preview module.
+ * @color: Color effect in preview module.
+ * @cfafmt: Color Filter Array (CFA) Format.
+ * @ispprev_mutex: Mutex for isp preview.
+ *
+ * This structure is used to store the OMAP ISP Preview module Information.
+ */
+static struct isp_prev {
+	u8 prev_inuse;
+	u32 prevout_w;
+	u32 prevout_h;
+	u32 previn_w;
+	u32 previn_h;
+	enum preview_input prev_inpfmt;
+	enum preview_output prev_outfmt;
+	u8 hmed_en;
+	u8 nf_en;
+	u8 dcor_en;
+	u8 cfa_en;
+	u8 csup_en;
+	u8 yenh_en;
+	u8 fmtavg;
+	u8 brightness;
+	u8 contrast;
+	enum v4l2_colorfx color;
+	enum cfa_fmt cfafmt;
+	struct mutex ispprev_mutex; /* For checking/modifying prev_inuse */
+	u32 sph;
+	u32 slv;
+} ispprev_obj;
+
+/* Saved parameters */
+static struct prev_params *prev_config_params;
+
+/*
+ * Coeficient Tables for the submodules in Preview.
+ * Array is initialised with the values from.the tables text file.
+ */
+
+/*
+ * CFA Filter Coefficient Table
+ *
+ */
+static u32 cfa_coef_table[] = {
+#include "cfa_coef_table.h"
+};
+
+/*
+ * Gamma Correction Table - Red
+ */
+static u32 redgamma_table[] = {
+#include "redgamma_table.h"
+};
+
+/*
+ * Gamma Correction Table - Green
+ */
+static u32 greengamma_table[] = {
+#include "greengamma_table.h"
+};
+
+/*
+ * Gamma Correction Table - Blue
+ */
+static u32 bluegamma_table[] = {
+#include "bluegamma_table.h"
+};
+
+/*
+ * Noise Filter Threshold table
+ */
+static u32 noise_filter_table[] = {
+#include "noise_filter_table.h"
+};
+
+/*
+ * Luminance Enhancement Table
+ */
+static u32 luma_enhance_table[] = {
+#include "luma_enhance_table.h"
+};
+
+/**
+ * omap34xx_isp_preview_config - Abstraction layer Preview configuration.
+ * @userspace_add: Pointer from Userspace to structure with flags and data to
+ *                 update.
+ **/
+int omap34xx_isp_preview_config(void *userspace_add)
+{
+	struct ispprev_hmed prev_hmed_t;
+	struct ispprev_cfa prev_cfa_t;
+	struct ispprev_csup csup_t;
+	struct ispprev_wbal prev_wbal_t;
+	struct ispprev_blkadj prev_blkadj_t;
+	struct ispprev_rgbtorgb rgb2rgb_t;
+	struct ispprev_csc prev_csc_t;
+	struct ispprev_yclimit yclimit_t;
+	struct ispprev_dcor prev_dcor_t;
+	struct ispprv_update_config *preview_struct;
+	struct isptables_update isp_table_update;
+	int yen_t[ISPPRV_YENH_TBL_SIZE];
+
+	if (userspace_add == NULL)
+		return -EINVAL;
+
+	preview_struct = userspace_add;
+
+	if (ISP_ABS_PREV_LUMAENH & preview_struct->flag) {
+		if (ISP_ABS_PREV_LUMAENH & preview_struct->update) {
+			if (copy_from_user(yen_t, preview_struct->yen,
+								sizeof(yen_t)))
+				goto err_copy_from_user;
+			isppreview_config_luma_enhancement(yen_t);
+		}
+		params->features |= PREV_LUMA_ENHANCE;
+	} else if (ISP_ABS_PREV_LUMAENH & preview_struct->update)
+			params->features &= ~PREV_LUMA_ENHANCE;
+
+	if (ISP_ABS_PREV_INVALAW & preview_struct->flag) {
+		isppreview_enable_invalaw(1);
+		params->features |= PREV_INVERSE_ALAW;
+	} else {
+		isppreview_enable_invalaw(0);
+		params->features &= ~PREV_INVERSE_ALAW;
+	}
+
+	if (ISP_ABS_PREV_HRZ_MED & preview_struct->flag) {
+		if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
+			if (copy_from_user(&prev_hmed_t,
+						(struct ispprev_hmed *)
+						preview_struct->prev_hmed,
+						sizeof(struct ispprev_hmed)))
+				goto err_copy_from_user;
+			isppreview_config_hmed(prev_hmed_t);
+		}
+		isppreview_enable_hmed(1);
+		params->features |= PREV_HORZ_MEDIAN_FILTER;
+	} else if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
+		isppreview_enable_hmed(0);
+		params->features &= ~PREV_HORZ_MEDIAN_FILTER;
+	}
+
+	if (ISP_ABS_PREV_CFA & preview_struct->flag) {
+		if (ISP_ABS_PREV_CFA & preview_struct->update) {
+			if (copy_from_user(&prev_cfa_t,
+						(struct ispprev_cfa *)
+						preview_struct->prev_cfa,
+						sizeof(struct ispprev_cfa)))
+				goto err_copy_from_user;
+
+			isppreview_config_cfa(prev_cfa_t);
+		}
+		isppreview_enable_cfa(1);
+		params->features |= PREV_CFA;
+	} else if (ISP_ABS_PREV_CFA & preview_struct->update) {
+		isppreview_enable_cfa(0);
+		params->features &= ~PREV_CFA;
+	}
+
+	if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->flag) {
+		if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
+			if (copy_from_user(&csup_t,
+						(struct ispprev_csup *)
+						preview_struct->csup,
+						sizeof(struct ispprev_csup)))
+				goto err_copy_from_user;
+			isppreview_config_chroma_suppression(csup_t);
+		}
+		isppreview_enable_chroma_suppression(1);
+		params->features |= PREV_CHROMA_SUPPRESS;
+	} else if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
+		isppreview_enable_chroma_suppression(0);
+		params->features &= ~PREV_CHROMA_SUPPRESS;
+	}
+
+	if (ISP_ABS_PREV_WB & preview_struct->update) {
+		if (copy_from_user(&prev_wbal_t, (struct ispprev_wbal *)
+						preview_struct->prev_wbal,
+						sizeof(struct ispprev_wbal)))
+			goto err_copy_from_user;
+		isppreview_config_whitebalance(prev_wbal_t);
+	}
+
+	if (ISP_ABS_PREV_BLKADJ & preview_struct->update) {
+		if (copy_from_user(&prev_blkadj_t, (struct ispprev_blkadjl *)
+					preview_struct->prev_blkadj,
+					sizeof(struct ispprev_blkadj)))
+			goto err_copy_from_user;
+		isppreview_config_blkadj(prev_blkadj_t);
+	}
+
+	if (ISP_ABS_PREV_RGB2RGB & preview_struct->update) {
+		if (copy_from_user(&rgb2rgb_t, (struct ispprev_rgbtorgb *)
+					preview_struct->rgb2rgb,
+					sizeof(struct ispprev_rgbtorgb)))
+			goto err_copy_from_user;
+		isppreview_config_rgb_blending(rgb2rgb_t);
+	}
+
+	if (ISP_ABS_PREV_COLOR_CONV & preview_struct->update) {
+		if (copy_from_user(&prev_csc_t, (struct ispprev_csc *)
+						preview_struct->prev_csc,
+						sizeof(struct ispprev_csc)))
+			goto err_copy_from_user;
+		isppreview_config_rgb_to_ycbcr(prev_csc_t);
+	}
+
+	if (ISP_ABS_PREV_YC_LIMIT & preview_struct->update) {
+		if (copy_from_user(&yclimit_t, (struct ispprev_yclimit *)
+					preview_struct->yclimit,
+					sizeof(struct ispprev_yclimit)))
+			goto err_copy_from_user;
+		isppreview_config_yc_range(yclimit_t);
+	}
+
+	if (ISP_ABS_PREV_DEFECT_COR & preview_struct->flag) {
+		if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
+			if (copy_from_user(&prev_dcor_t,
+						(struct ispprev_dcor *)
+						preview_struct->prev_dcor,
+						sizeof(struct ispprev_dcor)))
+				goto err_copy_from_user;
+			isppreview_config_dcor(prev_dcor_t);
+		}
+		isppreview_enable_dcor(1);
+		params->features |= PREV_DEFECT_COR;
+	} else if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
+		isppreview_enable_dcor(0);
+		params->features &= ~PREV_DEFECT_COR;
+	}
+
+	if (ISP_ABS_PREV_GAMMABYPASS & preview_struct->flag) {
+		isppreview_enable_gammabypass(1);
+		params->features |= PREV_GAMMA_BYPASS;
+	} else {
+		isppreview_enable_gammabypass(0);
+		params->features &= ~PREV_GAMMA_BYPASS;
+	}
+
+	isp_table_update.update = preview_struct->update;
+	isp_table_update.flag = preview_struct->flag;
+	isp_table_update.prev_nf = preview_struct->prev_nf;
+	isp_table_update.red_gamma = preview_struct->red_gamma;
+	isp_table_update.green_gamma = preview_struct->green_gamma;
+	isp_table_update.blue_gamma = preview_struct->blue_gamma;
+
+	if (omap34xx_isp_tables_update(&isp_table_update))
+		goto err_copy_from_user;
+
+	return 0;
+
+err_copy_from_user:
+	printk(KERN_ERR "Preview Config: Copy From User Error");
+	return -EFAULT;
+}
+EXPORT_SYMBOL_GPL(omap34xx_isp_preview_config);
+
+/**
+ * omap34xx_isp_tables_update - Abstraction layer Tables update.
+ * @isptables_struct: Pointer from Userspace to structure with flags and table
+ *                 data to update.
+ **/
+int omap34xx_isp_tables_update(struct isptables_update *isptables_struct)
+{
+
+	if (ISP_ABS_TBL_NF & isptables_struct->flag) {
+		nf_enable = 1;
+		params->features |= PREV_NOISE_FILTER;
+		if (ISP_ABS_TBL_NF & isptables_struct->update) {
+			if (copy_from_user(&prev_nf_t, (struct ispprev_nf *)
+						isptables_struct->prev_nf,
+						sizeof(struct ispprev_nf)))
+				goto err_copy_from_user;
+
+			nf_update = 1;
+		} else
+			nf_update = 0;
+	} else {
+		nf_enable = 0;
+		params->features &= ~PREV_NOISE_FILTER;
+		if (ISP_ABS_TBL_NF & isptables_struct->update)
+			nf_update = 1;
+		else
+			nf_update = 0;
+	}
+
+	if (ISP_ABS_TBL_REDGAMMA & isptables_struct->update) {
+		if (copy_from_user(redgamma_table, isptables_struct->red_gamma,
+						sizeof(redgamma_table))) {
+			goto err_copy_from_user;
+		}
+		rg_update = 1;
+	} else
+		rg_update = 0;
+
+	if (ISP_ABS_TBL_GREENGAMMA & isptables_struct->update) {
+		if (copy_from_user(greengamma_table,
+						isptables_struct->green_gamma,
+						sizeof(greengamma_table)))
+			goto err_copy_from_user;
+		gg_update = 1;
+	} else
+		gg_update = 0;
+
+	if (ISP_ABS_TBL_BLUEGAMMA & isptables_struct->update) {
+		if (copy_from_user(bluegamma_table,
+					isptables_struct->blue_gamma,
+					sizeof(bluegamma_table))) {
+			goto err_copy_from_user;
+		}
+		bg_update = 1;
+	} else
+		bg_update = 0;
+
+	return 0;
+
+err_copy_from_user:
+	printk(KERN_ERR "Preview Tables:Copy From User Error");
+	return -EFAULT;
+}
+
+/**
+ * isppreview_config_shadow_registers - Program shadow registers for preview.
+ *
+ * Allows user to program shadow registers associated with preview module.
+ **/
+void isppreview_config_shadow_registers()
+{
+	u8 current_brightness_contrast;
+	int ctr, prv_disabled;
+
+	isppreview_query_brightness(&current_brightness_contrast);
+	if (current_brightness_contrast !=
+			(ispprev_obj.brightness * ISPPRV_BRIGHT_UNITS)) {
+		DPRINTK_ISPPREV(" Changing Brightness level to %d\n",
+						ispprev_obj.brightness);
+		isppreview_config_brightness(ispprev_obj.brightness *
+							ISPPRV_BRIGHT_UNITS);
+	}
+
+	isppreview_query_contrast(&current_brightness_contrast);
+	if (current_brightness_contrast !=
+			(ispprev_obj.contrast * ISPPRV_CONTRAST_UNITS)) {
+		DPRINTK_ISPPREV(" Changing Contrast level to %d\n",
+							ispprev_obj.contrast);
+		isppreview_config_contrast(ispprev_obj.contrast *
+							ISPPRV_CONTRAST_UNITS);
+	}
+	if (update_color_matrix) {
+		isppreview_config_rgb_to_ycbcr(flr_prev_csc[ispprev_obj.color]);
+		update_color_matrix = 0;
+	}
+	if (gg_update || rg_update || bg_update || nf_update) {
+		isppreview_enable(0);
+		prv_disabled = 1;
+	}
+
+	if (gg_update) {
+		isp_reg_writel(ISPPRV_TBL_ADDR_GREEN_G_START,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+
+		for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
+			isp_reg_writel(greengamma_table[ctr],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+		}
+		gg_update = 0;
+	}
+
+	if (rg_update) {
+		isp_reg_writel(ISPPRV_TBL_ADDR_RED_G_START,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+
+		for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
+			isp_reg_writel(redgamma_table[ctr],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+		}
+		rg_update = 0;
+	}
+
+	if (bg_update) {
+		isp_reg_writel(ISPPRV_TBL_ADDR_BLUE_G_START,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+
+		for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
+			isp_reg_writel(bluegamma_table[ctr],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+		}
+		bg_update = 0;
+	}
+
+	if (nf_update && nf_enable) {
+		isp_reg_writel(0xC00,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+		isp_reg_writel(prev_nf_t.spread,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
+		for (ctr = 0; ctr < ISPPRV_NF_TBL_SIZE; ctr++) {
+			isp_reg_writel(prev_nf_t.table[ctr],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+		}
+		isppreview_enable_noisefilter(1);
+		nf_update = 0;
+	}
+
+	if (~nf_update && nf_enable)
+		isppreview_enable_noisefilter(1);
+
+	if (nf_update && ~nf_enable)
+		isppreview_enable_noisefilter(0);
+
+	if (prv_disabled) {
+		isppreview_enable(1);
+		prv_disabled = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_config_shadow_registers);
+
+/**
+ * isppreview_request - Reserves the preview module.
+ *
+ * Returns 0 if successful, or -EBUSY if the module was already reserved.
+ **/
+int isppreview_request()
+{
+	mutex_lock(&ispprev_obj.ispprev_mutex);
+	if (ispprev_obj.prev_inuse) {
+		mutex_unlock(&ispprev_obj.ispprev_mutex);
+		printk(KERN_ERR "ISP_ERR : Preview Module Busy\n");
+		return -EBUSY;
+	}
+	ispprev_obj.prev_inuse = 1;
+	mutex_unlock(&ispprev_obj.ispprev_mutex);
+	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_PREV_RAM_EN |
+						ISPCTRL_PREV_CLK_EN |
+						ISPCTRL_SBL_WR1_RAM_EN);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_request);
+
+/**
+ * isppreview_free - Frees the preview module.
+ *
+ * Returns 0 if successful, or -EINVAL if the module was already freed.
+ **/
+int isppreview_free()
+{
+	mutex_lock(&ispprev_obj.ispprev_mutex);
+	if (ispprev_obj.prev_inuse) {
+		ispprev_obj.prev_inuse = 0;
+		mutex_unlock(&ispprev_obj.ispprev_mutex);
+		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+						~(ISPCTRL_PREV_CLK_EN |
+						ISPCTRL_PREV_RAM_EN |
+						ISPCTRL_SBL_WR1_RAM_EN));
+		return 0;
+	} else {
+		mutex_unlock(&ispprev_obj.ispprev_mutex);
+		DPRINTK_ISPPREV("ISP_ERR : Preview Module already freed\n");
+		return -EINVAL;
+	}
+
+}
+EXPORT_SYMBOL_GPL(isppreview_free);
+
+/** isppreview_config_datapath - Specifies input and output modules for Preview
+ * @input: Indicates the module that gives the image to preview.
+ * @output: Indicates the module to which the preview outputs to.
+ *
+ * Configures the default configuration for the CCDC to work with.
+ *
+ * The valid values for the input are PRV_RAW_CCDC (0), PRV_RAW_MEM (1),
+ * PRV_RGBBAYERCFA (2), PRV_COMPCFA (3), PRV_CCDC_DRKF (4), PRV_OTHERS (5).
+ *
+ * The valid values for the output are PREVIEW_RSZ (0), PREVIEW_MEM (1).
+ *
+ * Returns 0 if successful, or -EINVAL if wrong input or output values are
+ * specified.
+ **/
+int isppreview_config_datapath(enum preview_input input,
+						enum preview_output output)
+{
+	u32 pcr = 0;
+	u8 enable = 0;
+	struct prev_params *params = prev_config_params;
+	struct ispprev_yclimit yclimit;
+
+	pcr = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+
+	switch (input) {
+	case PRV_RAW_CCDC:
+		pcr &= ~ISPPRV_PCR_SOURCE;
+		pcr &= ~ISPPRV_PCR_ONESHOT;
+		ispprev_obj.prev_inpfmt = PRV_RAW_CCDC;
+		break;
+	case PRV_RAW_MEM:
+		pcr |= ISPPRV_PCR_SOURCE;
+		pcr |= ISPPRV_PCR_ONESHOT;
+		ispprev_obj.prev_inpfmt = PRV_RAW_MEM;
+		break;
+	case PRV_CCDC_DRKF:
+		pcr |= ISPPRV_PCR_DRKFCAP;
+		pcr |= ISPPRV_PCR_ONESHOT;
+		ispprev_obj.prev_inpfmt = PRV_CCDC_DRKF;
+		break;
+	case PRV_COMPCFA:
+		ispprev_obj.prev_inpfmt = PRV_COMPCFA;
+		break;
+	case PRV_OTHERS:
+		ispprev_obj.prev_inpfmt = PRV_OTHERS;
+		break;
+	case PRV_RGBBAYERCFA:
+		ispprev_obj.prev_inpfmt = PRV_RGBBAYERCFA;
+		break;
+	default:
+		printk(KERN_ERR "ISP_ERR : Wrong Input\n");
+		return -EINVAL;
+	};
+
+	switch (output) {
+	case PREVIEW_RSZ:
+		pcr |= ISPPRV_PCR_RSZPORT;
+		pcr &= ~ISPPRV_PCR_SDRPORT;
+		break;
+	case PREVIEW_MEM:
+		pcr &= ~ISPPRV_PCR_RSZPORT;
+		pcr |= ISPPRV_PCR_SDRPORT;
+		break;
+	default:
+		printk(KERN_ERR "ISP_ERR : Wrong Output\n");
+		return -EINVAL;
+	}
+	ispprev_obj.prev_outfmt = output;
+
+	isp_reg_writel(pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+
+	isppreview_config_ycpos(params->pix_fmt);
+
+	if (params->cfa.cfa_table != NULL)
+		isppreview_config_cfa(params->cfa);
+	if (params->csup.hypf_en == 1)
+		isppreview_config_chroma_suppression(params->csup);
+	if (params->ytable != NULL)
+		isppreview_config_luma_enhancement(params->ytable);
+
+	if (params->gtable.redtable != NULL)
+		isppreview_config_gammacorrn(params->gtable);
+
+	enable = (params->features & PREV_CFA) ? 1 : 0;
+	isppreview_enable_cfa(enable);
+
+	enable = (params->features & PREV_CHROMA_SUPPRESS) ? 1 : 0;
+	isppreview_enable_chroma_suppression(enable);
+
+	enable = (params->features & PREV_LUMA_ENHANCE) ? 1 : 0;
+	isppreview_enable_luma_enhancement(enable);
+
+	enable = (params->features & PREV_NOISE_FILTER) ? 1 : 0;
+	if (enable)
+		isppreview_config_noisefilter(params->nf);
+	isppreview_enable_noisefilter(enable);
+
+	enable = (params->features & PREV_DEFECT_COR) ? 1 : 0;
+	if (enable)
+		isppreview_config_dcor(params->dcor);
+	isppreview_enable_dcor(enable);
+
+	enable = (params->features & PREV_GAMMA_BYPASS) ? 1 : 0;
+	isppreview_enable_gammabypass(enable);
+
+	isppreview_config_whitebalance(params->wbal);
+	isppreview_config_blkadj(params->blk_adj);
+	isppreview_config_rgb_blending(params->rgb2rgb);
+	isppreview_config_rgb_to_ycbcr(params->rgb2ycbcr);
+
+	isppreview_config_contrast(params->contrast * ISPPRV_CONTRAST_UNITS);
+	isppreview_config_brightness(params->brightness * ISPPRV_BRIGHT_UNITS);
+
+	yclimit.minC = ISPPRV_YC_MIN;
+	yclimit.maxC = ISPPRV_YC_MAX;
+	yclimit.minY = ISPPRV_YC_MIN;
+	yclimit.maxY = ISPPRV_YC_MAX;
+	isppreview_config_yc_range(yclimit);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_config_datapath);
+
+/**
+ * isppreview_set_skip - Set the number of rows/columns that should be skipped.
+ *  h - Start Pixel Horizontal.
+ *  v - Start Line Vertical.
+ **/
+void isppreview_set_skip(u32 h, u32 v)
+{
+	ispprev_obj.sph = h;
+	ispprev_obj.slv = v;
+}
+EXPORT_SYMBOL_GPL(isppreview_set_skip);
+
+/**
+ * isppreview_config_ycpos - Configure byte layout of YUV image.
+ * @mode: Indicates the required byte layout.
+ **/
+void isppreview_config_ycpos(enum preview_ycpos_mode mode)
+{
+	u32 pcr = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+	pcr &= ~ISPPRV_PCR_YCPOS_CrYCbY;
+	pcr |= (mode << ISPPRV_PCR_YCPOS_SHIFT);
+	isp_reg_writel(pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_ycpos);
+
+/**
+ * isppreview_config_averager - Enable / disable / configure averager
+ * @average: Average value to be configured.
+ **/
+void isppreview_config_averager(u8 average)
+{
+	int reg = 0;
+
+	reg = AVE_ODD_PIXEL_DIST | AVE_EVEN_PIXEL_DIST | average;
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_averager);
+
+/**
+ * isppreview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
+ * @enable: 1 - Reverse the A-Law done in CCDC.
+ **/
+void isppreview_enable_invalaw(u8 enable)
+{
+	u32 pcr_val = 0;
+	pcr_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+
+	if (enable) {
+		isp_reg_writel(pcr_val | ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+	} else {
+		isp_reg_writel(pcr_val &
+				~(ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW),
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_invalaw);
+
+/**
+ * isppreview_enable_drkframe - Enable/Disable of the darkframe subtract.
+ * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
+ *          subtracted with the pixels in the current frame.
+ *
+ * The proccess is applied for each captured frame.
+ **/
+void isppreview_enable_drkframe(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DRKFEN);
+	else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_DRKFEN);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_drkframe);
+
+/**
+ * isppreview_enable_shadcomp - Enables/Disables the shading compensation.
+ * @enable: 1 - Enables the shading compensation.
+ *
+ * If dark frame subtract won't be used, then enable this shading
+ * compensation.
+ **/
+void isppreview_enable_shadcomp(u8 enable)
+{
+
+	if (enable) {
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							ISPPRV_PCR_SCOMP_EN);
+		isppreview_enable_drkframe(1);
+	} else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_SCOMP_EN);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_shadcomp);
+
+/**
+ * isppreview_config_drkf_shadcomp - Configures shift value in shading comp.
+ * @scomp_shtval: 3bit value of shift used in shading compensation.
+ **/
+void isppreview_config_drkf_shadcomp(u8 scomp_shtval)
+{
+	u32 pcr_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+
+	pcr_val &= ISPPRV_PCR_SCOMP_SFT_MASK;
+	isp_reg_writel(pcr_val | (scomp_shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT),
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_drkf_shadcomp);
+
+/**
+ * isppreview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
+ * @enable: 1 - Enables Horizontal Median Filter.
+ **/
+void isppreview_enable_hmed(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_HMEDEN);
+	else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_HMEDEN);
+	}
+	ispprev_obj.hmed_en = enable ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_hmed);
+
+/**
+ * isppreview_config_hmed - Configures the Horizontal Median Filter.
+ * @prev_hmed: Structure containing the odd and even distance between the
+ *             pixels in the image along with the filter threshold.
+ **/
+void isppreview_config_hmed(struct ispprev_hmed prev_hmed)
+{
+
+	u32 odddist = 0;
+	u32 evendist = 0;
+
+	if (prev_hmed.odddist == 1)
+		odddist = ~ISPPRV_HMED_ODDDIST;
+	else
+		odddist = ISPPRV_HMED_ODDDIST;
+
+	if (prev_hmed.evendist == 1)
+		evendist = ~ISPPRV_HMED_EVENDIST;
+	else
+		evendist = ISPPRV_HMED_EVENDIST;
+
+	isp_reg_writel(odddist | evendist | (prev_hmed.thres <<
+					ISPPRV_HMED_THRESHOLD_SHIFT),
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
+
+}
+EXPORT_SYMBOL_GPL(isppreview_config_hmed);
+
+/**
+ * isppreview_config_noisefilter - Configures the Noise Filter.
+ * @prev_nf: Structure containing the noisefilter table, strength to be used
+ *           for the noise filter and the defect correction enable flag.
+ **/
+void isppreview_config_noisefilter(struct ispprev_nf prev_nf)
+{
+	int i = 0;
+
+	isp_reg_writel(prev_nf.spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
+	isp_reg_writel(ISPPRV_NF_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV,
+							ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < ISPPRV_NF_TBL_SIZE; i++) {
+		isp_reg_writel(prev_nf.table[i], OMAP3_ISP_IOMEM_PREV,
+							ISPPRV_SET_TBL_DATA);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_config_noisefilter);
+
+/**
+ * isppreview_config_dcor - Configures the defect correction
+ * @prev_nf: Structure containing the defect correction structure
+ **/
+void isppreview_config_dcor(struct ispprev_dcor prev_dcor)
+{
+	if (prev_dcor.couplet_mode_en) {
+		isp_reg_writel(prev_dcor.detect_correct[0],
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
+		isp_reg_writel(prev_dcor.detect_correct[1],
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
+		isp_reg_writel(prev_dcor.detect_correct[2],
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
+		isp_reg_writel(prev_dcor.detect_correct[3],
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DCCOUP);
+	} else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_DCCOUP);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_config_dcor);
+
+/**
+ * isppreview_config_cfa - Configures the CFA Interpolation parameters.
+ * @prev_cfa: Structure containing the CFA interpolation table, CFA format
+ *            in the image, vertical and horizontal gradient threshold.
+ **/
+void isppreview_config_cfa(struct ispprev_cfa prev_cfa)
+{
+	int i = 0;
+
+	ispprev_obj.cfafmt = prev_cfa.cfafmt;
+
+	isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+				(prev_cfa.cfafmt << ISPPRV_PCR_CFAFMT_SHIFT));
+
+	isp_reg_writel(
+		(prev_cfa.cfa_gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
+		(prev_cfa.cfa_gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
+		OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
+
+	isp_reg_writel(ISPPRV_CFA_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV,
+							ISPPRV_SET_TBL_ADDR);
+
+	for (i = 0; i < ISPPRV_CFA_TBL_SIZE; i++) {
+		isp_reg_writel(prev_cfa.cfa_table[i],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_config_cfa);
+
+/**
+ * isppreview_config_gammacorrn - Configures the Gamma Correction table values
+ * @gtable: Structure containing the table for red, blue, green gamma table.
+ **/
+void isppreview_config_gammacorrn(struct ispprev_gtable gtable)
+{
+	int i = 0;
+
+	isp_reg_writel(ISPPRV_REDGAMMA_TABLE_ADDR,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
+		isp_reg_writel(gtable.redtable[i],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+
+	isp_reg_writel(ISPPRV_GREENGAMMA_TABLE_ADDR,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
+		isp_reg_writel(gtable.greentable[i],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+
+	isp_reg_writel(ISPPRV_BLUEGAMMA_TABLE_ADDR,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
+		isp_reg_writel(gtable.bluetable[i],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_config_gammacorrn);
+
+/**
+ * isppreview_config_luma_enhancement - Sets the Luminance Enhancement table.
+ * @ytable: Structure containing the table for Luminance Enhancement table.
+ **/
+void isppreview_config_luma_enhancement(u32 *ytable)
+{
+	int i = 0;
+
+	isp_reg_writel(ISPPRV_YENH_TABLE_ADDR,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < ISPPRV_YENH_TBL_SIZE; i++) {
+		isp_reg_writel(ytable[i],
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_config_luma_enhancement);
+
+/**
+ * isppreview_config_chroma_suppression - Configures the Chroma Suppression.
+ * @csup: Structure containing the threshold value for suppression
+ *        and the hypass filter enable flag.
+ **/
+void isppreview_config_chroma_suppression(struct ispprev_csup csup)
+{
+	isp_reg_writel(csup.gain | (csup.thres << ISPPRV_CSUP_THRES_SHIFT) |
+				(csup.hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_chroma_suppression);
+
+/**
+ * isppreview_enable_noisefilter - Enables/Disables the Noise Filter.
+ * @enable: 1 - Enables the Noise Filter.
+ **/
+void isppreview_enable_noisefilter(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_NFEN);
+	else
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ~ISPPRV_PCR_NFEN);
+	ispprev_obj.nf_en = enable ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_noisefilter);
+
+/**
+ * isppreview_enable_dcor - Enables/Disables the defect correction.
+ * @enable: 1 - Enables the defect correction.
+ **/
+void isppreview_enable_dcor(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DCOREN);
+	else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_DCOREN);
+	}
+	ispprev_obj.dcor_en = enable ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_dcor);
+
+/**
+ * isppreview_enable_cfa - Enable/Disable the CFA Interpolation.
+ * @enable: 1 - Enables the CFA.
+ **/
+void isppreview_enable_cfa(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
+	else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_CFAEN);
+	}
+	ispprev_obj.cfa_en = enable ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_cfa);
+
+/**
+ * isppreview_enable_gammabypass - Enables/Disables the GammaByPass
+ * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
+ *          0 - Goes through Gamma Correction. input and output is 10bit.
+ **/
+void isppreview_enable_gammabypass(u8 enable)
+{
+	if (enable) {
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+						ISPPRV_PCR_GAMMA_BYPASS);
+	} else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+						~ISPPRV_PCR_GAMMA_BYPASS);
+	}
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_gammabypass);
+
+/**
+ * isppreview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
+ * @enable: 1 - Enable the Luminance Enhancement.
+ **/
+void isppreview_enable_luma_enhancement(u8 enable)
+{
+	if (enable) {
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							ISPPRV_PCR_YNENHEN);
+	} else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_YNENHEN);
+	}
+	ispprev_obj.yenh_en = enable ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_luma_enhancement);
+
+/**
+ * isppreview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
+ * @enable: 1 - Enable the Chrominance Suppression.
+ **/
+void isppreview_enable_chroma_suppression(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_SUPEN);
+	else {
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+							~ISPPRV_PCR_SUPEN);
+	}
+	ispprev_obj.csup_en = enable ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_enable_chroma_suppression);
+
+/**
+ * isppreview_config_whitebalance - Configures the White Balance parameters.
+ * @prev_wbal: Structure containing the digital gain and white balance
+ *             coefficient.
+ *
+ * Coefficient matrix always with default values.
+ **/
+void isppreview_config_whitebalance(struct ispprev_wbal prev_wbal)
+{
+	u32 val;
+
+	isp_reg_writel(prev_wbal.dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
+
+	val = (prev_wbal.coef0 << ISPPRV_WBGAIN_COEF0_SHIFT);
+	val |= (prev_wbal.coef1 << ISPPRV_WBGAIN_COEF1_SHIFT);
+	val |= (prev_wbal.coef2 << ISPPRV_WBGAIN_COEF2_SHIFT);
+	val |= (prev_wbal.coef3 << ISPPRV_WBGAIN_COEF3_SHIFT);
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
+
+	isp_reg_writel((ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT) |
+			(ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT) |
+			(ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT) |
+			(ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT) |
+			(ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT) |
+			(ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT) |
+			(ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT) |
+			(ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT) |
+			(ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT) |
+			(ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT) |
+			(ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT) |
+			(ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT) |
+			(ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT) |
+			(ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT) |
+			(ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT) |
+			(ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT),
+			OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_whitebalance);
+
+/**
+ * isppreview_config_whitebalance2 - Configures the White Balance parameters.
+ * @prev_wbal: Structure containing the digital gain and white balance
+ *             coefficient.
+ *
+ * Coefficient matrix can be changed.
+ **/
+void isppreview_config_whitebalance2(struct prev_white_balance prev_wbal)
+{
+	isp_reg_writel(prev_wbal.wb_dgain,
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
+	isp_reg_writel(prev_wbal.wb_gain[0] |
+			(prev_wbal.wb_gain[1] << ISPPRV_WBGAIN_COEF1_SHIFT) |
+			(prev_wbal.wb_gain[2] << ISPPRV_WBGAIN_COEF2_SHIFT) |
+			(prev_wbal.wb_gain[3] << ISPPRV_WBGAIN_COEF3_SHIFT),
+			OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
+
+	isp_reg_writel(
+		prev_wbal.wb_coefmatrix[0][0] << ISPPRV_WBSEL_N0_0_SHIFT |
+		prev_wbal.wb_coefmatrix[0][1] << ISPPRV_WBSEL_N0_1_SHIFT |
+		prev_wbal.wb_coefmatrix[0][2] << ISPPRV_WBSEL_N0_2_SHIFT |
+		prev_wbal.wb_coefmatrix[0][3] << ISPPRV_WBSEL_N0_3_SHIFT |
+		prev_wbal.wb_coefmatrix[1][0] << ISPPRV_WBSEL_N1_0_SHIFT |
+		prev_wbal.wb_coefmatrix[1][1] << ISPPRV_WBSEL_N1_1_SHIFT |
+		prev_wbal.wb_coefmatrix[1][2] << ISPPRV_WBSEL_N1_2_SHIFT |
+		prev_wbal.wb_coefmatrix[1][3] << ISPPRV_WBSEL_N1_3_SHIFT |
+		prev_wbal.wb_coefmatrix[2][0] << ISPPRV_WBSEL_N2_0_SHIFT |
+		prev_wbal.wb_coefmatrix[2][1] << ISPPRV_WBSEL_N2_1_SHIFT |
+		prev_wbal.wb_coefmatrix[2][2] << ISPPRV_WBSEL_N2_2_SHIFT |
+		prev_wbal.wb_coefmatrix[2][3] << ISPPRV_WBSEL_N2_3_SHIFT |
+		prev_wbal.wb_coefmatrix[3][0] << ISPPRV_WBSEL_N3_0_SHIFT |
+		prev_wbal.wb_coefmatrix[3][1] << ISPPRV_WBSEL_N3_1_SHIFT |
+		prev_wbal.wb_coefmatrix[3][2] << ISPPRV_WBSEL_N3_2_SHIFT |
+		prev_wbal.wb_coefmatrix[3][3] << ISPPRV_WBSEL_N3_3_SHIFT,
+		OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_whitebalance2);
+
+/**
+ * isppreview_config_blkadj - Configures the Black Adjustment parameters.
+ * @prev_blkadj: Structure containing the black adjustment towards red, green,
+ *               blue.
+ **/
+void isppreview_config_blkadj(struct ispprev_blkadj prev_blkadj)
+{
+	isp_reg_writel(prev_blkadj.blue |
+			(prev_blkadj.green << ISPPRV_BLKADJOFF_G_SHIFT) |
+			(prev_blkadj.red << ISPPRV_BLKADJOFF_R_SHIFT),
+			OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_blkadj);
+
+/**
+ * isppreview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
+ * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
+ *           offset.
+ **/
+void isppreview_config_rgb_blending(struct ispprev_rgbtorgb rgb2rgb)
+{
+	u32 val = 0;
+
+	val = (rgb2rgb.matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
+	val |= (rgb2rgb.matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
+
+	val = (rgb2rgb.matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
+	val |= (rgb2rgb.matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
+
+	val = (rgb2rgb.matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
+	val |= (rgb2rgb.matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
+
+	val = (rgb2rgb.matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
+	val |= (rgb2rgb.matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
+
+	val = (rgb2rgb.matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
+
+	val = (rgb2rgb.offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
+	val |= (rgb2rgb.offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
+
+	val = (rgb2rgb.offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_rgb_blending);
+
+/**
+ * Configures the RGB-YCbYCr conversion matrix
+ * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
+ *            YCbCr offset.
+ **/
+void isppreview_config_rgb_to_ycbcr(struct ispprev_csc prev_csc)
+{
+	u32 val = 0;
+
+	val = (prev_csc.matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
+	val |= (prev_csc.matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
+	val |= (prev_csc.matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
+
+	val = (prev_csc.matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
+	val |= (prev_csc.matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
+	val |= (prev_csc.matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
+
+	val = (prev_csc.matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
+	val |= (prev_csc.matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
+	val |= (prev_csc.matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
+
+	val = (prev_csc.offset[0] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
+	val |= (prev_csc.offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
+	val |= (prev_csc.offset[2] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_rgb_to_ycbcr);
+
+/**
+ * isppreview_query_contrast - Query the contrast.
+ * @contrast: Pointer to hold the current programmed contrast value.
+ **/
+void isppreview_query_contrast(u8 *contrast)
+{
+	u32 brt_cnt_val = 0;
+
+	brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
+	*contrast = (brt_cnt_val >> ISPPRV_CNT_BRT_CNT_SHIFT) & 0xFF;
+	DPRINTK_ISPPREV(" Current brt cnt value in hw is %x\n", brt_cnt_val);
+}
+EXPORT_SYMBOL_GPL(isppreview_query_contrast);
+
+/**
+ * isppreview_update_contrast - Updates the contrast.
+ * @contrast: Pointer to hold the current programmed contrast value.
+ *
+ * Value should be programmed before enabling the module.
+ **/
+void isppreview_update_contrast(u8 *contrast)
+{
+	ispprev_obj.contrast = *contrast;
+}
+EXPORT_SYMBOL_GPL(isppreview_update_contrast);
+
+/**
+ * isppreview_config_contrast - Configures the Contrast.
+ * @contrast: 8 bit value in U8Q4 format.
+ *
+ * Value should be programmed before enabling the module.
+ **/
+void isppreview_config_contrast(u8 contrast)
+{
+	u32 brt_cnt_val = 0;
+
+	brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
+	brt_cnt_val &= ~(0xFF << ISPPRV_CNT_BRT_CNT_SHIFT);
+	contrast &= 0xFF;
+	isp_reg_writel(brt_cnt_val | (contrast << ISPPRV_CNT_BRT_CNT_SHIFT),
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_contrast);
+
+/**
+ * isppreview_get_contrast_range - Gets the range contrast value.
+ * @min_contrast: Pointer to hold the minimum Contrast value.
+ * @max_contrast: Pointer to hold the maximum Contrast value.
+ **/
+void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast)
+{
+	*min_contrast = ISPPRV_CONTRAST_MIN;
+	*max_contrast = ISPPRV_CONTRAST_MAX;
+}
+EXPORT_SYMBOL_GPL(isppreview_get_contrast_range);
+
+/**
+ * isppreview_update_brightness - Updates the brightness in preview module.
+ * @brightness: Pointer to hold the current programmed brightness value.
+ *
+ **/
+void isppreview_update_brightness(u8 *brightness)
+{
+	ispprev_obj.brightness = *brightness;
+}
+EXPORT_SYMBOL_GPL(isppreview_update_brightness);
+
+/**
+ * isppreview_config_brightness - Configures the brightness.
+ * @contrast: 8bitvalue in U8Q0 format.
+ **/
+void isppreview_config_brightness(u8 brightness)
+{
+	u32 brt_cnt_val = 0;
+
+	DPRINTK_ISPPREV("\tConfiguring brightness in ISP: %d\n", brightness);
+	brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
+	brt_cnt_val &= ~(0xFF << ISPPRV_CNT_BRT_BRT_SHIFT);
+	brightness &= 0xFF;
+	isp_reg_writel(brt_cnt_val | (brightness << ISPPRV_CNT_BRT_BRT_SHIFT),
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_brightness);
+
+/**
+ * isppreview_query_brightness - Query the brightness.
+ * @brightness: Pointer to hold the current programmed brightness value.
+ **/
+void isppreview_query_brightness(u8 *brightness)
+{
+	*brightness = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
+}
+EXPORT_SYMBOL_GPL(isppreview_query_brightness);
+
+/**
+ * isppreview_get_brightness_range - Gets the range brightness value
+ * @min_brightness: Pointer to hold the minimum brightness value
+ * @max_brightness: Pointer to hold the maximum brightness value
+ **/
+void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness)
+{
+	*min_brightness = ISPPRV_BRIGHT_MIN;
+	*max_brightness = ISPPRV_BRIGHT_MAX;
+}
+EXPORT_SYMBOL_GPL(isppreview_get_brightness_range);
+
+/**
+ * isppreview_set_color - Sets the color effect.
+ * @mode: Indicates the required color effect.
+ **/
+void isppreview_set_color(u8 *mode)
+{
+	ispprev_obj.color = *mode;
+	update_color_matrix = 1;
+}
+EXPORT_SYMBOL_GPL(isppreview_set_color);
+
+/**
+ * isppreview_get_color - Gets the current color effect.
+ * @mode: Indicates the current color effect.
+ **/
+void isppreview_get_color(u8 *mode)
+{
+	*mode = ispprev_obj.color;
+}
+EXPORT_SYMBOL_GPL(isppreview_get_color);
+
+/**
+ * isppreview_config_yc_range - Configures the max and min Y and C values.
+ * @yclimit: Structure containing the range of Y and C values.
+ **/
+void isppreview_config_yc_range(struct ispprev_yclimit yclimit)
+{
+	isp_reg_writel(((yclimit.maxC << ISPPRV_SETUP_YC_MAXC_SHIFT) |
+				(yclimit.maxY << ISPPRV_SETUP_YC_MAXY_SHIFT) |
+				(yclimit.minC << ISPPRV_SETUP_YC_MINC_SHIFT) |
+				(yclimit.minY << ISPPRV_SETUP_YC_MINY_SHIFT)),
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
+}
+EXPORT_SYMBOL_GPL(isppreview_config_yc_range);
+
+/**
+ * isppreview_try_size - Calculates output dimensions with the modules enabled.
+ * @input_w: input width for the preview in number of pixels per line
+ * @input_h: input height for the preview in number of lines
+ * @output_w: output width from the preview in number of pixels per line
+ * @output_h: output height for the preview in number of lines
+ *
+ * Calculates the number of pixels cropped in the submodules that are enabled,
+ * Fills up the output width height variables in the isp_prev structure.
+ **/
+int isppreview_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
+{
+	u32 prevout_w = input_w;
+	u32 prevout_h = input_h;
+	u32 div = 0;
+	int max_out;
+
+	ispprev_obj.previn_w = input_w;
+	ispprev_obj.previn_h = input_h;
+
+	if (input_w < 32 || input_h < 32) {
+		printk(KERN_ERR "ISP_ERR : preview does not support "
+				"width < 16 or height < 32 \n");
+		return -EINVAL;
+	}
+	if (omap_rev() == OMAP3430_REV_ES1_0)
+		max_out = ISPPRV_MAXOUTPUT_WIDTH;
+	else
+		max_out = ISPPRV_MAXOUTPUT_WIDTH_ES2;
+
+	ispprev_obj.fmtavg = 0;
+
+	if (input_w > max_out) {
+		div = (input_w/max_out);
+		if (div >= 2 && div < 4) {
+			ispprev_obj.fmtavg = 1;
+			prevout_w /= 2;
+		} else if (div >= 4 && div < 8) {
+			ispprev_obj.fmtavg = 2;
+			prevout_w /= 4;
+		} else if (div >= 8) {
+			ispprev_obj.fmtavg = 3;
+			prevout_w /= 8;
+		}
+	}
+
+	if (ispprev_obj.hmed_en)
+		prevout_w -= 4;
+	if (ispprev_obj.nf_en) {
+		prevout_w -= 4;
+		prevout_h -= 4;
+	}
+	if (ispprev_obj.cfa_en) {
+		switch (ispprev_obj.cfafmt) {
+		case CFAFMT_BAYER:
+		case CFAFMT_SONYVGA:
+			prevout_w -= 4;
+			prevout_h -= 4;
+			break;
+		case CFAFMT_RGBFOVEON:
+		case CFAFMT_RRGGBBFOVEON:
+		case CFAFMT_DNSPL:
+		case CFAFMT_HONEYCOMB:
+			prevout_h -= 2;
+			break;
+		};
+	}
+	if (ispprev_obj.yenh_en || ispprev_obj.csup_en)
+		prevout_w -= 2;
+
+	/* Start at the correct row/column by skipping
+	 * a Sensor specific amount.
+	 */
+	prevout_w -= ispprev_obj.sph;
+	prevout_h -= ispprev_obj.slv;
+
+
+	if (prevout_w % 2)
+		prevout_w -= 1;
+
+	if (ispprev_obj.prev_outfmt == PREVIEW_MEM) {
+		if (((prevout_w * 2) & ISP_32B_BOUNDARY_OFFSET) !=
+							(prevout_w * 2)) {
+			prevout_w = ((prevout_w * 2) &
+						ISP_32B_BOUNDARY_OFFSET) / 2;
+		}
+	}
+	*output_w = prevout_w;
+	ispprev_obj.prevout_w = prevout_w;
+	*output_h = prevout_h;
+	ispprev_obj.prevout_h = prevout_h;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_try_size);
+
+/**
+ * isppreview_config_size - Sets the size of ISP preview output.
+ * @input_w: input width for the preview in number of pixels per line
+ * @input_h: input height for the preview in number of lines
+ * @output_w: output width from the preview in number of pixels per line
+ * @output_h: output height for the preview in number of lines
+ *
+ * Configures the appropriate values stored in the isp_prev structure to
+ * HORZ/VERT_INFO. Configures PRV_AVE if needed for downsampling as calculated
+ * in trysize.
+ **/
+int isppreview_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
+{
+	u32 prevsdroff;
+
+	if ((output_w != ispprev_obj.prevout_w) ||
+					(output_h != ispprev_obj.prevout_h)) {
+		printk(KERN_ERR "ISP_ERR : isppreview_try_size should "
+					"be called before config size\n");
+		return -EINVAL;
+	}
+
+	isp_reg_writel((ispprev_obj.sph << ISPPRV_HORZ_INFO_SPH_SHIFT) |
+					(ispprev_obj.previn_w - 1),
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
+	isp_reg_writel((ispprev_obj.slv << ISPPRV_VERT_INFO_SLV_SHIFT) |
+					(ispprev_obj.previn_h - 2),
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
+
+	if (ispprev_obj.cfafmt == CFAFMT_BAYER)
+		isp_reg_writel(ISPPRV_AVE_EVENDIST_2 <<
+					ISPPRV_AVE_EVENDIST_SHIFT |
+					ISPPRV_AVE_ODDDIST_2 <<
+					ISPPRV_AVE_ODDDIST_SHIFT |
+					ispprev_obj.fmtavg,
+					OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
+
+	if (ispprev_obj.prev_outfmt == PREVIEW_MEM) {
+		prevsdroff = ispprev_obj.prevout_w * 2;
+		if ((prevsdroff & ISP_32B_BOUNDARY_OFFSET) != prevsdroff) {
+			DPRINTK_ISPPREV("ISP_WARN: Preview output buffer line"
+						" size is truncated"
+						" to 32byte boundary\n");
+			prevsdroff &= ISP_32B_BOUNDARY_BUF ;
+		}
+		isppreview_config_outlineoffset(prevsdroff);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_config_size);
+
+/**
+ * isppreview_config_inlineoffset - Configures the Read address line offset.
+ * @offset: Line Offset for the input image.
+ **/
+int isppreview_config_inlineoffset(u32 offset)
+{
+	if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
+		isp_reg_writel(offset & 0xFFFF,
+				OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET);
+	} else {
+		printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
+								"boundary\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_config_inlineoffset);
+
+/**
+ * isppreview_set_inaddr - Sets memory address of input frame.
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ *
+ * Configures the memory address from which the input frame is to be read.
+ **/
+int isppreview_set_inaddr(u32 addr)
+{
+	if ((addr & ISP_32B_BOUNDARY_BUF) == addr)
+		isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
+	else {
+		printk(KERN_ERR "ISP_ERR: Address should be in 32 byte "
+								"boundary\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_set_inaddr);
+
+/**
+ * isppreview_config_outlineoffset - Configures the Write address line offset.
+ * @offset: Line Offset for the preview output.
+ **/
+int isppreview_config_outlineoffset(u32 offset)
+{
+	if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
+		printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
+								"boundary\n");
+		return -EINVAL;
+	}
+	isp_reg_writel(offset & 0xFFFF, OMAP3_ISP_IOMEM_PREV,
+							ISPPRV_WADD_OFFSET);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_config_outlineoffset);
+
+/**
+ * isppreview_set_outaddr - Sets the memory address to store output frame
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ *
+ * Configures the memory address to which the output frame is written.
+ **/
+int isppreview_set_outaddr(u32 addr)
+{
+	if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
+		printk(KERN_ERR "ISP_ERR: Address should be in 32 byte "
+								"boundary\n");
+		return -EINVAL;
+	}
+	isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_set_outaddr);
+
+/**
+ * isppreview_config_darklineoffset - Sets the Dark frame address line offset.
+ * @offset: Line Offset for the Darkframe.
+ **/
+int isppreview_config_darklineoffset(u32 offset)
+{
+	if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
+		printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
+								"boundary\n");
+		return -EINVAL;
+	}
+	isp_reg_writel(offset & 0xFFFF, OMAP3_ISP_IOMEM_PREV,
+							ISPPRV_DRKF_OFFSET);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_config_darklineoffset);
+
+/**
+ * isppreview_set_darkaddr - Sets the memory address to store Dark frame.
+ * @addr: 32bit memory address aligned on 32 bit boundary.
+ **/
+int isppreview_set_darkaddr(u32 addr)
+{
+	if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
+		printk(KERN_ERR "ISP_ERR : Address should be in 32 byte "
+								"boundary\n");
+		return -EINVAL;
+	}
+	isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(isppreview_set_darkaddr);
+
+/**
+ * isppreview_enable - Enables the Preview module.
+ * @enable: 1 - Enables the preview module.
+ *
+ * Client should configure all the sub modules in Preview before this.
+ **/
+void isppreview_enable(u8 enable)
+{
+	if (enable)
+		isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_EN);
+	else
+		isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ~ISPPRV_PCR_EN);
+}
+EXPORT_SYMBOL_GPL(isppreview_enable);
+
+/**
+ * isppreview_busy - Gets busy state of preview module.
+ **/
+int isppreview_busy(void)
+{
+	return isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR) &
+							ISPPRV_PCR_BUSY;
+}
+EXPORT_SYMBOL_GPL(isppreview_busy);
+
+/**
+ * isppreview_get_config - Gets parameters of preview module.
+ **/
+struct prev_params *isppreview_get_config(void)
+{
+	return prev_config_params;
+}
+EXPORT_SYMBOL_GPL(isppreview_get_config);
+
+/**
+ * isppreview_save_context - Saves the values of the preview module registers.
+ **/
+void isppreview_save_context(void)
+{
+	DPRINTK_ISPPREV("Saving context\n");
+	isp_save_context(ispprev_reg_list);
+}
+EXPORT_SYMBOL_GPL(isppreview_save_context);
+
+/**
+ * isppreview_restore_context - Restores the values of preview module registers
+ **/
+void isppreview_restore_context(void)
+{
+	DPRINTK_ISPPREV("Restoring context\n");
+	isp_restore_context(ispprev_reg_list);
+}
+EXPORT_SYMBOL_GPL(isppreview_restore_context);
+
+/**
+ * isppreview_print_status - Prints the values of the Preview Module registers.
+ *
+ * Also prints other debug information stored in the preview moduel.
+ **/
+void isppreview_print_status(void)
+{
+	DPRINTK_ISPPREV("Module in use =%d\n", ispprev_obj.prev_inuse);
+	DPRINTK_ISPPREV("Preview Input format =%d, Output Format =%d\n",
+						ispprev_obj.prev_inpfmt,
+						ispprev_obj.prev_outfmt);
+	DPRINTK_ISPPREV("Accepted Preview Input (width = %d,Height = %d)\n",
+						ispprev_obj.previn_w,
+						ispprev_obj.previn_h);
+	DPRINTK_ISPPREV("Accepted Preview Output (width = %d,Height = %d)\n",
+						ispprev_obj.prevout_w,
+						ispprev_obj.prevout_h);
+	DPRINTK_ISPPREV("###ISP_CTRL in preview =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
+	DPRINTK_ISPPREV("###ISP_IRQ0ENABLE in preview =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
+	DPRINTK_ISPPREV("###ISP_IRQ0STATUS in preview =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
+	DPRINTK_ISPPREV("###PRV PCR =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR));
+	DPRINTK_ISPPREV("###PRV HORZ_INFO =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO));
+	DPRINTK_ISPPREV("###PRV VERT_INFO =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO));
+	DPRINTK_ISPPREV("###PRV WSDR_ADDR =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR));
+	DPRINTK_ISPPREV("###PRV WADD_OFFSET =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET));
+	DPRINTK_ISPPREV("###PRV AVE =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE));
+	DPRINTK_ISPPREV("###PRV HMED =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED));
+	DPRINTK_ISPPREV("###PRV NF =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_NF));
+	DPRINTK_ISPPREV("###PRV WB_DGAIN =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN));
+	DPRINTK_ISPPREV("###PRV WBGAIN =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN));
+	DPRINTK_ISPPREV("###PRV WBSEL =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL));
+	DPRINTK_ISPPREV("###PRV CFA =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA));
+	DPRINTK_ISPPREV("###PRV BLKADJOFF =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF));
+	DPRINTK_ISPPREV("###PRV RGB_MAT1 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1));
+	DPRINTK_ISPPREV("###PRV RGB_MAT2 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2));
+	DPRINTK_ISPPREV("###PRV RGB_MAT3 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3));
+	DPRINTK_ISPPREV("###PRV RGB_MAT4 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4));
+	DPRINTK_ISPPREV("###PRV RGB_MAT5 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5));
+	DPRINTK_ISPPREV("###PRV RGB_OFF1 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1));
+	DPRINTK_ISPPREV("###PRV RGB_OFF2 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2));
+	DPRINTK_ISPPREV("###PRV CSC0 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0));
+	DPRINTK_ISPPREV("###PRV CSC1 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1));
+	DPRINTK_ISPPREV("###PRV CSC2 =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2));
+	DPRINTK_ISPPREV("###PRV CSC_OFFSET =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET));
+	DPRINTK_ISPPREV("###PRV CNT_BRT =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT));
+	DPRINTK_ISPPREV("###PRV CSUP =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP));
+	DPRINTK_ISPPREV("###PRV SETUP_YC =0x%x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC));
+}
+EXPORT_SYMBOL_GPL(isppreview_print_status);
+
+/**
+ * isp_preview_init - Module Initialization.
+ **/
+int __init isp_preview_init(void)
+{
+	int i = 0;
+
+	prev_config_params = kmalloc(sizeof(*prev_config_params), GFP_KERNEL);
+	if (!prev_config_params) {
+		printk(KERN_ERR "Can't get memory for isp_preview params!\n");
+		return -ENOMEM;
+	}
+	params = prev_config_params;
+
+	ispprev_obj.prev_inuse = 0;
+	mutex_init(&ispprev_obj.ispprev_mutex);
+
+	/* Init values */
+	ispprev_obj.sph = 2;
+	ispprev_obj.slv = 0;
+	ispprev_obj.color = V4L2_COLORFX_NONE;
+	ispprev_obj.contrast = ISPPRV_CONTRAST_DEF;
+	params->contrast = ISPPRV_CONTRAST_DEF;
+	ispprev_obj.brightness = ISPPRV_BRIGHT_DEF;
+	params->brightness = ISPPRV_BRIGHT_DEF;
+	params->average = NO_AVE;
+	params->lens_shading_shift = 0;
+	params->pix_fmt = YCPOS_YCrYCb;
+	params->cfa.cfafmt = CFAFMT_BAYER;
+	params->cfa.cfa_table = cfa_coef_table;
+	params->cfa.cfa_gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
+	params->cfa.cfa_gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
+	params->csup.gain = FLR_CSUP_GAIN;
+	params->csup.thres = FLR_CSUP_THRES;
+	params->csup.hypf_en = 0;
+	params->ytable = luma_enhance_table;
+	params->nf.spread = FLR_NF_STRGTH;
+	memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
+	params->dcor.couplet_mode_en = 1;
+	for (i = 0; i < 4; i++)
+		params->dcor.detect_correct[i] = 0xE;
+	params->gtable.bluetable = bluegamma_table;
+	params->gtable.greentable = greengamma_table;
+	params->gtable.redtable = redgamma_table;
+	params->wbal.dgain = FLR_WBAL_DGAIN;
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		params->wbal.coef0 = FLR_WBAL_COEF0_ES1;
+		params->wbal.coef1 = FLR_WBAL_COEF1_ES1;
+		params->wbal.coef2 = FLR_WBAL_COEF2_ES1;
+		params->wbal.coef3 = FLR_WBAL_COEF3_ES1;
+	} else {
+		params->wbal.coef0 = FLR_WBAL_COEF0;
+		params->wbal.coef1 = FLR_WBAL_COEF1;
+		params->wbal.coef2 = FLR_WBAL_COEF2;
+		params->wbal.coef3 = FLR_WBAL_COEF3;
+	}
+	params->blk_adj.red = FLR_BLKADJ_RED;
+	params->blk_adj.green = FLR_BLKADJ_GREEN;
+	params->blk_adj.blue = FLR_BLKADJ_BLUE;
+	params->rgb2rgb = flr_rgb2rgb;
+	params->rgb2ycbcr = flr_prev_csc[ispprev_obj.color];
+
+	params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER;
+	params->features &= ~(PREV_AVERAGER | PREV_INVERSE_ALAW |
+						PREV_HORZ_MEDIAN_FILTER |
+						PREV_GAMMA_BYPASS |
+						PREV_DARK_FRAME_SUBTRACT |
+						PREV_LENS_SHADING |
+						PREV_DARK_FRAME_CAPTURE |
+						PREV_CHROMA_SUPPRESS |
+						PREV_LUMA_ENHANCE);
+	return 0;
+}
+
+/**
+ * isp_preview_cleanup - Module Cleanup.
+ **/
+void isp_preview_cleanup(void)
+{
+	kfree(prev_config_params);
+}
diff --git a/drivers/media/video/isp/isppreview.h b/drivers/media/video/isp/isppreview.h
new file mode 100644
index 0000000..f8a12d5
--- /dev/null
+++ b/drivers/media/video/isp/isppreview.h
@@ -0,0 +1,350 @@
+/*
+ * isppreview.h
+ *
+ * Driver header file for Preview module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Senthilvadivu Guruswamy <svadivu@ti.com>
+ *	Pallavi Kulkarni <p-kulkarni@ti.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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_PREVIEW_H
+#define OMAP_ISP_PREVIEW_H
+
+#include <mach/isp_user.h>
+/* Isp query control structure */
+
+#define ISPPRV_BRIGHT_STEP		0x1
+#define ISPPRV_BRIGHT_DEF		0x0
+#define ISPPRV_BRIGHT_LOW		0x0
+#define ISPPRV_BRIGHT_HIGH		0xF
+#define ISPPRV_BRIGHT_UNITS		0x7
+
+#define ISPPRV_CONTRAST_STEP		0x1
+#define ISPPRV_CONTRAST_DEF		0x4
+#define ISPPRV_CONTRAST_LOW		0x0
+#define ISPPRV_CONTRAST_HIGH		0xF
+#define ISPPRV_CONTRAST_UNITS		0x4
+
+#define NO_AVE				0x0
+#define AVE_2_PIX			0x1
+#define AVE_4_PIX			0x2
+#define AVE_8_PIX			0x3
+#define AVE_ODD_PIXEL_DIST		(1 << 4) /* For Bayer Sensors */
+#define AVE_EVEN_PIXEL_DIST		(1 << 2)
+
+#define WB_GAIN_MAX			4
+
+/* Features list */
+#define PREV_AVERAGER			(1 << 0)
+#define PREV_INVERSE_ALAW 		(1 << 1)
+#define PREV_HORZ_MEDIAN_FILTER		(1 << 2)
+#define PREV_NOISE_FILTER 		(1 << 3)
+#define PREV_CFA			(1 << 4)
+#define PREV_GAMMA_BYPASS		(1 << 5)
+#define PREV_LUMA_ENHANCE		(1 << 6)
+#define PREV_CHROMA_SUPPRESS		(1 << 7)
+#define PREV_DARK_FRAME_SUBTRACT	(1 << 8)
+#define PREV_LENS_SHADING		(1 << 9)
+#define PREV_DARK_FRAME_CAPTURE		(1 << 10)
+#define PREV_DEFECT_COR			(1 << 11)
+
+
+#define ISP_NF_TABLE_SIZE 		(1 << 10)
+
+#define ISP_GAMMA_TABLE_SIZE 		(1 << 10)
+
+/* Table addresses */
+#define ISPPRV_TBL_ADDR_RED_G_START  0x00
+#define ISPPRV_TBL_ADDR_BLUE_G_START  0x800
+#define ISPPRV_TBL_ADDR_GREEN_G_START  0x400
+
+/*
+ *Enumeration Constants for input and output format
+ */
+enum preview_input {
+	PRV_RAW_CCDC,
+	PRV_RAW_MEM,
+	PRV_RGBBAYERCFA,
+	PRV_COMPCFA,
+	PRV_CCDC_DRKF,
+	PRV_OTHERS
+};
+enum preview_output {
+	PREVIEW_RSZ,
+	PREVIEW_MEM
+};
+/*
+ * Configure byte layout of YUV image
+ */
+enum preview_ycpos_mode {
+	YCPOS_YCrYCb = 0,
+	YCPOS_YCbYCr = 1,
+	YCPOS_CbYCrY = 2,
+	YCPOS_CrYCbY = 3
+};
+
+/**
+ * struct ispprev_gtable - Structure for Gamma Correction.
+ * @redtable: Pointer to the red gamma table.
+ * @greentable: Pointer to the green gamma table.
+ * @bluetable: Pointer to the blue gamma table.
+ */
+struct ispprev_gtable {
+	u32 *redtable;
+	u32 *greentable;
+	u32 *bluetable;
+};
+
+/**
+ * struct prev_white_balance - Structure for White Balance 2.
+ * @wb_dgain: White balance common gain.
+ * @wb_gain: Individual color gains.
+ * @wb_coefmatrix: Coefficient matrix
+ */
+struct prev_white_balance {
+	u16 wb_dgain; /* white balance common gain */
+	u8 wb_gain[WB_GAIN_MAX]; /* individual color gains */
+	u8 wb_coefmatrix[WB_GAIN_MAX][WB_GAIN_MAX];
+};
+
+/**
+ * struct prev_size_params - Structure for size parameters.
+ * @hstart: Starting pixel.
+ * @vstart: Starting line.
+ * @hsize: Width of input image.
+ * @vsize: Height of input image.
+ * @pixsize: Pixel size of the image in terms of bits.
+ * @in_pitch: Line offset of input image.
+ * @out_pitch: Line offset of output image.
+ */
+struct prev_size_params {
+	unsigned int hstart;
+	unsigned int vstart;
+	unsigned int hsize;
+	unsigned int vsize;
+	unsigned char pixsize;
+	unsigned short in_pitch;
+	unsigned short out_pitch;
+};
+
+/**
+ * struct prev_rgb2ycbcr_coeffs - Structure RGB2YCbCr parameters.
+ * @coeff: Color conversion gains in 3x3 matrix.
+ * @offset: Color conversion offsets.
+ */
+struct prev_rgb2ycbcr_coeffs {
+	short coeff[RGB_MAX][RGB_MAX];
+	short offset[RGB_MAX];
+};
+
+/**
+ * struct prev_darkfrm_params - Structure for Dark frame suppression.
+ * @addr: Memory start address.
+ * @offset: Line offset.
+ */
+struct prev_darkfrm_params {
+	u32 addr;
+	u32 offset;
+};
+
+/**
+ * struct prev_params - Structure for all configuration
+ * @features: Set of features enabled.
+ * @pix_fmt: Output pixel format.
+ * @cfa: CFA coefficients.
+ * @csup: Chroma suppression coefficients.
+ * @ytable: Pointer to Luma enhancement coefficients.
+ * @nf: Noise filter coefficients.
+ * @dcor: Noise filter coefficients.
+ * @gtable: Gamma coefficients.
+ * @wbal: White Balance parameters.
+ * @blk_adj: Black adjustment parameters.
+ * @rgb2rgb: RGB blending parameters.
+ * @rgb2ycbcr: RGB to ycbcr parameters.
+ * @hmf_params: Horizontal median filter.
+ * @size_params: Size parameters.
+ * @drkf_params: Darkframe parameters.
+ * @lens_shading_shift:
+ * @average: Downsampling rate for averager.
+ * @contrast: Contrast.
+ * @brightness: Brightness.
+ */
+struct prev_params {
+	u16 features;
+	enum preview_ycpos_mode pix_fmt;
+	struct ispprev_cfa cfa;
+	struct ispprev_csup csup;
+	u32 *ytable;
+	struct ispprev_nf nf;
+	struct ispprev_dcor dcor;
+	struct ispprev_gtable gtable;
+	struct ispprev_wbal wbal;
+	struct ispprev_blkadj blk_adj;
+	struct ispprev_rgbtorgb rgb2rgb;
+	struct ispprev_csc rgb2ycbcr;
+	struct ispprev_hmed hmf_params;
+	struct prev_size_params size_params;
+	struct prev_darkfrm_params drkf_params;
+	u8 lens_shading_shift;
+	u8 average;
+	u8 contrast;
+	u8 brightness;
+};
+
+/**
+ * struct isptables_update - Structure for Table Configuration.
+ * @update: Specifies which tables should be updated.
+ * @flag: Specifies which tables should be enabled.
+ * @prev_nf: Pointer to structure for Noise Filter
+ * @lsc: Pointer to LSC gain table. (currently not used)
+ * @red_gamma: Pointer to red gamma correction table.
+ * @green_gamma: Pointer to green gamma correction table.
+ * @blue_gamma: Pointer to blue gamma correction table.
+ */
+struct isptables_update {
+	u16 update;
+	u16 flag;
+	struct ispprev_nf *prev_nf;
+	u32 *lsc;
+	u32 *red_gamma;
+	u32 *green_gamma;
+	u32 *blue_gamma;
+};
+
+void isppreview_config_shadow_registers(void);
+
+int isppreview_request(void);
+
+int isppreview_free(void);
+
+int isppreview_config_datapath(enum preview_input input,
+					enum preview_output output);
+
+void isppreview_config_ycpos(enum preview_ycpos_mode mode);
+
+void isppreview_config_averager(u8 average);
+
+void isppreview_enable_invalaw(u8 enable);
+
+void isppreview_enable_drkframe(u8 enable);
+
+void isppreview_enable_shadcomp(u8 enable);
+
+void isppreview_config_drkf_shadcomp(u8 scomp_shtval);
+
+void isppreview_enable_gammabypass(u8 enable);
+
+void isppreview_enable_hmed(u8 enable);
+
+void isppreview_config_hmed(struct ispprev_hmed);
+
+void isppreview_enable_noisefilter(u8 enable);
+
+void isppreview_config_noisefilter(struct ispprev_nf prev_nf);
+
+void isppreview_enable_dcor(u8 enable);
+
+void isppreview_config_dcor(struct ispprev_dcor prev_dcor);
+
+
+void isppreview_config_cfa(struct ispprev_cfa);
+
+void isppreview_config_gammacorrn(struct ispprev_gtable);
+
+void isppreview_config_chroma_suppression(struct ispprev_csup csup);
+
+void isppreview_enable_cfa(u8 enable);
+
+void isppreview_config_luma_enhancement(u32 *ytable);
+
+void isppreview_enable_luma_enhancement(u8 enable);
+
+void isppreview_enable_chroma_suppression(u8 enable);
+
+void isppreview_config_whitebalance(struct ispprev_wbal);
+
+void isppreview_config_blkadj(struct ispprev_blkadj);
+
+void isppreview_config_rgb_blending(struct ispprev_rgbtorgb);
+
+void isppreview_config_rgb_to_ycbcr(struct ispprev_csc);
+
+void isppreview_update_contrast(u8 *contrast);
+
+void isppreview_query_contrast(u8 *contrast);
+
+void isppreview_config_contrast(u8 contrast);
+
+void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast);
+
+void isppreview_update_brightness(u8 *brightness);
+
+void isppreview_config_brightness(u8 brightness);
+
+void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness);
+
+void isppreview_set_color(u8 *mode);
+
+void isppreview_get_color(u8 *mode);
+
+void isppreview_query_brightness(u8 *brightness);
+
+void isppreview_config_yc_range(struct ispprev_yclimit yclimit);
+
+int isppreview_try_size(u32 input_w, u32 input_h, u32 *output_w,
+				u32 *output_h);
+
+int isppreview_config_size(u32 input_w, u32 input_h, u32 output_w,
+			u32 output_h);
+
+int isppreview_config_inlineoffset(u32 offset);
+
+int isppreview_set_inaddr(u32 addr);
+
+int isppreview_config_outlineoffset(u32 offset);
+
+int isppreview_set_outaddr(u32 addr);
+
+int isppreview_config_darklineoffset(u32 offset);
+
+int isppreview_set_darkaddr(u32 addr);
+
+void isppreview_enable(u8 enable);
+
+int isppreview_busy(void);
+
+struct prev_params *isppreview_get_config(void);
+
+void isppreview_print_status(void);
+
+#ifndef CONFIG_ARCH_OMAP3410
+void isppreview_save_context(void);
+#else
+static inline void isppreview_save_context(void) {}
+#endif
+
+#ifndef CONFIG_ARCH_OMAP3410
+void isppreview_restore_context(void);
+#else
+static inline void isppreview_restore_context(void) {}
+#endif
+
+int omap34xx_isp_preview_config(void *userspace_add);
+
+int omap34xx_isp_tables_update(struct isptables_update *isptables_struct);
+
+void isppreview_set_skip(u32 h, u32 v);
+
+#endif/* OMAP_ISP_PREVIEW_H */
diff --git a/drivers/media/video/isp/ispresizer.c b/drivers/media/video/isp/ispresizer.c
new file mode 100644
index 0000000..6fd2ba0
--- /dev/null
+++ b/drivers/media/video/isp/ispresizer.c
@@ -0,0 +1,897 @@
+/*
+ * ispresizer.c
+ *
+ * Driver Library for Resizer module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C)2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@ti.com>
+ * 	Mohit Jalori
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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 "isp.h"
+#include "ispreg.h"
+#include "ispresizer.h"
+
+/* Default configuration of resizer,filter coefficients,yenh for camera isp */
+static struct isprsz_yenh ispreszdefaultyenh = {0, 0, 0, 0};
+static struct isprsz_coef ispreszdefcoef = {
+	{
+		0x0027, 0x00B2, 0x00B2, 0x0027,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+		0x0027, 0x00B2, 0x0027, 0x00B2,
+	},
+	{
+		0x0000, 0x0100, 0x0000, 0x0000,
+		0x03FA, 0x00F6, 0x0010, 0x0000,
+		0x03F9, 0x00DB, 0x002C, 0x0000,
+		0x03FB, 0x00B3, 0x0053, 0x03FF,
+		0x03FD, 0x0082, 0x0084, 0x03FD,
+		0x03FF, 0x0053, 0x00B3, 0x03FB,
+		0x0000, 0x002C, 0x00DB, 0x03F9,
+		0x0000, 0x0010, 0x00F6, 0x03FA
+	},
+	{
+		0x0004, 0x0023, 0x0023, 0x005A,
+		0x005A, 0x0058, 0x0058, 0x0004,
+		0x0023, 0x0023, 0x005A, 0x005A,
+		0x0058, 0x0058, 0x0004, 0x0023,
+		0x0023, 0x005A, 0x005A, 0x0058,
+		0x0058, 0x0004, 0x0023, 0x0023,
+		0x005A, 0x005A, 0x0058, 0x0058
+	},
+	{
+		0x0004, 0x0023, 0x005A, 0x0058,
+		0x0023, 0x0004, 0x0000, 0x0002,
+		0x0018, 0x004d, 0x0060, 0x0031,
+		0x0008, 0x0000, 0x0001, 0x000f,
+		0x003f, 0x0062, 0x003f, 0x000f,
+		0x0001, 0x0000, 0x0008, 0x0031,
+		0x0060, 0x004d, 0x0018, 0x0002
+	}
+};
+
+/**
+ * struct isp_res - Structure for the resizer module to store its information.
+ * @res_inuse: Indicates if resizer module has been reserved. 1 - Reserved,
+ *             0 - Freed.
+ * @h_startphase: Horizontal starting phase.
+ * @v_startphase: Vertical starting phase.
+ * @h_resz: Horizontal resizing value.
+ * @v_resz: Vertical resizing value.
+ * @outputwidth: Output Image Width in pixels.
+ * @outputheight: Output Image Height in pixels.
+ * @inputwidth: Input Image Width in pixels.
+ * @inputheight: Input Image Height in pixels.
+ * @algo: Algorithm select. 0 - Disable, 1 - [-1 2 -1]/2 high-pass filter,
+ *        2 - [-1 -2 6 -2 -1]/4 high-pass filter.
+ * @ipht_crop: Vertical start line for cropping.
+ * @ipwd_crop: Horizontal start pixel for cropping.
+ * @cropwidth: Crop Width.
+ * @cropheight: Crop Height.
+ * @resinput: Resizer input.
+ * @coeflist: Register configuration for Resizer.
+ * @ispres_mutex: Mutex for isp resizer.
+ */
+static struct isp_res {
+	u8 res_inuse;
+	u8 h_startphase;
+	u8 v_startphase;
+	u16 h_resz;
+	u16 v_resz;
+	u32 outputwidth;
+	u32 outputheight;
+	u32 inputwidth;
+	u32 inputheight;
+	u8 algo;
+	u32 ipht_crop;
+	u32 ipwd_crop;
+	u32 cropwidth;
+	u32 cropheight;
+	dma_addr_t tmp_buf;
+	enum ispresizer_input resinput;
+	struct isprsz_coef coeflist;
+	struct mutex ispres_mutex; /* For checking/modifying res_inuse */
+} ispres_obj;
+
+/* Structure for saving/restoring resizer module registers */
+static struct isp_reg isprsz_reg_list[] = {
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT32, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT54, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT76, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT98, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1110, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1312, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1514, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1716, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1918, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2120, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2322, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2524, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2726, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2928, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT3130, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT32, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT54, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT76, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT98, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1110, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1312, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1514, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1716, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1918, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2120, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2322, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2524, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2726, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2928, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT3130, 0x0000},
+	{OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH, 0x0000},
+	{0, ISP_TOK_TERM, 0x0000}
+};
+
+/**
+ * ispresizer_config_shadow_registers - Configure shadow registers.
+ **/
+void ispresizer_config_shadow_registers()
+{
+	return;
+}
+EXPORT_SYMBOL(ispresizer_config_shadow_registers);
+
+/**
+ * ispresizer_trycrop - Validate crop dimensions.
+ * @left: Left distance to start position of crop.
+ * @top: Top distance to start position of crop.
+ * @width: Width of input image.
+ * @height: Height of input image.
+ * @ow: Width of output image.
+ * @oh: Height of output image.
+ **/
+void ispresizer_trycrop(u32 left, u32 top, u32 width, u32 height, u32 ow,
+									u32 oh)
+{
+	ispres_obj.cropwidth = width + 6;
+	ispres_obj.cropheight = height + 6;
+	ispresizer_try_size(&ispres_obj.cropwidth, &ispres_obj.cropheight, &ow,
+									&oh);
+	ispres_obj.ipht_crop = top;
+	ispres_obj.ipwd_crop = left;
+}
+EXPORT_SYMBOL(ispresizer_trycrop);
+
+/**
+ * ispresizer_applycrop - Apply crop to input image.
+ **/
+void ispresizer_applycrop(void)
+{
+	ispresizer_config_size(ispres_obj.cropwidth, ispres_obj.cropheight,
+						ispres_obj.outputwidth,
+						ispres_obj.outputheight);
+	return;
+}
+EXPORT_SYMBOL(ispresizer_applycrop);
+
+/**
+ * ispresizer_request - Reserves the Resizer module.
+ *
+ * Allows only one user at a time.
+ *
+ * Returns 0 if successful, or -EBUSY if resizer module was already requested.
+ **/
+int ispresizer_request()
+{
+	mutex_lock(&ispres_obj.ispres_mutex);
+	if (!ispres_obj.res_inuse) {
+		ispres_obj.res_inuse = 1;
+		mutex_unlock(&ispres_obj.ispres_mutex);
+		isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL) |
+					ISPCTRL_SBL_WR0_RAM_EN |
+					ISPCTRL_RSZ_CLK_EN,
+					OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
+		return 0;
+	} else {
+		mutex_unlock(&ispres_obj.ispres_mutex);
+		printk(KERN_ERR "ISP_ERR : Resizer Module Busy\n");
+		return -EBUSY;
+	}
+}
+EXPORT_SYMBOL(ispresizer_request);
+
+/**
+ * ispresizer_free - Makes Resizer module free.
+ *
+ * Returns 0 if successful, or -EINVAL if resizer module was already freed.
+ **/
+int ispresizer_free()
+{
+	mutex_lock(&ispres_obj.ispres_mutex);
+	if (ispres_obj.res_inuse) {
+		ispres_obj.res_inuse = 0;
+		mutex_unlock(&ispres_obj.ispres_mutex);
+		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+			~(ISPCTRL_RSZ_CLK_EN | ISPCTRL_SBL_WR0_RAM_EN));
+		return 0;
+	} else {
+		mutex_unlock(&ispres_obj.ispres_mutex);
+		DPRINTK_ISPRESZ("ISP_ERR : Resizer Module already freed\n");
+		return -EINVAL;
+	}
+}
+EXPORT_SYMBOL(ispresizer_free);
+
+/**
+ * ispresizer_config_datapath - Specifies which input to use in resizer module
+ * @input: Indicates the module that gives the image to resizer.
+ *
+ * Sets up the default resizer configuration according to the arguments.
+ *
+ * Returns 0 if successful, or -EINVAL if an unsupported input was requested.
+ **/
+int ispresizer_config_datapath(enum ispresizer_input input)
+{
+	u32 cnt = 0;
+	DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n");
+	ispres_obj.resinput = input;
+	switch (input) {
+	case RSZ_OTFLY_YUV:
+		cnt &= ~ISPRSZ_CNT_INPTYP;
+		cnt &= ~ISPRSZ_CNT_INPSRC;
+		ispresizer_set_inaddr(0);
+		ispresizer_config_inlineoffset(0);
+		break;
+	case RSZ_MEM_YUV:
+		cnt |= ISPRSZ_CNT_INPSRC;
+		cnt &= ~ISPRSZ_CNT_INPTYP;
+		break;
+	case RSZ_MEM_COL8:
+		cnt |= ISPRSZ_CNT_INPSRC;
+		cnt |= ISPRSZ_CNT_INPTYP;
+		break;
+	default:
+		printk(KERN_ERR "ISP_ERR : Wrong Input\n");
+		return -EINVAL;
+	}
+	isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt);
+	ispresizer_config_ycpos(0);
+	ispresizer_config_filter_coef(&ispreszdefcoef);
+	ispresizer_enable_cbilin(0);
+	ispresizer_config_luma_enhance(&ispreszdefaultyenh);
+	DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n");
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_config_datapath);
+
+/**
+ * ispresizer_try_size - Validates input and output images size.
+ * @input_w: input width for the resizer in number of pixels per line
+ * @input_h: input height for the resizer in number of lines
+ * @output_w: output width from the resizer in number of pixels per line
+ *            resizer when writing to memory needs this to be multiple of 16.
+ * @output_h: output height for the resizer in number of lines, must be even.
+ *
+ * Calculates the horizontal and vertical resize ratio, number of pixels to
+ * be cropped in the resizer module and checks the validity of various
+ * parameters. Formula used for calculation is:-
+ *
+ * 8-phase 4-tap mode :-
+ * inputwidth = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7
+ * inputheight = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4
+ * endpahse for width = ((32 * sph + (ow - 1) * hrsz + 16) >> 5) % 8
+ * endphase for height = ((32 * sph + (oh - 1) * hrsz + 16) >> 5) % 8
+ *
+ * 4-phase 7-tap mode :-
+ * inputwidth = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7
+ * inputheight = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7
+ * endpahse for width = ((64 * sph + (ow - 1) * hrsz + 32) >> 6) % 4
+ * endphase for height = ((64 * sph + (oh - 1) * hrsz + 32) >> 6) % 4
+ *
+ * Where:
+ * sph = Start phase horizontal
+ * spv = Start phase vertical
+ * ow = Output width
+ * oh = Output height
+ * hrsz = Horizontal resize value
+ * vrsz = Vertical resize value
+ *
+ * Fills up the output/input widht/height, horizontal/vertical resize ratio,
+ * horizontal/vertical crop variables in the isp_res structure.
+ **/
+int ispresizer_try_size(u32 *input_width, u32 *input_height, u32 *output_w,
+								u32 *output_h)
+{
+	u32 rsz, rsz_7, rsz_4;
+	u32 sph;
+	u32 input_w, input_h;
+	int max_in_otf, max_out_7tap;
+	input_w = *input_width;
+	input_h = *input_height;
+
+	if (input_w < 32 || input_h < 32) {
+		DPRINTK_ISPCCDC("ISP_ERR: RESIZER cannot handle input width"
+				" less than 32 pixels or height less than"
+				" 32\n");
+		return -EINVAL;
+	}
+	input_w -= 6;
+	input_h -= 6;
+
+	if (input_h > MAX_IN_HEIGHT)
+		return -EINVAL;
+
+	if (*output_w < 16)
+		*output_w = 16;
+
+	if (*output_h < 2)
+		*output_h = 2;
+
+	if (omap_rev() == OMAP3430_REV_ES1_0) {
+		max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE;
+		max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH;
+	} else {
+		max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
+		max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH_ES2;
+	}
+
+	if (ispres_obj.resinput == RSZ_OTFLY_YUV) {
+		if (input_w > max_in_otf)
+			return -EINVAL;
+	} else {
+		if (input_w > MAX_IN_WIDTH_MEMORY_MODE)
+			return -EINVAL;
+	}
+
+	*output_h &= 0xfffffffe;
+	sph = DEFAULTSTPHASE;
+
+	rsz_7 = ((input_h - 7) * 256) / (*output_h - 1);
+	rsz_4 = ((input_h - 4) * 256) / (*output_h - 1);
+
+	rsz = (input_h * 256) / *output_h;
+
+	if (rsz <= MID_RESIZE_VALUE) {
+		rsz = rsz_4;
+		if (rsz < MINIMUM_RESIZE_VALUE) {
+			rsz = MINIMUM_RESIZE_VALUE;
+			*output_h = (((input_h - 4) * 256) / rsz) + 1;
+			printk(KERN_INFO "%s: using output_h %d instead\n",
+							__func__, *output_h);
+		}
+	} else {
+		rsz = rsz_7;
+		if (*output_w > max_out_7tap)
+			*output_w = max_out_7tap;
+		if (rsz > MAXIMUM_RESIZE_VALUE) {
+			rsz = MAXIMUM_RESIZE_VALUE;
+			*output_h = (((input_h - 7) * 256) / rsz) + 1;
+			printk(KERN_INFO "%s: using output_h %d instead\n",
+							__func__, *output_h);
+		}
+	}
+
+	if (rsz > MID_RESIZE_VALUE) {
+		input_h =
+			(((64 * sph) + ((*output_h - 1) * rsz) + 32) / 256) + 7;
+	} else {
+		input_h =
+			(((32 * sph) + ((*output_h - 1) * rsz) + 16) / 256) + 4;
+	}
+
+	ispres_obj.outputheight = *output_h;
+	ispres_obj.v_resz = rsz;
+	ispres_obj.inputheight = input_h;
+	ispres_obj.ipht_crop = DEFAULTSTPIXEL;
+	ispres_obj.v_startphase = sph;
+
+	*output_w &= 0xfffffff0;
+	sph = DEFAULTSTPHASE;
+
+	rsz_7 = ((input_w - 7) * 256) / (*output_w - 1);
+	rsz_4 = ((input_w - 4) * 256) / (*output_w - 1);
+
+	rsz = (input_w * 256) / *output_w;
+	if (rsz > MID_RESIZE_VALUE) {
+		rsz = rsz_7;
+		if (rsz > MAXIMUM_RESIZE_VALUE) {
+			rsz = MAXIMUM_RESIZE_VALUE;
+			*output_w = (((input_w - 7) * 256) / rsz) + 1;
+			*output_w = (*output_w + 0xf) & 0xfffffff0;
+			printk(KERN_INFO "%s: using output_w %d instead\n",
+							__func__, *output_w);
+		}
+	} else {
+		rsz = rsz_4;
+		if (rsz < MINIMUM_RESIZE_VALUE) {
+			rsz = MINIMUM_RESIZE_VALUE;
+			*output_w = (((input_w - 4) * 256) / rsz) + 1;
+			*output_w = (*output_w + 0xf) & 0xfffffff0;
+			printk(KERN_INFO "%s: using output_w %d instead\n",
+							__func__, *output_w);
+		}
+	}
+
+	/* Recalculate input based on TRM equations */
+	if (rsz > MID_RESIZE_VALUE) {
+		input_w =
+			(((64 * sph) + ((*output_w - 1) * rsz) + 32) / 256) + 7;
+	} else {
+		input_w =
+			(((32 * sph) + ((*output_w - 1) * rsz) + 16) / 256) + 7;
+	}
+
+	ispres_obj.outputwidth = *output_w;
+	ispres_obj.h_resz = rsz;
+	ispres_obj.inputwidth = input_w;
+	ispres_obj.ipwd_crop = DEFAULTSTPIXEL;
+	ispres_obj.h_startphase = sph;
+
+	*input_height = input_h;
+	*input_width = input_w;
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_try_size);
+
+/**
+ * ispresizer_config_size - Configures input and output image size.
+ * @input_w: input width for the resizer in number of pixels per line.
+ * @input_h: input height for the resizer in number of lines.
+ * @output_w: output width from the resizer in number of pixels per line.
+ * @output_h: output height for the resizer in number of lines.
+ *
+ * Configures the appropriate values stored in the isp_res structure in the
+ * resizer registers.
+ *
+ * Returns 0 if successful, or -EINVAL if passed values haven't been verified
+ * with ispresizer_try_size() previously.
+ **/
+int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
+					u32 output_h)
+{
+	int i, j;
+	u32 res;
+	DPRINTK_ISPRESZ("ispresizer_config_size()+, input_w = %d,input_h ="
+						" %d, output_w = %d, output_h"
+						" = %d,hresz = %d,vresz = %d,"
+						" hcrop = %d, vcrop = %d,"
+						" hstph = %d, vstph = %d\n",
+						ispres_obj.inputwidth,
+						ispres_obj.inputheight,
+						ispres_obj.outputwidth,
+						ispres_obj.outputheight,
+						ispres_obj.h_resz,
+						ispres_obj.v_resz,
+						ispres_obj.ipwd_crop,
+						ispres_obj.ipht_crop,
+						ispres_obj.h_startphase,
+						ispres_obj.v_startphase);
+	if ((output_w != ispres_obj.outputwidth)
+				|| (output_h != ispres_obj.outputheight)) {
+		printk(KERN_ERR "Output parameters passed do not match the"
+						" values calculated by the"
+						" trysize passed w %d, h %d"
+						" \n", output_w , output_h);
+		return -EINVAL;
+	}
+
+	/* Set Resizer input address and offset adderss */
+	ispresizer_config_inlineoffset(isp_reg_readl(OMAP3_ISP_IOMEM_PREV,
+							ISPPRV_WADD_OFFSET));
+
+	res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
+			~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
+	isp_reg_writel(res |
+			(ispres_obj.h_startphase << ISPRSZ_CNT_HSTPH_SHIFT) |
+			(ispres_obj.v_startphase << ISPRSZ_CNT_VSTPH_SHIFT),
+			OMAP3_ISP_IOMEM_RESZ,
+			ISPRSZ_CNT);
+	/* Set start address for cropping */
+	isp_reg_writel(ispres_obj.tmp_buf + 2 * (ispres_obj.ipht_crop * ispres_obj.inputwidth +
+						(ispres_obj.ipwd_crop & ~15)),
+						OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
+
+	isp_reg_writel(((ispres_obj.ipwd_crop & 15) << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
+			(0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
+			OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
+
+	isp_reg_writel((0x00 << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
+					(0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
+					OMAP3_ISP_IOMEM_RESZ,
+					ISPRSZ_IN_START);
+
+	isp_reg_writel((ispres_obj.inputwidth << ISPRSZ_IN_SIZE_HORZ_SHIFT) |
+						(ispres_obj.inputheight <<
+						ISPRSZ_IN_SIZE_VERT_SHIFT),
+						OMAP3_ISP_IOMEM_RESZ,
+						ISPRSZ_IN_SIZE);
+	if (!ispres_obj.algo) {
+		isp_reg_writel((output_w << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
+				(output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
+				OMAP3_ISP_IOMEM_RESZ,
+				ISPRSZ_OUT_SIZE);
+	} else {
+		isp_reg_writel(((output_w - 4) << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
+				(output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
+				OMAP3_ISP_IOMEM_RESZ,
+				ISPRSZ_OUT_SIZE);
+	}
+
+	res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
+			~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
+	isp_reg_writel(res |
+			((ispres_obj.h_resz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) |
+			((ispres_obj.v_resz - 1) << ISPRSZ_CNT_VRSZ_SHIFT),
+			OMAP3_ISP_IOMEM_RESZ,
+			ISPRSZ_CNT);
+	if (ispres_obj.h_resz <= MID_RESIZE_VALUE) {
+		j = 0;
+		for (i = 0; i < 16; i++) {
+			isp_reg_writel(
+			    (ispres_obj.coeflist.h_filter_coef_4tap[j] <<
+				ISPRSZ_HFILT10_COEF0_SHIFT) |
+			    (ispres_obj.coeflist.h_filter_coef_4tap[j + 1] <<
+				ISPRSZ_HFILT10_COEF1_SHIFT),
+			    OMAP3_ISP_IOMEM_RESZ,
+			    ISPRSZ_HFILT10 + (i * 0x04));
+			j += 2;
+		}
+	} else {
+		j = 0;
+		for (i = 0; i < 16; i++) {
+			if ((i + 1) % 4 == 0) {
+				isp_reg_writel((ispres_obj.coeflist.
+						h_filter_coef_7tap[j] <<
+						ISPRSZ_HFILT10_COEF0_SHIFT),
+						OMAP3_ISP_IOMEM_RESZ,
+						ISPRSZ_HFILT10 + (i * 0x04));
+				j += 1;
+			} else {
+				isp_reg_writel((ispres_obj.coeflist.
+						h_filter_coef_7tap[j] <<
+						ISPRSZ_HFILT10_COEF0_SHIFT) |
+						(ispres_obj.coeflist.
+						h_filter_coef_7tap[j+1] <<
+						ISPRSZ_HFILT10_COEF1_SHIFT),
+						OMAP3_ISP_IOMEM_RESZ,
+						ISPRSZ_HFILT10 + (i * 0x04));
+				j += 2;
+			}
+		}
+	}
+	if (ispres_obj.v_resz <= MID_RESIZE_VALUE) {
+		j = 0;
+		for (i = 0; i < 16; i++) {
+			isp_reg_writel((ispres_obj.coeflist.
+						v_filter_coef_4tap[j] <<
+						ISPRSZ_VFILT10_COEF0_SHIFT) |
+						(ispres_obj.coeflist.
+						v_filter_coef_4tap[j + 1] <<
+						ISPRSZ_VFILT10_COEF1_SHIFT),
+						OMAP3_ISP_IOMEM_RESZ,
+						ISPRSZ_VFILT10 + (i * 0x04));
+			j += 2;
+		}
+	} else {
+		j = 0;
+		for (i = 0; i < 16; i++) {
+			if ((i + 1) % 4 == 0) {
+				isp_reg_writel((ispres_obj.coeflist.
+						v_filter_coef_7tap[j] <<
+						ISPRSZ_VFILT10_COEF0_SHIFT),
+						OMAP3_ISP_IOMEM_RESZ,
+						ISPRSZ_VFILT10 + (i * 0x04));
+				j += 1;
+			} else {
+				isp_reg_writel((ispres_obj.coeflist.
+						v_filter_coef_7tap[j] <<
+						ISPRSZ_VFILT10_COEF0_SHIFT) |
+						(ispres_obj.coeflist.
+						v_filter_coef_7tap[j+1] <<
+						ISPRSZ_VFILT10_COEF1_SHIFT),
+						OMAP3_ISP_IOMEM_RESZ,
+						ISPRSZ_VFILT10 + (i * 0x04));
+				j += 2;
+			}
+		}
+	}
+
+	ispresizer_config_outlineoffset(output_w*2);
+	DPRINTK_ISPRESZ("ispresizer_config_size()-\n");
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_config_size);
+
+/**
+ * ispresizer_enable - Enables the resizer module.
+ * @enable: 1 - Enable, 0 - Disable
+ *
+ * Client should configure all the sub modules in resizer before this.
+ **/
+void ispresizer_enable(u8 enable)
+{
+	int val;
+	DPRINTK_ISPRESZ("+ispresizer_enable()+\n");
+	if (enable) {
+		val = (isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & 0x2) |
+							ISPRSZ_PCR_ENABLE;
+	} else {
+		val = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
+							~ISPRSZ_PCR_ENABLE;
+	}
+	isp_reg_writel(val, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR);
+	DPRINTK_ISPRESZ("+ispresizer_enable()-\n");
+}
+EXPORT_SYMBOL(ispresizer_enable);
+
+/**
+ * ispresizer_busy - Checks if ISP resizer is busy.
+ *
+ * Returns busy field from ISPRSZ_PCR register.
+ **/
+int ispresizer_busy(void)
+{
+	return isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
+							ISPPRV_PCR_BUSY;
+}
+EXPORT_SYMBOL(ispresizer_busy);
+
+/**
+ * ispresizer_config_startphase - Sets the horizontal and vertical start phase.
+ * @hstartphase: horizontal start phase (0 - 7).
+ * @vstartphase: vertical startphase (0 - 7).
+ *
+ * This API just updates the isp_res struct. Actual register write happens in
+ * ispresizer_config_size.
+ **/
+void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase)
+{
+	DPRINTK_ISPRESZ("ispresizer_config_startphase()+\n");
+	ispres_obj.h_startphase = hstartphase;
+	ispres_obj.v_startphase = vstartphase;
+	DPRINTK_ISPRESZ("ispresizer_config_startphase()-\n");
+}
+EXPORT_SYMBOL(ispresizer_config_startphase);
+
+/**
+ * ispresizer_config_ycpos - Specifies if output should be in YC or CY format.
+ * @yc: 0 - YC format, 1 - CY format
+ **/
+void ispresizer_config_ycpos(u8 yc)
+{
+	DPRINTK_ISPRESZ("ispresizer_config_ycpos()+\n");
+	isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_YCPOS,
+					(yc ? ISPRSZ_CNT_YCPOS : 0));
+	DPRINTK_ISPRESZ("ispresizer_config_ycpos()-\n");
+}
+EXPORT_SYMBOL(ispresizer_config_ycpos);
+
+/**
+ * Sets the chrominance algorithm
+ * @cbilin: 0 - chrominance uses same processing as luminance,
+ *          1 - bilinear interpolation processing
+ **/
+void ispresizer_enable_cbilin(u8 enable)
+{
+	DPRINTK_ISPRESZ("ispresizer_enable_cbilin()+\n");
+	isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_CBILIN,
+					(enable ? ISPRSZ_CNT_CBILIN : 0));
+	DPRINTK_ISPRESZ("ispresizer_enable_cbilin()-\n");
+}
+EXPORT_SYMBOL(ispresizer_enable_cbilin);
+
+/**
+ * ispresizer_config_luma_enhance - Configures luminance enhancer parameters.
+ * @yenh: Pointer to structure containing desired values for core, slope, gain
+ *        and algo parameters.
+ **/
+void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh)
+{
+	DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()+\n");
+	ispres_obj.algo = yenh->algo;
+	isp_reg_writel((yenh->algo << ISPRSZ_YENH_ALGO_SHIFT) |
+				(yenh->gain << ISPRSZ_YENH_GAIN_SHIFT) |
+				(yenh->slope << ISPRSZ_YENH_SLOP_SHIFT) |
+				(yenh->coreoffset << ISPRSZ_YENH_CORE_SHIFT),
+				OMAP3_ISP_IOMEM_RESZ,
+				ISPRSZ_YENH);
+	DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()-\n");
+}
+EXPORT_SYMBOL(ispresizer_config_luma_enhance);
+
+/**
+ * ispresizer_config_filter_coef - Sets filter coefficients for 4 & 7-tap mode.
+ * This API just updates the isp_res struct.Actual register write happens in
+ * ispresizer_config_size.
+ * @coef: Structure containing horizontal and vertical filter coefficients for
+ *        both 4-tap and 7-tap mode.
+ **/
+void ispresizer_config_filter_coef(struct isprsz_coef *coef)
+{
+	int i;
+	DPRINTK_ISPRESZ("ispresizer_config_filter_coef()+\n");
+	for (i = 0; i < 32; i++) {
+		ispres_obj.coeflist.h_filter_coef_4tap[i] =
+						coef->h_filter_coef_4tap[i];
+		ispres_obj.coeflist.v_filter_coef_4tap[i] =
+						coef->v_filter_coef_4tap[i];
+	}
+	for (i = 0; i < 28; i++) {
+		ispres_obj.coeflist.h_filter_coef_7tap[i] =
+						coef->h_filter_coef_7tap[i];
+		ispres_obj.coeflist.v_filter_coef_7tap[i] =
+						coef->v_filter_coef_7tap[i];
+	}
+	DPRINTK_ISPRESZ("ispresizer_config_filter_coef()-\n");
+}
+EXPORT_SYMBOL(ispresizer_config_filter_coef);
+
+/**
+ * ispresizer_config_inlineoffset - Configures the read address line offset.
+ * @offset: Line Offset for the input image.
+ *
+ * Returns 0 if successful, or -EINVAL if offset is not 32 bits aligned.
+ **/
+int ispresizer_config_inlineoffset(u32 offset)
+{
+	DPRINTK_ISPRESZ("ispresizer_config_inlineoffset()+\n");
+	if (offset % 32)
+		return -EINVAL;
+	isp_reg_writel(offset << ISPRSZ_SDR_INOFF_OFFSET_SHIFT,
+				OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF);
+	DPRINTK_ISPRESZ("ispresizer_config_inlineoffset()-\n");
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_config_inlineoffset);
+
+/**
+ * ispresizer_set_inaddr - Sets the memory address of the input frame.
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ *
+ * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
+ **/
+int ispresizer_set_inaddr(u32 addr)
+{
+	DPRINTK_ISPRESZ("ispresizer_set_inaddr()+\n");
+	if (addr % 32)
+		return -EINVAL;
+	isp_reg_writel(addr << ISPRSZ_SDR_INADD_ADDR_SHIFT,
+				OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
+	ispres_obj.tmp_buf = addr;
+	DPRINTK_ISPRESZ("ispresizer_set_inaddr()-\n");
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_set_inaddr);
+
+/**
+ * ispresizer_config_outlineoffset - Configures the write address line offset.
+ * @offset: Line offset for the preview output.
+ *
+ * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
+ **/
+int ispresizer_config_outlineoffset(u32 offset)
+{
+	DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()+\n");
+	if (offset % 32)
+		return -EINVAL;
+	isp_reg_writel(offset << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT,
+				OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF);
+	DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()-\n");
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_config_outlineoffset);
+
+/**
+ * Configures the memory address to which the output frame is written.
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ **/
+int ispresizer_set_outaddr(u32 addr)
+{
+	DPRINTK_ISPRESZ("ispresizer_set_outaddr()+\n");
+	if (addr % 32)
+		return -EINVAL;
+	isp_reg_writel(addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT,
+				OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD);
+	DPRINTK_ISPRESZ("ispresizer_set_outaddr()-\n");
+	return 0;
+}
+EXPORT_SYMBOL(ispresizer_set_outaddr);
+
+/**
+ * ispresizer_save_context - Saves the values of the resizer module registers.
+ **/
+void ispresizer_save_context(void)
+{
+	DPRINTK_ISPRESZ("Saving context\n");
+	isp_save_context(isprsz_reg_list);
+}
+EXPORT_SYMBOL(ispresizer_save_context);
+
+/**
+ * ispresizer_restore_context - Restores resizer module register values.
+ **/
+void ispresizer_restore_context(void)
+{
+	DPRINTK_ISPRESZ("Restoring context\n");
+	isp_restore_context(isprsz_reg_list);
+}
+EXPORT_SYMBOL(ispresizer_restore_context);
+
+/**
+ * ispresizer_print_status - Prints the values of the resizer module registers.
+ **/
+void ispresizer_print_status()
+{
+	if (!is_ispresz_debug_enabled())
+		return;
+	DPRINTK_ISPRESZ("###ISP_CTRL inresizer =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
+	DPRINTK_ISPRESZ("###ISP_IRQ0ENABLE in resizer =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
+	DPRINTK_ISPRESZ("###ISP_IRQ0STATUS in resizer =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
+	DPRINTK_ISPRESZ("###RSZ PCR =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR));
+	DPRINTK_ISPRESZ("###RSZ CNT =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT));
+	DPRINTK_ISPRESZ("###RSZ OUT SIZE =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE));
+	DPRINTK_ISPRESZ("###RSZ IN START =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START));
+	DPRINTK_ISPRESZ("###RSZ IN SIZE =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE));
+	DPRINTK_ISPRESZ("###RSZ SDR INADD =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD));
+	DPRINTK_ISPRESZ("###RSZ SDR INOFF =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF));
+	DPRINTK_ISPRESZ("###RSZ SDR OUTADD =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD));
+	DPRINTK_ISPRESZ("###RSZ SDR OTOFF =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF));
+	DPRINTK_ISPRESZ("###RSZ YENH =0x%x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH));
+}
+EXPORT_SYMBOL(ispresizer_print_status);
+
+/**
+ * isp_resizer_init - Module Initialisation.
+ *
+ * Always returns 0.
+ **/
+int __init isp_resizer_init(void)
+{
+	mutex_init(&ispres_obj.ispres_mutex);
+	return 0;
+}
+
+/**
+ * isp_resizer_cleanup - Module Cleanup.
+ **/
+void isp_resizer_cleanup(void)
+{
+}
diff --git a/drivers/media/video/isp/ispresizer.h b/drivers/media/video/isp/ispresizer.h
new file mode 100644
index 0000000..b778aa2
--- /dev/null
+++ b/drivers/media/video/isp/ispresizer.h
@@ -0,0 +1,154 @@
+/*
+ * ispresizer.h
+ *
+ * Driver header file for Resizer module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ * 	Sameer Venkatraman <sameerv@ti.com>
+ * 	Mohit Jalori
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *
+ * 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_RESIZER_H
+#define OMAP_ISP_RESIZER_H
+
+/*
+ * Resizer Constants
+ */
+#define MAX_IN_WIDTH_MEMORY_MODE	4095
+
+#define MAX_IN_WIDTH_ONTHEFLY_MODE	1280
+#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2	4095
+#define MAX_IN_HEIGHT			4095
+#define MINIMUM_RESIZE_VALUE		64
+#define MAXIMUM_RESIZE_VALUE		1024
+#define MID_RESIZE_VALUE		512
+
+#define MAX_7TAP_HRSZ_OUTWIDTH		1280
+#define MAX_7TAP_VRSZ_OUTWIDTH		640
+
+#define MAX_7TAP_HRSZ_OUTWIDTH_ES2	3300
+#define MAX_7TAP_VRSZ_OUTWIDTH_ES2	1650
+
+#define DEFAULTSTPIXEL			0
+#define DEFAULTSTPHASE			1
+#define DEFAULTHSTPIXEL4TAPMODE		3
+#define FOURPHASE			4
+#define EIGHTPHASE			8
+#define RESIZECONSTANT			256
+#define SHIFTER4TAPMODE			0
+#define SHIFTER7TAPMODE			1
+#define DEFAULTOFFSET			7
+#define OFFSETVERT4TAPMODE		4
+#define OPWDALIGNCONSTANT		0xFFFFFFF0
+
+/*
+ * The client is supposed to call resizer API in the following sequence:
+ * 	- request()
+ * 	- config_datatpath()
+ * 	- optionally config/enable sub modules
+ * 	- try/config size
+ * 	- setup callback
+ * 	- setup in/out memory offsets and ptrs
+ * 	- enable()
+ * 	...
+ * 	- disable()
+ * 	- free()
+ */
+
+enum ispresizer_input {
+	RSZ_OTFLY_YUV,
+	RSZ_MEM_YUV,
+	RSZ_MEM_COL8
+};
+
+/**
+ * struct isprsz_coef - Structure for resizer filter coeffcients.
+ * @h_filter_coef_4tap: Horizontal filter coefficients for 8-phase/4-tap
+ *			mode (.5x-4x)
+ * @v_filter_coef_4tap: Vertical filter coefficients for 8-phase/4-tap
+ *			mode (.5x-4x)
+ * @h_filter_coef_7tap: Horizontal filter coefficients for 4-phase/7-tap
+ *			mode (.25x-.5x)
+ * @v_filter_coef_7tap: Vertical filter coefficients for 4-phase/7-tap
+ *			mode (.25x-.5x)
+ */
+struct isprsz_coef {
+	u16 h_filter_coef_4tap[32];
+	u16 v_filter_coef_4tap[32];
+	u16 h_filter_coef_7tap[28];
+	u16 v_filter_coef_7tap[28];
+};
+
+/**
+ * struct isprsz_yenh - Structure for resizer luminance enhancer parameters.
+ * @algo: Algorithm select.
+ * @gain: Maximum gain.
+ * @slope: Slope.
+ * @coreoffset: Coring offset.
+ */
+struct isprsz_yenh {
+	u8 algo;
+	u8 gain;
+	u8 slope;
+	u8 coreoffset;
+};
+
+void ispresizer_config_shadow_registers(void);
+
+int ispresizer_request(void);
+
+int ispresizer_free(void);
+
+int ispresizer_config_datapath(enum ispresizer_input input);
+
+void ispresizer_enable_cbilin(u8 enable);
+
+void ispresizer_config_ycpos(u8 yc);
+
+void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase);
+
+void ispresizer_config_filter_coef(struct isprsz_coef *coef);
+
+void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh);
+
+int ispresizer_try_size(u32 *input_w, u32 *input_h, u32 *output_w,
+								u32 *output_h);
+
+void ispresizer_applycrop(void);
+
+void ispresizer_trycrop(u32 left, u32 top, u32 width, u32 height, u32 ow,
+								u32 oh);
+
+int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
+					u32 output_h);
+
+int ispresizer_config_inlineoffset(u32 offset);
+
+int ispresizer_set_inaddr(u32 addr);
+
+int ispresizer_config_outlineoffset(u32 offset);
+
+int ispresizer_set_outaddr(u32 addr);
+
+void ispresizer_enable(u8 enable);
+
+int ispresizer_busy(void);
+
+void ispresizer_save_context(void);
+
+void ispresizer_restore_context(void);
+
+void ispresizer_print_status(void);
+
+#endif		/* OMAP_ISP_RESIZER_H */
-- 
1.5.6.5


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

* [PATCH 6/9] omap3isp: Add statistics collection modules (H3A and HIST)
  2009-03-03 10:06         ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Sakari Ailus
@ 2009-03-03 10:06           ` Sakari Ailus
  2009-03-03 10:06             ` [PATCH 7/9] omap3isp: Add CSI2 interface support Sakari Ailus
  2009-03-03 12:23           ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Alexey Klimov
  1 sibling, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/isp/isp_af.c  |  758 +++++++++++++++++++++++++++++++
 drivers/media/video/isp/isp_af.h  |  123 +++++
 drivers/media/video/isp/isph3a.c  |  902 +++++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/isph3a.h  |  123 +++++
 drivers/media/video/isp/isphist.c |  584 ++++++++++++++++++++++++
 drivers/media/video/isp/isphist.h |  101 ++++
 6 files changed, 2591 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/isp_af.c
 create mode 100644 drivers/media/video/isp/isp_af.h
 create mode 100644 drivers/media/video/isp/isph3a.c
 create mode 100644 drivers/media/video/isp/isph3a.h
 create mode 100644 drivers/media/video/isp/isphist.c
 create mode 100644 drivers/media/video/isp/isphist.h

diff --git a/drivers/media/video/isp/isp_af.c b/drivers/media/video/isp/isp_af.c
new file mode 100644
index 0000000..2e39d1f
--- /dev/null
+++ b/drivers/media/video/isp/isp_af.c
@@ -0,0 +1,758 @@
+/*
+ * isp_af.c
+ *
+ * AF module for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Troy Laramy
+ *
+ * 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.
+ */
+
+/* Linux specific include files */
+#include <asm/cacheflush.h>
+
+#include <linux/uaccess.h>
+#include <linux/dma-mapping.h>
+#include <asm/atomic.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "isph3a.h"
+#include "isp_af.h"
+#include "ispmmu.h"
+
+/**
+ * struct isp_af_buffer - AF frame stats buffer.
+ * @virt_addr: Virtual address to mmap the buffer.
+ * @phy_addr: Physical address of the buffer.
+ * @addr_align: Virtual Address 32 bytes aligned.
+ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
+ * @mmap_addr: Mapped memory area of buffer. For userspace access.
+ * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
+ * @frame_num: Frame number from which the statistics are taken.
+ * @lens_position: Lens position currently set in the DW9710 Coil motor driver.
+ * @next: Pointer to link next buffer.
+ */
+struct isp_af_buffer {
+	unsigned long virt_addr;
+	unsigned long phy_addr;
+	unsigned long addr_align;
+	unsigned long ispmmu_addr;
+	unsigned long mmap_addr;
+
+	u8 locked;
+	u16 frame_num;
+	u32 config_counter;
+	struct isp_af_xtrastats xtrastats;
+	struct isp_af_buffer *next;
+};
+
+/**
+ * struct isp_af_status - AF status.
+ * @initialized: 1 - Buffers initialized.
+ * @update: 1 - Update registers.
+ * @stats_req: 1 - Future stats requested.
+ * @stats_done: 1 - Stats ready for user.
+ * @frame_req: Number of frame requested for statistics.
+ * @af_buff: Array of statistics buffers to access.
+ * @stats_buf_size: Statistics buffer size.
+ * @curr_cfg_buf_size: Current user configured stats buff size.
+ * @min_buf_size: Minimum statisitics buffer size.
+ * @frame_count: Frame Count.
+ * @stats_wait: Wait primitive for locking/unlocking the stats request.
+ * @buffer_lock: Spinlock for statistics buffers access.
+ */
+static struct isp_af_status {
+	u8 initialized;
+	u8 update;
+	u8 stats_req;
+	u8 stats_done;
+	u16 frame_req;
+
+	struct isp_af_buffer af_buff[H3A_MAX_BUFF];
+	unsigned int stats_buf_size;
+	unsigned int min_buf_size;
+	unsigned int curr_cfg_buf_size;
+
+	u32 frame_count;
+	wait_queue_head_t stats_wait;
+	atomic_t config_counter;
+	spinlock_t buffer_lock;		/* For stats buffers read/write sync */
+} afstat;
+
+struct af_device *af_dev_configptr;
+static struct isp_af_buffer *active_buff;
+static int af_major = -1;
+static int camnotify;
+
+/**
+ * isp_af_setxtrastats - Receives extra statistics from prior frames.
+ * @xtrastats: Pointer to structure containing extra statistics fields like
+ *             field count and timestamp of frame.
+ *
+ * Called from update_vbq in camera driver
+ **/
+void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag)
+{
+	int i, past_i;
+
+	if (active_buff == NULL)
+		return;
+
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		if (afstat.af_buff[i].frame_num == active_buff->frame_num)
+			break;
+	}
+
+	if (i == H3A_MAX_BUFF)
+		return;
+
+	if (i == 0) {
+		if (afstat.af_buff[H3A_MAX_BUFF - 1].locked == 0)
+			past_i = H3A_MAX_BUFF - 1;
+		else
+			past_i = H3A_MAX_BUFF - 2;
+	} else if (i == 1) {
+		if (afstat.af_buff[0].locked == 0)
+			past_i = 0;
+		else
+			past_i = H3A_MAX_BUFF - 1;
+	} else {
+		if (afstat.af_buff[i - 1].locked == 0)
+			past_i = i - 1;
+		else
+			past_i = i - 2;
+	}
+
+	if (updateflag & AF_UPDATEXS_TS)
+		afstat.af_buff[past_i].xtrastats.ts = xtrastats->ts;
+
+	if (updateflag & AF_UPDATEXS_FIELDCOUNT)
+		afstat.af_buff[past_i].xtrastats.field_count =
+							xtrastats->field_count;
+}
+EXPORT_SYMBOL(isp_af_setxtrastats);
+
+/*
+ * Helper function to update buffer cache pages
+ */
+static void isp_af_update_req_buffer(struct isp_af_buffer *buffer)
+{
+	int size = afstat.stats_buf_size;
+
+	size = PAGE_ALIGN(size);
+	/* Update the kernel pages of the requested buffer */
+	dmac_inv_range((void *)buffer->addr_align, (void *)buffer->addr_align +
+									size);
+}
+
+#define IS_OUT_OF_BOUNDS(value, min, max) \
+	(((value) < (min)) || ((value) > (max)))
+
+/* Function to check paxel parameters */
+int isp_af_check_paxel(void)
+{
+	struct af_paxel *paxel_cfg = &af_dev_configptr->config->paxel_config;
+	struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
+
+	/* Check horizontal Count */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->hz_cnt, AF_PAXEL_HORIZONTAL_COUNT_MIN,
+					AF_PAXEL_HORIZONTAL_COUNT_MAX)) {
+		DPRINTK_ISP_AF("Error : Horizontal Count is incorrect");
+		return -AF_ERR_HZ_COUNT;
+	}
+
+	/*Check Vertical Count */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_cnt, AF_PAXEL_VERTICAL_COUNT_MIN,
+					AF_PAXEL_VERTICAL_COUNT_MAX)) {
+		DPRINTK_ISP_AF("Error : Vertical Count is incorrect");
+		return -AF_ERR_VT_COUNT;
+	}
+
+	/*Check Height */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->height, AF_PAXEL_HEIGHT_MIN,
+					AF_PAXEL_HEIGHT_MAX)) {
+		DPRINTK_ISP_AF("Error : Height is incorrect");
+		return -AF_ERR_HEIGHT;
+	}
+
+	/*Check width */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->width, AF_PAXEL_WIDTH_MIN,
+					AF_PAXEL_WIDTH_MAX)) {
+		DPRINTK_ISP_AF("Error : Width is incorrect");
+		return -AF_ERR_WIDTH;
+	}
+
+	/*Check Line Increment */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->line_incr, AF_PAXEL_INCREMENT_MIN,
+					AF_PAXEL_INCREMENT_MAX)) {
+		DPRINTK_ISP_AF("Error : Line Increment is incorrect");
+		return -AF_ERR_INCR;
+	}
+
+	/*Check Horizontal Start */
+	if ((paxel_cfg->hz_start % 2 != 0) ||
+			(paxel_cfg->hz_start < (iir_cfg->hz_start_pos + 2)) ||
+			IS_OUT_OF_BOUNDS(paxel_cfg->hz_start,
+			AF_PAXEL_HZSTART_MIN, AF_PAXEL_HZSTART_MAX)) {
+		DPRINTK_ISP_AF("Error : Horizontal Start is incorrect");
+		return -AF_ERR_HZ_START;
+	}
+
+	/*Check Vertical Start */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_start, AF_PAXEL_VTSTART_MIN,
+					AF_PAXEL_VTSTART_MAX)) {
+		DPRINTK_ISP_AF("Error : Vertical Start is incorrect");
+		return -AF_ERR_VT_START;
+	}
+	return 0;
+}
+
+/**
+ * isp_af_check_iir - Function to check IIR Coefficient.
+ **/
+int isp_af_check_iir(void)
+{
+	struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
+	int index;
+
+	for (index = 0; index < AF_NUMBER_OF_COEF; index++) {
+		if ((iir_cfg->coeff_set0[index]) > AF_COEF_MAX) {
+			DPRINTK_ISP_AF("Error : Coefficient for set 0 is "
+								"incorrect");
+			return -AF_ERR_IIR_COEF;
+		}
+
+		if ((iir_cfg->coeff_set1[index]) > AF_COEF_MAX) {
+			DPRINTK_ISP_AF("Error : Coefficient for set 1 is "
+								"incorrect");
+			return -AF_ERR_IIR_COEF;
+		}
+	}
+
+	if (IS_OUT_OF_BOUNDS(iir_cfg->hz_start_pos, AF_IIRSH_MIN,
+								AF_IIRSH_MAX)) {
+		DPRINTK_ISP_AF("Error : IIRSH is incorrect");
+		return -AF_ERR_IIRSH;
+	}
+
+	return 0;
+}
+/**
+ * isp_af_unlock_buffers - Helper function to unlock all buffers.
+ **/
+static void isp_af_unlock_buffers(void)
+{
+	int i;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&afstat.buffer_lock, irqflags);
+	for (i = 0; i < H3A_MAX_BUFF; i++)
+		afstat.af_buff[i].locked = 0;
+
+	spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
+}
+
+/*
+ * Helper function to link allocated buffers
+ */
+static void isp_af_link_buffers(void)
+{
+	int i;
+
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		if ((i + 1) < H3A_MAX_BUFF)
+			afstat.af_buff[i].next = &afstat.af_buff[i + 1];
+		else
+			afstat.af_buff[i].next = &afstat.af_buff[0];
+	}
+}
+
+/* Function to perform hardware set up */
+int isp_af_configure(struct af_configuration *afconfig)
+{
+	int result;
+	int buff_size, i;
+	unsigned int busyaf;
+	struct af_configuration *af_curr_cfg = af_dev_configptr->config;
+
+	if (NULL == afconfig) {
+		printk(KERN_ERR "Null argument in configuration. \n");
+		return -EINVAL;
+	}
+
+	memcpy(af_curr_cfg, afconfig, sizeof(struct af_configuration));
+	/* Get the value of PCR register */
+	busyaf = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
+
+	if ((busyaf & AF_BUSYAF) == AF_BUSYAF) {
+		DPRINTK_ISP_AF("AF_register_setup_ERROR : Engine Busy");
+		DPRINTK_ISP_AF("\n Configuration cannot be done ");
+		return -AF_ERR_ENGINE_BUSY;
+	}
+
+	/* Check IIR Coefficient and start Values */
+	result = isp_af_check_iir();
+	if (result < 0)
+		return result;
+
+	/* Check Paxel Values */
+	result = isp_af_check_paxel();
+	if (result < 0)
+		return result;
+
+	/* Check HMF Threshold Values */
+	if (af_curr_cfg->hmf_config.threshold > AF_THRESHOLD_MAX) {
+		DPRINTK_ISP_AF("Error : HMF Threshold is incorrect");
+		return -AF_ERR_THRESHOLD;
+	}
+
+	/* Compute buffer size */
+	buff_size = (af_curr_cfg->paxel_config.hz_cnt + 1) *
+			(af_curr_cfg->paxel_config.vt_cnt + 1) * AF_PAXEL_SIZE;
+
+	afstat.curr_cfg_buf_size = buff_size;
+	/* Deallocate the previous buffers */
+	if (afstat.stats_buf_size && (buff_size	> afstat.stats_buf_size)) {
+		isp_af_enable(0);
+		for (i = 0; i < H3A_MAX_BUFF; i++) {
+			ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
+			dma_free_coherent(NULL, afstat.min_buf_size,
+					(void *)afstat.af_buff[i].virt_addr,
+					(dma_addr_t)afstat.af_buff[i].phy_addr);
+			afstat.af_buff[i].virt_addr = 0;
+		}
+		afstat.stats_buf_size = 0;
+	}
+
+	if (!afstat.af_buff[0].virt_addr) {
+		afstat.stats_buf_size = buff_size;
+		afstat.min_buf_size = PAGE_ALIGN(afstat.stats_buf_size);
+
+		for (i = 0; i < H3A_MAX_BUFF; i++) {
+			afstat.af_buff[i].virt_addr =
+					(unsigned long)dma_alloc_coherent(NULL,
+					afstat.min_buf_size,
+					(dma_addr_t *)
+					&afstat.af_buff[i].phy_addr,
+					GFP_KERNEL | GFP_DMA);
+			if (afstat.af_buff[i].virt_addr == 0) {
+				printk(KERN_ERR "Can't acquire memory for "
+							"buffer[%d]\n", i);
+				return -ENOMEM;
+			}
+			afstat.af_buff[i].addr_align =
+						afstat.af_buff[i].virt_addr;
+			while ((afstat.af_buff[i].addr_align & 0xFFFFFFC0) !=
+						afstat.af_buff[i].addr_align)
+				afstat.af_buff[i].addr_align++;
+			afstat.af_buff[i].ispmmu_addr =
+				ispmmu_kmap(afstat.af_buff[i].phy_addr,
+							afstat.min_buf_size);
+		}
+		isp_af_unlock_buffers();
+		isp_af_link_buffers();
+
+		/* First active buffer */
+		if (active_buff == NULL)
+			active_buff = &afstat.af_buff[0];
+		isp_af_set_address(active_buff->ispmmu_addr);
+	}
+
+	result = isp_af_register_setup(af_dev_configptr);
+	if (result < 0)
+		return result;
+	af_dev_configptr->size_paxel = buff_size;
+	atomic_inc(&afstat.config_counter);
+	afstat.initialized = 1;
+	afstat.frame_count = 1;
+	active_buff->frame_num = 1;
+	/* Set configuration flag to indicate HW setup done */
+	if (af_curr_cfg->af_config)
+		isp_af_enable(1);
+	else
+		isp_af_enable(0);
+
+	/* Success */
+	return 0;
+}
+EXPORT_SYMBOL(isp_af_configure);
+
+int isp_af_register_setup(struct af_device *af_dev)
+{
+	unsigned int pcr = 0, pax1 = 0, pax2 = 0, paxstart = 0;
+	unsigned int coef = 0;
+	unsigned int base_coef_set0 = 0;
+	unsigned int base_coef_set1 = 0;
+	int index;
+
+	/* Configure Hardware Registers */
+	/* Read PCR Register */
+	pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
+
+	/* Set Accumulator Mode */
+	if (af_dev->config->mode == ACCUMULATOR_PEAK)
+		pcr |= FVMODE;
+	else
+		pcr &= ~FVMODE;
+
+	/* Set A-law */
+	if (af_dev->config->alaw_enable == H3A_AF_ALAW_ENABLE)
+		pcr |= AF_ALAW_EN;
+	else
+		pcr &= ~AF_ALAW_EN;
+
+	/* Set RGB Position */
+	pcr &= ~RGBPOS;
+	pcr |= (af_dev->config->rgb_pos) << AF_RGBPOS_SHIFT;
+
+	/* HMF Configurations */
+	if (af_dev->config->hmf_config.enable == H3A_AF_HMF_ENABLE) {
+		pcr &= ~AF_MED_EN;
+		/* Enable HMF */
+		pcr |= AF_MED_EN;
+
+		/* Set Median Threshold */
+		pcr &= ~MED_TH;
+		pcr |= (af_dev->config->hmf_config.threshold) <<
+							AF_MED_TH_SHIFT;
+	} else
+		pcr &= ~AF_MED_EN;
+
+	/* Set PCR Register */
+	isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
+
+	pax1 &= ~PAXW;
+	pax1 |= (af_dev->config->paxel_config.width) << AF_PAXW_SHIFT;
+
+	/* Set height in AFPAX1 */
+	pax1 &= ~PAXH;
+	pax1 |= af_dev->config->paxel_config.height;
+
+	isp_reg_writel(pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
+
+	/* Configure AFPAX2 Register */
+	/* Set Line Increment in AFPAX2 Register */
+	pax2 &= ~AFINCV;
+	pax2 |= (af_dev->config->paxel_config.line_incr) << AF_LINE_INCR_SHIFT;
+	/* Set Vertical Count */
+	pax2 &= ~PAXVC;
+	pax2 |= (af_dev->config->paxel_config.vt_cnt) << AF_VT_COUNT_SHIFT;
+	/* Set Horizontal Count */
+	pax2 &= ~PAXHC;
+	pax2 |= af_dev->config->paxel_config.hz_cnt;
+	isp_reg_writel(pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
+
+	/* Configure PAXSTART Register */
+	/*Configure Horizontal Start */
+	paxstart &= ~PAXSH;
+	paxstart |= (af_dev->config->paxel_config.hz_start) <<
+							AF_HZ_START_SHIFT;
+	/* Configure Vertical Start */
+	paxstart &= ~PAXSV;
+	paxstart |= af_dev->config->paxel_config.vt_start;
+	isp_reg_writel(paxstart, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART);
+
+	/*SetIIRSH Register */
+	isp_reg_writel(af_dev->config->iir_config.hz_start_pos,
+					OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
+
+	/*Set IIR Filter0 Coefficients */
+	base_coef_set0 = ISPH3A_AFCOEF010;
+	for (index = 0; index <= 8; index += 2) {
+		coef &= ~COEF_MASK0;
+		coef |= af_dev->config->iir_config.coeff_set0[index];
+		coef &= ~COEF_MASK1;
+		coef |= (af_dev->config->iir_config.coeff_set0[index + 1]) <<
+								AF_COEF_SHIFT;
+		isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set0);
+		base_coef_set0 = base_coef_set0 + AFCOEF_OFFSET;
+	}
+
+	/* set AFCOEF0010 Register */
+	isp_reg_writel(af_dev->config->iir_config.coeff_set0[10],
+				OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010);
+
+	/*Set IIR Filter1 Coefficients */
+
+	base_coef_set1 = ISPH3A_AFCOEF110;
+	for (index = 0; index <= 8; index += 2) {
+		coef &= ~COEF_MASK0;
+		coef |= af_dev->config->iir_config.coeff_set1[index];
+		coef &= ~COEF_MASK1;
+		coef |= (af_dev->config->iir_config.coeff_set1[index + 1]) <<
+								AF_COEF_SHIFT;
+		isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set1);
+
+		base_coef_set1 = base_coef_set1 + AFCOEF_OFFSET;
+	}
+	isp_reg_writel(af_dev->config->iir_config.coeff_set1[10],
+				OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
+
+	return 0;
+}
+
+/* Function to set address */
+void isp_af_set_address(unsigned long address)
+{
+	isp_reg_writel(address, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST);
+}
+
+static int isp_af_stats_available(struct isp_af_data *afdata)
+{
+	int i, ret;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&afstat.buffer_lock, irqflags);
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		DPRINTK_ISP_AF("Checking Stats buff[%d] (%d) for %d\n",
+				i, afstat.af_buff[i].frame_num,
+				afdata->frame_number);
+		if ((afdata->frame_number == afstat.af_buff[i].frame_num) &&
+						(afstat.af_buff[i].frame_num !=
+						active_buff->frame_num)) {
+			afstat.af_buff[i].locked = 1;
+			spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
+			isp_af_update_req_buffer(&afstat.af_buff[i]);
+			afstat.af_buff[i].frame_num = 0;
+			ret = copy_to_user((void *)afdata->af_statistics_buf,
+					(void *)afstat.af_buff[i].virt_addr,
+					afstat.curr_cfg_buf_size);
+			if (ret) {
+				printk(KERN_ERR "Failed copy_to_user for "
+					"H3A stats buff, %d\n", ret);
+			}
+			afdata->xtrastats.ts = afstat.af_buff[i].xtrastats.ts;
+			afdata->xtrastats.field_count =
+					afstat.af_buff[i].xtrastats.field_count;
+			return 0;
+		}
+	}
+	spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
+	/* Stats unavailable */
+
+	return -1;
+}
+
+void isp_af_notify(int notify)
+{
+	camnotify = notify;
+	if (camnotify && afstat.initialized) {
+		printk(KERN_DEBUG "Warning Camera Off \n");
+		afstat.stats_req = 0;
+		afstat.stats_done = 1;
+		wake_up_interruptible(&afstat.stats_wait);
+	}
+}
+EXPORT_SYMBOL(isp_af_notify);
+/*
+ * This API allows the user to update White Balance gains, as well as
+ * exposure time and analog gain. It is also used to request frame
+ * statistics.
+ */
+int isp_af_request_statistics(struct isp_af_data *afdata)
+{
+	int ret = 0;
+	u16 frame_diff = 0;
+	u16 frame_cnt = afstat.frame_count;
+	wait_queue_t wqt;
+
+	if (!af_dev_configptr->config->af_config) {
+		printk(KERN_ERR "AF engine not enabled\n");
+		return -EINVAL;
+	}
+
+	if (!(afdata->update & REQUEST_STATISTICS)) {
+		afdata->af_statistics_buf = NULL;
+		goto out;
+	}
+
+	isp_af_unlock_buffers();
+	/* Stats available? */
+	DPRINTK_ISP_AF("Stats available?\n");
+	ret = isp_af_stats_available(afdata);
+	if (!ret)
+		goto out;
+
+	/* Stats in near future? */
+	DPRINTK_ISP_AF("Stats in near future?\n");
+	if (afdata->frame_number > frame_cnt)
+		frame_diff = afdata->frame_number - frame_cnt;
+	else if (afdata->frame_number < frame_cnt) {
+		if ((frame_cnt > (MAX_FRAME_COUNT - MAX_FUTURE_FRAMES)) &&
+				(afdata->frame_number < MAX_FRAME_COUNT)) {
+			frame_diff = afdata->frame_number + MAX_FRAME_COUNT -
+								frame_cnt;
+		} else {
+			/* Frame unavailable */
+			frame_diff = MAX_FUTURE_FRAMES + 1;
+		}
+	}
+
+	if (frame_diff > MAX_FUTURE_FRAMES) {
+		printk(KERN_ERR "Invalid frame requested, returning current"
+							" frame stats\n");
+		afdata->frame_number = frame_cnt;
+	}
+	if (!camnotify) {
+		/* Block until frame in near future completes */
+		afstat.frame_req = afdata->frame_number;
+		afstat.stats_req = 1;
+		afstat.stats_done = 0;
+		init_waitqueue_entry(&wqt, current);
+		ret = wait_event_interruptible(afstat.stats_wait,
+							afstat.stats_done == 1);
+		if (ret < 0) {
+			afdata->af_statistics_buf = NULL;
+			return ret;
+		}
+		DPRINTK_ISP_AF("ISP AF request status interrupt raised\n");
+
+		/* Stats now available */
+		ret = isp_af_stats_available(afdata);
+		if (ret) {
+			printk(KERN_ERR "After waiting for stats, stats not"
+							" available!!\n");
+			afdata->af_statistics_buf = NULL;
+		}
+	}
+
+out:
+	afdata->curr_frame = afstat.frame_count;
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_af_request_statistics);
+
+/* This function will handle the H3A interrupt. */
+static void isp_af_isr(unsigned long status, isp_vbq_callback_ptr arg1,
+								void *arg2)
+{
+	u16 frame_align;
+
+	if ((H3A_AF_DONE & status) != H3A_AF_DONE)
+		return;
+
+	/* timestamp stats buffer */
+	do_gettimeofday(&active_buff->xtrastats.ts);
+	active_buff->config_counter = atomic_read(&afstat.config_counter);
+
+	/* Exchange buffers */
+	active_buff = active_buff->next;
+	if (active_buff->locked == 1)
+		active_buff = active_buff->next;
+	isp_af_set_address(active_buff->ispmmu_addr);
+
+	/* Update frame counter */
+	afstat.frame_count++;
+	frame_align = afstat.frame_count;
+	if (afstat.frame_count > MAX_FRAME_COUNT) {
+		afstat.frame_count = 1;
+		frame_align++;
+	}
+	active_buff->frame_num = afstat.frame_count;
+
+	/* Future Stats requested? */
+	if (afstat.stats_req) {
+		/* Is the frame we want already done? */
+		if (frame_align >= (afstat.frame_req + 1)) {
+			afstat.stats_req = 0;
+			afstat.stats_done = 1;
+			wake_up_interruptible(&afstat.stats_wait);
+		}
+	}
+}
+
+/* Function to Enable/Disable AF Engine */
+int isp_af_enable(int enable)
+{
+	unsigned int pcr;
+
+	pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
+
+	/* Set AF_EN bit in PCR Register */
+	if (enable) {
+		if (isp_set_callback(CBK_H3A_AF_DONE, isp_af_isr,
+						(void *)NULL, (void *)NULL)) {
+			printk(KERN_ERR "No callback for AF\n");
+			return -EINVAL;
+		}
+
+		pcr |= AF_EN;
+	} else {
+		isp_unset_callback(CBK_H3A_AF_DONE);
+		pcr &= ~AF_EN;
+	}
+	isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
+	return 0;
+}
+
+int isp_af_busy(void)
+{
+	return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
+		& ISPH3A_PCR_BUSYAF;
+}
+
+/* Function to register the AF character device driver. */
+int __init isp_af_init(void)
+{
+	/*allocate memory for device structure and initialize it with 0 */
+	af_dev_configptr = kzalloc(sizeof(struct af_device), GFP_KERNEL);
+	if (!af_dev_configptr)
+		goto err_nomem1;
+
+	active_buff = NULL;
+
+	af_dev_configptr->config = (struct af_configuration *)
+			kzalloc(sizeof(struct af_configuration), GFP_KERNEL);
+
+	if (af_dev_configptr->config == NULL)
+		goto err_nomem2;
+
+	memset(&afstat, 0, sizeof(afstat));
+
+	init_waitqueue_head(&afstat.stats_wait);
+	spin_lock_init(&afstat.buffer_lock);
+
+	return 0;
+
+err_nomem2:
+	kfree(af_dev_configptr);
+err_nomem1:
+	printk(KERN_ERR "Error: kmalloc fail");
+	return -ENOMEM;
+}
+
+void isp_af_exit(void)
+{
+	int i;
+
+	/* Free buffers */
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		if (!afstat.af_buff[i].phy_addr)
+			continue;
+
+		ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
+
+		dma_free_coherent(NULL,
+				  afstat.min_buf_size,
+				  (void *)afstat.af_buff[i].virt_addr,
+				  (dma_addr_t)afstat.af_buff[i].phy_addr);
+	}
+	kfree(af_dev_configptr->config);
+	kfree(af_dev_configptr);
+
+	memset(&afstat, 0, sizeof(afstat));
+
+	af_major = -1;
+}
diff --git a/drivers/media/video/isp/isp_af.h b/drivers/media/video/isp/isp_af.h
new file mode 100644
index 0000000..aad2dce
--- /dev/null
+++ b/drivers/media/video/isp/isp_af.h
@@ -0,0 +1,123 @@
+/*
+ * isp_af.h
+ *
+ * Include file for AF module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Troy Laramy
+ *
+ * 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.
+ */
+
+/* Device Constants */
+#ifndef OMAP_ISP_AF_H
+#define OMAP_ISP_AF_H
+
+#include <mach/isp_user.h>
+
+#define AF_MAJOR_NUMBER			0
+#define ISPAF_NAME			"OMAPISP_AF"
+#define AF_NR_DEVS			1
+#define AF_TIMEOUT			((300 * HZ) / 1000)
+
+
+
+/* Print Macros */
+/*list of error code */
+#define AF_ERR_HZ_COUNT			800	/* Invalid Horizontal Count */
+#define AF_ERR_VT_COUNT			801	/* Invalid Vertical Count */
+#define AF_ERR_HEIGHT			802	/* Invalid Height */
+#define AF_ERR_WIDTH			803	/* Invalid width */
+#define AF_ERR_INCR			804	/* Invalid Increment */
+#define AF_ERR_HZ_START			805	/* Invalid horizontal Start */
+#define AF_ERR_VT_START			806	/* Invalud vertical Start */
+#define AF_ERR_IIRSH			807	/* Invalid IIRSH value */
+#define AF_ERR_IIR_COEF			808	/* Invalid Coefficient */
+#define AF_ERR_SETUP			809	/* Setup not done */
+#define AF_ERR_THRESHOLD		810	/* Invalid Threshold */
+#define AF_ERR_ENGINE_BUSY		811	/* Engine is busy */
+
+#define AFPID				0x0	/* Peripheral Revision
+						 * and Class Information
+						 */
+
+#define AFCOEF_OFFSET			0x00000004	/* COEFFICIENT BASE
+							 * ADDRESS
+							 */
+
+/*
+ * PCR fields
+ */
+#define AF_BUSYAF			(1 << 15)
+#define FVMODE				(1 << 14)
+#define RGBPOS				(0x7 << 11)
+#define MED_TH				(0xFF << 3)
+#define AF_MED_EN			(1 << 2)
+#define AF_ALAW_EN			(1 << 1)
+#define AF_EN				(1 << 0)
+
+/*
+ * AFPAX1 fields
+ */
+#define PAXW				(0x7F << 16)
+#define PAXH				0x7F
+
+/*
+ * AFPAX2 fields
+ */
+#define AFINCV				(0xF << 13)
+#define PAXVC				(0x7F << 6)
+#define PAXHC				0x3F
+
+/*
+ * AFPAXSTART fields
+ */
+#define PAXSH				(0xFFF<<16)
+#define PAXSV				0xFFF
+
+/*
+ * COEFFICIENT MASK
+ */
+
+#define COEF_MASK0			0xFFF
+#define COEF_MASK1			(0xFFF<<16)
+
+/* BIT SHIFTS */
+#define AF_RGBPOS_SHIFT			11
+#define AF_MED_TH_SHIFT			3
+#define AF_PAXW_SHIFT			16
+#define AF_LINE_INCR_SHIFT		13
+#define AF_VT_COUNT_SHIFT		6
+#define AF_HZ_START_SHIFT		16
+#define AF_COEF_SHIFT			16
+
+#define AF_UPDATEXS_TS			(1 << 0)
+#define AF_UPDATEXS_FIELDCOUNT	(1 << 1)
+#define AF_UPDATEXS_LENSPOS		(1 << 2)
+
+/* Structure for device of AF Engine */
+struct af_device {
+	struct af_configuration *config; /*Device configuration structure */
+	int size_paxel;		/*Paxel size in bytes */
+};
+
+int isp_af_check_paxel(void);
+int isp_af_check_iir(void);
+int isp_af_register_setup(struct af_device *af_dev);
+int isp_af_enable(int);
+int isp_af_busy(void);
+void isp_af_notify(int notify);
+int isp_af_request_statistics(struct isp_af_data *afdata);
+int isp_af_configure(struct af_configuration *afconfig);
+void isp_af_set_address(unsigned long);
+void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag);
+#endif	/* OMAP_ISP_AF_H */
diff --git a/drivers/media/video/isp/isph3a.c b/drivers/media/video/isp/isph3a.c
new file mode 100644
index 0000000..e0a0983
--- /dev/null
+++ b/drivers/media/video/isp/isph3a.c
@@ -0,0 +1,902 @@
+/*
+ * isph3a.c
+ *
+ * H3A module for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Troy Laramy
+ *
+ * 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 <asm/cacheflush.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "isph3a.h"
+#include "ispmmu.h"
+#include "isppreview.h"
+
+/**
+ * struct isph3a_aewb_buffer - AE, AWB frame stats buffer.
+ * @virt_addr: Virtual address to mmap the buffer.
+ * @phy_addr: Physical address of the buffer.
+ * @addr_align: Virtual Address 32 bytes aligned.
+ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
+ * @mmap_addr: Mapped memory area of buffer. For userspace access.
+ * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
+ * @frame_num: Frame number from which the statistics are taken.
+ * @next: Pointer to link next buffer.
+ */
+struct isph3a_aewb_buffer {
+	unsigned long virt_addr;
+	unsigned long phy_addr;
+	unsigned long addr_align;
+	unsigned long ispmmu_addr;
+	unsigned long mmap_addr;	/* For userspace */
+	struct timeval ts;
+	u32 config_counter;
+
+	u8 locked;
+	u16 frame_num;
+	struct isph3a_aewb_buffer *next;
+};
+
+/**
+ * struct isph3a_aewb_status - AE, AWB status.
+ * @initialized: 1 - Buffers initialized.
+ * @update: 1 - Update registers.
+ * @stats_req: 1 - Future stats requested.
+ * @stats_done: 1 - Stats ready for user.
+ * @frame_req: Number of frame requested for statistics.
+ * @h3a_buff: Array of statistics buffers to access.
+ * @stats_buf_size: Statistics buffer size.
+ * @min_buf_size: Minimum statisitics buffer size.
+ * @win_count: Window Count.
+ * @frame_count: Frame Count.
+ * @stats_wait: Wait primitive for locking/unlocking the stats request.
+ * @buffer_lock: Spinlock for statistics buffers access.
+ */
+static struct isph3a_aewb_status {
+	u8 initialized;
+	u8 update;
+	u8 stats_req;
+	u8 stats_done;
+	u16 frame_req;
+
+	struct isph3a_aewb_buffer h3a_buff[H3A_MAX_BUFF];
+	unsigned int stats_buf_size;
+	unsigned int min_buf_size;
+	unsigned int curr_cfg_buf_size;
+
+	atomic_t config_counter;
+
+	u16 win_count;
+	u32 frame_count;
+	wait_queue_head_t stats_wait;
+	spinlock_t buffer_lock;		/* For stats buffers read/write sync */
+} aewbstat;
+
+/**
+ * struct isph3a_aewb_regs - Current value of AE, AWB configuration registers.
+ * reg_pcr: Peripheral control register.
+ * reg_win1: Control register.
+ * reg_start: Start position register.
+ * reg_blk: Black line register.
+ * reg_subwin: Configuration register.
+ */
+static struct isph3a_aewb_regs {
+	u32 reg_pcr;
+	u32 reg_win1;
+	u32 reg_start;
+	u32 reg_blk;
+	u32 reg_subwin;
+} aewb_regs;
+
+static struct isph3a_aewb_config aewb_config_local = {
+	.saturation_limit = 0x3FF,
+	.win_height = 0,
+	.win_width = 0,
+	.ver_win_count = 0,
+	.hor_win_count = 0,
+	.ver_win_start = 0,
+	.hor_win_start = 0,
+	.blk_ver_win_start = 0,
+	.blk_win_height = 0,
+	.subsample_ver_inc = 0,
+	.subsample_hor_inc = 0,
+	.alaw_enable = 0,
+	.aewb_enable = 0,
+};
+
+/* Structure for saving/restoring h3a module registers */
+static struct isp_reg isph3a_reg_list[] = {
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF032, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF054, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF076, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF098, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF110, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF132, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF154, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF176, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF198, 0},
+	{OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010, 0},
+	{0, ISP_TOK_TERM, 0}
+};
+
+static struct ispprev_wbal h3awb_update;
+static struct isph3a_aewb_buffer *active_buff;
+static struct isph3a_aewb_xtrastats h3a_xtrastats[H3A_MAX_BUFF];
+static int camnotify;
+static int wb_update;
+static void isph3a_print_status(void);
+
+/**
+ * isph3a_aewb_setxtrastats - Receives extra statistics from prior frames.
+ * @xtrastats: Pointer to structure containing extra statistics fields like
+ *             field count and timestamp of frame.
+ *
+ * Called from update_vbq in camera driver
+ **/
+void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats)
+{
+	int i;
+
+	if (active_buff == NULL)
+		return;
+
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		if (aewbstat.h3a_buff[i].frame_num != active_buff->frame_num)
+			continue;
+
+		if (i == 0) {
+			if (aewbstat.h3a_buff[H3A_MAX_BUFF - 1].
+							locked == 0) {
+				h3a_xtrastats[H3A_MAX_BUFF - 1] =
+							*xtrastats;
+			} else {
+				h3a_xtrastats[H3A_MAX_BUFF - 2] =
+							*xtrastats;
+			}
+		} else if (i == 1) {
+			if (aewbstat.h3a_buff[0].locked == 0)
+				h3a_xtrastats[0] = *xtrastats;
+			else {
+				h3a_xtrastats[H3A_MAX_BUFF - 1] =
+							*xtrastats;
+			}
+		} else {
+			if (aewbstat.h3a_buff[i - 1].locked == 0)
+				h3a_xtrastats[i - 1] = *xtrastats;
+			else
+				h3a_xtrastats[i - 2] = *xtrastats;
+		}
+		return;
+	}
+}
+EXPORT_SYMBOL(isph3a_aewb_setxtrastats);
+
+/**
+ * isph3a_aewb_enable - Enables AE, AWB engine in the H3A module.
+ * @enable: 1 - Enables the AE & AWB engine.
+ *
+ * Client should configure all the AE & AWB registers in H3A before this.
+ **/
+void isph3a_aewb_enable(u8 enable)
+{
+	isp_reg_writel(IRQ0STATUS_H3A_AWB_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
+							ISP_IRQ0STATUS);
+
+	if (enable) {
+		aewb_regs.reg_pcr |= ISPH3A_PCR_AEW_EN;
+		DPRINTK_ISPH3A("    H3A enabled \n");
+	} else {
+		aewb_regs.reg_pcr &= ~ISPH3A_PCR_AEW_EN;
+		DPRINTK_ISPH3A("    H3A disabled \n");
+	}
+	isp_reg_and_or(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ~ISPH3A_PCR_AEW_EN,
+					(enable ? ISPH3A_PCR_AEW_EN : 0));
+	aewb_config_local.aewb_enable = enable;
+}
+
+int isph3a_aewb_busy(void)
+{
+	return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
+		& ISPH3A_PCR_BUSYAEAWB;
+}
+
+/**
+ * isph3a_update_wb - Updates WB parameters.
+ *
+ * Needs to be called when no ISP Preview processing is taking place.
+ **/
+void isph3a_update_wb(void)
+{
+	if (wb_update) {
+		isppreview_config_whitebalance(h3awb_update);
+		wb_update = 0;
+	}
+	return;
+}
+EXPORT_SYMBOL(isph3a_update_wb);
+
+/**
+ * isph3a_aewb_update_regs - Helper function to update h3a registers.
+ **/
+static void isph3a_aewb_update_regs(void)
+{
+	isp_reg_writel(aewb_regs.reg_pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
+	isp_reg_writel(aewb_regs.reg_win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
+	isp_reg_writel(aewb_regs.reg_start, OMAP3_ISP_IOMEM_H3A,
+							ISPH3A_AEWINSTART);
+	isp_reg_writel(aewb_regs.reg_blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
+	isp_reg_writel(aewb_regs.reg_subwin, OMAP3_ISP_IOMEM_H3A,
+							ISPH3A_AEWSUBWIN);
+
+	aewbstat.update = 0;
+	aewbstat.frame_count = 1;
+}
+
+/**
+ * isph3a_aewb_update_req_buffer - Helper function to update buffer cache pages
+ * @buffer: Pointer to structure
+ **/
+static void isph3a_aewb_update_req_buffer(struct isph3a_aewb_buffer *buffer)
+{
+	int size = aewbstat.stats_buf_size;
+
+	size = PAGE_ALIGN(size);
+	dmac_inv_range((void *)buffer->addr_align,
+					(void *)buffer->addr_align + size);
+}
+
+/**
+ * isph3a_aewb_stats_available - Check for stats available of specified frame.
+ * @aewbdata: Pointer to return AE AWB statistics data
+ *
+ * Returns 0 if successful, or -1 if statistics are unavailable.
+ **/
+static int isph3a_aewb_stats_available(struct isph3a_aewb_data *aewbdata)
+{
+	int i, ret;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		DPRINTK_ISPH3A("Checking Stats buff[%d] (%d) for %d\n",
+				i, aewbstat.h3a_buff[i].frame_num,
+				aewbdata->frame_number);
+		if ((aewbdata->frame_number !=
+				aewbstat.h3a_buff[i].frame_num) ||
+			(aewbstat.h3a_buff[i].frame_num ==
+				active_buff->frame_num))
+			continue;
+		aewbstat.h3a_buff[i].locked = 1;
+		spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
+		isph3a_aewb_update_req_buffer(&aewbstat.h3a_buff[i]);
+		aewbstat.h3a_buff[i].frame_num = 0;
+		ret = copy_to_user((void *)aewbdata->h3a_aewb_statistics_buf,
+					(void *)aewbstat.h3a_buff[i].virt_addr,
+					aewbstat.curr_cfg_buf_size);
+		if (ret) {
+			printk(KERN_ERR "Failed copy_to_user for "
+					"H3A stats buff, %d\n", ret);
+		}
+		aewbdata->ts = aewbstat.h3a_buff[i].ts;
+		aewbdata->config_counter = aewbstat.h3a_buff[i].config_counter;
+		aewbdata->field_count = h3a_xtrastats[i].field_count;
+		return 0;
+	}
+	spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
+
+	return -1;
+}
+
+/**
+ * isph3a_aewb_link_buffers - Helper function to link allocated buffers.
+ **/
+static void isph3a_aewb_link_buffers(void)
+{
+	int i;
+
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		if ((i + 1) < H3A_MAX_BUFF) {
+			aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[i + 1];
+			h3a_xtrastats[i].next = &h3a_xtrastats[i + 1];
+		} else {
+			aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[0];
+			h3a_xtrastats[i].next = &h3a_xtrastats[0];
+		}
+	}
+}
+
+/**
+ * isph3a_aewb_unlock_buffers - Helper function to unlock all buffers.
+ **/
+static void isph3a_aewb_unlock_buffers(void)
+{
+	int i;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
+	for (i = 0; i < H3A_MAX_BUFF; i++)
+		aewbstat.h3a_buff[i].locked = 0;
+
+	spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
+}
+
+/**
+ * isph3a_aewb_isr - Callback from ISP driver for H3A AEWB interrupt.
+ * @status: IRQ0STATUS in case of MMU error, 0 for H3A interrupt.
+ * @arg1: Not used as of now.
+ * @arg2: Not used as of now.
+ */
+static void isph3a_aewb_isr(unsigned long status, isp_vbq_callback_ptr arg1,
+								void *arg2)
+{
+	u16 frame_align;
+
+	if ((H3A_AWB_DONE & status) != H3A_AWB_DONE)
+		return;
+
+	do_gettimeofday(&active_buff->ts);
+	active_buff->config_counter = atomic_read(&aewbstat.config_counter);
+	active_buff = active_buff->next;
+	if (active_buff->locked == 1)
+		active_buff = active_buff->next;
+	isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
+							ISPH3A_AEWBUFST);
+
+	aewbstat.frame_count++;
+	frame_align = aewbstat.frame_count;
+	if (aewbstat.frame_count > MAX_FRAME_COUNT) {
+		aewbstat.frame_count = 1;
+		frame_align++;
+	}
+	active_buff->frame_num = aewbstat.frame_count;
+
+	if (aewbstat.stats_req) {
+		DPRINTK_ISPH3A("waiting for frame %d\n", aewbstat.frame_req);
+		if (frame_align >= (aewbstat.frame_req + 1)) {
+			aewbstat.stats_req = 0;
+			aewbstat.stats_done = 1;
+			wake_up_interruptible(&aewbstat.stats_wait);
+		}
+	}
+
+	if (aewbstat.update)
+		isph3a_aewb_update_regs();
+}
+
+/**
+ * isph3a_aewb_set_params - Helper function to check & store user given params.
+ * @user_cfg: Pointer to AE and AWB parameters struct.
+ *
+ * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
+ * program them during ISR.
+ *
+ * Returns 0 if successful, or -EINVAL if any of the parameters are invalid.
+ **/
+static int isph3a_aewb_set_params(struct isph3a_aewb_config *user_cfg)
+{
+	if (unlikely(user_cfg->saturation_limit > MAX_SATURATION_LIM)) {
+		printk(KERN_ERR "Invalid Saturation_limit: %d\n",
+			user_cfg->saturation_limit);
+		return -EINVAL;
+	}
+	if (aewb_config_local.saturation_limit != user_cfg->saturation_limit) {
+		WRITE_SAT_LIM(aewb_regs.reg_pcr, user_cfg->saturation_limit);
+		aewb_config_local.saturation_limit =
+						user_cfg->saturation_limit;
+		aewbstat.update = 1;
+	}
+
+	if (aewb_config_local.alaw_enable != user_cfg->alaw_enable) {
+		WRITE_ALAW(aewb_regs.reg_pcr, user_cfg->alaw_enable);
+		aewb_config_local.alaw_enable = user_cfg->alaw_enable;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->win_height < MIN_WIN_H) ||
+					(user_cfg->win_height > MAX_WIN_H) ||
+					(user_cfg->win_height & 0x01))) {
+		printk(KERN_ERR "Invalid window height: %d\n",
+							user_cfg->win_height);
+		return -EINVAL;
+	}
+	if (aewb_config_local.win_height != user_cfg->win_height) {
+		WRITE_WIN_H(aewb_regs.reg_win1, user_cfg->win_height);
+		aewb_config_local.win_height = user_cfg->win_height;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->win_width < MIN_WIN_W) ||
+					(user_cfg->win_width > MAX_WIN_W) ||
+					(user_cfg->win_width & 0x01))) {
+		printk(KERN_ERR "Invalid window width: %d\n",
+							user_cfg->win_width);
+		return -EINVAL;
+	}
+	if (aewb_config_local.win_width != user_cfg->win_width) {
+		WRITE_WIN_W(aewb_regs.reg_win1, user_cfg->win_width);
+		aewb_config_local.win_width = user_cfg->win_width;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->ver_win_count < 1) ||
+				(user_cfg->ver_win_count > MAX_WINVC))) {
+		printk(KERN_ERR "Invalid vertical window count: %d\n",
+						user_cfg->ver_win_count);
+		return -EINVAL;
+	}
+	if (aewb_config_local.ver_win_count != user_cfg->ver_win_count) {
+		WRITE_VER_C(aewb_regs.reg_win1, user_cfg->ver_win_count);
+		aewb_config_local.ver_win_count = user_cfg->ver_win_count;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->hor_win_count < 1) ||
+				(user_cfg->hor_win_count > MAX_WINHC))) {
+		printk(KERN_ERR "Invalid horizontal window count: %d\n",
+						user_cfg->hor_win_count);
+		return -EINVAL;
+	}
+	if (aewb_config_local.hor_win_count != user_cfg->hor_win_count) {
+		WRITE_HOR_C(aewb_regs.reg_win1, user_cfg->hor_win_count);
+		aewb_config_local.hor_win_count	= user_cfg->hor_win_count;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely(user_cfg->ver_win_start > MAX_WINSTART)) {
+		printk(KERN_ERR "Invalid vertical window start: %d\n",
+						user_cfg->ver_win_start);
+		return -EINVAL;
+	}
+	if (aewb_config_local.ver_win_start != user_cfg->ver_win_start) {
+		WRITE_VER_WIN_ST(aewb_regs.reg_start, user_cfg->ver_win_start);
+		aewb_config_local.ver_win_start = user_cfg->ver_win_start;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely(user_cfg->hor_win_start > MAX_WINSTART)) {
+		printk(KERN_ERR "Invalid horizontal window start: %d\n",
+						user_cfg->hor_win_start);
+		return -EINVAL;
+	}
+	if (aewb_config_local.hor_win_start != user_cfg->hor_win_start) {
+		WRITE_HOR_WIN_ST(aewb_regs.reg_start, user_cfg->hor_win_start);
+		aewb_config_local.hor_win_start	= user_cfg->hor_win_start;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely(user_cfg->blk_ver_win_start > MAX_WINSTART)) {
+		printk(KERN_ERR "Invalid black vertical window start: %d\n",
+						user_cfg->blk_ver_win_start);
+		return -EINVAL;
+	}
+	if (aewb_config_local.blk_ver_win_start !=
+						user_cfg->blk_ver_win_start) {
+		WRITE_BLK_VER_WIN_ST(aewb_regs.reg_blk,
+						user_cfg->blk_ver_win_start);
+		aewb_config_local.blk_ver_win_start =
+						user_cfg->blk_ver_win_start;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->blk_win_height < MIN_WIN_H) ||
+				(user_cfg->blk_win_height > MAX_WIN_H) ||
+				(user_cfg->blk_win_height & 0x01))) {
+		printk(KERN_ERR "Invalid black window height: %d\n",
+						user_cfg->blk_win_height);
+		return -EINVAL;
+	}
+	if (aewb_config_local.blk_win_height != user_cfg->blk_win_height) {
+		WRITE_BLK_WIN_H(aewb_regs.reg_blk, user_cfg->blk_win_height);
+		aewb_config_local.blk_win_height = user_cfg->blk_win_height;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->subsample_ver_inc < MIN_SUB_INC) ||
+				(user_cfg->subsample_ver_inc > MAX_SUB_INC) ||
+				(user_cfg->subsample_ver_inc & 0x01))) {
+		printk(KERN_ERR "Invalid vertical subsample increment: %d\n",
+						user_cfg->subsample_ver_inc);
+		return -EINVAL;
+	}
+	if (aewb_config_local.subsample_ver_inc !=
+						user_cfg->subsample_ver_inc) {
+		WRITE_SUB_VER_INC(aewb_regs.reg_subwin,
+						user_cfg->subsample_ver_inc);
+		aewb_config_local.subsample_ver_inc =
+						user_cfg->subsample_ver_inc;
+		aewbstat.update = 1;
+	}
+
+	if (unlikely((user_cfg->subsample_hor_inc < MIN_SUB_INC) ||
+				(user_cfg->subsample_hor_inc > MAX_SUB_INC) ||
+				(user_cfg->subsample_hor_inc & 0x01))) {
+		printk(KERN_ERR "Invalid horizontal subsample increment: %d\n",
+						user_cfg->subsample_hor_inc);
+		return -EINVAL;
+	}
+	if (aewb_config_local.subsample_hor_inc !=
+						user_cfg->subsample_hor_inc) {
+		WRITE_SUB_HOR_INC(aewb_regs.reg_subwin,
+						user_cfg->subsample_hor_inc);
+		aewb_config_local.subsample_hor_inc =
+						user_cfg->subsample_hor_inc;
+		aewbstat.update = 1;
+	}
+
+	if ((!aewbstat.initialized) || (0 == aewb_config_local.aewb_enable)) {
+		isph3a_aewb_update_regs();
+		aewbstat.initialized = 1;
+	}
+	return 0;
+}
+
+/**
+ * isph3a_aewb_configure - Configure AEWB regs, enable/disable H3A engine.
+ * @aewbcfg: Pointer to AEWB config structure.
+ *
+ * Returns 0 if successful, -EINVAL if aewbcfg pointer is NULL, -ENOMEM if
+ * was unable to allocate memory for the buffer, of other errors if H3A
+ * callback is not set or the parameters for AEWB are invalid.
+ **/
+int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg)
+{
+	int ret = 0;
+	int i;
+	int win_count = 0;
+
+	if (NULL == aewbcfg) {
+		printk(KERN_ERR "Null argument in configuration. \n");
+		return -EINVAL;
+	}
+
+	if (!aewbstat.initialized) {
+		DPRINTK_ISPH3A("Setting callback for H3A\n");
+		ret = isp_set_callback(CBK_H3A_AWB_DONE, isph3a_aewb_isr,
+						(void *)NULL, (void *)NULL);
+		if (ret) {
+			printk(KERN_ERR "No callback for H3A\n");
+			return ret;
+		}
+	}
+
+	ret = isph3a_aewb_set_params(aewbcfg);
+	if (ret) {
+		printk(KERN_ERR "Invalid parameters! \n");
+		return ret;
+	}
+
+	win_count = (aewbcfg->ver_win_count * aewbcfg->hor_win_count);
+	win_count += aewbcfg->hor_win_count;
+	ret = (win_count / 8);
+	win_count += (win_count % 8) ? 1 : 0;
+	win_count += ret;
+
+	aewbstat.win_count = win_count;
+	aewbstat.curr_cfg_buf_size = win_count * AEWB_PACKET_SIZE;
+
+	if (aewbstat.stats_buf_size && ((win_count * AEWB_PACKET_SIZE) >
+						aewbstat.stats_buf_size)) {
+		DPRINTK_ISPH3A("There was a previous buffer... "
+			"Freeing/unmapping current stat busffs\n");
+		isph3a_aewb_enable(0);
+		for (i = 0; i < H3A_MAX_BUFF; i++) {
+			ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
+			dma_free_coherent(NULL,
+				aewbstat.min_buf_size,
+				(void *)aewbstat.h3a_buff[i].virt_addr,
+				(dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
+			aewbstat.h3a_buff[i].virt_addr = 0;
+		}
+		aewbstat.stats_buf_size = 0;
+	}
+
+	if (!aewbstat.h3a_buff[0].virt_addr) {
+		aewbstat.stats_buf_size = win_count * AEWB_PACKET_SIZE;
+		aewbstat.min_buf_size = PAGE_ALIGN(aewbstat.stats_buf_size);
+
+		DPRINTK_ISPH3A("Allocating/mapping new stat buffs\n");
+		for (i = 0; i < H3A_MAX_BUFF; i++) {
+			aewbstat.h3a_buff[i].virt_addr =
+				(unsigned long)dma_alloc_coherent(NULL,
+				aewbstat.min_buf_size,
+				(dma_addr_t *)&aewbstat.h3a_buff[i].phy_addr,
+				GFP_KERNEL | GFP_DMA);
+			if (aewbstat.h3a_buff[i].virt_addr == 0) {
+				printk(KERN_ERR "Can't acquire memory for "
+					"buffer[%d]\n", i);
+				return -ENOMEM;
+			}
+			aewbstat.h3a_buff[i].addr_align =
+						aewbstat.h3a_buff[i].virt_addr;
+			while ((aewbstat.h3a_buff[i].addr_align &
+							0xFFFFFFC0) !=
+							aewbstat.h3a_buff[i].
+							addr_align)
+				aewbstat.h3a_buff[i].addr_align++;
+			aewbstat.h3a_buff[i].ispmmu_addr = ispmmu_kmap(aewbstat.
+							h3a_buff[i].phy_addr,
+							aewbstat.min_buf_size);
+		}
+		isph3a_aewb_unlock_buffers();
+		isph3a_aewb_link_buffers();
+
+		if (active_buff == NULL)
+			active_buff = &aewbstat.h3a_buff[0];
+
+		isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
+							ISPH3A_AEWBUFST);
+	}
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		DPRINTK_ISPH3A("buff[%d] addr is:\n    virt    0x%lX\n"
+					"    aligned 0x%lX\n"
+					"    phys    0x%lX\n"
+					"    ispmmu  0x%08lX\n"
+					"    mmapped 0x%lX\n"
+					"    frame_num %d\n", i,
+					aewbstat.h3a_buff[i].virt_addr,
+					aewbstat.h3a_buff[i].addr_align,
+					aewbstat.h3a_buff[i].phy_addr,
+					aewbstat.h3a_buff[i].ispmmu_addr,
+					aewbstat.h3a_buff[i].mmap_addr,
+					aewbstat.h3a_buff[i].frame_num);
+	}
+
+	active_buff->frame_num = 1;
+
+	atomic_inc(&aewbstat.config_counter);
+	isph3a_aewb_enable(aewbcfg->aewb_enable);
+	isph3a_print_status();
+
+	return 0;
+}
+EXPORT_SYMBOL(isph3a_aewb_configure);
+
+/**
+ * isph3a_aewb_request_statistics - REquest statistics and update gains in AEWB
+ * @aewbdata: Pointer to return AE AWB statistics data.
+ *
+ * This API allows the user to update White Balance gains, as well as
+ * exposure time and analog gain. It is also used to request frame
+ * statistics.
+ *
+ * Returns 0 if successful, -EINVAL when H3A engine is not enabled, or other
+ * errors when setting gains.
+ **/
+int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata)
+{
+	int ret = 0;
+	u16 frame_diff = 0;
+	u16 frame_cnt = aewbstat.frame_count;
+	wait_queue_t wqt;
+
+	if (!aewb_config_local.aewb_enable) {
+		printk(KERN_ERR "H3A engine not enabled\n");
+		return -EINVAL;
+	}
+
+	DPRINTK_ISPH3A("isph3a_aewb_request_statistics: Enter "
+		"(frame req. => %d, current frame => %d, update => %d)\n",
+		aewbdata->frame_number, frame_cnt, aewbdata->update);
+	DPRINTK_ISPH3A("User data received: \n");
+	DPRINTK_ISPH3A("Digital gain = 0x%04x\n", aewbdata->dgain);
+	DPRINTK_ISPH3A("WB gain b *=   0x%04x\n", aewbdata->wb_gain_b);
+	DPRINTK_ISPH3A("WB gain r *=   0x%04x\n", aewbdata->wb_gain_r);
+	DPRINTK_ISPH3A("WB gain gb =   0x%04x\n", aewbdata->wb_gain_gb);
+	DPRINTK_ISPH3A("WB gain gr =   0x%04x\n", aewbdata->wb_gain_gr);
+
+	if (!aewbdata->update) {
+		aewbdata->h3a_aewb_statistics_buf = NULL;
+		goto out;
+	}
+	if (aewbdata->update & SET_DIGITAL_GAIN)
+		h3awb_update.dgain = (u16)aewbdata->dgain;
+	if (aewbdata->update & SET_COLOR_GAINS) {
+		h3awb_update.coef0 = (u8)aewbdata->wb_gain_gr;
+		h3awb_update.coef1 = (u8)aewbdata->wb_gain_r;
+		h3awb_update.coef2 = (u8)aewbdata->wb_gain_b;
+		h3awb_update.coef3 = (u8)aewbdata->wb_gain_gb;
+	}
+	if (aewbdata->update & (SET_COLOR_GAINS | SET_DIGITAL_GAIN))
+		wb_update = 1;
+
+	if (!(aewbdata->update & REQUEST_STATISTICS)) {
+		aewbdata->h3a_aewb_statistics_buf = NULL;
+		goto out;
+	}
+
+	if (aewbdata->frame_number < 1) {
+		printk(KERN_ERR "Illeagal frame number "
+			"requested (%d)\n",
+			aewbdata->frame_number);
+		return -EINVAL;
+	}
+
+	isph3a_aewb_unlock_buffers();
+
+	DPRINTK_ISPH3A("Stats available?\n");
+	ret = isph3a_aewb_stats_available(aewbdata);
+	if (!ret)
+		goto out;
+
+	DPRINTK_ISPH3A("Stats in near future?\n");
+	if (aewbdata->frame_number > frame_cnt)
+		frame_diff = aewbdata->frame_number - frame_cnt;
+	else if (aewbdata->frame_number < frame_cnt) {
+		if ((frame_cnt > (MAX_FRAME_COUNT - MAX_FUTURE_FRAMES)) &&
+				(aewbdata->frame_number < MAX_FRAME_COUNT)) {
+			frame_diff = aewbdata->frame_number + MAX_FRAME_COUNT -
+								frame_cnt;
+		} else
+			frame_diff = MAX_FUTURE_FRAMES + 1;
+	}
+
+	if (frame_diff > MAX_FUTURE_FRAMES) {
+		printk(KERN_ERR "Invalid frame requested, returning current"
+							" frame stats\n");
+		aewbdata->frame_number = frame_cnt;
+	}
+	if (camnotify) {
+		DPRINTK_ISPH3A("NOT Waiting on stats IRQ for frame %d "
+			"because camnotify set\n", aewbdata->frame_number);
+		aewbdata->h3a_aewb_statistics_buf = NULL;
+		goto out;
+	}
+	DPRINTK_ISPH3A("Waiting on stats IRQ for frame %d\n",
+						aewbdata->frame_number);
+	aewbstat.frame_req = aewbdata->frame_number;
+	aewbstat.stats_req = 1;
+	aewbstat.stats_done = 0;
+	init_waitqueue_entry(&wqt, current);
+	ret = wait_event_interruptible(aewbstat.stats_wait,
+						aewbstat.stats_done == 1);
+	if (ret < 0) {
+		printk(KERN_ERR "isph3a_aewb_request_statistics"
+					" Error on wait event %d\n", ret);
+		aewbdata->h3a_aewb_statistics_buf = NULL;
+		return ret;
+	}
+
+	DPRINTK_ISPH3A("ISP AEWB request status interrupt raised\n");
+	ret = isph3a_aewb_stats_available(aewbdata);
+	if (ret) {
+		DPRINTK_ISPH3A("After waiting for stats,"
+						" stats not available!!\n");
+		aewbdata->h3a_aewb_statistics_buf = NULL;
+	}
+out:
+	DPRINTK_ISPH3A("isph3a_aewb_request_statistics: "
+				"aewbdata->h3a_aewb_statistics_buf => %p\n",
+				aewbdata->h3a_aewb_statistics_buf);
+	aewbdata->curr_frame = aewbstat.frame_count;
+
+	return 0;
+}
+EXPORT_SYMBOL(isph3a_aewb_request_statistics);
+
+/**
+ * isph3a_aewb_init - Module Initialisation.
+ *
+ * Always returns 0.
+ **/
+int __init isph3a_aewb_init(void)
+{
+	memset(&aewbstat, 0, sizeof(aewbstat));
+	memset(&aewb_regs, 0, sizeof(aewb_regs));
+
+	init_waitqueue_head(&aewbstat.stats_wait);
+	spin_lock_init(&aewbstat.buffer_lock);
+	return 0;
+}
+
+/**
+ * isph3a_aewb_cleanup - Module exit.
+ **/
+void isph3a_aewb_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < H3A_MAX_BUFF; i++) {
+		if (!aewbstat.h3a_buff[i].phy_addr)
+			continue;
+
+		ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
+		dma_free_coherent(NULL,
+				  aewbstat.min_buf_size,
+				  (void *)aewbstat.h3a_buff[i].virt_addr,
+				  (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
+	}
+	memset(&aewbstat, 0, sizeof(aewbstat));
+	memset(&aewb_regs, 0, sizeof(aewb_regs));
+}
+
+/**
+ * isph3a_print_status - Debug print. Values of H3A related registers.
+ **/
+static void isph3a_print_status(void)
+{
+	DPRINTK_ISPH3A("ISPH3A_PCR = 0x%08x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR));
+	DPRINTK_ISPH3A("ISPH3A_AEWWIN1 = 0x%08x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1));
+	DPRINTK_ISPH3A("ISPH3A_AEWINSTART = 0x%08x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART));
+	DPRINTK_ISPH3A("ISPH3A_AEWINBLK = 0x%08x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK));
+	DPRINTK_ISPH3A("ISPH3A_AEWSUBWIN = 0x%08x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN));
+	DPRINTK_ISPH3A("ISPH3A_AEWBUFST = 0x%08x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST));
+	DPRINTK_ISPH3A("stats windows = %d\n", aewbstat.win_count);
+	DPRINTK_ISPH3A("stats buff size = %d\n", aewbstat.stats_buf_size);
+	DPRINTK_ISPH3A("currently configured stats buff size = %d\n",
+						aewbstat.curr_cfg_buf_size);
+}
+
+/**
+ * isph3a_notify - Unblocks user request for statistics when camera is off
+ * @notify: 1 - Camera is turned off
+ *
+ * Used when the user has requested statistics about a future frame, but the
+ * camera is turned off before it happens, and this function unblocks the
+ * request so the user can continue in its program.
+ **/
+void isph3a_notify(int notify)
+{
+	camnotify = notify;
+	if (camnotify && aewbstat.initialized) {
+		printk(KERN_DEBUG "Warning Camera Off \n");
+		aewbstat.stats_req = 0;
+		aewbstat.stats_done = 1;
+		wake_up_interruptible(&aewbstat.stats_wait);
+	}
+}
+EXPORT_SYMBOL(isph3a_notify);
+
+/**
+ * isph3a_save_context - Saves the values of the h3a module registers.
+ **/
+void isph3a_save_context(void)
+{
+	DPRINTK_ISPH3A(" Saving context\n");
+	isp_save_context(isph3a_reg_list);
+}
+EXPORT_SYMBOL(isph3a_save_context);
+
+/**
+ * isph3a_restore_context - Restores the values of the h3a module registers.
+ **/
+void isph3a_restore_context(void)
+{
+	DPRINTK_ISPH3A(" Restoring context\n");
+	isp_restore_context(isph3a_reg_list);
+}
+EXPORT_SYMBOL(isph3a_restore_context);
diff --git a/drivers/media/video/isp/isph3a.h b/drivers/media/video/isp/isph3a.h
new file mode 100644
index 0000000..e87c8a2
--- /dev/null
+++ b/drivers/media/video/isp/isph3a.h
@@ -0,0 +1,123 @@
+/*
+ * isph3a.h
+ *
+ * Include file for H3A module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Troy Laramy
+ *
+ * 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_H3A_H
+#define OMAP_ISP_H3A_H
+
+#include <mach/isp_user.h>
+
+#define AEWB_PACKET_SIZE	16
+#define H3A_MAX_BUFF		5
+
+/* Flags for changed registers */
+#define PCR_CHNG		(1 << 0)
+#define AEWWIN1_CHNG		(1 << 1)
+#define AEWINSTART_CHNG		(1 << 2)
+#define AEWINBLK_CHNG		(1 << 3)
+#define AEWSUBWIN_CHNG		(1 << 4)
+#define PRV_WBDGAIN_CHNG	(1 << 5)
+#define PRV_WBGAIN_CHNG		(1 << 6)
+
+/* ISPH3A REGISTERS bits */
+#define ISPH3A_PCR_AF_EN	(1 << 0)
+#define ISPH3A_PCR_AF_ALAW_EN	(1 << 1)
+#define ISPH3A_PCR_AF_MED_EN	(1 << 2)
+#define ISPH3A_PCR_AF_BUSY	(1 << 15)
+#define ISPH3A_PCR_AEW_EN	(1 << 16)
+#define ISPH3A_PCR_AEW_ALAW_EN	(1 << 17)
+#define ISPH3A_PCR_AEW_BUSY	(1 << 18)
+
+#define WRITE_SAT_LIM(reg, sat_limit)	\
+		(reg = (reg & (~(ISPH3A_PCR_AEW_AVE2LMT_MASK))) \
+			| (sat_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT))
+
+#define WRITE_ALAW(reg, alaw_en) \
+		(reg = (reg & (~(ISPH3A_PCR_AEW_ALAW_EN))) \
+			| ((alaw_en & ISPH3A_PCR_AF_ALAW_EN) \
+			<< ISPH3A_PCR_AEW_ALAW_EN_SHIFT))
+
+#define WRITE_WIN_H(reg, height) \
+		(reg = (reg & (~(ISPH3A_AEWWIN1_WINH_MASK))) \
+			| (((height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT))
+
+#define WRITE_WIN_W(reg, width) \
+		(reg = (reg & (~(ISPH3A_AEWWIN1_WINW_MASK))) \
+			| (((width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT))
+
+#define WRITE_VER_C(reg, ver_count) \
+		(reg = (reg & ~(ISPH3A_AEWWIN1_WINVC_MASK)) \
+			| ((ver_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT))
+
+#define WRITE_HOR_C(reg, hor_count) \
+		(reg = (reg & ~(ISPH3A_AEWWIN1_WINHC_MASK)) \
+			| ((hor_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT))
+
+#define WRITE_VER_WIN_ST(reg, ver_win_st) \
+		(reg = (reg & ~(ISPH3A_AEWINSTART_WINSV_MASK)) \
+			| (ver_win_st << ISPH3A_AEWINSTART_WINSV_SHIFT))
+
+#define WRITE_HOR_WIN_ST(reg, hor_win_st) \
+		(reg = (reg & ~(ISPH3A_AEWINSTART_WINSH_MASK)) \
+			| (hor_win_st << ISPH3A_AEWINSTART_WINSH_SHIFT))
+
+#define WRITE_BLK_VER_WIN_ST(reg, blk_win_st) \
+		(reg = (reg & ~(ISPH3A_AEWINBLK_WINSV_MASK)) \
+			| (blk_win_st << ISPH3A_AEWINBLK_WINSV_SHIFT))
+
+#define WRITE_BLK_WIN_H(reg, height) \
+		(reg = (reg & ~(ISPH3A_AEWINBLK_WINH_MASK)) \
+			| (((height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT))
+
+#define WRITE_SUB_VER_INC(reg, sub_ver_inc) \
+		(reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCV_MASK)) \
+		| (((sub_ver_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCV_SHIFT))
+
+#define WRITE_SUB_HOR_INC(reg, sub_hor_inc) \
+		(reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCH_MASK)) \
+		| (((sub_hor_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCH_SHIFT))
+
+/**
+ * struct isph3a_aewb_xtrastats - Structure with extra statistics sent by cam.
+ * @field_count: Sequence number of returned framestats.
+ * @isph3a_aewb_xtrastats: Pointer to next buffer with extra stats.
+ */
+struct isph3a_aewb_xtrastats {
+	unsigned long field_count;
+	struct isph3a_aewb_xtrastats *next;
+};
+
+void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats);
+
+int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg);
+
+int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata);
+
+void isph3a_save_context(void);
+
+void isph3a_restore_context(void);
+
+void isph3a_aewb_enable(u8 enable);
+
+int isph3a_aewb_busy(void);
+
+void isph3a_update_wb(void);
+
+void isph3a_notify(int notify);
+#endif		/* OMAP_ISP_H3A_H */
diff --git a/drivers/media/video/isp/isphist.c b/drivers/media/video/isp/isphist.c
new file mode 100644
index 0000000..270dbc2
--- /dev/null
+++ b/drivers/media/video/isp/isphist.c
@@ -0,0 +1,584 @@
+/*
+ * isphist.c
+ *
+ * HISTOGRAM module for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Troy Laramy
+ *
+ * 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 <asm/cacheflush.h>
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "isphist.h"
+#include "ispmmu.h"
+
+/**
+ * struct isp_hist_status - Histogram status.
+ * @hist_enable: Enables the histogram module.
+ * @initialized: Flag to indicate that the module is correctly initializated.
+ * @frame_cnt: Actual frame count.
+ * @frame_req: Frame requested by user.
+ * @completed: Flag to indicate if a frame request is completed.
+ */
+struct isp_hist_status {
+	u8 hist_enable;
+	u8 initialized;
+	u8 frame_cnt;
+	u8 frame_req;
+	u8 completed;
+} histstat;
+
+/**
+ * struct isp_hist_buffer - Frame histogram buffer.
+ * @virt_addr: Virtual address to mmap the buffer.
+ * @phy_addr: Physical address of the buffer.
+ * @addr_align: Virtual Address 32 bytes aligned.
+ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
+ * @mmap_addr: Mapped memory area of buffer. For userspace access.
+ */
+struct isp_hist_buffer {
+	unsigned long virt_addr;
+	unsigned long phy_addr;
+	unsigned long addr_align;
+	unsigned long ispmmu_addr;
+	unsigned long mmap_addr;
+} hist_buff;
+
+/**
+ * struct isp_hist_regs - Current value of Histogram configuration registers.
+ * @reg_pcr: Peripheral control register.
+ * @reg_cnt: Histogram control register.
+ * @reg_wb_gain: Histogram white balance gain register.
+ * @reg_r0_h: Region 0 horizontal register.
+ * @reg_r0_v: Region 0 vertical register.
+ * @reg_r1_h: Region 1 horizontal register.
+ * @reg_r1_v: Region 1 vertical register.
+ * @reg_r2_h: Region 2 horizontal register.
+ * @reg_r2_v: Region 2 vertical register.
+ * @reg_r3_h: Region 3 horizontal register.
+ * @reg_r3_v: Region 3 vertical register.
+ * @reg_hist_addr: Histogram address register.
+ * @reg_hist_data: Histogram data.
+ * @reg_hist_radd: Address register. When input data comes from mem.
+ * @reg_hist_radd_off: Address offset register. When input data comes from mem.
+ * @reg_h_v_info: Image size register. When input data comes from mem.
+ */
+static struct isp_hist_regs {
+	u32 reg_pcr;
+	u32 reg_cnt;
+	u32 reg_wb_gain;
+	u32 reg_r0_h;
+	u32 reg_r0_v;
+	u32 reg_r1_h;
+	u32 reg_r1_v;
+	u32 reg_r2_h;
+	u32 reg_r2_v;
+	u32 reg_r3_h;
+	u32 reg_r3_v;
+	u32 reg_hist_addr;
+	u32 reg_hist_data;
+	u32 reg_hist_radd;
+	u32 reg_hist_radd_off;
+	u32 reg_h_v_info;
+} hist_regs;
+
+/* Structure for saving/restoring histogram module registers */
+struct isp_reg isphist_reg_list[] = {
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF, 0},
+	{OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO, 0},
+	{0, ISP_TOK_TERM, 0}
+};
+
+static void isp_hist_print_status(void);
+
+/**
+ * isp_hist_enable - Enables ISP Histogram submodule operation.
+ * @enable: 1 - Enables the histogram submodule.
+ *
+ * Client should configure all the Histogram registers before calling this
+ * function.
+ **/
+void isp_hist_enable(u8 enable)
+{
+	if (enable)
+		DPRINTK_ISPHIST("   histogram enabled \n");
+	else
+		DPRINTK_ISPHIST("   histogram disabled \n");
+
+	isp_reg_and_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ~ISPHIST_PCR_EN,
+						(enable ? ISPHIST_PCR_EN : 0));
+	histstat.hist_enable = enable;
+}
+
+int isp_hist_busy(void)
+{
+	return isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR) &
+							ISPHIST_PCR_BUSY;
+}
+
+
+/**
+ * isp_hist_update_regs - Helper function to update Histogram registers.
+ **/
+static void isp_hist_update_regs(void)
+{
+	isp_reg_writel(hist_regs.reg_pcr, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR);
+	isp_reg_writel(hist_regs.reg_cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
+	isp_reg_writel(hist_regs.reg_wb_gain, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_WB_GAIN);
+	isp_reg_writel(hist_regs.reg_r0_h, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R0_HORZ);
+	isp_reg_writel(hist_regs.reg_r0_v, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R0_VERT);
+	isp_reg_writel(hist_regs.reg_r1_h, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R1_HORZ);
+	isp_reg_writel(hist_regs.reg_r1_v, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R1_VERT);
+	isp_reg_writel(hist_regs.reg_r2_h, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R2_HORZ);
+	isp_reg_writel(hist_regs.reg_r2_v, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R2_VERT);
+	isp_reg_writel(hist_regs.reg_r3_h, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R3_HORZ);
+	isp_reg_writel(hist_regs.reg_r3_v, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_R3_VERT);
+	isp_reg_writel(hist_regs.reg_hist_addr, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_ADDR);
+	isp_reg_writel(hist_regs.reg_hist_data, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_DATA);
+	isp_reg_writel(hist_regs.reg_hist_radd, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_RADD);
+	isp_reg_writel(hist_regs.reg_hist_radd_off, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_RADD_OFF);
+	isp_reg_writel(hist_regs.reg_h_v_info, OMAP3_ISP_IOMEM_HIST,
+							ISPHIST_H_V_INFO);
+}
+
+/**
+ * isp_hist_isr - Callback from ISP driver for HIST interrupt.
+ * @status: IRQ0STATUS in case of MMU error, 0 for hist interrupt.
+ *          arg1 and arg2 Not used as of now.
+ **/
+static void isp_hist_isr(unsigned long status, isp_vbq_callback_ptr arg1,
+								void *arg2)
+{
+	isp_hist_enable(0);
+
+	if ((HIST_DONE & status) != HIST_DONE)
+		return;
+
+	if (!histstat.completed) {
+		if (histstat.frame_req == histstat.frame_cnt) {
+			histstat.frame_cnt = 0;
+			histstat.frame_req = 0;
+			histstat.completed = 1;
+		} else {
+			isp_hist_enable(1);
+			histstat.frame_cnt++;
+		}
+	}
+}
+
+/**
+ * isp_hist_reset_mem - clear Histogram memory before start stats engine.
+ *
+ * Returns 0 after histogram memory was cleared.
+ **/
+static int isp_hist_reset_mem(void)
+{
+	int i;
+
+	isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
+
+	for (i = 0; i < HIST_MEM_SIZE; i++)
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+
+	isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ~ISPHIST_CNT_CLR_EN);
+
+	return 0;
+}
+
+/**
+ * isp_hist_set_params - Helper function to check and store user given params.
+ * @user_cfg: Pointer to user configuration structure.
+ *
+ * Returns 0 on success configuration.
+ **/
+static int isp_hist_set_params(struct isp_hist_config *user_cfg)
+{
+
+	int reg_num = 0;
+	int bit_shift = 0;
+
+
+	if (isp_hist_busy())
+		return -EINVAL;
+
+	if (user_cfg->input_bit_width > MIN_BIT_WIDTH)
+		WRITE_DATA_SIZE(hist_regs.reg_cnt, 0);
+	else
+		WRITE_DATA_SIZE(hist_regs.reg_cnt, 1);
+
+	WRITE_SOURCE(hist_regs.reg_cnt, user_cfg->hist_source);
+
+	if (user_cfg->hist_source) {
+		WRITE_HV_INFO(hist_regs.reg_h_v_info, user_cfg->hist_h_v_info);
+
+		if ((user_cfg->hist_radd & ISP_32B_BOUNDARY_BUF) ==
+							user_cfg->hist_radd) {
+			WRITE_RADD(hist_regs.reg_hist_radd,
+							user_cfg->hist_radd);
+		} else {
+			printk(KERN_ERR "Address should be in 32 byte boundary"
+									"\n");
+			return -EINVAL;
+		}
+
+		if ((user_cfg->hist_radd_off & ISP_32B_BOUNDARY_OFFSET) ==
+						user_cfg->hist_radd_off) {
+			WRITE_RADD_OFF(hist_regs.reg_hist_radd_off,
+						user_cfg->hist_radd_off);
+		} else {
+			printk(KERN_ERR "Offset should be in 32 byte boundary"
+									"\n");
+			return -EINVAL;
+		}
+
+	}
+
+	isp_hist_reset_mem();
+	DPRINTK_ISPHIST("ISPHIST: Memory Cleared\n");
+	histstat.frame_req = user_cfg->hist_frames;
+
+	if (unlikely((user_cfg->wb_gain_R > MAX_WB_GAIN) ||
+				(user_cfg->wb_gain_RG > MAX_WB_GAIN) ||
+				(user_cfg->wb_gain_B > MAX_WB_GAIN) ||
+				(user_cfg->wb_gain_BG > MAX_WB_GAIN))) {
+		printk(KERN_ERR "Invalid WB gain\n");
+		return -EINVAL;
+	} else {
+		WRITE_WB_R(hist_regs.reg_wb_gain, user_cfg->wb_gain_R);
+		WRITE_WB_RG(hist_regs.reg_wb_gain, user_cfg->wb_gain_RG);
+		WRITE_WB_B(hist_regs.reg_wb_gain, user_cfg->wb_gain_B);
+		WRITE_WB_BG(hist_regs.reg_wb_gain, user_cfg->wb_gain_BG);
+	}
+
+	/* Regions size and position */
+
+	if (user_cfg->num_regions > MAX_REGIONS)
+		return -EINVAL;
+
+	if (likely((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HEND_MASK) -
+					((user_cfg->reg0_hor &
+					ISPHIST_REGHORIZ_HSTART_MASK) >>
+					ISPHIST_REGHORIZ_HSTART_SHIFT))) {
+		WRITE_REG_HORIZ(hist_regs.reg_r0_h, user_cfg->reg0_hor);
+		reg_num++;
+	} else {
+		printk(KERN_ERR "Invalid Region parameters\n");
+		return -EINVAL;
+	}
+
+	if (likely((user_cfg->reg0_ver & ISPHIST_REGVERT_VEND_MASK) -
+			((user_cfg->reg0_ver & ISPHIST_REGVERT_VSTART_MASK) >>
+			ISPHIST_REGVERT_VSTART_SHIFT))) {
+		WRITE_REG_VERT(hist_regs.reg_r0_v, user_cfg->reg0_ver);
+	} else {
+		printk(KERN_ERR "Invalid Region parameters\n");
+		return -EINVAL;
+	}
+
+	if (user_cfg->num_regions >= 1) {
+		if (likely((user_cfg->reg1_hor & ISPHIST_REGHORIZ_HEND_MASK) -
+					((user_cfg->reg1_hor &
+					ISPHIST_REGHORIZ_HSTART_MASK) >>
+					ISPHIST_REGHORIZ_HSTART_SHIFT))) {
+			WRITE_REG_HORIZ(hist_regs.reg_r1_h, user_cfg->reg1_hor);
+		} else {
+			printk(KERN_ERR "Invalid Region parameters\n");
+			return -EINVAL;
+		}
+
+		if (likely((user_cfg->reg1_ver & ISPHIST_REGVERT_VEND_MASK) -
+					((user_cfg->reg1_ver &
+					ISPHIST_REGVERT_VSTART_MASK) >>
+					ISPHIST_REGVERT_VSTART_SHIFT))) {
+			WRITE_REG_VERT(hist_regs.reg_r1_v, user_cfg->reg1_ver);
+		} else {
+			printk(KERN_ERR "Invalid Region parameters\n");
+			return -EINVAL;
+		}
+	}
+
+	if (user_cfg->num_regions >= 2) {
+		if (likely((user_cfg->reg2_hor & ISPHIST_REGHORIZ_HEND_MASK) -
+					((user_cfg->reg2_hor &
+					ISPHIST_REGHORIZ_HSTART_MASK) >>
+					ISPHIST_REGHORIZ_HSTART_SHIFT))) {
+			WRITE_REG_HORIZ(hist_regs.reg_r2_h, user_cfg->reg2_hor);
+		} else {
+			printk(KERN_ERR "Invalid Region parameters\n");
+			return -EINVAL;
+		}
+
+		if (likely((user_cfg->reg2_ver & ISPHIST_REGVERT_VEND_MASK) -
+					((user_cfg->reg2_ver &
+					ISPHIST_REGVERT_VSTART_MASK) >>
+					ISPHIST_REGVERT_VSTART_SHIFT))) {
+			WRITE_REG_VERT(hist_regs.reg_r2_v, user_cfg->reg2_ver);
+		} else {
+			printk(KERN_ERR "Invalid Region parameters\n");
+			return -EINVAL;
+		}
+	}
+
+	if (user_cfg->num_regions >= 3) {
+		if (likely((user_cfg->reg3_hor & ISPHIST_REGHORIZ_HEND_MASK) -
+					((user_cfg->reg3_hor &
+					ISPHIST_REGHORIZ_HSTART_MASK) >>
+					ISPHIST_REGHORIZ_HSTART_SHIFT))) {
+			WRITE_REG_HORIZ(hist_regs.reg_r3_h, user_cfg->reg3_hor);
+		} else {
+			printk(KERN_ERR "Invalid Region parameters\n");
+			return -EINVAL;
+		}
+
+		if (likely((user_cfg->reg3_ver & ISPHIST_REGVERT_VEND_MASK) -
+					((user_cfg->reg3_ver &
+					ISPHIST_REGVERT_VSTART_MASK) >>
+					ISPHIST_REGVERT_VSTART_SHIFT))) {
+			WRITE_REG_VERT(hist_regs.reg_r3_v, user_cfg->reg3_ver);
+		} else {
+			printk(KERN_ERR "Invalid Region parameters\n");
+			return -EINVAL;
+		}
+	}
+	reg_num = user_cfg->num_regions;
+	if (unlikely(((user_cfg->hist_bins > BINS_256) &&
+				(user_cfg->hist_bins != BINS_32)) ||
+				((user_cfg->hist_bins == BINS_256) &&
+				reg_num != 0) || ((user_cfg->hist_bins ==
+				BINS_128) && reg_num >= 2))) {
+		printk(KERN_ERR "Invalid Bins Number: %d\n",
+							user_cfg->hist_bins);
+		return -EINVAL;
+	} else {
+		WRITE_NUM_BINS(hist_regs.reg_cnt, user_cfg->hist_bins);
+	}
+
+	if ((user_cfg->input_bit_width > MAX_BIT_WIDTH) ||
+				(user_cfg->input_bit_width < MIN_BIT_WIDTH)) {
+		printk(KERN_ERR "Invalid Bit Width: %d\n",
+						user_cfg->input_bit_width);
+		return -EINVAL;
+	} else {
+		switch (user_cfg->hist_bins) {
+		case BINS_256:
+			bit_shift = user_cfg->input_bit_width - 8;
+			break;
+		case BINS_128:
+			bit_shift = user_cfg->input_bit_width - 7;
+			break;
+		case BINS_64:
+			bit_shift = user_cfg->input_bit_width - 6;
+			break;
+		case BINS_32:
+			bit_shift = user_cfg->input_bit_width - 5;
+			break;
+		default:
+			return -EINVAL;
+		}
+		WRITE_BIT_SHIFT(hist_regs.reg_cnt, bit_shift);
+	}
+
+	isp_hist_update_regs();
+	histstat.initialized = 1;
+
+	return 0;
+}
+
+/**
+ * isp_hist_configure - API to configure HIST registers.
+ * @histcfg: Pointer to user configuration structure.
+ *
+ * Returns 0 on success configuration.
+ **/
+int isp_hist_configure(struct isp_hist_config *histcfg)
+{
+
+	int ret = 0;
+
+	if (NULL == histcfg) {
+		printk(KERN_ERR "Null argument in configuration. \n");
+		return -EINVAL;
+	}
+
+	if (!histstat.initialized) {
+		DPRINTK_ISPHIST("Setting callback for HISTOGRAM\n");
+		ret = isp_set_callback(CBK_HIST_DONE, isp_hist_isr,
+						(void *)NULL, (void *)NULL);
+		if (ret) {
+			printk(KERN_ERR "No callback for HIST\n");
+			return ret;
+		}
+	}
+
+	ret = isp_hist_set_params(histcfg);
+	if (ret) {
+		printk(KERN_ERR "Invalid parameters! \n");
+		return ret;
+	}
+
+	histstat.frame_cnt = 0;
+	histstat.completed = 0;
+	isp_hist_enable(1);
+	isp_hist_print_status();
+
+	return 0;
+}
+EXPORT_SYMBOL(isp_hist_configure);
+
+/**
+ * isp_hist_request_statistics - Request statistics in Histogram.
+ * @histdata: Pointer to data structure.
+ *
+ * This API allows the user to request for histogram statistics.
+ *
+ * Returns 0 on successful request.
+ **/
+int isp_hist_request_statistics(struct isp_hist_data *histdata)
+{
+	int i, ret;
+	u32 curr;
+
+	if (isp_hist_busy())
+		return -EBUSY;
+
+	if (!histstat.completed && histstat.initialized)
+		return -EINVAL;
+
+	isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
+
+	for (i = 0; i < HIST_MEM_SIZE; i++) {
+		curr = isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		ret = put_user(curr, (histdata->hist_statistics_buf + i));
+		if (ret) {
+			printk(KERN_ERR "Failed copy_to_user for "
+						"HIST stats buff, %d\n", ret);
+		}
+	}
+
+	isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
+						~ISPHIST_CNT_CLR_EN);
+	histstat.completed = 0;
+	return 0;
+}
+EXPORT_SYMBOL(isp_hist_request_statistics);
+
+/**
+ * isp_hist_init - Module Initialization.
+ *
+ * Returns 0 if successful.
+ **/
+int __init isp_hist_init(void)
+{
+	memset(&histstat, 0, sizeof(histstat));
+	memset(&hist_regs, 0, sizeof(hist_regs));
+
+	return 0;
+}
+
+/**
+ * isp_hist_cleanup - Module cleanup.
+ **/
+void isp_hist_cleanup(void)
+{
+	memset(&histstat, 0, sizeof(histstat));
+	memset(&hist_regs, 0, sizeof(hist_regs));
+}
+
+/**
+ * isphist_save_context - Saves the values of the histogram module registers.
+ **/
+void isphist_save_context(void)
+{
+	DPRINTK_ISPHIST(" Saving context\n");
+	isp_save_context(isphist_reg_list);
+}
+EXPORT_SYMBOL(isphist_save_context);
+
+/**
+ * isphist_restore_context - Restores the values of the histogram module regs.
+ **/
+void isphist_restore_context(void)
+{
+	DPRINTK_ISPHIST(" Restoring context\n");
+	isp_restore_context(isphist_reg_list);
+}
+EXPORT_SYMBOL(isphist_restore_context);
+
+/**
+ * isp_hist_print_status - Debug print
+ **/
+static void isp_hist_print_status(void)
+{
+	DPRINTK_ISPHIST("ISPHIST_PCR = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR));
+	DPRINTK_ISPHIST("ISPHIST_CNT = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT));
+	DPRINTK_ISPHIST("ISPHIST_WB_GAIN = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN));
+	DPRINTK_ISPHIST("ISPHIST_R0_HORZ = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ));
+	DPRINTK_ISPHIST("ISPHIST_R0_VERT = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT));
+	DPRINTK_ISPHIST("ISPHIST_R1_HORZ = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ));
+	DPRINTK_ISPHIST("ISPHIST_R1_VERT = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT));
+	DPRINTK_ISPHIST("ISPHIST_R2_HORZ = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ));
+	DPRINTK_ISPHIST("ISPHIST_R2_VERT = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT));
+	DPRINTK_ISPHIST("ISPHIST_R3_HORZ = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ));
+	DPRINTK_ISPHIST("ISPHIST_R3_VERT = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT));
+	DPRINTK_ISPHIST("ISPHIST_ADDR = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR));
+	DPRINTK_ISPHIST("ISPHIST_RADD = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD));
+	DPRINTK_ISPHIST("ISPHIST_RADD_OFF = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF));
+	DPRINTK_ISPHIST("ISPHIST_H_V_INFO = 0x%08x\n",
+		isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO));
+}
diff --git a/drivers/media/video/isp/isphist.h b/drivers/media/video/isp/isphist.h
new file mode 100644
index 0000000..e5c80d6
--- /dev/null
+++ b/drivers/media/video/isp/isphist.h
@@ -0,0 +1,101 @@
+/*
+ * isphist.h
+ *
+ * Header file for HISTOGRAM module in TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contributors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Troy Laramy
+ *
+ * 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_HIST_H
+#define OMAP_ISP_HIST_H
+
+#include <mach/isp_user.h>
+
+#define MAX_REGIONS		0x4
+#define MAX_WB_GAIN		255
+#define MIN_WB_GAIN		0x0
+#define MAX_BIT_WIDTH		14
+#define MIN_BIT_WIDTH		8
+
+#define ISPHIST_PCR_EN		(1 << 0)
+#define HIST_MEM_SIZE		1024
+#define ISPHIST_CNT_CLR_EN	(1 << 7)
+
+#define WRITE_SOURCE(reg, source)	\
+		(reg = (reg & ~(ISPHIST_CNT_SOURCE_MASK)) \
+		| (source << ISPHIST_CNT_SOURCE_SHIFT))
+
+#define WRITE_HV_INFO(reg, hv_info) \
+		(reg = ((reg & ~(ISPHIST_HV_INFO_MASK)) \
+		| (hv_info & ISPHIST_HV_INFO_MASK)))
+
+#define WRITE_RADD(reg, radd) \
+		(reg = (reg & ~(ISPHIST_RADD_MASK)) \
+		| (radd << ISPHIST_RADD_SHIFT))
+
+#define WRITE_RADD_OFF(reg, radd_off) \
+		(reg = (reg & ~(ISPHIST_RADD_OFF_MASK)) \
+		| (radd_off << ISPHIST_RADD_OFF_SHIFT))
+
+#define WRITE_BIT_SHIFT(reg, bit_shift) \
+		(reg = (reg & ~(ISPHIST_CNT_SHIFT_MASK)) \
+		| (bit_shift << ISPHIST_CNT_SHIFT_SHIFT))
+
+#define WRITE_DATA_SIZE(reg, data_size) \
+		(reg = (reg & ~(ISPHIST_CNT_DATASIZE_MASK)) \
+		| (data_size << ISPHIST_CNT_DATASIZE_SHIFT))
+
+#define WRITE_NUM_BINS(reg, num_bins) \
+		(reg = (reg & ~(ISPHIST_CNT_BINS_MASK)) \
+		| (num_bins << ISPHIST_CNT_BINS_SHIFT))
+
+#define WRITE_WB_R(reg, reg_wb_gain) \
+		reg = ((reg & ~(ISPHIST_WB_GAIN_WG00_MASK)) \
+		| (reg_wb_gain << ISPHIST_WB_GAIN_WG00_SHIFT))
+
+#define WRITE_WB_RG(reg, reg_wb_gain) \
+		(reg = (reg & ~(ISPHIST_WB_GAIN_WG01_MASK)) \
+		| (reg_wb_gain << ISPHIST_WB_GAIN_WG01_SHIFT))
+
+#define WRITE_WB_B(reg, reg_wb_gain) \
+		(reg = (reg & ~(ISPHIST_WB_GAIN_WG02_MASK)) \
+		| (reg_wb_gain << ISPHIST_WB_GAIN_WG02_SHIFT))
+
+#define WRITE_WB_BG(reg, reg_wb_gain) \
+		(reg = (reg & ~(ISPHIST_WB_GAIN_WG03_MASK)) \
+		| (reg_wb_gain << ISPHIST_WB_GAIN_WG03_SHIFT))
+
+#define WRITE_REG_HORIZ(reg, reg_n_hor) \
+		(reg = ((reg & ~ISPHIST_REGHORIZ_MASK) \
+		| (reg_n_hor & ISPHIST_REGHORIZ_MASK)))
+
+#define WRITE_REG_VERT(reg, reg_n_vert) \
+		(reg = ((reg & ~ISPHIST_REGVERT_MASK) \
+		| (reg_n_vert & ISPHIST_REGVERT_MASK)))
+
+
+void isp_hist_enable(u8 enable);
+
+int isp_hist_busy(void);
+
+int isp_hist_configure(struct isp_hist_config *histcfg);
+
+int isp_hist_request_statistics(struct isp_hist_data *histdata);
+
+void isphist_save_context(void);
+
+void isphist_restore_context(void);
+
+#endif				/* OMAP_ISP_HIST */
-- 
1.5.6.5


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

* [PATCH 7/9] omap3isp: Add CSI2 interface support
  2009-03-03 10:06           ` [PATCH 6/9] omap3isp: Add statistics collection modules (H3A and HIST) Sakari Ailus
@ 2009-03-03 10:06             ` Sakari Ailus
  2009-03-03 10:06               ` [PATCH 8/9] omap3isp: Add ISP tables Sakari Ailus
  0 siblings, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/isp/ispcsi2.c | 2124 +++++++++++++++++++++++++++++++++++++
 drivers/media/video/isp/ispcsi2.h |  232 ++++
 2 files changed, 2356 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/ispcsi2.c
 create mode 100644 drivers/media/video/isp/ispcsi2.h

diff --git a/drivers/media/video/isp/ispcsi2.c b/drivers/media/video/isp/ispcsi2.c
new file mode 100644
index 0000000..b1d60a8
--- /dev/null
+++ b/drivers/media/video/isp/ispcsi2.c
@@ -0,0 +1,2124 @@
+/*
+ * ispcsi2.c
+ *
+ * Driver Library for ISP CSI Control module in TI's OMAP3 Camera ISP
+ * ISP CSI interface and IRQ related APIs are defined here.
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * Contributors:
+ * 	Sergio Aguirre <saaguirre@ti.com>
+ * 	Dominic Curran <dcurran@ti.com>
+ *
+ * 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/delay.h>
+#include <media/v4l2-common.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispcsi2.h"
+
+static struct isp_csi2_cfg current_csi2_cfg;
+static struct isp_csi2_cfg_update current_csi2_cfg_update;
+
+static bool update_complexio_cfg1;
+static bool update_phy_cfg0;
+static bool update_phy_cfg1;
+static bool update_ctx_ctrl1[8];
+static bool update_ctx_ctrl2[8];
+static bool update_ctx_ctrl3[8];
+static bool update_timing;
+static bool update_ctrl;
+static bool uses_videoport;
+
+/**
+ * isp_csi2_complexio_lanes_config - Configuration of CSI2 ComplexIO lanes.
+ * @reqcfg: Pointer to structure containing desired lane configuration
+ *
+ * Validates and saves to internal driver memory the passed configuration.
+ * Returns 0 if successful, or -EINVAL if null pointer is passed, invalid
+ * lane position or polarity is set, and if 2 lanes try to occupy the same
+ * position. To apply this settings, use the isp_csi2_complexio_lanes_update()
+ * function just after calling this function.
+ **/
+int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg)
+{
+	int i;
+	bool pos_occupied[5] = {false, false, false, false, false};
+	struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
+	struct isp_csi2_lanes_cfg_update *currlanes_u =
+					&current_csi2_cfg_update.lanes;
+
+	/* Validating parameters sent by driver */
+	if (reqcfg == NULL) {
+		printk(KERN_ERR "Invalid Complex IO Configuration sent by"
+								" sensor\n");
+		goto err_einval;
+	}
+
+	/* Data lanes verification */
+	for (i = 0; i < 4; i++) {
+		if ((reqcfg->data[i].pol > 1) || (reqcfg->data[i].pos > 5)) {
+			printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
+					" parameters for data lane #%d\n", i);
+			goto err_einval;
+		}
+		if (pos_occupied[reqcfg->data[i].pos - 1] &&
+						reqcfg->data[i].pos > 0) {
+			printk(KERN_ERR "Lane #%d already occupied\n",
+							reqcfg->data[i].pos);
+			goto err_einval;
+		} else
+			pos_occupied[reqcfg->data[i].pos - 1] = true;
+	}
+
+	/* Clock lane verification */
+	if ((reqcfg->clk.pol > 1) || (reqcfg->clk.pos > 5) ||
+						(reqcfg->clk.pos == 0)) {
+		printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
+						" parameters for clock lane\n");
+		goto err_einval;
+	}
+	if (pos_occupied[reqcfg->clk.pos - 1]) {
+		printk(KERN_ERR "Lane #%d already occupied",
+							reqcfg->clk.pos);
+		goto err_einval;
+	} else
+		pos_occupied[reqcfg->clk.pos - 1] = true;
+
+	for (i = 0; i < 4; i++) {
+		if (currlanes->data[i].pos != reqcfg->data[i].pos) {
+			currlanes->data[i].pos = reqcfg->data[i].pos;
+			currlanes_u->data[i] = true;
+			update_complexio_cfg1 = true;
+		}
+		if (currlanes->data[i].pol != reqcfg->data[i].pol) {
+			currlanes->data[i].pol = reqcfg->data[i].pol;
+			currlanes_u->data[i] = true;
+			update_complexio_cfg1 = true;
+		}
+	}
+
+	if (currlanes->clk.pos != reqcfg->clk.pos) {
+		currlanes->clk.pos = reqcfg->clk.pos;
+		currlanes_u->clk = true;
+		update_complexio_cfg1 = true;
+	}
+	if (currlanes->clk.pol != reqcfg->clk.pol) {
+		currlanes->clk.pol = reqcfg->clk.pol;
+		currlanes_u->clk = true;
+		update_complexio_cfg1 = true;
+	}
+	return 0;
+err_einval:
+	return -EINVAL;
+}
+
+/**
+ * isp_csi2_complexio_lanes_update - Applies CSI2 ComplexIO lanes configuration.
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_complexio_lanes_config() function.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_complexio_lanes_config() function, unless the force_update flag is
+ * set to true.
+ * Always returns 0.
+ **/
+int isp_csi2_complexio_lanes_update(bool force_update)
+{
+	struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
+	struct isp_csi2_lanes_cfg_update *currlanes_u =
+					&current_csi2_cfg_update.lanes;
+	u32 reg;
+	int i;
+
+	if (!update_complexio_cfg1 && !force_update)
+		return 0;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
+	for (i = 0; i < 4; i++) {
+		if (currlanes_u->data[i] || force_update) {
+			reg &= ~(ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1) |
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i +
+									1));
+			reg |= (currlanes->data[i].pol <<
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1));
+			reg |= (currlanes->data[i].pos <<
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i +
+									1));
+			currlanes_u->data[i] = false;
+		}
+	}
+
+	if (currlanes_u->clk || force_update) {
+		reg &= ~(ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK |
+				ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK);
+		reg |= (currlanes->clk.pol <<
+				ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT);
+		reg |= (currlanes->clk.pos <<
+				ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT);
+		currlanes_u->clk = false;
+	}
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
+
+	update_complexio_cfg1 = false;
+	return 0;
+}
+
+/**
+ * isp_csi2_complexio_lanes_get - Gets CSI2 ComplexIO lanes configuration.
+ *
+ * Gets settings from HW registers and fills in the internal driver memory
+ * Always returns 0.
+ **/
+int isp_csi2_complexio_lanes_get(void)
+{
+	struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
+	struct isp_csi2_lanes_cfg_update *currlanes_u =
+					&current_csi2_cfg_update.lanes;
+	u32 reg;
+	int i;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
+	for (i = 0; i < 4; i++) {
+		currlanes->data[i].pol = (reg &
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1)) >>
+				ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1);
+		currlanes->data[i].pos = (reg &
+			ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i + 1)) >>
+			ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i + 1);
+		currlanes_u->data[i] = false;
+	}
+	currlanes->clk.pol = (reg & ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK) >>
+					ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT;
+	currlanes->clk.pos = (reg &
+				ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK) >>
+				ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT;
+	currlanes_u->clk = false;
+
+	update_complexio_cfg1 = false;
+	return 0;
+}
+
+/**
+ * isp_csi2_complexio_power_status - Gets CSI2 ComplexIO power status.
+ *
+ * Returns 3 possible valid states: ISP_CSI2_POWER_OFF, ISP_CSI2_POWER_ON,
+ * and ISP_CSI2_POWER_ULPW.
+ **/
+static enum isp_csi2_power_cmds isp_csi2_complexio_power_status(void)
+{
+	enum isp_csi2_power_cmds ret;
+	u32 reg;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
+					ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK;
+	switch (reg) {
+	case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF:
+		ret = ISP_CSI2_POWER_OFF;
+		break;
+	case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON:
+		ret = ISP_CSI2_POWER_ON;
+		break;
+	case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW:
+		ret = ISP_CSI2_POWER_ULPW;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/**
+ * isp_csi2_complexio_power_autoswitch - Sets CSI2 ComplexIO power autoswitch.
+ * @enable: Sets or clears the autoswitch function enable flag.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_complexio_power_autoswitch(bool enable)
+{
+	u32 reg;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
+	reg &= ~ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK;
+
+	if (enable)
+		reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE;
+	else
+		reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE;
+
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
+	return 0;
+}
+
+/**
+ * isp_csi2_complexio_power - Sets the desired power command for CSI2 ComplexIO.
+ * @power_cmd: Power command to be set.
+ *
+ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
+ **/
+int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd)
+{
+	enum isp_csi2_power_cmds current_state;
+	u32 reg;
+	u8 retry_count;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
+					~ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK;
+	switch (power_cmd) {
+	case ISP_CSI2_POWER_OFF:
+		reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF;
+		break;
+	case ISP_CSI2_POWER_ON:
+		reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON;
+		break;
+	case ISP_CSI2_POWER_ULPW:
+		reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW;
+		break;
+	default:
+		printk(KERN_ERR "CSI2: ERROR - Wrong Power command!\n");
+		return -EINVAL;
+	}
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
+
+	retry_count = 0;
+	do {
+		udelay(50);
+		current_state = isp_csi2_complexio_power_status();
+
+		if (current_state != power_cmd) {
+			printk(KERN_DEBUG "CSI2: Complex IO power command not"
+								" yet taken.");
+			if (++retry_count < 100) {
+				printk(KERN_DEBUG " Retrying...\n");
+				udelay(50);
+			} else {
+				printk(KERN_DEBUG " Retry count exceeded!\n");
+			}
+		}
+	} while ((current_state != power_cmd) && (retry_count < 100));
+
+	if (retry_count == 100)
+		return -EBUSY;
+
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_frame_mode - Configure if_en behaviour for CSI2
+ * @frame_mode: Desired action for IF_EN switch off. 0 - disable IF immediately
+ *              1 - disable after all Frame end Code is received in all
+ *              contexts.
+ *
+ * Validates and saves to internal driver memory the passed configuration.
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->frame_mode != frame_mode) {
+		currctrl->frame_mode = frame_mode;
+		currctrl_u->frame_mode = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_vp_clk_enable - Enables/disables CSI2 Videoport clock.
+ * @vp_clk_enable: Boolean value to specify the Videoport clock state.
+ *
+ * Validates and saves to internal driver memory the passed configuration.
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->vp_clk_enable != vp_clk_enable) {
+		currctrl->vp_clk_enable = vp_clk_enable;
+		currctrl_u->vp_clk_enable = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_vp_only_enable - Sets CSI2 Videoport clock as exclusive
+ * @vp_only_enable: Boolean value to specify if the Videoport clock is
+ *                  exclusive, setting the OCP port as disabled.
+ *
+ * Validates and saves to internal driver memory the passed configuration.
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->vp_only_enable != vp_only_enable) {
+		currctrl->vp_only_enable = vp_only_enable;
+		currctrl_u->vp_only_enable = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_vp_out_ctrl - Sets CSI2 Videoport clock divider
+ * @vp_out_ctrl: Divider value for setting videoport clock frequency based on
+ *               OCP port frequency, valid dividers are between 1 and 4.
+ *
+ * Validates and saves to internal driver memory the passed configuration.
+ * Returns 0 if successful, or -EINVAL if wrong divider value is passed.
+ **/
+int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if ((vp_out_ctrl == 0) || (vp_out_ctrl > 4)) {
+		printk(KERN_ERR "CSI2: Wrong divisor value. Must be between"
+								" 1 and 4");
+		return -EINVAL;
+	}
+
+	if (currctrl->vp_out_ctrl != vp_out_ctrl) {
+		currctrl->vp_out_ctrl = vp_out_ctrl;
+		currctrl_u->vp_out_ctrl = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_debug_enable - Sets CSI2 debug
+ * @debug_enable: Boolean for setting debug configuration on CSI2.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_debug_enable(bool debug_enable)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->debug_enable != debug_enable) {
+		currctrl->debug_enable = debug_enable;
+		currctrl_u->debug_enable = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_burst_size - Sets CSI2 burst size.
+ * @burst_size: Burst size of the memory saving capability of receiver.
+ *
+ * Returns 0 if successful, or -EINVAL if burst size is wrong.
+ **/
+int isp_csi2_ctrl_config_burst_size(u8 burst_size)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+	if (burst_size > 3) {
+		printk(KERN_ERR "CSI2: Wrong burst size. Must be between"
+								" 0 and 3");
+		return -EINVAL;
+	}
+
+	if (currctrl->burst_size != burst_size) {
+		currctrl->burst_size = burst_size;
+		currctrl_u->burst_size = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
+ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->ecc_enable != ecc_enable) {
+		currctrl->ecc_enable = ecc_enable;
+		currctrl_u->ecc_enable = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
+ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_secure_mode(bool secure_mode)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->secure_mode != secure_mode) {
+		currctrl->secure_mode = secure_mode;
+		currctrl_u->secure_mode = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_config_if_enable - Enables CSI2 Receiver interface.
+ * @if_enable: Boolean to enable/disable the CSI2 receiver interface.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_config_if_enable(bool if_enable)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+
+	if (currctrl->if_enable != if_enable) {
+		currctrl->if_enable = if_enable;
+		currctrl_u->if_enable = true;
+		update_ctrl = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_update - Applies CSI2 control configuration.
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_ctrl_config_*() functions.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_ctrl_config_*() functions, unless the force_update flag is
+ * set to true.
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_update(bool force_update)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+	u32 reg;
+
+	if (update_ctrl || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
+		if (currctrl_u->frame_mode || force_update) {
+			reg &= ~ISPCSI2_CTRL_FRAME_MASK;
+			if (currctrl->frame_mode)
+				reg |= ISPCSI2_CTRL_FRAME_DISABLE_FEC;
+			else
+				reg |= ISPCSI2_CTRL_FRAME_DISABLE_IMM;
+			currctrl_u->frame_mode = false;
+		}
+		if (currctrl_u->vp_clk_enable || force_update) {
+			reg &= ~ISPCSI2_CTRL_VP_CLK_EN_MASK;
+			if (currctrl->vp_clk_enable)
+				reg |= ISPCSI2_CTRL_VP_CLK_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTRL_VP_CLK_EN_DISABLE;
+			currctrl_u->vp_clk_enable = false;
+		}
+		if (currctrl_u->vp_only_enable || force_update) {
+			reg &= ~ISPCSI2_CTRL_VP_ONLY_EN_MASK;
+			uses_videoport = currctrl->vp_only_enable;
+			if (currctrl->vp_only_enable)
+				reg |= ISPCSI2_CTRL_VP_ONLY_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTRL_VP_ONLY_EN_DISABLE;
+			currctrl_u->vp_only_enable = false;
+		}
+		if (currctrl_u->vp_out_ctrl || force_update) {
+			reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
+			reg |= (currctrl->vp_out_ctrl - 1) <<
+						ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
+			currctrl_u->vp_out_ctrl = false;
+		}
+		if (currctrl_u->debug_enable || force_update) {
+			reg &= ~ISPCSI2_CTRL_DBG_EN_MASK;
+			if (currctrl->debug_enable)
+				reg |= ISPCSI2_CTRL_DBG_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTRL_DBG_EN_DISABLE;
+			currctrl_u->debug_enable = false;
+		}
+		if (currctrl_u->burst_size || force_update) {
+			reg &= ~ISPCSI2_CTRL_BURST_SIZE_MASK;
+			reg |= currctrl->burst_size <<
+						ISPCSI2_CTRL_BURST_SIZE_SHIFT;
+			currctrl_u->burst_size = false;
+		}
+		if (currctrl_u->ecc_enable || force_update) {
+			reg &= ~ISPCSI2_CTRL_ECC_EN_MASK;
+			if (currctrl->ecc_enable)
+				reg |= ISPCSI2_CTRL_ECC_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTRL_ECC_EN_DISABLE;
+			currctrl_u->ecc_enable = false;
+		}
+		if (currctrl_u->secure_mode || force_update) {
+			reg &= ~ISPCSI2_CTRL_SECURE_MASK;
+			if (currctrl->secure_mode)
+				reg |= ISPCSI2_CTRL_SECURE_ENABLE;
+			else
+				reg |= ISPCSI2_CTRL_SECURE_DISABLE;
+			currctrl_u->secure_mode = false;
+		}
+		if (currctrl_u->if_enable || force_update) {
+			reg &= ~ISPCSI2_CTRL_IF_EN_MASK;
+			if (currctrl->if_enable)
+				reg |= ISPCSI2_CTRL_IF_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTRL_IF_EN_DISABLE;
+			currctrl_u->if_enable = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
+		update_ctrl = false;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctrl_get - Gets CSI2 control configuration
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctrl_get(void)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
+	struct isp_csi2_ctrl_cfg_update *currctrl_u =
+						&current_csi2_cfg_update.ctrl;
+	u32 reg;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
+	currctrl->frame_mode = (reg & ISPCSI2_CTRL_FRAME_MASK) >>
+						ISPCSI2_CTRL_FRAME_SHIFT;
+	currctrl_u->frame_mode = false;
+
+	if ((reg & ISPCSI2_CTRL_VP_CLK_EN_MASK) ==
+						ISPCSI2_CTRL_VP_CLK_EN_ENABLE)
+		currctrl->vp_clk_enable = true;
+	else
+		currctrl->vp_clk_enable = false;
+	currctrl_u->vp_clk_enable = false;
+
+	if ((reg & ISPCSI2_CTRL_VP_ONLY_EN_MASK) ==
+						ISPCSI2_CTRL_VP_ONLY_EN_ENABLE)
+		currctrl->vp_only_enable = true;
+	else
+		currctrl->vp_only_enable = false;
+	uses_videoport = currctrl->vp_only_enable;
+	currctrl_u->vp_only_enable = false;
+
+	currctrl->vp_out_ctrl = ((reg & ISPCSI2_CTRL_VP_OUT_CTRL_MASK) >>
+					ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT) + 1;
+	currctrl_u->vp_out_ctrl = false;
+
+	if ((reg & ISPCSI2_CTRL_DBG_EN_MASK) == ISPCSI2_CTRL_DBG_EN_ENABLE)
+		currctrl->debug_enable = true;
+	else
+		currctrl->debug_enable = false;
+	currctrl_u->debug_enable = false;
+
+	currctrl->burst_size = (reg & ISPCSI2_CTRL_BURST_SIZE_MASK) >>
+					ISPCSI2_CTRL_BURST_SIZE_SHIFT;
+	currctrl_u->burst_size = false;
+
+	if ((reg & ISPCSI2_CTRL_ECC_EN_MASK) == ISPCSI2_CTRL_ECC_EN_ENABLE)
+		currctrl->ecc_enable = true;
+	else
+		currctrl->ecc_enable = false;
+	currctrl_u->ecc_enable = false;
+
+	if ((reg & ISPCSI2_CTRL_SECURE_MASK) == ISPCSI2_CTRL_SECURE_ENABLE)
+		currctrl->secure_mode = true;
+	else
+		currctrl->secure_mode = false;
+	currctrl_u->secure_mode = false;
+
+	if ((reg & ISPCSI2_CTRL_IF_EN_MASK) == ISPCSI2_CTRL_IF_EN_ENABLE)
+		currctrl->if_enable = true;
+	else
+		currctrl->if_enable = false;
+	currctrl_u->if_enable = false;
+
+	update_ctrl = false;
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_validate - Validates the context number value
+ * @ctxnum: Pointer to variable containing context number.
+ *
+ * If the value is not in range (3 bits), it is being ANDed with 0x7 to force
+ * it to be on range.
+ **/
+static void isp_csi2_ctx_validate(u8 *ctxnum)
+{
+	if (*ctxnum > 7) {
+		printk(KERN_ERR "Invalid context number. Forcing valid"
+								" value...\n");
+		*ctxnum &= ~(0x7);
+	}
+}
+
+/**
+ * isp_csi2_ctx_config_virtual_id - Maps a virtual ID with a CSI2 Rx context
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @virtual_id: CSI2 Virtual ID to associate with specified context number.
+ *
+ * Returns 0 if successful, or -EINVAL if Virtual ID is not in range (0-3).
+ **/
+int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	if (virtual_id > 3) {
+		printk(KERN_ERR "Wrong requested virtual_id\n");
+		return -EINVAL;
+	}
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->virtual_id != virtual_id) {
+		selected_ctx->virtual_id = virtual_id;
+		selected_ctx_u->virtual_id = true;
+		update_ctx_ctrl2[ctxnum] = true;
+	}
+
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_frame_count - Sets frame count to be received in CSI2 Rx.
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @frame_count: Number of frames to acquire.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->frame_count != frame_count) {
+		selected_ctx->frame_count = frame_count;
+		selected_ctx_u->frame_count = true;
+		update_ctx_ctrl1[ctxnum] = true;
+	}
+
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_format - Maps a pixel format to a specified context.
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @pixformat: V4L2 structure for pixel format.
+ *
+ * Returns 0 if successful, or -EINVAL if the format is not supported by the
+ * receiver.
+ **/
+int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+	struct v4l2_pix_format pix;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	pix.pixelformat = pixformat;
+	switch (pix.pixelformat) {
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_RGB565X:
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_RGB555:
+	case V4L2_PIX_FMT_RGB555X:
+	case V4L2_PIX_FMT_SGRBG10:
+	break;
+	default:
+		printk(KERN_ERR "Context config pixel format unsupported\n");
+		return -EINVAL;
+	}
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	selected_ctx->format = pix;
+	selected_ctx_u->format = true;
+	update_ctx_ctrl2[ctxnum] = true;
+
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_alpha - Sets the alpha value for pixel format
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @alpha: Alpha value.
+ *
+ * Returns 0 if successful, or -EINVAL if the alpha value is bigger than 16383.
+ **/
+int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	if (alpha > 0x3FFF) {
+		printk(KERN_ERR "Wrong alpha value\n");
+		return -EINVAL;
+	}
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->alpha != alpha) {
+		selected_ctx->alpha = alpha;
+		selected_ctx_u->alpha = true;
+		update_ctx_ctrl3[ctxnum] = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_data_offset - Sets the offset between received lines
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @data_offset: Offset between first pixel of each 2 contiguous lines.
+ *
+ * Returns 0 if successful, or -EINVAL if the line offset is bigger than 1023.
+ **/
+int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	if (data_offset > 0x3FF) {
+		printk(KERN_ERR "Wrong line offset\n");
+		return -EINVAL;
+	}
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->data_offset != data_offset) {
+		selected_ctx->data_offset = data_offset;
+		selected_ctx_u->data_offset = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_ping_addr - Sets Ping address for CSI2 Rx. buffer saving
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @ping_addr: 32 bit ISP MMU mapped address.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	ping_addr &= ~(0x1F);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->ping_addr != ping_addr) {
+		selected_ctx->ping_addr = ping_addr;
+		selected_ctx_u->ping_addr = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_pong_addr - Sets Pong address for CSI2 Rx. buffer saving
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @pong_addr: 32 bit ISP MMU mapped address.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	pong_addr &= ~(0x1F);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->pong_addr != pong_addr) {
+		selected_ctx->pong_addr = pong_addr;
+		selected_ctx_u->pong_addr = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_eof_enabled - Enables EOF signal assertion
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @eof_enabled: Boolean to enable/disable EOF signal assertion on received
+ *               packets.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->eof_enabled != eof_enabled) {
+		selected_ctx->eof_enabled = eof_enabled;
+		selected_ctx_u->eof_enabled = true;
+		update_ctx_ctrl1[ctxnum] = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_eol_enabled - Enables EOL signal assertion
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @eol_enabled: Boolean to enable/disable EOL signal assertion on received
+ *               packets.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->eol_enabled != eol_enabled) {
+		selected_ctx->eol_enabled = eol_enabled;
+		selected_ctx_u->eol_enabled = true;
+		update_ctx_ctrl1[ctxnum] = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_checksum_enabled - Enables Checksum check in rcvd packets
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @checksum_enabled: Boolean to enable/disable Checksum check on received
+ *                    packets
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->checksum_enabled != checksum_enabled) {
+		selected_ctx->checksum_enabled = checksum_enabled;
+		selected_ctx_u->checksum_enabled = true;
+		update_ctx_ctrl1[ctxnum] = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_config_enabled - Enables specified CSI2 context
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @enabled: Boolean to enable/disable specified context.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (selected_ctx->enabled != enabled) {
+		selected_ctx->enabled = enabled;
+		selected_ctx_u->enabled = true;
+		update_ctx_ctrl1[ctxnum] = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_update - Applies CSI2 context configuration.
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_ctx_config_*() functions.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
+ * set to true.
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_update(u8 ctxnum, bool force_update)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+	u32 reg;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	if (update_ctx_ctrl1[ctxnum] || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_CTRL1(ctxnum));
+		if (selected_ctx_u->frame_count || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL1_COUNT_MASK);
+			reg |= selected_ctx->frame_count <<
+						ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
+			selected_ctx_u->frame_count = false;
+		}
+		if (selected_ctx_u->eof_enabled || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL1_EOF_EN_MASK);
+			if (selected_ctx->eof_enabled)
+				reg |= ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE;
+			selected_ctx_u->eof_enabled = false;
+		}
+		if (selected_ctx_u->eol_enabled || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL1_EOL_EN_MASK);
+			if (selected_ctx->eol_enabled)
+				reg |= ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE;
+			selected_ctx_u->eol_enabled = false;
+		}
+		if (selected_ctx_u->checksum_enabled || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL1_CS_EN_MASK);
+			if (selected_ctx->checksum_enabled)
+				reg |= ISPCSI2_CTX_CTRL1_CS_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTX_CTRL1_CS_EN_DISABLE;
+			selected_ctx_u->checksum_enabled = false;
+		}
+		if (selected_ctx_u->enabled || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL1_CTX_EN_MASK);
+			if (selected_ctx->enabled)
+				reg |= ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE;
+			else
+				reg |= ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE;
+			selected_ctx_u->enabled = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_CTRL1(ctxnum));
+		update_ctx_ctrl1[ctxnum] = false;
+	}
+
+	if (update_ctx_ctrl2[ctxnum] || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_CTRL2(ctxnum));
+		if (selected_ctx_u->virtual_id || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
+			reg |= selected_ctx->virtual_id <<
+					ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
+			selected_ctx_u->virtual_id = false;
+		}
+
+		if (selected_ctx_u->format || force_update) {
+			struct v4l2_pix_format *pix;
+			u16 new_format = 0;
+
+			reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
+			pix = &selected_ctx->format;
+			switch (pix->pixelformat) {
+			case V4L2_PIX_FMT_RGB565:
+			case V4L2_PIX_FMT_RGB565X:
+				new_format = 0x22;
+				break;
+			case V4L2_PIX_FMT_YUYV:
+			case V4L2_PIX_FMT_UYVY:
+				if (uses_videoport)
+					new_format = 0x9E;
+				else
+					new_format = 0x1E;
+				break;
+			case V4L2_PIX_FMT_RGB555:
+			case V4L2_PIX_FMT_RGB555X:
+				new_format = 0xA1;
+				break;
+			case V4L2_PIX_FMT_SGRBG10:
+				if (uses_videoport)
+					new_format = 0x12F;
+				else
+					new_format = 0xAB;
+				break;
+			}
+			reg |= (new_format << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT);
+			selected_ctx_u->format = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_CTRL2(ctxnum));
+		update_ctx_ctrl2[ctxnum] = false;
+	}
+
+	if (update_ctx_ctrl3[ctxnum] || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_CTRL3(ctxnum));
+		if (selected_ctx_u->alpha || force_update) {
+			reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
+			reg |= (selected_ctx->alpha <<
+						ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
+			selected_ctx_u->alpha = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_CTRL3(ctxnum));
+		update_ctx_ctrl3[ctxnum] = false;
+	}
+
+	if (selected_ctx_u->data_offset) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_OFST(ctxnum));
+		reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
+		reg |= selected_ctx->data_offset <<
+					ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_OFST(ctxnum));
+		selected_ctx_u->data_offset = false;
+	}
+
+	if (selected_ctx_u->ping_addr) {
+		reg = selected_ctx->ping_addr;
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
+		selected_ctx_u->ping_addr = false;
+	}
+
+	if (selected_ctx_u->pong_addr) {
+		reg = selected_ctx->pong_addr;
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
+		selected_ctx_u->pong_addr = false;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_get - Gets specific CSI2 Context configuration
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_get(u8 ctxnum)
+{
+	struct isp_csi2_ctx_cfg *selected_ctx;
+	struct isp_csi2_ctx_cfg_update *selected_ctx_u;
+	u32 reg;
+
+	isp_csi2_ctx_validate(&ctxnum);
+
+	selected_ctx = &current_csi2_cfg.contexts[ctxnum];
+	selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL1(ctxnum));
+	selected_ctx->frame_count = (reg & ISPCSI2_CTX_CTRL1_COUNT_MASK) >>
+						ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
+	selected_ctx_u->frame_count = false;
+
+	if ((reg & ISPCSI2_CTX_CTRL1_EOF_EN_MASK) ==
+						ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE)
+		selected_ctx->eof_enabled = true;
+	else
+		selected_ctx->eof_enabled = false;
+	selected_ctx_u->eof_enabled = false;
+
+	if ((reg & ISPCSI2_CTX_CTRL1_EOL_EN_MASK) ==
+						ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE)
+		selected_ctx->eol_enabled = true;
+	else
+		selected_ctx->eol_enabled = false;
+	selected_ctx_u->eol_enabled = false;
+
+	if ((reg & ISPCSI2_CTX_CTRL1_CS_EN_MASK) ==
+						ISPCSI2_CTX_CTRL1_CS_EN_ENABLE)
+		selected_ctx->checksum_enabled = true;
+	else
+		selected_ctx->checksum_enabled = false;
+	selected_ctx_u->checksum_enabled = false;
+
+	if ((reg & ISPCSI2_CTX_CTRL1_CTX_EN_MASK) ==
+						ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE)
+		selected_ctx->enabled = true;
+	else
+		selected_ctx->enabled = false;
+	selected_ctx_u->enabled = false;
+	update_ctx_ctrl1[ctxnum] = false;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL2(ctxnum));
+
+	selected_ctx->virtual_id = (reg & ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK) >>
+					ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
+	selected_ctx_u->virtual_id = false;
+
+	switch ((reg & ISPCSI2_CTX_CTRL2_FORMAT_MASK) >>
+				ISPCSI2_CTX_CTRL2_FORMAT_SHIFT) {
+	case 0x22:
+		selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB565;
+		break;
+	case 0x9E:
+	case 0x1E:
+		selected_ctx->format.pixelformat = V4L2_PIX_FMT_YUYV;
+		break;
+	case 0xA1:
+		selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB555;
+		break;
+	case 0xAB:
+	case 0x12F:
+		selected_ctx->format.pixelformat = V4L2_PIX_FMT_SGRBG10;
+		break;
+	}
+	selected_ctx_u->format = false;
+	update_ctx_ctrl2[ctxnum] = false;
+
+	selected_ctx->alpha = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_CTRL3(ctxnum)) &
+					ISPCSI2_CTX_CTRL3_ALPHA_MASK) >>
+					ISPCSI2_CTX_CTRL3_ALPHA_SHIFT;
+	selected_ctx_u->alpha = false;
+	update_ctx_ctrl3[ctxnum] = false;
+
+	selected_ctx->data_offset = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_OFST(ctxnum)) &
+					ISPCSI2_CTX_DAT_OFST_OFST_MASK) >>
+					ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
+	selected_ctx_u->data_offset = false;
+
+	selected_ctx->ping_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
+	selected_ctx_u->ping_addr = false;
+
+	selected_ctx->pong_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+					ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
+	selected_ctx_u->pong_addr = false;
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_update_all - Applies all CSI2 context configuration.
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_ctx_config_*() functions.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
+ * set to true.
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_update_all(bool force_update)
+{
+	u8 ctxnum;
+
+	for (ctxnum = 0; ctxnum < 8; ctxnum++)
+		isp_csi2_ctx_update(ctxnum, force_update);
+
+	return 0;
+}
+
+/**
+ * isp_csi2_ctx_get_all - Gets all CSI2 Context configurations
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_ctx_get_all(void)
+{
+	u8 ctxnum;
+
+	for (ctxnum = 0; ctxnum < 8; ctxnum++)
+		isp_csi2_ctx_get(ctxnum);
+
+	return 0;
+}
+
+int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig)
+{
+	struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
+	struct isp_csi2_phy_cfg_update *currphy_u =
+						&current_csi2_cfg_update.phy;
+
+	if ((desiredphyconfig->tclk_term > 0x7f) ||
+				(desiredphyconfig->tclk_miss > 0x3)) {
+		printk(KERN_ERR "Invalid PHY configuration sent by the"
+								" driver\n");
+		return -EINVAL;
+	}
+
+	if (currphy->ths_term != desiredphyconfig->ths_term) {
+		currphy->ths_term = desiredphyconfig->ths_term;
+		currphy_u->ths_term = true;
+		update_phy_cfg0 = true;
+	}
+	if (currphy->ths_settle != desiredphyconfig->ths_settle) {
+		currphy->ths_settle = desiredphyconfig->ths_settle;
+		currphy_u->ths_settle = true;
+		update_phy_cfg0 = true;
+	}
+	if (currphy->tclk_term != desiredphyconfig->tclk_term) {
+		currphy->tclk_term = desiredphyconfig->tclk_term;
+		currphy_u->tclk_term = true;
+		update_phy_cfg1 = true;
+	}
+	if (currphy->tclk_miss != desiredphyconfig->tclk_miss) {
+		currphy->tclk_miss = desiredphyconfig->tclk_miss;
+		currphy_u->tclk_miss = true;
+		update_phy_cfg1 = true;
+	}
+	if (currphy->tclk_settle != desiredphyconfig->tclk_settle) {
+		currphy->tclk_settle = desiredphyconfig->tclk_settle;
+		currphy_u->tclk_settle = true;
+		update_phy_cfg1 = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_calc_phy_cfg0 - Calculates D-PHY config based on the MIPIClk speed.
+ * @mipiclk: MIPI clock frequency being used with CSI2 sensor.
+ * @lbound_hs_settle: Lower bound for CSI2 High Speed Settle transition.
+ * @ubound_hs_settle: Upper bound for CSI2 High Speed Settle transition.
+ *
+ * From TRM, we have the same calculation for HS Termination signal.
+ *  THS_TERM  = ceil( 12.5ns / DDRCLK period ) - 1
+ * But for Settle, we use the mid value between the two passed boundaries from
+ * sensor:
+ *  THS_SETTLE = (Upper bound + Lower bound) / 2
+ *
+ * Always returns 0.
+ */
+int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
+							u32 ubound_hs_settle)
+{
+	struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
+	struct isp_csi2_phy_cfg_update *currphy_u =
+						&current_csi2_cfg_update.phy;
+	u32 tmp, ddrclk = mipiclk >> 1;
+
+	/* Calculate THS_TERM */
+	tmp = ddrclk / 80000000;
+	if ((ddrclk % 80000000) > 0)
+		tmp++;
+	currphy->ths_term = tmp - 1;
+	currphy_u->ths_term = true;
+
+	/* Calculate THS_SETTLE */
+	currphy->ths_settle = (ubound_hs_settle + lbound_hs_settle) / 2;
+
+	currphy_u->ths_settle = true;
+	isp_csi2_phy_update(true);
+	return 0;
+}
+EXPORT_SYMBOL(isp_csi2_calc_phy_cfg0);
+
+/**
+ * isp_csi2_phy_update - Applies CSI2 D-PHY configuration.
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_phy_config_*() functions.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_phy_config_*() functions, unless the force_update flag is
+ * set to true.
+ * Always returns 0.
+ **/
+int isp_csi2_phy_update(bool force_update)
+{
+	struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
+	struct isp_csi2_phy_cfg_update *currphy_u =
+						&current_csi2_cfg_update.phy;
+	u32 reg;
+
+	if (update_phy_cfg0 || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
+		if (currphy_u->ths_term || force_update) {
+			reg &= ~ISPCSI2PHY_CFG0_THS_TERM_MASK;
+			reg |= (currphy->ths_term <<
+					ISPCSI2PHY_CFG0_THS_TERM_SHIFT);
+			currphy_u->ths_term = false;
+		}
+		if (currphy_u->ths_settle || force_update) {
+			reg &= ~ISPCSI2PHY_CFG0_THS_SETTLE_MASK;
+			reg |= (currphy->ths_settle <<
+					ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT);
+			currphy_u->ths_settle = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
+		update_phy_cfg0 = false;
+	}
+
+	if (update_phy_cfg1 || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
+		if (currphy_u->tclk_term || force_update) {
+			reg &= ~ISPCSI2PHY_CFG1_TCLK_TERM_MASK;
+			reg |= (currphy->tclk_term <<
+					ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT);
+			currphy_u->tclk_term = false;
+		}
+		if (currphy_u->tclk_miss || force_update) {
+			reg &= ~ISPCSI2PHY_CFG1_TCLK_MISS_MASK;
+			reg |= (currphy->tclk_miss <<
+					ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT);
+			currphy_u->tclk_miss = false;
+		}
+		if (currphy_u->tclk_settle || force_update) {
+			reg &= ~ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK;
+			reg |= (currphy->tclk_settle <<
+					ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT);
+			currphy_u->tclk_settle = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
+		update_phy_cfg1 = false;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_phy_get - Gets CSI2 D-PHY configuration
+ *
+ * Gets settings from HW registers and fills in the internal driver memory
+ * Always returns 0.
+ **/
+int isp_csi2_phy_get(void)
+{
+	struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
+	struct isp_csi2_phy_cfg_update *currphy_u =
+						&current_csi2_cfg_update.phy;
+	u32 reg;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
+	currphy->ths_term = (reg & ISPCSI2PHY_CFG0_THS_TERM_MASK) >>
+						ISPCSI2PHY_CFG0_THS_TERM_SHIFT;
+	currphy_u->ths_term = false;
+
+	currphy->ths_settle = (reg & ISPCSI2PHY_CFG0_THS_SETTLE_MASK) >>
+					ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT;
+	currphy_u->ths_settle = false;
+	update_phy_cfg0 = false;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
+
+	currphy->tclk_term = (reg & ISPCSI2PHY_CFG1_TCLK_TERM_MASK) >>
+						ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT;
+	currphy_u->tclk_term = false;
+
+	currphy->tclk_miss = (reg & ISPCSI2PHY_CFG1_TCLK_MISS_MASK) >>
+						ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT;
+	currphy_u->tclk_miss = false;
+
+	currphy->tclk_settle = (reg & ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK) >>
+					ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT;
+	currphy_u->tclk_settle = false;
+
+	update_phy_cfg1 = false;
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_config_forcerxmode - Sets Force Rx mode on stop state count
+ * @force_rx_mode: Boolean to enable/disable forcing Rx mode in CSI2 receiver
+ *
+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
+ **/
+int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode)
+{
+	struct isp_csi2_timings_cfg *currtimings;
+	struct isp_csi2_timings_cfg_update *currtimings_u;
+
+	if (io < 1 || io > 2) {
+		printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
+		return -EINVAL;
+	}
+
+	currtimings = &current_csi2_cfg.timings[io - 1];
+	currtimings_u = &current_csi2_cfg_update.timings[io - 1];
+	if (currtimings->force_rx_mode != force_rx_mode) {
+		currtimings->force_rx_mode = force_rx_mode;
+		currtimings_u->force_rx_mode = true;
+		update_timing = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_config_stopstate_16x - Sets 16x factor for L3 cycles
+ * @stop_state_16x: Boolean to use or not use the 16x multiplier for stop count
+ *
+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
+ **/
+int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x)
+{
+	struct isp_csi2_timings_cfg *currtimings;
+	struct isp_csi2_timings_cfg_update *currtimings_u;
+
+	if (io < 1 || io > 2) {
+		printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
+		return -EINVAL;
+	}
+
+	currtimings = &current_csi2_cfg.timings[io - 1];
+	currtimings_u = &current_csi2_cfg_update.timings[io - 1];
+	if (currtimings->stop_state_16x != stop_state_16x) {
+		currtimings->stop_state_16x = stop_state_16x;
+		currtimings_u->stop_state_16x = true;
+		update_timing = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_config_stopstate_4x - Sets 4x factor for L3 cycles
+ * @stop_state_4x: Boolean to use or not use the 4x multiplier for stop count
+ *
+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
+ **/
+int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x)
+{
+	struct isp_csi2_timings_cfg *currtimings;
+	struct isp_csi2_timings_cfg_update *currtimings_u;
+
+	if (io < 1 || io > 2) {
+		printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
+		return -EINVAL;
+	}
+
+	currtimings = &current_csi2_cfg.timings[io - 1];
+	currtimings_u = &current_csi2_cfg_update.timings[io - 1];
+	if (currtimings->stop_state_4x != stop_state_4x) {
+		currtimings->stop_state_4x = stop_state_4x;
+		currtimings_u->stop_state_4x = true;
+		update_timing = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_config_stopstate_cnt - Sets L3 cycles
+ * @stop_state_counter: Stop state counter value for L3 cycles
+ *
+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
+ **/
+int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter)
+{
+	struct isp_csi2_timings_cfg *currtimings;
+	struct isp_csi2_timings_cfg_update *currtimings_u;
+
+	if (io < 1 || io > 2) {
+		printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
+		return -EINVAL;
+	}
+
+	currtimings = &current_csi2_cfg.timings[io - 1];
+	currtimings_u = &current_csi2_cfg_update.timings[io - 1];
+	if (currtimings->stop_state_counter != stop_state_counter) {
+		currtimings->stop_state_counter = (stop_state_counter & 0x1FFF);
+		currtimings_u->stop_state_counter = true;
+		update_timing = true;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_update - Applies specified CSI2 timing configuration.
+ * @io: IO number (1 or 2) which specifies which ComplexIO are we updating
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_timings_config_*() functions.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_timings_config_*() functions, unless the force_update flag is
+ * set to true.
+ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
+ **/
+int isp_csi2_timings_update(u8 io, bool force_update)
+{
+	struct isp_csi2_timings_cfg *currtimings;
+	struct isp_csi2_timings_cfg_update *currtimings_u;
+	u32 reg;
+
+	if (io < 1 || io > 2) {
+		printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
+		return -EINVAL;
+	}
+
+	currtimings = &current_csi2_cfg.timings[io - 1];
+	currtimings_u = &current_csi2_cfg_update.timings[io - 1];
+
+	if (update_timing || force_update) {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
+		if (currtimings_u->force_rx_mode || force_update) {
+			reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io);
+			if (currtimings->force_rx_mode)
+				reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE
+									(io);
+			else
+				reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE
+									(io);
+			currtimings_u->force_rx_mode = false;
+		}
+		if (currtimings_u->stop_state_16x || force_update) {
+			reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io);
+			if (currtimings->stop_state_16x)
+				reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE
+									(io);
+			else
+				reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE
+									(io);
+			currtimings_u->stop_state_16x = false;
+		}
+		if (currtimings_u->stop_state_4x || force_update) {
+			reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io);
+			if (currtimings->stop_state_4x) {
+				reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE
+									(io);
+			} else {
+				reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE
+									(io);
+			}
+			currtimings_u->stop_state_4x = false;
+		}
+		if (currtimings_u->stop_state_counter || force_update) {
+			reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io);
+			reg |= currtimings->stop_state_counter <<
+				ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
+			currtimings_u->stop_state_counter = false;
+		}
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
+		update_timing = false;
+	}
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_get - Gets specific CSI2 ComplexIO timing configuration
+ * @io: IO number (1 or 2) which specifies which ComplexIO are we getting
+ *
+ * Gets settings from HW registers and fills in the internal driver memory
+ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
+ **/
+int isp_csi2_timings_get(u8 io)
+{
+	struct isp_csi2_timings_cfg *currtimings;
+	struct isp_csi2_timings_cfg_update *currtimings_u;
+	u32 reg;
+
+	if (io < 1 || io > 2) {
+		printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
+		return -EINVAL;
+	}
+
+	currtimings = &current_csi2_cfg.timings[io - 1];
+	currtimings_u = &current_csi2_cfg_update.timings[io - 1];
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
+	if ((reg & ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io)) ==
+				ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(io))
+		currtimings->force_rx_mode = true;
+	else
+		currtimings->force_rx_mode = false;
+	currtimings_u->force_rx_mode = false;
+
+	if ((reg & ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io)) ==
+				ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(io))
+		currtimings->stop_state_16x = true;
+	else
+		currtimings->stop_state_16x = false;
+	currtimings_u->stop_state_16x = false;
+
+	if ((reg & ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io)) ==
+				ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(io))
+		currtimings->stop_state_4x = true;
+	else
+		currtimings->stop_state_4x = false;
+	currtimings_u->stop_state_4x = false;
+
+	currtimings->stop_state_counter = (reg &
+			ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io)) >>
+			ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
+	currtimings_u->stop_state_counter = false;
+	update_timing = false;
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_update_all - Applies specified CSI2 timing configuration.
+ * @force_update: Flag to force rewrite of registers, even if they haven't been
+ *                updated with the isp_csi2_timings_config_*() functions.
+ *
+ * It only saves settings when they were previously updated using the
+ * isp_csi2_timings_config_*() functions, unless the force_update flag is
+ * set to true.
+ * Always returns 0.
+ **/
+int isp_csi2_timings_update_all(bool force_update)
+{
+	int i;
+
+	for (i = 1; i < 3; i++)
+		isp_csi2_timings_update(i, force_update);
+	return 0;
+}
+
+/**
+ * isp_csi2_timings_get_all - Gets all CSI2 ComplexIO timing configurations
+ *
+ * Always returns 0.
+ **/
+int isp_csi2_timings_get_all(void)
+{
+	int i;
+
+	for (i = 1; i < 3; i++)
+		isp_csi2_timings_get(i);
+	return 0;
+}
+
+/**
+ * isp_csi2_isr - CSI2 interrupt handling.
+ **/
+void isp_csi2_isr(void)
+{
+	u32 csi2_irqstatus, cpxio1_irqstatus, ctxirqstatus;
+
+	csi2_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_IRQSTATUS);
+	isp_reg_writel(csi2_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_IRQSTATUS);
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
+		cpxio1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_COMPLEXIO1_IRQSTATUS);
+		isp_reg_writel(cpxio1_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_COMPLEXIO1_IRQSTATUS);
+		printk(KERN_ERR "CSI2: ComplexIO Error IRQ %x\n",
+							cpxio1_irqstatus);
+	}
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) {
+		ctxirqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_IRQSTATUS(0));
+		isp_reg_writel(ctxirqstatus, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_IRQSTATUS(0));
+	}
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_OCP_ERR_IRQ)
+		printk(KERN_ERR "CSI2: OCP Transmission Error\n");
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ)
+		printk(KERN_ERR "CSI2: Short packet receive error\n");
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
+		printk(KERN_DEBUG "CSI2: ECC correction done\n");
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ)
+		printk(KERN_ERR "CSI2: ECC correction failed\n");
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ)
+		printk(KERN_ERR "CSI2: ComplexIO #2 failed\n");
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)
+		printk(KERN_ERR "CSI2: FIFO overflow error\n");
+
+	return;
+}
+EXPORT_SYMBOL(isp_csi2_isr);
+
+/**
+ * isp_csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
+ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
+ **/
+void isp_csi2_irq_complexio1_set(int enable)
+{
+	u32 reg;
+	reg = ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1 |
+				ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1;
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_COMPLEXIO1_IRQSTATUS);
+	if (enable) {
+		reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_COMPLEXIO1_IRQENABLE);
+	} else
+		reg = 0;
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_COMPLEXIO1_IRQENABLE);
+}
+EXPORT_SYMBOL(isp_csi2_irq_complexio1_set);
+
+/**
+ * isp_csi2_irq_ctx_set - Enables CSI2 Context IRQs.
+ * @enable: Enable/disable CSI2 Context interrupts
+ **/
+void isp_csi2_irq_ctx_set(int enable)
+{
+	u32 reg;
+	int i;
+
+	reg = ISPCSI2_CTX_IRQSTATUS_FS_IRQ | ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
+	for (i = 0; i < 8; i++) {
+		isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_IRQSTATUS(i));
+		if (enable) {
+			isp_reg_or(OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_IRQENABLE(i), reg);
+		} else {
+			isp_reg_writel(0, OMAP3_ISP_IOMEM_CSI2A,
+						ISPCSI2_CTX_IRQENABLE(i));
+		}
+	}
+
+}
+EXPORT_SYMBOL(isp_csi2_irq_ctx_set);
+
+/**
+ * isp_csi2_irq_status_set - Enables CSI2 Status IRQs.
+ * @enable: Enable/disable CSI2 Status interrupts
+ **/
+void isp_csi2_irq_status_set(int enable)
+{
+	u32 reg;
+	reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
+				ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
+				ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
+				ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
+				ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
+				ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
+				ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
+				ISPCSI2_IRQSTATUS_CONTEXT(0);
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQSTATUS);
+	if (enable)
+		reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
+	else
+		reg = 0;
+
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
+}
+EXPORT_SYMBOL(isp_csi2_irq_status_set);
+
+/**
+ * isp_csi2_irq_status_set - Enables main CSI2 IRQ.
+ * @enable: Enable/disable main CSI2 interrupt
+ **/
+void isp_csi2_irq_set(int enable)
+{
+	isp_reg_writel(IRQ0STATUS_CSIA_IRQ, OMAP3_ISP_IOMEM_MAIN,
+					ISP_IRQ0STATUS);
+	isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+					~IRQ0ENABLE_CSIA_IRQ,
+					(enable ? IRQ0ENABLE_CSIA_IRQ : 0));
+}
+EXPORT_SYMBOL(isp_csi2_irq_set);
+
+/**
+ * isp_csi2_irq_all_set - Enable/disable CSI2 interrupts.
+ * @enable: 0-Disable, 1-Enable.
+ **/
+void isp_csi2_irq_all_set(int enable)
+{
+	if (enable) {
+		isp_csi2_irq_complexio1_set(enable);
+		isp_csi2_irq_ctx_set(enable);
+		isp_csi2_irq_status_set(enable);
+		isp_csi2_irq_set(enable);
+	} else {
+		isp_csi2_irq_set(enable);
+		isp_csi2_irq_status_set(enable);
+		isp_csi2_irq_ctx_set(enable);
+		isp_csi2_irq_complexio1_set(enable);
+	}
+	return;
+}
+EXPORT_SYMBOL(isp_csi2_irq_all_set);
+
+/**
+ * isp_csi2_reset - Resets the CSI2 module.
+ *
+ * Returns 0 if successful, or -EBUSY if power command didn't respond.
+ **/
+int isp_csi2_reset(void)
+{
+	u32 reg;
+	u8 soft_reset_retries = 0;
+	int i;
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
+	reg |= ISPCSI2_SYSCONFIG_SOFT_RESET_RESET;
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
+
+	do {
+		reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSSTATUS) &
+				ISPCSI2_SYSSTATUS_RESET_DONE_MASK;
+		if (reg == ISPCSI2_SYSSTATUS_RESET_DONE_DONE)
+			break;
+		soft_reset_retries++;
+		if (soft_reset_retries < 5)
+			udelay(100);
+	} while (soft_reset_retries < 5);
+
+	if (soft_reset_retries == 5) {
+		printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
+		return -EBUSY;
+	}
+
+	reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
+	reg &= ~ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK;
+	reg |= ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO;
+	reg &= ~ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK;
+	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
+
+	uses_videoport = false;
+	update_complexio_cfg1 = false;
+	update_phy_cfg0 = false;
+	update_phy_cfg1 = false;
+	for (i = 0; i < 8; i++) {
+		update_ctx_ctrl1[i] = false;
+		update_ctx_ctrl2[i] = false;
+		update_ctx_ctrl3[i] = false;
+	}
+	update_timing = false;
+	update_ctrl = false;
+
+	isp_csi2_complexio_lanes_get();
+	isp_csi2_ctrl_get();
+	isp_csi2_ctx_get_all();
+	isp_csi2_phy_get();
+	isp_csi2_timings_get_all();
+
+	isp_csi2_complexio_power_autoswitch(true);
+	isp_csi2_complexio_power(ISP_CSI2_POWER_ON);
+
+	isp_csi2_timings_config_forcerxmode(1, true);
+	isp_csi2_timings_config_stopstate_cnt(1, 0x1FF);
+	isp_csi2_timings_update_all(true);
+
+	return 0;
+}
+
+/**
+ * isp_csi2_enable - Enables the CSI2 module.
+ * @enable: Enables/disables the CSI2 module.
+ **/
+void isp_csi2_enable(int enable)
+{
+	if (enable) {
+		isp_csi2_ctx_config_enabled(0, true);
+		isp_csi2_ctx_config_eof_enabled(0, true);
+		isp_csi2_ctx_config_checksum_enabled(0, true);
+		isp_csi2_ctx_update(0, false);
+
+		isp_csi2_ctrl_config_ecc_enable(true);
+		isp_csi2_ctrl_config_if_enable(true);
+		isp_csi2_ctrl_update(false);
+	} else {
+		isp_csi2_ctx_config_enabled(0, false);
+		isp_csi2_ctx_config_eof_enabled(0, false);
+		isp_csi2_ctx_config_checksum_enabled(0, false);
+		isp_csi2_ctx_update(0, false);
+
+		isp_csi2_ctrl_config_ecc_enable(false);
+		isp_csi2_ctrl_config_if_enable(false);
+		isp_csi2_ctrl_update(false);
+	}
+}
+EXPORT_SYMBOL(isp_csi2_enable);
+
+/**
+ * isp_csi2_regdump - Prints CSI2 debug information.
+ **/
+void isp_csi2_regdump(void)
+{
+	printk(KERN_DEBUG "-------------Register dump-------------\n");
+
+	printk(KERN_DEBUG "ISP_CTRL: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
+	printk(KERN_DEBUG "ISP_TCTRL_CTRL: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
+
+	printk(KERN_DEBUG "ISPCCDC_SDR_ADDR: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
+	printk(KERN_DEBUG "ISPCCDC_SYN_MODE: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
+	printk(KERN_DEBUG "ISPCCDC_CFG: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
+	printk(KERN_DEBUG "ISPCCDC_FMTCFG: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
+	printk(KERN_DEBUG "ISPCCDC_HSIZE_OFF: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
+	printk(KERN_DEBUG "ISPCCDC_HORZ_INFO: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
+	printk(KERN_DEBUG "ISPCCDC_VERT_START: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
+				ISPCCDC_VERT_START));
+	printk(KERN_DEBUG "ISPCCDC_VERT_LINES: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
+				ISPCCDC_VERT_LINES));
+
+	printk(KERN_DEBUG "ISPCSI2_COMPLEXIO_CFG1: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_COMPLEXIO_CFG1));
+	printk(KERN_DEBUG "ISPCSI2_SYSSTATUS: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_SYSSTATUS));
+	printk(KERN_DEBUG "ISPCSI2_SYSCONFIG: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_SYSCONFIG));
+	printk(KERN_DEBUG "ISPCSI2_IRQENABLE: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_IRQENABLE));
+	printk(KERN_DEBUG "ISPCSI2_IRQSTATUS: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_IRQSTATUS));
+
+	printk(KERN_DEBUG "ISPCSI2_CTX_IRQENABLE(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_IRQENABLE(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTX_IRQSTATUS(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_IRQSTATUS(0)));
+	printk(KERN_DEBUG "ISPCSI2_TIMING: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING));
+	printk(KERN_DEBUG "ISPCSI2PHY_CFG0: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
+				ISPCSI2PHY_CFG0));
+	printk(KERN_DEBUG "ISPCSI2PHY_CFG1: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
+				ISPCSI2PHY_CFG1));
+	printk(KERN_DEBUG "ISPCSI2_CTX_CTRL1(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_CTRL1(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTX_CTRL2(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_CTRL2(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTX_CTRL3(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_CTRL3(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTX_DAT_OFST(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_DAT_OFST(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PING_ADDR(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_DAT_PING_ADDR(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PONG_ADDR(0): %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
+				ISPCSI2_CTX_DAT_PONG_ADDR(0)));
+	printk(KERN_DEBUG "ISPCSI2_CTRL: %x\n",
+			isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL));
+	printk(KERN_DEBUG "---------------------------------------\n");
+}
+
+/**
+ * isp_csi2_cleanup - Routine for module driver cleanup
+ **/
+void isp_csi2_cleanup(void)
+{
+	return;
+}
+
+/**
+ * isp_csi2_init - Routine for module driver init
+ **/
+int __init isp_csi2_init(void)
+{
+	int i;
+
+	update_complexio_cfg1 = false;
+	update_phy_cfg0 = false;
+	update_phy_cfg1 = false;
+	for (i = 0; i < 8; i++) {
+		update_ctx_ctrl1[i] = false;
+		update_ctx_ctrl2[i] = false;
+		update_ctx_ctrl3[i] = false;
+	}
+	update_timing = false;
+	update_ctrl = false;
+
+	memset(&current_csi2_cfg, 0, sizeof(current_csi2_cfg));
+	memset(&current_csi2_cfg_update, 0, sizeof(current_csi2_cfg_update));
+	return 0;
+}
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("ISP CSI2 Receiver Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/isp/ispcsi2.h b/drivers/media/video/isp/ispcsi2.h
new file mode 100644
index 0000000..56e3d25
--- /dev/null
+++ b/drivers/media/video/isp/ispcsi2.h
@@ -0,0 +1,232 @@
+/*
+ * ispcsi2.h
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * Contributors:
+ * 	Sergio Aguirre <saaguirre@ti.com>
+ * 	Dominic Curran <dcurran@ti.com>
+ *
+ * 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_CSI2_API_H
+#define OMAP_ISP_CSI2_API_H
+#include <linux/videodev2.h>
+
+enum isp_csi2_irqevents {
+	OCP_ERR_IRQ = 0x4000,
+	SHORT_PACKET_IRQ = 0x2000,
+	ECC_CORRECTION_IRQ = 0x1000,
+	ECC_NO_CORRECTION_IRQ = 0x800,
+	COMPLEXIO2_ERR_IRQ = 0x400,
+	COMPLEXIO1_ERR_IRQ = 0x200,
+	FIFO_OVF_IRQ = 0x100,
+	CONTEXT7 = 0x80,
+	CONTEXT6 = 0x40,
+	CONTEXT5 = 0x20,
+	CONTEXT4 = 0x10,
+	CONTEXT3 = 0x8,
+	CONTEXT2 = 0x4,
+	CONTEXT1 = 0x2,
+	CONTEXT0 = 0x1,
+};
+
+enum isp_csi2_ctx_irqevents {
+	CTX_ECC_CORRECTION = 0x100,
+	CTX_LINE_NUMBER = 0x80,
+	CTX_FRAME_NUMBER = 0x40,
+	CTX_CS = 0x20,
+	CTX_LE = 0x8,
+	CTX_LS = 0x4,
+	CTX_FE = 0x2,
+	CTX_FS = 0x1,
+};
+
+enum isp_csi2_power_cmds {
+	ISP_CSI2_POWER_OFF,
+	ISP_CSI2_POWER_ON,
+	ISP_CSI2_POWER_ULPW,
+};
+
+enum isp_csi2_frame_mode {
+	ISP_CSI2_FRAME_IMMEDIATE,
+	ISP_CSI2_FRAME_AFTERFEC,
+};
+
+struct csi2_lanecfg {
+	u8 pos;
+	u8 pol;
+};
+
+struct isp_csi2_lanes_cfg {
+	struct csi2_lanecfg data[4];
+	struct csi2_lanecfg clk;
+};
+
+struct isp_csi2_lanes_cfg_update {
+	bool data[4];
+	bool clk;
+};
+
+struct isp_csi2_phy_cfg {
+	u8 ths_term;
+	u8 ths_settle;
+	u8 tclk_term;
+	unsigned tclk_miss:1;
+	u8 tclk_settle;
+};
+
+struct isp_csi2_phy_cfg_update {
+	bool ths_term;
+	bool ths_settle;
+	bool tclk_term;
+	bool tclk_miss;
+	bool tclk_settle;
+};
+
+struct isp_csi2_ctx_cfg {
+	u8 virtual_id;
+	u8 frame_count;
+	struct v4l2_pix_format format;
+	u16 alpha;
+	u16 data_offset;
+	u32 ping_addr;
+	u32 pong_addr;
+	bool eof_enabled;
+	bool eol_enabled;
+	bool checksum_enabled;
+	bool enabled;
+};
+
+struct isp_csi2_ctx_cfg_update {
+	bool virtual_id;
+	bool frame_count;
+	bool format;
+	bool alpha;
+	bool data_offset;
+	bool ping_addr;
+	bool pong_addr;
+	bool eof_enabled;
+	bool eol_enabled;
+	bool checksum_enabled;
+	bool enabled;
+};
+
+struct isp_csi2_timings_cfg {
+	bool force_rx_mode;
+	bool stop_state_16x;
+	bool stop_state_4x;
+	u16 stop_state_counter;
+};
+
+struct isp_csi2_timings_cfg_update {
+	bool force_rx_mode;
+	bool stop_state_16x;
+	bool stop_state_4x;
+	bool stop_state_counter;
+};
+
+struct isp_csi2_ctrl_cfg {
+	bool vp_clk_enable;
+	bool vp_only_enable;
+	u8 vp_out_ctrl;
+	bool debug_enable;
+	u8 burst_size;
+	enum isp_csi2_frame_mode frame_mode;
+	bool ecc_enable;
+	bool secure_mode;
+	bool if_enable;
+};
+
+struct isp_csi2_ctrl_cfg_update {
+	bool vp_clk_enable;
+	bool vp_only_enable;
+	bool vp_out_ctrl;
+	bool debug_enable;
+	bool burst_size;
+	bool frame_mode;
+	bool ecc_enable;
+	bool secure_mode;
+	bool if_enable;
+};
+
+struct isp_csi2_cfg {
+	struct isp_csi2_lanes_cfg lanes;
+	struct isp_csi2_phy_cfg phy;
+	struct isp_csi2_ctx_cfg contexts[8];
+	struct isp_csi2_timings_cfg timings[2];
+	struct isp_csi2_ctrl_cfg ctrl;
+};
+
+struct isp_csi2_cfg_update {
+	struct isp_csi2_lanes_cfg_update lanes;
+	struct isp_csi2_phy_cfg_update phy;
+	struct isp_csi2_ctx_cfg_update contexts[8];
+	struct isp_csi2_timings_cfg_update timings[2];
+	struct isp_csi2_ctrl_cfg_update ctrl;
+};
+
+int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg);
+int isp_csi2_complexio_lanes_update(bool force_update);
+int isp_csi2_complexio_lanes_get(void);
+int isp_csi2_complexio_power_autoswitch(bool enable);
+int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd);
+int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode);
+int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable);
+int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable);
+int isp_csi2_ctrl_config_debug_enable(bool debug_enable);
+int isp_csi2_ctrl_config_burst_size(u8 burst_size);
+int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable);
+int isp_csi2_ctrl_config_secure_mode(bool secure_mode);
+int isp_csi2_ctrl_config_if_enable(bool if_enable);
+int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl);
+int isp_csi2_ctrl_update(bool force_update);
+int isp_csi2_ctrl_get(void);
+int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id);
+int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count);
+int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat);
+int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha);
+int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset);
+int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr);
+int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr);
+int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled);
+int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled);
+int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled);
+int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled);
+int isp_csi2_ctx_update(u8 ctxnum, bool force_update);
+int isp_csi2_ctx_get(u8 ctxnum);
+int isp_csi2_ctx_update_all(bool force_update);
+int isp_csi2_ctx_get_all(void);
+int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig);
+int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
+							u32 ubound_hs_settle);
+int isp_csi2_phy_update(bool force_update);
+int isp_csi2_phy_get(void);
+int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode);
+int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x);
+int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x);
+int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter);
+int isp_csi2_timings_update(u8 io, bool force_update);
+int isp_csi2_timings_get(u8 io);
+int isp_csi2_timings_update_all(bool force_update);
+int isp_csi2_timings_get_all(void);
+void isp_csi2_irq_complexio1_set(int enable);
+void isp_csi2_irq_ctx_set(int enable);
+void isp_csi2_irq_status_set(int enable);
+void isp_csi2_irq_set(int enable);
+void isp_csi2_irq_all_set(int enable);
+
+void isp_csi2_isr(void);
+int isp_csi2_reset(void);
+void isp_csi2_enable(int enable);
+void isp_csi2_regdump(void);
+
+#endif	/* OMAP_ISP_CSI2_H */
+
-- 
1.5.6.5


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

* [PATCH 8/9] omap3isp: Add ISP tables
  2009-03-03 10:06             ` [PATCH 7/9] omap3isp: Add CSI2 interface support Sakari Ailus
@ 2009-03-03 10:06               ` Sakari Ailus
  2009-03-03 10:06                 ` [PATCH 9/9] omap34xxcam: Add camera driver Sakari Ailus
  0 siblings, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

* Blue Gamma gain table
* CFA gain table
* Green Gamma gain table
* Luma Enhancement gain table
* Noise filter gain table
* Red Gamma gain table

TODO:

- Get rid of this kind of tables. Either generate them at runtime or
  use a user space program to fill defaults.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/isp/bluegamma_table.h    | 1040 ++++++++++++++++++++++++++
 drivers/media/video/isp/cfa_coef_table.h     |  603 +++++++++++++++
 drivers/media/video/isp/greengamma_table.h   | 1040 ++++++++++++++++++++++++++
 drivers/media/video/isp/luma_enhance_table.h |  144 ++++
 drivers/media/video/isp/noise_filter_table.h |   79 ++
 drivers/media/video/isp/redgamma_table.h     | 1040 ++++++++++++++++++++++++++
 6 files changed, 3946 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/isp/bluegamma_table.h
 create mode 100644 drivers/media/video/isp/cfa_coef_table.h
 create mode 100644 drivers/media/video/isp/greengamma_table.h
 create mode 100644 drivers/media/video/isp/luma_enhance_table.h
 create mode 100644 drivers/media/video/isp/noise_filter_table.h
 create mode 100644 drivers/media/video/isp/redgamma_table.h

diff --git a/drivers/media/video/isp/bluegamma_table.h b/drivers/media/video/isp/bluegamma_table.h
new file mode 100644
index 0000000..301382a
--- /dev/null
+++ b/drivers/media/video/isp/bluegamma_table.h
@@ -0,0 +1,1040 @@
+/*
+ * bluegamma_table.h
+ *
+ * Gamma Table values for BLUE for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+
+0,
+0,
+1,
+2,
+3,
+3,
+4,
+5,
+6,
+8,
+10,
+12,
+14,
+16,
+18,
+20,
+22,
+23,
+25,
+26,
+28,
+29,
+31,
+32,
+34,
+35,
+36,
+37,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+63,
+64,
+65,
+66,
+66,
+67,
+68,
+69,
+69,
+70,
+71,
+72,
+72,
+73,
+74,
+75,
+75,
+76,
+77,
+78,
+78,
+79,
+80,
+81,
+81,
+82,
+83,
+84,
+84,
+85,
+86,
+87,
+88,
+88,
+89,
+90,
+91,
+91,
+92,
+93,
+94,
+94,
+95,
+96,
+97,
+97,
+98,
+98,
+99,
+99,
+100,
+100,
+101,
+101,
+102,
+103,
+104,
+104,
+105,
+106,
+107,
+108,
+108,
+109,
+110,
+111,
+111,
+112,
+113,
+114,
+114,
+115,
+116,
+117,
+117,
+118,
+119,
+119,
+120,
+120,
+121,
+121,
+122,
+122,
+123,
+123,
+124,
+124,
+125,
+125,
+126,
+126,
+127,
+127,
+128,
+128,
+129,
+129,
+130,
+130,
+131,
+131,
+132,
+132,
+133,
+133,
+134,
+134,
+135,
+135,
+136,
+136,
+137,
+137,
+138,
+138,
+139,
+139,
+140,
+140,
+141,
+141,
+142,
+142,
+143,
+143,
+144,
+144,
+145,
+145,
+146,
+146,
+147,
+147,
+148,
+148,
+149,
+149,
+150,
+150,
+151,
+151,
+152,
+152,
+153,
+153,
+153,
+153,
+154,
+154,
+154,
+154,
+155,
+155,
+156,
+156,
+157,
+157,
+158,
+158,
+158,
+159,
+159,
+159,
+160,
+160,
+160,
+161,
+161,
+162,
+162,
+163,
+163,
+164,
+164,
+164,
+164,
+165,
+165,
+165,
+165,
+166,
+166,
+167,
+167,
+168,
+168,
+169,
+169,
+170,
+170,
+170,
+170,
+171,
+171,
+171,
+171,
+172,
+172,
+173,
+173,
+174,
+174,
+175,
+175,
+176,
+176,
+176,
+176,
+177,
+177,
+177,
+177,
+178,
+178,
+178,
+178,
+179,
+179,
+179,
+179,
+180,
+180,
+180,
+180,
+181,
+181,
+181,
+181,
+182,
+182,
+182,
+182,
+183,
+183,
+183,
+183,
+184,
+184,
+184,
+184,
+185,
+185,
+185,
+185,
+186,
+186,
+186,
+186,
+187,
+187,
+187,
+187,
+188,
+188,
+188,
+188,
+189,
+189,
+189,
+189,
+190,
+190,
+190,
+190,
+191,
+191,
+191,
+191,
+192,
+192,
+192,
+192,
+193,
+193,
+193,
+193,
+194,
+194,
+194,
+194,
+195,
+195,
+195,
+195,
+196,
+196,
+196,
+196,
+197,
+197,
+197,
+197,
+198,
+198,
+198,
+198,
+199,
+199,
+199,
+199,
+200,
+200,
+200,
+200,
+201,
+201,
+201,
+201,
+202,
+202,
+202,
+203,
+203,
+203,
+203,
+204,
+204,
+204,
+204,
+205,
+205,
+205,
+205,
+206,
+206,
+206,
+206,
+207,
+207,
+207,
+207,
+208,
+208,
+208,
+208,
+209,
+209,
+209,
+209,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+212,
+212,
+212,
+212,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+214,
+214,
+214,
+214,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+216,
+216,
+216,
+216,
+217,
+217,
+217,
+217,
+218,
+218,
+218,
+218,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+220,
+220,
+220,
+220,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+222,
+222,
+222,
+222,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+224,
+224,
+224,
+224,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+226,
+226,
+226,
+226,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+228,
+228,
+228,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+230,
+230,
+230,
+230,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+233,
+233,
+233,
+233,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+235,
+235,
+235,
+235,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+237,
+237,
+237,
+237,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+239,
+239,
+239,
+239,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+241,
+241,
+241,
+241,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+243,
+243,
+243,
+243,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+245,
+245,
+245,
+245,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+247,
+247,
+247,
+247,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+249,
+249,
+249,
+249,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+251,
+251,
+251,
+251,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+254,
+254,
+254,
+254,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255
diff --git a/drivers/media/video/isp/cfa_coef_table.h b/drivers/media/video/isp/cfa_coef_table.h
new file mode 100644
index 0000000..8cafa1f
--- /dev/null
+++ b/drivers/media/video/isp/cfa_coef_table.h
@@ -0,0 +1,603 @@
+/*
+ * cfa_coef_table.h
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *          Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *
+ * Written by Gjorgji Rosikopulos
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+244,
+0,
+247,
+0,
+12,
+27,
+36,
+247,
+250,
+0,
+27,
+0,
+4,
+250,
+12,
+244,
+248,
+0,
+0,
+0,
+0,
+40,
+0,
+0,
+244,
+12,
+250,
+4,
+0,
+27,
+0,
+250,
+247,
+36,
+27,
+12,
+0,
+247,
+0,
+244,
+0,
+0,
+40,
+0,
+0,
+0,
+0,
+248,
+244,
+0,
+247,
+0,
+12,
+27,
+36,
+247,
+250,
+0,
+27,
+0,
+4,
+250,
+12,
+244,
+248,
+0,
+0,
+0,
+0,
+40,
+0,
+0,
+244,
+12,
+250,
+4,
+0,
+27,
+0,
+250,
+247,
+36,
+27,
+12,
+0,
+247,
+0,
+244,
+0,
+0,
+40,
+0,
+0,
+0,
+0,
+248,
+244,
+0,
+247,
+0,
+12,
+27,
+36,
+247,
+250,
+0,
+27,
+0,
+4,
+250,
+12,
+244,
+248,
+0,
+0,
+0,
+0,
+40,
+0,
+0,
+244,
+12,
+250,
+4,
+0,
+27,
+0,
+250,
+247,
+36,
+27,
+12,
+0,
+247,
+0,
+244,
+0,
+0,
+40,
+0,
+0,
+0,
+0,
+248,
+0,
+247,
+0,
+244,
+247,
+36,
+27,
+12,
+0,
+27,
+0,
+250,
+244,
+12,
+250,
+4,
+0,
+0,
+0,
+248,
+0,
+0,
+40,
+0,
+4,
+250,
+12,
+244,
+250,
+0,
+27,
+0,
+12,
+27,
+36,
+247,
+244,
+0,
+247,
+0,
+0,
+40,
+0,
+0,
+248,
+0,
+0,
+0,
+0,
+247,
+0,
+244,
+247,
+36,
+27,
+12,
+0,
+27,
+0,
+250,
+244,
+12,
+250,
+4,
+0,
+0,
+0,
+248,
+0,
+0,
+40,
+0,
+4,
+250,
+12,
+244,
+250,
+0,
+27,
+0,
+12,
+27,
+36,
+247,
+244,
+0,
+247,
+0,
+0,
+40,
+0,
+0,
+248,
+0,
+0,
+0,
+0,
+247,
+0,
+244,
+247,
+36,
+27,
+12,
+0,
+27,
+0,
+250,
+244,
+12,
+250,
+4,
+0,
+0,
+0,
+248,
+0,
+0,
+40,
+0,
+4,
+250,
+12,
+244,
+250,
+0,
+27,
+0,
+12,
+27,
+36,
+247,
+244,
+0,
+247,
+0,
+0,
+40,
+0,
+0,
+248,
+0,
+0,
+0,
+4,
+250,
+12,
+244,
+250,
+0,
+27,
+0,
+12,
+27,
+36,
+247,
+244,
+0,
+247,
+0,
+0,
+0,
+0,
+248,
+0,
+0,
+40,
+0,
+0,
+247,
+0,
+244,
+247,
+36,
+27,
+12,
+0,
+27,
+0,
+250,
+244,
+12,
+250,
+4,
+0,
+40,
+0,
+0,
+248,
+0,
+0,
+0,
+4,
+250,
+12,
+244,
+250,
+0,
+27,
+0,
+12,
+27,
+36,
+247,
+244,
+0,
+247,
+0,
+0,
+0,
+0,
+248,
+0,
+0,
+40,
+0,
+0,
+247,
+0,
+244,
+247,
+36,
+27,
+12,
+0,
+27,
+0,
+250,
+244,
+12,
+250,
+4,
+0,
+40,
+0,
+0,
+248,
+0,
+0,
+0,
+4,
+250,
+12,
+244,
+250,
+0,
+27,
+0,
+12,
+27,
+36,
+247,
+244,
+0,
+247,
+0,
+0,
+0,
+0,
+248,
+0,
+0,
+40,
+0,
+0,
+247,
+0,
+244,
+247,
+36,
+27,
+12,
+0,
+27,
+0,
+250,
+244,
+12,
+250,
+4,
+0,
+40,
+0,
+0,
+248,
+0,
+0,
+0,
+244,
+12,
+250,
+4,
+0,
+27,
+0,
+250,
+247,
+36,
+27,
+12,
+0,
+247,
+0,
+244,
+248,
+0,
+0,
+0,
+0,
+40,
+0,
+0,
+244,
+0,
+247,
+0,
+12,
+27,
+36,
+247,
+250,
+0,
+27,
+0,
+4,
+250,
+12,
+244,
+0,
+0,
+40,
+0,
+0,
+0,
+0,
+248,
+244,
+12,
+250,
+4,
+0,
+27,
+0,
+250,
+247,
+36,
+27,
+12,
+0,
+247,
+0,
+244,
+248,
+0,
+0,
+0,
+0,
+40,
+0,
+0,
+244,
+0,
+247,
+0,
+12,
+27,
+36,
+247,
+250,
+0,
+27,
+0,
+4,
+250,
+12,
+244,
+0,
+0,
+40,
+0,
+0,
+0,
+0,
+248,
+244,
+12,
+250,
+4,
+0,
+27,
+0,
+250,
+247,
+36,
+27,
+12,
+0,
+247,
+0,
+244,
+248,
+0,
+0,
+0,
+0,
+40,
+0,
+0,
+244,
+0,
+247,
+0,
+12,
+27,
+36,
+247,
+250,
+0,
+27,
+0,
+4,
+250,
+12,
+244,
+0,
+0,
+40,
+0,
+0,
+0,
+0,
+248
+
diff --git a/drivers/media/video/isp/greengamma_table.h b/drivers/media/video/isp/greengamma_table.h
new file mode 100644
index 0000000..0f5c5e4
--- /dev/null
+++ b/drivers/media/video/isp/greengamma_table.h
@@ -0,0 +1,1040 @@
+/*
+ * greengamma_table.h
+ *
+ * Gamma Table values for GREEN for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+
+0,
+0,
+1,
+2,
+3,
+3,
+4,
+5,
+6,
+8,
+10,
+12,
+14,
+16,
+18,
+20,
+22,
+23,
+25,
+26,
+28,
+29,
+31,
+32,
+34,
+35,
+36,
+37,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+63,
+64,
+65,
+66,
+66,
+67,
+68,
+69,
+69,
+70,
+71,
+72,
+72,
+73,
+74,
+75,
+75,
+76,
+77,
+78,
+78,
+79,
+80,
+81,
+81,
+82,
+83,
+84,
+84,
+85,
+86,
+87,
+88,
+88,
+89,
+90,
+91,
+91,
+92,
+93,
+94,
+94,
+95,
+96,
+97,
+97,
+98,
+98,
+99,
+99,
+100,
+100,
+101,
+101,
+102,
+103,
+104,
+104,
+105,
+106,
+107,
+108,
+108,
+109,
+110,
+111,
+111,
+112,
+113,
+114,
+114,
+115,
+116,
+117,
+117,
+118,
+119,
+119,
+120,
+120,
+121,
+121,
+122,
+122,
+123,
+123,
+124,
+124,
+125,
+125,
+126,
+126,
+127,
+127,
+128,
+128,
+129,
+129,
+130,
+130,
+131,
+131,
+132,
+132,
+133,
+133,
+134,
+134,
+135,
+135,
+136,
+136,
+137,
+137,
+138,
+138,
+139,
+139,
+140,
+140,
+141,
+141,
+142,
+142,
+143,
+143,
+144,
+144,
+145,
+145,
+146,
+146,
+147,
+147,
+148,
+148,
+149,
+149,
+150,
+150,
+151,
+151,
+152,
+152,
+153,
+153,
+153,
+153,
+154,
+154,
+154,
+154,
+155,
+155,
+156,
+156,
+157,
+157,
+158,
+158,
+158,
+159,
+159,
+159,
+160,
+160,
+160,
+161,
+161,
+162,
+162,
+163,
+163,
+164,
+164,
+164,
+164,
+165,
+165,
+165,
+165,
+166,
+166,
+167,
+167,
+168,
+168,
+169,
+169,
+170,
+170,
+170,
+170,
+171,
+171,
+171,
+171,
+172,
+172,
+173,
+173,
+174,
+174,
+175,
+175,
+176,
+176,
+176,
+176,
+177,
+177,
+177,
+177,
+178,
+178,
+178,
+178,
+179,
+179,
+179,
+179,
+180,
+180,
+180,
+180,
+181,
+181,
+181,
+181,
+182,
+182,
+182,
+182,
+183,
+183,
+183,
+183,
+184,
+184,
+184,
+184,
+185,
+185,
+185,
+185,
+186,
+186,
+186,
+186,
+187,
+187,
+187,
+187,
+188,
+188,
+188,
+188,
+189,
+189,
+189,
+189,
+190,
+190,
+190,
+190,
+191,
+191,
+191,
+191,
+192,
+192,
+192,
+192,
+193,
+193,
+193,
+193,
+194,
+194,
+194,
+194,
+195,
+195,
+195,
+195,
+196,
+196,
+196,
+196,
+197,
+197,
+197,
+197,
+198,
+198,
+198,
+198,
+199,
+199,
+199,
+199,
+200,
+200,
+200,
+200,
+201,
+201,
+201,
+201,
+202,
+202,
+202,
+203,
+203,
+203,
+203,
+204,
+204,
+204,
+204,
+205,
+205,
+205,
+205,
+206,
+206,
+206,
+206,
+207,
+207,
+207,
+207,
+208,
+208,
+208,
+208,
+209,
+209,
+209,
+209,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+212,
+212,
+212,
+212,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+214,
+214,
+214,
+214,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+216,
+216,
+216,
+216,
+217,
+217,
+217,
+217,
+218,
+218,
+218,
+218,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+220,
+220,
+220,
+220,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+222,
+222,
+222,
+222,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+224,
+224,
+224,
+224,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+226,
+226,
+226,
+226,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+228,
+228,
+228,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+230,
+230,
+230,
+230,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+233,
+233,
+233,
+233,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+235,
+235,
+235,
+235,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+237,
+237,
+237,
+237,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+239,
+239,
+239,
+239,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+241,
+241,
+241,
+241,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+243,
+243,
+243,
+243,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+245,
+245,
+245,
+245,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+247,
+247,
+247,
+247,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+249,
+249,
+249,
+249,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+251,
+251,
+251,
+251,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+254,
+254,
+254,
+254,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255
diff --git a/drivers/media/video/isp/luma_enhance_table.h b/drivers/media/video/isp/luma_enhance_table.h
new file mode 100644
index 0000000..99c8b05
--- /dev/null
+++ b/drivers/media/video/isp/luma_enhance_table.h
@@ -0,0 +1,144 @@
+/*
+ * luma_enhance_table.h
+ *
+ * Luminance Enhancement table values for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1047552,
+1048575,
+1047551,
+1046527,
+1045503,
+1044479,
+1043455,
+1042431,
+1041407,
+1040383,
+1039359,
+1038335,
+1037311,
+1036287,
+1035263,
+1034239,
+1033215,
+1032191,
+1031167,
+1030143,
+1028096,
+1028096,
+1028096,
+1028096,
+1028096,
+1028096,
+1028096,
+1028096,
+1028096,
+1028096,
+1028100,
+1032196,
+1036292,
+1040388,
+1044484,
+0,
+0,
+0,
+5,
+5125,
+10245,
+15365,
+20485,
+25605,
+30720,
+30720,
+30720,
+30720,
+30720,
+30720,
+30720,
+30720,
+30720,
+30720,
+30720,
+31743,
+30719,
+29695,
+28671,
+27647,
+26623,
+25599,
+24575,
+23551,
+22527,
+21503,
+20479,
+19455,
+18431,
+17407,
+16383,
+15359,
+14335,
+13311,
+12287,
+11263,
+10239,
+9215,
+8191,
+7167,
+6143,
+5119,
+4095,
+3071,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024,
+1024
diff --git a/drivers/media/video/isp/noise_filter_table.h b/drivers/media/video/isp/noise_filter_table.h
new file mode 100644
index 0000000..7345f90
--- /dev/null
+++ b/drivers/media/video/isp/noise_filter_table.h
@@ -0,0 +1,79 @@
+/*
+ * noise_filter_table.h
+ *
+ * Noise Filter Table values for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+16,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31,
+31
diff --git a/drivers/media/video/isp/redgamma_table.h b/drivers/media/video/isp/redgamma_table.h
new file mode 100644
index 0000000..ad0232a
--- /dev/null
+++ b/drivers/media/video/isp/redgamma_table.h
@@ -0,0 +1,1040 @@
+/*
+ * redgamma_table.h
+ *
+ * Gamma Table values for RED for TI's OMAP3 Camera ISP
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+
+0,
+0,
+1,
+2,
+3,
+3,
+4,
+5,
+6,
+8,
+10,
+12,
+14,
+16,
+18,
+20,
+22,
+23,
+25,
+26,
+28,
+29,
+31,
+32,
+34,
+35,
+36,
+37,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+63,
+64,
+65,
+66,
+66,
+67,
+68,
+69,
+69,
+70,
+71,
+72,
+72,
+73,
+74,
+75,
+75,
+76,
+77,
+78,
+78,
+79,
+80,
+81,
+81,
+82,
+83,
+84,
+84,
+85,
+86,
+87,
+88,
+88,
+89,
+90,
+91,
+91,
+92,
+93,
+94,
+94,
+95,
+96,
+97,
+97,
+98,
+98,
+99,
+99,
+100,
+100,
+101,
+101,
+102,
+103,
+104,
+104,
+105,
+106,
+107,
+108,
+108,
+109,
+110,
+111,
+111,
+112,
+113,
+114,
+114,
+115,
+116,
+117,
+117,
+118,
+119,
+119,
+120,
+120,
+121,
+121,
+122,
+122,
+123,
+123,
+124,
+124,
+125,
+125,
+126,
+126,
+127,
+127,
+128,
+128,
+129,
+129,
+130,
+130,
+131,
+131,
+132,
+132,
+133,
+133,
+134,
+134,
+135,
+135,
+136,
+136,
+137,
+137,
+138,
+138,
+139,
+139,
+140,
+140,
+141,
+141,
+142,
+142,
+143,
+143,
+144,
+144,
+145,
+145,
+146,
+146,
+147,
+147,
+148,
+148,
+149,
+149,
+150,
+150,
+151,
+151,
+152,
+152,
+153,
+153,
+153,
+153,
+154,
+154,
+154,
+154,
+155,
+155,
+156,
+156,
+157,
+157,
+158,
+158,
+158,
+159,
+159,
+159,
+160,
+160,
+160,
+161,
+161,
+162,
+162,
+163,
+163,
+164,
+164,
+164,
+164,
+165,
+165,
+165,
+165,
+166,
+166,
+167,
+167,
+168,
+168,
+169,
+169,
+170,
+170,
+170,
+170,
+171,
+171,
+171,
+171,
+172,
+172,
+173,
+173,
+174,
+174,
+175,
+175,
+176,
+176,
+176,
+176,
+177,
+177,
+177,
+177,
+178,
+178,
+178,
+178,
+179,
+179,
+179,
+179,
+180,
+180,
+180,
+180,
+181,
+181,
+181,
+181,
+182,
+182,
+182,
+182,
+183,
+183,
+183,
+183,
+184,
+184,
+184,
+184,
+185,
+185,
+185,
+185,
+186,
+186,
+186,
+186,
+187,
+187,
+187,
+187,
+188,
+188,
+188,
+188,
+189,
+189,
+189,
+189,
+190,
+190,
+190,
+190,
+191,
+191,
+191,
+191,
+192,
+192,
+192,
+192,
+193,
+193,
+193,
+193,
+194,
+194,
+194,
+194,
+195,
+195,
+195,
+195,
+196,
+196,
+196,
+196,
+197,
+197,
+197,
+197,
+198,
+198,
+198,
+198,
+199,
+199,
+199,
+199,
+200,
+200,
+200,
+200,
+201,
+201,
+201,
+201,
+202,
+202,
+202,
+203,
+203,
+203,
+203,
+204,
+204,
+204,
+204,
+205,
+205,
+205,
+205,
+206,
+206,
+206,
+206,
+207,
+207,
+207,
+207,
+208,
+208,
+208,
+208,
+209,
+209,
+209,
+209,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+210,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+211,
+212,
+212,
+212,
+212,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+213,
+214,
+214,
+214,
+214,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+215,
+216,
+216,
+216,
+216,
+217,
+217,
+217,
+217,
+218,
+218,
+218,
+218,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+219,
+220,
+220,
+220,
+220,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+221,
+222,
+222,
+222,
+222,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+223,
+224,
+224,
+224,
+224,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+225,
+226,
+226,
+226,
+226,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+227,
+228,
+228,
+228,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+229,
+230,
+230,
+230,
+230,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+231,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+232,
+233,
+233,
+233,
+233,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+234,
+235,
+235,
+235,
+235,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+236,
+237,
+237,
+237,
+237,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+238,
+239,
+239,
+239,
+239,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+240,
+241,
+241,
+241,
+241,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+242,
+243,
+243,
+243,
+243,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+244,
+245,
+245,
+245,
+245,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+246,
+247,
+247,
+247,
+247,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+248,
+249,
+249,
+249,
+249,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+250,
+251,
+251,
+251,
+251,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+252,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+253,
+254,
+254,
+254,
+254,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255,
+255
-- 
1.5.6.5


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

* [PATCH 9/9] omap34xxcam: Add camera driver
  2009-03-03 10:06               ` [PATCH 8/9] omap3isp: Add ISP tables Sakari Ailus
@ 2009-03-03 10:06                 ` Sakari Ailus
  2009-03-03 17:31                   ` Alexey Klimov
  0 siblings, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 10:06 UTC (permalink / raw)
  To: linux-media; +Cc: linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

This is the camera driver for the OMAP 3 camera ISP and v4l2-int-device
sensors, lenses and (led) flashes. There are a few connections to OMAP
3 left but after those have been broken this is hardware independent.
Namely, the OMAP 3 ISP must offer a standard interface through
v4l2_subdev (or v4l2-int-device) first.

This driver has originated from the omap24xxcam camera driver written
specifically for OMAP 2.

TODO:

- Convert to use v4l2_subdev instead of v4l2-int-device.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/Kconfig       |    9 +
 drivers/media/video/Makefile      |    2 +
 drivers/media/video/omap34xxcam.c | 1962 +++++++++++++++++++++++++++++++++++++
 drivers/media/video/omap34xxcam.h |  207 ++++
 4 files changed, 2180 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/omap34xxcam.c
 create mode 100644 drivers/media/video/omap34xxcam.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 19cf3b8..3cdb5a4 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -711,6 +711,15 @@ 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
+	select OMAP_IOMMU
+	depends on VIDEO_V4L2 && ARCH_OMAP34XX
+	---help---
+	  Driver for an OMAP 3 camera controller.
+
 config SOC_CAMERA
 	tristate "SoC camera support"
 	depends on VIDEO_V4L2 && HAS_DMA
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index e654270..74a684e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -108,6 +108,8 @@ obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
 
 obj-y				+= isp/
 
+obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o
+
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
diff --git a/drivers/media/video/omap34xxcam.c b/drivers/media/video/omap34xxcam.c
new file mode 100644
index 0000000..4d75b6f
--- /dev/null
+++ b/drivers/media/video/omap34xxcam.c
@@ -0,0 +1,1962 @@
+/*
+ * omap34xxcam.c
+ *
+ * Copyright (C) 2006--2009 Nokia Corporation
+ * Copyright (C) 2007--2009 Texas Instruments
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *          Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *
+ * Originally based on the OMAP 2 camera driver.
+ *
+ * Written by Sakari Ailus <sakari.ailus@nokia.com>
+ *            Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *            Sergio Aguirre <saaguirre@ti.com>
+ *            Mohit Jalori
+ *            Sameer Venkatraman
+ *            Leonides Martinez
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#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 <media/v4l2-ioctl.h>
+
+#include "omap34xxcam.h"
+#include "isp/isp.h"
+#include "isp/ispmmu.h"
+#include "isp/ispreg.h"
+#include "isp/ispccdc.h"
+#include "isp/isph3a.h"
+#include "isp/isp_af.h"
+#include "isp/isphist.h"
+#include "isp/isppreview.h"
+#include "isp/ispresizer.h"
+
+#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
+
+/* global variables */
+static struct omap34xxcam_device *omap34xxcam;
+
+/*
+ *
+ * Sensor handling.
+ *
+ */
+
+/**
+ * omap34xxcam_slave_power_set - set slave power state
+ * @vdev: per-video device data structure
+ * @power: new power state
+ */
+static int omap34xxcam_slave_power_set(struct omap34xxcam_videodev *vdev,
+				       enum v4l2_power power,
+				       int mask)
+{
+	int rval = 0, i = 0;
+
+	BUG_ON(!mutex_is_locked(&vdev->mutex));
+
+#ifdef OMAP34XXCAM_POWEROFF_DELAY
+	vdev->power_state_wish = -1;
+#endif
+
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		if (vdev->slave[i] == v4l2_int_device_dummy())
+			continue;
+
+		if (!(mask & (1 << i))
+		    || power == vdev->power_state[i])
+			continue;
+
+		rval = vidioc_int_s_power(vdev->slave[i], power);
+
+		if (rval && power != V4L2_POWER_OFF) {
+			power = V4L2_POWER_OFF;
+			goto out;
+		}
+
+		vdev->power_state[i] = power;
+	}
+
+	return 0;
+
+out:
+	for (i--; i >= 0; i--) {
+		if (vdev->slave[i] == v4l2_int_device_dummy())
+			continue;
+
+		if (!(mask & (1 << i)))
+			continue;
+
+		vidioc_int_s_power(vdev->slave[i], power);
+		vdev->power_state[i] = power;
+	}
+
+	return rval;
+}
+
+#ifdef OMAP34XXCAM_POWEROFF_DELAY
+static void omap34xxcam_slave_power_work(struct work_struct *work)
+{
+	struct omap34xxcam_videodev *vdev =
+		container_of(work, struct omap34xxcam_videodev, poweroff_work);
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->power_state_wish != -1)
+		omap34xxcam_slave_power_set(vdev, vdev->power_state_wish,
+					    vdev->power_state_mask);
+
+	mutex_unlock(&vdev->mutex);
+}
+
+static void omap34xxcam_slave_power_timer(unsigned long ptr)
+{
+	struct omap34xxcam_videodev *vdev = (void *)ptr;
+
+	schedule_work(&vdev->poweroff_work);
+}
+
+/**
+ * omap34xxcam_slave_power_suggest - delayed power state change
+ *
+ * @vdev: per-video device data structure
+ * @power: new power state
+ */
+static void omap34xxcam_slave_power_suggest(struct omap34xxcam_videodev *vdev,
+					    enum v4l2_power power,
+					    int mask)
+{
+	BUG_ON(!mutex_is_locked(&vdev->mutex));
+
+	del_timer(&vdev->poweroff_timer);
+
+	vdev->power_state_wish = power;
+	vdev->power_state_mask = mask;
+
+	mod_timer(&vdev->poweroff_timer, jiffies + OMAP34XXCAM_POWEROFF_DELAY);
+}
+#else /* OMAP34XXCAM_POWEROFF_DELAY */
+#define omap34xxcam_slave_power_suggest(a, b, c) do {} while(0)
+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
+
+/**
+ * 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.
+ */
+void omap34xxcam_vbq_complete(struct videobuf_buffer *vb, void *priv)
+{
+	struct omap34xxcam_fh *fh = priv;
+
+	do_gettimeofday(&vb->ts);
+	vb->field_count = atomic_add_return(2, &fh->field_count);
+
+	wake_up(&vb->done);
+}
+
+/**
+ * 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 omap34xxcam_videodev *vdev = fh->vdev;
+
+	if (*cnt <= 0)
+		*cnt = VIDEO_MAX_FRAME;	/* supply a default number of buffers */
+
+	if (*cnt > VIDEO_MAX_FRAME)
+		*cnt = VIDEO_MAX_FRAME;
+
+	*size = vdev->pix.sizeimage;
+
+	while (*size * *cnt > fh->vdev->vdev_sensor_config.capture_mem)
+		(*cnt)--;
+
+	return isp_vbq_setup(vbq, cnt, size);
+}
+
+/**
+ * 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 omap34xxcam_fh *fh = vbq->priv_data;
+	struct omap34xxcam_videodev *vdev = fh->vdev;
+	int err = 0;
+
+	/*
+	 * 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 (vdev->pix.sizeimage > vb->bsize)
+			/* The buffer isn't big enough. */
+			return -EINVAL;
+	} else {
+		if (vb->state != VIDEOBUF_NEEDS_INIT
+		    && vdev->pix.sizeimage > vb->bsize)
+			/*
+			 * We have a kernel bounce buffer that has
+			 * already been allocated.
+			 */
+			omap34xxcam_vbq_release(vbq, vb);
+	}
+
+	vb->size = vdev->pix.bytesperline * vdev->pix.height;
+	vb->width = vdev->pix.width;
+	vb->height = vdev->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;
+
+	vb->state = VIDEOBUF_ACTIVE;
+
+	isp_buf_queue(vb, omap34xxcam_vbq_complete, (void *)fh);
+}
+
+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_SHORT_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, vdev->vfd->name, sizeof(cap->card));
+	cap->version = OMAP34XXCAM_VERSION;
+	if (vdev->vdev_sensor != v4l2_int_device_dummy())
+		cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+	return 0;
+}
+
+/**
+ * vidioc_enum_fmt_vid_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_vid_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 == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	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_vid_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_vid_cap(struct file *file, void *fh,
+				struct v4l2_format *f)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	f->fmt.pix = vdev->pix;
+	mutex_unlock(&vdev->mutex);
+
+	return 0;
+}
+
+static int try_pix_parm(struct omap34xxcam_videodev *vdev,
+			struct v4l2_pix_format *best_pix_in,
+			struct v4l2_pix_format *wanted_pix_out,
+			struct v4l2_fract *best_ival)
+{
+	int fps;
+	int fmtd_index;
+	int rval;
+	struct v4l2_pix_format best_pix_out;
+
+	if (best_ival->numerator == 0
+	    || best_ival->denominator == 0)
+		*best_ival = vdev->vdev_sensor_config.ival_default;
+
+	fps = best_ival->denominator / best_ival->numerator;
+
+	best_ival->denominator = 0;
+	best_pix_out.height = INT_MAX >> 1;
+	best_pix_out.width = best_pix_out.height;
+
+	for (fmtd_index = 0; ; fmtd_index++) {
+		int size_index;
+		struct v4l2_fmtdesc fmtd;
+
+		fmtd.index = fmtd_index;
+		fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, &fmtd);
+		if (rval)
+			break;
+		dev_info(&vdev->vfd->dev, "trying fmt %8.8x (%d)\n",
+			 fmtd.pixelformat, fmtd_index);
+		/*
+		 * Get supported resolutions.
+		 */
+		for (size_index = 0; ; size_index++) {
+			struct v4l2_frmsizeenum frms;
+			struct v4l2_pix_format pix_tmp_in, pix_tmp_out;
+			int ival_index;
+
+			frms.index = size_index;
+			frms.pixel_format = fmtd.pixelformat;
+
+			rval = vidioc_int_enum_framesizes(vdev->vdev_sensor,
+							  &frms);
+			if (rval)
+				break;
+
+			pix_tmp_in.pixelformat = frms.pixel_format;
+			pix_tmp_in.width = frms.discrete.width;
+			pix_tmp_in.height = frms.discrete.height;
+			pix_tmp_out = *wanted_pix_out;
+			/* Don't do upscaling. */
+			if (pix_tmp_out.width > pix_tmp_in.width)
+				pix_tmp_out.width = pix_tmp_in.width;
+			if (pix_tmp_out.height > pix_tmp_in.height)
+				pix_tmp_out.height = pix_tmp_in.height;
+			rval = isp_try_fmt_cap(&pix_tmp_in, &pix_tmp_out);
+			if (rval)
+				return rval;
+
+			dev_info(&vdev->vfd->dev, "this w %d\th %d\tfmt %8.8x\t"
+				 "-> w %d\th %d\t fmt %8.8x"
+				 "\twanted w %d\th %d\t fmt %8.8x\n",
+				 pix_tmp_in.width, pix_tmp_in.height,
+				 pix_tmp_in.pixelformat,
+				 pix_tmp_out.width, pix_tmp_out.height,
+				 pix_tmp_out.pixelformat,
+				 wanted_pix_out->width, wanted_pix_out->height,
+				 wanted_pix_out->pixelformat);
+
+#define IS_SMALLER_OR_EQUAL(pix1, pix2)				\
+			((pix1)->width + (pix1)->height		\
+			 < (pix2)->width + (pix2)->height)
+#define SIZE_DIFF(pix1, pix2)						\
+			(abs((pix1)->width - (pix2)->width)		\
+			 + abs((pix1)->height - (pix2)->height))
+
+			/*
+			 * Don't use modes that are farther from wanted size
+			 * that what we already got.
+			 */
+			if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
+			    > SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
+				dev_info(&vdev->vfd->dev, "size diff bigger: "
+					 "w %d\th %d\tw %d\th %d\n",
+					 pix_tmp_out.width, pix_tmp_out.height,
+					 best_pix_out.width,
+					 best_pix_out.height);
+				continue;
+			}
+
+			/*
+			 * There's an input mode that can provide output
+			 * closer to wanted.
+			 */
+			if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
+			    < SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
+				/* Force renegotation of fps etc. */
+				best_ival->denominator = 0;
+				dev_info(&vdev->vfd->dev, "renegotiate: "
+					 "w %d\th %d\tw %d\th %d\n",
+					 pix_tmp_out.width, pix_tmp_out.height,
+					 best_pix_out.width,
+					 best_pix_out.height);
+			}
+
+			for (ival_index = 0; ; ival_index++) {
+				struct v4l2_frmivalenum frmi;
+
+				frmi.index = ival_index;
+				frmi.pixel_format = frms.pixel_format;
+				frmi.width = frms.discrete.width;
+				frmi.height = frms.discrete.height;
+				/* FIXME: try to fix standard... */
+				frmi.reserved[0] = 0xdeafbeef;
+
+				rval = vidioc_int_enum_frameintervals(
+					vdev->vdev_sensor, &frmi);
+				if (rval)
+					break;
+
+				dev_info(&vdev->vfd->dev, "fps %d\n",
+					 frmi.discrete.denominator
+					 / frmi.discrete.numerator);
+
+				if (best_ival->denominator == 0)
+					goto do_it_now;
+
+				/*
+				 * We aim to use maximum resolution
+				 * from the sensor, provided that the
+				 * fps is at least as close as on the
+				 * current mode.
+				 */
+#define FPS_ABS_DIFF(fps, ival) abs(fps - (ival).denominator / (ival).numerator)
+
+				/* Select mode with closest fps. */
+				if (FPS_ABS_DIFF(fps, frmi.discrete)
+				    < FPS_ABS_DIFF(fps, *best_ival)) {
+					dev_info(&vdev->vfd->dev, "closer fps: "
+						 "fps %d\t fps %d\n",
+						 FPS_ABS_DIFF(fps, frmi.discrete),
+						 FPS_ABS_DIFF(fps, *best_ival));
+					goto do_it_now;
+				}
+
+				/*
+				 * Select bigger resolution if it's available
+				 * at same fps.
+				 */
+				if (frmi.width + frmi.height
+				    > best_pix_in->width + best_pix_in->height
+				    && FPS_ABS_DIFF(fps, frmi.discrete)
+				    <= FPS_ABS_DIFF(fps, *best_ival)) {
+					dev_info(&vdev->vfd->dev, "bigger res, "
+						 "same fps: "
+						 "w %d\th %d\tw %d\th %d\n",
+						 frmi.width, frmi.height,
+						 best_pix_in->width,
+						 best_pix_in->height);
+					goto do_it_now;
+				}
+
+				dev_info(&vdev->vfd->dev, "falling through\n");
+
+				continue;
+
+			do_it_now:
+				*best_ival = frmi.discrete;
+				best_pix_out = pix_tmp_out;
+				best_pix_in->width = frmi.width;
+				best_pix_in->height = frmi.height;
+				best_pix_in->pixelformat = frmi.pixel_format;
+
+				dev_info(&vdev->vfd->dev,
+					 "best_pix_in: w %d\th %d\tfmt %8.8x"
+					 "\tival %d/%d\n",
+					 best_pix_in->width,
+					 best_pix_in->height,
+					 best_pix_in->pixelformat,
+					 best_ival->numerator,
+					 best_ival->denominator);
+			}
+		}
+	}
+
+	if (best_ival->denominator == 0)
+		return -EINVAL;
+
+	*wanted_pix_out = best_pix_out;
+
+	dev_info(&vdev->vfd->dev, "w %d, h %d, fmt %8.8x -> w %d, h %d\n",
+		 best_pix_in->width, best_pix_in->height,
+		 best_pix_in->pixelformat,
+		 best_pix_out.width, best_pix_out.height);
+
+	return isp_try_fmt_cap(best_pix_in, wanted_pix_out);
+}
+
+static int s_pix_parm(struct omap34xxcam_videodev *vdev,
+		      struct v4l2_pix_format *best_pix,
+		      struct v4l2_pix_format *pix,
+		      struct v4l2_fract *best_ival)
+{
+	struct v4l2_streamparm a;
+	struct v4l2_format fmt;
+	int rval;
+
+	rval = try_pix_parm(vdev, best_pix, pix, best_ival);
+	if (rval)
+		return rval;
+
+	rval = isp_s_fmt_cap(best_pix, pix);
+	if (rval)
+		return rval;
+
+	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	fmt.fmt.pix = *best_pix;
+	rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, &fmt);
+	if (rval)
+		return rval;
+
+	a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a.parm.capture.timeperframe = *best_ival;
+	rval = vidioc_int_s_parm(vdev->vdev_sensor, &a);
+
+	return rval;
+}
+
+/**
+ * vidioc_s_fmt_vid_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_vid_cap().
+ */
+static int vidioc_s_fmt_vid_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_tmp;
+	struct v4l2_fract timeperframe;
+	int rval;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		rval = -EBUSY;
+		goto out;
+	}
+
+	vdev->want_pix = f->fmt.pix;
+
+	timeperframe = vdev->want_timeperframe;
+
+	rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
+	if (!rval)
+		vdev->pix = f->fmt.pix;
+
+out:
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+/**
+ * vidioc_try_fmt_vid_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_vid_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_tmp;
+	struct v4l2_fract timeperframe;
+	int rval;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+
+	timeperframe = vdev->want_timeperframe;
+
+	rval = try_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
+
+	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;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		mutex_unlock(&vdev->mutex);
+		return -EBUSY;
+	}
+
+	rval = videobuf_reqbufs(&ofh->vbq, b);
+
+	mutex_unlock(&vdev->mutex);
+
+	/*
+	 * 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;
+	int rval;
+
+videobuf_dqbuf_again:
+	rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
+
+	/*
+	 * This is a hack. We don't want to show -EIO to the user
+	 * space. Requeue the buffer and try again if we're not doing
+	 * this in non-blocking mode.
+	 */
+	if (rval == -EIO) {
+		videobuf_qbuf(&ofh->vbq, b);
+		if (!(file->f_flags & O_NONBLOCK))
+			goto videobuf_dqbuf_again;
+		/*
+		 * We don't have a videobuf_buffer now --- maybe next
+		 * time...
+		 */
+		rval = -EAGAIN;
+	}
+
+	return rval;
+}
+
+/**
+ * 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;
+	int rval;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		rval = -EBUSY;
+		goto out;
+	}
+
+	rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
+					   OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
+	if (rval) {
+		dev_dbg(&vdev->vfd->dev, "omap34xxcam_slave_power_set failed\n");
+		goto out;
+	}
+
+	rval = videobuf_streamon(&ofh->vbq);
+	if (rval)
+		omap34xxcam_slave_power_set(
+			vdev, V4L2_POWER_OFF,
+			OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
+	else
+		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;
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->streaming == file)
+		isp_stop();
+
+	rval = videobuf_streamoff(q);
+	if (!rval) {
+		vdev->streaming = NULL;
+
+		omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY,
+					    OMAP34XXCAM_SLAVE_POWER_SENSOR);
+		omap34xxcam_slave_power_suggest(vdev, V4L2_POWER_STANDBY,
+						OMAP34XXCAM_SLAVE_POWER_LENS);
+	}
+
+	mutex_unlock(&vdev->mutex);
+
+	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;
+	struct v4l2_queryctrl a_tmp;
+	int best_slave = -1;
+	u32 best_ctrl = (u32)-1;
+	int i;
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		return vidioc_int_queryctrl(vdev->vdev_sensor, a);
+
+	/* No next flags: try slaves directly. */
+	if (!(a->id & V4L2_CTRL_FLAG_NEXT_CTRL)) {
+		for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+			if (!vidioc_int_queryctrl(vdev->slave[i], a))
+				return 0;
+		}
+		return isp_queryctrl(a);
+	}
+
+	/* Find slave with smallest next control id. */
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		a_tmp = *a;
+
+		if (vidioc_int_queryctrl(vdev->slave[i], &a_tmp))
+			continue;
+
+		if (a_tmp.id < best_ctrl) {
+			best_slave = i;
+			best_ctrl = a_tmp.id;
+		}
+	}
+
+	a_tmp = *a;
+	if (!isp_queryctrl(&a_tmp)) {
+		if (a_tmp.id < best_ctrl) {
+			*a = a_tmp;
+
+			return 0;
+		}
+	}
+
+	if (best_slave == -1)
+		return -EINVAL;
+
+	a->id = best_ctrl;
+	return vidioc_int_queryctrl(vdev->slave[best_slave], a);
+}
+
+/**
+ * vidioc_querymenu - V4L2 query menu IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @a: standard V4L2 query menu ioctl structure
+ *
+ * If the requested control is supported, returns the menu information
+ * in the v4l2_querymenu structure.  Otherwise, returns -EINVAL if the
+ * control is not supported or is not a menu.  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
+ * menu control, the request is forwarded to the "raw" sensor driver to
+ * see if it supports it.
+ */
+static int vidioc_querymenu(struct file *file, void *fh,
+			    struct v4l2_querymenu *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int i;
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		return vidioc_int_querymenu(vdev->vdev_sensor, a);
+
+	/* Try slaves directly. */
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		if (!vidioc_int_querymenu(vdev->slave[i], a))
+			return 0;
+	}
+	return isp_querymenu(a);
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *fh,
+			      struct v4l2_ext_controls *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int i, ctrl_idx, rval = 0;
+
+	mutex_lock(&vdev->mutex);
+
+	for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
+		struct v4l2_control ctrl;
+
+		ctrl.id = a->controls[ctrl_idx].id;
+
+		if (vdev->vdev_sensor_config.sensor_isp) {
+			rval = vidioc_int_g_ctrl(vdev->vdev_sensor, &ctrl);
+		} else {
+			for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+				rval = vidioc_int_g_ctrl(vdev->slave[i], &ctrl);
+				if (!rval)
+					break;
+			}
+		}
+
+		if (rval)
+			rval = isp_g_ctrl(&ctrl);
+
+		if (rval) {
+			a->error_idx = ctrl_idx;
+			break;
+		}
+
+		a->controls[ctrl_idx].value = ctrl.value;
+	}
+
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *fh,
+			      struct v4l2_ext_controls *a)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int i, ctrl_idx, rval = 0;
+
+	mutex_lock(&vdev->mutex);
+
+	for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
+		struct v4l2_control ctrl;
+
+		ctrl.id = a->controls[ctrl_idx].id;
+		ctrl.value = a->controls[ctrl_idx].value;
+
+		if (vdev->vdev_sensor_config.sensor_isp) {
+			rval = vidioc_int_s_ctrl(vdev->vdev_sensor, &ctrl);
+		} else {
+			for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+				rval = vidioc_int_s_ctrl(vdev->slave[i], &ctrl);
+				if (!rval)
+					break;
+			}
+		}
+
+		if (rval)
+			rval = isp_s_ctrl(&ctrl);
+
+		if (rval) {
+			a->error_idx = ctrl_idx;
+			break;
+		}
+
+		a->controls[ctrl_idx].value = ctrl.value;
+	}
+
+	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_pix_format pix_tmp_sensor, pix_tmp;
+	int rval;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+	if (vdev->streaming) {
+		rval = -EBUSY;
+		goto out;
+	}
+
+	vdev->want_timeperframe = a->parm.capture.timeperframe;
+
+	pix_tmp = vdev->want_pix;
+
+	rval = s_pix_parm(vdev, &pix_tmp_sensor, &pix_tmp,
+			  &a->parm.capture.timeperframe);
+
+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 == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+
+	rval = vidioc_int_cropcap(vdev->vdev_sensor, a);
+
+	if (rval && !vdev->vdev_sensor_config.sensor_isp) {
+		struct v4l2_format f;
+
+		/* cropcap failed, try to do this via g_fmt_cap */
+		rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &f);
+		if (!rval) {
+			cropcap->bounds.top = 0;
+			cropcap->bounds.left = 0;
+			cropcap->bounds.width = f.fmt.pix.width;
+			cropcap->bounds.height = f.fmt.pix.height;
+			cropcap->defrect = cropcap->bounds;
+			cropcap->pixelaspect.numerator = 1;
+			cropcap->pixelaspect.denominator = 1;
+		}
+	}
+
+	mutex_unlock(&vdev->mutex);
+
+	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 == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		rval = vidioc_int_g_crop(vdev->vdev_sensor, a);
+	else
+		rval = isp_g_crop(a);
+
+	mutex_unlock(&vdev->mutex);
+
+	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;
+	int rval = 0;
+
+	if (vdev->vdev_sensor == v4l2_int_device_dummy())
+		return -EINVAL;
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->vdev_sensor_config.sensor_isp)
+		rval = vidioc_int_s_crop(vdev->vdev_sensor, a);
+	else
+		rval = isp_s_crop(a, &vdev->pix);
+
+	mutex_unlock(&vdev->mutex);
+
+	return rval;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *fh,
+				  struct v4l2_frmsizeenum *frms)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	u32 pixel_format;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
+	} else {
+		pixel_format = frms->pixel_format;
+		frms->pixel_format = -1;	/* ISP does format conversion */
+		rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
+		frms->pixel_format = pixel_format;
+	}
+
+	mutex_unlock(&vdev->mutex);
+	return rval;
+}
+
+static int vidioc_enum_frameintervals(struct file *file, void *fh,
+				      struct v4l2_frmivalenum *frmi)
+{
+	struct omap34xxcam_fh *ofh = fh;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	u32 pixel_format;
+	int rval;
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
+	} else {
+		pixel_format = frmi->pixel_format;
+		frmi->pixel_format = -1;	/* ISP does format conversion */
+		rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
+		frmi->pixel_format = pixel_format;
+	}
+
+	mutex_unlock(&vdev->mutex);
+	return rval;
+}
+
+/**
+ * vidioc_default - private IOCTL handler
+ * @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 long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+{
+	struct omap34xxcam_fh *ofh = file->private_data;
+	struct omap34xxcam_videodev *vdev = ofh->vdev;
+	int rval;
+
+	if (vdev->vdev_sensor_config.sensor_isp) {
+		rval = -EINVAL;
+	} else {
+		switch (cmd) {
+		case VIDIOC_PRIVATE_ISP_AEWB_REQ:
+		{
+			/* Need to update sensor first */
+			struct isph3a_aewb_data *data;
+			struct v4l2_control vc;
+
+			data = (struct isph3a_aewb_data *) arg;
+			if (data->update & SET_EXPOSURE) {
+				dev_info(&vdev->vfd->dev, "using "
+					 "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
+					 "exposure is deprecated!\n");
+				vc.id = V4L2_CID_EXPOSURE;
+				vc.value = data->shutter;
+				mutex_lock(&vdev->mutex);
+				rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
+							 &vc);
+				mutex_unlock(&vdev->mutex);
+				if (rval)
+					goto out;
+			}
+			if (data->update & SET_ANALOG_GAIN) {
+				dev_info(&vdev->vfd->dev, "using "
+					 "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
+					 "gain is deprecated!\n");
+				vc.id = V4L2_CID_GAIN;
+				vc.value = data->gain;
+				mutex_lock(&vdev->mutex);
+				rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
+							 &vc);
+				mutex_unlock(&vdev->mutex);
+				if (rval)
+					goto out;
+			}
+		}
+		break;
+		case VIDIOC_PRIVATE_ISP_AF_REQ: {
+			/* Need to update lens first */
+			struct isp_af_data *data;
+			struct v4l2_control vc;
+
+			if (!vdev->vdev_lens) {
+				rval = -EINVAL;
+				goto out;
+			}
+			data = (struct isp_af_data *) arg;
+			if (data->update & LENS_DESIRED_POSITION) {
+				dev_info(&vdev->vfd->dev, "using "
+					 "VIDIOC_PRIVATE_ISP_AF_REQ to set "
+					 "lens position is deprecated!\n");
+				vc.id = V4L2_CID_FOCUS_ABSOLUTE;
+				vc.value = data->desired_lens_direction;
+				mutex_lock(&vdev->mutex);
+				rval = vidioc_int_s_ctrl(vdev->vdev_lens, &vc);
+				mutex_unlock(&vdev->mutex);
+				if (rval)
+					goto out;
+			}
+		}
+			break;
+		}
+
+		mutex_lock(&vdev->mutex);
+		rval = isp_handle_private(cmd, arg);
+		mutex_unlock(&vdev->mutex);
+	}
+out:
+	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 file *file)
+{
+	int rval = 0;
+	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(file->f_dentry->d_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] != v4l2_int_device_dummy()
+		    && !try_module_get(vdev->slave[i]->module)) {
+			mutex_unlock(&vdev->mutex);
+			dev_err(&vdev->vfd->dev, "can't try_module_get %s\n",
+				vdev->slave[i]->name);
+			rval = -ENODEV;
+			goto out_try_module_get;
+		}
+	}
+
+	if (atomic_inc_return(&vdev->users) == 1) {
+		rval = isp_get();
+		if (rval < 0) {
+			dev_err(&vdev->vfd->dev, "can't get isp\n");
+			goto out_isp_get;
+		}
+		if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
+						OMAP34XXCAM_SLAVE_POWER_ALL)) {
+			dev_err(&vdev->vfd->dev, "can't power up slaves\n");
+			rval = -EBUSY;
+			goto out_slave_power_set_standby;
+		}
+		omap34xxcam_slave_power_set(
+			vdev, V4L2_POWER_STANDBY,
+			OMAP34XXCAM_SLAVE_POWER_SENSOR);
+		omap34xxcam_slave_power_suggest(
+			vdev, V4L2_POWER_STANDBY,
+			OMAP34XXCAM_SLAVE_POWER_LENS);
+	}
+
+	fh->vdev = vdev;
+
+	if (!vdev->pix.width
+	    && vdev->vdev_sensor != v4l2_int_device_dummy()) {
+		memset(&format, 0, sizeof(format));
+		if (vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format)) {
+			dev_err(&vdev->vfd->dev,
+				"can't get current pix from sensor!\n");
+			goto out_vidioc_int_g_fmt_cap;
+		}
+		if (!vdev->vdev_sensor_config.sensor_isp) {
+			struct v4l2_pix_format pix = format.fmt.pix;
+			if (isp_s_fmt_cap(&pix, &format.fmt.pix)) {
+				dev_err(&vdev->vfd->dev,
+					"isp doesn't like the sensor!\n");
+				goto out_isp_s_fmt_cap;
+			}
+		}
+		vdev->pix = format.fmt.pix;
+	}
+
+	mutex_unlock(&vdev->mutex);
+
+	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_isp_s_fmt_cap:
+out_vidioc_int_g_fmt_cap:
+	omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
+				    OMAP34XXCAM_SLAVE_POWER_ALL);
+out_slave_power_set_standby:
+	isp_put();
+
+out_isp_get:
+	atomic_dec(&vdev->users);
+	mutex_unlock(&vdev->mutex);
+
+out_try_module_get:
+	for (i--; i >= 0; i--)
+		if (vdev->slave[i] != v4l2_int_device_dummy())
+			module_put(vdev->slave[i]->module);
+
+	kfree(fh);
+
+	return rval;
+}
+
+/**
+ * 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 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,
+			OMAP34XXCAM_SLAVE_POWER_SENSOR);
+		omap34xxcam_slave_power_suggest(
+			vdev, V4L2_POWER_STANDBY,
+			OMAP34XXCAM_SLAVE_POWER_LENS);
+		vdev->streaming = NULL;
+	}
+
+	if (atomic_dec_return(&vdev->users) == 0) {
+		omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
+					    OMAP34XXCAM_SLAVE_POWER_ALL);
+		isp_put();
+	}
+	mutex_unlock(&vdev->mutex);
+
+	file->private_data = NULL;
+
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++)
+		if (vdev->slave[i] != v4l2_int_device_dummy())
+			module_put(vdev->slave[i]->module);
+
+	kfree(fh);
+
+	return 0;
+}
+
+static struct v4l2_file_operations omap34xxcam_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = omap34xxcam_poll,
+	.mmap = omap34xxcam_mmap,
+	.open = omap34xxcam_open,
+	.release = omap34xxcam_release,
+};
+
+static void omap34xxcam_vfd_name_update(struct omap34xxcam_videodev *vdev)
+{
+	struct video_device *vfd = vdev->vfd;
+	int i;
+
+	strlcpy(vfd->name, CAM_SHORT_NAME, sizeof(vfd->name));
+	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
+		strlcat(vfd->name, "/", sizeof(vfd->name));
+		if (vdev->slave[i] == v4l2_int_device_dummy())
+			continue;
+		strlcat(vfd->name, vdev->slave[i]->name, sizeof(vfd->name));
+	}
+	dev_info(&vdev->vfd->dev, "video%d is now %s\n", vfd->num, vfd->name);
+}
+
+/**
+ * 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);
+
+	mutex_lock(&vdev->mutex);
+
+	if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy()) {
+		vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
+		vdev->slaves--;
+		omap34xxcam_vfd_name_update(vdev);
+	}
+
+	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;
+	}
+
+	mutex_unlock(&vdev->mutex);
+}
+
+static const struct v4l2_ioctl_ops omap34xxcam_ioctl_ops = {
+	.vidioc_querycap		= vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		= vidioc_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		= vidioc_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt_vid_cap,
+	.vidioc_reqbufs			= vidioc_reqbufs,
+	.vidioc_querybuf		= vidioc_querybuf,
+	.vidioc_qbuf			= vidioc_qbuf,
+	.vidioc_dqbuf			= vidioc_dqbuf,
+	.vidioc_streamon		= vidioc_streamon,
+	.vidioc_streamoff		= vidioc_streamoff,
+	.vidioc_enum_input		= vidioc_enum_input,
+	.vidioc_g_input			= vidioc_g_input,
+	.vidioc_s_input			= vidioc_s_input,
+	.vidioc_queryctrl		= vidioc_queryctrl,
+	.vidioc_querymenu		= vidioc_querymenu,
+	.vidioc_g_ext_ctrls		= vidioc_g_ext_ctrls,
+	.vidioc_s_ext_ctrls		= vidioc_s_ext_ctrls,
+	.vidioc_g_parm			= vidioc_g_parm,
+	.vidioc_s_parm			= vidioc_s_parm,
+	.vidioc_cropcap			= vidioc_cropcap,
+	.vidioc_g_crop			= vidioc_g_crop,
+	.vidioc_s_crop			= vidioc_s_crop,
+	.vidioc_enum_framesizes		= vidioc_enum_framesizes,
+	.vidioc_enum_frameintervals	= vidioc_enum_frameintervals,
+	.vidioc_default			= vidioc_default,
+};
+
+/**
+ * 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_hw_config hwc;
+	int rval;
+
+	/* We need to check rval just once. The place is here. */
+	if (vidioc_int_g_priv(s, &hwc))
+		return -ENODEV;
+
+	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] != v4l2_int_device_dummy())
+		return -EBUSY;
+
+	mutex_lock(&vdev->mutex);
+	if (atomic_read(&vdev->users)) {
+		dev_err(&vdev->vfd->dev, "we're open (%d), can't register\n",
+			atomic_read(&vdev->users));
+		mutex_unlock(&vdev->mutex);
+		return -EBUSY;
+	}
+
+	vdev->slaves++;
+	vdev->slave[hwc.dev_type] = s;
+	vdev->slave_config[hwc.dev_type] = hwc;
+
+	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
+		rval = isp_get();
+		if (rval < 0) {
+			dev_err(&vdev->vfd->dev,
+				"can't get ISP, sensor init failed\n");
+			goto err;
+		}
+	}
+	rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
+					   1 << hwc.dev_type);
+	if (rval)
+		goto err_omap34xxcam_slave_power_set;
+	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
+		struct v4l2_format format;
+
+		format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format);
+		if (rval)
+			rval = -EBUSY;
+
+		vdev->want_pix = format.fmt.pix;
+	}
+	omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF, 1 << hwc.dev_type);
+	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
+		isp_put();
+
+	if (rval)
+		goto err;
+
+	/* Are we the first slave? */
+	if (vdev->slaves == 1) {
+		/* initialize the video_device struct */
+		vdev->vfd = video_device_alloc();
+		if (!vdev->vfd) {
+			dev_err(&vdev->vfd->dev,
+				"could not allocate video device struct\n");
+			return -ENOMEM;
+		}
+		vdev->vfd->release	= video_device_release;
+		vdev->vfd->minor	= -1;
+		vdev->vfd->fops		= &omap34xxcam_fops;
+		vdev->vfd->ioctl_ops	= &omap34xxcam_ioctl_ops;
+		video_set_drvdata(vdev->vfd, vdev);
+
+		if (video_register_device(vdev->vfd, VFL_TYPE_GRABBER,
+					  hwc.dev_minor) < 0) {
+			dev_err(&vdev->vfd->dev,
+				"could not register V4L device\n");
+			vdev->vfd->minor = -1;
+			rval = -EBUSY;
+			goto err;
+		}
+	}
+
+	omap34xxcam_vfd_name_update(vdev);
+
+	mutex_unlock(&vdev->mutex);
+
+	return 0;
+
+err_omap34xxcam_slave_power_set:
+	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
+		isp_put();
+
+err:
+	if (s == vdev->slave[hwc.dev_type]) {
+		vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
+		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,
+};
+
+/*
+ *
+ * Module initialisation and deinitialisation
+ *
+ */
+
+static void omap34xxcam_exit(void)
+{
+	struct omap34xxcam_device *cam = omap34xxcam;
+	int i;
+
+	if (!cam)
+		return;
+
+	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;
+	}
+
+	omap34xxcam = NULL;
+
+	kfree(cam);
+}
+
+static int __init omap34xxcam_init(void)
+{
+	struct omap34xxcam_device *cam;
+	int i;
+
+	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
+	if (!cam) {
+		printk(KERN_ERR "%s: could not allocate memory\n", __func__);
+		goto err;
+	}
+
+	omap34xxcam = cam;
+
+	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;
+
+		mutex_init(&vdev->mutex);
+		vdev->index             = i;
+		vdev->cam               = cam;
+		vdev->vdev_sensor =
+			vdev->vdev_lens =
+			vdev->vdev_flash = v4l2_int_device_dummy();
+#ifdef OMAP34XXCAM_POWEROFF_DELAY
+		setup_timer(&vdev->poweroff_timer,
+			    omap34xxcam_slave_power_timer, (unsigned long)vdev);
+		INIT_WORK(&vdev->poweroff_work, omap34xxcam_slave_power_work);
+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
+
+		if (v4l2_int_device_register(m))
+			goto err;
+	}
+
+	return 0;
+
+err:
+	omap34xxcam_exit();
+	return -ENODEV;
+}
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("OMAP34xx Video for Linux camera driver");
+MODULE_LICENSE("GPL");
+
+late_initcall(omap34xxcam_init);
+module_exit(omap34xxcam_exit);
diff --git a/drivers/media/video/omap34xxcam.h b/drivers/media/video/omap34xxcam.h
new file mode 100644
index 0000000..9859d15
--- /dev/null
+++ b/drivers/media/video/omap34xxcam.h
@@ -0,0 +1,207 @@
+/*
+ * omap34xxcam.h
+ *
+ * Copyright (C) 2006--2009 Nokia Corporation
+ * Copyright (C) 2007--2009 Texas Instruments
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *          Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *
+ * Originally based on the OMAP 2 camera driver.
+ *
+ * Written by Sakari Ailus <sakari.ailus@nokia.com>
+ *            Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+ *            Sergio Aguirre <saaguirre@ti.com>
+ *            Mohit Jalori
+ *            Sameer Venkatraman
+ *            Leonides Martinez
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef OMAP34XXCAM_H
+#define OMAP34XXCAM_H
+
+#include <media/v4l2-int-device.h>
+#include "isp/isp.h"
+
+#define CAM_NAME			"omap34xxcam"
+#define CAM_SHORT_NAME			"omap3"
+
+#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! */
+
+/* mask for omap34xxcam_slave_power_set */
+#define OMAP34XXCAM_SLAVE_POWER_SENSOR	(1 << OMAP34XXCAM_SLAVE_SENSOR)
+#define OMAP34XXCAM_SLAVE_POWER_LENS	(1 << OMAP34XXCAM_SLAVE_LENS)
+#define OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS \
+	(OMAP34XXCAM_SLAVE_POWER_SENSOR | OMAP34XXCAM_SLAVE_POWER_LENS)
+#define OMAP34XXCAM_SLAVE_POWER_FLASH	(1 << OMAP34XXCAM_SLAVE_FLASH)
+#define OMAP34XXCAM_SLAVE_POWER_ALL	-1
+
+#define OMAP34XXCAM_VIDEODEVS		4
+
+/* #define OMAP34XXCAM_POWEROFF_DELAY (2 * HZ) */
+
+struct omap34xxcam_device;
+struct omap34xxcam_videodev;
+
+struct omap34xxcam_sensor_config {
+	int xclk;
+	int sensor_isp;
+	u32 capture_mem;
+	struct v4l2_fract ival_default;
+};
+
+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
+ * @power_state: Current power state
+ * @power_state_wish: New power state when poweroff_timer expires
+ * @power_state_mask: Bitmask of devices to set the new power state
+ * @poweroff_timer: Timer for dispatching poweroff_work
+ * @poweroff_work: Work for slave power state change
+ * @sensor_config: ISP-speicific sensor configuration
+ * @lens_config: ISP-speicific lens configuration
+ * @flash_config: ISP-speicific flash configuration
+ * @want_timeperframe: Desired timeperframe
+ * @want_pix: Desired pix
+ * @pix: Current pix
+ * @streaming: streaming file handle, if streaming is enabled
+ */
+struct omap34xxcam_videodev {
+	struct mutex mutex; /* serialises access to this structure */
+
+	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 ***/
+	int index;
+	atomic_t users;
+	enum v4l2_power power_state[OMAP34XXCAM_SLAVE_FLASH + 1];
+#ifdef OMAP34XXCAM_POWEROFF_DELAY
+	enum v4l2_power power_state_wish;
+	int power_state_mask;
+	struct timer_list poweroff_timer;
+	struct work_struct poweroff_work;
+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
+
+#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 ***/
+	struct file *streaming;
+	struct v4l2_fract want_timeperframe;
+	struct v4l2_pix_format want_pix;
+	spinlock_t pix_lock;
+	struct v4l2_pix_format pix;
+};
+
+/**
+ * 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
+ * @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; /* serialises access to this structure */
+
+	/*** interfaces and device ***/
+	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
+ * @field_count: field counter for videobuf_buffer
+ * @vdev: our /dev/video specific structure
+ */
+struct omap34xxcam_fh {
+	spinlock_t vbq_lock; /* spinlock for the videobuf queue */
+	struct videobuf_queue vbq;
+	atomic_t field_count;
+	struct omap34xxcam_videodev *vdev;
+};
+
+#endif /* ifndef OMAP34XXCAM_H */
-- 
1.5.6.5


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

* Re: [PATCH 1/9] omap3isp: Add ISP main driver and register definitions
  2009-03-03 10:06 ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Sakari Ailus
  2009-03-03 10:06   ` [PATCH 2/9] omap3isp: Add ISP MMU wrapper Sakari Ailus
@ 2009-03-03 11:56   ` Alexey Klimov
  2009-03-05 11:34     ` Sakari Ailus
  1 sibling, 1 reply; 30+ messages in thread
From: Alexey Klimov @ 2009-03-03 11:56 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

On Tue, 2009-03-03 at 12:06 +0200, Sakari Ailus wrote:
> TODO:
> 
> - Release resoures in isp_probe() if something fails.
> 
> - Implement a sensible generic interface so that the ISP can offer a
>   v4l2_subdev (like the v4l2-int-device slaves) interface towards the
>   camera driver.
> 
> - Handle CSI1 and CSI2 error cases (currently unhandled?).
> 
> - Fix H3A / HIST interrupt enabling / disabling.
> 
> - Clean up the private ioctls.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> ---
>  drivers/media/video/Makefile     |    2 +
>  drivers/media/video/isp/Makefile |   12 +
>  drivers/media/video/isp/isp.c    | 2418 ++++++++++++++++++++++++++++++++++++++
>  drivers/media/video/isp/isp.h    |  318 +++++
>  drivers/media/video/isp/ispreg.h | 1673 ++++++++++++++++++++++++++
>  5 files changed, 4423 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/isp/Makefile
>  create mode 100644 drivers/media/video/isp/isp.c
>  create mode 100644 drivers/media/video/isp/isp.h
>  create mode 100644 drivers/media/video/isp/ispreg.h
> 
> diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> index 72f6d03..e654270 100644
> --- a/drivers/media/video/Makefile
> +++ b/drivers/media/video/Makefile
> @@ -106,6 +106,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
>  obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
>  obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
>  
> +obj-y				+= isp/
> +
>  obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
>  
>  obj-$(CONFIG_USB_DABUSB)        += dabusb.o
> diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
> new file mode 100644
> index 0000000..f14d617
> --- /dev/null
> +++ b/drivers/media/video/isp/Makefile
> @@ -0,0 +1,12 @@
> +# Makefile for OMAP3 ISP driver
> +
> +ifdef CONFIG_ARCH_OMAP3410
> +isp-mod-objs += \
> +	isp.o ispccdc.o
> +else
> +isp-mod-objs += \
> +	isp.o ispccdc.o ispmmu.o \
> +	isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
> +endif
> +
> +obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
> diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
> new file mode 100644
> index 0000000..12a545c
> --- /dev/null
> +++ b/drivers/media/video/isp/isp.c
> @@ -0,0 +1,2418 @@
> +/*
> + * isp.c
> + *
> + * Driver Library for ISP Control module in TI's OMAP3 Camera ISP
> + * ISP interface and IRQ related APIs are defined here.
> + *
> + * Copyright (C) 2009 Texas Instruments.
> + * Copyright (C) 2009 Nokia.
> + *
> + * Contributors:
> + * 	Sameer Venkatraman <sameerv@ti.com>
> + * 	Mohit Jalori <mjalori@ti.com>
> + * 	Sergio Aguirre <saaguirre@ti.com>
> + * 	Sakari Ailus <sakari.ailus@nokia.com>
> + * 	Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
> + *	Toni Leinonen <toni.leinonen@nokia.com>
> + *
> + * 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 <asm/cacheflush.h>
> +
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/clk.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/vmalloc.h>
> +#include <linux/platform_device.h>
> +
> +#include "isp.h"
> +#include "ispmmu.h"
> +#include "ispreg.h"
> +#include "ispccdc.h"
> +#include "isph3a.h"
> +#include "isphist.h"
> +#include "isp_af.h"
> +#include "isppreview.h"
> +#include "ispresizer.h"
> +#include "ispcsi2.h"
> +
> +static struct isp_device *omap3isp;
> +
> +static int isp_try_size(struct v4l2_pix_format *pix_input,
> +					struct v4l2_pix_format *pix_output);
> +
> +static void isp_save_ctx(void);
> +
> +static void isp_restore_ctx(void);
> +
> +static void isp_buf_init(void);
> +
> +/* 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[] = {
> +	{
> +		{
> +			.id = V4L2_CID_BRIGHTNESS,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +			.name = "Brightness",
> +			.minimum = ISPPRV_BRIGHT_LOW,
> +			.maximum = ISPPRV_BRIGHT_HIGH,
> +			.step = ISPPRV_BRIGHT_STEP,
> +			.default_value = ISPPRV_BRIGHT_DEF,
> +		},
> +		.current_value = ISPPRV_BRIGHT_DEF,
> +	},
> +	{
> +		{
> +			.id = V4L2_CID_CONTRAST,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +			.name = "Contrast",
> +			.minimum = ISPPRV_CONTRAST_LOW,
> +			.maximum = ISPPRV_CONTRAST_HIGH,
> +			.step = ISPPRV_CONTRAST_STEP,
> +			.default_value = ISPPRV_CONTRAST_DEF,
> +		},
> +		.current_value = ISPPRV_CONTRAST_DEF,
> +	},
> +	{
> +		{
> +			.id = V4L2_CID_COLORFX,
> +			.type = V4L2_CTRL_TYPE_MENU,
> +			.name = "Color Effects",
> +			.minimum = V4L2_COLORFX_NONE,
> +			.maximum = V4L2_COLORFX_SEPIA,
> +			.step = 1,
> +			.default_value = V4L2_COLORFX_NONE,
> +		},
> +		.current_value = V4L2_COLORFX_NONE,
> +	}
> +};
> +
> +static struct v4l2_querymenu video_menu[] = {
> +	{
> +		.id = V4L2_CID_COLORFX,
> +		.index = 0,
> +		.name = "None",
> +	},
> +	{
> +		.id = V4L2_CID_COLORFX,
> +		.index = 1,
> +		.name = "B&W",
> +	},
> +	{
> +		.id = V4L2_CID_COLORFX,
> +		.index = 2,
> +		.name = "Sepia",
> +	},
> +};
> +
> +struct isp_buf {
> +	dma_addr_t isp_addr;
> +	void (*complete)(struct videobuf_buffer *vb, void *priv);
> +	struct videobuf_buffer *vb;
> +	void *priv;
> +	u32 vb_state;
> +};
> +
> +#define ISP_BUFS_IS_FULL(bufs) \
> +	(((bufs)->queue + 1) % NUM_BUFS == (bufs)->done)
> +#define ISP_BUFS_IS_EMPTY(bufs)		((bufs)->queue == (bufs)->done)
> +#define ISP_BUFS_IS_LAST(bufs) \
> +	((bufs)->queue == ((bufs)->done + 1) % NUM_BUFS)
> +#define ISP_BUFS_QUEUED(bufs) \
> +	((((bufs)->done - (bufs)->queue + NUM_BUFS)) % NUM_BUFS)
> +#define ISP_BUF_DONE(bufs)		((bufs)->buf + (bufs)->done)
> +#define ISP_BUF_NEXT_DONE(bufs)	\
> +	((bufs)->buf + ((bufs)->done + 1) % NUM_BUFS)
> +#define ISP_BUF_QUEUE(bufs)		((bufs)->buf + (bufs)->queue)
> +#define ISP_BUF_MARK_DONE(bufs) \
> +	(bufs)->done = ((bufs)->done + 1) % NUM_BUFS;
> +#define ISP_BUF_MARK_QUEUED(bufs) \
> +	(bufs)->queue = ((bufs)->queue + 1) % NUM_BUFS;
> +
> +struct isp_bufs {
> +	dma_addr_t isp_addr_capture[VIDEO_MAX_FRAME];
> +	spinlock_t lock;	/* For handling current buffer */
> +	/* queue full: (ispsg.queue + 1) % NUM_BUFS == ispsg.done
> +	   queue empty: ispsg.queue == ispsg.done */
> +	struct isp_buf buf[NUM_BUFS];
> +	/* Next slot to queue a buffer. */
> +	int queue;
> +	/* Buffer that is being processed. */
> +	int done;
> +	/* Wait for this many hs_vs before anything else. */
> +	int wait_hs_vs;
> +};
> +
> +/**
> + * 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).
> + */
> +struct isp_irq {
> +	isp_callback_t isp_callbk[CBK_END];
> +	isp_vbq_callback_ptr isp_callbk_arg1[CBK_END];
> +	void *isp_callbk_arg2[CBK_END];
> +};
> +
> +/**
> + * struct ispmodule - Structure for storing ISP sub-module information.
> + * @isp_pipeline: Bit mask for submodules enabled within the ISP.
> + * @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 isp_module {
> +	unsigned int isp_pipeline;
> +	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;
> +};
> +
> +#define RAW_CAPTURE(isp) \
> +	(!((isp)->module.isp_pipeline & OMAP_ISP_PREVIEW))
> +
> +/**
> + * struct isp - Structure for storing ISP Control module information
> + * @lock: Spinlock to sync between isr and processes.
> + * @isp_mutex: Semaphore used to get access to the ISP.
> + * @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;	/* For handling registered ISP callbacks */
> +	struct mutex isp_mutex;	/* For handling ref_count field */
> +	int ref_count;
> +	struct clk *cam_ick;
> +	struct clk *cam_mclk;
> +	struct clk *csi2_fck;
> +	struct isp_interface_config *config;
> +	dma_addr_t tmp_buf;
> +	size_t tmp_buf_size;
> +	unsigned long tmp_buf_offset;
> +	 struct isp_bufs bufs;
> +	 struct isp_irq irq;
> +	 struct isp_module module;
> +} isp_obj;
> +
> +/* Structure for saving/restoring ISP module registers */
> +static struct isp_reg isp_reg_list[] = {
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_GRESET_LENGTH, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_REPLAY, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_FRAME, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_DELAY, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_DELAY, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_DELAY, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_LENGTH, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_LENGTH, 0},
> +	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_LENGTH, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_SYSCONFIG, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_IRQENABLE, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_CTRL, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_CTRL, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_START, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_START, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_END, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_END, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_WINDOWSIZE, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_WINDOWSIZE, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_THRESHOLD, 0},
> +	{OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_THRESHOLD, 0},
> +	{0, ISP_TOK_TERM, 0}
> +};
> +
> +u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset)
> +{
> +	return __raw_readl(omap3isp->mmio_base[isp_mmio_range] + reg_offset);
> +}
> +EXPORT_SYMBOL(isp_reg_readl);
> +
> +void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
> +								u32 reg_offset)
> +{
> +	__raw_writel(reg_value,
> +			omap3isp->mmio_base[isp_mmio_range] + reg_offset);
> +}
> +EXPORT_SYMBOL(isp_reg_writel);
> +
> +/*
> + *
> + * 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;
> +}
> +
> +static int find_next_vctrl(int id)
> +{
> +	int i;
> +	u32 best = (u32)-1;
> +
> +	for (i = 0; i < ARRAY_SIZE(video_control); i++) {
> +		if (video_control[i].qc.id > id &&
> +						(best == (u32)-1 ||
> +						video_control[i].qc.id <
> +						video_control[best].qc.id)) {
> +			best = i;
> +		}
> +	}
> +
> +	if (best == (u32)-1)
> +		return -EINVAL;
> +
> +	return best;
> +}
> +
> +/**
> + * find_vmenu - Returns index of the menu array of the requested ctrl option.
> + * @id: Requested control ID.
> + * @index: Requested menu option index.
> + *
> + * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
> + * domain.
> + **/
> +static int find_vmenu(int id, int index)
> +{
> +	int i;
> +
> +	if (id < V4L2_CID_BASE)
> +		return -EDOM;
> +
> +	for (i = (ARRAY_SIZE(video_menu) - 1); i >= 0; i--) {
> +		if ((video_menu[i].id != id) || (video_menu[i].index != index))
> +			continue;
> +		return i;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +/**
> + * isp_release_resources - Free ISP submodules
> + **/
> +static void isp_release_resources(void)
> +{
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
> +		ispccdc_free();
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW)
> +		isppreview_free();
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER)
> +		ispresizer_free();
> +	return;
> +}
> +
> +static int isp_wait(int (*busy)(void), int wait_for_busy, int max_wait)
> +{
> +	int wait = 0;
> +
> +	if (max_wait == 0)
> +		max_wait = 10000; /* 10 ms */
> +
> +	while ((wait_for_busy && !busy())
> +	       || (!wait_for_busy && busy())) {
> +		rmb();
> +		udelay(1);
> +		wait++;
> +		if (wait > max_wait) {
> +			printk(KERN_ALERT "%s: wait is too much\n", __func__);
> +			return -EBUSY;
> +		}
> +	}
> +	DPRINTK_ISPCTRL(KERN_ALERT "%s: wait %d\n", __func__, wait);
> +
> +	return 0;
> +}
> +
> +static int ispccdc_sbl_wait_idle(int max_wait)
> +{
> +	return isp_wait(ispccdc_sbl_busy, 0, max_wait);
> +}
> +
> +static void isp_enable_interrupts(int is_raw)
> +{
> +	isp_reg_writel(-1, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +		    IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
> +		    IRQ0ENABLE_HS_VS_IRQ |
> +		    IRQ0ENABLE_CCDC_VD0_IRQ |
> +		    IRQ0ENABLE_CCDC_VD1_IRQ);
> +
> +	if (is_raw)
> +		return;
> +
> +	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +		    IRQ0ENABLE_PRV_DONE_IRQ |
> +		    IRQ0ENABLE_RSZ_DONE_IRQ);
> +
> +	return;
> +}
> +
> +static void isp_disable_interrupts(void)
> +{
> +	isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +		    ~(IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
> +			IRQ0ENABLE_HS_VS_IRQ |
> +			IRQ0ENABLE_CCDC_VD0_IRQ |
> +			IRQ0ENABLE_CCDC_VD1_IRQ |
> +			IRQ0ENABLE_PRV_DONE_IRQ |
> +			IRQ0ENABLE_RSZ_DONE_IRQ));
> +}
> +
> +/**
> + * 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);
> +	isp_obj.irq.isp_callbk[type] = callback;
> +	isp_obj.irq.isp_callbk_arg1[type] = arg1;
> +	isp_obj.irq.isp_callbk_arg2[type] = arg2;
> +	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
> +
> +	switch (type) {
> +	case CBK_H3A_AWB_DONE:
> +		isp_reg_writel(IRQ0ENABLE_H3A_AWB_DONE_IRQ,
> +					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						IRQ0ENABLE_H3A_AWB_DONE_IRQ);
> +		break;
> +	case CBK_H3A_AF_DONE:
> +		isp_reg_writel(IRQ0ENABLE_H3A_AF_DONE_IRQ,
> +					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						IRQ0ENABLE_H3A_AF_DONE_IRQ);
> +		break;
> +	case CBK_HIST_DONE:
> +		isp_reg_writel(IRQ0ENABLE_HIST_DONE_IRQ,
> +					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						IRQ0ENABLE_HIST_DONE_IRQ);
> +		break;
> +	case CBK_PREV_DONE:
> +		isp_reg_writel(IRQ0ENABLE_PRV_DONE_IRQ,
> +					OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						IRQ0ENABLE_PRV_DONE_IRQ);
> +		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);
> +	isp_obj.irq.isp_callbk[type] = NULL;
> +	isp_obj.irq.isp_callbk_arg1[type] = NULL;
> +	isp_obj.irq.isp_callbk_arg2[type] = NULL;
> +	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
> +
> +	switch (type) {
> +	case CBK_H3A_AWB_DONE:
> +		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						~IRQ0ENABLE_H3A_AWB_DONE_IRQ);
> +		break;
> +	case CBK_H3A_AF_DONE:
> +		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						~IRQ0ENABLE_H3A_AF_DONE_IRQ);
> +		break;
> +	case CBK_HIST_DONE:
> +		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						~IRQ0ENABLE_HIST_DONE_IRQ);
> +		break;
> +	case CBK_CSIA:
> +		isp_csi2_irq_set(0);
> +		break;
> +	case CBK_CSIB:
> +		isp_reg_writel(IRQ0ENABLE_CSIB_IRQ, OMAP3_ISP_IOMEM_MAIN,
> +							ISP_IRQ0STATUS);
> +		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						IRQ0ENABLE_CSIB_IRQ);
> +		break;
> +	case CBK_PREV_DONE:
> +		isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
> +						~IRQ0ENABLE_PRV_DONE_IRQ);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(isp_unset_callback);
> +
> +/**
> + * 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:
> +		isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
> +					~ISPTCTRL_CTRL_DIVA_MASK,
> +					divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
> +		DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclka set to %d Hz\n",
> +								currentxclk);
> +		break;
> +	case 1:
> +		isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
> +					~ISPTCTRL_CTRL_DIVB_MASK,
> +					divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
> +		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_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.
> + **/
> +static void isp_power_settings(int idle)
> +{
> +	if (idle) {
> +		isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
> +				(ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY <<
> +				ISP_SYSCONFIG_MIDLEMODE_SHIFT),
> +				OMAP3_ISP_IOMEM_MAIN,
> +				ISP_SYSCONFIG);
> +		if (omap_rev() == OMAP3430_REV_ES1_0) {
> +			isp_reg_writel(ISPCSI1_AUTOIDLE |
> +					(ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
> +					ISPCSI1_MIDLEMODE_SHIFT),
> +					OMAP3_ISP_IOMEM_CSI2A,
> +					ISP_CSIA_SYSCONFIG);
> +			isp_reg_writel(ISPCSI1_AUTOIDLE |
> +					(ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
> +					ISPCSI1_MIDLEMODE_SHIFT),
> +					OMAP3_ISP_IOMEM_CCP2,
> +					ISP_CSIB_SYSCONFIG);
> +		}
> +		isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
> +								ISP_CTRL);
> +
> +	} else {
> +		isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
> +				(ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY <<
> +				ISP_SYSCONFIG_MIDLEMODE_SHIFT),
> +				OMAP3_ISP_IOMEM_MAIN,
> +				ISP_SYSCONFIG);
> +		if (omap_rev() == OMAP3430_REV_ES1_0) {
> +			isp_reg_writel(ISPCSI1_AUTOIDLE |
> +					(ISPCSI1_MIDLEMODE_FORCESTANDBY <<
> +					ISPCSI1_MIDLEMODE_SHIFT),
> +					OMAP3_ISP_IOMEM_CSI2A,
> +					ISP_CSIA_SYSCONFIG);
> +
> +			isp_reg_writel(ISPCSI1_AUTOIDLE |
> +					(ISPCSI1_MIDLEMODE_FORCESTANDBY <<
> +					ISPCSI1_MIDLEMODE_SHIFT),
> +					OMAP3_ISP_IOMEM_CCP2,
> +					ISP_CSIB_SYSCONFIG);
> +		}
> +
> +		isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
> +								ISP_CTRL);
> +	}
> +}
> +
> +#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 */
> +	isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSCONFIG) |
> +							BIT(1),
> +							OMAP3_ISP_IOMEM_CCP2,
> +							ISPCSI1_SYSCONFIG);
> +	while (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
> +								BIT(0))) {
> +		udelay(10);
> +		if (i++ > 10)
> +			break;
> +	}
> +	if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
> +								BIT(0))) {
> +		printk(KERN_WARNING
> +			"omap3_isp: timeout waiting for csi reset\n");
> +	}
> +
> +	/* ISPCSI1_CTRL */
> +	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, 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 */
> +	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
> +
> +	/* ISPCSI1_LCx_CTRL logical channel #0 */
> +	reg = ISPCSI1_LCx_CTRL(0);	/* reg = ISPCSI1_CTRL1; */
> +	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, 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);
> +	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
> +
> +	/* ISPCSI1_DAT_START for logical channel #0 */
> +	reg = ISPCSI1_LCx_DAT_START(0);		/* reg = ISPCSI1_DAT_START; */
> +	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
> +	BIT_SET(val, 16, 0xfff, config->u.csi.data_start);
> +	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
> +
> +	/* ISPCSI1_DAT_SIZE for logical channel #0 */
> +	reg = ISPCSI1_LCx_DAT_SIZE(0);		/* reg = ISPCSI1_DAT_SIZE; */
> +	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
> +	BIT_SET(val, 16, 0xfff, config->u.csi.data_size);
> +	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
> +
> +	/* Clear status bits for logical channel #0 */
> +	isp_reg_writel(0xFFF & ~BIT(6), OMAP3_ISP_IOMEM_CCP2,
> +						ISPCSI1_LC01_IRQSTATUS);
> +
> +	/* Enable CSI1 */
> +	val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
> +	val |=  BIT(0) | BIT(4);
> +	isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
> +
> +	if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, 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 = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
> +	int r;
> +
> +	isp_obj.config = config;
> +
> +	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);
> +
> +	isp_buf_init();
> +
> +	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_CSIA:
> +		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
> +		ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
> +
> +		isp_csi2_ctx_config_format(0, config->u.csi.format);
> +		isp_csi2_ctx_update(0, false);
> +
> +		if (config->u.csi.crc)
> +			isp_csi2_ctrl_config_ecc_enable(true);
> +
> +		isp_csi2_ctrl_config_vp_out_ctrl(config->u.csi.vpclk);
> +		isp_csi2_ctrl_config_vp_only_enable(true);
> +		isp_csi2_ctrl_config_vp_clk_enable(true);
> +		isp_csi2_ctrl_update(false);
> +
> +		isp_csi2_irq_complexio1_set(1);
> +		isp_csi2_irq_status_set(1);
> +		isp_csi2_irq_set(1);
> +
> +		isp_csi2_enable(1);
> +		mdelay(3);
> +		break;
> +	case ISP_CSIB:
> +		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
> +		r = isp_init_csi(config);
> +		if (r)
> +			return r;
> +		break;
> +	case ISP_NONE:
> +		return 0;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	ispctrl_val &= ~(ISPCTRL_SYNC_DETECT_VSRISE);
> +	ispctrl_val |= (config->hsvs_syncdetect);
> +
> +	isp_reg_writel(ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
> +
> +	/* Set sensor specific fields in CCDC and Previewer module.*/
> +	isppreview_set_skip(config->prev_sph, config->prev_slv);
> +	ispccdc_set_wenlog(config->wenlog);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(isp_configure_interface);
> +
> +static int isp_buf_process(struct isp_bufs *bufs);
> +
> +/**
> + * 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 isp_obj.irq 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 *_isp)
> +{
> +	struct isp *isp = _isp;
> +	struct isp_irq *irqdis = &isp->irq;
> +	struct isp_bufs *bufs = &isp->bufs;
> +	unsigned long flags;
> +	u32 irqstatus = 0;
> +	unsigned long irqflags = 0;
> +	int wait_hs_vs = 0;
> +
> +	irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +	isp_reg_writel(irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
> +
> +	spin_lock_irqsave(&bufs->lock, flags);
> +	wait_hs_vs = bufs->wait_hs_vs;
> +	if (irqstatus & HS_VS && bufs->wait_hs_vs)
> +		bufs->wait_hs_vs--;
> +	spin_unlock_irqrestore(&bufs->lock, flags);
> +
> +	spin_lock_irqsave(&isp_obj.lock, irqflags);
> +	/*
> +	 * We need to wait for the first HS_VS interrupt from CCDC.
> +	 * Otherwise our frame (and everything else) might be bad.
> +	 */
> +	if (wait_hs_vs)
> +		goto out_ignore_buff;
> +
> +	if ((irqstatus & CCDC_VD0) == CCDC_VD0) {
> +		if (RAW_CAPTURE(&isp_obj))
> +			isp_buf_process(bufs);
> +	}
> +
> +	if ((irqstatus & PREV_DONE) == PREV_DONE) {
> +		if (irqdis->isp_callbk[CBK_PREV_DONE])
> +			irqdis->isp_callbk[CBK_PREV_DONE](PREV_DONE,
> +				irqdis->isp_callbk_arg1[CBK_PREV_DONE],
> +				irqdis->isp_callbk_arg2[CBK_PREV_DONE]);
> +		else if (!RAW_CAPTURE(&isp_obj) && !ispresizer_busy()) {
> +			if (isp_obj.module.applyCrop) {
> +				ispresizer_applycrop();
> +				if (!ispresizer_busy())
> +					isp_obj.module.applyCrop = 0;
> +			}
> +			if (!isppreview_busy()) {
> +				ispresizer_enable(1);
> +				if (isppreview_busy()) {
> +					/* FIXME: locking! */
> +					ISP_BUF_DONE(bufs)->vb_state =
> +						VIDEOBUF_ERROR;
> +					printk(KERN_ERR "%s: can't stop"
> +					       " preview\n", __func__);
> +				}
> +			}
> +			if (!isppreview_busy())
> +				isppreview_config_shadow_registers();
> +			if (!isppreview_busy())
> +				isph3a_update_wb();
> +		}
> +	}
> +
> +	if ((irqstatus & RESZ_DONE) == RESZ_DONE) {
> +		if (!RAW_CAPTURE(&isp_obj)) {
> +			if (!ispresizer_busy())
> +				ispresizer_config_shadow_registers();
> +			isp_buf_process(bufs);
> +		}
> +	}
> +
> +	if ((irqstatus & H3A_AWB_DONE) == H3A_AWB_DONE) {
> +		if (irqdis->isp_callbk[CBK_H3A_AWB_DONE])
> +			irqdis->isp_callbk[CBK_H3A_AWB_DONE](H3A_AWB_DONE,
> +				irqdis->isp_callbk_arg1[CBK_H3A_AWB_DONE],
> +				irqdis->isp_callbk_arg2[CBK_H3A_AWB_DONE]);
> +	}
> +
> +	if ((irqstatus & HIST_DONE) == HIST_DONE) {
> +		if (irqdis->isp_callbk[CBK_HIST_DONE])
> +			irqdis->isp_callbk[CBK_HIST_DONE](HIST_DONE,
> +				irqdis->isp_callbk_arg1[CBK_HIST_DONE],
> +				irqdis->isp_callbk_arg2[CBK_HIST_DONE]);
> +	}
> +
> +	if ((irqstatus & H3A_AF_DONE) == H3A_AF_DONE) {
> +		if (irqdis->isp_callbk[CBK_H3A_AF_DONE])
> +			irqdis->isp_callbk[CBK_H3A_AF_DONE](H3A_AF_DONE,
> +				irqdis->isp_callbk_arg1[CBK_H3A_AF_DONE],
> +				irqdis->isp_callbk_arg2[CBK_H3A_AF_DONE]);
> +	}
> +
> +
> +out_ignore_buff:
> +	if (irqstatus & LSC_PRE_ERR) {
> +		struct isp_buf *buf = ISP_BUF_DONE(bufs);
> +		ispccdc_enable_lsc(0);
> +		ispccdc_enable_lsc(1);
> +		/* Mark buffer faulty. */
> +		buf->vb_state = VIDEOBUF_ERROR;
> +		printk(KERN_ERR "%s: lsc prefetch error\n", __func__);
> +	}
> +
> +	if ((irqstatus & CSIA) == CSIA) {
> +		struct isp_buf *buf = ISP_BUF_DONE(bufs);
> +		isp_csi2_isr();
> +		buf->vb_state = VIDEOBUF_ERROR;
> +	}
> +
> +	if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
> +		u32 ispcsi1_irqstatus;
> +
> +		ispcsi1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2,
> +						ISPCSI1_LC01_IRQSTATUS);
> +		DPRINTK_ISPCTRL("%x\n", ispcsi1_irqstatus);
> +	}
> +
> +	if (irqdis->isp_callbk[CBK_CATCHALL]) {
> +		irqdis->isp_callbk[CBK_CATCHALL](irqstatus,
> +			irqdis->isp_callbk_arg1[CBK_CATCHALL],
> +			irqdis->isp_callbk_arg2[CBK_CATCHALL]);
> +	}
> +
> +	spin_unlock_irqrestore(&isp_obj.lock, irqflags);
> +
> +#if 1
> +	{
> +		static const struct {
> +			int num;
> +			char *name;
> +		} bits[] = {
> +			{ 31, "HS_VS_IRQ" },
> +			{ 30, "SEC_ERR_IRQ" },
> +			{ 29, "OCP_ERR_IRQ" },
> +			{ 28, "MMU_ERR_IRQ" },
> +			{ 27, "res27" },
> +			{ 26, "res26" },
> +			{ 25, "OVF_IRQ" },
> +			{ 24, "RSZ_DONE_IRQ" },
> +			{ 23, "res23" },
> +			{ 22, "res22" },
> +			{ 21, "CBUFF_IRQ" },
> +			{ 20, "PRV_DONE_IRQ" },
> +			{ 19, "CCDC_LSC_PREFETCH_ERROR" },
> +			{ 18, "CCDC_LSC_PREFETCH_COMPLETED" },
> +			{ 17, "CCDC_LSC_DONE" },
> +			{ 16, "HIST_DONE_IRQ" },
> +			{ 15, "res15" },
> +			{ 14, "res14" },
> +			{ 13, "H3A_AWB_DONE_IRQ" },
> +			{ 12, "H3A_AF_DONE_IRQ" },
> +			{ 11, "CCDC_ERR_IRQ" },
> +			{ 10, "CCDC_VD2_IRQ" },
> +			{  9, "CCDC_VD1_IRQ" },
> +			{  8, "CCDC_VD0_IRQ" },
> +			{  7, "res7" },
> +			{  6, "res6" },
> +			{  5, "res5" },
> +			{  4, "CSIB_IRQ" },
> +			{  3, "CSIB_LCM_IRQ" },
> +			{  2, "res2" },
> +			{  1, "res1" },
> +			{  0, "CSIA_IRQ" },
> +		};
> +		int i;
> +		for (i = 0; i < ARRAY_SIZE(bits); i++) {
> +			if ((1 << bits[i].num) & irqstatus)
> +				DPRINTK_ISPCTRL("%s ", bits[i].name);
> +		}
> +		DPRINTK_ISPCTRL("\n");
> +	}
> +#endif
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/* Device name, needed for resource tracking layer */
> +struct device_driver camera_drv = {
> +	.name = "camera"
> +};
> +
> +struct device camera_dev = {
> +	.driver = &camera_drv,
> +};
> +
> +/**
> + *  isp_tmp_buf_free - To free allocated 10MB memory
> + *
> + **/
> +static void isp_tmp_buf_free(void)
> +{
> +	if (isp_obj.tmp_buf) {
> +		ispmmu_vfree(isp_obj.tmp_buf);
> +		isp_obj.tmp_buf = 0;
> +		isp_obj.tmp_buf_size = 0;
> +	}
> +}
> +
> +/**
> + *  isp_tmp_buf_alloc - To allocate a 10MB memory
> + *
> + **/
> +static u32 isp_tmp_buf_alloc(size_t size)
> +{
> +	isp_tmp_buf_free();
> +
> +	printk(KERN_INFO "%s: allocating %d bytes\n", __func__, size);
> +
> +	isp_obj.tmp_buf = ispmmu_vmalloc(size);
> +	if (IS_ERR((void *)isp_obj.tmp_buf)) {
> +		printk(KERN_ERR "ispmmu_vmap mapping failed ");
> +		return -ENOMEM;
> +	}
> +	isp_obj.tmp_buf_size = size;
> +
> +	isppreview_set_outaddr(isp_obj.tmp_buf);
> +	ispresizer_set_inaddr(isp_obj.tmp_buf);
> +
> +	return 0;
> +}
> +
> +/**
> + * isp_start - Starts ISP submodule
> + *
> + * Start the needed isp components assuming these components
> + * are configured correctly.
> + **/
> +void isp_start(void)
> +{
> +	if ((isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) &&
> +						is_isppreview_enabled())
> +		isppreview_enable(1);
> +
> +	return;
> +}
> +EXPORT_SYMBOL(isp_start);
> +
> +#define ISP_STATISTICS_BUSY				\
> +	()
> +#define ISP_STOP_TIMEOUT	msecs_to_jiffies(1000)
> +/**
> + * isp_stop - Stops isp submodules
> + **/
> +void isp_stop()
> +{
> +	unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
> +	int reset = 0;
> +
> +	isp_disable_interrupts();
> +
> +	/*
> +	 * We need to stop all the modules after CCDC first or they'll
> +	 * never stop since they may not get a full frame from CCDC.
> +	 */
> +	isp_af_enable(0);
> +	isph3a_aewb_enable(0);
> +	isp_hist_enable(0);
> +	isppreview_enable(0);
> +	ispresizer_enable(0);
> +
> +	timeout = jiffies + ISP_STOP_TIMEOUT;
> +	while (isp_af_busy()
> +	       || isph3a_aewb_busy()
> +	       || isp_hist_busy()
> +	       || isppreview_busy()
> +	       || ispresizer_busy()) {
> +		if (time_after(jiffies, timeout)) {
> +			printk(KERN_ERR "%s: can't stop non-ccdc modules\n",
> +			       __func__);
> +			reset = 1;
> +			break;
> +		}
> +		msleep(1);
> +	}
> +
> +	/* Let's stop CCDC now. */
> +	ispccdc_enable_lsc(0);
> +	ispccdc_enable(0);
> +
> +	timeout = jiffies + ISP_STOP_TIMEOUT;
> +	while (ispccdc_busy()) {
> +		if (time_after(jiffies, timeout)) {
> +			printk(KERN_ERR "%s: can't stop ccdc\n", __func__);
> +			reset = 1;
> +			break;
> +		}
> +		msleep(1);
> +	}
> +
> +	isp_buf_init();
> +
> +	if (!reset)
> +		return;
> +
> +	isp_save_ctx();
> +	isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
> +		       | ISP_SYSCONFIG_SOFTRESET,
> +		       OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
> +	timeout = 0;
> +	while (!(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS) & 0x1)) {
> +		if (timeout++ > 10000) {
> +			printk(KERN_ALERT "%s: cannot reset ISP\n", __func__);
> +			break;
> +		}
> +		udelay(1);
> +	}
> +	isp_restore_ctx();
> +}
> +EXPORT_SYMBOL(isp_stop);
> +
> +static void isp_set_buf(struct isp_buf *buf)
> +{
> +	if ((isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) &&
> +						is_ispresizer_enabled())
> +		ispresizer_set_outaddr(buf->isp_addr);
> +	else if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
> +		ispccdc_set_outaddr(buf->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.
> + **/
> +static u32 isp_calc_pipeline(struct v4l2_pix_format *pix_input,
> +			     struct v4l2_pix_format *pix_output)
> +{
> +	isp_release_resources();
> +	if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
> +	     || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
> +	    && pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10) {
> +		isp_obj.module.isp_pipeline = OMAP_ISP_CCDC | OMAP_ISP_PREVIEW |
> +							OMAP_ISP_RESIZER;
> +		ispccdc_request();
> +		isppreview_request();
> +		ispresizer_request();
> +		ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP);
> +		isppreview_config_datapath(PRV_RAW_CCDC, PREVIEW_MEM);
> +		ispresizer_config_datapath(RSZ_MEM_YUV);
> +	} else {
> +		isp_obj.module.isp_pipeline = OMAP_ISP_CCDC;
> +		ispccdc_request();
> +		if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
> +		    || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
> +			ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP_MEM);
> +		else
> +			ispccdc_config_datapath(CCDC_YUV_SYNC,
> +							CCDC_OTHERS_MEM);
> +	}
> +	return 0;
> +}
> +
> +/**
> + * 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.
> + **/
> +static void isp_config_pipeline(struct v4l2_pix_format *pix_input,
> +				struct v4l2_pix_format *pix_output)
> +{
> +	ispccdc_config_size(isp_obj.module.ccdc_input_width,
> +			isp_obj.module.ccdc_input_height,
> +			isp_obj.module.ccdc_output_width,
> +			isp_obj.module.ccdc_output_height);
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
> +		isppreview_config_size(isp_obj.module.preview_input_width,
> +			isp_obj.module.preview_input_height,
> +			isp_obj.module.preview_output_width,
> +			isp_obj.module.preview_output_height);
> +	}
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
> +		ispresizer_config_size(isp_obj.module.resizer_input_width,
> +					isp_obj.module.resizer_input_height,
> +					isp_obj.module.resizer_output_width,
> +					isp_obj.module.resizer_output_height);
> +	}
> +
> +	if (pix_output->pixelformat == V4L2_PIX_FMT_UYVY) {
> +		isppreview_config_ycpos(YCPOS_YCrYCb);
> +		if (is_ispresizer_enabled())
> +			ispresizer_config_ycpos(0);
> +	} else {
> +		isppreview_config_ycpos(YCPOS_CrYCbY);
> +		if (is_ispresizer_enabled())
> +			ispresizer_config_ycpos(1);
> +	}
> +
> +	return;
> +}
> +
> +static void isp_buf_init(void)
> +{
> +	struct isp_bufs *bufs = &isp_obj.bufs;
> +	int sg;
> +
> +	bufs->queue = 0;
> +	bufs->done = 0;
> +	bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
> +	for (sg = 0; sg < NUM_BUFS; sg++) {
> +		bufs->buf[sg].complete = NULL;
> +		bufs->buf[sg].vb = NULL;
> +		bufs->buf[sg].priv = NULL;
> +	}
> +}
> +
> +/**
> + * isp_vbq_sync - Walks the pages table and flushes the cache for
> + *                each page.
> + **/
> +static int isp_vbq_sync(struct videobuf_buffer *vb, int when)
> +{
> +	flush_cache_all();
> +
> +	return 0;
> +}
> +
> +static int isp_buf_process(struct isp_bufs *bufs)
> +{
> +	struct isp_buf *buf = NULL;
> +	unsigned long flags;
> +	int last;
> +
> +	spin_lock_irqsave(&bufs->lock, flags);
> +
> +	if (ISP_BUFS_IS_EMPTY(bufs))
> +		goto out;
> +
> +	if (RAW_CAPTURE(&isp_obj) && ispccdc_sbl_wait_idle(1000)) {
> +		printk(KERN_ERR "ccdc %d won't become idle!\n",
> +		       RAW_CAPTURE(&isp_obj));
> +		goto out;
> +	}
> +
> +	/* We had at least one buffer in queue. */
> +	buf = ISP_BUF_DONE(bufs);
> +	last = ISP_BUFS_IS_LAST(bufs);
> +
> +	if (!last) {
> +		/* Set new buffer address. */
> +		isp_set_buf(ISP_BUF_NEXT_DONE(bufs));
> +	} else {
> +		/* Tell ISP not to write any of our buffers. */
> +		isp_disable_interrupts();
> +		if (RAW_CAPTURE(&isp_obj))
> +			ispccdc_enable(0);
> +		else
> +			ispresizer_enable(0);
> +		/*
> +		 * We must wait for the HS_VS since before that the
> +		 * CCDC may trigger interrupts even if it's not
> +		 * receiving a frame.
> +		 */
> +		bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
> +	}
> +	if ((RAW_CAPTURE(&isp_obj) && ispccdc_busy())
> +	    || (!RAW_CAPTURE(&isp_obj) && ispresizer_busy())) {
> +		/*
> +		 * Next buffer available: for the transfer to succeed, the
> +		 * CCDC (RAW capture) or resizer (YUV capture) must be idle
> +		 * for the duration of transfer setup. Bad things happen
> +		 * otherwise!
> +		 *
> +		 * Next buffer not available: if we fail to stop the
> +		 * ISP the buffer is probably going to be bad.
> +		 */
> +		/* Mark this buffer faulty. */
> +		buf->vb_state = VIDEOBUF_ERROR;
> +		/* Mark next faulty, too, in case we have one. */
> +		if (!last) {
> +			ISP_BUF_NEXT_DONE(bufs)->vb_state =
> +				VIDEOBUF_ERROR;
> +			printk(KERN_ALERT "OUCH!!!\n");
> +		} else {
> +			printk(KERN_ALERT "Ouch!\n");
> +		}
> +	}
> +
> +	/* Mark the current buffer as done. */
> +	ISP_BUF_MARK_DONE(bufs);
> +
> +	DPRINTK_ISPCTRL(KERN_ALERT "%s: finish %d mmu %p\n", __func__,
> +	       (bufs->done - 1 + NUM_BUFS) % NUM_BUFS,
> +	       (bufs->buf+((bufs->done - 1 + NUM_BUFS) % NUM_BUFS))->isp_addr);
> +
> +out:
> +	spin_unlock_irqrestore(&bufs->lock, flags);
> +
> +	if (buf != NULL) {
> +		/*
> +		 * We want to dequeue a buffer from the video buffer
> +		 * queue. Let's do it!
> +		 */
> +		isp_vbq_sync(buf->vb, DMA_FROM_DEVICE);
> +		buf->vb->state = buf->vb_state;
> +		buf->complete(buf->vb, buf->priv);
> +	}
> +
> +	return 0;
> +}
> +
> +int isp_buf_queue(struct videobuf_buffer *vb,
> +		  void (*complete)(struct videobuf_buffer *vb, void *priv),
> +		  void *priv)
> +{
> +	unsigned long flags;
> +	struct isp_buf *buf;
> +	struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
> +	const struct scatterlist *sglist = dma->sglist;
> +	struct isp_bufs *bufs = &isp_obj.bufs;
> +	int sglen = dma->sglen;
> +
> +	BUG_ON(sglen < 0 || !sglist);
> +
> +	isp_vbq_sync(vb, DMA_TO_DEVICE);
> +
> +	spin_lock_irqsave(&bufs->lock, flags);
> +
> +	BUG_ON(ISP_BUFS_IS_FULL(bufs));
> +
> +	buf = ISP_BUF_QUEUE(bufs);
> +
> +	buf->isp_addr = bufs->isp_addr_capture[vb->i];
> +	buf->complete = complete;
> +	buf->vb = vb;
> +	buf->priv = priv;
> +	buf->vb_state = VIDEOBUF_DONE;
> +
> +	if (ISP_BUFS_IS_EMPTY(bufs)) {
> +		isp_enable_interrupts(RAW_CAPTURE(&isp_obj));
> +		isp_set_buf(buf);
> +		ispccdc_enable(1);
> +		isp_start();
> +	}
> +
> +	ISP_BUF_MARK_QUEUED(bufs);
> +
> +	spin_unlock_irqrestore(&bufs->lock, flags);
> +
> +	DPRINTK_ISPCTRL(KERN_ALERT "%s: queue %d vb %d, mmu %p\n", __func__,
> +	       (bufs->queue - 1 + NUM_BUFS) % NUM_BUFS, vb->i,
> +	       buf->isp_addr);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(isp_buf_queue);
> +
> +int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
> +		  unsigned int *size)
> +{
> +	int rval = 0;
> +	size_t tmp_size = PAGE_ALIGN(isp_obj.module.preview_output_width
> +				     * isp_obj.module.preview_output_height
> +				     * ISP_BYTES_PER_PIXEL);
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW
> +	    && isp_obj.tmp_buf_size < tmp_size)
> +		rval = isp_tmp_buf_alloc(tmp_size);
> +
> +	return rval;
> +}
> +EXPORT_SYMBOL(isp_vbq_setup);
> +
> +/**
> + * 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;
> +	struct isp_bufs *bufs = &isp_obj.bufs;
> +
> +	int err = 0;
> +
> +	vdma = videobuf_to_dma(vb);
> +
> +	isp_addr = ispmmu_vmap(vdma->sglist, vdma->sglen);
> +
> +	if (IS_ERR_VALUE(isp_addr))
> +		err = -EIO;
> +	else
> +		bufs->isp_addr_capture[vb->i] = isp_addr;
> +
> +	return err;
> +}
> +EXPORT_SYMBOL(isp_vbq_prepare);
> +
> +/**
> + * 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)
> +{
> +	struct isp_bufs *bufs = &isp_obj.bufs;
> +
> +	ispmmu_vunmap(bufs->isp_addr_capture[vb->i]);
> +	bufs->isp_addr_capture[vb->i] = (dma_addr_t)NULL;
> +	return;
> +}
> +EXPORT_SYMBOL(isp_vbq_release);
> +
> +/**
> + * 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;
> +
> +	if (a->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
> +		a->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
> +		i = find_next_vctrl(a->id);
> +	} else {
> +		i = find_vctrl(a->id);
> +	}
> +
> +	if (i < 0)
> +		return -EINVAL;
> +
> +	*a = video_control[i].qc;
> +	return 0;
> +}
> +EXPORT_SYMBOL(isp_queryctrl);
> +
> +/**
> + * 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_querymenu(struct v4l2_querymenu *a)
> +{
> +	int i;
> +
> +	i = find_vmenu(a->id, a->index);
> +
> +	if (i < 0)
> +		return -EINVAL;
> +
> +	*a = video_menu[i];
> +	return 0;
> +}
> +EXPORT_SYMBOL(isp_querymenu);
> +
> +/**
> + * 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)
> +{
> +	u8 current_value;
> +	int rval = 0;
> +
> +	if (!isp_obj.ref_count)
> +		return -EINVAL;
> +
> +	switch (a->id) {
> +	case V4L2_CID_BRIGHTNESS:
> +		isppreview_query_brightness(&current_value);
> +		a->value = current_value / ISPPRV_BRIGHT_UNITS;
> +		break;
> +	case V4L2_CID_CONTRAST:
> +		isppreview_query_contrast(&current_value);
> +		a->value = current_value / ISPPRV_CONTRAST_UNITS;
> +		break;
> +	case V4L2_CID_COLORFX:
> +		isppreview_get_color(&current_value);
> +		a->value = current_value;
> +		break;
> +	default:
> +		rval = -EINVAL;
> +		break;
> +	}
> +
> +	return rval;
> +}
> +EXPORT_SYMBOL(isp_g_ctrl);
> +
> +/**
> + * 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;
> +	u8 new_value = a->value;
> +
> +	if (!isp_obj.ref_count)
> +		return -EINVAL;
> +
> +	switch (a->id) {
> +	case V4L2_CID_BRIGHTNESS:
> +		if (new_value > ISPPRV_BRIGHT_HIGH)
> +			rval = -EINVAL;
> +		else
> +			isppreview_update_brightness(&new_value);
> +		break;
> +	case V4L2_CID_CONTRAST:
> +		if (new_value > ISPPRV_CONTRAST_HIGH)
> +			rval = -EINVAL;
> +		else
> +			isppreview_update_contrast(&new_value);
> +		break;
> +	case V4L2_CID_COLORFX:
> +		if (new_value > V4L2_COLORFX_SEPIA)
> +			rval = -EINVAL;
> +		else
> +			isppreview_set_color(&new_value);
> +		break;
> +	default:
> +		rval = -EINVAL;
> +		break;
> +	}
> +
> +	return rval;
> +}
> +EXPORT_SYMBOL(isp_s_ctrl);
> +
> +/**
> + * 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;
> +
> +	if (!isp_obj.ref_count)
> +		return -EINVAL;
> +
> +	switch (cmd) {
> +	case VIDIOC_PRIVATE_ISP_CCDC_CFG:
> +		rval = omap34xx_isp_ccdc_config(arg);
> +		break;
> +	case VIDIOC_PRIVATE_ISP_PRV_CFG:
> +		rval = omap34xx_isp_preview_config(arg);
> +		break;
> +	case VIDIOC_PRIVATE_ISP_AEWB_CFG: {
> +		struct isph3a_aewb_config *params;
> +		params = (struct isph3a_aewb_config *)arg;
> +		rval = isph3a_aewb_configure(params);
> +		}
> +		break;
> +	case VIDIOC_PRIVATE_ISP_AEWB_REQ: {
> +		struct isph3a_aewb_data *data;
> +		data = (struct isph3a_aewb_data *)arg;
> +		rval = isph3a_aewb_request_statistics(data);
> +		}
> +		break;
> +	case VIDIOC_PRIVATE_ISP_HIST_CFG: {
> +		struct isp_hist_config *params;
> +		params = (struct isp_hist_config *)arg;
> +		rval = isp_hist_configure(params);
> +		}
> +		break;
> +	case VIDIOC_PRIVATE_ISP_HIST_REQ: {
> +		struct isp_hist_data *data;
> +		data = (struct isp_hist_data *)arg;
> +		rval = isp_hist_request_statistics(data);
> +		}
> +		break;
> +	case VIDIOC_PRIVATE_ISP_AF_CFG: {
> +		struct af_configuration *params;
> +		params = (struct af_configuration *)arg;
> +		rval = isp_af_configure(params);
> +		}
> +		break;
> +	case VIDIOC_PRIVATE_ISP_AF_REQ: {
> +		struct isp_af_data *data;
> +		data = (struct isp_af_data *)arg;
> +		rval = isp_af_request_statistics(data);
> +		}
> +		break;
> +	default:
> +		rval = -EINVAL;
> +		break;
> +	}
> +	return rval;
> +}
> +EXPORT_SYMBOL(isp_handle_private);
> +
> +/**
> + * 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_pix_format *pix)
> +{
> +	*pix = isp_obj.module.pix;
> +	return;
> +}
> +EXPORT_SYMBOL(isp_g_fmt_cap);
> +
> +/**
> + * 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 = 0, crop_scaling_h = 0;
> +	int rval = 0;
> +
> +	if (!isp_obj.ref_count)
> +		return -EINVAL;
> +
> +	rval = isp_calc_pipeline(pix_input, pix_output);
> +	if (rval)
> +		goto out;
> +
> +	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 ((isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) &&
> +	    (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;
> +	unsigned long org_left, num_pix, new_top;
> +
> +	struct v4l2_pix_format *pix = croppix;
> +
> +	crop_scaling_w = (isp_obj.module.preview_output_width * 10) /
> +								pix->width;
> +	crop_scaling_h = (isp_obj.module.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;
> +
> +	org_left = cur_rect.left;
> +	while (((int)cur_rect.left & 0xFFFFFFF0) != (int)cur_rect.left)
> +		(int)cur_rect.left--;
> +
> +	num_pix = org_left - cur_rect.left;
> +	new_top = (int)(num_pix * 3) / 4;
> +	cur_rect.top = cur_rect.top - new_top;
> +	cur_rect.height = (2 * new_top) + cur_rect.height;
> +
> +	cur_rect.width = cur_rect.width + (2 * num_pix);
> +	while (((int)cur_rect.width & 0xFFFFFFF0) != (int)cur_rect.width)
> +		(int)cur_rect.width--;
> +
> +	isp_obj.tmp_buf_offset = ((cur_rect.left * 2) +
> +		((isp_obj.module.preview_output_width) * 2 * cur_rect.top));
> +
> +	ispresizer_trycrop(cur_rect.left, cur_rect.top, cur_rect.width,
> +					cur_rect.height,
> +					isp_obj.module.resizer_output_width,
> +					isp_obj.module.resizer_output_height);
> +
> +	return;
> +}
> +EXPORT_SYMBOL(isp_config_crop);
> +
> +/**
> + * 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;
> +}
> +EXPORT_SYMBOL(isp_g_crop);
> +
> +/**
> + * 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 (!isp_obj.ref_count)
> +		return -EINVAL;
> +
> +	if (crop->c.left < 0)
> +		crop->c.left = 0;
> +	if (crop->c.width < 0)
> +		crop->c.width = 0;
> +	if (crop->c.top < 0)
> +		crop->c.top = 0;
> +	if (crop->c.height < 0)
> +		crop->c.height = 0;
> +
> +	if (crop->c.left >= pix->width)
> +		crop->c.left = pix->width - 1;
> +	if (crop->c.top >= pix->height)
> +		crop->c.top = pix->height - 1;
> +
> +	if (crop->c.left + crop->c.width > pix->width)
> +		crop->c.width = pix->width - crop->c.left;
> +	if (crop->c.top + crop->c.height > pix->height)
> +		crop->c.height = pix->height - crop->c.top;
> +
> +	ispcroprect.left = crop->c.left;
> +	ispcroprect.top = crop->c.top;
> +	ispcroprect.width = crop->c.width;
> +	ispcroprect.height = crop->c.height;
> +
> +	isp_config_crop(pix);
> +
> +	isp_obj.module.applyCrop = 1;
> +
> +	return rval;
> +}
> +EXPORT_SYMBOL(isp_s_crop);
> +
> +/**
> + * 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;
> +
> +	rval = isp_calc_pipeline(pix_input, pix_output);
> +	if (rval)
> +		goto out;
> +
> +	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.
> + **/
> +static int isp_try_size(struct v4l2_pix_format *pix_input,
> +			struct v4l2_pix_format *pix_output)
> +{
> +	int rval = 0;
> +
> +	if ((pix_output->width <= ISPRSZ_MIN_OUTPUT) ||
> +				(pix_output->height <= ISPRSZ_MIN_OUTPUT))
> +		return -EINVAL;
> +
> +	if ((pix_output->width >= ISPRSZ_MAX_OUTPUT) ||
> +				(pix_output->height > ISPRSZ_MAX_OUTPUT))
> +		return -EINVAL;
> +
> +	isp_obj.module.ccdc_input_width = pix_input->width;
> +	isp_obj.module.ccdc_input_height = pix_input->height;
> +	isp_obj.module.resizer_output_width = pix_output->width;
> +	isp_obj.module.resizer_output_height = pix_output->height;
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC) {
> +		rval = ispccdc_try_size(isp_obj.module.ccdc_input_width,
> +					isp_obj.module.ccdc_input_height,
> +					&isp_obj.module.ccdc_output_width,
> +					&isp_obj.module.ccdc_output_height);
> +		if (rval) {
> +			printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
> +					" supported\n", pix_input->width,
> +					pix_input->height);
> +			return rval;
> +		}
> +		pix_output->width = isp_obj.module.ccdc_output_width;
> +		pix_output->height = isp_obj.module.ccdc_output_height;
> +	}
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
> +		isp_obj.module.preview_input_width =
> +					isp_obj.module.ccdc_output_width;
> +		isp_obj.module.preview_input_height =
> +					isp_obj.module.ccdc_output_height;
> +		rval = isppreview_try_size(isp_obj.module.preview_input_width,
> +					isp_obj.module.preview_input_height,
> +					&isp_obj.module.preview_output_width,
> +					&isp_obj.module.preview_output_height);
> +		if (rval) {
> +			printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
> +					" supported\n", pix_input->width,
> +					pix_input->height);
> +			return rval;
> +		}
> +		pix_output->width = isp_obj.module.preview_output_width;
> +		pix_output->height = isp_obj.module.preview_output_height;
> +	}
> +
> +	if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
> +		isp_obj.module.resizer_input_width =
> +					isp_obj.module.preview_output_width;
> +		isp_obj.module.resizer_input_height =
> +					isp_obj.module.preview_output_height;
> +		rval = ispresizer_try_size(&isp_obj.module.resizer_input_width,
> +					&isp_obj.module.resizer_input_height,
> +					&isp_obj.module.resizer_output_width,
> +					&isp_obj.module.resizer_output_height);
> +		if (rval) {
> +			printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
> +					" supported\n", pix_input->width,
> +					pix_input->height);
> +			return rval;
> +		}
> +		pix_output->width = isp_obj.module.resizer_output_width;
> +		pix_output->height = isp_obj.module.resizer_output_height;
> +	}
> +
> +	return rval;
> +}
> +
> +/**
> + * 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 =
> +		PAGE_ALIGN(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;
> +	}
> +
> +	isp_obj.module.pix.pixelformat = pix_output->pixelformat;
> +	isp_obj.module.pix.width = pix_output->width;
> +	isp_obj.module.pix.height = pix_output->height;
> +	isp_obj.module.pix.field = pix_output->field;
> +	isp_obj.module.pix.bytesperline = pix_output->bytesperline;
> +	isp_obj.module.pix.sizeimage = pix_output->sizeimage;
> +	isp_obj.module.pix.priv = pix_output->priv;
> +	isp_obj.module.pix.colorspace = pix_output->colorspace;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(isp_try_fmt);
> +
> +/**
> + * 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.
> + **/
> +static void isp_save_ctx(void)
> +{
> +	isp_save_context(isp_reg_list);
> +	ispccdc_save_context();
> +	ispmmu_save_context();
> +	isphist_save_context();
> +	isph3a_save_context();
> +	isppreview_save_context();
> +	ispresizer_save_context();
> +}
> +
> +/**
> + * 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.
> + **/
> +static void isp_restore_ctx(void)
> +{
> +	isp_restore_context(isp_reg_list);
> +	ispccdc_restore_context();
> +	ispmmu_restore_context();
> +	isphist_restore_context();
> +	isph3a_restore_context();
> +	isppreview_restore_context();
> +	ispresizer_restore_context();
> +}
> +
> +/**
> + * isp_get - Adquires the ISP resource.
> + *
> + * Initializes the clocks for the first acquire.
> + **/
> +int isp_get(void)
> +{
> +	static int has_context = 0;
> +	int ret_err = 0;
> +
> +	if (omap3isp == NULL)
> +		return -EBUSY;
> +
> +	DPRINTK_ISPCTRL("isp_get: old %d\n", isp_obj.ref_count);
> +	mutex_lock(&(isp_obj.isp_mutex));
> +	if (isp_obj.ref_count == 0) {
> +		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;
> +		}
> +		ret_err = clk_enable(isp_obj.csi2_fck);
> +		if (ret_err) {
> +			DPRINTK_ISPCTRL("ISP_ERR: clk_en for csi2_fclk"
> +								" failed\n");
> +			goto out_clk_enable_csi2_fclk;
> +		}
> +
> +		/* We don't want to restore context before saving it! */
> +		if (has_context)
> +			isp_restore_ctx();
> +		else
> +			has_context = 1;
> +	} else {
> +		mutex_unlock(&isp_obj.isp_mutex);
> +		return -EBUSY;
> +	}
> +	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_csi2_fclk:
> +	clk_disable(isp_obj.cam_mclk);
> +out_clk_enable_mclk:
> +	clk_disable(isp_obj.cam_ick);
> +out_clk_enable_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)
> +{
> +	if (omap3isp == NULL)
> +		return -EBUSY;
> +
> +	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();
> +			isp_tmp_buf_free();
> +			isp_release_resources();
> +			isp_obj.module.isp_pipeline = 0;
> +			clk_disable(isp_obj.cam_ick);
> +			clk_disable(isp_obj.cam_mclk);
> +			clk_disable(isp_obj.csi2_fck);
> +			memset(&ispcroprect, 0, sizeof(ispcroprect));
> +			memset(&cur_rect, 0, sizeof(cur_rect));
> +		}
> +	}
> +	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 = isp_reg_readl(next->mmio_range, 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++)
> +		isp_reg_writel(next->val, next->mmio_range, next->reg);
> +}
> +EXPORT_SYMBOL(isp_restore_context);
> +
> +static int isp_remove(struct platform_device *pdev)
> +{
> +	struct isp_device *isp = platform_get_drvdata(pdev);
> +	int i;
> +
> +	isp_csi2_cleanup();
> +	isp_af_exit();
> +	isp_resizer_cleanup();
> +	isp_preview_cleanup();
> +	ispmmu_cleanup();
> +	isph3a_aewb_cleanup();
> +	isp_hist_cleanup();
> +	isp_ccdc_cleanup();
> +
> +	if (!isp)
> +		return 0;
> +
> +	clk_put(isp_obj.cam_ick);
> +	clk_put(isp_obj.cam_mclk);
> +	clk_put(isp_obj.csi2_fck);
> +
> +	free_irq(isp->irq, &isp_obj);
> +
> +	for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
> +		if (isp->mmio_base[i]) {
> +			iounmap((void *)isp->mmio_base[i]);
> +			isp->mmio_base[i] = 0;
> +		}
> +
> +		if (isp->mmio_base_phys[i]) {
> +			release_mem_region(isp->mmio_base_phys[i],
> +						isp->mmio_size[i]);
> +			isp->mmio_base_phys[i] = 0;
> +		}
> +	}
> +
> +	omap3isp = NULL;
> +
> +	kfree(isp);
> +
> +	return 0;
> +}
> +
> +static int isp_probe(struct platform_device *pdev)
> +{
> +	struct isp_device *isp;
> +	int ret_err = 0;
> +	int i;
> +
> +	isp = kzalloc(sizeof(*isp), GFP_KERNEL);
> +	if (!isp) {
> +		dev_err(&pdev->dev, "could not allocate memory\n");
> +		return -ENODEV;

return -ENOMEM; ?

> +	}
> +
> +	platform_set_drvdata(pdev, isp);
> +
> +	isp->dev = &pdev->dev;
> +
> +	for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
> +		struct resource *mem;
> +		/* request the mem region for the camera registers */
> +		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
> +		if (!mem) {
> +			dev_err(isp->dev, "no mem resource?\n");
> +			return -ENODEV;

Maybe ENODEV is not apropriate here too..

> +		}
> +
> +		if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
> +					pdev->name)) {
> +			dev_err(isp->dev,
> +				"cannot reserve camera register I/O region\n");
> +			return -ENODEV;
> +


<snip>

-- 
Best regards, Klimov Alexey


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

* Re: [PATCH 4/9] omap3isp: Add ISP frontend (CCDC)
  2009-03-03 10:06       ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Sakari Ailus
  2009-03-03 10:06         ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Sakari Ailus
@ 2009-03-03 12:07         ` Alexey Klimov
  1 sibling, 0 replies; 30+ messages in thread
From: Alexey Klimov @ 2009-03-03 12:07 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

On Tue, 2009-03-03 at 12:06 +0200, Sakari Ailus wrote:
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> ---
>  drivers/media/video/isp/ispccdc.c | 1568 +++++++++++++++++++++++++++++++++++++
>  drivers/media/video/isp/ispccdc.h |  203 +++++
>  2 files changed, 1771 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/isp/ispccdc.c
>  create mode 100644 drivers/media/video/isp/ispccdc.h
> 
> diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c
> new file mode 100644
> index 0000000..80ab762
> --- /dev/null
> +++ b/drivers/media/video/isp/ispccdc.c
> @@ -0,0 +1,1568 @@
> +/*
> + * ispccdc.c
> + *
> + * Driver Library for CCDC module in TI's OMAP3 Camera ISP
> + *
> + * Copyright (C) 2009 Texas Instruments, Inc.
> + *
> + * Contributors:
> + *	Senthilvadivu Guruswamy <svadivu@ti.com>
> + *	Pallavi Kulkarni <p-kulkarni@ti.com>
> + *	Sergio Aguirre <saaguirre@ti.com>
> + *
> + * 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/uaccess.h>
> +
> +#include "isp.h"
> +#include "ispreg.h"
> +#include "ispccdc.h"
> +#include "ispmmu.h"
> +
> +#define LSC_TABLE_INIT_SIZE	50052
> +
> +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; /* For checking/modifying ccdc_inuse */
> +	u32 wenlog;
> +} ispccdc_obj;
> +
> +static struct ispccdc_lsc_config lsc_config;
> +static u8 *lsc_gain_table;
> +static unsigned long lsc_ispmmu_addr;
> +static int lsc_initialized;
> +static u8 ccdc_use_lsc;
> +static u8 *lsc_gain_table_tmp;
> +
> +/* Structure for saving/restoring CCDC module registers*/
> +static struct isp_reg ispccdc_reg_list[] = {
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HD_VD_WID, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PIX_LINES, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR0, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR1, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR2, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR3, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR4, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR5, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR6, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR7, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN0, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN1, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD0, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD1, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE, 0},
> +	{OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_OFFSET, 0},
> +	{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 = userspace_add;
> +
> +	if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) {
> +		if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
> +			ispccdc_config_alaw(ccdc_struct->alawip);
> +		ispccdc_enable_alaw(1);
> +	} else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
> +		ispccdc_enable_alaw(0);
> +
> +	if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
> +		ispccdc_enable_lpf(1);
> +	else
> +		ispccdc_enable_lpf(0);
> +
> +	if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) {
> +		if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
> +			if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
> +						(ccdc_struct->bclamp),
> +						sizeof(struct ispccdc_bclamp)))
> +				goto copy_from_user_err;
> +
> +			ispccdc_enable_black_clamp(1);
> +			ispccdc_config_black_clamp(bclamp_t);
> +		} else
> +			ispccdc_enable_black_clamp(1);
> +	} else {
> +		if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
> +			if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
> +						(ccdc_struct->bclamp),
> +						sizeof(struct ispccdc_bclamp)))
> +				goto copy_from_user_err;
> +
> +			ispccdc_enable_black_clamp(0);
> +			ispccdc_config_black_clamp(bclamp_t);
> +		}
> +	}
> +
> +	if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) {
> +		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) {
> +		if (ISP_ABS_CCDC_FPC & ccdc_struct->update) {
> +			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_kmap(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)
> +			ispccdc_enable_fpc(0);
> +
> +	if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
> +		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 (is_isplsc_activated()) {
> +		if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) {
> +			if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
> +				if (copy_from_user(&lsc_config,
> +						(struct ispccdc_lsc_config *)
> +						(ccdc_struct->lsc_cfg),
> +						sizeof(struct
> +						ispccdc_lsc_config)))
> +					goto copy_from_user_err;
> +				ispccdc_config_lsc(&lsc_config);
> +			}
> +			ccdc_use_lsc = 1;
> +		} else if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
> +				ispccdc_enable_lsc(0);
> +				ccdc_use_lsc = 0;
> +		}
> +		if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
> +			if (copy_from_user(lsc_gain_table,
> +				(ccdc_struct->lsc), lsc_config.size))
> +				goto copy_from_user_err;
> +			ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
> +		}
> +	}
> +
> +	if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
> +		ispccdc_config_imgattr(ccdc_struct->colptn);
> +
> +	return 0;
> +
> +copy_from_user_err:
> +	printk(KERN_ERR "CCDC Config:Copy From User Error");

"\n" is missed, right ?
Please, see below with the same. It's better to check all messages..

> +	return -EINVAL ;
> +}
> +EXPORT_SYMBOL(omap34xx_isp_ccdc_config);
> +
> +/**
> + * Set the value to be used for CCDC_CFG.WENLOG.
> + *  w - Value of wenlog.
> + */
> +void ispccdc_set_wenlog(u32 wenlog)
> +{
> +	ispccdc_obj.wenlog = wenlog;
> +}
> +EXPORT_SYMBOL(ispccdc_set_wenlog);
> +
> +/**
> + * 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");

"\n" ?

> +		return -EBUSY;
> +	}
> +
> +	ispccdc_obj.ccdc_inuse = 1;
> +	mutex_unlock(&ispccdc_obj.mutexlock);
> +	isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_CCDC_RAM_EN |
> +							ISPCTRL_CCDC_CLK_EN |
> +							ISPCTRL_SBL_WR1_RAM_EN);
> +	isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
> +	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);
> +	isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
> +			~(ISPCTRL_CCDC_CLK_EN |
> +			ISPCTRL_CCDC_RAM_EN |
> +			ISPCTRL_SBL_WR1_RAM_EN));
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_free);
> +
> +/**
> + * ispccdc_free_lsc - Frees Lens Shading Compensation table
> + *
> + * Always returns 0.
> + **/
> +static int ispccdc_free_lsc(void)
> +{
> +	if (!lsc_ispmmu_addr)
> +		return 0;
> +
> +	ispccdc_enable_lsc(0);
> +	lsc_initialized = 0;
> +	isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
> +	ispmmu_kunmap(lsc_ispmmu_addr);
> +	kfree(lsc_gain_table);
> +	return 0;
> +}
> +
> +/**
> + * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table
> + * @table_size: LSC gain table size.
> + *
> + * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
> + * table_size is zero.
> + **/
> +static int ispccdc_allocate_lsc(u32 table_size)
> +{
> +	if (table_size == 0)
> +		return -EINVAL;
> +
> +	if ((lsc_config.size >= table_size) && lsc_gain_table)
> +		return 0;
> +
> +	ispccdc_free_lsc();
> +
> +	lsc_gain_table = kmalloc(table_size, GFP_KERNEL | GFP_DMA);
> +
> +	if (!lsc_gain_table) {
> +		printk(KERN_ERR "Cannot allocate memory for gain tables \n");
> +		return -ENOMEM;
> +	}
> +
> +	lsc_ispmmu_addr = ispmmu_kmap(virt_to_phys(lsc_gain_table), table_size);
> +	if (lsc_ispmmu_addr <= 0) {
> +		printk(KERN_ERR "Cannot map memory for gain tables \n");
> +		kfree(lsc_gain_table);
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ispccdc_program_lsc - Program Lens Shading Compensation table.
> + * @table_size: LSC gain table size.
> + *
> + * Returns 0 if successful, or -EINVAL if there's no mapped address for the
> + * table yet.
> + **/
> +static int ispccdc_program_lsc(void)
> +{
> +	if (!lsc_ispmmu_addr)
> +		return -EINVAL;
> +
> +	if (lsc_initialized)
> +		return 0;
> +
> +	isp_reg_writel(lsc_ispmmu_addr, OMAP3_ISP_IOMEM_CCDC,
> +						ISPCCDC_LSC_TABLE_BASE);
> +	lsc_initialized = 1;
> +	return 0;
> +}
> +
> +/**
> + * ispccdc_load_lsc - Load Lens Shading Compensation table.
> + * @table_addr: LSC gain table MMU Mapped address.
> + * @table_size: LSC gain table size.
> + *
> + * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
> + * table_size is zero.
> + **/
> +int ispccdc_load_lsc(u8 *table_addr, u32 table_size)
> +{
> +	int ret;
> +
> +	if (!is_isplsc_activated())
> +		return 0;
> +
> +	if (!table_addr)
> +		return -EINVAL;
> +
> +	ret = ispccdc_allocate_lsc(table_size);
> +	if (ret)
> +		return ret;
> +
> +	if (table_addr != lsc_gain_table)
> +		memcpy(lsc_gain_table, table_addr, table_size);
> +	ret = ispccdc_program_lsc();
> +	if (ret)
> +		return ret;
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_load_lsc);
> +
> +/**
> + * ispccdc_config_lsc - Configures the lens shading compensation module
> + * @lsc_cfg: LSC configuration structure
> + **/
> +void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg)
> +{
> +	int reg;
> +
> +	if (!is_isplsc_activated())
> +		return;
> +
> +	ispccdc_enable_lsc(0);
> +	isp_reg_writel(lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_LSC_TABLE_OFFSET);
> +
> +	reg = 0;
> +	reg |= (lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT);
> +	reg |= (lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT);
> +	reg |= (lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT);
> +	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
> +
> +	reg = 0;
> +	reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
> +	reg |= (lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT);
> +	reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
> +	reg |= (lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT);
> +	isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL);
> +}
> +EXPORT_SYMBOL(ispccdc_config_lsc);
> +
> +/**
> + * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module.
> + * @enable: 0 Disables LSC, 1 Enables LSC.
> + **/
> +void ispccdc_enable_lsc(u8 enable)
> +{
> +	if (!is_isplsc_activated())
> +		return;
> +
> +	if (enable) {
> +		isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
> +			ISPCTRL_SBL_SHARED_RPORTB | ISPCTRL_SBL_RD_RAM_EN);
> +
> +		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0x1);
> +
> +		ispccdc_obj.lsc_en = 1;
> +	} else {
> +		isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0xFFFE);
> +		ispccdc_obj.lsc_en = 0;
> +	}
> +}
> +EXPORT_SYMBOL(ispccdc_enable_lsc);
> +
> +
> +/**
> + * 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 % 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_RSZ)) {
> +		DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC I/O Combination\n");
> +		return -EINVAL;
> +	}
> +
> +	syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
> +
> +	switch (output) {
> +	case CCDC_YUV_RSZ:
> +		syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
> +		break;
> +
> +	case CCDC_YUV_MEM_RSZ:
> +		syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
> +		ispccdc_obj.wen = 1;
> +		syn_mode |= ISPCCDC_SYN_MODE_WEN;
> +		break;
> +
> +	case CCDC_OTHERS_VP:
> +		syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
> +		vpcfg.bitshift_sel = BIT9_0;
> +		vpcfg.freq_sel = PIXCLKBY2;
> +		ispccdc_config_vp(vpcfg);
> +		ispccdc_enable_vp(1);
> +		break;
> +
> +	case CCDC_OTHERS_MEM:
> +		syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
> +		syn_mode |= ISPCCDC_SYN_MODE_WEN;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
> +		isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
> +							~ISPCCDC_CFG_WENLOG);
> +		vpcfg.bitshift_sel = BIT11_2;
> +		vpcfg.freq_sel = PIXCLKBY2;
> +		ispccdc_config_vp(vpcfg);
> +		ispccdc_enable_vp(0);
> +		break;
> +
> +	case CCDC_OTHERS_VP_MEM:
> +		syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
> +		syn_mode |= ISPCCDC_SYN_MODE_WEN;
> +		syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
> +
> +		isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
> +							~ISPCCDC_CFG_WENLOG,
> +							ispccdc_obj.wenlog);
> +		vpcfg.bitshift_sel = BIT9_0;
> +		vpcfg.freq_sel = PIXCLKBY2;
> +		ispccdc_config_vp(vpcfg);
> +		ispccdc_enable_vp(1);
> +		break;
> +	default:
> +		DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output");
> +		return -EINVAL;
> +	};
> +
> +	isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
> +
> +	switch (input) {
> +	case CCDC_RAW:
> +		syncif.ccdc_mastermode = 0;
> +		syncif.datapol = 0;
> +		syncif.datsz = DAT10;
> +		syncif.fldmode = 0;
> +		syncif.fldout = 0;
> +		syncif.fldpol = 0;
> +		syncif.fldstat = 0;
> +		syncif.hdpol = 0;
> +		syncif.ipmod = RAW;
> +		syncif.vdpol = 0;
> +		ispccdc_config_sync_if(syncif);
> +		ispccdc_config_imgattr(colptn);
> +		blkcfg.dcsubval = 64;
> +		ispccdc_config_black_clamp(blkcfg);
> +		if (is_isplsc_activated()) {
> +			ispccdc_config_lsc(&lsc_config);
> +			ispccdc_load_lsc(lsc_gain_table_tmp,
> +							LSC_TABLE_INIT_SIZE);
> +		}
> +
> +		break;
> +	case CCDC_YUV_SYNC:
> +		syncif.ccdc_mastermode = 0;
> +		syncif.datapol = 0;
> +		syncif.datsz = DAT8;
> +		syncif.fldmode = 0;
> +		syncif.fldout = 0;
> +		syncif.fldpol = 0;
> +		syncif.fldstat = 0;
> +		syncif.hdpol = 0;
> +		syncif.ipmod = YUV16;
> +		syncif.vdpol = 1;
> +		ispccdc_config_imgattr(0);
> +		ispccdc_config_sync_if(syncif);
> +		blkcfg.dcsubval = 0;
> +		ispccdc_config_black_clamp(blkcfg);
> +		break;
> +	case CCDC_YUV_BT:
> +		break;
> +	case CCDC_OTHERS:
> +		break;
> +	default:
> +		DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input");
> +		return -EINVAL;
> +	}
> +
> +	ispccdc_obj.ccdc_inpfmt = input;
> +	ispccdc_obj.ccdc_outfmt = output;
> +	ispccdc_print_status();
> +	isp_print_status();
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_config_datapath);
> +
> +/**
> + * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC.
> + * @syncif: Structure containing the sync parameters like field state, CCDC in
> + *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
> + *          signals.
> + **/
> +void ispccdc_config_sync_if(struct ispccdc_syncif syncif)
> +{
> +	u32 syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
> +
> +	syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
> +
> +	if (syncif.fldstat)
> +		syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
> +	else
> +		syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
> +
> +	syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
> +	ispccdc_obj.syncif_ipmod = syncif.ipmod;
> +
> +	switch (syncif.ipmod) {
> +	case RAW:
> +		break;
> +	case YUV16:
> +		syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
> +		break;
> +	case YUV8:
> +		syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
> +		break;
> +	};
> +
> +	syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
> +	switch (syncif.datsz) {
> +	case DAT8:
> +		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
> +		break;
> +	case DAT10:
> +		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
> +		break;
> +	case DAT11:
> +		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
> +		break;
> +	case DAT12:
> +		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
> +		break;
> +	};
> +
> +	if (syncif.fldmode)
> +		syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
> +	else
> +		syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
> +
> +	if (syncif.datapol)
> +		syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
> +	else
> +		syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
> +
> +	if (syncif.fldpol)
> +		syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
> +	else
> +		syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
> +
> +	if (syncif.hdpol)
> +		syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
> +	else
> +		syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
> +
> +	if (syncif.vdpol)
> +		syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
> +	else
> +		syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
> +
> +	if (syncif.ccdc_mastermode) {
> +		syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
> +		isp_reg_writel((syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT)
> +						| (syncif.vs_width <<
> +						ISPCCDC_HD_VD_WID_VDW_SHIFT),
> +						OMAP3_ISP_IOMEM_CCDC,
> +						ISPCCDC_HD_VD_WID);
> +
> +		isp_reg_writel(syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
> +			| syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
> +			OMAP3_ISP_IOMEM_CCDC,
> +			ISPCCDC_PIX_LINES);
> +	} else
> +		syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
> +						ISPCCDC_SYN_MODE_VDHDOUT);
> +
> +	isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
> +
> +	if (!(syncif.bt_r656_en)) {
> +		isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
> +						~ISPCCDC_REC656IF_R656ON);
> +	}
> +}
> +EXPORT_SYMBOL(ispccdc_config_sync_if);
> +
> +/**
> + * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC.
> + * @bclamp: Structure containing the optical black average gain, optical black
> + *          sample length, sample lines, and the start pixel position of the
> + *          samples w.r.t the HS pulse.
> + * Configures the clamp parameters in CCDC. Either if its being used the
> + * optical black clamp, or the digital clamp. If its a digital clamp, then
> + * assures to put a valid DC substraction level.
> + *
> + * Returns always 0 when completed.
> + **/
> +int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp)
> +{
> +	u32 bclamp_val = 0;
> +
> +	if (ispccdc_obj.obclamp_en) {
> +		bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
> +		bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
> +		bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
> +		bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
> +		isp_reg_writel(bclamp_val, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_CLAMP);
> +	} else {
> +		if (omap_rev() < OMAP3430_REV_ES2_0)
> +			if ((ispccdc_obj.syncif_ipmod == YUV16) ||
> +					(ispccdc_obj.syncif_ipmod == YUV8) ||
> +					(isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_REC656IF) &
> +					ISPCCDC_REC656IF_R656ON))
> +				bclamp.dcsubval = 0;
> +		isp_reg_writel(bclamp.dcsubval, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_DCSUB);
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_config_black_clamp);
> +
> +/**
> + * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp.
> + * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp.
> + *
> + * Enables or disables the optical black clamp. When disabled, the digital
> + * clamp operates.
> + **/
> +void ispccdc_enable_black_clamp(u8 enable)
> +{
> +	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
> +					~ISPCCDC_CLAMP_CLAMPEN,
> +					enable ? ISPCCDC_CLAMP_CLAMPEN : 0);
> +	ispccdc_obj.obclamp_en = enable;
> +}
> +EXPORT_SYMBOL(ispccdc_enable_black_clamp);
> +
> +/**
> + * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
> + * @fpc: Structure containing the number of faulty pixels corrected in the
> + *       frame, address of the FPC table.
> + *
> + * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
> + * boundary.
> + **/
> +int ispccdc_config_fpc(struct ispccdc_fpc fpc)
> +{
> +	u32 fpc_val = 0;
> +
> +	fpc_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
> +
> +	if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
> +		isp_reg_writel(fpc_val & (~ISPCCDC_FPC_FPCEN),
> +					OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
> +		isp_reg_writel(fpc.fpcaddr,
> +				OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
> +	} else {
> +		DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
> +		return -EINVAL;
> +	}
> +	isp_reg_writel(fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_config_fpc);
> +
> +/**
> + * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
> + * @enable: 0 Disables FPC, 1 Enables FPC.
> + **/
> +void ispccdc_enable_fpc(u8 enable)
> +{
> +	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
> +					~ISPCCDC_FPC_FPCEN,
> +					enable ? ISPCCDC_FPC_FPCEN : 0);
> +}
> +EXPORT_SYMBOL(ispccdc_enable_fpc);
> +
> +/**
> + * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
> + * @blcomp: Structure containing the black level compensation value for RGrGbB
> + *          pixels. in 2's complement.
> + **/
> +void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp)
> +{
> +	u32 blcomp_val = 0;
> +
> +	blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
> +	blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
> +	blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
> +	blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
> +
> +	isp_reg_writel(blcomp_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
> +}
> +EXPORT_SYMBOL(ispccdc_config_black_comp);
> +
> +/**
> + * ispccdc_config_vp - Configures the Video Port Configuration parameters.
> + * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
> + *         format.
> + **/
> +void ispccdc_config_vp(struct ispccdc_vp vpcfg)
> +{
> +	u32 fmtcfg_vp = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
> +
> +	fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCF_VPIF_FRQ_MASK;
> +
> +	switch (vpcfg.bitshift_sel) {
> +	case BIT9_0:
> +		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
> +		break;
> +	case BIT10_1:
> +		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
> +		break;
> +	case BIT11_2:
> +		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
> +		break;
> +	case BIT12_3:
> +		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
> +		break;
> +	};
> +	switch (vpcfg.freq_sel) {
> +	case PIXCLKBY2:
> +		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY2;
> +		break;
> +	case PIXCLKBY3_5:
> +		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY3;
> +		break;
> +	case PIXCLKBY4_5:
> +		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY4;
> +		break;
> +	case PIXCLKBY5_5:
> +		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY5;
> +		break;
> +	case PIXCLKBY6_5:
> +		fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY6;
> +		break;
> +	};
> +	isp_reg_writel(fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
> +}
> +EXPORT_SYMBOL(ispccdc_config_vp);
> +
> +/**
> + * ispccdc_enable_vp - Enables the Video Port.
> + * @enable: 0 Disables VP, 1 Enables VP
> + **/
> +void ispccdc_enable_vp(u8 enable)
> +{
> +	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
> +					~ISPCCDC_FMTCFG_VPEN,
> +					enable ? ISPCCDC_FMTCFG_VPEN : 0);
> +}
> +EXPORT_SYMBOL(ispccdc_enable_vp);
> +
> +/**
> + * ispccdc_config_reformatter - Configures the Reformatter.
> + * @refmt: Structure containing the memory address to format and the bit fields
> + *         for the reformatter registers.
> + *
> + * Configures the Reformatter register values if line alternating is disabled.
> + * Else, just enabling line alternating is enough.
> + **/
> +void ispccdc_config_reformatter(struct ispccdc_refmt refmt)
> +{
> +	u32 fmtcfg_val = 0;
> +
> +	fmtcfg_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
> +
> +	if (refmt.lnalt)
> +		fmtcfg_val |= ISPCCDC_FMTCFG_LNALT;
> +	else {
> +		fmtcfg_val &= ~ISPCCDC_FMTCFG_LNALT;
> +		fmtcfg_val &= 0xFFFFF003;
> +		fmtcfg_val |= refmt.lnum << ISPCCDC_FMTCFG_LNUM_SHIFT;
> +		fmtcfg_val |= refmt.plen_even <<
> +						ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT;
> +		fmtcfg_val |= refmt.plen_odd << ISPCCDC_FMTCFG_PLEN_ODD_SHIFT;
> +
> +		isp_reg_writel(refmt.prgeven0, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_PRGEVEN0);
> +		isp_reg_writel(refmt.prgeven1, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_PRGEVEN1);
> +		isp_reg_writel(refmt.prgodd0, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_PRGODD0);
> +		isp_reg_writel(refmt.prgodd1, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_PRGODD1);
> +		isp_reg_writel(refmt.fmtaddr0, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR0);
> +		isp_reg_writel(refmt.fmtaddr1, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR1);
> +		isp_reg_writel(refmt.fmtaddr2, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR2);
> +		isp_reg_writel(refmt.fmtaddr3, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR3);
> +		isp_reg_writel(refmt.fmtaddr4, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR4);
> +		isp_reg_writel(refmt.fmtaddr5, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR5);
> +		isp_reg_writel(refmt.fmtaddr6, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR6);
> +		isp_reg_writel(refmt.fmtaddr7, OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_FMT_ADDR7);
> +	}
> +	isp_reg_writel(fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
> +}
> +EXPORT_SYMBOL(ispccdc_config_reformatter);
> +
> +/**
> + * ispccdc_enable_reformatter - Enables the Reformatter.
> + * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter
> + **/
> +void ispccdc_enable_reformatter(u8 enable)
> +{
> +	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
> +					~ISPCCDC_FMTCFG_FMTEN,
> +					enable ? ISPCCDC_FMTCFG_FMTEN : 0);
> +	ispccdc_obj.refmt_en = enable;
> +}
> +EXPORT_SYMBOL(ispccdc_enable_reformatter);
> +
> +/**
> + * ispccdc_config_culling - Configures the culling parameters.
> + * @cull: Structure containing the vertical culling pattern, and horizontal
> + *        culling pattern for odd and even lines.
> + **/
> +void ispccdc_config_culling(struct ispccdc_culling cull)
> +{
> +	u32 culling_val = 0;
> +
> +	culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
> +	culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
> +	culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;
> +
> +	isp_reg_writel(culling_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING);
> +}
> +EXPORT_SYMBOL(ispccdc_config_culling);
> +
> +/**
> + * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
> + * @enable: 0 Disables LPF, 1 Enables LPF
> + **/
> +void ispccdc_enable_lpf(u8 enable)
> +{
> +	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
> +					~ISPCCDC_SYN_MODE_LPF,
> +					enable ? ISPCCDC_SYN_MODE_LPF : 0);
> +}
> +EXPORT_SYMBOL(ispccdc_enable_lpf);
> +
> +/**
> + * ispccdc_config_alaw - Configures the input width for A-law.
> + * @ipwidth: Input width for A-law
> + **/
> +void ispccdc_config_alaw(enum alaw_ipwidth ipwidth)
> +{
> +	isp_reg_writel(ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
> +					OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
> +}
> +EXPORT_SYMBOL(ispccdc_config_alaw);
> +
> +/**
> + * ispccdc_enable_alaw - Enables the A-law compression.
> + * @enable: 0 - Disables A-law, 1 - Enables A-law
> + **/
> +void ispccdc_enable_alaw(u8 enable)
> +{
> +	isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
> +					~ISPCCDC_ALAW_CCDTBL,
> +					enable ? ISPCCDC_ALAW_CCDTBL : 0);
> +}
> +EXPORT_SYMBOL(ispccdc_enable_alaw);
> +
> +/**
> + * ispccdc_config_imgattr - Configures the sensor image specific attributes.
> + * @colptn: Color pattern of the sensor.
> + **/
> +void ispccdc_config_imgattr(u32 colptn)
> +{
> +	isp_reg_writel(colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
> +}
> +EXPORT_SYMBOL(ispccdc_config_imgattr);
> +
> +/**
> + * ispccdc_config_shadow_registers - Programs the shadow registers for CCDC.
> + * Currently nothing to program in shadow, but kept for future use.
> + **/
> +void ispccdc_config_shadow_registers(void)
> +{
> +	return;
> +}
> +EXPORT_SYMBOL(ispccdc_config_shadow_registers);
> +
> +/**
> + * ispccdc_try_size - Checks if requested Input/output dimensions are valid
> + * @input_w: input width for the CCDC in number of pixels per line
> + * @input_h: input height for the CCDC in number of lines
> + * @output_w: output width from the CCDC in number of pixels per line
> + * @output_h: output height for the CCDC in number of lines
> + *
> + * Calculates the number of pixels cropped if the reformater is disabled,
> + * Fills up the output width and height variables in the isp_ccdc structure.
> + *
> + * Returns 0 if successful, or -EINVAL if the input width is less than 2 pixels
> + **/
> +int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
> +{
> +	if (input_w < 32 || input_h < 32) {
> +		DPRINTK_ISPCCDC("ISP_ERR: CCDC cannot handle input width less"
> +				" than 32 pixels or height less than 32\n");
> +		return -EINVAL;
> +	}
> +
> +	if (ispccdc_obj.crop_w)
> +		*output_w = ispccdc_obj.crop_w;
> +	else
> +		*output_w = input_w;
> +
> +	if (ispccdc_obj.crop_h)
> +		*output_h = ispccdc_obj.crop_h;
> +	else
> +		*output_h = input_h;
> +
> +	if ((!ispccdc_obj.refmt_en) && ((ispccdc_obj.ccdc_outfmt !=
> +		CCDC_OTHERS_MEM) && ispccdc_obj.ccdc_outfmt !=
> +					CCDC_OTHERS_VP_MEM))
> +		*output_h -= 1;
> +
> +	if ((ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) ||
> +						(ispccdc_obj.ccdc_outfmt ==
> +						CCDC_OTHERS_VP_MEM)) {
> +		if (*output_w % 16) {
> +			*output_w -= (*output_w % 16);
> +			*output_w += 16;
> +		}
> +	}
> +
> +	ispccdc_obj.ccdcout_w = *output_w;
> +	ispccdc_obj.ccdcout_h = *output_h;
> +	ispccdc_obj.ccdcin_w = input_w;
> +	ispccdc_obj.ccdcin_h = input_h;
> +
> +	DPRINTK_ISPCCDC("try size: ccdcin_w=%u,ccdcin_h=%u,ccdcout_w=%u,"
> +							" ccdcout_h=%u\n",
> +							ispccdc_obj.ccdcin_w,
> +							ispccdc_obj.ccdcin_h,
> +							ispccdc_obj.ccdcout_w,
> +							ispccdc_obj.ccdcout_h);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_try_size);
> +
> +/**
> + * ispccdc_config_size - Configure the dimensions of the CCDC input/output
> + * @input_w: input width for the CCDC in number of pixels per line
> + * @input_h: input height for the CCDC in number of lines
> + * @output_w: output width from the CCDC in number of pixels per line
> + * @output_h: output height for the CCDC in number of lines
> + *
> + * Configures the appropriate values stored in the isp_ccdc structure to
> + * HORZ/VERT_INFO registers and the VP_OUT depending on whether the image
> + * is stored in memory or given to the another module in the ISP pipeline.
> + *
> + * Returns 0 if successful, or -EINVAL if try_size was not called before to
> + * validate the requested dimensions.
> + **/
> +int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
> +{
> +	DPRINTK_ISPCCDC("config size: input_w=%u, input_h=%u, output_w=%u,"
> +							" output_h=%u\n",
> +							input_w, input_h,
> +							output_w, output_h);
> +	if ((output_w != ispccdc_obj.ccdcout_w) || (output_h !=
> +						ispccdc_obj.ccdcout_h)) {
> +		DPRINTK_ISPCCDC("ISP_ERR : ispccdc_try_size should"
> +					" be called before config size\n");
> +		return -EINVAL;
> +	}
> +
> +	if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP) {
> +		isp_reg_writel((ispccdc_obj.ccdcin_woffset <<
> +					ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
> +					(ispccdc_obj.ccdcin_w <<
> +					ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_FMT_HORZ);
> +		isp_reg_writel((ispccdc_obj.ccdcin_hoffset <<
> +					ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
> +					(ispccdc_obj.ccdcin_h <<
> +					ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_FMT_VERT);
> +		isp_reg_writel((ispccdc_obj.ccdcout_w <<
> +					ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
> +					(ispccdc_obj.ccdcout_h - 1) <<
> +					ISPCCDC_VP_OUT_VERT_NUM_SHIFT,
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VP_OUT);
> +		isp_reg_writel((((ispccdc_obj.ccdcout_h - 25) &
> +					ISPCCDC_VDINT_0_MASK) <<
> +					ISPCCDC_VDINT_0_SHIFT) |
> +					((50 & ISPCCDC_VDINT_1_MASK) <<
> +					ISPCCDC_VDINT_1_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VDINT);
> +
> +	} else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) {
> +		isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
> +		if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
> +			isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
> +					| ((ispccdc_obj.ccdcout_w - 1)
> +					<< ISPCCDC_HORZ_INFO_NPH_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_HORZ_INFO);
> +		} else {
> +			isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
> +					| ((ispccdc_obj.ccdcout_w - 1)
> +					<< ISPCCDC_HORZ_INFO_NPH_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_HORZ_INFO);
> +		}
> +		isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
> +							OMAP3_ISP_IOMEM_CCDC,
> +							ISPCCDC_VERT_START);
> +		isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
> +						ISPCCDC_VERT_LINES_NLV_SHIFT,
> +						OMAP3_ISP_IOMEM_CCDC,
> +						ISPCCDC_VERT_LINES);
> +
> +		ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
> +		isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
> +					ISPCCDC_VDINT_0_MASK) <<
> +					ISPCCDC_VDINT_0_SHIFT) |
> +					((100 & ISPCCDC_VDINT_1_MASK) <<
> +					ISPCCDC_VDINT_1_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VDINT);
> +	} else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
> +		isp_reg_writel((0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
> +					(ispccdc_obj.ccdcin_w <<
> +					ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_FMT_HORZ);
> +		isp_reg_writel((0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
> +					((ispccdc_obj.ccdcin_h) <<
> +					ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_FMT_VERT);
> +		isp_reg_writel((ispccdc_obj.ccdcout_w
> +					<< ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
> +					((ispccdc_obj.ccdcout_h - 1) <<
> +					ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VP_OUT);
> +		isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
> +					((ispccdc_obj.ccdcout_w - 1) <<
> +					ISPCCDC_HORZ_INFO_NPH_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_HORZ_INFO);
> +		isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VERT_START);
> +		isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
> +					ISPCCDC_VERT_LINES_NLV_SHIFT,
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VERT_LINES);
> +		ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
> +		isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
> +					ISPCCDC_VDINT_0_MASK) <<
> +					ISPCCDC_VDINT_0_SHIFT) |
> +					((100 & ISPCCDC_VDINT_1_MASK) <<
> +					ISPCCDC_VDINT_1_SHIFT),
> +					OMAP3_ISP_IOMEM_CCDC,
> +					ISPCCDC_VDINT);
> +	}
> +
> +	if (is_isplsc_activated()) {
> +		if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
> +			ispccdc_config_lsc(&lsc_config);
> +			ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_config_size);
> +
> +/**
> + * ispccdc_config_outlineoffset - Configures the output line offset
> + * @offset: Must be twice the Output width and aligned on 32 byte boundary
> + * @oddeven: Specifies the odd/even line pattern to be chosen to store the
> + *           output.
> + * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
> + *
> + * - Configures the output line offset when stored in memory
> + * - Sets the odd/even line pattern to store the output
> + *    (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
> + * - Configures the number of even and odd line fields in case of rearranging
> + * the lines.
> + *
> + * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
> + * boundary.
> + **/
> +int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines)
> +{
> +	if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
> +		isp_reg_writel((offset & 0xFFFF), OMAP3_ISP_IOMEM_CCDC,
> +						ISPCCDC_HSIZE_OFF);
> +	} else {
> +		DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
> +								" boundary");

"\n" ?

> +		return -EINVAL;
> +	}
> +
> +	isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
> +						~ISPCCDC_SDOFST_FINV);
> +
> +	isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
> +						~ISPCCDC_SDOFST_FOFST_4L);
> +
> +	switch (oddeven) {
> +	case EVENEVEN:
> +		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
> +			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
> +		break;
> +	case ODDEVEN:
> +		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
> +			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
> +		break;
> +	case EVENODD:
> +		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
> +			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
> +		break;
> +	case ODDODD:
> +		isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
> +			(numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
> +		break;
> +	default:
> +		break;
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL(ispccdc_config_outlineoffset);
> +
> +/**
> + * ispccdc_set_outaddr - Sets the memory address where the output will be saved
> + * @addr: 32-bit memory address aligned on 32 byte boundary.
> + *
> + * Sets the memory address where the output will be saved.
> + *
> + * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
> + * boundary.
> + **/
> +int ispccdc_set_outaddr(u32 addr)
> +{
> +	if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
> +		isp_reg_writel(addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
> +		return 0;
> +	} else {
> +		DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
> +								" boundary");

"\n" ?


<snip>

> 
> Best regards, Klimov Alexey


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

* Re: [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ)
  2009-03-03 10:06         ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Sakari Ailus
  2009-03-03 10:06           ` [PATCH 6/9] omap3isp: Add statistics collection modules (H3A and HIST) Sakari Ailus
@ 2009-03-03 12:23           ` Alexey Klimov
  1 sibling, 0 replies; 30+ messages in thread
From: Alexey Klimov @ 2009-03-03 12:23 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

On Tue, 2009-03-03 at 12:06 +0200, Sakari Ailus wrote:
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> ---
>  drivers/media/video/isp/isppreview.c | 1896 ++++++++++++++++++++++++++++++++++
>  drivers/media/video/isp/isppreview.h |  350 +++++++
>  drivers/media/video/isp/ispresizer.c |  897 ++++++++++++++++
>  drivers/media/video/isp/ispresizer.h |  154 +++
>  4 files changed, 3297 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/isp/isppreview.c
>  create mode 100644 drivers/media/video/isp/isppreview.h
>  create mode 100644 drivers/media/video/isp/ispresizer.c
>  create mode 100644 drivers/media/video/isp/ispresizer.h
> 
> diff --git a/drivers/media/video/isp/isppreview.c b/drivers/media/video/isp/isppreview.c
> new file mode 100644
> index 0000000..242b578
> --- /dev/null
> +++ b/drivers/media/video/isp/isppreview.c
> @@ -0,0 +1,1896 @@
> +/*
> + * isppreview.c
> + *
> + * Driver Library for Preview module in TI's OMAP3 Camera ISP
> + *
> + * Copyright (C) 2009 Texas Instruments, Inc.
> + *
> + * Contributors:
> + *	Senthilvadivu Guruswamy <svadivu@ti.com>
> + *	Pallavi Kulkarni <p-kulkarni@ti.com>
> + *	Sergio Aguirre <saaguirre@ti.com>
> + *
> + * 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/uaccess.h>
> +
> +#include "isp.h"
> +#include "ispreg.h"
> +#include "isppreview.h"
> +
> +static struct ispprev_nf prev_nf_t;
> +static struct prev_params *params;
> +static int rg_update, gg_update, bg_update, nf_enable, nf_update;
> +
> +/* Structure for saving/restoring preview module registers */
> +static struct isp_reg ispprev_reg_list[] = {
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_DRKF_OFFSET, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_NF, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3, 0x0000},
> +	{OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 0x0000},
> +	{0, ISP_TOK_TERM, 0x0000}
> +};
> +
> +
> +/* Default values in Office Flourescent Light for RGBtoRGB Blending */
> +static struct ispprev_rgbtorgb flr_rgb2rgb = {
> +	{	/* RGB-RGB Matrix */
> +		{0x01E2, 0x0F30, 0x0FEE},
> +		{0x0F9B, 0x01AC, 0x0FB9},
> +		{0x0FE0, 0x0EC0, 0x0260}
> +	},	/* RGB Offset */
> +	{0x0000, 0x0000, 0x0000}
> +};
> +
> +/* Default values in Office Flourescent Light for RGB to YUV Conversion*/
> +static struct ispprev_csc flr_prev_csc[] = {
> +	{
> +		{	/* CSC Coef Matrix */
> +			{66, 129, 25},
> +			{-38, -75, 112},
> +			{112, -94 , -18}
> +		},	/* CSC Offset */
> +		{0x0, 0x0, 0x0}
> +	},
> +	{
> +		{	/* CSC Coef Matrix BW */
> +			{66, 129, 25},
> +			{0, 0, 0},
> +			{0, 0, 0}
> +		},	/* CSC Offset */
> +		{0x0, 0x0, 0x0}
> +	},
> +	{
> +		{	/* CSC Coef Matrix Sepia */
> +			{19, 38, 7},
> +			{0, 0, 0},
> +			{0, 0, 0}
> +		},	/* CSC Offset */
> +		{0x0, 0xE7, 0x14}
> +	}
> +};
> +
> +
> +/* Default values in Office Flourescent Light for CFA Gradient*/
> +#define FLR_CFA_GRADTHRS_HORZ	0x28
> +#define FLR_CFA_GRADTHRS_VERT	0x28
> +
> +/* Default values in Office Flourescent Light for Chroma Suppression*/
> +#define FLR_CSUP_GAIN		0x0D
> +#define FLR_CSUP_THRES		0xEB
> +
> +/* Default values in Office Flourescent Light for Noise Filter*/
> +#define FLR_NF_STRGTH		0x03
> +
> +/* Default values in Office Flourescent Light for White Balance*/
> +#define FLR_WBAL_DGAIN		0x100
> +#define FLR_WBAL_COEF0		0x20
> +#define FLR_WBAL_COEF1		0x29
> +#define FLR_WBAL_COEF2		0x2d
> +#define FLR_WBAL_COEF3		0x20
> +
> +#define FLR_WBAL_COEF0_ES1	0x20
> +#define FLR_WBAL_COEF1_ES1	0x23
> +#define FLR_WBAL_COEF2_ES1	0x39
> +#define FLR_WBAL_COEF3_ES1	0x20
> +
> +/* Default values in Office Flourescent Light for Black Adjustment*/
> +#define FLR_BLKADJ_BLUE		0x0
> +#define FLR_BLKADJ_GREEN	0x0
> +#define FLR_BLKADJ_RED		0x0
> +
> +static int update_color_matrix;
> +
> +/**
> + * struct isp_prev - Structure for storing ISP Preview module information
> + * @prev_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
> + * @prevout_w: Preview output width.
> + * @prevout_h: Preview output height.
> + * @previn_w: Preview input width.
> + * @previn_h: Preview input height.
> + * @prev_inpfmt: Preview input format.
> + * @prev_outfmt: Preview output format.
> + * @hmed_en: Horizontal median filter enable.
> + * @nf_en: Noise filter enable.
> + * @dcor_en: Defect correction enable.
> + * @cfa_en: Color Filter Array (CFA) interpolation enable.
> + * @csup_en: Chrominance suppression enable.
> + * @yenh_en: Luma enhancement enable.
> + * @fmtavg: Number of horizontal pixels to average in input formatter. The
> + *          input width should be a multiple of this number.
> + * @brightness: Brightness in preview module.
> + * @contrast: Contrast in preview module.
> + * @color: Color effect in preview module.
> + * @cfafmt: Color Filter Array (CFA) Format.
> + * @ispprev_mutex: Mutex for isp preview.
> + *
> + * This structure is used to store the OMAP ISP Preview module Information.
> + */
> +static struct isp_prev {
> +	u8 prev_inuse;
> +	u32 prevout_w;
> +	u32 prevout_h;
> +	u32 previn_w;
> +	u32 previn_h;
> +	enum preview_input prev_inpfmt;
> +	enum preview_output prev_outfmt;
> +	u8 hmed_en;
> +	u8 nf_en;
> +	u8 dcor_en;
> +	u8 cfa_en;
> +	u8 csup_en;
> +	u8 yenh_en;
> +	u8 fmtavg;
> +	u8 brightness;
> +	u8 contrast;
> +	enum v4l2_colorfx color;
> +	enum cfa_fmt cfafmt;
> +	struct mutex ispprev_mutex; /* For checking/modifying prev_inuse */
> +	u32 sph;
> +	u32 slv;
> +} ispprev_obj;
> +
> +/* Saved parameters */
> +static struct prev_params *prev_config_params;
> +
> +/*
> + * Coeficient Tables for the submodules in Preview.
> + * Array is initialised with the values from.the tables text file.
> + */
> +
> +/*
> + * CFA Filter Coefficient Table
> + *
> + */
> +static u32 cfa_coef_table[] = {
> +#include "cfa_coef_table.h"
> +};
> +
> +/*
> + * Gamma Correction Table - Red
> + */
> +static u32 redgamma_table[] = {
> +#include "redgamma_table.h"
> +};
> +
> +/*
> + * Gamma Correction Table - Green
> + */
> +static u32 greengamma_table[] = {
> +#include "greengamma_table.h"
> +};
> +
> +/*
> + * Gamma Correction Table - Blue
> + */
> +static u32 bluegamma_table[] = {
> +#include "bluegamma_table.h"
> +};
> +
> +/*
> + * Noise Filter Threshold table
> + */
> +static u32 noise_filter_table[] = {
> +#include "noise_filter_table.h"
> +};
> +
> +/*
> + * Luminance Enhancement Table
> + */
> +static u32 luma_enhance_table[] = {
> +#include "luma_enhance_table.h"
> +};
> +
> +/**
> + * omap34xx_isp_preview_config - Abstraction layer Preview configuration.
> + * @userspace_add: Pointer from Userspace to structure with flags and data to
> + *                 update.
> + **/
> +int omap34xx_isp_preview_config(void *userspace_add)
> +{
> +	struct ispprev_hmed prev_hmed_t;
> +	struct ispprev_cfa prev_cfa_t;
> +	struct ispprev_csup csup_t;
> +	struct ispprev_wbal prev_wbal_t;
> +	struct ispprev_blkadj prev_blkadj_t;
> +	struct ispprev_rgbtorgb rgb2rgb_t;
> +	struct ispprev_csc prev_csc_t;
> +	struct ispprev_yclimit yclimit_t;
> +	struct ispprev_dcor prev_dcor_t;
> +	struct ispprv_update_config *preview_struct;
> +	struct isptables_update isp_table_update;
> +	int yen_t[ISPPRV_YENH_TBL_SIZE];
> +
> +	if (userspace_add == NULL)
> +		return -EINVAL;
> +
> +	preview_struct = userspace_add;
> +
> +	if (ISP_ABS_PREV_LUMAENH & preview_struct->flag) {
> +		if (ISP_ABS_PREV_LUMAENH & preview_struct->update) {
> +			if (copy_from_user(yen_t, preview_struct->yen,
> +								sizeof(yen_t)))
> +				goto err_copy_from_user;
> +			isppreview_config_luma_enhancement(yen_t);
> +		}
> +		params->features |= PREV_LUMA_ENHANCE;
> +	} else if (ISP_ABS_PREV_LUMAENH & preview_struct->update)
> +			params->features &= ~PREV_LUMA_ENHANCE;
> +
> +	if (ISP_ABS_PREV_INVALAW & preview_struct->flag) {
> +		isppreview_enable_invalaw(1);
> +		params->features |= PREV_INVERSE_ALAW;
> +	} else {
> +		isppreview_enable_invalaw(0);
> +		params->features &= ~PREV_INVERSE_ALAW;
> +	}
> +
> +	if (ISP_ABS_PREV_HRZ_MED & preview_struct->flag) {
> +		if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
> +			if (copy_from_user(&prev_hmed_t,
> +						(struct ispprev_hmed *)
> +						preview_struct->prev_hmed,
> +						sizeof(struct ispprev_hmed)))
> +				goto err_copy_from_user;
> +			isppreview_config_hmed(prev_hmed_t);
> +		}
> +		isppreview_enable_hmed(1);
> +		params->features |= PREV_HORZ_MEDIAN_FILTER;
> +	} else if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
> +		isppreview_enable_hmed(0);
> +		params->features &= ~PREV_HORZ_MEDIAN_FILTER;
> +	}
> +
> +	if (ISP_ABS_PREV_CFA & preview_struct->flag) {
> +		if (ISP_ABS_PREV_CFA & preview_struct->update) {
> +			if (copy_from_user(&prev_cfa_t,
> +						(struct ispprev_cfa *)
> +						preview_struct->prev_cfa,
> +						sizeof(struct ispprev_cfa)))
> +				goto err_copy_from_user;
> +
> +			isppreview_config_cfa(prev_cfa_t);
> +		}
> +		isppreview_enable_cfa(1);
> +		params->features |= PREV_CFA;
> +	} else if (ISP_ABS_PREV_CFA & preview_struct->update) {
> +		isppreview_enable_cfa(0);
> +		params->features &= ~PREV_CFA;
> +	}
> +
> +	if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->flag) {
> +		if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
> +			if (copy_from_user(&csup_t,
> +						(struct ispprev_csup *)
> +						preview_struct->csup,
> +						sizeof(struct ispprev_csup)))
> +				goto err_copy_from_user;
> +			isppreview_config_chroma_suppression(csup_t);
> +		}
> +		isppreview_enable_chroma_suppression(1);
> +		params->features |= PREV_CHROMA_SUPPRESS;
> +	} else if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
> +		isppreview_enable_chroma_suppression(0);
> +		params->features &= ~PREV_CHROMA_SUPPRESS;
> +	}
> +
> +	if (ISP_ABS_PREV_WB & preview_struct->update) {
> +		if (copy_from_user(&prev_wbal_t, (struct ispprev_wbal *)
> +						preview_struct->prev_wbal,
> +						sizeof(struct ispprev_wbal)))
> +			goto err_copy_from_user;
> +		isppreview_config_whitebalance(prev_wbal_t);
> +	}
> +
> +	if (ISP_ABS_PREV_BLKADJ & preview_struct->update) {
> +		if (copy_from_user(&prev_blkadj_t, (struct ispprev_blkadjl *)
> +					preview_struct->prev_blkadj,
> +					sizeof(struct ispprev_blkadj)))
> +			goto err_copy_from_user;
> +		isppreview_config_blkadj(prev_blkadj_t);
> +	}
> +
> +	if (ISP_ABS_PREV_RGB2RGB & preview_struct->update) {
> +		if (copy_from_user(&rgb2rgb_t, (struct ispprev_rgbtorgb *)
> +					preview_struct->rgb2rgb,
> +					sizeof(struct ispprev_rgbtorgb)))
> +			goto err_copy_from_user;
> +		isppreview_config_rgb_blending(rgb2rgb_t);
> +	}
> +
> +	if (ISP_ABS_PREV_COLOR_CONV & preview_struct->update) {
> +		if (copy_from_user(&prev_csc_t, (struct ispprev_csc *)
> +						preview_struct->prev_csc,
> +						sizeof(struct ispprev_csc)))
> +			goto err_copy_from_user;
> +		isppreview_config_rgb_to_ycbcr(prev_csc_t);
> +	}
> +
> +	if (ISP_ABS_PREV_YC_LIMIT & preview_struct->update) {
> +		if (copy_from_user(&yclimit_t, (struct ispprev_yclimit *)
> +					preview_struct->yclimit,
> +					sizeof(struct ispprev_yclimit)))
> +			goto err_copy_from_user;
> +		isppreview_config_yc_range(yclimit_t);
> +	}
> +
> +	if (ISP_ABS_PREV_DEFECT_COR & preview_struct->flag) {
> +		if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
> +			if (copy_from_user(&prev_dcor_t,
> +						(struct ispprev_dcor *)
> +						preview_struct->prev_dcor,
> +						sizeof(struct ispprev_dcor)))
> +				goto err_copy_from_user;
> +			isppreview_config_dcor(prev_dcor_t);
> +		}
> +		isppreview_enable_dcor(1);
> +		params->features |= PREV_DEFECT_COR;
> +	} else if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
> +		isppreview_enable_dcor(0);
> +		params->features &= ~PREV_DEFECT_COR;
> +	}
> +
> +	if (ISP_ABS_PREV_GAMMABYPASS & preview_struct->flag) {
> +		isppreview_enable_gammabypass(1);
> +		params->features |= PREV_GAMMA_BYPASS;
> +	} else {
> +		isppreview_enable_gammabypass(0);
> +		params->features &= ~PREV_GAMMA_BYPASS;
> +	}
> +
> +	isp_table_update.update = preview_struct->update;
> +	isp_table_update.flag = preview_struct->flag;
> +	isp_table_update.prev_nf = preview_struct->prev_nf;
> +	isp_table_update.red_gamma = preview_struct->red_gamma;
> +	isp_table_update.green_gamma = preview_struct->green_gamma;
> +	isp_table_update.blue_gamma = preview_struct->blue_gamma;
> +
> +	if (omap34xx_isp_tables_update(&isp_table_update))
> +		goto err_copy_from_user;
> +
> +	return 0;
> +
> +err_copy_from_user:
> +	printk(KERN_ERR "Preview Config: Copy From User Error");

:) "\n" right ?
And, probably it's not clear from what module this printk come from.
Please, add module name or something here and in others such printks.

<snip>

-- 
Best regards, Klimov Alexey


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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-03 10:06 [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
  2009-03-03 10:06 ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Sakari Ailus
@ 2009-03-03 13:09 ` Sakari Ailus
  2009-03-04 15:28 ` Hiremath, Vaibhav
  2009-03-05  5:00   ` DongSoo(Nathaniel) Kim
  3 siblings, 0 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-03 13:09 UTC (permalink / raw)
  To: linux-media, linux-omap
  Cc: Aguirre Rodriguez, Sergio Alberto, Toivonen Tuukka Olli Artturi,
	Hiroshi DOYU, DongSoo Kim

Sakari Ailus wrote:
> Any feedback is appreciated.

Just one more thing: these patches haven't been checked with 
checkpatch.pl yet. Style problems are a certainty.

I'm working on the issue.

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [PATCH 9/9] omap34xxcam: Add camera driver
  2009-03-03 10:06                 ` [PATCH 9/9] omap34xxcam: Add camera driver Sakari Ailus
@ 2009-03-03 17:31                   ` Alexey Klimov
  2009-03-05 14:09                     ` Sakari Ailus
  0 siblings, 1 reply; 30+ messages in thread
From: Alexey Klimov @ 2009-03-03 17:31 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

On Tue, 2009-03-03 at 12:06 +0200, Sakari Ailus wrote:
> This is the camera driver for the OMAP 3 camera ISP and v4l2-int-device
> sensors, lenses and (led) flashes. There are a few connections to OMAP
> 3 left but after those have been broken this is hardware independent.
> Namely, the OMAP 3 ISP must offer a standard interface through
> v4l2_subdev (or v4l2-int-device) first.
> 
> This driver has originated from the omap24xxcam camera driver written
> specifically for OMAP 2.
> 
> TODO:
> 
> - Convert to use v4l2_subdev instead of v4l2-int-device.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> ---
>  drivers/media/video/Kconfig       |    9 +
>  drivers/media/video/Makefile      |    2 +
>  drivers/media/video/omap34xxcam.c | 1962 +++++++++++++++++++++++++++++++++++++
>  drivers/media/video/omap34xxcam.h |  207 ++++
>  4 files changed, 2180 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/omap34xxcam.c
>  create mode 100644 drivers/media/video/omap34xxcam.h
> 
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 19cf3b8..3cdb5a4 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -711,6 +711,15 @@ 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
> +	select OMAP_IOMMU
> +	depends on VIDEO_V4L2 && ARCH_OMAP34XX
> +	---help---
> +	  Driver for an OMAP 3 camera controller.
> +
>  config SOC_CAMERA
>  	tristate "SoC camera support"
>  	depends on VIDEO_V4L2 && HAS_DMA
> diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> index e654270..74a684e 100644
> --- a/drivers/media/video/Makefile
> +++ b/drivers/media/video/Makefile
> @@ -108,6 +108,8 @@ obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
>  
>  obj-y				+= isp/
>  
> +obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o
> +
>  obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
>  
>  obj-$(CONFIG_USB_DABUSB)        += dabusb.o
> diff --git a/drivers/media/video/omap34xxcam.c b/drivers/media/video/omap34xxcam.c
> new file mode 100644
> index 0000000..4d75b6f
> --- /dev/null
> +++ b/drivers/media/video/omap34xxcam.c
> @@ -0,0 +1,1962 @@
> +/*
> + * omap34xxcam.c
> + *
> + * Copyright (C) 2006--2009 Nokia Corporation
> + * Copyright (C) 2007--2009 Texas Instruments
> + *
> + * Contact: Sakari Ailus <sakari.ailus@nokia.com>
> + *          Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
> + *
> + * Originally based on the OMAP 2 camera driver.
> + *
> + * Written by Sakari Ailus <sakari.ailus@nokia.com>
> + *            Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
> + *            Sergio Aguirre <saaguirre@ti.com>
> + *            Mohit Jalori
> + *            Sameer Venkatraman
> + *            Leonides Martinez
> + *
> + * This program 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 program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + *
> + */
> +
> +#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 <media/v4l2-ioctl.h>
> +
> +#include "omap34xxcam.h"
> +#include "isp/isp.h"
> +#include "isp/ispmmu.h"
> +#include "isp/ispreg.h"
> +#include "isp/ispccdc.h"
> +#include "isp/isph3a.h"
> +#include "isp/isp_af.h"
> +#include "isp/isphist.h"
> +#include "isp/isppreview.h"
> +#include "isp/ispresizer.h"
> +
> +#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
> +
> +/* global variables */
> +static struct omap34xxcam_device *omap34xxcam;
> +
> +/*
> + *
> + * Sensor handling.
> + *
> + */
> +
> +/**
> + * omap34xxcam_slave_power_set - set slave power state
> + * @vdev: per-video device data structure
> + * @power: new power state
> + */
> +static int omap34xxcam_slave_power_set(struct omap34xxcam_videodev *vdev,
> +				       enum v4l2_power power,
> +				       int mask)
> +{
> +	int rval = 0, i = 0;
> +
> +	BUG_ON(!mutex_is_locked(&vdev->mutex));
> +
> +#ifdef OMAP34XXCAM_POWEROFF_DELAY
> +	vdev->power_state_wish = -1;
> +#endif
> +
> +	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +		if (vdev->slave[i] == v4l2_int_device_dummy())
> +			continue;
> +
> +		if (!(mask & (1 << i))
> +		    || power == vdev->power_state[i])
> +			continue;
> +
> +		rval = vidioc_int_s_power(vdev->slave[i], power);
> +
> +		if (rval && power != V4L2_POWER_OFF) {
> +			power = V4L2_POWER_OFF;
> +			goto out;
> +		}
> +
> +		vdev->power_state[i] = power;
> +	}
> +
> +	return 0;
> +
> +out:
> +	for (i--; i >= 0; i--) {
> +		if (vdev->slave[i] == v4l2_int_device_dummy())
> +			continue;
> +
> +		if (!(mask & (1 << i)))
> +			continue;
> +
> +		vidioc_int_s_power(vdev->slave[i], power);
> +		vdev->power_state[i] = power;
> +	}
> +
> +	return rval;
> +}
> +
> +#ifdef OMAP34XXCAM_POWEROFF_DELAY
> +static void omap34xxcam_slave_power_work(struct work_struct *work)
> +{
> +	struct omap34xxcam_videodev *vdev =
> +		container_of(work, struct omap34xxcam_videodev, poweroff_work);
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->power_state_wish != -1)
> +		omap34xxcam_slave_power_set(vdev, vdev->power_state_wish,
> +					    vdev->power_state_mask);
> +
> +	mutex_unlock(&vdev->mutex);
> +}
> +
> +static void omap34xxcam_slave_power_timer(unsigned long ptr)
> +{
> +	struct omap34xxcam_videodev *vdev = (void *)ptr;
> +
> +	schedule_work(&vdev->poweroff_work);
> +}
> +
> +/**
> + * omap34xxcam_slave_power_suggest - delayed power state change
> + *
> + * @vdev: per-video device data structure
> + * @power: new power state
> + */
> +static void omap34xxcam_slave_power_suggest(struct omap34xxcam_videodev *vdev,
> +					    enum v4l2_power power,
> +					    int mask)
> +{
> +	BUG_ON(!mutex_is_locked(&vdev->mutex));
> +
> +	del_timer(&vdev->poweroff_timer);
> +
> +	vdev->power_state_wish = power;
> +	vdev->power_state_mask = mask;
> +
> +	mod_timer(&vdev->poweroff_timer, jiffies + OMAP34XXCAM_POWEROFF_DELAY);
> +}
> +#else /* OMAP34XXCAM_POWEROFF_DELAY */
> +#define omap34xxcam_slave_power_suggest(a, b, c) do {} while(0)
> +#endif /* OMAP34XXCAM_POWEROFF_DELAY */
> +
> +/**
> + * 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.
> + */
> +void omap34xxcam_vbq_complete(struct videobuf_buffer *vb, void *priv)
> +{
> +	struct omap34xxcam_fh *fh = priv;
> +
> +	do_gettimeofday(&vb->ts);
> +	vb->field_count = atomic_add_return(2, &fh->field_count);
> +
> +	wake_up(&vb->done);
> +}
> +
> +/**
> + * 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 omap34xxcam_videodev *vdev = fh->vdev;
> +
> +	if (*cnt <= 0)
> +		*cnt = VIDEO_MAX_FRAME;	/* supply a default number of buffers */
> +
> +	if (*cnt > VIDEO_MAX_FRAME)
> +		*cnt = VIDEO_MAX_FRAME;
> +
> +	*size = vdev->pix.sizeimage;
> +
> +	while (*size * *cnt > fh->vdev->vdev_sensor_config.capture_mem)
> +		(*cnt)--;
> +
> +	return isp_vbq_setup(vbq, cnt, size);
> +}
> +
> +/**
> + * 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 omap34xxcam_fh *fh = vbq->priv_data;
> +	struct omap34xxcam_videodev *vdev = fh->vdev;
> +	int err = 0;
> +
> +	/*
> +	 * 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 (vdev->pix.sizeimage > vb->bsize)
> +			/* The buffer isn't big enough. */
> +			return -EINVAL;
> +	} else {
> +		if (vb->state != VIDEOBUF_NEEDS_INIT
> +		    && vdev->pix.sizeimage > vb->bsize)
> +			/*
> +			 * We have a kernel bounce buffer that has
> +			 * already been allocated.
> +			 */
> +			omap34xxcam_vbq_release(vbq, vb);
> +	}
> +
> +	vb->size = vdev->pix.bytesperline * vdev->pix.height;
> +	vb->width = vdev->pix.width;
> +	vb->height = vdev->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;
> +
> +	vb->state = VIDEOBUF_ACTIVE;
> +
> +	isp_buf_queue(vb, omap34xxcam_vbq_complete, (void *)fh);
> +}
> +
> +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_SHORT_NAME, sizeof(cap->driver));
> +	strlcpy(cap->card, vdev->vfd->name, sizeof(cap->card));
> +	cap->version = OMAP34XXCAM_VERSION;
> +	if (vdev->vdev_sensor != v4l2_int_device_dummy())
> +		cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
> +
> +	return 0;
> +}
> +
> +/**
> + * vidioc_enum_fmt_vid_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_vid_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 == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	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_vid_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_vid_cap(struct file *file, void *fh,
> +				struct v4l2_format *f)
> +{
> +	struct omap34xxcam_fh *ofh = fh;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +	f->fmt.pix = vdev->pix;
> +	mutex_unlock(&vdev->mutex);

Hmmmm, you are using mutex_lock to lock reading from vdev structure..
Well, i don't if this is right approach. I am used to that mutex_lock is
used to prevent _changing_ of members in structure..


> +
> +	return 0;
> +}
> +
> +static int try_pix_parm(struct omap34xxcam_videodev *vdev,
> +			struct v4l2_pix_format *best_pix_in,
> +			struct v4l2_pix_format *wanted_pix_out,
> +			struct v4l2_fract *best_ival)
> +{
> +	int fps;
> +	int fmtd_index;
> +	int rval;
> +	struct v4l2_pix_format best_pix_out;
> +
> +	if (best_ival->numerator == 0
> +	    || best_ival->denominator == 0)
> +		*best_ival = vdev->vdev_sensor_config.ival_default;
> +
> +	fps = best_ival->denominator / best_ival->numerator;
> +
> +	best_ival->denominator = 0;
> +	best_pix_out.height = INT_MAX >> 1;
> +	best_pix_out.width = best_pix_out.height;
> +
> +	for (fmtd_index = 0; ; fmtd_index++) {
> +		int size_index;
> +		struct v4l2_fmtdesc fmtd;
> +
> +		fmtd.index = fmtd_index;
> +		fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +		rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, &fmtd);
> +		if (rval)
> +			break;
> +		dev_info(&vdev->vfd->dev, "trying fmt %8.8x (%d)\n",
> +			 fmtd.pixelformat, fmtd_index);
> +		/*
> +		 * Get supported resolutions.
> +		 */
> +		for (size_index = 0; ; size_index++) {
> +			struct v4l2_frmsizeenum frms;
> +			struct v4l2_pix_format pix_tmp_in, pix_tmp_out;
> +			int ival_index;
> +
> +			frms.index = size_index;
> +			frms.pixel_format = fmtd.pixelformat;
> +
> +			rval = vidioc_int_enum_framesizes(vdev->vdev_sensor,
> +							  &frms);
> +			if (rval)
> +				break;
> +
> +			pix_tmp_in.pixelformat = frms.pixel_format;
> +			pix_tmp_in.width = frms.discrete.width;
> +			pix_tmp_in.height = frms.discrete.height;
> +			pix_tmp_out = *wanted_pix_out;
> +			/* Don't do upscaling. */
> +			if (pix_tmp_out.width > pix_tmp_in.width)
> +				pix_tmp_out.width = pix_tmp_in.width;
> +			if (pix_tmp_out.height > pix_tmp_in.height)
> +				pix_tmp_out.height = pix_tmp_in.height;
> +			rval = isp_try_fmt_cap(&pix_tmp_in, &pix_tmp_out);
> +			if (rval)
> +				return rval;
> +
> +			dev_info(&vdev->vfd->dev, "this w %d\th %d\tfmt %8.8x\t"
> +				 "-> w %d\th %d\t fmt %8.8x"
> +				 "\twanted w %d\th %d\t fmt %8.8x\n",
> +				 pix_tmp_in.width, pix_tmp_in.height,
> +				 pix_tmp_in.pixelformat,
> +				 pix_tmp_out.width, pix_tmp_out.height,
> +				 pix_tmp_out.pixelformat,
> +				 wanted_pix_out->width, wanted_pix_out->height,
> +				 wanted_pix_out->pixelformat);
> +
> +#define IS_SMALLER_OR_EQUAL(pix1, pix2)				\
> +			((pix1)->width + (pix1)->height		\
> +			 < (pix2)->width + (pix2)->height)
> +#define SIZE_DIFF(pix1, pix2)						\
> +			(abs((pix1)->width - (pix2)->width)		\
> +			 + abs((pix1)->height - (pix2)->height))
> +
> +			/*
> +			 * Don't use modes that are farther from wanted size
> +			 * that what we already got.
> +			 */
> +			if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
> +			    > SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
> +				dev_info(&vdev->vfd->dev, "size diff bigger: "
> +					 "w %d\th %d\tw %d\th %d\n",
> +					 pix_tmp_out.width, pix_tmp_out.height,
> +					 best_pix_out.width,
> +					 best_pix_out.height);
> +				continue;
> +			}
> +
> +			/*
> +			 * There's an input mode that can provide output
> +			 * closer to wanted.
> +			 */
> +			if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
> +			    < SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
> +				/* Force renegotation of fps etc. */
> +				best_ival->denominator = 0;
> +				dev_info(&vdev->vfd->dev, "renegotiate: "
> +					 "w %d\th %d\tw %d\th %d\n",
> +					 pix_tmp_out.width, pix_tmp_out.height,
> +					 best_pix_out.width,
> +					 best_pix_out.height);
> +			}
> +
> +			for (ival_index = 0; ; ival_index++) {
> +				struct v4l2_frmivalenum frmi;
> +
> +				frmi.index = ival_index;
> +				frmi.pixel_format = frms.pixel_format;
> +				frmi.width = frms.discrete.width;
> +				frmi.height = frms.discrete.height;
> +				/* FIXME: try to fix standard... */
> +				frmi.reserved[0] = 0xdeafbeef;
> +
> +				rval = vidioc_int_enum_frameintervals(
> +					vdev->vdev_sensor, &frmi);
> +				if (rval)
> +					break;
> +
> +				dev_info(&vdev->vfd->dev, "fps %d\n",
> +					 frmi.discrete.denominator
> +					 / frmi.discrete.numerator);
> +
> +				if (best_ival->denominator == 0)
> +					goto do_it_now;
> +
> +				/*
> +				 * We aim to use maximum resolution
> +				 * from the sensor, provided that the
> +				 * fps is at least as close as on the
> +				 * current mode.
> +				 */
> +#define FPS_ABS_DIFF(fps, ival) abs(fps - (ival).denominator / (ival).numerator)
> +
> +				/* Select mode with closest fps. */
> +				if (FPS_ABS_DIFF(fps, frmi.discrete)
> +				    < FPS_ABS_DIFF(fps, *best_ival)) {
> +					dev_info(&vdev->vfd->dev, "closer fps: "
> +						 "fps %d\t fps %d\n",
> +						 FPS_ABS_DIFF(fps, frmi.discrete),
> +						 FPS_ABS_DIFF(fps, *best_ival));
> +					goto do_it_now;
> +				}
> +
> +				/*
> +				 * Select bigger resolution if it's available
> +				 * at same fps.
> +				 */
> +				if (frmi.width + frmi.height
> +				    > best_pix_in->width + best_pix_in->height
> +				    && FPS_ABS_DIFF(fps, frmi.discrete)
> +				    <= FPS_ABS_DIFF(fps, *best_ival)) {
> +					dev_info(&vdev->vfd->dev, "bigger res, "
> +						 "same fps: "
> +						 "w %d\th %d\tw %d\th %d\n",
> +						 frmi.width, frmi.height,
> +						 best_pix_in->width,
> +						 best_pix_in->height);
> +					goto do_it_now;
> +				}
> +
> +				dev_info(&vdev->vfd->dev, "falling through\n");
> +
> +				continue;
> +
> +			do_it_now:
> +				*best_ival = frmi.discrete;
> +				best_pix_out = pix_tmp_out;
> +				best_pix_in->width = frmi.width;
> +				best_pix_in->height = frmi.height;
> +				best_pix_in->pixelformat = frmi.pixel_format;
> +
> +				dev_info(&vdev->vfd->dev,
> +					 "best_pix_in: w %d\th %d\tfmt %8.8x"
> +					 "\tival %d/%d\n",
> +					 best_pix_in->width,
> +					 best_pix_in->height,
> +					 best_pix_in->pixelformat,
> +					 best_ival->numerator,
> +					 best_ival->denominator);
> +			}
> +		}
> +	}
> +
> +	if (best_ival->denominator == 0)
> +		return -EINVAL;
> +
> +	*wanted_pix_out = best_pix_out;
> +
> +	dev_info(&vdev->vfd->dev, "w %d, h %d, fmt %8.8x -> w %d, h %d\n",
> +		 best_pix_in->width, best_pix_in->height,
> +		 best_pix_in->pixelformat,
> +		 best_pix_out.width, best_pix_out.height);
> +
> +	return isp_try_fmt_cap(best_pix_in, wanted_pix_out);
> +}
> +
> +static int s_pix_parm(struct omap34xxcam_videodev *vdev,
> +		      struct v4l2_pix_format *best_pix,
> +		      struct v4l2_pix_format *pix,
> +		      struct v4l2_fract *best_ival)
> +{
> +	struct v4l2_streamparm a;
> +	struct v4l2_format fmt;
> +	int rval;
> +
> +	rval = try_pix_parm(vdev, best_pix, pix, best_ival);
> +	if (rval)
> +		return rval;
> +
> +	rval = isp_s_fmt_cap(best_pix, pix);
> +	if (rval)
> +		return rval;
> +
> +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	fmt.fmt.pix = *best_pix;
> +	rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, &fmt);
> +	if (rval)
> +		return rval;
> +
> +	a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	a.parm.capture.timeperframe = *best_ival;
> +	rval = vidioc_int_s_parm(vdev->vdev_sensor, &a);
> +
> +	return rval;
> +}
> +
> +/**
> + * vidioc_s_fmt_vid_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_vid_cap().
> + */
> +static int vidioc_s_fmt_vid_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_tmp;
> +	struct v4l2_fract timeperframe;
> +	int rval;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +	if (vdev->streaming) {
> +		rval = -EBUSY;
> +		goto out;
> +	}

Well, why don't remove goto, place return -EBUSY, and move mutex after
if (vdev->streaming) check ?

> +
> +	vdev->want_pix = f->fmt.pix;
> +
> +	timeperframe = vdev->want_timeperframe;
> +
> +	rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
> +	if (!rval)
> +		vdev->pix = f->fmt.pix;
> +
> +out:
> +	mutex_unlock(&vdev->mutex);
> +
> +	return rval;
> +}
> +
> +/**
> + * vidioc_try_fmt_vid_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_vid_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_tmp;
> +	struct v4l2_fract timeperframe;
> +	int rval;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	timeperframe = vdev->want_timeperframe;
> +
> +	rval = try_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
> +
> +	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;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +	if (vdev->streaming) {
> +		mutex_unlock(&vdev->mutex);
> +		return -EBUSY;
> +	}

If i'm doing this i prefer to place mutex_lock after this
if(vdev->streaming) check.

> +
> +	rval = videobuf_reqbufs(&ofh->vbq, b);
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	/*
> +	 * 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;
> +	int rval;
> +
> +videobuf_dqbuf_again:
> +	rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
> +
> +	/*
> +	 * This is a hack. We don't want to show -EIO to the user
> +	 * space. Requeue the buffer and try again if we're not doing
> +	 * this in non-blocking mode.
> +	 */
> +	if (rval == -EIO) {
> +		videobuf_qbuf(&ofh->vbq, b);
> +		if (!(file->f_flags & O_NONBLOCK))
> +			goto videobuf_dqbuf_again;
> +		/*
> +		 * We don't have a videobuf_buffer now --- maybe next
> +		 * time...
> +		 */
> +		rval = -EAGAIN;
> +	}
> +
> +	return rval;
> +}
> +
> +/**
> + * 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;
> +	int rval;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +	if (vdev->streaming) {
> +		rval = -EBUSY;
> +		goto out;
> +	}
> +
> +	rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
> +					   OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
> +	if (rval) {
> +		dev_dbg(&vdev->vfd->dev, "omap34xxcam_slave_power_set failed\n");
> +		goto out;
> +	}
> +
> +	rval = videobuf_streamon(&ofh->vbq);
> +	if (rval)
> +		omap34xxcam_slave_power_set(
> +			vdev, V4L2_POWER_OFF,
> +			OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
> +	else
> +		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;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->streaming == file)
> +		isp_stop();
> +
> +	rval = videobuf_streamoff(q);
> +	if (!rval) {
> +		vdev->streaming = NULL;
> +
> +		omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY,
> +					    OMAP34XXCAM_SLAVE_POWER_SENSOR);
> +		omap34xxcam_slave_power_suggest(vdev, V4L2_POWER_STANDBY,
> +						OMAP34XXCAM_SLAVE_POWER_LENS);
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	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;
> +	struct v4l2_queryctrl a_tmp;
> +	int best_slave = -1;
> +	u32 best_ctrl = (u32)-1;
> +	int i;
> +
> +	if (vdev->vdev_sensor_config.sensor_isp)
> +		return vidioc_int_queryctrl(vdev->vdev_sensor, a);
> +
> +	/* No next flags: try slaves directly. */
> +	if (!(a->id & V4L2_CTRL_FLAG_NEXT_CTRL)) {
> +		for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +			if (!vidioc_int_queryctrl(vdev->slave[i], a))
> +				return 0;
> +		}
> +		return isp_queryctrl(a);
> +	}
> +
> +	/* Find slave with smallest next control id. */
> +	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +		a_tmp = *a;
> +
> +		if (vidioc_int_queryctrl(vdev->slave[i], &a_tmp))
> +			continue;
> +
> +		if (a_tmp.id < best_ctrl) {
> +			best_slave = i;
> +			best_ctrl = a_tmp.id;
> +		}
> +	}
> +
> +	a_tmp = *a;
> +	if (!isp_queryctrl(&a_tmp)) {
> +		if (a_tmp.id < best_ctrl) {
> +			*a = a_tmp;
> +
> +			return 0;
> +		}
> +	}
> +
> +	if (best_slave == -1)
> +		return -EINVAL;
> +
> +	a->id = best_ctrl;
> +	return vidioc_int_queryctrl(vdev->slave[best_slave], a);
> +}
> +
> +/**
> + * vidioc_querymenu - V4L2 query menu IOCTL handler
> + * @file: ptr. to system file structure
> + * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
> + * @a: standard V4L2 query menu ioctl structure
> + *
> + * If the requested control is supported, returns the menu information
> + * in the v4l2_querymenu structure.  Otherwise, returns -EINVAL if the
> + * control is not supported or is not a menu.  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
> + * menu control, the request is forwarded to the "raw" sensor driver to
> + * see if it supports it.
> + */
> +static int vidioc_querymenu(struct file *file, void *fh,
> +			    struct v4l2_querymenu *a)
> +{
> +	struct omap34xxcam_fh *ofh = fh;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +	int i;
> +
> +	if (vdev->vdev_sensor_config.sensor_isp)
> +		return vidioc_int_querymenu(vdev->vdev_sensor, a);
> +
> +	/* Try slaves directly. */
> +	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +		if (!vidioc_int_querymenu(vdev->slave[i], a))
> +			return 0;
> +	}
> +	return isp_querymenu(a);
> +}
> +
> +static int vidioc_g_ext_ctrls(struct file *file, void *fh,
> +			      struct v4l2_ext_controls *a)
> +{
> +	struct omap34xxcam_fh *ofh = fh;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +	int i, ctrl_idx, rval = 0;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
> +		struct v4l2_control ctrl;
> +
> +		ctrl.id = a->controls[ctrl_idx].id;
> +
> +		if (vdev->vdev_sensor_config.sensor_isp) {
> +			rval = vidioc_int_g_ctrl(vdev->vdev_sensor, &ctrl);
> +		} else {
> +			for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +				rval = vidioc_int_g_ctrl(vdev->slave[i], &ctrl);
> +				if (!rval)
> +					break;
> +			}
> +		}
> +
> +		if (rval)
> +			rval = isp_g_ctrl(&ctrl);
> +
> +		if (rval) {
> +			a->error_idx = ctrl_idx;
> +			break;
> +		}
> +
> +		a->controls[ctrl_idx].value = ctrl.value;
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	return rval;
> +}
> +
> +static int vidioc_s_ext_ctrls(struct file *file, void *fh,
> +			      struct v4l2_ext_controls *a)
> +{
> +	struct omap34xxcam_fh *ofh = fh;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +	int i, ctrl_idx, rval = 0;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
> +		struct v4l2_control ctrl;
> +
> +		ctrl.id = a->controls[ctrl_idx].id;
> +		ctrl.value = a->controls[ctrl_idx].value;
> +
> +		if (vdev->vdev_sensor_config.sensor_isp) {
> +			rval = vidioc_int_s_ctrl(vdev->vdev_sensor, &ctrl);
> +		} else {
> +			for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +				rval = vidioc_int_s_ctrl(vdev->slave[i], &ctrl);
> +				if (!rval)
> +					break;
> +			}
> +		}
> +
> +		if (rval)
> +			rval = isp_s_ctrl(&ctrl);
> +
> +		if (rval) {
> +			a->error_idx = ctrl_idx;
> +			break;
> +		}
> +
> +		a->controls[ctrl_idx].value = ctrl.value;
> +	}
> +
> +	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_pix_format pix_tmp_sensor, pix_tmp;
> +	int rval;
> +
> +	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +	if (vdev->streaming) {
> +		rval = -EBUSY;
> +		goto out;
> +	}
> +
> +	vdev->want_timeperframe = a->parm.capture.timeperframe;
> +
> +	pix_tmp = vdev->want_pix;
> +
> +	rval = s_pix_parm(vdev, &pix_tmp_sensor, &pix_tmp,
> +			  &a->parm.capture.timeperframe);
> +
> +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 == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	rval = vidioc_int_cropcap(vdev->vdev_sensor, a);
> +
> +	if (rval && !vdev->vdev_sensor_config.sensor_isp) {
> +		struct v4l2_format f;
> +
> +		/* cropcap failed, try to do this via g_fmt_cap */
> +		rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &f);
> +		if (!rval) {
> +			cropcap->bounds.top = 0;
> +			cropcap->bounds.left = 0;
> +			cropcap->bounds.width = f.fmt.pix.width;
> +			cropcap->bounds.height = f.fmt.pix.height;
> +			cropcap->defrect = cropcap->bounds;
> +			cropcap->pixelaspect.numerator = 1;
> +			cropcap->pixelaspect.denominator = 1;
> +		}
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	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 == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->vdev_sensor_config.sensor_isp)
> +		rval = vidioc_int_g_crop(vdev->vdev_sensor, a);
> +	else
> +		rval = isp_g_crop(a);
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	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;
> +	int rval = 0;
> +
> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> +		return -EINVAL;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->vdev_sensor_config.sensor_isp)
> +		rval = vidioc_int_s_crop(vdev->vdev_sensor, a);
> +	else
> +		rval = isp_s_crop(a, &vdev->pix);
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	return rval;
> +}
> +
> +static int vidioc_enum_framesizes(struct file *file, void *fh,
> +				  struct v4l2_frmsizeenum *frms)
> +{
> +	struct omap34xxcam_fh *ofh = fh;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +	u32 pixel_format;
> +	int rval;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->vdev_sensor_config.sensor_isp) {
> +		rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
> +	} else {
> +		pixel_format = frms->pixel_format;
> +		frms->pixel_format = -1;	/* ISP does format conversion */
> +		rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
> +		frms->pixel_format = pixel_format;
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +	return rval;
> +}
> +
> +static int vidioc_enum_frameintervals(struct file *file, void *fh,
> +				      struct v4l2_frmivalenum *frmi)
> +{
> +	struct omap34xxcam_fh *ofh = fh;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +	u32 pixel_format;
> +	int rval;
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->vdev_sensor_config.sensor_isp) {
> +		rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
> +	} else {
> +		pixel_format = frmi->pixel_format;
> +		frmi->pixel_format = -1;	/* ISP does format conversion */
> +		rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
> +		frmi->pixel_format = pixel_format;
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +	return rval;
> +}
> +
> +/**
> + * vidioc_default - private IOCTL handler
> + * @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 long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
> +{
> +	struct omap34xxcam_fh *ofh = file->private_data;
> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> +	int rval;
> +
> +	if (vdev->vdev_sensor_config.sensor_isp) {
> +		rval = -EINVAL;
> +	} else {
> +		switch (cmd) {
> +		case VIDIOC_PRIVATE_ISP_AEWB_REQ:
> +		{
> +			/* Need to update sensor first */
> +			struct isph3a_aewb_data *data;
> +			struct v4l2_control vc;
> +
> +			data = (struct isph3a_aewb_data *) arg;
> +			if (data->update & SET_EXPOSURE) {
> +				dev_info(&vdev->vfd->dev, "using "
> +					 "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
> +					 "exposure is deprecated!\n");
> +				vc.id = V4L2_CID_EXPOSURE;
> +				vc.value = data->shutter;
> +				mutex_lock(&vdev->mutex);
> +				rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
> +							 &vc);
> +				mutex_unlock(&vdev->mutex);
> +				if (rval)
> +					goto out;
> +			}
> +			if (data->update & SET_ANALOG_GAIN) {
> +				dev_info(&vdev->vfd->dev, "using "
> +					 "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
> +					 "gain is deprecated!\n");
> +				vc.id = V4L2_CID_GAIN;
> +				vc.value = data->gain;
> +				mutex_lock(&vdev->mutex);
> +				rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
> +							 &vc);
> +				mutex_unlock(&vdev->mutex);
> +				if (rval)
> +					goto out;
> +			}
> +		}
> +		break;
> +		case VIDIOC_PRIVATE_ISP_AF_REQ: {
> +			/* Need to update lens first */
> +			struct isp_af_data *data;
> +			struct v4l2_control vc;
> +
> +			if (!vdev->vdev_lens) {
> +				rval = -EINVAL;
> +				goto out;
> +			}
> +			data = (struct isp_af_data *) arg;
> +			if (data->update & LENS_DESIRED_POSITION) {
> +				dev_info(&vdev->vfd->dev, "using "
> +					 "VIDIOC_PRIVATE_ISP_AF_REQ to set "
> +					 "lens position is deprecated!\n");
> +				vc.id = V4L2_CID_FOCUS_ABSOLUTE;
> +				vc.value = data->desired_lens_direction;
> +				mutex_lock(&vdev->mutex);
> +				rval = vidioc_int_s_ctrl(vdev->vdev_lens, &vc);
> +				mutex_unlock(&vdev->mutex);
> +				if (rval)
> +					goto out;
> +			}
> +		}
> +			break;
> +		}
> +
> +		mutex_lock(&vdev->mutex);
> +		rval = isp_handle_private(cmd, arg);
> +		mutex_unlock(&vdev->mutex);
> +	}
> +out:
> +	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 file *file)
> +{
> +	int rval = 0;
> +	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(file->f_dentry->d_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] != v4l2_int_device_dummy()
> +		    && !try_module_get(vdev->slave[i]->module)) {
> +			mutex_unlock(&vdev->mutex);
> +			dev_err(&vdev->vfd->dev, "can't try_module_get %s\n",
> +				vdev->slave[i]->name);
> +			rval = -ENODEV;
> +			goto out_try_module_get;
> +		}
> +	}
> +
> +	if (atomic_inc_return(&vdev->users) == 1) {
> +		rval = isp_get();
> +		if (rval < 0) {
> +			dev_err(&vdev->vfd->dev, "can't get isp\n");
> +			goto out_isp_get;
> +		}
> +		if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
> +						OMAP34XXCAM_SLAVE_POWER_ALL)) {
> +			dev_err(&vdev->vfd->dev, "can't power up slaves\n");
> +			rval = -EBUSY;
> +			goto out_slave_power_set_standby;
> +		}
> +		omap34xxcam_slave_power_set(
> +			vdev, V4L2_POWER_STANDBY,
> +			OMAP34XXCAM_SLAVE_POWER_SENSOR);
> +		omap34xxcam_slave_power_suggest(
> +			vdev, V4L2_POWER_STANDBY,
> +			OMAP34XXCAM_SLAVE_POWER_LENS);
> +	}
> +
> +	fh->vdev = vdev;
> +
> +	if (!vdev->pix.width
> +	    && vdev->vdev_sensor != v4l2_int_device_dummy()) {
> +		memset(&format, 0, sizeof(format));
> +		if (vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format)) {
> +			dev_err(&vdev->vfd->dev,
> +				"can't get current pix from sensor!\n");
> +			goto out_vidioc_int_g_fmt_cap;
> +		}
> +		if (!vdev->vdev_sensor_config.sensor_isp) {
> +			struct v4l2_pix_format pix = format.fmt.pix;
> +			if (isp_s_fmt_cap(&pix, &format.fmt.pix)) {
> +				dev_err(&vdev->vfd->dev,
> +					"isp doesn't like the sensor!\n");
> +				goto out_isp_s_fmt_cap;
> +			}
> +		}
> +		vdev->pix = format.fmt.pix;
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	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_isp_s_fmt_cap:
> +out_vidioc_int_g_fmt_cap:
> +	omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
> +				    OMAP34XXCAM_SLAVE_POWER_ALL);
> +out_slave_power_set_standby:
> +	isp_put();
> +
> +out_isp_get:
> +	atomic_dec(&vdev->users);
> +	mutex_unlock(&vdev->mutex);
> +
> +out_try_module_get:
> +	for (i--; i >= 0; i--)
> +		if (vdev->slave[i] != v4l2_int_device_dummy())
> +			module_put(vdev->slave[i]->module);
> +
> +	kfree(fh);
> +
> +	return rval;
> +}
> +
> +/**
> + * 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 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,
> +			OMAP34XXCAM_SLAVE_POWER_SENSOR);
> +		omap34xxcam_slave_power_suggest(
> +			vdev, V4L2_POWER_STANDBY,
> +			OMAP34XXCAM_SLAVE_POWER_LENS);
> +		vdev->streaming = NULL;
> +	}
> +
> +	if (atomic_dec_return(&vdev->users) == 0) {
> +		omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
> +					    OMAP34XXCAM_SLAVE_POWER_ALL);
> +		isp_put();
> +	}
> +	mutex_unlock(&vdev->mutex);
> +
> +	file->private_data = NULL;
> +
> +	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++)
> +		if (vdev->slave[i] != v4l2_int_device_dummy())
> +			module_put(vdev->slave[i]->module);
> +
> +	kfree(fh);
> +
> +	return 0;
> +}
> +
> +static struct v4l2_file_operations omap34xxcam_fops = {
> +	.owner = THIS_MODULE,
> +	.unlocked_ioctl = video_ioctl2,
> +	.poll = omap34xxcam_poll,
> +	.mmap = omap34xxcam_mmap,
> +	.open = omap34xxcam_open,
> +	.release = omap34xxcam_release,
> +};
> +
> +static void omap34xxcam_vfd_name_update(struct omap34xxcam_videodev *vdev)
> +{
> +	struct video_device *vfd = vdev->vfd;
> +	int i;
> +
> +	strlcpy(vfd->name, CAM_SHORT_NAME, sizeof(vfd->name));
> +	for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
> +		strlcat(vfd->name, "/", sizeof(vfd->name));
> +		if (vdev->slave[i] == v4l2_int_device_dummy())
> +			continue;
> +		strlcat(vfd->name, vdev->slave[i]->name, sizeof(vfd->name));
> +	}
> +	dev_info(&vdev->vfd->dev, "video%d is now %s\n", vfd->num, vfd->name);
> +}
> +
> +/**
> + * 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);
> +
> +	mutex_lock(&vdev->mutex);
> +
> +	if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy()) {
> +		vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
> +		vdev->slaves--;
> +		omap34xxcam_vfd_name_update(vdev);
> +	}
> +
> +	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;
> +	}
> +
> +	mutex_unlock(&vdev->mutex);
> +}
> +
> +static const struct v4l2_ioctl_ops omap34xxcam_ioctl_ops = {
> +	.vidioc_querycap		= vidioc_querycap,
> +	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap		= vidioc_g_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap		= vidioc_s_fmt_vid_cap,
> +	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt_vid_cap,
> +	.vidioc_reqbufs			= vidioc_reqbufs,
> +	.vidioc_querybuf		= vidioc_querybuf,
> +	.vidioc_qbuf			= vidioc_qbuf,
> +	.vidioc_dqbuf			= vidioc_dqbuf,
> +	.vidioc_streamon		= vidioc_streamon,
> +	.vidioc_streamoff		= vidioc_streamoff,
> +	.vidioc_enum_input		= vidioc_enum_input,
> +	.vidioc_g_input			= vidioc_g_input,
> +	.vidioc_s_input			= vidioc_s_input,
> +	.vidioc_queryctrl		= vidioc_queryctrl,
> +	.vidioc_querymenu		= vidioc_querymenu,
> +	.vidioc_g_ext_ctrls		= vidioc_g_ext_ctrls,
> +	.vidioc_s_ext_ctrls		= vidioc_s_ext_ctrls,
> +	.vidioc_g_parm			= vidioc_g_parm,
> +	.vidioc_s_parm			= vidioc_s_parm,
> +	.vidioc_cropcap			= vidioc_cropcap,
> +	.vidioc_g_crop			= vidioc_g_crop,
> +	.vidioc_s_crop			= vidioc_s_crop,
> +	.vidioc_enum_framesizes		= vidioc_enum_framesizes,
> +	.vidioc_enum_frameintervals	= vidioc_enum_frameintervals,
> +	.vidioc_default			= vidioc_default,
> +};
> +
> +/**
> + * 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_hw_config hwc;
> +	int rval;
> +
> +	/* We need to check rval just once. The place is here. */

I didn't understand this comment. You doing nothin in next few lines
with int variable rval(which introduced in this function). Is comment
talking about struct v4l2_int_device *s ?

> +	if (vidioc_int_g_priv(s, &hwc))
> +		return -ENODEV;
> +
> +	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] != v4l2_int_device_dummy())
> +		return -EBUSY;
> +
> +	mutex_lock(&vdev->mutex);
> +	if (atomic_read(&vdev->users)) {
> +		dev_err(&vdev->vfd->dev, "we're open (%d), can't register\n",
> +			atomic_read(&vdev->users));
> +		mutex_unlock(&vdev->mutex);
> +		return -EBUSY;
> +	}
> +
> +	vdev->slaves++;
> +	vdev->slave[hwc.dev_type] = s;
> +	vdev->slave_config[hwc.dev_type] = hwc;
> +
> +	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
> +		rval = isp_get();
> +		if (rval < 0) {
> +			dev_err(&vdev->vfd->dev,
> +				"can't get ISP, sensor init failed\n");
> +			goto err;
> +		}
> +	}
> +	rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
> +					   1 << hwc.dev_type);
> +	if (rval)
> +		goto err_omap34xxcam_slave_power_set;
> +	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
> +		struct v4l2_format format;
> +
> +		format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +		rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format);
> +		if (rval)
> +			rval = -EBUSY;
> +
> +		vdev->want_pix = format.fmt.pix;
> +	}
> +	omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF, 1 << hwc.dev_type);
> +	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
> +		isp_put();
> +
> +	if (rval)
> +		goto err;
> +
> +	/* Are we the first slave? */
> +	if (vdev->slaves == 1) {
> +		/* initialize the video_device struct */
> +		vdev->vfd = video_device_alloc();
> +		if (!vdev->vfd) {
> +			dev_err(&vdev->vfd->dev,
> +				"could not allocate video device struct\n");

Do i understand you code in right way ?
You call video_device_alloc() to get vdev->vfd. Then if vdev->vfd is
null(empty) you make message dev_err which based on vdev->vfd->dev but
dev->vfd allocating is failed.. If i'm not wrong you message will
provide kernel oops.
One more point here is that you use dev_err(&vdev->vfd->dev before call
to video_device_alloc() in this function.


> +			return -ENOMEM;
> +		}
> +		vdev->vfd->release	= video_device_release;
> +		vdev->vfd->minor	= -1;
> +		vdev->vfd->fops		= &omap34xxcam_fops;
> +		vdev->vfd->ioctl_ops	= &omap34xxcam_ioctl_ops;
> +		video_set_drvdata(vdev->vfd, vdev);
> +
> +		if (video_register_device(vdev->vfd, VFL_TYPE_GRABBER,
> +					  hwc.dev_minor) < 0) {
> +			dev_err(&vdev->vfd->dev,
> +				"could not register V4L device\n");
> +			vdev->vfd->minor = -1;
> +			rval = -EBUSY;
> +			goto err;
> +		}
> +	}
> +
> +	omap34xxcam_vfd_name_update(vdev);
> +
> +	mutex_unlock(&vdev->mutex);
> +
> +	return 0;
> +
> +err_omap34xxcam_slave_power_set:
> +	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
> +		isp_put();
> +
> +err:
> +	if (s == vdev->slave[hwc.dev_type]) {
> +		vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
> +		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,
> +};
> +
> +/*
> + *
> + * Module initialisation and deinitialisation
> + *
> + */
> +
> +static void omap34xxcam_exit(void)
> +{
> +	struct omap34xxcam_device *cam = omap34xxcam;
> +	int i;
> +
> +	if (!cam)
> +		return;
> +
> +	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;
> +	}
> +
> +	omap34xxcam = NULL;
> +
> +	kfree(cam);
> +}
> +
> +static int __init omap34xxcam_init(void)
> +{
> +	struct omap34xxcam_device *cam;
> +	int i;
> +
> +	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
> +	if (!cam) {
> +		printk(KERN_ERR "%s: could not allocate memory\n", __func__);
> +		goto err;

If kzalloc failed you return -ENODEV; but this is ENOMEM error.


> +	}
> +
> +	omap34xxcam = cam;
> +
> +	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;
> +
> +		mutex_init(&vdev->mutex);
> +		vdev->index             = i;
> +		vdev->cam               = cam;
> +		vdev->vdev_sensor =
> +			vdev->vdev_lens =
> +			vdev->vdev_flash = v4l2_int_device_dummy();
> +#ifdef OMAP34XXCAM_POWEROFF_DELAY
> +		setup_timer(&vdev->poweroff_timer,
> +			    omap34xxcam_slave_power_timer, (unsigned long)vdev);
> +		INIT_WORK(&vdev->poweroff_work, omap34xxcam_slave_power_work);
> +#endif /* OMAP34XXCAM_POWEROFF_DELAY */
> +
> +		if (v4l2_int_device_register(m))
> +			goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	omap34xxcam_exit();
> +	return -ENODEV;
> +}
> +
> +MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
> +MODULE_DESCRIPTION("OMAP34xx Video for Linux camera driver");
> +MODULE_LICENSE("GPL");
> +
> +late_initcall(omap34xxcam_init);
> +module_exit(omap34xxcam_exit);
> diff --git a/drivers/media/video/omap34xxcam.h b/drivers/media/video/omap34xxcam.h
> new file mode 100644
> index 0000000..9859d15
> --- /dev/null
> +++ b/drivers/media/video/omap34xxcam.h
> @@ -0,0 +1,207 @@
> +/*
> + * omap34xxcam.h
> + *
> + * Copyright (C) 2006--2009 Nokia Corporation
> + * Copyright (C) 2007--2009 Texas Instruments
> + *
> + * Contact: Sakari Ailus <sakari.ailus@nokia.com>
> + *          Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
> + *
> + * Originally based on the OMAP 2 camera driver.
> + *
> + * Written by Sakari Ailus <sakari.ailus@nokia.com>
> + *            Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
> + *            Sergio Aguirre <saaguirre@ti.com>
> + *            Mohit Jalori
> + *            Sameer Venkatraman
> + *            Leonides Martinez
> + *
> + * This program 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 program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + *
> + */
> +
> +#ifndef OMAP34XXCAM_H
> +#define OMAP34XXCAM_H
> +
> +#include <media/v4l2-int-device.h>
> +#include "isp/isp.h"
> +
> +#define CAM_NAME			"omap34xxcam"
> +#define CAM_SHORT_NAME			"omap3"
> +
> +#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! */
> +
> +/* mask for omap34xxcam_slave_power_set */
> +#define OMAP34XXCAM_SLAVE_POWER_SENSOR	(1 << OMAP34XXCAM_SLAVE_SENSOR)
> +#define OMAP34XXCAM_SLAVE_POWER_LENS	(1 << OMAP34XXCAM_SLAVE_LENS)
> +#define OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS \
> +	(OMAP34XXCAM_SLAVE_POWER_SENSOR | OMAP34XXCAM_SLAVE_POWER_LENS)
> +#define OMAP34XXCAM_SLAVE_POWER_FLASH	(1 << OMAP34XXCAM_SLAVE_FLASH)
> +#define OMAP34XXCAM_SLAVE_POWER_ALL	-1
> +
> +#define OMAP34XXCAM_VIDEODEVS		4
> +
> +/* #define OMAP34XXCAM_POWEROFF_DELAY (2 * HZ) */
> +
> +struct omap34xxcam_device;
> +struct omap34xxcam_videodev;
> +
> +struct omap34xxcam_sensor_config {
> +	int xclk;
> +	int sensor_isp;
> +	u32 capture_mem;
> +	struct v4l2_fract ival_default;
> +};
> +
> +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
> + * @power_state: Current power state
> + * @power_state_wish: New power state when poweroff_timer expires
> + * @power_state_mask: Bitmask of devices to set the new power state
> + * @poweroff_timer: Timer for dispatching poweroff_work
> + * @poweroff_work: Work for slave power state change
> + * @sensor_config: ISP-speicific sensor configuration
> + * @lens_config: ISP-speicific lens configuration
> + * @flash_config: ISP-speicific flash configuration
> + * @want_timeperframe: Desired timeperframe
> + * @want_pix: Desired pix
> + * @pix: Current pix
> + * @streaming: streaming file handle, if streaming is enabled
> + */
> +struct omap34xxcam_videodev {
> +	struct mutex mutex; /* serialises access to this structure */
> +
> +	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 ***/
> +	int index;
> +	atomic_t users;
> +	enum v4l2_power power_state[OMAP34XXCAM_SLAVE_FLASH + 1];
> +#ifdef OMAP34XXCAM_POWEROFF_DELAY
> +	enum v4l2_power power_state_wish;
> +	int power_state_mask;
> +	struct timer_list poweroff_timer;
> +	struct work_struct poweroff_work;
> +#endif /* OMAP34XXCAM_POWEROFF_DELAY */
> +
> +#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 ***/
> +	struct file *streaming;
> +	struct v4l2_fract want_timeperframe;
> +	struct v4l2_pix_format want_pix;
> +	spinlock_t pix_lock;
> +	struct v4l2_pix_format pix;
> +};
> +
> +/**
> + * 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
> + * @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; /* serialises access to this structure */
> +
> +	/*** interfaces and device ***/
> +	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
> + * @field_count: field counter for videobuf_buffer
> + * @vdev: our /dev/video specific structure
> + */
> +struct omap34xxcam_fh {
> +	spinlock_t vbq_lock; /* spinlock for the videobuf queue */
> +	struct videobuf_queue vbq;
> +	atomic_t field_count;
> +	struct omap34xxcam_videodev *vdev;
> +};
> +
> +#endif /* ifndef OMAP34XXCAM_H */
-- 
Best regards, Klimov Alexey


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

* RE: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-03 10:06 [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
  2009-03-03 10:06 ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Sakari Ailus
  2009-03-03 13:09 ` [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
@ 2009-03-04 15:28 ` Hiremath, Vaibhav
  2009-03-04 15:38   ` Sakari Ailus
  2009-03-05  5:00   ` DongSoo(Nathaniel) Kim
  3 siblings, 1 reply; 30+ messages in thread
From: Hiremath, Vaibhav @ 2009-03-04 15:28 UTC (permalink / raw)
  To: Sakari Ailus, linux-media, linux-omap
  Cc: Aguirre Rodriguez, Sergio Alberto, Toivonen Tuukka Olli Artturi,
	Hiroshi DOYU, DongSoo Kim

[-- Attachment #1: Type: text/plain, Size: 3728 bytes --]



Thanks,
Vaibhav Hiremath

> -----Original Message-----
> From: linux-media-owner@vger.kernel.org [mailto:linux-media-
> owner@vger.kernel.org] On Behalf Of Sakari Ailus
> Sent: Tuesday, March 03, 2009 3:37 PM
> To: linux-media@vger.kernel.org; linux-omap@vger.kernel.org
> Cc: Aguirre Rodriguez, Sergio Alberto; Toivonen Tuukka Olli Artturi;
> Hiroshi DOYU; DongSoo Kim
> Subject: [RFC 0/9] OMAP3 ISP and camera drivers
> 
> Hi,
> 
> So here's the patchset for OMAP 3 ISP and camera drivers plus the
> associated V4L changes. Sergio Aguirre has been posting a related
> patchset earlier, containing also sensor and lens driver used on
> SDP.
> This patchset is agains the linux-omap tree:
> 
> <URL:http://www.muru.com/linux/omap/README_OMAP_GIT>
> 
[Hiremath, Vaibhav] Sakari, Let me ask you basic question, have you tested/verified these patch-sets?

The reason I am asking this question is, for me it was not working. I had to debug this and found that - 

	- Changes missing in devices.c file, so isp_probe function will not be called at all, keeping omap3isp = NULL. You will end up into kernel crash in omap34xxcam_device_register.

	- The patches from Hiroshi DOYU doesn't build as is, you need to add one include line #include <linux/hardirq.h> in iovmmu.c
(I am using the patches submitted on 16th Jan 2009)

I have attached "git diff" output here with this mail for reference.

Am I missing any patches here? I am not sure how Sergio is able to use these patches?
If I am not missing anything, then I think you should mention all these issues clearly in the patch so that anybody who might want to use will not suffer.

> So I and Sergio have synchronised our versions of the ISP and camera
> drivers and this is the end result. There is still a lot of work to
> do,
> though. You can find some comments in individual patch descriptions.
> If
> the todo list for a patch is empty it doesn't mean there wouldn't be
> anything left to do. ;)
> 
> There's at least one major change to Sergio Aguirre's earlier
> patches
> which is that the ISP driver now uses the IOMMU from Hiroshi Doyu.
> Hiroshi is away for some time now so there are just some hacks on
> top of
> Hiroshi's older iommu patches to use with current linux-omap.
> 
> This patchset does not contain the resizer or preview wrappers from
> TI
> but they have been left intentionally out. A proper interface (V4L)
> should be used for those and the camera driver should be somehow
> involved --- the wrappers are just duplicating much of the camera
> driver's functionality.
> 
> I don't have any sensor or lens drivers to publish at this time.
> 
> This patchset should work with the SDP and OMAPZoom boards although
> you
> need the associated sensor drivers + the board code from Sergio
> Aguirre
> to use it. You'll also need the IOMMU patchset from Hiroshi Doyu.
> Everything except the sensor / board stuff is available here:
> 
> <URL:http://www.gitorious.org/projects/omap3camera>
> 
> In short, on linux-omap:
> 
> $ git pull http://git.gitorious.org/omap3camera/mainline.git v4l \
>    iommu omap3camera base
> 
> Hiroshi's original iommu tree is here (branch iommu):
> 
> <URL:http://git.gitorious.org/lk/mainline.git>
> 
> Some of the camera and ISP driver development history is available,
> too.
> See the first link.
> 
> Any feedback is appreciated.
> 
> Sincerely,
> 
> --
> Sakari Ailus
> sakari.ailus@maxwell.research.nokia.com
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


[-- Attachment #2: isp_patch_fix.patch --]
[-- Type: application/octet-stream, Size: 4377 bytes --]

diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
old mode 100644
new mode 100755
index dad4528..2568b0c
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -56,10 +56,60 @@ static inline void omap_init_camera(void)
 
 #elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
 
-static struct resource cam_resources[] = {
+static struct resource omap3isp_resources[] = {
+	{
+		.start		= OMAP3430_ISP_BASE,
+		.end		= OMAP3430_ISP_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CBUFF_BASE,
+		.end		= OMAP3430_ISP_CBUFF_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CCP2_BASE,
+		.end		= OMAP3430_ISP_CCP2_END,
+		.flags		= IORESOURCE_MEM,
+	},
 	{
-		.start		= OMAP34XX_CAMERA_BASE,
-		.end		= OMAP34XX_CAMERA_BASE + 0x1B70,
+		.start		= OMAP3430_ISP_CCDC_BASE,
+		.end		= OMAP3430_ISP_CCDC_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_HIST_BASE,
+		.end		= OMAP3430_ISP_HIST_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_H3A_BASE,
+		.end		= OMAP3430_ISP_H3A_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_PREV_BASE,
+		.end		= OMAP3430_ISP_PREV_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_RESZ_BASE,
+		.end		= OMAP3430_ISP_RESZ_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_SBL_BASE,
+		.end		= OMAP3430_ISP_SBL_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CSI2A_BASE,
+		.end		= OMAP3430_ISP_CSI2A_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CSI2PHY_BASE,
+		.end		= OMAP3430_ISP_CSI2PHY_END,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
@@ -68,16 +118,16 @@ static struct resource cam_resources[] = {
 	}
 };
 
-static struct platform_device omap_cam_device = {
-	.name		= "omap34xxcam",
+static struct platform_device omap3isp_device = {
+	.name		= "omap3isp",
 	.id		= -1,
-	.num_resources	= ARRAY_SIZE(cam_resources),
-	.resource	= cam_resources,
+	.num_resources	= ARRAY_SIZE(omap3isp_resources),
+	.resource	= omap3isp_resources,
 };
 
 static inline void omap_init_camera(void)
 {
-	platform_device_register(&omap_cam_device);
+	platform_device_register(&omap3isp_device);
 }
 #else
 static inline void omap_init_camera(void)
diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h
old mode 100644
new mode 100755
index 27a1e45..9a16c96
--- a/arch/arm/plat-omap/include/mach/omap34xx.h
+++ b/arch/arm/plat-omap/include/mach/omap34xx.h
@@ -49,6 +49,33 @@
 #define OMAP343X_CTRL_BASE	OMAP343X_SCM_BASE
 
 #define OMAP34XX_IC_BASE	0x48200000
+
+#define OMAP3430_ISP_BASE		(L4_34XX_BASE + 0xBC000)
+#define OMAP3430_ISP_CBUFF_BASE		(OMAP3430_ISP_BASE + 0x0100)
+#define OMAP3430_ISP_CCP2_BASE		(OMAP3430_ISP_BASE + 0x0400)
+#define OMAP3430_ISP_CCDC_BASE		(OMAP3430_ISP_BASE + 0x0600)
+#define OMAP3430_ISP_HIST_BASE		(OMAP3430_ISP_BASE + 0x0A00)
+#define OMAP3430_ISP_H3A_BASE		(OMAP3430_ISP_BASE + 0x0C00)
+#define OMAP3430_ISP_PREV_BASE		(OMAP3430_ISP_BASE + 0x0E00)
+#define OMAP3430_ISP_RESZ_BASE		(OMAP3430_ISP_BASE + 0x1000)
+#define OMAP3430_ISP_SBL_BASE		(OMAP3430_ISP_BASE + 0x1200)
+#define OMAP3430_ISP_MMU_BASE		(OMAP3430_ISP_BASE + 0x1400)
+#define OMAP3430_ISP_CSI2A_BASE		(OMAP3430_ISP_BASE + 0x1800)
+#define OMAP3430_ISP_CSI2PHY_BASE	(OMAP3430_ISP_BASE + 0x1970)
+
+#define OMAP3430_ISP_END		(OMAP3430_ISP_BASE         + 0x06F)
+#define OMAP3430_ISP_CBUFF_END		(OMAP3430_ISP_CBUFF_BASE   + 0x077)
+#define OMAP3430_ISP_CCP2_END		(OMAP3430_ISP_CCP2_BASE    + 0x1EF)
+#define OMAP3430_ISP_CCDC_END		(OMAP3430_ISP_CCDC_BASE    + 0x0A7)
+#define OMAP3430_ISP_HIST_END		(OMAP3430_ISP_HIST_BASE    + 0x047)
+#define OMAP3430_ISP_H3A_END		(OMAP3430_ISP_H3A_BASE     + 0x05F)
+#define OMAP3430_ISP_PREV_END		(OMAP3430_ISP_PREV_BASE    + 0x09F)
+#define OMAP3430_ISP_RESZ_END		(OMAP3430_ISP_RESZ_BASE    + 0x0AB)
+#define OMAP3430_ISP_SBL_END		(OMAP3430_ISP_SBL_BASE     + 0x0FB)
+#define OMAP3430_ISP_MMU_END		(OMAP3430_ISP_MMU_BASE     + 0x06F)
+#define OMAP3430_ISP_CSI2A_END		(OMAP3430_ISP_CSI2A_BASE   + 0x16F)
+#define OMAP3430_ISP_CSI2PHY_END	(OMAP3430_ISP_CSI2PHY_BASE + 0x007)
+
 #define OMAP34XX_IVA_INTC_BASE	0x40000000
 #define OMAP34XX_HSUSB_OTG_BASE	(L4_34XX_BASE + 0xAB000)
 #define OMAP34XX_HSUSB_HOST_BASE	(L4_34XX_BASE + 0x64000)

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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-04 15:28 ` Hiremath, Vaibhav
@ 2009-03-04 15:38   ` Sakari Ailus
  2009-03-05  0:10     ` DongSoo(Nathaniel) Kim
  0 siblings, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-04 15:38 UTC (permalink / raw)
  To: Hiremath, Vaibhav
  Cc: linux-media, linux-omap, Aguirre Rodriguez, Sergio Alberto,
	Toivonen Tuukka Olli Artturi, Hiroshi DOYU, DongSoo Kim

Hiremath, Vaibhav wrote:
> [Hiremath, Vaibhav] Sakari, Let me ask you basic question, have you
> tested/verified these patch-sets?

For the ISP and camera drivers, yes. That's actually the only thing 
that's contained in the patchset.

> The reason I am asking this question is, for me it was not working. I
> had to debug this and found that -
> 
> - Changes missing in devices.c file, so isp_probe function will not
> be called at all, keeping omap3isp = NULL. You will end up into
> kernel crash in omap34xxcam_device_register.

Anyway a crash shouldn't happen here. Could I see the kernel oops if 
there was such?

> - The patches from Hiroshi DOYU doesn't build as is, you need to add
> one include line #include <linux/hardirq.h> in iovmmu.c (I am using
> the patches submitted on 16th Jan 2009)

Just pull the iommu branch, the Hiroshi's original patches are missing 
some hacks that you need to use them now. I'd expect Hiroshi to update 
the patchset when he comes back.

> I have attached "git diff" output here with this mail for reference.

Please pull also the "base" branch.

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-04 15:38   ` Sakari Ailus
@ 2009-03-05  0:10     ` DongSoo(Nathaniel) Kim
  2009-03-05  3:53       ` Hiremath, Vaibhav
  0 siblings, 1 reply; 30+ messages in thread
From: DongSoo(Nathaniel) Kim @ 2009-03-05  0:10 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Hiremath, Vaibhav, linux-media, linux-omap, Aguirre Rodriguez,
	Sergio Alberto, Toivonen Tuukka Olli Artturi, Hiroshi DOYU

Hi Sakari,

I'm also facing same issue with Hiremath.

Here you are my kernel stack dump.

Cheers,

Nate

[    6.465606] [<c019e194>] (dev_driver_string+0x0/0x44) from
[<c01cc5e0>] (omap34xxcam_device_register+0x110/0x2f8)
[    6.475952] [<c01cc4d0>] (omap34xxcam_device_register+0x0/0x2f8)
from [<c01b91a0>] (__v4l2_int_device_try_attach_all+0xb0/0x108)
[    6.487609]  r7:00000000 r6:c03e4fcc r5:cfbbf834 r4:c03e4f94
[    6.493347] [<c01b90f0>]
(__v4l2_int_device_try_attach_all+0x0/0x108) from [<c01b9258>]
(v4l2_int_device_register+0x60/0x7c)
[    6.504638]  r7:c03e4eec r6:cf9e5020 r5:c03e4f94 r4:c03e03f8
[    6.510375] [<c01b91f8>] (v4l2_int_device_register+0x0/0x7c) from
[<c00182e4>] (ce131f_probe+0x88/0xa8)
[    6.519836]  r5:00000000 r4:cf9e5000
[    6.523437] [<c001825c>] (ce131f_probe+0x0/0xa8) from [<c01cefa4>]
(i2c_device_probe+0x78/0x90)
[    6.532226]  r5:cf9e5000 r4:c001825c
[    6.535827] [<c01cef2c>] (i2c_device_probe+0x0/0x90) from
[<c01a1634>] (driver_probe_device+0xd4/0x180)
[    6.545318]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
[    6.551025] [<c01a1560>] (driver_probe_device+0x0/0x180) from
[<c01a1748>] (__driver_attach+0x68/0x8c)
[    6.560394]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
[    6.566131] [<c01a16e0>] (__driver_attach+0x0/0x8c) from
[<c01a0a8c>] (bus_for_each_dev+0x4c/0x84)
[    6.575164]  r7:c03e4eec r6:c01a16e0 r5:cf821cc8 r4:00000000
[    6.580871] [<c01a0a40>] (bus_for_each_dev+0x0/0x84) from
[<c01a1478>] (driver_attach+0x20/0x28)
[    6.589721]  r7:cfb121a0 r6:c0018224 r5:c03e4eec r4:00000000
[    6.595458] [<c01a1458>] (driver_attach+0x0/0x28) from [<c01a1054>]
(bus_add_driver+0xa8/0x214)
[    6.604217] [<c01a0fac>] (bus_add_driver+0x0/0x214) from
[<c01a196c>] (driver_register+0x98/0x120)
[    6.613250]  r8:00000000 r7:c03ef760 r6:c0018224 r5:c03e4eec r4:c03e4ec0
[    6.620025] [<c01a18d4>] (driver_register+0x0/0x120) from
[<c01cfffc>] (i2c_register_driver+0x98/0xfc)
[    6.629425] [<c01cff64>] (i2c_register_driver+0x0/0xfc) from
[<c001823c>] (ce131f_isp_init+0x18/0x38)
[    6.638702]  r7:c03ef760 r6:c0018224 r5:c0022d78 r4:c0023128
[    6.644439] [<c0018224>] (ce131f_isp_init+0x0/0x38) from
[<c002a2d0>] (do_one_initcall+0x78/0x1d8)
[    6.653472]  r5:c0022d78 r4:c0023128
[    6.657073] [<c002a258>] (do_one_initcall+0x0/0x1d8) from
[<c0008720>] (kernel_init+0x74/0xe0)
[    6.665740]  r8:00000000 r7:00000000 r6:00000000 r5:c0022d78 r4:c0023128
[    6.672515] [<c00086ac>] (kernel_init+0x0/0xe0) from [<c005c234>]
(do_exit+0x0/0x684)
[    6.680419]  r5:00000000 r4:00000000
[    6.684020] Code: c036e993 e1a0c00d e92dd800 e24cb004 (e5903098)
[    6.690246] ---[ end trace cc13b15a4191e849 ]---
[    6.694915] Kernel panic - not syncing: Attempted to kill init!

On Thu, Mar 5, 2009 at 12:38 AM, Sakari Ailus
<sakari.ailus@maxwell.research.nokia.com> wrote:
> Hiremath, Vaibhav wrote:
>>
>> [Hiremath, Vaibhav] Sakari, Let me ask you basic question, have you
>> tested/verified these patch-sets?
>
> For the ISP and camera drivers, yes. That's actually the only thing that's
> contained in the patchset.
>
>> The reason I am asking this question is, for me it was not working. I
>> had to debug this and found that -
>>
>> - Changes missing in devices.c file, so isp_probe function will not
>> be called at all, keeping omap3isp = NULL. You will end up into
>> kernel crash in omap34xxcam_device_register.
>
> Anyway a crash shouldn't happen here. Could I see the kernel oops if there
> was such?
>
>> - The patches from Hiroshi DOYU doesn't build as is, you need to add
>> one include line #include <linux/hardirq.h> in iovmmu.c (I am using
>> the patches submitted on 16th Jan 2009)
>
> Just pull the iommu branch, the Hiroshi's original patches are missing some
> hacks that you need to use them now. I'd expect Hiroshi to update the
> patchset when he comes back.
>
>> I have attached "git diff" output here with this mail for reference.
>
> Please pull also the "base" branch.
>
> --
> Sakari Ailus
> sakari.ailus@maxwell.research.nokia.com
>



-- 
========================================================
DongSoo(Nathaniel), Kim
Engineer
Mobile S/W Platform Lab. S/W centre
Telecommunication R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
          dongsoo45.kim@samsung.com
========================================================

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

* RE: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-05  0:10     ` DongSoo(Nathaniel) Kim
@ 2009-03-05  3:53       ` Hiremath, Vaibhav
  2009-03-05  4:54           ` DongSoo(Nathaniel) Kim
                           ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Hiremath, Vaibhav @ 2009-03-05  3:53 UTC (permalink / raw)
  To: DongSoo(Nathaniel) Kim, Sakari Ailus
  Cc: linux-media, linux-omap, Aguirre Rodriguez, Sergio Alberto,
	Toivonen Tuukka Olli Artturi, Hiroshi DOYU



Thanks,
Vaibhav Hiremath

> -----Original Message-----
> From: DongSoo(Nathaniel) Kim [mailto:dongsoo.kim@gmail.com]
> Sent: Thursday, March 05, 2009 5:41 AM
> To: Sakari Ailus
> Cc: Hiremath, Vaibhav; linux-media@vger.kernel.org; linux-
> omap@vger.kernel.org; Aguirre Rodriguez, Sergio Alberto; Toivonen
> Tuukka Olli Artturi; Hiroshi DOYU
> Subject: Re: [RFC 0/9] OMAP3 ISP and camera drivers
> 
> Hi Sakari,
> 
> I'm also facing same issue with Hiremath.
> 
> Here you are my kernel stack dump.
> 
[Hiremath, Vaibhav] I was getting same kernel crash,  The reason is -

Since  isp_probe doesn't get called, leaving omap3isp = NULL. So isp_get will return -EBUSY from the very beginning of function.  And the function "omap34xxcam_device_register" which calls isp_get tries to access vdev->vfd->dev where it crashes. Which is completely wrong, since the vfd gets initialize later part of function


if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
    rval = isp_get();
    if (rval < 0) {
        dev_err(&vdev->vfd->dev, "can't get ISP, sensor init 					failed\n");
[Vaibhav] - Here it crashes.
         goto err;
     }
}

There are some instances where vdev->vfd is being accessed before initializing.

> Cheers,
> 
> Nate
> 
> [    6.465606] [<c019e194>] (dev_driver_string+0x0/0x44) from
> [<c01cc5e0>] (omap34xxcam_device_register+0x110/0x2f8)
> [    6.475952] [<c01cc4d0>] (omap34xxcam_device_register+0x0/0x2f8)
> from [<c01b91a0>] (__v4l2_int_device_try_attach_all+0xb0/0x108)
> [    6.487609]  r7:00000000 r6:c03e4fcc r5:cfbbf834 r4:c03e4f94
> [    6.493347] [<c01b90f0>]
> (__v4l2_int_device_try_attach_all+0x0/0x108) from [<c01b9258>]
> (v4l2_int_device_register+0x60/0x7c)
> [    6.504638]  r7:c03e4eec r6:cf9e5020 r5:c03e4f94 r4:c03e03f8
> [    6.510375] [<c01b91f8>] (v4l2_int_device_register+0x0/0x7c) from
> [<c00182e4>] (ce131f_probe+0x88/0xa8)
> [    6.519836]  r5:00000000 r4:cf9e5000
> [    6.523437] [<c001825c>] (ce131f_probe+0x0/0xa8) from
> [<c01cefa4>]
> (i2c_device_probe+0x78/0x90)
> [    6.532226]  r5:cf9e5000 r4:c001825c
> [    6.535827] [<c01cef2c>] (i2c_device_probe+0x0/0x90) from
> [<c01a1634>] (driver_probe_device+0xd4/0x180)
> [    6.545318]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
> [    6.551025] [<c01a1560>] (driver_probe_device+0x0/0x180) from
> [<c01a1748>] (__driver_attach+0x68/0x8c)
> [    6.560394]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
> [    6.566131] [<c01a16e0>] (__driver_attach+0x0/0x8c) from
> [<c01a0a8c>] (bus_for_each_dev+0x4c/0x84)
> [    6.575164]  r7:c03e4eec r6:c01a16e0 r5:cf821cc8 r4:00000000
> [    6.580871] [<c01a0a40>] (bus_for_each_dev+0x0/0x84) from
> [<c01a1478>] (driver_attach+0x20/0x28)
> [    6.589721]  r7:cfb121a0 r6:c0018224 r5:c03e4eec r4:00000000
> [    6.595458] [<c01a1458>] (driver_attach+0x0/0x28) from
> [<c01a1054>]
> (bus_add_driver+0xa8/0x214)
> [    6.604217] [<c01a0fac>] (bus_add_driver+0x0/0x214) from
> [<c01a196c>] (driver_register+0x98/0x120)
> [    6.613250]  r8:00000000 r7:c03ef760 r6:c0018224 r5:c03e4eec
> r4:c03e4ec0
> [    6.620025] [<c01a18d4>] (driver_register+0x0/0x120) from
> [<c01cfffc>] (i2c_register_driver+0x98/0xfc)
> [    6.629425] [<c01cff64>] (i2c_register_driver+0x0/0xfc) from
> [<c001823c>] (ce131f_isp_init+0x18/0x38)
> [    6.638702]  r7:c03ef760 r6:c0018224 r5:c0022d78 r4:c0023128
> [    6.644439] [<c0018224>] (ce131f_isp_init+0x0/0x38) from
> [<c002a2d0>] (do_one_initcall+0x78/0x1d8)
> [    6.653472]  r5:c0022d78 r4:c0023128
> [    6.657073] [<c002a258>] (do_one_initcall+0x0/0x1d8) from
> [<c0008720>] (kernel_init+0x74/0xe0)
> [    6.665740]  r8:00000000 r7:00000000 r6:00000000 r5:c0022d78
> r4:c0023128
> [    6.672515] [<c00086ac>] (kernel_init+0x0/0xe0) from [<c005c234>]
> (do_exit+0x0/0x684)
> [    6.680419]  r5:00000000 r4:00000000
> [    6.684020] Code: c036e993 e1a0c00d e92dd800 e24cb004 (e5903098)
> [    6.690246] ---[ end trace cc13b15a4191e849 ]---
> [    6.694915] Kernel panic - not syncing: Attempted to kill init!
> 
> On Thu, Mar 5, 2009 at 12:38 AM, Sakari Ailus
> <sakari.ailus@maxwell.research.nokia.com> wrote:
> > Hiremath, Vaibhav wrote:
> >>
> >> [Hiremath, Vaibhav] Sakari, Let me ask you basic question, have
> you
> >> tested/verified these patch-sets?
> >
> > For the ISP and camera drivers, yes. That's actually the only
> thing that's
> > contained in the patchset.
> >
> >> The reason I am asking this question is, for me it was not
> working. I
> >> had to debug this and found that -
> >>
> >> - Changes missing in devices.c file, so isp_probe function will
> not
> >> be called at all, keeping omap3isp = NULL. You will end up into
> >> kernel crash in omap34xxcam_device_register.
> >
> > Anyway a crash shouldn't happen here. Could I see the kernel oops
> if there
> > was such?
> >
> >> - The patches from Hiroshi DOYU doesn't build as is, you need to
> add
> >> one include line #include <linux/hardirq.h> in iovmmu.c (I am
> using
> >> the patches submitted on 16th Jan 2009)
> >
> > Just pull the iommu branch, the Hiroshi's original patches are
> missing some
> > hacks that you need to use them now. I'd expect Hiroshi to update
> the
> > patchset when he comes back.
> >
> >> I have attached "git diff" output here with this mail for
> reference.
> >
> > Please pull also the "base" branch.
> >
> > --
> > Sakari Ailus
> > sakari.ailus@maxwell.research.nokia.com
> >
> 
> 
> 
> --
> ========================================================
> DongSoo(Nathaniel), Kim
> Engineer
> Mobile S/W Platform Lab. S/W centre
> Telecommunication R&D Centre
> Samsung Electronics CO., LTD.
> e-mail : dongsoo.kim@gmail.com
>           dongsoo45.kim@samsung.com
> ========================================================


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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-05  3:53       ` Hiremath, Vaibhav
@ 2009-03-05  4:54           ` DongSoo(Nathaniel) Kim
  2009-03-05  7:30         ` Sakari Ailus
  2009-03-05 14:26         ` [PATCH] omap34xxcam: Don't use dev_err before we have a video device Sakari Ailus
  2 siblings, 0 replies; 30+ messages in thread
From: DongSoo(Nathaniel) Kim @ 2009-03-05  4:54 UTC (permalink / raw)
  To: Hiremath, Vaibhav
  Cc: Sakari Ailus, linux-media, linux-omap, Aguirre Rodriguez,
	Sergio Alberto, Toivonen Tuukka Olli Artturi, Hiroshi DOYU

Hi,

You are right. I checked with my JTAG debugger.
It crashes just exactly there because of the reason you issued.
Cheers,

Nate

On Thu, Mar 5, 2009 at 12:53 PM, Hiremath, Vaibhav <hvaibhav@ti.com> wrote:
>
>
> Thanks,
> Vaibhav Hiremath
>
>> -----Original Message-----
>> From: DongSoo(Nathaniel) Kim [mailto:dongsoo.kim@gmail.com]
>> Sent: Thursday, March 05, 2009 5:41 AM
>> To: Sakari Ailus
>> Cc: Hiremath, Vaibhav; linux-media@vger.kernel.org; linux-
>> omap@vger.kernel.org; Aguirre Rodriguez, Sergio Alberto; Toivonen
>> Tuukka Olli Artturi; Hiroshi DOYU
>> Subject: Re: [RFC 0/9] OMAP3 ISP and camera drivers
>>
>> Hi Sakari,
>>
>> I'm also facing same issue with Hiremath.
>>
>> Here you are my kernel stack dump.
>>
> [Hiremath, Vaibhav] I was getting same kernel crash,  The reason is -
>
> Since  isp_probe doesn't get called, leaving omap3isp = NULL. So isp_get will return -EBUSY from the very beginning of function.  And the function "omap34xxcam_device_register" which calls isp_get tries to access vdev->vfd->dev where it crashes. Which is completely wrong, since the vfd gets initialize later part of function
>
>
> if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
>    rval = isp_get();
>    if (rval < 0) {
>        dev_err(&vdev->vfd->dev, "can't get ISP, sensor init                                    failed\n");
> [Vaibhav] - Here it crashes.
>         goto err;
>     }
> }
>
> There are some instances where vdev->vfd is being accessed before initializing.
>
>> Cheers,
>>
>> Nate
>>
>> [    6.465606] [<c019e194>] (dev_driver_string+0x0/0x44) from
>> [<c01cc5e0>] (omap34xxcam_device_register+0x110/0x2f8)
>> [    6.475952] [<c01cc4d0>] (omap34xxcam_device_register+0x0/0x2f8)
>> from [<c01b91a0>] (__v4l2_int_device_try_attach_all+0xb0/0x108)
>> [    6.487609]  r7:00000000 r6:c03e4fcc r5:cfbbf834 r4:c03e4f94
>> [    6.493347] [<c01b90f0>]
>> (__v4l2_int_device_try_attach_all+0x0/0x108) from [<c01b9258>]
>> (v4l2_int_device_register+0x60/0x7c)
>> [    6.504638]  r7:c03e4eec r6:cf9e5020 r5:c03e4f94 r4:c03e03f8
>> [    6.510375] [<c01b91f8>] (v4l2_int_device_register+0x0/0x7c) from
>> [<c00182e4>] (ce131f_probe+0x88/0xa8)
>> [    6.519836]  r5:00000000 r4:cf9e5000
>> [    6.523437] [<c001825c>] (ce131f_probe+0x0/0xa8) from
>> [<c01cefa4>]
>> (i2c_device_probe+0x78/0x90)
>> [    6.532226]  r5:cf9e5000 r4:c001825c
>> [    6.535827] [<c01cef2c>] (i2c_device_probe+0x0/0x90) from
>> [<c01a1634>] (driver_probe_device+0xd4/0x180)
>> [    6.545318]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
>> [    6.551025] [<c01a1560>] (driver_probe_device+0x0/0x180) from
>> [<c01a1748>] (__driver_attach+0x68/0x8c)
>> [    6.560394]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
>> [    6.566131] [<c01a16e0>] (__driver_attach+0x0/0x8c) from
>> [<c01a0a8c>] (bus_for_each_dev+0x4c/0x84)
>> [    6.575164]  r7:c03e4eec r6:c01a16e0 r5:cf821cc8 r4:00000000
>> [    6.580871] [<c01a0a40>] (bus_for_each_dev+0x0/0x84) from
>> [<c01a1478>] (driver_attach+0x20/0x28)
>> [    6.589721]  r7:cfb121a0 r6:c0018224 r5:c03e4eec r4:00000000
>> [    6.595458] [<c01a1458>] (driver_attach+0x0/0x28) from
>> [<c01a1054>]
>> (bus_add_driver+0xa8/0x214)
>> [    6.604217] [<c01a0fac>] (bus_add_driver+0x0/0x214) from
>> [<c01a196c>] (driver_register+0x98/0x120)
>> [    6.613250]  r8:00000000 r7:c03ef760 r6:c0018224 r5:c03e4eec
>> r4:c03e4ec0
>> [    6.620025] [<c01a18d4>] (driver_register+0x0/0x120) from
>> [<c01cfffc>] (i2c_register_driver+0x98/0xfc)
>> [    6.629425] [<c01cff64>] (i2c_register_driver+0x0/0xfc) from
>> [<c001823c>] (ce131f_isp_init+0x18/0x38)
>> [    6.638702]  r7:c03ef760 r6:c0018224 r5:c0022d78 r4:c0023128
>> [    6.644439] [<c0018224>] (ce131f_isp_init+0x0/0x38) from
>> [<c002a2d0>] (do_one_initcall+0x78/0x1d8)
>> [    6.653472]  r5:c0022d78 r4:c0023128
>> [    6.657073] [<c002a258>] (do_one_initcall+0x0/0x1d8) from
>> [<c0008720>] (kernel_init+0x74/0xe0)
>> [    6.665740]  r8:00000000 r7:00000000 r6:00000000 r5:c0022d78
>> r4:c0023128
>> [    6.672515] [<c00086ac>] (kernel_init+0x0/0xe0) from [<c005c234>]
>> (do_exit+0x0/0x684)
>> [    6.680419]  r5:00000000 r4:00000000
>> [    6.684020] Code: c036e993 e1a0c00d e92dd800 e24cb004 (e5903098)
>> [    6.690246] ---[ end trace cc13b15a4191e849 ]---
>> [    6.694915] Kernel panic - not syncing: Attempted to kill init!
>>
>> On Thu, Mar 5, 2009 at 12:38 AM, Sakari Ailus
>> <sakari.ailus@maxwell.research.nokia.com> wrote:
>> > Hiremath, Vaibhav wrote:
>> >>
>> >> [Hiremath, Vaibhav] Sakari, Let me ask you basic question, have
>> you
>> >> tested/verified these patch-sets?
>> >
>> > For the ISP and camera drivers, yes. That's actually the only
>> thing that's
>> > contained in the patchset.
>> >
>> >> The reason I am asking this question is, for me it was not
>> working. I
>> >> had to debug this and found that -
>> >>
>> >> - Changes missing in devices.c file, so isp_probe function will
>> not
>> >> be called at all, keeping omap3isp = NULL. You will end up into
>> >> kernel crash in omap34xxcam_device_register.
>> >
>> > Anyway a crash shouldn't happen here. Could I see the kernel oops
>> if there
>> > was such?
>> >
>> >> - The patches from Hiroshi DOYU doesn't build as is, you need to
>> add
>> >> one include line #include <linux/hardirq.h> in iovmmu.c (I am
>> using
>> >> the patches submitted on 16th Jan 2009)
>> >
>> > Just pull the iommu branch, the Hiroshi's original patches are
>> missing some
>> > hacks that you need to use them now. I'd expect Hiroshi to update
>> the
>> > patchset when he comes back.
>> >
>> >> I have attached "git diff" output here with this mail for
>> reference.
>> >
>> > Please pull also the "base" branch.
>> >
>> > --
>> > Sakari Ailus
>> > sakari.ailus@maxwell.research.nokia.com
>> >
>>
>>
>>
>> --
>> ========================================================
>> DongSoo(Nathaniel), Kim
>> Engineer
>> Mobile S/W Platform Lab. S/W centre
>> Telecommunication R&D Centre
>> Samsung Electronics CO., LTD.
>> e-mail : dongsoo.kim@gmail.com
>>           dongsoo45.kim@samsung.com
>> ========================================================
>
>



-- 
========================================================
DongSoo(Nathaniel), Kim
Engineer
Mobile S/W Platform Lab. S/W Team.
DMC
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
          dongsoo45.kim@samsung.com
========================================================

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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
@ 2009-03-05  4:54           ` DongSoo(Nathaniel) Kim
  0 siblings, 0 replies; 30+ messages in thread
From: DongSoo(Nathaniel) Kim @ 2009-03-05  4:54 UTC (permalink / raw)
  To: Hiremath, Vaibhav
  Cc: Sakari Ailus, linux-media, linux-omap, Aguirre Rodriguez,
	Sergio Alberto, Toivonen Tuukka Olli Artturi, Hiroshi DOYU

Hi,

You are right. I checked with my JTAG debugger.
It crashes just exactly there because of the reason you issued.
Cheers,

Nate

On Thu, Mar 5, 2009 at 12:53 PM, Hiremath, Vaibhav <hvaibhav@ti.com> wrote:
>
>
> Thanks,
> Vaibhav Hiremath
>
>> -----Original Message-----
>> From: DongSoo(Nathaniel) Kim [mailto:dongsoo.kim@gmail.com]
>> Sent: Thursday, March 05, 2009 5:41 AM
>> To: Sakari Ailus
>> Cc: Hiremath, Vaibhav; linux-media@vger.kernel.org; linux-
>> omap@vger.kernel.org; Aguirre Rodriguez, Sergio Alberto; Toivonen
>> Tuukka Olli Artturi; Hiroshi DOYU
>> Subject: Re: [RFC 0/9] OMAP3 ISP and camera drivers
>>
>> Hi Sakari,
>>
>> I'm also facing same issue with Hiremath.
>>
>> Here you are my kernel stack dump.
>>
> [Hiremath, Vaibhav] I was getting same kernel crash,  The reason is -
>
> Since  isp_probe doesn't get called, leaving omap3isp = NULL. So isp_get will return -EBUSY from the very beginning of function.  And the function "omap34xxcam_device_register" which calls isp_get tries to access vdev->vfd->dev where it crashes. Which is completely wrong, since the vfd gets initialize later part of function
>
>
> if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
>    rval = isp_get();
>    if (rval < 0) {
>        dev_err(&vdev->vfd->dev, "can't get ISP, sensor init                                    failed\n");
> [Vaibhav] - Here it crashes.
>         goto err;
>     }
> }
>
> There are some instances where vdev->vfd is being accessed before initializing.
>
>> Cheers,
>>
>> Nate
>>
>> [    6.465606] [<c019e194>] (dev_driver_string+0x0/0x44) from
>> [<c01cc5e0>] (omap34xxcam_device_register+0x110/0x2f8)
>> [    6.475952] [<c01cc4d0>] (omap34xxcam_device_register+0x0/0x2f8)
>> from [<c01b91a0>] (__v4l2_int_device_try_attach_all+0xb0/0x108)
>> [    6.487609]  r7:00000000 r6:c03e4fcc r5:cfbbf834 r4:c03e4f94
>> [    6.493347] [<c01b90f0>]
>> (__v4l2_int_device_try_attach_all+0x0/0x108) from [<c01b9258>]
>> (v4l2_int_device_register+0x60/0x7c)
>> [    6.504638]  r7:c03e4eec r6:cf9e5020 r5:c03e4f94 r4:c03e03f8
>> [    6.510375] [<c01b91f8>] (v4l2_int_device_register+0x0/0x7c) from
>> [<c00182e4>] (ce131f_probe+0x88/0xa8)
>> [    6.519836]  r5:00000000 r4:cf9e5000
>> [    6.523437] [<c001825c>] (ce131f_probe+0x0/0xa8) from
>> [<c01cefa4>]
>> (i2c_device_probe+0x78/0x90)
>> [    6.532226]  r5:cf9e5000 r4:c001825c
>> [    6.535827] [<c01cef2c>] (i2c_device_probe+0x0/0x90) from
>> [<c01a1634>] (driver_probe_device+0xd4/0x180)
>> [    6.545318]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
>> [    6.551025] [<c01a1560>] (driver_probe_device+0x0/0x180) from
>> [<c01a1748>] (__driver_attach+0x68/0x8c)
>> [    6.560394]  r7:c03e4eec r6:c03e4eec r5:cf9e50a8 r4:cf9e5020
>> [    6.566131] [<c01a16e0>] (__driver_attach+0x0/0x8c) from
>> [<c01a0a8c>] (bus_for_each_dev+0x4c/0x84)
>> [    6.575164]  r7:c03e4eec r6:c01a16e0 r5:cf821cc8 r4:00000000
>> [    6.580871] [<c01a0a40>] (bus_for_each_dev+0x0/0x84) from
>> [<c01a1478>] (driver_attach+0x20/0x28)
>> [    6.589721]  r7:cfb121a0 r6:c0018224 r5:c03e4eec r4:00000000
>> [    6.595458] [<c01a1458>] (driver_attach+0x0/0x28) from
>> [<c01a1054>]
>> (bus_add_driver+0xa8/0x214)
>> [    6.604217] [<c01a0fac>] (bus_add_driver+0x0/0x214) from
>> [<c01a196c>] (driver_register+0x98/0x120)
>> [    6.613250]  r8:00000000 r7:c03ef760 r6:c0018224 r5:c03e4eec
>> r4:c03e4ec0
>> [    6.620025] [<c01a18d4>] (driver_register+0x0/0x120) from
>> [<c01cfffc>] (i2c_register_driver+0x98/0xfc)
>> [    6.629425] [<c01cff64>] (i2c_register_driver+0x0/0xfc) from
>> [<c001823c>] (ce131f_isp_init+0x18/0x38)
>> [    6.638702]  r7:c03ef760 r6:c0018224 r5:c0022d78 r4:c0023128
>> [    6.644439] [<c0018224>] (ce131f_isp_init+0x0/0x38) from
>> [<c002a2d0>] (do_one_initcall+0x78/0x1d8)
>> [    6.653472]  r5:c0022d78 r4:c0023128
>> [    6.657073] [<c002a258>] (do_one_initcall+0x0/0x1d8) from
>> [<c0008720>] (kernel_init+0x74/0xe0)
>> [    6.665740]  r8:00000000 r7:00000000 r6:00000000 r5:c0022d78
>> r4:c0023128
>> [    6.672515] [<c00086ac>] (kernel_init+0x0/0xe0) from [<c005c234>]
>> (do_exit+0x0/0x684)
>> [    6.680419]  r5:00000000 r4:00000000
>> [    6.684020] Code: c036e993 e1a0c00d e92dd800 e24cb004 (e5903098)
>> [    6.690246] ---[ end trace cc13b15a4191e849 ]---
>> [    6.694915] Kernel panic - not syncing: Attempted to kill init!
>>
>> On Thu, Mar 5, 2009 at 12:38 AM, Sakari Ailus
>> <sakari.ailus@maxwell.research.nokia.com> wrote:
>> > Hiremath, Vaibhav wrote:
>> >>
>> >> [Hiremath, Vaibhav] Sakari, Let me ask you basic question, have
>> you
>> >> tested/verified these patch-sets?
>> >
>> > For the ISP and camera drivers, yes. That's actually the only
>> thing that's
>> > contained in the patchset.
>> >
>> >> The reason I am asking this question is, for me it was not
>> working. I
>> >> had to debug this and found that -
>> >>
>> >> - Changes missing in devices.c file, so isp_probe function will
>> not
>> >> be called at all, keeping omap3isp = NULL. You will end up into
>> >> kernel crash in omap34xxcam_device_register.
>> >
>> > Anyway a crash shouldn't happen here. Could I see the kernel oops
>> if there
>> > was such?
>> >
>> >> - The patches from Hiroshi DOYU doesn't build as is, you need to
>> add
>> >> one include line #include <linux/hardirq.h> in iovmmu.c (I am
>> using
>> >> the patches submitted on 16th Jan 2009)
>> >
>> > Just pull the iommu branch, the Hiroshi's original patches are
>> missing some
>> > hacks that you need to use them now. I'd expect Hiroshi to update
>> the
>> > patchset when he comes back.
>> >
>> >> I have attached "git diff" output here with this mail for
>> reference.
>> >
>> > Please pull also the "base" branch.
>> >
>> > --
>> > Sakari Ailus
>> > sakari.ailus@maxwell.research.nokia.com
>> >
>>
>>
>>
>> --
>> ========================================================
>> DongSoo(Nathaniel), Kim
>> Engineer
>> Mobile S/W Platform Lab. S/W centre
>> Telecommunication R&D Centre
>> Samsung Electronics CO., LTD.
>> e-mail : dongsoo.kim@gmail.com
>>           dongsoo45.kim@samsung.com
>> ========================================================
>
>



-- 
========================================================
DongSoo(Nathaniel), Kim
Engineer
Mobile S/W Platform Lab. S/W Team.
DMC
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
          dongsoo45.kim@samsung.com
========================================================
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-03 10:06 [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
@ 2009-03-05  5:00   ` DongSoo(Nathaniel) Kim
  2009-03-03 13:09 ` [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 30+ messages in thread
From: DongSoo(Nathaniel) Kim @ 2009-03-05  5:00 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, Aguirre Rodriguez, Sergio Alberto,
	Toivonen Tuukka Olli Artturi, Hiroshi DOYU

Hi Sakari,

Reviewing your driver, I couldn't find JPEG sync mode or where to make
programme ISP_CTRL with ISPCTRL_JPEG_FLUSH.
Is JPEG sync mode is not the coverage of this version? or I'm missing something.
If JPEG sync mode is not considered yet please let me know.
Cheers,

Nate

On Tue, Mar 3, 2009 at 7:06 PM, Sakari Ailus
<sakari.ailus@maxwell.research.nokia.com> wrote:
> Hi,
>
> So here's the patchset for OMAP 3 ISP and camera drivers plus the
> associated V4L changes. Sergio Aguirre has been posting a related
> patchset earlier, containing also sensor and lens driver used on SDP. This
> patchset is agains the linux-omap tree:
>
> <URL:http://www.muru.com/linux/omap/README_OMAP_GIT>
>
> So I and Sergio have synchronised our versions of the ISP and camera
> drivers and this is the end result. There is still a lot of work to do,
> though. You can find some comments in individual patch descriptions. If the
> todo list for a patch is empty it doesn't mean there wouldn't be anything
> left to do. ;)
>
> There's at least one major change to Sergio Aguirre's earlier patches which
> is that the ISP driver now uses the IOMMU from Hiroshi Doyu. Hiroshi is away
> for some time now so there are just some hacks on top of Hiroshi's older
> iommu patches to use with current linux-omap.
>
> This patchset does not contain the resizer or preview wrappers from TI but
> they have been left intentionally out. A proper interface (V4L) should be
> used for those and the camera driver should be somehow involved --- the
> wrappers are just duplicating much of the camera driver's functionality.
>
> I don't have any sensor or lens drivers to publish at this time.
>
> This patchset should work with the SDP and OMAPZoom boards although you
> need the associated sensor drivers + the board code from Sergio Aguirre to
> use it. You'll also need the IOMMU patchset from Hiroshi Doyu. Everything
> except the sensor / board stuff is available here:
>
> <URL:http://www.gitorious.org/projects/omap3camera>
>
> In short, on linux-omap:
>
> $ git pull http://git.gitorious.org/omap3camera/mainline.git v4l \
>  iommu omap3camera base
>
> Hiroshi's original iommu tree is here (branch iommu):
>
> <URL:http://git.gitorious.org/lk/mainline.git>
>
> Some of the camera and ISP driver development history is available, too. See
> the first link.
>
> Any feedback is appreciated.
>
> Sincerely,
>
> --
> Sakari Ailus
> sakari.ailus@maxwell.research.nokia.com
>
>



-- 
========================================================
DongSoo(Nathaniel), Kim
Engineer
Mobile S/W Platform Lab. S/W Team.
DMC
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
          dongsoo45.kim@samsung.com
========================================================

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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
@ 2009-03-05  5:00   ` DongSoo(Nathaniel) Kim
  0 siblings, 0 replies; 30+ messages in thread
From: DongSoo(Nathaniel) Kim @ 2009-03-05  5:00 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, Aguirre Rodriguez, Sergio Alberto,
	Toivonen Tuukka Olli Artturi, Hiroshi DOYU

Hi Sakari,

Reviewing your driver, I couldn't find JPEG sync mode or where to make
programme ISP_CTRL with ISPCTRL_JPEG_FLUSH.
Is JPEG sync mode is not the coverage of this version? or I'm missing something.
If JPEG sync mode is not considered yet please let me know.
Cheers,

Nate

On Tue, Mar 3, 2009 at 7:06 PM, Sakari Ailus
<sakari.ailus@maxwell.research.nokia.com> wrote:
> Hi,
>
> So here's the patchset for OMAP 3 ISP and camera drivers plus the
> associated V4L changes. Sergio Aguirre has been posting a related
> patchset earlier, containing also sensor and lens driver used on SDP. This
> patchset is agains the linux-omap tree:
>
> <URL:http://www.muru.com/linux/omap/README_OMAP_GIT>
>
> So I and Sergio have synchronised our versions of the ISP and camera
> drivers and this is the end result. There is still a lot of work to do,
> though. You can find some comments in individual patch descriptions. If the
> todo list for a patch is empty it doesn't mean there wouldn't be anything
> left to do. ;)
>
> There's at least one major change to Sergio Aguirre's earlier patches which
> is that the ISP driver now uses the IOMMU from Hiroshi Doyu. Hiroshi is away
> for some time now so there are just some hacks on top of Hiroshi's older
> iommu patches to use with current linux-omap.
>
> This patchset does not contain the resizer or preview wrappers from TI but
> they have been left intentionally out. A proper interface (V4L) should be
> used for those and the camera driver should be somehow involved --- the
> wrappers are just duplicating much of the camera driver's functionality.
>
> I don't have any sensor or lens drivers to publish at this time.
>
> This patchset should work with the SDP and OMAPZoom boards although you
> need the associated sensor drivers + the board code from Sergio Aguirre to
> use it. You'll also need the IOMMU patchset from Hiroshi Doyu. Everything
> except the sensor / board stuff is available here:
>
> <URL:http://www.gitorious.org/projects/omap3camera>
>
> In short, on linux-omap:
>
> $ git pull http://git.gitorious.org/omap3camera/mainline.git v4l \
>  iommu omap3camera base
>
> Hiroshi's original iommu tree is here (branch iommu):
>
> <URL:http://git.gitorious.org/lk/mainline.git>
>
> Some of the camera and ISP driver development history is available, too. See
> the first link.
>
> Any feedback is appreciated.
>
> Sincerely,
>
> --
> Sakari Ailus
> sakari.ailus@maxwell.research.nokia.com
>
>



-- 
========================================================
DongSoo(Nathaniel), Kim
Engineer
Mobile S/W Platform Lab. S/W Team.
DMC
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
          dongsoo45.kim@samsung.com
========================================================
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC 0/9] OMAP3 ISP and camera drivers
  2009-03-05  3:53       ` Hiremath, Vaibhav
  2009-03-05  4:54           ` DongSoo(Nathaniel) Kim
@ 2009-03-05  7:30         ` Sakari Ailus
  2009-03-05 14:26         ` [PATCH] omap34xxcam: Don't use dev_err before we have a video device Sakari Ailus
  2 siblings, 0 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-05  7:30 UTC (permalink / raw)
  To: Hiremath, Vaibhav
  Cc: DongSoo(Nathaniel) Kim, linux-media, linux-omap,
	Aguirre Rodriguez, Sergio Alberto, Toivonen Tuukka Olli Artturi,
	Hiroshi DOYU

Hiremath, Vaibhav wrote:
> 
> Thanks,
> Vaibhav Hiremath
> 
>> -----Original Message-----
>> From: DongSoo(Nathaniel) Kim [mailto:dongsoo.kim@gmail.com]
>> Sent: Thursday, March 05, 2009 5:41 AM
>> To: Sakari Ailus
>> Cc: Hiremath, Vaibhav; linux-media@vger.kernel.org; linux-
>> omap@vger.kernel.org; Aguirre Rodriguez, Sergio Alberto; Toivonen
>> Tuukka Olli Artturi; Hiroshi DOYU
>> Subject: Re: [RFC 0/9] OMAP3 ISP and camera drivers
>>
>> Hi Sakari,
>>
>> I'm also facing same issue with Hiremath.
>>
>> Here you are my kernel stack dump.
>>
> [Hiremath, Vaibhav] I was getting same kernel crash,  The reason is -
> 
> Since  isp_probe doesn't get called, leaving omap3isp = NULL. So isp_get will return -EBUSY from the very beginning of function.  And the function "omap34xxcam_device_register" which calls isp_get tries to access vdev->vfd->dev where it crashes. Which is completely wrong, since the vfd gets initialize later part of function
> 
> 
> if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
>     rval = isp_get();
>     if (rval < 0) {
>         dev_err(&vdev->vfd->dev, "can't get ISP, sensor init 					failed\n");
> [Vaibhav] - Here it crashes.
>          goto err;
>      }
> }
> 
> There are some instances where vdev->vfd is being accessed before initializing.

Ooops.

Some parts of those dev_* were just mechanically changed from something 
else. And I think Alexey Klimov already notified me about that problem. 
I'm surprised that it was hit it so soon. ;)

Just removing the dev_err helps to resolve the crash, I guess. You could 
use late_initcall instead of module_init in the sensor, but that's just 
a hack, too.

If you are using modules, please load iommu2 and omap3-iommu before isp-mod.

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [PATCH 1/9] omap3isp: Add ISP main driver and register definitions
  2009-03-03 11:56   ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Alexey Klimov
@ 2009-03-05 11:34     ` Sakari Ailus
  2009-03-07 15:25       ` Alexey Klimov
  0 siblings, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-05 11:34 UTC (permalink / raw)
  To: Alexey Klimov
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Thanks for the comments, Alexey!

Alexey Klimov wrote:
>> +static int isp_probe(struct platform_device *pdev)
>> +{
>> +	struct isp_device *isp;
>> +	int ret_err = 0;
>> +	int i;
>> +
>> +	isp = kzalloc(sizeof(*isp), GFP_KERNEL);
>> +	if (!isp) {
>> +		dev_err(&pdev->dev, "could not allocate memory\n");
>> +		return -ENODEV;
> 
> return -ENOMEM; ?

Done.

>> +	}
>> +
>> +	platform_set_drvdata(pdev, isp);
>> +
>> +	isp->dev = &pdev->dev;
>> +
>> +	for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
>> +		struct resource *mem;
>> +		/* request the mem region for the camera registers */
>> +		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
>> +		if (!mem) {
>> +			dev_err(isp->dev, "no mem resource?\n");
>> +			return -ENODEV;
> 
> Maybe ENODEV is not apropriate here too..

What else it could be? ENOENT comes to mind but I'm not sure it's 
significantly better.

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [PATCH 9/9] omap34xxcam: Add camera driver
  2009-03-03 17:31                   ` Alexey Klimov
@ 2009-03-05 14:09                     ` Sakari Ailus
  2009-03-07 14:38                       ` Alexey Klimov
  0 siblings, 1 reply; 30+ messages in thread
From: Sakari Ailus @ 2009-03-05 14:09 UTC (permalink / raw)
  To: Alexey Klimov
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Alexey Klimov wrote:
>> +static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
>> +				struct v4l2_format *f)
>> +{
>> +	struct omap34xxcam_fh *ofh = fh;
>> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
>> +
>> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&vdev->mutex);
>> +	f->fmt.pix = vdev->pix;
>> +	mutex_unlock(&vdev->mutex);
> 
> Hmmmm, you are using mutex_lock to lock reading from vdev structure..
> Well, i don't if this is right approach. I am used to that mutex_lock is
> used to prevent _changing_ of members in structure..

The vdev->mutex is acquired since we want to prevent concurrent access 
to vdev->pix. Otherwise it might change while we are reading it, right?

>> +static int vidioc_s_fmt_vid_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_tmp;
>> +	struct v4l2_fract timeperframe;
>> +	int rval;
>> +
>> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&vdev->mutex);
>> +	if (vdev->streaming) {
>> +		rval = -EBUSY;
>> +		goto out;
>> +	}
> 
> Well, why don't remove goto, place return -EBUSY, and move mutex after
> if (vdev->streaming) check ?

The streaming state may change in the meantime. See vidioc_streamon. 
It's not very likely but possible as far as I understand.

>> +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;
>> +
>> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&vdev->mutex);
>> +	if (vdev->streaming) {
>> +		mutex_unlock(&vdev->mutex);
>> +		return -EBUSY;
>> +	}
> 
> If i'm doing this i prefer to place mutex_lock after this
> if(vdev->streaming) check.

Same here.

>> +static int omap34xxcam_device_register(struct v4l2_int_device *s)
>> +{
>> +	struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
>> +	struct omap34xxcam_hw_config hwc;
>> +	int rval;
>> +
>> +	/* We need to check rval just once. The place is here. */
> 
> I didn't understand this comment. You doing nothin in next few lines
> with int variable rval(which introduced in this function). Is comment
> talking about struct v4l2_int_device *s ?

Yes. If the g_priv() succeeds now it will succeed in future, too. This 
comes from the platform data through the slave device.

>> +	/* Are we the first slave? */
>> +	if (vdev->slaves == 1) {
>> +		/* initialize the video_device struct */
>> +		vdev->vfd = video_device_alloc();
>> +		if (!vdev->vfd) {
>> +			dev_err(&vdev->vfd->dev,
>> +				"could not allocate video device struct\n");
> 
> Do i understand you code in right way ?
> You call video_device_alloc() to get vdev->vfd. Then if vdev->vfd is
> null(empty) you make message dev_err which based on vdev->vfd->dev but
> dev->vfd allocating is failed.. If i'm not wrong you message will
> provide kernel oops.
> One more point here is that you use dev_err(&vdev->vfd->dev before call
> to video_device_alloc() in this function.

Indeed. Others hit this already. Thanks.

>> +static int __init omap34xxcam_init(void)
>> +{
>> +	struct omap34xxcam_device *cam;
>> +	int i;
>> +
>> +	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
>> +	if (!cam) {
>> +		printk(KERN_ERR "%s: could not allocate memory\n", __func__);
>> +		goto err;
> 
> If kzalloc failed you return -ENODEV; but this is ENOMEM error.

Yes. Will fix.

Thanks again for the comments.

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* [PATCH] omap34xxcam: Don't use dev_err before we have a video device
  2009-03-05  3:53       ` Hiremath, Vaibhav
  2009-03-05  4:54           ` DongSoo(Nathaniel) Kim
  2009-03-05  7:30         ` Sakari Ailus
@ 2009-03-05 14:26         ` Sakari Ailus
  2 siblings, 0 replies; 30+ messages in thread
From: Sakari Ailus @ 2009-03-05 14:26 UTC (permalink / raw)
  To: dongsoo.kim, hvaibhav; +Cc: linux-media, saaguirre

Also return -ENOMEM instead of -ENODEV if kzalloc fails.

Thanks to Alexey Klimov <klimov.linux@gmail.com> for noticing this.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/omap34xxcam.c |   18 +++++++++---------
 1 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/media/video/omap34xxcam.c b/drivers/media/video/omap34xxcam.c
index 586718a..8398819 100644
--- a/drivers/media/video/omap34xxcam.c
+++ b/drivers/media/video/omap34xxcam.c
@@ -1793,8 +1793,8 @@ static int omap34xxcam_device_register(struct v4l2_int_device *s)
 
 	mutex_lock(&vdev->mutex);
 	if (atomic_read(&vdev->users)) {
-		dev_err(&vdev->vfd->dev, "we're open (%d), can't register\n",
-			atomic_read(&vdev->users));
+		printk(KERN_ERR "%s: we're open (%d), can't register\n",
+		       __func__, atomic_read(&vdev->users));
 		mutex_unlock(&vdev->mutex);
 		return -EBUSY;
 	}
@@ -1806,8 +1806,8 @@ static int omap34xxcam_device_register(struct v4l2_int_device *s)
 	if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
 		rval = isp_get();
 		if (rval < 0) {
-			dev_err(&vdev->vfd->dev,
-				"can't get ISP, sensor init failed\n");
+			printk(KERN_ERR "%s: can't get ISP, "
+			       "sensor init failed\n", __func__);
 			goto err;
 		}
 	}
@@ -1837,8 +1837,8 @@ static int omap34xxcam_device_register(struct v4l2_int_device *s)
 		/* initialize the video_device struct */
 		vdev->vfd = video_device_alloc();
 		if (!vdev->vfd) {
-			dev_err(&vdev->vfd->dev,
-				"could not allocate video device struct\n");
+			printk(KERN_ERR "%s: could not allocate "
+			       "video device struct\n", __func__);
 			return -ENOMEM;
 		}
 		vdev->vfd->release	= video_device_release;
@@ -1849,8 +1849,8 @@ static int omap34xxcam_device_register(struct v4l2_int_device *s)
 
 		if (video_register_device(vdev->vfd, VFL_TYPE_GRABBER,
 					  hwc.dev_minor) < 0) {
-			dev_err(&vdev->vfd->dev,
-				"could not register V4L device\n");
+			printk(KERN_ERR "%s: could not register V4L device\n",
+				__func__);
 			vdev->vfd->minor = -1;
 			rval = -EBUSY;
 			goto err;
@@ -1919,7 +1919,7 @@ static int __init omap34xxcam_init(void)
 	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
 	if (!cam) {
 		printk(KERN_ERR "%s: could not allocate memory\n", __func__);
-		goto err;
+		return -ENOMEM;
 	}
 
 	omap34xxcam = cam;
-- 
1.5.6.5


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

* Re: [PATCH 3/9] omap3isp: Add userspace header
  2009-03-03 10:06     ` [PATCH 3/9] omap3isp: Add userspace header Sakari Ailus
  2009-03-03 10:06       ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Sakari Ailus
@ 2009-03-06 12:51       ` Hans Verkuil
  1 sibling, 0 replies; 30+ messages in thread
From: Hans Verkuil @ 2009-03-06 12:51 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

On Tuesday 03 March 2009 11:06:50 Sakari Ailus wrote:
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> ---
>  arch/arm/plat-omap/include/mach/isp_user.h |  676 ++++++++++++++++++++++++++++
>  1 files changed, 676 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/plat-omap/include/mach/isp_user.h

Hi Sakari,

First a general note:

I suggest adding 'reserved' fields at the end of these structures. It gives
you an opportunity to add extra fields in the future without breaking the
API. Both apps and drivers should set these to 0.

More notes below:

> diff --git a/arch/arm/plat-omap/include/mach/isp_user.h b/arch/arm/plat-omap/include/mach/isp_user.h
> new file mode 100644
> index 0000000..b819e26
> --- /dev/null
> +++ b/arch/arm/plat-omap/include/mach/isp_user.h
> @@ -0,0 +1,676 @@
> +/*
> + * isp_user.h
> + *
> + * Include file for OMAP ISP module in TI's OMAP3.
> + *
> + * Copyright (C) 2009 Texas Instruments, Inc.
> + *
> + * Contributors:
> + *	Mohit Jalori <mjalori@ti.com>
> + *	Sergio Aguirre <saaguirre@ti.com>
> + *
> + * 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_USER_H
> +#define OMAP_ISP_USER_H
> +
> +/* 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 \
> +	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct af_configuration)
> +#define VIDIOC_PRIVATE_ISP_AF_REQ \
> +	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct isp_af_data)
> +
> +/* AE/AWB related structures and flags*/
> +
> +/* Flags for update field */
> +#define REQUEST_STATISTICS	(1 << 0)
> +#define SET_COLOR_GAINS		(1 << 1)
> +#define SET_DIGITAL_GAIN	(1 << 2)
> +#define SET_EXPOSURE		(1 << 3)
> +#define SET_ANALOG_GAIN		(1 << 4)
> +
> +#define MAX_FRAME_COUNT		0x0FFF
> +#define MAX_FUTURE_FRAMES	10
> +
> +#define MAX_SATURATION_LIM	1023
> +#define MIN_WIN_H		2
> +#define MAX_WIN_H		256
> +#define MIN_WIN_W		6
> +#define MAX_WIN_W		256
> +#define MAX_WINVC		128
> +#define MAX_WINHC		36
> +#define MAX_WINSTART		4095
> +#define MIN_SUB_INC		2
> +#define MAX_SUB_INC		32
> +
> +/* Range Constants */
> +#define AF_IIRSH_MIN			0
> +#define AF_IIRSH_MAX			4094
> +#define AF_PAXEL_HORIZONTAL_COUNT_MIN	0
> +#define AF_PAXEL_HORIZONTAL_COUNT_MAX	35
> +#define AF_PAXEL_VERTICAL_COUNT_MIN	0
> +#define AF_PAXEL_VERTICAL_COUNT_MAX	127
> +#define AF_PAXEL_INCREMENT_MIN		0
> +#define AF_PAXEL_INCREMENT_MAX		14
> +#define AF_PAXEL_HEIGHT_MIN		0
> +#define AF_PAXEL_HEIGHT_MAX		127
> +#define AF_PAXEL_WIDTH_MIN		0
> +#define AF_PAXEL_WIDTH_MAX		127
> +#define AF_PAXEL_HZSTART_MIN		2
> +#define AF_PAXEL_HZSTART_MAX		4094
> +
> +#define AF_PAXEL_VTSTART_MIN		0
> +#define AF_PAXEL_VTSTART_MAX		4095
> +#define AF_THRESHOLD_MAX		255
> +#define AF_COEF_MAX			4095
> +#define AF_PAXEL_SIZE			48
> +
> +/**
> + * struct isph3a_aewb_config - AE AWB configuration reset values.
> + * saturation_limit: Saturation limit.
> + * @win_height: Window Height. Range 2 - 256, even values only.
> + * @win_width: Window Width. Range 6 - 256, even values only.
> + * @ver_win_count: Vertical Window Count. Range 1 - 128.
> + * @hor_win_count: Horizontal Window Count. Range 1 - 36.
> + * @ver_win_start: Vertical Window Start. Range 0 - 4095.
> + * @hor_win_start: Horizontal Window Start. Range 0 - 4095.
> + * @blk_ver_win_start: Black Vertical Windows Start. Range 0 - 4095.
> + * @blk_win_height: Black Window Height. Range 2 - 256, even values only.
> + * @subsample_ver_inc: Subsample Vertical points increment Range 2 - 32, even
> + *                     values only.
> + * @subsample_hor_inc: Subsample Horizontal points increment Range 2 - 32, even
> + *                     values only.
> + * @alaw_enable: AEW ALAW EN flag.
> + * @aewb_enable: AE AWB stats generation EN flag.
> + */
> +struct isph3a_aewb_config {
> +	__u16 saturation_limit;
> +	__u16 win_height;
> +	__u16 win_width;
> +	__u16 ver_win_count;
> +	__u16 hor_win_count;
> +	__u16 ver_win_start;
> +	__u16 hor_win_start;
> +	__u16 blk_ver_win_start;
> +	__u16 blk_win_height;
> +	__u16 subsample_ver_inc;
> +	__u16 subsample_hor_inc;
> +	__u8 alaw_enable;
> +	__u8 aewb_enable;
> +};
> +
> +/**
> + * struct isph3a_aewb_data - Structure of data sent to or received from user
> + * @h3a_aewb_statistics_buf: Pointer to pass to user.

How does the user know how much memory to allocate here? Can this also
be NULL?

Please document.

> + * @shutter: Shutter speed.
> + * @gain: Sensor analog Gain.
> + * @shutter_cap: Shutter speed for capture.
> + * @gain_cap: Sensor Gain for capture.
> + * @dgain: White balance digital gain.
> + * @wb_gain_b: White balance color gain blue.
> + * @wb_gain_r: White balance color gain red.
> + * @wb_gain_gb: White balance color gain green blue.
> + * @wb_gain_gr: White balance color gain green red.
> + * @frame_number: Frame number of requested stats.
> + * @curr_frame: Current frame number being processed.
> + * @update: Bitwise flags to update parameters.
> + * @ts: Timestamp of returned framestats.
> + * @field_count: Sequence number of returned framestats.
> + */
> +struct isph3a_aewb_data {
> +	void *h3a_aewb_statistics_buf;
> +	__u32 shutter;
> +	__u16 gain;
> +	__u32 shutter_cap;
> +	__u16 gain_cap;
> +	__u16 dgain;
> +	__u16 wb_gain_b;
> +	__u16 wb_gain_r;
> +	__u16 wb_gain_gb;
> +	__u16 wb_gain_gr;
> +	__u16 frame_number;
> +	__u16 curr_frame;
> +	__u8 update;
> +	struct timeval ts;
> +	__u32 config_counter;
> +	unsigned long field_count;
> +};
> +
> +
> +/* Histogram related structs */
> +/* Flags for number of bins */
> +#define BINS_32			0x0
> +#define BINS_64			0x1
> +#define BINS_128		0x2
> +#define BINS_256		0x3
> +
> +struct isp_hist_config {
> +	__u8 hist_source;		/* CCDC or Memory */
> +	__u8 input_bit_width;	/* Needed o know the size per pixel */
> +	__u8 hist_frames;		/* Num of frames to be processed and
> +				 * accumulated
> +				 */
> +	__u8 hist_h_v_info;	/* frame-input width and height if source is
> +				 * memory
> +				 */
> +	__u16 hist_radd;		/* frame-input address in memory */
> +	__u16 hist_radd_off;	/* line-offset for frame-input */
> +	__u16 hist_bins;	/* number of bins: 32, 64, 128, or 256 */
> +	__u16 wb_gain_R;	/* White Balance Field-to-Pattern Assignments */
> +	__u16 wb_gain_RG;	/* White Balance Field-to-Pattern Assignments */
> +	__u16 wb_gain_B;	/* White Balance Field-to-Pattern Assignments */
> +	__u16 wb_gain_BG;	/* White Balance Field-to-Pattern Assignments */
> +	__u8 num_regions;		/* number of regions to be configured */
> +	__u16 reg0_hor;		/* Region 0 size and position */
> +	__u16 reg0_ver;		/* Region 0 size and position */
> +	__u16 reg1_hor;		/* Region 1 size and position */
> +	__u16 reg1_ver;		/* Region 1 size and position */
> +	__u16 reg2_hor;		/* Region 2 size and position */
> +	__u16 reg2_ver;		/* Region 2 size and position */
> +	__u16 reg3_hor;		/* Region 3 size and position */
> +	__u16 reg3_ver;		/* Region 3 size and position */
> +};
> +
> +struct isp_hist_data {
> +	__u32 *hist_statistics_buf;	/* Pointer to pass to user */

Same question as above.

If there is a known fixed upper bound to the statistics buffer, then
you can also consider making this an array.

> +};
> +
> +/* Auto Focus related structs */
> +
> +#define AF_NUMBER_OF_COEF		11
> +
> +/* Flags for update field */
> +#define REQUEST_STATISTICS		(1 << 0)
> +#define LENS_DESIRED_POSITION	(1 << 1)
> +#define LENS_CURRENT_POSITION	(1 << 2)
> +
> +/**
> + * struct isp_af_xtrastats - Extra statistics related to AF generated stats.
> + * @ts: Timestamp when the frame gets delivered to the user.
> + * @field_count: Field count of the frame delivered to the user.
> + * @lens_position: Lens position when the stats are being generated.
> + */
> +struct isp_af_xtrastats {
> +	struct timeval ts;
> +	unsigned long field_count;
> +	__u16 lens_position; /* deprecated */
> +};
> +
> +/**
> + * struct isp_af_data - AF statistics data to transfer between driver and user.
> + * @af_statistics_buf: Pointer to pass to user.
> + * @lens_current_position: Read value of lens absolute position.
> + * @desired_lens_direction: Lens desired location.
> + * @update: Bitwise flags to update parameters.
> + * @frame_number: Data for which frame is desired/given.
> + * @curr_frame: Current frame number being processed by AF module.
> + * @xtrastats: Extra statistics structure.
> + */
> +struct isp_af_data {
> +	void *af_statistics_buf;
> +	__u16 lens_current_position; /* deprecated */
> +	__u16 desired_lens_direction; /* deprecated */
> +	__u16 update;
> +	__u16 frame_number;
> +	__u16 curr_frame;
> +	__u32 config_counter;
> +	struct isp_af_xtrastats xtrastats;
> +};
> +
> +/* enum used for status of specific feature */
> +enum af_alaw_enable {
> +	H3A_AF_ALAW_DISABLE = 0,
> +	H3A_AF_ALAW_ENABLE = 1
> +};
> +
> +enum af_hmf_enable {
> +	H3A_AF_HMF_DISABLE = 0,
> +	H3A_AF_HMF_ENABLE = 1
> +};
> +
> +enum af_config_flag {
> +	H3A_AF_CFG_DISABLE = 0,
> +	H3A_AF_CFG_ENABLE = 1
> +};
> +
> +enum af_mode {
> +	ACCUMULATOR_SUMMED = 0,
> +	ACCUMULATOR_PEAK = 1
> +};
> +
> +/* Red, Green, and blue pixel location in the AF windows */
> +enum rgbpos {
> +	GR_GB_BAYER = 0,	/* GR and GB as Bayer pattern */
> +	RG_GB_BAYER = 1,	/* RG and GB as Bayer pattern */
> +	GR_BG_BAYER = 2,	/* GR and BG as Bayer pattern */
> +	RG_BG_BAYER = 3,	/* RG and BG as Bayer pattern */
> +	GG_RB_CUSTOM = 4,	/* GG and RB as custom pattern */
> +	RB_GG_CUSTOM = 5	/* RB and GG as custom pattern */
> +};
> +
> +/* Contains the information regarding the Horizontal Median Filter */
> +struct af_hmf {
> +	enum af_hmf_enable enable;	/* Status of Horizontal Median Filter */
> +	unsigned int threshold;	/* Threshhold Value for Horizontal Median
> +				 * Filter
> +				 */
> +};
> +
> +/* Contains the information regarding the IIR Filters */
> +struct af_iir {
> +	unsigned int hz_start_pos;	/* IIR Start Register Value */
> +	int coeff_set0[AF_NUMBER_OF_COEF];	/*
> +						 * IIR Filter Coefficient for
> +						 * Set 0
> +						 */
> +	int coeff_set1[AF_NUMBER_OF_COEF];	/*
> +						 * IIR Filter Coefficient for
> +						 * Set 1
> +						 */
> +};
> +
> +/* Contains the information regarding the Paxels Structure in AF Engine */
> +struct af_paxel {
> +	unsigned int width;	/* Width of the Paxel */
> +	unsigned int height;	/* Height of the Paxel */
> +	unsigned int hz_start;	/* Horizontal Start Position */
> +	unsigned int vt_start;	/* Vertical Start Position */
> +	unsigned int hz_cnt;	/* Horizontal Count */
> +	unsigned int vt_cnt;	/* vertical Count */
> +	unsigned int line_incr;	/* Line Increment */
> +};
> +/* Contains the parameters required for hardware set up of AF Engine */
> +struct af_configuration {
> +	enum af_alaw_enable alaw_enable;	/*ALWAW status */
> +	struct af_hmf hmf_config;	/*HMF configurations */
> +	enum rgbpos rgb_pos;		/*RGB Positions */
> +	struct af_iir iir_config;	/*IIR filter configurations */
> +	struct af_paxel paxel_config;	/*Paxel parameters */
> +	enum af_mode mode;		/*Accumulator mode */
> +	enum af_config_flag af_config; /*Flag indicates Engine is configured */
> +};
> +
> +/* ISP CCDC structs */
> +
> +/* Abstraction layer CCDC configurations */
> +#define ISP_ABS_CCDC_ALAW		(1 << 0)
> +#define ISP_ABS_CCDC_LPF 		(1 << 1)
> +#define ISP_ABS_CCDC_BLCLAMP		(1 << 2)
> +#define ISP_ABS_CCDC_BCOMP		(1 << 3)
> +#define ISP_ABS_CCDC_FPC		(1 << 4)
> +#define ISP_ABS_CCDC_CULL		(1 << 5)
> +#define ISP_ABS_CCDC_COLPTN		(1 << 6)
> +#define ISP_ABS_CCDC_CONFIG_LSC		(1 << 7)
> +#define ISP_ABS_TBL_LSC			(1 << 8)
> +
> +#define RGB_MAX				3
> +
> +/* Enumeration constants for Alaw input width */
> +enum alaw_ipwidth {
> +	ALAW_BIT12_3 = 0x3,
> +	ALAW_BIT11_2 = 0x4,
> +	ALAW_BIT10_1 = 0x5,
> +	ALAW_BIT9_0 = 0x6
> +};
> +
> +/* Enumeration constants for Video Port */
> +enum vpin {
> +	BIT12_3 = 3,
> +	BIT11_2 = 4,
> +	BIT10_1 = 5,
> +	BIT9_0 = 6
> +};
> +
> +enum vpif_freq {
> +	PIXCLKBY2,
> +	PIXCLKBY3_5,
> +	PIXCLKBY4_5,
> +	PIXCLKBY5_5,
> +	PIXCLKBY6_5
> +};
> +
> +/**
> + * struct ispccdc_lsc_config - Structure for LSC configuration.
> + * @offset: Table Offset of the gain table.
> + * @gain_mode_n: Vertical dimension of a paxel in LSC configuration.
> + * @gain_mode_m: Horizontal dimension of a paxel in LSC configuration.
> + * @gain_format: Gain table format.
> + * @fmtsph: Start pixel horizontal from start of the HS sync pulse.
> + * @fmtlnh: Number of pixels in horizontal direction to use for the data
> + *          reformatter.
> + * @fmtslv: Start line from start of VS sync pulse for the data reformatter.
> + * @fmtlnv: Number of lines in vertical direction for the data reformatter.
> + * @initial_x: X position, in pixels, of the first active pixel in reference
> + *             to the first active paxel. Must be an even number.
> + * @initial_y: Y position, in pixels, of the first active pixel in reference
> + *             to the first active paxel. Must be an even number.
> + * @size: Size of LSC gain table. Filled when loaded from userspace.
> + */
> +struct ispccdc_lsc_config {
> +	__u16 offset;
> +	__u8 gain_mode_n;
> +	__u8 gain_mode_m;
> +	__u8 gain_format;
> +	__u16 fmtsph;
> +	__u16 fmtlnh;
> +	__u16 fmtslv;
> +	__u16 fmtlnv;
> +	__u8 initial_x;
> +	__u8 initial_y;
> +	__u32 size;
> +};
> +
> +/**
> + * struct ispccdc_bclamp - Structure for Optical & Digital black clamp subtract
> + * @obgain: Optical black average gain.
> + * @obstpixel: Start Pixel w.r.t. HS pulse in Optical black sample.
> + * @oblines: Optical Black Sample lines.
> + * @oblen: Optical Black Sample Length.
> + * @dcsubval: Digital Black Clamp subtract value.
> + */
> +struct ispccdc_bclamp {
> +	__u8 obgain;
> +	__u8 obstpixel;
> +	__u8 oblines;
> +	__u8 oblen;
> +	__u16 dcsubval;
> +};
> +
> +/**
> + * ispccdc_fpc - Structure for FPC
> + * @fpnum: Number of faulty pixels to be corrected in the frame.
> + * @fpcaddr: Memory address of the FPC Table
> + */
> +struct ispccdc_fpc {
> +	__u16 fpnum;
> +	__u32 fpcaddr;
> +};
> +
> +/**
> + * ispccdc_blcomp - Structure for Black Level Compensation parameters.
> + * @b_mg: B/Mg pixels. 2's complement. -128 to +127.
> + * @gb_g: Gb/G pixels. 2's complement. -128 to +127.
> + * @gr_cy: Gr/Cy pixels. 2's complement. -128 to +127.
> + * @r_ye: R/Ye pixels. 2's complement. -128 to +127.
> + */
> +struct ispccdc_blcomp {
> +	__u8 b_mg;
> +	__u8 gb_g;
> +	__u8 gr_cy;
> +	__u8 r_ye;
> +};
> +
> +/**
> + * struct ispccdc_vp - Structure for Video Port parameters
> + * @bitshift_sel: Video port input select. 3 - bits 12-3, 4 - bits 11-2,
> + *                5 - bits 10-1, 6 - bits 9-0.
> + * @freq_sel: Video port data ready frequency. 1 - 1/3.5, 2 - 1/4.5,
> + *            3 - 1/5.5, 4 - 1/6.5.
> + */
> +struct ispccdc_vp {
> +	enum vpin bitshift_sel;
> +	enum vpif_freq freq_sel;
> +};
> +
> +/**
> + * ispccdc_culling - Structure for Culling parameters.
> + * @v_pattern: Vertical culling pattern.
> + * @h_odd: Horizontal Culling pattern for odd lines.
> + * @h_even: Horizontal Culling pattern for even lines.
> + */
> +struct ispccdc_culling {
> +	__u8 v_pattern;
> +	__u16 h_odd;
> +	__u16 h_even;
> +};
> +
> +/**
> + * ispccdc_update_config - Structure for CCDC configuration.
> + * @update: Specifies which CCDC registers should be updated.
> + * @flag: Specifies which CCDC functions should be enabled.
> + * @alawip: Enable/Disable A-Law compression.
> + * @bclamp: Black clamp control register.
> + * @blcomp: Black level compensation value for RGrGbB Pixels. 2's complement.
> + * @fpc: Number of faulty pixels corrected in the frame, address of FPC table.
> + * @cull: Cull control register.
> + * @colptn: Color pattern of the sensor.
> + * @lsc: Pointer to LSC gain table.
> + */
> +struct ispccdc_update_config {
> +	__u16 update;
> +	__u16 flag;
> +	enum alaw_ipwidth alawip;
> +	struct ispccdc_bclamp *bclamp;
> +	struct ispccdc_blcomp *blcomp;
> +	struct ispccdc_fpc *fpc;
> +	struct ispccdc_lsc_config *lsc_cfg;
> +	struct ispccdc_culling *cull;
> +	__u32 colptn;
> +	__u8 *lsc;

Can these pointers be NULL? Why are these pointers in the first place?
Unless these are arrays, and in that case it should be documented what the
array sizes are. And if the arrays have a fixed, small upper bound, then
consider including the entire array here.

> +};
> +
> +/* Preview configuration */
> +
> +/*Abstraction layer preview configurations*/
> +#define ISP_ABS_PREV_LUMAENH		(1 << 0)
> +#define ISP_ABS_PREV_INVALAW		(1 << 1)
> +#define ISP_ABS_PREV_HRZ_MED		(1 << 2)
> +#define ISP_ABS_PREV_CFA		(1 << 3)
> +#define ISP_ABS_PREV_CHROMA_SUPP	(1 << 4)
> +#define ISP_ABS_PREV_WB			(1 << 5)
> +#define ISP_ABS_PREV_BLKADJ		(1 << 6)
> +#define ISP_ABS_PREV_RGB2RGB		(1 << 7)
> +#define ISP_ABS_PREV_COLOR_CONV		(1 << 8)
> +#define ISP_ABS_PREV_YC_LIMIT		(1 << 9)
> +#define ISP_ABS_PREV_DEFECT_COR		(1 << 10)
> +#define ISP_ABS_PREV_GAMMABYPASS	(1 << 11)
> +#define ISP_ABS_TBL_NF 			(1 << 12)
> +#define ISP_ABS_TBL_REDGAMMA		(1 << 13)
> +#define ISP_ABS_TBL_GREENGAMMA		(1 << 14)
> +#define ISP_ABS_TBL_BLUEGAMMA		(1 << 15)
> +
> +#define ISPPRV_NF_TBL_SIZE		64
> +#define ISPPRV_CFA_TBL_SIZE		576
> +#define ISPPRV_GAMMA_TBL_SIZE		1024
> +#define ISPPRV_YENH_TBL_SIZE		128
> +
> +/**
> + * struct ispprev_hmed - Structure for Horizontal Median Filter.
> + * @odddist: Distance between consecutive pixels of same color in the odd line.
> + * @evendist: Distance between consecutive pixels of same color in the even
> + *            line.
> + * @thres: Horizontal median filter threshold.
> + */
> +struct ispprev_hmed {
> +	__u8 odddist;
> +	__u8 evendist;
> +	__u8 thres;
> +};
> +
> +/*
> + * Enumeration for CFA Formats supported by preview
> + */
> +enum cfa_fmt {
> +	CFAFMT_BAYER, CFAFMT_SONYVGA, CFAFMT_RGBFOVEON,
> +	CFAFMT_DNSPL, CFAFMT_HONEYCOMB, CFAFMT_RRGGBBFOVEON
> +};
> +
> +/**
> + * struct ispprev_cfa - Structure for CFA Inpterpolation.
> + * @cfafmt: CFA Format Enum value supported by preview.
> + * @cfa_gradthrs_vert: CFA Gradient Threshold - Vertical.
> + * @cfa_gradthrs_horz: CFA Gradient Threshold - Horizontal.
> + * @cfa_table: Pointer to the CFA table.
> + */
> +struct ispprev_cfa {
> +	enum cfa_fmt cfafmt;
> +	__u8 cfa_gradthrs_vert;
> +	__u8 cfa_gradthrs_horz;
> +	__u32 *cfa_table;

Same questions as above.

> +};
> +
> +/**
> + * struct ispprev_csup - Structure for Chrominance Suppression.
> + * @gain: Gain.
> + * @thres: Threshold.
> + * @hypf_en: Flag to enable/disable the High Pass Filter.
> + */
> +struct ispprev_csup {
> +	__u8 gain;
> +	__u8 thres;
> +	__u8 hypf_en;
> +};
> +
> +/**
> + * struct ispprev_wbal - Structure for White Balance.
> + * @dgain: Digital gain (U10Q8).
> + * @coef3: White balance gain - COEF 3 (U8Q5).
> + * @coef2: White balance gain - COEF 2 (U8Q5).
> + * @coef1: White balance gain - COEF 1 (U8Q5).
> + * @coef0: White balance gain - COEF 0 (U8Q5).
> + */
> +struct ispprev_wbal {
> +	__u16 dgain;
> +	__u8 coef3;
> +	__u8 coef2;
> +	__u8 coef1;
> +	__u8 coef0;
> +};
> +
> +/**
> + * struct ispprev_blkadj - Structure for Black Adjustment.
> + * @red: Black level offset adjustment for Red in 2's complement format
> + * @green: Black level offset adjustment for Green in 2's complement format
> + * @blue: Black level offset adjustment for Blue in 2's complement format
> + */
> +struct ispprev_blkadj {
> +	/*Black level offset adjustment for Red in 2's complement format */
> +	__u8 red;
> +	/*Black level offset adjustment for Green in 2's complement format */
> +	__u8 green;
> +	/* Black level offset adjustment for Blue in 2's complement format */
> +	__u8 blue;
> +};
> +
> +/**
> + * struct ispprev_rgbtorgb - Structure for RGB to RGB Blending.
> + * @matrix: Blending values(S12Q8 format)
> + *              [RR] [GR] [BR]
> + *              [RG] [GG] [BG]
> + *              [RB] [GB] [BB]
> + * @offset: Blending offset value for R,G,B in 2's complement integer format.
> + */
> +struct ispprev_rgbtorgb {
> +	__u16 matrix[3][3];
> +	__u16 offset[3];
> +};
> +
> +/**
> + * struct ispprev_csc - Structure for Color Space Conversion from RGB-YCbYCr
> + * @matrix: Color space conversion coefficients(S10Q8)
> + *              [CSCRY]  [CSCGY]  [CSCBY]
> + *              [CSCRCB] [CSCGCB] [CSCBCB]
> + *              [CSCRCR] [CSCGCR] [CSCBCR]
> + * @offset: CSC offset values for Y offset, CB offset and CR offset respectively
> + */
> +struct ispprev_csc {
> +	__u16 matrix[RGB_MAX][RGB_MAX];
> +	__s16 offset[RGB_MAX];
> +};
> +
> +/**
> + * struct ispprev_yclimit - Structure for Y, C Value Limit.
> + * @minC: Minimum C value
> + * @maxC: Maximum C value
> + * @minY: Minimum Y value
> + * @maxY: Maximum Y value
> + */
> +struct ispprev_yclimit {
> +	__u8 minC;
> +	__u8 maxC;
> +	__u8 minY;
> +	__u8 maxY;
> +};
> +
> +/**
> + * struct ispprev_dcor - Structure for Defect correction.
> + * @couplet_mode_en: Flag to enable or disable the couplet dc Correction in NF
> + * @detect_correct: Thresholds for correction bit 0:10 detect 16:25 correct
> + */
> +struct ispprev_dcor {
> +	__u8 couplet_mode_en;
> +	__u32 detect_correct[4];
> +};
> +
> +/**
> + * struct ispprev_nf - Structure for Noise Filter
> + * @spread: Spread value to be used in Noise Filter
> + * @table: Pointer to the Noise Filter table
> + */
> +struct ispprev_nf {
> +	__u8 spread;
> +	__u32 table[ISPPRV_NF_TBL_SIZE];
> +};
> +
> +/**
> + * struct ispprv_update_config - Structure for Preview Configuration (user).
> + * @update: Specifies which ISP Preview registers should be updated.
> + * @flag: Specifies which ISP Preview functions should be enabled.
> + * @yen: Pointer to luma enhancement table.
> + * @shading_shift: 3bit value of shift used in shading compensation.
> + * @prev_hmed: Pointer to structure containing the odd and even distance.
> + *             between the pixels in the image along with the filter threshold.
> + * @prev_cfa: Pointer to structure containing the CFA interpolation table, CFA.
> + *            format in the image, vertical and horizontal gradient threshold.
> + * @csup: Pointer to Structure for Chrominance Suppression coefficients.
> + * @prev_wbal: Pointer to structure for White Balance.
> + * @prev_blkadj: Pointer to structure for Black Adjustment.
> + * @rgb2rgb: Pointer to structure for RGB to RGB Blending.
> + * @prev_csc: Pointer to structure for Color Space Conversion from RGB-YCbYCr.
> + * @yclimit: Pointer to structure for Y, C Value Limit.
> + * @prev_dcor: Pointer to structure for defect correction.
> + * @prev_nf: Pointer to structure for Noise Filter
> + * @red_gamma: Pointer to red gamma correction table.
> + * @green_gamma: Pointer to green gamma correction table.
> + * @blue_gamma: Pointer to blue gamma correction table.
> + */
> +struct ispprv_update_config {
> +	__u16 update;
> +	__u16 flag;
> +	void *yen;
> +	__u32 shading_shift;
> +	struct ispprev_hmed *prev_hmed;
> +	struct ispprev_cfa *prev_cfa;
> +	struct ispprev_csup *csup;
> +	struct ispprev_wbal *prev_wbal;
> +	struct ispprev_blkadj *prev_blkadj;
> +	struct ispprev_rgbtorgb *rgb2rgb;
> +	struct ispprev_csc *prev_csc;
> +	struct ispprev_yclimit *yclimit;
> +	struct ispprev_dcor *prev_dcor;
> +	struct ispprev_nf *prev_nf;
> +	__u32 *red_gamma;
> +	__u32 *green_gamma;
> +	__u32 *blue_gamma;

Ditto.

> +};
> +
> +#endif /* OMAP_ISP_USER_H */

Pointers are much harder to manage then fixed-sized structures and arrays.

So in general it is better to avoid them unless they are really needed.

Regards,

          Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG

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

* Re: [PATCH 9/9] omap34xxcam: Add camera driver
  2009-03-05 14:09                     ` Sakari Ailus
@ 2009-03-07 14:38                       ` Alexey Klimov
  0 siblings, 0 replies; 30+ messages in thread
From: Alexey Klimov @ 2009-03-07 14:38 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

Hello, Sakari Ailus

On Thu, 2009-03-05 at 16:09 +0200, Sakari Ailus wrote:
> Alexey Klimov wrote:
> >> +static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
> >> +				struct v4l2_format *f)
> >> +{
> >> +	struct omap34xxcam_fh *ofh = fh;
> >> +	struct omap34xxcam_videodev *vdev = ofh->vdev;
> >> +
> >> +	if (vdev->vdev_sensor == v4l2_int_device_dummy())
> >> +		return -EINVAL;
> >> +
> >> +	mutex_lock(&vdev->mutex);
> >> +	f->fmt.pix = vdev->pix;
> >> +	mutex_unlock(&vdev->mutex);
> > 
> > Hmmmm, you are using mutex_lock to lock reading from vdev structure..
> > Well, i don't if this is right approach. I am used to that mutex_lock is
> > used to prevent _changing_ of members in structure..
> 
> The vdev->mutex is acquired since we want to prevent concurrent access 
> to vdev->pix. Otherwise it might change while we are reading it, right?

I thought more about this and looks like that i was wrong. You are
right. You are reading structure, and i wasn't able to notice that first
time. Sorry for bothering about this.

<snip>

> >> +static int omap34xxcam_device_register(struct v4l2_int_device *s)
> >> +{
> >> +	struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
> >> +	struct omap34xxcam_hw_config hwc;
> >> +	int rval;
> >> +
> >> +	/* We need to check rval just once. The place is here. */
> > 
> > I didn't understand this comment. You doing nothin in next few lines
> > with int variable rval(which introduced in this function). Is comment
> > talking about struct v4l2_int_device *s ?
> 
> Yes. If the g_priv() succeeds now it will succeed in future, too. This 
> comes from the platform data through the slave device.

Well, okay. I mean that for me this comment looks ambiguous. Please, if
you don't mind it's better not to use word "rval" because it  creates
confusion with int rval;.


-- 
Best regards, Klimov Alexey


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

* Re: [PATCH 1/9] omap3isp: Add ISP main driver and register definitions
  2009-03-05 11:34     ` Sakari Ailus
@ 2009-03-07 15:25       ` Alexey Klimov
  0 siblings, 0 replies; 30+ messages in thread
From: Alexey Klimov @ 2009-03-07 15:25 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, linux-omap, saaguirre, tuukka.o.toivonen, dongsoo.kim

On Thu, 2009-03-05 at 13:34 +0200, Sakari Ailus wrote:
> Thanks for the comments, Alexey!
> 
> Alexey Klimov wrote:
> >> +static int isp_probe(struct platform_device *pdev)
> >> +{
> >> +	struct isp_device *isp;
> >> +	int ret_err = 0;
> >> +	int i;
> >> +
> >> +	isp = kzalloc(sizeof(*isp), GFP_KERNEL);
> >> +	if (!isp) {
> >> +		dev_err(&pdev->dev, "could not allocate memory\n");
> >> +		return -ENODEV;
> > 
> > return -ENOMEM; ?
> 
> Done.
> 
> >> +	}
> >> +
> >> +	platform_set_drvdata(pdev, isp);
> >> +
> >> +	isp->dev = &pdev->dev;
> >> +
> >> +	for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
> >> +		struct resource *mem;
> >> +		/* request the mem region for the camera registers */
> >> +		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
> >> +		if (!mem) {
> >> +			dev_err(isp->dev, "no mem resource?\n");
> >> +			return -ENODEV;
> > 
> > Maybe ENODEV is not apropriate here too..
> 
> What else it could be? ENOENT comes to mind but I'm not sure it's 
> significantly better.

ENODEV is okay, sorry.

-- 
Best regards, Klimov Alexey


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

end of thread, other threads:[~2009-03-07 15:24 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-03 10:06 [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
2009-03-03 10:06 ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Sakari Ailus
2009-03-03 10:06   ` [PATCH 2/9] omap3isp: Add ISP MMU wrapper Sakari Ailus
2009-03-03 10:06     ` [PATCH 3/9] omap3isp: Add userspace header Sakari Ailus
2009-03-03 10:06       ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Sakari Ailus
2009-03-03 10:06         ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Sakari Ailus
2009-03-03 10:06           ` [PATCH 6/9] omap3isp: Add statistics collection modules (H3A and HIST) Sakari Ailus
2009-03-03 10:06             ` [PATCH 7/9] omap3isp: Add CSI2 interface support Sakari Ailus
2009-03-03 10:06               ` [PATCH 8/9] omap3isp: Add ISP tables Sakari Ailus
2009-03-03 10:06                 ` [PATCH 9/9] omap34xxcam: Add camera driver Sakari Ailus
2009-03-03 17:31                   ` Alexey Klimov
2009-03-05 14:09                     ` Sakari Ailus
2009-03-07 14:38                       ` Alexey Klimov
2009-03-03 12:23           ` [PATCH 5/9] omap3isp: Add ISP backend (PRV and RSZ) Alexey Klimov
2009-03-03 12:07         ` [PATCH 4/9] omap3isp: Add ISP frontend (CCDC) Alexey Klimov
2009-03-06 12:51       ` [PATCH 3/9] omap3isp: Add userspace header Hans Verkuil
2009-03-03 11:56   ` [PATCH 1/9] omap3isp: Add ISP main driver and register definitions Alexey Klimov
2009-03-05 11:34     ` Sakari Ailus
2009-03-07 15:25       ` Alexey Klimov
2009-03-03 13:09 ` [RFC 0/9] OMAP3 ISP and camera drivers Sakari Ailus
2009-03-04 15:28 ` Hiremath, Vaibhav
2009-03-04 15:38   ` Sakari Ailus
2009-03-05  0:10     ` DongSoo(Nathaniel) Kim
2009-03-05  3:53       ` Hiremath, Vaibhav
2009-03-05  4:54         ` DongSoo(Nathaniel) Kim
2009-03-05  4:54           ` DongSoo(Nathaniel) Kim
2009-03-05  7:30         ` Sakari Ailus
2009-03-05 14:26         ` [PATCH] omap34xxcam: Don't use dev_err before we have a video device Sakari Ailus
2009-03-05  5:00 ` [RFC 0/9] OMAP3 ISP and camera drivers DongSoo(Nathaniel) Kim
2009-03-05  5:00   ` DongSoo(Nathaniel) Kim

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