diff mbox

[1/5,-,v0] V4L-vpfe capture - adding CCDC driver for DM365

Message ID 1259703533-1789-1-git-send-email-m-karicheri2@ti.com (mailing list archive)
State Superseded
Headers show

Commit Message

Murali Karicheri Dec. 1, 2009, 9:38 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/media/video/davinci/dm365_ccdc.c b/drivers/media/video/davinci/dm365_ccdc.c
new file mode 100644
index 0000000..2f27696
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ccdc.c
@@ -0,0 +1,1529 @@ 
+/*
+ * Copyright (C) 2008-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This is the isif hardware module for DM365.
+ * TODO: 1) Raw bayer parameter settings and bayer capture
+ *	 2) Add support for control ioctl
+ */
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <mach/mux.h>
+#include <media/davinci/dm365_ccdc.h>
+#include <media/davinci/vpss.h>
+#include "dm365_ccdc_regs.h"
+#include "ccdc_hw_device.h"
+
+static struct device *dev;
+
+/* Defauts for module configuation paramaters */
+static struct ccdc_config_params_raw ccdc_config_defaults = {
+	.linearize = {
+		.en = 0,
+		.corr_shft = CCDC_NO_SHIFT,
+		.scale_fact = {1, 0},
+	},
+	.df_csc = {
+		.df_or_csc = 0,
+		.csc = {
+			.en = 0
+		},
+	},
+	.dfc = {
+		.en = 0
+	},
+	.bclamp = {
+		.en = 0
+	},
+	.gain_offset = {
+		.gain = {
+			.r_ye = {1, 0},
+			.gr_cy = {1, 0},
+			.gb_g = {1, 0},
+			.b_mg = {1, 0},
+		},
+	},
+	.culling = {
+		.hcpat_odd = 0xff,
+		.hcpat_even = 0xff,
+		.vcpat = 0xff
+	},
+	.compress = {
+		.alg = CCDC_ALAW,
+	},
+};
+
+/* ISIF operation configuration */
+struct ccdc_oper_config {
+	enum vpfe_hw_if_type if_type;
+	struct ccdc_ycbcr_config ycbcr;
+	struct ccdc_params_raw bayer;
+	enum ccdc_data_pack data_pack;
+	void *__iomem base_addr;
+	void *__iomem linear_tbl0_addr;
+	void *__iomem linear_tbl1_addr;
+};
+
+static struct ccdc_oper_config ccdc_cfg = {
+	.ycbcr = {
+		.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
+		.frm_fmt = CCDC_FRMFMT_INTERLACED,
+		.win = CCDC_WIN_NTSC,
+		.fid_pol = VPFE_PINPOL_POSITIVE,
+		.vd_pol = VPFE_PINPOL_POSITIVE,
+		.hd_pol = VPFE_PINPOL_POSITIVE,
+		.pix_order = CCDC_PIXORDER_CBYCRY,
+		.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED,
+	},
+	.bayer = {
+		.pix_fmt = CCDC_PIXFMT_RAW,
+		.frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
+		.win = CCDC_WIN_VGA,
+		.fid_pol = VPFE_PINPOL_POSITIVE,
+		.vd_pol = VPFE_PINPOL_POSITIVE,
+		.hd_pol = VPFE_PINPOL_POSITIVE,
+		.gain = {
+			.r_ye = {1, 0},
+			.gr_cy = {1, 0},
+			.gb_g = {1, 0},
+			.b_mg = {1, 0},
+		},
+		.cfa_pat = CCDC_CFA_PAT_MOSAIC,
+		.data_msb = CCDC_BIT_MSB_11,
+		.config_params = {
+			.data_shift = CCDC_NO_SHIFT,
+			.col_pat_field0 = {
+				.olop = CCDC_GREEN_BLUE,
+				.olep = CCDC_BLUE,
+				.elop = CCDC_RED,
+				.elep = CCDC_GREEN_RED,
+			},
+			.col_pat_field1 = {
+				.olop = CCDC_GREEN_BLUE,
+				.olep = CCDC_BLUE,
+				.elop = CCDC_RED,
+				.elep = CCDC_GREEN_RED,
+			},
+			.test_pat_gen = 0,
+		},
+	},
+	.data_pack = CCDC_DATA_PACK8,
+};
+
+/* Raw Bayer formats */
+static u32 ccdc_raw_bayer_pix_formats[] =
+		{V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
+
+/* Raw YUV formats */
+static u32 ccdc_raw_yuv_pix_formats[] =
+		{V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
+
+/* register access routines */
+static inline u32 regr(u32 offset)
+{
+	return __raw_readl(ccdc_cfg.base_addr + offset);
+}
+
+static inline void regw(u32 val, u32 offset)
+{
+	__raw_writel(val, ccdc_cfg.base_addr + offset);
+}
+
+static inline u32 ccdc_merge(u32 mask, u32 val, u32 offset)
+{
+	u32 new_val = (regr(offset) & ~mask) | (val & mask);
+
+	regw(new_val, offset);
+	return new_val;
+}
+
+static inline void regw_lin_tbl(u32 val, u32 offset, int i)
+{
+	if (!i)
+		__raw_writel(val, ccdc_cfg.linear_tbl0_addr + offset);
+	else
+		__raw_writel(val, ccdc_cfg.linear_tbl1_addr + offset);
+}
+
+static void ccdc_disable_all_modules(void)
+{
+	/* disable BC */
+	regw(0, CLAMPCFG);
+	/* disable vdfc */
+	regw(0, DFCCTL);
+	/* disable CSC */
+	regw(0, CSCCTL);
+	/* disable linearization */
+	regw(0, LINCFG0);
+	/* disable other modules here as they are supported */
+}
+
+static void ccdc_enable(int en)
+{
+	if (!en) {
+		/* Before disable isif, disable all ISIF modules */
+		ccdc_disable_all_modules();
+		/**
+		 * wait for next VD. Assume lowest scan rate is 12 Hz. So
+		 * 100 msec delay is good enough
+		 */
+	}
+	msleep(100);
+	ccdc_merge(CCDC_SYNCEN_VDHDEN_MASK, en, SYNCEN);
+}
+
+static void ccdc_enable_output_to_sdram(int en)
+{
+	ccdc_merge(CCDC_SYNCEN_WEN_MASK, en << CCDC_SYNCEN_WEN_SHIFT, SYNCEN);
+}
+
+static void ccdc_config_culling(struct ccdc_cul *cul)
+{
+	u32 val;
+
+	/* Horizontal pattern */
+	val = (cul->hcpat_even) << CULL_PAT_EVEN_LINE_SHIFT;
+	val |= cul->hcpat_odd;
+	regw(val, CULH);
+
+	/* vertical pattern */
+	regw(cul->vcpat, CULV);
+
+	/* LPF */
+	ccdc_merge((CCDC_LPF_MASK << CCDC_LPF_SHIFT),
+		   (cul->en_lpf << CCDC_LPF_SHIFT), MODESET);
+}
+
+static void ccdc_config_gain_offset(void)
+{
+	struct ccdc_gain_offsets_adj *gain_off_ptr =
+		&ccdc_cfg.bayer.config_params.gain_offset;
+	u32 val;
+
+	val = ((gain_off_ptr->gain_sdram_en & 1) << GAIN_SDRAM_EN_SHIFT) |
+	((gain_off_ptr->gain_ipipe_en & 1) << GAIN_IPIPE_EN_SHIFT) |
+	((gain_off_ptr->gain_h3a_en & 1) << GAIN_H3A_EN_SHIFT) |
+	((gain_off_ptr->offset_sdram_en & 1) << OFST_SDRAM_EN_SHIFT) |
+	((gain_off_ptr->offset_ipipe_en & 1) << OFST_IPIPE_EN_SHIFT) |
+	((gain_off_ptr->offset_h3a_en & 1) << OFST_H3A_EN_SHIFT);
+
+	ccdc_merge(GAIN_OFFSET_EN_MASK, val, CGAMMAWD);
+
+	val = ((gain_off_ptr->gain.r_ye.integer	& GAIN_INTEGER_MASK)
+		<< GAIN_INTEGER_SHIFT);
+	val |= (ccdc_cfg.bayer.
+		config_params.gain_offset.gain.r_ye.decimal &
+		GAIN_DECIMAL_MASK);
+	regw(val, CRGAIN);
+
+	val = ((gain_off_ptr->gain.gr_cy
+		.integer & GAIN_INTEGER_MASK) << GAIN_INTEGER_SHIFT);
+	val |= (gain_off_ptr->gain.gr_cy
+		.decimal & GAIN_DECIMAL_MASK);
+	regw(val, CGRGAIN);
+
+	val = ((gain_off_ptr->gain.gb_g
+		.integer & GAIN_INTEGER_MASK) << GAIN_INTEGER_SHIFT);
+	val |= (gain_off_ptr->gain.gb_g
+		.decimal & GAIN_DECIMAL_MASK);
+	regw(val, CGBGAIN);
+
+	val = ((gain_off_ptr->gain.b_mg
+		.integer & GAIN_INTEGER_MASK) << GAIN_INTEGER_SHIFT);
+	val |= (gain_off_ptr->gain.b_mg
+		.decimal & GAIN_DECIMAL_MASK);
+	regw(val, CBGAIN);
+
+	regw((gain_off_ptr->offset &
+		OFFSET_MASK), COFSTA);
+}
+
+static void ccdc_restore_defaults(void)
+{
+	enum vpss_ccdc_source_sel source = VPSS_CCDCIN;
+	int i;
+
+	memcpy(&ccdc_cfg.bayer.config_params, &ccdc_config_defaults,
+		sizeof(struct ccdc_config_params_raw));
+
+	dev_dbg(dev, "\nstarting ccdc_restore_defaults...");
+	/* Enable clock to ISIF, IPIPEIF and BL */
+	vpss_enable_clock(VPSS_CCDC_CLOCK, 1);
+	vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
+	vpss_enable_clock(VPSS_BL_CLOCK, 1);
+
+	/* set all registers to default value */
+	for (i = 0; i <= 0x1f8; i += 4)
+		regw(0, i);
+
+	/* no culling support */
+	regw(0xffff, CULH);
+	regw(0xff, CULV);
+
+	/* Set default offset and gain */
+	ccdc_config_gain_offset();
+
+	vpss_select_ccdc_source(source);
+
+	dev_dbg(dev, "\nEnd of ccdc_restore_defaults...");
+}
+
+static int ccdc_open(struct device *device)
+{
+	dev = device;
+	ccdc_restore_defaults();
+	return 0;
+}
+
+/* This function will configure the window size to be capture in CCDC reg */
+static void ccdc_setwin(struct v4l2_rect *image_win,
+			enum ccdc_frmfmt frm_fmt, int ppc)
+{
+	int horz_start, horz_nr_pixels;
+	int vert_start, vert_nr_lines;
+	int mid_img = 0;
+
+	dev_dbg(dev, "\nStarting ccdc_setwin...");
+	/**
+	 * ppc - per pixel count. indicates how many pixels per cell
+	 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
+	 * raw capture this is 1
+	 */
+	horz_start = image_win->left << (ppc - 1);
+	horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1;
+
+	/* Writing the horizontal info into the registers */
+	regw(horz_start & START_PX_HOR_MASK, SPH);
+	regw(horz_nr_pixels & NUM_PX_HOR_MASK, LNH);
+	vert_start = image_win->top;
+
+	if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		vert_nr_lines = (image_win->height >> 1) - 1;
+		vert_start >>= 1;
+		/* To account for VD since line 0 doesn't have any data */
+		vert_start += 1;
+	} else {
+		/* To account for VD since line 0 doesn't have any data */
+		vert_start += 1;
+		vert_nr_lines = image_win->height - 1;
+		/* configure VDINT0 and VDINT1 */
+		mid_img = vert_start + (image_win->height / 2);
+		regw(mid_img, VDINT1);
+	}
+
+	regw(0, VDINT0);
+	regw(vert_start & START_VER_ONE_MASK, SLV0);
+	regw(vert_start & START_VER_TWO_MASK, SLV1);
+	regw(vert_nr_lines & NUM_LINES_VER, LNV);
+}
+
+static void ccdc_config_bclamp(struct ccdc_black_clamp *bc)
+{
+	u32 val;
+
+	/**
+	 * DC Offset is always added to image data irrespective of bc enable
+	 * status
+	 */
+	val = bc->dc_offset & CCDC_BC_DCOFFSET_MASK;
+	regw(val, CLDCOFST);
+
+	if (bc->en) {
+		val = (bc->bc_mode_color & CCDC_BC_MODE_COLOR_MASK) <<
+			CCDC_BC_MODE_COLOR_SHIFT;
+
+		/* Enable BC and horizontal clamp caculation paramaters */
+		val = val | 1 | ((bc->horz.mode & CCDC_HORZ_BC_MODE_MASK) <<
+		CCDC_HORZ_BC_MODE_SHIFT);
+
+		regw(val, CLAMPCFG);
+
+		if (bc->horz.mode != CCDC_HORZ_BC_DISABLE) {
+			/**
+			 * Window count for calculation
+			 * Base window selection
+			 * pixel limit
+			 * Horizontal size of window
+			 * vertical size of the window
+			 * Horizontal start position of the window
+			 * Vertical start position of the window
+			 */
+			val = (bc->horz.win_count_calc &
+				CCDC_HORZ_BC_WIN_COUNT_MASK) |
+				((bc->horz.base_win_sel_calc & 1)
+				<< CCDC_HORZ_BC_WIN_SEL_SHIFT) |
+				((bc->horz.clamp_pix_limit & 1)
+				<< CCDC_HORZ_BC_PIX_LIMIT_SHIFT) |
+				((bc->horz.win_h_sz_calc &
+				CCDC_HORZ_BC_WIN_H_SIZE_MASK)
+				<< CCDC_HORZ_BC_WIN_H_SIZE_SHIFT) |
+				((bc->horz.win_v_sz_calc &
+				CCDC_HORZ_BC_WIN_V_SIZE_MASK)
+				<< CCDC_HORZ_BC_WIN_V_SIZE_SHIFT);
+
+			regw(val, CLHWIN0);
+
+			val = (bc->horz.win_start_h_calc &
+				CCDC_HORZ_BC_WIN_START_H_MASK);
+			regw(val, CLHWIN1);
+
+			val =
+			    (bc->horz.
+			     win_start_v_calc & CCDC_HORZ_BC_WIN_START_V_MASK);
+			regw(val, CLHWIN2);
+		}
+
+		/* vertical clamp caculation paramaters */
+
+		/* OB H Valid */
+		val = (bc->vert.ob_h_sz_calc & CCDC_VERT_BC_OB_H_SZ_MASK);
+
+		/* Reset clamp value sel for previous line */
+		val |= ((bc->vert.reset_val_sel &
+			CCDC_VERT_BC_RST_VAL_SEL_MASK)
+			<< CCDC_VERT_BC_RST_VAL_SEL_SHIFT);
+
+		/* Line average coefficient */
+		val |= (bc->vert.line_ave_coef <<
+			CCDC_VERT_BC_LINE_AVE_COEF_SHIFT);
+		regw(val, CLVWIN0);
+
+		/* Configured reset value */
+		if (bc->vert.reset_val_sel ==
+		    CCDC_VERT_BC_USE_CONFIG_CLAMP_VAL) {
+			val =
+			    (bc->vert.
+			     reset_clamp_val & CCDC_VERT_BC_RST_VAL_MASK);
+			regw(val, CLVRV);
+		}
+
+		/* Optical Black horizontal start position */
+		val = (bc->vert.ob_start_h & CCDC_VERT_BC_OB_START_HORZ_MASK);
+		regw(val, CLVWIN1);
+
+		/* Optical Black vertical start position */
+		val = (bc->vert.ob_start_v & CCDC_VERT_BC_OB_START_VERT_MASK);
+		regw(val, CLVWIN2);
+
+		val = (bc->vert.ob_v_sz_calc & CCDC_VERT_BC_OB_VERT_SZ_MASK);
+		regw(val, CLVWIN3);
+
+		/* Vertical start position for BC subtraction */
+		val = (bc->vert_start_sub & CCDC_BC_VERT_START_SUB_V_MASK);
+		regw(val, CLSV);
+	}
+}
+
+static void ccdc_config_linearization(struct ccdc_linearize *linearize)
+{
+	u32 val, i;
+	if (!linearize->en) {
+		regw(0, LINCFG0);
+		return;
+	}
+
+	/* shift value for correction */
+	val = (linearize->corr_shft & CCDC_LIN_CORRSFT_MASK)
+	    << CCDC_LIN_CORRSFT_SHIFT;
+	/* enable */
+	val |= 1;
+	regw(val, LINCFG0);
+
+	/* Scale factor */
+	val = (linearize->scale_fact.integer & 1)
+	    << CCDC_LIN_SCALE_FACT_INTEG_SHIFT;
+	val |= (linearize->scale_fact.decimal &
+				CCDC_LIN_SCALE_FACT_DECIMAL_MASK);
+	regw(val, LINCFG1);
+
+	for (i = 0; i < CCDC_LINEAR_TAB_SIZE; i++) {
+		val = linearize->table[i] & CCDC_LIN_ENTRY_MASK;
+		if (i%2)
+			regw_lin_tbl(val, ((i >> 1) << 2), 1);
+		else
+			regw_lin_tbl(val, ((i >> 1) << 2), 0);
+	}
+}
+
+static void ccdc_config_dfc(struct ccdc_dfc *vdfc)
+{
+#define DFC_WRITE_WAIT_COUNT	1000
+	u32 val, count = DFC_WRITE_WAIT_COUNT;
+	int i;
+
+	if (!vdfc->en)
+		return;
+
+	/* Correction mode */
+	val = ((vdfc->corr_mode & CCDC_VDFC_CORR_MOD_MASK)
+		<< CCDC_VDFC_CORR_MOD_SHIFT);
+
+	/* Correct whole line or partial */
+	if (vdfc->corr_whole_line)
+		val |= 1 << CCDC_VDFC_CORR_WHOLE_LN_SHIFT;
+
+	/* level shift value */
+	val |= (vdfc->def_level_shift & CCDC_VDFC_LEVEL_SHFT_MASK) <<
+		CCDC_VDFC_LEVEL_SHFT_SHIFT;
+
+	regw(val, DFCCTL);
+
+	/* Defect saturation level */
+	val = vdfc->def_sat_level & CCDC_VDFC_SAT_LEVEL_MASK;
+	regw(val, VDFSATLV);
+
+	regw(vdfc->table[0].pos_vert & CCDC_VDFC_POS_MASK, DFCMEM0);
+	regw(vdfc->table[0].pos_horz & CCDC_VDFC_POS_MASK, DFCMEM1);
+	if (vdfc->corr_mode == CCDC_VDFC_NORMAL ||
+	    vdfc->corr_mode == CCDC_VDFC_HORZ_INTERPOL_IF_SAT) {
+		regw(vdfc->table[0].level_at_pos, DFCMEM2);
+		regw(vdfc->table[0].level_up_pixels, DFCMEM3);
+		regw(vdfc->table[0].level_low_pixels, DFCMEM4);
+	}
+
+	val = regr(DFCMEMCTL);
+	/* set DFCMARST and set DFCMWR */
+	val |= 1 << CCDC_DFCMEMCTL_DFCMARST_SHIFT;
+	val |= 1;
+	regw(val, DFCMEMCTL);
+
+	while (count && (regr(DFCMEMCTL) & 0x01))
+		count--;
+
+	val = regr(DFCMEMCTL);
+	if (!count) {
+		dev_dbg(dev, "defect table write timeout !!!\n");
+		return;
+	}
+
+	for (i = 1; i < vdfc->num_vdefects; i++) {
+		regw(vdfc->table[i].pos_vert & CCDC_VDFC_POS_MASK,
+			   DFCMEM0);
+		regw(vdfc->table[i].pos_horz & CCDC_VDFC_POS_MASK,
+			   DFCMEM1);
+		if (vdfc->corr_mode == CCDC_VDFC_NORMAL ||
+		    vdfc->corr_mode == CCDC_VDFC_HORZ_INTERPOL_IF_SAT) {
+			regw(vdfc->table[i].level_at_pos, DFCMEM2);
+			regw(vdfc->table[i].level_up_pixels, DFCMEM3);
+			regw(vdfc->table[i].level_low_pixels, DFCMEM4);
+		}
+		val = regr(DFCMEMCTL);
+		/* clear DFCMARST and set DFCMWR */
+		val &= ~(1 << CCDC_DFCMEMCTL_DFCMARST_SHIFT);
+		val |= 1;
+		regw(val, DFCMEMCTL);
+
+		count = DFC_WRITE_WAIT_COUNT;
+		while (count && (regr(DFCMEMCTL) & 0x01))
+			count--;
+
+		val = regr(DFCMEMCTL);
+		if (!count) {
+			dev_err(dev, "defect table write timeout !!!\n");
+			return;
+		}
+	}
+	if (vdfc->num_vdefects < CCDC_VDFC_TABLE_SIZE) {
+		/* Extra cycle needed */
+		regw(0, DFCMEM0);
+		regw(0x1FFF, DFCMEM1);
+		val = 1;
+		regw(val, DFCMEMCTL);
+	}
+
+	/* enable VDFC */
+	ccdc_merge((1 << CCDC_VDFC_EN_SHIFT), (1 << CCDC_VDFC_EN_SHIFT),
+		   DFCCTL);
+
+	ccdc_merge((1 << CCDC_VDFC_EN_SHIFT), (0 << CCDC_VDFC_EN_SHIFT),
+		   DFCCTL);
+
+	regw(0x6, DFCMEMCTL);
+	for (i = 0 ; i < vdfc->num_vdefects; i++) {
+		count = DFC_WRITE_WAIT_COUNT;
+		while (count && (regr(DFCMEMCTL) & 0x2))
+			count--;
+
+		val = regr(DFCMEMCTL);
+		if (!count) {
+			dev_err(dev, "defect table write timeout !!!\n");
+			return;
+		}
+
+		val = regr(DFCMEM0) | regr(DFCMEM1) | regr(DFCMEM2) |
+			regr(DFCMEM3) | regr(DFCMEM4);
+		regw(0x2, DFCMEMCTL);
+	}
+}
+
+static void ccdc_config_csc(struct ccdc_df_csc *df_csc)
+{
+	u32 val1 = 0, val2 = 0, i;
+
+	if (!df_csc->csc.en) {
+		regw(0, CSCCTL);
+		return;
+	}
+	for (i = 0; i < CCDC_CSC_NUM_COEFF; i++) {
+		if ((i % 2) == 0) {
+			/* CSCM - LSB */
+			val1 =
+				((df_csc->csc.coeff[i].integer &
+				CCDC_CSC_COEF_INTEG_MASK)
+				<< CCDC_CSC_COEF_INTEG_SHIFT) |
+				((df_csc->csc.coeff[i].decimal &
+				CCDC_CSC_COEF_DECIMAL_MASK));
+		} else {
+
+			/* CSCM - MSB */
+			val2 =
+				((df_csc->csc.coeff[i].integer &
+				CCDC_CSC_COEF_INTEG_MASK)
+				<< CCDC_CSC_COEF_INTEG_SHIFT) |
+				((df_csc->csc.coeff[i].decimal &
+				CCDC_CSC_COEF_DECIMAL_MASK));
+			val2 <<= CCDC_CSCM_MSB_SHIFT;
+			val2 |= val1;
+			regw(val2, (CSCM0 + ((i-1) << 1)));
+		}
+	}
+
+	/* program the active area */
+	regw(df_csc->start_pix & CCDC_DF_CSC_SPH_MASK, FMTSPH);
+	/**
+	 * one extra pixel as required for CSC. Actually number of
+	 * pixel - 1 should be configured in this register. So we
+	 * need to subtract 1 before writing to FMTSPH, but we will
+	 * not do this since csc requires one extra pixel
+	 */
+	regw((df_csc->num_pixels) & CCDC_DF_CSC_SPH_MASK, FMTLNH);
+	regw(df_csc->start_line & CCDC_DF_CSC_SPH_MASK, FMTSLV);
+	/**
+	 * one extra line as required for CSC. See reason documented for
+	 * num_pixels
+	 */
+	regw((df_csc->num_lines) & CCDC_DF_CSC_SPH_MASK, FMTLNV);
+
+	/* Enable CSC */
+	regw(1, CSCCTL);
+}
+
+static int ccdc_config_raw(void)
+{
+	struct ccdc_params_raw *params = &ccdc_cfg.bayer;
+	struct ccdc_config_params_raw *module_params =
+		&ccdc_cfg.bayer.config_params;
+	struct vpss_pg_frame_size frame_size;
+	struct vpss_sync_pol sync;
+	u32 val;
+
+	dev_dbg(dev, "\nStarting ccdc_config_raw..\n");
+
+	/* Configure CCDCFG register */
+
+	/**
+	 * Set CCD Not to swap input since input is RAW data
+	 * Set FID detection function to Latch at V-Sync
+	 * Set WENLOG - ccdc valid area
+	 * Set TRGSEL
+	 * Set EXTRG
+	 * Packed to 8 or 16 bits
+	 */
+
+	val = CCDC_YCINSWP_RAW | CCDC_CCDCFG_FIDMD_LATCH_VSYNC |
+		CCDC_CCDCFG_WENLOG_AND | CCDC_CCDCFG_TRGSEL_WEN |
+		CCDC_CCDCFG_EXTRG_DISABLE | (ccdc_cfg.data_pack &
+		CCDC_DATA_PACK_MASK);
+
+	dev_dbg(dev, "Writing 0x%x to ...CCDCFG \n", val);
+	regw(val, CCDCFG);
+
+	/**
+	 * Configure the vertical sync polarity(MODESET.VDPOL)
+	 * Configure the horizontal sync polarity (MODESET.HDPOL)
+	 * Configure frame id polarity (MODESET.FLDPOL)
+	 * Configure data polarity
+	 * Configure External WEN Selection
+	 * Configure frame format(progressive or interlace)
+	 * Configure pixel format (Input mode)
+	 * Configure the data shift
+	 */
+
+	val = CCDC_VDHDOUT_INPUT |
+		((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
+		((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
+		((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
+		((CCDC_DATAPOL_NORMAL & CCDC_DATAPOL_MASK)
+			<< CCDC_DATAPOL_SHIFT) |
+		((CCDC_EXWEN_DISABLE & CCDC_EXWEN_MASK) << CCDC_EXWEN_SHIFT) |
+		((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
+		((params->pix_fmt & CCDC_INPUT_MASK) << CCDC_INPUT_SHIFT) |
+		((params->config_params.data_shift & CCDC_DATASFT_MASK)
+			<< CCDC_DATASFT_SHIFT);
+
+	regw(val, MODESET);
+	dev_dbg(dev, "Writing 0x%x to MODESET...\n", val);
+
+	/**
+	 * Configure GAMMAWD register
+	 * CFA pattern setting
+	 */
+	val = (params->cfa_pat & CCDC_GAMMAWD_CFA_MASK) <<
+		CCDC_GAMMAWD_CFA_SHIFT;
+
+	/* Gamma msb */
+	if (module_params->compress.alg == CCDC_ALAW)
+		val = val | CCDC_ALAW_ENABLE;
+
+	val = val | ((params->data_msb & CCDC_ALAW_GAMA_WD_MASK) <<
+			CCDC_ALAW_GAMA_WD_SHIFT);
+
+	regw(val, CGAMMAWD);
+
+	/* Configure DPCM compression settings */
+	if (module_params->compress.alg == CCDC_DPCM) {
+		val =  1 << CCDC_DPCM_EN_SHIFT;
+		val |= (module_params->compress.pred &
+			CCDC_DPCM_PREDICTOR_MASK) << CCDC_DPCM_PREDICTOR_SHIFT;
+	}
+
+	regw(val, MISC);
+	/* Configure Gain & Offset */
+
+	ccdc_config_gain_offset();
+
+	/* Configure Color pattern */
+	val = (params->config_params.col_pat_field0.olop) |
+	(params->config_params.col_pat_field0.olep << 2) |
+	(params->config_params.col_pat_field0.elop << 4) |
+	(params->config_params.col_pat_field0.elep << 6) |
+	(params->config_params.col_pat_field1.olop << 8) |
+	(params->config_params.col_pat_field1.olep << 10) |
+	(params->config_params.col_pat_field1.elop << 12) |
+	(params->config_params.col_pat_field1.elep << 14);
+	regw(val, CCOLP);
+	dev_dbg(dev, "Writing %x to CCOLP ...\n", val);
+
+	/* Configure HSIZE register  */
+	val =
+	    (params->
+	     horz_flip_en & CCDC_HSIZE_FLIP_MASK) << CCDC_HSIZE_FLIP_SHIFT;
+
+	/* calculate line offset in 32 bytes based on pack value */
+	if (ccdc_cfg.data_pack == CCDC_PACK_8BIT)
+		val |= (((params->win.width + 31) >> 5) & CCDC_LINEOFST_MASK);
+	else if (ccdc_cfg.data_pack == CCDC_PACK_12BIT)
+		val |= ((((params->win.width +
+			   (params->win.width >> 2)) +
+			  31) >> 5) & CCDC_LINEOFST_MASK);
+	else
+		val |=
+		    ((((params->win.width * 2) +
+		       31) >> 5) & CCDC_LINEOFST_MASK);
+	regw(val, HSIZE);
+
+	/* Configure SDOFST register  */
+	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		if (params->image_invert_en) {
+			/* For interlace inverse mode */
+			regw(0x4B6D, SDOFST);
+			dev_dbg(dev, "Writing 0x4B6D to SDOFST...\n");
+		} else {
+			/* For interlace non inverse mode */
+			regw(0x0B6D, SDOFST);
+			dev_dbg(dev, "Writing 0x0B6D to SDOFST...\n");
+		}
+	} else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
+		if (params->image_invert_en) {
+			/* For progessive inverse mode */
+			regw(0x4000, SDOFST);
+			dev_dbg(dev, "Writing 0x4000 to SDOFST...\n");
+		} else {
+			/* For progessive non inverse mode */
+			regw(0x0000, SDOFST);
+			dev_dbg(dev, "Writing 0x0000 to SDOFST...\n");
+		}
+	}
+
+	/* Configure video window */
+	ccdc_setwin(&params->win, params->frm_fmt, 1);
+
+	/* Configure Black Clamp */
+	ccdc_config_bclamp(&module_params->bclamp);
+
+	/* Configure Vertical Defection Pixel Correction */
+	ccdc_config_dfc(&module_params->dfc);
+
+	if (!module_params->df_csc.df_or_csc)
+		/* Configure Color Space Conversion */
+		ccdc_config_csc(&module_params->df_csc);
+
+	ccdc_config_linearization(&module_params->linearize);
+
+	/* Configure Culling */
+	ccdc_config_culling(&module_params->culling);
+
+	/* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */
+	val = module_params->horz_offset & CCDC_DATA_H_OFFSET_MASK;
+	regw(val, DATAHOFST);
+
+	val = module_params->vert_offset & CCDC_DATA_V_OFFSET_MASK;
+	regw(val, DATAVOFST);
+
+	/* Setup test pattern if enabled */
+	if (params->config_params.test_pat_gen) {
+		/* Use the HD/VD pol settings from user */
+		sync.ccdpg_hdpol = params->hd_pol & CCDC_HD_POL_MASK;
+		sync.ccdpg_vdpol = params->vd_pol & CCDC_VD_POL_MASK;
+
+		dm365_vpss_set_sync_pol(sync);
+
+		frame_size.hlpfr = ccdc_cfg.bayer.win.width;
+		frame_size.pplen = ccdc_cfg.bayer.win.height;
+		dm365_vpss_set_pg_frame_size(frame_size);
+		vpss_select_ccdc_source(VPSS_PGLPBK);
+	}
+
+	dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n");
+	return 0;
+}
+
+static int ccdc_validate_df_csc_params(struct ccdc_df_csc *df_csc)
+{
+	struct ccdc_color_space_conv *csc;
+	int i, csc_df_en = 0;
+	int err = -EINVAL;
+
+	if (!df_csc->df_or_csc) {
+		/* csc configuration */
+		csc = &df_csc->csc;
+		if (csc->en) {
+			csc_df_en = 1;
+			for (i = 0; i < CCDC_CSC_NUM_COEFF; i++) {
+				if (csc->coeff[i].integer >
+					CCDC_CSC_COEF_INTEG_MASK ||
+				    csc->coeff[i].decimal >
+					CCDC_CSC_COEF_DECIMAL_MASK) {
+					dev_dbg(dev,
+					       "invalid csc coefficients \n");
+					return err;
+				}
+			}
+		}
+	}
+
+	if (df_csc->start_pix > CCDC_DF_CSC_SPH_MASK) {
+		dev_dbg(dev, "invalid df_csc start pix value \n");
+		return err;
+	}
+	if (df_csc->num_pixels > CCDC_DF_NUMPIX) {
+		dev_dbg(dev, "invalid df_csc num pixels value \n");
+		return err;
+	}
+	if (df_csc->start_line > CCDC_DF_CSC_LNH_MASK) {
+		dev_dbg(dev, "invalid df_csc start_line value \n");
+		return err;
+	}
+	if (df_csc->num_lines > CCDC_DF_NUMLINES) {
+		dev_dbg(dev, "invalid df_csc num_lines value \n");
+		return err;
+	}
+	return 0;
+}
+
+static int ccdc_validate_dfc_params(struct ccdc_dfc *dfc)
+{
+	int err = -EINVAL;
+	int i;
+
+	if (dfc->en) {
+		if (dfc->corr_whole_line > 1) {
+			dev_dbg(dev, "invalid corr_whole_line value \n");
+			return err;
+		}
+
+		if (dfc->def_level_shift > 4) {
+			dev_dbg(dev, "invalid def_level_shift value \n");
+			return err;
+		}
+
+		if (dfc->def_sat_level > 4095) {
+			dev_dbg(dev, "invalid def_sat_level value \n");
+			return err;
+		}
+		if ((!dfc->num_vdefects) || (dfc->num_vdefects > 8)) {
+			dev_dbg(dev, "invalid num_vdefects value \n");
+			return err;
+		}
+		for (i = 0; i < CCDC_VDFC_TABLE_SIZE; i++) {
+			if (dfc->table[i].pos_vert > 0x1fff) {
+				dev_dbg(dev, "invalid pos_vert value \n");
+				return err;
+			}
+			if (dfc->table[i].pos_horz > 0x1fff) {
+				dev_dbg(dev, "invalid pos_horz value \n");
+				return err;
+			}
+		}
+	}
+	return 0;
+}
+
+static int ccdc_validate_bclamp_params(struct ccdc_black_clamp *bclamp)
+{
+	int err = -EINVAL;
+
+	if (bclamp->dc_offset > 0x1fff) {
+		dev_dbg(dev, "invalid bclamp dc_offset value \n");
+		return err;
+	}
+
+	if (bclamp->en) {
+		if (bclamp->horz.clamp_pix_limit > 1) {
+			dev_dbg(dev,
+			       "invalid bclamp horz clamp_pix_limit value \n");
+			return err;
+		}
+
+		if (bclamp->horz.win_count_calc < 1 ||
+		    bclamp->horz.win_count_calc > 32) {
+			dev_dbg(dev,
+			       "invalid bclamp horz win_count_calc value \n");
+			return err;
+		}
+
+		if (bclamp->horz.win_start_h_calc > 0x1fff) {
+			dev_dbg(dev,
+			       "invalid bclamp win_start_v_calc value \n");
+			return err;
+		}
+
+		if (bclamp->horz.win_start_v_calc > 0x1fff) {
+			dev_dbg(dev,
+			       "invalid bclamp win_start_v_calc value \n");
+			return err;
+		}
+
+		if (bclamp->vert.reset_clamp_val > 0xfff) {
+			dev_dbg(dev,
+			       "invalid bclamp reset_clamp_val value \n");
+			return err;
+		}
+
+		if (bclamp->vert.ob_v_sz_calc > 0x1fff) {
+			dev_dbg(dev, "invalid bclamp ob_v_sz_calc value \n");
+			return err;
+		}
+
+		if (bclamp->vert.ob_start_h > 0x1fff) {
+			dev_dbg(dev, "invalid bclamp ob_start_h value \n");
+			return err;
+		}
+
+		if (bclamp->vert.ob_start_v > 0x1fff) {
+			dev_dbg(dev, "invalid bclamp ob_start_h value \n");
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int ccdc_validate_gain_ofst_params(struct ccdc_gain_offsets_adj
+					  *gain_offset)
+{
+	int err = -EINVAL;
+
+	if (gain_offset->gain_sdram_en ||
+	    gain_offset->gain_ipipe_en ||
+	    gain_offset->gain_h3a_en) {
+		if ((gain_offset->gain.r_ye.integer > 7) ||
+		    (gain_offset->gain.r_ye.decimal > 0x1ff)) {
+			dev_dbg(dev, "invalid  gain r_ye\n");
+			return err;
+		}
+		if ((gain_offset->gain.gr_cy.integer > 7) ||
+		    (gain_offset->gain.gr_cy.decimal > 0x1ff)) {
+			dev_dbg(dev, "invalid  gain gr_cy\n");
+			return err;
+		}
+		if ((gain_offset->gain.gb_g.integer > 7) ||
+		    (gain_offset->gain.gb_g.decimal > 0x1ff)) {
+			dev_dbg(dev, "invalid  gain gb_g\n");
+			return err;
+		}
+		if ((gain_offset->gain.b_mg.integer > 7) ||
+		    (gain_offset->gain.b_mg.decimal > 0x1ff)) {
+			dev_dbg(dev, "invalid  gain b_mg\n");
+			return err;
+		}
+	}
+	if (gain_offset->offset_sdram_en ||
+	    gain_offset->offset_ipipe_en ||
+	    gain_offset->offset_h3a_en) {
+		if (gain_offset->offset > 0xfff) {
+			dev_dbg(dev, "invalid  gain b_mg\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+validate_ccdc_config_params_raw(struct ccdc_config_params_raw *params)
+{
+	int err;
+
+	err = ccdc_validate_df_csc_params(&params->df_csc);
+	if (err)
+		goto exit;
+	err = ccdc_validate_dfc_params(&params->dfc);
+	if (err)
+		goto exit;
+	err = ccdc_validate_bclamp_params(&params->bclamp);
+	if (err)
+		goto exit;
+	err = ccdc_validate_gain_ofst_params(&params->gain_offset);
+exit:
+	return err;
+}
+
+static int ccdc_set_buftype(enum ccdc_buftype buf_type)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		ccdc_cfg.bayer.buf_type = buf_type;
+	else
+		ccdc_cfg.ycbcr.buf_type = buf_type;
+
+	return 0;
+
+}
+static enum ccdc_buftype ccdc_get_buftype(void)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		return ccdc_cfg.bayer.buf_type;
+
+	return ccdc_cfg.ycbcr.buf_type;
+}
+
+static int ccdc_enum_pix(u32 *pix, int i)
+{
+	int ret = -EINVAL;
+
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
+			*pix = ccdc_raw_bayer_pix_formats[i];
+			ret = 0;
+		}
+	} else {
+		if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
+			*pix = ccdc_raw_yuv_pix_formats[i];
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+static int ccdc_set_pixel_format(unsigned int pixfmt)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		if (pixfmt == V4L2_PIX_FMT_SBGGR8) {
+			if ((ccdc_cfg.bayer.config_params.compress.alg !=
+					CCDC_ALAW) &&
+			    (ccdc_cfg.bayer.config_params.compress.alg !=
+					CCDC_DPCM)) {
+				dev_dbg(dev, "Either configure A-Law or"
+						"DPCM\n");
+				return -EINVAL;
+			}
+			ccdc_cfg.data_pack = CCDC_PACK_8BIT;
+		} else if (pixfmt == V4L2_PIX_FMT_SBGGR16) {
+			ccdc_cfg.bayer.config_params.compress.alg =
+					CCDC_NO_COMPRESSION;
+			ccdc_cfg.data_pack = CCDC_PACK_16BIT;
+		} else
+			return -EINVAL;
+		ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
+	} else {
+		if (pixfmt == V4L2_PIX_FMT_YUYV)
+			ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
+		else if (pixfmt == V4L2_PIX_FMT_UYVY)
+			ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		else
+			return -EINVAL;
+		ccdc_cfg.data_pack = CCDC_PACK_8BIT;
+	}
+	return 0;
+}
+
+static u32 ccdc_get_pixel_format(void)
+{
+	u32 pixfmt;
+
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		if (ccdc_cfg.bayer.config_params.compress.alg
+			== CCDC_ALAW
+			|| ccdc_cfg.bayer.config_params.compress.alg
+			== CCDC_DPCM)
+				pixfmt = V4L2_PIX_FMT_SBGGR8;
+		else
+			pixfmt = V4L2_PIX_FMT_SBGGR16;
+	else {
+		if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
+			pixfmt = V4L2_PIX_FMT_YUYV;
+		else
+			pixfmt = V4L2_PIX_FMT_UYVY;
+	}
+	return pixfmt;
+}
+
+static int ccdc_set_image_window(struct v4l2_rect *win)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		ccdc_cfg.bayer.win.top = win->top;
+		ccdc_cfg.bayer.win.left = win->left;
+		ccdc_cfg.bayer.win.width = win->width;
+		ccdc_cfg.bayer.win.height = win->height;
+	} else {
+		ccdc_cfg.ycbcr.win.top = win->top;
+		ccdc_cfg.ycbcr.win.left = win->left;
+		ccdc_cfg.ycbcr.win.width = win->width;
+		ccdc_cfg.ycbcr.win.height = win->height;
+	}
+	return 0;
+}
+
+static void ccdc_get_image_window(struct v4l2_rect *win)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		*win = ccdc_cfg.bayer.win;
+	else
+		*win = ccdc_cfg.ycbcr.win;
+}
+
+static unsigned int ccdc_get_line_length(void)
+{
+	unsigned int len;
+
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		if (ccdc_cfg.data_pack == CCDC_PACK_8BIT)
+			len = ((ccdc_cfg.bayer.win.width));
+		else if (ccdc_cfg.data_pack == CCDC_PACK_12BIT)
+			len = (((ccdc_cfg.bayer.win.width * 2) +
+				 (ccdc_cfg.bayer.win.width >> 2)));
+		else
+			len = (((ccdc_cfg.bayer.win.width * 2)));
+	} else
+		len = (((ccdc_cfg.ycbcr.win.width * 2)));
+
+	return ALIGN(len, 32);
+}
+
+static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		ccdc_cfg.bayer.frm_fmt = frm_fmt;
+	else
+		ccdc_cfg.ycbcr.frm_fmt = frm_fmt;
+
+	return 0;
+}
+static enum ccdc_frmfmt ccdc_get_frame_format(void)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		return ccdc_cfg.bayer.frm_fmt;
+	else
+		return ccdc_cfg.ycbcr.frm_fmt;
+}
+
+static int ccdc_getfid(void)
+{
+	return (regr(MODESET) >> 15) & 0x1;
+}
+
+/* misc operations */
+static void ccdc_setfbaddr(unsigned long addr)
+{
+	regw((addr >> 21) & 0x07ff, CADU);
+	regw((addr >> 5) & 0x0ffff, CADL);
+}
+
+static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
+{
+	ccdc_cfg.if_type = params->if_type;
+
+	switch (params->if_type) {
+	case VPFE_BT656:
+	case VPFE_BT656_10BIT:
+	case VPFE_YCBCR_SYNC_8:
+		ccdc_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT;
+		ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		break;
+	case VPFE_BT1120:
+	case VPFE_YCBCR_SYNC_16:
+		ccdc_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_16BIT;
+		ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		break;
+	case VPFE_RAW_BAYER:
+		ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
+		break;
+	default:
+		dev_dbg(dev, "Invalid interface type\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Parameter operations */
+static int ccdc_get_params(void __user *params)
+{
+	/* only raw module parameters can be set through the IOCTL */
+	if (ccdc_cfg.if_type != VPFE_RAW_BAYER)
+		return -EINVAL;
+
+	if (copy_to_user(params,
+			&ccdc_cfg.bayer.config_params,
+			sizeof(ccdc_cfg.bayer.config_params))) {
+		dev_dbg(dev, "ccdc_get_params: error in copying ccdc params\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+/* Parameter operations */
+static int ccdc_set_params(void __user *params)
+{
+	struct ccdc_config_params_raw *ccdc_raw_params;
+	int ret = -EINVAL;
+
+	/* only raw module parameters can be set through the IOCTL */
+	if (ccdc_cfg.if_type != VPFE_RAW_BAYER)
+		return ret;
+
+	ccdc_raw_params = kzalloc(sizeof(*ccdc_raw_params), GFP_KERNEL);
+
+	if (NULL == ccdc_raw_params)
+		return -ENOMEM;
+
+	ret = copy_from_user(ccdc_raw_params,
+			     params, sizeof(*ccdc_raw_params));
+	if (ret) {
+		dev_dbg(dev, "ccdc_set_params: error in copying ccdc"
+			"params, %d\n", ret);
+		ret = -EFAULT;
+		goto free_out;
+	}
+
+	if (!validate_ccdc_config_params_raw(ccdc_raw_params)) {
+		memcpy(&ccdc_cfg.bayer.config_params,
+			ccdc_raw_params,
+			sizeof(*ccdc_raw_params));
+		ret = 0;
+	} else
+		ret = -EINVAL;
+free_out:
+	kfree(ccdc_raw_params);
+	return ret;
+}
+
+/* This function will configure CCDC for YCbCr parameters. */
+static int ccdc_config_ycbcr(void)
+{
+	struct ccdc_ycbcr_config *params = &ccdc_cfg.ycbcr;
+	struct vpss_pg_frame_size frame_size;
+	u32 modeset = 0, ccdcfg = 0;
+	struct vpss_sync_pol sync;
+
+	/**
+	 * first reset the CCDC
+	 * all registers have default values after reset
+	 * This is important since we assume default values to be set in
+	 * a lot of registers that we didn't touch
+	 */
+	dev_dbg(dev, "\nStarting ccdc_config_ycbcr...");
+
+	/* configure pixel format or input mode */
+	modeset = modeset | ((params->pix_fmt & CCDC_INPUT_MASK)
+		<< CCDC_INPUT_SHIFT) |
+	((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
+	(((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT))	|
+	(((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT)) |
+	(((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT));
+
+	/* pack the data to 8-bit CCDCCFG */
+	switch (ccdc_cfg.if_type) {
+	case VPFE_BT656:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -1;
+		}
+		modeset |=
+			((VPFE_PINPOL_NEGATIVE & CCDC_VD_POL_MASK)
+			<< CCDC_VD_POL_SHIFT);
+		regw(3, REC656IF);
+		ccdcfg = ccdcfg | CCDC_DATA_PACK8 | CCDC_YCINSWP_YCBCR;
+		break;
+	case VPFE_BT656_10BIT:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -1;
+		}
+		/* setup BT.656, embedded sync  */
+		regw(3, REC656IF);
+		/* enable 10 bit mode in ccdcfg */
+		ccdcfg = ccdcfg | CCDC_DATA_PACK8 | CCDC_YCINSWP_YCBCR |
+			CCDC_BW656_ENABLE;
+		break;
+	case VPFE_BT1120:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		regw(3, REC656IF);
+		break;
+
+	case VPFE_YCBCR_SYNC_8:
+		ccdcfg |= CCDC_DATA_PACK8;
+		ccdcfg |= CCDC_YCINSWP_YCBCR;
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		break;
+	case VPFE_YCBCR_SYNC_16:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		/* should never come here */
+		dev_dbg(dev, "Invalid interface type\n");
+		return -EINVAL;
+	}
+
+	regw(modeset, MODESET);
+
+	/* Set up pix order */
+	ccdcfg |= (params->pix_order & CCDC_PIX_ORDER_MASK) <<
+		CCDC_PIX_ORDER_SHIFT;
+
+	regw(ccdcfg, CCDCFG);
+
+	/* configure video window */
+	if ((ccdc_cfg.if_type == VPFE_BT1120) ||
+	    (ccdc_cfg.if_type == VPFE_YCBCR_SYNC_16))
+		ccdc_setwin(&params->win, params->frm_fmt, 1);
+	else
+		ccdc_setwin(&params->win, params->frm_fmt, 2);
+
+	/**
+	 * configure the horizontal line offset
+	 * this is done by rounding up width to a multiple of 16 pixels
+	 * and multiply by two to account for y:cb:cr 4:2:2 data
+	 */
+	regw(((((params->win.width * 2) + 31) & 0xffffffe0) >> 5), HSIZE);
+
+	/* configure the memory line offset */
+	if ((params->frm_fmt == CCDC_FRMFMT_INTERLACED) &&
+	    (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED))
+		/* two fields are interleaved in memory */
+		regw(0x00000249, SDOFST);
+
+	/* Setup test pattern if enabled */
+	if (ccdc_cfg.bayer.config_params.test_pat_gen) {
+		sync.ccdpg_hdpol = (params->hd_pol & CCDC_HD_POL_MASK);
+		sync.ccdpg_vdpol = (params->vd_pol & CCDC_VD_POL_MASK);
+		dm365_vpss_set_sync_pol(sync);
+		dm365_vpss_set_pg_frame_size(frame_size);
+	}
+
+	return 0;
+}
+
+static int ccdc_configure(void)
+{
+	if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		return ccdc_config_raw();
+	else
+		ccdc_config_ycbcr();
+
+	return 0;
+}
+
+static int ccdc_close(struct device *device)
+{
+	/* copy defaults to module params */
+	memcpy(&ccdc_cfg.bayer.config_params,
+	       &ccdc_config_defaults,
+	       sizeof(struct ccdc_config_params_raw));
+
+	return 0;
+}
+
+static struct ccdc_hw_device ccdc_hw_dev = {
+	.name = "DM365 ISIF",
+	.owner = THIS_MODULE,
+	.hw_ops = {
+		.open = ccdc_open,
+		.close = ccdc_close,
+		.enable = ccdc_enable,
+		.enable_out_to_sdram = ccdc_enable_output_to_sdram,
+		.set_hw_if_params = ccdc_set_hw_if_params,
+		.set_params = ccdc_set_params,
+		.get_params = ccdc_get_params,
+		.configure = ccdc_configure,
+		.set_buftype = ccdc_set_buftype,
+		.get_buftype = ccdc_get_buftype,
+		.enum_pix = ccdc_enum_pix,
+		.set_pixel_format = ccdc_set_pixel_format,
+		.get_pixel_format = ccdc_get_pixel_format,
+		.set_frame_format = ccdc_set_frame_format,
+		.get_frame_format = ccdc_get_frame_format,
+		.set_image_window = ccdc_set_image_window,
+		.get_image_window = ccdc_get_image_window,
+		.get_line_length = ccdc_get_line_length,
+		.setfbaddr = ccdc_setfbaddr,
+		.getfid = ccdc_getfid,
+	},
+};
+
+static int __init dm365_ccdc_probe(struct platform_device *pdev)
+{
+	static resource_size_t  res_len;
+	struct resource	*res;
+	void *__iomem addr;
+	int status = 0, i;
+
+	/**
+	 * first try to register with vpfe. If not correct platform, then we
+	 * don't have to iomap
+	 */
+	status = vpfe_register_ccdc_device(&ccdc_hw_dev);
+	if (status < 0)
+		return status;
+
+	i = 0;
+	/* Get the ISIF base address, linearization table0 and table1 addr. */
+	while (i < 3) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			status = -ENOENT;
+			goto fail_nobase_res;
+		}
+		res_len = res->end - res->start + 1;
+		res = request_mem_region(res->start, res_len, res->name);
+		if (!res) {
+			status = -EBUSY;
+			goto fail_nobase_res;
+		}
+		addr = ioremap_nocache(res->start, res_len);
+		if (!addr) {
+			status = -EBUSY;
+			goto fail_base_iomap;
+		}
+		switch (i) {
+		case 0:
+			/* ISIF base address */
+			ccdc_cfg.base_addr = addr;
+			break;
+		case 1:
+			/* ISIF linear tbl0 address */
+			ccdc_cfg.linear_tbl0_addr = addr;
+			break;
+		default:
+			/* ISIF linear tbl0 address */
+			ccdc_cfg.linear_tbl1_addr = addr;
+			break;
+		}
+		i++;
+	}
+
+	davinci_cfg_reg(DM365_VIN_CAM_WEN);
+	davinci_cfg_reg(DM365_VIN_CAM_VD);
+	davinci_cfg_reg(DM365_VIN_CAM_HD);
+	davinci_cfg_reg(DM365_VIN_YIN4_7_EN);
+	davinci_cfg_reg(DM365_VIN_YIN0_3_EN);
+
+	printk(KERN_NOTICE "%s is registered with vpfe.\n",
+		ccdc_hw_dev.name);
+	return 0;
+fail_base_iomap:
+	release_mem_region(res->start, res_len);
+	i--;
+fail_nobase_res:
+	if (ccdc_cfg.base_addr)
+		iounmap(ccdc_cfg.base_addr);
+	if (ccdc_cfg.linear_tbl0_addr)
+		iounmap(ccdc_cfg.linear_tbl0_addr);
+
+	while (i >= 0) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		release_mem_region(res->start, res_len);
+		i--;
+	}
+	vpfe_unregister_ccdc_device(&ccdc_hw_dev);
+	return status;
+}
+
+static int dm365_ccdc_remove(struct platform_device *pdev)
+{
+	struct resource	*res;
+	int i = 0;
+
+	iounmap(ccdc_cfg.base_addr);
+	iounmap(ccdc_cfg.linear_tbl0_addr);
+	iounmap(ccdc_cfg.linear_tbl1_addr);
+	while (i < 3) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (res)
+			release_mem_region(res->start,
+					   res->end - res->start + 1);
+		i++;
+	}
+	vpfe_unregister_ccdc_device(&ccdc_hw_dev);
+	return 0;
+}
+
+static struct platform_driver dm365_ccdc_driver = {
+	.driver = {
+		.name	= "dm365_isif",
+		.owner = THIS_MODULE,
+	},
+	.remove = __devexit_p(dm365_ccdc_remove),
+	.probe = dm365_ccdc_probe,
+};
+
+static int dm365_ccdc_init(void)
+{
+	return platform_driver_register(&dm365_ccdc_driver);
+}
+
+
+static void dm365_ccdc_exit(void)
+{
+	platform_driver_unregister(&dm365_ccdc_driver);
+}
+
+module_init(dm365_ccdc_init);
+module_exit(dm365_ccdc_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/dm365_ccdc_regs.h b/drivers/media/video/davinci/dm365_ccdc_regs.h
new file mode 100644
index 0000000..d3f4b13
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ccdc_regs.h
@@ -0,0 +1,293 @@ 
+#ifndef _DM365_CCDC_REGS_H
+#define _DM365_CCDC_REGS_H
+
+/* ISIF registers relative offsets */
+#define SYNCEN					0x00
+#define MODESET					0x04
+#define HDW					0x08
+#define VDW					0x0c
+#define PPLN					0x10
+#define LPFR					0x14
+#define SPH					0x18
+#define LNH					0x1c
+#define SLV0					0x20
+#define SLV1					0x24
+#define LNV					0x28
+#define CULH					0x2c
+#define CULV					0x30
+#define HSIZE					0x34
+#define SDOFST					0x38
+#define CADU					0x3c
+#define CADL					0x40
+#define LINCFG0					0x44
+#define LINCFG1					0x48
+#define CCOLP					0x4c
+#define CRGAIN 					0x50
+#define CGRGAIN					0x54
+#define CGBGAIN					0x58
+#define CBGAIN					0x5c
+#define COFSTA					0x60
+#define FLSHCFG0				0x64
+#define FLSHCFG1				0x68
+#define FLSHCFG2				0x6c
+#define VDINT0					0x70
+#define VDINT1					0x74
+#define VDINT2					0x78
+#define MISC 					0x7c
+#define CGAMMAWD				0x80
+#define REC656IF				0x84
+#define CCDCFG					0x88
+/*****************************************************
+* Defect Correction registers
+*****************************************************/
+#define DFCCTL					0x8c
+#define VDFSATLV				0x90
+#define DFCMEMCTL				0x94
+#define DFCMEM0					0x98
+#define DFCMEM1					0x9c
+#define DFCMEM2					0xa0
+#define DFCMEM3					0xa4
+#define DFCMEM4					0xa8
+/****************************************************
+* Black Clamp registers
+****************************************************/
+#define CLAMPCFG				0xac
+#define CLDCOFST				0xb0
+#define CLSV					0xb4
+#define CLHWIN0					0xb8
+#define CLHWIN1					0xbc
+#define CLHWIN2					0xc0
+#define CLVRV					0xc4
+#define CLVWIN0					0xc8
+#define CLVWIN1					0xcc
+#define CLVWIN2					0xd0
+#define CLVWIN3					0xd4
+/****************************************************
+* Lense Shading Correction
+****************************************************/
+#define DATAHOFST				0xd8
+#define DATAVOFST				0xdc
+#define LSCHVAL					0xe0
+#define LSCVVAL					0xe4
+#define TWODLSCCFG				0xe8
+#define TWODLSCOFST				0xec
+#define TWODLSCINI				0xf0
+#define TWODLSCGRBU				0xf4
+#define TWODLSCGRBL				0xf8
+#define TWODLSCGROF				0xfc
+#define TWODLSCORBU				0x100
+#define TWODLSCORBL				0x104
+#define TWODLSCOROF				0x108
+#define TWODLSCIRQEN				0x10c
+#define TWODLSCIRQST				0x110
+/****************************************************
+* Data formatter
+****************************************************/
+#define FMTCFG					0x114
+#define FMTPLEN					0x118
+#define FMTSPH					0x11c
+#define FMTLNH					0x120
+#define FMTSLV					0x124
+#define FMTLNV					0x128
+#define FMTRLEN					0x12c
+#define FMTHCNT					0x130
+#define FMTAPTR_BASE				0x134
+/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */
+#define FMTAPTR(i)			(FMTAPTR_BASE + (i * 4))
+#define FMTPGMVF0				0x174
+#define FMTPGMVF1				0x178
+#define FMTPGMAPU0				0x17c
+#define FMTPGMAPU1				0x180
+#define FMTPGMAPS0				0x184
+#define FMTPGMAPS1				0x188
+#define FMTPGMAPS2				0x18c
+#define FMTPGMAPS3				0x190
+#define FMTPGMAPS4				0x194
+#define FMTPGMAPS5				0x198
+#define FMTPGMAPS6				0x19c
+#define FMTPGMAPS7				0x1a0
+/************************************************
+* Color Space Converter
+************************************************/
+#define CSCCTL					0x1a4
+#define CSCM0					0x1a8
+#define CSCM1					0x1ac
+#define CSCM2					0x1b0
+#define CSCM3					0x1b4
+#define CSCM4					0x1b8
+#define CSCM5					0x1bc
+#define CSCM6					0x1c0
+#define CSCM7					0x1c4
+#define OBWIN0					0x1c8
+#define OBWIN1					0x1cc
+#define OBWIN2					0x1d0
+#define OBWIN3					0x1d4
+#define OBVAL0					0x1d8
+#define OBVAL1					0x1dc
+#define OBVAL2					0x1e0
+#define OBVAL3					0x1e4
+#define OBVAL4					0x1e8
+#define OBVAL5					0x1ec
+#define OBVAL6					0x1f0
+#define OBVAL7					0x1f4
+#define CLKCTL					0x1f8
+
+#define CCDC_LINEAR_LUT0_ADDR			0x1C7C000
+#define CCDC_LINEAR_LUT1_ADDR			0x1C7C400
+
+/* Masks & Shifts below */
+#define START_PX_HOR_MASK			(0x7FFF)
+#define NUM_PX_HOR_MASK				(0x7FFF)
+#define START_VER_ONE_MASK			(0x7FFF)
+#define START_VER_TWO_MASK			(0x7FFF)
+#define NUM_LINES_VER				(0x7FFF)
+
+/* gain - offset masks */
+#define GAIN_INTEGER_MASK			(0x7)
+#define GAIN_INTEGER_SHIFT			(0x9)
+#define GAIN_DECIMAL_MASK			(0x1FF)
+#define OFFSET_MASK			  	(0xFFF)
+#define GAIN_SDRAM_EN_SHIFT			(12)
+#define GAIN_IPIPE_EN_SHIFT			(13)
+#define GAIN_H3A_EN_SHIFT			(14)
+#define OFST_SDRAM_EN_SHIFT			(8)
+#define OFST_IPIPE_EN_SHIFT			(9)
+#define OFST_H3A_EN_SHIFT			(10)
+#define GAIN_OFFSET_EN_MASK			(0x7700)
+
+/* Culling */
+#define CULL_PAT_EVEN_LINE_SHIFT		(8)
+
+/* CCDCFG register */
+#define CCDC_YCINSWP_RAW			(0x00 << 4)
+#define CCDC_YCINSWP_YCBCR			(0x01 << 4)
+#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC		(0x00 << 6)
+#define CCDC_CCDCFG_WENLOG_AND			(0x00 << 8)
+#define CCDC_CCDCFG_TRGSEL_WEN			(0x00 << 9)
+#define CCDC_CCDCFG_EXTRG_DISABLE		(0x00 << 10)
+#define CCDC_LATCH_ON_VSYNC_DISABLE		(0x01 << 15)
+#define CCDC_LATCH_ON_VSYNC_ENABLE		(0x00 << 15)
+#define CCDC_DATA_PACK_MASK			(0x03)
+#define CCDC_DATA_PACK16			(0x0)
+#define CCDC_DATA_PACK12			(0x1)
+#define CCDC_DATA_PACK8				(0x2)
+#define CCDC_PIX_ORDER_SHIFT			(11)
+#define CCDC_PIX_ORDER_MASK			(0x01)
+#define CCDC_BW656_ENABLE			(0x01 << 5)
+
+/* MODESET registers */
+#define CCDC_VDHDOUT_INPUT			(0x00 << 0)
+#define CCDC_INPUT_MASK				(0x03)
+#define CCDC_INPUT_SHIFT			(12)
+#define CCDC_RAW_INPUT_MODE			(0x00)
+#define CCDC_FID_POL_MASK			(0x01)
+#define CCDC_FID_POL_SHIFT			(4)
+#define CCDC_HD_POL_MASK			(0x01)
+#define CCDC_HD_POL_SHIFT			(3)
+#define CCDC_VD_POL_MASK			(0x01)
+#define CCDC_VD_POL_SHIFT			(2)
+#define CCDC_DATAPOL_NORMAL			(0x00)
+#define CCDC_DATAPOL_MASK			(0x01)
+#define CCDC_DATAPOL_SHIFT			(6)
+#define CCDC_EXWEN_DISABLE 			(0x00)
+#define CCDC_EXWEN_MASK				(0x01)
+#define CCDC_EXWEN_SHIFT			(5)
+#define CCDC_FRM_FMT_MASK			(0x01)
+#define CCDC_FRM_FMT_SHIFT			(7)
+#define CCDC_DATASFT_MASK			(0x07)
+#define CCDC_DATASFT_SHIFT			(8)
+#define CCDC_LPF_SHIFT				(14)
+#define CCDC_LPF_MASK				(0x1)
+
+/* GAMMAWD registers */
+#define CCDC_ALAW_GAMA_WD_MASK			(0xF)
+#define CCDC_ALAW_GAMA_WD_SHIFT			(1)
+#define CCDC_ALAW_ENABLE			(0x01)
+#define CCDC_GAMMAWD_CFA_MASK			(0x01)
+#define CCDC_GAMMAWD_CFA_SHIFT			(5)
+
+/* HSIZE registers */
+#define CCDC_HSIZE_FLIP_MASK			(0x01)
+#define CCDC_HSIZE_FLIP_SHIFT			(12)
+#define CCDC_LINEOFST_MASK			(0xFFF)
+
+/* MISC registers */
+#define CCDC_DPCM_EN_SHIFT			(12)
+#define CCDC_DPCM_EN_MASK			(1)
+#define CCDC_DPCM_PREDICTOR_SHIFT		(13)
+#define CCDC_DPCM_PREDICTOR_MASK 		(1)
+
+/* Black clamp related */
+#define CCDC_BC_DCOFFSET_MASK			(0x1FFF)
+#define CCDC_BC_MODE_COLOR_MASK			(1)
+#define CCDC_BC_MODE_COLOR_SHIFT		(4)
+#define CCDC_HORZ_BC_MODE_MASK			(3)
+#define CCDC_HORZ_BC_MODE_SHIFT			(1)
+#define CCDC_HORZ_BC_WIN_COUNT_MASK		(0x1F)
+#define CCDC_HORZ_BC_WIN_SEL_SHIFT		(5)
+#define CCDC_HORZ_BC_PIX_LIMIT_SHIFT		(6)
+#define CCDC_HORZ_BC_WIN_H_SIZE_MASK		(3)
+#define CCDC_HORZ_BC_WIN_H_SIZE_SHIFT		(8)
+#define CCDC_HORZ_BC_WIN_V_SIZE_MASK		(3)
+#define CCDC_HORZ_BC_WIN_V_SIZE_SHIFT		(12)
+#define CCDC_HORZ_BC_WIN_START_H_MASK		(0x1FFF)
+#define CCDC_HORZ_BC_WIN_START_V_MASK		(0x1FFF)
+#define CCDC_VERT_BC_OB_H_SZ_MASK		(7)
+#define CCDC_VERT_BC_RST_VAL_SEL_MASK		(3)
+#define	CCDC_VERT_BC_RST_VAL_SEL_SHIFT		(4)
+#define CCDC_VERT_BC_LINE_AVE_COEF_SHIFT	(8)
+#define	CCDC_VERT_BC_OB_START_HORZ_MASK		(0x1FFF)
+#define CCDC_VERT_BC_OB_START_VERT_MASK		(0x1FFF)
+#define CCDC_VERT_BC_OB_VERT_SZ_MASK		(0x1FFF)
+#define CCDC_VERT_BC_RST_VAL_MASK		(0xFFF)
+#define CCDC_BC_VERT_START_SUB_V_MASK		(0x1FFF)
+
+/* VDFC registers */
+#define CCDC_VDFC_EN_SHIFT			(4)
+#define CCDC_VDFC_CORR_MOD_MASK			(3)
+#define CCDC_VDFC_CORR_MOD_SHIFT		(5)
+#define CCDC_VDFC_CORR_WHOLE_LN_SHIFT		(7)
+#define CCDC_VDFC_LEVEL_SHFT_MASK		(7)
+#define CCDC_VDFC_LEVEL_SHFT_SHIFT		(8)
+#define CCDC_VDFC_SAT_LEVEL_MASK		(0xFFF)
+#define CCDC_VDFC_POS_MASK			(0x1FFF)
+#define CCDC_DFCMEMCTL_DFCMARST_SHIFT		(2)
+
+/* CSC registers */
+#define CCDC_CSC_COEF_INTEG_MASK		(7)
+#define CCDC_CSC_COEF_DECIMAL_MASK		(0x1f)
+#define CCDC_CSC_COEF_INTEG_SHIFT		(5)
+#define CCDC_CSCM_MSB_SHIFT			(8)
+#define CCDC_DF_CSC_SPH_MASK			(0x1FFF)
+#define CCDC_DF_CSC_LNH_MASK			(0x1FFF)
+#define CCDC_DF_CSC_SLV_MASK			(0x1FFF)
+#define CCDC_DF_CSC_LNV_MASK			(0x1FFF)
+#define CCDC_DF_NUMLINES			(0x7FFF)
+#define CCDC_DF_NUMPIX				(0x1FFF)
+
+/* Offsets for LSC/DFC/Gain */
+#define CCDC_DATA_H_OFFSET_MASK			(0x1FFF)
+#define CCDC_DATA_V_OFFSET_MASK			(0x1FFF)
+
+/* Linearization */
+#define CCDC_LIN_CORRSFT_MASK			(7)
+#define CCDC_LIN_CORRSFT_SHIFT			(4)
+#define CCDC_LIN_SCALE_FACT_INTEG_SHIFT		(10)
+#define CCDC_LIN_SCALE_FACT_DECIMAL_MASK	(0x3FF)
+#define CCDC_LIN_ENTRY_MASK			(0x3FF)
+
+#define CCDC_DF_FMTRLEN_MASK			(0x1FFF)
+#define CCDC_DF_FMTHCNT_MASK			(0x1FFF)
+
+/* Pattern registers */
+#define CCDC_PG_EN				(1 << 3)
+#define CCDC_SEL_PG_SRC				(3 << 4)
+#define CCDC_PG_VD_POL_SHIFT			(0)
+#define CCDC_PG_HD_POL_SHIFT			(1)
+
+/*random other junk*/
+#define CCDC_SYNCEN_VDHDEN_MASK			(1 << 0)
+#define CCDC_SYNCEN_WEN_MASK			(1 << 1)
+#define CCDC_SYNCEN_WEN_SHIFT			1
+
+#endif
diff --git a/include/media/davinci/dm365_ccdc.h b/include/media/davinci/dm365_ccdc.h
new file mode 100644
index 0000000..1ce52a7
--- /dev/null
+++ b/include/media/davinci/dm365_ccdc.h
@@ -0,0 +1,555 @@ 
+/*
+ * Copyright (C) 2008-2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ccdc header file for DM365 ISIF
+ */
+#ifndef _DM365_CCDC_H
+#define _DM365_CCDC_H
+#include <media/davinci/ccdc_types.h>
+#include <media/davinci/vpfe_types.h>
+/* ccdc float type S8Q8/U8Q8 */
+struct ccdc_float_8 {
+	/* 8 bit integer part */
+	__u8 integer;
+	/* 8 bit decimal part */
+	__u8 decimal;
+};
+
+/* brief ccdc float type U16Q16/S16Q16 */
+struct ccdc_float_16 {
+	/* 16 bit integer part */
+	__u16 integer;
+	/* 16 bit decimal part */
+	__u16 decimal;
+};
+
+/************************************************************************
+ *   Vertical Defect Correction parameters
+ ***********************************************************************/
+/* Defect Correction (DFC) table entry */
+struct ccdc_vdfc_entry {
+	/* vertical position of defect */
+	__u16 pos_vert;
+	/* horizontal position of defect */
+	__u16 pos_horz;
+	/*
+	 * Defect level of Vertical line defect position. This is subtracted
+	 * from the data at the defect position
+	 */
+	__u8 level_at_pos;
+	/*
+	 * Defect level of the pixels upper than the vertical line defect.
+	 * This is subtracted from the data
+	 */
+	__u8 level_up_pixels;
+	/*
+	 * Defect level of the pixels lower than the vertical line defect.
+	 * This is subtracted from the data
+	 */
+	__u8 level_low_pixels;
+};
+
+#define CCDC_VDFC_TABLE_SIZE		8
+struct ccdc_dfc {
+	/* enable vertical defect correction */
+	__u8 en;
+	/* Defect level subtraction. Just fed through if saturating */
+#define	CCDC_VDFC_NORMAL		0
+	/*
+	 * Defect level subtraction. Horizontal interpolation ((i-2)+(i+2))/2
+	 * if data saturating
+	 */
+#define CCDC_VDFC_HORZ_INTERPOL_IF_SAT	1
+	/* Horizontal interpolation (((i-2)+(i+2))/2) */
+#define	CCDC_VDFC_HORZ_INTERPOL		2
+	/* one of the vertical defect correction modes above */
+	__u8 corr_mode;
+	/* 0 - whole line corrected, 1 - not pixels upper than the defect */
+	__u8 corr_whole_line;
+#define CCDC_VDFC_NO_SHIFT		0
+#define CCDC_VDFC_SHIFT_1		1
+#define CCDC_VDFC_SHIFT_2		2
+#define CCDC_VDFC_SHIFT_3		3
+#define CCDC_VDFC_SHIFT_4		4
+	/*
+	 * defect level shift value. level_at_pos, level_upper_pos,
+	 * and level_lower_pos can be shifted up by this value. Choose
+	 * one of the values above
+	 */
+	__u8 def_level_shift;
+	/* defect saturation level */
+	__u16 def_sat_level;
+	/* number of vertical defects. Max is CCDC_VDFC_TABLE_SIZE */
+	__u16 num_vdefects;
+	/* VDFC table ptr */
+	struct ccdc_vdfc_entry table[CCDC_VDFC_TABLE_SIZE];
+};
+
+struct ccdc_horz_bclamp {
+
+	/* Horizontal clamp disabled. Only vertical clamp value is subtracted */
+#define	CCDC_HORZ_BC_DISABLE		0
+	/*
+	 * Horizontal clamp value is calculated and subtracted from image data
+	 * along with vertical clamp value
+	 */
+#define CCDC_HORZ_BC_CLAMP_CALC_ENABLED	1
+	/*
+	 * Horizontal clamp value calculated from previous image is subtracted
+	 * from image data along with vertical clamp value.
+	 */
+#define CCDC_HORZ_BC_CLAMP_NOT_UPDATED	2
+	/* horizontal clamp mode. One of the values above */
+	__u8 mode;
+	/*
+	 * pixel value limit enable.
+	 *  0 - limit disabled
+	 *  1 - pixel value limited to 1023
+	 */
+	__u8 clamp_pix_limit;
+	/* Select Most left window for bc calculation */
+#define	CCDC_SEL_MOST_LEFT_WIN		0
+	/* Select Most right window for bc calculation */
+#define CCDC_SEL_MOST_RIGHT_WIN		1
+	/* Select most left or right window for clamp val calculation */
+	__u8 base_win_sel_calc;
+	/* Window count per color for calculation. range 1-32 */
+	__u8 win_count_calc;
+	/* Window start position - horizontal for calculation. 0 - 8191 */
+	__u16 win_start_h_calc;
+	/* Window start position - vertical for calculation 0 - 8191 */
+	__u16 win_start_v_calc;
+#define CCDC_HORZ_BC_SZ_H_2PIXELS	0
+#define CCDC_HORZ_BC_SZ_H_4PIXELS	1
+#define CCDC_HORZ_BC_SZ_H_8PIXELS	2
+#define CCDC_HORZ_BC_SZ_H_16PIXELS	3
+	/* Width of the sample window in pixels for calculation */
+	__u8 win_h_sz_calc;
+#define CCDC_HORZ_BC_SZ_V_32PIXELS	0
+#define CCDC_HORZ_BC_SZ_V_64PIXELS	1
+#define	CCDC_HORZ_BC_SZ_V_128PIXELS	2
+#define CCDC_HORZ_BC_SZ_V_256PIXELS	3
+	/* Height of the sample window in pixels for calculation */
+	__u8 win_v_sz_calc;
+};
+
+/************************************************************************
+ *  Black Clamp parameters
+ ***********************************************************************/
+struct ccdc_vert_bclamp {
+	/* Reset value used is the clamp value calculated */
+#define	CCDC_VERT_BC_USE_HORZ_CLAMP_VAL		0
+	/* Reset value used is reset_clamp_val configured */
+#define	CCDC_VERT_BC_USE_CONFIG_CLAMP_VAL	1
+	/* No update, previous image value is used */
+#define	CCDC_VERT_BC_NO_UPDATE			2
+	/*
+	 * Reset value selector for vertical clamp calculation. Use one of
+	 * the above values
+	 */
+	__u8 reset_val_sel;
+	/* U12 value if reset_val_sel = CCDC_BC_VERT_USE_CONFIG_CLAMP_VAL */
+	__u16 reset_clamp_val;
+	/* U8Q8. Line average coefficient used in vertical clamp calculation */
+	__u8 line_ave_coef;
+#define	CCDC_VERT_BC_SZ_H_2PIXELS	0
+#define CCDC_VERT_BC_SZ_H_4PIXELS	1
+#define	CCDC_VERT_BC_SZ_H_8PIXELS	2
+#define	CCDC_VERT_BC_SZ_H_16PIXELS	3
+#define	CCDC_VERT_BC_SZ_H_32PIXELS	4
+#define	CCDC_VERT_BC_SZ_H_64PIXELS	5
+	/* Width in pixels of the optical black region used for calculation */
+	__u8 ob_h_sz_calc;
+	/* Height of the optical black region for calculation */
+	__u16 ob_v_sz_calc;
+	/* Optical black region start position - horizontal. 0 - 8191 */
+	__u16 ob_start_h;
+	/* Optical black region start position - vertical 0 - 8191 */
+	__u16 ob_start_v;
+};
+
+struct ccdc_black_clamp {
+	/*
+	 * This offset value is added irrespective of the clamp enable status.
+	 * S13
+	 */
+	__u16 dc_offset;
+	/*
+	 * Enable black/digital clamp value to be subtracted from the image data
+	 */
+	__u8 en;
+	/*
+	 * black clamp mode. same/separate clamp for 4 colors
+	 * 0 - disable - same clamp value for all colors
+	 * 1 - clamp value calculated separately for all colors
+	 */
+	__u8 bc_mode_color;
+	/* Vrtical start position for bc subtraction */
+	__u16 vert_start_sub;
+	/* Black clamp for horizontal direction */
+	struct ccdc_horz_bclamp horz;
+	/* Black clamp for vertical direction */
+	struct ccdc_vert_bclamp vert;
+};
+
+/*************************************************************************
+** Color Space Convertion (CSC)
+*************************************************************************/
+#define CCDC_CSC_NUM_COEFF	16
+struct ccdc_color_space_conv {
+	/* Enable color space conversion */
+	__u8 en;
+	/*
+	 * csc coeffient table. S8Q5, M00 at index 0, M01 at index 1, and
+	 * so forth
+	 */
+	struct ccdc_float_8 coeff[CCDC_CSC_NUM_COEFF];
+};
+
+
+/*************************************************************************
+**  Black  Compensation parameters
+*************************************************************************/
+struct ccdc_black_comp {
+	/* Comp for Red */
+	__s8 r_comp;
+	/* Comp for Gr */
+	__s8 gr_comp;
+	/* Comp for Blue */
+	__s8 b_comp;
+	/* Comp for Gb */
+	__s8 gb_comp;
+};
+
+/*************************************************************************
+**  Gain parameters
+*************************************************************************/
+struct ccdc_gain {
+	/* Gain for Red or ye */
+	struct ccdc_float_16 r_ye;
+	/* Gain for Gr or cy */
+	struct ccdc_float_16 gr_cy;
+	/* Gain for Gb or g */
+	struct ccdc_float_16 gb_g;
+	/* Gain for Blue or mg */
+	struct ccdc_float_16 b_mg;
+};
+
+#define CCDC_LINEAR_TAB_SIZE	192
+/*************************************************************************
+**  Linearization parameters
+*************************************************************************/
+struct ccdc_linearize {
+	/* Enable or Disable linearization of data */
+	__u8 en;
+	/* Shift value applied */
+	__u8 corr_shft;
+	/* scale factor applied U11Q10 */
+	struct ccdc_float_16 scale_fact;
+	/* Size of the linear table */
+	__u16 table[CCDC_LINEAR_TAB_SIZE];
+};
+
+/* Color patterns */
+#define CCDC_RED	0
+#define	CCDC_GREEN_RED	1
+#define CCDC_GREEN_BLUE	2
+#define CCDC_BLUE	3
+struct ccdc_col_pat {
+	__u8 olop;
+	__u8 olep;
+	__u8 elop;
+	__u8 elep;
+};
+
+/*************************************************************************
+**  Data formatter parameters
+*************************************************************************/
+struct ccdc_fmtplen {
+	/*
+	 * number of program entries for SET0, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	__u16 plen0;
+	/*
+	 * number of program entries for SET1, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	__u16 plen1;
+	/**
+	 * number of program entries for SET2, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	__u16 plen2;
+	/**
+	 * number of program entries for SET3, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	__u16 plen3;
+};
+
+struct ccdc_fmt_cfg {
+#define CCDC_SPLIT		0
+#define CCDC_COMBINE		1
+	/* Split or combine or line alternate */
+	__u8 fmtmode;
+	/* enable or disable line alternating mode */
+	__u8 ln_alter_en;
+#define CCDC_1LINE		0
+#define	CCDC_2LINES		1
+#define	CCDC_3LINES		2
+#define	CCDC_4LINES		3
+	/* Split/combine line number */
+	__u8 lnum;
+	/* Address increment Range 1 - 16 */
+	__u8 addrinc;
+};
+
+struct ccdc_fmt_addr_ptr {
+	/* Initial address */
+	__u32 init_addr;
+	/* output line number */
+#define CCDC_1STLINE		0
+#define	CCDC_2NDLINE		1
+#define	CCDC_3RDLINE		2
+#define	CCDC_4THLINE		3
+	__u8 out_line;
+};
+
+struct ccdc_fmtpgm_ap {
+	/* program address pointer */
+	__u8 pgm_aptr;
+	/* program address increment or decrement */
+	__u8 pgmupdt;
+};
+
+struct ccdc_data_formatter {
+	/* Enable/Disable data formatter */
+	__u8 en;
+	/* data formatter configuration */
+	struct ccdc_fmt_cfg cfg;
+	/* Formatter program entries length */
+	struct ccdc_fmtplen plen;
+	/* first pixel in a line fed to formatter */
+	__u16 fmtrlen;
+	/* HD interval for output line. Only valid when split line */
+	__u16 fmthcnt;
+	/* formatter address pointers */
+	struct ccdc_fmt_addr_ptr fmtaddr_ptr[16];
+	/* program enable/disable */
+	__u8 pgm_en[32];
+	/* program address pointers */
+	struct ccdc_fmtpgm_ap fmtpgm_ap[32];
+};
+
+struct ccdc_df_csc {
+	/* Color Space Conversion confguration, 0 - csc, 1 - df */
+	__u8 df_or_csc;
+	/* csc configuration valid if df_or_csc is 0 */
+	struct ccdc_color_space_conv csc;
+	/* data formatter configuration valid if df_or_csc is 1 */
+	struct ccdc_data_formatter df;
+	/* start pixel in a line at the input */
+	__u32 start_pix;
+	/* number of pixels in input line */
+	__u32 num_pixels;
+	/* start line at the input */
+	__u32 start_line;
+	/* number of lines at the input */
+	__u32 num_lines;
+};
+
+struct ccdc_gain_offsets_adj {
+	/* Gain adjustment per color */
+	struct ccdc_gain gain;
+	/* Offset adjustment */
+	__u16 offset;
+	/* Enable or Disable Gain adjustment for SDRAM data */
+	__u8 gain_sdram_en;
+	/* Enable or Disable Gain adjustment for IPIPE data */
+	__u8 gain_ipipe_en;
+	/* Enable or Disable Gain adjustment for H3A data */
+	__u8 gain_h3a_en;
+	/* Enable or Disable Gain adjustment for SDRAM data */
+	__u8 offset_sdram_en;
+	/* Enable or Disable Gain adjustment for IPIPE data */
+	__u8 offset_ipipe_en;
+	/* Enable or Disable Gain adjustment for H3A data */
+	__u8 offset_h3a_en;
+};
+
+struct ccdc_cul {
+	/* Horizontal Cull pattern for odd lines */
+	__u8 hcpat_odd;
+	/* Horizontal Cull pattern for even lines */
+	__u8 hcpat_even;
+	/* Vertical Cull pattern */
+	__u8 vcpat;
+	/* Enable or disable lpf. Apply when cull is enabled */
+	__u8 en_lpf;
+};
+
+struct ccdc_compress {
+#define CCDC_ALAW		0
+#define CCDC_DPCM		1
+#define CCDC_NO_COMPRESSION	2
+	/* Compression Algorithm used */
+	__u8 alg;
+	/* Choose Predictor1 for DPCM compression */
+#define CCDC_DPCM_PRED1		0
+	/* Choose Predictor2 for DPCM compression */
+#define CCDC_DPCM_PRED2		1
+	/* Predictor for DPCM compression */
+	__u8 pred;
+};
+
+/* all the stuff in this struct will be provided by userland */
+struct ccdc_config_params_raw {
+	/* Linearization parameters for image sensor data input */
+	struct ccdc_linearize linearize;
+	/* Data formatter or CSC */
+	struct ccdc_df_csc df_csc;
+	/* Defect Pixel Correction (DFC) confguration */
+	struct ccdc_dfc dfc;
+	/* Black/Digital Clamp configuration */
+	struct ccdc_black_clamp bclamp;
+	/* Gain, offset adjustments */
+	struct ccdc_gain_offsets_adj gain_offset;
+	/* Culling */
+	struct ccdc_cul culling;
+	/* A-Law and DPCM compression options */
+	struct ccdc_compress compress;
+	/* horizontal offset for Gain/LSC/DFC */
+	__u16 horz_offset;
+	/* vertical offset for Gain/LSC/DFC */
+	__u16 vert_offset;
+	/* color pattern for field 0 */
+	struct ccdc_col_pat col_pat_field0;
+	/* color pattern for field 1 */
+	struct ccdc_col_pat col_pat_field1;
+	/* No Shift */
+#define CCDC_NO_SHIFT		0
+	/* 1 bit Shift */
+#define	CCDC_1BIT_SHIFT		1
+	/* 2 bit Shift */
+#define	CCDC_2BIT_SHIFT		2
+	/* 3 bit Shift */
+#define	CCDC_3BIT_SHIFT		3
+	/* 4 bit Shift */
+#define	CCDC_4BIT_SHIFT		4
+	/* 5 bit Shift */
+#define CCDC_5BIT_SHIFT		5
+	/* 6 bit Shift */
+#define CCDC_6BIT_SHIFT		6
+	/* Data shift applied before storing to SDRAM */
+	__u8 data_shift;
+	/* enable input test pattern generation */
+	__u8 test_pat_gen;
+};
+
+#ifdef __KERNEL__
+struct ccdc_ycbcr_config {
+	/* ccdc pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* ccdc frame format */
+	enum ccdc_frmfmt frm_fmt;
+	/* CCDC crop window */
+	struct v4l2_rect win;
+	/* field polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* interface VD polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* interface HD polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* ccdc pix order. Only used for ycbcr capture */
+	enum ccdc_pixorder pix_order;
+	/* ccdc buffer type. Only used for ycbcr capture */
+	enum ccdc_buftype buf_type;
+};
+
+/* MSB of image data connected to sensor port */
+enum ccdc_data_msb {
+	/* MSB b15 */
+	CCDC_BIT_MSB_15,
+	/* MSB b14 */
+	CCDC_BIT_MSB_14,
+	/* MSB b13 */
+	CCDC_BIT_MSB_13,
+	/* MSB b12 */
+	CCDC_BIT_MSB_12,
+	/* MSB b11 */
+	CCDC_BIT_MSB_11,
+	/* MSB b10 */
+	CCDC_BIT_MSB_10,
+	/* MSB b9 */
+	CCDC_BIT_MSB_9,
+	/* MSB b8 */
+	CCDC_BIT_MSB_8,
+	/* MSB b7 */
+	CCDC_BIT_MSB_7
+};
+
+enum ccdc_cfa_pattern {
+	CCDC_CFA_PAT_MOSAIC,
+	CCDC_CFA_PAT_STRIPE
+};
+
+struct ccdc_params_raw {
+	/* ccdc pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* ccdc frame format */
+	enum ccdc_frmfmt frm_fmt;
+	/* video window */
+	struct v4l2_rect win;
+	/* field polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* interface VD polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* interface HD polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* buffer type. Applicable for interlaced mode */
+	enum ccdc_buftype buf_type;
+	/* Gain values */
+	struct ccdc_gain gain;
+	/* cfa pattern */
+	enum ccdc_cfa_pattern cfa_pat;
+	/* Data MSB position */
+	enum ccdc_data_msb data_msb;
+	/* Enable horizontal flip */
+	unsigned char horz_flip_en;
+	/* Enable image invert vertically */
+	unsigned char image_invert_en;
+
+	/* all the userland defined stuff*/
+	struct ccdc_config_params_raw config_params;
+};
+
+enum ccdc_data_pack {
+	CCDC_PACK_16BIT,
+	CCDC_PACK_12BIT,
+	CCDC_PACK_8BIT
+};
+
+#define CCDC_WIN_NTSC				{0, 0, 720, 480}
+#define CCDC_WIN_VGA				{0, 0, 640, 480}
+#define ISP5_CCDCMUX				0x20
+#endif
+#endif