All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
To: linux-media@vger.kernel.org
Cc: linux-omap@vger.kernel.org, saaguirre@ti.com,
	tuukka.o.toivonen@nokia.com, dongsoo.kim@gmail.com
Subject: [PATCH 4/9] omap3isp: Add ISP frontend (CCDC)
Date: Tue,  3 Mar 2009 12:06:51 +0200	[thread overview]
Message-ID: <1236074816-30018-4-git-send-email-sakari.ailus@maxwell.research.nokia.com> (raw)
In-Reply-To: <1236074816-30018-3-git-send-email-sakari.ailus@maxwell.research.nokia.com>

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


  reply	other threads:[~2009-03-03 10:07 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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       ` Sakari Ailus [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1236074816-30018-4-git-send-email-sakari.ailus@maxwell.research.nokia.com \
    --to=sakari.ailus@maxwell.research.nokia.com \
    --cc=dongsoo.kim@gmail.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=saaguirre@ti.com \
    --cc=tuukka.o.toivonen@nokia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.