[PATCH v4 4/9] davinci: vpfe: dm365: add ISIF driver based on media framework

Prabhakar Lad prabhakar.csengg at gmail.com
Fri Nov 30 12:01:14 UTC 2012


From: Manjunath Hadli <manjunath.hadli at ti.com>

add support for ISIF as a subdevice for dm365 vpfe capture driver.
ISIF is responsible for capturing video data both in raw bayer format
on sync seperate signals and YUV through BT656/1120 interfaces.
ISIF is exposed as a subdev for the vpfe driver and allows users to
use the driver through standard media controller interface.

Signed-off-by: Manjunath Hadli <manjunath.hadli at ti.com>
Signed-off-by: Lad, Prabhakar <prabhakar.lad at ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus at iki.fi>
Acked-by: Hans Verkuil <hans.verkuil at cisco.com>
---
 drivers/staging/media/davinci_vpfe/dm365_isif.c    | 2104 ++++++++++++++++++++
 drivers/staging/media/davinci_vpfe/dm365_isif.h    |  203 ++
 .../staging/media/davinci_vpfe/dm365_isif_regs.h   |  294 +++
 3 files changed, 2601 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/media/davinci_vpfe/dm365_isif.c
 create mode 100644 drivers/staging/media/davinci_vpfe/dm365_isif.h
 create mode 100644 drivers/staging/media/davinci_vpfe/dm365_isif_regs.h

diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
new file mode 100644
index 0000000..ebeea72
--- /dev/null
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
@@ -0,0 +1,2104 @@
+/*
+ * Copyright (C) 2012 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 version 2.
+ *
+ * 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
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli at ti.com>
+ *      Prabhakar Lad <prabhakar.lad at ti.com>
+ */
+
+#include "dm365_isif.h"
+#include "vpfe_mc_capture.h"
+
+#define MAX_WIDTH	4096
+#define MAX_HEIGHT	4096
+
+static const unsigned int isif_fmts[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_YUYV8_1X16,
+	V4L2_MBUS_FMT_YUYV10_1X20,
+	V4L2_MBUS_FMT_SGRBG12_1X12,
+	V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
+	V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+};
+
+#define ISIF_COLPTN_R_Ye	0x0
+#define ISIF_COLPTN_Gr_Cy	0x1
+#define ISIF_COLPTN_Gb_G	0x2
+#define ISIF_COLPTN_B_Mg	0x3
+
+#define ISIF_CCOLP_CP01_0	0
+#define ISIF_CCOLP_CP03_2	2
+#define ISIF_CCOLP_CP05_4	4
+#define ISIF_CCOLP_CP07_6	6
+#define ISIF_CCOLP_CP11_0	8
+#define ISIF_CCOLP_CP13_2	10
+#define ISIF_CCOLP_CP15_4	12
+#define ISIF_CCOLP_CP17_6	14
+
+static const u32 isif_sgrbg_pattern =
+	ISIF_COLPTN_Gr_Cy <<  ISIF_CCOLP_CP01_0 |
+	ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP03_2 |
+	ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP05_4 |
+	ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP07_6 |
+	ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP11_0 |
+	ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP13_2 |
+	ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP15_4 |
+	ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP17_6;
+
+static const u32 isif_srggb_pattern =
+	ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP01_0 |
+	ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP03_2 |
+	ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP05_4 |
+	ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP07_6 |
+	ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP11_0 |
+	ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP13_2 |
+	ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP15_4 |
+	ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP17_6;
+
+static inline u32 isif_read(void *__iomem base_addr, u32 offset)
+{
+	return readl(base_addr + offset);
+}
+
+static inline void isif_write(void *__iomem base_addr, u32 val, u32 offset)
+{
+	writel(val, base_addr + offset);
+}
+
+static inline u32 isif_merge(void *__iomem base_addr, u32 mask, u32 val,
+			     u32 offset)
+{
+	u32 new_val = (isif_read(base_addr, offset) & ~mask) | (val & mask);
+
+	isif_write(base_addr, new_val, offset);
+
+	return new_val;
+}
+
+static void isif_enable_output_to_sdram(struct vpfe_isif_device *isif, int en)
+{
+	isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_WEN_MASK,
+		   en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN);
+}
+
+static inline void
+isif_regw_lin_tbl(struct vpfe_isif_device *isif, u32 val, u32 offset, int i)
+{
+	if (!i)
+		writel(val, isif->isif_cfg.linear_tbl0_addr + offset);
+	else
+		writel(val, isif->isif_cfg.linear_tbl1_addr + offset);
+}
+
+static void isif_disable_all_modules(struct vpfe_isif_device *isif)
+{
+	/* disable BC */
+	isif_write(isif->isif_cfg.base_addr, 0, CLAMPCFG);
+	/* disable vdfc */
+	isif_write(isif->isif_cfg.base_addr, 0, DFCCTL);
+	/* disable CSC */
+	isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
+	/* disable linearization */
+	isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
+}
+
+static void isif_enable(struct vpfe_isif_device *isif, int en)
+{
+	if (!en)
+		/* Before disable isif, disable all ISIF modules */
+		isif_disable_all_modules(isif);
+
+	/*
+	 * wait for next VD. Assume lowest scan rate is 12 Hz. So
+	 * 100 msec delay is good enough
+	 */
+	msleep(100);
+	isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_VDHDEN_MASK,
+		   en, SYNCEN);
+}
+
+/*
+ * ISIF helper functions
+ */
+
+#define DM365_ISIF_MDFS_OFFSET		15
+#define DM365_ISIF_MDFS_MASK		0x1
+
+/* get field id in isif hardware */
+enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif;
+	u32 field_status;
+
+	field_status = isif_read(isif->isif_cfg.base_addr, MODESET);
+	field_status = (field_status >> DM365_ISIF_MDFS_OFFSET) &
+			DM365_ISIF_MDFS_MASK;
+	return field_status;
+}
+
+static int
+isif_set_pixel_format(struct vpfe_isif_device *isif, unsigned int pixfmt)
+{
+	if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12) {
+		if (pixfmt == V4L2_PIX_FMT_SBGGR16)
+			isif->isif_cfg.data_pack = ISIF_PACK_16BIT;
+		else if ((pixfmt == V4L2_PIX_FMT_SGRBG10DPCM8) ||
+				(pixfmt == V4L2_PIX_FMT_SGRBG10ALAW8))
+			isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
+		else
+			return -EINVAL;
+
+		isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW;
+		isif->isif_cfg.bayer.v4l2_pix_fmt = pixfmt;
+	} else {
+		if (pixfmt == V4L2_PIX_FMT_YUYV)
+			isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_YCBYCR;
+		else if (pixfmt == V4L2_PIX_FMT_UYVY)
+			isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY;
+		else
+			return -EINVAL;
+
+		isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
+		isif->isif_cfg.ycbcr.v4l2_pix_fmt = pixfmt;
+	}
+
+	return 0;
+}
+
+static int
+isif_set_frame_format(struct vpfe_isif_device *isif,
+		      enum isif_frmfmt frm_fmt)
+{
+	if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12)
+		isif->isif_cfg.bayer.frm_fmt = frm_fmt;
+	else
+		isif->isif_cfg.ycbcr.frm_fmt = frm_fmt;
+
+	return 0;
+}
+
+static int isif_set_image_window(struct vpfe_isif_device *isif)
+{
+	struct v4l2_rect *win = &isif->crop;
+
+	if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12) {
+		isif->isif_cfg.bayer.win.top = win->top;
+		isif->isif_cfg.bayer.win.left = win->left;
+		isif->isif_cfg.bayer.win.width = win->width;
+		isif->isif_cfg.bayer.win.height = win->height;
+		return 0;
+	}
+	isif->isif_cfg.ycbcr.win.top = win->top;
+	isif->isif_cfg.ycbcr.win.left = win->left;
+	isif->isif_cfg.ycbcr.win.width = win->width;
+	isif->isif_cfg.ycbcr.win.height = win->height;
+
+	return 0;
+}
+
+static int
+isif_set_buftype(struct vpfe_isif_device *isif, enum isif_buftype buf_type)
+{
+	if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12)
+		isif->isif_cfg.bayer.buf_type = buf_type;
+	else
+		isif->isif_cfg.ycbcr.buf_type = buf_type;
+
+	return 0;
+}
+
+/* configure format in isif hardware */
+static int
+isif_config_format(struct vpfe_device *vpfe_dev, unsigned int pad)
+{
+	struct vpfe_isif_device *vpfe_isif = &vpfe_dev->vpfe_isif;
+	enum isif_frmfmt frm_fmt = ISIF_FRMFMT_INTERLACED;
+	struct v4l2_pix_format format;
+	int ret = 0;
+
+	v4l2_fill_pix_format(&format, &vpfe_dev->vpfe_isif.formats[pad]);
+	mbus_to_pix(&vpfe_dev->vpfe_isif.formats[pad], &format);
+
+	if (isif_set_pixel_format(vpfe_isif, format.pixelformat) < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			 "Failed to set pixel format in isif\n");
+		return -EINVAL;
+	}
+
+	/* call for s_crop will override these values */
+	vpfe_isif->crop.left = 0;
+	vpfe_isif->crop.top = 0;
+	vpfe_isif->crop.width = format.width;
+	vpfe_isif->crop.height = format.height;
+
+	/* configure the image window */
+	isif_set_image_window(vpfe_isif);
+
+	switch (vpfe_dev->vpfe_isif.formats[pad].field) {
+	case V4L2_FIELD_INTERLACED:
+		/* do nothing, since it is default */
+		ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_INTERLEAVED);
+		break;
+
+	case V4L2_FIELD_NONE:
+		frm_fmt = ISIF_FRMFMT_PROGRESSIVE;
+		/* buffer type only applicable for interlaced scan */
+		break;
+
+	case V4L2_FIELD_SEQ_TB:
+		ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_SEPARATED);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* set the frame format */
+	if (!ret)
+		ret = isif_set_frame_format(vpfe_isif, frm_fmt);
+
+	return ret;
+}
+
+/*
+ * isif_try_format() - Try video format on a pad
+ * @isif: VPFE isif device
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ */
+static void
+isif_try_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
+		struct v4l2_subdev_format *fmt)
+{
+	unsigned int width = fmt->format.width;
+	unsigned int height = fmt->format.height;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(isif_fmts); i++) {
+		if (fmt->format.code == isif_fmts[i])
+			break;
+	}
+
+	/* If not found, use YUYV8_2x8 as default */
+	if (i >= ARRAY_SIZE(isif_fmts))
+		fmt->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+	/* Clamp the size. */
+	fmt->format.width = clamp_t(u32, width, 32, MAX_WIDTH);
+	fmt->format.height = clamp_t(u32, height, 32, MAX_HEIGHT);
+
+	/* The data formatter truncates the number of horizontal output
+	 * pixels to a multiple of 16. To avoid clipping data, allow
+	 * callers to request an output size bigger than the input size
+	 * up to the nearest multiple of 16.
+	 */
+	if (fmt->pad == ISIF_PAD_SOURCE)
+		fmt->format.width &= ~15;
+}
+
+/*
+ * vpfe_isif_buffer_isr() - isif module non-progressive buffer scheduling isr
+ * @isif: Pointer to isif subdevice.
+ */
+void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif)
+{
+	struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
+	struct vpfe_video_device *video = &isif->video_out;
+	enum v4l2_field field;
+	int fid;
+
+	if (!video->started)
+		return;
+
+	field = video->fmt.fmt.pix.field;
+
+	if (field == V4L2_FIELD_NONE) {
+		/* handle progressive frame capture */
+		if (video->cur_frm != video->next_frm)
+			vpfe_video_process_buffer_complete(video);
+		return;
+	}
+
+	/* interlaced or TB capture check which field we
+	 * are in hardware
+	 */
+	fid = vpfe_isif_get_fid(vpfe_dev);
+
+	/* switch the software maintained field id */
+	video->field_id ^= 1;
+	if (fid == video->field_id) {
+		/* we are in-sync here,continue */
+		if (fid == 0) {
+			/*
+			 * One frame is just being captured. If the
+			 * next frame is available, release the current
+			 * frame and move on
+			 */
+			if (video->cur_frm != video->next_frm)
+				vpfe_video_process_buffer_complete(video);
+			/*
+			 * based on whether the two fields are stored
+			 * interleavely or separately in memory,
+			 * reconfigure the ISIF memory address
+			 */
+			if (field == V4L2_FIELD_SEQ_TB)
+				vpfe_video_schedule_bottom_field(video);
+			return;
+		}
+		/*
+		 * if one field is just being captured configure
+		 * the next frame get the next frame from the
+		 * empty queue if no frame is available hold on
+		 * to the current buffer
+		 */
+		spin_lock(&video->dma_queue_lock);
+		if (!list_empty(&video->dma_queue) &&
+		video->cur_frm == video->next_frm)
+			vpfe_video_schedule_next_buffer(video);
+		spin_unlock(&video->dma_queue_lock);
+	} else if (fid == 0) {
+		/*
+		 * out of sync. Recover from any hardware out-of-sync.
+		 * May loose one frame
+		 */
+		video->field_id = fid;
+	}
+}
+
+/*
+ * vpfe_isif_vidint1_isr() - ISIF module progressive buffer scheduling isr
+ * @isif: Pointer to isif subdevice.
+ */
+void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif)
+{
+	struct vpfe_video_device *video = &isif->video_out;
+
+	if (!video->started)
+		return;
+
+	spin_lock(&video->dma_queue_lock);
+	if (video->fmt.fmt.pix.field == V4L2_FIELD_NONE &&
+	    !list_empty(&video->dma_queue) && video->cur_frm == video->next_frm)
+		vpfe_video_schedule_next_buffer(video);
+
+	spin_unlock(&video->dma_queue_lock);
+}
+
+/*
+ * VPFE video operations
+ */
+
+static int isif_video_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
+{
+	struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif;
+
+	isif_write(isif->isif_cfg.base_addr, (addr >> 21) &
+		ISIF_CADU_BITS, CADU);
+	isif_write(isif->isif_cfg.base_addr, (addr >> 5) &
+		ISIF_CADL_BITS, CADL);
+
+	return 0;
+}
+
+static const struct vpfe_video_operations isif_video_ops = {
+	.queue = isif_video_queue,
+};
+
+/*
+ * V4L2 subdev operations
+ */
+
+/* Parameter operations */
+static int isif_get_params(struct v4l2_subdev *sd, void *params)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+
+	/* only raw module parameters can be set through the IOCTL */
+	if (isif->formats[ISIF_PAD_SINK].code != V4L2_MBUS_FMT_SGRBG12_1X12)
+		return -EINVAL;
+	memcpy(params, &isif->isif_cfg.bayer.config_params,
+			sizeof(isif->isif_cfg.bayer.config_params));
+	return 0;
+}
+
+static int isif_validate_df_csc_params(struct vpfe_isif_df_csc *df_csc)
+{
+	struct vpfe_isif_color_space_conv *csc;
+	int err = -EINVAL;
+	int csc_df_en;
+	int i;
+
+	if (!df_csc->df_or_csc) {
+		/* csc configuration */
+		csc = &df_csc->csc;
+		if (csc->en) {
+			csc_df_en = 1;
+			for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++)
+				if (csc->coeff[i].integer >
+				    ISIF_CSC_COEF_INTEG_MASK ||
+				    csc->coeff[i].decimal >
+				    ISIF_CSC_COEF_DECIMAL_MASK) {
+					pr_err("Invalid CSC coefficients\n");
+					return err;
+				}
+		}
+	}
+	if (df_csc->start_pix > ISIF_DF_CSC_SPH_MASK) {
+		pr_err("Invalid df_csc start pix value\n");
+		return err;
+	}
+
+	if (df_csc->num_pixels > ISIF_DF_NUMPIX) {
+		pr_err("Invalid df_csc num pixels value\n");
+		return err;
+	}
+
+	if (df_csc->start_line > ISIF_DF_CSC_LNH_MASK) {
+		pr_err("Invalid df_csc start_line value\n");
+		return err;
+	}
+
+	if (df_csc->num_lines > ISIF_DF_NUMLINES) {
+		pr_err("Invalid df_csc num_lines value\n");
+		return err;
+	}
+
+	return 0;
+}
+
+#define DM365_ISIF_MAX_VDFLSFT		4
+#define DM365_ISIF_MAX_VDFSLV		4095
+#define DM365_ISIF_MAX_DFCMEM0		0x1fff
+#define DM365_ISIF_MAX_DFCMEM1		0x1fff
+
+static int isif_validate_dfc_params(struct vpfe_isif_dfc *dfc)
+{
+	int err = -EINVAL;
+	int i;
+
+	if (!dfc->en)
+		return 0;
+
+	if (dfc->corr_whole_line > 1) {
+		pr_err("Invalid corr_whole_line value\n");
+		return err;
+	}
+
+	if (dfc->def_level_shift > DM365_ISIF_MAX_VDFLSFT) {
+		pr_err("Invalid def_level_shift value\n");
+		return err;
+	}
+
+	if (dfc->def_sat_level > DM365_ISIF_MAX_VDFSLV) {
+		pr_err("Invalid def_sat_level value\n");
+		return err;
+	}
+
+	if (!dfc->num_vdefects ||
+	    dfc->num_vdefects > VPFE_ISIF_VDFC_TABLE_SIZE) {
+		pr_err("Invalid num_vdefects value\n");
+		return err;
+	}
+
+	for (i = 0; i < VPFE_ISIF_VDFC_TABLE_SIZE; i++) {
+		if (dfc->table[i].pos_vert > DM365_ISIF_MAX_DFCMEM0) {
+			pr_err("Invalid pos_vert value\n");
+			return err;
+		}
+		if (dfc->table[i].pos_horz > DM365_ISIF_MAX_DFCMEM1) {
+			pr_err("Invalid pos_horz value\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+#define DM365_ISIF_MAX_CLVRV			0xfff
+#define DM365_ISIF_MAX_CLDC			0x1fff
+#define DM365_ISIF_MAX_CLHSH			0x1fff
+#define DM365_ISIF_MAX_CLHSV			0x1fff
+#define DM365_ISIF_MAX_CLVSH			0x1fff
+#define DM365_ISIF_MAX_CLVSV			0x1fff
+#define DM365_ISIF_MAX_HEIGHT_BLACK_REGION	0x1fff
+
+static int isif_validate_bclamp_params(struct vpfe_isif_black_clamp *bclamp)
+{
+	int err = -EINVAL;
+
+	if (bclamp->dc_offset > DM365_ISIF_MAX_CLDC) {
+		pr_err("Invalid bclamp dc_offset value\n");
+		return err;
+	}
+	if (!bclamp->en)
+		return 0;
+	if (bclamp->horz.clamp_pix_limit > 1) {
+		pr_err("Invalid bclamp horz clamp_pix_limit value\n");
+		return err;
+	}
+	if (bclamp->horz.win_count_calc < 1 ||
+			bclamp->horz.win_count_calc > 32) {
+		pr_err("Invalid bclamp horz win_count_calc value\n");
+		return err;
+	}
+	if (bclamp->horz.win_start_h_calc > DM365_ISIF_MAX_CLHSH) {
+		pr_err("Invalid bclamp win_start_v_calc value\n");
+		return err;
+	}
+
+	if (bclamp->horz.win_start_v_calc > DM365_ISIF_MAX_CLHSV) {
+		pr_err("Invalid bclamp win_start_v_calc value\n");
+		return err;
+	}
+	if (bclamp->vert.reset_clamp_val > DM365_ISIF_MAX_CLVRV) {
+		pr_err("Invalid bclamp reset_clamp_val value\n");
+		return err;
+	}
+	if (bclamp->vert.ob_v_sz_calc > DM365_ISIF_MAX_HEIGHT_BLACK_REGION) {
+		pr_err("Invalid bclamp ob_v_sz_calc value\n");
+		return err;
+	}
+	if (bclamp->vert.ob_start_h > DM365_ISIF_MAX_CLVSH) {
+		pr_err("Invalid bclamp ob_start_h value\n");
+		return err;
+	}
+	if (bclamp->vert.ob_start_v > DM365_ISIF_MAX_CLVSV) {
+		pr_err("Invalid bclamp ob_start_h value\n");
+		return err;
+	}
+	return 0;
+}
+
+static int
+isif_validate_raw_params(struct vpfe_isif_raw_config *params)
+{
+	int ret;
+
+	ret = isif_validate_df_csc_params(&params->df_csc);
+	if (ret)
+		return ret;
+	ret = isif_validate_dfc_params(&params->dfc);
+	if (ret)
+		return ret;
+	ret = isif_validate_bclamp_params(&params->bclamp);
+	return ret;
+}
+
+static int isif_set_params(struct v4l2_subdev *sd, void *params)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	struct vpfe_isif_raw_config isif_raw_params;
+	int ret = -EINVAL;
+
+	/* only raw module parameters can be set through the IOCTL */
+	if (isif->formats[ISIF_PAD_SINK].code != V4L2_MBUS_FMT_SGRBG12_1X12)
+		return ret;
+
+	memcpy(&isif_raw_params, params, sizeof(isif_raw_params));
+	if (!isif_validate_raw_params(&isif_raw_params)) {
+		memcpy(&isif->isif_cfg.bayer.config_params, &isif_raw_params,
+			sizeof(isif_raw_params));
+		ret = 0;
+	}
+	return ret;
+}
+/*
+ * isif_ioctl() - isif module private ioctl's
+ * @sd: VPFE isif V4L2 subdevice
+ * @cmd: ioctl command
+ * @arg: ioctl argument
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static long isif_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case VIDIOC_VPFE_ISIF_S_RAW_PARAMS:
+		ret = isif_set_params(sd, arg);
+		break;
+
+	case VIDIOC_VPFE_ISIF_G_RAW_PARAMS:
+		ret = isif_get_params(sd, arg);
+		break;
+
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static void isif_config_gain_offset(struct vpfe_isif_device *isif)
+{
+	struct vpfe_isif_gain_offsets_adj *gain_off_ptr =
+		&isif->isif_cfg.bayer.config_params.gain_offset;
+	void *__iomem base = isif->isif_cfg.base_addr;
+	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);
+	isif_merge(base, GAIN_OFFSET_EN_MASK, val, CGAMMAWD);
+
+	isif_write(base, isif->isif_cfg.isif_gain_params.cr_gain, CRGAIN);
+	isif_write(base, isif->isif_cfg.isif_gain_params.cgr_gain, CGRGAIN);
+	isif_write(base, isif->isif_cfg.isif_gain_params.cgb_gain, CGBGAIN);
+	isif_write(base, isif->isif_cfg.isif_gain_params.cb_gain, CBGAIN);
+	isif_write(base, isif->isif_cfg.isif_gain_params.offset & OFFSET_MASK,
+		   COFSTA);
+
+}
+
+static void isif_config_bclamp(struct vpfe_isif_device *isif,
+		   struct vpfe_isif_black_clamp *bc)
+{
+	u32 val;
+
+	/**
+	 * DC Offset is always added to image data irrespective of bc enable
+	 * status
+	 */
+	val = bc->dc_offset & ISIF_BC_DCOFFSET_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, CLDCOFST);
+
+	if (!bc->en)
+		return;
+
+	val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) <<
+		ISIF_BC_MODE_COLOR_SHIFT;
+
+	/* Enable BC and horizontal clamp caculation paramaters */
+	val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) <<
+	      ISIF_HORZ_BC_MODE_SHIFT);
+
+	isif_write(isif->isif_cfg.base_addr, val, CLAMPCFG);
+
+	if (bc->horz.mode != VPFE_ISIF_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 & ISIF_HORZ_BC_WIN_COUNT_MASK) |
+		      ((bc->horz.base_win_sel_calc & 1) <<
+		      ISIF_HORZ_BC_WIN_SEL_SHIFT) |
+		      ((bc->horz.clamp_pix_limit & 1) <<
+		      ISIF_HORZ_BC_PIX_LIMIT_SHIFT) |
+		      ((bc->horz.win_h_sz_calc &
+		      ISIF_HORZ_BC_WIN_H_SIZE_MASK) <<
+		      ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) |
+		      ((bc->horz.win_v_sz_calc &
+		      ISIF_HORZ_BC_WIN_V_SIZE_MASK) <<
+		      ISIF_HORZ_BC_WIN_V_SIZE_SHIFT);
+
+		isif_write(isif->isif_cfg.base_addr, val, CLHWIN0);
+
+		val = bc->horz.win_start_h_calc & ISIF_HORZ_BC_WIN_START_H_MASK;
+		isif_write(isif->isif_cfg.base_addr, val, CLHWIN1);
+
+		val = bc->horz.win_start_v_calc & ISIF_HORZ_BC_WIN_START_V_MASK;
+		isif_write(isif->isif_cfg.base_addr, val, CLHWIN2);
+	}
+
+	/* vertical clamp caculation paramaters */
+	/* OB H Valid */
+	val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK;
+
+	/* Reset clamp value sel for previous line */
+	val |= (bc->vert.reset_val_sel & ISIF_VERT_BC_RST_VAL_SEL_MASK) <<
+				ISIF_VERT_BC_RST_VAL_SEL_SHIFT;
+
+	/* Line average coefficient */
+	val |= bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT;
+	isif_write(isif->isif_cfg.base_addr, val, CLVWIN0);
+
+	/* Configured reset value */
+	if (bc->vert.reset_val_sel == VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL) {
+		val = bc->vert.reset_clamp_val & ISIF_VERT_BC_RST_VAL_MASK;
+		isif_write(isif->isif_cfg.base_addr, val, CLVRV);
+	}
+
+	/* Optical Black horizontal start position */
+	val = bc->vert.ob_start_h & ISIF_VERT_BC_OB_START_HORZ_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, CLVWIN1);
+
+	/* Optical Black vertical start position */
+	val = bc->vert.ob_start_v & ISIF_VERT_BC_OB_START_VERT_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, CLVWIN2);
+
+	val = bc->vert.ob_v_sz_calc & ISIF_VERT_BC_OB_VERT_SZ_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, CLVWIN3);
+
+	/* Vertical start position for BC subtraction */
+	val = bc->vert_start_sub & ISIF_BC_VERT_START_SUB_V_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, CLSV);
+}
+
+/* This function will configure the window size to be capture in ISIF reg */
+static void
+isif_setwin(struct vpfe_isif_device *isif, struct v4l2_rect *image_win,
+	    enum isif_frmfmt frm_fmt, int ppc, int mode)
+{
+	int horz_nr_pixels;
+	int vert_nr_lines;
+	int horz_start;
+	int vert_start;
+	int mid_img;
+
+	/*
+	 * 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 */
+	isif_write(isif->isif_cfg.base_addr,
+		   horz_start & START_PX_HOR_MASK, SPH);
+	isif_write(isif->isif_cfg.base_addr,
+		   horz_nr_pixels & NUM_PX_HOR_MASK, LNH);
+	vert_start = image_win->top;
+
+	if (frm_fmt == ISIF_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);
+		isif_write(isif->isif_cfg.base_addr, mid_img, VDINT1);
+	}
+
+	if (!mode)
+		isif_write(isif->isif_cfg.base_addr, 0, VDINT0);
+	else
+		isif_write(isif->isif_cfg.base_addr, vert_nr_lines, VDINT0);
+	isif_write(isif->isif_cfg.base_addr,
+		   vert_start & START_VER_ONE_MASK, SLV0);
+	isif_write(isif->isif_cfg.base_addr,
+		   vert_start & START_VER_TWO_MASK, SLV1);
+	isif_write(isif->isif_cfg.base_addr,
+		   vert_nr_lines & NUM_LINES_VER, LNV);
+}
+
+#define DM365_ISIF_DFCMWR_MEMORY_WRITE		1
+#define DM365_ISIF_DFCMRD_MEMORY_READ		0x2
+
+static void
+isif_config_dfc(struct vpfe_isif_device *isif, struct vpfe_isif_dfc *vdfc)
+{
+#define DFC_WRITE_WAIT_COUNT	1000
+	u32 count = DFC_WRITE_WAIT_COUNT;
+	u32 val;
+	int i;
+
+	if (!vdfc->en)
+		return;
+
+	/* Correction mode */
+	val = (vdfc->corr_mode & ISIF_VDFC_CORR_MOD_MASK) <<
+	       ISIF_VDFC_CORR_MOD_SHIFT;
+
+	/* Correct whole line or partial */
+	if (vdfc->corr_whole_line)
+		val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT;
+
+	/* level shift value */
+	val |= (vdfc->def_level_shift & ISIF_VDFC_LEVEL_SHFT_MASK) <<
+		ISIF_VDFC_LEVEL_SHFT_SHIFT;
+
+	isif_write(isif->isif_cfg.base_addr, val, DFCCTL);
+
+	/* Defect saturation level */
+	val = vdfc->def_sat_level & ISIF_VDFC_SAT_LEVEL_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, VDFSATLV);
+
+	isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_vert &
+		   ISIF_VDFC_POS_MASK, DFCMEM0);
+	isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_horz &
+		   ISIF_VDFC_POS_MASK, DFCMEM1);
+	if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL ||
+	    vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
+		isif_write(isif->isif_cfg.base_addr,
+			   vdfc->table[0].level_at_pos, DFCMEM2);
+		isif_write(isif->isif_cfg.base_addr,
+			   vdfc->table[0].level_up_pixels, DFCMEM3);
+		isif_write(isif->isif_cfg.base_addr,
+			   vdfc->table[0].level_low_pixels, DFCMEM4);
+	}
+
+	val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+	/* set DFCMARST and set DFCMWR */
+	val |= 1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT;
+	val |= 1;
+	isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL);
+
+	while (count && (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x01))
+		count--;
+
+	val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+	if (!count) {
+		pr_debug("defect table write timeout !!\n");
+		return;
+	}
+
+	for (i = 1; i < vdfc->num_vdefects; i++) {
+		isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_vert &
+			ISIF_VDFC_POS_MASK, DFCMEM0);
+
+		isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_horz &
+			ISIF_VDFC_POS_MASK, DFCMEM1);
+
+		if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL ||
+		    vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
+			isif_write(isif->isif_cfg.base_addr,
+				   vdfc->table[i].level_at_pos, DFCMEM2);
+			isif_write(isif->isif_cfg.base_addr,
+				   vdfc->table[i].level_up_pixels, DFCMEM3);
+			isif_write(isif->isif_cfg.base_addr,
+				   vdfc->table[i].level_low_pixels, DFCMEM4);
+		}
+		val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+		/* clear DFCMARST and set DFCMWR */
+		val &= ~(1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT);
+		val |= 1;
+		isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL);
+
+		count = DFC_WRITE_WAIT_COUNT;
+		while (count && (isif_read(isif->isif_cfg.base_addr,
+			DFCMEMCTL) & 0x01))
+			count--;
+
+		val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+		if (!count) {
+			pr_debug("defect table write timeout !!\n");
+			return;
+		}
+	}
+	if (vdfc->num_vdefects < VPFE_ISIF_VDFC_TABLE_SIZE) {
+		/* Extra cycle needed */
+		isif_write(isif->isif_cfg.base_addr, 0, DFCMEM0);
+		isif_write(isif->isif_cfg.base_addr,
+			   DM365_ISIF_MAX_DFCMEM1, DFCMEM1);
+		isif_write(isif->isif_cfg.base_addr,
+			   DM365_ISIF_DFCMWR_MEMORY_WRITE, DFCMEMCTL);
+	}
+	/* enable VDFC */
+	isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT),
+		   (1 << ISIF_VDFC_EN_SHIFT), DFCCTL);
+
+	isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT),
+		   (0 << ISIF_VDFC_EN_SHIFT), DFCCTL);
+
+	isif_write(isif->isif_cfg.base_addr, 0x6, DFCMEMCTL);
+	for (i = 0 ; i < vdfc->num_vdefects; i++) {
+		count = DFC_WRITE_WAIT_COUNT;
+		while (count &&
+			(isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x2))
+			count--;
+		val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
+		if (!count) {
+			pr_debug("defect table write timeout !!\n");
+			return;
+		}
+		isif_write(isif->isif_cfg.base_addr,
+			   DM365_ISIF_DFCMRD_MEMORY_READ, DFCMEMCTL);
+	}
+}
+
+static void
+isif_config_csc(struct vpfe_isif_device *isif, struct vpfe_isif_df_csc *df_csc)
+{
+	u32 val1;
+	u32 val2;
+	u32 i;
+
+	if (!df_csc->csc.en) {
+		isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
+		return;
+	}
+	/* initialize all bits to 0 */
+	val1 = 0;
+	for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) {
+		if ((i % 2) == 0) {
+			/* CSCM - LSB */
+			val1 = ((df_csc->csc.coeff[i].integer &
+				ISIF_CSC_COEF_INTEG_MASK) <<
+				ISIF_CSC_COEF_INTEG_SHIFT) |
+				((df_csc->csc.coeff[i].decimal &
+				ISIF_CSC_COEF_DECIMAL_MASK));
+		} else {
+
+			/* CSCM - MSB */
+			val2 = ((df_csc->csc.coeff[i].integer &
+				ISIF_CSC_COEF_INTEG_MASK) <<
+				ISIF_CSC_COEF_INTEG_SHIFT) |
+				((df_csc->csc.coeff[i].decimal &
+				ISIF_CSC_COEF_DECIMAL_MASK));
+			val2 <<= ISIF_CSCM_MSB_SHIFT;
+			val2 |= val1;
+			isif_write(isif->isif_cfg.base_addr, val2,
+				   (CSCM0 + ((i-1) << 1)));
+		}
+	}
+	/* program the active area */
+	isif_write(isif->isif_cfg.base_addr, df_csc->start_pix &
+		ISIF_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
+	 */
+	isif_write(isif->isif_cfg.base_addr, df_csc->num_pixels &
+		ISIF_DF_CSC_SPH_MASK, FMTLNH);
+	isif_write(isif->isif_cfg.base_addr, df_csc->start_line &
+		ISIF_DF_CSC_SPH_MASK, FMTSLV);
+	/*
+	 * one extra line as required for CSC. See reason documented for
+	 * num_pixels
+	 */
+	isif_write(isif->isif_cfg.base_addr, df_csc->num_lines &
+		ISIF_DF_CSC_SPH_MASK, FMTLNV);
+	/* Enable CSC */
+	isif_write(isif->isif_cfg.base_addr, 1, CSCCTL);
+}
+
+static void
+isif_config_linearization(struct vpfe_isif_device *isif,
+			  struct vpfe_isif_linearize *linearize)
+{
+	u32 val;
+	u32 i;
+
+	if (!linearize->en) {
+		isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
+		return;
+	}
+	/* shift value for correction */
+	val = (linearize->corr_shft & ISIF_LIN_CORRSFT_MASK) <<
+	      ISIF_LIN_CORRSFT_SHIFT;
+	/* enable */
+	val |= 1;
+	isif_write(isif->isif_cfg.base_addr, val, LINCFG0);
+	/* Scale factor */
+	val = (linearize->scale_fact.integer & 1) <<
+	      ISIF_LIN_SCALE_FACT_INTEG_SHIFT;
+	val |= linearize->scale_fact.decimal & ISIF_LIN_SCALE_FACT_DECIMAL_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, LINCFG1);
+
+	for (i = 0; i < VPFE_ISIF_LINEAR_TAB_SIZE; i++) {
+		val = linearize->table[i] & ISIF_LIN_ENTRY_MASK;
+		if (i%2)
+			isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 1);
+		else
+			isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 0);
+	}
+}
+
+static void
+isif_config_culling(struct vpfe_isif_device *isif, struct vpfe_isif_cul *cul)
+{
+	u32 val;
+
+	/* Horizontal pattern */
+	val = cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT;
+	val |= cul->hcpat_odd;
+	isif_write(isif->isif_cfg.base_addr, val, CULH);
+	/* vertical pattern */
+	isif_write(isif->isif_cfg.base_addr, cul->vcpat, CULV);
+	/* LPF */
+	isif_merge(isif->isif_cfg.base_addr, ISIF_LPF_MASK << ISIF_LPF_SHIFT,
+		   cul->en_lpf << ISIF_LPF_SHIFT, MODESET);
+}
+
+static int isif_get_pix_fmt(u32 mbus_code)
+{
+	switch (mbus_code) {
+	case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SGRBG12_1X12:
+		return ISIF_PIXFMT_RAW;
+
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_YUYV10_2X10:
+	case V4L2_MBUS_FMT_Y8_1X8:
+		return ISIF_PIXFMT_YCBCR_8BIT;
+
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+		return ISIF_PIXFMT_YCBCR_16BIT;
+
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+#define ISIF_INTERLACE_INVERSE_MODE		0x4b6d
+#define ISIF_INTERLACE_NON_INVERSE_MODE		0x0b6d
+#define ISIF_PROGRESSIVE_INVERSE_MODE		0x4000
+#define ISIF_PROGRESSIVE_NON_INVERSE_MODE	0x0000
+
+static int isif_config_raw(struct v4l2_subdev *sd, int mode)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	struct isif_params_raw *params = &isif->isif_cfg.bayer;
+	struct vpfe_isif_raw_config *module_params =
+				&isif->isif_cfg.bayer.config_params;
+	struct v4l2_mbus_framefmt *format;
+	int pix_fmt;
+	u32 val;
+
+	format = &isif->formats[ISIF_PAD_SINK];
+
+	/* In case of user has set BT656IF earlier, it should be reset
+	 * when configuring for raw input.
+	 */
+	isif_write(isif->isif_cfg.base_addr, 0, REC656IF);
+	/* 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 - isif valid area
+	 * Set TRGSEL
+	 * Set EXTRG
+	 * Packed to 8 or 16 bits
+	 */
+	val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC |
+	      ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN |
+	      ISIF_CCDCFG_EXTRG_DISABLE | (isif->isif_cfg.data_pack &
+	      ISIF_DATA_PACK_MASK);
+	isif_write(isif->isif_cfg.base_addr, val, CCDCFG);
+
+	pix_fmt = isif_get_pix_fmt(format->code);
+	if (pix_fmt < 0) {
+		pr_debug("Invalid pix_fmt(input mode)\n");
+		return -EINVAL;
+	}
+	/*
+	 * 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 = ISIF_VDHDOUT_INPUT | ((params->vd_pol & ISIF_VD_POL_MASK) <<
+	      ISIF_VD_POL_SHIFT) | ((params->hd_pol & ISIF_HD_POL_MASK) <<
+	      ISIF_HD_POL_SHIFT) | ((params->fid_pol & ISIF_FID_POL_MASK) <<
+	      ISIF_FID_POL_SHIFT) | ((ISIF_DATAPOL_NORMAL &
+	      ISIF_DATAPOL_MASK) << ISIF_DATAPOL_SHIFT) | ((ISIF_EXWEN_DISABLE &
+	      ISIF_EXWEN_MASK) << ISIF_EXWEN_SHIFT) | ((params->frm_fmt &
+	      ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) | ((pix_fmt &
+	      ISIF_INPUT_MASK) << ISIF_INPUT_SHIFT);
+
+	/* currently only V4L2_MBUS_FMT_SGRBG12_1X12 is
+	 * supported. shift appropriately depending on
+	 * different MBUS fmt's added
+	 */
+	if (format->code == V4L2_MBUS_FMT_SGRBG12_1X12)
+		val |= ((VPFE_ISIF_NO_SHIFT &
+			ISIF_DATASFT_MASK) << ISIF_DATASFT_SHIFT);
+
+	isif_write(isif->isif_cfg.base_addr, val, MODESET);
+	/*
+	 * Configure GAMMAWD register
+	 * CFA pattern setting
+	 */
+	val = (params->cfa_pat & ISIF_GAMMAWD_CFA_MASK) <<
+		ISIF_GAMMAWD_CFA_SHIFT;
+	/* Gamma msb */
+	if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10ALAW8)
+		val = val | ISIF_ALAW_ENABLE;
+
+	val = val | ((params->data_msb & ISIF_ALAW_GAMA_WD_MASK) <<
+			ISIF_ALAW_GAMA_WD_SHIFT);
+
+	isif_write(isif->isif_cfg.base_addr, val, CGAMMAWD);
+	/* Configure DPCM compression settings */
+	if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10DPCM8) {
+		val =  1 << ISIF_DPCM_EN_SHIFT;
+		val |= (params->dpcm_predictor &
+			ISIF_DPCM_PREDICTOR_MASK) << ISIF_DPCM_PREDICTOR_SHIFT;
+	}
+	isif_write(isif->isif_cfg.base_addr, val, MISC);
+	/* Configure Gain & Offset */
+	isif_config_gain_offset(isif);
+	/* Configure Color pattern */
+	if (format->code == V4L2_MBUS_FMT_SGRBG12_1X12)
+		val = isif_sgrbg_pattern;
+	else
+		/* default set to rggb */
+		val = isif_srggb_pattern;
+
+	isif_write(isif->isif_cfg.base_addr, val, CCOLP);
+
+	/* Configure HSIZE register  */
+	val = (params->horz_flip_en & ISIF_HSIZE_FLIP_MASK) <<
+	      ISIF_HSIZE_FLIP_SHIFT;
+
+	/* calculate line offset in 32 bytes based on pack value */
+	if (isif->isif_cfg.data_pack == ISIF_PACK_8BIT)
+		val |= ((params->win.width + 31) >> 5) & ISIF_LINEOFST_MASK;
+	else if (isif->isif_cfg.data_pack == ISIF_PACK_12BIT)
+		val |= ((((params->win.width + (params->win.width >> 2)) +
+			31) >> 5) & ISIF_LINEOFST_MASK);
+	else
+		val |= (((params->win.width * 2) + 31) >> 5) &
+			ISIF_LINEOFST_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, HSIZE);
+	/* Configure SDOFST register  */
+	if (params->frm_fmt == ISIF_FRMFMT_INTERLACED) {
+		if (params->image_invert_en)
+			/* For interlace inverse mode */
+			isif_write(isif->isif_cfg.base_addr,
+				   ISIF_INTERLACE_INVERSE_MODE, SDOFST);
+		else
+			/* For interlace non inverse mode */
+			isif_write(isif->isif_cfg.base_addr,
+				   ISIF_INTERLACE_NON_INVERSE_MODE, SDOFST);
+	} else if (params->frm_fmt == ISIF_FRMFMT_PROGRESSIVE) {
+		if (params->image_invert_en)
+			isif_write(isif->isif_cfg.base_addr,
+				   ISIF_PROGRESSIVE_INVERSE_MODE, SDOFST);
+		else
+			/* For progessive non inverse mode */
+			isif_write(isif->isif_cfg.base_addr,
+				   ISIF_PROGRESSIVE_NON_INVERSE_MODE, SDOFST);
+	}
+	/* Configure video window */
+	isif_setwin(isif, &params->win, params->frm_fmt, 1, mode);
+	/* Configure Black Clamp */
+	isif_config_bclamp(isif, &module_params->bclamp);
+	/* Configure Vertical Defection Pixel Correction */
+	isif_config_dfc(isif, &module_params->dfc);
+	if (!module_params->df_csc.df_or_csc)
+		/* Configure Color Space Conversion */
+		isif_config_csc(isif, &module_params->df_csc);
+
+	isif_config_linearization(isif, &module_params->linearize);
+	/* Configure Culling */
+	isif_config_culling(isif, &module_params->culling);
+	/* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */
+	val = module_params->horz_offset & ISIF_DATA_H_OFFSET_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, DATAHOFST);
+
+	val = module_params->vert_offset & ISIF_DATA_V_OFFSET_MASK;
+	isif_write(isif->isif_cfg.base_addr, val, DATAVOFST);
+
+	return 0;
+}
+
+#define DM365_ISIF_HSIZE_MASK		0xffffffe0
+#define DM365_ISIF_SDOFST_2_LINES	0x00000249
+
+/* This function will configure ISIF for YCbCr parameters. */
+static int isif_config_ycbcr(struct v4l2_subdev *sd, int mode)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	struct isif_ycbcr_config *params = &isif->isif_cfg.ycbcr;
+	struct v4l2_mbus_framefmt *format;
+	int pix_fmt;
+	u32 modeset;
+	u32 ccdcfg;
+
+	format = &isif->formats[ISIF_PAD_SINK];
+	/*
+	 * first reset the ISIF
+	 * 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
+	 */
+	/* start with all bits zero */
+	ccdcfg = modeset = 0;
+	pix_fmt = isif_get_pix_fmt(format->code);
+	if (pix_fmt < 0) {
+		pr_debug("Invalid pix_fmt(input mode)\n");
+		return -EINVAL;
+	}
+	/* configure pixel format or input mode */
+	modeset = modeset | ((pix_fmt & ISIF_INPUT_MASK) <<
+		  ISIF_INPUT_SHIFT) | ((params->frm_fmt & ISIF_FRM_FMT_MASK) <<
+		  ISIF_FRM_FMT_SHIFT) | (((params->fid_pol &
+		  ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT)) |
+		  (((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT)) |
+		  (((params->vd_pol & ISIF_VD_POL_MASK) << ISIF_VD_POL_SHIFT));
+	/* pack the data to 8-bit CCDCCFG */
+	switch (format->code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
+			pr_debug("Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		modeset |= ((VPFE_PINPOL_NEGATIVE & ISIF_VD_POL_MASK) <<
+				ISIF_VD_POL_SHIFT);
+		isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
+		ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR;
+		break;
+
+	case V4L2_MBUS_FMT_YUYV10_2X10:
+		if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
+			pr_debug("Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		/* setup BT.656, embedded sync  */
+		isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
+		/* enable 10 bit mode in ccdcfg */
+		ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR |
+			ISIF_BW656_ENABLE;
+		break;
+
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+		if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) {
+			pr_debug("Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
+		break;
+
+	case V4L2_MBUS_FMT_Y8_1X8:
+		ccdcfg |= ISIF_PACK_8BIT;
+		ccdcfg |= ISIF_YCINSWP_YCBCR;
+		if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
+			pr_debug("Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		break;
+
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+		if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) {
+			pr_debug("Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		break;
+
+	default:
+		/* should never come here */
+		pr_debug("Invalid interface type\n");
+		return -EINVAL;
+	}
+	isif_write(isif->isif_cfg.base_addr, modeset, MODESET);
+	/* Set up pix order */
+	ccdcfg |= (params->pix_order & ISIF_PIX_ORDER_MASK) <<
+		ISIF_PIX_ORDER_SHIFT;
+	isif_write(isif->isif_cfg.base_addr, ccdcfg, CCDCFG);
+	/* configure video window */
+	if (format->code == V4L2_MBUS_FMT_YUYV10_1X20 ||
+			format->code == V4L2_MBUS_FMT_YUYV8_1X16)
+		isif_setwin(isif, &params->win, params->frm_fmt, 1, mode);
+	else
+		isif_setwin(isif, &params->win, params->frm_fmt, 2, mode);
+
+	/*
+	 * 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
+	 */
+	isif_write(isif->isif_cfg.base_addr,
+		   ((((params->win.width * 2) + 31) &
+		   DM365_ISIF_HSIZE_MASK) >> 5), HSIZE);
+
+	/* configure the memory line offset */
+	if (params->frm_fmt == ISIF_FRMFMT_INTERLACED &&
+	    params->buf_type == ISIF_BUFTYPE_FLD_INTERLEAVED)
+		/* two fields are interleaved in memory */
+		isif_write(isif->isif_cfg.base_addr,
+			   DM365_ISIF_SDOFST_2_LINES, SDOFST);
+	return 0;
+}
+
+static int isif_configure(struct v4l2_subdev *sd, int mode)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = &isif->formats[ISIF_PAD_SINK];
+
+	switch (format->code) {
+	case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
+	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SGRBG12_1X12:
+		return isif_config_raw(sd, mode);
+
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_YUYV10_2X10:
+	case V4L2_MBUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+		return isif_config_ycbcr(sd, mode);
+
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+/*
+ * isif_set_stream() - Enable/Disable streaming on the ISIF module
+ * @sd: VPFE ISIF V4L2 subdevice
+ * @enable: Enable/disable stream
+ */
+static int isif_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	int ret;
+
+	if (enable) {
+		ret = isif_configure(sd,
+			(isif->output == ISIF_OUTPUT_MEMORY) ? 0 : 1);
+		if (ret)
+			return ret;
+		if (isif->output == ISIF_OUTPUT_MEMORY)
+			isif_enable_output_to_sdram(isif, 1);
+		isif_enable(isif, 1);
+	} else {
+		isif_enable(isif, 0);
+		isif_enable_output_to_sdram(isif, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * __isif_get_format() - helper function for getting isif format
+ * @isif: pointer to isif private structure.
+ * @pad: pad number.
+ * @fh: V4L2 subdev file handle.
+ * @which: wanted subdev format.
+ */
+static struct v4l2_mbus_framefmt *
+__isif_get_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
+		  unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_subdev_format fmt;
+
+		fmt.pad = pad;
+		fmt.which = which;
+
+		return v4l2_subdev_get_try_format(fh, pad);
+	}
+	return &isif->formats[pad];
+}
+
+/*
+* isif_set_format() - set format on pad
+* @sd    : VPFE ISIF device
+* @fh    : V4L2 subdev file handle
+* @fmt   : pointer to v4l2 subdev format structure
+*
+* Return 0 on success or -EINVAL if format or pad is invalid
+*/
+static int
+isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		struct v4l2_subdev_format *fmt)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __isif_get_format(isif, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	isif_try_format(isif, fh, fmt);
+	memcpy(format, &fmt->format, sizeof(*format));
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+		return 0;
+
+	if (fmt->pad == ISIF_PAD_SOURCE)
+		return isif_config_format(vpfe_dev, fmt->pad);
+
+	return 0;
+}
+
+/*
+ * isif_get_format() - Retrieve the video format on a pad
+ * @sd: VPFE ISIF V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int
+isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		struct v4l2_subdev_format *fmt)
+{
+	struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __isif_get_format(vpfe_isif, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	memcpy(&fmt->format, format, sizeof(fmt->format));
+
+	return 0;
+}
+
+/*
+ * isif_enum_frame_size() - enum frame sizes on pads
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_frame_size_enum structure
+ */
+static int
+isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		     struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+	struct v4l2_subdev_format format;
+
+	if (fse->index != 0)
+		return -EINVAL;
+
+	format.pad = fse->pad;
+	format.format.code = fse->code;
+	format.format.width = 1;
+	format.format.height = 1;
+	format.which = V4L2_SUBDEV_FORMAT_TRY;
+	isif_try_format(isif, fh, &format);
+	fse->min_width = format.format.width;
+	fse->min_height = format.format.height;
+
+	if (format.format.code != fse->code)
+		return -EINVAL;
+
+	format.pad = fse->pad;
+	format.format.code = fse->code;
+	format.format.width = -1;
+	format.format.height = -1;
+	format.which = V4L2_SUBDEV_FORMAT_TRY;
+	isif_try_format(isif, fh, &format);
+	fse->max_width = format.format.width;
+	fse->max_height = format.format.height;
+
+	return 0;
+}
+
+/*
+ * isif_enum_mbus_code() - enum mbus codes for pads
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ */
+static int
+isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		    struct v4l2_subdev_mbus_code_enum *code)
+{
+	switch (code->pad) {
+	case ISIF_PAD_SINK:
+	case ISIF_PAD_SOURCE:
+		if (code->index >= ARRAY_SIZE(isif_fmts))
+			return -EINVAL;
+		code->code = isif_fmts[code->index];
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * isif_pad_set_crop() - set crop rectangle on pad
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return 0 on success, -EINVAL if pad is invalid
+ */
+static int
+isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		  struct v4l2_subdev_crop *crop)
+{
+	struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	/* check wether its a valid pad */
+	if (crop->pad != ISIF_PAD_SINK)
+		return -EINVAL;
+
+	format = __isif_get_format(vpfe_isif, fh, crop->pad, crop->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	/* check wether crop rect is within limits */
+	if (crop->rect.top < 0 || crop->rect.left < 0 ||
+		(crop->rect.left + crop->rect.width >
+		vpfe_isif->formats[ISIF_PAD_SINK].width) ||
+		(crop->rect.top + crop->rect.height >
+			vpfe_isif->formats[ISIF_PAD_SINK].height)) {
+		crop->rect.left = 0;
+		crop->rect.top = 0;
+		crop->rect.width = format->width;
+		crop->rect.height = format->height;
+	}
+	/* adjust the width to 16 pixel boundry */
+	crop->rect.width = ((crop->rect.width + 15) & ~0xf);
+	vpfe_isif->crop = crop->rect;
+	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		isif_set_image_window(vpfe_isif);
+	} else {
+		struct v4l2_rect *rect;
+
+		rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
+		memcpy(rect, &vpfe_isif->crop, sizeof(*rect));
+	}
+	return 0;
+}
+
+/*
+ * isif_pad_get_crop() - get crop rectangle on pad
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return 0 on success, -EINVAL if pad is invalid
+ */
+static int
+isif_pad_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		  struct v4l2_subdev_crop *crop)
+{
+	struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
+
+	/* check wether its a valid pad */
+	if (crop->pad != ISIF_PAD_SINK)
+		return -EINVAL;
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_rect *rect;
+		rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
+		memcpy(&crop->rect, rect, sizeof(*rect));
+	} else {
+		crop->rect = vpfe_isif->crop;
+	}
+
+	return 0;
+}
+
+/*
+ * isif_init_formats() - Initialize formats on all pads
+ * @sd: VPFE isif V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int
+isif_init_formats(struct v4l2_subdev *sd,
+		  struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_subdev_format format;
+	struct v4l2_subdev_crop crop;
+
+	memset(&format, 0, sizeof(format));
+	format.pad = ISIF_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+	format.format.width = MAX_WIDTH;
+	format.format.height = MAX_HEIGHT;
+	isif_set_format(sd, fh, &format);
+
+	memset(&format, 0, sizeof(format));
+	format.pad = ISIF_PAD_SOURCE;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+	format.format.width = MAX_WIDTH;
+	format.format.height = MAX_HEIGHT;
+	isif_set_format(sd, fh, &format);
+
+	memset(&crop, 0, sizeof(crop));
+	crop.pad = ISIF_PAD_SINK;
+	crop.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	crop.rect.width = MAX_WIDTH;
+	crop.rect.height = MAX_HEIGHT;
+	isif_pad_set_crop(sd, fh, &crop);
+
+	return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops isif_v4l2_core_ops = {
+	.ioctl = isif_ioctl,
+};
+
+/* subdev file operations */
+static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops = {
+	.open = isif_init_formats,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops isif_v4l2_video_ops = {
+	.s_stream = isif_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = {
+	.enum_mbus_code = isif_enum_mbus_code,
+	.enum_frame_size = isif_enum_frame_size,
+	.get_fmt = isif_get_format,
+	.set_fmt = isif_set_format,
+	.set_crop = isif_pad_set_crop,
+	.get_crop = isif_pad_get_crop,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops isif_v4l2_ops = {
+	.core = &isif_v4l2_core_ops,
+	.video = &isif_v4l2_video_ops,
+	.pad = &isif_v4l2_pad_ops,
+};
+
+/*
+ * Media entity operations
+ */
+
+/*
+ * isif_link_setup() - Setup isif connections
+ * @entity: isif media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int
+isif_link_setup(struct media_entity *entity, const struct media_pad *local,
+		const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case ISIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* read from decoder/sensor */
+		if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+			isif->input = ISIF_INPUT_NONE;
+			break;
+		}
+		if (isif->input != ISIF_INPUT_NONE)
+			return -EBUSY;
+		isif->input = ISIF_INPUT_PARALLEL;
+		break;
+
+	case ISIF_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+		/* write to memory */
+		if (flags & MEDIA_LNK_FL_ENABLED)
+			isif->output = ISIF_OUTPUT_MEMORY;
+		else
+			isif->output = ISIF_OUTPUT_NONE;
+		break;
+
+	case ISIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+		if (flags & MEDIA_LNK_FL_ENABLED)
+			isif->output = ISIF_OUTPUT_IPIPEIF;
+		else
+			isif->output = ISIF_OUTPUT_NONE;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+static const struct media_entity_operations isif_media_ops = {
+	.link_setup = isif_link_setup,
+};
+
+/*
+ * vpfe_isif_unregister_entities() - isif unregister entity
+ * @isif - pointer to isif subdevice structure.
+ */
+void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif)
+{
+	vpfe_video_unregister(&isif->video_out);
+	/* cleanup entity */
+	media_entity_cleanup(&isif->subdev.entity);
+	/* unregister subdev */
+	v4l2_device_unregister_subdev(&isif->subdev);
+}
+
+static void isif_restore_defaults(struct vpfe_isif_device *isif)
+{
+	enum vpss_ccdc_source_sel source = VPSS_CCDCIN;
+	int i;
+
+	memset(&isif->isif_cfg.bayer.config_params, 0,
+	       sizeof(struct vpfe_isif_raw_config));
+
+	isif->isif_cfg.bayer.config_params.linearize.corr_shft =
+					VPFE_ISIF_NO_SHIFT;
+	isif->isif_cfg.bayer.config_params.linearize.scale_fact.integer = 1;
+	isif->isif_cfg.bayer.config_params.culling.hcpat_odd =
+			ISIF_CULLING_HCAPT_ODD;
+	isif->isif_cfg.bayer.config_params.culling.hcpat_even =
+			ISIF_CULLING_HCAPT_EVEN;
+	isif->isif_cfg.bayer.config_params.culling.vcpat = ISIF_CULLING_VCAPT;
+	/* 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)
+		isif_write(isif->isif_cfg.base_addr, 0, i);
+	/* no culling support */
+	isif_write(isif->isif_cfg.base_addr, 0xffff, CULH);
+	isif_write(isif->isif_cfg.base_addr, 0xff, CULV);
+
+	/* Set default offset and gain */
+	isif_config_gain_offset(isif);
+	vpss_select_ccdc_source(source);
+}
+
+/*
+ * vpfe_isif_register_entities() - isif register entity
+ * @isif - pointer to isif subdevice structure.
+ * @vdev: pointer to v4l2 device structure.
+ */
+int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
+			    struct v4l2_device *vdev)
+{
+	struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
+	unsigned int flags;
+	int ret;
+
+	/* Register the subdev */
+	ret = v4l2_device_register_subdev(vdev, &isif->subdev);
+	if (ret < 0)
+		return ret;
+
+	isif_restore_defaults(isif);
+	ret = vpfe_video_register(&isif->video_out, vdev);
+	if (ret) {
+		pr_err("Failed to register isif video out device\n");
+		goto out_video_register;
+	}
+	isif->video_out.vpfe_dev = vpfe_dev;
+	flags = 0;
+	/* connect isif to video node */
+	ret = media_entity_create_link(&isif->subdev.entity, 1,
+				       &isif->video_out.video_dev.entity,
+				       0, flags);
+	if (ret < 0)
+		goto out_create_link;
+	return 0;
+out_create_link:
+	vpfe_video_unregister(&isif->video_out);
+out_video_register:
+	v4l2_device_unregister_subdev(&isif->subdev);
+	return ret;
+}
+
+/* -------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+static int vpfe_isif_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vpfe_isif_device *isif =
+	     container_of(ctrl->handler, struct vpfe_isif_device, ctrls);
+	struct isif_oper_config *config = &isif->isif_cfg;
+
+	switch (ctrl->id) {
+	case VPFE_CID_DPCM_PREDICTOR:
+		config->bayer.dpcm_predictor = ctrl->val;
+		break;
+
+	case VPFE_ISIF_CID_CRGAIN:
+		config->isif_gain_params.cr_gain = ctrl->val;
+		break;
+
+	case VPFE_ISIF_CID_CGRGAIN:
+		config->isif_gain_params.cgr_gain = ctrl->val;
+		break;
+
+	case VPFE_ISIF_CID_CGBGAIN:
+		config->isif_gain_params.cgb_gain = ctrl->val;
+		break;
+
+	case VPFE_ISIF_CID_CBGAIN:
+		config->isif_gain_params.cb_gain = ctrl->val;
+		break;
+
+	case VPFE_ISIF_CID_GAIN_OFFSET:
+		config->isif_gain_params.offset = ctrl->val;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops = {
+	.s_ctrl = vpfe_isif_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_dpcm_pred = {
+	.ops = &vpfe_isif_ctrl_ops,
+	.id = VPFE_CID_DPCM_PREDICTOR,
+	.name = "DPCM Predictor",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_crgain = {
+	.ops = &vpfe_isif_ctrl_ops,
+	.id = VPFE_ISIF_CID_CRGAIN,
+	.name = "CRGAIN",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = (1 << 12) - 1,
+	.step = 1,
+	.def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_cgrgain = {
+	.ops = &vpfe_isif_ctrl_ops,
+	.id = VPFE_ISIF_CID_CGRGAIN,
+	.name = "CGRGAIN",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = (1 << 12) - 1,
+	.step = 1,
+	.def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_cgbgain = {
+	.ops = &vpfe_isif_ctrl_ops,
+	.id = VPFE_ISIF_CID_CGBGAIN,
+	.name = "CGBGAIN",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = (1 << 12) - 1,
+	.step = 1,
+	.def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_cbgain = {
+	.ops = &vpfe_isif_ctrl_ops,
+	.id = VPFE_ISIF_CID_CBGAIN,
+	.name = "CBGAIN",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = (1 << 12) - 1,
+	.step = 1,
+	.def = 0,
+};
+
+static const struct v4l2_ctrl_config vpfe_isif_gain_offset = {
+	.ops = &vpfe_isif_ctrl_ops,
+	.id = VPFE_ISIF_CID_GAIN_OFFSET,
+	.name = "Gain Offset",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = (1 << 12) - 1,
+	.step = 1,
+	.def = 0,
+};
+
+static void isif_remove(struct vpfe_isif_device *isif,
+			struct platform_device *pdev)
+{
+	struct resource *res;
+	int i = 0;
+
+	iounmap(isif->isif_cfg.base_addr);
+	iounmap(isif->isif_cfg.linear_tbl0_addr);
+	iounmap(isif->isif_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++;
+	}
+}
+
+static void isif_config_defaults(struct vpfe_isif_device *isif)
+{
+	isif->isif_cfg.ycbcr.v4l2_pix_fmt = V4L2_PIX_FMT_UYVY;
+	isif->isif_cfg.ycbcr.pix_fmt = ISIF_PIXFMT_YCBCR_8BIT;
+	isif->isif_cfg.ycbcr.frm_fmt = ISIF_FRMFMT_INTERLACED;
+	isif->isif_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE;
+	isif->isif_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE;
+	isif->isif_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE;
+	isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY;
+	isif->isif_cfg.ycbcr.buf_type = ISIF_BUFTYPE_FLD_INTERLEAVED;
+
+	isif->isif_cfg.bayer.v4l2_pix_fmt = V4L2_PIX_FMT_SGRBG10ALAW8;
+	isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW;
+	isif->isif_cfg.bayer.frm_fmt = ISIF_FRMFMT_PROGRESSIVE;
+	isif->isif_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE;
+	isif->isif_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE;
+	isif->isif_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE;
+	isif->isif_cfg.bayer.cfa_pat = ISIF_CFA_PAT_MOSAIC;
+	isif->isif_cfg.bayer.data_msb = ISIF_BIT_MSB_11;
+	isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
+}
+/*
+ * vpfe_isif_init() - Initialize V4L2 subdev and media entity
+ * @isif: VPFE isif module
+ * @pdev: Pointer to platform device structure.
+ * Return 0 on success and a negative error code on failure.
+ */
+int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev)
+{
+	struct v4l2_subdev *sd = &isif->subdev;
+	struct media_pad *pads = &isif->pads[0];
+	struct media_entity *me = &sd->entity;
+	static resource_size_t res_len;
+	struct resource *res;
+	void *__iomem addr;
+	int status;
+	int 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 */
+			isif->isif_cfg.base_addr = addr;
+			break;
+		case 1:
+			/* ISIF linear tbl0 address */
+			isif->isif_cfg.linear_tbl0_addr = addr;
+			break;
+		default:
+			/* ISIF linear tbl0 address */
+			isif->isif_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);
+
+	/* queue ops */
+	isif->video_out.ops = &isif_video_ops;
+	v4l2_subdev_init(sd, &isif_v4l2_ops);
+	sd->internal_ops = &isif_v4l2_internal_ops;
+	strlcpy(sd->name, "DAVINCI ISIF", sizeof(sd->name));
+	sd->grp_id = 1 << 16;	/* group ID for davinci subdevs */
+	v4l2_set_subdevdata(sd, isif);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+	pads[ISIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	pads[ISIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	isif->input = ISIF_INPUT_NONE;
+	isif->output = ISIF_OUTPUT_NONE;
+	me->ops = &isif_media_ops;
+	status = media_entity_init(me, ISIF_PADS_NUM, pads, 0);
+	if (status)
+		goto isif_fail;
+	isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	status = vpfe_video_init(&isif->video_out, "ISIF");
+	if (status) {
+		pr_err("Failed to init isif-out video device\n");
+		goto isif_fail;
+	}
+	v4l2_ctrl_handler_init(&isif->ctrls, 6);
+	v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_crgain, NULL);
+	v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgrgain, NULL);
+	v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgbgain, NULL);
+	v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cbgain, NULL);
+	v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_gain_offset, NULL);
+	v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_dpcm_pred, NULL);
+
+	v4l2_ctrl_handler_setup(&isif->ctrls);
+	sd->ctrl_handler = &isif->ctrls;
+	isif_config_defaults(isif);
+	return 0;
+fail_base_iomap:
+	release_mem_region(res->start, res_len);
+	i--;
+fail_nobase_res:
+	if (isif->isif_cfg.base_addr)
+		iounmap(isif->isif_cfg.base_addr);
+	if (isif->isif_cfg.linear_tbl0_addr)
+		iounmap(isif->isif_cfg.linear_tbl0_addr);
+
+	while (i >= 0) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		release_mem_region(res->start, res_len);
+		i--;
+	}
+	return status;
+isif_fail:
+	v4l2_ctrl_handler_free(&isif->ctrls);
+	isif_remove(isif, pdev);
+	return status;
+}
+
+/*
+ * vpfe_isif_cleanup - isif module cleanup
+ * @isif: pointer to isif subdevice
+ * @dev: pointer to platform device structure
+ */
+void
+vpfe_isif_cleanup(struct vpfe_isif_device *isif, struct platform_device *pdev)
+{
+	isif_remove(isif, pdev);
+}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.h b/drivers/staging/media/davinci_vpfe/dm365_isif.h
new file mode 100644
index 0000000..473fd2c
--- /dev/null
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2012 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 version 2.
+ *
+ * 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
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli at ti.com>
+ *      Prabhakar Lad <prabhakar.lad at ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_ISIF_H
+#define _DAVINCI_VPFE_DM365_ISIF_H
+
+#include <linux/platform_device.h>
+
+#include <mach/mux.h>
+
+#include <media/davinci/vpfe_types.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#include "davinci_vpfe_user.h"
+#include "dm365_isif_regs.h"
+#include "vpfe_video.h"
+
+#define ISIF_CULLING_HCAPT_ODD		0xff
+#define ISIF_CULLING_HCAPT_EVEN		0xff
+#define ISIF_CULLING_VCAPT		0xff
+
+#define ISIF_CADU_BITS			0x07ff
+#define ISIF_CADL_BITS			0x0ffff
+
+enum isif_pixfmt {
+	ISIF_PIXFMT_RAW = 0,
+	ISIF_PIXFMT_YCBCR_16BIT = 1,
+	ISIF_PIXFMT_YCBCR_8BIT = 2,
+};
+
+enum isif_frmfmt {
+	ISIF_FRMFMT_PROGRESSIVE = 0,
+	ISIF_FRMFMT_INTERLACED = 1,
+};
+
+/* PIXEL ORDER IN MEMORY from LSB to MSB */
+/* only applicable for 8-bit input mode  */
+enum isif_pixorder {
+	ISIF_PIXORDER_YCBYCR = 0,
+	ISIF_PIXORDER_CBYCRY = 1,
+};
+
+enum isif_buftype {
+	ISIF_BUFTYPE_FLD_INTERLEAVED = 0,
+	ISIF_BUFTYPE_FLD_SEPARATED = 1,
+};
+
+struct isif_ycbcr_config {
+	/* v4l2 pixel format */
+	unsigned long v4l2_pix_fmt;
+	/* isif pixel format */
+	enum isif_pixfmt pix_fmt;
+	/* isif frame format */
+	enum isif_frmfmt frm_fmt;
+	/* isif 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;
+	/* isif pix order. Only used for ycbcr capture */
+	enum isif_pixorder pix_order;
+	/* isif buffer type. Only used for ycbcr capture */
+	enum isif_buftype buf_type;
+};
+
+enum isif_cfa_pattern {
+	ISIF_CFA_PAT_MOSAIC = 0,
+	ISIF_CFA_PAT_STRIPE = 1,
+};
+
+enum isif_data_msb {
+	/* MSB b15 */
+	ISIF_BIT_MSB_15 = 0,
+	/* MSB b14 */
+	ISIF_BIT_MSB_14 = 1,
+	/* MSB b13 */
+	ISIF_BIT_MSB_13 = 2,
+	/* MSB b12 */
+	ISIF_BIT_MSB_12 = 3,
+	/* MSB b11 */
+	ISIF_BIT_MSB_11 = 4,
+	/* MSB b10 */
+	ISIF_BIT_MSB_10 = 5,
+	/* MSB b9 */
+	ISIF_BIT_MSB_9 = 6,
+	/* MSB b8 */
+	ISIF_BIT_MSB_8 = 7,
+	/* MSB b7 */
+	ISIF_BIT_MSB_7 = 8,
+};
+
+struct isif_params_raw {
+	/* v4l2 pixel format */
+	unsigned long v4l2_pix_fmt;
+	/* isif pixel format */
+	enum isif_pixfmt pix_fmt;
+	/* isif frame format */
+	enum isif_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 isif_buftype buf_type;
+	/* cfa pattern */
+	enum isif_cfa_pattern cfa_pat;
+	/* Data MSB position */
+	enum isif_data_msb data_msb;
+	/* Enable horizontal flip */
+	unsigned char horz_flip_en;
+	/* Enable image invert vertically */
+	unsigned char image_invert_en;
+	unsigned char dpcm_predictor;
+	struct vpfe_isif_raw_config config_params;
+};
+
+enum isif_data_pack {
+	ISIF_PACK_16BIT = 0,
+	ISIF_PACK_12BIT = 1,
+	ISIF_PACK_8BIT = 2,
+};
+
+struct isif_gain_values {
+	unsigned int cr_gain;
+	unsigned int cgr_gain;
+	unsigned int cgb_gain;
+	unsigned int cb_gain;
+	unsigned int offset;
+};
+
+struct isif_oper_config {
+	struct isif_ycbcr_config ycbcr;
+	struct isif_params_raw bayer;
+	enum isif_data_pack data_pack;
+	struct isif_gain_values isif_gain_params;
+	void *__iomem base_addr;
+	void *__iomem linear_tbl0_addr;
+	void *__iomem linear_tbl1_addr;
+};
+
+#define ISIF_PAD_SINK      0
+#define ISIF_PAD_SOURCE    1
+
+#define ISIF_PADS_NUM      2
+
+enum isif_input_entity {
+	ISIF_INPUT_NONE = 0,
+	ISIF_INPUT_PARALLEL = 1,
+};
+
+#define ISIF_OUTPUT_NONE	(0)
+#define ISIF_OUTPUT_MEMORY	(1 << 0)
+#define ISIF_OUTPUT_IPIPEIF	(1 << 1)
+
+struct vpfe_isif_device {
+	struct v4l2_subdev		subdev;
+	struct media_pad		pads[ISIF_PADS_NUM];
+	struct v4l2_mbus_framefmt	formats[ISIF_PADS_NUM];
+	enum isif_input_entity		input;
+	unsigned int			output;
+	struct v4l2_ctrl_handler        ctrls;
+	struct v4l2_rect		crop;
+	struct isif_oper_config		isif_cfg;
+	struct vpfe_video_device	video_out;
+};
+
+enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev);
+void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif);
+int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
+				struct v4l2_device *dev);
+int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev);
+void vpfe_isif_cleanup(struct vpfe_isif_device *vpfe_isif,
+		       struct platform_device *pdev);
+void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif);
+void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif);
+
+#endif		/* _DAVINCI_VPFE_DM365_ISIF_H */
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h b/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h
new file mode 100644
index 0000000..8aceabb
--- /dev/null
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 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 version 2.
+ *
+ * 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
+ *
+ * Contributors:
+ *      Manjunath Hadli <manjunath.hadli at ti.com>
+ *      Prabhakar Lad <prabhakar.lad at ti.com>
+ */
+
+#ifndef _DAVINCI_VPFE_DM365_ISIF_REGS_H
+#define _DAVINCI_VPFE_DM365_ISIF_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
+
+/* 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 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 ISIF_YCINSWP_RAW			(0x00 << 4)
+#define ISIF_YCINSWP_YCBCR			(0x01 << 4)
+#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC		(0x00 << 6)
+#define ISIF_CCDCFG_WENLOG_AND			(0x00 << 8)
+#define ISIF_CCDCFG_TRGSEL_WEN			(0x00 << 9)
+#define ISIF_CCDCFG_EXTRG_DISABLE		(0x00 << 10)
+#define ISIF_LATCH_ON_VSYNC_DISABLE		(0x01 << 15)
+#define ISIF_LATCH_ON_VSYNC_ENABLE		(0x00 << 15)
+#define ISIF_DATA_PACK_MASK			0x03
+#define ISIF_PIX_ORDER_SHIFT			11
+#define ISIF_PIX_ORDER_MASK			0x01
+#define ISIF_BW656_ENABLE			(0x01 << 5)
+
+/* MODESET registers */
+#define ISIF_VDHDOUT_INPUT			(0x00 << 0)
+#define ISIF_INPUT_MASK				0x03
+#define ISIF_INPUT_SHIFT			12
+#define ISIF_FID_POL_MASK			0x01
+#define ISIF_FID_POL_SHIFT			4
+#define ISIF_HD_POL_MASK			0x01
+#define ISIF_HD_POL_SHIFT			3
+#define ISIF_VD_POL_MASK			0x01
+#define ISIF_VD_POL_SHIFT			2
+#define ISIF_DATAPOL_NORMAL			0x00
+#define ISIF_DATAPOL_MASK			0x01
+#define ISIF_DATAPOL_SHIFT			6
+#define ISIF_EXWEN_DISABLE			0x00
+#define ISIF_EXWEN_MASK				0x01
+#define ISIF_EXWEN_SHIFT			5
+#define ISIF_FRM_FMT_MASK			0x01
+#define ISIF_FRM_FMT_SHIFT			7
+#define ISIF_DATASFT_MASK			0x07
+#define ISIF_DATASFT_SHIFT			8
+#define ISIF_LPF_SHIFT				14
+#define ISIF_LPF_MASK				0x1
+
+/* GAMMAWD registers */
+#define ISIF_ALAW_GAMA_WD_MASK			0xf
+#define ISIF_ALAW_GAMA_WD_SHIFT			1
+#define ISIF_ALAW_ENABLE			0x01
+#define ISIF_GAMMAWD_CFA_MASK			0x01
+#define ISIF_GAMMAWD_CFA_SHIFT			5
+
+/* HSIZE registers */
+#define ISIF_HSIZE_FLIP_MASK			0x01
+#define ISIF_HSIZE_FLIP_SHIFT			12
+#define ISIF_LINEOFST_MASK			0xfff
+
+/* MISC registers */
+#define ISIF_DPCM_EN_SHIFT			12
+#define ISIF_DPCM_PREDICTOR_SHIFT		13
+#define ISIF_DPCM_PREDICTOR_MASK		1
+
+/* Black clamp related */
+#define ISIF_BC_DCOFFSET_MASK			0x1fff
+#define ISIF_BC_MODE_COLOR_MASK			1
+#define ISIF_BC_MODE_COLOR_SHIFT		4
+#define ISIF_HORZ_BC_MODE_MASK			3
+#define ISIF_HORZ_BC_MODE_SHIFT			1
+#define ISIF_HORZ_BC_WIN_COUNT_MASK		0x1f
+#define ISIF_HORZ_BC_WIN_SEL_SHIFT		5
+#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT		6
+#define ISIF_HORZ_BC_WIN_H_SIZE_MASK		3
+#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT		8
+#define ISIF_HORZ_BC_WIN_V_SIZE_MASK		3
+#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT		12
+#define ISIF_HORZ_BC_WIN_START_H_MASK		0x1fff
+#define ISIF_HORZ_BC_WIN_START_V_MASK		0x1fff
+#define ISIF_VERT_BC_OB_H_SZ_MASK		7
+#define ISIF_VERT_BC_RST_VAL_SEL_MASK		3
+#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT		4
+#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT	8
+#define ISIF_VERT_BC_OB_START_HORZ_MASK		0x1fff
+#define ISIF_VERT_BC_OB_START_VERT_MASK		0x1fff
+#define ISIF_VERT_BC_OB_VERT_SZ_MASK		0x1fff
+#define ISIF_VERT_BC_RST_VAL_MASK		0xfff
+#define ISIF_BC_VERT_START_SUB_V_MASK		0x1fff
+
+/* VDFC registers */
+#define ISIF_VDFC_EN_SHIFT			4
+#define ISIF_VDFC_CORR_MOD_MASK			3
+#define ISIF_VDFC_CORR_MOD_SHIFT		5
+#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT		7
+#define ISIF_VDFC_LEVEL_SHFT_MASK		7
+#define ISIF_VDFC_LEVEL_SHFT_SHIFT		8
+#define ISIF_VDFC_SAT_LEVEL_MASK		0xfff
+#define ISIF_VDFC_POS_MASK			0x1fff
+#define ISIF_DFCMEMCTL_DFCMARST_SHIFT		2
+
+/* CSC registers */
+#define ISIF_CSC_COEF_INTEG_MASK		7
+#define ISIF_CSC_COEF_DECIMAL_MASK		0x1f
+#define ISIF_CSC_COEF_INTEG_SHIFT		5
+#define ISIF_CSCM_MSB_SHIFT			8
+#define ISIF_DF_CSC_SPH_MASK			0x1fff
+#define ISIF_DF_CSC_LNH_MASK			0x1fff
+#define ISIF_DF_CSC_SLV_MASK			0x1fff
+#define ISIF_DF_CSC_LNV_MASK			0x1fff
+#define ISIF_DF_NUMLINES			0x7fff
+#define ISIF_DF_NUMPIX				0x1fff
+
+/* Offsets for LSC/DFC/Gain */
+#define ISIF_DATA_H_OFFSET_MASK			0x1fff
+#define ISIF_DATA_V_OFFSET_MASK			0x1fff
+
+/* Linearization */
+#define ISIF_LIN_CORRSFT_MASK			7
+#define ISIF_LIN_CORRSFT_SHIFT			4
+#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT		10
+#define ISIF_LIN_SCALE_FACT_DECIMAL_MASK	0x3ff
+#define ISIF_LIN_ENTRY_MASK			0x3ff
+
+/* masks and shifts*/
+#define ISIF_SYNCEN_VDHDEN_MASK			(1 << 0)
+#define ISIF_SYNCEN_WEN_MASK			(1 << 1)
+#define ISIF_SYNCEN_WEN_SHIFT			1
+
+#endif		/* _DAVINCI_VPFE_DM365_ISIF_REGS_H */
-- 
1.7.4.1




More information about the devel mailing list