All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
@ 2011-08-29 15:07 Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module Manjunath Hadli
                   ` (10 more replies)
  0 siblings, 11 replies; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli

changes from last patch set:
1. Made changes based on Sakari's feedback mainly:
        a. returned early to allow unindenting
        b. reformatting to shift the code to left where possible
        c. changed hex numbers to lower case
        d. corrected the defines according to module names.
        e. magic numbers removed.
        f. changed non-integer returning functions to void
        g. removed unwanted paranthses.
        h. fixed error codes.
        i. fixed some RESET_BIt code to what it was intended for.
2. reorganized the header files to move the kernel-only headers
along with the c files and interface headers in the include folder.

Manjunath Hadli (6):
  davinci: vpfe: add dm3xx IPIPEIF hardware support module
  davinci: vpfe: add support for CCDC hardware for dm365
  davinci: vpfe: add ccdc driver with media controller interface
  davinci: vpfe: add v4l2 video driver support
  davinci: vpfe: v4l2 capture driver with media interface
  davinci: vpfe: build infrastructure for dm365

Nagabhushana Netagunte (2):
  davinci: vpfe: add IPIPE hardware layer support
  davinci: vpfe: add IPIPE support for media controller driver

 drivers/media/video/davinci/Kconfig           |   46 +-
 drivers/media/video/davinci/Makefile          |   17 +-
 drivers/media/video/davinci/ccdc_hw_device.h  |   10 +-
 drivers/media/video/davinci/ccdc_types.h      |   43 +
 drivers/media/video/davinci/dm365_ccdc.c      | 1519 ++++++++++
 drivers/media/video/davinci/dm365_ccdc.h      |   88 +
 drivers/media/video/davinci/dm365_ccdc_regs.h |  309 ++
 drivers/media/video/davinci/dm365_def_para.c  |  486 +++
 drivers/media/video/davinci/dm365_def_para.h  |   39 +
 drivers/media/video/davinci/dm365_ipipe.c     | 3966 +++++++++++++++++++++++++
 drivers/media/video/davinci/dm365_ipipe.h     |  300 ++
 drivers/media/video/davinci/dm365_ipipe_hw.c  |  949 ++++++
 drivers/media/video/davinci/dm365_ipipe_hw.h  |  539 ++++
 drivers/media/video/davinci/dm3xx_ipipeif.c   |  317 ++
 drivers/media/video/davinci/dm3xx_ipipeif.h   |  258 ++
 drivers/media/video/davinci/imp_common.h      |   85 +
 drivers/media/video/davinci/imp_hw_if.h       |  178 ++
 drivers/media/video/davinci/vpfe_capture.c    |  793 +++++
 drivers/media/video/davinci/vpfe_capture.h    |  104 +
 drivers/media/video/davinci/vpfe_ccdc.c       |  813 +++++
 drivers/media/video/davinci/vpfe_ccdc.h       |   85 +
 drivers/media/video/davinci/vpfe_video.c      | 1712 +++++++++++
 drivers/media/video/davinci/vpfe_video.h      |  142 +
 include/linux/davinci_vpfe.h                  | 1223 ++++++++
 include/linux/dm365_ccdc.h                    |  664 +++++
 include/linux/dm3xx_ipipeif.h                 |   64 +
 include/media/davinci/vpfe.h                  |   91 +
 27 files changed, 14829 insertions(+), 11 deletions(-)
 create mode 100644 drivers/media/video/davinci/ccdc_types.h
 create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
 create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
 create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
 create mode 100644 drivers/media/video/davinci/dm365_def_para.c
 create mode 100644 drivers/media/video/davinci/dm365_def_para.h
 create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
 create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
 create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c
 create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h
 create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
 create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
 create mode 100644 drivers/media/video/davinci/imp_common.h
 create mode 100644 drivers/media/video/davinci/imp_hw_if.h
 create mode 100644 drivers/media/video/davinci/vpfe_capture.c
 create mode 100644 drivers/media/video/davinci/vpfe_capture.h
 create mode 100644 drivers/media/video/davinci/vpfe_ccdc.c
 create mode 100644 drivers/media/video/davinci/vpfe_ccdc.h
 create mode 100644 drivers/media/video/davinci/vpfe_video.c
 create mode 100644 drivers/media/video/davinci/vpfe_video.h
 create mode 100644 include/linux/davinci_vpfe.h
 create mode 100644 include/linux/dm365_ccdc.h
 create mode 100644 include/linux/dm3xx_ipipeif.h
 create mode 100644 include/media/davinci/vpfe.h


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

* [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-09-01 20:47   ` Sylwester Nawrocki
  2011-08-29 15:07 ` [PATCH v2 2/8] davinci: vpfe: add IPIPE hardware layer support Manjunath Hadli
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli, Nagabhushana Netagunte

add support for dm3xx IPIPEIF hardware setup. This is the
lowest software layer for the dm3x vpfe driver which directly
accesses hardware. Add support for features like default
pixel correction, dark frame substraction  and hardware setup.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/dm3xx_ipipeif.c |  317 +++++++++++++++++++++++++++
 drivers/media/video/davinci/dm3xx_ipipeif.h |  258 ++++++++++++++++++++++
 include/linux/dm3xx_ipipeif.h               |   64 ++++++
 3 files changed, 639 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
 create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
 create mode 100644 include/linux/dm3xx_ipipeif.h

diff --git a/drivers/media/video/davinci/dm3xx_ipipeif.c b/drivers/media/video/davinci/dm3xx_ipipeif.c
new file mode 100644
index 0000000..ebc8895
--- /dev/null
+++ b/drivers/media/video/davinci/dm3xx_ipipeif.c
@@ -0,0 +1,317 @@
+/*
+* Copyright (C) 2011 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
+*
+* ipipe module to hold common functionality across DM355 and DM365
+*/
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/davinci/vpfe.h>
+#include "dm3xx_ipipeif.h"
+
+static void *__iomem ipipeif_base_addr;
+
+static inline u32 regr_if(u32 offset)
+{
+	return readl(ipipeif_base_addr + offset);
+}
+
+static inline void regw_if(u32 val, u32 offset)
+{
+	writel(val, ipipeif_base_addr + offset);
+}
+
+void ipipeif_set_enable(char en, unsigned int mode)
+{
+	regw_if(1, IPIPEIF_ENABLE);
+}
+
+u32 ipipeif_get_enable(void)
+{
+	return regr_if(IPIPEIF_ENABLE);
+}
+
+int ipipeif_set_address(struct ipipeif *params, unsigned int address)
+{
+	u32 val;
+
+	if (params->source == 0)
+		return -EINVAL;
+
+	val = (params->adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK;
+	regw_if(val, IPIPEIF_ADOFS);
+
+	/* lower sixteen bit */
+	val = (address >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK;
+	regw_if(val, IPIPEIF_ADDRL);
+
+	/* upper next seven bit */
+	val = (address >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK;
+	regw_if(val, IPIPEIF_ADDRU);
+
+	return 0;
+}
+
+static void ipipeif_config_dpc(struct ipipeif_dpc *dpc)
+{
+	u32 val;
+
+	/* Intialize val*/
+	val = 0;
+
+	if (dpc->en) {
+		val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT;
+		val |= dpc->thr & IPIPEIF_DPC2_THR_MASK;
+	}
+
+	regw_if(val, IPIPEIF_DPC2);
+}
+
+#define RD_DATA_15_2	0x7
+/* This function sets up IPIPEIF and is called from
+ * ipipe_hw_setup()
+ */
+int ipipeif_hw_setup(struct ipipeif *params, int device_type)
+{
+	enum v4l2_mbus_pixelcode isif_port_if;
+	unsigned int val;
+
+	if (params == NULL)
+		return -EINVAL;
+
+	/* Enable clock to IPIPEIF and IPIPE */
+	if (device_type == DM365)
+		vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
+
+	/* Combine all the fields to make CFG1 register of IPIPEIF */
+	val = params->mode << ONESHOT_SHIFT;
+	val |= params->source << INPSRC_SHIFT;
+	val |= params->clock_select << CLKSEL_SHIFT;
+	val |= params->avg_filter << AVGFILT_SHIFT;
+	val |= params->decimation << DECIM_SHIFT;
+
+	if (device_type == DM355) {
+		val |= params->var.if_base.ialaw << IALAW_SHIFT;
+		val |= params->var.if_base.pack_mode << PACK8IN_SHIFT;
+		val |= params->var.if_base.clk_div << CLKDIV_SHIFT;
+		val |= params->var.if_base.data_shift << DATASFT_SHIFT;
+	} else {
+		/* DM365 IPIPE 5.1 */
+		val |= params->var.if_5_1.pack_mode << PACK8IN_SHIFT;
+		val |= params->var.if_5_1.source1 << INPSRC1_SHIFT;
+		if (params->source != IPIPEIF_SDRAM_YUV)
+			val |= params->var.if_5_1.data_shift << DATASFT_SHIFT;
+		else
+			val &= ~(RD_DATA_15_2 << DATASFT_SHIFT);
+	}
+	regw_if(val, IPIPEIF_CFG1);
+
+	switch (params->source) {
+	case IPIPEIF_CCDC:
+		regw_if(params->gain, IPIPEIF_GAIN);
+		break;
+	case IPIPEIF_SDRAM_RAW:
+	case IPIPEIF_CCDC_DARKFM:
+		regw_if(params->gain, IPIPEIF_GAIN);
+		/* fall through */
+	case IPIPEIF_SDRAM_YUV:
+		val |= params->var.if_5_1.data_shift << DATASFT_SHIFT;
+		regw_if(params->glob_hor_size, IPIPEIF_PPLN);
+		regw_if(params->glob_ver_size, IPIPEIF_LPFR);
+		regw_if(params->hnum, IPIPEIF_HNUM);
+		regw_if(params->vnum, IPIPEIF_VNUM);
+		break;
+	default:
+		/* Do nothing */
+		return -EINVAL;
+	}
+
+	/*check if decimation is enable or not */
+	if (params->decimation)
+		regw_if(params->rsz, IPIPEIF_RSZ);
+
+	if (device_type != DM365)
+		return 0;
+
+	/* Setup sync alignment and initial rsz position */
+	val = params->var.if_5_1.align_sync & 1;
+	val <<= IPIPEIF_INIRSZ_ALNSYNC_SHIFT;
+	val |= params->var.if_5_1.rsz_start & IPIPEIF_INIRSZ_MASK;
+	regw_if(val, IPIPEIF_INIRSZ);
+
+	/* Enable DPCM decompression */
+	switch (params->source) {
+	case IPIPEIF_SDRAM_RAW:
+		val = 0;
+		if (params->var.if_5_1.dpcm.en) {
+			val = params->var.if_5_1.dpcm.en & 1;
+			val |= (params->var.if_5_1.dpcm.type & 1) <<
+				IPIPEIF_DPCM_BITS_SHIFT;
+			val |= (params->var.if_5_1.dpcm.pred & 1) <<
+				IPIPEIF_DPCM_PRED_SHIFT;
+		}
+		regw_if(val, IPIPEIF_DPCM);
+
+		/* set DPC */
+		ipipeif_config_dpc(&params->var.if_5_1.dpc);
+
+		regw_if(params->var.if_5_1.clip, IPIPEIF_OCLIP);
+		/* fall through for SDRAM YUV mode */
+		isif_port_if = params->var.if_5_1.isif_port.if_type;
+		/* configure CFG2 */
+		val = regr_if(IPIPEIF_CFG2);
+		switch (isif_port_if) {
+		case V4L2_MBUS_FMT_YUYV8_1X16:
+			RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+			SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+			regw_if(val, IPIPEIF_CFG2);
+			break;
+		default:
+			RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+			RESETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+			regw_if(val, IPIPEIF_CFG2);
+			break;
+		}
+		break;
+	case IPIPEIF_SDRAM_YUV:
+		/* Set clock divider */
+		if (params->clock_select == IPIPEIF_SDRAM_CLK) {
+			val = regr_if(IPIPEIF_CLKDIV);
+			val |= (params->var.if_5_1.clk_div.m - 1) <<
+				IPIPEIF_CLKDIV_M_SHIFT;
+			val |= (params->var.if_5_1.clk_div.n - 1);
+			regw_if(val, IPIPEIF_CLKDIV);
+		}
+		break;
+	case IPIPEIF_CCDC:
+	case IPIPEIF_CCDC_DARKFM:
+		/* set DPC */
+		ipipeif_config_dpc(&params->var.if_5_1.dpc);
+
+		/* Set DF gain & threshold control */
+		val = 0;
+		if (params->var.if_5_1.df_gain_en) {
+			val = params->var.if_5_1.df_gain_thr &
+				IPIPEIF_DF_GAIN_THR_MASK;
+			regw_if(val, IPIPEIF_DFSGTH);
+			val = (params->var.if_5_1.df_gain_en & 1) <<
+				IPIPEIF_DF_GAIN_EN_SHIFT;
+			val |= params->var.if_5_1.df_gain &
+				IPIPEIF_DF_GAIN_MASK;
+		}
+		regw_if(val, IPIPEIF_DFSGVL);
+		isif_port_if = params->var.if_5_1.isif_port.if_type;
+
+		/* configure CFG2 */
+		val = params->var.if_5_1.isif_port.hdpol <<
+			IPIPEIF_CFG2_HDPOL_SHIFT;
+		val |= params->var.if_5_1.isif_port.vdpol <<
+			IPIPEIF_CFG2_VDPOL_SHIFT;
+
+		switch (isif_port_if) {
+		case V4L2_MBUS_FMT_YUYV8_1X16:
+		case V4L2_MBUS_FMT_YUYV10_1X20:
+			RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+			SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+			break;
+		case V4L2_MBUS_FMT_YUYV8_2X8:
+		case V4L2_MBUS_FMT_Y8_1X8:
+		case V4L2_MBUS_FMT_YUYV10_2X10:
+			SETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
+			SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+			val |= params->var.if_5_1.pix_order <<
+				IPIPEIF_CFG2_YUV8P_SHIFT;
+			break;
+		default:
+			/* Bayer */
+			regw_if(params->var.if_5_1.clip,
+				IPIPEIF_OCLIP);
+			RESETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
+		}
+		regw_if(val, IPIPEIF_CFG2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __devinit dm3xx_ipipeif_probe(struct platform_device *pdev)
+{
+	static resource_size_t  res_len;
+	struct resource *res;
+	int status;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	res_len = res->end - res->start + 1;
+
+	res = request_mem_region(res->start, res_len, res->name);
+	if (!res)
+		return -EBUSY;
+
+	ipipeif_base_addr = ioremap_nocache(res->start, res_len);
+	if (!ipipeif_base_addr) {
+		status = -EBUSY;
+		goto fail;
+	}
+	return 0;
+
+fail:
+	release_mem_region(res->start, res_len);
+
+	return status;
+}
+
+static int dm3xx_ipipeif_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	iounmap(ipipeif_base_addr);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		release_mem_region(res->start, res->end - res->start + 1);
+	return 0;
+}
+
+static struct platform_driver dm3xx_ipipeif_driver = {
+	.driver = {
+		.name   = "dm3xx_ipipeif",
+		.owner = THIS_MODULE,
+	},
+	.remove = __devexit_p(dm3xx_ipipeif_remove),
+	.probe = dm3xx_ipipeif_probe,
+};
+
+static int dm3xx_ipipeif_init(void)
+{
+	return platform_driver_register(&dm3xx_ipipeif_driver);
+}
+
+static void dm3xx_ipipeif_exit(void)
+{
+	platform_driver_unregister(&dm3xx_ipipeif_driver);
+}
+
+module_init(dm3xx_ipipeif_init);
+module_exit(dm3xx_ipipeif_exit);
+
+MODULE_LICENSE("GPL2");
diff --git a/drivers/media/video/davinci/dm3xx_ipipeif.h b/drivers/media/video/davinci/dm3xx_ipipeif.h
new file mode 100644
index 0000000..f3289f0
--- /dev/null
+++ b/drivers/media/video/davinci/dm3xx_ipipeif.h
@@ -0,0 +1,258 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _DM3XX_IPIPEIF_H
+#define _DM3XX_IPIPEIF_H
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/dm3xx_ipipeif.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include "vpss.h"
+
+/* Used to shift input image data based on the data lines connected
+ * to parallel port
+ */
+/* IPIPE base specific types */
+enum ipipeif_data_shift {
+	IPIPEIF_BITS15_2,
+	IPIPEIF_BITS14_1,
+	IPIPEIF_BITS13_0,
+	IPIPEIF_BITS12_0,
+	IPIPEIF_BITS11_0,
+	IPIPEIF_BITS10_0,
+	IPIPEIF_BITS9_0
+};
+
+enum ipipeif_clkdiv {
+	IPIPEIF_DIVIDE_HALF,
+	IPIPEIF_DIVIDE_THIRD,
+	IPIPEIF_DIVIDE_FOURTH,
+	IPIPEIF_DIVIDE_FIFTH,
+	IPIPEIF_DIVIDE_SIXTH,
+	IPIPEIF_DIVIDE_EIGHTH,
+	IPIPEIF_DIVIDE_SIXTEENTH,
+	IPIPEIF_DIVIDE_THIRTY
+};
+
+enum ipipeif_clock {
+	IPIPEIF_PIXCEL_CLK,
+	IPIPEIF_SDRAM_CLK
+};
+
+enum ipipeif_pack_mode  {
+	IPIPEIF_PACK_16_BIT,
+	IPIPEIF_PACK_8_BIT
+};
+
+enum ipipe_oper_mode {
+	IPIPEIF_CONTINUOUS,
+	IPIPEIF_ONE_SHOT
+};
+
+enum ipipeif_5_1_pack_mode  {
+	IPIPEIF_5_1_PACK_16_BIT,
+	IPIPEIF_5_1_PACK_8_BIT,
+	IPIPEIF_5_1_PACK_8_BIT_A_LAW,
+	IPIPEIF_5_1_PACK_12_BIT
+};
+
+enum  ipipeif_avg_filter {
+	IPIPEIF_AVG_OFF,
+	IPIPEIF_AVG_ON
+};
+
+enum  ipipeif_input_source {
+	IPIPEIF_CCDC,
+	IPIPEIF_SDRAM_RAW,
+	IPIPEIF_CCDC_DARKFM,
+	IPIPEIF_SDRAM_YUV
+};
+
+enum ipipeif_ialaw {
+	IPIPEIF_ALAW_OFF,
+	IPIPEIF_ALAW_ON
+};
+
+struct ipipeif_base {
+	enum ipipeif_ialaw ialaw;
+	enum ipipeif_pack_mode pack_mode;
+	enum ipipeif_data_shift data_shift;
+	enum ipipeif_clkdiv clk_div;
+};
+
+enum  ipipeif_input_src1 {
+	IPIPEIF_SRC1_PARALLEL_PORT,
+	IPIPEIF_SRC1_SDRAM_RAW,
+	IPIPEIF_SRC1_ISIF_DARKFM,
+	IPIPEIF_SRC1_SDRAM_YUV
+};
+
+enum ipipeif_dpcm_type {
+	IPIPEIF_DPCM_8BIT_10BIT,
+	IPIPEIF_DPCM_8BIT_12BIT
+};
+
+struct ipipeif_dpcm_decomp {
+	unsigned char en;
+	enum ipipeif_dpcm_type type;
+	enum ipipeif_dpcm_pred pred;
+};
+
+enum ipipeif_dfs_dir {
+	IPIPEIF_PORT_MINUS_SDRAM,
+	IPIPEIF_SDRAM_MINUS_PORT
+};
+
+struct ipipeif_5_1 {
+	enum ipipeif_5_1_pack_mode pack_mode;
+	enum ipipeif_5_1_data_shift data_shift;
+	enum ipipeif_input_src1 source1;
+	struct ipipeif_5_1_clkdiv clk_div;
+	/* Defect pixel correction */
+	struct ipipeif_dpc dpc;
+	/* DPCM decompression */
+	struct ipipeif_dpcm_decomp dpcm;
+	/* ISIF port pixel order */
+	enum ipipeif_pixel_order pix_order;
+	/* interface parameters from isif */
+	struct vpfe_hw_if_param isif_port;
+	/* clipped to this value */
+	unsigned short clip;
+	/* Align HSync and VSync to rsz_start */
+	unsigned char align_sync;
+	/* resizer start position */
+	unsigned int rsz_start;
+	/* DF gain enable */
+	unsigned char df_gain_en;
+	/* DF gain value */
+	unsigned short df_gain;
+	/* DF gain threshold value */
+	unsigned short df_gain_thr;
+};
+
+/* ipipeif structures common to DM350 and DM365 used by ipipeif API */
+struct ipipeif {
+	enum ipipe_oper_mode mode;
+	enum ipipeif_input_source source;
+	enum ipipeif_clock clock_select;
+	unsigned int glob_hor_size;
+	unsigned int glob_ver_size;
+	unsigned int hnum;
+	unsigned int vnum;
+	unsigned int adofs;
+	unsigned char rsz;
+	enum ipipeif_decimation decimation;
+	enum ipipeif_avg_filter avg_filter;
+	unsigned short gain;
+	/* IPIPE 5.1 */
+	union var_part {
+		struct ipipeif_base if_base;
+		struct ipipeif_5_1  if_5_1;
+	} var;
+};
+
+/* IPIPEIF Register Offsets from the base address */
+#define IPIPEIF_ENABLE			(0x00)
+#define IPIPEIF_CFG1			(0x04)
+#define IPIPEIF_PPLN			(0x08)
+#define IPIPEIF_LPFR			(0x0c)
+#define IPIPEIF_HNUM			(0x10)
+#define IPIPEIF_VNUM			(0x14)
+#define IPIPEIF_ADDRU			(0x18)
+#define IPIPEIF_ADDRL			(0x1c)
+#define IPIPEIF_ADOFS			(0x20)
+#define IPIPEIF_RSZ			(0x24)
+#define IPIPEIF_GAIN			(0x28)
+
+/* Below registers are available only on IPIPE 5.1 */
+#define IPIPEIF_DPCM			(0x2c)
+#define IPIPEIF_CFG2			(0x30)
+#define IPIPEIF_INIRSZ			(0x34)
+#define IPIPEIF_OCLIP			(0x38)
+#define IPIPEIF_DTUDF			(0x3c)
+#define IPIPEIF_CLKDIV			(0x40)
+#define IPIPEIF_DPC1			(0x44)
+#define IPIPEIF_DPC2			(0x48)
+#define IPIPEIF_DFSGVL			(0x4c)
+#define IPIPEIF_DFSGTH			(0x50)
+#define IPIPEIF_RSZ3A			(0x54)
+#define IPIPEIF_INIRSZ3A		(0x58)
+#define IPIPEIF_RSZ_MIN			(16)
+#define IPIPEIF_RSZ_MAX			(112)
+#define IPIPEIF_RSZ_CONST		(16)
+#define SETBIT(reg, bit)   (reg = ((reg) | ((0x00000001)<<(bit))))
+#define RESETBIT(reg, bit) (reg = ((reg) & (~(0x00000001<<(bit)))))
+
+#define IPIPEIF_ADOFS_LSB_MASK		(0x1ff)
+#define IPIPEIF_ADOFS_LSB_SHIFT		(5)
+#define IPIPEIF_ADOFS_MSB_MASK		(0x200)
+#define IPIPEIF_ADDRU_MASK		(0x7ff)
+#define IPIPEIF_ADDRL_SHIFT		(5)
+#define IPIPEIF_ADDRL_MASK		(0xffff)
+#define IPIPEIF_ADDRU_SHIFT		(21)
+#define IPIPEIF_ADDRMSB_SHIFT		(31)
+#define IPIPEIF_ADDRMSB_LEFT_SHIFT	(10)
+
+/* CFG1 Masks and shifts */
+#define ONESHOT_SHIFT			(0)
+#define DECIM_SHIFT			(1)
+#define INPSRC_SHIFT			(2)
+#define CLKDIV_SHIFT			(4)
+#define AVGFILT_SHIFT			(7)
+#define PACK8IN_SHIFT			(8)
+#define IALAW_SHIFT			(9)
+#define CLKSEL_SHIFT			(10)
+#define DATASFT_SHIFT			(11)
+#define INPSRC1_SHIFT			(14)
+
+/* DPC2 */
+#define IPIPEIF_DPC2_EN_SHIFT		(12)
+#define IPIPEIF_DPC2_THR_MASK		(0xfff)
+/* Applicable for IPIPE 5.1 */
+#define IPIPEIF_DF_GAIN_EN_SHIFT	(10)
+#define IPIPEIF_DF_GAIN_MASK		(0x3ff)
+#define IPIPEIF_DF_GAIN_THR_MASK	(0xfff)
+/* DPCM */
+#define IPIPEIF_DPCM_BITS_SHIFT		(2)
+#define IPIPEIF_DPCM_PRED_SHIFT		(1)
+/* CFG2 */
+#define IPIPEIF_CFG2_HDPOL_SHIFT	(1)
+#define IPIPEIF_CFG2_VDPOL_SHIFT	(2)
+#define IPIPEIF_CFG2_YUV8_SHIFT		(6)
+#define	IPIPEIF_CFG2_YUV16_SHIFT	(3)
+#define	IPIPEIF_CFG2_YUV8P_SHIFT	(7)
+
+/* INIRSZ */
+#define IPIPEIF_INIRSZ_ALNSYNC_SHIFT	(13)
+#define IPIPEIF_INIRSZ_MASK		(0x1fff)
+
+/* CLKDIV */
+#define IPIPEIF_CLKDIV_M_SHIFT		8
+
+int ipipeif_set_address(struct ipipeif *if_params, unsigned int address);
+void ipipeif_set_enable(char en, unsigned int mode);
+int ipipeif_hw_setup(struct ipipeif *if_params, int device_type);
+u32 ipipeif_get_enable(void);
+
+#define DM355	0
+#define DM365	1
+
+#endif
+
+#endif
diff --git a/include/linux/dm3xx_ipipeif.h b/include/linux/dm3xx_ipipeif.h
new file mode 100644
index 0000000..a63ead5
--- /dev/null
+++ b/include/linux/dm3xx_ipipeif.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _DM3XX_IPIPEIF_INCLUDE_H
+#define _DM3XX_IPIPEIF_INCLUDE_H
+
+#include <media/davinci/vpfe.h>
+
+/* IPIPE 5.1 interface types */
+/* dpcm predicator for IPIPE 5.1 */
+enum ipipeif_dpcm_pred {
+	IPIPEIF_DPCM_SIMPLE_PRED,
+	IPIPEIF_DPCM_ADV_PRED
+};
+
+/* clockdiv for IPIPE 5.1 */
+struct ipipeif_5_1_clkdiv {
+	unsigned char m;
+	unsigned char n;
+};
+
+/* data shift for IPIPE 5.1 */
+enum ipipeif_5_1_data_shift {
+	IPIPEIF_5_1_BITS11_0,
+	IPIPEIF_5_1_BITS10_0,
+	IPIPEIF_5_1_BITS9_0,
+	IPIPEIF_5_1_BITS8_0,
+	IPIPEIF_5_1_BITS7_0,
+	IPIPEIF_5_1_BITS15_4,
+};
+
+enum ipipeif_decimation {
+	IPIPEIF_DECIMATION_OFF,
+	IPIPEIF_DECIMATION_ON
+};
+
+/* DPC at the if for IPIPE 5.1 */
+struct ipipeif_dpc {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* threshold */
+	unsigned short thr;
+};
+
+enum	ipipeif_pixel_order {
+	IPIPEIF_CBCR_Y,
+	IPIPEIF_Y_CBCR
+};
+
+#endif
-- 
1.6.2.4


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

* [PATCH v2 2/8] davinci: vpfe: add IPIPE hardware layer support
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver Manjunath Hadli
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Nagabhushana Netagunte, Manjunath Hadli

From: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>

add dm365 IPIPE hardware support. IPIPE is the hardware IP which
implements the functionality required for resizer, previewer and
the associated feature support. This is built along with the vpfe
driver, and implements hardware setup including coeffcient
programming for various hardware filters, gamma, cfa and clock
enable.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/dm365_ipipe_hw.c |  949 ++++++++++++++++++++++++++
 drivers/media/video/davinci/dm365_ipipe_hw.h |  539 +++++++++++++++
 2 files changed, 1488 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c
 create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h

diff --git a/drivers/media/video/davinci/dm365_ipipe_hw.c b/drivers/media/video/davinci/dm365_ipipe_hw.c
new file mode 100644
index 0000000..cb8f6e3
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ipipe_hw.c
@@ -0,0 +1,949 @@
+/*
+* Copyright (C) 2011 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
+*/
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/davinci/vpfe.h>
+#include "dm365_ipipe.h"
+#include "dm3xx_ipipeif.h"
+#include "dm365_ipipe_hw.h"
+
+static void ipipe_clock_enable(void)
+{
+	/* enable IPIPE MMR for register write access */
+	regw_ip(IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR);
+	/* enable the clock wb,cfa,dfc,d2f,pre modules */
+	regw_ip(IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX);
+	/* enable RSZ MMR for register write access */
+}
+
+/* Set input channel format to either 420 Y or C format */
+void rsz_set_in_pix_format(unsigned char y_c)
+{
+	u32 val;
+
+	val = regr_rsz(RSZ_SRC_FMT1);
+	val |= y_c & 1;
+	regw_rsz(val, RSZ_SRC_FMT1);
+}
+
+static void rsz_set_common_params(struct ipipe_params *params)
+{
+	struct rsz_common_params *rsz_common = &params->rsz_common;
+	u32 val;
+
+	/* Set mode */
+	regw_rsz(params->ipipe_mode, RSZ_SRC_MODE);
+
+	/* data source selection  and bypass */
+	val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) |
+		rsz_common->source;
+
+	regw_rsz(val, RSZ_SRC_FMT0);
+	val = regr_rsz(RSZ_SRC_MODE);
+	/* src image selection */
+	val = (rsz_common->raw_flip & 1) |
+		(rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) |
+		((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT);
+
+	regw_rsz(val, RSZ_SRC_FMT1);
+	regw_rsz(rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS);
+	regw_rsz(rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS);
+	regw_rsz(rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ);
+	regw_rsz(rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ);
+	regw_rsz(rsz_common->yuv_y_min, RSZ_YUV_Y_MIN);
+	regw_rsz(rsz_common->yuv_y_max, RSZ_YUV_Y_MAX);
+	regw_rsz(rsz_common->yuv_c_min, RSZ_YUV_C_MIN);
+	regw_rsz(rsz_common->yuv_c_max, RSZ_YUV_C_MAX);
+	/* chromatic position */
+	regw_rsz(rsz_common->out_chr_pos, RSZ_YUV_PHS);
+	val = regr_rsz(RSZ_SRC_MODE);
+}
+
+static void rsz_set_rsz_regs(unsigned int rsz_id, struct ipipe_params *params)
+{
+	struct ipipe_rsz_rescale_param *rsc_params;
+	struct ipipe_ext_mem_param *ext_mem;
+	struct ipipe_rsz_resize2rgb *rgb;
+	u32 reg_base;
+	u32 val;
+
+	val = regr_rsz(RSZ_SEQ);
+	rsc_params = &params->rsz_rsc_param[rsz_id];
+	rgb = &params->rsz2rgb[rsz_id];
+	ext_mem = &params->ext_mem_param[rsz_id];
+
+	if (rsz_id == RSZ_A) {
+		val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT;
+		val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT;
+		reg_base = RSZ_EN_A;
+	} else {
+		val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT;
+		val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT;
+		reg_base = RSZ_EN_B;
+	}
+	/* update flip settings */
+	regw_rsz(val, RSZ_SEQ);
+
+	regw_rsz(rsc_params->mode, reg_base + RSZ_MODE);
+	val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen;
+	regw_rsz(val, reg_base + RSZ_420);
+	regw_rsz(rsc_params->i_vps & RSZ_VPS_MASK, reg_base + RSZ_I_VPS);
+	regw_rsz(rsc_params->i_hps & RSZ_HPS_MASK, reg_base + RSZ_I_HPS);
+	regw_rsz(rsc_params->o_vsz & RSZ_O_VSZ_MASK, reg_base + RSZ_O_VSZ);
+	regw_rsz(rsc_params->o_hsz & RSZ_O_HSZ_MASK, reg_base + RSZ_O_HSZ);
+	regw_rsz(rsc_params->v_phs_y & RSZ_V_PHS_MASK, reg_base + RSZ_V_PHS_Y);
+	regw_rsz(rsc_params->v_phs_c & RSZ_V_PHS_MASK, reg_base + RSZ_V_PHS_C);
+	/* keep this additional adjustment to zero for now */
+	regw_rsz(rsc_params->v_dif & RSZ_V_DIF_MASK, reg_base + RSZ_V_DIF);
+
+	val = (rsc_params->v_typ_y & 1)
+		| ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT);
+	regw_rsz(val, reg_base + RSZ_V_TYP);
+
+	val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) |
+		 ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) <<
+		 RSZ_LPF_INT_C_SHIFT);
+	regw_rsz(val, reg_base + RSZ_V_LPF);
+
+	regw_rsz(rsc_params->h_phs & RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS);
+	regw_rsz(0, reg_base + RSZ_H_PHS_ADJ);
+	regw_rsz(rsc_params->h_dif & RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF);
+	val = (rsc_params->h_typ_y & 1) |
+		((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT);
+	regw_rsz(val, reg_base + RSZ_H_TYP);
+	val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) |
+		 ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) <<
+		 RSZ_LPF_INT_C_SHIFT);
+	regw_rsz(val, reg_base + RSZ_H_LPF);
+
+	regw_rsz(rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN);
+	val = rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK;
+	val |= (rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) <<
+		  RSZ_DWN_SCALE_AV_SZ_V_SHIFT;
+	regw_rsz(val, reg_base + RSZ_DWN_AV);
+
+	/* setting rgb conversion parameters */
+	regw_rsz(rgb->rgb_en, reg_base + RSZ_RGB_EN);
+	val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) |
+		 (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) |
+		 (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT);
+	regw_rsz(val, reg_base + RSZ_RGB_TYP);
+	regw_rsz(rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK,
+		reg_base + RSZ_RGB_BLD);
+
+	/* setting external memory parameters */
+	regw_rsz(ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT);
+	regw_rsz(ext_mem->rsz_sdr_ptr_s_y, reg_base + RSZ_SDR_Y_PTR_S);
+	regw_rsz(ext_mem->rsz_sdr_ptr_e_y, reg_base + RSZ_SDR_Y_PTR_E);
+	regw_rsz(ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT);
+	regw_rsz(ext_mem->rsz_sdr_ptr_s_c, reg_base + RSZ_SDR_C_PTR_S);
+	regw_rsz((ext_mem->rsz_sdr_ptr_e_c >> 1), reg_base + RSZ_SDR_C_PTR_E);
+}
+
+static void ipipe_setup_resizer(struct ipipe_params *params)
+{				/*set the registers of either RSZ0 or RSZ1 */
+	u32 val;
+
+	/* enable MMR gate to write to Resizer */
+	regw_rsz(1, RSZ_GCK_MMR);
+
+	/* Enable resizer if it is not in bypass mode */
+	if (params->rsz_common.passthrough)
+		regw_rsz(0, RSZ_GCK_SDR);
+	else
+		regw_rsz(1, RSZ_GCK_SDR);
+
+	rsz_set_common_params(params);
+
+	regw_rsz(params->rsz_en[RSZ_A], RSZ_EN_A);
+	if (params->rsz_en[RSZ_A])
+		/*setting rescale parameters */
+		rsz_set_rsz_regs(RSZ_A, params);
+
+	regw_rsz(params->rsz_en[RSZ_B], RSZ_EN_B);
+	if (params->rsz_en[RSZ_B])
+		rsz_set_rsz_regs(RSZ_B, params);
+
+	val = regr_rsz(RSZ_SRC_MODE);
+}
+
+/* ipipe_hw_setup:It is used for Hardware Setup */
+int ipipe_hw_setup(struct ipipe_params *config)
+{
+	u32 data_format;
+	u32 val;
+
+	if (!config) {
+		printk(KERN_ERR "NULL config block received\n");
+		return -EINVAL;
+	}
+
+	if (ipipeif_hw_setup(&config->ipipeif_param, DM365) < 0) {
+		printk(KERN_ERR "Unable to configure IPIPEIF");
+		return -EINVAL;
+	}
+
+	/* enable clock to IPIPE */
+	vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
+	/* enable clock to MMR and modules before writting
+	 * to ipipe registers
+	 */
+	ipipe_clock_enable();
+
+	if (config->rsz_common.source == IPIPEIF_DATA) {
+		/* we need to skip configuring IPIPE */
+		regw_ip(0, IPIPE_SRC_EN);
+	} else {
+		/* enable ipipe mode to either one shot or continuous */
+		val = config->ipipe_mode;
+		regw_ip(val, IPIPE_SRC_MODE);
+		data_format = config->ipipe_dpaths_fmt;
+		regw_ip(data_format, IPIPE_SRC_FMT);
+		/* set size */
+		regw_ip(config->ipipe_vps & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS);
+		regw_ip(config->ipipe_hps & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS);
+		regw_ip(config->ipipe_vsz & IPIPE_RSZ_VSZ_MASK, IPIPE_SRC_VSZ);
+		regw_ip(config->ipipe_hsz & IPIPE_RSZ_HSZ_MASK, IPIPE_SRC_HSZ);
+
+		if ((data_format == IPIPE_RAW2YUV) ||
+		    (data_format == IPIPE_RAW2RAW)) {
+			/* Combine all the fields to make COLPAT register
+			 * of IPIPE
+			 */
+			val = config->ipipe_colpat_elep <<
+				COLPAT_EE_SHIFT;
+			val |= config->ipipe_colpat_elop <<
+				COLPAT_EO_SHIFT;
+			val |= config->ipipe_colpat_olep <<
+				COLPAT_OE_SHIFT;
+			val |= config->ipipe_colpat_olop <<
+				COLPAT_OO_SHIFT;
+			regw_ip(val, IPIPE_SRC_COL);
+		}
+	}
+	ipipe_setup_resizer(config);
+
+	return 0;
+}
+
+static void rsz_set_y_address(unsigned int address, unsigned int offset)
+{
+	u32 val;
+
+	val = address & SET_LOW_ADD;
+	regw_rsz(val, offset + RSZ_SDR_Y_BAD_L);
+	regw_rsz(val, offset + RSZ_SDR_Y_SAD_L);
+	val = (address & SET_HIGH_ADD) >> 16;
+	regw_rsz(val, offset + RSZ_SDR_Y_BAD_H);
+	regw_rsz(val, offset + RSZ_SDR_Y_SAD_H);
+}
+
+static void rsz_set_c_address(unsigned int address, unsigned int offset)
+{
+	u32 val;
+
+	val = address & SET_LOW_ADD;
+
+	regw_rsz(val, offset + RSZ_SDR_C_BAD_L);
+	regw_rsz(val, offset + RSZ_SDR_C_SAD_L);
+	val = (address & SET_HIGH_ADD) >> 16;
+	regw_rsz(val, offset + RSZ_SDR_C_BAD_H);
+	regw_rsz(val, offset + RSZ_SDR_C_SAD_H);
+}
+
+/* Assume we get a valid params ptr and resize_no set to RSZ_A
+ * or RSZ_B. This could be called in the interrupt context and
+ * must be efficient
+ */
+void rsz_set_output_address(struct ipipe_params *params,
+			   int resize_no, unsigned int address)
+{
+	unsigned int rsz_start_add;
+	unsigned int val;
+
+	struct ipipe_ext_mem_param *mem_param =
+		&params->ext_mem_param[resize_no];
+	struct rsz_common_params *rsz_common =
+		&params->rsz_common;
+	struct ipipe_rsz_rescale_param *rsc_param =
+		&params->rsz_rsc_param[resize_no];
+
+	if (resize_no == RSZ_A)
+		rsz_start_add = RSZ_EN_A;
+	else
+		rsz_start_add = RSZ_EN_B;
+	/* y_c = 0 for y, = 1 for c */
+	if (rsz_common->src_img_fmt == RSZ_IMG_420) {
+		if (rsz_common->y_c) {
+			/* C channel */
+			val = address + mem_param->flip_ofst_c;
+			rsz_set_c_address(val, rsz_start_add);
+		} else {
+			val = address + mem_param->flip_ofst_y;
+			rsz_set_y_address(val, rsz_start_add);
+		}
+	} else {
+		if (rsc_param->cen && rsc_param->yen) {
+			/* 420 */
+			val = address + mem_param->c_offset;
+			val = address + mem_param->c_offset +
+				mem_param->flip_ofst_c;
+			val += mem_param->user_y_ofst +
+				mem_param->user_c_ofst;
+			if (resize_no == RSZ_B)
+				val +=
+				params->ext_mem_param[RSZ_A].user_y_ofst +
+				params->ext_mem_param[RSZ_A].user_c_ofst;
+			/* set C address */
+			rsz_set_c_address(val, rsz_start_add);
+		}
+		val = address + mem_param->flip_ofst_y;
+		val += mem_param->user_y_ofst;
+		if (resize_no == RSZ_B)
+			val += params->ext_mem_param[RSZ_A].user_y_ofst +
+				params->ext_mem_param[RSZ_A].user_c_ofst;
+		/* set Y address */
+		rsz_set_y_address(val, rsz_start_add);
+	}
+	/* resizer must be enabled */
+	regw_rsz(params->rsz_en[resize_no], rsz_start_add);
+
+}
+
+void ipipe_set_lutdpc_regs(struct prev_lutdpc *dpc)
+{
+	u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1;
+	u32 lut_start_addr = DPC_TB0_START_ADDR;
+	u32 val;
+	u32 count;
+
+	ipipe_clock_enable();
+	regw_ip(dpc->en, DPC_LUT_EN);
+	if (dpc->en != 1)
+		return;
+
+	/* if dpc is enabled */
+	val = LUTDPC_TBL_256_EN;
+	val |= dpc->repl_white & 1;
+	regw_ip(val, DPC_LUT_SEL);
+	regw_ip(LUT_DPC_START_ADDR, DPC_LUT_ADR);
+	regw_ip(dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK);
+
+	if (dpc->table == NULL)
+		return;
+
+	for (count = 0; count < dpc->dpc_size; count++) {
+		if (count >= max_tbl_size)
+			lut_start_addr = DPC_TB1_START_ADDR;
+		val = dpc->table[count].horz_pos
+			& LUT_DPC_H_POS_MASK;
+		val |= (dpc->table[count].vert_pos &
+			LUT_DPC_V_POS_MASK) <<
+			LUT_DPC_V_POS_SHIFT;
+		val |= dpc->table[count].method <<
+			LUT_DPC_CORR_METH_SHIFT;
+		w_ip_table(val, (lut_start_addr +
+			((count % max_tbl_size) << 2)));
+	}
+}
+
+static void set_dpc_thresholds(struct prev_otfdpc_2_0 *dpc_thr)
+{
+	regw_ip((dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2C_THR_R);
+	regw_ip((dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2C_THR_GR);
+	regw_ip((dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2C_THR_GB);
+	regw_ip((dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2C_THR_B);
+	regw_ip((dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2D_THR_R);
+	regw_ip((dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2D_THR_GR);
+	regw_ip((dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2D_THR_GB);
+	regw_ip((dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK),
+		DPC_OTF_2D_THR_B);
+}
+
+void ipipe_set_otfdpc_regs(struct prev_otfdpc *otfdpc)
+{
+	struct prev_otfdpc_2_0 *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0;
+	struct prev_otfdpc_3_0 *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0;
+	u32 val;
+
+	ipipe_clock_enable();
+
+	regw_ip((otfdpc->en & 1), DPC_OTF_EN);
+	if (otfdpc->en != 1)
+		return;
+
+	/* dpc enabled */
+	val = otfdpc->det_method << OTF_DET_METHOD_SHIFT;
+	val |= otfdpc->alg;
+	regw_ip(val, DPC_OTF_TYP);
+	if (otfdpc->det_method == IPIPE_DPC_OTF_MIN_MAX) {
+		/* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0
+		 * DPC_OTF_2C_THR_[x] = Maximum thresohld
+		 * MinMax method
+		 */
+		dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb =
+		dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0;
+		set_dpc_thresholds(dpc_2_0);
+	} else {
+		/* MinMax2 */
+		if (otfdpc->alg == IPIPE_OTFDPC_2_0)
+			set_dpc_thresholds(dpc_2_0);
+		else {
+			regw_ip((dpc_3_0->act_adj_shf & OTF_DPC3_0_SHF_MASK),
+				DPC_OTF_3_SHF);
+			/* Detection thresholds */
+			regw_ip(((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) <<
+				OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR);
+			regw_ip((dpc_3_0->det_slp & OTF_DPC3_0_SLP_MASK),
+				DPC_OTF_3D_SLP);
+			regw_ip((dpc_3_0->det_thr_min & OTF_DPC3_0_DET_MASK),
+				DPC_OTF_3D_MIN);
+			regw_ip((dpc_3_0->det_thr_max & OTF_DPC3_0_DET_MASK),
+				DPC_OTF_3D_MAX);
+			/* Correction thresholds */
+			regw_ip(((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) <<
+				OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR);
+			regw_ip((dpc_3_0->corr_slp & OTF_DPC3_0_SLP_MASK),
+				DPC_OTF_3C_SLP);
+			regw_ip((dpc_3_0->corr_thr_min & OTF_DPC3_0_CORR_MASK),
+				DPC_OTF_3C_MIN);
+			regw_ip((dpc_3_0->corr_thr_max & OTF_DPC3_0_CORR_MASK),
+				DPC_OTF_3C_MAX);
+		}
+	}
+}
+
+/* 2D Noise filter */
+void ipipe_set_d2f_regs(unsigned int id, struct prev_nf *noise_filter)
+{
+
+	u32 offset = D2F_1ST;
+	int count;
+	u32 val;
+
+	/* id = 0 , NF1 & id = 1, NF 2 */
+	if (id)
+		offset = D2F_2ND;
+	ipipe_clock_enable();
+	regw_ip(noise_filter->en & 1, offset + D2F_EN);
+	if (noise_filter->en != 1)
+		return;
+
+	/*noise filter enabled */
+	/* Combine all the fields to make D2F_CFG register of IPIPE */
+	val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) <<
+		 D2F_SPR_VAL_SHIFT) |
+		 ((noise_filter->shft_val & D2F_SHFT_VAL_MASK) <<
+		 D2F_SHFT_VAL_SHIFT) |
+		 (noise_filter->gr_sample_meth <<
+		 D2F_SAMPLE_METH_SHIFT) |
+		 ((noise_filter->apply_lsc_gain & 1) <<
+		 D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL;
+
+	regw_ip(val, offset + D2F_TYP);
+	/* edge detection minimum */
+	regw_ip(noise_filter->edge_det_min_thr & D2F_EDGE_DET_THR_MASK,
+		offset + D2F_EDG_MIN);
+	/* edge detection maximum */
+	regw_ip(noise_filter->edge_det_max_thr & D2F_EDGE_DET_THR_MASK,
+		offset + D2F_EDG_MAX);
+	for (count = 0; count < IPIPE_NF_STR_TABLE_SIZE; count++) {
+		regw_ip((noise_filter->str[count] & D2F_STR_VAL_MASK),
+			offset + D2F_STR + count * 4);
+
+	}
+	for (count = 0; count < IPIPE_NF_THR_TABLE_SIZE; count++) {
+		regw_ip(noise_filter->thr[count] & D2F_THR_VAL_MASK,
+			offset + D2F_THR + count * 4);
+	}
+}
+
+#define IPIPE_U8Q5(decimal, integer) \
+	(((decimal & 0x1f) | ((integer & 0x7) << 5)))
+
+/* Green Imbalance Correction */
+void ipipe_set_gic_regs(struct prev_gic *gic)
+{
+	u32 val;
+
+	ipipe_clock_enable();
+	regw_ip(gic->en & 1, GIC_EN);
+
+	if (!gic->en)
+		return;
+
+	/*gic enabled */
+	val = gic->wt_fn_type << GIC_TYP_SHIFT;
+	val |= gic->thr_sel << GIC_THR_SEL_SHIFT;
+	val |= (gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT;
+	regw_ip(val, GIC_TYP);
+	regw_ip(gic->gain & GIC_GAIN_MASK, GIC_GAN);
+	if (gic->gic_alg == IPIPE_GIC_ALG_ADAPT_GAIN) {
+		if (gic->thr_sel == IPIPE_GIC_THR_REG) {
+			regw_ip(gic->thr & GIC_THR_MASK, GIC_THR);
+			regw_ip(gic->slope & GIC_SLOPE_MASK, GIC_SLP);
+		} else {
+			/* Use NF thresholds */
+			val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal,
+					gic->nf2_thr_gain.integer);
+			regw_ip(val, GIC_NFGAN);
+		}
+	} else
+		/* Constant Gain. Set threshold to maximum */
+		regw_ip(GIC_THR_MASK, GIC_THR);
+}
+
+#define IPIPE_U13Q9(decimal, integer) \
+	(((decimal & 0x1ff) | ((integer & 0xf) << 9)))
+/* White balance */
+void ipipe_set_wb_regs(struct prev_wb *wb)
+{
+	u32 val;
+
+	ipipe_clock_enable();
+	/* Ofsets. S12 */
+	regw_ip(wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R);
+	regw_ip(wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR);
+	regw_ip(wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB);
+	regw_ip(wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B);
+
+	/* Gains. U13Q9 */
+	val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
+	regw_ip(val, WB2_WGN_R);
+	val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
+	regw_ip(val, WB2_WGN_GR);
+	val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
+	regw_ip(val, WB2_WGN_GB);
+	val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
+	regw_ip(val, WB2_WGN_B);
+}
+
+/* CFA */
+void ipipe_set_cfa_regs(struct prev_cfa *cfa)
+{
+	ipipe_clock_enable();
+	regw_ip(cfa->alg, CFA_MODE);
+	regw_ip(cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK, CFA_2DIR_HPF_THR);
+	regw_ip(cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK, CFA_2DIR_HPF_SLP);
+	regw_ip(cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
+			CFA_2DIR_MIX_THR);
+	regw_ip(cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
+			CFA_2DIR_MIX_SLP);
+	regw_ip(cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK, CFA_2DIR_DIR_THR);
+	regw_ip(cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK, CFA_2DIR_DIR_SLP);
+	regw_ip(cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK, CFA_2DIR_NDWT);
+	regw_ip(cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK, CFA_MONO_HUE_FRA);
+	regw_ip(cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK, CFA_MONO_EDG_THR);
+	regw_ip(cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK, CFA_MONO_THR_MIN);
+	regw_ip(cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK, CFA_MONO_THR_SLP);
+	regw_ip(cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK, CFA_MONO_SLP_MIN);
+	regw_ip(cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK, CFA_MONO_SLP_SLP);
+	regw_ip(cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK, CFA_MONO_LPWT);
+}
+
+void ipipe_set_rgb2rgb_regs(unsigned int id, struct prev_rgb2rgb *rgb)
+{
+	u32 offset_mask = RGB2RGB_1_OFST_MASK;
+	u32 offset = RGB1_MUL_BASE;
+	u32 integ_mask = 0xf;
+	u32 val;
+
+	ipipe_clock_enable();
+
+	if (id) {
+		/* For second RGB module, gain integer is 3 bits instead
+		of 4, offset has 11 bits insread of 13 */
+		offset = RGB2_MUL_BASE;
+		integ_mask = 0x7;
+		offset_mask = RGB2RGB_2_OFST_MASK;
+	}
+	/* Gains */
+	val = (rgb->coef_rr.decimal & 0xff) |
+		((rgb->coef_rr.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_RR);
+	val = (rgb->coef_gr.decimal & 0xff) |
+		((rgb->coef_gr.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_GR);
+	val = (rgb->coef_br.decimal & 0xff) |
+		((rgb->coef_br.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_BR);
+	val = (rgb->coef_rg.decimal & 0xff) |
+		((rgb->coef_rg.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_RG);
+	val = (rgb->coef_gg.decimal & 0xff) |
+		((rgb->coef_gg.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_GG);
+	val = (rgb->coef_bg.decimal & 0xff) |
+		((rgb->coef_bg.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_BG);
+	val = (rgb->coef_rb.decimal & 0xff) |
+		((rgb->coef_rb.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_RB);
+	val = (rgb->coef_gb.decimal & 0xff) |
+		((rgb->coef_gb.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_GB);
+	val = (rgb->coef_bb.decimal & 0xff) |
+		((rgb->coef_bb.integer & integ_mask) << 8);
+	regw_ip(val, offset + RGB_MUL_BB);
+
+	/* Offsets */
+	regw_ip(rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR);
+	regw_ip(rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG);
+	regw_ip(rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB);
+}
+
+static void ipipe_update_gamma_tbl(struct ipipe_gamma_entry *table,
+				   int size, u32 addr)
+{
+	int count;
+	u32 val;
+
+	for (count = 0; count < size; count++) {
+		val = table[count].slope & GAMMA_MASK;
+		val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT;
+		w_ip_table(val, (addr + (count * 4)));
+	}
+}
+
+/* Gamma correction */
+void ipipe_set_gamma_regs(struct prev_gamma *gamma)
+{
+	int table_size;
+	u32 val;
+
+	ipipe_clock_enable();
+	val = (gamma->bypass_r << GAMMA_BYPR_SHIFT)
+		| (gamma->bypass_b << GAMMA_BYPG_SHIFT)
+		| (gamma->bypass_g << GAMMA_BYPB_SHIFT)
+		| (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT)
+		| (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT);
+
+	regw_ip(val, GMM_CFG);
+
+	if (gamma->tbl_sel == IPIPE_GAMMA_TBL_RAM) {
+		table_size = gamma->tbl_size;
+
+		if (!(gamma->bypass_r) && (gamma->table_r != NULL)) {
+			ipipe_update_gamma_tbl(gamma->table_r,
+					       table_size,
+					       GAMMA_R_START_ADDR);
+		}
+		if (!(gamma->bypass_b) && (gamma->table_b != NULL)) {
+			ipipe_update_gamma_tbl(gamma->table_b,
+					       table_size,
+					       GAMMA_B_START_ADDR);
+		}
+		if (!(gamma->bypass_g) && (gamma->table_g != NULL)) {
+			ipipe_update_gamma_tbl(gamma->table_g,
+					       table_size,
+					       GAMMA_G_START_ADDR);
+		}
+	}
+}
+
+/* 3D LUT */
+void ipipe_set_3d_lut_regs(struct prev_3d_lut *lut_3d)
+{
+	struct ipipe_3d_lut_entry *tbl;
+	u32 bnk_index;
+	u32 tbl_index;
+	u32 val;
+	u32 i;
+
+	ipipe_clock_enable();
+	regw_ip(lut_3d->en, D3LUT_EN);
+
+	if (!lut_3d->en)
+		return;
+
+	/* lut_3d enabled */
+	if (!lut_3d->table)
+		return;
+
+	/* valied table */
+	tbl = lut_3d->table;
+	for (i = 0 ; i < MAX_SIZE_3D_LUT; i++) {
+		/* Each entry has 0-9 (B), 10-19 (G) and
+		20-29 R values */
+		val = tbl[i].b & D3_LUT_ENTRY_MASK;
+		val |= (tbl[i].g & D3_LUT_ENTRY_MASK) <<
+			 D3_LUT_ENTRY_G_SHIFT;
+		val |= (tbl[i].r & D3_LUT_ENTRY_MASK) <<
+			 D3_LUT_ENTRY_R_SHIFT;
+		bnk_index = i % 4;
+		tbl_index = i >> 2;
+		tbl_index <<= 2;
+		if (bnk_index == 0)
+			w_ip_table(val, tbl_index + D3L_TB0_START_ADDR);
+		else if (bnk_index == 1)
+			w_ip_table(val, tbl_index + D3L_TB1_START_ADDR);
+		else if (bnk_index == 2)
+			w_ip_table(val, tbl_index + D3L_TB2_START_ADDR);
+		else
+			w_ip_table(val, tbl_index + D3L_TB3_START_ADDR);
+	}
+}
+
+/* Lumina adjustments */
+void ipipe_set_lum_adj_regs(struct prev_lum_adj *lum_adj)
+{
+	u32 val;
+
+	ipipe_clock_enable();
+	/* combine fields of YUV_ADJ to set brightness and contrast */
+	val = (lum_adj->contrast << LUM_ADJ_CONTR_SHIFT)
+		|(lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT);
+	regw_ip(val, YUV_ADJ);
+}
+
+#define IPIPE_S12Q8(decimal, integer) \
+	(((decimal & 0xff) | ((integer & 0xf) << 8)))
+/* RGB2YUV */
+void ipipe_set_rgb2ycbcr_regs(struct prev_rgb2yuv *yuv)
+{
+	u32 val;
+
+	/* S10Q8 */
+	ipipe_clock_enable();
+	val = IPIPE_S12Q8(yuv->coef_ry.decimal, yuv->coef_ry.integer);
+	regw_ip(val, YUV_MUL_RY);
+	val = IPIPE_S12Q8(yuv->coef_gy.decimal, yuv->coef_gy.integer);
+	regw_ip(val, YUV_MUL_GY);
+	val = IPIPE_S12Q8(yuv->coef_by.decimal, yuv->coef_by.integer);
+	regw_ip(val, YUV_MUL_BY);
+	val = IPIPE_S12Q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer);
+	regw_ip(val, YUV_MUL_RCB);
+	val = IPIPE_S12Q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer);
+	regw_ip(val, YUV_MUL_GCB);
+	val = IPIPE_S12Q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer);
+	regw_ip(val, YUV_MUL_BCB);
+	val = IPIPE_S12Q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer);
+	regw_ip(val, YUV_MUL_RCR);
+	val = IPIPE_S12Q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer);
+	regw_ip(val, YUV_MUL_GCR);
+	val = IPIPE_S12Q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer);
+	regw_ip(val, YUV_MUL_BCR);
+	regw_ip(yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y);
+	regw_ip(yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB);
+	regw_ip(yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR);
+}
+
+/* YUV 422 conversion */
+void ipipe_set_yuv422_conv_regs(struct prev_yuv422_conv *conv)
+{
+	u32 val;
+
+	ipipe_clock_enable();
+	/* Combine all the fields to make YUV_PHS register of IPIPE */
+	val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1);
+	regw_ip(val, YUV_PHS);
+}
+
+/* GBCE */
+void ipipe_set_gbce_regs(struct prev_gbce *gbce)
+{
+	unsigned int tbl_index;
+	unsigned int count;
+	u32 mask = GBCE_Y_VAL_MASK;
+	u32 val;
+
+	if (gbce->type == IPIPE_GBCE_GAIN_TBL)
+		mask = GBCE_GAIN_VAL_MASK;
+
+	ipipe_clock_enable();
+	regw_ip(gbce->en & 1, GBCE_EN);
+
+	if (!gbce->en)
+		return;
+
+	regw_ip(gbce->type, GBCE_TYP);
+
+	if (!gbce->table)
+		return;
+
+	/* set to 0 */
+	val = 0;
+
+	for (count = 0; count < MAX_SIZE_GBCE_LUT; count++) {
+		tbl_index = count >> 1;
+		tbl_index <<= 2;
+		/* Each table has 2 LUT entries, first in LS
+		  * and second in MS positions
+		  */
+		if (count % 2) {
+			val |=
+				(gbce->table[count] & mask) <<
+				GBCE_ENTRY_SHIFT;
+			w_ip_table(val, tbl_index + GBCE_TB_START_ADDR);
+		} else
+			val = gbce->table[count] & mask;
+	}
+}
+
+/* Edge Enhancement */
+void ipipe_set_ee_regs(struct prev_yee *ee)
+{
+	unsigned int tbl_index;
+	unsigned int count;
+	u32 val;
+
+	ipipe_clock_enable();
+	regw_ip(ee->en, YEE_EN);
+
+	if (!ee->en)
+		return;
+
+	val = ee->en_halo_red & 1;
+	val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT;
+	regw_ip(val, YEE_TYP);
+	regw_ip(ee->hpf_shft, YEE_SHF);
+	regw_ip(ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00);
+	regw_ip(ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01);
+	regw_ip(ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02);
+	regw_ip(ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10);
+	regw_ip(ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11);
+	regw_ip(ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12);
+	regw_ip(ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20);
+	regw_ip(ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21);
+	regw_ip(ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22);
+	regw_ip(ee->yee_thr & YEE_THR_MASK, YEE_THR);
+	regw_ip(ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN);
+	regw_ip(ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1);
+	regw_ip(ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2);
+	regw_ip(ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN);
+	regw_ip(ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT);
+
+	if (ee->table == NULL)
+		return;
+
+	for (count = 0; count < MAX_SIZE_YEE_LUT; count++) {
+		tbl_index = count >> 1;
+		tbl_index <<= 2;
+		/* Each table has 2 LUT entries, first in LS
+		  * and second in MS positions
+		  */
+		if (count % 2) {
+			val |= (ee->table[count] &
+				YEE_ENTRY_MASK) <<
+				YEE_ENTRY_SHIFT;
+			w_ip_table(val,
+				tbl_index + YEE_TB_START_ADDR);
+		} else
+			val = ee->table[count] &
+				YEE_ENTRY_MASK;
+	}
+}
+
+/* Chromatic Artifact Correction. CAR */
+static void ipipe_set_mf(void)
+{
+	/* typ to dynamic switch */
+	regw_ip(IPIPE_CAR_DYN_SWITCH, CAR_TYP);
+	/* Set SW0 to maximum */
+	regw_ip(CAR_MF_THR, CAR_SW);
+}
+
+static void ipipe_set_gain_ctrl(struct prev_car *car)
+{
+	regw_ip(IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP);
+	regw_ip(car->hpf, CAR_HPF_TYP);
+	regw_ip(car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF);
+	regw_ip(car->hpf_thr, CAR_HPF_THR);
+	regw_ip(car->gain1.gain, CAR_GN1_GAN);
+	regw_ip(car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF);
+	regw_ip(car->gain1.gain_min & CAR_GAIN_MIN_MASK, CAR_GN1_MIN);
+	regw_ip(car->gain2.gain, CAR_GN2_GAN);
+	regw_ip(car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF);
+	regw_ip(car->gain2.gain_min & CAR_GAIN_MIN_MASK, CAR_GN2_MIN);
+}
+
+void ipipe_set_car_regs(struct prev_car *car)
+{
+	u32 val;
+
+	ipipe_clock_enable();
+	regw_ip(car->en, CAR_EN);
+
+	if (!car->en)
+		return;
+
+	switch (car->meth) {
+	case IPIPE_CAR_MED_FLTR:
+		ipipe_set_mf();
+		break;
+	case IPIPE_CAR_CHR_GAIN_CTRL:
+		ipipe_set_gain_ctrl(car);
+		break;
+	default:
+		/* Dynamic switch between MF and Gain Ctrl. */
+		ipipe_set_mf();
+		ipipe_set_gain_ctrl(car);
+		/* Set the threshold for switching between
+		  * the two Here we overwrite the MF SW0 value
+		  */
+		regw_ip(IPIPE_CAR_DYN_SWITCH, CAR_TYP);
+		val = car->sw1;
+		val <<= CAR_SW1_SHIFT;
+		val |= car->sw0;
+		regw_ip(val, CAR_SW);
+	}
+}
+
+/* Chromatic Gain Suppression */
+void ipipe_set_cgs_regs(struct prev_cgs *cgs)
+{
+	ipipe_clock_enable();
+	regw_ip(cgs->en, CGS_EN);
+
+	if (cgs->en) {
+		/* Set the bright side parameters */
+		regw_ip(cgs->h_thr, CGS_GN1_H_THR);
+		regw_ip(cgs->h_slope, CGS_GN1_H_GAN);
+		regw_ip(cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF);
+		regw_ip(cgs->h_min, CGS_GN1_H_MIN);
+	}
+}
+
+void rsz_src_enable(int enable)
+{
+	regw_rsz(enable, RSZ_SRC_EN);
+}
+
+int rsz_enable(int rsz_id, int enable)
+{
+	if (rsz_id == RSZ_A) {
+		regw_rsz(enable, RSZ_EN_A);
+		/* We always enable RSZ_A. RSZ_B is enable upon request from
+		 * application. So enable RSZ_SRC_EN along with RSZ_A
+		 */
+		regw_rsz(enable, RSZ_SRC_EN);
+	} else if (rsz_id == RSZ_B)
+		regw_rsz(enable, RSZ_EN_B);
+	else
+		return -EINVAL;
+
+	return 0;
+}
diff --git a/drivers/media/video/davinci/dm365_ipipe_hw.h b/drivers/media/video/davinci/dm365_ipipe_hw.h
new file mode 100644
index 0000000..0500e8b
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ipipe_hw.h
@@ -0,0 +1,539 @@
+/*
+* Copyright (C) 2011 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
+*/
+#ifndef _DM365_IPIPE_HW_H
+#define _DM365_IPIPE_HW_H
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#define IPIPE_IOBASE_VADDR		IO_ADDRESS(0x01c70800)
+#define RSZ_IOBASE_VADDR		IO_ADDRESS(0x01c70400)
+#define IPIPE_INT_TABLE_IOBASE_VADDR	IO_ADDRESS(0x01c70000)
+
+#define SET_LOW_ADD     0x0000ffff
+#define SET_HIGH_ADD    0xffff0000
+
+/* Below are the internal tables */
+#define DPC_TB0_START_ADDR	(0x8000)
+#define DPC_TB1_START_ADDR	(0x8400)
+
+#define GAMMA_R_START_ADDR	(0xa800)
+#define GAMMA_G_START_ADDR	(0xb000)
+#define GAMMA_B_START_ADDR	(0xb800)
+
+/* RAM table addresses for edge enhancement correction*/
+#define YEE_TB_START_ADDR	(0x8800)
+
+/* RAM table address for GBC LUT */
+#define GBCE_TB_START_ADDR	(0x9000)
+
+/* RAM table for 3D NF LUT */
+#define D3L_TB0_START_ADDR	(0x9800)
+#define D3L_TB1_START_ADDR	(0x9c00)
+#define D3L_TB2_START_ADDR	(0xa000)
+#define D3L_TB3_START_ADDR	(0xa400)
+
+/* IPIPE Register Offsets from the base address */
+#define IPIPE_SRC_EN		(0x0000)
+#define IPIPE_SRC_MODE		(0x0004)
+#define IPIPE_SRC_FMT		(0x0008)
+#define IPIPE_SRC_COL		(0x000c)
+#define IPIPE_SRC_VPS		(0x0010)
+#define IPIPE_SRC_VSZ		(0x0014)
+#define IPIPE_SRC_HPS		(0x0018)
+#define IPIPE_SRC_HSZ		(0x001c)
+
+#define IPIPE_SEL_SBU		(0x0020)
+
+#define IPIPE_DMA_STA		(0x0024)
+#define IPIPE_GCK_MMR		(0x0028)
+#define IPIPE_GCK_PIX		(0x002c)
+#define IPIPE_RESERVED0		(0x0030)
+
+/* Defect Correction */
+#define DPC_LUT_EN		(0x0034)
+#define DPC_LUT_SEL		(0x0038)
+#define DPC_LUT_ADR		(0x003c)
+#define DPC_LUT_SIZ		(0x0040)
+#define DPC_OTF_EN		(0x0044)
+#define DPC_OTF_TYP		(0x0048)
+#define DPC_OTF_2D_THR_R	(0x004c)
+#define DPC_OTF_2D_THR_GR	(0x0050)
+#define DPC_OTF_2D_THR_GB	(0x0054)
+#define DPC_OTF_2D_THR_B	(0x0058)
+#define DPC_OTF_2C_THR_R	(0x005c)
+#define DPC_OTF_2C_THR_GR	(0x0060)
+#define DPC_OTF_2C_THR_GB	(0x0064)
+#define DPC_OTF_2C_THR_B	(0x0068)
+#define DPC_OTF_3_SHF		(0x006c)
+#define DPC_OTF_3D_THR		(0x0070)
+#define DPC_OTF_3D_SLP		(0x0074)
+#define DPC_OTF_3D_MIN		(0x0078)
+#define DPC_OTF_3D_MAX		(0x007c)
+#define DPC_OTF_3C_THR		(0x0080)
+#define DPC_OTF_3C_SLP		(0x0084)
+#define DPC_OTF_3C_MIN		(0x0088)
+#define DPC_OTF_3C_MAX		(0x008c)
+
+/* Lense Shading Correction */
+#define LSC_VOFT		(0x90)
+#define LSC_VA2			(0x94)
+#define LSC_VA1			(0x98)
+#define LSC_VS			(0x9c)
+#define LSC_HOFT		(0xa0)
+#define LSC_HA2			(0xa4)
+#define LSC_HA1			(0xa8)
+#define LSC_HS			(0xac)
+#define LSC_GAIN_R		(0xb0)
+#define LSC_GAIN_GR		(0xb4)
+#define LSC_GAIN_GB		(0xb8)
+#define LSC_GAIN_B		(0xbc)
+#define LSC_OFT_R		(0xc0)
+#define LSC_OFT_GR		(0xc4)
+#define LSC_OFT_GB		(0xc8)
+#define LSC_OFT_B		(0xcc)
+#define LSC_SHF			(0xd0)
+#define LSC_MAX			(0xd4)
+
+/* Noise Filter 1. Ofsets from start address given */
+#define D2F_1ST			(0xd8)
+#define D2F_EN			(0x0)
+#define D2F_TYP			(0x4)
+#define D2F_THR			(0x8)
+#define D2F_STR			(0x28)
+#define D2F_SPR			(0x48)
+#define D2F_EDG_MIN		(0x68)
+#define D2F_EDG_MAX		(0x6c)
+
+/* Noise Filter 2 */
+#define D2F_2ND			(0x148)
+
+/* GIC */
+#define GIC_EN			(0x1b8)
+#define GIC_TYP			(0x1bc)
+#define GIC_GAN			(0x1c0)
+#define GIC_NFGAN		(0x1c4)
+#define GIC_THR			(0x1c8)
+#define GIC_SLP			(0x1cc)
+
+/* White Balance */
+#define WB2_OFT_R		(0x1d0)
+#define WB2_OFT_GR		(0x1d4)
+#define WB2_OFT_GB		(0x1d8)
+#define WB2_OFT_B		(0x1dc)
+#define WB2_WGN_R		(0x1e0)
+#define WB2_WGN_GR		(0x1e4)
+#define WB2_WGN_GB		(0x1e8)
+#define WB2_WGN_B		(0x1ec)
+
+/* CFA interpolation */
+#define CFA_MODE		(0x1f0)
+#define CFA_2DIR_HPF_THR	(0x1f4)
+#define CFA_2DIR_HPF_SLP	(0x1f8)
+#define CFA_2DIR_MIX_THR	(0x1fc)
+#define CFA_2DIR_MIX_SLP	(0x200)
+#define CFA_2DIR_DIR_THR	(0x204)
+#define CFA_2DIR_DIR_SLP	(0x208)
+#define CFA_2DIR_NDWT		(0x20c)
+#define CFA_MONO_HUE_FRA	(0x210)
+#define CFA_MONO_EDG_THR	(0x214)
+#define CFA_MONO_THR_MIN	(0x218)
+#define CFA_MONO_THR_SLP	(0x21c)
+#define CFA_MONO_SLP_MIN	(0x220)
+#define CFA_MONO_SLP_SLP	(0x224)
+#define CFA_MONO_LPWT		(0x228)
+
+/* RGB to RGB conversiona - 1st */
+#define RGB1_MUL_BASE		(0x22c)
+/* Offsets from base */
+#define RGB_MUL_RR		(0x0)
+#define RGB_MUL_GR		(0x4)
+#define RGB_MUL_BR		(0x8)
+#define RGB_MUL_RG		(0xc)
+#define RGB_MUL_GG		(0x10)
+#define RGB_MUL_BG		(0x14)
+#define RGB_MUL_RB		(0x18)
+#define RGB_MUL_GB		(0x1c)
+#define RGB_MUL_BB		(0x20)
+#define RGB_OFT_OR		(0x24)
+#define RGB_OFT_OG		(0x28)
+#define RGB_OFT_OB		(0x2c)
+
+/* Gamma */
+#define GMM_CFG			(0x25c)
+
+/* RGB to RGB conversiona - 2nd */
+#define RGB2_MUL_BASE		(0x260)
+
+/* 3D LUT */
+#define D3LUT_EN		(0x290)
+
+/* RGB to YUV(YCbCr) conversion */
+#define YUV_ADJ			(0x294)
+#define YUV_MUL_RY		(0x298)
+#define YUV_MUL_GY		(0x29c)
+#define YUV_MUL_BY		(0x2a0)
+#define YUV_MUL_RCB		(0x2a4)
+#define YUV_MUL_GCB		(0x2a8)
+#define YUV_MUL_BCB		(0x2ac)
+#define YUV_MUL_RCR		(0x2b0)
+#define YUV_MUL_GCR		(0x2b4)
+#define YUV_MUL_BCR		(0x2b8)
+#define YUV_OFT_Y		(0x2bc)
+#define YUV_OFT_CB		(0x2c0)
+#define YUV_OFT_CR		(0x2c4)
+#define YUV_PHS			(0x2c8)
+
+/* Global Brightness and Contrast */
+#define GBCE_EN			(0x2cc)
+#define GBCE_TYP		(0x2d0)
+
+/* Edge Enhancer */
+#define YEE_EN			(0x2d4)
+#define YEE_TYP			(0x2d8)
+#define YEE_SHF			(0x2dc)
+#define YEE_MUL_00		(0x2e0)
+#define YEE_MUL_01		(0x2e4)
+#define YEE_MUL_02		(0x2e8)
+#define YEE_MUL_10		(0x2ec)
+#define YEE_MUL_11		(0x2f0)
+#define YEE_MUL_12		(0x2f4)
+#define YEE_MUL_20		(0x2f8)
+#define YEE_MUL_21		(0x2fc)
+#define YEE_MUL_22		(0x300)
+#define YEE_THR			(0x304)
+#define YEE_E_GAN		(0x308)
+#define YEE_E_THR1		(0x30c)
+#define YEE_E_THR2		(0x310)
+#define YEE_G_GAN		(0x314)
+#define YEE_G_OFT		(0x318)
+
+/* Chroma Artifact Reduction */
+#define CAR_EN			(0x31c)
+#define CAR_TYP			(0x320)
+#define CAR_SW			(0x324)
+#define CAR_HPF_TYP		(0x328)
+#define CAR_HPF_SHF		(0x32c)
+#define	CAR_HPF_THR		(0x330)
+#define CAR_GN1_GAN		(0x334)
+#define CAR_GN1_SHF		(0x338)
+#define CAR_GN1_MIN		(0x33c)
+#define CAR_GN2_GAN		(0x340)
+#define CAR_GN2_SHF		(0x344)
+#define CAR_GN2_MIN		(0x348)
+
+/* Chroma Gain Suppression */
+#define CGS_EN			(0x34c)
+#define CGS_GN1_L_THR		(0x350)
+#define CGS_GN1_L_GAN		(0x354)
+#define CGS_GN1_L_SHF		(0x358)
+#define CGS_GN1_L_MIN		(0x35c)
+#define CGS_GN1_H_THR		(0x360)
+#define CGS_GN1_H_GAN		(0x364)
+#define CGS_GN1_H_SHF		(0x368)
+#define CGS_GN1_H_MIN		(0x36c)
+#define CGS_GN2_L_THR		(0x370)
+#define CGS_GN2_L_GAN		(0x374)
+#define CGS_GN2_L_SHF		(0x378)
+#define CGS_GN2_L_MIN		(0x37c)
+
+/* Resizer */
+#define RSZ_SRC_EN		(0x0)
+#define RSZ_SRC_MODE		(0x4)
+#define RSZ_SRC_FMT0		(0x8)
+#define RSZ_SRC_FMT1		(0xc)
+#define RSZ_SRC_VPS		(0x10)
+#define RSZ_SRC_VSZ		(0x14)
+#define RSZ_SRC_HPS		(0x18)
+#define RSZ_SRC_HSZ		(0x1c)
+#define RSZ_DMA_RZA		(0x20)
+#define RSZ_DMA_RZB		(0x24)
+#define RSZ_DMA_STA		(0x28)
+#define RSZ_GCK_MMR		(0x2c)
+#define RSZ_RESERVED0		(0x30)
+#define RSZ_GCK_SDR		(0x34)
+#define RSZ_IRQ_RZA		(0x38)
+#define RSZ_IRQ_RZB		(0x3c)
+#define RSZ_YUV_Y_MIN		(0x40)
+#define RSZ_YUV_Y_MAX		(0x44)
+#define RSZ_YUV_C_MIN		(0x48)
+#define RSZ_YUV_C_MAX		(0x4c)
+#define RSZ_YUV_PHS		(0x50)
+#define RSZ_SEQ			(0x54)
+
+/* Resizer Rescale Parameters */
+#define RSZ_EN_A		(0x58)
+#define RSZ_EN_B		(0xe8)
+/* offset of the registers to be added with base register of
+   either RSZ0 or RSZ1
+*/
+#define RSZ_MODE		(0x4)
+#define RSZ_420			(0x8)
+#define RSZ_I_VPS		(0xc)
+#define RSZ_I_HPS		(0x10)
+#define RSZ_O_VSZ		(0x14)
+#define RSZ_O_HSZ		(0x18)
+#define RSZ_V_PHS_Y		(0x1c)
+#define RSZ_V_PHS_C		(0x20)
+#define RSZ_V_DIF		(0x24)
+#define RSZ_V_TYP		(0x28)
+#define RSZ_V_LPF		(0x2c)
+#define RSZ_H_PHS		(0x30)
+#define RSZ_H_PHS_ADJ		(0x34)
+#define RSZ_H_DIF		(0x38)
+#define RSZ_H_TYP		(0x3c)
+#define RSZ_H_LPF		(0x40)
+#define RSZ_DWN_EN		(0x44)
+#define RSZ_DWN_AV		(0x48)
+
+/* Resizer RGB Conversion Parameters */
+#define RSZ_RGB_EN		(0x4c)
+#define RSZ_RGB_TYP		(0x50)
+#define RSZ_RGB_BLD		(0x54)
+
+/* Resizer External Memory Parameters */
+#define RSZ_SDR_Y_BAD_H		(0x58)
+#define RSZ_SDR_Y_BAD_L		(0x5c)
+#define RSZ_SDR_Y_SAD_H		(0x60)
+#define RSZ_SDR_Y_SAD_L		(0x64)
+#define RSZ_SDR_Y_OFT		(0x68)
+#define RSZ_SDR_Y_PTR_S		(0x6c)
+#define RSZ_SDR_Y_PTR_E		(0x70)
+#define RSZ_SDR_C_BAD_H		(0x74)
+#define RSZ_SDR_C_BAD_L		(0x78)
+#define RSZ_SDR_C_SAD_H		(0x7c)
+#define RSZ_SDR_C_SAD_L		(0x80)
+#define RSZ_SDR_C_OFT		(0x84)
+#define RSZ_SDR_C_PTR_S		(0x88)
+#define RSZ_SDR_C_PTR_E		(0x8c)
+
+/* Macro for resizer */
+#define IPIPE_RESIZER_A(i)	(RSZ_IOBASE_VADDR + RSZ_EN_A + i)
+#define IPIPE_RESIZER_B(i)	(RSZ_IOBASE_VADDR + RSZ_EN_B + i)
+
+#define RSZ_YUV_Y_MIN		(0x40)
+#define RSZ_YUV_Y_MAX		(0x44)
+#define RSZ_YUV_C_MIN		(0x48)
+#define RSZ_YUV_C_MAX		(0x4c)
+
+#define IPIPE_GCK_MMR_DEFAULT	(1)
+#define IPIPE_GCK_PIX_DEFAULT	(0xe)
+#define RSZ_GCK_MMR_DEFAULT	(1)
+#define RSZ_GCK_SDR_DEFAULT	(1)
+
+/* Below defines for masks and shifts */
+#define COLPAT_EE_SHIFT		(0)
+#define COLPAT_EO_SHIFT		(2)
+#define COLPAT_OE_SHIFT		(4)
+#define COLPAT_OO_SHIFT		(6)
+
+/* LUTDPC */
+#define LUTDPC_TBL_256_EN	(0 << 1)
+#define LUTDPC_INF_TBL_EN	(1)
+#define LUT_DPC_START_ADDR	(0)
+#define LUT_DPC_H_POS_MASK	(0x1fff)
+#define LUT_DPC_V_POS_MASK	(0x1fff)
+#define LUT_DPC_V_POS_SHIFT	(13)
+#define LUT_DPC_CORR_METH_SHIFT	(26)
+#define LUT_DPC_MAX_SIZE	(256)
+#define LUT_DPC_SIZE_MASK	(0x3ff)
+
+/* OTFDPC */
+#define OTFDPC_DPC2_THR_MASK	(0xfff)
+#define OTF_DET_METHOD_SHIFT	(1)
+#define OTF_DPC3_0_SHF_MASK	(3)
+#define OTF_DPC3_0_THR_SHIFT	(6)
+#define OTF_DPC3_0_THR_MASK	(0x3f)
+#define OTF_DPC3_0_SLP_MASK	(0x3f)
+#define OTF_DPC3_0_DET_MASK	(0xfff)
+#define OTF_DPC3_0_CORR_MASK	(0xfff)
+
+/* NF (D2F) */
+#define D2F_SPR_VAL_MASK		(0x1f)
+#define D2F_SPR_VAL_SHIFT		(0)
+#define D2F_SHFT_VAL_MASK		(3)
+#define D2F_SHFT_VAL_SHIFT		(5)
+#define D2F_SAMPLE_METH_SHIFT		(7)
+#define D2F_APPLY_LSC_GAIN_SHIFT	(8)
+#define D2F_USE_SPR_REG_VAL		(0 << 9)
+#define D2F_STR_VAL_MASK		(0x1f)
+#define D2F_THR_VAL_MASK		(0x3ff)
+#define D2F_EDGE_DET_THR_MASK		(0x7ff)
+
+/* Green Imbalance Correction */
+#define GIC_TYP_SHIFT			(0)
+#define GIC_THR_SEL_SHIFT		(1)
+#define	GIC_APPLY_LSC_GAIN_SHIFT	(2)
+#define GIC_GAIN_MASK			(0xff)
+#define GIC_THR_MASK			(0xfff)
+#define GIC_SLOPE_MASK			(0xfff)
+#define GIC_NFGAN_INT_MASK		(7)
+#define GIC_NFGAN_DECI_MASK		(0x1f)
+
+/* WB */
+#define WB_OFFSET_MASK			(0xfff)
+#define WB_GAIN_INT_MASK		(0xf)
+#define WB_GAIN_DECI_MASK		(0x1ff)
+
+/* CFA */
+#define CFA_HPF_THR_2DIR_MASK		(0x1fff)
+#define CFA_HPF_SLOPE_2DIR_MASK		(0x3ff)
+#define CFA_HPF_MIX_THR_2DIR_MASK	(0x1fff)
+#define CFA_HPF_MIX_SLP_2DIR_MASK	(0x3ff)
+#define CFA_DIR_THR_2DIR_MASK		(0x3ff)
+#define CFA_DIR_SLP_2DIR_MASK		(0x7f)
+#define CFA_ND_WT_2DIR_MASK		(0x3f)
+#define CFA_DAA_HUE_FRA_MASK		(0x3f)
+#define CFA_DAA_EDG_THR_MASK		(0xff)
+#define CFA_DAA_THR_MIN_MASK		(0x3ff)
+#define CFA_DAA_THR_SLP_MASK		(0x3ff)
+#define CFA_DAA_SLP_MIN_MASK		(0x3ff)
+#define CFA_DAA_SLP_SLP_MASK		(0x3ff)
+#define CFA_DAA_LP_WT_MASK		(0x3f)
+
+/* RGB2RGB */
+#define RGB2RGB_1_OFST_MASK		(0x1fff)
+#define RGB2RGB_1_GAIN_INT_MASK		(0xf)
+#define RGB2RGB_GAIN_DECI_MASK		(0xff)
+#define RGB2RGB_2_OFST_MASK		(0x7ff)
+#define RGB2RGB_2_GAIN_INT_MASK		(0x7)
+
+/* Gamma */
+#define GAMMA_BYPR_SHIFT		(0)
+#define GAMMA_BYPG_SHIFT		(1)
+#define GAMMA_BYPB_SHIFT		(2)
+#define GAMMA_TBL_SEL_SHIFT		(4)
+#define GAMMA_TBL_SIZE_SHIFT		(5)
+#define GAMMA_MASK			(0x3ff)
+#define GAMMA_SHIFT			(10)
+
+/* 3D LUT */
+#define D3_LUT_ENTRY_MASK		(0x3ff)
+#define D3_LUT_ENTRY_R_SHIFT		(20)
+#define D3_LUT_ENTRY_G_SHIFT		(10)
+#define D3_LUT_ENTRY_B_SHIFT		(0)
+
+/* Lumina adj */
+#define	LUM_ADJ_CONTR_SHIFT		(0)
+#define	LUM_ADJ_BRIGHT_SHIFT		(8)
+
+/* RGB2YCbCr */
+#define RGB2YCBCR_OFST_MASK		(0x7ff)
+#define RGB2YCBCR_COEF_INT_MASK		(0xf)
+#define RGB2YCBCR_COEF_DECI_MASK	(0xff)
+
+/* GBCE */
+#define GBCE_Y_VAL_MASK			(0xff)
+#define GBCE_GAIN_VAL_MASK		(0x3ff)
+#define GBCE_ENTRY_SHIFT		(10)
+
+/* Edge Enhancements */
+#define YEE_HALO_RED_EN_SHIFT		(1)
+#define YEE_HPF_SHIFT_MASK		(0xf)
+#define YEE_COEF_MASK			(0x3ff)
+#define YEE_THR_MASK			(0x3f)
+#define YEE_ES_GAIN_MASK		(0xfff)
+#define YEE_ES_THR1_MASK		(0xfff)
+#define YEE_ENTRY_SHIFT			(9)
+#define YEE_ENTRY_MASK			(0x1ff)
+
+/* CAR */
+#define CAR_MF_THR			(0xff)
+#define CAR_SW1_SHIFT			(8)
+#define CAR_GAIN1_SHFT_MASK		(7)
+#define CAR_GAIN_MIN_MASK		(0x1ff)
+#define CAR_GAIN2_SHFT_MASK		(0xf)
+#define CAR_HPF_SHIFT_MASK		(3)
+
+/* CGS */
+#define CAR_SHIFT_MASK			(3)
+
+/* Resizer */
+#define RSZ_BYPASS_SHIFT		(1)
+#define RSZ_SRC_IMG_FMT_SHIFT		(1)
+#define RSZ_SRC_Y_C_SEL_SHIFT		(2)
+#define IPIPE_RSZ_VPS_MASK		(0xffff)
+#define IPIPE_RSZ_HPS_MASK		(0xffff)
+#define IPIPE_RSZ_VSZ_MASK		(0x1fff)
+#define IPIPE_RSZ_HSZ_MASK		(0x1fff)
+#define RSZ_HPS_MASK			(0x1fff)
+#define RSZ_VPS_MASK			(0x1fff)
+#define RSZ_O_HSZ_MASK			(0x1fff)
+#define RSZ_O_VSZ_MASK			(0x1fff)
+#define RSZ_V_PHS_MASK			(0x3fff)
+#define RSZ_V_DIF_MASK			(0x3fff)
+
+#define RSZA_H_FLIP_SHIFT		(0)
+#define RSZA_V_FLIP_SHIFT		(1)
+#define RSZB_H_FLIP_SHIFT		(2)
+#define RSZB_V_FLIP_SHIFT		(3)
+#define RSZ_A				(0)
+#define RSZ_B				(1)
+#define RSZ_CEN_SHIFT			(1)
+#define RSZ_YEN_SHIFT			(0)
+#define RSZ_TYP_Y_SHIFT			(0)
+#define RSZ_TYP_C_SHIFT			(1)
+#define RSZ_LPF_INT_MASK		(0x3f)
+#define RSZ_LPF_INT_MASK		(0x3f)
+#define RSZ_LPF_INT_C_SHIFT		(6)
+#define RSZ_H_PHS_MASK			(0x3fff)
+#define RSZ_H_DIF_MASK			(0x3fff)
+#define RSZ_DIFF_DOWN_THR		(256)
+#define RSZ_DWN_SCALE_AV_SZ_V_SHIFT	(3)
+#define RSZ_DWN_SCALE_AV_SZ_MASK	(7)
+#define RSZ_RGB_MSK1_SHIFT		(2)
+#define RSZ_RGB_MSK0_SHIFT		(1)
+#define RSZ_RGB_TYP_SHIFT		(0)
+#define RSZ_RGB_ALPHA_MASK		(0xff)
+
+static inline u32 regr_ip(u32 offset)
+{
+	return readl(IPIPE_IOBASE_VADDR + offset);
+}
+
+static inline u32 regw_ip(u32 val, u32 offset)
+{
+	writel(val, IPIPE_IOBASE_VADDR + offset);
+
+	return val;
+}
+
+static inline u32 r_ip_table(u32 offset)
+{
+	return readl(IPIPE_INT_TABLE_IOBASE_VADDR + offset);
+}
+
+static inline u32 w_ip_table(u32 val, u32 offset)
+{
+	writel(val, IPIPE_INT_TABLE_IOBASE_VADDR + offset);
+
+	return val;
+}
+
+static inline u32 regr_rsz(u32 offset)
+{
+	return readl(RSZ_IOBASE_VADDR + offset);
+}
+
+static inline u32 regw_rsz(u32 val, u32 offset)
+{
+	writel(val, RSZ_IOBASE_VADDR + offset);
+
+	return val;
+}
+
+#endif  /* End of #ifdef _DM365_IPIPE_HW_H */
-- 
1.6.2.4


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

* [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 2/8] davinci: vpfe: add IPIPE hardware layer support Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-09-27 14:01   ` Sakari Ailus
  2011-08-29 15:07 ` [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365 Manjunath Hadli
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Nagabhushana Netagunte, Manjunath Hadli

From: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>

Add the IPIPE interfacing layer to the vpfe driver. This patch adds dm365
specific implementation of the genric imp_hw_interface interface for
programming the IPIPE block, mainly setting the resizer and previewer
configuration parameters. This is built as an independent module.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/dm365_def_para.c |  486 ++++
 drivers/media/video/davinci/dm365_def_para.h |   39 +
 drivers/media/video/davinci/dm365_ipipe.c    | 3966 ++++++++++++++++++++++++++
 drivers/media/video/davinci/dm365_ipipe.h    |  300 ++
 drivers/media/video/davinci/imp_common.h     |   85 +
 drivers/media/video/davinci/imp_hw_if.h      |  178 ++
 6 files changed, 5054 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/dm365_def_para.c
 create mode 100644 drivers/media/video/davinci/dm365_def_para.h
 create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
 create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
 create mode 100644 drivers/media/video/davinci/imp_common.h
 create mode 100644 drivers/media/video/davinci/imp_hw_if.h

diff --git a/drivers/media/video/davinci/dm365_def_para.c b/drivers/media/video/davinci/dm365_def_para.c
new file mode 100644
index 0000000..d5af73b
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_def_para.c
@@ -0,0 +1,486 @@
+/*
+* Copyright (C) 2011 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
+*/
+#include <linux/v4l2-mediabus.h>
+#include <media/davinci/vpfe.h>
+#include "dm365_ipipe.h"
+
+/* Defaults for lutdpc */
+struct prev_lutdpc dm365_lutdpc_defaults = {
+	.en = 0
+};
+
+/* Defaults for otfdpc */
+struct prev_lutdpc dm365_otfdpc_defaults = {
+	.en = 0
+};
+
+/* Defaults for 2D - nf */
+struct prev_nf dm365_nf_defaults = {
+	.en = 0
+};
+
+/* defaults for GIC */
+struct prev_gic dm365_gic_defaults = {
+	.en = 0
+};
+
+/* Defaults for white balance */
+struct prev_wb dm365_wb_defaults = {
+	.gain_r = {2, 0x00},
+	.gain_gr = {2, 0x00},
+	.gain_gb = {2, 0x00},
+	.gain_b = {2, 0x00}
+};
+
+/* Defaults for CFA */
+struct prev_cfa dm365_cfa_defaults = {
+	.alg = IPIPE_CFA_ALG_2DIRAC,
+	.hpf_thr_2dir = 0,
+	.hpf_slp_2dir = 0,
+	.hp_mix_thr_2dir = 0,
+	.hp_mix_slope_2dir = 0,
+	.dir_thr_2dir = 0,
+	.dir_slope_2dir = 0,
+	.nd_wt_2dir = 0,
+	.hue_fract_daa = 0,
+	.edge_thr_daa = 0,
+	.thr_min_daa = 0,
+	.thr_slope_daa = 0,
+	.slope_min_daa = 0,
+	.slope_slope_daa = 0,
+	.lp_wt_daa = 0
+};
+
+/* Defaults for rgb2rgb */
+struct prev_rgb2rgb dm365_rgb2rgb_defaults = {
+	.coef_rr = {1, 0},	/* 256 */
+	.coef_gr = {0, 0},
+	.coef_br = {0, 0},
+	.coef_rg = {0, 0},
+	.coef_gg = {1, 0},	/* 256 */
+	.coef_bg = {0, 0},
+	.coef_rb = {0, 0},
+	.coef_gb = {0, 0},
+	.coef_bb = {1, 0},	/* 256 */
+	.out_ofst_r = 0,
+	.out_ofst_g = 0,
+	.out_ofst_b = 0
+};
+
+/* Defaults for gamma correction */
+struct prev_gamma dm365_gamma_defaults = {
+	.bypass_r = 0,
+	.bypass_b = 0,
+	.bypass_g = 0,
+	.tbl_sel = IPIPE_GAMMA_TBL_ROM
+};
+
+/* Defaults for 3d lut */
+struct prev_3d_lut dm365_3d_lut_defaults = {
+	.en = 0
+};
+
+/* Defaults for lumina adjustments */
+struct prev_lum_adj dm365_lum_adj_defaults = {
+	.brightness = 0,
+	.contrast = 16
+};
+
+/* Defaults for rgb2yuv conversion */
+struct prev_rgb2yuv dm365_rgb2yuv_defaults = {
+	.coef_ry = {0, 0x4D},
+	.coef_gy = {0, 0x96},
+	.coef_by = {0, 0x1D},
+	.coef_rcb = {0xF, 0xD5},
+	.coef_gcb = {0xF, 0xAB},
+	.coef_bcb = {0, 0x80},
+	.coef_rcr = {0, 0x80},
+	.coef_gcr = {0xF, 0x95},
+	.coef_bcr = {0xF, 0xEB},
+	.out_ofst_y = 0,
+	.out_ofst_cb = 0x80,
+	.out_ofst_cr = 0x80
+};
+
+/* Defaults for GBCE */
+struct prev_gbce dm365_gbce_defaults = {
+	.en = 0
+};
+
+/* Defaults for yuv 422 conversion */
+struct prev_yuv422_conv dm365_yuv422_conv_defaults = {
+	.en_chrom_lpf = 0,
+	.chrom_pos = IPIPE_YUV422_CHR_POS_COSITE
+};
+
+/* Defaults for Edge Ehnancements  */
+struct prev_yee dm365_yee_defaults = {
+	.en = 0,
+};
+
+/* Defaults for CAR conversion */
+struct prev_car dm365_car_defaults = {
+	.en = 0,
+};
+
+/* Defaults for CGS */
+struct prev_cgs dm365_cgs_defaults = {
+	.en = 0,
+};
+
+#define  WIDTH_I 640
+#define  HEIGHT_I 480
+#define  WIDTH_O 640
+#define  HEIGHT_O 480
+
+/* default ipipeif settings */
+struct ipipeif_5_1 ipipeif_5_1_defaults = {
+	.pack_mode = IPIPEIF_5_1_PACK_16_BIT,
+	.data_shift = IPIPEIF_BITS11_0,
+	.source1 = IPIPEIF_SRC1_PARALLEL_PORT,
+	.clk_div = {
+		.m = 1,	/* clock = sdram clock * (m/n) */
+		.n = 6
+	},
+	.dpc = {
+		.en = 0,
+	},
+	.dpcm = {
+		.en = 0,
+		.type = IPIPEIF_DPCM_8BIT_12BIT,
+		.pred = IPIPEIF_DPCM_SIMPLE_PRED
+	},
+	.pix_order = IPIPEIF_CBCR_Y,
+	.isif_port = {
+		.if_type = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.hdpol = VPFE_PINPOL_POSITIVE,
+		.vdpol = VPFE_PINPOL_POSITIVE
+	},
+	.clip = 4095,
+	.align_sync = 0,
+	.rsz_start = 0,
+	.df_gain_en = 0
+};
+
+struct ipipe_params dm365_ipipe_defs = {
+	.ipipeif_param = {
+		.mode = IPIPEIF_ONE_SHOT,
+		.source = IPIPEIF_SDRAM_RAW,
+		.clock_select = IPIPEIF_SDRAM_CLK,
+		.glob_hor_size = WIDTH_I + 8,
+		.glob_ver_size = HEIGHT_I + 10,
+		.hnum = WIDTH_I,
+		.vnum = HEIGHT_I,
+		.adofs = WIDTH_I * 2,
+		.rsz = 16,	/* resize ratio 16/rsz */
+		.decimation = IPIPEIF_DECIMATION_OFF,
+		.avg_filter = IPIPEIF_AVG_OFF,
+		.gain = 0x200,	/* U10Q9 */
+	},
+	.ipipe_mode = IPIPEIF_ONE_SHOT,
+	.ipipe_dpaths_fmt = IPIPE_RAW2YUV,
+	.ipipe_colpat_olop = IPIPE_GREEN_BLUE,
+	.ipipe_colpat_olep = IPIPE_BLUE,
+	.ipipe_colpat_elop = IPIPE_RED,
+	.ipipe_colpat_elep = IPIPE_GREEN_RED,
+	.ipipe_vps = 0,
+	.ipipe_vsz = HEIGHT_I - 1,
+	.ipipe_hps = 0,
+	.ipipe_hsz = WIDTH_I - 1,
+	.rsz_common = {
+		.vps = 0,
+		.vsz = HEIGHT_I - 1,
+		.hps = 0,
+		.hsz = WIDTH_I - 1,
+		.src_img_fmt = RSZ_IMG_422,
+		.y_c = 0,
+		.raw_flip = 1,	/* flip preserve Raw format */
+		.source = IPIPE_DATA,
+		.passthrough = IPIPE_BYPASS_OFF,
+		.yuv_y_min = 0,
+		.yuv_y_max = 255,
+		.yuv_c_min = 0,
+		.yuv_c_max = 255,
+		.rsz_seq_crv = DISABLE,
+		.out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE
+	},
+	.rsz_rsc_param = {
+		{
+			.mode = IPIPEIF_ONE_SHOT,
+			.h_flip = DISABLE,
+			.v_flip = DISABLE,
+			.cen = DISABLE,
+			.yen = DISABLE,
+			.i_vps = 0,
+			.i_hps = 0,
+			.o_vsz = HEIGHT_O - 1,
+			.o_hsz = WIDTH_O - 1,
+			.v_phs_y = 0,
+			.v_phs_c = 0,
+			.v_dif = 256,
+			.v_typ_y = RSZ_INTP_CUBIC,
+			.h_typ_c = RSZ_INTP_CUBIC,
+			.v_lpf_int_y = 0,
+			.v_lpf_int_c = 0,
+			.h_phs = 0,
+			.h_dif = 256,
+			.h_typ_y = RSZ_INTP_CUBIC,
+			.h_typ_c = RSZ_INTP_CUBIC,
+			.h_lpf_int_y = 0,
+			.h_lpf_int_c = 0,
+			.dscale_en = 0,
+			.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+			.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+			.f_div.en = 0
+		},
+		{
+			.mode = IPIPEIF_ONE_SHOT,
+			.h_flip = DISABLE,
+			.v_flip = DISABLE,
+			.cen = DISABLE,
+			.yen = DISABLE,
+			.i_vps = 0,
+			.i_hps = 0,
+			.o_vsz = HEIGHT_O - 1,
+			.o_hsz = WIDTH_O - 1,
+			.v_phs_y = 0,
+			.v_phs_c = 0,
+			.v_dif = 256,
+			.v_typ_y = RSZ_INTP_CUBIC,
+			.h_typ_c = RSZ_INTP_CUBIC,
+			.v_lpf_int_y = 0,
+			.v_lpf_int_c = 0,
+			.h_phs = 0,
+			.h_dif = 256,
+			.h_typ_y = RSZ_INTP_CUBIC,
+			.h_typ_c = RSZ_INTP_CUBIC,
+			.h_lpf_int_y = 0,
+			.h_lpf_int_c = 0,
+			.dscale_en = 0,
+			.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+			.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+			.f_div.en = 0
+		},
+	},
+	.rsz2rgb = {
+		{
+			.rgb_en = DISABLE
+		},
+		{
+			.rgb_en = DISABLE
+		}
+	},
+	.ext_mem_param = {
+		{
+			.rsz_sdr_oft_y = WIDTH_O << 1,
+			.rsz_sdr_ptr_s_y = 0,
+			.rsz_sdr_ptr_e_y = HEIGHT_O,
+			.rsz_sdr_oft_c = WIDTH_O,
+			.rsz_sdr_ptr_s_c = 0,
+			.rsz_sdr_ptr_e_c = HEIGHT_O >> 1,
+			.flip_ofst_y = 0,
+			.flip_ofst_c = 0,
+			.c_offset = 0,
+			.user_y_ofst = 0,
+			.user_c_ofst = 0
+		},
+		{
+			.rsz_sdr_oft_y = WIDTH_O << 1,
+			.rsz_sdr_ptr_s_y = 0,
+			.rsz_sdr_ptr_e_y = HEIGHT_O,
+			.rsz_sdr_oft_c = WIDTH_O,
+			.rsz_sdr_ptr_s_c = 0,
+			.rsz_sdr_ptr_e_c = HEIGHT_O,
+			.flip_ofst_y = 0,
+			.flip_ofst_c = 0,
+			.c_offset = 0,
+			.user_y_ofst = 0,
+			.user_c_ofst = 0
+		},
+	},
+	.rsz_en[0] = ENABLE,
+	.rsz_en[1] = DISABLE
+};
+
+struct prev_single_shot_config dm365_prev_ss_config_defs = {
+	.bypass = IPIPE_BYPASS_OFF,
+	.input = {
+		.image_width = WIDTH_I,
+		.image_height = HEIGHT_I,
+		.vst = 0,
+		.hst = 0,
+		.ppln = WIDTH_I + 8,
+		.lpfr = HEIGHT_I + 10,
+		.pred = IPIPEIF_DPCM_SIMPLE_PRED,
+		.clk_div = {1, 6},
+		.data_shift = IPIPEIF_BITS11_0,
+		.dec_en = 0,
+		.rsz = 16,	/* resize ratio 16/rsz */
+		.frame_div_mode_en = 0,
+		.avg_filter_en = IPIPEIF_AVG_OFF,
+		.dpc = {0, 0},
+		.gain = 512,
+		.clip = 4095,
+		.align_sync = 0,
+		.rsz_start = 0,
+		.pix_fmt = IPIPE_BAYER,
+		.colp_olop = IPIPE_GREEN_BLUE,
+		.colp_olep = IPIPE_BLUE,
+		.colp_elop = IPIPE_RED,
+		.colp_elep = IPIPE_GREEN_RED
+	},
+	.output = {
+		.pix_fmt = IPIPE_UYVY
+	}
+};
+
+struct prev_continuous_config dm365_prev_cont_config_defs = {
+	.bypass = IPIPE_BYPASS_OFF,
+	.input = {
+		.en_df_sub = 0,
+		.dec_en = 0,
+		.rsz = 16,
+		.avg_filter_en = IPIPEIF_AVG_OFF,
+		.gain = 512,
+		.clip = 4095,
+		.colp_olop = IPIPE_GREEN_BLUE,
+		.colp_olep = IPIPE_BLUE,
+		.colp_elop = IPIPE_RED,
+		.colp_elep = IPIPE_GREEN_RED
+	},
+};
+
+struct rsz_single_shot_config dm365_rsz_ss_config_defs = {
+	.input = {
+		.image_width = WIDTH_I,
+		.image_height = HEIGHT_I,
+		.vst = 0,
+		.hst = 0,
+		.ppln = WIDTH_I + 8,
+		.lpfr = HEIGHT_I + 10,
+		.clk_div = {1, 6},
+		.dec_en = 0,
+		.rsz = 16,	/* resize ratio 16/rsz */
+		.frame_div_mode_en = 0,
+		.avg_filter_en = IPIPEIF_AVG_OFF,
+		.align_sync = 0,
+		.rsz_start = 0,
+		.pix_fmt = IPIPE_UYVY
+	},
+	.output1 = {
+		.enable = 1,
+		.pix_fmt = IPIPE_UYVY,
+		.h_flip = 0,
+		.v_flip = 0,
+		.width = WIDTH_O,
+		.height = HEIGHT_O,
+		.vst_y = 0,
+		.vst_c = 0,
+		.v_typ_y = RSZ_INTP_CUBIC,
+		.v_typ_c = RSZ_INTP_CUBIC,
+		.v_lpf_int_y = 0,
+		.v_lpf_int_c = 0,
+		.h_typ_y = RSZ_INTP_CUBIC,
+		.h_typ_c = RSZ_INTP_CUBIC,
+		.h_lpf_int_y = 0,
+		.h_lpf_int_c = 0,
+		.en_down_scale = 0,
+		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.user_y_ofst = 0,
+		.user_c_ofst = 0
+	},
+	.output2 = {
+		.enable = 1,
+		.pix_fmt = IPIPE_UYVY,
+		.h_flip = 0,
+		.v_flip = 0,
+		.width = WIDTH_O,
+		.height = HEIGHT_O,
+		.vst_y = 0,
+		.vst_c = 0,
+		.v_typ_y = RSZ_INTP_CUBIC,
+		.v_typ_c = RSZ_INTP_CUBIC,
+		.v_lpf_int_y = 0,
+		.v_lpf_int_c = 0,
+		.h_typ_y = RSZ_INTP_CUBIC,
+		.h_typ_c = RSZ_INTP_CUBIC,
+		.h_lpf_int_y = 0,
+		.h_lpf_int_c = 0,
+		.en_down_scale = 0,
+		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.user_y_ofst = 0,
+		.user_c_ofst = 0
+	},
+	.chroma_sample_even = 0,
+	.yuv_y_min = 0,
+	.yuv_y_max = 255,
+	.yuv_c_min = 0,
+	.yuv_c_max = 255,
+	.out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE,
+};
+
+struct rsz_continuous_config dm365_rsz_cont_config_defs = {
+	.output1 = {
+		.enable = 1,
+		.h_flip = 0,
+		.v_flip = 0,
+		.v_typ_y = RSZ_INTP_CUBIC,
+		.v_typ_c = RSZ_INTP_CUBIC,
+		.v_lpf_int_y = 0,
+		.v_lpf_int_c = 0,
+		.h_typ_y = RSZ_INTP_CUBIC,
+		.h_typ_c = RSZ_INTP_CUBIC,
+		.h_lpf_int_y = 0,
+		.h_lpf_int_c = 0,
+		.en_down_scale = 0,
+		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.user_y_ofst = 0,
+		.user_c_ofst = 0
+	},
+	.output2 = {
+		.enable = 1,
+		.pix_fmt = IPIPE_UYVY,
+		.h_flip = 0,
+		.v_flip = 0,
+		.width = WIDTH_O,
+		.height = HEIGHT_O,
+		.vst_y = 0,
+		.vst_c = 0,
+		.v_typ_y = RSZ_INTP_CUBIC,
+		.v_typ_c = RSZ_INTP_CUBIC,
+		.v_lpf_int_y = 0,
+		.v_lpf_int_c = 0,
+		.h_typ_y = RSZ_INTP_CUBIC,
+		.h_typ_c = RSZ_INTP_CUBIC,
+		.h_lpf_int_y = 0,
+		.h_lpf_int_c = 0,
+		.en_down_scale = 0,
+		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
+		.user_y_ofst = 0,
+		.user_c_ofst = 0
+	},
+	.chroma_sample_even = 0,
+	.yuv_y_min = 0,
+	.yuv_y_max = 255,
+	.yuv_c_min = 0,
+	.yuv_c_max = 255,
+	.out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE,
+};
diff --git a/drivers/media/video/davinci/dm365_def_para.h b/drivers/media/video/davinci/dm365_def_para.h
new file mode 100644
index 0000000..872b3cb
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_def_para.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 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
+ */
+#include "dm365_ipipe.h"
+extern struct prev_lutdpc dm365_lutdpc_defaults;
+extern struct prev_otfdpc dm365_otfdpc_defaults;
+extern struct prev_nf dm365_nf_defaults;
+extern struct prev_gic dm365_gic_defaults;
+extern struct prev_wb dm365_wb_defaults;
+extern struct prev_cfa dm365_cfa_defaults;
+extern struct prev_rgb2rgb dm365_rgb2rgb_defaults;
+extern struct prev_gamma dm365_gamma_defaults;
+extern struct prev_3d_lut dm365_3d_lut_defaults;
+extern struct prev_lum_adj dm365_lum_adj_defaults;
+extern struct prev_rgb2yuv dm365_rgb2yuv_defaults;
+extern struct prev_yuv422_conv dm365_yuv422_conv_defaults;
+extern struct prev_gbce dm365_gbce_defaults;
+extern struct prev_yee dm365_yee_defaults;
+extern struct prev_car dm365_car_defaults;
+extern struct prev_cgs dm365_cgs_defaults;
+extern struct ipipe_params dm365_ipipe_defs;
+extern struct prev_single_shot_config dm365_prev_ss_config_defs;
+extern struct prev_continuous_config dm365_prev_cont_config_defs;
+extern struct rsz_single_shot_config dm365_rsz_ss_config_defs;
+extern struct rsz_continuous_config dm365_rsz_cont_config_defs;
+extern struct ipipeif_5_1 ipipeif_5_1_defaults;
diff --git a/drivers/media/video/davinci/dm365_ipipe.c b/drivers/media/video/davinci/dm365_ipipe.c
new file mode 100644
index 0000000..9f41784
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ipipe.c
@@ -0,0 +1,3966 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/davinci/vpfe.h>
+#include "dm365_ipipe.h"
+#include "imp_hw_if.h"
+
+#include "dm365_ipipe_hw.h"
+#include "dm365_def_para.h"
+
+/* IPIPE module operation state */
+struct ipipe_oper_state {
+	/* Operation state in continuous mode */
+	unsigned int state;
+	/* Semaphore to protect the common hardware configuration */
+	struct mutex lock;
+	/* previewer config state */
+	unsigned int prev_config_state;
+	/* Shared configuration of the hardware */
+	struct ipipe_params *shared_config_param;
+	/* shared resource in use */
+	unsigned int resource_in_use;
+	/* resizer config state */
+	unsigned int rsz_config_state;
+	/* resizer chained with previewer */
+	unsigned int rsz_chained;
+	/* Buffer type, interleaved or field seperated for interlaced
+	 *  scan
+	 */
+	unsigned int buffer_type;
+	/* frame format, 0 - interlaced, 1 - progressive */
+	unsigned int frame_format;
+	/* input pixel format */
+	enum imp_pix_formats in_pixel_format;
+	/* input pixel format */
+	enum imp_pix_formats out_pixel_format;
+};
+
+/* Operation mode of image processor (imp) */
+static u32 oper_mode = IMP_MODE_NOT_CONFIGURED;
+/* enable/disable serializer */
+static u32 en_serializer;
+
+#define CONFIG_IPIPE_PARAM_VALIDATION
+/* ipipe module operation state & configuration */
+static struct ipipe_oper_state oper_state;
+
+/* LUT Defect pixel correction data */
+static struct prev_lutdpc lutdpc;
+
+/* LUT Defect pixel correction data */
+static struct prev_otfdpc otfdpc;
+
+/* Noise filter */
+static struct prev_nf nf1;
+static struct prev_nf nf2;
+
+/* Green Imbalance Correction */
+static struct prev_gic gic;
+
+/* White Balance */
+static struct prev_wb wb;
+
+/* CFA */
+static struct prev_cfa cfa;
+
+/* RGB2RGB conversion */
+static struct prev_rgb2rgb rgb2rgb_1;
+static struct prev_rgb2rgb rgb2rgb_2;
+
+/* Gamma correction */
+static struct prev_gamma gamma;
+
+/* 3D LUT */
+static struct prev_3d_lut lut_3d;
+
+/* Lumina Adjustment */
+static struct prev_lum_adj lum_adj;
+
+/* RGB2YUV conversion */
+static struct prev_rgb2yuv rgb2yuv;
+
+/* YUV 422 conversion */
+static struct prev_yuv422_conv yuv422_conv;
+
+/* GBCE */
+static struct prev_gbce gbce;
+
+/* Edge Enhancement */
+static struct prev_yee yee;
+
+/* Chromatic Artifact Reduction, CAR */
+static struct prev_car car;
+
+/* Chromatic Artifact Reduction, CAR */
+static struct prev_cgs cgs;
+
+/* Tables for various tuning modules */
+static struct ipipe_lutdpc_entry ipipe_lutdpc_table[MAX_SIZE_DPC];
+static struct ipipe_3d_lut_entry ipipe_3d_lut_table[MAX_SIZE_3D_LUT];
+static unsigned short ipipe_gbce_table[MAX_SIZE_GBCE_LUT];
+static struct ipipe_gamma_entry ipipe_gamma_table_r[MAX_SIZE_GAMMA];
+static struct ipipe_gamma_entry ipipe_gamma_table_b[MAX_SIZE_GAMMA];
+static struct ipipe_gamma_entry ipipe_gamma_table_g[MAX_SIZE_GAMMA];
+static short ipipe_yee_table[MAX_SIZE_YEE_LUT];
+
+/* Raw YUV formats */
+static u32 ipipe_raw_yuv_pix_formats[] = { V4L2_PIX_FMT_UYVY,
+					  V4L2_PIX_FMT_NV12};
+
+
+static int ipipe_enum_pix(u32 *pix, int i)
+{
+	if (i >= ARRAY_SIZE(ipipe_raw_yuv_pix_formats))
+		return -EINVAL;
+
+	*pix = ipipe_raw_yuv_pix_formats[i];
+	return 0;
+}
+
+/* IPIPE hardware limits */
+#define IPIPE_MAX_OUTPUT_WIDTH_A	2176
+#define IPIPE_MAX_OUTPUT_WIDTH_B	640
+
+static int ipipe_get_max_output_width(int rsz)
+{
+	if (rsz == RSZ_A)
+		return IPIPE_MAX_OUTPUT_WIDTH_A;
+	return IPIPE_MAX_OUTPUT_WIDTH_B;
+}
+
+/* Based on max resolution supported. QXGA */
+#define IPIPE_MAX_OUTPUT_HEIGHT_A	1536
+/* Based on max resolution supported. VGA */
+#define IPIPE_MAX_OUTPUT_HEIGHT_B	480
+
+static int ipipe_get_max_output_height(int rsz)
+{
+	if (rsz == RSZ_A)
+		return IPIPE_MAX_OUTPUT_HEIGHT_A;
+	return IPIPE_MAX_OUTPUT_HEIGHT_B;
+}
+
+static int ipipe_serialize(void)
+{
+	return en_serializer;
+}
+
+static int ipipe_set_ipipe_if_address(void *config, unsigned int address)
+{
+	struct ipipeif *if_params;
+
+	if (ISNULL(config))
+		return -EINVAL;
+
+	if_params = &((struct ipipe_params *)config)->ipipeif_param;
+
+	return ipipeif_set_address(if_params, address);
+}
+
+static void ipipe_lock_chain(void)
+{
+	mutex_lock(&oper_state.lock);
+	oper_state.resource_in_use = 1;
+	mutex_unlock(&oper_state.lock);
+}
+
+static void ipipe_unlock_chain(void)
+{
+	mutex_lock(&oper_state.lock);
+	oper_state.resource_in_use = 0;
+	oper_state.prev_config_state = STATE_NOT_CONFIGURED;
+	oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
+	oper_state.rsz_chained = 0;
+	mutex_unlock(&oper_state.lock);
+}
+static int ipipe_process_pix_fmts(enum ipipe_pix_formats in_pix_fmt,
+				  enum ipipe_pix_formats out_pix_fmt,
+				  struct ipipe_params *param)
+{
+	enum ipipe_pix_formats temp_pix_fmt;
+
+	switch (in_pix_fmt) {
+	case IPIPE_BAYER_8BIT_PACK:
+		temp_pix_fmt = IPIPE_BAYER;
+		param->ipipeif_param.var.if_5_1.pack_mode
+		    = IPIPEIF_5_1_PACK_8_BIT;
+		break;
+	case IPIPE_BAYER_8BIT_PACK_ALAW:
+		param->ipipeif_param.var.if_5_1.pack_mode
+		    = IPIPEIF_5_1_PACK_8_BIT_A_LAW;
+		temp_pix_fmt = IPIPE_BAYER;
+		break;
+	case IPIPE_BAYER_8BIT_PACK_DPCM:
+		param->ipipeif_param.var.if_5_1.pack_mode
+		    = IPIPEIF_5_1_PACK_8_BIT;
+		param->ipipeif_param.var.if_5_1.dpcm.en = 1;
+		temp_pix_fmt = IPIPE_BAYER;
+		break;
+	case IPIPE_BAYER:
+		param->ipipeif_param.var.if_5_1.pack_mode
+		    = IPIPEIF_5_1_PACK_16_BIT;
+		temp_pix_fmt = IPIPE_BAYER;
+		break;
+	case IPIPE_BAYER_12BIT_PACK:
+		param->ipipeif_param.var.if_5_1.pack_mode
+		    = IPIPEIF_5_1_PACK_12_BIT;
+		temp_pix_fmt = IPIPE_BAYER;
+		break;
+	default:
+		temp_pix_fmt = IPIPE_UYVY;
+	}
+
+	if (temp_pix_fmt == IPIPE_BAYER)
+		if (out_pix_fmt == IPIPE_BAYER)
+			param->ipipe_dpaths_fmt = IPIPE_RAW2RAW;
+		else if ((out_pix_fmt == IPIPE_UYVY) ||
+			 (out_pix_fmt == IPIPE_YUV420SP))
+			param->ipipe_dpaths_fmt = IPIPE_RAW2YUV;
+		else
+			return -EINVAL;
+	else if (temp_pix_fmt == IPIPE_UYVY) {
+		if (out_pix_fmt == IPIPE_UYVY)
+			param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
+		else if (out_pix_fmt == IPIPE_YUV420SP)
+			param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
+		else
+			return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * calculate_resize_ratios()
+ *   calculates resize ratio for resizer A or B. This is called after setting
+ * the input size or output size
+ */
+static void calculate_resize_ratios(struct ipipe_params *param, int index)
+{
+	param->rsz_rsc_param[index].h_dif =
+	    ((param->ipipe_hsz + 1) * 256) /
+	    (param->rsz_rsc_param[index].o_hsz + 1);
+	param->rsz_rsc_param[index].v_dif =
+	    ((param->ipipe_vsz + 1) * 256) /
+	    (param->rsz_rsc_param[index].o_vsz + 1);
+}
+
+static int ipipe_do_hw_setup(struct device *dev, void *config)
+{
+	struct ipipe_params *param = (struct ipipe_params *)config;
+	int ret;
+
+	dev_dbg(dev, "ipipe_do_hw_setup\n");
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+
+	if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS)) {
+		/* continuous mode */
+		param = oper_state.shared_config_param;
+		if (param->rsz_en[RSZ_A])
+			calculate_resize_ratios(param, RSZ_A);
+		if (param->rsz_en[RSZ_B])
+			calculate_resize_ratios(param, RSZ_B);
+		ret = ipipe_hw_setup(param);
+	}
+	mutex_unlock(&oper_state.lock);
+
+	return ret;
+}
+
+static unsigned int ipipe_rsz_chain_state(void)
+{
+	return oper_state.rsz_chained;
+}
+
+static void ipipe_update_outbuf1_address(void *config, unsigned int address)
+{
+	if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS))
+		rsz_set_output_address(oper_state.shared_config_param,
+				       0,
+				       address);
+	else
+		rsz_set_output_address((struct ipipe_params *)config,
+				       0,
+				       address);
+}
+
+static void ipipe_update_outbuf2_address(void *config, unsigned int address)
+{
+	if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS))
+		rsz_set_output_address(oper_state.shared_config_param,
+				       1,
+				       address);
+	else
+		rsz_set_output_address((struct ipipe_params *)config,
+				       1,
+				       address);
+}
+
+static void ipipe_enable(unsigned char en, void *config)
+{
+	unsigned char val = 0, ret = 0;
+	struct ipipe_params *param = (struct ipipe_params *)config;
+
+	if (en)
+		val = 1;
+
+	if (oper_mode == IMP_MODE_CONTINUOUS)
+		param = oper_state.shared_config_param;
+
+	if (en && param->rsz_common.source == IPIPE_DATA) {
+		/* wait for IPIPE to become inactive */
+		do {
+			ret = regr_ip(IPIPE_SRC_EN);
+		} while (ret);
+
+		regw_ip(val, IPIPE_SRC_EN);
+	} else
+		regw_ip(0, IPIPE_SRC_EN);
+
+	if (en) {
+		/* wait for RSZ_SRC_EN to be reset by hardware */
+		do {
+			ret = regr_rsz(RSZ_SRC_EN);
+		} while (ret);
+	}
+
+	if (param->rsz_en[RSZ_A]) {
+		if (en) {
+			/* wait for RSZ-A to become inactive */
+			do {
+				ret = regr_rsz(RSZ_A);
+			} while (ret);
+		}
+
+		rsz_enable(RSZ_A, en);
+	}
+	if (param->rsz_en[RSZ_B]) {
+		if (en) {
+			/* wait for RSZ-B to become inactive */
+			do {
+				ret = regr_rsz(RSZ_B);
+			} while (ret);
+		}
+
+		rsz_enable(RSZ_B, en);
+	}
+	if (oper_mode == IMP_MODE_SINGLE_SHOT) {
+		/* wait for IPIPEIF ENABLE.ENABLE to be reset by hardware */
+		if (en) {
+			do {
+				ret = ipipeif_get_enable();
+			} while (ret & 0x1);
+		}
+
+	 ipipeif_set_enable(val, oper_mode);
+	}
+}
+
+static int validate_lutdpc_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	int i;
+
+	if (lutdpc.en > 1 ||
+	    lutdpc.repl_white > 1 ||
+	    lutdpc.dpc_size > LUT_DPC_MAX_SIZE)
+		return -EINVAL;
+	if (lutdpc.en && (ISNULL(lutdpc.table)))
+		return -EINVAL;
+	for (i = 0; i < lutdpc.dpc_size; i++) {
+		if (lutdpc.table[i].horz_pos > LUT_DPC_H_POS_MASK ||
+		    lutdpc.table[i].vert_pos > LUT_DPC_V_POS_MASK)
+			return -EINVAL;
+	}
+#endif
+	return 0;
+}
+
+static int set_lutdpc_params(struct device *dev, void *param, int len)
+{
+	struct ipipe_lutdpc_entry *temp_lutdpc;
+	struct prev_lutdpc dpc_param;
+
+	if (ISNULL(param)) {
+		/* Copy defaults for dfc */
+		temp_lutdpc = lutdpc.table;
+		memcpy((void *)&lutdpc,
+		       (void *)&dm365_lutdpc_defaults,
+		       sizeof(struct prev_lutdpc));
+		lutdpc.table = temp_lutdpc;
+		goto success;
+	}
+
+	if (len != sizeof(struct prev_lutdpc)) {
+		dev_err(dev,
+			"set_lutdpc_params: param struct length"
+			" mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&dpc_param,
+			    (struct prev_lutdpc *)param,
+			    sizeof(struct prev_lutdpc))) {
+		dev_err(dev,
+			"set_lutdpc_params: Error in copy to kernel\n");
+		return -EFAULT;
+	}
+
+	if (ISNULL(dpc_param.table)) {
+		dev_err(dev, "Invalid user dpc table ptr\n");
+		return -EINVAL;
+	}
+	lutdpc.en = dpc_param.en;
+	lutdpc.repl_white = dpc_param.repl_white;
+	lutdpc.dpc_size = dpc_param.dpc_size;
+	if (copy_from_user
+		(lutdpc.table,
+		(struct ipipe_dpc_entry *)dpc_param.table,
+		(lutdpc.dpc_size *
+		sizeof(struct ipipe_lutdpc_entry)))) {
+		dev_err(dev,
+			"set_lutdpc_params: Error in copying "
+			"dfc table to kernel\n");
+		return -EFAULT;
+	}
+
+	if (validate_lutdpc_params(dev) < 0)
+		return -EINVAL;
+
+
+success:
+	ipipe_set_lutdpc_regs(&lutdpc);
+
+	return 0;
+}
+
+static int get_lutdpc_params(struct device *dev, void *param, int len)
+{
+	struct prev_lutdpc *lut_param = (struct prev_lutdpc *)param;
+	struct prev_lutdpc user_lutdpc;
+
+	if (ISNULL(lut_param)) {
+		dev_err(dev, "get_lutdpc_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_lutdpc)) {
+		dev_err(dev,
+			"get_lutdpc_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&user_lutdpc,
+			   lut_param,
+			   sizeof(struct prev_lutdpc))) {
+		dev_err(dev, "get_lutdpc_params: Error in copy to  kernel\n");
+		return -EFAULT;
+	}
+
+	user_lutdpc.en = lutdpc.en;
+	user_lutdpc.repl_white = lutdpc.repl_white;
+	user_lutdpc.dpc_size = lutdpc.dpc_size;
+	if (ISNULL(user_lutdpc.table)) {
+		dev_err(dev, "get_lutdpc_params:" " Invalid table ptr");
+		return -EINVAL;
+	}
+	if (copy_to_user(user_lutdpc.table,
+			 lutdpc.table,
+			 (lutdpc.dpc_size *
+			  sizeof(struct ipipe_lutdpc_entry)))) {
+		dev_err(dev,
+			"get_lutdpc_params:Table Error in" " copy to user\n");
+		return -EFAULT;
+	}
+
+	if (copy_to_user(lut_param,
+			 &user_lutdpc,
+			 sizeof(struct prev_lutdpc))) {
+		dev_err(dev, "get_lutdpc_params: Error in copy" " to user\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_otfdpc_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)&otfdpc;
+	struct prev_otfdpc_2_0 *dpc_2_0;
+	struct prev_otfdpc_3_0 *dpc_3_0;
+
+	if (dpc_param->en > 1)
+		return -EINVAL;
+	if (dpc_param->alg == IPIPE_OTFDPC_2_0) {
+		dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0;
+		if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK ||
+		    dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK)
+			return -EINVAL;
+	} else {
+		dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0;
+		if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK ||
+		    dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK ||
+		    dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK ||
+		    dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK ||
+		    dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK ||
+		    dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK ||
+		    dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK ||
+		    dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK ||
+		    dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK)
+			return -EINVAL;
+	}
+#endif
+	return 0;
+}
+
+static int set_otfdpc_params(struct device *dev, void *param, int len)
+{
+	struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)param;
+
+	if (ISNULL(param)) {
+		/* Copy defaults for dpc2.0 defaults */
+		memcpy((void *)&otfdpc,
+		       (void *)&dm365_otfdpc_defaults,
+		       sizeof(struct ipipe_otfdpc_2_0));
+	} else {
+		if (len != sizeof(struct prev_otfdpc)) {
+			dev_err(dev,
+				"set_otfdpc_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&otfdpc,
+				   dpc_param,
+				   sizeof(struct prev_otfdpc))) {
+			dev_err(dev,
+				"set_otfdpc_params: Error in "
+				"copy to kernel\n");
+			return -EFAULT;
+		}
+
+		if (validate_otfdpc_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_otfdpc_regs(&otfdpc);
+
+	return 0;
+}
+
+static int get_otfdpc_params(struct device *dev, void *param, int len)
+{
+	struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)param;
+
+	if (ISNULL(dpc_param)) {
+		dev_err(dev, "get_otfdpc_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_otfdpc)) {
+		dev_err(dev,
+			"get_otfdpc_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user(dpc_param,
+			 &otfdpc,
+			 sizeof(struct prev_otfdpc))) {
+		dev_err(dev,
+			"get_otfdpc_params: Error in copy dpc "
+			"table to user\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_nf_params(struct device *dev, unsigned int id)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	struct prev_nf *nf_param = &nf1;
+	int i;
+
+	if (id)
+		nf_param = &nf2;
+	if (nf_param->en > 1 ||
+	    nf_param->shft_val > D2F_SHFT_VAL_MASK ||
+	    nf_param->spread_val > D2F_SPR_VAL_MASK ||
+	    nf_param->apply_lsc_gain > 1 ||
+	    nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK ||
+	    nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK)
+		return -EINVAL;
+
+	for (i = 0; i < IPIPE_NF_THR_TABLE_SIZE; i++)
+		if (nf_param->thr[i] > D2F_THR_VAL_MASK)
+			return -EINVAL;
+	for (i = 0; i < IPIPE_NF_STR_TABLE_SIZE; i++)
+		if (nf_param->str[i] > D2F_STR_VAL_MASK)
+			return -EINVAL;
+#endif
+	return 0;
+}
+
+static int set_nf_params(struct device *dev, unsigned int id,
+			 void *param, int len)
+{
+	struct prev_nf *nf_param = (struct prev_nf *)param;
+	struct prev_nf *nf = &nf1;
+
+	if (id)
+		nf = &nf2;
+
+	if (ISNULL(nf_param)) {
+		/* Copy defaults for nf */
+		memcpy((void *)nf,
+		       (void *)&dm365_nf_defaults,
+		       sizeof(struct prev_nf));
+		memset((void *)nf->thr, 0, IPIPE_NF_THR_TABLE_SIZE);
+		memset((void *)nf->str, 0, IPIPE_NF_THR_TABLE_SIZE);
+	} else {
+		if (len != sizeof(struct prev_nf)) {
+			dev_err(dev,
+				"set_nf_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(nf, nf_param, sizeof(struct prev_nf))) {
+			dev_err(dev,
+				"set_nf_params: Error in copy to kernel\n");
+			return -EFAULT;
+		}
+		if (validate_nf_params(dev, id) < 0)
+			return -EINVAL;
+	}
+	/* Now set the values in the hw */
+	ipipe_set_d2f_regs(id, nf);
+
+	return 0;
+}
+
+static int set_nf1_params(struct device *dev, void *param, int len)
+{
+	return set_nf_params(dev, 0, param, len);
+}
+
+static int set_nf2_params(struct device *dev, void *param, int len)
+{
+	return set_nf_params(dev, 1, param, len);
+}
+
+static int get_nf_params(struct device *dev, unsigned int id, void *param,
+			 int len)
+{
+	struct prev_nf *nf_param = (struct prev_nf *)param;
+	struct prev_nf *nf = &nf1;
+
+	if (ISNULL(nf_param)) {
+		dev_err(dev, "get_nf_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_nf)) {
+		dev_err(dev,
+			"get_nf_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (id)
+		nf = &nf2;
+	if (copy_to_user((struct prev_nf *)nf_param, nf,
+			 sizeof(struct prev_nf))) {
+		dev_err(dev, "get_nf_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int get_nf1_params(struct device *dev, void *param, int len)
+{
+	return get_nf_params(dev, 0, param, len);
+}
+
+static int get_nf2_params(struct device *dev, void *param, int len)
+{
+	return get_nf_params(dev, 1, param, len);
+}
+
+static int validate_gic_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (gic.en > 1 ||
+	    gic.gain > GIC_GAIN_MASK ||
+	    gic.thr > GIC_THR_MASK ||
+	    gic.slope > GIC_SLOPE_MASK ||
+	    gic.apply_lsc_gain > 1 ||
+	    gic.nf2_thr_gain.integer > GIC_NFGAN_INT_MASK ||
+	    gic.nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK)
+		return -1;
+#endif
+	return 0;
+}
+
+static int set_gic_params(struct device *dev, void *param, int len)
+{
+	struct prev_gic *gic_param = (struct prev_gic *)param;
+
+	if (ISNULL(gic_param)) {
+		/* Copy defaults for nf */
+		memcpy((void *)&gic,
+		       (void *)&dm365_gic_defaults,
+		       sizeof(struct prev_gic));
+	} else {
+		if (len != sizeof(struct prev_gic)) {
+			dev_err(dev,
+				"set_gic_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&gic, gic_param, sizeof(struct prev_gic))) {
+			dev_err(dev,
+				"set_gic_params: Error in copy to kernel\n");
+			return -EFAULT;
+		}
+		if (validate_gic_params(dev) < 0)
+			return -EINVAL;
+	}
+	/* Now set the values in the hw */
+	ipipe_set_gic_regs(&gic);
+
+	return 0;
+}
+
+static int get_gic_params(struct device *dev, void *param, int len)
+{
+	struct prev_gic *gic_param = (struct prev_gic *)param;
+
+	if (ISNULL(gic_param)) {
+		dev_err(dev, "get_gic_params: invalid user ptr");
+		return -EINVAL;
+	}
+
+	if (len != sizeof(struct prev_gic)) {
+		dev_err(dev,
+			"get_gic_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+
+	if (copy_to_user((struct prev_gic *)gic_param,
+			 &gic,
+			 sizeof(struct prev_gic))) {
+		dev_err(dev, "get_gic_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_wb_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (wb.ofst_r > WB_OFFSET_MASK ||
+	    wb.ofst_gr > WB_OFFSET_MASK ||
+	    wb.ofst_gb > WB_OFFSET_MASK ||
+	    wb.ofst_b > WB_OFFSET_MASK ||
+	    wb.gain_r.integer > WB_GAIN_INT_MASK ||
+	    wb.gain_r.decimal > WB_GAIN_DECI_MASK ||
+	    wb.gain_gr.integer > WB_GAIN_INT_MASK ||
+	    wb.gain_gr.decimal > WB_GAIN_DECI_MASK ||
+	    wb.gain_gb.integer > WB_GAIN_INT_MASK ||
+	    wb.gain_gb.decimal > WB_GAIN_DECI_MASK ||
+	    wb.gain_b.integer > WB_GAIN_INT_MASK ||
+	    wb.gain_b.decimal > WB_GAIN_DECI_MASK)
+		return -EINVAL;
+#endif
+	return 0;
+}
+static int set_wb_params(struct device *dev, void *param, int len)
+{
+	struct prev_wb *wb_param = (struct prev_wb *)param;
+
+	dev_dbg(dev, "set_wb_params");
+	if (ISNULL(wb_param)) {
+		/* Copy defaults for wb */
+		memcpy((void *)&wb,
+		       (void *)&dm365_wb_defaults,
+		       sizeof(struct prev_wb));
+	} else {
+		if (len != sizeof(struct prev_wb)) {
+			dev_err(dev,
+				"set_wb_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&wb, wb_param, sizeof(struct prev_wb))) {
+			dev_err(dev,
+				"set_wb_params: Error in copy to kernel\n");
+			return -EFAULT;
+		}
+		if (validate_wb_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	/* Now set the values in the hw */
+	ipipe_set_wb_regs(&wb);
+
+	return 0;
+}
+static int get_wb_params(struct device *dev, void *param, int len)
+{
+	struct prev_wb *wb_param = (struct prev_wb *)param;
+
+	if (ISNULL(wb_param)) {
+		dev_err(dev, "get_wb_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_wb)) {
+		dev_err(dev,
+			"get_wb_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user((struct prev_wb *)wb_param,
+			 &wb,
+			 sizeof(struct prev_wb))) {
+		dev_err(dev, "get_wb_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_cfa_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (cfa.hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK ||
+	    cfa.hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK ||
+	    cfa.hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK ||
+	    cfa.hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK ||
+	    cfa.dir_thr_2dir > CFA_DIR_THR_2DIR_MASK ||
+	    cfa.dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK ||
+	    cfa.nd_wt_2dir > CFA_ND_WT_2DIR_MASK ||
+	    cfa.hue_fract_daa > CFA_DAA_HUE_FRA_MASK ||
+	    cfa.edge_thr_daa > CFA_DAA_EDG_THR_MASK ||
+	    cfa.thr_min_daa > CFA_DAA_THR_MIN_MASK ||
+	    cfa.thr_slope_daa > CFA_DAA_THR_SLP_MASK ||
+	    cfa.slope_min_daa > CFA_DAA_SLP_MIN_MASK ||
+	    cfa.slope_slope_daa > CFA_DAA_SLP_SLP_MASK ||
+	    cfa.lp_wt_daa > CFA_DAA_LP_WT_MASK)
+		return -EINVAL;
+#endif
+	return 0;
+}
+static int set_cfa_params(struct device *dev, void *param, int len)
+{
+	struct prev_cfa *cfa_param = (struct prev_cfa *)param;
+
+	dev_dbg(dev, "set_cfa_params");
+	if (ISNULL(cfa_param)) {
+		/* Copy defaults for wb */
+		memcpy((void *)&cfa,
+		       (void *)&dm365_cfa_defaults,
+		       sizeof(struct prev_cfa));
+	} else {
+		if (len != sizeof(struct prev_cfa)) {
+			dev_err(dev,
+				"set_cfa_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&cfa, cfa_param, sizeof(struct prev_cfa))) {
+			dev_err(dev,
+				"set_cfa_params: Error in copy to kernel\n");
+			return -EFAULT;
+		}
+		if (validate_cfa_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	/* Now set the values in the hw */
+	ipipe_set_cfa_regs(&cfa);
+
+	return 0;
+}
+static int get_cfa_params(struct device *dev, void *param, int len)
+{
+	struct prev_cfa *cfa_param = (struct prev_cfa *)param;
+
+	dev_dbg(dev, "get_cfa_params\n");
+	if (ISNULL(cfa_param)) {
+		dev_err(dev, "get_cfa_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_cfa)) {
+		dev_err(dev,
+			"get_cfa_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user((struct prev_cfa *)cfa_param,
+			 &cfa,
+			 sizeof(struct prev_cfa))) {
+		dev_err(dev, "get_cfa_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_rgb2rgb_params(struct device *dev, unsigned int id)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
+	u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK;
+	u32 offset_upper = RGB2RGB_1_OFST_MASK;
+
+	if (id) {
+		rgb2rgb = &rgb2rgb_2;
+		offset_upper = RGB2RGB_2_OFST_MASK;
+		gain_int_upper = RGB2RGB_2_GAIN_INT_MASK;
+	}
+	if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_rr.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_gr.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_br.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_rg.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_gg.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_bg.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_rb.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_gb.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK ||
+	    rgb2rgb->coef_bb.integer > gain_int_upper)
+		return -EINVAL;
+
+	if (rgb2rgb->out_ofst_r > offset_upper ||
+	    rgb2rgb->out_ofst_g > offset_upper ||
+	    rgb2rgb->out_ofst_b > offset_upper)
+		return -EINVAL;
+#endif
+	return 0;
+}
+
+static int set_rgb2rgb_params(struct device *dev, unsigned int id,
+			      void *param, int len)
+{
+	struct prev_rgb2rgb *rgb2rgb_param = (struct prev_rgb2rgb *)param;
+	struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
+
+	if (id)
+		rgb2rgb = &rgb2rgb_2;
+	if (ISNULL(rgb2rgb_param)) {
+		/* Copy defaults for rgb2rgb conversion */
+		memcpy((void *)rgb2rgb,
+		       (void *)&dm365_rgb2rgb_defaults,
+		       sizeof(struct prev_rgb2rgb));
+	} else {
+
+		if (len != sizeof(struct prev_rgb2rgb)) {
+			dev_err(dev,
+				"set_rgb2rgb_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+
+		if (copy_from_user(rgb2rgb,
+				   rgb2rgb_param,
+				   sizeof(struct prev_rgb2rgb))) {
+			dev_err(dev,
+				"set_rgb2rgb_params: Error in "
+				"copy to kernel\n");
+			return -EFAULT;
+		}
+		if (validate_rgb2rgb_params(dev, id) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_rgb2rgb_regs(id, rgb2rgb);
+
+	return 0;
+}
+
+static int set_rgb2rgb_1_params(struct device *dev, void *param, int len)
+{
+	return set_rgb2rgb_params(dev, 0, param, len);
+}
+
+static int set_rgb2rgb_2_params(struct device *dev, void *param, int len)
+{
+	return set_rgb2rgb_params(dev, 1, param, len);
+}
+
+static int get_rgb2rgb_params(struct device *dev, unsigned int id,
+			      void *param, int len)
+{
+	struct prev_rgb2rgb *rgb2rgb_param = (struct prev_rgb2rgb *)param;
+	struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
+
+	if (ISNULL(rgb2rgb_param)) {
+		dev_err(dev, "get_rgb2rgb_params: invalid user ptr");
+		return -EINVAL;
+	}
+
+	if (len != sizeof(struct prev_rgb2rgb)) {
+		dev_err(dev,
+			"get_rgb2rgb_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+
+	if (id)
+		rgb2rgb = &rgb2rgb_2;
+	if (copy_to_user((struct prev_rgb2rgb *)rgb2rgb_param,
+			 rgb2rgb,
+			 sizeof(struct prev_rgb2rgb))) {
+		dev_err(dev, "get_rgb2rgb_params: Error in copy to user\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int get_rgb2rgb_1_params(struct device *dev, void *param, int len)
+{
+	return get_rgb2rgb_params(dev, 0, param, len);
+}
+
+static int get_rgb2rgb_2_params(struct device *dev, void *param, int len)
+{
+	return get_rgb2rgb_params(dev, 1, param, len);
+}
+
+static int validate_gamma_entry(struct ipipe_gamma_entry *table, int size)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	int i;
+
+	if (ISNULL(table))
+		return -EINVAL;
+
+	for (i = 0; i < size; i++) {
+		if (table[i].slope > GAMMA_MASK ||
+		    table[i].offset > GAMMA_MASK)
+			return -EINVAL;
+	}
+#endif
+	return 0;
+}
+
+static int validate_gamma_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	int table_size;
+	int err;
+
+	if (gamma.bypass_r > 1 ||
+	    gamma.bypass_b > 1 ||
+	    gamma.bypass_g > 1)
+		return -EINVAL;
+
+	if (gamma.tbl_sel != IPIPE_GAMMA_TBL_RAM)
+		return 0;
+
+	table_size = gamma.tbl_size;
+	if (!gamma.bypass_r) {
+		err = validate_gamma_entry(gamma.table_r, table_size);
+		if (err) {
+			dev_err(dev, "GAMMA R - table entry invalid\n");
+			return err;
+		}
+	}
+	if (!gamma.bypass_b) {
+		err = validate_gamma_entry(gamma.table_b, table_size);
+		if (err) {
+			dev_err(dev, "GAMMA B - table entry invalid\n");
+			return err;
+		}
+	}
+	if (!gamma.bypass_g) {
+		err = validate_gamma_entry(gamma.table_g, table_size);
+		if (err) {
+			dev_err(dev, "GAMMA G - table entry invalid\n");
+			return err;
+		}
+	}
+#endif
+	return 0;
+}
+static int set_gamma_params(struct device *dev, void *param, int len)
+{
+
+	struct prev_gamma *gamma_param = (struct prev_gamma *)param;
+	struct prev_gamma user_gamma;
+	int table_size;
+
+	if (ISNULL(gamma_param)) {
+		/* Copy defaults for gamma */
+		gamma.bypass_r = dm365_gamma_defaults.bypass_r;
+		gamma.bypass_g = dm365_gamma_defaults.bypass_g;
+		gamma.bypass_b = dm365_gamma_defaults.bypass_b;
+		gamma.tbl_sel = dm365_gamma_defaults.tbl_sel;
+		gamma.tbl_size = dm365_gamma_defaults.tbl_size;
+		/* By default, we bypass the gamma correction.
+		 * So no values by default for tables
+		 */
+		goto success;
+	}
+
+	if (len != sizeof(struct prev_gamma)) {
+		dev_err(dev,
+			"set_gamma_params: param struct length"
+			" mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&user_gamma, gamma_param,
+			    sizeof(struct prev_gamma))) {
+		dev_err(dev,
+			"set_gamma_params: Error in copy to kernel\n");
+		return -EFAULT;
+	}
+
+	if (validate_gamma_params(dev) < 0)
+		return -EINVAL;
+
+	gamma.bypass_r = user_gamma.bypass_r;
+	gamma.bypass_b = user_gamma.bypass_b;
+	gamma.bypass_g = user_gamma.bypass_g;
+	gamma.tbl_sel = user_gamma.tbl_sel;
+	gamma.tbl_size = user_gamma.tbl_size;
+
+	if (user_gamma.tbl_sel != IPIPE_GAMMA_TBL_RAM)
+		goto success;
+
+	table_size = user_gamma.tbl_size;
+
+	if (!user_gamma.bypass_r) {
+		if (ISNULL(user_gamma.table_r)) {
+			dev_err(dev,
+				"set_gamma_params: Invalid"
+				" table ptr for R\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(gamma.table_r,
+				    user_gamma.table_r,
+				    (table_size *
+				    sizeof(struct \
+				    ipipe_gamma_entry)))) {
+			dev_err(dev,
+				"set_gamma_params: R-Error"
+				" in copy to kernel\n");
+			return -EFAULT;
+		}
+	}
+
+	if (!user_gamma.bypass_b) {
+		if (ISNULL(user_gamma.table_b)) {
+			dev_err(dev,
+				"set_gamma_params: Invalid"
+				" table ptr for B\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(gamma.table_b,
+				    user_gamma.table_b,
+				    (table_size *
+				    sizeof(struct \
+				    ipipe_gamma_entry)))) {
+			dev_err(dev,
+				"set_gamma_params: B-Error"
+				" in copy to kernel\n");
+			return -EFAULT;
+		}
+	}
+
+	if (!user_gamma.bypass_g) {
+		if (ISNULL(user_gamma.table_g)) {
+			dev_err(dev,
+				"set_gamma_params: Invalid"
+				" table ptr for G\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(gamma.table_g,
+				    user_gamma.table_g,
+				    (table_size *
+				    sizeof(struct \
+				    ipipe_gamma_entry)))) {
+			dev_err(dev,
+				"set_gamma_params: G-Error "
+				"in copy to kernel\n");
+			return -EFAULT;
+		}
+	}
+
+success:
+	ipipe_set_gamma_regs(&gamma);
+
+	return 0;
+}
+
+static int get_gamma_params(struct device *dev, void *param, int len)
+{
+	struct prev_gamma *gamma_param = (struct prev_gamma *)param;
+	struct prev_gamma user_gamma;
+	int table_size;
+
+	if (ISNULL(gamma_param)) {
+		dev_err(dev, "get_gamma_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_gamma)) {
+		dev_err(dev,
+			"get_gamma_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&user_gamma,
+			   gamma_param,
+			   sizeof(struct prev_gamma))) {
+		dev_err(dev, "get_gamma_params: Error in copy to kernel\n");
+		return -EFAULT;
+	}
+
+	user_gamma.bypass_r = gamma.bypass_r;
+	user_gamma.bypass_g = gamma.bypass_g;
+	user_gamma.bypass_b = gamma.bypass_b;
+	user_gamma.tbl_sel = gamma.tbl_sel;
+	user_gamma.tbl_size = gamma.tbl_size;
+	if (gamma.tbl_sel == IPIPE_GAMMA_TBL_RAM) {
+		table_size = gamma.tbl_size;
+
+		if ((!gamma.bypass_r) && ((ISNULL(user_gamma.table_r)))) {
+			dev_err(dev,
+				"get_gamma_params: table ptr empty for R\n");
+			return -EINVAL;
+		} else {
+			if (copy_to_user(user_gamma.table_r,
+					 gamma.table_r,
+					 (table_size *
+					 sizeof(struct ipipe_gamma_entry)))) {
+				dev_err(dev,
+					"set_gamma_params: R-Table Error in"
+					" copy to user\n");
+				return -EFAULT;
+			}
+		}
+
+		if ((!gamma.bypass_b) && ((ISNULL(user_gamma.table_b)))) {
+			dev_err(dev,
+				"get_gamma_params: table ptr empty for B\n");
+			return -EINVAL;
+		} else {
+			if (copy_to_user(user_gamma.table_b,
+					 gamma.table_b,
+					 (table_size *
+					  sizeof(struct ipipe_gamma_entry)))) {
+				dev_err(dev,
+					"set_gamma_params: B-Table Error in"
+					" copy to user\n");
+				return -EFAULT;
+			}
+		}
+
+		if ((!gamma.bypass_g) && ((ISNULL(user_gamma.table_g)))) {
+			dev_err(dev,
+				"get_gamma_params: table ptr empty for G\n");
+			return -EINVAL;
+		} else {
+			if (copy_from_user(gamma.table_g,
+				user_gamma.table_g,
+				(table_size *
+				sizeof(struct ipipe_gamma_entry)))) {
+				dev_err(dev,
+					"set_gamma_params: G-Table"
+					"copy error\n");
+				return -EFAULT;
+			}
+		}
+
+	}
+	if (copy_to_user(gamma_param, &user_gamma,
+		sizeof(struct prev_gamma))) {
+		dev_err(dev, "get_dfc_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_3d_lut_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	int i;
+
+	if (!lut_3d.en)
+		return 0;
+
+	for (i = 0; i < MAX_SIZE_3D_LUT; i++) {
+		if (lut_3d.table[i].r > D3_LUT_ENTRY_MASK ||
+		    lut_3d.table[i].g > D3_LUT_ENTRY_MASK ||
+		    lut_3d.table[i].b > D3_LUT_ENTRY_MASK)
+			return -EINVAL;
+	}
+#endif
+	return 0;
+}
+static int set_3d_lut_params(struct device *dev, void *param, int len)
+{
+	struct prev_3d_lut *lut_param = (struct prev_3d_lut *)param;
+	struct prev_3d_lut user_3d_lut;
+
+	if (ISNULL(lut_param)) {
+		/* Copy defaults for gamma */
+		lut_3d.en = dm365_3d_lut_defaults.en;
+		/* By default, 3D lut is disabled
+		 */
+	} else {
+		if (len != sizeof(struct prev_3d_lut)) {
+			dev_err(dev,
+				"set_3d_lut_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&user_3d_lut,
+				   lut_param,
+				   sizeof(struct prev_3d_lut))) {
+			dev_err(dev,
+				"set_3d_lut_params: Error in copy to"
+				" kernel\n");
+			return -EFAULT;
+		}
+		lut_3d.en = user_3d_lut.en;
+		if (ISNULL(user_3d_lut.table)) {
+			dev_err(dev, "set_3d_lut_params: Invalid table ptr");
+			return -EINVAL;
+		}
+		if (copy_from_user(lut_3d.table,
+				   user_3d_lut.table,
+				   (MAX_SIZE_3D_LUT *
+				   sizeof(struct ipipe_3d_lut_entry)))) {
+			dev_err(dev,
+				"set_3d_lut_params:Error"
+				" in copy to kernel\n");
+			return -EFAULT;
+		}
+
+		if (validate_3d_lut_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_3d_lut_regs(&lut_3d);
+
+	return 0;
+}
+static int get_3d_lut_params(struct device *dev, void *param, int len)
+{
+	struct prev_3d_lut *lut_param = (struct prev_3d_lut *)param;
+	struct prev_3d_lut user_3d_lut;
+
+	if (ISNULL(lut_param)) {
+		dev_err(dev, "get_3d_lut_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_3d_lut)) {
+		dev_err(dev,
+			"get_3d_lut_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&user_3d_lut,
+			   lut_param,
+			   sizeof(struct prev_3d_lut))) {
+		dev_err(dev, "get_3d_lut_params: Error in copy to kernel\n");
+		return -EFAULT;
+	}
+
+	user_3d_lut.en = lut_3d.en;
+	if (ISNULL(user_3d_lut.table)) {
+		dev_err(dev, "get_3d_lut_params:" " Invalid table ptr");
+		return -EINVAL;
+	}
+	if (copy_to_user(user_3d_lut.table, lut_3d.table,
+			 (MAX_SIZE_3D_LUT *
+			  sizeof(struct ipipe_3d_lut_entry)))) {
+		dev_err(dev,
+			"get_3d_lut_params:Table Error in" " copy to user\n");
+		return -EFAULT;
+	}
+
+	if (copy_to_user(lut_param, &user_3d_lut,
+		sizeof(struct prev_3d_lut))) {
+		dev_err(dev, "get_3d_lut_params: Error in copy" " to user\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_lum_adj_params(struct device *dev)
+{
+	/* nothing to validate */
+	return 0;
+}
+
+static int set_lum_adj_params(struct device *dev, void *param, int len)
+{
+	struct prev_lum_adj *lum_adj_param = (struct prev_lum_adj *)param;
+
+	if (ISNULL(lum_adj_param)) {
+		/* Copy defaults for Luminance adjustments */
+		memcpy((void *)&lum_adj,
+		       (void *)&dm365_lum_adj_defaults,
+		       sizeof(struct prev_lum_adj));
+	} else {
+		if (len != sizeof(struct prev_lum_adj)) {
+			dev_err(dev,
+				"set_lum_adj_params: param struct length"
+				" mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&lum_adj,
+				   lum_adj_param,
+				   sizeof(struct prev_lum_adj))) {
+			dev_err(dev,
+				"set_lum_adj_params: Error in copy"
+				" from user\n");
+			return -EFAULT;
+		}
+		if (validate_lum_adj_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_lum_adj_regs(&lum_adj);
+
+	return 0;
+}
+
+static int get_lum_adj_params(struct device *dev, void *param, int len)
+{
+	struct prev_lum_adj *lum_adj_param = (struct prev_lum_adj *)param;
+
+	if (ISNULL(lum_adj_param)) {
+		dev_err(dev, "get_lum_adj_params: invalid user ptr");
+		return -EINVAL;
+	}
+
+	if (len != sizeof(struct prev_lum_adj)) {
+		dev_err(dev,
+			"get_lum_adj_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+
+	if (copy_to_user(lum_adj_param,
+			 &lum_adj,
+			 sizeof(struct prev_lum_adj))) {
+		dev_err(dev, "get_lum_adj_params: Error in copy to" " user\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_rgb2yuv_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (rgb2yuv.coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_ry.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_gy.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_by.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
+	    rgb2yuv.coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK)
+		return -EINVAL;
+
+	if (rgb2yuv.out_ofst_y > RGB2YCBCR_OFST_MASK ||
+	    rgb2yuv.out_ofst_cb > RGB2YCBCR_OFST_MASK ||
+	    rgb2yuv.out_ofst_cr > RGB2YCBCR_OFST_MASK)
+		return -EINVAL;
+#endif
+	return 0;
+}
+static int set_rgb2yuv_params(struct device *dev, void *param, int len)
+{
+	struct prev_rgb2yuv *rgb2yuv_param = (struct prev_rgb2yuv *)param;
+
+	if (ISNULL(rgb2yuv_param)) {
+		/* Copy defaults for rgb2yuv conversion  */
+		memcpy((void *)&rgb2yuv,
+		       (void *)&dm365_rgb2yuv_defaults,
+		       sizeof(struct prev_rgb2yuv));
+	} else {
+		if (len != sizeof(struct prev_rgb2yuv)) {
+			dev_err(dev,
+				"set_rgb2yuv_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&rgb2yuv,
+				   rgb2yuv_param,
+				   sizeof(struct prev_rgb2yuv))) {
+			dev_err(dev,
+				"set_rgb2yuv_params: Error in copy from"
+				" user\n");
+			return -EFAULT;
+		}
+		if (validate_rgb2yuv_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_rgb2ycbcr_regs(&rgb2yuv);
+
+	return 0;
+}
+static int get_rgb2yuv_params(struct device *dev, void *param, int len)
+{
+	struct prev_rgb2yuv *rgb2yuv_param = (struct prev_rgb2yuv *)param;
+
+	if (ISNULL(rgb2yuv_param)) {
+		dev_err(dev, "get_rgb2yuv_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_rgb2yuv)) {
+		dev_err(dev,
+			"get_rgb2yuv_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user((struct prev_rgb2yuv *)rgb2yuv_param,
+			 &rgb2yuv,
+			 sizeof(struct prev_rgb2yuv))) {
+		dev_err(dev, "get_rgb2yuv_params: Error in copy from"
+			" kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_gbce_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	u32 max = GBCE_Y_VAL_MASK;
+	int i;
+
+	if (!gbce.en)
+		return 0;
+
+	if (gbce.type == IPIPE_GBCE_GAIN_TBL)
+		max = GBCE_GAIN_VAL_MASK;
+	for (i = 0; i < MAX_SIZE_GBCE_LUT; i++)
+		if (gbce.table[i] > max)
+			return -EINVAL;
+#endif
+	return 0;
+}
+static int set_gbce_params(struct device *dev, void *param, int len)
+{
+	struct prev_gbce *gbce_param = (struct prev_gbce *)param;
+	struct prev_gbce user_gbce;
+
+	if (ISNULL(gbce_param))
+		/* Copy defaults for gamma */
+		gbce.en = dm365_gbce_defaults.en;
+		/* By default, GBCE is disabled
+		 */
+	else {
+		if (len != sizeof(struct prev_gbce)) {
+			dev_err(dev,
+				"set_gbce_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&user_gbce,
+				   gbce_param,
+				   sizeof(struct prev_gbce))) {
+			dev_err(dev,
+				"set_gbce_params: Error in copy to"
+				" kernel\n");
+			return -EFAULT;
+		}
+		gbce.en = user_gbce.en;
+		gbce.type = user_gbce.type;
+		if (ISNULL(user_gbce.table)) {
+			dev_err(dev, "set_gbce_params:" " Invalid table ptr");
+			return -EINVAL;
+		}
+
+		if (copy_from_user(gbce.table,
+				   user_gbce.table,
+				   (MAX_SIZE_GBCE_LUT *
+				   sizeof(unsigned short)))) {
+			dev_err(dev, "set_gbce_params:Error"
+					" in copy to kernel\n");
+			return -EFAULT;
+		}
+		if (validate_gbce_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_gbce_regs(&gbce);
+
+	return 0;
+}
+static int get_gbce_params(struct device *dev, void *param, int len)
+{
+	struct prev_gbce *gbce_param = (struct prev_gbce *)param;
+	struct prev_gbce user_gbce;
+
+	if (ISNULL(gbce_param)) {
+		dev_err(dev, "get_gbce_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_gbce)) {
+		dev_err(dev,
+			"get_gbce_params: param struct length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&user_gbce, gbce_param, sizeof(struct prev_gbce))) {
+		dev_err(dev, "get_gbce_params: Error in copy to" " kernel\n");
+		return -EFAULT;
+	}
+
+	user_gbce.en = gbce.en;
+	user_gbce.type = gbce.type;
+	if (ISNULL(user_gbce.table)) {
+		dev_err(dev, "get_gbce_params:" " Invalid table ptr");
+		return -EINVAL;
+	}
+	if (copy_to_user(user_gbce.table,
+			 gbce.table,
+			 (MAX_SIZE_GBCE_LUT *
+			 sizeof(unsigned short)))) {
+		dev_err(dev,
+			"get_gbce_params:Table Error in" " copy to user\n");
+		return -EFAULT;
+	}
+
+	if (copy_to_user(gbce_param, &user_gbce, sizeof(struct prev_gbce))) {
+		dev_err(dev, "get_gbce_params: Error in copy" " to user\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_yuv422_conv_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (yuv422_conv.en_chrom_lpf > 1)
+		return -EINVAL;
+#endif
+	return 0;
+}
+
+static int set_yuv422_conv_params(struct device *dev, void *param, int len)
+{
+	struct prev_yuv422_conv *yuv422_conv_param =
+	    (struct prev_yuv422_conv *)param;
+
+	if (ISNULL(yuv422_conv_param)) {
+		/* Copy defaults for yuv 422 conversion */
+		memcpy((void *)&yuv422_conv,
+		       (void *)&dm365_yuv422_conv_defaults,
+		       sizeof(struct prev_yuv422_conv));
+	} else {
+		if (len != sizeof(struct prev_yuv422_conv)) {
+			dev_err(dev,
+				"set_yuv422_conv_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&yuv422_conv,
+				   yuv422_conv_param,
+				   sizeof(struct prev_yuv422_conv))) {
+			dev_err(dev,
+				"set_yuv422_conv_params: Error in copy"
+				" from user\n");
+			return -EFAULT;
+		}
+		if (validate_yuv422_conv_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_yuv422_conv_regs(&yuv422_conv);
+
+	return 0;
+}
+static int get_yuv422_conv_params(struct device *dev, void *param, int len)
+{
+	struct prev_yuv422_conv *yuv422_conv_param =
+	    (struct prev_yuv422_conv *)param;
+
+	if (ISNULL(yuv422_conv_param)) {
+		dev_err(dev, "get_yuv422_conv_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_yuv422_conv)) {
+		dev_err(dev,
+			"get_yuv422_conv_params: param struct"
+			" length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user(yuv422_conv_param,
+			 &yuv422_conv,
+			 sizeof(struct prev_yuv422_conv))) {
+		dev_err(dev,
+			"get_yuv422_conv_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_yee_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	int i;
+
+	if (yee.en > 1 ||
+	    yee.en_halo_red > 1 ||
+	    yee.hpf_shft > YEE_HPF_SHIFT_MASK)
+		return -EINVAL;
+
+	if (yee.hpf_coef_00 > YEE_COEF_MASK ||
+	    yee.hpf_coef_01 > YEE_COEF_MASK ||
+	    yee.hpf_coef_02 > YEE_COEF_MASK ||
+	    yee.hpf_coef_10 > YEE_COEF_MASK ||
+	    yee.hpf_coef_11 > YEE_COEF_MASK ||
+	    yee.hpf_coef_12 > YEE_COEF_MASK ||
+	    yee.hpf_coef_20 > YEE_COEF_MASK ||
+	    yee.hpf_coef_21 > YEE_COEF_MASK ||
+	    yee.hpf_coef_22 > YEE_COEF_MASK)
+		return -EINVAL;
+
+	if (yee.yee_thr > YEE_THR_MASK ||
+	    yee.es_gain > YEE_ES_GAIN_MASK ||
+	    yee.es_thr1 > YEE_ES_THR1_MASK ||
+	    yee.es_thr2 > YEE_THR_MASK ||
+	    yee.es_gain_grad > YEE_THR_MASK ||
+	    yee.es_ofst_grad > YEE_THR_MASK)
+		return -EINVAL;
+
+	for (i = 0; i < MAX_SIZE_YEE_LUT ; i++)
+		if (yee.table[i] > YEE_ENTRY_MASK)
+			return -EINVAL;
+#endif
+	return 0;
+}
+static int set_yee_params(struct device *dev, void *param, int len)
+{
+	struct prev_yee *yee_param = (struct prev_yee *)param;
+	struct prev_yee user_yee;
+	short *temp_table;
+
+	if (ISNULL(yee_param)) {
+		temp_table = yee.table;
+		/* Copy defaults for ns */
+		memcpy((void *)&yee,
+		       (void *)&dm365_yee_defaults,
+		       sizeof(struct prev_yee));
+		yee.table = temp_table;
+	} else {
+		if (len != sizeof(struct prev_yee)) {
+			dev_err(dev,
+				"set_yee_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&user_yee,
+				   yee_param,
+				   sizeof(struct prev_yee))) {
+			dev_err(dev,
+				"set_yee_params: Error in copy from user\n");
+			return -EFAULT;
+		}
+		if (ISNULL(user_yee.table)) {
+			dev_err(dev, "get_yee_params: yee table ptr null\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(yee.table,
+				   user_yee.table,
+				   (MAX_SIZE_YEE_LUT * sizeof(short)))) {
+			dev_err(dev,
+				"set_yee_params: Error in copy from user\n");
+			return -EFAULT;
+		}
+		temp_table = yee.table;
+		memcpy(&yee, &user_yee, sizeof(struct prev_yee));
+		yee.table = temp_table;
+		if (validate_yee_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_ee_regs(&yee);
+
+	return 0;
+}
+static int get_yee_params(struct device *dev, void *param, int len)
+{
+	struct prev_yee *yee_param = (struct prev_yee *)param;
+	struct prev_yee user_yee;
+	short *temp_table;
+
+	if (ISNULL(yee_param)) {
+		dev_err(dev, "get_yee_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_yee)) {
+		dev_err(dev,
+			"get_yee_params: param struct"
+			" length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_from_user(&user_yee, yee_param, sizeof(struct prev_yee))) {
+		dev_err(dev, "get_yee_params: Error in copy to kernel\n");
+		return -EFAULT;
+	}
+	if (ISNULL(user_yee.table)) {
+		dev_err(dev, "get_yee_params: yee table ptr null\n");
+		return -EINVAL;
+	}
+	if (copy_to_user(user_yee.table, yee.table,
+			 (MAX_SIZE_YEE_LUT * sizeof(short)))) {
+		dev_err(dev, "get_yee_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+	temp_table = user_yee.table;
+	memcpy(&user_yee, &yee, sizeof(struct prev_yee));
+	user_yee.table = temp_table;
+
+	if (copy_to_user(yee_param, &user_yee, sizeof(struct prev_yee))) {
+		dev_err(dev, "get_yee_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_car_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (car.en > 1 ||
+	    car.hpf_shft > CAR_HPF_SHIFT_MASK ||
+	    car.gain1.shft > CAR_GAIN1_SHFT_MASK ||
+	    car.gain1.gain_min > CAR_GAIN_MIN_MASK ||
+	    car.gain2.shft > CAR_GAIN2_SHFT_MASK ||
+	    car.gain2.gain_min > CAR_GAIN_MIN_MASK)
+		return -EINVAL;
+#endif
+	return 0;
+}
+
+static int set_car_params(struct device *dev, void *param, int len)
+{
+	struct prev_car *car_param = (struct prev_car *)param;
+
+	if (ISNULL(car_param)) {
+		/* Copy defaults for ns */
+		memcpy((void *)&car,
+		       (void *)&dm365_car_defaults,
+		       sizeof(struct prev_car));
+	} else {
+		if (len != sizeof(struct prev_car)) {
+			dev_err(dev,
+				"set_car_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&car, car_param, sizeof(struct prev_car))) {
+			dev_err(dev,
+				"set_car_params: Error in copy from user\n");
+			return -EFAULT;
+		}
+		if (validate_car_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_car_regs(&car);
+
+	return 0;
+}
+static int get_car_params(struct device *dev, void *param, int len)
+{
+	struct prev_car *car_param = (struct prev_car *)param;
+
+	if (ISNULL(car_param)) {
+		dev_err(dev, "get_car_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_car)) {
+		dev_err(dev,
+			"get_car_params: param struct"
+			" length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user(car_param, &car, sizeof(struct prev_car))) {
+		dev_err(dev, "get_car_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int validate_cgs_params(struct device *dev)
+{
+#ifdef CONFIG_IPIPE_PARAM_VALIDATION
+	if (cgs.en > 1 ||
+	    cgs.h_shft > CAR_SHIFT_MASK)
+		return -EINVAL;
+#endif
+	return 0;
+}
+
+static int set_cgs_params(struct device *dev, void *param, int len)
+{
+	struct prev_cgs *cgs_param = (struct prev_cgs *)param;
+
+	if (ISNULL(cgs_param)) {
+		/* Copy defaults for ns */
+		memcpy((void *)&cgs,
+		       (void *)&dm365_cgs_defaults,
+		       sizeof(struct prev_cgs));
+	} else {
+		if (len != sizeof(struct prev_cgs)) {
+			dev_err(dev,
+				"set_cgs_params: param struct"
+				" length mismatch\n");
+			return -EINVAL;
+		}
+		if (copy_from_user(&cgs, cgs_param, sizeof(struct prev_cgs))) {
+			dev_err(dev,
+				"set_cgs_params: Error in copy from user\n");
+			return -EFAULT;
+		}
+		if (validate_cgs_params(dev) < 0)
+			return -EINVAL;
+	}
+
+	ipipe_set_cgs_regs(&cgs);
+
+	return 0;
+}
+
+static int get_cgs_params(struct device *dev, void *param, int len)
+{
+	struct prev_cgs *cgs_param = (struct prev_cgs *)param;
+
+	if (ISNULL(cgs_param)) {
+		dev_err(dev, "get_cgs_params: invalid user ptr");
+		return -EINVAL;
+	}
+	if (len != sizeof(struct prev_cgs)) {
+		dev_err(dev,
+			"get_cgs_params: param struct"
+			" length mismatch\n");
+		return -EINVAL;
+	}
+	if (copy_to_user(cgs_param, &cgs, sizeof(struct prev_cgs))) {
+		dev_err(dev, "get_cgs_params: Error in copy from kernel\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static struct prev_module_if prev_modules[PREV_MAX_MODULES] = {
+	{
+		.version = "5.1",
+		.module_id = PREV_LUTDPC,
+		.module_name = "LUT Defect Correction",
+		.control = 0,
+		.path = IMP_RAW2RAW | IMP_RAW2YUV,
+		.set = set_lutdpc_params,
+		.get = get_lutdpc_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_OTFDPC,
+		.module_name = "OTF Defect Pixel Correction",
+		.control = 0,
+		.path = IMP_RAW2RAW | IMP_RAW2YUV,
+		.set = set_otfdpc_params,
+		.get = get_otfdpc_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_NF1,
+		.module_name = "2-D Noise filter - 1",
+		.control = 0,
+		.path = IMP_RAW2RAW | IMP_RAW2YUV,
+		.set = set_nf1_params,
+		.get = get_nf1_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_NF2,
+		.module_name = "2-D Noise filter - 2",
+		.control = 0,
+		.path = IMP_RAW2RAW | IMP_RAW2YUV,
+		.set = set_nf2_params,
+		.get = get_nf2_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_GIC,
+		.module_name = "Green Imbalance Correction",
+		.control = 0,
+		.path = IMP_RAW2RAW | IMP_RAW2YUV,
+		.set = set_gic_params,
+		.get = get_gic_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_WB,
+		.module_name = "White balance",
+		.control = 1,
+		.path = IMP_RAW2RAW | IMP_RAW2YUV,
+		.set = set_wb_params,
+		.get = get_wb_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_CFA,
+		.module_name = "CFA Interpolation",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_cfa_params,
+		.get = get_cfa_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_RGB2RGB_1,
+		.module_name = "RGB-RGB Conversion - 1",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_rgb2rgb_1_params,
+		.get = get_rgb2rgb_1_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_GAMMA,
+		.module_name = "Gamma Correction",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_gamma_params,
+		.get = get_gamma_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_RGB2RGB_2,
+		.module_name = "RGB-RGB Conversion - 2",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_rgb2rgb_2_params,
+		.get = get_rgb2rgb_2_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_3D_LUT,
+		.module_name = "3D LUT",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_3d_lut_params,
+		.get = get_3d_lut_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_RGB2YUV,
+		.module_name = "RGB-YCbCr conversion",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_rgb2yuv_params,
+		.get = get_rgb2yuv_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_GBCE,
+		.module_name = "Global Brightness,Contrast Control",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_gbce_params,
+		.get = get_gbce_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_YUV422_CONV,
+		.module_name = "YUV 422 conversion",
+		.control = 0,
+		.path = IMP_RAW2YUV,
+		.set = set_yuv422_conv_params,
+		.get = get_yuv422_conv_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_LUM_ADJ,
+		.module_name = "Luminance Adjustment",
+		.control = 1,
+		.path = IMP_RAW2YUV,
+		.set = set_lum_adj_params,
+		.get = get_lum_adj_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_YEE,
+		.module_name = "Edge Enhancer",
+		.control = 1,
+		.path = IMP_RAW2YUV | IMP_YUV2YUV,
+		.set = set_yee_params,
+		.get = get_yee_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_CAR,
+		.module_name = "Chromatic Artifact Reduction",
+		.control = 1,
+		.path = IMP_RAW2YUV | IMP_YUV2YUV,
+		.set = set_car_params,
+		.get = get_car_params
+	},
+	{
+		.version = "5.1",
+		.module_id = PREV_CGS,
+		.module_name = "Chromatic Gain Suppression",
+		.control = 1,
+		.path = IMP_RAW2YUV | IMP_YUV2YUV,
+		.set = set_cgs_params,
+		.get = get_cgs_params
+	}
+};
+
+static struct prev_module_if *prev_enum_preview_cap(struct device *dev,
+						    int index)
+{
+	dev_dbg(dev, "prev_enum_preview_cap: index = %d\n", index);
+
+	if ((index + 1) > PREV_MAX_MODULES)
+		return NULL;
+
+	return &prev_modules[index];
+}
+
+static int ipipe_set_oper_mode(unsigned int mode)
+{
+	if (oper_mode == IMP_MODE_NOT_CONFIGURED)
+		oper_mode = mode;
+	else {
+		printk(KERN_ERR "IPIPE is already active!\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void ipipe_reset_oper_mode(void)
+{
+	oper_mode = IMP_MODE_NOT_CONFIGURED;
+	oper_state.prev_config_state = STATE_NOT_CONFIGURED;
+	oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
+	oper_state.rsz_chained = 0;
+}
+
+static unsigned int prev_get_oper_mode(void)
+{
+	return oper_mode;
+}
+
+static unsigned int ipipe_get_oper_state(void)
+{
+	return oper_state.state;
+}
+
+static void ipipe_set_oper_state(unsigned int state)
+{
+	mutex_lock(&oper_state.lock);
+	oper_state.state = state;
+	mutex_unlock(&oper_state.lock);
+}
+
+static unsigned int ipipe_get_prev_config_state(void)
+{
+	return oper_state.prev_config_state;
+}
+
+static unsigned int ipipe_get_rsz_config_state(void)
+{
+	return oper_state.rsz_config_state;
+}
+
+/* function: calculate_normal_f_div_param
+ * Algorithm to calculate the frame division parameters for resizer.
+ * in normal mode. Please refer the application note in DM360 functional
+ * spec for details of the algorithm
+ */
+static int calculate_normal_f_div_param(struct device *dev,
+					int input_width,
+					int output_width,
+					struct ipipe_rsz_rescale_param *param)
+{
+	/* rsz = R, input_width = H, output width = h in the equation */
+	unsigned int val1;
+	unsigned int rsz;
+	unsigned int val;
+	unsigned int h1;
+	unsigned int h2;
+	unsigned int o;
+
+	if (output_width > input_width) {
+		dev_err(dev, "frame div mode is used for scale down only\n");
+		return -EINVAL;
+	}
+
+	rsz = (input_width << 8) / output_width;
+	val = rsz << 1;
+	val = ((input_width << 8) / val) + 1;
+	o = 14;
+	if (!(val % 2)) {
+		h1 = val;
+	} else {
+		val = (input_width << 7);
+		val -= (rsz >> 1);
+		val /= (rsz << 1);
+		val <<= 1;
+		val += 2;
+		o += ((CEIL(rsz, 1024)) << 1);
+		h1 = val;
+	}
+	h2 = output_width - h1;
+	/* phi */
+	val = (h1 * rsz) - (((input_width >> 1) - o) << 8);
+	/* skip */
+	val1 = ((val - 1024) >> 9) << 1;
+	param->f_div.num_passes = IPIPE_MAX_PASSES;
+	param->f_div.pass[0].o_hsz = h1 - 1;
+	param->f_div.pass[0].i_hps = 0;
+	param->f_div.pass[0].h_phs = 0;
+	param->f_div.pass[0].src_hps = 0;
+	param->f_div.pass[0].src_hsz = (input_width >> 2) + o;
+	param->f_div.pass[1].o_hsz = h2 - 1;
+	param->f_div.pass[1].i_hps = val1;
+	param->f_div.pass[1].h_phs = (val - (val1 << 8));
+	param->f_div.pass[1].src_hps = (input_width >> 2) - o;
+	param->f_div.pass[1].src_hsz = (input_width >> 2) + o;
+
+	return 0;
+}
+
+/* function: calculate_down_scale_f_div_param
+ * Algorithm to calculate the frame division parameters for resizer in
+ * downscale mode. Please refer the application note in DM360 functional
+ * spec for details of the algorithm
+ */
+static int calculate_down_scale_f_div_param(struct device *dev,
+					    int input_width,
+					    int output_width,
+					    struct ipipe_rsz_rescale_param
+					    *param)
+{
+	/* rsz = R, input_width = H, output width = h in the equation */
+	unsigned int two_power;
+	unsigned int upper_h1;
+	unsigned int upper_h2;
+	unsigned int val1;
+	unsigned int val;
+	unsigned int rsz;
+	unsigned int h1;
+	unsigned int h2;
+	unsigned int o;
+	unsigned int n;
+
+	upper_h1 = input_width >> 1;
+	n = param->h_dscale_ave_sz;
+	/* 2 ^ (scale+1) */
+	two_power = 1 << (n + 1);
+	upper_h1 = (upper_h1 >> (n + 1)) << (n + 1);
+	upper_h2 = input_width - upper_h1;
+	if (upper_h2 % two_power) {
+		dev_err(dev, "frame halves to be a multiple of 2 power n+1\n");
+		return -EINVAL;
+	}
+	two_power = 1 << n;
+	rsz = (input_width << 8) / output_width;
+	val = rsz * two_power;
+	val = ((upper_h1 << 8) / val) + 1;
+	if (!(val % 2))
+		h1 = val;
+	else {
+		val = (upper_h1 << 8);
+		val >>= (n + 1);
+		val -= (rsz >> 1);
+		val /= (rsz << 1);
+		val <<= 1;
+		val += 2;
+		h1 = val;
+	}
+	o = 10 + (two_power << 2);
+	if (((input_width << 7) / rsz) % 2)
+		o += (((CEIL(rsz, 1024)) << 1) << n);
+	h2 = output_width - h1;
+	/* phi */
+	val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8);
+	/* skip */
+	val1 = ((val - 1024) >> 9) << 1;
+	param->f_div.num_passes = IPIPE_MAX_PASSES;
+	param->f_div.pass[0].o_hsz = h1 - 1;
+	param->f_div.pass[0].i_hps = 0;
+	param->f_div.pass[0].h_phs = 0;
+	param->f_div.pass[0].src_hps = 0;
+	param->f_div.pass[0].src_hsz = upper_h1 + o;
+	param->f_div.pass[1].o_hsz = h2 - 1;
+	param->f_div.pass[1].i_hps = 10 + (val1 * two_power);
+	param->f_div.pass[1].h_phs = (val - (val1 << 8));
+	param->f_div.pass[1].src_hps = (upper_h1 - o);
+	param->f_div.pass[1].src_hsz = (upper_h2 + o);
+
+	return 0;
+}
+
+/* update the parameter in param for a given input and output width */
+static int update_preview_f_div_params(struct device *dev,
+				       int input_width,
+				       int output_width,
+				       struct ipipe_rsz_rescale_param *param)
+{
+	unsigned int val;
+
+	val = input_width >> 1;
+	if (val < 8) {
+		dev_err(dev, "input width must me atleast 16 pixels\n");
+		return -EINVAL;
+	}
+	param->f_div.en = 1;
+	param->f_div.num_passes = IPIPE_MAX_PASSES;
+	param->f_div.pass[0].o_hsz = val;
+	param->f_div.pass[0].i_hps = 0;
+	param->f_div.pass[0].h_phs = 0;
+	param->f_div.pass[0].src_hps = 0;
+	param->f_div.pass[0].src_hsz = val + 10;
+	param->f_div.pass[1].o_hsz = val;
+	param->f_div.pass[1].i_hps = 0;
+	param->f_div.pass[1].h_phs = 0;
+	param->f_div.pass[1].src_hps = val - 8;
+	param->f_div.pass[1].src_hsz = val + 10;
+
+	return 0;
+}
+
+/* Use shared to allocate exclusive blocks as required
+ * by resize applications in single shot mode
+ */
+static void *ipipe_alloc_config_block(struct device *dev)
+{
+	/* return common data block */
+	mutex_lock(&oper_state.lock);
+	if (oper_state.resource_in_use) {
+		dev_err(dev, "resource in use\n");
+		mutex_unlock(&oper_state.lock);
+		return NULL;
+	}
+	mutex_unlock(&oper_state.lock);
+
+	return oper_state.shared_config_param;
+}
+
+/* Used to free only non-shared config block allocated through
+ * imp_alloc_config_block
+ */
+static void ipipe_dealloc_config_block(struct device *dev, void *config_block)
+{
+	if (config_block) {
+		if (config_block != oper_state.shared_config_param)
+			kfree(config_block);
+		else
+			dev_err(dev, "Trying to free shared config block\n");
+	}
+}
+
+static void ipipe_dealloc_user_config_block(struct device *dev,
+					    void *config_block)
+{
+	kfree(config_block);
+}
+
+static void *ipipe_alloc_user_config_block(struct device *dev,
+					   enum imp_log_chan_t chan_type,
+					   int *len)
+{
+	void *config = NULL;
+
+	if (oper_mode == IMP_MODE_SINGLE_SHOT) {
+		if (chan_type == IMP_PREVIEWER) {
+			config =
+			    kmalloc(sizeof(struct prev_single_shot_config),
+				    GFP_KERNEL);
+			*len = sizeof(struct prev_single_shot_config);
+		} else if (chan_type == IMP_RESIZER) {
+			config =
+			    kmalloc(sizeof(struct rsz_single_shot_config),
+				    GFP_KERNEL);
+			*len = sizeof(struct rsz_single_shot_config);
+		}
+
+	} else {
+		if (chan_type == IMP_PREVIEWER) {
+			config =
+			    kmalloc(sizeof(struct prev_continuous_config),
+				    GFP_KERNEL);
+			*len = sizeof(struct prev_continuous_config);
+		} else if (chan_type == IMP_RESIZER) {
+			config =
+			    kmalloc(sizeof(struct rsz_continuous_config),
+				    GFP_KERNEL);
+			*len = sizeof(struct rsz_continuous_config);
+		}
+	}
+
+	return config;
+}
+
+static void ipipe_set_user_config_defaults(struct device *dev,
+					   enum imp_log_chan_t chan_type,
+					   void *config)
+{
+	dev_dbg(dev, "ipipe_set_user_config_defaults\n");
+
+	if (oper_mode == IMP_MODE_SINGLE_SHOT) {
+		if (chan_type == IMP_PREVIEWER) {
+			dev_dbg(dev, "SS-Preview\n");
+			/* preview channel in single shot mode */
+			memcpy(config,
+			       (void *)&dm365_prev_ss_config_defs,
+			       sizeof(struct prev_single_shot_config));
+		} else {
+			dev_dbg(dev, "SS-Resize\n");
+			/* resizer channel in single shot mode */
+			memcpy(config,
+			       (void *)&dm365_rsz_ss_config_defs,
+			       sizeof(struct rsz_single_shot_config));
+		}
+	} else if (oper_mode == IMP_MODE_CONTINUOUS) {
+		/* Continuous mode */
+		if (chan_type == IMP_PREVIEWER) {
+			dev_dbg(dev, "Cont Preview\n");
+			/* previewer defaults */
+			memcpy(config,
+			       (void *)&dm365_prev_cont_config_defs,
+			       sizeof(struct prev_continuous_config));
+		} else {
+			dev_dbg(dev, "Cont resize\n");
+			/* resizer defaults */
+			memcpy(config,
+			       (void *)&dm365_rsz_cont_config_defs,
+			       sizeof(struct rsz_continuous_config));
+		}
+	} else
+		dev_err(dev, "Incorrect mode used\n");
+}
+
+/* function :calculate_sdram_offsets()
+ *	This function calculates the offsets from start of buffer for the C
+ *	plane when output format is YUV420SP. It also calculates the offsets
+ *	from the start of the buffer when the image is flipped vertically
+ *	or horizontally for ycbcr/y/c planes
+ */
+static int calculate_sdram_offsets(struct ipipe_params *param, int index)
+{
+	int bytesperline = 2;
+	int image_height;
+	int image_width;
+	int yuv_420;
+	int offset;
+
+	if (!param->rsz_en[index])
+		return -EINVAL;
+
+	image_height = param->rsz_rsc_param[index].o_vsz + 1;
+	image_width = param->rsz_rsc_param[index].o_hsz + 1;
+	param->ext_mem_param[index].c_offset = 0;
+	param->ext_mem_param[index].flip_ofst_y = 0;
+	param->ext_mem_param[index].flip_ofst_c = 0;
+	if ((param->ipipe_dpaths_fmt != IPIPE_RAW2RAW) &&
+	    (param->ipipe_dpaths_fmt != IPIPE_RAW2BOX) &&
+	    param->rsz_rsc_param[index].cen &&
+	    param->rsz_rsc_param[index].yen) {
+		/* YUV 420 */
+		yuv_420 = 1;
+		bytesperline = 1;
+	}
+
+	/* set offset value */
+	offset = 0;
+
+	if (param->rsz_rsc_param[index].h_flip)
+		/* width * bytesperline - 1 */
+		offset = (image_width * bytesperline) - 1;
+	if (param->rsz_rsc_param[index].v_flip)
+		offset += (image_height - 1) *
+			param->ext_mem_param[index].rsz_sdr_oft_y;
+	param->ext_mem_param[index].flip_ofst_y = offset;
+	if (yuv_420) {
+		offset = 0;
+		/* half height for c-plane */
+		if (param->rsz_rsc_param[index].h_flip)
+			/* width * bytesperline - 1 */
+			offset = image_width - 1;
+		if (param->rsz_rsc_param[index].v_flip)
+			offset += (((image_height >> 1) - 1) *
+			param->ext_mem_param[index].
+			rsz_sdr_oft_c);
+		param->ext_mem_param[index].flip_ofst_c =
+			offset;
+		param->ext_mem_param[index].c_offset =
+		    param->ext_mem_param[index].
+		    rsz_sdr_oft_y * image_height;
+	}
+
+	return 0;
+}
+
+static void enable_422_420_conversion(struct ipipe_params *param,
+				      int index, enum enable_disable_t en)
+{
+	/* Enable 422 to 420 conversion */
+	param->rsz_rsc_param[index].cen = en;
+	param->rsz_rsc_param[index].yen = en;
+}
+
+static void configure_resizer_out_params(struct ipipe_params *param,
+					int index,
+					void *output_spec,
+					unsigned char partial, unsigned flag)
+{
+	if (partial) {
+		struct rsz_part_output_spec *partial_output =
+		    (struct rsz_part_output_spec *)output_spec;
+		if (partial_output->enable) {
+			param->rsz_en[index] = ENABLE;
+			param->rsz_rsc_param[index].h_flip =
+			    partial_output->h_flip;
+			param->rsz_rsc_param[index].v_flip =
+			    partial_output->v_flip;
+			param->rsz_rsc_param[index].v_typ_y =
+			    partial_output->v_typ_y;
+			param->rsz_rsc_param[index].v_typ_c =
+			    partial_output->v_typ_c;
+			param->rsz_rsc_param[index].v_lpf_int_y =
+			    partial_output->v_lpf_int_y;
+			param->rsz_rsc_param[index].v_lpf_int_c =
+			    partial_output->v_lpf_int_c;
+			param->rsz_rsc_param[index].h_typ_y =
+			    partial_output->h_typ_y;
+			param->rsz_rsc_param[index].h_typ_c =
+			    partial_output->h_typ_c;
+			param->rsz_rsc_param[index].h_lpf_int_y =
+			    partial_output->h_lpf_int_y;
+			param->rsz_rsc_param[index].h_lpf_int_c =
+			    partial_output->h_lpf_int_c;
+			param->rsz_rsc_param[index].dscale_en =
+			    partial_output->en_down_scale;
+			param->rsz_rsc_param[index].h_dscale_ave_sz =
+			    partial_output->h_dscale_ave_sz;
+			param->rsz_rsc_param[index].v_dscale_ave_sz =
+			    partial_output->v_dscale_ave_sz;
+			param->ext_mem_param[index].user_y_ofst =
+			    (partial_output->user_y_ofst + 31) & ~0x1F;
+			param->ext_mem_param[index].user_c_ofst =
+			    (partial_output->user_c_ofst + 31) & ~0x1F;
+
+		} else
+			param->rsz_en[index] = DISABLE;
+
+	} else {
+		struct rsz_output_spec *output =
+		    (struct rsz_output_spec *)output_spec;
+		if (output->enable) {
+			param->rsz_en[index] = ENABLE;
+			param->rsz_rsc_param[index].o_vsz = output->height - 1;
+			param->rsz_rsc_param[index].o_hsz = output->width - 1;
+			param->ext_mem_param[index].rsz_sdr_ptr_s_y =
+			    output->vst_y;
+			param->ext_mem_param[index].rsz_sdr_ptr_e_y =
+			    output->height;
+			param->ext_mem_param[index].rsz_sdr_ptr_s_c =
+			    output->vst_c;
+			param->ext_mem_param[index].rsz_sdr_ptr_e_c =
+			    output->height;
+
+			if (flag) {
+				/* update common parameters */
+				param->rsz_rsc_param[index].h_flip =
+				    output->h_flip;
+				param->rsz_rsc_param[index].v_flip =
+				    output->v_flip;
+				param->rsz_rsc_param[index].v_typ_y =
+				    output->v_typ_y;
+				param->rsz_rsc_param[index].v_typ_c =
+				    output->v_typ_c;
+				param->rsz_rsc_param[index].v_lpf_int_y =
+				    output->v_lpf_int_y;
+				param->rsz_rsc_param[index].v_lpf_int_c =
+				    output->v_lpf_int_c;
+				param->rsz_rsc_param[index].h_typ_y =
+				    output->h_typ_y;
+				param->rsz_rsc_param[index].h_typ_c =
+				    output->h_typ_c;
+				param->rsz_rsc_param[index].h_lpf_int_y =
+				    output->h_lpf_int_y;
+				param->rsz_rsc_param[index].h_lpf_int_c =
+				    output->h_lpf_int_c;
+				param->rsz_rsc_param[index].dscale_en =
+				    output->en_down_scale;
+				param->rsz_rsc_param[index].h_dscale_ave_sz =
+				    output->h_dscale_ave_sz;
+				param->rsz_rsc_param[index].v_dscale_ave_sz =
+				    output->h_dscale_ave_sz;
+				param->ext_mem_param[index].user_y_ofst =
+				    (output->user_y_ofst + 31) & ~0x1F;
+				param->ext_mem_param[index].user_c_ofst =
+				    (output->user_c_ofst + 31) & ~0x1F;
+			}
+		} else
+			param->rsz_en[index] = DISABLE;
+	}
+
+}
+
+/* function :calculate_line_length()
+ *	This function calculates the line length of various image
+ *	planes at the input and output
+ */
+static void calculate_line_length(enum ipipe_pix_formats pix,
+				 int width,
+				 int height, int *line_len, int *line_len_c)
+{
+	*line_len = 0;
+	*line_len_c = 0;
+
+	if ((pix == IPIPE_UYVY) || (pix == IPIPE_BAYER))
+		*line_len = width << 1;
+	else if (pix == IPIPE_420SP_Y || pix == IPIPE_420SP_C) {
+		*line_len = width;
+		*line_len_c = width;
+	} else {
+		/* YUV 420 */
+		/* round width to upper 32 byte boundary */
+		*line_len = width;
+		*line_len_c = width;
+	}
+	/* adjust the line len to be a multiple of 32 */
+	*line_len += 31;
+	*line_len &= ~0x1f;
+	*line_len_c += 31;
+	*line_len_c &= ~0x1f;
+}
+
+static inline int rsz_validate_input_image_format(struct device *dev,
+						  enum ipipe_pix_formats pix,
+						  int width,
+						  int height, int *line_len)
+{
+	int val;
+
+	if (pix != IPIPE_UYVY && pix != IPIPE_420SP_Y &&
+		pix != IPIPE_420SP_C) {
+		dev_err(dev,
+			"rsz_validate_out_pix_formats"
+			"pix format not supported, %d\n", pix);
+		return -EINVAL;
+	}
+
+	if (width == 0 || height == 0) {
+		dev_err(dev, "validate_line_length: invalid "
+				"width or height\n");
+		return -EINVAL;
+	}
+
+	if (pix == IPIPE_420SP_C)
+		calculate_line_length(pix,
+				      width,
+				      height,
+				      &val,
+				      line_len);
+	else
+		calculate_line_length(pix,
+				      width,
+				      height,
+				      line_len,
+				      &val);
+
+	return 0;
+}
+
+static inline int rsz_validate_output_image_format(struct device *dev,
+						   enum ipipe_pix_formats pix,
+						   int width,
+						   int height,
+						   int *in_line_len,
+						   int *in_line_len_c)
+{
+	if (pix != IPIPE_UYVY && pix != IPIPE_420SP_Y &&
+		pix != IPIPE_420SP_C && pix != IPIPE_YUV420SP &&
+		pix != IPIPE_BAYER) {
+		dev_err(dev,
+			"rsz_validate_out_pix_formats"
+			"pix format not supported, %d\n", pix);
+		return -EINVAL;
+	}
+
+	if (width == 0 || height == 0) {
+		dev_err(dev, "validate_line_length: invalid"
+				" width or height\n");
+		return -EINVAL;
+	}
+
+	calculate_line_length(pix,
+			      width,
+			      height, in_line_len, in_line_len_c);
+	return 0;
+}
+
+static void configure_common_rsz_params(struct device *dev,
+			struct ipipe_params *param,
+			struct rsz_single_shot_config *ss_config)
+{
+	param->rsz_common.yuv_y_min = ss_config->yuv_y_min;
+	param->rsz_common.yuv_y_max = ss_config->yuv_y_max;
+	param->rsz_common.yuv_c_min = ss_config->yuv_c_min;
+	param->rsz_common.yuv_c_max = ss_config->yuv_c_max;
+	param->rsz_common.out_chr_pos = ss_config->out_chr_pos;
+	param->rsz_common.rsz_seq_crv = ss_config->chroma_sample_even;
+
+}
+
+static int configure_common_rsz_in_params(struct device *dev,
+					  struct ipipe_params *param,
+					  int flag, int rsz_chained,
+					  void *input_spec)
+{
+	enum ipipe_pix_formats pix;
+
+	if (!flag) {
+		struct prev_ss_input_spec *in_specs =
+		    (struct prev_ss_input_spec *)input_spec;
+		param->rsz_common.vsz = in_specs->image_height - 1;
+		param->rsz_common.hsz = in_specs->image_width - 1;
+		pix = in_specs->pix_fmt;
+	} else {
+		struct rsz_ss_input_spec *in_specs =
+		    (struct rsz_ss_input_spec *)input_spec;
+		if (!rsz_chained) {
+			param->rsz_common.vps = in_specs->vst;
+			param->rsz_common.hps = in_specs->hst;
+		}
+		param->rsz_common.vsz = in_specs->image_height - 1;
+		param->rsz_common.hsz = in_specs->image_width - 1;
+		pix = in_specs->pix_fmt;
+	}
+	switch (pix) {
+	case IPIPE_BAYER_8BIT_PACK:
+	case IPIPE_BAYER_8BIT_PACK_ALAW:
+	case IPIPE_BAYER_8BIT_PACK_DPCM:
+	case IPIPE_BAYER_12BIT_PACK:
+	case IPIPE_BAYER:
+		param->rsz_common.src_img_fmt = RSZ_IMG_422;
+		param->rsz_common.source = IPIPE_DATA;
+		break;
+	case IPIPE_UYVY:
+		param->rsz_common.src_img_fmt = RSZ_IMG_422;
+		if (rsz_chained)
+			param->rsz_common.source = IPIPE_DATA;
+		else
+			param->rsz_common.source = IPIPEIF_DATA;
+		param->rsz_common.raw_flip = 0;
+		break;
+	case IPIPE_420SP_Y:
+		param->rsz_common.src_img_fmt = RSZ_IMG_420;
+		/* Select y */
+		param->rsz_common.y_c = 0;
+		param->rsz_common.source = IPIPEIF_DATA;
+		param->rsz_common.raw_flip = 0;
+		break;
+	case IPIPE_420SP_C:
+		param->rsz_common.src_img_fmt = RSZ_IMG_420;
+		/* Select y */
+		param->rsz_common.y_c = 1;
+		param->rsz_common.source = IPIPEIF_DATA;
+		param->rsz_common.raw_flip = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int validate_ipipeif_decimation(struct device *dev,
+				       enum ipipeif_decimation dec_en,
+				       unsigned char rsz,
+				       unsigned char frame_div_mode_en,
+				       int width)
+{
+	if (dec_en && frame_div_mode_en) {
+		dev_err(dev,
+			"Both dec_en & frame_div_mode_en"
+			"can not enabled simultaneously\n");
+		return -EINVAL;
+	}
+	if (frame_div_mode_en) {
+		dev_err(dev, "frame_div_mode mode not supported");
+		return -EINVAL;
+	}
+	if (dec_en) {
+		if (width <= IPIPE_MAX_INPUT_WIDTH) {
+			dev_err(dev,
+				"image width to be more than"
+				" %d for decimation\n", IPIPE_MAX_INPUT_WIDTH);
+			return -EINVAL;
+		}
+		if ((rsz < IPIPEIF_RSZ_MIN) || (rsz > IPIPEIF_RSZ_MAX)) {
+			dev_err(dev, "rsz range is %d to %d\n",
+				IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int configure_resizer_in_ss_mode(struct device *dev,
+					void *user_config,
+					int resizer_chained,
+					struct ipipe_params *param)
+{
+	/* resizer in standalone mode. In this mode if serializer
+	 * is enabled, we need to set config params in the hw.
+	 */
+	struct rsz_single_shot_config *ss_config =
+	    (struct rsz_single_shot_config *)user_config;
+	int line_len_c;
+	int line_len;
+	int ret;
+
+	ret = rsz_validate_input_image_format(dev,
+					      ss_config->input.pix_fmt,
+					      ss_config->input.image_width,
+					      ss_config->input.image_height,
+					      &line_len);
+
+	if (ret)
+		return -EINVAL;
+
+	/* shared block */
+	if ((!ss_config->output1.enable) && (!ss_config->output2.enable)) {
+		dev_err(dev, "One of the resizer output must be enabled\n");
+		return -EINVAL;
+	}
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	if (!ss_config->input.line_length)
+		param->ipipeif_param.adofs = line_len;
+	else {
+		param->ipipeif_param.adofs = ss_config->input.line_length;
+		param->ipipeif_param.adofs =
+				(param->ipipeif_param.adofs + 31) & ~0x1f;
+	}
+	if (ss_config->output1.enable) {
+		param->rsz_en[RSZ_A] = ENABLE;
+		param->rsz_rsc_param[RSZ_A].mode = IPIPEIF_ONE_SHOT;
+		ret = rsz_validate_output_image_format(dev,
+					ss_config->output1.pix_fmt,
+					ss_config->output1.width,
+					ss_config->output1.height,
+					&line_len, &line_len_c);
+		if (ret) {
+			mutex_unlock(&oper_state.lock);
+			return ret;
+		}
+		param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
+		param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c;
+		configure_resizer_out_params(param,
+						   RSZ_A,
+						   &ss_config->output1,
+						   0,
+						   1);
+
+		if (ss_config->output1.pix_fmt == IMP_BAYER)
+			param->rsz_common.raw_flip = 1;
+		else
+			param->rsz_common.raw_flip = 0;
+
+		if (ss_config->output1.pix_fmt == IPIPE_YUV420SP)
+			enable_422_420_conversion(param, RSZ_A, ENABLE);
+		else
+			enable_422_420_conversion(param, RSZ_A,
+							  DISABLE);
+	}
+
+	if (ss_config->output2.enable) {
+		param->rsz_en[RSZ_A] = ENABLE;
+		param->rsz_rsc_param[RSZ_B].mode = IPIPEIF_ONE_SHOT;
+		ret = rsz_validate_output_image_format(dev,
+					ss_config->output2.pix_fmt,
+					ss_config->output2.width,
+					ss_config->output2.height,
+					&line_len, &line_len_c);
+		if (ret) {
+			mutex_unlock(&oper_state.lock);
+			return ret;
+		}
+		param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
+		param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
+		configure_resizer_out_params(param,
+						   RSZ_B,
+						   &ss_config->output2,
+						   0,
+						   1);
+		if (ss_config->output2.pix_fmt == IPIPE_YUV420SP)
+			enable_422_420_conversion(param, RSZ_B, ENABLE);
+		else
+			enable_422_420_conversion(param,
+						  RSZ_B,
+						  DISABLE);
+	}
+	configure_common_rsz_params(dev, param, ss_config);
+	if (resizer_chained) {
+		oper_state.rsz_chained = 1;
+		oper_state.rsz_config_state = STATE_CONFIGURED;
+	} else {
+		oper_state.rsz_chained = 0;
+		ret = validate_ipipeif_decimation(dev,
+						  ss_config->input.dec_en,
+						  ss_config->input.rsz,
+						  ss_config->input.
+						  frame_div_mode_en,
+						  ss_config->input.
+						  image_width);
+		if (ret) {
+			mutex_unlock(&oper_state.lock);
+			return ret;
+		}
+
+		if (ipipe_process_pix_fmts(ss_config->input.pix_fmt,
+				   ss_config->output1.pix_fmt,
+				   param) < 0) {
+			dev_err(dev, "error in input or output pix format\n");
+			mutex_unlock(&oper_state.lock);
+			return -EINVAL;
+		}
+
+		param->ipipeif_param.source = IPIPEIF_SDRAM_YUV;
+		param->ipipeif_param.glob_hor_size = ss_config->input.ppln;
+		param->ipipeif_param.glob_ver_size = ss_config->input.lpfr;
+		param->ipipeif_param.hnum = ss_config->input.image_width;
+		param->ipipeif_param.vnum = ss_config->input.image_height;
+		param->ipipeif_param.var.if_5_1.clk_div =
+		    ss_config->input.clk_div;
+		if (ss_config->input.dec_en) {
+			param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
+			param->ipipeif_param.rsz = ss_config->input.rsz;
+			param->ipipeif_param.avg_filter =
+			    (enum ipipeif_avg_filter)ss_config->input.
+			    avg_filter_en;
+			param->ipipe_hsz =
+			    (((ss_config->input.image_width *
+			       IPIPEIF_RSZ_CONST) / ss_config->input.rsz) - 1);
+		}
+		if (ss_config->input.pix_fmt == IPIPE_420SP_Y ||
+		  ss_config->input.pix_fmt == IPIPE_420SP_C) {
+			param->ipipeif_param.var.if_5_1.pack_mode
+				= IPIPEIF_5_1_PACK_8_BIT;
+			param->ipipeif_param.var.if_5_1.source1 = IPIPEIF_CCDC;
+			param->ipipeif_param.var.if_5_1.isif_port.if_type
+				= V4L2_MBUS_FMT_YUYV8_1X16;
+			param->ipipeif_param.var.if_5_1.data_shift
+				= IPIPEIF_5_1_BITS11_0;
+
+			param->ipipeif_param.source = IPIPEIF_SDRAM_RAW;
+
+
+		}
+		if (ss_config->input.pix_fmt == IPIPE_420SP_C)
+			param->ipipeif_param.var.if_5_1.isif_port.if_type
+				= V4L2_MBUS_FMT_SBGGR10_1X10;
+		param->ipipe_hsz = ss_config->input.image_width - 1;
+		param->ipipe_vsz = ss_config->input.image_height - 1;
+		param->ipipe_vps = ss_config->input.vst;
+		param->ipipe_hps = ss_config->input.hst;
+		param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
+		configure_common_rsz_in_params(dev, param, 1, resizer_chained,
+					       &ss_config->input);
+		if (param->rsz_en[RSZ_A]) {
+
+			calculate_resize_ratios(param, RSZ_A);
+			calculate_sdram_offsets(param, RSZ_A);
+
+			/* Overriding resize ratio calculation */
+			if (ss_config->input.pix_fmt == IPIPE_420SP_C) {
+				param->rsz_rsc_param[RSZ_A].v_dif =
+				    (((param->ipipe_vsz + 1) * 2) * 256) /
+				    (param->rsz_rsc_param[RSZ_A].o_vsz + 1);
+			}
+		}
+
+		if (param->rsz_en[RSZ_B]) {
+			calculate_resize_ratios(param, RSZ_B);
+			calculate_sdram_offsets(param, RSZ_B);
+
+			/* Overriding resize ratio calculation */
+			if (ss_config->input.pix_fmt == IPIPE_420SP_C) {
+				param->rsz_rsc_param[RSZ_B].v_dif =
+				    (((param->ipipe_vsz + 1) * 2) * 256) /
+				    (param->rsz_rsc_param[RSZ_B].o_vsz + 1);
+			}
+		}
+	}
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int configure_resizer_in_cont_mode(struct device *dev,
+					  void *user_config,
+					  int resizer_chained,
+					  struct ipipe_params *param)
+{
+	/* Continuous mode. This is a shared config block */
+	struct rsz_continuous_config *cont_config =
+	    (struct rsz_continuous_config *)user_config;
+	int line_len_c;
+	int line_len;
+	int ret;
+
+	if (!resizer_chained) {
+		dev_err(dev, "Resizer cannot be configured in standalone"
+			"for continuous mode\n");
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	if (!cont_config->output1.enable) {
+		dev_err(dev, "enable resizer - 0\n");
+		mutex_unlock(&oper_state.lock);
+		return -EINVAL;
+	}
+	param->rsz_en[RSZ_A] = ENABLE;
+	param->rsz_rsc_param[RSZ_A].mode = IPIPEIF_CONTINUOUS;
+	configure_resizer_out_params(param,
+				     RSZ_A,
+				     &cont_config->output1,
+				     1,
+				     0);
+	param->rsz_en[RSZ_B] = DISABLE;
+
+	if (cont_config->output2.enable) {
+		param->rsz_rsc_param[RSZ_B].mode = IPIPEIF_CONTINUOUS;
+		ret = rsz_validate_output_image_format(dev,
+						       cont_config->output2.
+						       pix_fmt,
+						       cont_config->output2.
+						       width,
+						       cont_config->output2.
+						       height,
+						       &line_len,
+						       &line_len_c);
+		if (ret) {
+			mutex_unlock(&oper_state.lock);
+			return ret;
+		}
+		param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
+		param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
+		configure_resizer_out_params(param,
+					     RSZ_B,
+					     &cont_config->output2,
+					     0,
+					     1);
+		if (cont_config->output2.pix_fmt == IPIPE_YUV420SP)
+			enable_422_420_conversion(param,
+						  RSZ_B, ENABLE);
+		else
+			enable_422_420_conversion(param,
+						  RSZ_B, DISABLE);
+	}
+	oper_state.rsz_chained = 1;
+	oper_state.rsz_config_state = STATE_CONFIGURED;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+static int ipipe_set_resize_config(struct device *dev,
+				   int resizer_chained,
+				   void *user_config, void *config)
+{
+	struct ipipe_params *param = (struct ipipe_params *)config;
+	int ret;
+
+	dev_dbg(dev, "ipipe_set_resize_config, resizer_chained = %d\n",
+		resizer_chained);
+	if ((ISNULL(user_config)) || (ISNULL(config))) {
+		dev_err(dev, "Invalid user_config or config ptr\n");
+		return -EINVAL;
+	}
+
+	memcpy((void *)config,
+	       (void *)&dm365_ipipe_defs,
+	       sizeof(struct ipipe_params));
+
+	if (oper_mode != IMP_MODE_SINGLE_SHOT)
+		return configure_resizer_in_cont_mode(dev,
+						      user_config,
+						      resizer_chained,
+						      param);
+
+	ret = configure_resizer_in_ss_mode(dev,
+					    user_config,
+					    resizer_chained,
+					    param);
+	if (!ret && (!en_serializer && !resizer_chained))
+		ret = ipipe_hw_setup(config);
+
+	return ret;
+}
+
+static void configure_resize_passthru(struct ipipe_params *param, int bypass)
+{
+	param->rsz_rsc_param[RSZ_A].cen = DISABLE;
+	param->rsz_rsc_param[RSZ_A].yen = DISABLE;
+	param->rsz_rsc_param[RSZ_A].v_phs_y = 0;
+	param->rsz_rsc_param[RSZ_A].v_phs_c = 0;
+	param->rsz_rsc_param[RSZ_A].v_dif = 256;
+	param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0;
+	param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0;
+	param->rsz_rsc_param[RSZ_A].h_phs = 0;
+	param->rsz_rsc_param[RSZ_A].h_dif = 256;
+	param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0;
+	param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0;
+	param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE;
+	param->rsz2rgb[RSZ_A].rgb_en = DISABLE;
+	param->rsz_en[RSZ_A] = ENABLE;
+	param->rsz_en[RSZ_B] = DISABLE;
+	if (bypass) {
+		param->rsz_rsc_param[RSZ_A].i_vps = 0;
+		param->rsz_rsc_param[RSZ_A].i_hps = 0;
+		/* Raw Bypass */
+		param->rsz_common.passthrough = IPIPE_BYPASS_ON;
+	}
+}
+
+static inline int prev_validate_output_image_format(struct device *dev,
+					enum ipipe_pix_formats pix,
+					int *line_len,
+					int in_width, int in_height)
+{
+	if (pix != IPIPE_UYVY && pix != IPIPE_BAYER) {
+		dev_err(dev,
+			"prev_validate_output_image_format"
+			"pix format not supported, %d\n", pix);
+		return -EINVAL;
+	}
+
+	if ((in_width == 0) || (in_height == 0)) {
+		dev_err(dev,
+			"prev_validate_output_image_format:"
+			" invalid width or height\n");
+		return -EINVAL;
+	}
+
+	*line_len = in_width * 2;
+
+	/* Adjust line length to be a multiple of 32 */
+	*line_len += 31;
+	*line_len &= ~0x1f;
+
+	return 0;
+}
+
+static inline int validate_preview_input_spec(struct device *dev,
+					      enum ipipe_pix_formats pix,
+					      int width,
+					      int height, int *line_len)
+{
+	if (pix != IPIPE_UYVY && pix != IPIPE_BAYER &&
+	  pix != IPIPE_BAYER_8BIT_PACK && pix != IPIPE_BAYER_8BIT_PACK_ALAW &&
+	  pix != IPIPE_BAYER_8BIT_PACK_DPCM &&
+	  pix != IPIPE_BAYER_12BIT_PACK) {
+		dev_err(dev,
+			"validate_preview_input_spec:"
+			"pix format not supported, %d\n", pix);
+		return -EINVAL;
+	}
+	if (width == 0 || height == 0) {
+		dev_err(dev,
+			"rsz_validate_out_image_formats: "
+			"invalid width or height\n");
+		return -EINVAL;
+	}
+
+	if (pix == IPIPE_UYVY || pix == IPIPE_BAYER)
+		*line_len = width * 2;
+	else if (pix == IPIPE_BAYER_8BIT_PACK ||
+		 pix == IPIPE_BAYER_8BIT_PACK_ALAW ||
+		 pix == IPIPE_BAYER_8BIT_PACK_DPCM)
+		*line_len = width;
+	else
+		/* 12 bit */
+		*line_len = width + (width >> 1);
+	/* Adjust line length to be a multiple of 32 */
+	*line_len += 31;
+	*line_len &= ~0x1f;
+
+	return 0;
+}
+
+static int configure_previewer_in_cont_mode(struct device *dev,
+					    void *user_config,
+					    struct ipipe_params *param)
+{
+	struct prev_continuous_config *cont_config =
+	    (struct prev_continuous_config *)user_config;
+	int ret;
+
+	if (cont_config->input.en_df_sub) {
+		dev_err(dev, "DF suV4L2_MBUS_FMT_SBGGR10_1X10btraction "
+				  "is not supported\n");
+		return -EINVAL;
+	}
+	if (cont_config->input.dec_en && ((cont_config->input.rsz <
+		IPIPEIF_RSZ_MIN) || (cont_config->input.rsz >
+		IPIPEIF_RSZ_MAX))) {
+		dev_err(dev, "rsz range is %d to %d\n",
+			IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
+		return -EINVAL;
+	}
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	param->rsz_common.passthrough = cont_config->bypass;
+	param->ipipeif_param.source = IPIPEIF_CCDC;
+	param->ipipeif_param.clock_select = IPIPEIF_PIXCEL_CLK;
+	param->ipipeif_param.mode = IPIPEIF_CONTINUOUS;
+	if (cont_config->input.dec_en) {
+		param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
+		param->ipipeif_param.rsz = cont_config->input.rsz;
+		param->ipipeif_param.avg_filter =
+		    (enum ipipeif_avg_filter)cont_config->input.avg_filter_en;
+	}
+	/* IPIPE mode */
+	param->ipipe_mode = IPIPEIF_CONTINUOUS;
+	param->ipipe_colpat_olop = cont_config->input.colp_olop;
+	param->ipipe_colpat_olep = cont_config->input.colp_olep;
+	param->ipipe_colpat_elop = cont_config->input.colp_elop;
+	param->ipipe_colpat_elep = cont_config->input.colp_elep;
+	param->ipipeif_param.gain = cont_config->input.gain;
+	param->ipipeif_param.var.if_5_1.clip = cont_config->input.clip;
+	param->ipipeif_param.var.if_5_1.dpc = cont_config->input.dpc;
+	param->ipipeif_param.var.if_5_1.align_sync =
+	    cont_config->input.align_sync;
+	param->ipipeif_param.var.if_5_1.rsz_start =
+	    cont_config->input.rsz_start;
+	if (!oper_state.rsz_chained) {
+		param->rsz_rsc_param[0].mode = IPIPEIF_CONTINUOUS;
+		/* setup bypass resizer */
+		configure_resize_passthru(param, 0);
+	}
+	if (cont_config->bypass)
+		configure_resize_passthru(param, 1);
+	oper_state.prev_config_state = STATE_CONFIGURED;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int configure_previewer_in_ss_mode(struct device *dev,
+					  void *user_config,
+					  struct ipipe_params *param)
+{
+	struct prev_single_shot_config *ss_config =
+	    (struct prev_single_shot_config *)user_config;
+	int line_len;
+	int ret;
+
+	ret = validate_preview_input_spec(dev,
+					  ss_config->input.pix_fmt,
+					  ss_config->input.image_width,
+					  ss_config->input.image_height,
+					  &line_len);
+	if (ret)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+
+	if (!ss_config->input.line_length)
+		param->ipipeif_param.adofs = line_len;
+	else {
+		param->ipipeif_param.adofs = ss_config->input.line_length;
+		param->ipipeif_param.adofs =
+				(param->ipipeif_param.adofs + 31) & ~0x1f;
+	}
+	if (ss_config->input.dec_en && ss_config->input.frame_div_mode_en) {
+		dev_err(dev,
+			"Both dec_en & frame_div_mode_en"
+			"can not enabled simultaneously\n");
+		mutex_unlock(&oper_state.lock);
+		return -EINVAL;
+	}
+
+	ret = validate_ipipeif_decimation(dev,
+					  ss_config->input.dec_en,
+					  ss_config->input.rsz,
+					  ss_config->input.frame_div_mode_en,
+					  ss_config->input.image_width);
+	if (ret) {
+		mutex_unlock(&oper_state.lock);
+		return -EINVAL;
+	}
+
+	if (!oper_state.rsz_chained) {
+		ret = prev_validate_output_image_format(dev,
+							ss_config->output.
+							pix_fmt, &line_len,
+							ss_config->input.
+							image_width,
+							ss_config->input.
+							image_height);
+		if (ret) {
+			mutex_unlock(&oper_state.lock);
+			return -EINVAL;
+		}
+		param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
+		if (ss_config->input.frame_div_mode_en)
+			ret = update_preview_f_div_params(dev,
+					ss_config->input.
+					image_width,
+					ss_config->input.
+					image_width,
+					&param->
+					rsz_rsc_param[RSZ_A]);
+		if (ret) {
+			mutex_unlock(&oper_state.lock);
+			return -EINVAL;
+		}
+	} else {
+		if (ss_config->input.frame_div_mode_en &&
+		    param->rsz_en[RSZ_A]) {
+			if (!param->rsz_rsc_param[RSZ_A].dscale_en)
+				ret = calculate_normal_f_div_param(
+							dev,
+							ss_config->input.
+							  image_width,
+							param->rsz_rsc_param
+							  [RSZ_A].
+							  o_vsz + 1,
+							&param->rsz_rsc_param
+							  [RSZ_A]);
+			else
+				ret = calculate_down_scale_f_div_param(
+							dev,
+							ss_config->
+							input.image_width,
+							param->rsz_rsc_param
+							  [RSZ_A].o_vsz + 1,
+							&param->rsz_rsc_param
+							  [RSZ_A]);
+			if (ret) {
+				mutex_unlock(&oper_state.lock);
+				return -EINVAL;
+			}
+		}
+		if (ss_config->input.frame_div_mode_en &&
+		    param->rsz_en[RSZ_B]) {
+			if (!param->rsz_rsc_param[RSZ_B].dscale_en)
+				ret = calculate_normal_f_div_param(
+							dev,
+							ss_config->input.
+							   image_width,
+							param->rsz_rsc_param
+							   [RSZ_B].o_vsz + 1,
+							&param->rsz_rsc_param
+							   [RSZ_B]);
+			else
+				ret = calculate_down_scale_f_div_param(
+							dev,
+							ss_config->input.
+							   image_width,
+							param->rsz_rsc_param
+							   [RSZ_B].o_vsz + 1,
+							&param->rsz_rsc_param
+							   [RSZ_B]);
+			if (ret) {
+				mutex_unlock(&oper_state.lock);
+				return -EINVAL;
+			}
+		}
+	}
+	if (ipipe_process_pix_fmts(ss_config->input.pix_fmt,
+				   ss_config->output.pix_fmt,
+				   param) < 0) {
+		dev_err(dev, "error in input or output pix format\n");
+		mutex_unlock(&oper_state.lock);
+		return -EINVAL;
+	}
+	param->ipipeif_param.hnum = ss_config->input.image_width;
+	param->ipipeif_param.vnum = ss_config->input.image_height;
+	param->ipipeif_param.glob_hor_size = ss_config->input.ppln;
+	param->ipipeif_param.glob_ver_size = ss_config->input.lpfr;
+	param->ipipeif_param.var.if_5_1.clk_div = ss_config->input.clk_div;
+	param->ipipeif_param.var.if_5_1.pix_order = ss_config->input.pix_order;
+	param->ipipeif_param.var.if_5_1.align_sync =
+	    ss_config->input.align_sync;
+	param->ipipeif_param.var.if_5_1.rsz_start = ss_config->input.rsz_start;
+	if (param->ipipeif_param.var.if_5_1.dpcm.en) {
+		param->ipipeif_param.var.if_5_1.dpcm.pred =
+		    ss_config->input.pred;
+		param->ipipeif_param.var.if_5_1.dpcm.type =
+		IPIPEIF_DPCM_8BIT_12BIT;
+	}
+	param->ipipeif_param.var.if_5_1.data_shift =
+	    ss_config->input.data_shift;
+
+	param->ipipe_hsz = ss_config->input.image_width - 1;
+	if (ss_config->input.dec_en) {
+		if ((ss_config->input.rsz < IPIPEIF_RSZ_MIN) ||
+		    (ss_config->input.rsz > IPIPEIF_RSZ_MAX)) {
+			dev_err(dev, "rsz range is %d to %d\n",
+				IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
+			mutex_unlock(&oper_state.lock);
+			return -EINVAL;
+		}
+		param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
+		param->ipipeif_param.rsz = ss_config->input.rsz;
+		param->ipipeif_param.avg_filter =
+		    (enum ipipeif_avg_filter)ss_config->input.avg_filter_en;
+		param->ipipe_hsz =
+		    (((ss_config->input.image_width * IPIPEIF_RSZ_CONST) /
+		      ss_config->input.rsz) - 1);
+	}
+	param->ipipeif_param.gain = ss_config->input.gain;
+	param->ipipeif_param.var.if_5_1.clip = ss_config->input.clip;
+	param->ipipeif_param.var.if_5_1.dpc = ss_config->input.dpc;
+	param->ipipe_colpat_olop = ss_config->input.colp_olop;
+	param->ipipe_colpat_olep = ss_config->input.colp_olep;
+	param->ipipe_colpat_elop = ss_config->input.colp_elop;
+	param->ipipe_colpat_elep = ss_config->input.colp_elep;
+	param->ipipe_vps = ss_config->input.vst;
+	param->ipipe_hps = ss_config->input.hst;
+	param->ipipe_vsz = ss_config->input.image_height - 1;
+	if (ss_config->input.pix_fmt == IPIPE_UYVY)
+		param->ipipeif_param.source = IPIPEIF_SDRAM_YUV;
+	else
+		param->ipipeif_param.source = IPIPEIF_SDRAM_RAW;
+
+	configure_common_rsz_in_params(dev, param, 1, oper_state.rsz_chained,
+					       &ss_config->input);
+
+	param->rsz_common.passthrough = ss_config->bypass;
+	/* update the resize parameters */
+	if (ss_config->bypass == IPIPE_BYPASS_ON ||
+	    param->ipipe_dpaths_fmt == IPIPE_RAW2RAW)
+		/* Bypass resizer */
+		configure_resize_passthru(param, 1);
+	else {
+		if (oper_state.rsz_chained) {
+			if (param->rsz_en[RSZ_A]) {
+				calculate_resize_ratios(param, RSZ_A);
+				calculate_sdram_offsets(param, RSZ_A);
+			}
+			if (param->rsz_en[RSZ_B]) {
+				calculate_resize_ratios(param, RSZ_B);
+				calculate_sdram_offsets(param, RSZ_B);
+			}
+		} else {
+			struct rsz_output_spec *output_specs =
+				kmalloc(sizeof(struct rsz_output_spec),
+					GFP_KERNEL);
+			if (ISNULL(output_specs)) {
+				dev_err(dev, "Memory Alloc failure\n");
+				mutex_unlock(&oper_state.lock);
+				return -EINVAL;
+			}
+				/* Using resizer as pass through */
+			configure_resize_passthru(param, 0);
+			memset((void *)output_specs, 0,
+				sizeof(struct rsz_output_spec));
+			output_specs->enable = 1;
+			output_specs->pix_fmt = IPIPE_UYVY;
+			output_specs->width = ss_config->input.image_width;
+			output_specs->height = ss_config->input.image_height;
+			output_specs->vst_y = ss_config->input.vst;
+			configure_resizer_out_params(param, RSZ_A,
+				output_specs, 0, 0);
+			calculate_sdram_offsets(param, RSZ_A);
+			kfree(output_specs);
+		}
+	}
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int ipipe_reconfig_resizer(struct device *dev,
+				struct rsz_reconfig *reconfig,
+				void *config)
+{
+	struct ipipe_params *param = (struct ipipe_params *)config;
+
+	if (ISNULL(reconfig)) {
+		dev_err(dev, "Null User ptr received for reconfig");
+		return -EINVAL;
+	}
+
+	if ((reconfig->pix_format != IMP_420SP_Y) &&
+		(reconfig->pix_format != IMP_420SP_C)) {
+		dev_err(dev, "reconfig - pixel format incorrect");
+		return -EINVAL;
+	}
+	if (param->rsz_common.src_img_fmt != RSZ_IMG_420) {
+		dev_err(dev, "reconfig - source format originally"
+				"configured is not YUV420SP\n");
+		return -EINVAL;
+	}
+	if ((param->rsz_common.y_c) && (reconfig->pix_format == IMP_420SP_C)) {
+		dev_err(dev, "reconfig - channel is already configured"
+				"for YUV420SP - C data\n");
+		return -EINVAL;
+	}
+	if ((!param->rsz_common.y_c) &&
+		(reconfig->pix_format == IMP_420SP_Y)) {
+		dev_err(dev, "reconfig - channel is already configured"
+				"for YUV420SP - Y data\n");
+		return -EINVAL;
+	}
+	if (reconfig->pix_format == IMP_420SP_Y)
+		param->rsz_common.y_c = 0;
+	else
+		param->rsz_common.y_c = 1;
+	if (!en_serializer)
+		rsz_set_in_pix_format(param->rsz_common.y_c);
+
+	return 0;
+}
+
+static int ipipe_set_preview_config(struct device *dev,
+				    void *user_config, void *config)
+{
+	struct ipipe_params *param = (struct ipipe_params *)config;
+	int ret;
+
+	dev_err(dev, "ipipe_set_preview_config\n");
+
+	if ((ISNULL(user_config)) || (ISNULL(config))) {
+		dev_err(dev, "Invalid user_config or config ptr\n");
+		return -EINVAL;
+	}
+
+	if (!oper_state.rsz_chained) {
+		/* For chained resizer, defaults are set by resizer */
+		memcpy((void *)config,
+		       (void *)&dm365_ipipe_defs,
+		       sizeof(struct ipipe_params));
+	}
+
+	/* continuous mode */
+	if (oper_mode == IMP_MODE_CONTINUOUS)
+		return configure_previewer_in_cont_mode(dev, user_config,
+							param);
+
+	/* shared block */
+	/* previewer in standalone mode. In this mode if serializer
+	 * is enabled, we need to set config params for hw.
+	 */
+	ret = configure_previewer_in_ss_mode(dev, user_config, param);
+
+	if ((!ret) && !en_serializer)
+		ret = ipipe_hw_setup(config);
+
+	return ret;
+}
+
+static int ipipe_set_input_win(struct imp_window *win)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+	int ret;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	if (param->ipipeif_param.decimation) {
+		param->ipipe_hsz =
+		    ((win->width * IPIPEIF_RSZ_CONST) /
+		     param->ipipeif_param.rsz) - 1;
+	} else
+		param->ipipe_hsz = win->width - 1;
+	if (!oper_state.frame_format) {
+		param->ipipe_vsz = (win->height >> 1) - 1;
+		param->ipipe_vps = (win->vst >> 1);
+	} else {
+		param->ipipe_vsz = win->height - 1;
+		param->ipipe_vps = win->vst;
+	}
+	param->ipipe_hps = win->hst;
+	param->rsz_common.vsz = param->ipipe_vsz;
+	param->rsz_common.hsz = param->ipipe_hsz;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+static int ipipe_get_input_win(struct imp_window *win)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+	int ret;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	if (param->ipipeif_param.decimation)
+		win->width =
+		    (((param->ipipe_hsz + 1) * param->ipipeif_param.rsz) >> 4);
+	else
+		win->width = param->ipipe_hsz + 1;
+	if (!oper_state.frame_format) {
+		win->height = (param->ipipe_vsz + 1) << 1;
+		win->vst = (param->ipipe_vps << 1);
+	} else {
+		win->height = param->ipipe_vsz + 1;
+		win->vst = param->ipipe_vps;
+	}
+	win->hst = param->ipipe_hps;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int ipipe_set_in_pixel_format(enum imp_pix_formats pix_fmt)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+	int ret;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	oper_state.in_pixel_format = pix_fmt;
+	param->rsz_common.src_img_fmt = RSZ_IMG_422;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int ipipe_set_out_pixel_format(enum imp_pix_formats pix_fmt)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+	int err;
+
+	/* if image is RAW, preserve raw image format while flipping.
+	 * otherwise preserve, preserve ycbcr format while flipping
+	 */
+	if (pix_fmt == IMP_BAYER)
+		param->rsz_common.raw_flip = 1;
+	else
+		param->rsz_common.raw_flip = 0;
+
+	err = mutex_lock_interruptible(&oper_state.lock);
+	if (err)
+		return err;
+	oper_state.out_pixel_format = pix_fmt;
+	err = ipipe_process_pix_fmts(oper_state.in_pixel_format,
+				     oper_state.out_pixel_format,
+				     param);
+
+	mutex_unlock(&oper_state.lock);
+
+	return err;
+}
+
+static int ipipe_set_buftype(unsigned char buf_type)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	oper_state.buffer_type = buf_type;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int ipipe_set_frame_format(unsigned char frm_fmt)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	oper_state.frame_format = frm_fmt;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static int ipipe_set_output_win(struct imp_window *win)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+	struct rsz_output_spec output_specs;
+	int line_len_c;
+	int line_len;
+	int ret = -EINVAL;
+
+	if (!param->rsz_en[0]) {
+		printk(KERN_ERR "resizer output1 not enabled\n");
+		return ret;
+	}
+	output_specs.enable = 1;
+	output_specs.width = win->width;
+	/* Always set output height same as in height
+	   for de-interlacing
+	 */
+	output_specs.height = win->height;
+	output_specs.vst_y = win->vst;
+	if (oper_state.out_pixel_format == IPIPE_YUV420SP)
+		output_specs.vst_c = win->vst;
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	configure_resizer_out_params(param, RSZ_A, &output_specs, 0, 0);
+	calculate_line_length(oper_state.out_pixel_format,
+				     param->rsz_rsc_param[0].o_hsz + 1,
+				     param->rsz_rsc_param[0].o_vsz + 1,
+				     &line_len,
+				     &line_len_c);
+	param->ext_mem_param[0].rsz_sdr_oft_y = line_len;
+	param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c;
+	calculate_resize_ratios(param, RSZ_A);
+	if (param->rsz_en[RSZ_B])
+		calculate_resize_ratios(param, RSZ_B);
+	if (oper_state.out_pixel_format == IPIPE_YUV420SP)
+		enable_422_420_conversion(param, RSZ_A, ENABLE);
+	else
+		enable_422_420_conversion(param, RSZ_A, DISABLE);
+
+	ret = calculate_sdram_offsets(param, RSZ_A);
+	if (param->rsz_en[RSZ_B])
+		ret = calculate_sdram_offsets(param, RSZ_B);
+
+	if (ret)
+		printk(KERN_ERR "error in calculating sdram offsets\n");
+	mutex_unlock(&oper_state.lock);
+
+	return ret;
+}
+static int ipipe_get_output_state(unsigned char out_sel)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+
+	if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
+		return 0;
+
+	return param->rsz_en[out_sel];
+}
+
+/* This should be called only after setting the output
+ * window params. This also assumes the corresponding
+ * output is configured prior to calling this.
+ */
+static int ipipe_get_line_length(unsigned char out_sel)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+
+	if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
+		return -EINVAL;
+	/* assume output is always UYVY. Change this if we
+	 * support RGB
+	 */
+	if (!param->rsz_en[out_sel])
+		return -EINVAL;
+
+	return param->ext_mem_param[out_sel].rsz_sdr_oft_y;
+}
+
+static int ipipe_get_image_height(unsigned char out_sel)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+
+	if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
+		return -EINVAL;
+	if (!param->rsz_en[out_sel])
+		return -EINVAL;
+
+	return param->rsz_rsc_param[out_sel].o_vsz + 1;
+}
+
+/* Assume valid param ptr */
+static int ipipe_set_hw_if_param(struct vpfe_hw_if_param *if_param)
+{
+	struct ipipe_params *param = oper_state.shared_config_param;
+	int ret;
+
+	ret = mutex_lock_interruptible(&oper_state.lock);
+	if (ret)
+		return ret;
+	param->ipipeif_param.var.if_5_1.isif_port = *if_param;
+	mutex_unlock(&oper_state.lock);
+
+	return 0;
+}
+
+static struct imp_hw_interface dm365_ipipe_interface = {
+	.name = "DM365 IPIPE",
+	.owner = THIS_MODULE,
+	.prev_enum_modules = prev_enum_preview_cap,
+	.set_oper_mode = ipipe_set_oper_mode,
+	.reset_oper_mode = ipipe_reset_oper_mode,
+	.get_oper_mode = prev_get_oper_mode,
+	.get_hw_state = ipipe_get_oper_state,
+	.set_hw_state = ipipe_set_oper_state,
+	.resizer_chain = ipipe_rsz_chain_state,
+	.lock_chain = ipipe_lock_chain,
+	.unlock_chain = ipipe_unlock_chain,
+	.serialize = ipipe_serialize,
+	.alloc_config_block = ipipe_alloc_config_block,
+	.dealloc_config_block = ipipe_dealloc_config_block,
+	.alloc_user_config_block = ipipe_alloc_user_config_block,
+	.dealloc_config_block = ipipe_dealloc_user_config_block,
+	.set_user_config_defaults = ipipe_set_user_config_defaults,
+	.set_preview_config = ipipe_set_preview_config,
+	.set_resizer_config = ipipe_set_resize_config,
+	.reconfig_resizer = ipipe_reconfig_resizer,
+	.update_inbuf_address = ipipe_set_ipipe_if_address,
+	.update_outbuf1_address = ipipe_update_outbuf1_address,
+	.update_outbuf2_address = ipipe_update_outbuf2_address,
+	.enable = ipipe_enable,
+	.enable_resize = rsz_src_enable,
+	.hw_setup = ipipe_do_hw_setup,
+	.get_resizer_config_state = ipipe_get_rsz_config_state,
+	.get_previewer_config_state = ipipe_get_prev_config_state,
+	.set_input_win = ipipe_set_input_win,
+	.get_input_win = ipipe_get_input_win,
+	.set_hw_if_param = ipipe_set_hw_if_param,
+	.set_in_pixel_format = ipipe_set_in_pixel_format,
+	.set_out_pixel_format = ipipe_set_out_pixel_format,
+	.set_buftype = ipipe_set_buftype,
+	.set_frame_format = ipipe_set_frame_format,
+	.set_output_win = ipipe_set_output_win,
+	.get_output_state = ipipe_get_output_state,
+	.get_line_length = ipipe_get_line_length,
+	.get_image_height = ipipe_get_image_height,
+	.get_image_height = ipipe_get_image_height,
+	.get_max_output_width = ipipe_get_max_output_width,
+	.get_max_output_height = ipipe_get_max_output_height,
+	.enum_pix = ipipe_enum_pix,
+};
+
+struct imp_hw_interface *imp_get_hw_if(void)
+{
+	return &dm365_ipipe_interface;
+}
+
+void enable_serializer(int val)
+{
+	en_serializer = val;
+}
+
+int ipipe_init(void)
+{
+	oper_state.shared_config_param =
+	    kmalloc(sizeof(struct ipipe_params), GFP_KERNEL);
+
+	if (ISNULL(oper_state.shared_config_param)) {
+		printk(KERN_ERR
+		       "dm365_ipipe_init: failed to allocate memory\n");
+		return -ENOMEM;
+	}
+	memcpy(&dm365_ipipe_defs.ipipeif_param.var.if_5_1,
+		&ipipeif_5_1_defaults,
+		sizeof(struct ipipeif_5_1));
+	lutdpc.table = ipipe_lutdpc_table;
+	lut_3d.table = ipipe_3d_lut_table;
+	gbce.table = ipipe_gbce_table;
+	gamma.table_r = ipipe_gamma_table_r;
+	gamma.table_b = ipipe_gamma_table_b;
+	gamma.table_g = ipipe_gamma_table_g;
+	yee.table = ipipe_yee_table;
+	mutex_init(&oper_state.lock);
+	oper_state.state = CHANNEL_FREE;
+	oper_state.prev_config_state = STATE_NOT_CONFIGURED;
+	oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
+	oper_state.frame_format = 1;
+	oper_state.in_pixel_format = IMP_BAYER;
+	oper_state.out_pixel_format = IMP_UYVY;
+
+	return 0;
+}
+
+void ipipe_cleanup(void)
+{
+	kfree(oper_state.shared_config_param);
+}
diff --git a/drivers/media/video/davinci/dm365_ipipe.h b/drivers/media/video/davinci/dm365_ipipe.h
new file mode 100644
index 0000000..9b5dfae
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ipipe.h
@@ -0,0 +1,300 @@
+/*
+* Copyright (C) 2011 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
+*
+* Feature description
+* ===================
+*
+* VPFE hardware setup
+*
+* case 1: Capture to SDRAM with out IPIPE
+* ****************************************
+*
+*            parallel
+*                port
+*
+* Image sensor/       ________
+* Yuv decoder    ---->| CCDC |--> SDRAM
+*                     |______|
+*
+* case 2: Capture to SDRAM with IPIPE Preview modules in Continuous
+*          (On the Fly mode)
+*
+* Image sensor/       ________    ____________________
+* Yuv decoder    ---->| CCDC |--> | Previewer modules |--> SDRAM
+*                     |______|    |___________________|
+*
+* case 3: Capture to SDRAM with IPIPE Preview modules  & Resizer
+*         in continuous (On the Fly mode)
+*
+* Image sensor/       ________    _____________   ___________
+* Yuv decoder    ---->| CCDC |--> | Previewer  |->| Resizer  |-> SDRAM
+*                     |______|    |____________|  |__________|
+*
+* case 4: Capture to SDRAM with IPIPE Resizer
+*         in continuous (On the Fly mode)
+*
+* Image sensor/       ________    ___________
+* Yuv decoder    ---->| CCDC |--> | Resizer  |-> SDRAM
+*                     |______|    |__________|
+*
+* case 5: Read from SDRAM and do preview and/or Resize
+*         in Single shot mode
+*
+*                   _____________   ___________
+*    SDRAM   ----> | Previewer  |->| Resizer  |-> SDRAM
+*                  |____________|  |__________|
+*
+*
+* Previewer allows fine tuning of the input image using different
+* tuning modules in IPIPE. Some examples :- Noise filter, Defect
+* pixel correction etc. It essentially operate on Bayer Raw data
+* or YUV raw data. To do image tuning, application call,
+* PREV_QUERY_CAP, and then call PREV_SET_PARAM to set parameter
+* for a module.
+*
+*
+* Resizer allows upscaling or downscaling a image to a desired
+* resolution. There are 2 resizer modules. both operating on the
+* same input image, but can have different output resolution.
+*/
+
+#ifndef DM365_IPIPE_H
+#define DM365_IPIPE_H
+
+#ifdef __KERNEL__
+#include "imp_common.h"
+#include "dm3xx_ipipeif.h"
+#include <linux/davinci_vpfe.h>
+
+/* Used for driver storage */
+struct ipipe_otfdpc_2_0 {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* defect detection method */
+	enum ipipe_otfdpc_det_meth det_method;
+	/* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
+	 * used
+	 */
+	enum ipipe_otfdpc_alg alg;
+	struct prev_otfdpc_2_0 otfdpc_2_0;
+};
+
+struct ipipe_otfdpc_3_0 {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* defect detection method */
+	enum ipipe_otfdpc_det_meth det_method;
+	/* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
+	 * used
+	 */
+	enum ipipe_otfdpc_alg alg;
+	struct prev_otfdpc_3_0 otfdpc_3_0;
+};
+
+enum enable_disable_t {
+	DISABLE,
+	ENABLE
+};
+
+#define CEIL(a, b)	(((a) + (b-1)) / (b))
+#define IPIPE_MAX_PASSES	2
+
+struct f_div_pass {
+	unsigned int o_hsz;
+	unsigned int i_hps;
+	unsigned int h_phs;
+	unsigned int src_hps;
+	unsigned int src_hsz;
+};
+
+struct f_div_param {
+	unsigned char en;
+	unsigned int num_passes;
+	struct f_div_pass pass[IPIPE_MAX_PASSES];
+};
+
+/* Resizer Rescale Parameters*/
+struct ipipe_rsz_rescale_param {
+	enum ipipe_oper_mode mode;
+	enum enable_disable_t h_flip;
+	enum enable_disable_t v_flip;
+	enum enable_disable_t cen;
+	enum enable_disable_t yen;
+	unsigned short i_vps;
+	unsigned short i_hps;
+	unsigned short o_vsz;
+	unsigned short o_hsz;
+	unsigned short v_phs_y;
+	unsigned short v_phs_c;
+	unsigned short v_dif;
+	/* resize method - Luminance */
+	enum rsz_intp_t v_typ_y;
+	/* resize method - Chrominance */
+	enum rsz_intp_t v_typ_c;
+	/* vertical lpf intensity - Luminance */
+	unsigned char v_lpf_int_y;
+	/* vertical lpf intensity - Chrominance */
+	unsigned char v_lpf_int_c;
+	unsigned short h_phs;
+	unsigned short h_dif;
+	/* resize method - Luminance */
+	enum rsz_intp_t h_typ_y;
+	/* resize method - Chrominance */
+	enum rsz_intp_t h_typ_c;
+	/* horizontal lpf intensity - Luminance */
+	unsigned char h_lpf_int_y;
+	/* horizontal lpf intensity - Chrominance */
+	unsigned char h_lpf_int_c;
+	enum enable_disable_t dscale_en;
+	enum down_scale_ave_sz h_dscale_ave_sz;
+	enum down_scale_ave_sz v_dscale_ave_sz;
+	/* store the calculated frame division parameter */
+	struct f_div_param f_div;
+};
+
+enum ipipe_rsz_rgb_t {
+	OUTPUT_32BIT,
+	OUTPUT_16BIT
+};
+
+enum ipipe_rsz_rgb_msk_t {
+	NOMASK,
+	MASKLAST2
+};
+
+/* Resizer RGB Conversion Parameters */
+struct ipipe_rsz_resize2rgb {
+	enum enable_disable_t rgb_en;
+	enum ipipe_rsz_rgb_t rgb_typ;
+	enum ipipe_rsz_rgb_msk_t rgb_msk0;
+	enum ipipe_rsz_rgb_msk_t rgb_msk1;
+	unsigned int rgb_alpha_val;
+};
+
+/* Resizer External Memory Parameters */
+struct ipipe_ext_mem_param {
+	unsigned int rsz_sdr_oft_y;
+	unsigned int rsz_sdr_ptr_s_y;
+	unsigned int rsz_sdr_ptr_e_y;
+	unsigned int rsz_sdr_oft_c;
+	unsigned int rsz_sdr_ptr_s_c;
+	unsigned int rsz_sdr_ptr_e_c;
+	/* offset to be added to buffer start when flipping for y/ycbcr */
+	unsigned int flip_ofst_y;
+	/* offset to be added to buffer start when flipping for c */
+	unsigned int flip_ofst_c;
+	/* c offset for YUV 420SP */
+	unsigned int c_offset;
+	/* User Defined Y offset for YUV 420SP or YUV420ILE data */
+	unsigned int user_y_ofst;
+	/* User Defined C offset for YUV 420SP data */
+	unsigned int user_c_ofst;
+};
+
+enum rsz_data_source {
+	IPIPE_DATA,
+	IPIPEIF_DATA
+};
+
+/* data paths */
+enum ipipe_data_paths {
+	IPIPE_RAW2YUV,
+	/* Bayer RAW input to YCbCr output */
+	IPIPE_RAW2RAW,
+	/* Bayer Raw to Bayer output */
+	IPIPE_RAW2BOX,
+	/* Bayer Raw to Boxcar output */
+	IPIPE_YUV2YUV
+	/* YUV Raw to YUV Raw output */
+};
+
+enum rsz_src_img_fmt {
+	RSZ_IMG_422,
+	RSZ_IMG_420
+};
+
+struct rsz_common_params {
+	unsigned int vps;
+	unsigned int vsz;
+	unsigned int hps;
+	unsigned int hsz;
+	/* 420 or 422 */
+	enum rsz_src_img_fmt src_img_fmt;
+	/* Y or C when src_fmt is 420, 0 - y, 1 - c */
+	unsigned char y_c;
+	/* flip raw or ycbcr */
+	unsigned char raw_flip;
+	/* IPIPE or IPIPEIF data */
+	enum rsz_data_source source;
+	enum ipipe_dpaths_bypass_t passthrough;
+	unsigned char yuv_y_min;
+	unsigned char yuv_y_max;
+	unsigned char yuv_c_min;
+	unsigned char yuv_c_max;
+	enum enable_disable_t rsz_seq_crv;
+	enum ipipe_chr_pos out_chr_pos;
+};
+
+struct ipipe_params {
+	struct ipipeif ipipeif_param;
+	enum ipipe_oper_mode ipipe_mode;
+	/* input/output datapath through IPIPE */
+	enum ipipe_data_paths ipipe_dpaths_fmt;
+	/* color pattern register */
+	enum ipipe_colpat_t ipipe_colpat_elep;
+	enum ipipe_colpat_t ipipe_colpat_elop;
+	enum ipipe_colpat_t ipipe_colpat_olep;
+	enum ipipe_colpat_t ipipe_colpat_olop;
+	/* horizontal/vertical start, horizontal/vertical size
+	 * for both IPIPE and RSZ input
+	 */
+	unsigned int ipipe_vps;
+	unsigned int ipipe_vsz;
+	unsigned int ipipe_hps;
+	unsigned int ipipe_hsz;
+
+	struct rsz_common_params rsz_common;
+	struct ipipe_rsz_rescale_param rsz_rsc_param[2];
+	struct ipipe_rsz_resize2rgb rsz2rgb[2];
+	struct ipipe_ext_mem_param ext_mem_param[2];
+	enum enable_disable_t rsz_en[2];
+};
+
+void ipipe_set_d2f_regs(unsigned int id, struct prev_nf *noise_filter);
+void ipipe_set_rgb2rgb_regs(unsigned int id, struct prev_rgb2rgb *rgb);
+void rsz_set_output_address(struct ipipe_params *params,
+			      int resize_no, unsigned int address);
+void ipipe_set_yuv422_conv_regs(struct prev_yuv422_conv *conv);
+void ipipe_set_lum_adj_regs(struct prev_lum_adj *lum_adj);
+void ipipe_set_rgb2ycbcr_regs(struct prev_rgb2yuv *yuv);
+void ipipe_set_lutdpc_regs(struct prev_lutdpc *lutdpc);
+void ipipe_set_otfdpc_regs(struct prev_otfdpc *otfdpc);
+void ipipe_set_3d_lut_regs(struct prev_3d_lut *lut_3d);
+void ipipe_set_gamma_regs(struct prev_gamma *gamma);
+int ipipe_hw_setup(struct ipipe_params *config);
+void ipipe_set_gbce_regs(struct prev_gbce *gbce);
+void ipipe_set_gic_regs(struct prev_gic *gic);
+void ipipe_set_cfa_regs(struct prev_cfa *cfa);
+void ipipe_set_car_regs(struct prev_car *car);
+void ipipe_set_cgs_regs(struct prev_cgs *cgs);
+void rsz_set_in_pix_format(unsigned char y_c);
+void ipipe_set_ee_regs(struct prev_yee *ee);
+void ipipe_set_wb_regs(struct prev_wb *wb);
+int rsz_enable(int rsz_id, int enable);
+void rsz_src_enable(int enable);
+
+#endif
+#endif
diff --git a/drivers/media/video/davinci/imp_common.h b/drivers/media/video/davinci/imp_common.h
new file mode 100644
index 0000000..25b2836
--- /dev/null
+++ b/drivers/media/video/davinci/imp_common.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (C) 2011 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
+*
+* imp_common.h file
+*/
+#ifndef _IMP_COMMON_H
+#define _IMP_COMMON_H
+
+#ifdef __KERNEL__
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#define MAX_CHANNELS		2
+#define	MAX_BUFFERS		6
+#define	MAX_PRIORITY		5
+#define	MIN_PRIORITY		0
+#define	DEFAULT_PRIORITY	3
+#define ENABLED			1
+#define DISABLED		0
+#define CHANNEL_BUSY		1
+#define CHANNEL_FREE		0
+#define ISNULL(val) ((val == NULL) ? 1 : 0)
+
+/* driver configured by application */
+#define STATE_CONFIGURED	1
+/* driver not configured by application */
+#define STATE_NOT_CONFIGURED	0
+
+enum imp_log_chan_t {
+	IMP_PREVIEWER,
+	IMP_RESIZER,
+	IMP_HISTOGRAM,
+	IMP_BOXCAR
+};
+
+/* IMP channel structure */
+struct imp_logical_channel {
+	/* channel type */
+	enum imp_log_chan_t type;
+	/* If this channel is chained with another channel, this is set */
+	char chained;
+	/* Set if there is a primary user of this channel */
+	char primary_user;
+	/* channel configuration for this logial channel */
+	void *config;
+	/* Size of the user configuration block */
+	int user_config_size;
+	/* Saves the user configuration */
+	void *user_config;
+	/* configure State of the channel */
+	unsigned int config_state;
+};
+
+/* Where hardware channel is shared, this is used for serialisation */
+struct imp_serializer {
+	/* channel config array for serialization */
+	struct imp_logical_channel *channel_config[MAX_CHANNELS];
+	/* number of elements in the array */
+	int array_count;
+	/* Semaphore for above config array */
+	struct mutex array_sem;
+	/* Completion semaphore when hw channel is common
+	 * Use device specific completion semaphore when request is serialized
+	 */
+	struct completion sem_isr;
+};
+
+
+
+#endif
+#endif
diff --git a/drivers/media/video/davinci/imp_hw_if.h b/drivers/media/video/davinci/imp_hw_if.h
new file mode 100644
index 0000000..20a2b7f
--- /dev/null
+++ b/drivers/media/video/davinci/imp_hw_if.h
@@ -0,0 +1,178 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _IMP_HW_IF_H
+#define _IMP_HW_IF_H
+
+#ifdef __KERNEL__
+#include <linux/davinci_vpfe.h>
+#include "imp_common.h"
+#include <media/davinci/vpfe.h>
+
+struct prev_module_if {
+	/* Version of the preview module */
+	char *version;
+	/* Module IDs as defined above */
+	unsigned short module_id;
+	/* Name of the module */
+	char *module_name;
+	/* control allowed in continous mode ? 1 - allowed , 0 - not allowed */
+	char control;
+	/* path in which module sits */
+	enum imp_data_paths path;
+	int (*set)(struct device *dev, void *param, int len);
+	int (*get)(struct device *dev, void *param, int len);
+};
+
+struct imp_hw_interface {
+	/* Name of the image processor hardware */
+	char *name;
+	/* module owner */
+	struct module *owner;
+	/*
+	 * enumerate preview modules. Return interface to the
+	 * the module
+	 */
+	struct prev_module_if *(*prev_enum_modules) (struct device *dev,
+						     int index);
+	/*
+	 * set operating mode for IPIPE; 1-single shot, 0-continous
+	 */
+	int (*set_oper_mode) (unsigned int mode);
+	/*
+	 * reset operating mode for IPIPE;
+	 */
+	void (*reset_oper_mode) (void);
+	/*
+	 *  get IPIPE operation mode
+	 */
+	unsigned int (*get_oper_mode) (void);
+	/* check if hw is busy in continuous mode.
+	 * Used for checking if hw is used by ccdc driver in
+	 * continuous mode. If streaming is ON, this will be
+	 * set to busy
+	 */
+	unsigned int (*get_hw_state) (void);
+	/* set hw state */
+	void (*set_hw_state) (unsigned int state);
+	/* is resizer chained ? */
+	unsigned int (*resizer_chain) (void);
+	/* this is used to lock shared resource */
+	void (*lock_chain) (void);
+	/* this is used unlock shared resouce */
+	void (*unlock_chain) (void);
+	/* Allocate a shared or exclusive config block for hardware
+	 * configuration
+	 */
+	void *(*alloc_config_block) (struct device *dev);
+	/* hw serialization enabled ?? */
+	int (*serialize) (void);
+	/* De-allocate the exclusive config block */
+	void (*dealloc_config_block) (struct device *dev, void *config);
+	/* Allocate a user confguration block */
+	void *(*alloc_user_config_block) (struct device *dev,
+					  enum imp_log_chan_t chan_type,
+					  int *len);
+
+	/* de-allocate user config block */
+	void (*dealloc_user_config_block) (struct device *dev, void *config);
+
+	/* set default configuration in the config block */
+	void (*set_user_config_defaults) (struct device *dev,
+					  enum imp_log_chan_t chan_type,
+					  void *user_config);
+	/* set user configuration for preview */
+	int (*set_preview_config) (struct device *dev,
+				   void *user_config, void *config);
+	/* set user configuration for resize */
+	int (*set_resizer_config) (struct device *dev,
+				   int resizer_chained,
+				   void *user_config, void *config);
+
+	int (*reconfig_resizer) (struct device *dev,
+				struct rsz_reconfig *user_config,
+				void *config);
+
+	/* update output buffer address for a channel
+	 * if config is NULL, the shared config is assumed
+	 * this is used only in single shot mode
+	 */
+	int (*update_inbuf_address) (void *config, unsigned int address);
+	/* update output buffer address for a channel
+	 * if config is NULL, the shared config is assumed
+	 */
+	void (*update_outbuf1_address) (void *config, unsigned int address);
+	/* update output buffer address for a channel
+	 * if config is NULL, the shared config is assumed
+	 */
+	void (*update_outbuf2_address) (void *config, unsigned int address);
+	/* enable or disable hw */
+	void (*enable) (unsigned char en, void *config);
+	/* enable or disable resizer to allow frame by frame resize in
+	 * continuous mode
+	 */
+	void (*enable_resize) (int en);
+	/* setup hardware for processing. if config is NULL,
+	 * shared channel is assumed
+	 */
+	int (*hw_setup) (struct device *dev, void *config);
+	/* Get configuration state of resizer in continuous mode */
+	unsigned int (*get_resizer_config_state) (void);
+	/* Get configuration state of previewer in continuous mode */
+	unsigned int (*get_previewer_config_state) (void);
+
+	/* Below APIs assume we are using shared configuration since
+	 * oper mode is continuous
+	 */
+	/* Set the input crop window at the IMP interface and IMP */
+	int (*set_input_win) (struct imp_window *win);
+	/* Get current input crop window param at the IMP */
+	int (*get_input_win) (struct imp_window *win);
+	/* Set interface parameter at IPIPEIF. Only valid for DM360 */
+	int (*set_hw_if_param) (struct vpfe_hw_if_param *param);
+	/* Set input pixel format */
+	int (*set_in_pixel_format) (enum imp_pix_formats pix_fmt);
+	/* set output pixel format */
+	int (*set_out_pixel_format) (enum imp_pix_formats pix_fmt);
+	/* 0 - interleaved, 1 - field seperated */
+	int (*set_buftype) (unsigned char buf_type);
+	/* 0 - interlaced, 1 - progressive */
+	int (*set_frame_format) (unsigned char frm_fmt);
+	/* Set the output window at the IMP, output selection
+	 * done by out_sel. 0 - output 1 and 1 - output 2
+	 */
+	int (*set_output_win) (struct imp_window *win);
+	/* Get output enable/disable status */
+	int (*get_output_state) (unsigned char out_sel);
+	/* Get output line lenght */
+	int (*get_line_length) (unsigned char out_sel);
+	/* Get the output image height */
+	int (*get_image_height) (unsigned char out_sel);
+	/* Get current output window param at the IMP */
+	int (*get_output_win) (struct imp_window *win);
+	/* get maximum output width of rsz-a or rsz_b*/
+	int (*get_max_output_width) (int rsz);
+	/* get maximum output height of rsa-a or rsz-b */
+	int (*get_max_output_height) (int rsz);
+	/* Enumerate pixel format for a given input format */
+	int (*enum_pix) (u32 *output_pix, int index);
+};
+
+struct imp_hw_interface *imp_get_hw_if(void);
+
+#endif
+#endif
-- 
1.6.2.4


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

* [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (2 preceding siblings ...)
  2011-08-29 15:07 ` [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-09-01 21:23   ` Sylwester Nawrocki
  2011-08-29 15:07 ` [PATCH v2 5/8] davinci: vpfe: add ccdc driver with media controller interface Manjunath Hadli
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli, Nagabhushana Netagunte

add support for ccdc on dm365 SoC. ccdc is responsible for
capturing video data- both raw bayer through sync seperate
signals and through BT656/1120 interfaces. This driver implements
the hardware functionality. Mainly- setting of hardware, validation
of parameters, and isr configuration.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/ccdc_types.h      |   43 +
 drivers/media/video/davinci/dm365_ccdc.c      | 1519 +++++++++++++++++++++++++
 drivers/media/video/davinci/dm365_ccdc.h      |   88 ++
 drivers/media/video/davinci/dm365_ccdc_regs.h |  309 +++++
 include/linux/dm365_ccdc.h                    |  664 +++++++++++
 5 files changed, 2623 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/ccdc_types.h
 create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
 create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
 create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
 create mode 100644 include/linux/dm365_ccdc.h

diff --git a/drivers/media/video/davinci/ccdc_types.h b/drivers/media/video/davinci/ccdc_types.h
new file mode 100644
index 0000000..5773874
--- /dev/null
+++ b/drivers/media/video/davinci/ccdc_types.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+ *
+ **************************************************************************/
+#ifndef _CCDC_TYPES_H
+#define _CCDC_TYPES_H
+enum ccdc_pixfmt {
+	CCDC_PIXFMT_RAW,
+	CCDC_PIXFMT_YCBCR_16BIT,
+	CCDC_PIXFMT_YCBCR_8BIT
+};
+
+enum ccdc_frmfmt {
+	CCDC_FRMFMT_PROGRESSIVE,
+	CCDC_FRMFMT_INTERLACED
+};
+
+/* PIXEL ORDER IN MEMORY from LSB to MSB */
+/* only applicable for 8-bit input mode  */
+enum ccdc_pixorder {
+	CCDC_PIXORDER_YCBYCR,
+	CCDC_PIXORDER_CBYCRY,
+};
+
+enum ccdc_buftype {
+	CCDC_BUFTYPE_FLD_INTERLEAVED,
+	CCDC_BUFTYPE_FLD_SEPARATED
+};
+#endif
diff --git a/drivers/media/video/davinci/dm365_ccdc.c b/drivers/media/video/davinci/dm365_ccdc.c
new file mode 100644
index 0000000..6c4538f
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ccdc.c
@@ -0,0 +1,1519 @@
+/*
+* Copyright (C) 2011 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
+*/
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <mach/mux.h>
+#include "dm365_ccdc.h"
+#include "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 v4l2_mbus_pixelcode 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_size = CCDC_12_BITS,
+			.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 readl(ccdc_cfg.base_addr + offset);
+}
+
+static inline void regw(u32 val, u32 offset)
+{
+	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)
+		writel(val, ccdc_cfg.linear_tbl0_addr + offset);
+	else
+		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 mode)
+{
+	int horz_nr_pixels;
+	int vert_nr_lines;
+	int horz_start;
+	int vert_start;
+	int mid_img;
+
+	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);
+	}
+
+	if (!mode)
+		regw(0, VDINT0);
+	else
+		regw(vert_nr_lines, 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)
+		return;
+
+	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;
+	u32 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 count = DFC_WRITE_WAIT_COUNT;
+	u32 val;
+	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;
+	u32 val2;
+	u32 i;
+
+	if (!df_csc->csc.en) {
+		regw(0, CSCCTL);
+		return;
+	}
+
+	/* initialize all bits to 0 */
+	val1 = 0;
+
+	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(int mode)
+{
+	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");
+
+	/* In case of user has set BT656IF earlier, it should be reset
+	   when configuring for raw input.
+	 */
+	regw(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 - 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, mode);
+
+	/* 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;
+
+		vpss_set_sync_pol(sync);
+
+		frame_size.hlpfr = ccdc_cfg.bayer.win.width;
+		frame_size.pplen = ccdc_cfg.bayer.win.height;
+		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 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 < 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 == V4L2_MBUS_FMT_SBGGR10_1X10)
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10)
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10) {
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10) {
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10)
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10) {
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10)
+		*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 == V4L2_MBUS_FMT_SBGGR10_1X10) {
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10)
+		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 == V4L2_MBUS_FMT_SBGGR10_1X10)
+		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 V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV10_2X10:
+	case V4L2_MBUS_FMT_Y8_1X8:
+		ccdc_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT;
+		ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		break;
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+		ccdc_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_16BIT;
+		ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+		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 *params)
+{
+	/* only raw module parameters can be set through the IOCTL */
+	if (ccdc_cfg.if_type != V4L2_MBUS_FMT_SBGGR10_1X10)
+		return -EINVAL;
+
+	memcpy(params,
+			&ccdc_cfg.bayer.config_params,
+			sizeof(ccdc_cfg.bayer.config_params));
+
+	return 0;
+}
+
+/* Parameter operations */
+static int ccdc_set_params(void *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 != V4L2_MBUS_FMT_SBGGR10_1X10)
+		return ret;
+
+	memcpy(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
+
+	if (!validate_ccdc_config_params_raw(&ccdc_raw_params)) {
+		memcpy(&ccdc_cfg.bayer.config_params,
+			&ccdc_raw_params,
+			sizeof(ccdc_raw_params));
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/* This function will configure CCDC for YCbCr parameters. */
+static int ccdc_config_ycbcr(int mode)
+{
+	struct ccdc_ycbcr_config *params = &ccdc_cfg.ycbcr;
+	struct vpss_pg_frame_size frame_size;
+	struct vpss_sync_pol sync;
+	u32 modeset;
+	u32 ccdcfg;
+
+	/**
+	 * 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...");
+
+	/* start with all bits zero */
+	modeset = 0;
+	ccdcfg = 0;
+
+	/* 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 V4L2_MBUS_FMT_YUYV8_2X8:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		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 V4L2_MBUS_FMT_YUYV10_2X10:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		/* 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 V4L2_MBUS_FMT_YUYV10_1X20:
+		if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) {
+			dev_dbg(dev, "Invalid pix_fmt(input mode)\n");
+			return -EINVAL;
+		}
+		regw(3, REC656IF);
+		break;
+
+	case V4L2_MBUS_FMT_Y8_1X8:
+		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 V4L2_MBUS_FMT_YUYV8_1X16:
+		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 == V4L2_MBUS_FMT_YUYV10_1X20) ||
+	    (ccdc_cfg.if_type == V4L2_MBUS_FMT_YUYV8_1X16))
+		ccdc_setwin(&params->win, params->frm_fmt, 1, mode);
+	else
+		ccdc_setwin(&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
+	 */
+	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);
+		vpss_set_sync_pol(sync);
+		vpss_set_pg_frame_size(frame_size);
+	}
+
+	return 0;
+}
+
+static int ccdc_configure(int mode)
+{
+	if (ccdc_cfg.if_type == V4L2_MBUS_FMT_SBGGR10_1X10)
+		return ccdc_config_raw(mode);
+	else
+		ccdc_config_ycbcr(mode);
+
+	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,
+	},
+};
+
+struct ccdc_hw_device *get_ccdc_dev(void)
+{
+	return &ccdc_hw_dev;
+}
+
+int ccdc_init(struct platform_device *pdev)
+{
+	static resource_size_t res_len;
+	struct resource *res;
+	void *__iomem addr;
+	int status;
+	int i;
+
+	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);
+
+	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--;
+	}
+
+	return status;
+}
+
+void ccdc_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+	int i;
+
+	iounmap(ccdc_cfg.base_addr);
+	iounmap(ccdc_cfg.linear_tbl0_addr);
+	iounmap(ccdc_cfg.linear_tbl1_addr);
+
+	i = 0;
+	while (i < 3) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (res)
+			release_mem_region(res->start,
+					   res->end - res->start + 1);
+		i++;
+	}
+}
diff --git a/drivers/media/video/davinci/dm365_ccdc.h b/drivers/media/video/davinci/dm365_ccdc.h
new file mode 100644
index 0000000..aae8035
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ccdc.h
@@ -0,0 +1,88 @@
+/*
+* Copyright (C) 2011 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
+*
+* ccdc header file for DM365 ISIF
+*/
+#ifndef _DM365_CCDC_H
+#define _DM365_CCDC_H
+
+#ifdef __KERNEL__
+
+#include <linux/dm365_ccdc.h>
+#include "ccdc_types.h"
+
+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;
+};
+
+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
+};
+
+struct ccdc_hw_device *get_ccdc_dev(void);
+
+#define CCDC_WIN_NTSC				{0, 0, 720, 480}
+#define CCDC_WIN_VGA				{0, 0, 640, 480}
+#define ISP5_CCDCMUX				0x20
+#endif
+#endif
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..9424cf3
--- /dev/null
+++ b/drivers/media/video/davinci/dm365_ccdc_regs.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2011 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
+ */
+#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)
+
+/*masks and shifts*/
+#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/linux/dm365_ccdc.h b/include/linux/dm365_ccdc.h
new file mode 100644
index 0000000..4e50529
--- /dev/null
+++ b/include/linux/dm365_ccdc.h
@@ -0,0 +1,664 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _DM365_CCDC_INCLUDE_H
+#define _DM365_CCDC_INCLUDE_H
+
+#include <media/davinci/vpfe.h>
+
+#define VPFE_CMD_S_CCDC_RAW_PARAMS _IOW('V', 1, \
+					struct ccdc_config_params_raw)
+#define VPFE_CMD_G_CCDC_RAW_PARAMS _IOR('V', 2, \
+					struct ccdc_config_params_raw)
+/**
+ * ccdc float type S8Q8/U8Q8
+ */
+struct ccdc_float_8 {
+	/* 8 bit integer part */
+	unsigned char integer;
+	/* 8 bit decimal part */
+	unsigned char decimal;
+};
+
+/**
+ * brief ccdc float type U16Q16/S16Q16
+ */
+struct ccdc_float_16 {
+	/* 16 bit integer part */
+	unsigned short integer;
+	/* 16 bit decimal part */
+	unsigned short decimal;
+};
+
+/*
+ * ccdc image(target) window parameters
+ */
+struct ccdc_cropwin {
+	/* horzontal offset of the top left corner in pixels */
+	unsigned int left;
+	/* vertical offset of the top left corner in pixels */
+	unsigned int top;
+	/* width in pixels of the rectangle */
+	unsigned int width;
+	/* height in lines of the rectangle */
+	unsigned int height;
+};
+
+/************************************************************************
+ *   Vertical Defect Correction parameters
+ ***********************************************************************/
+
+/**
+ * vertical defect correction methods
+ */
+enum ccdc_vdfc_corr_mode {
+	/* Defect level subtraction. Just fed through if saturating */
+	CCDC_VDFC_NORMAL,
+	/**
+	 * Defect level subtraction. Horizontal interpolation ((i-2)+(i+2))/2
+	 * if data saturating
+	 */
+	CCDC_VDFC_HORZ_INTERPOL_IF_SAT,
+	/* Horizontal interpolation (((i-2)+(i+2))/2) */
+	CCDC_VDFC_HORZ_INTERPOL
+};
+
+/**
+ * Max Size of the Vertical Defect Correction table
+ */
+#define CCDC_VDFC_TABLE_SIZE 8
+
+/**
+ * Values used for shifting up the vdfc defect level
+ */
+enum ccdc_vdfc_shift {
+	/* No Shift */
+	CCDC_VDFC_NO_SHIFT,
+	/* Shift by 1 bit */
+	CCDC_VDFC_SHIFT_1,
+	/* Shift by 2 bit */
+	CCDC_VDFC_SHIFT_2,
+	/* Shift by 3 bit */
+	CCDC_VDFC_SHIFT_3,
+	/* Shift by 4 bit */
+	CCDC_VDFC_SHIFT_4
+};
+
+/**
+ * Defect Correction (DFC) table entry
+ */
+struct ccdc_vdfc_entry {
+	/* vertical position of defect */
+	unsigned short pos_vert;
+	/* horizontal position of defect */
+	unsigned short pos_horz;
+	/**
+	 * Defect level of Vertical line defect position. This is subtracted
+	 * from the data at the defect position
+	 */
+	unsigned char level_at_pos;
+	/**
+	 * Defect level of the pixels upper than the vertical line defect.
+	 * This is subtracted from the data
+	 */
+	unsigned char level_up_pixels;
+	/**
+	 * Defect level of the pixels lower than the vertical line defect.
+	 * This is subtracted from the data
+	 */
+	unsigned char level_low_pixels;
+};
+
+/**
+ * Structure for Defect Correction (DFC) parameter
+ */
+struct ccdc_dfc {
+	/* enable vertical defect correction */
+	unsigned char en;
+	/* Correction methods */
+	enum ccdc_vdfc_corr_mode corr_mode;
+	/**
+	 * 0 - whole line corrected, 1 - not
+	 * pixels upper than the defect
+	 */
+	unsigned char corr_whole_line;
+	/**
+	 * defect level shift value. level_at_pos, level_upper_pos,
+	 * and level_lower_pos can be shifted up by this value
+	 */
+	enum ccdc_vdfc_shift def_level_shift;
+	/* defect saturation level */
+	unsigned short def_sat_level;
+	/* number of vertical defects. Max is CCDC_VDFC_TABLE_SIZE */
+	short num_vdefects;
+	/* VDFC table ptr */
+	struct ccdc_vdfc_entry table[CCDC_VDFC_TABLE_SIZE];
+};
+
+/************************************************************************
+*   Digital/Black clamp or DC Subtract parameters
+************************************************************************/
+/**
+ * Horizontal Black Clamp modes
+ */
+enum ccdc_horz_bc_mode {
+	/**
+	 * Horizontal clamp disabled. Only vertical clamp
+	 * value is subtracted
+	 */
+	CCDC_HORZ_BC_DISABLE,
+	/**
+	 * Horizontal clamp value is calculated and subtracted
+	 * from image data along with vertical clamp value
+	 */
+	CCDC_HORZ_BC_CLAMP_CALC_ENABLED,
+	/**
+	 * Horizontal clamp value calculated from previous image
+	 * is subtracted from image data along with vertical clamp
+	 * value. How the horizontal clamp value for the first image
+	 * is calculated in this case ???
+	 */
+	CCDC_HORZ_BC_CLAMP_NOT_UPDATED
+};
+
+/**
+ * Base window selection for Horizontal Black Clamp calculations
+ */
+enum ccdc_horz_bc_base_win_sel {
+	/* Select Most left window for bc calculation */
+	CCDC_SEL_MOST_LEFT_WIN,
+
+	/* Select Most right window for bc calculation */
+	CCDC_SEL_MOST_RIGHT_WIN,
+};
+
+/* Size of window in horizontal direction for horizontal bc */
+enum ccdc_horz_bc_sz_h {
+	CCDC_HORZ_BC_SZ_H_2PIXELS,
+	CCDC_HORZ_BC_SZ_H_4PIXELS,
+	CCDC_HORZ_BC_SZ_H_8PIXELS,
+	CCDC_HORZ_BC_SZ_H_16PIXELS
+};
+
+/* Size of window in vertcal direction for vertical bc */
+enum ccdc_horz_bc_sz_v {
+	CCDC_HORZ_BC_SZ_H_32PIXELS,
+	CCDC_HORZ_BC_SZ_H_64PIXELS,
+	CCDC_HORZ_BC_SZ_H_128PIXELS,
+	CCDC_HORZ_BC_SZ_H_256PIXELS
+};
+
+/**
+ * Structure for Horizontal Black Clamp config params
+ */
+struct ccdc_horz_bclamp {
+	/* horizontal clamp mode */
+	enum ccdc_horz_bc_mode mode;
+	/**
+	 * pixel value limit enable.
+	 *  0 - limit disabled
+	 *  1 - pixel value limited to 1023
+	 */
+	unsigned char clamp_pix_limit;
+	/**
+	 * Select most left or right window for clamp val
+	 * calculation
+	 */
+	enum ccdc_horz_bc_base_win_sel base_win_sel_calc;
+	/* Window count per color for calculation. range 1-32 */
+	unsigned char win_count_calc;
+	/* Window start position - horizontal for calculation. 0 - 8191 */
+	unsigned short win_start_h_calc;
+	/* Window start position - vertical for calculation 0 - 8191 */
+	unsigned short win_start_v_calc;
+	/* Width of the sample window in pixels for calculation */
+	enum ccdc_horz_bc_sz_h win_h_sz_calc;
+	/* Height of the sample window in pixels for calculation */
+	enum ccdc_horz_bc_sz_v win_v_sz_calc;
+};
+
+/**
+ * Black Clamp vertical reset values
+ */
+enum ccdc_vert_bc_reset_val_sel {
+	/* Reset value used is the clamp value calculated */
+	CCDC_VERT_BC_USE_HORZ_CLAMP_VAL,
+	/* Reset value used is reset_clamp_val configured */
+	CCDC_VERT_BC_USE_CONFIG_CLAMP_VAL,
+	/* No update, previous image value is used */
+	CCDC_VERT_BC_NO_UPDATE
+};
+
+enum ccdc_vert_bc_sz_h {
+	CCDC_VERT_BC_SZ_H_2PIXELS,
+	CCDC_VERT_BC_SZ_H_4PIXELS,
+	CCDC_VERT_BC_SZ_H_8PIXELS,
+	CCDC_VERT_BC_SZ_H_16PIXELS,
+	CCDC_VERT_BC_SZ_H_32PIXELS,
+	CCDC_VERT_BC_SZ_H_64PIXELS
+};
+
+/**
+ * Structure for Vetical Black Clamp configuration params
+ */
+struct ccdc_vert_bclamp {
+	/* Reset value selection for vertical clamp calculation */
+	enum ccdc_vert_bc_reset_val_sel reset_val_sel;
+	/* U12 value if reset_sel = CCDC_BC_VERT_USE_CONFIG_CLAMP_VAL */
+	unsigned short reset_clamp_val;
+	/**
+	 * U8Q8. Line average coefficient used in vertical clamp
+	 * calculation
+	 */
+	unsigned char line_ave_coef;
+	/* Width in pixels of the optical black region used for calculation. */
+	enum ccdc_vert_bc_sz_h ob_h_sz_calc;
+	/* Height of the optical black region for calculation */
+	unsigned short ob_v_sz_calc;
+	/* Optical black region start position - horizontal. 0 - 8191 */
+	unsigned short ob_start_h;
+	/* Optical black region start position - vertical 0 - 8191 */
+	unsigned short ob_start_v;
+};
+
+/**
+ * Structure for Black Clamp configuration params
+ */
+struct ccdc_black_clamp {
+	/**
+	 * this offset value is added irrespective of the clamp
+	 * enable status. S13
+	 */
+	unsigned short dc_offset;
+	/**
+	 * Enable black/digital clamp value to be subtracted
+	 * from the image data
+	 */
+	unsigned char 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
+	 */
+	unsigned char bc_mode_color;
+	/* Vrtical start position for bc subtraction */
+	unsigned short 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)
+*************************************************************************/
+/**
+ * Number of Coefficient values used for CSC
+ */
+#define CCDC_CSC_NUM_COEFF 16
+
+/*************************************************************************
+**  Color Space Conversion parameters
+*************************************************************************/
+/**
+ * Structure used for CSC config params
+ */
+struct ccdc_color_space_conv {
+	/* Enable color space conversion */
+	unsigned char 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];
+};
+
+/**
+ * CCDC image data size
+ */
+enum ccdc_data_size {
+	/* 8 bits */
+	CCDC_8_BITS,
+	/* 9 bits */
+	CCDC_9_BITS,
+	/* 10 bits */
+	CCDC_10_BITS,
+	/* 11 bits */
+	CCDC_11_BITS,
+	/* 12 bits */
+	CCDC_12_BITS,
+	/* 13 bits */
+	CCDC_13_BITS,
+	/* 14 bits */
+	CCDC_14_BITS,
+	/* 15 bits */
+	CCDC_15_BITS,
+	/* 16 bits */
+	CCDC_16_BITS
+};
+
+/**
+ * CCDC image data shift to right
+ */
+enum ccdc_datasft {
+	/* No Shift */
+	CCDC_NO_SHIFT,
+	/* 1 bit Shift */
+	CCDC_1BIT_SHIFT,
+	/* 2 bit Shift */
+	CCDC_2BIT_SHIFT,
+	/* 3 bit Shift */
+	CCDC_3BIT_SHIFT,
+	/* 4 bit Shift */
+	CCDC_4BIT_SHIFT,
+	/* 5 bit Shift */
+	CCDC_5BIT_SHIFT,
+	/* 6 bit Shift */
+	CCDC_6BIT_SHIFT
+};
+
+/**
+ * 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
+};
+
+/*************************************************************************
+**  Black  Compensation parameters
+*************************************************************************/
+/**
+ * Structure used for Black Compensation
+ */
+struct ccdc_black_comp {
+	/* Comp for Red */
+	char r_comp;
+	/* Comp for Gr */
+	char gr_comp;
+	/* Comp for Blue */
+	char b_comp;
+	/* Comp for Gb */
+	char gb_comp;
+};
+
+/*************************************************************************
+**  Gain parameters
+*************************************************************************/
+/**
+ * Structure for 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;
+};
+
+/**
+ * Predicator types for DPCM compression
+ */
+enum ccdc_dpcm_predictor {
+	/* Choose Predictor1 for DPCM compression */
+	CCDC_DPCM_PRED1,
+	/* Choose Predictor2 for DPCM compression */
+	CCDC_DPCM_PRED2
+};
+
+#define CCDC_LINEAR_TAB_SIZE 192
+/*************************************************************************
+**  Linearization parameters
+*************************************************************************/
+/**
+ * Structure for Sensor data linearization
+ */
+struct ccdc_linearize {
+	/* Enable or Disable linearization of data */
+	unsigned char en;
+	/* Shift value applied */
+	enum ccdc_datasft corr_shft;
+	/* scale factor applied U11Q10 */
+	struct ccdc_float_16 scale_fact;
+	/* Size of the linear table */
+	unsigned short table[CCDC_LINEAR_TAB_SIZE];
+};
+
+enum ccdc_cfa_pattern {
+	CCDC_CFA_PAT_MOSAIC,
+	CCDC_CFA_PAT_STRIPE
+};
+
+enum ccdc_colpats {
+	CCDC_RED,
+	CCDC_GREEN_RED,
+	CCDC_GREEN_BLUE,
+	CCDC_BLUE
+};
+
+struct ccdc_col_pat {
+	enum ccdc_colpats olop;
+	enum ccdc_colpats olep;
+	enum ccdc_colpats elop;
+	enum ccdc_colpats elep;
+};
+
+/*************************************************************************
+**  CCDC Raw configuration parameters
+*************************************************************************/
+enum ccdc_fmt_mode {
+	CCDC_SPLIT,
+	CCDC_COMBINE
+};
+
+enum ccdc_lnum {
+	CCDC_1LINE,
+	CCDC_2LINES,
+	CCDC_3LINES,
+	CCDC_4LINES
+};
+
+enum ccdc_line {
+	CCDC_1STLINE,
+	CCDC_2NDLINE,
+	CCDC_3RDLINE,
+	CCDC_4THLINE
+};
+
+struct ccdc_fmtplen {
+	/**
+	 * number of program entries for SET0, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	unsigned short plen0;
+	/**
+	 * number of program entries for SET1, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	unsigned short plen1;
+	/**
+	 * number of program entries for SET2, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	unsigned short plen2;
+	/**
+	 * number of program entries for SET3, range 1 - 16
+	 * when fmtmode is CCDC_SPLIT, 1 - 8 when fmtmode is
+	 * CCDC_COMBINE
+	 */
+	unsigned short plen3;
+};
+
+struct ccdc_fmt_cfg {
+	/* Split or combine or line alternate */
+	enum ccdc_fmt_mode fmtmode;
+	/* enable or disable line alternating mode */
+	unsigned char ln_alter_en;
+	/* Split/combine line number */
+	enum ccdc_lnum lnum;
+	/* Address increment Range 1 - 16 */
+	unsigned int addrinc;
+};
+
+struct ccdc_fmt_addr_ptr {
+	/* Initial address */
+	unsigned int init_addr;
+	/* output line number */
+	enum ccdc_line out_line;
+};
+
+struct ccdc_fmtpgm_ap {
+	/* program address pointer */
+	unsigned char pgm_aptr;
+	/* program address increment or decrement */
+	unsigned char pgmupdt;
+};
+
+struct ccdc_data_formatter {
+	/* Enable/Disable data formatter */
+	unsigned char 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 */
+	unsigned short fmtrlen;
+	/* HD interval for output line. Only valid when split line */
+	unsigned short fmthcnt;
+	/* formatter address pointers */
+	struct ccdc_fmt_addr_ptr fmtaddr_ptr[16];
+	/* program enable/disable */
+	unsigned char 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 */
+	unsigned int 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 */
+	unsigned int start_pix;
+	/* number of pixels in input line */
+	unsigned int num_pixels;
+	/* start line at the input */
+	unsigned int start_line;
+	/* number of lines at the input */
+	unsigned int num_lines;
+};
+
+struct ccdc_gain_offsets_adj {
+	/* Gain adjustment per color */
+	struct ccdc_gain gain;
+	/* Offset adjustment */
+	unsigned short offset;
+	/* Enable or Disable Gain adjustment for SDRAM data */
+	unsigned char gain_sdram_en;
+	/* Enable or Disable Gain adjustment for IPIPE data */
+	unsigned char gain_ipipe_en;
+	/* Enable or Disable Gain adjustment for H3A data */
+	unsigned char gain_h3a_en;
+	/* Enable or Disable Gain adjustment for SDRAM data */
+	unsigned char offset_sdram_en;
+	/* Enable or Disable Gain adjustment for IPIPE data */
+	unsigned char offset_ipipe_en;
+	/* Enable or Disable Gain adjustment for H3A data */
+	unsigned char offset_h3a_en;
+};
+
+struct ccdc_cul {
+	/* Horizontal Cull pattern for odd lines */
+	unsigned char hcpat_odd;
+	/* Horizontal Cull pattern for even lines */
+	unsigned char hcpat_even;
+	/* Vertical Cull pattern */
+	unsigned char vcpat;
+	/* Enable or disable lpf. Apply when cull is enabled */
+	unsigned char en_lpf;
+};
+
+enum ccdc_compress_alg {
+	CCDC_ALAW,
+	CCDC_DPCM,
+	CCDC_NO_COMPRESSION
+};
+
+struct ccdc_compress {
+	/* Enable or diable A-Law or DPCM compression. */
+	enum ccdc_compress_alg alg;
+	/* Predictor for DPCM compression */
+	enum ccdc_dpcm_predictor 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 */
+	unsigned short horz_offset;
+	/* vertical offset for Gain/LSC/DFC */
+	unsigned short 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;
+	/* data size from 8 to 16 bits */
+	enum ccdc_data_size data_size;
+	/* Data shift applied before storing to SDRAM */
+	enum ccdc_datasft data_shift;
+	/* enable input test pattern generation */
+	unsigned char test_pat_gen;
+};
+
+#endif
-- 
1.6.2.4


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

* [PATCH v2 5/8] davinci: vpfe: add ccdc driver with media controller interface
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (3 preceding siblings ...)
  2011-08-29 15:07 ` [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365 Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 6/8] davinci: vpfe: add v4l2 video driver support Manjunath Hadli
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli, Nagabhushana Netagunte

Add the CCDC driver for davinci Dm3XX SoCs. The driver supports
CCDC as a media entity with 2 pads - 1 input and 1 output. The
driver implements streaming support and subdev interface. The
ccdc supports bayer and YUV formats.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/ccdc_hw_device.h |   10 +-
 drivers/media/video/davinci/vpfe_ccdc.c      |  813 ++++++++++++++++++++++++++
 drivers/media/video/davinci/vpfe_ccdc.h      |   85 +++
 3 files changed, 901 insertions(+), 7 deletions(-)
 create mode 100644 drivers/media/video/davinci/vpfe_ccdc.c
 create mode 100644 drivers/media/video/davinci/vpfe_ccdc.h

diff --git a/drivers/media/video/davinci/ccdc_hw_device.h b/drivers/media/video/davinci/ccdc_hw_device.h
index 86b9b35..5394a06 100644
--- a/drivers/media/video/davinci/ccdc_hw_device.h
+++ b/drivers/media/video/davinci/ccdc_hw_device.h
@@ -23,8 +23,8 @@
 #ifdef __KERNEL__
 #include <linux/videodev2.h>
 #include <linux/device.h>
-#include <media/davinci/vpfe_types.h>
-#include <media/davinci/ccdc_types.h>
+#include "ccdc_types.h"
+#include <media/davinci/vpfe.h>
 
 /*
  * ccdc hw operations
@@ -57,7 +57,7 @@ struct ccdc_hw_ops {
 	 */
 	int (*get_params) (void *params);
 	/* Pointer to function to configure ccdc */
-	int (*configure) (void);
+	int (*configure) (int mode);
 
 	/* Pointer to function to set buffer type */
 	int (*set_buftype) (enum ccdc_buftype buf_type);
@@ -102,9 +102,5 @@ struct ccdc_hw_device {
 	struct ccdc_hw_ops hw_ops;
 };
 
-/* Used by CCDC module to register & unregister with vpfe capture driver */
-int vpfe_register_ccdc_device(struct ccdc_hw_device *dev);
-void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev);
-
 #endif
 #endif
diff --git a/drivers/media/video/davinci/vpfe_ccdc.c b/drivers/media/video/davinci/vpfe_ccdc.c
new file mode 100644
index 0000000..57d8b3d
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_ccdc.c
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2011 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@ti.com>
+ *      Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
+ */
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/media-entity.h>
+#include "vpfe_capture.h"
+
+#include "ccdc_hw_device.h"
+
+#define MAX_WIDTH	4096
+#define MAX_HEIGHT	4096
+
+static const unsigned int ccdc_fmts[] = {
+	V4L2_MBUS_FMT_Y8_1X8,
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_YUYV8_1X16,
+	V4L2_MBUS_FMT_YUYV10_1X20,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+};
+
+/*
+ * CCDC helper functions
+ */
+/* get field id in ccdc hardware */
+enum v4l2_field ccdc_get_fid(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_ccdc_device *ccdc = &vpfe_dev->vpfe_ccdc;
+	struct ccdc_hw_device *ccdc_dev = ccdc->ccdc_dev;
+
+	return ccdc_dev->hw_ops.getfid();
+}
+
+/* Retrieve active or try pad format based on query */
+static struct v4l2_mbus_framefmt *
+__ccdc_get_format(struct vpfe_ccdc_device *ccdc, 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);
+	} else
+		return &ccdc->formats[pad];
+}
+
+/* configure format in ccdc hardware */
+static int vpfe_config_ccdc_format(struct vpfe_device *vpfe_dev,
+				   unsigned int pad)
+{
+	struct ccdc_hw_device *ccdc_dev = vpfe_dev->vpfe_ccdc.ccdc_dev;
+	struct vpfe_ccdc_device *vpfe_ccdc = &vpfe_dev->vpfe_ccdc;
+	enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
+	struct v4l2_pix_format format;
+	int ret = 0;
+
+	v4l2_fill_pix_format(&format, &vpfe_dev->vpfe_ccdc.formats[pad]);
+	mbus_to_pix(&vpfe_dev->vpfe_ccdc.formats[pad], &format);
+
+	if (ccdc_dev->hw_ops.set_pixel_format(
+			format.pixelformat) < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"couldn't set pix format in ccdc\n");
+		return -EINVAL;
+	}
+
+	/* call for s_crop will override these values */
+	vpfe_ccdc->crop.left = 0;
+	vpfe_ccdc->crop.top = 0;
+	vpfe_ccdc->crop.width = format.width;
+	vpfe_ccdc->crop.height = format.height;
+
+	/* configure the image window */
+	ccdc_dev->hw_ops.set_image_window(&vpfe_ccdc->crop);
+
+	switch (vpfe_dev->vpfe_ccdc.formats[pad].field) {
+	case V4L2_FIELD_INTERLACED:
+		/* do nothing, since it is default */
+		ret = ccdc_dev->hw_ops.set_buftype(
+				CCDC_BUFTYPE_FLD_INTERLEAVED);
+		break;
+	case V4L2_FIELD_NONE:
+		frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
+		/* buffer type only applicable for interlaced scan */
+		break;
+	case V4L2_FIELD_SEQ_TB:
+		ret = ccdc_dev->hw_ops.set_buftype(
+				CCDC_BUFTYPE_FLD_SEPARATED);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set the frame format */
+	if (!ret)
+		ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt);
+
+	return ret;
+}
+
+/*
+ * ccdc_try_format - Try video format on a pad
+ * @ccdc: VPFE CCDC device
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ */
+static void
+ccdc_try_format(struct vpfe_ccdc_device *vpfe_ccdc, 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(ccdc_fmts); i++) {
+		if (fmt->format.code == ccdc_fmts[i])
+			break;
+	}
+
+	/* If not found, use YUYV8_2x8 as default */
+	if (i >= ARRAY_SIZE(ccdc_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 == CCDC_PAD_SOURCE)
+		fmt->format.width &= ~15;
+}
+
+/*
+ * ccdc_buffer_isr - CCDC module non-progressive buffer scheduling isr
+ * @ccdc: CCDC device pointer
+ *
+ */
+void ccdc_buffer_isr(struct vpfe_ccdc_device *ccdc)
+{
+	struct vpfe_video_device *video = &ccdc->video_out;
+	struct ccdc_hw_device *ccdc_dev = ccdc->ccdc_dev;
+	enum v4l2_field field;
+
+	if (!video->started)
+		return;
+
+	field = video->fmt.fmt.pix.field;
+
+	/* reset sbl overblow bit */
+	if (ccdc_dev->hw_ops.reset != NULL)
+		ccdc_dev->hw_ops.reset();
+
+	if (field == V4L2_FIELD_NONE) {
+		/* handle progressive frame capture */
+		if (video->cur_frm != video->next_frm)
+			vpfe_process_buffer_complete(video);
+	} else {
+		int fid;
+		/* interlaced or TB capture check which field we
+		 * are in hardware
+		 */
+		fid = ccdc_dev->hw_ops.getfid();
+
+		/* 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_process_buffer_complete(video);
+				/*
+				 * based on whether the two fields are stored
+				 * interleavely or separately in memory,
+				 * reconfigure the CCDC memory address
+				 */
+				if (field == V4L2_FIELD_SEQ_TB)
+					vpfe_schedule_bottom_field(video);
+
+				return;
+			} else {
+				/*
+				 * 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_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;
+		}
+	}
+}
+
+/*
+ * ccdc_vidint1_isr - CCDC module progressive buffer scheduling isr
+ * @ccdc: CCDC device pointer
+ *
+ */
+void ccdc_vidint1_isr(struct vpfe_ccdc_device *ccdc)
+{
+	struct vpfe_video_device *video = &ccdc->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_schedule_next_buffer(video);
+	spin_unlock(&video->dma_queue_lock);
+}
+
+/*
+ * VPFE video operations
+ */
+
+static void ccdc_video_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
+{
+	struct vpfe_ccdc_device *vpfe_ccdc = &vpfe_dev->vpfe_ccdc;
+	struct ccdc_hw_device *ccdc_dev = vpfe_ccdc->ccdc_dev;
+
+	ccdc_dev->hw_ops.setfbaddr(addr);
+}
+
+static const struct vpfe_video_operations ccdc_video_ops = {
+	.queue = ccdc_video_queue,
+};
+
+
+/*
+ * V4L2 subdev operations
+ */
+
+/*
+ * ccdc_ioctl - CCDC module private ioctl's
+ * @sd: VPFE CCDC V4L2 subdevice
+ * @cmd: ioctl command
+ * @arg: ioctl argument
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct vpfe_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct ccdc_hw_device *ccdc_dev = ccdc->ccdc_dev;
+	int ret;
+
+	switch (cmd) {
+	case VPFE_CMD_S_CCDC_RAW_PARAMS:
+		ret = ccdc_dev->hw_ops.set_params(arg);
+		break;
+	case VPFE_CMD_G_CCDC_RAW_PARAMS:
+		if (!ccdc_dev->hw_ops.get_params) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = ccdc_dev->hw_ops.get_params(arg);
+		break;
+
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+
+	return ret;
+}
+
+/*
+ * ccdc_set_stream - Enable/Disable streaming on the CCDC module
+ * @sd: VPFE CCDC V4L2 subdevice
+ * @enable: Enable/disable stream
+ */
+static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct vpfe_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct ccdc_hw_device *ccdc_dev = ccdc->ccdc_dev;
+	int ret;
+
+	if (enable) {
+		ret = ccdc_dev->hw_ops.configure(
+		(ccdc->output == CCDC_OUTPUT_MEMORY) ? 0 : 1);
+		if (ret)
+			return ret;
+
+		if ((ccdc_dev->hw_ops.enable_out_to_sdram) &&
+			(ccdc->output == CCDC_OUTPUT_MEMORY))
+			ccdc_dev->hw_ops.enable_out_to_sdram(1);
+
+		ccdc_dev->hw_ops.enable(1);
+	} else {
+
+		ccdc_dev->hw_ops.enable(0);
+
+		if (ccdc_dev->hw_ops.enable_out_to_sdram)
+			ccdc_dev->hw_ops.enable_out_to_sdram(0);
+	}
+
+	return 0;
+}
+
+/*
+* ccdc_set_format - set format on pad
+* @sd    : VPFE ccdc 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 ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct vpfe_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct vpfe_device *vpfe_dev = to_vpfe_device(ccdc);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	ccdc_try_format(ccdc, fh, fmt);
+	memcpy(format, &fmt->format, sizeof(*format));
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+		return 0;
+
+	if (fmt->pad == CCDC_PAD_SINK)
+		return vpfe_config_ccdc_format(vpfe_dev, fmt->pad);
+
+	return 0;
+}
+
+/*
+ * ccdc_get_format - Retrieve the video format on a pad
+ * @sd : VPFE CCDC V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct vpfe_ccdc_device *vpfe_ccdc = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __ccdc_get_format(vpfe_ccdc, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	memcpy(&fmt->format, format, sizeof(fmt->format));
+
+	return 0;
+}
+
+/*
+ * ccdc_enum_frame_size - enum frame sizes on pads
+ * @sd: VPFE ccdc V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_frame_size_enum structure
+ */
+static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct vpfe_ccdc_device *ccdc = 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;
+	ccdc_try_format(ccdc, 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;
+	ccdc_try_format(ccdc, fh, &format);
+	fse->max_width = format.format.width;
+	fse->max_height = format.format.height;
+
+	return 0;
+}
+
+/*
+ * ccdc_enum_mbus_code - enum mbus codes for pads
+ * @sd: VPFE ccdc V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ */
+static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_fh *fh,
+			       struct v4l2_subdev_mbus_code_enum *code)
+{
+	switch (code->pad) {
+	case CCDC_PAD_SINK:
+	case CCDC_PAD_SOURCE:
+		if (code->index >= ARRAY_SIZE(ccdc_fmts))
+			return -EINVAL;
+
+		code->code = ccdc_fmts[code->index];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * ccdc_pad_set_crop - set crop rectangle on pad
+ * @sd: VPFE ccdc 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 ccdc_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		       struct v4l2_subdev_crop *crop)
+{
+	struct vpfe_ccdc_device *vpfe_ccdc = v4l2_get_subdevdata(sd);
+	struct ccdc_hw_device *ccdc_dev = vpfe_ccdc->ccdc_dev;
+	struct v4l2_mbus_framefmt *format;
+
+	/* check wether its a valid pad */
+	if (crop->pad != CCDC_PAD_SINK)
+		return -EINVAL;
+
+	format = __ccdc_get_format(vpfe_ccdc, 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_ccdc->formats[CCDC_PAD_SINK].width) ||
+	(crop->rect.top + crop->rect.height >
+	vpfe_ccdc->formats[CCDC_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_ccdc->crop = crop->rect;
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		ccdc_dev->hw_ops.set_image_window(&vpfe_ccdc->crop);
+	else {
+		struct v4l2_rect *rect;
+
+		rect = v4l2_subdev_get_try_crop(fh, CCDC_PAD_SINK);
+		memcpy(rect, &vpfe_ccdc->crop, sizeof(*rect));
+	}
+
+	return 0;
+}
+
+/*
+ * ccdc_pad_get_crop - get crop rectangle on pad
+ * @sd: VPFE ccdc 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 ccdc_pad_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+		       struct v4l2_subdev_crop *crop)
+{
+	struct vpfe_ccdc_device *vpfe_ccdc = v4l2_get_subdevdata(sd);
+
+	/* check wether its a valid pad */
+	if (crop->pad != CCDC_PAD_SINK)
+		return -EINVAL;
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_rect *rect;
+		rect = v4l2_subdev_get_try_crop(fh, CCDC_PAD_SINK);
+		memcpy(&crop->rect, rect, sizeof(*rect));
+	} else
+		crop->rect = vpfe_ccdc->crop;
+
+	return 0;
+}
+
+/*
+ * ccdc_init_formats - Initialize formats on all pads
+ * @sd: VPFE ccdc 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 ccdc_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 = CCDC_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SBGGR10_1X10;
+	format.format.width = MAX_WIDTH;
+	format.format.height = MAX_HEIGHT;
+	ccdc_set_format(sd, fh, &format);
+
+	memset(&format, 0, sizeof(format));
+	format.pad = CCDC_PAD_SOURCE;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SBGGR10_1X10;
+	format.format.width = MAX_WIDTH;
+	format.format.height = MAX_HEIGHT;
+	ccdc_set_format(sd, fh, &format);
+
+	memset(&crop, 0, sizeof(crop));
+	crop.pad = CCDC_PAD_SINK;
+	crop.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	crop.rect.width = MAX_WIDTH;
+	crop.rect.height = MAX_HEIGHT;
+	ccdc_pad_set_crop(sd, fh, &crop);
+
+	return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = {
+	.ioctl = ccdc_ioctl,
+};
+
+/* subdev file operations */
+static const struct v4l2_subdev_file_ops ccdc_v4l2_file_ops = {
+	.open = ccdc_init_formats,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops ccdc_v4l2_video_ops = {
+	.s_stream = ccdc_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
+	.enum_mbus_code = ccdc_enum_mbus_code,
+	.enum_frame_size = ccdc_enum_frame_size,
+	.get_fmt = ccdc_get_format,
+	.set_fmt = ccdc_set_format,
+	.set_crop = ccdc_pad_set_crop,
+	.get_crop = ccdc_pad_get_crop,
+};
+
+/* v4l2 subdev operations */
+static const struct v4l2_subdev_ops ccdc_v4l2_ops = {
+	.core = &ccdc_v4l2_core_ops,
+	.file = &ccdc_v4l2_file_ops,
+	.video = &ccdc_v4l2_video_ops,
+	.pad = &ccdc_v4l2_pad_ops,
+};
+
+/*
+ * Media entity operations
+ */
+
+/*
+ * ccdc_link_setup - Setup CCDC connections
+ * @entity: CCDC 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 ccdc_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_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* read from decoder/sensor */
+		if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+			ccdc->input = CCDC_INPUT_NONE;
+			break;
+		}
+
+		if (ccdc->input != CCDC_INPUT_NONE)
+			return -EBUSY;
+
+		ccdc->input = CCDC_INPUT_PARALLEL;
+
+		break;
+
+	case CCDC_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+		/* write to memory */
+		if (flags & MEDIA_LNK_FL_ENABLED)
+			ccdc->output = CCDC_OUTPUT_MEMORY;
+		else
+			ccdc->output = CCDC_OUTPUT_NONE;
+		break;
+
+	case CCDC_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+		if (flags & MEDIA_LNK_FL_ENABLED)
+			ccdc->output = CCDC_OUTPUT_PREVIEWER;
+		else
+			ccdc->output = CCDC_OUTPUT_NONE;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+static const struct media_entity_operations ccdc_media_ops = {
+	.link_setup = ccdc_link_setup,
+};
+
+/*
+ * vpfe_ccdc_unregister_entities - CCDC subdevs/video
+ * driver unregistrations.
+ * @ccdc - pointer to ccdc subdevice structure.
+ */
+void vpfe_ccdc_unregister_entities(struct vpfe_ccdc_device *ccdc)
+{
+	struct ccdc_hw_device *ccdc_dev = ccdc->ccdc_dev;
+	struct device *dev = ccdc->subdev.v4l2_dev->dev;
+
+	vpfe_video_unregister(&ccdc->video_out);
+
+	if (ccdc_dev->hw_ops.close)
+		ccdc_dev->hw_ops.close(dev);
+
+	/* cleanup entity */
+	media_entity_cleanup(&ccdc->subdev.entity);
+	/* unregister subdev */
+	v4l2_device_unregister_subdev(&ccdc->subdev);
+}
+
+/*
+ * vpfe_ccdc_register_entities - CCDC subdevs/video
+ * driver registrations.
+ * @ccdc - pointer to ccdc subdevice structure.
+ * @vdev: pointer to v4l2 device structure.
+ */
+int vpfe_ccdc_register_entities(struct vpfe_ccdc_device *ccdc,
+				struct v4l2_device *vdev)
+{
+	struct ccdc_hw_device *ccdc_dev = NULL;
+	struct vpfe_device *vpfe_dev = to_vpfe_device(ccdc);
+	struct device *dev = vdev->dev;
+	unsigned int flags;
+	int ret;
+
+	/* Register the subdev */
+	ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
+	if (ret < 0)
+		return ret;
+
+	ccdc_dev = ccdc->ccdc_dev;
+
+	ret = ccdc_dev->hw_ops.open(dev);
+	if (ret)
+		goto out_ccdc_open;
+
+	ret = vpfe_video_register(&ccdc->video_out, vdev);
+	if (ret) {
+		printk(KERN_ERR "failed to register ccdc video out device\n");
+		goto out_video_register;
+	}
+
+	ccdc->video_out.vpfe_dev = vpfe_dev;
+
+	flags = 0;
+	/* connect ccdc to video node */
+	ret = media_entity_create_link(&ccdc->subdev.entity,
+				       1,
+				       &ccdc->video_out.video_dev.entity,
+				       0, flags);
+	if (ret < 0)
+		goto out_create_link;
+
+	return 0;
+out_create_link:
+	vpfe_video_unregister(&ccdc->video_out);
+out_video_register:
+	if (ccdc_dev->hw_ops.close)
+		ccdc_dev->hw_ops.close(dev);
+
+out_ccdc_open:
+	v4l2_device_unregister_subdev(&ccdc->subdev);
+
+	return ret;
+}
+
+/*
+ * vpfe_ccdc_init - Initialize V4L2 subdev and media entity
+ * @ccdc: VPFE CCDC module
+ *
+ * Return 0 on success and a negative error code on failure.
+ */
+int vpfe_ccdc_init(struct vpfe_ccdc_device *ccdc, struct platform_device *pdev)
+{
+	struct v4l2_subdev *sd = &ccdc->subdev;
+	struct media_pad *pads = &ccdc->pads[0];
+	struct media_entity *me = &sd->entity;
+	int ret;
+
+	if (ccdc_init(pdev)) {
+		printk(KERN_ERR "vpfe_ccdc_init-not supported\n");
+		return -1;
+	}
+
+	/* queue ops */
+	ccdc->video_out.ops = &ccdc_video_ops;
+
+	v4l2_subdev_init(sd, &ccdc_v4l2_ops);
+	strlcpy(sd->name, "DAVINCI CCDC", sizeof(sd->name));
+	sd->grp_id = 1 << 16;	/* group ID for davinci subdevs */
+	v4l2_set_subdevdata(sd, ccdc);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sd->nevents = DAVINCI_CCDC_NEVENTS;
+	pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_INPUT;
+	pads[CCDC_PAD_SOURCE].flags = MEDIA_PAD_FL_OUTPUT;
+
+	ccdc->input = CCDC_INPUT_NONE;
+	ccdc->output = CCDC_OUTPUT_NONE;
+
+	me->ops = &ccdc_media_ops;
+
+	ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0);
+	if (ret)
+		goto out_davanci_init;
+	ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ret = vpfe_video_init(&ccdc->video_out, "CCDC");
+	if (ret) {
+		printk(KERN_ERR "failed to init ccdc-out video device\n");
+		goto out_davanci_init;
+	}
+
+	ccdc->ccdc_dev = get_ccdc_dev();
+
+	return 0;
+
+out_davanci_init:
+	ccdc_remove(pdev);
+	return ret;
+}
+
+/*
+ * vpfe_ccdc_cleanup - CCDC module cleanup.
+ * @dev: Device pointer specific to the VPFE.
+ */
+void vpfe_ccdc_cleanup(struct platform_device *pdev)
+{
+	ccdc_remove(pdev);
+}
diff --git a/drivers/media/video/davinci/vpfe_ccdc.h b/drivers/media/video/davinci/vpfe_ccdc.h
new file mode 100644
index 0000000..92706e2
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_ccdc.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 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
+ */
+
+#ifndef _VPFE_CCDC_H
+#define _VPFE_CCDC_H
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_ARCH_DAVINCI_DM365
+#include "dm365_ccdc.h"
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI_DM355
+#include <../include/media/davinci/dm355_ccdc.h>
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI_DM644x
+#include <../include/media/davinci/dm644x_ccdc.h>
+#endif
+
+#define CCDC_PAD_SINK      0
+#define CCDC_PAD_SOURCE    1
+
+#define CCDC_PADS_NUM      2
+
+#define DAVINCI_CCDC_NEVENTS 0
+
+enum ccdc_input_entity {
+	CCDC_INPUT_NONE,
+	CCDC_INPUT_PARALLEL,
+};
+
+#define CCDC_OUTPUT_NONE	(0)
+#define CCDC_OUTPUT_MEMORY	(1 << 0)
+#define CCDC_OUTPUT_RESIZER	(1 << 1)
+#define CCDC_OUTPUT_PREVIEWER	(1 << 2)
+
+#define CCDC_NOT_CHAINED	0
+#define CCDC_CHAINED		1
+
+struct vpfe_ccdc_device {
+	struct v4l2_subdev		subdev;
+	struct media_pad		pads[CCDC_PADS_NUM];
+	struct v4l2_mbus_framefmt	formats[CCDC_PADS_NUM];
+	enum ccdc_input_entity		input;
+	unsigned int			output;
+
+	struct ccdc_hw_device		*ccdc_dev;
+	struct v4l2_rect		crop;
+
+	/* independent video device */
+	struct vpfe_video_device	video_out;
+};
+
+enum v4l2_field ccdc_get_fid(struct vpfe_device *vpfe_dev);
+void ccdc_remove(struct platform_device *pdev);
+int ccdc_init(struct platform_device *pdev);
+struct ccdc_hw_device *get_ccdc_dev(void);
+
+void vpfe_ccdc_unregister_entities(struct vpfe_ccdc_device *ccdc);
+int vpfe_ccdc_register_entities(struct vpfe_ccdc_device *ccdc,
+				struct v4l2_device *v4l2_dev);
+int vpfe_ccdc_init(struct vpfe_ccdc_device *vpfe_ccdc,
+			struct platform_device *pdev);
+void vpfe_ccdc_cleanup(struct platform_device *pdev);
+void ccdc_vidint1_isr(struct vpfe_ccdc_device *ccdc);
+void ccdc_buffer_isr(struct vpfe_ccdc_device *ccdc);
+
+#endif
+
+#endif
-- 
1.6.2.4


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

* [PATCH v2 6/8] davinci: vpfe: add v4l2 video driver support
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (4 preceding siblings ...)
  2011-08-29 15:07 ` [PATCH v2 5/8] davinci: vpfe: add ccdc driver with media controller interface Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 7/8] davinci: vpfe: v4l2 capture driver with media interface Manjunath Hadli
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli, Nagabhushana Netagunte

add a generic video driver functionality to be used by all the vpfe
drivers for davinci SoCs. The functionality includes all the
standard v4l2 interfaces including streaming.
The video node interface can be used both as an input and output
node for both continuous and single shot modes.Also supports
dv_presets to include HD modes, wth support for both user pointer
IO and mmap.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/vpfe_video.c | 1712 ++++++++++++++++++++++++++++++
 drivers/media/video/davinci/vpfe_video.h |  142 +++
 2 files changed, 1854 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/vpfe_video.c
 create mode 100644 drivers/media/video/davinci/vpfe_video.h

diff --git a/drivers/media/video/davinci/vpfe_video.c b/drivers/media/video/davinci/vpfe_video.c
new file mode 100644
index 0000000..bb405fb
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_video.c
@@ -0,0 +1,1712 @@
+/*
+ * Copyright (C) 2011 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@ti.com>
+ *	Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-mediabus.h>
+#include <media/media-entity.h>
+#include <media/media-device.h>
+#include "vpfe_capture.h"
+#include <mach/cputype.h>
+#include "ccdc_hw_device.h"
+
+/* number of buffers supported in single-shot mode */
+#define SS_NUM_BUFFERS		1
+/* minimum number of buffers needed in cont-mode */
+#define CONT_MIN_NUM_BUFFERS	3
+
+static int debug;
+
+/* get v4l2 subdev pointer to external subdev which is active */
+static struct v4l2_subdev *vpfe_get_input_sd(struct vpfe_video_device *video)
+{
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct media_pad *remote;
+
+	remote = media_entity_remote_source(&vpfe_dev->vpfe_ccdc.pads[0]);
+	if (remote == NULL) {
+		printk(KERN_ERR "invalid media connection to ccdc\n");
+		return NULL;
+	}
+
+	return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+/* updates external subdev(sensor/decoder) which is active */
+static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video)
+{
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_config *vpfe_cfg;
+	struct v4l2_subdev *subdev;
+	struct media_pad *remote;
+	int i;
+
+	remote = media_entity_remote_source(&vpfe_dev->vpfe_ccdc.pads[0]);
+	if (remote == NULL) {
+		printk(KERN_ERR "invalid media connection to ccdc\n");
+		return -1;
+	}
+
+	subdev = media_entity_to_v4l2_subdev(remote->entity);
+
+	vpfe_cfg = vpfe_dev->pdev->platform_data;
+
+	for (i = 0; i < vpfe_cfg->num_subdevs; i++) {
+		if (!strcmp(vpfe_cfg->sub_devs[i].module_name, subdev->name)) {
+			video->current_ext_subdev = &vpfe_cfg->sub_devs[i];
+			break;
+		}
+	}
+
+	/* if user not linked decoder/sensor to ccdc */
+	if (i == vpfe_cfg->num_subdevs) {
+		printk(KERN_ERR "invalid media chain connection to ccdc\n");
+		return -1;
+	}
+
+	/* find the v4l2 subdev pointer */
+	for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) {
+		if (!strcmp(video->current_ext_subdev->module_name,
+			vpfe_dev->sd[i]->name))
+			video->current_ext_subdev->subdev = vpfe_dev->sd[i];
+	}
+
+	return 0;
+}
+
+/* get the subdev which is connected to the output video node */
+static struct v4l2_subdev *
+vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad)
+{
+	struct media_pad *remote;
+
+	remote = media_entity_remote_source(&video->pad);
+
+	if (remote == NULL ||
+		remote->entity->type != MEDIA_ENT_T_V4L2_SUBDEV)
+		return NULL;
+
+	if (pad)
+		*pad = remote->index;
+
+	return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+/* get the format set at ouput pad of the adjacent subdev */
+static int
+__vpfe_video_get_format(struct vpfe_video_device *video,
+			struct v4l2_format *format)
+{
+	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *subdev;
+	struct media_pad *remote;
+	u32 pad;
+	int ret;
+
+	subdev = vpfe_video_remote_subdev(video, &pad);
+	if (subdev == NULL)
+		return -EINVAL;
+
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	remote = media_entity_remote_source(&video->pad);
+	fmt.pad = remote->index;
+
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+	if (ret == -ENOIOCTLCMD)
+		return -EINVAL;
+
+	format->type = video->type;
+	/* convert mbus_format to v4l2_format */
+	v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
+	mbus_to_pix(&fmt.format, &format->fmt.pix);
+
+	return 0;
+}
+
+/* return pointer to the VPFE video instance at the far end of the pipeline */
+static struct vpfe_video_device *
+vpfe_video_far_end(struct vpfe_video_device *video)
+{
+	struct media_entity *entity = &video->video_dev.entity;
+	struct media_device *mdev = entity->parent;
+	struct vpfe_video_device *far_end = NULL;
+	struct media_entity_graph graph;
+
+	mutex_lock(&mdev->graph_mutex);
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+		if (entity == &video->video_dev.entity)
+			continue;
+
+		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+			continue;
+
+		far_end = to_vpfe_video(media_entity_to_video_device(entity));
+		if (far_end->type != video->type)
+			break;
+
+		far_end = NULL;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+
+	return far_end;
+}
+
+/* update pipe state selected by user */
+static int vpfe_update_pipe_state(struct vpfe_video_device *video)
+{
+	struct vpfe_pipeline *pipe = &video->pipe;
+	struct vpfe_video_device *far_end = NULL;
+	int ret;
+
+	far_end = vpfe_video_far_end(video);
+	if (far_end == NULL) {
+		/* possible that it is continous mode */
+		ret = vpfe_update_current_ext_subdev(video);
+		if (ret) {
+			printk(KERN_ERR "invalid external subdev\n");
+			return ret;
+		}
+		pipe->state = VPFE_PIPELINE_STREAM_CONTINUOUS;
+		pipe->output = video;
+		pipe->input_sd = vpfe_get_input_sd(video);
+	} else if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT;
+		pipe->input = far_end;
+		pipe->output = video;
+	} else {
+		pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT;
+		pipe->output = far_end;
+		pipe->input = video;
+	}
+
+	video->initialized = 1;
+	video->skip_frame_count = 1;
+	video->skip_frame_count_init = 1;
+
+	return 0;
+}
+
+/* checks wether pipeline is ready for enabling */
+static int is_pipe_ready(struct vpfe_pipeline *pipe)
+{
+	if (pipe->state == VPFE_PIPELINE_STREAM_SINGLESHOT) {
+		if (!pipe->input->started ||
+			!(pipe->input->state & VPFE_VIDEO_BUFFER_QUEUED) ||
+			!pipe->output->started ||
+			!(pipe->output->state & VPFE_VIDEO_BUFFER_QUEUED))
+			return 0;
+	}
+
+	return 1;
+}
+
+/**
+ * Validate a pipeline by checking both ends of all links for format
+ * discrepancies.
+ *
+ * Return 0 if all formats match, or -EPIPE if at least one link is found with
+ * different formats on its two ends.
+ */
+static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe)
+{
+	struct v4l2_subdev_format fmt_source;
+	struct v4l2_subdev_format fmt_sink;
+	struct v4l2_subdev *subdev;
+	struct media_pad *pad;
+	int ret;
+
+	subdev = vpfe_video_remote_subdev(pipe->output, NULL);
+	if (subdev == NULL)
+		return -EPIPE;
+
+	while (1) {
+		/* Retrieve the sink format */
+		pad = &subdev->entity.pads[0];
+		if (!(pad->flags & MEDIA_PAD_FL_INPUT))
+			break;
+
+		fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		fmt_sink.pad = pad->index;
+		ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL,
+				       &fmt_sink);
+
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			return -EPIPE;
+
+		/* Retrieve the source format */
+		pad = media_entity_remote_source(pad);
+		if (pad == NULL ||
+			pad->entity->type != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		subdev = media_entity_to_v4l2_subdev(pad->entity);
+
+		fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		fmt_source.pad = pad->index;
+		ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			return -EPIPE;
+
+		/* Check if the two ends match */
+		if (fmt_source.format.code != fmt_sink.format.code ||
+		    fmt_source.format.width != fmt_sink.format.width ||
+		    fmt_source.format.height != fmt_sink.format.height)
+			return -EPIPE;
+	}
+
+	return 0;
+}
+
+/**
+ * vpfe_pipeline_enable - Enable streaming on a pipeline
+ * @vpfe_dev: vpfe device
+ * @pipe: vpfe pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and start
+ * all modules in the chain in the given mode.
+ *
+ * Return 0 if successfull, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
+{
+	struct media_entity_graph graph;
+	struct media_entity *entity;
+	struct v4l2_subdev *subdev;
+	struct media_device *mdev;
+	int ret = 0;
+
+	if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
+		entity = &pipe->input_sd->entity;
+	else
+		entity = &pipe->input->video_dev.entity;
+
+	mdev = entity->parent;
+
+	mutex_lock(&mdev->graph_mutex);
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+
+		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+			continue;
+
+		subdev = media_entity_to_v4l2_subdev(entity);
+
+		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			break;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+
+	return ret;
+}
+
+/**
+ * vpfe_pipeline_disable - Disable streaming on a pipeline
+ * @vpfe_dev: vpfe device
+ * @pipe: VPFE pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and stop
+ * all modules in the chain.
+ *
+ * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module
+ * can't be stopped.
+ */
+static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
+{
+	struct media_entity_graph graph;
+	struct media_entity *entity;
+	struct v4l2_subdev *subdev;
+	struct media_device *mdev;
+	int ret = 0;
+
+	if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
+		entity = &pipe->input_sd->entity;
+	else
+		entity = &pipe->input->video_dev.entity;
+
+	mdev = entity->parent;
+
+	mutex_lock(&mdev->graph_mutex);
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+
+		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+			continue;
+
+		subdev = media_entity_to_v4l2_subdev(entity);
+
+		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			break;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+
+	return (ret == 0) ? ret : -ETIMEDOUT ;
+}
+
+/**
+ * vpfe_pipeline_set_stream - Enable/disable streaming on a pipeline
+ * @vpfe_dev: VPFE device
+ * @pipe: VPFE pipeline
+ * @state: Stream state (stopped or active)
+ *
+ * Set the pipeline to the given stream state.
+ *
+ * Return 0 if successfull, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int vpfe_pipeline_set_stream(struct vpfe_pipeline *pipe,
+			    enum vpfe_pipeline_stream_state state)
+{
+	if (state == VPFE_PIPELINE_STREAM_STOPPED)
+		return vpfe_pipeline_disable(pipe);
+	else
+		return vpfe_pipeline_enable(pipe);
+}
+
+/*
+ * vpfe_open - open video device
+ * @file: file pointer
+ *
+ * initialize media pipeline state, allocate memory for file hadle
+ *
+ * Return 0 if successfull, or the return -ENODEV otherwise.
+ */
+static int vpfe_open(struct file *file)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_fh *fh;
+
+	/* Allocate memory for the file handle object */
+	fh = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
+
+	if (NULL == fh)
+		return -ENOMEM;
+	/* store pointer to fh in private_data member of file */
+	file->private_data = fh;
+	fh->video = video;
+	mutex_lock(&video->lock);
+	/* If decoder is not initialized. initialize it */
+	if (!video->initialized) {
+		if (vpfe_update_pipe_state(video)) {
+			mutex_unlock(&video->lock);
+			return -ENODEV;
+		}
+	}
+	/* Increment device usrs counter */
+	video->usrs++;
+	/* Set io_allowed member to false */
+	fh->io_allowed = 0;
+	/* Initialize priority of this instance to default priority */
+	fh->prio = V4L2_PRIORITY_UNSET;
+	v4l2_prio_open(&video->prio, &fh->prio);
+	mutex_unlock(&video->lock);
+
+	return 0;
+}
+
+/* get the next buffer available from dma queue */
+unsigned long vpfe_get_next_buffer(struct vpfe_video_device *video)
+{
+	/* mark next buffer as active */
+	video->next_frm = list_entry(video->dma_queue.next,
+					struct videobuf_buffer, queue);
+
+	/* in single shot mode both curr_frm
+	   and next_frm point to same buffer */
+	video->cur_frm = video->next_frm;
+	list_del(&video->next_frm->queue);
+	video->next_frm->state = VIDEOBUF_ACTIVE;
+
+	return videobuf_to_dma_contig(video->next_frm);
+}
+
+/* schedule the next buffer which is available on dma queue */
+void vpfe_schedule_next_buffer(struct vpfe_video_device *video)
+{
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	unsigned long addr;
+
+	video->next_frm = list_entry(video->dma_queue.next,
+					struct videobuf_buffer, queue);
+	list_del(&video->next_frm->queue);
+	video->next_frm->state = VIDEOBUF_ACTIVE;
+	addr = videobuf_to_dma_contig(video->next_frm);
+
+	video->ops->queue(vpfe_dev, addr);
+}
+
+/* schedule the buffer for capturing bottom field */
+void vpfe_schedule_bottom_field(struct vpfe_video_device *video)
+{
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	unsigned long addr;
+
+	addr = videobuf_to_dma_contig(video->cur_frm);
+	addr += video->field_off;
+
+	video->ops->queue(vpfe_dev, addr);
+}
+
+/* make buffer available for dequeue */
+void vpfe_process_buffer_complete(struct vpfe_video_device *video)
+{
+	struct vpfe_pipeline *pipe = &video->pipe;
+	struct timespec timespec;
+	s64 nsec;
+
+	ktime_get_ts(&timespec);
+	nsec = timespec_to_ns(&timespec);
+
+	video->cur_frm->ts = ns_to_timeval(nsec);
+	video->cur_frm->state = VIDEOBUF_DONE;
+	video->cur_frm->size = video->fmt.fmt.pix.sizeimage;
+	wake_up_interruptible(&video->cur_frm->done);
+	/* for continous mode, proceed with next buffer */
+	if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
+		video->cur_frm = video->next_frm;
+}
+
+/* vpfe_stop_capture: stop streaming in ccdc/isif */
+static void vpfe_stop_capture(struct vpfe_video_device *video)
+{
+	struct vpfe_pipeline *pipe = &video->pipe;
+
+	video->started = 0;
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return;
+
+	vpfe_pipeline_set_stream(pipe, VPFE_PIPELINE_STREAM_STOPPED);
+}
+
+/*
+ * vpfe_release - release video device
+ * @file: file pointer
+ *
+ * deletes buffer queue, frees the buffers and the vpfe file handle
+ *
+ * Return 0
+ */
+static int vpfe_release(struct file *file)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_fh *fh = file->private_data;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
+
+	/* Get the device lock */
+	mutex_lock(&video->lock);
+	/* if this instance is doing IO */
+	if (fh->io_allowed) {
+		if (video->started) {
+			vpfe_stop_capture(video);
+			videobuf_streamoff(&video->buffer_queue);
+		}
+		video->io_usrs = 0;
+	}
+
+	/* Decrement device usrs counter */
+	video->usrs--;
+	/* Close the priority */
+	v4l2_prio_close(&video->prio, fh->prio);
+
+	/* If this is the last file handle */
+	if (!video->usrs)
+		video->initialized = 0;
+
+	mutex_unlock(&video->lock);
+	file->private_data = NULL;
+	/* Free memory allocated to file handle object */
+	kzfree(fh);
+
+	return 0;
+}
+
+/*
+ * vpfe_mmap : It is used to map kernel space buffers
+ * into user spaces
+ */
+static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
+
+	return videobuf_mmap_mapper(&video->buffer_queue, vma);
+}
+
+/*
+ * vpfe_poll: It is used for select/poll system call
+ */
+static unsigned int vpfe_poll(struct file *file, poll_table *wait)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
+
+	if (video->started)
+		return videobuf_poll_stream(file,
+					    &video->buffer_queue, wait);
+
+	return 0;
+}
+
+/* vpfe capture driver file operations */
+static const struct v4l2_file_operations vpfe_fops = {
+	.owner = THIS_MODULE,
+	.open = vpfe_open,
+	.release = vpfe_release,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = vpfe_mmap,
+	.poll = vpfe_poll
+};
+
+/*
+ * vpfe_querycap - query capabilities of video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @cap: pointer to v4l2_capability structure
+ *
+ * fills v4l2 capabilities structure
+ *
+ * Return 0
+ */
+static int vpfe_querycap(struct file *file, void  *priv,
+			       struct v4l2_capability *cap)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	else
+		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+
+	cap->version = VPFE_CAPTURE_VERSION_CODE;
+	strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
+	strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
+
+	return 0;
+}
+
+/*
+ * vpfe_g_fmt - get the format which is active on video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_format structure
+ *
+ * fills v4l2 format structure with active format
+ *
+ * Return 0
+ */
+static int vpfe_g_fmt(struct file *file, void *priv,
+				struct v4l2_format *fmt)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt\n");
+	/* Fill in the information about format */
+	*fmt = video->fmt;
+
+	return 0;
+}
+
+/*
+ * vpfe_enum_fmt - enum formats supported on media chain
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_fmtdesc structure
+ *
+ * fills v4l2_fmtdesc structure with output format set on adjacent subdev,
+ * only one format is enumearted as subdevs are already configured
+ *
+ * Return 0 if successfull, error code otherwise
+ */
+static int vpfe_enum_fmt(struct file *file, void  *priv,
+				   struct v4l2_fmtdesc *fmt)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct v4l2_subdev_format sd_fmt;
+	struct v4l2_mbus_framefmt mbus;
+	struct v4l2_subdev *subdev;
+	struct v4l2_format format;
+	struct media_pad *remote;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n");
+
+	/* since already subdev pad format is set,
+	only one pixel format is available */
+	if (fmt->index > 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid index\n");
+		return -EINVAL;
+	}
+
+	/* get the remote pad */
+	remote = media_entity_remote_source(&video->pad);
+	if (remote == NULL) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote pad \
+					for video node\n");
+		return -EINVAL;
+	}
+
+	/* get the remote subdev */
+	subdev = vpfe_video_remote_subdev(video, NULL);
+	if (subdev == NULL) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote subdev \
+					for video node\n");
+		return -EINVAL;
+	}
+
+	sd_fmt.pad = remote->index;
+	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	/* get output format of remote subdev */
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL,
+				       &sd_fmt);
+	if (ret) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote subdev \
+					for video node\n");
+		return ret;
+	}
+	/* convert to pix format */
+	mbus.code = sd_fmt.format.code;
+	mbus_to_pix(&mbus, &format.fmt.pix);
+
+	/* copy the result */
+	fmt->pixelformat = format.fmt.pix.pixelformat;
+
+	return 0;
+}
+
+/*
+ * vpfe_s_fmt - set the format on video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_format structure
+ *
+ * validate and set the format on video device
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_fmt(struct file *file, void *priv,
+				struct v4l2_format *fmt)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct v4l2_format format;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n");
+
+	/* If streaming is started, return error */
+	if (video->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
+		return -EBUSY;
+	}
+
+	/* get adjacent subdev's output pad format */
+	ret = __vpfe_video_get_format(video, &format);
+	if (ret)
+		return ret;
+
+	*fmt = format;
+
+	video->fmt = *fmt;
+
+	return 0;
+}
+
+/*
+ * vpfe_try_fmt - try the format on video device
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_format structure
+ *
+ * validate the format, update with correct format
+ * based on output format set on adjacent subdev
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_try_fmt(struct file *file, void *priv,
+				  struct v4l2_format *fmt)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct v4l2_format format;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n");
+
+	/* get adjacent subdev's output pad format */
+	ret = __vpfe_video_get_format(video, &format);
+	if (ret)
+		return ret;
+
+	*fmt = format;
+
+	return 0;
+}
+
+/*
+ * vpfe_enum_input - enum inputs supported on media chain
+ * @file: file pointer
+ * @priv: void pointer
+ * @fmt: pointer to v4l2_fmtdesc structure
+ *
+ * fills v4l2_input structure with input available on media chain,
+ * only one input is enumearted as media chain is setup by this time
+ *
+ * Return 0 if successfull, -EINVAL is media chain is invalid
+ */
+static int vpfe_enum_input(struct file *file, void *priv,
+				 struct v4l2_input *inp)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_ext_subdev_info *sdinfo = video->current_ext_subdev;
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
+
+	/* enumerate from the subdev user has choosen through mc */
+	if (inp->index < sdinfo->num_inputs) {
+		memcpy(inp, &sdinfo->inputs[inp->index],
+		       sizeof(struct v4l2_input));
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * vpfe_g_input - get index of the input which is active
+ * @file: file pointer
+ * @priv: void pointer
+ * @index: pointer to unsigned int
+ *
+ * set index with input index which is active
+ *
+ * Return 0
+ */
+static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
+
+	*index = video->current_input;
+
+	return 0;
+}
+
+/*
+ * vpfe_s_input - set input which is pointed by input index
+ * @file: file pointer
+ * @priv: void pointer
+ * @index: pointer to unsigned int
+ *
+ * set input on external subdev
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct ccdc_hw_device *ccdc_dev = vpfe_dev->vpfe_ccdc.ccdc_dev;
+	struct imp_hw_interface *imp_hw_if = vpfe_dev->vpfe_previewer.imp_hw_if;
+	struct vpfe_ext_subdev_info *sdinfo;
+	struct vpfe_route *route;
+	struct v4l2_input *inps;
+	u32 output;
+	u32 input;
+	int ret;
+	int i;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
+
+	ret = mutex_lock_interruptible(&video->lock);
+	if (ret)
+		return ret;
+
+	/*
+	 * If streaming is started return device busy
+	 * error
+	 */
+	if (video->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
+		ret = -EBUSY;
+		goto unlock_out;
+	}
+
+	sdinfo = video->current_ext_subdev;
+
+	if (!sdinfo->registered) {
+		ret = -EINVAL;
+		goto unlock_out;
+	}
+
+	if (vpfe_dev->cfg->setup_input) {
+		if (vpfe_dev->cfg->setup_input(sdinfo->grp_id) < 0) {
+			ret = -EFAULT;
+			v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+				 "couldn't setup input for %s\n",
+				 sdinfo->module_name);
+			goto unlock_out;
+		}
+	}
+
+	route = &sdinfo->routes[index];
+	if (route && sdinfo->can_route) {
+		input = route->input;
+		output = route->output;
+		ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+						 sdinfo->grp_id, video,
+						 s_routing, input, output, 0);
+
+		if (ret) {
+			v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+				"s_input:error in setting input in decoder\n");
+			ret = -EINVAL;
+			goto unlock_out;
+		}
+	}
+
+	/* set standards set by subdev in video device */
+	for (i = 0; i < sdinfo->num_inputs; i++) {
+		inps = &sdinfo->inputs[i];
+		video->video_dev.tvnorms |= inps->std;
+	}
+
+	/* set the bus/interface parameter for the sub device in ccdc */
+	ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params);
+	if (ret)
+		goto unlock_out;
+
+	/* update the if parameters to imp hw interface */
+	if (imp_hw_if && imp_hw_if->set_hw_if_param)
+		ret = imp_hw_if->set_hw_if_param(&sdinfo->ccdc_if_params);
+	if (ret)
+		goto unlock_out;
+
+	video->current_input = index;
+
+unlock_out:
+	mutex_unlock(&video->lock);
+	return ret;
+}
+
+/*
+ * vpfe_querystd - query std which is being input on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @std_id: pointer to v4l2_std_id structure
+ *
+ * call external subdev through v4l2_device_call_until_err to
+ * get the std that is being active.
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_ext_subdev_info *sdinfo;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
+
+	ret = mutex_lock_interruptible(&video->lock);
+	sdinfo = video->current_ext_subdev;
+	if (ret)
+		return ret;
+
+	/* Call querystd function of decoder device */
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+					 video, querystd, std_id);
+	mutex_unlock(&video->lock);
+
+	return ret;
+}
+
+/*
+ * vpfe_s_std - set std on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @std_id: pointer to v4l2_std_id structure
+ *
+ * set std pointed by std_id on external subdev by calling it using
+ * v4l2_device_call_until_err
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_ext_subdev_info *sdinfo;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
+
+	/* Call decoder driver function to set the standard */
+	ret = mutex_lock_interruptible(&video->lock);
+	if (ret)
+		return ret;
+
+	sdinfo = video->current_ext_subdev;
+	/* If streaming is started, return device busy error */
+	if (video->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
+		ret = -EBUSY;
+		goto unlock_out;
+	}
+
+	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+					 core, s_std, *std_id);
+	if (ret < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
+		goto unlock_out;
+	}
+
+unlock_out:
+	mutex_unlock(&video->lock);
+	return ret;
+}
+
+/*
+ * vpfe_enum_preset - enumerate dv_preset which are supported by
+ * to external subdev
+ *
+ * @file: file pointer
+ * @priv: void pointer
+ * @preset: pointer to v4l2_dv_enum_preset structure
+ *
+ * enum dv_preset's which are supported by external subdev through
+ * v4l2_subdev_call
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_enum_preset(struct file *file, void *fh,
+			    struct v4l2_dv_enum_preset *preset)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_preset\n");
+
+	return v4l2_subdev_call(subdev, video, enum_dv_presets, preset);
+}
+
+/*
+ * vpfe_query_preset - query the dv_preset which is being input
+ * to external subdev
+ *
+ * @file: file pointer
+ * @priv: void pointer
+ * @preset: pointer to v4l2_preset structure
+ *
+ * get dv_preset which is being input on external subdev through
+ * v4l2_subdev_call
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_query_preset(struct file *file, void *fh,
+			     struct v4l2_dv_preset *preset)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_query_preset\n");
+
+	return v4l2_subdev_call(subdev, video, query_dv_preset, preset);
+}
+
+/*
+ * vpfe_s_preset - set dv_preset on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @preset: pointer to v4l2_preset structure
+ *
+ * set dv_preset pointed by preset on external subdev through
+ * v4l2_device_call_until_err, this configures amplifier also
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_s_preset(struct file *file, void *fh,
+			 struct v4l2_dv_preset *preset)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_preset\n");
+
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
+					  video->current_ext_subdev->grp_id,
+					  video, s_dv_preset, preset);
+}
+
+/*
+ * vpfe_g_preset - get dv_preset which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @preset: pointer to v4l2_preset structure
+ *
+ * get dv_preset which is set on external subdev through
+ * v4l2_subdev_call
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_g_preset(struct file *file, void *fh,
+			 struct v4l2_dv_preset *preset)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_preset\n");
+
+	return v4l2_subdev_call(subdev, video, query_dv_preset, preset);
+}
+
+/*
+ *  Videobuf operations
+ */
+static int vpfe_videobuf_setup(struct videobuf_queue *vq,
+				unsigned int *count,
+				unsigned int *size)
+{
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_video_device *video = fh->video;
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_pipeline *pipe = &video->pipe;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
+
+	*size = video->fmt.fmt.pix.sizeimage;
+
+	if (vpfe_dev->video_limit) {
+		while (*size * *count > vpfe_dev->video_limit)
+			(*count)--;
+	}
+
+	if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) {
+		if (*count < CONT_MIN_NUM_BUFFERS)
+			*count = CONT_MIN_NUM_BUFFERS;
+	} else
+		/* for single-shot mode */
+		*count = SS_NUM_BUFFERS;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+		"count=%d, size=%d\n", *count, *size);
+
+	return 0;
+}
+
+static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
+				struct videobuf_buffer *vb,
+				enum v4l2_field field)
+{
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_video_device *video = fh->video;
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	unsigned long addr;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_prepare\n");
+
+	/* If buffer is not initialized, initialize it */
+	if (VIDEOBUF_NEEDS_INIT == vb->state) {
+		vb->width = video->fmt.fmt.pix.width;
+		vb->height = video->fmt.fmt.pix.height;
+		vb->size = video->fmt.fmt.pix.sizeimage;
+		vb->field = field;
+
+		ret = videobuf_iolock(vq, vb, NULL);
+		if (ret < 0)
+			return ret;
+
+		addr = videobuf_to_dma_contig(vb);
+		/* Make sure user addresses are aligned to 32 bytes */
+		if (!ALIGN(addr, 32))
+			return -EINVAL;
+
+		vb->state = VIDEOBUF_PREPARED;
+	}
+
+	return 0;
+}
+
+static void vpfe_videobuf_queue(struct videobuf_queue *vq,
+				struct videobuf_buffer *vb)
+{
+	/* Get the file handle object and device object */
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_video_device *video = fh->video;
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_pipeline *pipe = &video->pipe;
+	unsigned long flags;
+	unsigned long empty;
+	unsigned long addr;
+
+	empty = list_empty(&video->dma_queue);
+
+	/* add the buffer to the DMA queue */
+	spin_lock_irqsave(&video->dma_queue_lock, flags);
+	list_add_tail(&vb->queue, &video->dma_queue);
+	spin_unlock_irqrestore(&video->dma_queue_lock, flags);
+
+	/* Change state of the buffer */
+	vb->state = VIDEOBUF_QUEUED;
+
+	/* this case happens in case of single shot */
+	if (empty && video->started && (pipe->state ==
+		VPFE_PIPELINE_STREAM_SINGLESHOT)){
+		spin_lock(&video->dma_queue_lock);
+		addr = vpfe_get_next_buffer(video);
+		video->ops->queue(vpfe_dev, addr);
+
+		video->state |= VPFE_VIDEO_BUFFER_QUEUED;
+		spin_unlock(&video->dma_queue_lock);
+		/* we need to enable h/w each time in single shot */
+		if (is_pipe_ready(pipe))
+			vpfe_pipeline_set_stream(pipe,
+					VPFE_PIPELINE_STREAM_SINGLESHOT);
+	}
+}
+
+static void vpfe_videobuf_release(struct videobuf_queue *vq,
+				  struct videobuf_buffer *vb)
+{
+	struct vpfe_fh *fh = vq->priv_data;
+	struct vpfe_video_device *video = fh->video;
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");
+
+	if (video->memory == V4L2_MEMORY_MMAP)
+		videobuf_dma_contig_free(vq, vb);
+	vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static struct videobuf_queue_ops vpfe_videobuf_qops = {
+	.buf_setup      = vpfe_videobuf_setup,
+	.buf_prepare    = vpfe_videobuf_prepare,
+	.buf_queue      = vpfe_videobuf_queue,
+	.buf_release    = vpfe_videobuf_release,
+};
+
+/*
+ * vpfe_reqbufs. supported REQBUF only once opening
+ * the device.
+ */
+static int vpfe_reqbufs(struct file *file, void *priv,
+			struct v4l2_requestbuffers *req_buf)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_fh *fh = file->private_data;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) &&
+		(V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&video->lock);
+	if (ret)
+		return ret;
+
+	if (video->io_usrs != 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
+		ret = -EBUSY;
+		goto unlock_out;
+	}
+
+	video->memory = req_buf->memory;
+	videobuf_queue_dma_contig_init(&video->buffer_queue,
+				&vpfe_videobuf_qops,
+				vpfe_dev->pdev,
+				&video->irqlock,
+				req_buf->type,
+				video->fmt.fmt.pix.field,
+				sizeof(struct videobuf_buffer),
+				fh,
+				NULL);
+
+	fh->io_allowed = 1;
+	video->io_usrs = 1;
+	INIT_LIST_HEAD(&video->dma_queue);
+	ret = videobuf_reqbufs(&video->buffer_queue, req_buf);
+
+unlock_out:
+	mutex_unlock(&video->lock);
+	return ret;
+}
+
+/*
+ * vpfe_querybuf. query buffers for exchange
+ */
+static int vpfe_querybuf(struct file *file, void *priv,
+			 struct v4l2_buffer *buf)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) &&
+		(V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return  -EINVAL;
+	}
+
+	if (video->memory != V4L2_MEMORY_MMAP) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
+		return -EINVAL;
+	}
+
+	/* Call videobuf_querybuf to get information */
+	return videobuf_querybuf(&video->buffer_queue, buf);
+}
+
+/*
+ * vpfe_qbuf. queue buffers for capture or processing
+ */
+static int vpfe_qbuf(struct file *file, void *priv,
+		     struct v4l2_buffer *p)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_fh *fh = file->private_data;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) &&
+		(V4L2_BUF_TYPE_VIDEO_OUTPUT != p->type)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * If this file handle is not allowed to do IO,
+	 * return error
+	 */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+		return -EACCES;
+	}
+
+	return videobuf_qbuf(&video->buffer_queue, p);
+}
+
+/*
+ * vpfe_dqbuf. deque buffer which is done with processing
+ */
+static int vpfe_dqbuf(struct file *file, void *priv,
+		      struct v4l2_buffer *buf)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) &&
+		(V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+
+	return videobuf_dqbuf(&video->buffer_queue,
+				      buf, file->f_flags & O_NONBLOCK);
+}
+
+/* vpfe_start_capture: start streaming on all the subdevs */
+static int vpfe_start_capture(struct vpfe_video_device *video)
+{
+	struct vpfe_pipeline *pipe = &video->pipe;
+	int ret = 0;
+
+	video->started = 1;
+
+	if (is_pipe_ready(pipe))
+		ret = vpfe_pipeline_set_stream(pipe, pipe->state);
+
+	return ret;
+}
+
+/*
+ * vpfe_streamon - get dv_preset which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @buf_type: enum v4l2_buf_type
+ *
+ * queue buffer onto hardware for capture/processing and
+ * start all the subdevs which are in media chain
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_streamon(struct file *file, void *priv,
+			 enum v4l2_buf_type buf_type)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_fh *fh = file->private_data;
+	struct vpfe_ext_subdev_info *sdinfo;
+	unsigned long addr;
+
+	struct vpfe_pipeline *pipe = &video->pipe;
+	int ret = -EINVAL;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) &&
+		(V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return ret;
+	}
+
+	/* If file handle is not allowed IO, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+		return -EACCES;
+	}
+
+	sdinfo = video->current_ext_subdev;
+
+	/* If buffer queue is empty, return error */
+	if (list_empty(&video->buffer_queue.stream)) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
+		return -EIO;
+	}
+
+	/* Validate the pipeline */
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE == buf_type) {
+		ret = vpfe_video_validate_pipeline(pipe);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Call videobuf_streamon to start streaming * in videobuf */
+	ret = videobuf_streamon(&video->buffer_queue);
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&video->lock);
+	if (ret)
+		goto streamoff;
+	/* Get the next frame from the buffer queue */
+	video->next_frm = list_entry(video->dma_queue.next,
+					struct videobuf_buffer, queue);
+	video->cur_frm = video->next_frm;
+	/* Remove buffer from the buffer queue */
+	list_del(&video->cur_frm->queue);
+	/* Mark state of the current frame to active */
+	video->cur_frm->state = VIDEOBUF_ACTIVE;
+	/* Initialize field_id and started member */
+	video->field_id = 0;
+	addr = videobuf_to_dma_contig(video->cur_frm);
+
+	video->ops->queue(vpfe_dev, addr);
+
+	video->state |= VPFE_VIDEO_BUFFER_QUEUED;
+
+	/* Image processor chained in the path */
+	if (!cpu_is_davinci_dm365() &&
+	    !video->current_ext_subdev->is_camera) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "Doesn't support chaining\n");
+		goto unlock_out;
+	}
+
+	ret = 0;
+
+	ret = vpfe_start_capture(video);
+	if (ret)
+		goto unlock_out;
+
+	mutex_unlock(&video->lock);
+
+	return ret;
+unlock_out:
+	mutex_unlock(&video->lock);
+streamoff:
+	ret = videobuf_streamoff(&video->buffer_queue);
+	return ret;
+}
+
+/*
+ * vpfe_streamoff - get dv_preset which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @buf_type: enum v4l2_buf_type
+ *
+ * stop all the subdevs which are in media chain
+ *
+ * Return 0 on success, error code otherwise
+ */
+static int vpfe_streamoff(struct file *file, void *priv,
+			  enum v4l2_buf_type buf_type)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_fh *fh = file->private_data;
+	int ret = 0;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) &&
+		(V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type)) {
+		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid buf type\n");
+		return -EINVAL;
+	}
+
+	/* If io is allowed for this file handle, return error */
+	if (!fh->io_allowed) {
+		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "fh->io_allowed\n");
+		return -EACCES;
+	}
+
+	/* If streaming is not started, return error */
+	if (!video->started) {
+		v4l2_err(&vpfe_dev->v4l2_dev, "device is not started\n");
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&video->lock);
+	if (ret)
+		return ret;
+
+	vpfe_stop_capture(video);
+
+	video->pipe.state = VPFE_PIPELINE_STREAM_STOPPED;
+
+	ret = videobuf_streamoff(&video->buffer_queue);
+	mutex_unlock(&video->lock);
+
+	return ret;
+}
+
+/*
+ * vpfe_queryctrl - query for v4l2 controls which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @ctrl: pointer to v4l2_control structure
+ *
+ * get the v4l2 controls active on external subdev through
+ * v4l2_device_call_until_err
+ *
+ * Return return value returned by v4l2_device_call_until_err
+ */
+static int vpfe_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *qc)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_ext_subdev_info *sub_dev = video->current_ext_subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_queryctrl\n");
+
+	/* pass it to sub device */
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
+					  core, queryctrl, qc);
+}
+
+/*
+ * vpfe_g_ctrl - get the v4l2 controls which is set on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @ctrl: pointer to v4l2_control structure
+ *
+ * get the v4l2 controls set on external subdev through
+ * v4l2_device_call_until_err
+ *
+ * Return return value returned by v4l2_device_call_until_err
+ */
+static int vpfe_g_ctrl(struct file *file, void *priv,
+			struct v4l2_control *ctrl)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_ext_subdev_info *sub_dev = video->current_ext_subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_ctrl\n");
+
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
+					  core, g_ctrl, ctrl);
+}
+
+/*
+ * vpfe_s_ctrl - set the v4l2 controls on external subdev
+ * @file: file pointer
+ * @priv: void pointer
+ * @ctrl: pointer to v4l2_control structure
+ *
+ * call external subdev through v4l2_device_call_until_err to
+ * set v4l2 controls
+ *
+ * Return return value returned by v4l2_device_call_until_err
+ */
+static int vpfe_s_ctrl(struct file *file, void *priv,
+			     struct v4l2_control *ctrl)
+{
+	struct vpfe_video_device *video = video_drvdata(file);
+	struct vpfe_device *vpfe_dev = video->vpfe_dev;
+	struct vpfe_ext_subdev_info *sub_dev = video->current_ext_subdev;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_ctrl\n");
+
+	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sub_dev->grp_id,
+					  core, s_ctrl, ctrl);
+}
+
+/* vpfe capture ioctl operations */
+static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
+	.vidioc_querycap	 = vpfe_querycap,
+	.vidioc_g_fmt_vid_cap    = vpfe_g_fmt,
+	.vidioc_s_fmt_vid_cap    = vpfe_s_fmt,
+	.vidioc_try_fmt_vid_cap  = vpfe_try_fmt,
+	.vidioc_enum_fmt_vid_cap = vpfe_enum_fmt,
+	.vidioc_g_fmt_vid_out    = vpfe_g_fmt,
+	.vidioc_s_fmt_vid_out    = vpfe_s_fmt,
+	.vidioc_try_fmt_vid_out  = vpfe_try_fmt,
+	.vidioc_enum_fmt_vid_out = vpfe_enum_fmt,
+	.vidioc_enum_input	 = vpfe_enum_input,
+	.vidioc_g_input		 = vpfe_g_input,
+	.vidioc_s_input		 = vpfe_s_input,
+	.vidioc_querystd	 = vpfe_querystd,
+	.vidioc_s_std		 = vpfe_s_std,
+	.vidioc_enum_dv_presets	 = vpfe_enum_preset,
+	.vidioc_query_dv_preset	 = vpfe_query_preset,
+	.vidioc_s_dv_preset	 = vpfe_s_preset,
+	.vidioc_g_dv_preset	 = vpfe_g_preset,
+	.vidioc_reqbufs		 = vpfe_reqbufs,
+	.vidioc_querybuf	 = vpfe_querybuf,
+	.vidioc_qbuf		 = vpfe_qbuf,
+	.vidioc_dqbuf		 = vpfe_dqbuf,
+	.vidioc_streamon	 = vpfe_streamon,
+	.vidioc_streamoff	 = vpfe_streamoff,
+	.vidioc_queryctrl	 = vpfe_queryctrl,
+	.vidioc_g_ctrl		 = vpfe_g_ctrl,
+	.vidioc_s_ctrl		 = vpfe_s_ctrl,
+};
+
+/**
+ * VPFE video core operations
+ */
+static const struct vpfe_video_operations vpfe_video_dummy_ops = {
+};
+
+/* VPFE video init function */
+int vpfe_video_init(struct vpfe_video_device *video, const char *name)
+{
+	const char *direction;
+	int ret;
+
+	switch (video->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		direction = "output";
+		video->pad.flags = MEDIA_PAD_FL_INPUT;
+		video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+		direction = "input";
+		video->pad.flags = MEDIA_PAD_FL_OUTPUT;
+		video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Initialize field of video device */
+	video->video_dev.release = video_device_release;
+	video->video_dev.fops = &vpfe_fops;
+	video->video_dev.ioctl_ops = &vpfe_ioctl_ops;
+	video->video_dev.minor = -1;
+	video->video_dev.tvnorms = 0;
+	video->video_dev.current_norm = V4L2_STD_NTSC;
+
+	snprintf(video->video_dev.name, sizeof(video->video_dev.name),
+		 "DAVINCI VIDEO %s %s", name, direction);
+
+	/* Initialize prio member of device object */
+	v4l2_prio_init(&video->prio);
+
+	spin_lock_init(&video->irqlock);
+	spin_lock_init(&video->dma_queue_lock);
+	mutex_init(&video->lock);
+
+	ret = media_entity_init(&video->video_dev.entity,
+				1, &video->pad, 0);
+	if (ret < 0)
+		return ret;
+
+	video_set_drvdata(&video->video_dev, video);
+
+	return 0;
+}
+
+/* vpfe video device register function */
+int vpfe_video_register(struct vpfe_video_device *video,
+			struct v4l2_device *vdev)
+{
+	int ret;
+
+	video->video_dev.v4l2_dev = vdev;
+
+	ret = video_register_device(&video->video_dev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0)
+		printk(KERN_ERR "%s: could not register video device (%d)\n",
+			__func__, ret);
+
+	return ret;
+}
+
+/* vpfe video device unregister function */
+void vpfe_video_unregister(struct vpfe_video_device *video)
+{
+	if (video_is_registered(&video->video_dev)) {
+		media_entity_cleanup(&video->video_dev.entity);
+		video_unregister_device(&video->video_dev);
+	}
+}
diff --git a/drivers/media/video/davinci/vpfe_video.h b/drivers/media/video/davinci/vpfe_video.h
new file mode 100644
index 0000000..4034d6a
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_video.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2011 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
+ */
+
+/* All video device related structures will go here */
+#ifndef _VPFE_VIDEO_H
+#define _VPFE_VIDEO_H
+
+#include <media/media-entity.h>
+#include <media/videobuf-dma-contig.h>
+
+struct vpfe_device;
+
+/*
+ * struct vpfe_video_operations - VPFE video operations
+ * @queue:	Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
+ *		if there was no buffer previously queued.
+ */
+struct vpfe_video_operations {
+	void(*queue)(struct vpfe_device *vpfe_dev, unsigned long addr);
+};
+
+enum vpfe_pipeline_stream_state {
+	VPFE_PIPELINE_STREAM_STOPPED,
+	VPFE_PIPELINE_STREAM_CONTINUOUS,
+	VPFE_PIPELINE_STREAM_SINGLESHOT
+};
+
+enum vpfe_video_state {
+	/* indicates that buffer is queued */
+	VPFE_VIDEO_BUFFER_QUEUED = 1,
+};
+
+struct vpfe_pipeline {
+	/* media pipeline */
+	struct media_pipeline		*pipe;
+	/* state of the pipeline, continous,
+	single-shot or stopped */
+	enum vpfe_pipeline_stream_state	state;
+	/* input subdev, tvp514x, mt9p031, tvp7002
+	in case of continous mode */
+	struct v4l2_subdev		*input_sd;
+	/* input video node in case of single-shot mode */
+	struct vpfe_video_device	*input;
+	/* capturing video node */
+	struct vpfe_video_device	*output;
+};
+
+#define to_vpfe_pipeline(__e) \
+	container_of((__e)->pipe, struct vpfe_pipeline, pipe)
+
+#define to_vpfe_video(vdev) \
+	container_of(vdev, struct vpfe_video_device, video_dev)
+
+struct vpfe_video_device {
+	/* vpfe device */
+	struct vpfe_device			*vpfe_dev;
+	/* video dev */
+	struct video_device			video_dev;
+	/* media pad of video entity */
+	struct media_pad			pad;
+	/* video operations supported by video device */
+	const struct vpfe_video_operations	*ops;
+	/* type of the video buffers used by user */
+	enum v4l2_buf_type			type;
+	/* Indicates id of the field which is being captured */
+	u32					field_id;
+	/* pipiline for which video device is part of */
+	struct vpfe_pipeline			pipe;
+	/* Indicates whether streaming started */
+	u8					started;
+	/* Indicates state of the stream */
+	unsigned int				state;
+	/* current input at the sub device */
+	int					current_input;
+	/*
+	 * This field keeps track of type of buffer exchange mechanism
+	 * user has selected
+	 */
+	enum v4l2_memory			memory;
+	/* Used to keep track of state of the priority */
+	struct v4l2_prio_state			prio;
+	/* number of open instances of the channel */
+	u32					usrs;
+	/* flag to indicate whether decoder is initialized */
+	u8					initialized;
+	/* skip frame count */
+	u8					skip_frame_count;
+	/* skip frame count init value */
+	u8					skip_frame_count_init;
+	/* time per frame for skipping */
+	struct v4l2_fract			timeperframe;
+	/* ptr to currently selected sub device */
+	struct vpfe_ext_subdev_info		*current_ext_subdev;
+	/* Pointer pointing to current v4l2_buffer */
+	struct videobuf_buffer			*cur_frm;
+	/* Pointer pointing to next v4l2_buffer */
+	struct videobuf_buffer			*next_frm;
+	/* Used to store pixel format */
+	struct v4l2_format			fmt;
+	/* Buffer queue used in video-buf */
+	struct videobuf_queue			buffer_queue;
+	/* Queue of filled frames */
+	struct list_head			dma_queue;
+	/* Used in video-buf */
+	spinlock_t				irqlock;
+	/* IRQ lock for DMA queue */
+	spinlock_t				dma_queue_lock;
+	/* lock used to access this structure */
+	struct mutex				lock;
+	/* number of users performing IO */
+	u32					io_usrs;
+	/*
+	 * offset where second field starts from the starting of the
+	 * buffer for field seperated YCbCr formats
+	 */
+	u32					field_off;
+};
+
+void vpfe_video_unregister(struct vpfe_video_device *video);
+int vpfe_video_register(struct vpfe_video_device *video,
+			struct v4l2_device *vdev);
+int vpfe_video_init(struct vpfe_video_device *video, const char *name);
+
+void vpfe_process_buffer_complete(struct vpfe_video_device *video);
+void vpfe_schedule_bottom_field(struct vpfe_video_device *video);
+void vpfe_schedule_next_buffer(struct vpfe_video_device *video);
+unsigned long vpfe_get_next_buffer(struct vpfe_video_device *video);
+#endif
-- 
1.6.2.4


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

* [PATCH v2 7/8] davinci: vpfe: v4l2 capture driver with media interface
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (5 preceding siblings ...)
  2011-08-29 15:07 ` [PATCH v2 6/8] davinci: vpfe: add v4l2 video driver support Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-08-29 15:07 ` [PATCH v2 8/8] davinci: vpfe: build infrastructure for dm365 Manjunath Hadli
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli, Nagabhushana Netagunte

Add the vpfe capture driver which implements media controller
interface. The driver suports all the setup functionality for
all all units nnamely- ccdc, previewer, resizer, h3a, aew.
The driver supports both dm365 and Dm355.
The driver does isr registration, v4l2 device registration,
media registration and platform driver registrations.
It calls the appropriate subdevs from here to cerate the
appropriate subdevices and media entities.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/vpfe_capture.c |  793 ++++++++++++++++++
 drivers/media/video/davinci/vpfe_capture.h |  104 +++
 include/linux/davinci_vpfe.h               | 1223 ++++++++++++++++++++++++++++
 include/media/davinci/vpfe.h               |   91 ++
 4 files changed, 2211 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/davinci/vpfe_capture.c
 create mode 100644 drivers/media/video/davinci/vpfe_capture.h
 create mode 100644 include/linux/davinci_vpfe.h
 create mode 100644 include/media/davinci/vpfe.h

diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
new file mode 100644
index 0000000..62f58e9
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -0,0 +1,793 @@
+/*
+ * Copyright (C) 2011 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@ti.com>
+ *	Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
+ *
+ * Driver name : VPFE Capture driver
+ *    VPFE Capture driver allows applications to capture and stream video
+ *    frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
+ *    TVP5146 or  Raw Bayer RGB image data from an image sensor
+ *    such as Microns' MT9T001, MT9T031 etc.
+ *
+ *    These SoCs have, in common, a Video Processing Subsystem (VPSS) that
+ *    consists of a Video Processing Front End (VPFE) for capturing
+ *    video/raw image data and Video Processing Back End (VPBE) for displaying
+ *    YUV data through an in-built analog encoder or Digital LCD port. This
+ *    driver is for capture through VPFE. A typical EVM using these SoCs have
+ *    following high level configuration.
+ *
+ *    decoder(TVP5146/		YUV/
+ *	MT9T001)   -->  Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
+ *			data input              |      |
+ *							V      |
+ *						      SDRAM    |
+ *							       V
+ *							   Image Processor
+ *							       |
+ *							       V
+ *							     SDRAM
+ *    The data flow happens from a decoder connected to the VPFE over a
+ *    YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
+ *    and to the input of VPFE through an optional MUX (if more inputs are
+ *    to be interfaced on the EVM). The input data is first passed through
+ *    CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
+ *    does very little or no processing on YUV data and does pre-process Raw
+ *    Bayer RGB data through modules such as Defect Pixel Correction (DFC)
+ *    Color Space Conversion (CSC), data gain/offset etc. After this, data
+ *    can be written to SDRAM or can be connected to the image processing
+ *    block such as IPIPE (on DM355/DM365 only).
+ *
+ *    Features supported
+ *		- MMAP IO
+ *		- USERPTR IO
+ *		- Capture using TVP5146 over BT.656
+ *		- Support for interfacing decoders using sub device model
+ *		- Work with DM365 or DM355 or DM6446 CCDC to do Raw Bayer
+ *		  RGB/YUV data capture to SDRAM.
+ *		- Chaining of Image Processor
+ *		- SINGLE-SHOT mode
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/media-entity.h>
+#include <media/media-device.h>
+#include "vpfe_capture.h"
+
+static int debug;
+static int interface;
+static u32 cont_bufoffset;
+static u32 cont_bufsize;
+static u32 en_serializer;
+
+module_param(interface, bool, S_IRUGO);
+module_param(debug, bool, 0644);
+module_param(cont_bufoffset, uint, S_IRUGO);
+module_param(cont_bufsize, uint, S_IRUGO);
+module_param(en_serializer, uint, S_IRUGO);
+
+/**
+ * VPFE capture can be used for capturing video such as from TVP5146 or TVP7002
+ * and for capture raw bayer data from camera sensors such as mt9p031. At this
+ * point there is problem in co-existence of mt9p031 and tvp5146 due to i2c
+ * address collision. So set the variable below from bootargs to do either video
+ * capture or camera capture.
+ * interface = 0 - video capture (from TVP514x or such),
+ * interface = 1 - Camera capture (from mt9p031 or such)
+ * Re-visit this when we fix the co-existence issue
+ */
+MODULE_PARM_DESC(interface, "interface 0-1 (default:0)");
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+MODULE_PARM_DESC(cont_bufoffset, "Capture buffer offset (default 0)");
+MODULE_PARM_DESC(cont_bufsize, "Capture buffer size (default 0)");
+MODULE_PARM_DESC(en_serializer, "enable IPIPE serializer (default:0)");
+
+MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments");
+
+/* map mbus_fmt to pixelformat */
+void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus,
+			   struct v4l2_pix_format *pix)
+{
+	/* TODO: revisit for other format support*/
+	switch (mbus->code) {
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		pix->pixelformat = V4L2_PIX_FMT_UYVY;
+		pix->bytesperline = pix->width * 2;
+		break;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		pix->pixelformat = V4L2_PIX_FMT_UYVY;
+		pix->bytesperline = pix->width * 2;
+		break;
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+		pix->pixelformat = V4L2_PIX_FMT_UYVY;
+		pix->bytesperline = pix->width * 2;
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+		pix->pixelformat = V4L2_PIX_FMT_SBGGR16;
+		pix->bytesperline = pix->width * 2;
+		break;
+	default:
+		printk(KERN_ERR "invalid mbus code\n");
+	}
+
+	/* pitch should be 32 bytes aligned */
+	pix->bytesperline = ALIGN(pix->bytesperline, 32);
+
+	pix->sizeimage = pix->bytesperline * pix->height;
+}
+
+/* ISR for VINT0*/
+static irqreturn_t vpfe_isr(int irq, void *dev_id)
+{
+	struct vpfe_device *vpfe_dev = dev_id;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_isr\n");
+
+	ccdc_buffer_isr(&vpfe_dev->vpfe_ccdc);
+
+	prv_buffer_isr(&vpfe_dev->vpfe_previewer);
+
+	rsz_buffer_isr(&vpfe_dev->vpfe_resizer);
+
+	return IRQ_HANDLED;
+}
+
+/* vpfe_vdint1_isr - isr handler for VINT1 interrupt */
+static irqreturn_t vpfe_vdint1_isr(int irq, void *dev_id)
+{
+	struct vpfe_device *vpfe_dev = dev_id;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_vdint1_isr\n");
+
+	ccdc_vidint1_isr(&vpfe_dev->vpfe_ccdc);
+
+	return IRQ_HANDLED;
+}
+
+/* ISR for ipipe dma completion */
+static irqreturn_t vpfe_imp_dma_isr(int irq, void *dev_id)
+{
+	struct vpfe_device *vpfe_dev = dev_id;
+
+	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_imp_dma_isr\n");
+
+	prv_dma_isr(&vpfe_dev->vpfe_previewer);
+
+	rsz_dma_isr(&vpfe_dev->vpfe_resizer);
+
+	return IRQ_HANDLED;
+}
+
+/* set user setting of serializer in ipipe */
+static void vpfe_initialize(void)
+{
+	/* inform user choice on serializer to ipipe */
+	enable_serializer(en_serializer);
+}
+
+/**
+ * vpfe_disable_clock() - Disable clocks for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Disables clocks defined in vpfe configuration. The function
+ * assumes that at least one clock is to be defined which is
+ * true as of now.
+ */
+static void vpfe_disable_clock(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
+	int i;
+
+	for (i = 0; i < vpfe_cfg->num_clocks; i++) {
+		clk_disable(vpfe_dev->clks[i]);
+		clk_put(vpfe_dev->clks[i]);
+	}
+
+	kzfree(vpfe_dev->clks);
+	v4l2_info(vpfe_dev->pdev->driver, "vpfe capture clocks disabled\n");
+}
+
+/**
+ * vpfe_enable_clock() - Enable clocks for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Enables clocks defined in vpfe configuration. The function
+ * assumes that at least one clock is to be defined which is
+ * true as of now.
+ */
+static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
+	int ret = -EFAULT;
+	int i;
+
+	if (!vpfe_cfg->num_clocks)
+		return 0;
+
+	vpfe_dev->clks = kzalloc(vpfe_cfg->num_clocks *
+				   sizeof(struct clock *), GFP_KERNEL);
+
+	if (NULL == vpfe_dev->clks) {
+		v4l2_err(vpfe_dev->pdev->driver, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < vpfe_cfg->num_clocks; i++) {
+		if (NULL == vpfe_cfg->clocks[i]) {
+			v4l2_err(vpfe_dev->pdev->driver,
+				"clock %s is not defined in vpfe config\n",
+				vpfe_cfg->clocks[i]);
+			goto out;
+		}
+
+		vpfe_dev->clks[i] = clk_get(vpfe_dev->pdev,
+					      vpfe_cfg->clocks[i]);
+		if (NULL == vpfe_dev->clks[i]) {
+			v4l2_err(vpfe_dev->pdev->driver,
+				"Failed to get clock %s\n",
+				vpfe_cfg->clocks[i]);
+			goto out;
+		}
+
+		if (clk_enable(vpfe_dev->clks[i])) {
+			v4l2_err(vpfe_dev->pdev->driver,
+				"vpfe clock %s not enabled\n",
+				vpfe_cfg->clocks[i]);
+			goto out;
+		}
+
+		v4l2_info(vpfe_dev->pdev->driver, "vpss clock %s enabled",
+			  vpfe_cfg->clocks[i]);
+	}
+
+	return 0;
+out:
+	for (i = 0; i < vpfe_cfg->num_clocks; i++) {
+		if (vpfe_dev->clks[i])
+			clk_put(vpfe_dev->clks[i]);
+	}
+
+	v4l2_err(vpfe_dev->pdev->driver,
+				"failed to enable clocks\n");
+
+	kzfree(vpfe_dev->clks);
+	return ret;
+}
+
+/**
+ * vpfe_detach_irq() - Detach IRQs for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Detach all IRQs defined in vpfe configuration.
+ */
+static void vpfe_detach_irq(struct vpfe_device *vpfe_dev)
+{
+	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+	free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
+	free_irq(vpfe_dev->imp_dma_irq, vpfe_dev);
+}
+
+/**
+ * vpfe_attach_irq() - Attach IRQs for vpfe capture driver
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * Attach all IRQs defined in vpfe configuration.
+ */
+static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
+{
+	int ret = 0;
+
+	ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
+			"vpfe_capture0", vpfe_dev);
+	if (ret < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"Error: requesting VINT0 interrupt\n");
+		return ret;
+	}
+
+	ret = request_irq(vpfe_dev->ccdc_irq1,
+					vpfe_vdint1_isr,
+					IRQF_DISABLED,
+					"vpfe_capture1", vpfe_dev);
+	if (ret < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"Error: requesting VINT1 interrupt\n");
+		free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+		return ret;
+	}
+
+	ret = request_irq(vpfe_dev->imp_dma_irq,
+				vpfe_imp_dma_isr,
+				IRQF_DISABLED,
+				"Imp_Sdram_Irq",
+				vpfe_dev);
+	if (ret < 0) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+				"Error: requesting IMP"
+				" IRQ interrupt\n");
+		free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
+		free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * register_i2c_devices() - register all i2c v4l2 subdevs
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * register all i2c v4l2 subdevs
+ */
+static int register_i2c_devices(struct vpfe_device *vpfe_dev)
+{
+	struct vpfe_ext_subdev_info *sdinfo;
+	struct vpfe_config *vpfe_cfg;
+	struct i2c_adapter *i2c_adap;
+	unsigned int num_subdevs;
+	int ret;
+	int i;
+	int k;
+
+	vpfe_cfg = vpfe_dev->cfg;
+
+	i2c_adap = i2c_get_adapter(1);
+	num_subdevs = vpfe_cfg->num_subdevs;
+
+	vpfe_dev->sd = kzalloc(sizeof(struct v4l2_subdev *) *num_subdevs,
+			       GFP_KERNEL);
+
+	if (NULL == vpfe_dev->sd) {
+		v4l2_err(&vpfe_dev->v4l2_dev,
+			"unable to allocate memory for subdevice pointers\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, k = 0; i < num_subdevs; i++) {
+		sdinfo = &vpfe_cfg->sub_devs[i];
+		/**
+		 * register subdevices based on interface setting. Currently
+		 * tvp5146 and mt9p031 cannot co-exists due to i2c address
+		 * conflicts. So only one of them is registered. Re-visit this
+		 * once we have support for i2c switch handling in i2c driver
+		 * framework
+		 */
+
+		if (interface == sdinfo->is_camera) {
+			/* setup input path */
+			if (vpfe_cfg->setup_input) {
+				if (vpfe_cfg->setup_input(sdinfo->grp_id) < 0) {
+					ret = -EFAULT;
+					v4l2_info(&vpfe_dev->v4l2_dev, "could"
+							" not setup input for %s\n",
+							sdinfo->module_name);
+					goto probe_sd_out;
+				}
+			}
+			/* Load up the subdevice */
+			vpfe_dev->sd[k] =
+				v4l2_i2c_new_subdev_board(
+						  &vpfe_dev->v4l2_dev,
+						  i2c_adap,
+						  &sdinfo->board_info,
+						  NULL,
+						1);
+			if (vpfe_dev->sd[k]) {
+				v4l2_info(&vpfe_dev->v4l2_dev,
+						"v4l2 sub device %s registered\n",
+						sdinfo->module_name);
+
+				vpfe_dev->sd[k]->grp_id = sdinfo->grp_id;
+				k++;
+
+				sdinfo->registered = 1;
+			}
+			} else {
+				v4l2_info(&vpfe_dev->v4l2_dev,
+						"v4l2 sub device %s is not registered\n",
+						sdinfo->module_name);
+			}
+	}
+
+	vpfe_dev->num_ext_subdevs = k;
+
+	return 0;
+
+probe_sd_out:
+	kzfree(vpfe_dev->sd);
+
+	return ret;
+}
+
+/**
+ * vpfe_register_entities() - register all v4l2 subdevs and media entities
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * register all v4l2 subdevs, media entities, and creates links
+ * between entities
+ */
+static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
+{
+	unsigned int flags = 0;
+	int ret;
+	int i;
+
+	/* register i2c devices first */
+	ret = register_i2c_devices(vpfe_dev);
+	if (ret)
+		return ret;
+
+	/* register rest of the sub-devs */
+	ret = vpfe_ccdc_register_entities(&vpfe_dev->vpfe_ccdc,
+					  &vpfe_dev->v4l2_dev);
+	if (ret)
+		return ret;
+
+	ret = vpfe_previewer_register_entities(&vpfe_dev->vpfe_previewer,
+					       &vpfe_dev->v4l2_dev);
+	if (ret)
+		goto out_ccdc_register;
+
+	ret = vpfe_resizer_register_entities(&vpfe_dev->vpfe_resizer,
+					     &vpfe_dev->v4l2_dev);
+	if (ret)
+		goto out_previewer_register;
+
+	ret = vpfe_aew_register_entities(&vpfe_dev->vpfe_aew,
+					 &vpfe_dev->v4l2_dev);
+	if (ret)
+		goto out_resizer_register;
+
+	ret = vpfe_af_register_entities(&vpfe_dev->vpfe_af,
+					&vpfe_dev->v4l2_dev);
+	if (ret)
+		goto out_aew_register;
+
+	/* create links now, starting with external(i2c) entities */
+	for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) {
+		/* if entity has no pads (ex: amplifier),
+		   cant establish link */
+		if (vpfe_dev->sd[i]->entity.num_pads) {
+			ret = media_entity_create_link(&vpfe_dev->sd[i]->entity,
+				0, &vpfe_dev->vpfe_ccdc.subdev.entity,
+				0, flags);
+			if (ret < 0)
+				goto out_resizer_register;
+		}
+	}
+
+	ret = media_entity_create_link(&vpfe_dev->vpfe_ccdc.subdev.entity,
+					1, &vpfe_dev->vpfe_aew.subdev.entity,
+					0, flags);
+	if (ret < 0)
+		goto out_resizer_register;
+
+	ret = media_entity_create_link(&vpfe_dev->vpfe_ccdc.subdev.entity,
+					1, &vpfe_dev->vpfe_af.subdev.entity,
+					0, flags);
+	if (ret < 0)
+		goto out_resizer_register;
+
+	ret = media_entity_create_link(&vpfe_dev->vpfe_ccdc.subdev.entity,
+				       1,
+				       &vpfe_dev->vpfe_previewer.subdev.entity,
+				       0, flags);
+	if (ret < 0)
+		goto out_resizer_register;
+
+	ret = media_entity_create_link(&vpfe_dev->vpfe_previewer.subdev.entity,
+				       1, &vpfe_dev->vpfe_resizer.subdev.entity,
+				       0, flags);
+	if (ret < 0)
+		goto out_resizer_register;
+
+	return 0;
+
+out_aew_register:
+	vpfe_aew_unregister_entities(&vpfe_dev->vpfe_aew);
+out_resizer_register:
+	vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer);
+out_previewer_register:
+	vpfe_previewer_unregister_entities(&vpfe_dev->vpfe_previewer);
+out_ccdc_register:
+	vpfe_ccdc_unregister_entities(&vpfe_dev->vpfe_ccdc);
+	return ret;
+}
+
+/**
+ * vpfe_unregister_entities() - unregister all v4l2 subdevs and media entities
+ * @vpfe_dev - ptr to vpfe capture device
+ *
+ * unregister all v4l2 subdevs and media entities
+ */
+static void vpfe_unregister_entities(struct vpfe_device *vpfe_dev)
+{
+	vpfe_ccdc_unregister_entities(&vpfe_dev->vpfe_ccdc);
+	vpfe_previewer_unregister_entities(&vpfe_dev->vpfe_previewer);
+	vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer);
+	vpfe_aew_unregister_entities(&vpfe_dev->vpfe_aew);
+	vpfe_af_unregister_entities(&vpfe_dev->vpfe_af);
+}
+
+/**
+ * vpfe_cleanup_modules() - cleanup all non-i2c v4l2 subdevs
+ * @vpfe_dev - ptr to vpfe capture device
+ * @pdev - pointer to platform device
+ *
+ * cleanup all v4l2 subdevs
+ */
+static void vpfe_cleanup_modules(struct vpfe_device *vpfe_dev,
+				 struct platform_device *pdev)
+{
+	vpfe_ccdc_cleanup(pdev);
+	vpfe_previewer_cleanup(pdev);
+	vpfe_aew_cleanup();
+	vpfe_af_cleanup();
+}
+
+/**
+ * vpfe_initialize_modules() - initialize all non-i2c v4l2 subdevs
+ * @vpfe_dev - ptr to vpfe capture device
+ * @pdev - pointer to platform device
+ *
+ * intialize all v4l2 subdevs and media entities
+ */
+static int vpfe_initialize_modules(struct vpfe_device *vpfe_dev,
+				   struct platform_device *pdev)
+{
+	int ret;
+
+	ret = vpfe_ccdc_init(&vpfe_dev->vpfe_ccdc, pdev);
+	if (ret)
+		return ret;
+
+	ret = vpfe_previewer_init(&vpfe_dev->vpfe_previewer, pdev);
+	if (ret)
+		goto out_ccdc_init;
+
+	ret = vpfe_resizer_init(&vpfe_dev->vpfe_resizer, pdev);
+	if (ret)
+		goto out_previewer_init;
+
+	ret = vpfe_aew_init(&vpfe_dev->vpfe_aew, pdev);
+	if (ret)
+		goto out_previewer_init;
+
+	ret = vpfe_af_init(&vpfe_dev->vpfe_af, pdev);
+	if (ret)
+		goto out_aew_init;
+
+	return 0;
+
+out_aew_init:
+	vpfe_aew_cleanup();
+out_previewer_init:
+	vpfe_previewer_cleanup(pdev);
+out_ccdc_init:
+	vpfe_ccdc_cleanup(pdev);
+
+	return ret;
+}
+
+/**
+ * vpfe_probe : vpfe probe function
+ * @pdev: platform device pointer
+ *
+ * This function creates device entries by register itself to the V4L2 driver
+ * and initializes fields of each device objects
+ */
+static __devinit int vpfe_probe(struct platform_device *pdev)
+{
+	struct vpfe_device *vpfe_dev;
+	struct resource *res1;
+	unsigned long phys_end_kernel;
+	int ret = -ENOMEM;
+	int err;
+	size_t size;
+
+	vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);
+	if (!vpfe_dev) {
+		v4l2_err(pdev->dev.driver,
+			"Failed to allocate memory for vpfe_dev\n");
+		return ret;
+	}
+
+	if (NULL == pdev->dev.platform_data) {
+		v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+
+	vpfe_dev->cfg = pdev->dev.platform_data;
+
+	if (NULL == vpfe_dev->cfg->card_name ||
+	    NULL == vpfe_dev->cfg->sub_devs) {
+		v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+
+	/* Get VINT0 irq resource */
+	res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res1) {
+		v4l2_err(pdev->dev.driver,
+			 "Unable to get interrupt for VINT0\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+	vpfe_dev->ccdc_irq0 = res1->start;
+
+	/* Get VINT1 irq resource */
+	res1 = platform_get_resource(pdev,
+				IORESOURCE_IRQ, 1);
+	if (!res1) {
+		v4l2_err(pdev->dev.driver,
+			 "Unable to get interrupt for VINT1\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+	vpfe_dev->ccdc_irq1 = res1->start;
+
+	/* Get DMA irq resource */
+	res1 = platform_get_resource(pdev,
+				IORESOURCE_IRQ, 2);
+	if (!res1) {
+		v4l2_err(pdev->dev.driver,
+			 "Unable to get interrupt for DMA\n");
+		ret = -ENOENT;
+		goto probe_free_dev_mem;
+	}
+	vpfe_dev->imp_dma_irq = res1->start;
+
+	vpfe_dev->pdev = &pdev->dev;
+
+	vpfe_initialize();
+
+	/* enable vpss clocks */
+	ret = vpfe_enable_clock(vpfe_dev);
+	if (ret)
+		goto probe_free_dev_mem;
+
+	if (vpfe_initialize_modules(vpfe_dev, pdev))
+		goto probe_disable_clock;
+
+	vpfe_dev->media_dev.dev = vpfe_dev->pdev;
+	strcpy((char *)&vpfe_dev->media_dev.model, "davinci-media");
+	ret = media_device_register(&vpfe_dev->media_dev);
+	if (ret) {
+		v4l2_err(pdev->dev.driver,
+			"Unable to register media device.\n");
+		goto probe_out_entities_cleanup;
+	}
+
+	vpfe_dev->v4l2_dev.mdev = &vpfe_dev->media_dev;
+
+	ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
+	if (ret) {
+		v4l2_err(pdev->dev.driver,
+			"Unable to register v4l2 device.\n");
+		goto probe_out_media_unregister;
+	}
+	v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
+
+	/* set the driver data in platform device */
+	platform_set_drvdata(pdev, vpfe_dev);
+
+	/* register subdevs/entities */
+	if (vpfe_register_entities(vpfe_dev))
+		goto probe_out_v4l2_unregister;
+
+	ret = vpfe_attach_irq(vpfe_dev);
+	if (ret)
+		goto probe_out_entities_unregister;
+
+	if (cont_bufsize) {
+		/* attempt to determine the end of Linux kernel memory */
+		phys_end_kernel = virt_to_phys((void *)PAGE_OFFSET) +
+			(num_physpages << PAGE_SHIFT);
+		size = cont_bufsize;
+		phys_end_kernel += cont_bufoffset;
+		err = dma_declare_coherent_memory(&pdev->dev, phys_end_kernel,
+				phys_end_kernel, size,
+				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+		if (!err) {
+			dev_err(&pdev->dev, "Unable to declare MMAP memory.\n");
+			ret = -ENOENT;
+			goto probe_detach_irq;
+		}
+		vpfe_dev->video_limit = size;
+	}
+
+	return 0;
+
+probe_detach_irq:
+	vpfe_detach_irq(vpfe_dev);
+probe_out_entities_unregister:
+	vpfe_unregister_entities(vpfe_dev);
+	kzfree(vpfe_dev->sd);
+probe_out_v4l2_unregister:
+	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
+probe_out_media_unregister:
+	media_device_unregister(&vpfe_dev->media_dev);
+probe_out_entities_cleanup:
+	vpfe_cleanup_modules(vpfe_dev, pdev);
+probe_disable_clock:
+	vpfe_disable_clock(vpfe_dev);
+probe_free_dev_mem:
+	kzfree(vpfe_dev);
+
+	return ret;
+}
+
+/*
+ * vpfe_remove : This function un-registers device from V4L2 driver
+ */
+static int vpfe_remove(struct platform_device *pdev)
+{
+	struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
+
+	v4l2_info(pdev->dev.driver, "vpfe_remove\n");
+
+	kzfree(vpfe_dev->sd);
+	vpfe_detach_irq(vpfe_dev);
+	vpfe_unregister_entities(vpfe_dev);
+	vpfe_cleanup_modules(vpfe_dev, pdev);
+	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
+	media_device_unregister(&vpfe_dev->media_dev);
+	vpfe_disable_clock(vpfe_dev);
+	kzfree(vpfe_dev);
+
+	return 0;
+}
+
+static struct platform_driver vpfe_driver = {
+	.driver = {
+		.name = CAPTURE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = vpfe_probe,
+	.remove = __devexit_p(vpfe_remove),
+};
+
+/**
+ * vpfe_init : This function registers device driver
+ */
+static __init int vpfe_init(void)
+{
+	/* Register driver to the kernel */
+	return platform_driver_register(&vpfe_driver);
+}
+
+/**
+ * vpfe_cleanup : This function un-registers device driver
+ */
+static void vpfe_cleanup(void)
+{
+	platform_driver_unregister(&vpfe_driver);
+}
+
+module_init(vpfe_init);
+module_exit(vpfe_cleanup);
diff --git a/drivers/media/video/davinci/vpfe_capture.h b/drivers/media/video/davinci/vpfe_capture.h
new file mode 100644
index 0000000..b6181e5
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_capture.h
@@ -0,0 +1,104 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _VPFE_CAPTURE_H
+#define _VPFE_CAPTURE_H
+
+#ifdef __KERNEL__
+
+/* Header files */
+#include <media/v4l2-dev.h>
+#include <linux/v4l2-subdev.h>
+#include <linux/videodev2.h>
+
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf-dma-contig.h>
+#include "imp_hw_if.h"
+#include "dm3xx_ipipeif.h"
+#include "dm365_ipipe.h"
+#include <media/davinci/vpfe.h>
+#include "vpfe_video.h"
+#include "vpfe_ccdc.h"
+#include "vpfe_resizer.h"
+#include "vpfe_previewer.h"
+#include "vpfe_aew.h"
+#include "vpfe_af.h"
+
+/* Macros */
+#define VPFE_MAJOR_RELEASE              0
+#define VPFE_MINOR_RELEASE              0
+#define VPFE_BUILD                      1
+#define VPFE_CAPTURE_VERSION_CODE       ((VPFE_MAJOR_RELEASE << 16) | \
+					(VPFE_MINOR_RELEASE << 8)  | \
+					VPFE_BUILD)
+
+#define to_vpfe_device(ptr_module)				\
+	container_of(ptr_module, struct vpfe_device, vpfe_##ptr_module)
+#define to_device(ptr_module)						\
+	(to_vpfe_device(ptr_module)->dev)
+
+struct vpfe_device {
+	/* external registered sub devices */
+	struct v4l2_subdev		**sd;
+	/* number of registered external subdevs */
+	unsigned int			num_ext_subdevs;
+	/* vpfe cfg */
+	struct vpfe_config		*cfg;
+	/* clock ptrs for vpfe capture */
+	struct clk			**clks;
+	/* V4l2 device */
+	struct v4l2_device		v4l2_dev;
+	/* parent device */
+	struct device			*pdev;
+	/* IRQ number for DMA transfer completion at the image processor */
+	unsigned int			imp_dma_irq;
+	/* CCDC IRQs used when CCDC/ISIF output to SDRAM */
+	unsigned int			ccdc_irq0;
+	unsigned int			ccdc_irq1;
+	/* maximum video memory that is available*/
+	unsigned int			video_limit;
+	/* media device */
+	struct media_device		media_dev;
+	/* ccdc subdevice */
+	struct vpfe_ccdc_device		vpfe_ccdc;
+	/* resizer subdevice */
+	struct vpfe_resizer_device	vpfe_resizer;
+	/* previewer subdevice */
+	struct vpfe_previewer_device	vpfe_previewer;
+	/* aew subdevice */
+	struct vpfe_aew_device		vpfe_aew;
+	/* af subdevice */
+	struct vpfe_af_device		vpfe_af;
+};
+
+/* File handle structure */
+struct vpfe_fh {
+	struct vpfe_video_device *video;
+	/* Indicates whether this file handle is doing IO */
+	u8 io_allowed;
+	/* Used to keep track priority of this instance */
+	enum v4l2_priority prio;
+};
+
+void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus,
+			   struct v4l2_pix_format *pix);
+
+#endif				/* End of __KERNEL__ */
+#endif				/* _DAVINCI_VPFE_H */
diff --git a/include/linux/davinci_vpfe.h b/include/linux/davinci_vpfe.h
new file mode 100644
index 0000000..87332ab
--- /dev/null
+++ b/include/linux/davinci_vpfe.h
@@ -0,0 +1,1223 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _DAVINCI_VPFE_INCLUDE_H
+#define _DAVINCI_VPFE_INCLUDE_H
+
+#include <linux/dm3xx_ipipeif.h>
+
+#define IMP_MODE_CONTINUOUS	0
+#define IMP_MODE_SINGLE_SHOT	1
+#define IMP_MODE_INVALID	2
+#define IMP_MODE_NOT_CONFIGURED	4
+#define IMP_MAX_NAME_SIZE	40
+
+enum imp_data_paths {
+	IMP_RAW2RAW = 1,
+	IMP_RAW2YUV = 2,
+	IMP_YUV2YUV = 4
+};
+
+enum imp_pix_formats {
+	IMP_BAYER_8BIT_PACK,
+	IMP_BAYER_8BIT_PACK_ALAW,
+	IMP_BAYER_8BIT_PACK_DPCM,
+	IMP_BAYER_12BIT_PACK,
+	IMP_BAYER, /* 16 bit */
+	IMP_UYVY,
+	IMP_YUYV,
+	IMP_RGB565,
+	IMP_RGB888,
+	IMP_YUV420SP,
+	IMP_420SP_Y,
+	IMP_420SP_C,
+};
+
+struct imp_window {
+	/* horizontal size */
+	unsigned int width;
+	/* vertical size */
+	unsigned int height;
+	/* horizontal start position */
+	unsigned int hst;
+	/* vertical start position */
+	unsigned int vst;
+};
+
+/* structure used by application to query the modules
+ * available in the image processorr for preview the input
+ * image. Used for PREV_QUERY_CAP IOCTL
+ */
+struct prev_cap {
+	/* application use this to iterate over the available
+	 * modules. stop when -EINVAL return code is returned by
+	 * the driver
+	 */
+	unsigned short index;
+	/* Version of the preview module */
+	char version[IMP_MAX_NAME_SIZE];
+	/* Module IDs as defined above */
+	unsigned short module_id;
+	/* control operation allowed in continuous mode ?
+	 * 1 - allowed, 0 - not allowed
+	 */
+	char control;
+	/* path on which the module is sitting */
+	enum imp_data_paths path;
+	char module_name[IMP_MAX_NAME_SIZE];
+};
+
+/* struct to configure preview modules for which structures
+ * are defined above. Used by PREV_SET_PARAM or PREV_GET_PARAM IOCTLs.
+ */
+struct prev_module_param {
+	/* Version of the preview module */
+	char version[IMP_MAX_NAME_SIZE];
+	/* Length of the module config structure */
+	unsigned short len;
+	/* Module IDs as defined above */
+	unsigned short module_id;
+	/* Ptr to module config parameter. If SET command and is NULL
+	 * module is reset to power on reset values
+	 */
+	void *param;
+};
+
+/* Structure for configuring the previewer driver.
+ * Used in PREV_SET_CONFIG/PREV_GET_CONFIG IOCTLs
+ */
+struct prev_channel_config {
+	/* Length of the user configuration */
+	unsigned short len;
+	/* Ptr to either preview_single_shot_config or
+	 * preview_continuous_config depending on oper_mode
+	 */
+	void *config;
+};
+
+struct prev_control {
+	/* Version of the preview module */
+	char version[IMP_MAX_NAME_SIZE];
+	/* Length of the module config structure */
+	unsigned short len;
+	/* Module IDs as defined above */
+	unsigned short module_id;
+	/* Ptr to module config parameter. If SET command and is NULL
+	 * module is reset to power on reset values
+	 */
+	void *param;
+};
+
+/* Structure for RSZ_SET_CONFIG and RSZ_GET_CONFIG IOCTLs */
+struct rsz_channel_config {
+	/* Chain this resizer at the previewer output */
+	unsigned char chain;
+	/* Length of the user configuration */
+	unsigned short len;
+	/* ptr to either rsz_single_shot_config or rsz_continuous_config
+	 * depending on oper_mode
+	 */
+	void *config;
+};
+
+/* RSZ_RECONFIG IOCTL. Used for re-configuring resizer
+ * before doing RSZ_RESIZE. This is a IOCTL to do fast reconfiguration
+ * of resizer. This assumes that corresponding resizer is already enabled
+ * through SET_CONFIG. This is used when the input image to be resized
+ * is either Y or C plane of a YUV 420 image. Typically, when channel is
+ * first configured, it is set up to resize Y plane. Then if application
+ * needs to resize C plane, this ioctl is called to switch the channel
+ * to resize C plane.
+ */
+struct rsz_reconfig {
+	enum imp_pix_formats pix_format;
+};
+
+/* ioctls definition for previewer operations */
+#define PREV_IOC_BASE		'P'
+#define PREV_S_PARAM		_IOWR(PREV_IOC_BASE, 1,\
+					struct prev_module_param)
+#define PREV_G_PARAM		_IOWR(PREV_IOC_BASE, 2,\
+					struct prev_module_param)
+#define PREV_ENUM_CAP		_IOWR(PREV_IOC_BASE, 3, struct prev_cap)
+#define PREV_S_CONFIG		_IOWR(PREV_IOC_BASE, 4,\
+					struct prev_channel_config)
+#define PREV_G_CONFIG		_IOWR(PREV_IOC_BASE, 5,\
+					struct prev_channel_config)
+
+/* ioctls definitions for resizer operations */
+#define RSZ_IOC_BASE		'R'
+#define RSZ_S_CONFIG		_IOWR(RSZ_IOC_BASE, 1,\
+					struct rsz_channel_config)
+#define RSZ_G_CONFIG		_IOWR(RSZ_IOC_BASE, 2,\
+					struct rsz_channel_config)
+
+
+/**********************************************************************
+**      Previewer API Structures
+**********************************************************************/
+
+/* Previewer module IDs used in PREV_SET/GET_PARAM IOCTL. Some
+ * modules can be also be updated during IPIPE operation. They are
+ * marked as control ID
+ */
+/* LUT based Defect Pixel Correction */
+#define PREV_LUTDPC		1
+/* On the fly (OTF) Defect Pixel Correction */
+#define PREV_OTFDPC		2
+/* Noise Filter - 1 */
+#define PREV_NF1		3
+/* Noise Filter - 2 */
+#define PREV_NF2		4
+/* White Balance.  Also a control ID */
+#define PREV_WB			5
+/* 1st RGB to RBG Blend module */
+#define PREV_RGB2RGB_1		6
+/* 2nd RGB to RBG Blend module */
+#define PREV_RGB2RGB_2		7
+/* Gamma Correction */
+#define PREV_GAMMA		8
+/* 3D LUT color conversion */
+#define PREV_3D_LUT		9
+/* RGB to YCbCr module */
+#define PREV_RGB2YUV		10
+/* YUV 422 conversion module */
+#define PREV_YUV422_CONV	11
+/* Luminance Adjustment module.  Also a control ID */
+#define PREV_LUM_ADJ		12
+/* Edge Enhancement */
+#define PREV_YEE		13
+/* Green Imbalance Correction */
+#define PREV_GIC		14
+/* CFA Interpolation */
+#define PREV_CFA		15
+/* Chroma Artifact Reduction */
+#define PREV_CAR		16
+/* Chroma Gain Suppression */
+#define PREV_CGS		17
+/* Global brighness and contrast control */
+#define PREV_GBCE		18
+/* Last module ID */
+#define PREV_MAX_MODULES	18
+
+struct ipipe_float_u16 {
+	unsigned short integer;
+	unsigned short decimal;
+};
+
+struct ipipe_float_s16 {
+	short integer;
+	unsigned short decimal;
+};
+
+struct ipipe_float_u8 {
+	unsigned char integer;
+	unsigned char decimal;
+};
+
+struct ipipe_win {
+	/* vertical start line */
+	unsigned int vst;
+	/* horizontal start pixel */
+	unsigned int hst;
+	/* width */
+	unsigned int width;
+	/* height */
+	unsigned int height;
+};
+
+/* Copy method selection for vertical correction
+ *  Used when ipipe_dfc_corr_meth is PREV_DPC_CTORB_AFTER_HINT
+ */
+enum ipipe_dpc_corr_meth {
+	/* replace by black or white dot specified by repl_white */
+	IPIPE_DPC_REPL_BY_DOT = 0,
+	/* Copy from left */
+	IPIPE_DPC_CL,
+	/* Copy from right */
+	IPIPE_DPC_CR,
+	/* Horizontal interpolation */
+	IPIPE_DPC_H_INTP,
+	/* Vertical interpolation */
+	IPIPE_DPC_V_INTP,
+	/* Copy from top  */
+	IPIPE_DPC_CT,
+	/* Copy from bottom */
+	IPIPE_DPC_CB,
+	/* 2D interpolation */
+	IPIPE_DPC_2D_INTP,
+};
+
+struct ipipe_lutdpc_entry {
+	/* Horizontal position */
+	unsigned short horz_pos;
+	/* vertical position */
+	unsigned short vert_pos;
+	enum ipipe_dpc_corr_meth method;
+};
+
+#define MAX_SIZE_DPC 256
+/* Struct for configuring DPC module */
+struct prev_lutdpc {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* 0 - replace with black dot, 1 - white dot when correction
+	 * method is  IPIPE_DFC_REPL_BY_DOT=0,
+	 */
+	unsigned char repl_white;
+	/* number of entries in the correction table. Currently only
+	 * support upto 256 entries. infinite mode is not supported
+	 */
+	unsigned short dpc_size;
+	struct ipipe_lutdpc_entry *table;
+};
+
+enum ipipe_otfdpc_det_meth {
+	IPIPE_DPC_OTF_MIN_MAX,
+	IPIPE_DPC_OTF_MIN_MAX2
+};
+
+struct ipipe_otfdpc_thr {
+	unsigned short r;
+	unsigned short gr;
+	unsigned short gb;
+	unsigned short b;
+};
+
+enum ipipe_otfdpc_alg {
+	IPIPE_OTFDPC_2_0,
+	IPIPE_OTFDPC_3_0
+};
+
+struct prev_otfdpc_2_0 {
+	/* defect detection threshold for MIN_MAX2 method  (DPC 2.0 alg) */
+	struct ipipe_otfdpc_thr det_thr;
+	/* defect correction threshold for MIN_MAX2 method (DPC 2.0 alg) or
+	 * maximum value for MIN_MAX method
+	 */
+	struct ipipe_otfdpc_thr corr_thr;
+};
+
+struct prev_otfdpc_3_0 {
+	/* DPC3.0 activity adj shf. activity = (max2-min2) >> (6 -shf)
+	 */
+	unsigned char act_adj_shf;
+	/* DPC3.0 detection threshold, THR */
+	unsigned short det_thr;
+	/* DPC3.0 detection threshold slope, SLP */
+	unsigned short det_slp;
+	/* DPC3.0 detection threshold min, MIN */
+	unsigned short det_thr_min;
+	/* DPC3.0 detection threshold max, MAX */
+	unsigned short det_thr_max;
+	/* DPC3.0 correction threshold, THR */
+	unsigned short corr_thr;
+	/* DPC3.0 correction threshold slope, SLP */
+	unsigned short corr_slp;
+	/* DPC3.0 correction threshold min, MIN */
+	unsigned short corr_thr_min;
+	/* DPC3.0 correction threshold max, MAX */
+	unsigned short corr_thr_max;
+};
+
+struct prev_otfdpc {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* defect detection method */
+	enum ipipe_otfdpc_det_meth det_method;
+	/* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
+	 * used
+	 */
+	enum ipipe_otfdpc_alg alg;
+	union {
+		/* if alg is IPIPE_OTFDPC_2_0 */
+		struct prev_otfdpc_2_0 dpc_2_0;
+		/* if alg is IPIPE_OTFDPC_3_0 */
+		struct prev_otfdpc_3_0 dpc_3_0;
+	} alg_cfg;
+};
+
+/* Threshold values table size */
+#define IPIPE_NF_THR_TABLE_SIZE 8
+/* Intensity values table size */
+#define IPIPE_NF_STR_TABLE_SIZE 8
+
+/* NF, sampling method for green pixels */
+enum ipipe_nf_sampl_meth {
+	/* Same as R or B */
+	IPIPE_NF_BOX,
+	/* Diamond mode */
+	IPIPE_NF_DIAMOND
+};
+
+/* Struct for configuring NF module */
+struct prev_nf {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* Sampling method for green pixels */
+	enum ipipe_nf_sampl_meth gr_sample_meth;
+	/* Down shift value in LUT reference address
+	 */
+	unsigned char shft_val;
+	/* Spread value in NF algorithm
+	 */
+	unsigned char spread_val;
+	/* Apply LSC gain to threshold. Enable this only if
+	 * LSC is enabled in ISIF
+	 */
+	unsigned char apply_lsc_gain;
+	/* Threshold values table */
+	unsigned short thr[IPIPE_NF_THR_TABLE_SIZE];
+	/* intensity values table */
+	unsigned char str[IPIPE_NF_STR_TABLE_SIZE];
+	/* Edge detection minimum threshold */
+	unsigned short edge_det_min_thr;
+	/* Edge detection maximum threshold */
+	unsigned short edge_det_max_thr;
+};
+
+enum ipipe_gic_alg {
+	IPIPE_GIC_ALG_CONST_GAIN,
+	IPIPE_GIC_ALG_ADAPT_GAIN
+};
+
+enum ipipe_gic_thr_sel {
+	IPIPE_GIC_THR_REG,
+	IPIPE_GIC_THR_NF
+};
+
+enum ipipe_gic_wt_fn_type {
+	/* Use difference as index */
+	IPIPE_GIC_WT_FN_TYP_DIF,
+	/* Use weight function as index */
+	IPIPE_GIC_WT_FN_TYP_HP_VAL
+};
+
+/* structure for Green Imbalance Correction */
+struct prev_gic {
+	/* 0 - disable, 1 - enable */
+	unsigned char en;
+	/* 0 - Constant gain , 1 - Adaptive gain algorithm */
+	enum ipipe_gic_alg gic_alg;
+	/* GIC gain or weight. Used for Constant gain and Adaptive algorithms
+	 */
+	unsigned short gain;
+	/* Threshold selection. GIC register values or NF2 thr table */
+	enum ipipe_gic_thr_sel thr_sel;
+	/* thr1. Used when thr_sel is  IPIPE_GIC_THR_REG */
+	unsigned short thr;
+	/* this value is used for thr2-thr1, thr3-thr2 or
+	 * thr4-thr3 when wt_fn_type is index. Otherwise it
+	 * is the
+	 */
+	unsigned short slope;
+	/* Apply LSC gain to threshold. Enable this only if
+	 * LSC is enabled in ISIF & thr_sel is IPIPE_GIC_THR_REG
+	 */
+	unsigned char apply_lsc_gain;
+	/* Multiply Nf2 threshold by this gain. Use this when thr_sel
+	 * is IPIPE_GIC_THR_NF
+	 */
+	struct ipipe_float_u8 nf2_thr_gain;
+	/* Weight function uses difference as index or high pass value.
+	 * Used for adaptive gain algorithm
+	 */
+	enum ipipe_gic_wt_fn_type wt_fn_type;
+};
+
+/* Struct for configuring WB module */
+struct prev_wb {
+	/* Offset (S12) for R */
+	short ofst_r;
+	/* Offset (S12) for Gr */
+	short ofst_gr;
+	/* Offset (S12) for Gb */
+	short ofst_gb;
+	/* Offset (S12) for B */
+	short ofst_b;
+	/* Gain (U13Q9) for Red */
+	struct ipipe_float_u16 gain_r;
+	/* Gain (U13Q9) for Gr */
+	struct ipipe_float_u16 gain_gr;
+	/* Gain (U13Q9) for Gb */
+	struct ipipe_float_u16 gain_gb;
+	/* Gain (U13Q9) for Blue */
+	struct ipipe_float_u16 gain_b;
+};
+
+enum ipipe_cfa_alg {
+	/* Algorithm is 2DirAC */
+	IPIPE_CFA_ALG_2DIRAC,
+	/* Algorithm is 2DirAC + Digital Antialiasing (DAA) */
+	IPIPE_CFA_ALG_2DIRAC_DAA,
+	/* Algorithm is DAA */
+	IPIPE_CFA_ALG_DAA
+};
+
+/* Structure for CFA Interpolation */
+struct prev_cfa {
+	/* 2DirAC or 2DirAC + DAA */
+	enum ipipe_cfa_alg alg;
+	/* 2Dir CFA HP value Low Threshold */
+	unsigned short hpf_thr_2dir;
+	/* 2Dir CFA HP value slope */
+	unsigned short hpf_slp_2dir;
+	/* 2Dir CFA HP mix threshold */
+	unsigned short hp_mix_thr_2dir;
+	/* 2Dir CFA HP mix slope */
+	unsigned short hp_mix_slope_2dir;
+	/* 2Dir Direction threshold */
+	unsigned short dir_thr_2dir;
+	/* 2Dir Direction slope */
+	unsigned short dir_slope_2dir;
+	/* 2Dir NonDirectional Weight */
+	unsigned short nd_wt_2dir;
+	/* DAA Mono Hue Fraction */
+	unsigned short hue_fract_daa;
+	/* DAA Mono Edge threshold */
+	unsigned short edge_thr_daa;
+	/* DAA Mono threshold minimum */
+	unsigned short thr_min_daa;
+	/* DAA Mono threshold slope */
+	unsigned short thr_slope_daa;
+	/* DAA Mono slope minimum */
+	unsigned short slope_min_daa;
+	/* DAA Mono slope slope */
+	unsigned short slope_slope_daa;
+	/* DAA Mono LP wight */
+	unsigned short lp_wt_daa;
+};
+
+/* Struct for configuring RGB2RGB blending module */
+struct prev_rgb2rgb {
+	/* Matrix coefficient for RR S12Q8 for ID = 1 and S11Q8 for ID = 2 */
+	struct ipipe_float_s16 coef_rr;
+	/* Matrix coefficient for GR S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_gr;
+	/* Matrix coefficient for BR S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_br;
+	/* Matrix coefficient for RG S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_rg;
+	/* Matrix coefficient for GG S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_gg;
+	/* Matrix coefficient for BG S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_bg;
+	/* Matrix coefficient for RB S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_rb;
+	/* Matrix coefficient for GB S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_gb;
+	/* Matrix coefficient for BB S12Q8/S11Q8 */
+	struct ipipe_float_s16 coef_bb;
+	/* Output offset for R S13/S11 */
+	int out_ofst_r;
+	/* Output offset for G S13/S11 */
+	int out_ofst_g;
+	/* Output offset for B S13/S11 */
+	int out_ofst_b;
+};
+
+#define MAX_SIZE_GAMMA 512
+
+enum ipipe_gamma_tbl_size {
+	IPIPE_GAMMA_TBL_SZ_64 = 64,
+	IPIPE_GAMMA_TBL_SZ_128 = 128,
+	IPIPE_GAMMA_TBL_SZ_256 = 256,
+	IPIPE_GAMMA_TBL_SZ_512 = 512
+};
+
+enum ipipe_gamma_tbl_sel {
+	IPIPE_GAMMA_TBL_RAM,
+	IPIPE_GAMMA_TBL_ROM
+};
+
+struct ipipe_gamma_entry {
+	/* 10 bit slope */
+	short slope;
+	/* 10 bit offset */
+	unsigned short offset;
+};
+
+/* Struct for configuring Gamma correction module */
+struct prev_gamma {
+	/* 0 - Enable Gamma correction for Red
+	 * 1 - bypass Gamma correction. Data is divided by 16
+	 */
+	unsigned char bypass_r;
+	/* 0 - Enable Gamma correction for Blue
+	 * 1 - bypass Gamma correction. Data is divided by 16
+	 */
+	unsigned char bypass_b;
+	/* 0 - Enable Gamma correction for Green
+	 * 1 - bypass Gamma correction. Data is divided by 16
+	 */
+	unsigned char bypass_g;
+	/* PREV_GAMMA_TBL_RAM or PREV_GAMMA_TBL_ROM */
+	enum ipipe_gamma_tbl_sel tbl_sel;
+	/* Table size for RAM gamma table.
+	 */
+	enum ipipe_gamma_tbl_size tbl_size;
+	/* R table */
+	struct ipipe_gamma_entry *table_r;
+	/* Blue table */
+	struct ipipe_gamma_entry *table_b;
+	/* Green table */
+	struct ipipe_gamma_entry *table_g;
+};
+
+#define MAX_SIZE_3D_LUT		(729)
+
+struct ipipe_3d_lut_entry {
+	/* 10 bit entry for red */
+	unsigned short r;
+	/* 10 bit entry for green */
+	unsigned short g;
+	/* 10 bit entry for blue */
+	unsigned short b;
+};
+
+/* structure for 3D-LUT */
+struct prev_3d_lut {
+	/* enable/disable 3D lut */
+	unsigned char en;
+	/* 3D - LUT table entry */
+	struct ipipe_3d_lut_entry *table;
+};
+
+/* Struct for configuring Luminance Adjustment module */
+struct prev_lum_adj {
+	/* Brightness adjustments */
+	unsigned char brightness;
+	/* contrast adjustments */
+	unsigned char contrast;
+};
+
+/* Struct for configuring rgb2ycbcr module */
+struct prev_rgb2yuv {
+	/* Matrix coefficient for RY S12Q8 */
+	struct ipipe_float_s16 coef_ry;
+	/* Matrix coefficient for GY S12Q8 */
+	struct ipipe_float_s16 coef_gy;
+	/* Matrix coefficient for BY S12Q8 */
+	struct ipipe_float_s16 coef_by;
+	/* Matrix coefficient for RCb S12Q8 */
+	struct ipipe_float_s16 coef_rcb;
+	/* Matrix coefficient for GCb S12Q8 */
+	struct ipipe_float_s16 coef_gcb;
+	/* Matrix coefficient for BCb S12Q8 */
+	struct ipipe_float_s16 coef_bcb;
+	/* Matrix coefficient for RCr S12Q8 */
+	struct ipipe_float_s16 coef_rcr;
+	/* Matrix coefficient for GCr S12Q8 */
+	struct ipipe_float_s16 coef_gcr;
+	/* Matrix coefficient for BCr S12Q8 */
+	struct ipipe_float_s16 coef_bcr;
+	/* Output offset for R S11 */
+	int out_ofst_y;
+	/* Output offset for Cb S11 */
+	int out_ofst_cb;
+	/* Output offset for Cr S11 */
+	int out_ofst_cr;
+};
+
+enum ipipe_gbce_type {
+	IPIPE_GBCE_Y_VAL_TBL,
+	IPIPE_GBCE_GAIN_TBL
+};
+
+#define MAX_SIZE_GBCE_LUT 1024
+
+/* structure for Global brighness and Contrast */
+struct prev_gbce {
+	/* enable/disable GBCE */
+	unsigned char en;
+	/* Y - value table or Gain table */
+	enum ipipe_gbce_type type;
+	/* ptr to LUT for GBCE with 1024 entries */
+	unsigned short *table;
+};
+
+/* Chrominance position. Applicable only for YCbCr input
+ * Applied after edge enhancement
+ */
+enum ipipe_chr_pos {
+	/* Cositing, same position with luminance */
+	IPIPE_YUV422_CHR_POS_COSITE,
+	/* Centering, In the middle of luminance */
+	IPIPE_YUV422_CHR_POS_CENTRE
+};
+
+/* Struct for configuring yuv422 conversion module */
+struct prev_yuv422_conv {
+	/* Max Chrominance value */
+	unsigned char en_chrom_lpf;
+	/* 1 - enable LPF for chrminance, 0 - disable */
+	enum ipipe_chr_pos chrom_pos;
+};
+
+#define MAX_SIZE_YEE_LUT 1024
+
+enum ipipe_yee_merge_meth {
+	IPIPE_YEE_ABS_MAX,
+	IPIPE_YEE_EE_ES
+};
+
+/* Struct for configuring YUV Edge Enhancement module */
+struct prev_yee {
+	/* 1 - enable enhancement, 0 - disable */
+	unsigned char en;
+	/* enable/disable halo reduction in edge sharpner */
+	unsigned char en_halo_red;
+	/* Merge method between Edge Enhancer and Edge sharpner */
+	enum ipipe_yee_merge_meth merge_meth;
+	/* HPF Shift length */
+	unsigned char hpf_shft;
+	/* HPF Coefficient 00, S10 */
+	short hpf_coef_00;
+	/* HPF Coefficient 01, S10 */
+	short hpf_coef_01;
+	/* HPF Coefficient 02, S10 */
+	short hpf_coef_02;
+	/* HPF Coefficient 10, S10 */
+	short hpf_coef_10;
+	/* HPF Coefficient 11, S10 */
+	short hpf_coef_11;
+	/* HPF Coefficient 12, S10 */
+	short hpf_coef_12;
+	/* HPF Coefficient 20, S10 */
+	short hpf_coef_20;
+	/* HPF Coefficient 21, S10 */
+	short hpf_coef_21;
+	/* HPF Coefficient 22, S10 */
+	short hpf_coef_22;
+	/* Lower threshold before refering to LUT */
+	unsigned short yee_thr;
+	/* Edge sharpener Gain */
+	unsigned short es_gain;
+	/* Edge sharpener lowe threshold */
+	unsigned short es_thr1;
+	/* Edge sharpener upper threshold */
+	unsigned short es_thr2;
+	/* Edge sharpener gain on gradient */
+	unsigned short es_gain_grad;
+	/* Edge sharpener offset on gradient */
+	unsigned short es_ofst_grad;
+	/* Ptr to EE table. Must have 1024 entries */
+	short *table;
+};
+
+enum ipipe_car_meth {
+	/* Chromatic Gain Control */
+	IPIPE_CAR_CHR_GAIN_CTRL,
+	/* Dynamic switching between CHR_GAIN_CTRL
+	 * and MED_FLTR
+	 */
+	IPIPE_CAR_DYN_SWITCH,
+	/* Median Filter */
+	IPIPE_CAR_MED_FLTR
+};
+
+enum ipipe_car_hpf_type {
+	IPIPE_CAR_HPF_Y,
+	IPIPE_CAR_HPF_H,
+	IPIPE_CAR_HPF_V,
+	IPIPE_CAR_HPF_2D,
+	/* 2D HPF from YUV Edge Enhancement */
+	IPIPE_CAR_HPF_2D_YEE
+};
+
+struct ipipe_car_gain {
+	/* csup_gain */
+	unsigned char gain;
+	/* csup_shf. */
+	unsigned char shft;
+	/* gain minimum */
+	unsigned short gain_min;
+};
+
+/* Structure for Chromatic Artifact Reduction */
+struct prev_car {
+	/* enable/disable */
+	unsigned char en;
+	/* Gain control or Dynamic switching */
+	enum ipipe_car_meth meth;
+	/* Gain1 function configuration for Gain control */
+	struct ipipe_car_gain gain1;
+	/* Gain2 function configuration for Gain control */
+	struct ipipe_car_gain gain2;
+	/* HPF type used for CAR */
+	enum ipipe_car_hpf_type hpf;
+	/* csup_thr: HPF threshold for Gain control */
+	unsigned char hpf_thr;
+	/* Down shift value for hpf. 2 bits */
+	unsigned char hpf_shft;
+	/* switch limit for median filter */
+	unsigned char sw0;
+	/* switch coefficient for Gain control */
+	unsigned char sw1;
+};
+
+/* structure for Chromatic Gain Suppression */
+struct prev_cgs {
+	/* enable/disable */
+	unsigned char en;
+	/* gain1 bright side threshold */
+	unsigned char h_thr;
+	/* gain1 bright side slope */
+	unsigned char h_slope;
+	/* gain1 down shift value for bright side */
+	unsigned char h_shft;
+	/* gain1 bright side minimum gain */
+	unsigned char h_min;
+};
+
+/* various pixel formats supported */
+enum ipipe_pix_formats {
+	IPIPE_BAYER_8BIT_PACK,
+	IPIPE_BAYER_8BIT_PACK_ALAW,
+	IPIPE_BAYER_8BIT_PACK_DPCM,
+	IPIPE_BAYER_12BIT_PACK,
+	IPIPE_BAYER,		/* 16 bit */
+	IPIPE_UYVY,
+	IPIPE_YUYV,
+	IPIPE_RGB565,
+	IPIPE_RGB888,
+	IPIPE_YUV420SP,
+	IPIPE_420SP_Y,
+	IPIPE_420SP_C
+};
+
+enum ipipe_dpaths_bypass_t {
+	IPIPE_BYPASS_OFF,
+	IPIPE_BYPASS_ON
+};
+
+enum ipipe_colpat_t {
+	IPIPE_RED,
+	IPIPE_GREEN_RED,
+	IPIPE_GREEN_BLUE,
+	IPIPE_BLUE
+};
+
+enum down_scale_ave_sz {
+	IPIPE_DWN_SCALE_1_OVER_2,
+	IPIPE_DWN_SCALE_1_OVER_4,
+	IPIPE_DWN_SCALE_1_OVER_8,
+	IPIPE_DWN_SCALE_1_OVER_16,
+	IPIPE_DWN_SCALE_1_OVER_32,
+	IPIPE_DWN_SCALE_1_OVER_64,
+	IPIPE_DWN_SCALE_1_OVER_128,
+	IPIPE_DWN_SCALE_1_OVER_256
+};
+
+/* Max pixels allowed in the input. If above this either decimation
+ * or frame division mode to be enabled
+ */
+#define IPIPE_MAX_INPUT_WIDTH 2600
+
+/* Max pixels in resizer - A output. In downscale
+ * (DSCALE) mode, image quality is better, but has lesser
+ * maximum width allowed
+ */
+#define IPIPE_MAX_OUTPUT1_WIDTH_NORMAL 2176
+#define IPIPE_MAX_OUTPUT1_WIDTH_DSCALE 1088
+
+/* Max pixels in resizer - B output. In downscale
+ * (DSCALE) mode, image quality is better, but has lesser
+ * maximum width allowed
+ */
+#define IPIPE_MAX_OUTPUT2_WIDTH_NORMAL 1088
+#define IPIPE_MAX_OUTPUT2_WIDTH_DSCALE 544
+
+/* Structure for configuring Single Shot mode in the previewer
+ *   channel
+ */
+struct prev_ss_input_spec {
+	/* width of the image in SDRAM. */
+	unsigned int image_width;
+	/* height of the image in SDRAM */
+	unsigned int image_height;
+	/* line length. This will allow application to set a
+	 * different line length than that calculated based on
+	 * width. Set it to zero, if not used,
+	 */
+	unsigned int line_length;
+	/* vertical start position of the image
+	 * data to IPIPE
+	 */
+	unsigned int vst;
+	/* horizontal start position of the image
+	 * data to IPIPE
+	 */
+	unsigned int hst;
+	/* Global frame HD rate */
+	unsigned int ppln;
+	/* Global frame VD rate */
+	unsigned int lpfr;
+	/* dpcm predicator selection */
+	enum ipipeif_dpcm_pred pred;
+	/* clock divide to bring down the pixel clock */
+	struct ipipeif_5_1_clkdiv clk_div;
+	/* Shift data as per image sensor capture format
+	 * only applicable for RAW Bayer inputs
+	 */
+	enum ipipeif_5_1_data_shift data_shift;
+	/* Enable decimation 1 - enable, 0 - disable
+	 * This is used when image width is greater than
+	 * ipipe line buffer size
+	 */
+	enum ipipeif_decimation dec_en;
+	/* used when en_dec = 1. Resize ratio for decimation
+	 * when frame size is  greater than what hw can handle.
+	 * 16 to 112. IPIPE input width is calculated as follows.
+	 * width = image_width * 16/ipipeif_rsz. For example
+	 * if image_width is 1920 and user want to scale it down
+	 * to 1280, use ipipeif_rsz = 24. 1920*16/24 = 1280
+	 */
+	unsigned char rsz;
+	/* When input image width is greater that line buffer
+	 * size, use this to do resize using frame division. The
+	 * frame is divided into two vertical slices and resize
+	 * is performed on each slice. Use either frame division
+	 *  mode or decimation, NOT both
+	 */
+	unsigned char frame_div_mode_en;
+	/* Enable/Disable avg filter at IPIPEIF.
+	 * 1 - enable, 0 - disable
+	 */
+	unsigned char avg_filter_en;
+	/* Simple defect pixel correction based on a threshold value */
+	struct ipipeif_dpc dpc;
+	/* gain applied to the ipipeif output */
+	unsigned short gain;
+	/* clipped to this value at the ipipeif */
+	unsigned short clip;
+	/* Align HSync and VSync to rsz_start */
+	unsigned char align_sync;
+	/* ipipeif resize start position */
+	unsigned int rsz_start;
+	/* Input pixels formats
+	 */
+	enum ipipe_pix_formats pix_fmt;
+	/* pix order for YUV */
+	enum ipipeif_pixel_order pix_order;
+	/* Color pattern for odd line, odd pixel */
+	enum ipipe_colpat_t colp_olop;
+	/* Color pattern for odd line, even pixel */
+	enum ipipe_colpat_t colp_olep;
+	/* Color pattern for even line, odd pixel */
+	enum ipipe_colpat_t colp_elop;
+	/* Color pattern for even line, even pixel */
+	enum ipipe_colpat_t colp_elep;
+};
+
+struct prev_ss_output_spec {
+	/* output pixel format */
+	enum ipipe_pix_formats pix_fmt;
+};
+
+struct prev_single_shot_config {
+	/* Bypass image processing. RAW -> RAW */
+	enum ipipe_dpaths_bypass_t bypass;
+	/* Input specification for the image data */
+	struct prev_ss_input_spec input;
+	/* Output specification for the image data */
+	struct prev_ss_output_spec output;
+};
+
+struct prev_cont_input_spec {
+	/* 1 - enable, 0 - disable df subtraction */
+	unsigned char en_df_sub;
+	/* DF gain enable */
+	unsigned char en_df_gain;
+	/* DF gain value */
+	unsigned int df_gain;
+	/* DF gain threshold value */
+	unsigned short df_gain_thr;
+	/* Enable decimation 1 - enable, 0 - disable
+	 * This is used for bringing down the line size
+	 * to that supported by IPIPE. DM355 IPIPE
+	 * can process only 1344 pixels per line.
+	 */
+	enum ipipeif_decimation dec_en;
+	/* used when en_dec = 1. Resize ratio for decimation
+	 * when frame size is  greater than what hw can handle.
+	 * 16 to 112. IPIPE input width is calculated as follows.
+	 * width = image_width * 16/ipipeif_rsz. For example
+	 * if image_width is 1920 and user want to scale it down
+	 * to 1280, use ipipeif_rsz = 24. 1920*16/24 = 1280
+	 */
+	unsigned char rsz;
+	/* Enable/Disable avg filter at IPIPEIF.
+	 * 1 - enable, 0 - disable
+	 */
+	unsigned char avg_filter_en;
+	/* Gain applied at IPIPEIF. 1 - 1023. divided by 512.
+	 * So can be from 1/512 to  1/1023.
+	 */
+	unsigned short gain;
+	/* clipped to this value at the output of IPIPEIF */
+	unsigned short clip;
+	/* Align HSync and VSync to rsz_start */
+	unsigned char align_sync;
+	/* ipipeif resize start position */
+	unsigned int rsz_start;
+	/* Simple defect pixel correction based on a threshold value */
+	struct ipipeif_dpc dpc;
+	/* Color pattern for odd line, odd pixel */
+	enum ipipe_colpat_t colp_olop;
+	/* Color pattern for odd line, even pixel */
+	enum ipipe_colpat_t colp_olep;
+	/* Color pattern for even line, odd pixel */
+	enum ipipe_colpat_t colp_elop;
+	/* Color pattern for even line, even pixel */
+	enum ipipe_colpat_t colp_elep;
+};
+
+/* Structure for configuring Continuous mode in the previewer
+ * channel . In continuous mode, only following parameters are
+ * available for configuration from user. Rest are configured
+ * through S_CROP and S_FMT IOCTLs in CCDC driver. In this mode
+ * data to IPIPEIF comes from CCDC
+ */
+struct prev_continuous_config {
+	/* Bypass image processing. RAW -> RAW */
+	enum ipipe_dpaths_bypass_t bypass;
+	/* Input specification for the image data */
+	struct prev_cont_input_spec input;
+};
+
+/*******************************************************************
+**  Resizer API structures
+*******************************************************************/
+/* Interpolation types used for horizontal rescale */
+enum rsz_intp_t {
+	RSZ_INTP_CUBIC,
+	RSZ_INTP_LINEAR
+};
+
+/* Horizontal LPF intensity selection */
+enum rsz_h_lpf_lse_t {
+	RSZ_H_LPF_LSE_INTERN,
+	RSZ_H_LPF_LSE_USER_VAL
+};
+
+/* Structure for configuring resizer in single shot mode.
+ * This structure is used when operation mode of the
+ * resizer is single shot. The related IOCTL is
+ * RSZ_S_CONFIG & RSZ_G_CONFIG. When chained, data to
+ * resizer comes from previewer. When not chained, only
+ * UYVY data input is allowed for resizer operation.
+ * To operate on RAW Bayer data from CCDC, chain resizer
+ * with previewer by setting chain field in the
+ * rsz_channel_config structure.
+ */
+
+struct rsz_ss_input_spec {
+	/* width of the image in SDRAM. */
+	unsigned int image_width;
+	/* height of the image in SDRAM */
+	unsigned int image_height;
+	/* line length. This will allow application to set a
+	 * different line length than that calculated based on
+	 * width. Set it to zero, if not used,
+	 */
+	unsigned int line_length;
+	/* vertical start position of the image
+	 * data to IPIPE
+	 */
+	unsigned int vst;
+	/* horizontal start position of the image
+	 * data to IPIPE
+	 */
+	unsigned int hst;
+	/* Global frame HD rate */
+	unsigned int ppln;
+	/* Global frame VD rate */
+	unsigned int lpfr;
+	/* clock divide to bring down the pixel clock */
+	struct ipipeif_5_1_clkdiv clk_div;
+	/* Enable decimation 1 - enable, 0 - disable.
+	 * Used when input image width is greater than ipipe
+	 * line buffer size, this is enabled to do resize
+	 * at the input of the IPIPE to clip the size
+	 */
+	enum ipipeif_decimation dec_en;
+	/* used when en_dec = 1. Resize ratio for decimation
+	 * when frame size is  greater than what hw can handle.
+	 * 16 to 112. IPIPE input width is calculated as follows.
+	 * width = image_width * 16/ipipeif_rsz. For example
+	 * if image_width is 1920 and user want to scale it down
+	 * to 1280, use ipipeif_rsz = 24. 1920*16/24 = 1280
+	 */
+	unsigned char rsz;
+	/* When input image width is greater that line buffer
+	 * size, use this to do resize using frame division. The
+	 * frame is divided into two vertical slices and resize
+	 * is performed on each slice
+	 */
+	unsigned char frame_div_mode_en;
+	/* Enable/Disable avg filter at IPIPEIF.
+	 * 1 - enable, 0 - disable
+	 */
+	unsigned char avg_filter_en;
+	/* Align HSync and VSync to rsz_start */
+	unsigned char align_sync;
+	/* ipipeif resize start position */
+	unsigned int rsz_start;
+	/* Input pixels formats
+	 */
+	enum ipipe_pix_formats pix_fmt;
+};
+
+struct rsz_output_spec {
+	/* enable the resizer output */
+	unsigned char enable;
+	/* output pixel format. Has to be UYVY */
+	enum ipipe_pix_formats pix_fmt;
+	/* enable horizontal flip */
+	unsigned char h_flip;
+	/* enable vertical flip */
+	unsigned char v_flip;
+	/* width in pixels. must be multiple of 16. */
+	unsigned int width;
+	/* height in lines */
+	unsigned int height;
+	/* line start offset for y. */
+	unsigned int vst_y;
+	/* line start offset for c. Only for 420 */
+	unsigned int vst_c;
+	/* vertical rescale interpolation type, YCbCr or Luminance */
+	enum rsz_intp_t v_typ_y;
+	/* vertical rescale interpolation type for Chrominance */
+	enum rsz_intp_t v_typ_c;
+	/* vertical lpf intensity - Luminance */
+	unsigned char v_lpf_int_y;
+	/* vertical lpf intensity - Chrominance */
+	unsigned char v_lpf_int_c;
+	/* horizontal rescale interpolation types, YCbCr or Luminance  */
+	enum rsz_intp_t h_typ_y;
+	/* horizontal rescale interpolation types, Chrominance */
+	enum rsz_intp_t h_typ_c;
+	/* horizontal lpf intensity - Luminance */
+	unsigned char h_lpf_int_y;
+	/* horizontal lpf intensity - Chrominance */
+	unsigned char h_lpf_int_c;
+	/* Use down scale mode for scale down */
+	unsigned char en_down_scale;
+	/* if downscale, set the downscale more average size for horizontal
+	 * direction. Used only if output width and height is less than
+	 * input sizes
+	 */
+	enum down_scale_ave_sz h_dscale_ave_sz;
+	/* if downscale, set the downscale more average size for vertical
+	 * direction. Used only if output width and height is less than
+	 * input sizes
+	 */
+	enum down_scale_ave_sz v_dscale_ave_sz;
+	/* Y offset. If set, the offset would be added to the base address
+	 */
+	unsigned int user_y_ofst;
+	/* C offset. If set, the offset would be added to the base address
+	 */
+	unsigned int user_c_ofst;
+};
+
+/* In continuous mode, few parameters are set by ccdc driver. So only
+ * part of the output spec is available for user configuration
+ */
+struct rsz_part_output_spec {
+	/* enable the resizer output */
+	unsigned char enable;
+	/* enable horizontal flip */
+	unsigned char h_flip;
+	/* vertical rescale interpolation type, YCbCr or Luminance */
+	unsigned char v_flip;
+	/* vertical rescale interpolation type for Chrominance */
+	enum rsz_intp_t v_typ_y;
+	/* vertical rescale interpolation types  */
+	enum rsz_intp_t v_typ_c;
+	/* vertical lpf intensity - Luminance */
+	unsigned char v_lpf_int_y;
+	/* horizontal rescale interpolation types, YCbCr or Luminance  */
+	unsigned char v_lpf_int_c;
+	/* horizontal rescale interpolation types, Chrominance */
+	enum rsz_intp_t h_typ_y;
+	/* vertical lpf intensity - Chrominance */
+	enum rsz_intp_t h_typ_c;
+	/* horizontal lpf intensity - Luminance */
+	unsigned char h_lpf_int_y;
+	/* Use down scale mode for scale down */
+	unsigned char h_lpf_int_c;
+	/* horizontal lpf intensity - Chrominance */
+	unsigned char en_down_scale;
+	/* if downscale, set the downscale more average size for horizontal
+	 * direction. Used only if output width and height is less than
+	 * input sizes
+	 */
+	enum down_scale_ave_sz h_dscale_ave_sz;
+	/* if downscale, set the downscale more average size for vertical
+	 * direction. Used only if output width and height is less than
+	 * input sizes
+	 */
+	enum down_scale_ave_sz v_dscale_ave_sz;
+	/* Y offset. If set, the offset would be added to the base address
+	 */
+	unsigned int user_y_ofst;
+	/* C offset. If set, the offset would be added to the base address
+	 */
+	unsigned int user_c_ofst;
+};
+
+struct rsz_single_shot_config {
+	/* input spec of the image data (UYVY). non-chained
+	 * mode. Only valid when not chained. For chained
+	 * operation, previewer settings are used
+	 */
+	struct rsz_ss_input_spec input;
+	/* output spec of the image data coming out of resizer - 0(UYVY).
+	 */
+	struct rsz_output_spec output1;
+	/* output spec of the image data coming out of resizer - 1(UYVY).
+	 */
+	struct rsz_output_spec output2;
+	/* 0 , chroma sample at odd pixel, 1 - even pixel */
+	unsigned char chroma_sample_even;
+	unsigned char yuv_y_min;
+	unsigned char yuv_y_max;
+	unsigned char yuv_c_min;
+	unsigned char yuv_c_max;
+	enum ipipe_chr_pos out_chr_pos;
+};
+
+struct rsz_continuous_config {
+	/* A subset of output spec is configured by application.
+	 * Others such as size, position etc are set by CCDC driver
+	 */
+	struct rsz_part_output_spec output1;
+	struct rsz_output_spec output2;
+	/* output spec of the image data coming out of resizer - 1(UYVY).
+	 */
+	unsigned char chroma_sample_even;
+	/* 0 , chroma sample at odd pixel, 1 - even pixel */
+	unsigned char yuv_y_min;
+	unsigned char yuv_y_max;
+	unsigned char yuv_c_min;
+	unsigned char yuv_c_max;
+	enum ipipe_chr_pos out_chr_pos;
+};
+
+#endif
diff --git a/include/media/davinci/vpfe.h b/include/media/davinci/vpfe.h
new file mode 100644
index 0000000..00d2b4d
--- /dev/null
+++ b/include/media/davinci/vpfe.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (C) 2011 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
+*/
+
+#ifndef _VPFE_H
+#define _VPFE_H
+
+#ifdef __KERNEL__
+#include <linux/v4l2-subdev.h>
+#include <linux/i2c.h>
+
+#define CAPTURE_DRV_NAME	"vpfe-capture"
+
+struct vpfe_route {
+	__u32 input;
+	__u32 output;
+};
+
+enum vpfe_subdev_id {
+	VPFE_SUBDEV_TVP5146 = 1,
+	VPFE_SUBDEV_MT9T031 = 2,
+	VPFE_SUBDEV_TVP7002 = 3,
+	VPFE_SUBDEV_MT9P031 = 4,
+};
+
+enum vpfe_pin_pol {
+	VPFE_PINPOL_POSITIVE,
+	VPFE_PINPOL_NEGATIVE
+};
+
+/* interface description */
+struct vpfe_hw_if_param {
+	enum v4l2_mbus_pixelcode if_type;
+	enum vpfe_pin_pol hdpol;
+	enum vpfe_pin_pol vdpol;
+};
+
+struct vpfe_ext_subdev_info {
+	/* v4l2 subdev */
+	struct v4l2_subdev *subdev;
+	/* Sub device module name */
+	char module_name[32];
+	/* Sub device group id */
+	int grp_id;
+	/* Number of inputs supported */
+	int num_inputs;
+	/* inputs available at the sub device */
+	struct v4l2_input *inputs;
+	/* Sub dev routing information for each input */
+	struct vpfe_route *routes;
+	/* ccdc bus/interface configuration */
+	struct vpfe_hw_if_param ccdc_if_params;
+	/* i2c subdevice board info */
+	struct i2c_board_info board_info;
+	/* Is this a camera sub device ? */
+	unsigned is_camera:1;
+	/* check if sub dev supports routing */
+	unsigned can_route:1;
+	/* registered ? */
+	unsigned registered:1;
+};
+
+struct vpfe_config {
+	/* Number of sub devices connected to vpfe */
+	int num_subdevs;
+	/* information about each subdev */
+	struct vpfe_ext_subdev_info *sub_devs;
+	/* evm card info */
+	char *card_name;
+	/* setup function for the input path */
+	int (*setup_input)(enum vpfe_subdev_id id);
+	/* number of clocks */
+	int num_clocks;
+	/* clocks used for vpfe capture */
+	char *clocks[];
+};
+#endif
+#endif
-- 
1.6.2.4


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

* [PATCH v2 8/8] davinci: vpfe: build infrastructure for dm365
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (6 preceding siblings ...)
  2011-08-29 15:07 ` [PATCH v2 7/8] davinci: vpfe: v4l2 capture driver with media interface Manjunath Hadli
@ 2011-08-29 15:07 ` Manjunath Hadli
  2011-08-29 15:20 ` [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Hadli, Manjunath
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 27+ messages in thread
From: Manjunath Hadli @ 2011-08-29 15:07 UTC (permalink / raw)
  To: LMML; +Cc: dlos, Manjunath Hadli, Nagabhushana Netagunte

add build infrastructure for dm365 specific modules
such as IPIPE, AEW, AF.

Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
---
 drivers/media/video/davinci/Kconfig  |   46 ++++++++++++++++++++++++++++++++-
 drivers/media/video/davinci/Makefile |   17 +++++++++++-
 2 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig
index 6b19540..6f6da53 100644
--- a/drivers/media/video/davinci/Kconfig
+++ b/drivers/media/video/davinci/Kconfig
@@ -11,6 +11,48 @@ config DISPLAY_DAVINCI_DM646X_EVM
 	  To compile this driver as a module, choose M here: the
 	  module will be called vpif_display.
 
+config VIDEO_DM365_3A_HW
+	tristate "DM365 Auto Focus, Auto Exposure/ White Balance HW module"
+	depends on ARCH_DAVINCI_DM365
+	help
+	  DM365 Auto Focus, Auto Exposure and Auto White Balancing HW module
+
+	  This module has functions which configure AEW/AF hardware, high level
+	  AF module and AEW module use these functionalities. It collects metrics
+	  about the image or video data
+
+config VIDEO_DM365_AF
+	tristate "DM365 Auto Focus Driver"
+	depends on ARCH_DAVINCI_DM365
+	select VIDEO_DM365_3A_HW
+	help
+	  DM365 Auto Focus hardware module.
+
+	  Auto Focus driver is used to support control loop for Auto Focus.
+	  It collects metrics about the image or video data. This provides
+	  hooks to AF subdevice driver.
+
+config VIDEO_DM365_AEW
+	tristate "DM365 Auto exposure /White Balance Driver"
+	depends on ARCH_DAVINCI_DM365
+	select VIDEO_DM365_3A_HW
+	help
+	  DM365 Auto Exposure and Auto White Balance hardware module.
+
+	  This is used to support the control loops for Auto Exposure
+	  and Auto White Balance. It collects metrics about the image
+	  or video data
+
+config DM365_IPIPE
+	depends on ARCH_DAVINCI && ARCH_DAVINCI_DM365
+	tristate "DM365 IPIPE"
+	help
+	  dm365 IPIPE hardware module.
+
+	  This is the hardware module that implements imp_hw_interface
+	  for DM365. This hardware module provides previewer and resizer
+	  functionality for image processing.
+
 config CAPTURE_DAVINCI_DM646X_EVM
 	tristate "DM646x EVM Video Capture"
 	depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
@@ -51,7 +93,7 @@ config VIDEO_VPFE_CAPTURE
 
 config VIDEO_DM6446_CCDC
 	tristate "DM6446 CCDC HW module"
-	depends on VIDEO_VPFE_CAPTURE
+	depends on VIDEO_VPFE_CAPTURE && ARCH_DAVINCI_DM644x
 	select VIDEO_VPSS_SYSTEM
 	default y
 	help
@@ -80,7 +122,7 @@ config VIDEO_DM355_CCDC
 	   module will be called vpfe.
 
 config VIDEO_ISIF
-	tristate "ISIF HW module"
+	tristate "DM365 ISIF HW module"
 	depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE
 	select VIDEO_VPSS_SYSTEM
 	default y
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile
index a379557..8544040 100644
--- a/drivers/media/video/davinci/Makefile
+++ b/drivers/media/video/davinci/Makefile
@@ -12,7 +12,20 @@ obj-$(CONFIG_CAPTURE_DAVINCI_DM646X_EVM) += vpif_capture.o
 
 # Capture: DM6446 and DM355
 obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o
-obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
+obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o vpfe_ccdc.o \
+                                       vpfe_resizer.o vpfe_previewer.o \
+                                       vpfe_aew.o vpfe_af.o vpfe_video.o
 obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o
 obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o
-obj-$(CONFIG_VIDEO_ISIF) += isif.o
+obj-$(CONFIG_VIDEO_ISIF) += dm365_ccdc.o
+
+dm365_a3_hw_driver-objs := dm365_a3_hw.o
+obj-$(CONFIG_VIDEO_DM365_3A_HW) += dm365_a3_hw_driver.o
+dm365_af_driver-objs := dm365_af.o
+obj-$(CONFIG_VIDEO_DM365_AF)    += dm365_af_driver.o
+dm365_aew_driver-objs := dm365_aew.o
+obj-$(CONFIG_VIDEO_DM365_AEW)   += dm365_aew_driver.o
+
+dm365_imp-objs                  := dm365_ipipe.o dm365_def_para.o \
+                                        dm365_ipipe_hw.o dm3xx_ipipeif.o
+obj-$(CONFIG_DM365_IPIPE)       += dm365_imp.o
-- 
1.6.2.4


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

* RE: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (7 preceding siblings ...)
  2011-08-29 15:07 ` [PATCH v2 8/8] davinci: vpfe: build infrastructure for dm365 Manjunath Hadli
@ 2011-08-29 15:20 ` Hadli, Manjunath
  2011-08-31 21:30 ` Sakari Ailus
  2011-09-18 14:35 ` Mauro Carvalho Chehab
  10 siblings, 0 replies; 27+ messages in thread
From: Hadli, Manjunath @ 2011-08-29 15:20 UTC (permalink / raw)
  To: Hadli, Manjunath, LMML; +Cc: dlos

Please treat the patches as RFC.

Thx,
-manju

On Mon, Aug 29, 2011 at 20:37:11, Hadli, Manjunath wrote:
> changes from last patch set:
> 1. Made changes based on Sakari's feedback mainly:
>         a. returned early to allow unindenting
>         b. reformatting to shift the code to left where possible
>         c. changed hex numbers to lower case
>         d. corrected the defines according to module names.
>         e. magic numbers removed.
>         f. changed non-integer returning functions to void
>         g. removed unwanted paranthses.
>         h. fixed error codes.
>         i. fixed some RESET_BIt code to what it was intended for.
> 2. reorganized the header files to move the kernel-only headers along with the c files and interface headers in the include folder.
> 
> Manjunath Hadli (6):
>   davinci: vpfe: add dm3xx IPIPEIF hardware support module
>   davinci: vpfe: add support for CCDC hardware for dm365
>   davinci: vpfe: add ccdc driver with media controller interface
>   davinci: vpfe: add v4l2 video driver support
>   davinci: vpfe: v4l2 capture driver with media interface
>   davinci: vpfe: build infrastructure for dm365
> 
> Nagabhushana Netagunte (2):
>   davinci: vpfe: add IPIPE hardware layer support
>   davinci: vpfe: add IPIPE support for media controller driver
> 
>  drivers/media/video/davinci/Kconfig           |   46 +-
>  drivers/media/video/davinci/Makefile          |   17 +-
>  drivers/media/video/davinci/ccdc_hw_device.h  |   10 +-
>  drivers/media/video/davinci/ccdc_types.h      |   43 +
>  drivers/media/video/davinci/dm365_ccdc.c      | 1519 ++++++++++
>  drivers/media/video/davinci/dm365_ccdc.h      |   88 +
>  drivers/media/video/davinci/dm365_ccdc_regs.h |  309 ++  drivers/media/video/davinci/dm365_def_para.c  |  486 +++
>  drivers/media/video/davinci/dm365_def_para.h  |   39 +
>  drivers/media/video/davinci/dm365_ipipe.c     | 3966 +++++++++++++++++++++++++
>  drivers/media/video/davinci/dm365_ipipe.h     |  300 ++
>  drivers/media/video/davinci/dm365_ipipe_hw.c  |  949 ++++++  drivers/media/video/davinci/dm365_ipipe_hw.h  |  539 ++++
>  drivers/media/video/davinci/dm3xx_ipipeif.c   |  317 ++
>  drivers/media/video/davinci/dm3xx_ipipeif.h   |  258 ++
>  drivers/media/video/davinci/imp_common.h      |   85 +
>  drivers/media/video/davinci/imp_hw_if.h       |  178 ++
>  drivers/media/video/davinci/vpfe_capture.c    |  793 +++++
>  drivers/media/video/davinci/vpfe_capture.h    |  104 +
>  drivers/media/video/davinci/vpfe_ccdc.c       |  813 +++++
>  drivers/media/video/davinci/vpfe_ccdc.h       |   85 +
>  drivers/media/video/davinci/vpfe_video.c      | 1712 +++++++++++
>  drivers/media/video/davinci/vpfe_video.h      |  142 +
>  include/linux/davinci_vpfe.h                  | 1223 ++++++++
>  include/linux/dm365_ccdc.h                    |  664 +++++
>  include/linux/dm3xx_ipipeif.h                 |   64 +
>  include/media/davinci/vpfe.h                  |   91 +
>  27 files changed, 14829 insertions(+), 11 deletions(-)  create mode 100644 drivers/media/video/davinci/ccdc_types.h
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.c
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h
>  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
>  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
>  create mode 100644 drivers/media/video/davinci/imp_common.h
>  create mode 100644 drivers/media/video/davinci/imp_hw_if.h
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.c
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.h
>  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.c
>  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.h
>  create mode 100644 drivers/media/video/davinci/vpfe_video.c
>  create mode 100644 drivers/media/video/davinci/vpfe_video.h
>  create mode 100644 include/linux/davinci_vpfe.h  create mode 100644 include/linux/dm365_ccdc.h  create mode 100644 include/linux/dm3xx_ipipeif.h  create mode 100644 include/media/davinci/vpfe.h
> 
> 


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

* Re: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (8 preceding siblings ...)
  2011-08-29 15:20 ` [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Hadli, Manjunath
@ 2011-08-31 21:30 ` Sakari Ailus
  2011-09-09 13:40   ` Hadli, Manjunath
  2011-09-18 14:35 ` Mauro Carvalho Chehab
  10 siblings, 1 reply; 27+ messages in thread
From: Sakari Ailus @ 2011-08-31 21:30 UTC (permalink / raw)
  To: Manjunath Hadli; +Cc: LMML, dlos

Hi Manju,

Do you have the media device grap that would be typical for this hardware
produced by media-ctl? That can be converted to postscript using dotfile.

this would make it a little easier to understan this driver. Thanks.

On Mon, Aug 29, 2011 at 08:37:11PM +0530, Manjunath Hadli wrote:
> changes from last patch set:
> 1. Made changes based on Sakari's feedback mainly:
>         a. returned early to allow unindenting
>         b. reformatting to shift the code to left where possible
>         c. changed hex numbers to lower case
>         d. corrected the defines according to module names.
>         e. magic numbers removed.
>         f. changed non-integer returning functions to void
>         g. removed unwanted paranthses.
>         h. fixed error codes.
>         i. fixed some RESET_BIt code to what it was intended for.
> 2. reorganized the header files to move the kernel-only headers
> along with the c files and interface headers in the include folder.
> 
> Manjunath Hadli (6):
>   davinci: vpfe: add dm3xx IPIPEIF hardware support module
>   davinci: vpfe: add support for CCDC hardware for dm365
>   davinci: vpfe: add ccdc driver with media controller interface
>   davinci: vpfe: add v4l2 video driver support
>   davinci: vpfe: v4l2 capture driver with media interface
>   davinci: vpfe: build infrastructure for dm365
> 
> Nagabhushana Netagunte (2):
>   davinci: vpfe: add IPIPE hardware layer support
>   davinci: vpfe: add IPIPE support for media controller driver
> 
>  drivers/media/video/davinci/Kconfig           |   46 +-
>  drivers/media/video/davinci/Makefile          |   17 +-
>  drivers/media/video/davinci/ccdc_hw_device.h  |   10 +-
>  drivers/media/video/davinci/ccdc_types.h      |   43 +
>  drivers/media/video/davinci/dm365_ccdc.c      | 1519 ++++++++++
>  drivers/media/video/davinci/dm365_ccdc.h      |   88 +
>  drivers/media/video/davinci/dm365_ccdc_regs.h |  309 ++
>  drivers/media/video/davinci/dm365_def_para.c  |  486 +++
>  drivers/media/video/davinci/dm365_def_para.h  |   39 +
>  drivers/media/video/davinci/dm365_ipipe.c     | 3966 +++++++++++++++++++++++++
>  drivers/media/video/davinci/dm365_ipipe.h     |  300 ++
>  drivers/media/video/davinci/dm365_ipipe_hw.c  |  949 ++++++
>  drivers/media/video/davinci/dm365_ipipe_hw.h  |  539 ++++
>  drivers/media/video/davinci/dm3xx_ipipeif.c   |  317 ++
>  drivers/media/video/davinci/dm3xx_ipipeif.h   |  258 ++
>  drivers/media/video/davinci/imp_common.h      |   85 +
>  drivers/media/video/davinci/imp_hw_if.h       |  178 ++
>  drivers/media/video/davinci/vpfe_capture.c    |  793 +++++
>  drivers/media/video/davinci/vpfe_capture.h    |  104 +
>  drivers/media/video/davinci/vpfe_ccdc.c       |  813 +++++
>  drivers/media/video/davinci/vpfe_ccdc.h       |   85 +
>  drivers/media/video/davinci/vpfe_video.c      | 1712 +++++++++++
>  drivers/media/video/davinci/vpfe_video.h      |  142 +
>  include/linux/davinci_vpfe.h                  | 1223 ++++++++
>  include/linux/dm365_ccdc.h                    |  664 +++++
>  include/linux/dm3xx_ipipeif.h                 |   64 +
>  include/media/davinci/vpfe.h                  |   91 +
>  27 files changed, 14829 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/media/video/davinci/ccdc_types.h
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.c
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h
>  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
>  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
>  create mode 100644 drivers/media/video/davinci/imp_common.h
>  create mode 100644 drivers/media/video/davinci/imp_hw_if.h
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.c
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.h
>  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.c
>  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.h
>  create mode 100644 drivers/media/video/davinci/vpfe_video.c
>  create mode 100644 drivers/media/video/davinci/vpfe_video.h
>  create mode 100644 include/linux/davinci_vpfe.h
>  create mode 100644 include/linux/dm365_ccdc.h
>  create mode 100644 include/linux/dm3xx_ipipeif.h
>  create mode 100644 include/media/davinci/vpfe.h
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Sakari Ailus
sakari.ailus@iki.fi

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

* Re: [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module
  2011-08-29 15:07 ` [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module Manjunath Hadli
@ 2011-09-01 20:47   ` Sylwester Nawrocki
  2011-09-09 13:20     ` Hadli, Manjunath
  0 siblings, 1 reply; 27+ messages in thread
From: Sylwester Nawrocki @ 2011-09-01 20:47 UTC (permalink / raw)
  To: Manjunath Hadli; +Cc: LMML, dlos, Nagabhushana Netagunte

Hi Manjunath,

A few comments below...

On 08/29/2011 05:07 PM, Manjunath Hadli wrote:
> add support for dm3xx IPIPEIF hardware setup. This is the
> lowest software layer for the dm3x vpfe driver which directly
> accesses hardware. Add support for features like default
> pixel correction, dark frame substraction  and hardware setup.
> 
> Signed-off-by: Manjunath Hadli<manjunath.hadli@ti.com>
> Signed-off-by: Nagabhushana Netagunte<nagabhushana.netagunte@ti.com>
> ---
>   drivers/media/video/davinci/dm3xx_ipipeif.c |  317 +++++++++++++++++++++++++++
>   drivers/media/video/davinci/dm3xx_ipipeif.h |  258 ++++++++++++++++++++++
>   include/linux/dm3xx_ipipeif.h               |   64 ++++++
>   3 files changed, 639 insertions(+), 0 deletions(-)
>   create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
>   create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
>   create mode 100644 include/linux/dm3xx_ipipeif.h
> 
> diff --git a/drivers/media/video/davinci/dm3xx_ipipeif.c b/drivers/media/video/davinci/dm3xx_ipipeif.c
> new file mode 100644
> index 0000000..ebc8895
> --- /dev/null
> +++ b/drivers/media/video/davinci/dm3xx_ipipeif.c
> @@ -0,0 +1,317 @@
...
> +
> +static void ipipeif_config_dpc(struct ipipeif_dpc *dpc)
> +{
> +	u32 val;
> +
> +	/* Intialize val*/
> +	val = 0;

s/Intialize/Initialize ? But this comment doesn't seem much helpful
and could probably be removed. Also it might be better to just do:

	u32 val = 0;

> +
> +	if (dpc->en) {
> +		val = (dpc->en&  1)<<  IPIPEIF_DPC2_EN_SHIFT;
> +		val |= dpc->thr&  IPIPEIF_DPC2_THR_MASK;
> +	}
> +
> +	regw_if(val, IPIPEIF_DPC2);
> +}
> +
...
> +
> +static int __devinit dm3xx_ipipeif_probe(struct platform_device *pdev)
> +{
> +	static resource_size_t  res_len;
> +	struct resource *res;
> +	int status;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENOENT;
> +
> +	res_len = res->end - res->start + 1;

resource_size(res) macro could be used here

> +
> +	res = request_mem_region(res->start, res_len, res->name);
> +	if (!res)
> +		return -EBUSY;
> +
> +	ipipeif_base_addr = ioremap_nocache(res->start, res_len);
> +	if (!ipipeif_base_addr) {
> +		status = -EBUSY;
> +		goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	release_mem_region(res->start, res_len);
> +
> +	return status;
> +}
> +
> +static int dm3xx_ipipeif_remove(struct platform_device *pdev)
> +{
> +	struct resource *res;
> +
> +	iounmap(ipipeif_base_addr);
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (res)
> +		release_mem_region(res->start, res->end - res->start + 1);

	release_mem_region(res->start, resource_size(res));

> +	return 0;
> +}
> +
> +static struct platform_driver dm3xx_ipipeif_driver = {
> +	.driver = {
> +		.name   = "dm3xx_ipipeif",
> +		.owner = THIS_MODULE,
> +	},
> +	.remove = __devexit_p(dm3xx_ipipeif_remove),
> +	.probe = dm3xx_ipipeif_probe,
> +};
> +
> +static int dm3xx_ipipeif_init(void)
> +{
> +	return platform_driver_register(&dm3xx_ipipeif_driver);
> +}
> +
> +static void dm3xx_ipipeif_exit(void)
> +{
> +	platform_driver_unregister(&dm3xx_ipipeif_driver);
> +}
> +
> +module_init(dm3xx_ipipeif_init);
> +module_exit(dm3xx_ipipeif_exit);
> +
> +MODULE_LICENSE("GPL2");
> diff --git a/drivers/media/video/davinci/dm3xx_ipipeif.h b/drivers/media/video/davinci/dm3xx_ipipeif.h
> new file mode 100644
> index 0000000..f3289f0
> --- /dev/null
> +++ b/drivers/media/video/davinci/dm3xx_ipipeif.h
> @@ -0,0 +1,258 @@
> +/*
...
> +
> +/* IPIPEIF Register Offsets from the base address */
> +#define IPIPEIF_ENABLE			(0x00)
> +#define IPIPEIF_CFG1			(0x04)
> +#define IPIPEIF_PPLN			(0x08)
> +#define IPIPEIF_LPFR			(0x0c)
> +#define IPIPEIF_HNUM			(0x10)
> +#define IPIPEIF_VNUM			(0x14)
> +#define IPIPEIF_ADDRU			(0x18)
> +#define IPIPEIF_ADDRL			(0x1c)
> +#define IPIPEIF_ADOFS			(0x20)
> +#define IPIPEIF_RSZ			(0x24)
> +#define IPIPEIF_GAIN			(0x28)
> +
> +/* Below registers are available only on IPIPE 5.1 */
> +#define IPIPEIF_DPCM			(0x2c)
> +#define IPIPEIF_CFG2			(0x30)
> +#define IPIPEIF_INIRSZ			(0x34)
> +#define IPIPEIF_OCLIP			(0x38)
> +#define IPIPEIF_DTUDF			(0x3c)
> +#define IPIPEIF_CLKDIV			(0x40)
> +#define IPIPEIF_DPC1			(0x44)
> +#define IPIPEIF_DPC2			(0x48)
> +#define IPIPEIF_DFSGVL			(0x4c)
> +#define IPIPEIF_DFSGTH			(0x50)
> +#define IPIPEIF_RSZ3A			(0x54)
> +#define IPIPEIF_INIRSZ3A		(0x58)
> +#define IPIPEIF_RSZ_MIN			(16)
> +#define IPIPEIF_RSZ_MAX			(112)
> +#define IPIPEIF_RSZ_CONST		(16)
> +#define SETBIT(reg, bit)   (reg = ((reg) | ((0x00000001)<<(bit))))
> +#define RESETBIT(reg, bit) (reg = ((reg)&  (~(0x00000001<<(bit)))))
> +
> +#define IPIPEIF_ADOFS_LSB_MASK		(0x1ff)
> +#define IPIPEIF_ADOFS_LSB_SHIFT		(5)
> +#define IPIPEIF_ADOFS_MSB_MASK		(0x200)
> +#define IPIPEIF_ADDRU_MASK		(0x7ff)
> +#define IPIPEIF_ADDRL_SHIFT		(5)
> +#define IPIPEIF_ADDRL_MASK		(0xffff)
> +#define IPIPEIF_ADDRU_SHIFT		(21)
> +#define IPIPEIF_ADDRMSB_SHIFT		(31)
> +#define IPIPEIF_ADDRMSB_LEFT_SHIFT	(10)
> +
> +/* CFG1 Masks and shifts */
> +#define ONESHOT_SHIFT			(0)
> +#define DECIM_SHIFT			(1)
> +#define INPSRC_SHIFT			(2)
> +#define CLKDIV_SHIFT			(4)
> +#define AVGFILT_SHIFT			(7)
> +#define PACK8IN_SHIFT			(8)
> +#define IALAW_SHIFT			(9)
> +#define CLKSEL_SHIFT			(10)
> +#define DATASFT_SHIFT			(11)
> +#define INPSRC1_SHIFT			(14)
> +
> +/* DPC2 */
> +#define IPIPEIF_DPC2_EN_SHIFT		(12)
> +#define IPIPEIF_DPC2_THR_MASK		(0xfff)
> +/* Applicable for IPIPE 5.1 */
> +#define IPIPEIF_DF_GAIN_EN_SHIFT	(10)
> +#define IPIPEIF_DF_GAIN_MASK		(0x3ff)
> +#define IPIPEIF_DF_GAIN_THR_MASK	(0xfff)
> +/* DPCM */
> +#define IPIPEIF_DPCM_BITS_SHIFT		(2)
> +#define IPIPEIF_DPCM_PRED_SHIFT		(1)
> +/* CFG2 */
> +#define IPIPEIF_CFG2_HDPOL_SHIFT	(1)
> +#define IPIPEIF_CFG2_VDPOL_SHIFT	(2)
> +#define IPIPEIF_CFG2_YUV8_SHIFT		(6)
> +#define	IPIPEIF_CFG2_YUV16_SHIFT	(3)
> +#define	IPIPEIF_CFG2_YUV8P_SHIFT	(7)
> +
> +/* INIRSZ */
> +#define IPIPEIF_INIRSZ_ALNSYNC_SHIFT	(13)
> +#define IPIPEIF_INIRSZ_MASK		(0x1fff)

Is there any good reason to use parentheses around the numbers ? 


--
Regards,
Sylwester

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

* Re: [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365
  2011-08-29 15:07 ` [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365 Manjunath Hadli
@ 2011-09-01 21:23   ` Sylwester Nawrocki
  2011-09-09 13:30     ` Hadli, Manjunath
  0 siblings, 1 reply; 27+ messages in thread
From: Sylwester Nawrocki @ 2011-09-01 21:23 UTC (permalink / raw)
  To: Manjunath Hadli; +Cc: LMML, dlos, Nagabhushana Netagunte

Hi Manjunath,

few more comments below..

On 08/29/2011 05:07 PM, Manjunath Hadli wrote:
> add support for ccdc on dm365 SoC. ccdc is responsible for
> capturing video data- both raw bayer through sync seperate
> signals and through BT656/1120 interfaces. This driver implements
> the hardware functionality. Mainly- setting of hardware, validation
> of parameters, and isr configuration.
> 
> Signed-off-by: Manjunath Hadli<manjunath.hadli@ti.com>
> Signed-off-by: Nagabhushana Netagunte<nagabhushana.netagunte@ti.com>
> ---
>   drivers/media/video/davinci/ccdc_types.h      |   43 +
>   drivers/media/video/davinci/dm365_ccdc.c      | 1519 +++++++++++++++++++++++++
>   drivers/media/video/davinci/dm365_ccdc.h      |   88 ++
>   drivers/media/video/davinci/dm365_ccdc_regs.h |  309 +++++
>   include/linux/dm365_ccdc.h                    |  664 +++++++++++
>   5 files changed, 2623 insertions(+), 0 deletions(-)
>   create mode 100644 drivers/media/video/davinci/ccdc_types.h
>   create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
>   create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
>   create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
>   create mode 100644 include/linux/dm365_ccdc.h
...
> +#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)
> +
> +/*masks and shifts*/
> +#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/linux/dm365_ccdc.h b/include/linux/dm365_ccdc.h
> new file mode 100644
> index 0000000..4e50529
> --- /dev/null
> +++ b/include/linux/dm365_ccdc.h
> @@ -0,0 +1,664 @@
...
> +#define VPFE_CMD_S_CCDC_RAW_PARAMS _IOW('V', 1, \
> +					struct ccdc_config_params_raw)
> +#define VPFE_CMD_G_CCDC_RAW_PARAMS _IOR('V', 2, \
> +					struct ccdc_config_params_raw)
> +/**
> + * ccdc float type S8Q8/U8Q8
> + */
> +struct ccdc_float_8 {
> +	/* 8 bit integer part */
> +	unsigned char integer;
> +	/* 8 bit decimal part */
> +	unsigned char decimal;
> +};

Isn't it better to use explicit width type, like u8, u16, etc. ?
Then we could just have:

+struct ccdc_float_8 {
+	u8 integer;
+	u8 decimal;
+};


> +
> +/**
> + * brief ccdc float type U16Q16/S16Q16

> + */
> +struct ccdc_float_16 {
> +	/* 16 bit integer part */
> +	unsigned short integer;
> +	/* 16 bit decimal part */
> +	unsigned short decimal;
> +};

and 

+struct ccdc_float_16 {
+	u16 integer;
+	u16 decimal;
+};

> +
> +/*
> + * ccdc image(target) window parameters
> + */
> +struct ccdc_cropwin {
> +	/* horzontal offset of the top left corner in pixels */
> +	unsigned int left;
> +	/* vertical offset of the top left corner in pixels */
> +	unsigned int top;
> +	/* width in pixels of the rectangle */
> +	unsigned int width;
> +	/* height in lines of the rectangle */
> +	unsigned int height;
> +};

How about using struct v4l2_rect instead ?

...
> +/**
> + * CCDC image data size
> + */
> +enum ccdc_data_size {
> +	/* 8 bits */
> +	CCDC_8_BITS,
> +	/* 9 bits */
> +	CCDC_9_BITS,
> +	/* 10 bits */
> +	CCDC_10_BITS,
> +	/* 11 bits */
> +	CCDC_11_BITS,
> +	/* 12 bits */
> +	CCDC_12_BITS,
> +	/* 13 bits */
> +	CCDC_13_BITS,
> +	/* 14 bits */
> +	CCDC_14_BITS,
> +	/* 15 bits */
> +	CCDC_15_BITS,
> +	/* 16 bits */
> +	CCDC_16_BITS
> +};
> +
> +/**
> + * CCDC image data shift to right
> + */
> +enum ccdc_datasft {
> +	/* No Shift */
> +	CCDC_NO_SHIFT,
> +	/* 1 bit Shift */
> +	CCDC_1BIT_SHIFT,
> +	/* 2 bit Shift */
> +	CCDC_2BIT_SHIFT,
> +	/* 3 bit Shift */
> +	CCDC_3BIT_SHIFT,
> +	/* 4 bit Shift */
> +	CCDC_4BIT_SHIFT,
> +	/* 5 bit Shift */
> +	CCDC_5BIT_SHIFT,
> +	/* 6 bit Shift */
> +	CCDC_6BIT_SHIFT
> +};
> +
> +/**
> + * 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

Could you live without the comments in these 3 enum declarations ? 
They don't seem to add any information.


--
Regards,
Sylwester


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

* RE: [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module
  2011-09-01 20:47   ` Sylwester Nawrocki
@ 2011-09-09 13:20     ` Hadli, Manjunath
  0 siblings, 0 replies; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-09 13:20 UTC (permalink / raw)
  To: Sylwester Nawrocki; +Cc: LMML, dlos, Netagunte, Nagabhushana

Hi Sylwester,
  Thank you for your comments.
My responses inline.

Thanks and Regards,
-Manju

On Fri, Sep 02, 2011 at 02:17:49, Sylwester Nawrocki wrote:
> Hi Manjunath,
> 
> A few comments below...
> 
> On 08/29/2011 05:07 PM, Manjunath Hadli wrote:
> > add support for dm3xx IPIPEIF hardware setup. This is the lowest 
> > software layer for the dm3x vpfe driver which directly accesses 
> > hardware. Add support for features like default pixel correction, dark 
> > frame substraction  and hardware setup.
> > 
> > Signed-off-by: Manjunath Hadli<manjunath.hadli@ti.com>
> > Signed-off-by: Nagabhushana Netagunte<nagabhushana.netagunte@ti.com>
> > ---
> >   drivers/media/video/davinci/dm3xx_ipipeif.c |  317 +++++++++++++++++++++++++++
> >   drivers/media/video/davinci/dm3xx_ipipeif.h |  258 ++++++++++++++++++++++
> >   include/linux/dm3xx_ipipeif.h               |   64 ++++++
> >   3 files changed, 639 insertions(+), 0 deletions(-)
> >   create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
> >   create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
> >   create mode 100644 include/linux/dm3xx_ipipeif.h
> > 
> > diff --git a/drivers/media/video/davinci/dm3xx_ipipeif.c 
> > b/drivers/media/video/davinci/dm3xx_ipipeif.c
> > new file mode 100644
> > index 0000000..ebc8895
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/dm3xx_ipipeif.c
> > @@ -0,0 +1,317 @@
> ...
> > +
> > +static void ipipeif_config_dpc(struct ipipeif_dpc *dpc) {
> > +	u32 val;
> > +
> > +	/* Intialize val*/
> > +	val = 0;
> 
> s/Intialize/Initialize ? But this comment doesn't seem much helpful and could probably be removed. Also it might be better to just do:
> 
> 	u32 val = 0;
Done.
> 
> > +
> > +	if (dpc->en) {
> > +		val = (dpc->en&  1)<<  IPIPEIF_DPC2_EN_SHIFT;
> > +		val |= dpc->thr&  IPIPEIF_DPC2_THR_MASK;
> > +	}
> > +
> > +	regw_if(val, IPIPEIF_DPC2);
> > +}
> > +
> ...
> > +
> > +static int __devinit dm3xx_ipipeif_probe(struct platform_device 
> > +*pdev) {
> > +	static resource_size_t  res_len;
> > +	struct resource *res;
> > +	int status;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!res)
> > +		return -ENOENT;
> > +
> > +	res_len = res->end - res->start + 1;
> 
> resource_size(res) macro could be used here
Done.
> 
> > +
> > +	res = request_mem_region(res->start, res_len, res->name);
> > +	if (!res)
> > +		return -EBUSY;
> > +
> > +	ipipeif_base_addr = ioremap_nocache(res->start, res_len);
> > +	if (!ipipeif_base_addr) {
> > +		status = -EBUSY;
> > +		goto fail;
> > +	}
> > +	return 0;
> > +
> > +fail:
> > +	release_mem_region(res->start, res_len);
> > +
> > +	return status;
> > +}
> > +
> > +static int dm3xx_ipipeif_remove(struct platform_device *pdev) {
> > +	struct resource *res;
> > +
> > +	iounmap(ipipeif_base_addr);
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (res)
> > +		release_mem_region(res->start, res->end - res->start + 1);
> 
> 	release_mem_region(res->start, resource_size(res));
Done.
> 
> > +	return 0;
> > +}
> > +
> > +static struct platform_driver dm3xx_ipipeif_driver = {
> > +	.driver = {
> > +		.name   = "dm3xx_ipipeif",
> > +		.owner = THIS_MODULE,
> > +	},
> > +	.remove = __devexit_p(dm3xx_ipipeif_remove),
> > +	.probe = dm3xx_ipipeif_probe,
> > +};
> > +
> > +static int dm3xx_ipipeif_init(void)
> > +{
> > +	return platform_driver_register(&dm3xx_ipipeif_driver);
> > +}
> > +
> > +static void dm3xx_ipipeif_exit(void)
> > +{
> > +	platform_driver_unregister(&dm3xx_ipipeif_driver);
> > +}
> > +
> > +module_init(dm3xx_ipipeif_init);
> > +module_exit(dm3xx_ipipeif_exit);
> > +
> > +MODULE_LICENSE("GPL2");
> > diff --git a/drivers/media/video/davinci/dm3xx_ipipeif.h 
> > b/drivers/media/video/davinci/dm3xx_ipipeif.h
> > new file mode 100644
> > index 0000000..f3289f0
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/dm3xx_ipipeif.h
> > @@ -0,0 +1,258 @@
> > +/*
> ...
> > +
> > +/* IPIPEIF Register Offsets from the base address */
> > +#define IPIPEIF_ENABLE			(0x00)
> > +#define IPIPEIF_CFG1			(0x04)
> > +#define IPIPEIF_PPLN			(0x08)
> > +#define IPIPEIF_LPFR			(0x0c)
> > +#define IPIPEIF_HNUM			(0x10)
> > +#define IPIPEIF_VNUM			(0x14)
> > +#define IPIPEIF_ADDRU			(0x18)
> > +#define IPIPEIF_ADDRL			(0x1c)
> > +#define IPIPEIF_ADOFS			(0x20)
> > +#define IPIPEIF_RSZ			(0x24)
> > +#define IPIPEIF_GAIN			(0x28)
> > +
> > +/* Below registers are available only on IPIPE 5.1 */
> > +#define IPIPEIF_DPCM			(0x2c)
> > +#define IPIPEIF_CFG2			(0x30)
> > +#define IPIPEIF_INIRSZ			(0x34)
> > +#define IPIPEIF_OCLIP			(0x38)
> > +#define IPIPEIF_DTUDF			(0x3c)
> > +#define IPIPEIF_CLKDIV			(0x40)
> > +#define IPIPEIF_DPC1			(0x44)
> > +#define IPIPEIF_DPC2			(0x48)
> > +#define IPIPEIF_DFSGVL			(0x4c)
> > +#define IPIPEIF_DFSGTH			(0x50)
> > +#define IPIPEIF_RSZ3A			(0x54)
> > +#define IPIPEIF_INIRSZ3A		(0x58)
> > +#define IPIPEIF_RSZ_MIN			(16)
> > +#define IPIPEIF_RSZ_MAX			(112)
> > +#define IPIPEIF_RSZ_CONST		(16)
> > +#define SETBIT(reg, bit)   (reg = ((reg) | ((0x00000001)<<(bit))))
> > +#define RESETBIT(reg, bit) (reg = ((reg)&  (~(0x00000001<<(bit)))))
> > +
> > +#define IPIPEIF_ADOFS_LSB_MASK		(0x1ff)
> > +#define IPIPEIF_ADOFS_LSB_SHIFT		(5)
> > +#define IPIPEIF_ADOFS_MSB_MASK		(0x200)
> > +#define IPIPEIF_ADDRU_MASK		(0x7ff)
> > +#define IPIPEIF_ADDRL_SHIFT		(5)
> > +#define IPIPEIF_ADDRL_MASK		(0xffff)
> > +#define IPIPEIF_ADDRU_SHIFT		(21)
> > +#define IPIPEIF_ADDRMSB_SHIFT		(31)
> > +#define IPIPEIF_ADDRMSB_LEFT_SHIFT	(10)
> > +
> > +/* CFG1 Masks and shifts */
> > +#define ONESHOT_SHIFT			(0)
> > +#define DECIM_SHIFT			(1)
> > +#define INPSRC_SHIFT			(2)
> > +#define CLKDIV_SHIFT			(4)
> > +#define AVGFILT_SHIFT			(7)
> > +#define PACK8IN_SHIFT			(8)
> > +#define IALAW_SHIFT			(9)
> > +#define CLKSEL_SHIFT			(10)
> > +#define DATASFT_SHIFT			(11)
> > +#define INPSRC1_SHIFT			(14)
> > +
> > +/* DPC2 */
> > +#define IPIPEIF_DPC2_EN_SHIFT		(12)
> > +#define IPIPEIF_DPC2_THR_MASK		(0xfff)
> > +/* Applicable for IPIPE 5.1 */
> > +#define IPIPEIF_DF_GAIN_EN_SHIFT	(10)
> > +#define IPIPEIF_DF_GAIN_MASK		(0x3ff)
> > +#define IPIPEIF_DF_GAIN_THR_MASK	(0xfff)
> > +/* DPCM */
> > +#define IPIPEIF_DPCM_BITS_SHIFT		(2)
> > +#define IPIPEIF_DPCM_PRED_SHIFT		(1)
> > +/* CFG2 */
> > +#define IPIPEIF_CFG2_HDPOL_SHIFT	(1)
> > +#define IPIPEIF_CFG2_VDPOL_SHIFT	(2)
> > +#define IPIPEIF_CFG2_YUV8_SHIFT		(6)
> > +#define	IPIPEIF_CFG2_YUV16_SHIFT	(3)
> > +#define	IPIPEIF_CFG2_YUV8P_SHIFT	(7)
> > +
> > +/* INIRSZ */
> > +#define IPIPEIF_INIRSZ_ALNSYNC_SHIFT	(13)
> > +#define IPIPEIF_INIRSZ_MASK		(0x1fff)
> 
> Is there any good reason to use parentheses around the numbers ? 
No. It was in the plan to remove them. Now it is taken care of.
> 
> 
> --
> Regards,
> Sylwester
> 


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

* RE: [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365
  2011-09-01 21:23   ` Sylwester Nawrocki
@ 2011-09-09 13:30     ` Hadli, Manjunath
  2011-09-09 16:39       ` Sylwester Nawrocki
  0 siblings, 1 reply; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-09 13:30 UTC (permalink / raw)
  To: Sylwester Nawrocki; +Cc: LMML, dlos, Netagunte, Nagabhushana

Thank you for these comments too.

My responses inlined.
-Manju

On Fri, Sep 02, 2011 at 02:53:08, Sylwester Nawrocki wrote:
> Hi Manjunath,
> 
> few more comments below..
> 
> On 08/29/2011 05:07 PM, Manjunath Hadli wrote:
> > add support for ccdc on dm365 SoC. ccdc is responsible for capturing 
> > video data- both raw bayer through sync seperate signals and through 
> > BT656/1120 interfaces. This driver implements the hardware 
> > functionality. Mainly- setting of hardware, validation of parameters, 
> > and isr configuration.
> > 
> > Signed-off-by: Manjunath Hadli<manjunath.hadli@ti.com>
> > Signed-off-by: Nagabhushana Netagunte<nagabhushana.netagunte@ti.com>
> > ---
> >   drivers/media/video/davinci/ccdc_types.h      |   43 +
> >   drivers/media/video/davinci/dm365_ccdc.c      | 1519 +++++++++++++++++++++++++
> >   drivers/media/video/davinci/dm365_ccdc.h      |   88 ++
> >   drivers/media/video/davinci/dm365_ccdc_regs.h |  309 +++++
> >   include/linux/dm365_ccdc.h                    |  664 +++++++++++
> >   5 files changed, 2623 insertions(+), 0 deletions(-)
> >   create mode 100644 drivers/media/video/davinci/ccdc_types.h
> >   create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
> >   create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
> >   create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
> >   create mode 100644 include/linux/dm365_ccdc.h
> ...
> > +#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)
> > +
> > +/*masks and shifts*/
> > +#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/linux/dm365_ccdc.h b/include/linux/dm365_ccdc.h 
> > new file mode 100644 index 0000000..4e50529
> > --- /dev/null
> > +++ b/include/linux/dm365_ccdc.h
> > @@ -0,0 +1,664 @@
> ...
> > +#define VPFE_CMD_S_CCDC_RAW_PARAMS _IOW('V', 1, \
> > +					struct ccdc_config_params_raw)
> > +#define VPFE_CMD_G_CCDC_RAW_PARAMS _IOR('V', 2, \
> > +					struct ccdc_config_params_raw)
> > +/**
> > + * ccdc float type S8Q8/U8Q8
> > + */
> > +struct ccdc_float_8 {
> > +	/* 8 bit integer part */
> > +	unsigned char integer;
> > +	/* 8 bit decimal part */
> > +	unsigned char decimal;
> > +};
> 
> Isn't it better to use explicit width type, like u8, u16, etc. ?
> Then we could just have:
> 
> +struct ccdc_float_8 {
> +	u8 integer;
> +	u8 decimal;
> +};
> 
This is an interface header which is also used by apps. So we have kept it as unsigned char. Any suggestions on that?
> 
> > +
> > +/**
> > + * brief ccdc float type U16Q16/S16Q16
> 
> > + */
> > +struct ccdc_float_16 {
> > +	/* 16 bit integer part */
> > +	unsigned short integer;
> > +	/* 16 bit decimal part */
> > +	unsigned short decimal;
> > +};
> 
> and 
> 
> +struct ccdc_float_16 {
> +	u16 integer;
> +	u16 decimal;
> +};
> 
Ditto.
> > +
> > +/*
> > + * ccdc image(target) window parameters  */ struct ccdc_cropwin {
> > +	/* horzontal offset of the top left corner in pixels */
> > +	unsigned int left;
> > +	/* vertical offset of the top left corner in pixels */
> > +	unsigned int top;
> > +	/* width in pixels of the rectangle */
> > +	unsigned int width;
> > +	/* height in lines of the rectangle */
> > +	unsigned int height;
> > +};
> 
> How about using struct v4l2_rect instead ?
Done.
> 
> ...
> > +/**
> > + * CCDC image data size
> > + */
> > +enum ccdc_data_size {
> > +	/* 8 bits */
> > +	CCDC_8_BITS,
> > +	/* 9 bits */
> > +	CCDC_9_BITS,
> > +	/* 10 bits */
> > +	CCDC_10_BITS,
> > +	/* 11 bits */
> > +	CCDC_11_BITS,
> > +	/* 12 bits */
> > +	CCDC_12_BITS,
> > +	/* 13 bits */
> > +	CCDC_13_BITS,
> > +	/* 14 bits */
> > +	CCDC_14_BITS,
> > +	/* 15 bits */
> > +	CCDC_15_BITS,
> > +	/* 16 bits */
> > +	CCDC_16_BITS
> > +};
> > +
> > +/**
> > + * CCDC image data shift to right
> > + */
> > +enum ccdc_datasft {
> > +	/* No Shift */
> > +	CCDC_NO_SHIFT,
> > +	/* 1 bit Shift */
> > +	CCDC_1BIT_SHIFT,
> > +	/* 2 bit Shift */
> > +	CCDC_2BIT_SHIFT,
> > +	/* 3 bit Shift */
> > +	CCDC_3BIT_SHIFT,
> > +	/* 4 bit Shift */
> > +	CCDC_4BIT_SHIFT,
> > +	/* 5 bit Shift */
> > +	CCDC_5BIT_SHIFT,
> > +	/* 6 bit Shift */
> > +	CCDC_6BIT_SHIFT
> > +};
> > +
> > +/**
> > + * 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
> 
> Could you live without the comments in these 3 enum declarations ? 
> They don't seem to add any information.
OK.
> 
> 
> --
> Regards,
> Sylwester
> 
> 


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

* RE: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-08-31 21:30 ` Sakari Ailus
@ 2011-09-09 13:40   ` Hadli, Manjunath
  2011-09-09 16:19     ` Sakari Ailus
  0 siblings, 1 reply; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-09 13:40 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: LMML, dlos

Hi Sakari,

On Thu, Sep 01, 2011 at 03:00:32, Sakari Ailus wrote:
> Hi Manju,
> 
> Do you have the media device grap that would be typical for this hardware produced by media-ctl? That can be converted to postscript using dotfile.
> 
> this would make it a little easier to understan this driver. Thanks.

Sure. But can you be a little more elaborate on how you need this information? If you can tell me in little more detail about this that will help me make the information in a way that everyone can understand.

Thanks and Regards,
-Manju


> 
> On Mon, Aug 29, 2011 at 08:37:11PM +0530, Manjunath Hadli wrote:
> > changes from last patch set:
> > 1. Made changes based on Sakari's feedback mainly:
> >         a. returned early to allow unindenting
> >         b. reformatting to shift the code to left where possible
> >         c. changed hex numbers to lower case
> >         d. corrected the defines according to module names.
> >         e. magic numbers removed.
> >         f. changed non-integer returning functions to void
> >         g. removed unwanted paranthses.
> >         h. fixed error codes.
> >         i. fixed some RESET_BIt code to what it was intended for.
> > 2. reorganized the header files to move the kernel-only headers along 
> > with the c files and interface headers in the include folder.
> > 
...



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

* Re: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-09 13:40   ` Hadli, Manjunath
@ 2011-09-09 16:19     ` Sakari Ailus
  2011-09-10  6:41       ` Hadli, Manjunath
  0 siblings, 1 reply; 27+ messages in thread
From: Sakari Ailus @ 2011-09-09 16:19 UTC (permalink / raw)
  To: Hadli, Manjunath; +Cc: LMML, dlos

On Fri, Sep 09, 2011 at 07:10:49PM +0530, Hadli, Manjunath wrote:
> Hi Sakari,
> 
> On Thu, Sep 01, 2011 at 03:00:32, Sakari Ailus wrote:
> > Hi Manju,
> > 
> > Do you have the media device grap that would be typical for this hardware produced by media-ctl? That can be converted to postscript using dotfile.
> > 
> > this would make it a little easier to understan this driver. Thanks.
> 
> Sure. But can you be a little more elaborate on how you need this
> information? If you can tell me in little more detail about this that will
> help me make the information in a way that everyone can understand.

Preferrably in PostScript format so it's easy to visualise the layout of the
hardware that the driver supports, as the OMAP 3 ISP example was.

> Thanks and Regards,
> -Manju
> 
> 
> > 
> > On Mon, Aug 29, 2011 at 08:37:11PM +0530, Manjunath Hadli wrote:
> > > changes from last patch set:
> > > 1. Made changes based on Sakari's feedback mainly:
> > >         a. returned early to allow unindenting
> > >         b. reformatting to shift the code to left where possible
> > >         c. changed hex numbers to lower case
> > >         d. corrected the defines according to module names.
> > >         e. magic numbers removed.
> > >         f. changed non-integer returning functions to void
> > >         g. removed unwanted paranthses.
> > >         h. fixed error codes.
> > >         i. fixed some RESET_BIt code to what it was intended for.
> > > 2. reorganized the header files to move the kernel-only headers along 
> > > with the c files and interface headers in the include folder.
> > > 
> ...
> 
> 

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk

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

* Re: [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365
  2011-09-09 13:30     ` Hadli, Manjunath
@ 2011-09-09 16:39       ` Sylwester Nawrocki
  0 siblings, 0 replies; 27+ messages in thread
From: Sylwester Nawrocki @ 2011-09-09 16:39 UTC (permalink / raw)
  To: Hadli, Manjunath; +Cc: LMML, dlos, Netagunte, Nagabhushana

Hi Manju,

On 09/09/2011 03:30 PM, Hadli, Manjunath wrote:
> Thank you for these comments too.
> 
> My responses inlined.
> -Manju

Thanks for addressing my comments.

> 
> On Fri, Sep 02, 2011 at 02:53:08, Sylwester Nawrocki wrote:
...
>>> +/**
>>> + * ccdc float type S8Q8/U8Q8
>>> + */
>>> +struct ccdc_float_8 {
>>> +	/* 8 bit integer part */
>>> +	unsigned char integer;
>>> +	/* 8 bit decimal part */
>>> +	unsigned char decimal;
>>> +};
>>
>> Isn't it better to use explicit width type, like u8, u16, etc. ?
>> Then we could just have:
>>
>> +struct ccdc_float_8 {
>> +	u8 integer;
>> +	u8 decimal;
>> +};
>>
> This is an interface header which is also used by apps. So we have
> kept it as unsigned char. Any suggestions on that?

OK, sorry, I haven't noticed that. Anyway, I think you could use the
double underscore prefixed types (__[u,s][8,32,16]), from linux/types.h.
They are widely used in in linux/videodev2.h for instance.


--
Regards,
Sylwester

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

* RE: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-09 16:19     ` Sakari Ailus
@ 2011-09-10  6:41       ` Hadli, Manjunath
  2011-09-12 11:59         ` Sakari Ailus
  0 siblings, 1 reply; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-10  6:41 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: LMML, dlos

Hi Sakari,
On Fri, Sep 09, 2011 at 21:49:40, Sakari Ailus wrote:
> On Fri, Sep 09, 2011 at 07:10:49PM +0530, Hadli, Manjunath wrote:
> > Hi Sakari,
> > 
> > On Thu, Sep 01, 2011 at 03:00:32, Sakari Ailus wrote:
> > > Hi Manju,
> > > 
> > > Do you have the media device grap that would be typical for this hardware produced by media-ctl? That can be converted to postscript using dotfile.
> > > 
> > > this would make it a little easier to understan this driver. Thanks.
> > 
> > Sure. But can you be a little more elaborate on how you need this 
> > information? If you can tell me in little more detail about this that 
> > will help me make the information in a way that everyone can understand.
> 
> Preferrably in PostScript format so it's easy to visualise the layout of the hardware that the driver supports, as the OMAP 3 ISP example was.
Sure.
 I was more looking for an example of the same so it could help me put the data together in the way it has been done before. Can you send across if you have one?

Many Thx,
-Manju

> 
> > Thanks and Regards,
> > -Manju
> > 
> > 
> > > 
> > > On Mon, Aug 29, 2011 at 08:37:11PM +0530, Manjunath Hadli wrote:
> > > > changes from last patch set:
> > > > 1. Made changes based on Sakari's feedback mainly:
> > > >         a. returned early to allow unindenting
> > > >         b. reformatting to shift the code to left where possible
> > > >         c. changed hex numbers to lower case
> > > >         d. corrected the defines according to module names.
> > > >         e. magic numbers removed.
> > > >         f. changed non-integer returning functions to void
> > > >         g. removed unwanted paranthses.
> > > >         h. fixed error codes.
> > > >         i. fixed some RESET_BIt code to what it was intended for.
> > > > 2. reorganized the header files to move the kernel-only headers 
> > > > along with the c files and interface headers in the include folder.
> > > > 
> > ...
> > 
> > 
> 
> --
> Sakari Ailus
> e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk
> 


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

* Re: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-10  6:41       ` Hadli, Manjunath
@ 2011-09-12 11:59         ` Sakari Ailus
  2011-09-12 14:18           ` Hadli, Manjunath
  2011-09-14 19:02           ` Hadli, Manjunath
  0 siblings, 2 replies; 27+ messages in thread
From: Sakari Ailus @ 2011-09-12 11:59 UTC (permalink / raw)
  To: Hadli, Manjunath; +Cc: LMML, dlos

On Sat, Sep 10, 2011 at 12:11:37PM +0530, Hadli, Manjunath wrote:
> Hi Sakari,
> On Fri, Sep 09, 2011 at 21:49:40, Sakari Ailus wrote:
> > On Fri, Sep 09, 2011 at 07:10:49PM +0530, Hadli, Manjunath wrote:
> > > Hi Sakari,
> > > 
> > > On Thu, Sep 01, 2011 at 03:00:32, Sakari Ailus wrote:
> > > > Hi Manju,
> > > > 
> > > > Do you have the media device grap that would be typical for this hardware produced by media-ctl? That can be converted to postscript using dotfile.
> > > > 
> > > > this would make it a little easier to understan this driver. Thanks.
> > > 
> > > Sure. But can you be a little more elaborate on how you need this 
> > > information? If you can tell me in little more detail about this that 
> > > will help me make the information in a way that everyone can understand.
> > 
> > Preferrably in PostScript format so it's easy to visualise the layout of the hardware that the driver supports, as the OMAP 3 ISP example was.
> Sure.
>  I was more looking for an example of the same so it could help me put the
> data together in the way it has been done before. Can you send across if
> you have one?

Ah. I think I misunderstood you first. :-)

On the device, run

	$ media-ctl --print-dot > graph.dot

This will produce a graph of the media device in the dot format. This is
then processed by program called dot:

	$ dot -o graph.ps -T ps < graph.dot

dot is available at least in Debian in a package called graphviz.

Cheers,

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk

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

* RE: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-12 11:59         ` Sakari Ailus
@ 2011-09-12 14:18           ` Hadli, Manjunath
  2011-09-14 19:02           ` Hadli, Manjunath
  1 sibling, 0 replies; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-12 14:18 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: LMML, dlos

Thank you Sakari.
-Manju

On Mon, Sep 12, 2011 at 17:29:25, Sakari Ailus wrote:
> On Sat, Sep 10, 2011 at 12:11:37PM +0530, Hadli, Manjunath wrote:
> > Hi Sakari,
> > On Fri, Sep 09, 2011 at 21:49:40, Sakari Ailus wrote:
> > > On Fri, Sep 09, 2011 at 07:10:49PM +0530, Hadli, Manjunath wrote:
> > > > Hi Sakari,
> > > > 
> > > > On Thu, Sep 01, 2011 at 03:00:32, Sakari Ailus wrote:
> > > > > Hi Manju,
> > > > > 
> > > > > Do you have the media device grap that would be typical for this hardware produced by media-ctl? That can be converted to postscript using dotfile.
> > > > > 
> > > > > this would make it a little easier to understan this driver. Thanks.
> > > > 
> > > > Sure. But can you be a little more elaborate on how you need this 
> > > > information? If you can tell me in little more detail about this 
> > > > that will help me make the information in a way that everyone can understand.
> > > 
> > > Preferrably in PostScript format so it's easy to visualise the layout of the hardware that the driver supports, as the OMAP 3 ISP example was.
> > Sure.
> >  I was more looking for an example of the same so it could help me put 
> > the data together in the way it has been done before. Can you send 
> > across if you have one?
> 
> Ah. I think I misunderstood you first. :-)
> 
> On the device, run
> 
> 	$ media-ctl --print-dot > graph.dot
> 
> This will produce a graph of the media device in the dot format. This is then processed by program called dot:
> 
> 	$ dot -o graph.ps -T ps < graph.dot
> 
> dot is available at least in Debian in a package called graphviz.
> 
> Cheers,
> 
> --
> Sakari Ailus
> e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk
> 


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

* RE: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-12 11:59         ` Sakari Ailus
  2011-09-12 14:18           ` Hadli, Manjunath
@ 2011-09-14 19:02           ` Hadli, Manjunath
  2011-09-16 21:05             ` Sakari Ailus
  1 sibling, 1 reply; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-14 19:02 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: LMML, dlos

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

Hello Sakari,
 I have attached two .ps files with the entity graph details in them, one with RAW input and the other with YCbCr.
Hope this is what you were looking for?

Thanks and Regards,
-Manju

On Mon, Sep 12, 2011 at 17:29:25, Sakari Ailus wrote:
> On Sat, Sep 10, 2011 at 12:11:37PM +0530, Hadli, Manjunath wrote:
> > Hi Sakari,
> > On Fri, Sep 09, 2011 at 21:49:40, Sakari Ailus wrote:
> > > On Fri, Sep 09, 2011 at 07:10:49PM +0530, Hadli, Manjunath wrote:
> > > > Hi Sakari,
> > > > 
> > > > On Thu, Sep 01, 2011 at 03:00:32, Sakari Ailus wrote:
> > > > > Hi Manju,
> > > > > 
> > > > > Do you have the media device grap that would be typical for this hardware produced by media-ctl? That can be converted to postscript using dotfile.
> > > > > 
> > > > > this would make it a little easier to understan this driver. Thanks.
> > > > 
> > > > Sure. But can you be a little more elaborate on how you need this 
> > > > information? If you can tell me in little more detail about this 
> > > > that will help me make the information in a way that everyone can understand.
> > > 
> > > Preferrably in PostScript format so it's easy to visualise the layout of the hardware that the driver supports, as the OMAP 3 ISP example was.
> > Sure.
> >  I was more looking for an example of the same so it could help me put 
> > the data together in the way it has been done before. Can you send 
> > across if you have one?
> 
> Ah. I think I misunderstood you first. :-)
> 
> On the device, run
> 
> 	$ media-ctl --print-dot > graph.dot
> 
> This will produce a graph of the media device in the dot format. This is then processed by program called dot:
> 
> 	$ dot -o graph.ps -T ps < graph.dot
> 
> dot is available at least in Debian in a package called graphviz.
> 
> Cheers,
> 
> --
> Sakari Ailus
> e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk
> 


[-- Attachment #2: tvp.ps --]
[-- Type: application/postscript, Size: 29137 bytes --]

[-- Attachment #3: capture.ps --]
[-- Type: application/postscript, Size: 26101 bytes --]

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

* Re: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-14 19:02           ` Hadli, Manjunath
@ 2011-09-16 21:05             ` Sakari Ailus
  0 siblings, 0 replies; 27+ messages in thread
From: Sakari Ailus @ 2011-09-16 21:05 UTC (permalink / raw)
  To: Hadli, Manjunath; +Cc: LMML, dlos

On Thu, Sep 15, 2011 at 12:32:33AM +0530, Hadli, Manjunath wrote:
> Hello Sakari,
>  I have attached two .ps files with the entity graph details in them, one with RAW input and the other with YCbCr.
> Hope this is what you were looking for?

Hi Manju,

This was exactly what I was looking for. Thanks!

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk

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

* Re: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
                   ` (9 preceding siblings ...)
  2011-08-31 21:30 ` Sakari Ailus
@ 2011-09-18 14:35 ` Mauro Carvalho Chehab
  2011-09-19  5:09   ` Hadli, Manjunath
  10 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2011-09-18 14:35 UTC (permalink / raw)
  To: Manjunath Hadli; +Cc: LMML, dlos

Em 29-08-2011 12:07, Manjunath Hadli escreveu:
> changes from last patch set:
> 1. Made changes based on Sakari's feedback mainly:
>         a. returned early to allow unindenting
>         b. reformatting to shift the code to left where possible
>         c. changed hex numbers to lower case
>         d. corrected the defines according to module names.
>         e. magic numbers removed.
>         f. changed non-integer returning functions to void
>         g. removed unwanted paranthses.
>         h. fixed error codes.
>         i. fixed some RESET_BIt code to what it was intended for.
> 2. reorganized the header files to move the kernel-only headers
> along with the c files and interface headers in the include folder.

Manju,

Please be sure to send me a pull request when you think this driver
is ready for merge. The first submission I'm noticing for this driver
was back on 2009, and still today, nobody sent me a git pull request
for it. Two years seems too much time to solve the pending issues
and sending a pull request for me to merge it!
> 
> Manjunath Hadli (6):
>   davinci: vpfe: add dm3xx IPIPEIF hardware support module
>   davinci: vpfe: add support for CCDC hardware for dm365
>   davinci: vpfe: add ccdc driver with media controller interface
>   davinci: vpfe: add v4l2 video driver support
>   davinci: vpfe: v4l2 capture driver with media interface
>   davinci: vpfe: build infrastructure for dm365
> 
> Nagabhushana Netagunte (2):
>   davinci: vpfe: add IPIPE hardware layer support
>   davinci: vpfe: add IPIPE support for media controller driver
> 
>  drivers/media/video/davinci/Kconfig           |   46 +-
>  drivers/media/video/davinci/Makefile          |   17 +-
>  drivers/media/video/davinci/ccdc_hw_device.h  |   10 +-
>  drivers/media/video/davinci/ccdc_types.h      |   43 +
>  drivers/media/video/davinci/dm365_ccdc.c      | 1519 ++++++++++
>  drivers/media/video/davinci/dm365_ccdc.h      |   88 +
>  drivers/media/video/davinci/dm365_ccdc_regs.h |  309 ++
>  drivers/media/video/davinci/dm365_def_para.c  |  486 +++
>  drivers/media/video/davinci/dm365_def_para.h  |   39 +
>  drivers/media/video/davinci/dm365_ipipe.c     | 3966 +++++++++++++++++++++++++
>  drivers/media/video/davinci/dm365_ipipe.h     |  300 ++
>  drivers/media/video/davinci/dm365_ipipe_hw.c  |  949 ++++++
>  drivers/media/video/davinci/dm365_ipipe_hw.h  |  539 ++++
>  drivers/media/video/davinci/dm3xx_ipipeif.c   |  317 ++
>  drivers/media/video/davinci/dm3xx_ipipeif.h   |  258 ++
>  drivers/media/video/davinci/imp_common.h      |   85 +
>  drivers/media/video/davinci/imp_hw_if.h       |  178 ++
>  drivers/media/video/davinci/vpfe_capture.c    |  793 +++++
>  drivers/media/video/davinci/vpfe_capture.h    |  104 +
>  drivers/media/video/davinci/vpfe_ccdc.c       |  813 +++++
>  drivers/media/video/davinci/vpfe_ccdc.h       |   85 +
>  drivers/media/video/davinci/vpfe_video.c      | 1712 +++++++++++
>  drivers/media/video/davinci/vpfe_video.h      |  142 +
>  include/linux/davinci_vpfe.h                  | 1223 ++++++++
>  include/linux/dm365_ccdc.h                    |  664 +++++
>  include/linux/dm3xx_ipipeif.h                 |   64 +
>  include/media/davinci/vpfe.h                  |   91 +
>  27 files changed, 14829 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/media/video/davinci/ccdc_types.h
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
>  create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.c
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h
>  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
>  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
>  create mode 100644 drivers/media/video/davinci/imp_common.h
>  create mode 100644 drivers/media/video/davinci/imp_hw_if.h
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.c
>  create mode 100644 drivers/media/video/davinci/vpfe_capture.h
>  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.c
>  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.h
>  create mode 100644 drivers/media/video/davinci/vpfe_video.c
>  create mode 100644 drivers/media/video/davinci/vpfe_video.h
>  create mode 100644 include/linux/davinci_vpfe.h
>  create mode 100644 include/linux/dm365_ccdc.h
>  create mode 100644 include/linux/dm3xx_ipipeif.h
>  create mode 100644 include/media/davinci/vpfe.h
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* RE: [PATCH v2 0/8] RFC for Media Controller capture driver for DM365
  2011-09-18 14:35 ` Mauro Carvalho Chehab
@ 2011-09-19  5:09   ` Hadli, Manjunath
  0 siblings, 0 replies; 27+ messages in thread
From: Hadli, Manjunath @ 2011-09-19  5:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: LMML, dlos

Mauro,
  Thank you for your note.
  The first RFC for this (VPFE MC) driver was sent only in August this year. The other driver being discussed before was VPBE (which did go through some grind but not 2 years) which you accepted. This series of patches is definitely not two years old (unless I am mistaken somewhere).
 Currently Sakari is taking active interest in reviewing the patches, but I would like to take the cue from your note to request others also to actively review these patches and help me get them accepted.

Thanks and Regards,
-Manju


On Sun, Sep 18, 2011 at 20:05:46, Mauro Carvalho Chehab wrote:
> Em 29-08-2011 12:07, Manjunath Hadli escreveu:
> > changes from last patch set:
> > 1. Made changes based on Sakari's feedback mainly:
> >         a. returned early to allow unindenting
> >         b. reformatting to shift the code to left where possible
> >         c. changed hex numbers to lower case
> >         d. corrected the defines according to module names.
> >         e. magic numbers removed.
> >         f. changed non-integer returning functions to void
> >         g. removed unwanted paranthses.
> >         h. fixed error codes.
> >         i. fixed some RESET_BIt code to what it was intended for.
> > 2. reorganized the header files to move the kernel-only headers along 
> > with the c files and interface headers in the include folder.
> 
> Manju,
> 
> Please be sure to send me a pull request when you think this driver is ready for merge. The first submission I'm noticing for this driver was back on 2009, and still today, nobody sent me a git pull request for it. Two years seems too much time to solve the pending issues and sending a pull request for me to merge it!
> > 
> > Manjunath Hadli (6):
> >   davinci: vpfe: add dm3xx IPIPEIF hardware support module
> >   davinci: vpfe: add support for CCDC hardware for dm365
> >   davinci: vpfe: add ccdc driver with media controller interface
> >   davinci: vpfe: add v4l2 video driver support
> >   davinci: vpfe: v4l2 capture driver with media interface
> >   davinci: vpfe: build infrastructure for dm365
> > 
> > Nagabhushana Netagunte (2):
> >   davinci: vpfe: add IPIPE hardware layer support
> >   davinci: vpfe: add IPIPE support for media controller driver
> > 
> >  drivers/media/video/davinci/Kconfig           |   46 +-
> >  drivers/media/video/davinci/Makefile          |   17 +-
> >  drivers/media/video/davinci/ccdc_hw_device.h  |   10 +-
> >  drivers/media/video/davinci/ccdc_types.h      |   43 +
> >  drivers/media/video/davinci/dm365_ccdc.c      | 1519 ++++++++++
> >  drivers/media/video/davinci/dm365_ccdc.h      |   88 +
> >  drivers/media/video/davinci/dm365_ccdc_regs.h |  309 ++  
> > drivers/media/video/davinci/dm365_def_para.c  |  486 +++
> >  drivers/media/video/davinci/dm365_def_para.h  |   39 +
> >  drivers/media/video/davinci/dm365_ipipe.c     | 3966 +++++++++++++++++++++++++
> >  drivers/media/video/davinci/dm365_ipipe.h     |  300 ++
> >  drivers/media/video/davinci/dm365_ipipe_hw.c  |  949 ++++++  
> > drivers/media/video/davinci/dm365_ipipe_hw.h  |  539 ++++
> >  drivers/media/video/davinci/dm3xx_ipipeif.c   |  317 ++
> >  drivers/media/video/davinci/dm3xx_ipipeif.h   |  258 ++
> >  drivers/media/video/davinci/imp_common.h      |   85 +
> >  drivers/media/video/davinci/imp_hw_if.h       |  178 ++
> >  drivers/media/video/davinci/vpfe_capture.c    |  793 +++++
> >  drivers/media/video/davinci/vpfe_capture.h    |  104 +
> >  drivers/media/video/davinci/vpfe_ccdc.c       |  813 +++++
> >  drivers/media/video/davinci/vpfe_ccdc.h       |   85 +
> >  drivers/media/video/davinci/vpfe_video.c      | 1712 +++++++++++
> >  drivers/media/video/davinci/vpfe_video.h      |  142 +
> >  include/linux/davinci_vpfe.h                  | 1223 ++++++++
> >  include/linux/dm365_ccdc.h                    |  664 +++++
> >  include/linux/dm3xx_ipipeif.h                 |   64 +
> >  include/media/davinci/vpfe.h                  |   91 +
> >  27 files changed, 14829 insertions(+), 11 deletions(-)  create mode 
> > 100644 drivers/media/video/davinci/ccdc_types.h
> >  create mode 100644 drivers/media/video/davinci/dm365_ccdc.c
> >  create mode 100644 drivers/media/video/davinci/dm365_ccdc.h
> >  create mode 100644 drivers/media/video/davinci/dm365_ccdc_regs.h
> >  create mode 100644 drivers/media/video/davinci/dm365_def_para.c
> >  create mode 100644 drivers/media/video/davinci/dm365_def_para.h
> >  create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
> >  create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
> >  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c
> >  create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h
> >  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.c
> >  create mode 100644 drivers/media/video/davinci/dm3xx_ipipeif.h
> >  create mode 100644 drivers/media/video/davinci/imp_common.h
> >  create mode 100644 drivers/media/video/davinci/imp_hw_if.h
> >  create mode 100644 drivers/media/video/davinci/vpfe_capture.c
> >  create mode 100644 drivers/media/video/davinci/vpfe_capture.h
> >  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.c
> >  create mode 100644 drivers/media/video/davinci/vpfe_ccdc.h
> >  create mode 100644 drivers/media/video/davinci/vpfe_video.c
> >  create mode 100644 drivers/media/video/davinci/vpfe_video.h
> >  create mode 100644 include/linux/davinci_vpfe.h  create mode 100644 
> > include/linux/dm365_ccdc.h  create mode 100644 
> > include/linux/dm3xx_ipipeif.h  create mode 100644 
> > include/media/davinci/vpfe.h
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" 
> > in the body of a message to majordomo@vger.kernel.org More majordomo 
> > info at  http://vger.kernel.org/majordomo-info.html
> 
> 


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

* Re: [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver
  2011-08-29 15:07 ` [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver Manjunath Hadli
@ 2011-09-27 14:01   ` Sakari Ailus
  2011-10-17 14:16     ` Hadli, Manjunath
  0 siblings, 1 reply; 27+ messages in thread
From: Sakari Ailus @ 2011-09-27 14:01 UTC (permalink / raw)
  To: Manjunath Hadli; +Cc: LMML, dlos, Nagabhushana Netagunte

Hi Manju,

My apologies for the very late review for these patches.

A general comment: all the functions that do need to use device specific
information must take the device as a parameter. Look at the OMAP 3 ISP
driver for an example.

Manjunath Hadli wrote:
> From: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
> 
> Add the IPIPE interfacing layer to the vpfe driver. This patch adds dm365
> specific implementation of the genric imp_hw_interface interface for
> programming the IPIPE block, mainly setting the resizer and previewer
> configuration parameters. This is built as an independent module.
> 
> Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
> Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
> ---
>  drivers/media/video/davinci/dm365_def_para.c |  486 ++++
>  drivers/media/video/davinci/dm365_def_para.h |   39 +
>  drivers/media/video/davinci/dm365_ipipe.c    | 3966 ++++++++++++++++++++++++++
>  drivers/media/video/davinci/dm365_ipipe.h    |  300 ++
>  drivers/media/video/davinci/imp_common.h     |   85 +
>  drivers/media/video/davinci/imp_hw_if.h      |  178 ++
>  6 files changed, 5054 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.c
>  create mode 100644 drivers/media/video/davinci/dm365_def_para.h
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
>  create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
>  create mode 100644 drivers/media/video/davinci/imp_common.h
>  create mode 100644 drivers/media/video/davinci/imp_hw_if.h
> 
> diff --git a/drivers/media/video/davinci/dm365_def_para.c b/drivers/media/video/davinci/dm365_def_para.c
> new file mode 100644
> index 0000000..d5af73b
> --- /dev/null
> +++ b/drivers/media/video/davinci/dm365_def_para.c
> @@ -0,0 +1,486 @@
> +/*
> +* Copyright (C) 2011 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
> +*/
> +#include <linux/v4l2-mediabus.h>
> +#include <media/davinci/vpfe.h>
> +#include "dm365_ipipe.h"
> +
> +/* Defaults for lutdpc */
> +struct prev_lutdpc dm365_lutdpc_defaults = {
> +	.en = 0
> +};
> +
> +/* Defaults for otfdpc */
> +struct prev_lutdpc dm365_otfdpc_defaults = {
> +	.en = 0
> +};
> +
> +/* Defaults for 2D - nf */
> +struct prev_nf dm365_nf_defaults = {
> +	.en = 0
> +};
> +
> +/* defaults for GIC */
> +struct prev_gic dm365_gic_defaults = {
> +	.en = 0
> +};
> +
> +/* Defaults for white balance */
> +struct prev_wb dm365_wb_defaults = {
> +	.gain_r = {2, 0x00},
> +	.gain_gr = {2, 0x00},
> +	.gain_gb = {2, 0x00},
> +	.gain_b = {2, 0x00}
> +};
> +
> +/* Defaults for CFA */
> +struct prev_cfa dm365_cfa_defaults = {
> +	.alg = IPIPE_CFA_ALG_2DIRAC,
> +	.hpf_thr_2dir = 0,
> +	.hpf_slp_2dir = 0,
> +	.hp_mix_thr_2dir = 0,
> +	.hp_mix_slope_2dir = 0,
> +	.dir_thr_2dir = 0,
> +	.dir_slope_2dir = 0,
> +	.nd_wt_2dir = 0,
> +	.hue_fract_daa = 0,
> +	.edge_thr_daa = 0,
> +	.thr_min_daa = 0,
> +	.thr_slope_daa = 0,
> +	.slope_min_daa = 0,
> +	.slope_slope_daa = 0,
> +	.lp_wt_daa = 0
> +};

Statically allocated memory is zero by default. You might want to do
this kind of initisation in a function initialising the device specific
structures rather than storing defaults to memory as almost all of this
is zeros.

> +/* Defaults for rgb2rgb */
> +struct prev_rgb2rgb dm365_rgb2rgb_defaults = {
> +	.coef_rr = {1, 0},	/* 256 */
> +	.coef_gr = {0, 0},
> +	.coef_br = {0, 0},
> +	.coef_rg = {0, 0},
> +	.coef_gg = {1, 0},	/* 256 */
> +	.coef_bg = {0, 0},
> +	.coef_rb = {0, 0},
> +	.coef_gb = {0, 0},
> +	.coef_bb = {1, 0},	/* 256 */
> +	.out_ofst_r = 0,
> +	.out_ofst_g = 0,
> +	.out_ofst_b = 0
> +};
> +
> +/* Defaults for gamma correction */
> +struct prev_gamma dm365_gamma_defaults = {
> +	.bypass_r = 0,
> +	.bypass_b = 0,
> +	.bypass_g = 0,
> +	.tbl_sel = IPIPE_GAMMA_TBL_ROM
> +};
> +
> +/* Defaults for 3d lut */
> +struct prev_3d_lut dm365_3d_lut_defaults = {
> +	.en = 0
> +};
> +
> +/* Defaults for lumina adjustments */
> +struct prev_lum_adj dm365_lum_adj_defaults = {
> +	.brightness = 0,
> +	.contrast = 16
> +};

This should probably be implemented as V4L2 controls. There are control
ids for both brightness and contrast.

> +/* Defaults for rgb2yuv conversion */
> +struct prev_rgb2yuv dm365_rgb2yuv_defaults = {
> +	.coef_ry = {0, 0x4D},
> +	.coef_gy = {0, 0x96},
> +	.coef_by = {0, 0x1D},
> +	.coef_rcb = {0xF, 0xD5},
> +	.coef_gcb = {0xF, 0xAB},
> +	.coef_bcb = {0, 0x80},
> +	.coef_rcr = {0, 0x80},
> +	.coef_gcr = {0xF, 0x95},
> +	.coef_bcr = {0xF, 0xEB},
> +	.out_ofst_y = 0,
> +	.out_ofst_cb = 0x80,
> +	.out_ofst_cr = 0x80
> +};

Lower case hexadecimals, please.

> +/* Defaults for GBCE */
> +struct prev_gbce dm365_gbce_defaults = {
> +	.en = 0
> +};
> +
> +/* Defaults for yuv 422 conversion */
> +struct prev_yuv422_conv dm365_yuv422_conv_defaults = {
> +	.en_chrom_lpf = 0,
> +	.chrom_pos = IPIPE_YUV422_CHR_POS_COSITE
> +};
> +
> +/* Defaults for Edge Ehnancements  */
> +struct prev_yee dm365_yee_defaults = {
> +	.en = 0,
> +};
> +
> +/* Defaults for CAR conversion */
> +struct prev_car dm365_car_defaults = {
> +	.en = 0,
> +};
> +
> +/* Defaults for CGS */
> +struct prev_cgs dm365_cgs_defaults = {
> +	.en = 0,
> +};
> +
> +#define  WIDTH_I 640
> +#define  HEIGHT_I 480
> +#define  WIDTH_O 640
> +#define  HEIGHT_O 480

Is the image size that this hardware block process static?

> +/* default ipipeif settings */
> +struct ipipeif_5_1 ipipeif_5_1_defaults = {
> +	.pack_mode = IPIPEIF_5_1_PACK_16_BIT,
> +	.data_shift = IPIPEIF_BITS11_0,
> +	.source1 = IPIPEIF_SRC1_PARALLEL_PORT,
> +	.clk_div = {
> +		.m = 1,	/* clock = sdram clock * (m/n) */
> +		.n = 6
> +	},
> +	.dpc = {
> +		.en = 0,
> +	},
> +	.dpcm = {
> +		.en = 0,
> +		.type = IPIPEIF_DPCM_8BIT_12BIT,
> +		.pred = IPIPEIF_DPCM_SIMPLE_PRED
> +	},
> +	.pix_order = IPIPEIF_CBCR_Y,
> +	.isif_port = {
> +		.if_type = V4L2_MBUS_FMT_SBGGR10_1X10,
> +		.hdpol = VPFE_PINPOL_POSITIVE,
> +		.vdpol = VPFE_PINPOL_POSITIVE
> +	},
> +	.clip = 4095,
> +	.align_sync = 0,
> +	.rsz_start = 0,
> +	.df_gain_en = 0
> +};
> +
> +struct ipipe_params dm365_ipipe_defs = {
> +	.ipipeif_param = {
> +		.mode = IPIPEIF_ONE_SHOT,
> +		.source = IPIPEIF_SDRAM_RAW,
> +		.clock_select = IPIPEIF_SDRAM_CLK,
> +		.glob_hor_size = WIDTH_I + 8,
> +		.glob_ver_size = HEIGHT_I + 10,
> +		.hnum = WIDTH_I,
> +		.vnum = HEIGHT_I,
> +		.adofs = WIDTH_I * 2,
> +		.rsz = 16,	/* resize ratio 16/rsz */
> +		.decimation = IPIPEIF_DECIMATION_OFF,
> +		.avg_filter = IPIPEIF_AVG_OFF,
> +		.gain = 0x200,	/* U10Q9 */
> +	},
> +	.ipipe_mode = IPIPEIF_ONE_SHOT,
> +	.ipipe_dpaths_fmt = IPIPE_RAW2YUV,
> +	.ipipe_colpat_olop = IPIPE_GREEN_BLUE,
> +	.ipipe_colpat_olep = IPIPE_BLUE,
> +	.ipipe_colpat_elop = IPIPE_RED,
> +	.ipipe_colpat_elep = IPIPE_GREEN_RED,
> +	.ipipe_vps = 0,
> +	.ipipe_vsz = HEIGHT_I - 1,
> +	.ipipe_hps = 0,
> +	.ipipe_hsz = WIDTH_I - 1,
> +	.rsz_common = {
> +		.vps = 0,
> +		.vsz = HEIGHT_I - 1,
> +		.hps = 0,
> +		.hsz = WIDTH_I - 1,
> +		.src_img_fmt = RSZ_IMG_422,
> +		.y_c = 0,
> +		.raw_flip = 1,	/* flip preserve Raw format */
> +		.source = IPIPE_DATA,
> +		.passthrough = IPIPE_BYPASS_OFF,
> +		.yuv_y_min = 0,
> +		.yuv_y_max = 255,
> +		.yuv_c_min = 0,
> +		.yuv_c_max = 255,
> +		.rsz_seq_crv = DISABLE,
> +		.out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE
> +	},
> +	.rsz_rsc_param = {
> +		{
> +			.mode = IPIPEIF_ONE_SHOT,
> +			.h_flip = DISABLE,
> +			.v_flip = DISABLE,
> +			.cen = DISABLE,
> +			.yen = DISABLE,
> +			.i_vps = 0,
> +			.i_hps = 0,
> +			.o_vsz = HEIGHT_O - 1,
> +			.o_hsz = WIDTH_O - 1,
> +			.v_phs_y = 0,
> +			.v_phs_c = 0,
> +			.v_dif = 256,
> +			.v_typ_y = RSZ_INTP_CUBIC,
> +			.h_typ_c = RSZ_INTP_CUBIC,
> +			.v_lpf_int_y = 0,
> +			.v_lpf_int_c = 0,
> +			.h_phs = 0,
> +			.h_dif = 256,
> +			.h_typ_y = RSZ_INTP_CUBIC,
> +			.h_typ_c = RSZ_INTP_CUBIC,
> +			.h_lpf_int_y = 0,
> +			.h_lpf_int_c = 0,
> +			.dscale_en = 0,
> +			.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +			.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +			.f_div.en = 0
> +		},
> +		{
> +			.mode = IPIPEIF_ONE_SHOT,
> +			.h_flip = DISABLE,
> +			.v_flip = DISABLE,
> +			.cen = DISABLE,
> +			.yen = DISABLE,
> +			.i_vps = 0,
> +			.i_hps = 0,
> +			.o_vsz = HEIGHT_O - 1,
> +			.o_hsz = WIDTH_O - 1,
> +			.v_phs_y = 0,
> +			.v_phs_c = 0,
> +			.v_dif = 256,
> +			.v_typ_y = RSZ_INTP_CUBIC,
> +			.h_typ_c = RSZ_INTP_CUBIC,
> +			.v_lpf_int_y = 0,
> +			.v_lpf_int_c = 0,
> +			.h_phs = 0,
> +			.h_dif = 256,
> +			.h_typ_y = RSZ_INTP_CUBIC,
> +			.h_typ_c = RSZ_INTP_CUBIC,
> +			.h_lpf_int_y = 0,
> +			.h_lpf_int_c = 0,
> +			.dscale_en = 0,
> +			.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +			.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +			.f_div.en = 0
> +		},
> +	},
> +	.rsz2rgb = {
> +		{
> +			.rgb_en = DISABLE
> +		},
> +		{
> +			.rgb_en = DISABLE
> +		}
> +	},
> +	.ext_mem_param = {
> +		{
> +			.rsz_sdr_oft_y = WIDTH_O << 1,
> +			.rsz_sdr_ptr_s_y = 0,
> +			.rsz_sdr_ptr_e_y = HEIGHT_O,
> +			.rsz_sdr_oft_c = WIDTH_O,
> +			.rsz_sdr_ptr_s_c = 0,
> +			.rsz_sdr_ptr_e_c = HEIGHT_O >> 1,
> +			.flip_ofst_y = 0,
> +			.flip_ofst_c = 0,
> +			.c_offset = 0,
> +			.user_y_ofst = 0,
> +			.user_c_ofst = 0
> +		},
> +		{
> +			.rsz_sdr_oft_y = WIDTH_O << 1,
> +			.rsz_sdr_ptr_s_y = 0,
> +			.rsz_sdr_ptr_e_y = HEIGHT_O,
> +			.rsz_sdr_oft_c = WIDTH_O,
> +			.rsz_sdr_ptr_s_c = 0,
> +			.rsz_sdr_ptr_e_c = HEIGHT_O,
> +			.flip_ofst_y = 0,
> +			.flip_ofst_c = 0,
> +			.c_offset = 0,
> +			.user_y_ofst = 0,
> +			.user_c_ofst = 0
> +		},
> +	},
> +	.rsz_en[0] = ENABLE,
> +	.rsz_en[1] = DISABLE
> +};
> +
> +struct prev_single_shot_config dm365_prev_ss_config_defs = {
> +	.bypass = IPIPE_BYPASS_OFF,
> +	.input = {
> +		.image_width = WIDTH_I,
> +		.image_height = HEIGHT_I,
> +		.vst = 0,
> +		.hst = 0,
> +		.ppln = WIDTH_I + 8,
> +		.lpfr = HEIGHT_I + 10,
> +		.pred = IPIPEIF_DPCM_SIMPLE_PRED,
> +		.clk_div = {1, 6},
> +		.data_shift = IPIPEIF_BITS11_0,
> +		.dec_en = 0,
> +		.rsz = 16,	/* resize ratio 16/rsz */
> +		.frame_div_mode_en = 0,
> +		.avg_filter_en = IPIPEIF_AVG_OFF,
> +		.dpc = {0, 0},
> +		.gain = 512,
> +		.clip = 4095,
> +		.align_sync = 0,
> +		.rsz_start = 0,
> +		.pix_fmt = IPIPE_BAYER,
> +		.colp_olop = IPIPE_GREEN_BLUE,
> +		.colp_olep = IPIPE_BLUE,
> +		.colp_elop = IPIPE_RED,
> +		.colp_elep = IPIPE_GREEN_RED
> +	},
> +	.output = {
> +		.pix_fmt = IPIPE_UYVY
> +	}
> +};
> +
> +struct prev_continuous_config dm365_prev_cont_config_defs = {
> +	.bypass = IPIPE_BYPASS_OFF,
> +	.input = {
> +		.en_df_sub = 0,
> +		.dec_en = 0,
> +		.rsz = 16,
> +		.avg_filter_en = IPIPEIF_AVG_OFF,
> +		.gain = 512,
> +		.clip = 4095,
> +		.colp_olop = IPIPE_GREEN_BLUE,
> +		.colp_olep = IPIPE_BLUE,
> +		.colp_elop = IPIPE_RED,
> +		.colp_elep = IPIPE_GREEN_RED
> +	},
> +};
> +
> +struct rsz_single_shot_config dm365_rsz_ss_config_defs = {
> +	.input = {
> +		.image_width = WIDTH_I,
> +		.image_height = HEIGHT_I,
> +		.vst = 0,
> +		.hst = 0,
> +		.ppln = WIDTH_I + 8,
> +		.lpfr = HEIGHT_I + 10,
> +		.clk_div = {1, 6},
> +		.dec_en = 0,
> +		.rsz = 16,	/* resize ratio 16/rsz */
> +		.frame_div_mode_en = 0,
> +		.avg_filter_en = IPIPEIF_AVG_OFF,
> +		.align_sync = 0,
> +		.rsz_start = 0,
> +		.pix_fmt = IPIPE_UYVY
> +	},
> +	.output1 = {
> +		.enable = 1,
> +		.pix_fmt = IPIPE_UYVY,
> +		.h_flip = 0,
> +		.v_flip = 0,
> +		.width = WIDTH_O,
> +		.height = HEIGHT_O,
> +		.vst_y = 0,
> +		.vst_c = 0,
> +		.v_typ_y = RSZ_INTP_CUBIC,
> +		.v_typ_c = RSZ_INTP_CUBIC,
> +		.v_lpf_int_y = 0,
> +		.v_lpf_int_c = 0,
> +		.h_typ_y = RSZ_INTP_CUBIC,
> +		.h_typ_c = RSZ_INTP_CUBIC,
> +		.h_lpf_int_y = 0,
> +		.h_lpf_int_c = 0,
> +		.en_down_scale = 0,
> +		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.user_y_ofst = 0,
> +		.user_c_ofst = 0
> +	},
> +	.output2 = {
> +		.enable = 1,
> +		.pix_fmt = IPIPE_UYVY,
> +		.h_flip = 0,
> +		.v_flip = 0,
> +		.width = WIDTH_O,
> +		.height = HEIGHT_O,
> +		.vst_y = 0,
> +		.vst_c = 0,
> +		.v_typ_y = RSZ_INTP_CUBIC,
> +		.v_typ_c = RSZ_INTP_CUBIC,
> +		.v_lpf_int_y = 0,
> +		.v_lpf_int_c = 0,
> +		.h_typ_y = RSZ_INTP_CUBIC,
> +		.h_typ_c = RSZ_INTP_CUBIC,
> +		.h_lpf_int_y = 0,
> +		.h_lpf_int_c = 0,
> +		.en_down_scale = 0,
> +		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.user_y_ofst = 0,
> +		.user_c_ofst = 0
> +	},
> +	.chroma_sample_even = 0,
> +	.yuv_y_min = 0,
> +	.yuv_y_max = 255,
> +	.yuv_c_min = 0,
> +	.yuv_c_max = 255,
> +	.out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE,
> +};
> +
> +struct rsz_continuous_config dm365_rsz_cont_config_defs = {
> +	.output1 = {
> +		.enable = 1,
> +		.h_flip = 0,
> +		.v_flip = 0,
> +		.v_typ_y = RSZ_INTP_CUBIC,
> +		.v_typ_c = RSZ_INTP_CUBIC,
> +		.v_lpf_int_y = 0,
> +		.v_lpf_int_c = 0,
> +		.h_typ_y = RSZ_INTP_CUBIC,
> +		.h_typ_c = RSZ_INTP_CUBIC,
> +		.h_lpf_int_y = 0,
> +		.h_lpf_int_c = 0,
> +		.en_down_scale = 0,
> +		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.user_y_ofst = 0,
> +		.user_c_ofst = 0
> +	},
> +	.output2 = {
> +		.enable = 1,
> +		.pix_fmt = IPIPE_UYVY,
> +		.h_flip = 0,
> +		.v_flip = 0,
> +		.width = WIDTH_O,
> +		.height = HEIGHT_O,
> +		.vst_y = 0,
> +		.vst_c = 0,
> +		.v_typ_y = RSZ_INTP_CUBIC,
> +		.v_typ_c = RSZ_INTP_CUBIC,
> +		.v_lpf_int_y = 0,
> +		.v_lpf_int_c = 0,
> +		.h_typ_y = RSZ_INTP_CUBIC,
> +		.h_typ_c = RSZ_INTP_CUBIC,
> +		.h_lpf_int_y = 0,
> +		.h_lpf_int_c = 0,
> +		.en_down_scale = 0,
> +		.h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> +		.user_y_ofst = 0,
> +		.user_c_ofst = 0
> +	},
> +	.chroma_sample_even = 0,
> +	.yuv_y_min = 0,
> +	.yuv_y_max = 255,
> +	.yuv_c_min = 0,
> +	.yuv_c_max = 255,
> +	.out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE,
> +};
> diff --git a/drivers/media/video/davinci/dm365_def_para.h b/drivers/media/video/davinci/dm365_def_para.h
> new file mode 100644
> index 0000000..872b3cb
> --- /dev/null
> +++ b/drivers/media/video/davinci/dm365_def_para.h
> @@ -0,0 +1,39 @@
> +/*
> + * Copyright (C) 2011 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
> + */
> +#include "dm365_ipipe.h"
> +extern struct prev_lutdpc dm365_lutdpc_defaults;
> +extern struct prev_otfdpc dm365_otfdpc_defaults;
> +extern struct prev_nf dm365_nf_defaults;
> +extern struct prev_gic dm365_gic_defaults;
> +extern struct prev_wb dm365_wb_defaults;
> +extern struct prev_cfa dm365_cfa_defaults;
> +extern struct prev_rgb2rgb dm365_rgb2rgb_defaults;
> +extern struct prev_gamma dm365_gamma_defaults;
> +extern struct prev_3d_lut dm365_3d_lut_defaults;
> +extern struct prev_lum_adj dm365_lum_adj_defaults;
> +extern struct prev_rgb2yuv dm365_rgb2yuv_defaults;
> +extern struct prev_yuv422_conv dm365_yuv422_conv_defaults;
> +extern struct prev_gbce dm365_gbce_defaults;
> +extern struct prev_yee dm365_yee_defaults;
> +extern struct prev_car dm365_car_defaults;
> +extern struct prev_cgs dm365_cgs_defaults;
> +extern struct ipipe_params dm365_ipipe_defs;
> +extern struct prev_single_shot_config dm365_prev_ss_config_defs;
> +extern struct prev_continuous_config dm365_prev_cont_config_defs;
> +extern struct rsz_single_shot_config dm365_rsz_ss_config_defs;
> +extern struct rsz_continuous_config dm365_rsz_cont_config_defs;
> +extern struct ipipeif_5_1 ipipeif_5_1_defaults;
> diff --git a/drivers/media/video/davinci/dm365_ipipe.c b/drivers/media/video/davinci/dm365_ipipe.c
> new file mode 100644
> index 0000000..9f41784
> --- /dev/null
> +++ b/drivers/media/video/davinci/dm365_ipipe.c
> @@ -0,0 +1,3966 @@
> +/*
> +* Copyright (C) 2011 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
> +*/
> +
> +#include <linux/string.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/errno.h>
> +#include <linux/types.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/uaccess.h>
> +#include <linux/mutex.h>
> +#include <linux/device.h>
> +#include <linux/videodev2.h>
> +#include <linux/v4l2-mediabus.h>
> +#include <media/davinci/vpfe.h>
> +#include "dm365_ipipe.h"
> +#include "imp_hw_if.h"
> +
> +#include "dm365_ipipe_hw.h"
> +#include "dm365_def_para.h"
> +
> +/* IPIPE module operation state */
> +struct ipipe_oper_state {
> +	/* Operation state in continuous mode */
> +	unsigned int state;

What does operation state mean and which values are possible?

> +	/* Semaphore to protect the common hardware configuration */
> +	struct mutex lock;
> +	/* previewer config state */
> +	unsigned int prev_config_state;
> +	/* Shared configuration of the hardware */
> +	struct ipipe_params *shared_config_param;
> +	/* shared resource in use */
> +	unsigned int resource_in_use;
> +	/* resizer config state */
> +	unsigned int rsz_config_state;
> +	/* resizer chained with previewer */
> +	unsigned int rsz_chained;
> +	/* Buffer type, interleaved or field seperated for interlaced
> +	 *  scan
> +	 */
> +	unsigned int buffer_type;
> +	/* frame format, 0 - interlaced, 1 - progressive */
> +	unsigned int frame_format;
> +	/* input pixel format */
> +	enum imp_pix_formats in_pixel_format;
> +	/* input pixel format */
> +	enum imp_pix_formats out_pixel_format;

How about using v4l2_mbus_pixelcode instead? Or does using
imp_pix_formats have an advantage that I can't see?

> +};
> +
> +/* Operation mode of image processor (imp) */
> +static u32 oper_mode = IMP_MODE_NOT_CONFIGURED;
> +/* enable/disable serializer */
> +static u32 en_serializer;
> +
> +#define CONFIG_IPIPE_PARAM_VALIDATION
> +/* ipipe module operation state & configuration */
> +static struct ipipe_oper_state oper_state;
> +
> +/* LUT Defect pixel correction data */
> +static struct prev_lutdpc lutdpc;
> +
> +/* LUT Defect pixel correction data */
> +static struct prev_otfdpc otfdpc;
> +
> +/* Noise filter */
> +static struct prev_nf nf1;
> +static struct prev_nf nf2;
> +
> +/* Green Imbalance Correction */
> +static struct prev_gic gic;
> +
> +/* White Balance */
> +static struct prev_wb wb;
> +
> +/* CFA */
> +static struct prev_cfa cfa;
> +
> +/* RGB2RGB conversion */
> +static struct prev_rgb2rgb rgb2rgb_1;
> +static struct prev_rgb2rgb rgb2rgb_2;
> +
> +/* Gamma correction */
> +static struct prev_gamma gamma;
> +
> +/* 3D LUT */
> +static struct prev_3d_lut lut_3d;
> +
> +/* Lumina Adjustment */
> +static struct prev_lum_adj lum_adj;
> +
> +/* RGB2YUV conversion */
> +static struct prev_rgb2yuv rgb2yuv;
> +
> +/* YUV 422 conversion */
> +static struct prev_yuv422_conv yuv422_conv;
> +
> +/* GBCE */
> +static struct prev_gbce gbce;
> +
> +/* Edge Enhancement */
> +static struct prev_yee yee;
> +
> +/* Chromatic Artifact Reduction, CAR */
> +static struct prev_car car;
> +
> +/* Chromatic Artifact Reduction, CAR */
> +static struct prev_cgs cgs;
> +
> +/* Tables for various tuning modules */
> +static struct ipipe_lutdpc_entry ipipe_lutdpc_table[MAX_SIZE_DPC];
> +static struct ipipe_3d_lut_entry ipipe_3d_lut_table[MAX_SIZE_3D_LUT];
> +static unsigned short ipipe_gbce_table[MAX_SIZE_GBCE_LUT];
> +static struct ipipe_gamma_entry ipipe_gamma_table_r[MAX_SIZE_GAMMA];
> +static struct ipipe_gamma_entry ipipe_gamma_table_b[MAX_SIZE_GAMMA];
> +static struct ipipe_gamma_entry ipipe_gamma_table_g[MAX_SIZE_GAMMA];
> +static short ipipe_yee_table[MAX_SIZE_YEE_LUT];
> +
> +/* Raw YUV formats */
> +static u32 ipipe_raw_yuv_pix_formats[] = { V4L2_PIX_FMT_UYVY,
> +					  V4L2_PIX_FMT_NV12};

Shouldn't all this be part of the device specific structure?

> +static int ipipe_enum_pix(u32 *pix, int i)
> +{
> +	if (i >= ARRAY_SIZE(ipipe_raw_yuv_pix_formats))
> +		return -EINVAL;
> +
> +	*pix = ipipe_raw_yuv_pix_formats[i];
> +	return 0;
> +}
> +
> +/* IPIPE hardware limits */
> +#define IPIPE_MAX_OUTPUT_WIDTH_A	2176
> +#define IPIPE_MAX_OUTPUT_WIDTH_B	640
> +
> +static int ipipe_get_max_output_width(int rsz)
> +{
> +	if (rsz == RSZ_A)
> +		return IPIPE_MAX_OUTPUT_WIDTH_A;
> +	return IPIPE_MAX_OUTPUT_WIDTH_B;
> +}
> +
> +/* Based on max resolution supported. QXGA */
> +#define IPIPE_MAX_OUTPUT_HEIGHT_A	1536
> +/* Based on max resolution supported. VGA */
> +#define IPIPE_MAX_OUTPUT_HEIGHT_B	480
> +
> +static int ipipe_get_max_output_height(int rsz)
> +{
> +	if (rsz == RSZ_A)
> +		return IPIPE_MAX_OUTPUT_HEIGHT_A;
> +	return IPIPE_MAX_OUTPUT_HEIGHT_B;
> +}
> +
> +static int ipipe_serialize(void)
> +{
> +	return en_serializer;
> +}
> +
> +static int ipipe_set_ipipe_if_address(void *config, unsigned int address)

address should probably be u32.

> +{
> +	struct ipipeif *if_params;
> +
> +	if (ISNULL(config))
> +		return -EINVAL;

Please just use !config or config == NULL.

> +	if_params = &((struct ipipe_params *)config)->ipipeif_param;
> +
> +	return ipipeif_set_address(if_params, address);
> +}
> +
> +static void ipipe_lock_chain(void)
> +{
> +	mutex_lock(&oper_state.lock);
> +	oper_state.resource_in_use = 1;
> +	mutex_unlock(&oper_state.lock);
> +}
> +
> +static void ipipe_unlock_chain(void)
> +{
> +	mutex_lock(&oper_state.lock);
> +	oper_state.resource_in_use = 0;
> +	oper_state.prev_config_state = STATE_NOT_CONFIGURED;
> +	oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
> +	oper_state.rsz_chained = 0;
> +	mutex_unlock(&oper_state.lock);
> +}
> +static int ipipe_process_pix_fmts(enum ipipe_pix_formats in_pix_fmt,
> +				  enum ipipe_pix_formats out_pix_fmt,
> +				  struct ipipe_params *param)
> +{
> +	enum ipipe_pix_formats temp_pix_fmt;
> +
> +	switch (in_pix_fmt) {
> +	case IPIPE_BAYER_8BIT_PACK:
> +		temp_pix_fmt = IPIPE_BAYER;
> +		param->ipipeif_param.var.if_5_1.pack_mode
> +		    = IPIPEIF_5_1_PACK_8_BIT;
> +		break;
> +	case IPIPE_BAYER_8BIT_PACK_ALAW:
> +		param->ipipeif_param.var.if_5_1.pack_mode
> +		    = IPIPEIF_5_1_PACK_8_BIT_A_LAW;
> +		temp_pix_fmt = IPIPE_BAYER;
> +		break;
> +	case IPIPE_BAYER_8BIT_PACK_DPCM:
> +		param->ipipeif_param.var.if_5_1.pack_mode
> +		    = IPIPEIF_5_1_PACK_8_BIT;
> +		param->ipipeif_param.var.if_5_1.dpcm.en = 1;
> +		temp_pix_fmt = IPIPE_BAYER;
> +		break;
> +	case IPIPE_BAYER:
> +		param->ipipeif_param.var.if_5_1.pack_mode
> +		    = IPIPEIF_5_1_PACK_16_BIT;
> +		temp_pix_fmt = IPIPE_BAYER;
> +		break;
> +	case IPIPE_BAYER_12BIT_PACK:
> +		param->ipipeif_param.var.if_5_1.pack_mode
> +		    = IPIPEIF_5_1_PACK_12_BIT;
> +		temp_pix_fmt = IPIPE_BAYER;
> +		break;
> +	default:
> +		temp_pix_fmt = IPIPE_UYVY;
> +	}
> +
> +	if (temp_pix_fmt == IPIPE_BAYER)
> +		if (out_pix_fmt == IPIPE_BAYER)
> +			param->ipipe_dpaths_fmt = IPIPE_RAW2RAW;
> +		else if ((out_pix_fmt == IPIPE_UYVY) ||
> +			 (out_pix_fmt == IPIPE_YUV420SP))
> +			param->ipipe_dpaths_fmt = IPIPE_RAW2YUV;
> +		else
> +			return -EINVAL;

Using braces in the outermost if might make sense.

> +	else if (temp_pix_fmt == IPIPE_UYVY) {
> +		if (out_pix_fmt == IPIPE_UYVY)
> +			param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
> +		else if (out_pix_fmt == IPIPE_YUV420SP)
> +			param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
> +		else
> +			return -EINVAL;
> +	}
> +	return 0;
> +}

I wonder if the above function should rather deal with the
v4l2_mbus_pixelcodes instead. Shouldn't VIDIOC_SUBDEV_S_FMT be used to
configure this?

> +/*
> + * calculate_resize_ratios()
> + *   calculates resize ratio for resizer A or B. This is called after setting
> + * the input size or output size
> + */
> +static void calculate_resize_ratios(struct ipipe_params *param, int index)
> +{
> +	param->rsz_rsc_param[index].h_dif =
> +	    ((param->ipipe_hsz + 1) * 256) /
> +	    (param->rsz_rsc_param[index].o_hsz + 1);
> +	param->rsz_rsc_param[index].v_dif =
> +	    ((param->ipipe_vsz + 1) * 256) /
> +	    (param->rsz_rsc_param[index].o_vsz + 1);
> +}
> +
> +static int ipipe_do_hw_setup(struct device *dev, void *config)
> +{
> +	struct ipipe_params *param = (struct ipipe_params *)config;
> +	int ret;
> +
> +	dev_dbg(dev, "ipipe_do_hw_setup\n");
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +
> +	if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS)) {
> +		/* continuous mode */
> +		param = oper_state.shared_config_param;
> +		if (param->rsz_en[RSZ_A])
> +			calculate_resize_ratios(param, RSZ_A);
> +		if (param->rsz_en[RSZ_B])
> +			calculate_resize_ratios(param, RSZ_B);
> +		ret = ipipe_hw_setup(param);
> +	}
> +	mutex_unlock(&oper_state.lock);
> +
> +	return ret;
> +}
> +
> +static unsigned int ipipe_rsz_chain_state(void)
> +{
> +	return oper_state.rsz_chained;
> +}
> +
> +static void ipipe_update_outbuf1_address(void *config, unsigned int address)
> +{
> +	if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS))
> +		rsz_set_output_address(oper_state.shared_config_param,
> +				       0,
> +				       address);
> +	else
> +		rsz_set_output_address((struct ipipe_params *)config,
> +				       0,
> +				       address);
> +}
> +
> +static void ipipe_update_outbuf2_address(void *config, unsigned int address)
> +{
> +	if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS))
> +		rsz_set_output_address(oper_state.shared_config_param,
> +				       1,
> +				       address);
> +	else
> +		rsz_set_output_address((struct ipipe_params *)config,
> +				       1,
> +				       address);
> +}
> +
> +static void ipipe_enable(unsigned char en, void *config)
> +{
> +	unsigned char val = 0, ret = 0;
> +	struct ipipe_params *param = (struct ipipe_params *)config;
> +
> +	if (en)
> +		val = 1;

You can en = !!en and drop val.

> +	if (oper_mode == IMP_MODE_CONTINUOUS)
> +		param = oper_state.shared_config_param;
> +
> +	if (en && param->rsz_common.source == IPIPE_DATA) {
> +		/* wait for IPIPE to become inactive */
> +		do {
> +			ret = regr_ip(IPIPE_SRC_EN);
> +		} while (ret);
> +
> +		regw_ip(val, IPIPE_SRC_EN);
> +	} else
> +		regw_ip(0, IPIPE_SRC_EN);
> +
> +	if (en) {
> +		/* wait for RSZ_SRC_EN to be reset by hardware */
> +		do {
> +			ret = regr_rsz(RSZ_SRC_EN);
> +		} while (ret);
> +	}
> +
> +	if (param->rsz_en[RSZ_A]) {
> +		if (en) {
> +			/* wait for RSZ-A to become inactive */
> +			do {
> +				ret = regr_rsz(RSZ_A);
> +			} while (ret);
> +		}
> +
> +		rsz_enable(RSZ_A, en);
> +	}
> +	if (param->rsz_en[RSZ_B]) {
> +		if (en) {
> +			/* wait for RSZ-B to become inactive */
> +			do {
> +				ret = regr_rsz(RSZ_B);
> +			} while (ret);
> +		}
> +
> +		rsz_enable(RSZ_B, en);
> +	}
> +	if (oper_mode == IMP_MODE_SINGLE_SHOT) {
> +		/* wait for IPIPEIF ENABLE.ENABLE to be reset by hardware */
> +		if (en) {
> +			do {
> +				ret = ipipeif_get_enable();
> +			} while (ret & 0x1);
> +		}
> +
> +	 ipipeif_set_enable(val, oper_mode);

Indentation.

> +	}
> +}
> +
> +static int validate_lutdpc_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	int i;
> +
> +	if (lutdpc.en > 1 ||
> +	    lutdpc.repl_white > 1 ||
> +	    lutdpc.dpc_size > LUT_DPC_MAX_SIZE)
> +		return -EINVAL;
> +	if (lutdpc.en && (ISNULL(lutdpc.table)))
> +		return -EINVAL;
> +	for (i = 0; i < lutdpc.dpc_size; i++) {
> +		if (lutdpc.table[i].horz_pos > LUT_DPC_H_POS_MASK ||
> +		    lutdpc.table[i].vert_pos > LUT_DPC_V_POS_MASK)
> +			return -EINVAL;
> +	}
> +#endif
> +	return 0;
> +}
> +
> +static int set_lutdpc_params(struct device *dev, void *param, int len)
> +{
> +	struct ipipe_lutdpc_entry *temp_lutdpc;
> +	struct prev_lutdpc dpc_param;
> +
> +	if (ISNULL(param)) {
> +		/* Copy defaults for dfc */
> +		temp_lutdpc = lutdpc.table;
> +		memcpy((void *)&lutdpc,
> +		       (void *)&dm365_lutdpc_defaults,
> +		       sizeof(struct prev_lutdpc));
> +		lutdpc.table = temp_lutdpc;
> +		goto success;
> +	}
> +
> +	if (len != sizeof(struct prev_lutdpc)) {
> +		dev_err(dev,
> +			"set_lutdpc_params: param struct length"
> +			" mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&dpc_param,
> +			    (struct prev_lutdpc *)param,
> +			    sizeof(struct prev_lutdpc))) {
> +		dev_err(dev,
> +			"set_lutdpc_params: Error in copy to kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	if (ISNULL(dpc_param.table)) {
> +		dev_err(dev, "Invalid user dpc table ptr\n");
> +		return -EINVAL;
> +	}
> +	lutdpc.en = dpc_param.en;
> +	lutdpc.repl_white = dpc_param.repl_white;
> +	lutdpc.dpc_size = dpc_param.dpc_size;
> +	if (copy_from_user
> +		(lutdpc.table,
> +		(struct ipipe_dpc_entry *)dpc_param.table,
> +		(lutdpc.dpc_size *
> +		sizeof(struct ipipe_lutdpc_entry)))) {
> +		dev_err(dev,
> +			"set_lutdpc_params: Error in copying "
> +			"dfc table to kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	if (validate_lutdpc_params(dev) < 0)
> +		return -EINVAL;
> +
> +
> +success:
> +	ipipe_set_lutdpc_regs(&lutdpc);
> +
> +	return 0;
> +}
> +
> +static int get_lutdpc_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_lutdpc *lut_param = (struct prev_lutdpc *)param;
> +	struct prev_lutdpc user_lutdpc;
> +
> +	if (ISNULL(lut_param)) {
> +		dev_err(dev, "get_lutdpc_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_lutdpc)) {
> +		dev_err(dev,
> +			"get_lutdpc_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&user_lutdpc,
> +			   lut_param,
> +			   sizeof(struct prev_lutdpc))) {
> +		dev_err(dev, "get_lutdpc_params: Error in copy to  kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	user_lutdpc.en = lutdpc.en;
> +	user_lutdpc.repl_white = lutdpc.repl_white;
> +	user_lutdpc.dpc_size = lutdpc.dpc_size;
> +	if (ISNULL(user_lutdpc.table)) {
> +		dev_err(dev, "get_lutdpc_params:" " Invalid table ptr");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(user_lutdpc.table,
> +			 lutdpc.table,
> +			 (lutdpc.dpc_size *
> +			  sizeof(struct ipipe_lutdpc_entry)))) {
> +		dev_err(dev,
> +			"get_lutdpc_params:Table Error in" " copy to user\n");
> +		return -EFAULT;
> +	}
> +
> +	if (copy_to_user(lut_param,
> +			 &user_lutdpc,
> +			 sizeof(struct prev_lutdpc))) {
> +		dev_err(dev, "get_lutdpc_params: Error in copy" " to user\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_otfdpc_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION

Are there cases where you wouldn't want the parameters to be validated?

> +	struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)&otfdpc;
> +	struct prev_otfdpc_2_0 *dpc_2_0;
> +	struct prev_otfdpc_3_0 *dpc_3_0;
> +
> +	if (dpc_param->en > 1)
> +		return -EINVAL;
> +	if (dpc_param->alg == IPIPE_OTFDPC_2_0) {
> +		dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0;
> +		if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK ||
> +		    dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK)
> +			return -EINVAL;
> +	} else {
> +		dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0;
> +		if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK ||
> +		    dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK ||
> +		    dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK ||
> +		    dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK ||
> +		    dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK ||
> +		    dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK ||
> +		    dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK ||
> +		    dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK ||
> +		    dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK)
> +			return -EINVAL;
> +	}
> +#endif
> +	return 0;
> +}
> +
> +static int set_otfdpc_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)param;
> +
> +	if (ISNULL(param)) {
> +		/* Copy defaults for dpc2.0 defaults */
> +		memcpy((void *)&otfdpc,
> +		       (void *)&dm365_otfdpc_defaults,
> +		       sizeof(struct ipipe_otfdpc_2_0));
> +	} else {
> +		if (len != sizeof(struct prev_otfdpc)) {
> +			dev_err(dev,
> +				"set_otfdpc_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&otfdpc,
> +				   dpc_param,
> +				   sizeof(struct prev_otfdpc))) {
> +			dev_err(dev,
> +				"set_otfdpc_params: Error in "
> +				"copy to kernel\n");
> +			return -EFAULT;
> +		}
> +
> +		if (validate_otfdpc_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_otfdpc_regs(&otfdpc);
> +
> +	return 0;
> +}
> +
> +static int get_otfdpc_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)param;
> +
> +	if (ISNULL(dpc_param)) {
> +		dev_err(dev, "get_otfdpc_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_otfdpc)) {
> +		dev_err(dev,
> +			"get_otfdpc_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(dpc_param,
> +			 &otfdpc,
> +			 sizeof(struct prev_otfdpc))) {
> +		dev_err(dev,
> +			"get_otfdpc_params: Error in copy dpc "
> +			"table to user\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_nf_params(struct device *dev, unsigned int id)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	struct prev_nf *nf_param = &nf1;
> +	int i;
> +
> +	if (id)
> +		nf_param = &nf2;
> +	if (nf_param->en > 1 ||
> +	    nf_param->shft_val > D2F_SHFT_VAL_MASK ||
> +	    nf_param->spread_val > D2F_SPR_VAL_MASK ||
> +	    nf_param->apply_lsc_gain > 1 ||
> +	    nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK ||
> +	    nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK)
> +		return -EINVAL;
> +
> +	for (i = 0; i < IPIPE_NF_THR_TABLE_SIZE; i++)
> +		if (nf_param->thr[i] > D2F_THR_VAL_MASK)
> +			return -EINVAL;
> +	for (i = 0; i < IPIPE_NF_STR_TABLE_SIZE; i++)
> +		if (nf_param->str[i] > D2F_STR_VAL_MASK)
> +			return -EINVAL;
> +#endif
> +	return 0;
> +}
> +
> +static int set_nf_params(struct device *dev, unsigned int id,
> +			 void *param, int len)
> +{
> +	struct prev_nf *nf_param = (struct prev_nf *)param;
> +	struct prev_nf *nf = &nf1;
> +
> +	if (id)
> +		nf = &nf2;
> +
> +	if (ISNULL(nf_param)) {
> +		/* Copy defaults for nf */
> +		memcpy((void *)nf,
> +		       (void *)&dm365_nf_defaults,
> +		       sizeof(struct prev_nf));
> +		memset((void *)nf->thr, 0, IPIPE_NF_THR_TABLE_SIZE);
> +		memset((void *)nf->str, 0, IPIPE_NF_THR_TABLE_SIZE);
> +	} else {
> +		if (len != sizeof(struct prev_nf)) {
> +			dev_err(dev,
> +				"set_nf_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(nf, nf_param, sizeof(struct prev_nf))) {
> +			dev_err(dev,
> +				"set_nf_params: Error in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +		if (validate_nf_params(dev, id) < 0)
> +			return -EINVAL;
> +	}
> +	/* Now set the values in the hw */
> +	ipipe_set_d2f_regs(id, nf);
> +
> +	return 0;
> +}
> +
> +static int set_nf1_params(struct device *dev, void *param, int len)
> +{
> +	return set_nf_params(dev, 0, param, len);
> +}
> +
> +static int set_nf2_params(struct device *dev, void *param, int len)
> +{
> +	return set_nf_params(dev, 1, param, len);
> +}
> +
> +static int get_nf_params(struct device *dev, unsigned int id, void *param,
> +			 int len)
> +{
> +	struct prev_nf *nf_param = (struct prev_nf *)param;
> +	struct prev_nf *nf = &nf1;
> +
> +	if (ISNULL(nf_param)) {
> +		dev_err(dev, "get_nf_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_nf)) {
> +		dev_err(dev,
> +			"get_nf_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (id)
> +		nf = &nf2;
> +	if (copy_to_user((struct prev_nf *)nf_param, nf,
> +			 sizeof(struct prev_nf))) {
> +		dev_err(dev, "get_nf_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int get_nf1_params(struct device *dev, void *param, int len)
> +{
> +	return get_nf_params(dev, 0, param, len);
> +}
> +
> +static int get_nf2_params(struct device *dev, void *param, int len)
> +{
> +	return get_nf_params(dev, 1, param, len);
> +}
> +
> +static int validate_gic_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (gic.en > 1 ||
> +	    gic.gain > GIC_GAIN_MASK ||
> +	    gic.thr > GIC_THR_MASK ||
> +	    gic.slope > GIC_SLOPE_MASK ||
> +	    gic.apply_lsc_gain > 1 ||
> +	    gic.nf2_thr_gain.integer > GIC_NFGAN_INT_MASK ||
> +	    gic.nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK)
> +		return -1;
> +#endif
> +	return 0;
> +}
> +
> +static int set_gic_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_gic *gic_param = (struct prev_gic *)param;
> +
> +	if (ISNULL(gic_param)) {
> +		/* Copy defaults for nf */
> +		memcpy((void *)&gic,
> +		       (void *)&dm365_gic_defaults,
> +		       sizeof(struct prev_gic));
> +	} else {
> +		if (len != sizeof(struct prev_gic)) {
> +			dev_err(dev,
> +				"set_gic_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&gic, gic_param, sizeof(struct prev_gic))) {
> +			dev_err(dev,
> +				"set_gic_params: Error in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +		if (validate_gic_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +	/* Now set the values in the hw */
> +	ipipe_set_gic_regs(&gic);
> +
> +	return 0;
> +}
> +
> +static int get_gic_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_gic *gic_param = (struct prev_gic *)param;
> +
> +	if (ISNULL(gic_param)) {
> +		dev_err(dev, "get_gic_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +
> +	if (len != sizeof(struct prev_gic)) {
> +		dev_err(dev,
> +			"get_gic_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +
> +	if (copy_to_user((struct prev_gic *)gic_param,
> +			 &gic,
> +			 sizeof(struct prev_gic))) {
> +		dev_err(dev, "get_gic_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_wb_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (wb.ofst_r > WB_OFFSET_MASK ||
> +	    wb.ofst_gr > WB_OFFSET_MASK ||
> +	    wb.ofst_gb > WB_OFFSET_MASK ||
> +	    wb.ofst_b > WB_OFFSET_MASK ||
> +	    wb.gain_r.integer > WB_GAIN_INT_MASK ||
> +	    wb.gain_r.decimal > WB_GAIN_DECI_MASK ||
> +	    wb.gain_gr.integer > WB_GAIN_INT_MASK ||
> +	    wb.gain_gr.decimal > WB_GAIN_DECI_MASK ||
> +	    wb.gain_gb.integer > WB_GAIN_INT_MASK ||
> +	    wb.gain_gb.decimal > WB_GAIN_DECI_MASK ||
> +	    wb.gain_b.integer > WB_GAIN_INT_MASK ||
> +	    wb.gain_b.decimal > WB_GAIN_DECI_MASK)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +static int set_wb_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_wb *wb_param = (struct prev_wb *)param;
> +
> +	dev_dbg(dev, "set_wb_params");
> +	if (ISNULL(wb_param)) {
> +		/* Copy defaults for wb */
> +		memcpy((void *)&wb,
> +		       (void *)&dm365_wb_defaults,
> +		       sizeof(struct prev_wb));
> +	} else {
> +		if (len != sizeof(struct prev_wb)) {
> +			dev_err(dev,
> +				"set_wb_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&wb, wb_param, sizeof(struct prev_wb))) {
> +			dev_err(dev,
> +				"set_wb_params: Error in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +		if (validate_wb_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	/* Now set the values in the hw */
> +	ipipe_set_wb_regs(&wb);
> +
> +	return 0;
> +}
> +static int get_wb_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_wb *wb_param = (struct prev_wb *)param;
> +
> +	if (ISNULL(wb_param)) {
> +		dev_err(dev, "get_wb_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_wb)) {
> +		dev_err(dev,
> +			"get_wb_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user((struct prev_wb *)wb_param,
> +			 &wb,
> +			 sizeof(struct prev_wb))) {
> +		dev_err(dev, "get_wb_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_cfa_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (cfa.hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK ||
> +	    cfa.hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK ||
> +	    cfa.hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK ||
> +	    cfa.hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK ||
> +	    cfa.dir_thr_2dir > CFA_DIR_THR_2DIR_MASK ||
> +	    cfa.dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK ||
> +	    cfa.nd_wt_2dir > CFA_ND_WT_2DIR_MASK ||
> +	    cfa.hue_fract_daa > CFA_DAA_HUE_FRA_MASK ||
> +	    cfa.edge_thr_daa > CFA_DAA_EDG_THR_MASK ||
> +	    cfa.thr_min_daa > CFA_DAA_THR_MIN_MASK ||
> +	    cfa.thr_slope_daa > CFA_DAA_THR_SLP_MASK ||
> +	    cfa.slope_min_daa > CFA_DAA_SLP_MIN_MASK ||
> +	    cfa.slope_slope_daa > CFA_DAA_SLP_SLP_MASK ||
> +	    cfa.lp_wt_daa > CFA_DAA_LP_WT_MASK)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +static int set_cfa_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_cfa *cfa_param = (struct prev_cfa *)param;
> +
> +	dev_dbg(dev, "set_cfa_params");
> +	if (ISNULL(cfa_param)) {
> +		/* Copy defaults for wb */
> +		memcpy((void *)&cfa,
> +		       (void *)&dm365_cfa_defaults,
> +		       sizeof(struct prev_cfa));
> +	} else {
> +		if (len != sizeof(struct prev_cfa)) {
> +			dev_err(dev,
> +				"set_cfa_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&cfa, cfa_param, sizeof(struct prev_cfa))) {
> +			dev_err(dev,
> +				"set_cfa_params: Error in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +		if (validate_cfa_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	/* Now set the values in the hw */
> +	ipipe_set_cfa_regs(&cfa);
> +
> +	return 0;
> +}
> +static int get_cfa_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_cfa *cfa_param = (struct prev_cfa *)param;
> +
> +	dev_dbg(dev, "get_cfa_params\n");
> +	if (ISNULL(cfa_param)) {
> +		dev_err(dev, "get_cfa_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_cfa)) {
> +		dev_err(dev,
> +			"get_cfa_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user((struct prev_cfa *)cfa_param,
> +			 &cfa,
> +			 sizeof(struct prev_cfa))) {
> +		dev_err(dev, "get_cfa_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_rgb2rgb_params(struct device *dev, unsigned int id)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
> +	u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK;
> +	u32 offset_upper = RGB2RGB_1_OFST_MASK;
> +
> +	if (id) {
> +		rgb2rgb = &rgb2rgb_2;
> +		offset_upper = RGB2RGB_2_OFST_MASK;
> +		gain_int_upper = RGB2RGB_2_GAIN_INT_MASK;
> +	}
> +	if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_rr.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_gr.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_br.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_rg.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_gg.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_bg.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_rb.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_gb.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK ||
> +	    rgb2rgb->coef_bb.integer > gain_int_upper)
> +		return -EINVAL;
> +
> +	if (rgb2rgb->out_ofst_r > offset_upper ||
> +	    rgb2rgb->out_ofst_g > offset_upper ||
> +	    rgb2rgb->out_ofst_b > offset_upper)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +
> +static int set_rgb2rgb_params(struct device *dev, unsigned int id,
> +			      void *param, int len)
> +{
> +	struct prev_rgb2rgb *rgb2rgb_param = (struct prev_rgb2rgb *)param;
> +	struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
> +
> +	if (id)
> +		rgb2rgb = &rgb2rgb_2;
> +	if (ISNULL(rgb2rgb_param)) {
> +		/* Copy defaults for rgb2rgb conversion */
> +		memcpy((void *)rgb2rgb,
> +		       (void *)&dm365_rgb2rgb_defaults,
> +		       sizeof(struct prev_rgb2rgb));
> +	} else {
> +
> +		if (len != sizeof(struct prev_rgb2rgb)) {
> +			dev_err(dev,
> +				"set_rgb2rgb_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +
> +		if (copy_from_user(rgb2rgb,
> +				   rgb2rgb_param,
> +				   sizeof(struct prev_rgb2rgb))) {
> +			dev_err(dev,
> +				"set_rgb2rgb_params: Error in "
> +				"copy to kernel\n");
> +			return -EFAULT;
> +		}
> +		if (validate_rgb2rgb_params(dev, id) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_rgb2rgb_regs(id, rgb2rgb);
> +
> +	return 0;
> +}
> +
> +static int set_rgb2rgb_1_params(struct device *dev, void *param, int len)
> +{
> +	return set_rgb2rgb_params(dev, 0, param, len);
> +}
> +
> +static int set_rgb2rgb_2_params(struct device *dev, void *param, int len)
> +{
> +	return set_rgb2rgb_params(dev, 1, param, len);
> +}
> +
> +static int get_rgb2rgb_params(struct device *dev, unsigned int id,
> +			      void *param, int len)
> +{
> +	struct prev_rgb2rgb *rgb2rgb_param = (struct prev_rgb2rgb *)param;
> +	struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
> +
> +	if (ISNULL(rgb2rgb_param)) {
> +		dev_err(dev, "get_rgb2rgb_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +
> +	if (len != sizeof(struct prev_rgb2rgb)) {
> +		dev_err(dev,
> +			"get_rgb2rgb_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +
> +	if (id)
> +		rgb2rgb = &rgb2rgb_2;
> +	if (copy_to_user((struct prev_rgb2rgb *)rgb2rgb_param,
> +			 rgb2rgb,
> +			 sizeof(struct prev_rgb2rgb))) {
> +		dev_err(dev, "get_rgb2rgb_params: Error in copy to user\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int get_rgb2rgb_1_params(struct device *dev, void *param, int len)
> +{
> +	return get_rgb2rgb_params(dev, 0, param, len);
> +}
> +
> +static int get_rgb2rgb_2_params(struct device *dev, void *param, int len)
> +{
> +	return get_rgb2rgb_params(dev, 1, param, len);
> +}
> +
> +static int validate_gamma_entry(struct ipipe_gamma_entry *table, int size)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	int i;
> +
> +	if (ISNULL(table))
> +		return -EINVAL;
> +
> +	for (i = 0; i < size; i++) {
> +		if (table[i].slope > GAMMA_MASK ||
> +		    table[i].offset > GAMMA_MASK)
> +			return -EINVAL;
> +	}
> +#endif
> +	return 0;
> +}
> +
> +static int validate_gamma_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	int table_size;
> +	int err;
> +
> +	if (gamma.bypass_r > 1 ||
> +	    gamma.bypass_b > 1 ||
> +	    gamma.bypass_g > 1)
> +		return -EINVAL;
> +
> +	if (gamma.tbl_sel != IPIPE_GAMMA_TBL_RAM)
> +		return 0;
> +
> +	table_size = gamma.tbl_size;
> +	if (!gamma.bypass_r) {
> +		err = validate_gamma_entry(gamma.table_r, table_size);
> +		if (err) {
> +			dev_err(dev, "GAMMA R - table entry invalid\n");
> +			return err;
> +		}
> +	}
> +	if (!gamma.bypass_b) {
> +		err = validate_gamma_entry(gamma.table_b, table_size);
> +		if (err) {
> +			dev_err(dev, "GAMMA B - table entry invalid\n");
> +			return err;
> +		}
> +	}
> +	if (!gamma.bypass_g) {
> +		err = validate_gamma_entry(gamma.table_g, table_size);
> +		if (err) {
> +			dev_err(dev, "GAMMA G - table entry invalid\n");
> +			return err;
> +		}
> +	}
> +#endif
> +	return 0;
> +}
> +static int set_gamma_params(struct device *dev, void *param, int len)
> +{
> +
> +	struct prev_gamma *gamma_param = (struct prev_gamma *)param;
> +	struct prev_gamma user_gamma;
> +	int table_size;
> +
> +	if (ISNULL(gamma_param)) {
> +		/* Copy defaults for gamma */
> +		gamma.bypass_r = dm365_gamma_defaults.bypass_r;
> +		gamma.bypass_g = dm365_gamma_defaults.bypass_g;
> +		gamma.bypass_b = dm365_gamma_defaults.bypass_b;
> +		gamma.tbl_sel = dm365_gamma_defaults.tbl_sel;
> +		gamma.tbl_size = dm365_gamma_defaults.tbl_size;
> +		/* By default, we bypass the gamma correction.
> +		 * So no values by default for tables
> +		 */
> +		goto success;
> +	}
> +
> +	if (len != sizeof(struct prev_gamma)) {
> +		dev_err(dev,
> +			"set_gamma_params: param struct length"
> +			" mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&user_gamma, gamma_param,
> +			    sizeof(struct prev_gamma))) {
> +		dev_err(dev,
> +			"set_gamma_params: Error in copy to kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	if (validate_gamma_params(dev) < 0)
> +		return -EINVAL;
> +
> +	gamma.bypass_r = user_gamma.bypass_r;
> +	gamma.bypass_b = user_gamma.bypass_b;
> +	gamma.bypass_g = user_gamma.bypass_g;
> +	gamma.tbl_sel = user_gamma.tbl_sel;
> +	gamma.tbl_size = user_gamma.tbl_size;
> +
> +	if (user_gamma.tbl_sel != IPIPE_GAMMA_TBL_RAM)
> +		goto success;
> +
> +	table_size = user_gamma.tbl_size;
> +
> +	if (!user_gamma.bypass_r) {
> +		if (ISNULL(user_gamma.table_r)) {
> +			dev_err(dev,
> +				"set_gamma_params: Invalid"
> +				" table ptr for R\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(gamma.table_r,
> +				    user_gamma.table_r,
> +				    (table_size *
> +				    sizeof(struct \
> +				    ipipe_gamma_entry)))) {
> +			dev_err(dev,
> +				"set_gamma_params: R-Error"
> +				" in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +	}
> +
> +	if (!user_gamma.bypass_b) {
> +		if (ISNULL(user_gamma.table_b)) {
> +			dev_err(dev,
> +				"set_gamma_params: Invalid"
> +				" table ptr for B\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(gamma.table_b,
> +				    user_gamma.table_b,
> +				    (table_size *
> +				    sizeof(struct \
> +				    ipipe_gamma_entry)))) {
> +			dev_err(dev,
> +				"set_gamma_params: B-Error"
> +				" in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +	}
> +
> +	if (!user_gamma.bypass_g) {
> +		if (ISNULL(user_gamma.table_g)) {
> +			dev_err(dev,
> +				"set_gamma_params: Invalid"
> +				" table ptr for G\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(gamma.table_g,
> +				    user_gamma.table_g,
> +				    (table_size *
> +				    sizeof(struct \
> +				    ipipe_gamma_entry)))) {
> +			dev_err(dev,
> +				"set_gamma_params: G-Error "
> +				"in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +	}
> +
> +success:
> +	ipipe_set_gamma_regs(&gamma);
> +
> +	return 0;
> +}
> +
> +static int get_gamma_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_gamma *gamma_param = (struct prev_gamma *)param;
> +	struct prev_gamma user_gamma;
> +	int table_size;
> +
> +	if (ISNULL(gamma_param)) {
> +		dev_err(dev, "get_gamma_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_gamma)) {
> +		dev_err(dev,
> +			"get_gamma_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&user_gamma,
> +			   gamma_param,
> +			   sizeof(struct prev_gamma))) {
> +		dev_err(dev, "get_gamma_params: Error in copy to kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	user_gamma.bypass_r = gamma.bypass_r;
> +	user_gamma.bypass_g = gamma.bypass_g;
> +	user_gamma.bypass_b = gamma.bypass_b;
> +	user_gamma.tbl_sel = gamma.tbl_sel;
> +	user_gamma.tbl_size = gamma.tbl_size;
> +	if (gamma.tbl_sel == IPIPE_GAMMA_TBL_RAM) {
> +		table_size = gamma.tbl_size;
> +
> +		if ((!gamma.bypass_r) && ((ISNULL(user_gamma.table_r)))) {
> +			dev_err(dev,
> +				"get_gamma_params: table ptr empty for R\n");
> +			return -EINVAL;
> +		} else {
> +			if (copy_to_user(user_gamma.table_r,
> +					 gamma.table_r,
> +					 (table_size *
> +					 sizeof(struct ipipe_gamma_entry)))) {
> +				dev_err(dev,
> +					"set_gamma_params: R-Table Error in"
> +					" copy to user\n");
> +				return -EFAULT;
> +			}
> +		}
> +
> +		if ((!gamma.bypass_b) && ((ISNULL(user_gamma.table_b)))) {
> +			dev_err(dev,
> +				"get_gamma_params: table ptr empty for B\n");
> +			return -EINVAL;
> +		} else {
> +			if (copy_to_user(user_gamma.table_b,
> +					 gamma.table_b,
> +					 (table_size *
> +					  sizeof(struct ipipe_gamma_entry)))) {
> +				dev_err(dev,
> +					"set_gamma_params: B-Table Error in"
> +					" copy to user\n");
> +				return -EFAULT;
> +			}
> +		}
> +
> +		if ((!gamma.bypass_g) && ((ISNULL(user_gamma.table_g)))) {
> +			dev_err(dev,
> +				"get_gamma_params: table ptr empty for G\n");
> +			return -EINVAL;
> +		} else {
> +			if (copy_from_user(gamma.table_g,
> +				user_gamma.table_g,
> +				(table_size *
> +				sizeof(struct ipipe_gamma_entry)))) {
> +				dev_err(dev,
> +					"set_gamma_params: G-Table"
> +					"copy error\n");
> +				return -EFAULT;
> +			}
> +		}
> +
> +	}
> +	if (copy_to_user(gamma_param, &user_gamma,
> +		sizeof(struct prev_gamma))) {
> +		dev_err(dev, "get_dfc_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_3d_lut_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	int i;
> +
> +	if (!lut_3d.en)
> +		return 0;
> +
> +	for (i = 0; i < MAX_SIZE_3D_LUT; i++) {
> +		if (lut_3d.table[i].r > D3_LUT_ENTRY_MASK ||
> +		    lut_3d.table[i].g > D3_LUT_ENTRY_MASK ||
> +		    lut_3d.table[i].b > D3_LUT_ENTRY_MASK)
> +			return -EINVAL;
> +	}
> +#endif
> +	return 0;
> +}
> +static int set_3d_lut_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_3d_lut *lut_param = (struct prev_3d_lut *)param;
> +	struct prev_3d_lut user_3d_lut;
> +
> +	if (ISNULL(lut_param)) {
> +		/* Copy defaults for gamma */
> +		lut_3d.en = dm365_3d_lut_defaults.en;
> +		/* By default, 3D lut is disabled
> +		 */
> +	} else {
> +		if (len != sizeof(struct prev_3d_lut)) {
> +			dev_err(dev,
> +				"set_3d_lut_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&user_3d_lut,
> +				   lut_param,
> +				   sizeof(struct prev_3d_lut))) {
> +			dev_err(dev,
> +				"set_3d_lut_params: Error in copy to"
> +				" kernel\n");
> +			return -EFAULT;
> +		}
> +		lut_3d.en = user_3d_lut.en;
> +		if (ISNULL(user_3d_lut.table)) {
> +			dev_err(dev, "set_3d_lut_params: Invalid table ptr");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(lut_3d.table,
> +				   user_3d_lut.table,
> +				   (MAX_SIZE_3D_LUT *
> +				   sizeof(struct ipipe_3d_lut_entry)))) {
> +			dev_err(dev,
> +				"set_3d_lut_params:Error"
> +				" in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +
> +		if (validate_3d_lut_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_3d_lut_regs(&lut_3d);
> +
> +	return 0;
> +}
> +static int get_3d_lut_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_3d_lut *lut_param = (struct prev_3d_lut *)param;
> +	struct prev_3d_lut user_3d_lut;
> +
> +	if (ISNULL(lut_param)) {
> +		dev_err(dev, "get_3d_lut_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_3d_lut)) {
> +		dev_err(dev,
> +			"get_3d_lut_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&user_3d_lut,
> +			   lut_param,
> +			   sizeof(struct prev_3d_lut))) {
> +		dev_err(dev, "get_3d_lut_params: Error in copy to kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	user_3d_lut.en = lut_3d.en;
> +	if (ISNULL(user_3d_lut.table)) {
> +		dev_err(dev, "get_3d_lut_params:" " Invalid table ptr");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(user_3d_lut.table, lut_3d.table,
> +			 (MAX_SIZE_3D_LUT *
> +			  sizeof(struct ipipe_3d_lut_entry)))) {
> +		dev_err(dev,
> +			"get_3d_lut_params:Table Error in" " copy to user\n");
> +		return -EFAULT;
> +	}
> +
> +	if (copy_to_user(lut_param, &user_3d_lut,
> +		sizeof(struct prev_3d_lut))) {
> +		dev_err(dev, "get_3d_lut_params: Error in copy" " to user\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_lum_adj_params(struct device *dev)
> +{
> +	/* nothing to validate */
> +	return 0;
> +}
> +
> +static int set_lum_adj_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_lum_adj *lum_adj_param = (struct prev_lum_adj *)param;
> +
> +	if (ISNULL(lum_adj_param)) {
> +		/* Copy defaults for Luminance adjustments */
> +		memcpy((void *)&lum_adj,
> +		       (void *)&dm365_lum_adj_defaults,
> +		       sizeof(struct prev_lum_adj));
> +	} else {
> +		if (len != sizeof(struct prev_lum_adj)) {
> +			dev_err(dev,
> +				"set_lum_adj_params: param struct length"
> +				" mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&lum_adj,
> +				   lum_adj_param,
> +				   sizeof(struct prev_lum_adj))) {
> +			dev_err(dev,
> +				"set_lum_adj_params: Error in copy"
> +				" from user\n");
> +			return -EFAULT;
> +		}
> +		if (validate_lum_adj_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_lum_adj_regs(&lum_adj);
> +
> +	return 0;
> +}
> +
> +static int get_lum_adj_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_lum_adj *lum_adj_param = (struct prev_lum_adj *)param;
> +
> +	if (ISNULL(lum_adj_param)) {
> +		dev_err(dev, "get_lum_adj_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +
> +	if (len != sizeof(struct prev_lum_adj)) {
> +		dev_err(dev,
> +			"get_lum_adj_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +
> +	if (copy_to_user(lum_adj_param,
> +			 &lum_adj,
> +			 sizeof(struct prev_lum_adj))) {
> +		dev_err(dev, "get_lum_adj_params: Error in copy to" " user\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_rgb2yuv_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (rgb2yuv.coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_ry.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_gy.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_by.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> +	    rgb2yuv.coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK)
> +		return -EINVAL;
> +
> +	if (rgb2yuv.out_ofst_y > RGB2YCBCR_OFST_MASK ||
> +	    rgb2yuv.out_ofst_cb > RGB2YCBCR_OFST_MASK ||
> +	    rgb2yuv.out_ofst_cr > RGB2YCBCR_OFST_MASK)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +static int set_rgb2yuv_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_rgb2yuv *rgb2yuv_param = (struct prev_rgb2yuv *)param;
> +
> +	if (ISNULL(rgb2yuv_param)) {
> +		/* Copy defaults for rgb2yuv conversion  */
> +		memcpy((void *)&rgb2yuv,
> +		       (void *)&dm365_rgb2yuv_defaults,
> +		       sizeof(struct prev_rgb2yuv));
> +	} else {
> +		if (len != sizeof(struct prev_rgb2yuv)) {
> +			dev_err(dev,
> +				"set_rgb2yuv_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&rgb2yuv,
> +				   rgb2yuv_param,
> +				   sizeof(struct prev_rgb2yuv))) {
> +			dev_err(dev,
> +				"set_rgb2yuv_params: Error in copy from"
> +				" user\n");
> +			return -EFAULT;
> +		}
> +		if (validate_rgb2yuv_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_rgb2ycbcr_regs(&rgb2yuv);
> +
> +	return 0;
> +}
> +static int get_rgb2yuv_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_rgb2yuv *rgb2yuv_param = (struct prev_rgb2yuv *)param;
> +
> +	if (ISNULL(rgb2yuv_param)) {
> +		dev_err(dev, "get_rgb2yuv_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_rgb2yuv)) {
> +		dev_err(dev,
> +			"get_rgb2yuv_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user((struct prev_rgb2yuv *)rgb2yuv_param,
> +			 &rgb2yuv,
> +			 sizeof(struct prev_rgb2yuv))) {
> +		dev_err(dev, "get_rgb2yuv_params: Error in copy from"
> +			" kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_gbce_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	u32 max = GBCE_Y_VAL_MASK;
> +	int i;
> +
> +	if (!gbce.en)
> +		return 0;
> +
> +	if (gbce.type == IPIPE_GBCE_GAIN_TBL)
> +		max = GBCE_GAIN_VAL_MASK;
> +	for (i = 0; i < MAX_SIZE_GBCE_LUT; i++)
> +		if (gbce.table[i] > max)
> +			return -EINVAL;
> +#endif
> +	return 0;
> +}
> +static int set_gbce_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_gbce *gbce_param = (struct prev_gbce *)param;
> +	struct prev_gbce user_gbce;
> +
> +	if (ISNULL(gbce_param))
> +		/* Copy defaults for gamma */
> +		gbce.en = dm365_gbce_defaults.en;
> +		/* By default, GBCE is disabled
> +		 */
> +	else {
> +		if (len != sizeof(struct prev_gbce)) {
> +			dev_err(dev,
> +				"set_gbce_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&user_gbce,
> +				   gbce_param,
> +				   sizeof(struct prev_gbce))) {
> +			dev_err(dev,
> +				"set_gbce_params: Error in copy to"
> +				" kernel\n");
> +			return -EFAULT;
> +		}
> +		gbce.en = user_gbce.en;
> +		gbce.type = user_gbce.type;
> +		if (ISNULL(user_gbce.table)) {
> +			dev_err(dev, "set_gbce_params:" " Invalid table ptr");
> +			return -EINVAL;
> +		}
> +
> +		if (copy_from_user(gbce.table,
> +				   user_gbce.table,
> +				   (MAX_SIZE_GBCE_LUT *
> +				   sizeof(unsigned short)))) {
> +			dev_err(dev, "set_gbce_params:Error"
> +					" in copy to kernel\n");
> +			return -EFAULT;
> +		}
> +		if (validate_gbce_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_gbce_regs(&gbce);
> +
> +	return 0;
> +}
> +static int get_gbce_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_gbce *gbce_param = (struct prev_gbce *)param;
> +	struct prev_gbce user_gbce;
> +
> +	if (ISNULL(gbce_param)) {
> +		dev_err(dev, "get_gbce_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_gbce)) {
> +		dev_err(dev,
> +			"get_gbce_params: param struct length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&user_gbce, gbce_param, sizeof(struct prev_gbce))) {
> +		dev_err(dev, "get_gbce_params: Error in copy to" " kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	user_gbce.en = gbce.en;
> +	user_gbce.type = gbce.type;
> +	if (ISNULL(user_gbce.table)) {
> +		dev_err(dev, "get_gbce_params:" " Invalid table ptr");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(user_gbce.table,
> +			 gbce.table,
> +			 (MAX_SIZE_GBCE_LUT *
> +			 sizeof(unsigned short)))) {
> +		dev_err(dev,
> +			"get_gbce_params:Table Error in" " copy to user\n");
> +		return -EFAULT;
> +	}
> +
> +	if (copy_to_user(gbce_param, &user_gbce, sizeof(struct prev_gbce))) {
> +		dev_err(dev, "get_gbce_params: Error in copy" " to user\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_yuv422_conv_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (yuv422_conv.en_chrom_lpf > 1)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +
> +static int set_yuv422_conv_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_yuv422_conv *yuv422_conv_param =
> +	    (struct prev_yuv422_conv *)param;
> +
> +	if (ISNULL(yuv422_conv_param)) {
> +		/* Copy defaults for yuv 422 conversion */
> +		memcpy((void *)&yuv422_conv,
> +		       (void *)&dm365_yuv422_conv_defaults,
> +		       sizeof(struct prev_yuv422_conv));
> +	} else {
> +		if (len != sizeof(struct prev_yuv422_conv)) {
> +			dev_err(dev,
> +				"set_yuv422_conv_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&yuv422_conv,
> +				   yuv422_conv_param,
> +				   sizeof(struct prev_yuv422_conv))) {
> +			dev_err(dev,
> +				"set_yuv422_conv_params: Error in copy"
> +				" from user\n");
> +			return -EFAULT;
> +		}
> +		if (validate_yuv422_conv_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_yuv422_conv_regs(&yuv422_conv);
> +
> +	return 0;
> +}
> +static int get_yuv422_conv_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_yuv422_conv *yuv422_conv_param =
> +	    (struct prev_yuv422_conv *)param;
> +
> +	if (ISNULL(yuv422_conv_param)) {
> +		dev_err(dev, "get_yuv422_conv_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_yuv422_conv)) {
> +		dev_err(dev,
> +			"get_yuv422_conv_params: param struct"
> +			" length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(yuv422_conv_param,
> +			 &yuv422_conv,
> +			 sizeof(struct prev_yuv422_conv))) {
> +		dev_err(dev,
> +			"get_yuv422_conv_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_yee_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	int i;
> +
> +	if (yee.en > 1 ||
> +	    yee.en_halo_red > 1 ||
> +	    yee.hpf_shft > YEE_HPF_SHIFT_MASK)
> +		return -EINVAL;
> +
> +	if (yee.hpf_coef_00 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_01 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_02 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_10 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_11 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_12 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_20 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_21 > YEE_COEF_MASK ||
> +	    yee.hpf_coef_22 > YEE_COEF_MASK)
> +		return -EINVAL;
> +
> +	if (yee.yee_thr > YEE_THR_MASK ||
> +	    yee.es_gain > YEE_ES_GAIN_MASK ||
> +	    yee.es_thr1 > YEE_ES_THR1_MASK ||
> +	    yee.es_thr2 > YEE_THR_MASK ||
> +	    yee.es_gain_grad > YEE_THR_MASK ||
> +	    yee.es_ofst_grad > YEE_THR_MASK)
> +		return -EINVAL;
> +
> +	for (i = 0; i < MAX_SIZE_YEE_LUT ; i++)
> +		if (yee.table[i] > YEE_ENTRY_MASK)
> +			return -EINVAL;
> +#endif
> +	return 0;
> +}
> +static int set_yee_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_yee *yee_param = (struct prev_yee *)param;
> +	struct prev_yee user_yee;
> +	short *temp_table;
> +
> +	if (ISNULL(yee_param)) {
> +		temp_table = yee.table;
> +		/* Copy defaults for ns */
> +		memcpy((void *)&yee,
> +		       (void *)&dm365_yee_defaults,
> +		       sizeof(struct prev_yee));
> +		yee.table = temp_table;
> +	} else {
> +		if (len != sizeof(struct prev_yee)) {
> +			dev_err(dev,
> +				"set_yee_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&user_yee,
> +				   yee_param,
> +				   sizeof(struct prev_yee))) {
> +			dev_err(dev,
> +				"set_yee_params: Error in copy from user\n");
> +			return -EFAULT;
> +		}
> +		if (ISNULL(user_yee.table)) {
> +			dev_err(dev, "get_yee_params: yee table ptr null\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(yee.table,
> +				   user_yee.table,
> +				   (MAX_SIZE_YEE_LUT * sizeof(short)))) {
> +			dev_err(dev,
> +				"set_yee_params: Error in copy from user\n");
> +			return -EFAULT;
> +		}
> +		temp_table = yee.table;
> +		memcpy(&yee, &user_yee, sizeof(struct prev_yee));
> +		yee.table = temp_table;
> +		if (validate_yee_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_ee_regs(&yee);
> +
> +	return 0;
> +}
> +static int get_yee_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_yee *yee_param = (struct prev_yee *)param;
> +	struct prev_yee user_yee;
> +	short *temp_table;
> +
> +	if (ISNULL(yee_param)) {
> +		dev_err(dev, "get_yee_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_yee)) {
> +		dev_err(dev,
> +			"get_yee_params: param struct"
> +			" length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_from_user(&user_yee, yee_param, sizeof(struct prev_yee))) {
> +		dev_err(dev, "get_yee_params: Error in copy to kernel\n");
> +		return -EFAULT;
> +	}
> +	if (ISNULL(user_yee.table)) {
> +		dev_err(dev, "get_yee_params: yee table ptr null\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(user_yee.table, yee.table,
> +			 (MAX_SIZE_YEE_LUT * sizeof(short)))) {
> +		dev_err(dev, "get_yee_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +	temp_table = user_yee.table;
> +	memcpy(&user_yee, &yee, sizeof(struct prev_yee));
> +	user_yee.table = temp_table;
> +
> +	if (copy_to_user(yee_param, &user_yee, sizeof(struct prev_yee))) {
> +		dev_err(dev, "get_yee_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_car_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (car.en > 1 ||
> +	    car.hpf_shft > CAR_HPF_SHIFT_MASK ||
> +	    car.gain1.shft > CAR_GAIN1_SHFT_MASK ||
> +	    car.gain1.gain_min > CAR_GAIN_MIN_MASK ||
> +	    car.gain2.shft > CAR_GAIN2_SHFT_MASK ||
> +	    car.gain2.gain_min > CAR_GAIN_MIN_MASK)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +
> +static int set_car_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_car *car_param = (struct prev_car *)param;
> +
> +	if (ISNULL(car_param)) {
> +		/* Copy defaults for ns */
> +		memcpy((void *)&car,
> +		       (void *)&dm365_car_defaults,
> +		       sizeof(struct prev_car));
> +	} else {
> +		if (len != sizeof(struct prev_car)) {
> +			dev_err(dev,
> +				"set_car_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&car, car_param, sizeof(struct prev_car))) {
> +			dev_err(dev,
> +				"set_car_params: Error in copy from user\n");
> +			return -EFAULT;
> +		}
> +		if (validate_car_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_car_regs(&car);
> +
> +	return 0;
> +}
> +static int get_car_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_car *car_param = (struct prev_car *)param;
> +
> +	if (ISNULL(car_param)) {
> +		dev_err(dev, "get_car_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_car)) {
> +		dev_err(dev,
> +			"get_car_params: param struct"
> +			" length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(car_param, &car, sizeof(struct prev_car))) {
> +		dev_err(dev, "get_car_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_cgs_params(struct device *dev)
> +{
> +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> +	if (cgs.en > 1 ||
> +	    cgs.h_shft > CAR_SHIFT_MASK)
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +
> +static int set_cgs_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_cgs *cgs_param = (struct prev_cgs *)param;
> +
> +	if (ISNULL(cgs_param)) {
> +		/* Copy defaults for ns */
> +		memcpy((void *)&cgs,
> +		       (void *)&dm365_cgs_defaults,
> +		       sizeof(struct prev_cgs));
> +	} else {
> +		if (len != sizeof(struct prev_cgs)) {
> +			dev_err(dev,
> +				"set_cgs_params: param struct"
> +				" length mismatch\n");
> +			return -EINVAL;
> +		}
> +		if (copy_from_user(&cgs, cgs_param, sizeof(struct prev_cgs))) {
> +			dev_err(dev,
> +				"set_cgs_params: Error in copy from user\n");
> +			return -EFAULT;
> +		}
> +		if (validate_cgs_params(dev) < 0)
> +			return -EINVAL;
> +	}
> +
> +	ipipe_set_cgs_regs(&cgs);
> +
> +	return 0;
> +}
> +
> +static int get_cgs_params(struct device *dev, void *param, int len)
> +{
> +	struct prev_cgs *cgs_param = (struct prev_cgs *)param;
> +
> +	if (ISNULL(cgs_param)) {
> +		dev_err(dev, "get_cgs_params: invalid user ptr");
> +		return -EINVAL;
> +	}
> +	if (len != sizeof(struct prev_cgs)) {
> +		dev_err(dev,
> +			"get_cgs_params: param struct"
> +			" length mismatch\n");
> +		return -EINVAL;
> +	}
> +	if (copy_to_user(cgs_param, &cgs, sizeof(struct prev_cgs))) {
> +		dev_err(dev, "get_cgs_params: Error in copy from kernel\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct prev_module_if prev_modules[PREV_MAX_MODULES] = {
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_LUTDPC,
> +		.module_name = "LUT Defect Correction",
> +		.control = 0,
> +		.path = IMP_RAW2RAW | IMP_RAW2YUV,
> +		.set = set_lutdpc_params,
> +		.get = get_lutdpc_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_OTFDPC,
> +		.module_name = "OTF Defect Pixel Correction",
> +		.control = 0,
> +		.path = IMP_RAW2RAW | IMP_RAW2YUV,
> +		.set = set_otfdpc_params,
> +		.get = get_otfdpc_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_NF1,
> +		.module_name = "2-D Noise filter - 1",
> +		.control = 0,
> +		.path = IMP_RAW2RAW | IMP_RAW2YUV,
> +		.set = set_nf1_params,
> +		.get = get_nf1_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_NF2,
> +		.module_name = "2-D Noise filter - 2",
> +		.control = 0,
> +		.path = IMP_RAW2RAW | IMP_RAW2YUV,
> +		.set = set_nf2_params,
> +		.get = get_nf2_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_GIC,
> +		.module_name = "Green Imbalance Correction",
> +		.control = 0,
> +		.path = IMP_RAW2RAW | IMP_RAW2YUV,
> +		.set = set_gic_params,
> +		.get = get_gic_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_WB,
> +		.module_name = "White balance",
> +		.control = 1,
> +		.path = IMP_RAW2RAW | IMP_RAW2YUV,
> +		.set = set_wb_params,
> +		.get = get_wb_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_CFA,
> +		.module_name = "CFA Interpolation",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_cfa_params,
> +		.get = get_cfa_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_RGB2RGB_1,
> +		.module_name = "RGB-RGB Conversion - 1",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_rgb2rgb_1_params,
> +		.get = get_rgb2rgb_1_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_GAMMA,
> +		.module_name = "Gamma Correction",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_gamma_params,
> +		.get = get_gamma_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_RGB2RGB_2,
> +		.module_name = "RGB-RGB Conversion - 2",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_rgb2rgb_2_params,
> +		.get = get_rgb2rgb_2_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_3D_LUT,
> +		.module_name = "3D LUT",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_3d_lut_params,
> +		.get = get_3d_lut_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_RGB2YUV,
> +		.module_name = "RGB-YCbCr conversion",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_rgb2yuv_params,
> +		.get = get_rgb2yuv_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_GBCE,
> +		.module_name = "Global Brightness,Contrast Control",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_gbce_params,
> +		.get = get_gbce_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_YUV422_CONV,
> +		.module_name = "YUV 422 conversion",
> +		.control = 0,
> +		.path = IMP_RAW2YUV,
> +		.set = set_yuv422_conv_params,
> +		.get = get_yuv422_conv_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_LUM_ADJ,
> +		.module_name = "Luminance Adjustment",
> +		.control = 1,
> +		.path = IMP_RAW2YUV,
> +		.set = set_lum_adj_params,
> +		.get = get_lum_adj_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_YEE,
> +		.module_name = "Edge Enhancer",
> +		.control = 1,
> +		.path = IMP_RAW2YUV | IMP_YUV2YUV,
> +		.set = set_yee_params,
> +		.get = get_yee_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_CAR,
> +		.module_name = "Chromatic Artifact Reduction",
> +		.control = 1,
> +		.path = IMP_RAW2YUV | IMP_YUV2YUV,
> +		.set = set_car_params,
> +		.get = get_car_params
> +	},
> +	{
> +		.version = "5.1",
> +		.module_id = PREV_CGS,
> +		.module_name = "Chromatic Gain Suppression",
> +		.control = 1,
> +		.path = IMP_RAW2YUV | IMP_YUV2YUV,
> +		.set = set_cgs_params,
> +		.get = get_cgs_params
> +	}
> +};
> +
> +static struct prev_module_if *prev_enum_preview_cap(struct device *dev,
> +						    int index)
> +{
> +	dev_dbg(dev, "prev_enum_preview_cap: index = %d\n", index);
> +
> +	if ((index + 1) > PREV_MAX_MODULES)
> +		return NULL;

if (index < 0 || index >= PREV_MAX_MODULES)
	return NULL;

You might want to use unsigned for index as well. That avoids some traps.

> +	return &prev_modules[index];
> +}
> +
> +static int ipipe_set_oper_mode(unsigned int mode)
> +{
> +	if (oper_mode == IMP_MODE_NOT_CONFIGURED)
> +		oper_mode = mode;
> +	else {
> +		printk(KERN_ERR "IPIPE is already active!\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void ipipe_reset_oper_mode(void)
> +{
> +	oper_mode = IMP_MODE_NOT_CONFIGURED;
> +	oper_state.prev_config_state = STATE_NOT_CONFIGURED;
> +	oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
> +	oper_state.rsz_chained = 0;
> +}
> +
> +static unsigned int prev_get_oper_mode(void)
> +{
> +	return oper_mode;
> +}
> +
> +static unsigned int ipipe_get_oper_state(void)
> +{
> +	return oper_state.state;
> +}
> +
> +static void ipipe_set_oper_state(unsigned int state)
> +{
> +	mutex_lock(&oper_state.lock);
> +	oper_state.state = state;
> +	mutex_unlock(&oper_state.lock);
> +}
> +
> +static unsigned int ipipe_get_prev_config_state(void)
> +{
> +	return oper_state.prev_config_state;
> +}
> +
> +static unsigned int ipipe_get_rsz_config_state(void)
> +{
> +	return oper_state.rsz_config_state;
> +}
> +
> +/* function: calculate_normal_f_div_param
> + * Algorithm to calculate the frame division parameters for resizer.
> + * in normal mode. Please refer the application note in DM360 functional
> + * spec for details of the algorithm
> + */
> +static int calculate_normal_f_div_param(struct device *dev,
> +					int input_width,
> +					int output_width,
> +					struct ipipe_rsz_rescale_param *param)
> +{
> +	/* rsz = R, input_width = H, output width = h in the equation */
> +	unsigned int val1;
> +	unsigned int rsz;
> +	unsigned int val;
> +	unsigned int h1;
> +	unsigned int h2;
> +	unsigned int o;
> +
> +	if (output_width > input_width) {
> +		dev_err(dev, "frame div mode is used for scale down only\n");
> +		return -EINVAL;
> +	}
> +
> +	rsz = (input_width << 8) / output_width;
> +	val = rsz << 1;
> +	val = ((input_width << 8) / val) + 1;
> +	o = 14;
> +	if (!(val % 2)) {
> +		h1 = val;
> +	} else {
> +		val = (input_width << 7);
> +		val -= (rsz >> 1);
> +		val /= (rsz << 1);
> +		val <<= 1;
> +		val += 2;
> +		o += ((CEIL(rsz, 1024)) << 1);
> +		h1 = val;
> +	}
> +	h2 = output_width - h1;
> +	/* phi */
> +	val = (h1 * rsz) - (((input_width >> 1) - o) << 8);
> +	/* skip */
> +	val1 = ((val - 1024) >> 9) << 1;
> +	param->f_div.num_passes = IPIPE_MAX_PASSES;
> +	param->f_div.pass[0].o_hsz = h1 - 1;
> +	param->f_div.pass[0].i_hps = 0;
> +	param->f_div.pass[0].h_phs = 0;
> +	param->f_div.pass[0].src_hps = 0;
> +	param->f_div.pass[0].src_hsz = (input_width >> 2) + o;
> +	param->f_div.pass[1].o_hsz = h2 - 1;
> +	param->f_div.pass[1].i_hps = val1;
> +	param->f_div.pass[1].h_phs = (val - (val1 << 8));
> +	param->f_div.pass[1].src_hps = (input_width >> 2) - o;
> +	param->f_div.pass[1].src_hsz = (input_width >> 2) + o;
> +
> +	return 0;
> +}
> +
> +/* function: calculate_down_scale_f_div_param
> + * Algorithm to calculate the frame division parameters for resizer in
> + * downscale mode. Please refer the application note in DM360 functional
> + * spec for details of the algorithm
> + */
> +static int calculate_down_scale_f_div_param(struct device *dev,
> +					    int input_width,
> +					    int output_width,
> +					    struct ipipe_rsz_rescale_param
> +					    *param)
> +{
> +	/* rsz = R, input_width = H, output width = h in the equation */
> +	unsigned int two_power;
> +	unsigned int upper_h1;
> +	unsigned int upper_h2;
> +	unsigned int val1;
> +	unsigned int val;
> +	unsigned int rsz;
> +	unsigned int h1;
> +	unsigned int h2;
> +	unsigned int o;
> +	unsigned int n;
> +
> +	upper_h1 = input_width >> 1;
> +	n = param->h_dscale_ave_sz;
> +	/* 2 ^ (scale+1) */
> +	two_power = 1 << (n + 1);
> +	upper_h1 = (upper_h1 >> (n + 1)) << (n + 1);
> +	upper_h2 = input_width - upper_h1;
> +	if (upper_h2 % two_power) {
> +		dev_err(dev, "frame halves to be a multiple of 2 power n+1\n");
> +		return -EINVAL;
> +	}
> +	two_power = 1 << n;
> +	rsz = (input_width << 8) / output_width;
> +	val = rsz * two_power;
> +	val = ((upper_h1 << 8) / val) + 1;
> +	if (!(val % 2))
> +		h1 = val;
> +	else {
> +		val = (upper_h1 << 8);
> +		val >>= (n + 1);
> +		val -= (rsz >> 1);
> +		val /= (rsz << 1);
> +		val <<= 1;
> +		val += 2;
> +		h1 = val;
> +	}
> +	o = 10 + (two_power << 2);
> +	if (((input_width << 7) / rsz) % 2)
> +		o += (((CEIL(rsz, 1024)) << 1) << n);
> +	h2 = output_width - h1;
> +	/* phi */
> +	val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8);
> +	/* skip */
> +	val1 = ((val - 1024) >> 9) << 1;
> +	param->f_div.num_passes = IPIPE_MAX_PASSES;
> +	param->f_div.pass[0].o_hsz = h1 - 1;
> +	param->f_div.pass[0].i_hps = 0;
> +	param->f_div.pass[0].h_phs = 0;
> +	param->f_div.pass[0].src_hps = 0;
> +	param->f_div.pass[0].src_hsz = upper_h1 + o;
> +	param->f_div.pass[1].o_hsz = h2 - 1;
> +	param->f_div.pass[1].i_hps = 10 + (val1 * two_power);
> +	param->f_div.pass[1].h_phs = (val - (val1 << 8));
> +	param->f_div.pass[1].src_hps = (upper_h1 - o);
> +	param->f_div.pass[1].src_hsz = (upper_h2 + o);
> +
> +	return 0;
> +}
> +
> +/* update the parameter in param for a given input and output width */
> +static int update_preview_f_div_params(struct device *dev,
> +				       int input_width,
> +				       int output_width,
> +				       struct ipipe_rsz_rescale_param *param)
> +{
> +	unsigned int val;
> +
> +	val = input_width >> 1;
> +	if (val < 8) {
> +		dev_err(dev, "input width must me atleast 16 pixels\n");
> +		return -EINVAL;
> +	}
> +	param->f_div.en = 1;
> +	param->f_div.num_passes = IPIPE_MAX_PASSES;
> +	param->f_div.pass[0].o_hsz = val;
> +	param->f_div.pass[0].i_hps = 0;
> +	param->f_div.pass[0].h_phs = 0;
> +	param->f_div.pass[0].src_hps = 0;
> +	param->f_div.pass[0].src_hsz = val + 10;
> +	param->f_div.pass[1].o_hsz = val;
> +	param->f_div.pass[1].i_hps = 0;
> +	param->f_div.pass[1].h_phs = 0;
> +	param->f_div.pass[1].src_hps = val - 8;
> +	param->f_div.pass[1].src_hsz = val + 10;
> +
> +	return 0;
> +}
> +
> +/* Use shared to allocate exclusive blocks as required
> + * by resize applications in single shot mode
> + */
> +static void *ipipe_alloc_config_block(struct device *dev)
> +{
> +	/* return common data block */
> +	mutex_lock(&oper_state.lock);
> +	if (oper_state.resource_in_use) {
> +		dev_err(dev, "resource in use\n");
> +		mutex_unlock(&oper_state.lock);
> +		return NULL;
> +	}
> +	mutex_unlock(&oper_state.lock);
> +
> +	return oper_state.shared_config_param;
> +}
> +
> +/* Used to free only non-shared config block allocated through
> + * imp_alloc_config_block
> + */
> +static void ipipe_dealloc_config_block(struct device *dev, void *config_block)
> +{
> +	if (config_block) {
> +		if (config_block != oper_state.shared_config_param)
> +			kfree(config_block);
> +		else
> +			dev_err(dev, "Trying to free shared config block\n");
> +	}
> +}
> +
> +static void ipipe_dealloc_user_config_block(struct device *dev,
> +					    void *config_block)
> +{
> +	kfree(config_block);
> +}
> +
> +static void *ipipe_alloc_user_config_block(struct device *dev,
> +					   enum imp_log_chan_t chan_type,
> +					   int *len)
> +{
> +	void *config = NULL;
> +
> +	if (oper_mode == IMP_MODE_SINGLE_SHOT) {
> +		if (chan_type == IMP_PREVIEWER) {
> +			config =
> +			    kmalloc(sizeof(struct prev_single_shot_config),
> +				    GFP_KERNEL);
> +			*len = sizeof(struct prev_single_shot_config);
> +		} else if (chan_type == IMP_RESIZER) {
> +			config =
> +			    kmalloc(sizeof(struct rsz_single_shot_config),
> +				    GFP_KERNEL);
> +			*len = sizeof(struct rsz_single_shot_config);
> +		}
> +
> +	} else {
> +		if (chan_type == IMP_PREVIEWER) {
> +			config =
> +			    kmalloc(sizeof(struct prev_continuous_config),
> +				    GFP_KERNEL);
> +			*len = sizeof(struct prev_continuous_config);
> +		} else if (chan_type == IMP_RESIZER) {
> +			config =
> +			    kmalloc(sizeof(struct rsz_continuous_config),
> +				    GFP_KERNEL);
> +			*len = sizeof(struct rsz_continuous_config);
> +		}
> +	}
> +
> +	return config;
> +}
> +
> +static void ipipe_set_user_config_defaults(struct device *dev,
> +					   enum imp_log_chan_t chan_type,
> +					   void *config)
> +{
> +	dev_dbg(dev, "ipipe_set_user_config_defaults\n");
> +
> +	if (oper_mode == IMP_MODE_SINGLE_SHOT) {
> +		if (chan_type == IMP_PREVIEWER) {
> +			dev_dbg(dev, "SS-Preview\n");
> +			/* preview channel in single shot mode */
> +			memcpy(config,
> +			       (void *)&dm365_prev_ss_config_defs,
> +			       sizeof(struct prev_single_shot_config));
> +		} else {
> +			dev_dbg(dev, "SS-Resize\n");
> +			/* resizer channel in single shot mode */
> +			memcpy(config,
> +			       (void *)&dm365_rsz_ss_config_defs,
> +			       sizeof(struct rsz_single_shot_config));
> +		}
> +	} else if (oper_mode == IMP_MODE_CONTINUOUS) {
> +		/* Continuous mode */
> +		if (chan_type == IMP_PREVIEWER) {
> +			dev_dbg(dev, "Cont Preview\n");
> +			/* previewer defaults */
> +			memcpy(config,
> +			       (void *)&dm365_prev_cont_config_defs,
> +			       sizeof(struct prev_continuous_config));
> +		} else {
> +			dev_dbg(dev, "Cont resize\n");
> +			/* resizer defaults */
> +			memcpy(config,
> +			       (void *)&dm365_rsz_cont_config_defs,
> +			       sizeof(struct rsz_continuous_config));
> +		}
> +	} else
> +		dev_err(dev, "Incorrect mode used\n");
> +}
> +
> +/* function :calculate_sdram_offsets()
> + *	This function calculates the offsets from start of buffer for the C
> + *	plane when output format is YUV420SP. It also calculates the offsets
> + *	from the start of the buffer when the image is flipped vertically
> + *	or horizontally for ycbcr/y/c planes
> + */
> +static int calculate_sdram_offsets(struct ipipe_params *param, int index)
> +{
> +	int bytesperline = 2;
> +	int image_height;
> +	int image_width;
> +	int yuv_420;
> +	int offset;
> +
> +	if (!param->rsz_en[index])
> +		return -EINVAL;
> +
> +	image_height = param->rsz_rsc_param[index].o_vsz + 1;
> +	image_width = param->rsz_rsc_param[index].o_hsz + 1;
> +	param->ext_mem_param[index].c_offset = 0;
> +	param->ext_mem_param[index].flip_ofst_y = 0;
> +	param->ext_mem_param[index].flip_ofst_c = 0;
> +	if ((param->ipipe_dpaths_fmt != IPIPE_RAW2RAW) &&
> +	    (param->ipipe_dpaths_fmt != IPIPE_RAW2BOX) &&

No need for extra parenthesis.

> +	    param->rsz_rsc_param[index].cen &&
> +	    param->rsz_rsc_param[index].yen) {
> +		/* YUV 420 */
> +		yuv_420 = 1;
> +		bytesperline = 1;

bytesperline == 1? Really?

> +	}
> +
> +	/* set offset value */
> +	offset = 0;
> +
> +	if (param->rsz_rsc_param[index].h_flip)
> +		/* width * bytesperline - 1 */
> +		offset = (image_width * bytesperline) - 1;
> +	if (param->rsz_rsc_param[index].v_flip)
> +		offset += (image_height - 1) *
> +			param->ext_mem_param[index].rsz_sdr_oft_y;
> +	param->ext_mem_param[index].flip_ofst_y = offset;
> +	if (yuv_420) {
> +		offset = 0;
> +		/* half height for c-plane */
> +		if (param->rsz_rsc_param[index].h_flip)
> +			/* width * bytesperline - 1 */
> +			offset = image_width - 1;
> +		if (param->rsz_rsc_param[index].v_flip)
> +			offset += (((image_height >> 1) - 1) *
> +			param->ext_mem_param[index].
> +			rsz_sdr_oft_c);
> +		param->ext_mem_param[index].flip_ofst_c =
> +			offset;
> +		param->ext_mem_param[index].c_offset =
> +		    param->ext_mem_param[index].
> +		    rsz_sdr_oft_y * image_height;
> +	}
> +
> +	return 0;
> +}
> +
> +static void enable_422_420_conversion(struct ipipe_params *param,
> +				      int index, enum enable_disable_t en)
> +{
> +	/* Enable 422 to 420 conversion */
> +	param->rsz_rsc_param[index].cen = en;
> +	param->rsz_rsc_param[index].yen = en;
> +}
> +
> +static void configure_resizer_out_params(struct ipipe_params *param,
> +					int index,
> +					void *output_spec,
> +					unsigned char partial, unsigned flag)
> +{
> +	if (partial) {
> +		struct rsz_part_output_spec *partial_output =
> +		    (struct rsz_part_output_spec *)output_spec;
> +		if (partial_output->enable) {
> +			param->rsz_en[index] = ENABLE;
> +			param->rsz_rsc_param[index].h_flip =
> +			    partial_output->h_flip;
> +			param->rsz_rsc_param[index].v_flip =
> +			    partial_output->v_flip;
> +			param->rsz_rsc_param[index].v_typ_y =
> +			    partial_output->v_typ_y;
> +			param->rsz_rsc_param[index].v_typ_c =
> +			    partial_output->v_typ_c;
> +			param->rsz_rsc_param[index].v_lpf_int_y =
> +			    partial_output->v_lpf_int_y;
> +			param->rsz_rsc_param[index].v_lpf_int_c =
> +			    partial_output->v_lpf_int_c;
> +			param->rsz_rsc_param[index].h_typ_y =
> +			    partial_output->h_typ_y;
> +			param->rsz_rsc_param[index].h_typ_c =
> +			    partial_output->h_typ_c;
> +			param->rsz_rsc_param[index].h_lpf_int_y =
> +			    partial_output->h_lpf_int_y;
> +			param->rsz_rsc_param[index].h_lpf_int_c =
> +			    partial_output->h_lpf_int_c;
> +			param->rsz_rsc_param[index].dscale_en =
> +			    partial_output->en_down_scale;
> +			param->rsz_rsc_param[index].h_dscale_ave_sz =
> +			    partial_output->h_dscale_ave_sz;
> +			param->rsz_rsc_param[index].v_dscale_ave_sz =
> +			    partial_output->v_dscale_ave_sz;
> +			param->ext_mem_param[index].user_y_ofst =
> +			    (partial_output->user_y_ofst + 31) & ~0x1F;
> +			param->ext_mem_param[index].user_c_ofst =
> +			    (partial_output->user_c_ofst + 31) & ~0x1F;
> +
> +		} else
> +			param->rsz_en[index] = DISABLE;
> +
> +	} else {
> +		struct rsz_output_spec *output =
> +		    (struct rsz_output_spec *)output_spec;
> +		if (output->enable) {
> +			param->rsz_en[index] = ENABLE;
> +			param->rsz_rsc_param[index].o_vsz = output->height - 1;
> +			param->rsz_rsc_param[index].o_hsz = output->width - 1;
> +			param->ext_mem_param[index].rsz_sdr_ptr_s_y =
> +			    output->vst_y;
> +			param->ext_mem_param[index].rsz_sdr_ptr_e_y =
> +			    output->height;
> +			param->ext_mem_param[index].rsz_sdr_ptr_s_c =
> +			    output->vst_c;
> +			param->ext_mem_param[index].rsz_sdr_ptr_e_c =
> +			    output->height;
> +
> +			if (flag) {
> +				/* update common parameters */
> +				param->rsz_rsc_param[index].h_flip =
> +				    output->h_flip;
> +				param->rsz_rsc_param[index].v_flip =
> +				    output->v_flip;
> +				param->rsz_rsc_param[index].v_typ_y =
> +				    output->v_typ_y;
> +				param->rsz_rsc_param[index].v_typ_c =
> +				    output->v_typ_c;
> +				param->rsz_rsc_param[index].v_lpf_int_y =
> +				    output->v_lpf_int_y;
> +				param->rsz_rsc_param[index].v_lpf_int_c =
> +				    output->v_lpf_int_c;
> +				param->rsz_rsc_param[index].h_typ_y =
> +				    output->h_typ_y;
> +				param->rsz_rsc_param[index].h_typ_c =
> +				    output->h_typ_c;
> +				param->rsz_rsc_param[index].h_lpf_int_y =
> +				    output->h_lpf_int_y;
> +				param->rsz_rsc_param[index].h_lpf_int_c =
> +				    output->h_lpf_int_c;
> +				param->rsz_rsc_param[index].dscale_en =
> +				    output->en_down_scale;
> +				param->rsz_rsc_param[index].h_dscale_ave_sz =
> +				    output->h_dscale_ave_sz;
> +				param->rsz_rsc_param[index].v_dscale_ave_sz =
> +				    output->h_dscale_ave_sz;
> +				param->ext_mem_param[index].user_y_ofst =
> +				    (output->user_y_ofst + 31) & ~0x1F;
> +				param->ext_mem_param[index].user_c_ofst =
> +				    (output->user_c_ofst + 31) & ~0x1F;
> +			}
> +		} else
> +			param->rsz_en[index] = DISABLE;
> +	}
> +
> +}
> +
> +/* function :calculate_line_length()
> + *	This function calculates the line length of various image
> + *	planes at the input and output
> + */
> +static void calculate_line_length(enum ipipe_pix_formats pix,
> +				 int width,
> +				 int height, int *line_len, int *line_len_c)
> +{
> +	*line_len = 0;
> +	*line_len_c = 0;
> +
> +	if ((pix == IPIPE_UYVY) || (pix == IPIPE_BAYER))
> +		*line_len = width << 1;
> +	else if (pix == IPIPE_420SP_Y || pix == IPIPE_420SP_C) {
> +		*line_len = width;
> +		*line_len_c = width;
> +	} else {
> +		/* YUV 420 */
> +		/* round width to upper 32 byte boundary */
> +		*line_len = width;
> +		*line_len_c = width;
> +	}
> +	/* adjust the line len to be a multiple of 32 */
> +	*line_len += 31;
> +	*line_len &= ~0x1f;
> +	*line_len_c += 31;
> +	*line_len_c &= ~0x1f;
> +}
> +
> +static inline int rsz_validate_input_image_format(struct device *dev,
> +						  enum ipipe_pix_formats pix,
> +						  int width,
> +						  int height, int *line_len)
> +{
> +	int val;
> +
> +	if (pix != IPIPE_UYVY && pix != IPIPE_420SP_Y &&
> +		pix != IPIPE_420SP_C) {
> +		dev_err(dev,
> +			"rsz_validate_out_pix_formats"
> +			"pix format not supported, %d\n", pix);
> +		return -EINVAL;
> +	}
> +
> +	if (width == 0 || height == 0) {
> +		dev_err(dev, "validate_line_length: invalid "
> +				"width or height\n");
> +		return -EINVAL;
> +	}
> +
> +	if (pix == IPIPE_420SP_C)
> +		calculate_line_length(pix,
> +				      width,
> +				      height,
> +				      &val,
> +				      line_len);
> +	else
> +		calculate_line_length(pix,
> +				      width,
> +				      height,
> +				      line_len,
> +				      &val);
> +
> +	return 0;
> +}
> +
> +static inline int rsz_validate_output_image_format(struct device *dev,
> +						   enum ipipe_pix_formats pix,
> +						   int width,
> +						   int height,
> +						   int *in_line_len,
> +						   int *in_line_len_c)
> +{
> +	if (pix != IPIPE_UYVY && pix != IPIPE_420SP_Y &&
> +		pix != IPIPE_420SP_C && pix != IPIPE_YUV420SP &&
> +		pix != IPIPE_BAYER) {
> +		dev_err(dev,
> +			"rsz_validate_out_pix_formats"
> +			"pix format not supported, %d\n", pix);
> +		return -EINVAL;
> +	}
> +
> +	if (width == 0 || height == 0) {
> +		dev_err(dev, "validate_line_length: invalid"
> +				" width or height\n");
> +		return -EINVAL;
> +	}
> +
> +	calculate_line_length(pix,
> +			      width,
> +			      height, in_line_len, in_line_len_c);
> +	return 0;
> +}
> +
> +static void configure_common_rsz_params(struct device *dev,
> +			struct ipipe_params *param,
> +			struct rsz_single_shot_config *ss_config)
> +{
> +	param->rsz_common.yuv_y_min = ss_config->yuv_y_min;
> +	param->rsz_common.yuv_y_max = ss_config->yuv_y_max;
> +	param->rsz_common.yuv_c_min = ss_config->yuv_c_min;
> +	param->rsz_common.yuv_c_max = ss_config->yuv_c_max;
> +	param->rsz_common.out_chr_pos = ss_config->out_chr_pos;
> +	param->rsz_common.rsz_seq_crv = ss_config->chroma_sample_even;
> +
> +}
> +
> +static int configure_common_rsz_in_params(struct device *dev,
> +					  struct ipipe_params *param,
> +					  int flag, int rsz_chained,
> +					  void *input_spec)
> +{
> +	enum ipipe_pix_formats pix;
> +
> +	if (!flag) {
> +		struct prev_ss_input_spec *in_specs =
> +		    (struct prev_ss_input_spec *)input_spec;
> +		param->rsz_common.vsz = in_specs->image_height - 1;
> +		param->rsz_common.hsz = in_specs->image_width - 1;
> +		pix = in_specs->pix_fmt;
> +	} else {
> +		struct rsz_ss_input_spec *in_specs =
> +		    (struct rsz_ss_input_spec *)input_spec;
> +		if (!rsz_chained) {
> +			param->rsz_common.vps = in_specs->vst;
> +			param->rsz_common.hps = in_specs->hst;
> +		}
> +		param->rsz_common.vsz = in_specs->image_height - 1;
> +		param->rsz_common.hsz = in_specs->image_width - 1;
> +		pix = in_specs->pix_fmt;
> +	}
> +	switch (pix) {
> +	case IPIPE_BAYER_8BIT_PACK:
> +	case IPIPE_BAYER_8BIT_PACK_ALAW:
> +	case IPIPE_BAYER_8BIT_PACK_DPCM:
> +	case IPIPE_BAYER_12BIT_PACK:
> +	case IPIPE_BAYER:
> +		param->rsz_common.src_img_fmt = RSZ_IMG_422;
> +		param->rsz_common.source = IPIPE_DATA;
> +		break;
> +	case IPIPE_UYVY:
> +		param->rsz_common.src_img_fmt = RSZ_IMG_422;
> +		if (rsz_chained)
> +			param->rsz_common.source = IPIPE_DATA;
> +		else
> +			param->rsz_common.source = IPIPEIF_DATA;
> +		param->rsz_common.raw_flip = 0;
> +		break;
> +	case IPIPE_420SP_Y:
> +		param->rsz_common.src_img_fmt = RSZ_IMG_420;
> +		/* Select y */
> +		param->rsz_common.y_c = 0;
> +		param->rsz_common.source = IPIPEIF_DATA;
> +		param->rsz_common.raw_flip = 0;
> +		break;
> +	case IPIPE_420SP_C:
> +		param->rsz_common.src_img_fmt = RSZ_IMG_420;
> +		/* Select y */
> +		param->rsz_common.y_c = 1;
> +		param->rsz_common.source = IPIPEIF_DATA;
> +		param->rsz_common.raw_flip = 0;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int validate_ipipeif_decimation(struct device *dev,
> +				       enum ipipeif_decimation dec_en,
> +				       unsigned char rsz,
> +				       unsigned char frame_div_mode_en,
> +				       int width)
> +{
> +	if (dec_en && frame_div_mode_en) {
> +		dev_err(dev,
> +			"Both dec_en & frame_div_mode_en"
> +			"can not enabled simultaneously\n");
> +		return -EINVAL;
> +	}
> +	if (frame_div_mode_en) {
> +		dev_err(dev, "frame_div_mode mode not supported");
> +		return -EINVAL;
> +	}
> +	if (dec_en) {
> +		if (width <= IPIPE_MAX_INPUT_WIDTH) {
> +			dev_err(dev,
> +				"image width to be more than"
> +				" %d for decimation\n", IPIPE_MAX_INPUT_WIDTH);
> +			return -EINVAL;
> +		}
> +		if ((rsz < IPIPEIF_RSZ_MIN) || (rsz > IPIPEIF_RSZ_MAX)) {
> +			dev_err(dev, "rsz range is %d to %d\n",
> +				IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int configure_resizer_in_ss_mode(struct device *dev,
> +					void *user_config,
> +					int resizer_chained,
> +					struct ipipe_params *param)
> +{
> +	/* resizer in standalone mode. In this mode if serializer
> +	 * is enabled, we need to set config params in the hw.
> +	 */
> +	struct rsz_single_shot_config *ss_config =
> +	    (struct rsz_single_shot_config *)user_config;
> +	int line_len_c;
> +	int line_len;
> +	int ret;
> +
> +	ret = rsz_validate_input_image_format(dev,
> +					      ss_config->input.pix_fmt,
> +					      ss_config->input.image_width,
> +					      ss_config->input.image_height,
> +					      &line_len);
> +
> +	if (ret)
> +		return -EINVAL;
> +
> +	/* shared block */
> +	if ((!ss_config->output1.enable) && (!ss_config->output2.enable)) {
> +		dev_err(dev, "One of the resizer output must be enabled\n");
> +		return -EINVAL;
> +	}
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	if (!ss_config->input.line_length)
> +		param->ipipeif_param.adofs = line_len;
> +	else {
> +		param->ipipeif_param.adofs = ss_config->input.line_length;
> +		param->ipipeif_param.adofs =
> +				(param->ipipeif_param.adofs + 31) & ~0x1f;
> +	}
> +	if (ss_config->output1.enable) {
> +		param->rsz_en[RSZ_A] = ENABLE;
> +		param->rsz_rsc_param[RSZ_A].mode = IPIPEIF_ONE_SHOT;
> +		ret = rsz_validate_output_image_format(dev,
> +					ss_config->output1.pix_fmt,
> +					ss_config->output1.width,
> +					ss_config->output1.height,
> +					&line_len, &line_len_c);
> +		if (ret) {
> +			mutex_unlock(&oper_state.lock);
> +			return ret;
> +		}
> +		param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
> +		param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c;
> +		configure_resizer_out_params(param,
> +						   RSZ_A,
> +						   &ss_config->output1,
> +						   0,
> +						   1);
> +
> +		if (ss_config->output1.pix_fmt == IMP_BAYER)
> +			param->rsz_common.raw_flip = 1;
> +		else
> +			param->rsz_common.raw_flip = 0;
> +
> +		if (ss_config->output1.pix_fmt == IPIPE_YUV420SP)
> +			enable_422_420_conversion(param, RSZ_A, ENABLE);
> +		else
> +			enable_422_420_conversion(param, RSZ_A,
> +							  DISABLE);
> +	}
> +
> +	if (ss_config->output2.enable) {
> +		param->rsz_en[RSZ_A] = ENABLE;
> +		param->rsz_rsc_param[RSZ_B].mode = IPIPEIF_ONE_SHOT;
> +		ret = rsz_validate_output_image_format(dev,
> +					ss_config->output2.pix_fmt,
> +					ss_config->output2.width,
> +					ss_config->output2.height,
> +					&line_len, &line_len_c);
> +		if (ret) {
> +			mutex_unlock(&oper_state.lock);
> +			return ret;
> +		}
> +		param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
> +		param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
> +		configure_resizer_out_params(param,
> +						   RSZ_B,
> +						   &ss_config->output2,
> +						   0,
> +						   1);
> +		if (ss_config->output2.pix_fmt == IPIPE_YUV420SP)
> +			enable_422_420_conversion(param, RSZ_B, ENABLE);
> +		else
> +			enable_422_420_conversion(param,
> +						  RSZ_B,
> +						  DISABLE);
> +	}
> +	configure_common_rsz_params(dev, param, ss_config);
> +	if (resizer_chained) {
> +		oper_state.rsz_chained = 1;
> +		oper_state.rsz_config_state = STATE_CONFIGURED;
> +	} else {
> +		oper_state.rsz_chained = 0;
> +		ret = validate_ipipeif_decimation(dev,
> +						  ss_config->input.dec_en,
> +						  ss_config->input.rsz,
> +						  ss_config->input.
> +						  frame_div_mode_en,
> +						  ss_config->input.
> +						  image_width);
> +		if (ret) {
> +			mutex_unlock(&oper_state.lock);
> +			return ret;
> +		}
> +
> +		if (ipipe_process_pix_fmts(ss_config->input.pix_fmt,
> +				   ss_config->output1.pix_fmt,
> +				   param) < 0) {
> +			dev_err(dev, "error in input or output pix format\n");
> +			mutex_unlock(&oper_state.lock);
> +			return -EINVAL;
> +		}
> +
> +		param->ipipeif_param.source = IPIPEIF_SDRAM_YUV;
> +		param->ipipeif_param.glob_hor_size = ss_config->input.ppln;
> +		param->ipipeif_param.glob_ver_size = ss_config->input.lpfr;
> +		param->ipipeif_param.hnum = ss_config->input.image_width;
> +		param->ipipeif_param.vnum = ss_config->input.image_height;
> +		param->ipipeif_param.var.if_5_1.clk_div =
> +		    ss_config->input.clk_div;
> +		if (ss_config->input.dec_en) {
> +			param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
> +			param->ipipeif_param.rsz = ss_config->input.rsz;
> +			param->ipipeif_param.avg_filter =
> +			    (enum ipipeif_avg_filter)ss_config->input.
> +			    avg_filter_en;
> +			param->ipipe_hsz =
> +			    (((ss_config->input.image_width *
> +			       IPIPEIF_RSZ_CONST) / ss_config->input.rsz) - 1);
> +		}
> +		if (ss_config->input.pix_fmt == IPIPE_420SP_Y ||
> +		  ss_config->input.pix_fmt == IPIPE_420SP_C) {
> +			param->ipipeif_param.var.if_5_1.pack_mode
> +				= IPIPEIF_5_1_PACK_8_BIT;
> +			param->ipipeif_param.var.if_5_1.source1 = IPIPEIF_CCDC;
> +			param->ipipeif_param.var.if_5_1.isif_port.if_type
> +				= V4L2_MBUS_FMT_YUYV8_1X16;
> +			param->ipipeif_param.var.if_5_1.data_shift
> +				= IPIPEIF_5_1_BITS11_0;
> +
> +			param->ipipeif_param.source = IPIPEIF_SDRAM_RAW;
> +
> +
> +		}
> +		if (ss_config->input.pix_fmt == IPIPE_420SP_C)
> +			param->ipipeif_param.var.if_5_1.isif_port.if_type
> +				= V4L2_MBUS_FMT_SBGGR10_1X10;
> +		param->ipipe_hsz = ss_config->input.image_width - 1;
> +		param->ipipe_vsz = ss_config->input.image_height - 1;
> +		param->ipipe_vps = ss_config->input.vst;
> +		param->ipipe_hps = ss_config->input.hst;
> +		param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
> +		configure_common_rsz_in_params(dev, param, 1, resizer_chained,
> +					       &ss_config->input);
> +		if (param->rsz_en[RSZ_A]) {
> +
> +			calculate_resize_ratios(param, RSZ_A);
> +			calculate_sdram_offsets(param, RSZ_A);
> +
> +			/* Overriding resize ratio calculation */
> +			if (ss_config->input.pix_fmt == IPIPE_420SP_C) {
> +				param->rsz_rsc_param[RSZ_A].v_dif =
> +				    (((param->ipipe_vsz + 1) * 2) * 256) /
> +				    (param->rsz_rsc_param[RSZ_A].o_vsz + 1);
> +			}
> +		}
> +
> +		if (param->rsz_en[RSZ_B]) {
> +			calculate_resize_ratios(param, RSZ_B);
> +			calculate_sdram_offsets(param, RSZ_B);
> +
> +			/* Overriding resize ratio calculation */
> +			if (ss_config->input.pix_fmt == IPIPE_420SP_C) {
> +				param->rsz_rsc_param[RSZ_B].v_dif =
> +				    (((param->ipipe_vsz + 1) * 2) * 256) /
> +				    (param->rsz_rsc_param[RSZ_B].o_vsz + 1);
> +			}
> +		}
> +	}
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int configure_resizer_in_cont_mode(struct device *dev,
> +					  void *user_config,
> +					  int resizer_chained,
> +					  struct ipipe_params *param)
> +{
> +	/* Continuous mode. This is a shared config block */
> +	struct rsz_continuous_config *cont_config =
> +	    (struct rsz_continuous_config *)user_config;
> +	int line_len_c;
> +	int line_len;
> +	int ret;
> +
> +	if (!resizer_chained) {
> +		dev_err(dev, "Resizer cannot be configured in standalone"
> +			"for continuous mode\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	if (!cont_config->output1.enable) {
> +		dev_err(dev, "enable resizer - 0\n");
> +		mutex_unlock(&oper_state.lock);
> +		return -EINVAL;
> +	}
> +	param->rsz_en[RSZ_A] = ENABLE;
> +	param->rsz_rsc_param[RSZ_A].mode = IPIPEIF_CONTINUOUS;
> +	configure_resizer_out_params(param,
> +				     RSZ_A,
> +				     &cont_config->output1,
> +				     1,
> +				     0);
> +	param->rsz_en[RSZ_B] = DISABLE;
> +
> +	if (cont_config->output2.enable) {
> +		param->rsz_rsc_param[RSZ_B].mode = IPIPEIF_CONTINUOUS;
> +		ret = rsz_validate_output_image_format(dev,
> +						       cont_config->output2.
> +						       pix_fmt,
> +						       cont_config->output2.
> +						       width,
> +						       cont_config->output2.
> +						       height,
> +						       &line_len,
> +						       &line_len_c);
> +		if (ret) {
> +			mutex_unlock(&oper_state.lock);
> +			return ret;
> +		}
> +		param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
> +		param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
> +		configure_resizer_out_params(param,
> +					     RSZ_B,
> +					     &cont_config->output2,
> +					     0,
> +					     1);
> +		if (cont_config->output2.pix_fmt == IPIPE_YUV420SP)
> +			enable_422_420_conversion(param,
> +						  RSZ_B, ENABLE);
> +		else
> +			enable_422_420_conversion(param,
> +						  RSZ_B, DISABLE);
> +	}
> +	oper_state.rsz_chained = 1;
> +	oper_state.rsz_config_state = STATE_CONFIGURED;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +static int ipipe_set_resize_config(struct device *dev,
> +				   int resizer_chained,
> +				   void *user_config, void *config)
> +{
> +	struct ipipe_params *param = (struct ipipe_params *)config;
> +	int ret;
> +
> +	dev_dbg(dev, "ipipe_set_resize_config, resizer_chained = %d\n",
> +		resizer_chained);
> +	if ((ISNULL(user_config)) || (ISNULL(config))) {
> +		dev_err(dev, "Invalid user_config or config ptr\n");
> +		return -EINVAL;
> +	}
> +
> +	memcpy((void *)config,
> +	       (void *)&dm365_ipipe_defs,
> +	       sizeof(struct ipipe_params));
> +
> +	if (oper_mode != IMP_MODE_SINGLE_SHOT)
> +		return configure_resizer_in_cont_mode(dev,
> +						      user_config,
> +						      resizer_chained,
> +						      param);
> +
> +	ret = configure_resizer_in_ss_mode(dev,
> +					    user_config,
> +					    resizer_chained,
> +					    param);
> +	if (!ret && (!en_serializer && !resizer_chained))
> +		ret = ipipe_hw_setup(config);
> +
> +	return ret;
> +}
> +
> +static void configure_resize_passthru(struct ipipe_params *param, int bypass)
> +{
> +	param->rsz_rsc_param[RSZ_A].cen = DISABLE;
> +	param->rsz_rsc_param[RSZ_A].yen = DISABLE;
> +	param->rsz_rsc_param[RSZ_A].v_phs_y = 0;
> +	param->rsz_rsc_param[RSZ_A].v_phs_c = 0;
> +	param->rsz_rsc_param[RSZ_A].v_dif = 256;
> +	param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0;
> +	param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0;
> +	param->rsz_rsc_param[RSZ_A].h_phs = 0;
> +	param->rsz_rsc_param[RSZ_A].h_dif = 256;
> +	param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0;
> +	param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0;
> +	param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE;
> +	param->rsz2rgb[RSZ_A].rgb_en = DISABLE;
> +	param->rsz_en[RSZ_A] = ENABLE;
> +	param->rsz_en[RSZ_B] = DISABLE;
> +	if (bypass) {
> +		param->rsz_rsc_param[RSZ_A].i_vps = 0;
> +		param->rsz_rsc_param[RSZ_A].i_hps = 0;
> +		/* Raw Bypass */
> +		param->rsz_common.passthrough = IPIPE_BYPASS_ON;
> +	}
> +}
> +
> +static inline int prev_validate_output_image_format(struct device *dev,
> +					enum ipipe_pix_formats pix,
> +					int *line_len,
> +					int in_width, int in_height)
> +{
> +	if (pix != IPIPE_UYVY && pix != IPIPE_BAYER) {
> +		dev_err(dev,
> +			"prev_validate_output_image_format"
> +			"pix format not supported, %d\n", pix);
> +		return -EINVAL;
> +	}
> +
> +	if ((in_width == 0) || (in_height == 0)) {
> +		dev_err(dev,
> +			"prev_validate_output_image_format:"
> +			" invalid width or height\n");
> +		return -EINVAL;
> +	}
> +
> +	*line_len = in_width * 2;
> +
> +	/* Adjust line length to be a multiple of 32 */
> +	*line_len += 31;
> +	*line_len &= ~0x1f;
> +
> +	return 0;
> +}
> +
> +static inline int validate_preview_input_spec(struct device *dev,
> +					      enum ipipe_pix_formats pix,
> +					      int width,
> +					      int height, int *line_len)
> +{
> +	if (pix != IPIPE_UYVY && pix != IPIPE_BAYER &&
> +	  pix != IPIPE_BAYER_8BIT_PACK && pix != IPIPE_BAYER_8BIT_PACK_ALAW &&
> +	  pix != IPIPE_BAYER_8BIT_PACK_DPCM &&
> +	  pix != IPIPE_BAYER_12BIT_PACK) {
> +		dev_err(dev,
> +			"validate_preview_input_spec:"
> +			"pix format not supported, %d\n", pix);
> +		return -EINVAL;
> +	}
> +	if (width == 0 || height == 0) {
> +		dev_err(dev,
> +			"rsz_validate_out_image_formats: "
> +			"invalid width or height\n");
> +		return -EINVAL;
> +	}
> +
> +	if (pix == IPIPE_UYVY || pix == IPIPE_BAYER)
> +		*line_len = width * 2;
> +	else if (pix == IPIPE_BAYER_8BIT_PACK ||
> +		 pix == IPIPE_BAYER_8BIT_PACK_ALAW ||
> +		 pix == IPIPE_BAYER_8BIT_PACK_DPCM)
> +		*line_len = width;
> +	else
> +		/* 12 bit */
> +		*line_len = width + (width >> 1);
> +	/* Adjust line length to be a multiple of 32 */
> +	*line_len += 31;
> +	*line_len &= ~0x1f;
> +
> +	return 0;
> +}
> +
> +static int configure_previewer_in_cont_mode(struct device *dev,
> +					    void *user_config,
> +					    struct ipipe_params *param)
> +{
> +	struct prev_continuous_config *cont_config =
> +	    (struct prev_continuous_config *)user_config;
> +	int ret;
> +
> +	if (cont_config->input.en_df_sub) {
> +		dev_err(dev, "DF suV4L2_MBUS_FMT_SBGGR10_1X10btraction "
> +				  "is not supported\n");
> +		return -EINVAL;
> +	}
> +	if (cont_config->input.dec_en && ((cont_config->input.rsz <
> +		IPIPEIF_RSZ_MIN) || (cont_config->input.rsz >
> +		IPIPEIF_RSZ_MAX))) {
> +		dev_err(dev, "rsz range is %d to %d\n",
> +			IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
> +		return -EINVAL;
> +	}
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	param->rsz_common.passthrough = cont_config->bypass;
> +	param->ipipeif_param.source = IPIPEIF_CCDC;
> +	param->ipipeif_param.clock_select = IPIPEIF_PIXCEL_CLK;
> +	param->ipipeif_param.mode = IPIPEIF_CONTINUOUS;
> +	if (cont_config->input.dec_en) {
> +		param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
> +		param->ipipeif_param.rsz = cont_config->input.rsz;
> +		param->ipipeif_param.avg_filter =
> +		    (enum ipipeif_avg_filter)cont_config->input.avg_filter_en;
> +	}
> +	/* IPIPE mode */
> +	param->ipipe_mode = IPIPEIF_CONTINUOUS;
> +	param->ipipe_colpat_olop = cont_config->input.colp_olop;
> +	param->ipipe_colpat_olep = cont_config->input.colp_olep;
> +	param->ipipe_colpat_elop = cont_config->input.colp_elop;
> +	param->ipipe_colpat_elep = cont_config->input.colp_elep;
> +	param->ipipeif_param.gain = cont_config->input.gain;
> +	param->ipipeif_param.var.if_5_1.clip = cont_config->input.clip;
> +	param->ipipeif_param.var.if_5_1.dpc = cont_config->input.dpc;
> +	param->ipipeif_param.var.if_5_1.align_sync =
> +	    cont_config->input.align_sync;
> +	param->ipipeif_param.var.if_5_1.rsz_start =
> +	    cont_config->input.rsz_start;
> +	if (!oper_state.rsz_chained) {
> +		param->rsz_rsc_param[0].mode = IPIPEIF_CONTINUOUS;
> +		/* setup bypass resizer */
> +		configure_resize_passthru(param, 0);
> +	}
> +	if (cont_config->bypass)
> +		configure_resize_passthru(param, 1);
> +	oper_state.prev_config_state = STATE_CONFIGURED;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int configure_previewer_in_ss_mode(struct device *dev,
> +					  void *user_config,
> +					  struct ipipe_params *param)
> +{
> +	struct prev_single_shot_config *ss_config =
> +	    (struct prev_single_shot_config *)user_config;
> +	int line_len;
> +	int ret;
> +
> +	ret = validate_preview_input_spec(dev,
> +					  ss_config->input.pix_fmt,
> +					  ss_config->input.image_width,
> +					  ss_config->input.image_height,
> +					  &line_len);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +
> +	if (!ss_config->input.line_length)
> +		param->ipipeif_param.adofs = line_len;
> +	else {
> +		param->ipipeif_param.adofs = ss_config->input.line_length;
> +		param->ipipeif_param.adofs =
> +				(param->ipipeif_param.adofs + 31) & ~0x1f;
> +	}
> +	if (ss_config->input.dec_en && ss_config->input.frame_div_mode_en) {
> +		dev_err(dev,
> +			"Both dec_en & frame_div_mode_en"
> +			"can not enabled simultaneously\n");
> +		mutex_unlock(&oper_state.lock);
> +		return -EINVAL;
> +	}
> +
> +	ret = validate_ipipeif_decimation(dev,
> +					  ss_config->input.dec_en,
> +					  ss_config->input.rsz,
> +					  ss_config->input.frame_div_mode_en,
> +					  ss_config->input.image_width);
> +	if (ret) {
> +		mutex_unlock(&oper_state.lock);
> +		return -EINVAL;
> +	}
> +
> +	if (!oper_state.rsz_chained) {
> +		ret = prev_validate_output_image_format(dev,
> +							ss_config->output.
> +							pix_fmt, &line_len,
> +							ss_config->input.
> +							image_width,
> +							ss_config->input.
> +							image_height);
> +		if (ret) {
> +			mutex_unlock(&oper_state.lock);
> +			return -EINVAL;
> +		}
> +		param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
> +		if (ss_config->input.frame_div_mode_en)
> +			ret = update_preview_f_div_params(dev,
> +					ss_config->input.
> +					image_width,
> +					ss_config->input.
> +					image_width,
> +					&param->
> +					rsz_rsc_param[RSZ_A]);
> +		if (ret) {
> +			mutex_unlock(&oper_state.lock);
> +			return -EINVAL;
> +		}
> +	} else {
> +		if (ss_config->input.frame_div_mode_en &&
> +		    param->rsz_en[RSZ_A]) {
> +			if (!param->rsz_rsc_param[RSZ_A].dscale_en)
> +				ret = calculate_normal_f_div_param(
> +							dev,
> +							ss_config->input.
> +							  image_width,
> +							param->rsz_rsc_param
> +							  [RSZ_A].
> +							  o_vsz + 1,
> +							&param->rsz_rsc_param
> +							  [RSZ_A]);
> +			else
> +				ret = calculate_down_scale_f_div_param(
> +							dev,
> +							ss_config->
> +							input.image_width,
> +							param->rsz_rsc_param
> +							  [RSZ_A].o_vsz + 1,
> +							&param->rsz_rsc_param
> +							  [RSZ_A]);
> +			if (ret) {
> +				mutex_unlock(&oper_state.lock);
> +				return -EINVAL;
> +			}
> +		}
> +		if (ss_config->input.frame_div_mode_en &&
> +		    param->rsz_en[RSZ_B]) {
> +			if (!param->rsz_rsc_param[RSZ_B].dscale_en)
> +				ret = calculate_normal_f_div_param(
> +							dev,
> +							ss_config->input.
> +							   image_width,
> +							param->rsz_rsc_param
> +							   [RSZ_B].o_vsz + 1,
> +							&param->rsz_rsc_param
> +							   [RSZ_B]);
> +			else
> +				ret = calculate_down_scale_f_div_param(
> +							dev,
> +							ss_config->input.
> +							   image_width,
> +							param->rsz_rsc_param
> +							   [RSZ_B].o_vsz + 1,
> +							&param->rsz_rsc_param
> +							   [RSZ_B]);
> +			if (ret) {
> +				mutex_unlock(&oper_state.lock);
> +				return -EINVAL;
> +			}
> +		}

Are there differences between the two above ifs other than the resizer
number? I don't think so and I don't think this is the only place.

> +	}
> +	if (ipipe_process_pix_fmts(ss_config->input.pix_fmt,
> +				   ss_config->output.pix_fmt,
> +				   param) < 0) {
> +		dev_err(dev, "error in input or output pix format\n");
> +		mutex_unlock(&oper_state.lock);
> +		return -EINVAL;
> +	}
> +	param->ipipeif_param.hnum = ss_config->input.image_width;
> +	param->ipipeif_param.vnum = ss_config->input.image_height;
> +	param->ipipeif_param.glob_hor_size = ss_config->input.ppln;
> +	param->ipipeif_param.glob_ver_size = ss_config->input.lpfr;
> +	param->ipipeif_param.var.if_5_1.clk_div = ss_config->input.clk_div;
> +	param->ipipeif_param.var.if_5_1.pix_order = ss_config->input.pix_order;
> +	param->ipipeif_param.var.if_5_1.align_sync =
> +	    ss_config->input.align_sync;
> +	param->ipipeif_param.var.if_5_1.rsz_start = ss_config->input.rsz_start;
> +	if (param->ipipeif_param.var.if_5_1.dpcm.en) {
> +		param->ipipeif_param.var.if_5_1.dpcm.pred =
> +		    ss_config->input.pred;
> +		param->ipipeif_param.var.if_5_1.dpcm.type =
> +		IPIPEIF_DPCM_8BIT_12BIT;
> +	}
> +	param->ipipeif_param.var.if_5_1.data_shift =
> +	    ss_config->input.data_shift;
> +
> +	param->ipipe_hsz = ss_config->input.image_width - 1;
> +	if (ss_config->input.dec_en) {
> +		if ((ss_config->input.rsz < IPIPEIF_RSZ_MIN) ||
> +		    (ss_config->input.rsz > IPIPEIF_RSZ_MAX)) {
> +			dev_err(dev, "rsz range is %d to %d\n",
> +				IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
> +			mutex_unlock(&oper_state.lock);
> +			return -EINVAL;
> +		}
> +		param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
> +		param->ipipeif_param.rsz = ss_config->input.rsz;
> +		param->ipipeif_param.avg_filter =
> +		    (enum ipipeif_avg_filter)ss_config->input.avg_filter_en;
> +		param->ipipe_hsz =
> +		    (((ss_config->input.image_width * IPIPEIF_RSZ_CONST) /
> +		      ss_config->input.rsz) - 1);
> +	}
> +	param->ipipeif_param.gain = ss_config->input.gain;
> +	param->ipipeif_param.var.if_5_1.clip = ss_config->input.clip;
> +	param->ipipeif_param.var.if_5_1.dpc = ss_config->input.dpc;
> +	param->ipipe_colpat_olop = ss_config->input.colp_olop;
> +	param->ipipe_colpat_olep = ss_config->input.colp_olep;
> +	param->ipipe_colpat_elop = ss_config->input.colp_elop;
> +	param->ipipe_colpat_elep = ss_config->input.colp_elep;
> +	param->ipipe_vps = ss_config->input.vst;
> +	param->ipipe_hps = ss_config->input.hst;
> +	param->ipipe_vsz = ss_config->input.image_height - 1;
> +	if (ss_config->input.pix_fmt == IPIPE_UYVY)
> +		param->ipipeif_param.source = IPIPEIF_SDRAM_YUV;
> +	else
> +		param->ipipeif_param.source = IPIPEIF_SDRAM_RAW;
> +
> +	configure_common_rsz_in_params(dev, param, 1, oper_state.rsz_chained,
> +					       &ss_config->input);
> +
> +	param->rsz_common.passthrough = ss_config->bypass;
> +	/* update the resize parameters */
> +	if (ss_config->bypass == IPIPE_BYPASS_ON ||
> +	    param->ipipe_dpaths_fmt == IPIPE_RAW2RAW)
> +		/* Bypass resizer */
> +		configure_resize_passthru(param, 1);
> +	else {
> +		if (oper_state.rsz_chained) {
> +			if (param->rsz_en[RSZ_A]) {
> +				calculate_resize_ratios(param, RSZ_A);
> +				calculate_sdram_offsets(param, RSZ_A);
> +			}
> +			if (param->rsz_en[RSZ_B]) {
> +				calculate_resize_ratios(param, RSZ_B);
> +				calculate_sdram_offsets(param, RSZ_B);
> +			}
> +		} else {
> +			struct rsz_output_spec *output_specs =
> +				kmalloc(sizeof(struct rsz_output_spec),
> +					GFP_KERNEL);
> +			if (ISNULL(output_specs)) {
> +				dev_err(dev, "Memory Alloc failure\n");
> +				mutex_unlock(&oper_state.lock);
> +				return -EINVAL;
> +			}
> +				/* Using resizer as pass through */
> +			configure_resize_passthru(param, 0);
> +			memset((void *)output_specs, 0,
> +				sizeof(struct rsz_output_spec));
> +			output_specs->enable = 1;
> +			output_specs->pix_fmt = IPIPE_UYVY;
> +			output_specs->width = ss_config->input.image_width;
> +			output_specs->height = ss_config->input.image_height;
> +			output_specs->vst_y = ss_config->input.vst;
> +			configure_resizer_out_params(param, RSZ_A,
> +				output_specs, 0, 0);
> +			calculate_sdram_offsets(param, RSZ_A);
> +			kfree(output_specs);
> +		}
> +	}
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int ipipe_reconfig_resizer(struct device *dev,
> +				struct rsz_reconfig *reconfig,
> +				void *config)
> +{
> +	struct ipipe_params *param = (struct ipipe_params *)config;
> +
> +	if (ISNULL(reconfig)) {
> +		dev_err(dev, "Null User ptr received for reconfig");
> +		return -EINVAL;
> +	}
> +
> +	if ((reconfig->pix_format != IMP_420SP_Y) &&
> +		(reconfig->pix_format != IMP_420SP_C)) {
> +		dev_err(dev, "reconfig - pixel format incorrect");
> +		return -EINVAL;
> +	}
> +	if (param->rsz_common.src_img_fmt != RSZ_IMG_420) {
> +		dev_err(dev, "reconfig - source format originally"
> +				"configured is not YUV420SP\n");
> +		return -EINVAL;
> +	}
> +	if ((param->rsz_common.y_c) && (reconfig->pix_format == IMP_420SP_C)) {
> +		dev_err(dev, "reconfig - channel is already configured"
> +				"for YUV420SP - C data\n");
> +		return -EINVAL;
> +	}
> +	if ((!param->rsz_common.y_c) &&
> +		(reconfig->pix_format == IMP_420SP_Y)) {
> +		dev_err(dev, "reconfig - channel is already configured"
> +				"for YUV420SP - Y data\n");
> +		return -EINVAL;
> +	}
> +	if (reconfig->pix_format == IMP_420SP_Y)
> +		param->rsz_common.y_c = 0;
> +	else
> +		param->rsz_common.y_c = 1;
> +	if (!en_serializer)
> +		rsz_set_in_pix_format(param->rsz_common.y_c);
> +
> +	return 0;
> +}
> +
> +static int ipipe_set_preview_config(struct device *dev,
> +				    void *user_config, void *config)
> +{
> +	struct ipipe_params *param = (struct ipipe_params *)config;
> +	int ret;
> +
> +	dev_err(dev, "ipipe_set_preview_config\n");
> +
> +	if ((ISNULL(user_config)) || (ISNULL(config))) {
> +		dev_err(dev, "Invalid user_config or config ptr\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!oper_state.rsz_chained) {
> +		/* For chained resizer, defaults are set by resizer */
> +		memcpy((void *)config,
> +		       (void *)&dm365_ipipe_defs,
> +		       sizeof(struct ipipe_params));
> +	}
> +
> +	/* continuous mode */
> +	if (oper_mode == IMP_MODE_CONTINUOUS)
> +		return configure_previewer_in_cont_mode(dev, user_config,
> +							param);
> +
> +	/* shared block */
> +	/* previewer in standalone mode. In this mode if serializer
> +	 * is enabled, we need to set config params for hw.
> +	 */
> +	ret = configure_previewer_in_ss_mode(dev, user_config, param);
> +
> +	if ((!ret) && !en_serializer)
> +		ret = ipipe_hw_setup(config);
> +
> +	return ret;
> +}
> +
> +static int ipipe_set_input_win(struct imp_window *win)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	if (param->ipipeif_param.decimation) {
> +		param->ipipe_hsz =
> +		    ((win->width * IPIPEIF_RSZ_CONST) /
> +		     param->ipipeif_param.rsz) - 1;
> +	} else
> +		param->ipipe_hsz = win->width - 1;
> +	if (!oper_state.frame_format) {
> +		param->ipipe_vsz = (win->height >> 1) - 1;
> +		param->ipipe_vps = (win->vst >> 1);
> +	} else {
> +		param->ipipe_vsz = win->height - 1;
> +		param->ipipe_vps = win->vst;
> +	}
> +	param->ipipe_hps = win->hst;
> +	param->rsz_common.vsz = param->ipipe_vsz;
> +	param->rsz_common.hsz = param->ipipe_hsz;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +static int ipipe_get_input_win(struct imp_window *win)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	if (param->ipipeif_param.decimation)
> +		win->width =
> +		    (((param->ipipe_hsz + 1) * param->ipipeif_param.rsz) >> 4);
> +	else
> +		win->width = param->ipipe_hsz + 1;
> +	if (!oper_state.frame_format) {
> +		win->height = (param->ipipe_vsz + 1) << 1;
> +		win->vst = (param->ipipe_vps << 1);
> +	} else {
> +		win->height = param->ipipe_vsz + 1;
> +		win->vst = param->ipipe_vps;
> +	}
> +	win->hst = param->ipipe_hps;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int ipipe_set_in_pixel_format(enum imp_pix_formats pix_fmt)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	oper_state.in_pixel_format = pix_fmt;
> +	param->rsz_common.src_img_fmt = RSZ_IMG_422;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int ipipe_set_out_pixel_format(enum imp_pix_formats pix_fmt)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +	int err;
> +
> +	/* if image is RAW, preserve raw image format while flipping.
> +	 * otherwise preserve, preserve ycbcr format while flipping
> +	 */
> +	if (pix_fmt == IMP_BAYER)
> +		param->rsz_common.raw_flip = 1;
> +	else
> +		param->rsz_common.raw_flip = 0;
> +
> +	err = mutex_lock_interruptible(&oper_state.lock);
> +	if (err)
> +		return err;
> +	oper_state.out_pixel_format = pix_fmt;
> +	err = ipipe_process_pix_fmts(oper_state.in_pixel_format,
> +				     oper_state.out_pixel_format,
> +				     param);
> +
> +	mutex_unlock(&oper_state.lock);
> +
> +	return err;
> +}
> +
> +static int ipipe_set_buftype(unsigned char buf_type)
> +{
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	oper_state.buffer_type = buf_type;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int ipipe_set_frame_format(unsigned char frm_fmt)
> +{
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	oper_state.frame_format = frm_fmt;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static int ipipe_set_output_win(struct imp_window *win)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +	struct rsz_output_spec output_specs;
> +	int line_len_c;
> +	int line_len;
> +	int ret = -EINVAL;
> +
> +	if (!param->rsz_en[0]) {
> +		printk(KERN_ERR "resizer output1 not enabled\n");
> +		return ret;
> +	}
> +	output_specs.enable = 1;
> +	output_specs.width = win->width;
> +	/* Always set output height same as in height
> +	   for de-interlacing
> +	 */
> +	output_specs.height = win->height;
> +	output_specs.vst_y = win->vst;
> +	if (oper_state.out_pixel_format == IPIPE_YUV420SP)
> +		output_specs.vst_c = win->vst;
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	configure_resizer_out_params(param, RSZ_A, &output_specs, 0, 0);
> +	calculate_line_length(oper_state.out_pixel_format,
> +				     param->rsz_rsc_param[0].o_hsz + 1,
> +				     param->rsz_rsc_param[0].o_vsz + 1,
> +				     &line_len,
> +				     &line_len_c);
> +	param->ext_mem_param[0].rsz_sdr_oft_y = line_len;
> +	param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c;
> +	calculate_resize_ratios(param, RSZ_A);
> +	if (param->rsz_en[RSZ_B])
> +		calculate_resize_ratios(param, RSZ_B);
> +	if (oper_state.out_pixel_format == IPIPE_YUV420SP)
> +		enable_422_420_conversion(param, RSZ_A, ENABLE);
> +	else
> +		enable_422_420_conversion(param, RSZ_A, DISABLE);
> +
> +	ret = calculate_sdram_offsets(param, RSZ_A);
> +	if (param->rsz_en[RSZ_B])
> +		ret = calculate_sdram_offsets(param, RSZ_B);
> +
> +	if (ret)
> +		printk(KERN_ERR "error in calculating sdram offsets\n");
> +	mutex_unlock(&oper_state.lock);
> +
> +	return ret;
> +}
> +static int ipipe_get_output_state(unsigned char out_sel)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +
> +	if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
> +		return 0;
> +
> +	return param->rsz_en[out_sel];
> +}
> +
> +/* This should be called only after setting the output
> + * window params. This also assumes the corresponding
> + * output is configured prior to calling this.
> + */
> +static int ipipe_get_line_length(unsigned char out_sel)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +
> +	if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
> +		return -EINVAL;
> +	/* assume output is always UYVY. Change this if we
> +	 * support RGB
> +	 */
> +	if (!param->rsz_en[out_sel])
> +		return -EINVAL;
> +
> +	return param->ext_mem_param[out_sel].rsz_sdr_oft_y;
> +}
> +
> +static int ipipe_get_image_height(unsigned char out_sel)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +
> +	if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
> +		return -EINVAL;
> +	if (!param->rsz_en[out_sel])
> +		return -EINVAL;
> +
> +	return param->rsz_rsc_param[out_sel].o_vsz + 1;
> +}
> +
> +/* Assume valid param ptr */
> +static int ipipe_set_hw_if_param(struct vpfe_hw_if_param *if_param)
> +{
> +	struct ipipe_params *param = oper_state.shared_config_param;
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&oper_state.lock);
> +	if (ret)
> +		return ret;
> +	param->ipipeif_param.var.if_5_1.isif_port = *if_param;
> +	mutex_unlock(&oper_state.lock);
> +
> +	return 0;
> +}
> +
> +static struct imp_hw_interface dm365_ipipe_interface = {
> +	.name = "DM365 IPIPE",
> +	.owner = THIS_MODULE,
> +	.prev_enum_modules = prev_enum_preview_cap,
> +	.set_oper_mode = ipipe_set_oper_mode,
> +	.reset_oper_mode = ipipe_reset_oper_mode,
> +	.get_oper_mode = prev_get_oper_mode,
> +	.get_hw_state = ipipe_get_oper_state,
> +	.set_hw_state = ipipe_set_oper_state,
> +	.resizer_chain = ipipe_rsz_chain_state,
> +	.lock_chain = ipipe_lock_chain,
> +	.unlock_chain = ipipe_unlock_chain,
> +	.serialize = ipipe_serialize,
> +	.alloc_config_block = ipipe_alloc_config_block,
> +	.dealloc_config_block = ipipe_dealloc_config_block,
> +	.alloc_user_config_block = ipipe_alloc_user_config_block,
> +	.dealloc_config_block = ipipe_dealloc_user_config_block,
> +	.set_user_config_defaults = ipipe_set_user_config_defaults,
> +	.set_preview_config = ipipe_set_preview_config,
> +	.set_resizer_config = ipipe_set_resize_config,
> +	.reconfig_resizer = ipipe_reconfig_resizer,
> +	.update_inbuf_address = ipipe_set_ipipe_if_address,
> +	.update_outbuf1_address = ipipe_update_outbuf1_address,
> +	.update_outbuf2_address = ipipe_update_outbuf2_address,
> +	.enable = ipipe_enable,
> +	.enable_resize = rsz_src_enable,
> +	.hw_setup = ipipe_do_hw_setup,
> +	.get_resizer_config_state = ipipe_get_rsz_config_state,
> +	.get_previewer_config_state = ipipe_get_prev_config_state,
> +	.set_input_win = ipipe_set_input_win,
> +	.get_input_win = ipipe_get_input_win,
> +	.set_hw_if_param = ipipe_set_hw_if_param,
> +	.set_in_pixel_format = ipipe_set_in_pixel_format,
> +	.set_out_pixel_format = ipipe_set_out_pixel_format,
> +	.set_buftype = ipipe_set_buftype,
> +	.set_frame_format = ipipe_set_frame_format,
> +	.set_output_win = ipipe_set_output_win,
> +	.get_output_state = ipipe_get_output_state,
> +	.get_line_length = ipipe_get_line_length,
> +	.get_image_height = ipipe_get_image_height,
> +	.get_image_height = ipipe_get_image_height,
> +	.get_max_output_width = ipipe_get_max_output_width,
> +	.get_max_output_height = ipipe_get_max_output_height,
> +	.enum_pix = ipipe_enum_pix,
> +};
> +
> +struct imp_hw_interface *imp_get_hw_if(void)
> +{
> +	return &dm365_ipipe_interface;
> +}
> +
> +void enable_serializer(int val)
> +{
> +	en_serializer = val;
> +}
> +
> +int ipipe_init(void)
> +{
> +	oper_state.shared_config_param =
> +	    kmalloc(sizeof(struct ipipe_params), GFP_KERNEL);
> +
> +	if (ISNULL(oper_state.shared_config_param)) {
> +		printk(KERN_ERR
> +		       "dm365_ipipe_init: failed to allocate memory\n");
> +		return -ENOMEM;
> +	}
> +	memcpy(&dm365_ipipe_defs.ipipeif_param.var.if_5_1,
> +		&ipipeif_5_1_defaults,
> +		sizeof(struct ipipeif_5_1));
> +	lutdpc.table = ipipe_lutdpc_table;
> +	lut_3d.table = ipipe_3d_lut_table;
> +	gbce.table = ipipe_gbce_table;
> +	gamma.table_r = ipipe_gamma_table_r;
> +	gamma.table_b = ipipe_gamma_table_b;
> +	gamma.table_g = ipipe_gamma_table_g;
> +	yee.table = ipipe_yee_table;
> +	mutex_init(&oper_state.lock);
> +	oper_state.state = CHANNEL_FREE;
> +	oper_state.prev_config_state = STATE_NOT_CONFIGURED;
> +	oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
> +	oper_state.frame_format = 1;
> +	oper_state.in_pixel_format = IMP_BAYER;
> +	oper_state.out_pixel_format = IMP_UYVY;
> +
> +	return 0;
> +}
> +
> +void ipipe_cleanup(void)
> +{
> +	kfree(oper_state.shared_config_param);
> +}
> diff --git a/drivers/media/video/davinci/dm365_ipipe.h b/drivers/media/video/davinci/dm365_ipipe.h
> new file mode 100644
> index 0000000..9b5dfae
> --- /dev/null
> +++ b/drivers/media/video/davinci/dm365_ipipe.h
> @@ -0,0 +1,300 @@
> +/*
> +* Copyright (C) 2011 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
> +*
> +* Feature description
> +* ===================
> +*
> +* VPFE hardware setup
> +*
> +* case 1: Capture to SDRAM with out IPIPE
> +* ****************************************
> +*
> +*            parallel
> +*                port
> +*
> +* Image sensor/       ________
> +* Yuv decoder    ---->| CCDC |--> SDRAM
> +*                     |______|
> +*
> +* case 2: Capture to SDRAM with IPIPE Preview modules in Continuous
> +*          (On the Fly mode)
> +*
> +* Image sensor/       ________    ____________________
> +* Yuv decoder    ---->| CCDC |--> | Previewer modules |--> SDRAM
> +*                     |______|    |___________________|
> +*
> +* case 3: Capture to SDRAM with IPIPE Preview modules  & Resizer
> +*         in continuous (On the Fly mode)
> +*
> +* Image sensor/       ________    _____________   ___________
> +* Yuv decoder    ---->| CCDC |--> | Previewer  |->| Resizer  |-> SDRAM
> +*                     |______|    |____________|  |__________|
> +*
> +* case 4: Capture to SDRAM with IPIPE Resizer
> +*         in continuous (On the Fly mode)
> +*
> +* Image sensor/       ________    ___________
> +* Yuv decoder    ---->| CCDC |--> | Resizer  |-> SDRAM
> +*                     |______|    |__________|
> +*
> +* case 5: Read from SDRAM and do preview and/or Resize
> +*         in Single shot mode
> +*
> +*                   _____________   ___________
> +*    SDRAM   ----> | Previewer  |->| Resizer  |-> SDRAM
> +*                  |____________|  |__________|
> +*
> +*
> +* Previewer allows fine tuning of the input image using different
> +* tuning modules in IPIPE. Some examples :- Noise filter, Defect
> +* pixel correction etc. It essentially operate on Bayer Raw data
> +* or YUV raw data. To do image tuning, application call,
> +* PREV_QUERY_CAP, and then call PREV_SET_PARAM to set parameter
> +* for a module.
> +*
> +*
> +* Resizer allows upscaling or downscaling a image to a desired
> +* resolution. There are 2 resizer modules. both operating on the
> +* same input image, but can have different output resolution.
> +*/
> +
> +#ifndef DM365_IPIPE_H
> +#define DM365_IPIPE_H
> +
> +#ifdef __KERNEL__
> +#include "imp_common.h"
> +#include "dm3xx_ipipeif.h"
> +#include <linux/davinci_vpfe.h>
> +
> +/* Used for driver storage */
> +struct ipipe_otfdpc_2_0 {
> +	/* 0 - disable, 1 - enable */
> +	unsigned char en;
> +	/* defect detection method */
> +	enum ipipe_otfdpc_det_meth det_method;
> +	/* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
> +	 * used
> +	 */
> +	enum ipipe_otfdpc_alg alg;
> +	struct prev_otfdpc_2_0 otfdpc_2_0;
> +};
> +
> +struct ipipe_otfdpc_3_0 {
> +	/* 0 - disable, 1 - enable */
> +	unsigned char en;
> +	/* defect detection method */
> +	enum ipipe_otfdpc_det_meth det_method;
> +	/* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
> +	 * used
> +	 */
> +	enum ipipe_otfdpc_alg alg;
> +	struct prev_otfdpc_3_0 otfdpc_3_0;
> +};
> +
> +enum enable_disable_t {
> +	DISABLE,
> +	ENABLE
> +};

Does that bring value over using e.g. boolean?

> +#define CEIL(a, b)	(((a) + (b-1)) / (b))
> +#define IPIPE_MAX_PASSES	2
> +
> +struct f_div_pass {
> +	unsigned int o_hsz;
> +	unsigned int i_hps;
> +	unsigned int h_phs;
> +	unsigned int src_hps;
> +	unsigned int src_hsz;
> +};
> +
> +struct f_div_param {
> +	unsigned char en;
> +	unsigned int num_passes;
> +	struct f_div_pass pass[IPIPE_MAX_PASSES];
> +};
> +
> +/* Resizer Rescale Parameters*/
> +struct ipipe_rsz_rescale_param {
> +	enum ipipe_oper_mode mode;
> +	enum enable_disable_t h_flip;
> +	enum enable_disable_t v_flip;
> +	enum enable_disable_t cen;
> +	enum enable_disable_t yen;
> +	unsigned short i_vps;
> +	unsigned short i_hps;
> +	unsigned short o_vsz;
> +	unsigned short o_hsz;
> +	unsigned short v_phs_y;
> +	unsigned short v_phs_c;
> +	unsigned short v_dif;
> +	/* resize method - Luminance */
> +	enum rsz_intp_t v_typ_y;
> +	/* resize method - Chrominance */
> +	enum rsz_intp_t v_typ_c;
> +	/* vertical lpf intensity - Luminance */
> +	unsigned char v_lpf_int_y;
> +	/* vertical lpf intensity - Chrominance */
> +	unsigned char v_lpf_int_c;
> +	unsigned short h_phs;
> +	unsigned short h_dif;
> +	/* resize method - Luminance */
> +	enum rsz_intp_t h_typ_y;
> +	/* resize method - Chrominance */
> +	enum rsz_intp_t h_typ_c;
> +	/* horizontal lpf intensity - Luminance */
> +	unsigned char h_lpf_int_y;
> +	/* horizontal lpf intensity - Chrominance */
> +	unsigned char h_lpf_int_c;
> +	enum enable_disable_t dscale_en;
> +	enum down_scale_ave_sz h_dscale_ave_sz;
> +	enum down_scale_ave_sz v_dscale_ave_sz;
> +	/* store the calculated frame division parameter */
> +	struct f_div_param f_div;
> +};
> +
> +enum ipipe_rsz_rgb_t {
> +	OUTPUT_32BIT,
> +	OUTPUT_16BIT
> +};
> +
> +enum ipipe_rsz_rgb_msk_t {
> +	NOMASK,
> +	MASKLAST2
> +};
> +
> +/* Resizer RGB Conversion Parameters */
> +struct ipipe_rsz_resize2rgb {
> +	enum enable_disable_t rgb_en;
> +	enum ipipe_rsz_rgb_t rgb_typ;
> +	enum ipipe_rsz_rgb_msk_t rgb_msk0;
> +	enum ipipe_rsz_rgb_msk_t rgb_msk1;
> +	unsigned int rgb_alpha_val;
> +};
> +
> +/* Resizer External Memory Parameters */
> +struct ipipe_ext_mem_param {
> +	unsigned int rsz_sdr_oft_y;
> +	unsigned int rsz_sdr_ptr_s_y;
> +	unsigned int rsz_sdr_ptr_e_y;
> +	unsigned int rsz_sdr_oft_c;
> +	unsigned int rsz_sdr_ptr_s_c;
> +	unsigned int rsz_sdr_ptr_e_c;
> +	/* offset to be added to buffer start when flipping for y/ycbcr */
> +	unsigned int flip_ofst_y;
> +	/* offset to be added to buffer start when flipping for c */
> +	unsigned int flip_ofst_c;
> +	/* c offset for YUV 420SP */
> +	unsigned int c_offset;
> +	/* User Defined Y offset for YUV 420SP or YUV420ILE data */
> +	unsigned int user_y_ofst;
> +	/* User Defined C offset for YUV 420SP data */
> +	unsigned int user_c_ofst;
> +};
> +
> +enum rsz_data_source {
> +	IPIPE_DATA,
> +	IPIPEIF_DATA
> +};
> +
> +/* data paths */
> +enum ipipe_data_paths {
> +	IPIPE_RAW2YUV,
> +	/* Bayer RAW input to YCbCr output */
> +	IPIPE_RAW2RAW,
> +	/* Bayer Raw to Bayer output */
> +	IPIPE_RAW2BOX,
> +	/* Bayer Raw to Boxcar output */
> +	IPIPE_YUV2YUV
> +	/* YUV Raw to YUV Raw output */
> +};
> +
> +enum rsz_src_img_fmt {
> +	RSZ_IMG_422,
> +	RSZ_IMG_420
> +};
> +
> +struct rsz_common_params {
> +	unsigned int vps;
> +	unsigned int vsz;
> +	unsigned int hps;
> +	unsigned int hsz;
> +	/* 420 or 422 */
> +	enum rsz_src_img_fmt src_img_fmt;
> +	/* Y or C when src_fmt is 420, 0 - y, 1 - c */
> +	unsigned char y_c;
> +	/* flip raw or ycbcr */
> +	unsigned char raw_flip;
> +	/* IPIPE or IPIPEIF data */
> +	enum rsz_data_source source;
> +	enum ipipe_dpaths_bypass_t passthrough;
> +	unsigned char yuv_y_min;
> +	unsigned char yuv_y_max;
> +	unsigned char yuv_c_min;
> +	unsigned char yuv_c_max;
> +	enum enable_disable_t rsz_seq_crv;
> +	enum ipipe_chr_pos out_chr_pos;
> +};
> +
> +struct ipipe_params {
> +	struct ipipeif ipipeif_param;
> +	enum ipipe_oper_mode ipipe_mode;
> +	/* input/output datapath through IPIPE */
> +	enum ipipe_data_paths ipipe_dpaths_fmt;
> +	/* color pattern register */
> +	enum ipipe_colpat_t ipipe_colpat_elep;
> +	enum ipipe_colpat_t ipipe_colpat_elop;
> +	enum ipipe_colpat_t ipipe_colpat_olep;
> +	enum ipipe_colpat_t ipipe_colpat_olop;
> +	/* horizontal/vertical start, horizontal/vertical size
> +	 * for both IPIPE and RSZ input
> +	 */
> +	unsigned int ipipe_vps;
> +	unsigned int ipipe_vsz;
> +	unsigned int ipipe_hps;
> +	unsigned int ipipe_hsz;
> +
> +	struct rsz_common_params rsz_common;
> +	struct ipipe_rsz_rescale_param rsz_rsc_param[2];
> +	struct ipipe_rsz_resize2rgb rsz2rgb[2];
> +	struct ipipe_ext_mem_param ext_mem_param[2];
> +	enum enable_disable_t rsz_en[2];
> +};
> +
> +void ipipe_set_d2f_regs(unsigned int id, struct prev_nf *noise_filter);
> +void ipipe_set_rgb2rgb_regs(unsigned int id, struct prev_rgb2rgb *rgb);
> +void rsz_set_output_address(struct ipipe_params *params,
> +			      int resize_no, unsigned int address);
> +void ipipe_set_yuv422_conv_regs(struct prev_yuv422_conv *conv);
> +void ipipe_set_lum_adj_regs(struct prev_lum_adj *lum_adj);
> +void ipipe_set_rgb2ycbcr_regs(struct prev_rgb2yuv *yuv);
> +void ipipe_set_lutdpc_regs(struct prev_lutdpc *lutdpc);
> +void ipipe_set_otfdpc_regs(struct prev_otfdpc *otfdpc);
> +void ipipe_set_3d_lut_regs(struct prev_3d_lut *lut_3d);
> +void ipipe_set_gamma_regs(struct prev_gamma *gamma);
> +int ipipe_hw_setup(struct ipipe_params *config);
> +void ipipe_set_gbce_regs(struct prev_gbce *gbce);
> +void ipipe_set_gic_regs(struct prev_gic *gic);
> +void ipipe_set_cfa_regs(struct prev_cfa *cfa);
> +void ipipe_set_car_regs(struct prev_car *car);
> +void ipipe_set_cgs_regs(struct prev_cgs *cgs);
> +void rsz_set_in_pix_format(unsigned char y_c);
> +void ipipe_set_ee_regs(struct prev_yee *ee);
> +void ipipe_set_wb_regs(struct prev_wb *wb);
> +int rsz_enable(int rsz_id, int enable);
> +void rsz_src_enable(int enable);
> +
> +#endif
> +#endif
> diff --git a/drivers/media/video/davinci/imp_common.h b/drivers/media/video/davinci/imp_common.h
> new file mode 100644
> index 0000000..25b2836
> --- /dev/null
> +++ b/drivers/media/video/davinci/imp_common.h
> @@ -0,0 +1,85 @@
> +/*
> +* Copyright (C) 2011 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
> +*
> +* imp_common.h file
> +*/
> +#ifndef _IMP_COMMON_H
> +#define _IMP_COMMON_H
> +
> +#ifdef __KERNEL__

This is a kernel-only header file. No need to check for __KERNEL__.

> +#include <linux/completion.h>
> +#include <linux/interrupt.h>
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +#define MAX_CHANNELS		2
> +#define	MAX_BUFFERS		6
> +#define	MAX_PRIORITY		5
> +#define	MIN_PRIORITY		0
> +#define	DEFAULT_PRIORITY	3
> +#define ENABLED			1
> +#define DISABLED		0
> +#define CHANNEL_BUSY		1
> +#define CHANNEL_FREE		0
> +#define ISNULL(val) ((val == NULL) ? 1 : 0)
> +
> +/* driver configured by application */
> +#define STATE_CONFIGURED	1
> +/* driver not configured by application */
> +#define STATE_NOT_CONFIGURED	0
> +
> +enum imp_log_chan_t {
> +	IMP_PREVIEWER,
> +	IMP_RESIZER,
> +	IMP_HISTOGRAM,
> +	IMP_BOXCAR
> +};
> +
> +/* IMP channel structure */
> +struct imp_logical_channel {
> +	/* channel type */
> +	enum imp_log_chan_t type;
> +	/* If this channel is chained with another channel, this is set */
> +	char chained;
> +	/* Set if there is a primary user of this channel */
> +	char primary_user;
> +	/* channel configuration for this logial channel */
> +	void *config;
> +	/* Size of the user configuration block */
> +	int user_config_size;
> +	/* Saves the user configuration */
> +	void *user_config;
> +	/* configure State of the channel */
> +	unsigned int config_state;
> +};
> +
> +/* Where hardware channel is shared, this is used for serialisation */
> +struct imp_serializer {
> +	/* channel config array for serialization */
> +	struct imp_logical_channel *channel_config[MAX_CHANNELS];
> +	/* number of elements in the array */
> +	int array_count;
> +	/* Semaphore for above config array */
> +	struct mutex array_sem;
> +	/* Completion semaphore when hw channel is common
> +	 * Use device specific completion semaphore when request is serialized
> +	 */
> +	struct completion sem_isr;
> +};
> +
> +
> +
> +#endif
> +#endif
> diff --git a/drivers/media/video/davinci/imp_hw_if.h b/drivers/media/video/davinci/imp_hw_if.h
> new file mode 100644
> index 0000000..20a2b7f
> --- /dev/null
> +++ b/drivers/media/video/davinci/imp_hw_if.h
> @@ -0,0 +1,178 @@
> +/*
> +* Copyright (C) 2011 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
> +*/
> +
> +#ifndef _IMP_HW_IF_H
> +#define _IMP_HW_IF_H
> +
> +#ifdef __KERNEL__

Same here.

> +#include <linux/davinci_vpfe.h>
> +#include "imp_common.h"
> +#include <media/davinci/vpfe.h>
> +
> +struct prev_module_if {
> +	/* Version of the preview module */
> +	char *version;
> +	/* Module IDs as defined above */
> +	unsigned short module_id;
> +	/* Name of the module */
> +	char *module_name;
> +	/* control allowed in continous mode ? 1 - allowed , 0 - not allowed */
> +	char control;
> +	/* path in which module sits */
> +	enum imp_data_paths path;
> +	int (*set)(struct device *dev, void *param, int len);
> +	int (*get)(struct device *dev, void *param, int len);
> +};
> +
> +struct imp_hw_interface {
> +	/* Name of the image processor hardware */
> +	char *name;
> +	/* module owner */
> +	struct module *owner;
> +	/*
> +	 * enumerate preview modules. Return interface to the
> +	 * the module
> +	 */
> +	struct prev_module_if *(*prev_enum_modules) (struct device *dev,
> +						     int index);
> +	/*
> +	 * set operating mode for IPIPE; 1-single shot, 0-continous
> +	 */
> +	int (*set_oper_mode) (unsigned int mode);
> +	/*
> +	 * reset operating mode for IPIPE;
> +	 */
> +	void (*reset_oper_mode) (void);
> +	/*
> +	 *  get IPIPE operation mode
> +	 */
> +	unsigned int (*get_oper_mode) (void);
> +	/* check if hw is busy in continuous mode.
> +	 * Used for checking if hw is used by ccdc driver in
> +	 * continuous mode. If streaming is ON, this will be
> +	 * set to busy
> +	 */
> +	unsigned int (*get_hw_state) (void);
> +	/* set hw state */
> +	void (*set_hw_state) (unsigned int state);
> +	/* is resizer chained ? */
> +	unsigned int (*resizer_chain) (void);
> +	/* this is used to lock shared resource */
> +	void (*lock_chain) (void);
> +	/* this is used unlock shared resouce */
> +	void (*unlock_chain) (void);
> +	/* Allocate a shared or exclusive config block for hardware
> +	 * configuration
> +	 */
> +	void *(*alloc_config_block) (struct device *dev);
> +	/* hw serialization enabled ?? */
> +	int (*serialize) (void);
> +	/* De-allocate the exclusive config block */
> +	void (*dealloc_config_block) (struct device *dev, void *config);
> +	/* Allocate a user confguration block */
> +	void *(*alloc_user_config_block) (struct device *dev,
> +					  enum imp_log_chan_t chan_type,
> +					  int *len);
> +
> +	/* de-allocate user config block */
> +	void (*dealloc_user_config_block) (struct device *dev, void *config);
> +
> +	/* set default configuration in the config block */
> +	void (*set_user_config_defaults) (struct device *dev,
> +					  enum imp_log_chan_t chan_type,
> +					  void *user_config);
> +	/* set user configuration for preview */
> +	int (*set_preview_config) (struct device *dev,
> +				   void *user_config, void *config);
> +	/* set user configuration for resize */
> +	int (*set_resizer_config) (struct device *dev,
> +				   int resizer_chained,
> +				   void *user_config, void *config);
> +
> +	int (*reconfig_resizer) (struct device *dev,
> +				struct rsz_reconfig *user_config,
> +				void *config);
> +
> +	/* update output buffer address for a channel
> +	 * if config is NULL, the shared config is assumed
> +	 * this is used only in single shot mode
> +	 */
> +	int (*update_inbuf_address) (void *config, unsigned int address);
> +	/* update output buffer address for a channel
> +	 * if config is NULL, the shared config is assumed
> +	 */
> +	void (*update_outbuf1_address) (void *config, unsigned int address);
> +	/* update output buffer address for a channel
> +	 * if config is NULL, the shared config is assumed
> +	 */
> +	void (*update_outbuf2_address) (void *config, unsigned int address);
> +	/* enable or disable hw */
> +	void (*enable) (unsigned char en, void *config);
> +	/* enable or disable resizer to allow frame by frame resize in
> +	 * continuous mode
> +	 */
> +	void (*enable_resize) (int en);
> +	/* setup hardware for processing. if config is NULL,
> +	 * shared channel is assumed
> +	 */
> +	int (*hw_setup) (struct device *dev, void *config);
> +	/* Get configuration state of resizer in continuous mode */
> +	unsigned int (*get_resizer_config_state) (void);
> +	/* Get configuration state of previewer in continuous mode */
> +	unsigned int (*get_previewer_config_state) (void);
> +
> +	/* Below APIs assume we are using shared configuration since
> +	 * oper mode is continuous
> +	 */
> +	/* Set the input crop window at the IMP interface and IMP */
> +	int (*set_input_win) (struct imp_window *win);
> +	/* Get current input crop window param at the IMP */
> +	int (*get_input_win) (struct imp_window *win);
> +	/* Set interface parameter at IPIPEIF. Only valid for DM360 */
> +	int (*set_hw_if_param) (struct vpfe_hw_if_param *param);
> +	/* Set input pixel format */
> +	int (*set_in_pixel_format) (enum imp_pix_formats pix_fmt);
> +	/* set output pixel format */
> +	int (*set_out_pixel_format) (enum imp_pix_formats pix_fmt);
> +	/* 0 - interleaved, 1 - field seperated */
> +	int (*set_buftype) (unsigned char buf_type);
> +	/* 0 - interlaced, 1 - progressive */
> +	int (*set_frame_format) (unsigned char frm_fmt);
> +	/* Set the output window at the IMP, output selection
> +	 * done by out_sel. 0 - output 1 and 1 - output 2
> +	 */
> +	int (*set_output_win) (struct imp_window *win);
> +	/* Get output enable/disable status */
> +	int (*get_output_state) (unsigned char out_sel);
> +	/* Get output line lenght */
> +	int (*get_line_length) (unsigned char out_sel);
> +	/* Get the output image height */
> +	int (*get_image_height) (unsigned char out_sel);
> +	/* Get current output window param at the IMP */
> +	int (*get_output_win) (struct imp_window *win);
> +	/* get maximum output width of rsz-a or rsz_b*/
> +	int (*get_max_output_width) (int rsz);
> +	/* get maximum output height of rsa-a or rsz-b */
> +	int (*get_max_output_height) (int rsz);
> +	/* Enumerate pixel format for a given input format */
> +	int (*enum_pix) (u32 *output_pix, int index);
> +};

Are there real benefits from using the above struct? I'm not sure if
this makes anything clearer. Is it being used elsewhere than in a single
instance (dm365_ipipe_interface)?

> +struct imp_hw_interface *imp_get_hw_if(void);
> +
> +#endif
> +#endif

Regards,

-- 
Sakari Ailus
sakari.ailus@iki.fi

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

* RE: [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver
  2011-09-27 14:01   ` Sakari Ailus
@ 2011-10-17 14:16     ` Hadli, Manjunath
  0 siblings, 0 replies; 27+ messages in thread
From: Hadli, Manjunath @ 2011-10-17 14:16 UTC (permalink / raw)
  To: 'Sakari Ailus'; +Cc: LMML, dlos

Hi Sakari,
 Thank you for your comments, some questions clarifications below.

On Tue, Sep 27, 2011 at 19:31:35, Sakari Ailus wrote:
> Hi Manju,
>
> My apologies for the very late review for these patches.
>
> A general comment: all the functions that do need to use device specific
> information must take the device as a parameter. Look at the OMAP 3 ISP
> driver for an example.
Sure.
    This is a lower level interface to dm365, and a similar interface exists for dm355 which will be posted later. I agree that soe of the long list of statics have to be zipped into a device specific state structure and used as an argument for most functions. Wherever the v4l2 device structure is needed, I think currently it is taken care of. I looked at the OMAP3 ISP and saw that it is implemented similarly.
>
> Manjunath Hadli wrote:
> > From: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
> >
> > Add the IPIPE interfacing layer to the vpfe driver. This patch adds dm365
> > specific implementation of the genric imp_hw_interface interface for
> > programming the IPIPE block, mainly setting the resizer and previewer
> > configuration parameters. This is built as an independent module.
> >
> > Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
> > Signed-off-by: Nagabhushana Netagunte <nagabhushana.netagunte@ti.com>
> > ---
> >  drivers/media/video/davinci/dm365_def_para.c |  486 ++++
> >  drivers/media/video/davinci/dm365_def_para.h |   39 +
> >  drivers/media/video/davinci/dm365_ipipe.c    | 3966 ++++++++++++++++++++++++++
> >  drivers/media/video/davinci/dm365_ipipe.h    |  300 ++
> >  drivers/media/video/davinci/imp_common.h     |   85 +
> >  drivers/media/video/davinci/imp_hw_if.h      |  178 ++
> >  6 files changed, 5054 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/media/video/davinci/dm365_def_para.c
> >  create mode 100644 drivers/media/video/davinci/dm365_def_para.h
> >  create mode 100644 drivers/media/video/davinci/dm365_ipipe.c
> >  create mode 100644 drivers/media/video/davinci/dm365_ipipe.h
> >  create mode 100644 drivers/media/video/davinci/imp_common.h
> >  create mode 100644 drivers/media/video/davinci/imp_hw_if.h
> >
> > diff --git a/drivers/media/video/davinci/dm365_def_para.c b/drivers/media/video/davinci/dm365_def_para.c
> > new file mode 100644
> > index 0000000..d5af73b
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/dm365_def_para.c
> > @@ -0,0 +1,486 @@
> > +/*
> > +* Copyright (C) 2011 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
> > +*/
> > +#include <linux/v4l2-mediabus.h>
> > +#include <media/davinci/vpfe.h>
> > +#include "dm365_ipipe.h"
> > +
> > +/* Defaults for lutdpc */
> > +struct prev_lutdpc dm365_lutdpc_defaults = {
> > +   .en = 0
> > +};
> > +
> > +/* Defaults for otfdpc */
> > +struct prev_lutdpc dm365_otfdpc_defaults = {
> > +   .en = 0
> > +};
> > +
> > +/* Defaults for 2D - nf */
> > +struct prev_nf dm365_nf_defaults = {
> > +   .en = 0
> > +};
> > +
> > +/* defaults for GIC */
> > +struct prev_gic dm365_gic_defaults = {
> > +   .en = 0
> > +};
> > +
> > +/* Defaults for white balance */
> > +struct prev_wb dm365_wb_defaults = {
> > +   .gain_r = {2, 0x00},
> > +   .gain_gr = {2, 0x00},
> > +   .gain_gb = {2, 0x00},
> > +   .gain_b = {2, 0x00}
> > +};
> > +
> > +/* Defaults for CFA */
> > +struct prev_cfa dm365_cfa_defaults = {
> > +   .alg = IPIPE_CFA_ALG_2DIRAC,
> > +   .hpf_thr_2dir = 0,
> > +   .hpf_slp_2dir = 0,
> > +   .hp_mix_thr_2dir = 0,
> > +   .hp_mix_slope_2dir = 0,
> > +   .dir_thr_2dir = 0,
> > +   .dir_slope_2dir = 0,
> > +   .nd_wt_2dir = 0,
> > +   .hue_fract_daa = 0,
> > +   .edge_thr_daa = 0,
> > +   .thr_min_daa = 0,
> > +   .thr_slope_daa = 0,
> > +   .slope_min_daa = 0,
> > +   .slope_slope_daa = 0,
> > +   .lp_wt_daa = 0
> > +};
>
> Statically allocated memory is zero by default. You might want to do
> this kind of initisation in a function initialising the device specific
> structures rather than storing defaults to memory as almost all of this
> is zeros.
I would like to keep all the data initialization separate, but as you say, there might not be a need for us to init the ones with zero values. They are kept mainly for purpose of clarity, but if you feel the members need not be initialized to zero, I can leave them out.
>
> > +/* Defaults for rgb2rgb */
> > +struct prev_rgb2rgb dm365_rgb2rgb_defaults = {
> > +   .coef_rr = {1, 0},      /* 256 */
> > +   .coef_gr = {0, 0},
> > +   .coef_br = {0, 0},
> > +   .coef_rg = {0, 0},
> > +   .coef_gg = {1, 0},      /* 256 */
> > +   .coef_bg = {0, 0},
> > +   .coef_rb = {0, 0},
> > +   .coef_gb = {0, 0},
> > +   .coef_bb = {1, 0},      /* 256 */
> > +   .out_ofst_r = 0,
> > +   .out_ofst_g = 0,
> > +   .out_ofst_b = 0
> > +};
> > +
> > +/* Defaults for gamma correction */
> > +struct prev_gamma dm365_gamma_defaults = {
> > +   .bypass_r = 0,
> > +   .bypass_b = 0,
> > +   .bypass_g = 0,
> > +   .tbl_sel = IPIPE_GAMMA_TBL_ROM
> > +};
> > +
> > +/* Defaults for 3d lut */
> > +struct prev_3d_lut dm365_3d_lut_defaults = {
> > +   .en = 0
> > +};
> > +
> > +/* Defaults for lumina adjustments */
> > +struct prev_lum_adj dm365_lum_adj_defaults = {
> > +   .brightness = 0,
> > +   .contrast = 16
> > +};
>
> This should probably be implemented as V4L2 controls. There are control
> ids for both brightness and contrast.
Agreed.
>
> > +/* Defaults for rgb2yuv conversion */
> > +struct prev_rgb2yuv dm365_rgb2yuv_defaults = {
> > +   .coef_ry = {0, 0x4D},
> > +   .coef_gy = {0, 0x96},
> > +   .coef_by = {0, 0x1D},
> > +   .coef_rcb = {0xF, 0xD5},
> > +   .coef_gcb = {0xF, 0xAB},
> > +   .coef_bcb = {0, 0x80},
> > +   .coef_rcr = {0, 0x80},
> > +   .coef_gcr = {0xF, 0x95},
> > +   .coef_bcr = {0xF, 0xEB},
> > +   .out_ofst_y = 0,
> > +   .out_ofst_cb = 0x80,
> > +   .out_ofst_cr = 0x80
> > +};
>
> Lower case hexadecimals, please.
Sure.
>
> > +/* Defaults for GBCE */
> > +struct prev_gbce dm365_gbce_defaults = {
> > +   .en = 0
> > +};
> > +
> > +/* Defaults for yuv 422 conversion */
> > +struct prev_yuv422_conv dm365_yuv422_conv_defaults = {
> > +   .en_chrom_lpf = 0,
> > +   .chrom_pos = IPIPE_YUV422_CHR_POS_COSITE
> > +};
> > +
> > +/* Defaults for Edge Ehnancements  */
> > +struct prev_yee dm365_yee_defaults = {
> > +   .en = 0,
> > +};
> > +
> > +/* Defaults for CAR conversion */
> > +struct prev_car dm365_car_defaults = {
> > +   .en = 0,
> > +};
> > +
> > +/* Defaults for CGS */
> > +struct prev_cgs dm365_cgs_defaults = {
> > +   .en = 0,
> > +};
> > +
> > +#define  WIDTH_I 640
> > +#define  HEIGHT_I 480
> > +#define  WIDTH_O 640
> > +#define  HEIGHT_O 480
>
> Is the image size that this hardware block process static?
No. but these are just defaults.
>
> > +/* default ipipeif settings */
> > +struct ipipeif_5_1 ipipeif_5_1_defaults = {
> > +   .pack_mode = IPIPEIF_5_1_PACK_16_BIT,
> > +   .data_shift = IPIPEIF_BITS11_0,
> > +   .source1 = IPIPEIF_SRC1_PARALLEL_PORT,
> > +   .clk_div = {
> > +           .m = 1, /* clock = sdram clock * (m/n) */
> > +           .n = 6
> > +   },
> > +   .dpc = {
> > +           .en = 0,
> > +   },
> > +   .dpcm = {
> > +           .en = 0,
> > +           .type = IPIPEIF_DPCM_8BIT_12BIT,
> > +           .pred = IPIPEIF_DPCM_SIMPLE_PRED
> > +   },
> > +   .pix_order = IPIPEIF_CBCR_Y,
> > +   .isif_port = {
> > +           .if_type = V4L2_MBUS_FMT_SBGGR10_1X10,
> > +           .hdpol = VPFE_PINPOL_POSITIVE,
> > +           .vdpol = VPFE_PINPOL_POSITIVE
> > +   },
> > +   .clip = 4095,
> > +   .align_sync = 0,
> > +   .rsz_start = 0,
> > +   .df_gain_en = 0
> > +};
> > +
> > +struct ipipe_params dm365_ipipe_defs = {
> > +   .ipipeif_param = {
> > +           .mode = IPIPEIF_ONE_SHOT,
> > +           .source = IPIPEIF_SDRAM_RAW,
> > +           .clock_select = IPIPEIF_SDRAM_CLK,
> > +           .glob_hor_size = WIDTH_I + 8,
> > +           .glob_ver_size = HEIGHT_I + 10,
> > +           .hnum = WIDTH_I,
> > +           .vnum = HEIGHT_I,
> > +           .adofs = WIDTH_I * 2,
> > +           .rsz = 16,      /* resize ratio 16/rsz */
> > +           .decimation = IPIPEIF_DECIMATION_OFF,
> > +           .avg_filter = IPIPEIF_AVG_OFF,
> > +           .gain = 0x200,  /* U10Q9 */
> > +   },
> > +   .ipipe_mode = IPIPEIF_ONE_SHOT,
> > +   .ipipe_dpaths_fmt = IPIPE_RAW2YUV,
> > +   .ipipe_colpat_olop = IPIPE_GREEN_BLUE,
> > +   .ipipe_colpat_olep = IPIPE_BLUE,
> > +   .ipipe_colpat_elop = IPIPE_RED,
> > +   .ipipe_colpat_elep = IPIPE_GREEN_RED,
> > +   .ipipe_vps = 0,
> > +   .ipipe_vsz = HEIGHT_I - 1,
> > +   .ipipe_hps = 0,
> > +   .ipipe_hsz = WIDTH_I - 1,
> > +   .rsz_common = {
> > +           .vps = 0,
> > +           .vsz = HEIGHT_I - 1,
> > +           .hps = 0,
> > +           .hsz = WIDTH_I - 1,
> > +           .src_img_fmt = RSZ_IMG_422,
> > +           .y_c = 0,
> > +           .raw_flip = 1,  /* flip preserve Raw format */
> > +           .source = IPIPE_DATA,
> > +           .passthrough = IPIPE_BYPASS_OFF,
> > +           .yuv_y_min = 0,
> > +           .yuv_y_max = 255,
> > +           .yuv_c_min = 0,
> > +           .yuv_c_max = 255,
> > +           .rsz_seq_crv = DISABLE,
> > +           .out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE
> > +   },
> > +   .rsz_rsc_param = {
> > +           {
> > +                   .mode = IPIPEIF_ONE_SHOT,
> > +                   .h_flip = DISABLE,
> > +                   .v_flip = DISABLE,
> > +                   .cen = DISABLE,
> > +                   .yen = DISABLE,
> > +                   .i_vps = 0,
> > +                   .i_hps = 0,
> > +                   .o_vsz = HEIGHT_O - 1,
> > +                   .o_hsz = WIDTH_O - 1,
> > +                   .v_phs_y = 0,
> > +                   .v_phs_c = 0,
> > +                   .v_dif = 256,
> > +                   .v_typ_y = RSZ_INTP_CUBIC,
> > +                   .h_typ_c = RSZ_INTP_CUBIC,
> > +                   .v_lpf_int_y = 0,
> > +                   .v_lpf_int_c = 0,
> > +                   .h_phs = 0,
> > +                   .h_dif = 256,
> > +                   .h_typ_y = RSZ_INTP_CUBIC,
> > +                   .h_typ_c = RSZ_INTP_CUBIC,
> > +                   .h_lpf_int_y = 0,
> > +                   .h_lpf_int_c = 0,
> > +                   .dscale_en = 0,
> > +                   .h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +                   .v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +                   .f_div.en = 0
> > +           },
> > +           {
> > +                   .mode = IPIPEIF_ONE_SHOT,
> > +                   .h_flip = DISABLE,
> > +                   .v_flip = DISABLE,
> > +                   .cen = DISABLE,
> > +                   .yen = DISABLE,
> > +                   .i_vps = 0,
> > +                   .i_hps = 0,
> > +                   .o_vsz = HEIGHT_O - 1,
> > +                   .o_hsz = WIDTH_O - 1,
> > +                   .v_phs_y = 0,
> > +                   .v_phs_c = 0,
> > +                   .v_dif = 256,
> > +                   .v_typ_y = RSZ_INTP_CUBIC,
> > +                   .h_typ_c = RSZ_INTP_CUBIC,
> > +                   .v_lpf_int_y = 0,
> > +                   .v_lpf_int_c = 0,
> > +                   .h_phs = 0,
> > +                   .h_dif = 256,
> > +                   .h_typ_y = RSZ_INTP_CUBIC,
> > +                   .h_typ_c = RSZ_INTP_CUBIC,
> > +                   .h_lpf_int_y = 0,
> > +                   .h_lpf_int_c = 0,
> > +                   .dscale_en = 0,
> > +                   .h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +                   .v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +                   .f_div.en = 0
> > +           },
> > +   },
> > +   .rsz2rgb = {
> > +           {
> > +                   .rgb_en = DISABLE
> > +           },
> > +           {
> > +                   .rgb_en = DISABLE
> > +           }
> > +   },
> > +   .ext_mem_param = {
> > +           {
> > +                   .rsz_sdr_oft_y = WIDTH_O << 1,
> > +                   .rsz_sdr_ptr_s_y = 0,
> > +                   .rsz_sdr_ptr_e_y = HEIGHT_O,
> > +                   .rsz_sdr_oft_c = WIDTH_O,
> > +                   .rsz_sdr_ptr_s_c = 0,
> > +                   .rsz_sdr_ptr_e_c = HEIGHT_O >> 1,
> > +                   .flip_ofst_y = 0,
> > +                   .flip_ofst_c = 0,
> > +                   .c_offset = 0,
> > +                   .user_y_ofst = 0,
> > +                   .user_c_ofst = 0
> > +           },
> > +           {
> > +                   .rsz_sdr_oft_y = WIDTH_O << 1,
> > +                   .rsz_sdr_ptr_s_y = 0,
> > +                   .rsz_sdr_ptr_e_y = HEIGHT_O,
> > +                   .rsz_sdr_oft_c = WIDTH_O,
> > +                   .rsz_sdr_ptr_s_c = 0,
> > +                   .rsz_sdr_ptr_e_c = HEIGHT_O,
> > +                   .flip_ofst_y = 0,
> > +                   .flip_ofst_c = 0,
> > +                   .c_offset = 0,
> > +                   .user_y_ofst = 0,
> > +                   .user_c_ofst = 0
> > +           },
> > +   },
> > +   .rsz_en[0] = ENABLE,
> > +   .rsz_en[1] = DISABLE
> > +};
> > +
> > +struct prev_single_shot_config dm365_prev_ss_config_defs = {
> > +   .bypass = IPIPE_BYPASS_OFF,
> > +   .input = {
> > +           .image_width = WIDTH_I,
> > +           .image_height = HEIGHT_I,
> > +           .vst = 0,
> > +           .hst = 0,
> > +           .ppln = WIDTH_I + 8,
> > +           .lpfr = HEIGHT_I + 10,
> > +           .pred = IPIPEIF_DPCM_SIMPLE_PRED,
> > +           .clk_div = {1, 6},
> > +           .data_shift = IPIPEIF_BITS11_0,
> > +           .dec_en = 0,
> > +           .rsz = 16,      /* resize ratio 16/rsz */
> > +           .frame_div_mode_en = 0,
> > +           .avg_filter_en = IPIPEIF_AVG_OFF,
> > +           .dpc = {0, 0},
> > +           .gain = 512,
> > +           .clip = 4095,
> > +           .align_sync = 0,
> > +           .rsz_start = 0,
> > +           .pix_fmt = IPIPE_BAYER,
> > +           .colp_olop = IPIPE_GREEN_BLUE,
> > +           .colp_olep = IPIPE_BLUE,
> > +           .colp_elop = IPIPE_RED,
> > +           .colp_elep = IPIPE_GREEN_RED
> > +   },
> > +   .output = {
> > +           .pix_fmt = IPIPE_UYVY
> > +   }
> > +};
> > +
> > +struct prev_continuous_config dm365_prev_cont_config_defs = {
> > +   .bypass = IPIPE_BYPASS_OFF,
> > +   .input = {
> > +           .en_df_sub = 0,
> > +           .dec_en = 0,
> > +           .rsz = 16,
> > +           .avg_filter_en = IPIPEIF_AVG_OFF,
> > +           .gain = 512,
> > +           .clip = 4095,
> > +           .colp_olop = IPIPE_GREEN_BLUE,
> > +           .colp_olep = IPIPE_BLUE,
> > +           .colp_elop = IPIPE_RED,
> > +           .colp_elep = IPIPE_GREEN_RED
> > +   },
> > +};
> > +
> > +struct rsz_single_shot_config dm365_rsz_ss_config_defs = {
> > +   .input = {
> > +           .image_width = WIDTH_I,
> > +           .image_height = HEIGHT_I,
> > +           .vst = 0,
> > +           .hst = 0,
> > +           .ppln = WIDTH_I + 8,
> > +           .lpfr = HEIGHT_I + 10,
> > +           .clk_div = {1, 6},
> > +           .dec_en = 0,
> > +           .rsz = 16,      /* resize ratio 16/rsz */
> > +           .frame_div_mode_en = 0,
> > +           .avg_filter_en = IPIPEIF_AVG_OFF,
> > +           .align_sync = 0,
> > +           .rsz_start = 0,
> > +           .pix_fmt = IPIPE_UYVY
> > +   },
> > +   .output1 = {
> > +           .enable = 1,
> > +           .pix_fmt = IPIPE_UYVY,
> > +           .h_flip = 0,
> > +           .v_flip = 0,
> > +           .width = WIDTH_O,
> > +           .height = HEIGHT_O,
> > +           .vst_y = 0,
> > +           .vst_c = 0,
> > +           .v_typ_y = RSZ_INTP_CUBIC,
> > +           .v_typ_c = RSZ_INTP_CUBIC,
> > +           .v_lpf_int_y = 0,
> > +           .v_lpf_int_c = 0,
> > +           .h_typ_y = RSZ_INTP_CUBIC,
> > +           .h_typ_c = RSZ_INTP_CUBIC,
> > +           .h_lpf_int_y = 0,
> > +           .h_lpf_int_c = 0,
> > +           .en_down_scale = 0,
> > +           .h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .user_y_ofst = 0,
> > +           .user_c_ofst = 0
> > +   },
> > +   .output2 = {
> > +           .enable = 1,
> > +           .pix_fmt = IPIPE_UYVY,
> > +           .h_flip = 0,
> > +           .v_flip = 0,
> > +           .width = WIDTH_O,
> > +           .height = HEIGHT_O,
> > +           .vst_y = 0,
> > +           .vst_c = 0,
> > +           .v_typ_y = RSZ_INTP_CUBIC,
> > +           .v_typ_c = RSZ_INTP_CUBIC,
> > +           .v_lpf_int_y = 0,
> > +           .v_lpf_int_c = 0,
> > +           .h_typ_y = RSZ_INTP_CUBIC,
> > +           .h_typ_c = RSZ_INTP_CUBIC,
> > +           .h_lpf_int_y = 0,
> > +           .h_lpf_int_c = 0,
> > +           .en_down_scale = 0,
> > +           .h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .user_y_ofst = 0,
> > +           .user_c_ofst = 0
> > +   },
> > +   .chroma_sample_even = 0,
> > +   .yuv_y_min = 0,
> > +   .yuv_y_max = 255,
> > +   .yuv_c_min = 0,
> > +   .yuv_c_max = 255,
> > +   .out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE,
> > +};
> > +
> > +struct rsz_continuous_config dm365_rsz_cont_config_defs = {
> > +   .output1 = {
> > +           .enable = 1,
> > +           .h_flip = 0,
> > +           .v_flip = 0,
> > +           .v_typ_y = RSZ_INTP_CUBIC,
> > +           .v_typ_c = RSZ_INTP_CUBIC,
> > +           .v_lpf_int_y = 0,
> > +           .v_lpf_int_c = 0,
> > +           .h_typ_y = RSZ_INTP_CUBIC,
> > +           .h_typ_c = RSZ_INTP_CUBIC,
> > +           .h_lpf_int_y = 0,
> > +           .h_lpf_int_c = 0,
> > +           .en_down_scale = 0,
> > +           .h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .user_y_ofst = 0,
> > +           .user_c_ofst = 0
> > +   },
> > +   .output2 = {
> > +           .enable = 1,
> > +           .pix_fmt = IPIPE_UYVY,
> > +           .h_flip = 0,
> > +           .v_flip = 0,
> > +           .width = WIDTH_O,
> > +           .height = HEIGHT_O,
> > +           .vst_y = 0,
> > +           .vst_c = 0,
> > +           .v_typ_y = RSZ_INTP_CUBIC,
> > +           .v_typ_c = RSZ_INTP_CUBIC,
> > +           .v_lpf_int_y = 0,
> > +           .v_lpf_int_c = 0,
> > +           .h_typ_y = RSZ_INTP_CUBIC,
> > +           .h_typ_c = RSZ_INTP_CUBIC,
> > +           .h_lpf_int_y = 0,
> > +           .h_lpf_int_c = 0,
> > +           .en_down_scale = 0,
> > +           .h_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .v_dscale_ave_sz = IPIPE_DWN_SCALE_1_OVER_2,
> > +           .user_y_ofst = 0,
> > +           .user_c_ofst = 0
> > +   },
> > +   .chroma_sample_even = 0,
> > +   .yuv_y_min = 0,
> > +   .yuv_y_max = 255,
> > +   .yuv_c_min = 0,
> > +   .yuv_c_max = 255,
> > +   .out_chr_pos = IPIPE_YUV422_CHR_POS_COSITE,
> > +};
> > diff --git a/drivers/media/video/davinci/dm365_def_para.h b/drivers/media/video/davinci/dm365_def_para.h
> > new file mode 100644
> > index 0000000..872b3cb
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/dm365_def_para.h
> > @@ -0,0 +1,39 @@
> > +/*
> > + * Copyright (C) 2011 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
> > + */
> > +#include "dm365_ipipe.h"
> > +extern struct prev_lutdpc dm365_lutdpc_defaults;
> > +extern struct prev_otfdpc dm365_otfdpc_defaults;
> > +extern struct prev_nf dm365_nf_defaults;
> > +extern struct prev_gic dm365_gic_defaults;
> > +extern struct prev_wb dm365_wb_defaults;
> > +extern struct prev_cfa dm365_cfa_defaults;
> > +extern struct prev_rgb2rgb dm365_rgb2rgb_defaults;
> > +extern struct prev_gamma dm365_gamma_defaults;
> > +extern struct prev_3d_lut dm365_3d_lut_defaults;
> > +extern struct prev_lum_adj dm365_lum_adj_defaults;
> > +extern struct prev_rgb2yuv dm365_rgb2yuv_defaults;
> > +extern struct prev_yuv422_conv dm365_yuv422_conv_defaults;
> > +extern struct prev_gbce dm365_gbce_defaults;
> > +extern struct prev_yee dm365_yee_defaults;
> > +extern struct prev_car dm365_car_defaults;
> > +extern struct prev_cgs dm365_cgs_defaults;
> > +extern struct ipipe_params dm365_ipipe_defs;
> > +extern struct prev_single_shot_config dm365_prev_ss_config_defs;
> > +extern struct prev_continuous_config dm365_prev_cont_config_defs;
> > +extern struct rsz_single_shot_config dm365_rsz_ss_config_defs;
> > +extern struct rsz_continuous_config dm365_rsz_cont_config_defs;
> > +extern struct ipipeif_5_1 ipipeif_5_1_defaults;
> > diff --git a/drivers/media/video/davinci/dm365_ipipe.c b/drivers/media/video/davinci/dm365_ipipe.c
> > new file mode 100644
> > index 0000000..9f41784
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/dm365_ipipe.c
> > @@ -0,0 +1,3966 @@
> > +/*
> > +* Copyright (C) 2011 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
> > +*/
> > +
> > +#include <linux/string.h>
> > +#include <linux/kernel.h>
> > +#include <linux/slab.h>
> > +#include <linux/errno.h>
> > +#include <linux/types.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/mutex.h>
> > +#include <linux/device.h>
> > +#include <linux/videodev2.h>
> > +#include <linux/v4l2-mediabus.h>
> > +#include <media/davinci/vpfe.h>
> > +#include "dm365_ipipe.h"
> > +#include "imp_hw_if.h"
> > +
> > +#include "dm365_ipipe_hw.h"
> > +#include "dm365_def_para.h"
> > +
> > +/* IPIPE module operation state */
> > +struct ipipe_oper_state {
> > +   /* Operation state in continuous mode */
> > +   unsigned int state;
>
> What does operation state mean and which values are possible?
Currently it means continuous and single shot. I will update the comment.
>
> > +   /* Semaphore to protect the common hardware configuration */
> > +   struct mutex lock;
> > +   /* previewer config state */
> > +   unsigned int prev_config_state;
> > +   /* Shared configuration of the hardware */
> > +   struct ipipe_params *shared_config_param;
> > +   /* shared resource in use */
> > +   unsigned int resource_in_use;
> > +   /* resizer config state */
> > +   unsigned int rsz_config_state;
> > +   /* resizer chained with previewer */
> > +   unsigned int rsz_chained;
> > +   /* Buffer type, interleaved or field seperated for interlaced
> > +    *  scan
> > +    */
> > +   unsigned int buffer_type;
> > +   /* frame format, 0 - interlaced, 1 - progressive */
> > +   unsigned int frame_format;
> > +   /* input pixel format */
> > +   enum imp_pix_formats in_pixel_format;
> > +   /* input pixel format */
> > +   enum imp_pix_formats out_pixel_format;
>
> How about using v4l2_mbus_pixelcode instead? Or does using
> imp_pix_formats have an advantage that I can't see?
Sure. Will change it to v4l2_mbus_pixelcode.
>
> > +};
> > +
> > +/* Operation mode of image processor (imp) */
> > +static u32 oper_mode = IMP_MODE_NOT_CONFIGURED;
> > +/* enable/disable serializer */
> > +static u32 en_serializer;
> > +
> > +#define CONFIG_IPIPE_PARAM_VALIDATION
> > +/* ipipe module operation state & configuration */
> > +static struct ipipe_oper_state oper_state;
> > +
> > +/* LUT Defect pixel correction data */
> > +static struct prev_lutdpc lutdpc;
> > +
> > +/* LUT Defect pixel correction data */
> > +static struct prev_otfdpc otfdpc;
> > +
> > +/* Noise filter */
> > +static struct prev_nf nf1;
> > +static struct prev_nf nf2;
> > +
> > +/* Green Imbalance Correction */
> > +static struct prev_gic gic;
> > +
> > +/* White Balance */
> > +static struct prev_wb wb;
> > +
> > +/* CFA */
> > +static struct prev_cfa cfa;
> > +
> > +/* RGB2RGB conversion */
> > +static struct prev_rgb2rgb rgb2rgb_1;
> > +static struct prev_rgb2rgb rgb2rgb_2;
> > +
> > +/* Gamma correction */
> > +static struct prev_gamma gamma;
> > +
> > +/* 3D LUT */
> > +static struct prev_3d_lut lut_3d;
> > +
> > +/* Lumina Adjustment */
> > +static struct prev_lum_adj lum_adj;
> > +
> > +/* RGB2YUV conversion */
> > +static struct prev_rgb2yuv rgb2yuv;
> > +
> > +/* YUV 422 conversion */
> > +static struct prev_yuv422_conv yuv422_conv;
> > +
> > +/* GBCE */
> > +static struct prev_gbce gbce;
> > +
> > +/* Edge Enhancement */
> > +static struct prev_yee yee;
> > +
> > +/* Chromatic Artifact Reduction, CAR */
> > +static struct prev_car car;
> > +
> > +/* Chromatic Artifact Reduction, CAR */
> > +static struct prev_cgs cgs;
> > +
> > +/* Tables for various tuning modules */
> > +static struct ipipe_lutdpc_entry ipipe_lutdpc_table[MAX_SIZE_DPC];
> > +static struct ipipe_3d_lut_entry ipipe_3d_lut_table[MAX_SIZE_3D_LUT];
> > +static unsigned short ipipe_gbce_table[MAX_SIZE_GBCE_LUT];
> > +static struct ipipe_gamma_entry ipipe_gamma_table_r[MAX_SIZE_GAMMA];
> > +static struct ipipe_gamma_entry ipipe_gamma_table_b[MAX_SIZE_GAMMA];
> > +static struct ipipe_gamma_entry ipipe_gamma_table_g[MAX_SIZE_GAMMA];
> > +static short ipipe_yee_table[MAX_SIZE_YEE_LUT];
> > +
> > +/* Raw YUV formats */
> > +static u32 ipipe_raw_yuv_pix_formats[] = { V4L2_PIX_FMT_UYVY,
> > +                                     V4L2_PIX_FMT_NV12};
>
> Shouldn't all this be part of the device specific structure?
Sure. I will move all the above to a device specific structure.
>
> > +static int ipipe_enum_pix(u32 *pix, int i)
> > +{
> > +   if (i >= ARRAY_SIZE(ipipe_raw_yuv_pix_formats))
> > +           return -EINVAL;
> > +
> > +   *pix = ipipe_raw_yuv_pix_formats[i];
> > +   return 0;
> > +}
> > +
> > +/* IPIPE hardware limits */
> > +#define IPIPE_MAX_OUTPUT_WIDTH_A   2176
> > +#define IPIPE_MAX_OUTPUT_WIDTH_B   640
> > +
> > +static int ipipe_get_max_output_width(int rsz)
> > +{
> > +   if (rsz == RSZ_A)
> > +           return IPIPE_MAX_OUTPUT_WIDTH_A;
> > +   return IPIPE_MAX_OUTPUT_WIDTH_B;
> > +}
> > +
> > +/* Based on max resolution supported. QXGA */
> > +#define IPIPE_MAX_OUTPUT_HEIGHT_A  1536
> > +/* Based on max resolution supported. VGA */
> > +#define IPIPE_MAX_OUTPUT_HEIGHT_B  480
> > +
> > +static int ipipe_get_max_output_height(int rsz)
> > +{
> > +   if (rsz == RSZ_A)
> > +           return IPIPE_MAX_OUTPUT_HEIGHT_A;
> > +   return IPIPE_MAX_OUTPUT_HEIGHT_B;
> > +}
> > +
> > +static int ipipe_serialize(void)
> > +{
> > +   return en_serializer;
> > +}
> > +
> > +static int ipipe_set_ipipe_if_address(void *config, unsigned int address)
>
> address should probably be u32.
OK.
>
> > +{
> > +   struct ipipeif *if_params;
> > +
> > +   if (ISNULL(config))
> > +           return -EINVAL;
>
> Please just use !config or config == NULL.
OK.
>
> > +   if_params = &((struct ipipe_params *)config)->ipipeif_param;
> > +
> > +   return ipipeif_set_address(if_params, address);
> > +}
> > +
> > +static void ipipe_lock_chain(void)
> > +{
> > +   mutex_lock(&oper_state.lock);
> > +   oper_state.resource_in_use = 1;
> > +   mutex_unlock(&oper_state.lock);
> > +}
> > +
> > +static void ipipe_unlock_chain(void)
> > +{
> > +   mutex_lock(&oper_state.lock);
> > +   oper_state.resource_in_use = 0;
> > +   oper_state.prev_config_state = STATE_NOT_CONFIGURED;
> > +   oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
> > +   oper_state.rsz_chained = 0;
> > +   mutex_unlock(&oper_state.lock);
> > +}
> > +static int ipipe_process_pix_fmts(enum ipipe_pix_formats in_pix_fmt,
> > +                             enum ipipe_pix_formats out_pix_fmt,
> > +                             struct ipipe_params *param)
> > +{
> > +   enum ipipe_pix_formats temp_pix_fmt;
> > +
> > +   switch (in_pix_fmt) {
> > +   case IPIPE_BAYER_8BIT_PACK:
> > +           temp_pix_fmt = IPIPE_BAYER;
> > +           param->ipipeif_param.var.if_5_1.pack_mode
> > +               = IPIPEIF_5_1_PACK_8_BIT;
> > +           break;
> > +   case IPIPE_BAYER_8BIT_PACK_ALAW:
> > +           param->ipipeif_param.var.if_5_1.pack_mode
> > +               = IPIPEIF_5_1_PACK_8_BIT_A_LAW;
> > +           temp_pix_fmt = IPIPE_BAYER;
> > +           break;
> > +   case IPIPE_BAYER_8BIT_PACK_DPCM:
> > +           param->ipipeif_param.var.if_5_1.pack_mode
> > +               = IPIPEIF_5_1_PACK_8_BIT;
> > +           param->ipipeif_param.var.if_5_1.dpcm.en = 1;
> > +           temp_pix_fmt = IPIPE_BAYER;
> > +           break;
> > +   case IPIPE_BAYER:
> > +           param->ipipeif_param.var.if_5_1.pack_mode
> > +               = IPIPEIF_5_1_PACK_16_BIT;
> > +           temp_pix_fmt = IPIPE_BAYER;
> > +           break;
> > +   case IPIPE_BAYER_12BIT_PACK:
> > +           param->ipipeif_param.var.if_5_1.pack_mode
> > +               = IPIPEIF_5_1_PACK_12_BIT;
> > +           temp_pix_fmt = IPIPE_BAYER;
> > +           break;
> > +   default:
> > +           temp_pix_fmt = IPIPE_UYVY;
> > +   }
> > +
> > +   if (temp_pix_fmt == IPIPE_BAYER)
> > +           if (out_pix_fmt == IPIPE_BAYER)
> > +                   param->ipipe_dpaths_fmt = IPIPE_RAW2RAW;
> > +           else if ((out_pix_fmt == IPIPE_UYVY) ||
> > +                    (out_pix_fmt == IPIPE_YUV420SP))
> > +                   param->ipipe_dpaths_fmt = IPIPE_RAW2YUV;
> > +           else
> > +                   return -EINVAL;
>
> Using braces in the outermost if might make sense.
>
> > +   else if (temp_pix_fmt == IPIPE_UYVY) {
> > +           if (out_pix_fmt == IPIPE_UYVY)
> > +                   param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
> > +           else if (out_pix_fmt == IPIPE_YUV420SP)
> > +                   param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
> > +           else
> > +                   return -EINVAL;
> > +   }
> > +   return 0;
> > +}
>
> I wonder if the above function should rather deal with the
> v4l2_mbus_pixelcodes instead. Shouldn't VIDIOC_SUBDEV_S_FMT be used to
> configure this?
In fact it is the implementation of VIDIOC_SUBDEV_S_FMT at a lower level. But I will see if I can use v4l2_mbus_fmt for the enums.
>
> > +/*
> > + * calculate_resize_ratios()
> > + *   calculates resize ratio for resizer A or B. This is called after setting
> > + * the input size or output size
> > + */
> > +static void calculate_resize_ratios(struct ipipe_params *param, int index)
> > +{
> > +   param->rsz_rsc_param[index].h_dif =
> > +       ((param->ipipe_hsz + 1) * 256) /
> > +       (param->rsz_rsc_param[index].o_hsz + 1);
> > +   param->rsz_rsc_param[index].v_dif =
> > +       ((param->ipipe_vsz + 1) * 256) /
> > +       (param->rsz_rsc_param[index].o_vsz + 1);
> > +}
> > +
> > +static int ipipe_do_hw_setup(struct device *dev, void *config)
> > +{
> > +   struct ipipe_params *param = (struct ipipe_params *)config;
> > +   int ret;
> > +
> > +   dev_dbg(dev, "ipipe_do_hw_setup\n");
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +
> > +   if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS)) {
> > +           /* continuous mode */
> > +           param = oper_state.shared_config_param;
> > +           if (param->rsz_en[RSZ_A])
> > +                   calculate_resize_ratios(param, RSZ_A);
> > +           if (param->rsz_en[RSZ_B])
> > +                   calculate_resize_ratios(param, RSZ_B);
> > +           ret = ipipe_hw_setup(param);
> > +   }
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return ret;
> > +}
> > +
> > +static unsigned int ipipe_rsz_chain_state(void)
> > +{
> > +   return oper_state.rsz_chained;
> > +}
> > +
> > +static void ipipe_update_outbuf1_address(void *config, unsigned int address)
> > +{
> > +   if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS))
> > +           rsz_set_output_address(oper_state.shared_config_param,
> > +                                  0,
> > +                                  address);
> > +   else
> > +           rsz_set_output_address((struct ipipe_params *)config,
> > +                                  0,
> > +                                  address);
> > +}
> > +
> > +static void ipipe_update_outbuf2_address(void *config, unsigned int address)
> > +{
> > +   if ((ISNULL(config)) && (oper_mode == IMP_MODE_CONTINUOUS))
> > +           rsz_set_output_address(oper_state.shared_config_param,
> > +                                  1,
> > +                                  address);
> > +   else
> > +           rsz_set_output_address((struct ipipe_params *)config,
> > +                                  1,
> > +                                  address);
> > +}
> > +
> > +static void ipipe_enable(unsigned char en, void *config)
> > +{
> > +   unsigned char val = 0, ret = 0;
> > +   struct ipipe_params *param = (struct ipipe_params *)config;
> > +
> > +   if (en)
> > +           val = 1;
>
> You can en = !!en and drop val.
>
> > +   if (oper_mode == IMP_MODE_CONTINUOUS)
> > +           param = oper_state.shared_config_param;
> > +
> > +   if (en && param->rsz_common.source == IPIPE_DATA) {
> > +           /* wait for IPIPE to become inactive */
> > +           do {
> > +                   ret = regr_ip(IPIPE_SRC_EN);
> > +           } while (ret);
> > +
> > +           regw_ip(val, IPIPE_SRC_EN);
> > +   } else
> > +           regw_ip(0, IPIPE_SRC_EN);
> > +
> > +   if (en) {
> > +           /* wait for RSZ_SRC_EN to be reset by hardware */
> > +           do {
> > +                   ret = regr_rsz(RSZ_SRC_EN);
> > +           } while (ret);
> > +   }
> > +
> > +   if (param->rsz_en[RSZ_A]) {
> > +           if (en) {
> > +                   /* wait for RSZ-A to become inactive */
> > +                   do {
> > +                           ret = regr_rsz(RSZ_A);
> > +                   } while (ret);
> > +           }
> > +
> > +           rsz_enable(RSZ_A, en);
> > +   }
> > +   if (param->rsz_en[RSZ_B]) {
> > +           if (en) {
> > +                   /* wait for RSZ-B to become inactive */
> > +                   do {
> > +                           ret = regr_rsz(RSZ_B);
> > +                   } while (ret);
> > +           }
> > +
> > +           rsz_enable(RSZ_B, en);
> > +   }
> > +   if (oper_mode == IMP_MODE_SINGLE_SHOT) {
> > +           /* wait for IPIPEIF ENABLE.ENABLE to be reset by hardware */
> > +           if (en) {
> > +                   do {
> > +                           ret = ipipeif_get_enable();
> > +                   } while (ret & 0x1);
> > +           }
> > +
> > +    ipipeif_set_enable(val, oper_mode);
>
> Indentation.
Ok.
>
> > +   }
> > +}
> > +
> > +static int validate_lutdpc_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   int i;
> > +
> > +   if (lutdpc.en > 1 ||
> > +       lutdpc.repl_white > 1 ||
> > +       lutdpc.dpc_size > LUT_DPC_MAX_SIZE)
> > +           return -EINVAL;
> > +   if (lutdpc.en && (ISNULL(lutdpc.table)))
> > +           return -EINVAL;
> > +   for (i = 0; i < lutdpc.dpc_size; i++) {
> > +           if (lutdpc.table[i].horz_pos > LUT_DPC_H_POS_MASK ||
> > +               lutdpc.table[i].vert_pos > LUT_DPC_V_POS_MASK)
> > +                   return -EINVAL;
> > +   }
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_lutdpc_params(struct device *dev, void *param, int len)
> > +{
> > +   struct ipipe_lutdpc_entry *temp_lutdpc;
> > +   struct prev_lutdpc dpc_param;
> > +
> > +   if (ISNULL(param)) {
> > +           /* Copy defaults for dfc */
> > +           temp_lutdpc = lutdpc.table;
> > +           memcpy((void *)&lutdpc,
> > +                  (void *)&dm365_lutdpc_defaults,
> > +                  sizeof(struct prev_lutdpc));
> > +           lutdpc.table = temp_lutdpc;
> > +           goto success;
> > +   }
> > +
> > +   if (len != sizeof(struct prev_lutdpc)) {
> > +           dev_err(dev,
> > +                   "set_lutdpc_params: param struct length"
> > +                   " mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&dpc_param,
> > +                       (struct prev_lutdpc *)param,
> > +                       sizeof(struct prev_lutdpc))) {
> > +           dev_err(dev,
> > +                   "set_lutdpc_params: Error in copy to kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   if (ISNULL(dpc_param.table)) {
> > +           dev_err(dev, "Invalid user dpc table ptr\n");
> > +           return -EINVAL;
> > +   }
> > +   lutdpc.en = dpc_param.en;
> > +   lutdpc.repl_white = dpc_param.repl_white;
> > +   lutdpc.dpc_size = dpc_param.dpc_size;
> > +   if (copy_from_user
> > +           (lutdpc.table,
> > +           (struct ipipe_dpc_entry *)dpc_param.table,
> > +           (lutdpc.dpc_size *
> > +           sizeof(struct ipipe_lutdpc_entry)))) {
> > +           dev_err(dev,
> > +                   "set_lutdpc_params: Error in copying "
> > +                   "dfc table to kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   if (validate_lutdpc_params(dev) < 0)
> > +           return -EINVAL;
> > +
> > +
> > +success:
> > +   ipipe_set_lutdpc_regs(&lutdpc);
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_lutdpc_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_lutdpc *lut_param = (struct prev_lutdpc *)param;
> > +   struct prev_lutdpc user_lutdpc;
> > +
> > +   if (ISNULL(lut_param)) {
> > +           dev_err(dev, "get_lutdpc_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_lutdpc)) {
> > +           dev_err(dev,
> > +                   "get_lutdpc_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&user_lutdpc,
> > +                      lut_param,
> > +                      sizeof(struct prev_lutdpc))) {
> > +           dev_err(dev, "get_lutdpc_params: Error in copy to  kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   user_lutdpc.en = lutdpc.en;
> > +   user_lutdpc.repl_white = lutdpc.repl_white;
> > +   user_lutdpc.dpc_size = lutdpc.dpc_size;
> > +   if (ISNULL(user_lutdpc.table)) {
> > +           dev_err(dev, "get_lutdpc_params:" " Invalid table ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(user_lutdpc.table,
> > +                    lutdpc.table,
> > +                    (lutdpc.dpc_size *
> > +                     sizeof(struct ipipe_lutdpc_entry)))) {
> > +           dev_err(dev,
> > +                   "get_lutdpc_params:Table Error in" " copy to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   if (copy_to_user(lut_param,
> > +                    &user_lutdpc,
> > +                    sizeof(struct prev_lutdpc))) {
> > +           dev_err(dev, "get_lutdpc_params: Error in copy" " to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_otfdpc_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
>
> Are there cases where you wouldn't want the parameters to be validated?
No. I will remove the define and checks
>
> > +   struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)&otfdpc;
> > +   struct prev_otfdpc_2_0 *dpc_2_0;
> > +   struct prev_otfdpc_3_0 *dpc_3_0;
> > +
> > +   if (dpc_param->en > 1)
> > +           return -EINVAL;
> > +   if (dpc_param->alg == IPIPE_OTFDPC_2_0) {
> > +           dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0;
> > +           if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK ||
> > +               dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK)
> > +                   return -EINVAL;
> > +   } else {
> > +           dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0;
> > +           if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK ||
> > +               dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK ||
> > +               dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK ||
> > +               dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK ||
> > +               dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK ||
> > +               dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK ||
> > +               dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK ||
> > +               dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK ||
> > +               dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK)
> > +                   return -EINVAL;
> > +   }
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_otfdpc_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)param;
> > +
> > +   if (ISNULL(param)) {
> > +           /* Copy defaults for dpc2.0 defaults */
> > +           memcpy((void *)&otfdpc,
> > +                  (void *)&dm365_otfdpc_defaults,
> > +                  sizeof(struct ipipe_otfdpc_2_0));
> > +   } else {
> > +           if (len != sizeof(struct prev_otfdpc)) {
> > +                   dev_err(dev,
> > +                           "set_otfdpc_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&otfdpc,
> > +                              dpc_param,
> > +                              sizeof(struct prev_otfdpc))) {
> > +                   dev_err(dev,
> > +                           "set_otfdpc_params: Error in "
> > +                           "copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +
> > +           if (validate_otfdpc_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_otfdpc_regs(&otfdpc);
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_otfdpc_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_otfdpc *dpc_param = (struct prev_otfdpc *)param;
> > +
> > +   if (ISNULL(dpc_param)) {
> > +           dev_err(dev, "get_otfdpc_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_otfdpc)) {
> > +           dev_err(dev,
> > +                   "get_otfdpc_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(dpc_param,
> > +                    &otfdpc,
> > +                    sizeof(struct prev_otfdpc))) {
> > +           dev_err(dev,
> > +                   "get_otfdpc_params: Error in copy dpc "
> > +                   "table to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_nf_params(struct device *dev, unsigned int id)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   struct prev_nf *nf_param = &nf1;
> > +   int i;
> > +
> > +   if (id)
> > +           nf_param = &nf2;
> > +   if (nf_param->en > 1 ||
> > +       nf_param->shft_val > D2F_SHFT_VAL_MASK ||
> > +       nf_param->spread_val > D2F_SPR_VAL_MASK ||
> > +       nf_param->apply_lsc_gain > 1 ||
> > +       nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK ||
> > +       nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK)
> > +           return -EINVAL;
> > +
> > +   for (i = 0; i < IPIPE_NF_THR_TABLE_SIZE; i++)
> > +           if (nf_param->thr[i] > D2F_THR_VAL_MASK)
> > +                   return -EINVAL;
> > +   for (i = 0; i < IPIPE_NF_STR_TABLE_SIZE; i++)
> > +           if (nf_param->str[i] > D2F_STR_VAL_MASK)
> > +                   return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_nf_params(struct device *dev, unsigned int id,
> > +                    void *param, int len)
> > +{
> > +   struct prev_nf *nf_param = (struct prev_nf *)param;
> > +   struct prev_nf *nf = &nf1;
> > +
> > +   if (id)
> > +           nf = &nf2;
> > +
> > +   if (ISNULL(nf_param)) {
> > +           /* Copy defaults for nf */
> > +           memcpy((void *)nf,
> > +                  (void *)&dm365_nf_defaults,
> > +                  sizeof(struct prev_nf));
> > +           memset((void *)nf->thr, 0, IPIPE_NF_THR_TABLE_SIZE);
> > +           memset((void *)nf->str, 0, IPIPE_NF_THR_TABLE_SIZE);
> > +   } else {
> > +           if (len != sizeof(struct prev_nf)) {
> > +                   dev_err(dev,
> > +                           "set_nf_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(nf, nf_param, sizeof(struct prev_nf))) {
> > +                   dev_err(dev,
> > +                           "set_nf_params: Error in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_nf_params(dev, id) < 0)
> > +                   return -EINVAL;
> > +   }
> > +   /* Now set the values in the hw */
> > +   ipipe_set_d2f_regs(id, nf);
> > +
> > +   return 0;
> > +}
> > +
> > +static int set_nf1_params(struct device *dev, void *param, int len)
> > +{
> > +   return set_nf_params(dev, 0, param, len);
> > +}
> > +
> > +static int set_nf2_params(struct device *dev, void *param, int len)
> > +{
> > +   return set_nf_params(dev, 1, param, len);
> > +}
> > +
> > +static int get_nf_params(struct device *dev, unsigned int id, void *param,
> > +                    int len)
> > +{
> > +   struct prev_nf *nf_param = (struct prev_nf *)param;
> > +   struct prev_nf *nf = &nf1;
> > +
> > +   if (ISNULL(nf_param)) {
> > +           dev_err(dev, "get_nf_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_nf)) {
> > +           dev_err(dev,
> > +                   "get_nf_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (id)
> > +           nf = &nf2;
> > +   if (copy_to_user((struct prev_nf *)nf_param, nf,
> > +                    sizeof(struct prev_nf))) {
> > +           dev_err(dev, "get_nf_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_nf1_params(struct device *dev, void *param, int len)
> > +{
> > +   return get_nf_params(dev, 0, param, len);
> > +}
> > +
> > +static int get_nf2_params(struct device *dev, void *param, int len)
> > +{
> > +   return get_nf_params(dev, 1, param, len);
> > +}
> > +
> > +static int validate_gic_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (gic.en > 1 ||
> > +       gic.gain > GIC_GAIN_MASK ||
> > +       gic.thr > GIC_THR_MASK ||
> > +       gic.slope > GIC_SLOPE_MASK ||
> > +       gic.apply_lsc_gain > 1 ||
> > +       gic.nf2_thr_gain.integer > GIC_NFGAN_INT_MASK ||
> > +       gic.nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK)
> > +           return -1;
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_gic_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_gic *gic_param = (struct prev_gic *)param;
> > +
> > +   if (ISNULL(gic_param)) {
> > +           /* Copy defaults for nf */
> > +           memcpy((void *)&gic,
> > +                  (void *)&dm365_gic_defaults,
> > +                  sizeof(struct prev_gic));
> > +   } else {
> > +           if (len != sizeof(struct prev_gic)) {
> > +                   dev_err(dev,
> > +                           "set_gic_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&gic, gic_param, sizeof(struct prev_gic))) {
> > +                   dev_err(dev,
> > +                           "set_gic_params: Error in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_gic_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +   /* Now set the values in the hw */
> > +   ipipe_set_gic_regs(&gic);
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_gic_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_gic *gic_param = (struct prev_gic *)param;
> > +
> > +   if (ISNULL(gic_param)) {
> > +           dev_err(dev, "get_gic_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (len != sizeof(struct prev_gic)) {
> > +           dev_err(dev,
> > +                   "get_gic_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (copy_to_user((struct prev_gic *)gic_param,
> > +                    &gic,
> > +                    sizeof(struct prev_gic))) {
> > +           dev_err(dev, "get_gic_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_wb_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (wb.ofst_r > WB_OFFSET_MASK ||
> > +       wb.ofst_gr > WB_OFFSET_MASK ||
> > +       wb.ofst_gb > WB_OFFSET_MASK ||
> > +       wb.ofst_b > WB_OFFSET_MASK ||
> > +       wb.gain_r.integer > WB_GAIN_INT_MASK ||
> > +       wb.gain_r.decimal > WB_GAIN_DECI_MASK ||
> > +       wb.gain_gr.integer > WB_GAIN_INT_MASK ||
> > +       wb.gain_gr.decimal > WB_GAIN_DECI_MASK ||
> > +       wb.gain_gb.integer > WB_GAIN_INT_MASK ||
> > +       wb.gain_gb.decimal > WB_GAIN_DECI_MASK ||
> > +       wb.gain_b.integer > WB_GAIN_INT_MASK ||
> > +       wb.gain_b.decimal > WB_GAIN_DECI_MASK)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +static int set_wb_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_wb *wb_param = (struct prev_wb *)param;
> > +
> > +   dev_dbg(dev, "set_wb_params");
> > +   if (ISNULL(wb_param)) {
> > +           /* Copy defaults for wb */
> > +           memcpy((void *)&wb,
> > +                  (void *)&dm365_wb_defaults,
> > +                  sizeof(struct prev_wb));
> > +   } else {
> > +           if (len != sizeof(struct prev_wb)) {
> > +                   dev_err(dev,
> > +                           "set_wb_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&wb, wb_param, sizeof(struct prev_wb))) {
> > +                   dev_err(dev,
> > +                           "set_wb_params: Error in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_wb_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   /* Now set the values in the hw */
> > +   ipipe_set_wb_regs(&wb);
> > +
> > +   return 0;
> > +}
> > +static int get_wb_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_wb *wb_param = (struct prev_wb *)param;
> > +
> > +   if (ISNULL(wb_param)) {
> > +           dev_err(dev, "get_wb_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_wb)) {
> > +           dev_err(dev,
> > +                   "get_wb_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user((struct prev_wb *)wb_param,
> > +                    &wb,
> > +                    sizeof(struct prev_wb))) {
> > +           dev_err(dev, "get_wb_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_cfa_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (cfa.hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK ||
> > +       cfa.hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK ||
> > +       cfa.hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK ||
> > +       cfa.hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK ||
> > +       cfa.dir_thr_2dir > CFA_DIR_THR_2DIR_MASK ||
> > +       cfa.dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK ||
> > +       cfa.nd_wt_2dir > CFA_ND_WT_2DIR_MASK ||
> > +       cfa.hue_fract_daa > CFA_DAA_HUE_FRA_MASK ||
> > +       cfa.edge_thr_daa > CFA_DAA_EDG_THR_MASK ||
> > +       cfa.thr_min_daa > CFA_DAA_THR_MIN_MASK ||
> > +       cfa.thr_slope_daa > CFA_DAA_THR_SLP_MASK ||
> > +       cfa.slope_min_daa > CFA_DAA_SLP_MIN_MASK ||
> > +       cfa.slope_slope_daa > CFA_DAA_SLP_SLP_MASK ||
> > +       cfa.lp_wt_daa > CFA_DAA_LP_WT_MASK)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +static int set_cfa_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_cfa *cfa_param = (struct prev_cfa *)param;
> > +
> > +   dev_dbg(dev, "set_cfa_params");
> > +   if (ISNULL(cfa_param)) {
> > +           /* Copy defaults for wb */
> > +           memcpy((void *)&cfa,
> > +                  (void *)&dm365_cfa_defaults,
> > +                  sizeof(struct prev_cfa));
> > +   } else {
> > +           if (len != sizeof(struct prev_cfa)) {
> > +                   dev_err(dev,
> > +                           "set_cfa_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&cfa, cfa_param, sizeof(struct prev_cfa))) {
> > +                   dev_err(dev,
> > +                           "set_cfa_params: Error in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_cfa_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   /* Now set the values in the hw */
> > +   ipipe_set_cfa_regs(&cfa);
> > +
> > +   return 0;
> > +}
> > +static int get_cfa_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_cfa *cfa_param = (struct prev_cfa *)param;
> > +
> > +   dev_dbg(dev, "get_cfa_params\n");
> > +   if (ISNULL(cfa_param)) {
> > +           dev_err(dev, "get_cfa_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_cfa)) {
> > +           dev_err(dev,
> > +                   "get_cfa_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user((struct prev_cfa *)cfa_param,
> > +                    &cfa,
> > +                    sizeof(struct prev_cfa))) {
> > +           dev_err(dev, "get_cfa_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_rgb2rgb_params(struct device *dev, unsigned int id)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
> > +   u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK;
> > +   u32 offset_upper = RGB2RGB_1_OFST_MASK;
> > +
> > +   if (id) {
> > +           rgb2rgb = &rgb2rgb_2;
> > +           offset_upper = RGB2RGB_2_OFST_MASK;
> > +           gain_int_upper = RGB2RGB_2_GAIN_INT_MASK;
> > +   }
> > +   if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_rr.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_gr.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_br.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_rg.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_gg.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_bg.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_rb.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_gb.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK ||
> > +       rgb2rgb->coef_bb.integer > gain_int_upper)
> > +           return -EINVAL;
> > +
> > +   if (rgb2rgb->out_ofst_r > offset_upper ||
> > +       rgb2rgb->out_ofst_g > offset_upper ||
> > +       rgb2rgb->out_ofst_b > offset_upper)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_rgb2rgb_params(struct device *dev, unsigned int id,
> > +                         void *param, int len)
> > +{
> > +   struct prev_rgb2rgb *rgb2rgb_param = (struct prev_rgb2rgb *)param;
> > +   struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
> > +
> > +   if (id)
> > +           rgb2rgb = &rgb2rgb_2;
> > +   if (ISNULL(rgb2rgb_param)) {
> > +           /* Copy defaults for rgb2rgb conversion */
> > +           memcpy((void *)rgb2rgb,
> > +                  (void *)&dm365_rgb2rgb_defaults,
> > +                  sizeof(struct prev_rgb2rgb));
> > +   } else {
> > +
> > +           if (len != sizeof(struct prev_rgb2rgb)) {
> > +                   dev_err(dev,
> > +                           "set_rgb2rgb_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +
> > +           if (copy_from_user(rgb2rgb,
> > +                              rgb2rgb_param,
> > +                              sizeof(struct prev_rgb2rgb))) {
> > +                   dev_err(dev,
> > +                           "set_rgb2rgb_params: Error in "
> > +                           "copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_rgb2rgb_params(dev, id) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_rgb2rgb_regs(id, rgb2rgb);
> > +
> > +   return 0;
> > +}
> > +
> > +static int set_rgb2rgb_1_params(struct device *dev, void *param, int len)
> > +{
> > +   return set_rgb2rgb_params(dev, 0, param, len);
> > +}
> > +
> > +static int set_rgb2rgb_2_params(struct device *dev, void *param, int len)
> > +{
> > +   return set_rgb2rgb_params(dev, 1, param, len);
> > +}
> > +
> > +static int get_rgb2rgb_params(struct device *dev, unsigned int id,
> > +                         void *param, int len)
> > +{
> > +   struct prev_rgb2rgb *rgb2rgb_param = (struct prev_rgb2rgb *)param;
> > +   struct prev_rgb2rgb *rgb2rgb = &rgb2rgb_1;
> > +
> > +   if (ISNULL(rgb2rgb_param)) {
> > +           dev_err(dev, "get_rgb2rgb_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (len != sizeof(struct prev_rgb2rgb)) {
> > +           dev_err(dev,
> > +                   "get_rgb2rgb_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (id)
> > +           rgb2rgb = &rgb2rgb_2;
> > +   if (copy_to_user((struct prev_rgb2rgb *)rgb2rgb_param,
> > +                    rgb2rgb,
> > +                    sizeof(struct prev_rgb2rgb))) {
> > +           dev_err(dev, "get_rgb2rgb_params: Error in copy to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_rgb2rgb_1_params(struct device *dev, void *param, int len)
> > +{
> > +   return get_rgb2rgb_params(dev, 0, param, len);
> > +}
> > +
> > +static int get_rgb2rgb_2_params(struct device *dev, void *param, int len)
> > +{
> > +   return get_rgb2rgb_params(dev, 1, param, len);
> > +}
> > +
> > +static int validate_gamma_entry(struct ipipe_gamma_entry *table, int size)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   int i;
> > +
> > +   if (ISNULL(table))
> > +           return -EINVAL;
> > +
> > +   for (i = 0; i < size; i++) {
> > +           if (table[i].slope > GAMMA_MASK ||
> > +               table[i].offset > GAMMA_MASK)
> > +                   return -EINVAL;
> > +   }
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int validate_gamma_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   int table_size;
> > +   int err;
> > +
> > +   if (gamma.bypass_r > 1 ||
> > +       gamma.bypass_b > 1 ||
> > +       gamma.bypass_g > 1)
> > +           return -EINVAL;
> > +
> > +   if (gamma.tbl_sel != IPIPE_GAMMA_TBL_RAM)
> > +           return 0;
> > +
> > +   table_size = gamma.tbl_size;
> > +   if (!gamma.bypass_r) {
> > +           err = validate_gamma_entry(gamma.table_r, table_size);
> > +           if (err) {
> > +                   dev_err(dev, "GAMMA R - table entry invalid\n");
> > +                   return err;
> > +           }
> > +   }
> > +   if (!gamma.bypass_b) {
> > +           err = validate_gamma_entry(gamma.table_b, table_size);
> > +           if (err) {
> > +                   dev_err(dev, "GAMMA B - table entry invalid\n");
> > +                   return err;
> > +           }
> > +   }
> > +   if (!gamma.bypass_g) {
> > +           err = validate_gamma_entry(gamma.table_g, table_size);
> > +           if (err) {
> > +                   dev_err(dev, "GAMMA G - table entry invalid\n");
> > +                   return err;
> > +           }
> > +   }
> > +#endif
> > +   return 0;
> > +}
> > +static int set_gamma_params(struct device *dev, void *param, int len)
> > +{
> > +
> > +   struct prev_gamma *gamma_param = (struct prev_gamma *)param;
> > +   struct prev_gamma user_gamma;
> > +   int table_size;
> > +
> > +   if (ISNULL(gamma_param)) {
> > +           /* Copy defaults for gamma */
> > +           gamma.bypass_r = dm365_gamma_defaults.bypass_r;
> > +           gamma.bypass_g = dm365_gamma_defaults.bypass_g;
> > +           gamma.bypass_b = dm365_gamma_defaults.bypass_b;
> > +           gamma.tbl_sel = dm365_gamma_defaults.tbl_sel;
> > +           gamma.tbl_size = dm365_gamma_defaults.tbl_size;
> > +           /* By default, we bypass the gamma correction.
> > +            * So no values by default for tables
> > +            */
> > +           goto success;
> > +   }
> > +
> > +   if (len != sizeof(struct prev_gamma)) {
> > +           dev_err(dev,
> > +                   "set_gamma_params: param struct length"
> > +                   " mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&user_gamma, gamma_param,
> > +                       sizeof(struct prev_gamma))) {
> > +           dev_err(dev,
> > +                   "set_gamma_params: Error in copy to kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   if (validate_gamma_params(dev) < 0)
> > +           return -EINVAL;
> > +
> > +   gamma.bypass_r = user_gamma.bypass_r;
> > +   gamma.bypass_b = user_gamma.bypass_b;
> > +   gamma.bypass_g = user_gamma.bypass_g;
> > +   gamma.tbl_sel = user_gamma.tbl_sel;
> > +   gamma.tbl_size = user_gamma.tbl_size;
> > +
> > +   if (user_gamma.tbl_sel != IPIPE_GAMMA_TBL_RAM)
> > +           goto success;
> > +
> > +   table_size = user_gamma.tbl_size;
> > +
> > +   if (!user_gamma.bypass_r) {
> > +           if (ISNULL(user_gamma.table_r)) {
> > +                   dev_err(dev,
> > +                           "set_gamma_params: Invalid"
> > +                           " table ptr for R\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(gamma.table_r,
> > +                               user_gamma.table_r,
> > +                               (table_size *
> > +                               sizeof(struct \
> > +                               ipipe_gamma_entry)))) {
> > +                   dev_err(dev,
> > +                           "set_gamma_params: R-Error"
> > +                           " in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +   }
> > +
> > +   if (!user_gamma.bypass_b) {
> > +           if (ISNULL(user_gamma.table_b)) {
> > +                   dev_err(dev,
> > +                           "set_gamma_params: Invalid"
> > +                           " table ptr for B\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(gamma.table_b,
> > +                               user_gamma.table_b,
> > +                               (table_size *
> > +                               sizeof(struct \
> > +                               ipipe_gamma_entry)))) {
> > +                   dev_err(dev,
> > +                           "set_gamma_params: B-Error"
> > +                           " in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +   }
> > +
> > +   if (!user_gamma.bypass_g) {
> > +           if (ISNULL(user_gamma.table_g)) {
> > +                   dev_err(dev,
> > +                           "set_gamma_params: Invalid"
> > +                           " table ptr for G\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(gamma.table_g,
> > +                               user_gamma.table_g,
> > +                               (table_size *
> > +                               sizeof(struct \
> > +                               ipipe_gamma_entry)))) {
> > +                   dev_err(dev,
> > +                           "set_gamma_params: G-Error "
> > +                           "in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +   }
> > +
> > +success:
> > +   ipipe_set_gamma_regs(&gamma);
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_gamma_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_gamma *gamma_param = (struct prev_gamma *)param;
> > +   struct prev_gamma user_gamma;
> > +   int table_size;
> > +
> > +   if (ISNULL(gamma_param)) {
> > +           dev_err(dev, "get_gamma_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_gamma)) {
> > +           dev_err(dev,
> > +                   "get_gamma_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&user_gamma,
> > +                      gamma_param,
> > +                      sizeof(struct prev_gamma))) {
> > +           dev_err(dev, "get_gamma_params: Error in copy to kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   user_gamma.bypass_r = gamma.bypass_r;
> > +   user_gamma.bypass_g = gamma.bypass_g;
> > +   user_gamma.bypass_b = gamma.bypass_b;
> > +   user_gamma.tbl_sel = gamma.tbl_sel;
> > +   user_gamma.tbl_size = gamma.tbl_size;
> > +   if (gamma.tbl_sel == IPIPE_GAMMA_TBL_RAM) {
> > +           table_size = gamma.tbl_size;
> > +
> > +           if ((!gamma.bypass_r) && ((ISNULL(user_gamma.table_r)))) {
> > +                   dev_err(dev,
> > +                           "get_gamma_params: table ptr empty for R\n");
> > +                   return -EINVAL;
> > +           } else {
> > +                   if (copy_to_user(user_gamma.table_r,
> > +                                    gamma.table_r,
> > +                                    (table_size *
> > +                                    sizeof(struct ipipe_gamma_entry)))) {
> > +                           dev_err(dev,
> > +                                   "set_gamma_params: R-Table Error in"
> > +                                   " copy to user\n");
> > +                           return -EFAULT;
> > +                   }
> > +           }
> > +
> > +           if ((!gamma.bypass_b) && ((ISNULL(user_gamma.table_b)))) {
> > +                   dev_err(dev,
> > +                           "get_gamma_params: table ptr empty for B\n");
> > +                   return -EINVAL;
> > +           } else {
> > +                   if (copy_to_user(user_gamma.table_b,
> > +                                    gamma.table_b,
> > +                                    (table_size *
> > +                                     sizeof(struct ipipe_gamma_entry)))) {
> > +                           dev_err(dev,
> > +                                   "set_gamma_params: B-Table Error in"
> > +                                   " copy to user\n");
> > +                           return -EFAULT;
> > +                   }
> > +           }
> > +
> > +           if ((!gamma.bypass_g) && ((ISNULL(user_gamma.table_g)))) {
> > +                   dev_err(dev,
> > +                           "get_gamma_params: table ptr empty for G\n");
> > +                   return -EINVAL;
> > +           } else {
> > +                   if (copy_from_user(gamma.table_g,
> > +                           user_gamma.table_g,
> > +                           (table_size *
> > +                           sizeof(struct ipipe_gamma_entry)))) {
> > +                           dev_err(dev,
> > +                                   "set_gamma_params: G-Table"
> > +                                   "copy error\n");
> > +                           return -EFAULT;
> > +                   }
> > +           }
> > +
> > +   }
> > +   if (copy_to_user(gamma_param, &user_gamma,
> > +           sizeof(struct prev_gamma))) {
> > +           dev_err(dev, "get_dfc_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_3d_lut_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   int i;
> > +
> > +   if (!lut_3d.en)
> > +           return 0;
> > +
> > +   for (i = 0; i < MAX_SIZE_3D_LUT; i++) {
> > +           if (lut_3d.table[i].r > D3_LUT_ENTRY_MASK ||
> > +               lut_3d.table[i].g > D3_LUT_ENTRY_MASK ||
> > +               lut_3d.table[i].b > D3_LUT_ENTRY_MASK)
> > +                   return -EINVAL;
> > +   }
> > +#endif
> > +   return 0;
> > +}
> > +static int set_3d_lut_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_3d_lut *lut_param = (struct prev_3d_lut *)param;
> > +   struct prev_3d_lut user_3d_lut;
> > +
> > +   if (ISNULL(lut_param)) {
> > +           /* Copy defaults for gamma */
> > +           lut_3d.en = dm365_3d_lut_defaults.en;
> > +           /* By default, 3D lut is disabled
> > +            */
> > +   } else {
> > +           if (len != sizeof(struct prev_3d_lut)) {
> > +                   dev_err(dev,
> > +                           "set_3d_lut_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&user_3d_lut,
> > +                              lut_param,
> > +                              sizeof(struct prev_3d_lut))) {
> > +                   dev_err(dev,
> > +                           "set_3d_lut_params: Error in copy to"
> > +                           " kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           lut_3d.en = user_3d_lut.en;
> > +           if (ISNULL(user_3d_lut.table)) {
> > +                   dev_err(dev, "set_3d_lut_params: Invalid table ptr");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(lut_3d.table,
> > +                              user_3d_lut.table,
> > +                              (MAX_SIZE_3D_LUT *
> > +                              sizeof(struct ipipe_3d_lut_entry)))) {
> > +                   dev_err(dev,
> > +                           "set_3d_lut_params:Error"
> > +                           " in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +
> > +           if (validate_3d_lut_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_3d_lut_regs(&lut_3d);
> > +
> > +   return 0;
> > +}
> > +static int get_3d_lut_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_3d_lut *lut_param = (struct prev_3d_lut *)param;
> > +   struct prev_3d_lut user_3d_lut;
> > +
> > +   if (ISNULL(lut_param)) {
> > +           dev_err(dev, "get_3d_lut_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_3d_lut)) {
> > +           dev_err(dev,
> > +                   "get_3d_lut_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&user_3d_lut,
> > +                      lut_param,
> > +                      sizeof(struct prev_3d_lut))) {
> > +           dev_err(dev, "get_3d_lut_params: Error in copy to kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   user_3d_lut.en = lut_3d.en;
> > +   if (ISNULL(user_3d_lut.table)) {
> > +           dev_err(dev, "get_3d_lut_params:" " Invalid table ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(user_3d_lut.table, lut_3d.table,
> > +                    (MAX_SIZE_3D_LUT *
> > +                     sizeof(struct ipipe_3d_lut_entry)))) {
> > +           dev_err(dev,
> > +                   "get_3d_lut_params:Table Error in" " copy to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   if (copy_to_user(lut_param, &user_3d_lut,
> > +           sizeof(struct prev_3d_lut))) {
> > +           dev_err(dev, "get_3d_lut_params: Error in copy" " to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_lum_adj_params(struct device *dev)
> > +{
> > +   /* nothing to validate */
> > +   return 0;
> > +}
> > +
> > +static int set_lum_adj_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_lum_adj *lum_adj_param = (struct prev_lum_adj *)param;
> > +
> > +   if (ISNULL(lum_adj_param)) {
> > +           /* Copy defaults for Luminance adjustments */
> > +           memcpy((void *)&lum_adj,
> > +                  (void *)&dm365_lum_adj_defaults,
> > +                  sizeof(struct prev_lum_adj));
> > +   } else {
> > +           if (len != sizeof(struct prev_lum_adj)) {
> > +                   dev_err(dev,
> > +                           "set_lum_adj_params: param struct length"
> > +                           " mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&lum_adj,
> > +                              lum_adj_param,
> > +                              sizeof(struct prev_lum_adj))) {
> > +                   dev_err(dev,
> > +                           "set_lum_adj_params: Error in copy"
> > +                           " from user\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_lum_adj_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_lum_adj_regs(&lum_adj);
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_lum_adj_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_lum_adj *lum_adj_param = (struct prev_lum_adj *)param;
> > +
> > +   if (ISNULL(lum_adj_param)) {
> > +           dev_err(dev, "get_lum_adj_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (len != sizeof(struct prev_lum_adj)) {
> > +           dev_err(dev,
> > +                   "get_lum_adj_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (copy_to_user(lum_adj_param,
> > +                    &lum_adj,
> > +                    sizeof(struct prev_lum_adj))) {
> > +           dev_err(dev, "get_lum_adj_params: Error in copy to" " user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_rgb2yuv_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (rgb2yuv.coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_ry.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_gy.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_by.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
> > +       rgb2yuv.coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (rgb2yuv.out_ofst_y > RGB2YCBCR_OFST_MASK ||
> > +       rgb2yuv.out_ofst_cb > RGB2YCBCR_OFST_MASK ||
> > +       rgb2yuv.out_ofst_cr > RGB2YCBCR_OFST_MASK)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +static int set_rgb2yuv_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_rgb2yuv *rgb2yuv_param = (struct prev_rgb2yuv *)param;
> > +
> > +   if (ISNULL(rgb2yuv_param)) {
> > +           /* Copy defaults for rgb2yuv conversion  */
> > +           memcpy((void *)&rgb2yuv,
> > +                  (void *)&dm365_rgb2yuv_defaults,
> > +                  sizeof(struct prev_rgb2yuv));
> > +   } else {
> > +           if (len != sizeof(struct prev_rgb2yuv)) {
> > +                   dev_err(dev,
> > +                           "set_rgb2yuv_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&rgb2yuv,
> > +                              rgb2yuv_param,
> > +                              sizeof(struct prev_rgb2yuv))) {
> > +                   dev_err(dev,
> > +                           "set_rgb2yuv_params: Error in copy from"
> > +                           " user\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_rgb2yuv_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_rgb2ycbcr_regs(&rgb2yuv);
> > +
> > +   return 0;
> > +}
> > +static int get_rgb2yuv_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_rgb2yuv *rgb2yuv_param = (struct prev_rgb2yuv *)param;
> > +
> > +   if (ISNULL(rgb2yuv_param)) {
> > +           dev_err(dev, "get_rgb2yuv_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_rgb2yuv)) {
> > +           dev_err(dev,
> > +                   "get_rgb2yuv_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user((struct prev_rgb2yuv *)rgb2yuv_param,
> > +                    &rgb2yuv,
> > +                    sizeof(struct prev_rgb2yuv))) {
> > +           dev_err(dev, "get_rgb2yuv_params: Error in copy from"
> > +                   " kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_gbce_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   u32 max = GBCE_Y_VAL_MASK;
> > +   int i;
> > +
> > +   if (!gbce.en)
> > +           return 0;
> > +
> > +   if (gbce.type == IPIPE_GBCE_GAIN_TBL)
> > +           max = GBCE_GAIN_VAL_MASK;
> > +   for (i = 0; i < MAX_SIZE_GBCE_LUT; i++)
> > +           if (gbce.table[i] > max)
> > +                   return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +static int set_gbce_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_gbce *gbce_param = (struct prev_gbce *)param;
> > +   struct prev_gbce user_gbce;
> > +
> > +   if (ISNULL(gbce_param))
> > +           /* Copy defaults for gamma */
> > +           gbce.en = dm365_gbce_defaults.en;
> > +           /* By default, GBCE is disabled
> > +            */
> > +   else {
> > +           if (len != sizeof(struct prev_gbce)) {
> > +                   dev_err(dev,
> > +                           "set_gbce_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&user_gbce,
> > +                              gbce_param,
> > +                              sizeof(struct prev_gbce))) {
> > +                   dev_err(dev,
> > +                           "set_gbce_params: Error in copy to"
> > +                           " kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           gbce.en = user_gbce.en;
> > +           gbce.type = user_gbce.type;
> > +           if (ISNULL(user_gbce.table)) {
> > +                   dev_err(dev, "set_gbce_params:" " Invalid table ptr");
> > +                   return -EINVAL;
> > +           }
> > +
> > +           if (copy_from_user(gbce.table,
> > +                              user_gbce.table,
> > +                              (MAX_SIZE_GBCE_LUT *
> > +                              sizeof(unsigned short)))) {
> > +                   dev_err(dev, "set_gbce_params:Error"
> > +                                   " in copy to kernel\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_gbce_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_gbce_regs(&gbce);
> > +
> > +   return 0;
> > +}
> > +static int get_gbce_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_gbce *gbce_param = (struct prev_gbce *)param;
> > +   struct prev_gbce user_gbce;
> > +
> > +   if (ISNULL(gbce_param)) {
> > +           dev_err(dev, "get_gbce_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_gbce)) {
> > +           dev_err(dev,
> > +                   "get_gbce_params: param struct length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&user_gbce, gbce_param, sizeof(struct prev_gbce))) {
> > +           dev_err(dev, "get_gbce_params: Error in copy to" " kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   user_gbce.en = gbce.en;
> > +   user_gbce.type = gbce.type;
> > +   if (ISNULL(user_gbce.table)) {
> > +           dev_err(dev, "get_gbce_params:" " Invalid table ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(user_gbce.table,
> > +                    gbce.table,
> > +                    (MAX_SIZE_GBCE_LUT *
> > +                    sizeof(unsigned short)))) {
> > +           dev_err(dev,
> > +                   "get_gbce_params:Table Error in" " copy to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   if (copy_to_user(gbce_param, &user_gbce, sizeof(struct prev_gbce))) {
> > +           dev_err(dev, "get_gbce_params: Error in copy" " to user\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_yuv422_conv_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (yuv422_conv.en_chrom_lpf > 1)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_yuv422_conv_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_yuv422_conv *yuv422_conv_param =
> > +       (struct prev_yuv422_conv *)param;
> > +
> > +   if (ISNULL(yuv422_conv_param)) {
> > +           /* Copy defaults for yuv 422 conversion */
> > +           memcpy((void *)&yuv422_conv,
> > +                  (void *)&dm365_yuv422_conv_defaults,
> > +                  sizeof(struct prev_yuv422_conv));
> > +   } else {
> > +           if (len != sizeof(struct prev_yuv422_conv)) {
> > +                   dev_err(dev,
> > +                           "set_yuv422_conv_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&yuv422_conv,
> > +                              yuv422_conv_param,
> > +                              sizeof(struct prev_yuv422_conv))) {
> > +                   dev_err(dev,
> > +                           "set_yuv422_conv_params: Error in copy"
> > +                           " from user\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_yuv422_conv_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_yuv422_conv_regs(&yuv422_conv);
> > +
> > +   return 0;
> > +}
> > +static int get_yuv422_conv_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_yuv422_conv *yuv422_conv_param =
> > +       (struct prev_yuv422_conv *)param;
> > +
> > +   if (ISNULL(yuv422_conv_param)) {
> > +           dev_err(dev, "get_yuv422_conv_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_yuv422_conv)) {
> > +           dev_err(dev,
> > +                   "get_yuv422_conv_params: param struct"
> > +                   " length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(yuv422_conv_param,
> > +                    &yuv422_conv,
> > +                    sizeof(struct prev_yuv422_conv))) {
> > +           dev_err(dev,
> > +                   "get_yuv422_conv_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_yee_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   int i;
> > +
> > +   if (yee.en > 1 ||
> > +       yee.en_halo_red > 1 ||
> > +       yee.hpf_shft > YEE_HPF_SHIFT_MASK)
> > +           return -EINVAL;
> > +
> > +   if (yee.hpf_coef_00 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_01 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_02 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_10 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_11 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_12 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_20 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_21 > YEE_COEF_MASK ||
> > +       yee.hpf_coef_22 > YEE_COEF_MASK)
> > +           return -EINVAL;
> > +
> > +   if (yee.yee_thr > YEE_THR_MASK ||
> > +       yee.es_gain > YEE_ES_GAIN_MASK ||
> > +       yee.es_thr1 > YEE_ES_THR1_MASK ||
> > +       yee.es_thr2 > YEE_THR_MASK ||
> > +       yee.es_gain_grad > YEE_THR_MASK ||
> > +       yee.es_ofst_grad > YEE_THR_MASK)
> > +           return -EINVAL;
> > +
> > +   for (i = 0; i < MAX_SIZE_YEE_LUT ; i++)
> > +           if (yee.table[i] > YEE_ENTRY_MASK)
> > +                   return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +static int set_yee_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_yee *yee_param = (struct prev_yee *)param;
> > +   struct prev_yee user_yee;
> > +   short *temp_table;
> > +
> > +   if (ISNULL(yee_param)) {
> > +           temp_table = yee.table;
> > +           /* Copy defaults for ns */
> > +           memcpy((void *)&yee,
> > +                  (void *)&dm365_yee_defaults,
> > +                  sizeof(struct prev_yee));
> > +           yee.table = temp_table;
> > +   } else {
> > +           if (len != sizeof(struct prev_yee)) {
> > +                   dev_err(dev,
> > +                           "set_yee_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&user_yee,
> > +                              yee_param,
> > +                              sizeof(struct prev_yee))) {
> > +                   dev_err(dev,
> > +                           "set_yee_params: Error in copy from user\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (ISNULL(user_yee.table)) {
> > +                   dev_err(dev, "get_yee_params: yee table ptr null\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(yee.table,
> > +                              user_yee.table,
> > +                              (MAX_SIZE_YEE_LUT * sizeof(short)))) {
> > +                   dev_err(dev,
> > +                           "set_yee_params: Error in copy from user\n");
> > +                   return -EFAULT;
> > +           }
> > +           temp_table = yee.table;
> > +           memcpy(&yee, &user_yee, sizeof(struct prev_yee));
> > +           yee.table = temp_table;
> > +           if (validate_yee_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_ee_regs(&yee);
> > +
> > +   return 0;
> > +}
> > +static int get_yee_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_yee *yee_param = (struct prev_yee *)param;
> > +   struct prev_yee user_yee;
> > +   short *temp_table;
> > +
> > +   if (ISNULL(yee_param)) {
> > +           dev_err(dev, "get_yee_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_yee)) {
> > +           dev_err(dev,
> > +                   "get_yee_params: param struct"
> > +                   " length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_from_user(&user_yee, yee_param, sizeof(struct prev_yee))) {
> > +           dev_err(dev, "get_yee_params: Error in copy to kernel\n");
> > +           return -EFAULT;
> > +   }
> > +   if (ISNULL(user_yee.table)) {
> > +           dev_err(dev, "get_yee_params: yee table ptr null\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(user_yee.table, yee.table,
> > +                    (MAX_SIZE_YEE_LUT * sizeof(short)))) {
> > +           dev_err(dev, "get_yee_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +   temp_table = user_yee.table;
> > +   memcpy(&user_yee, &yee, sizeof(struct prev_yee));
> > +   user_yee.table = temp_table;
> > +
> > +   if (copy_to_user(yee_param, &user_yee, sizeof(struct prev_yee))) {
> > +           dev_err(dev, "get_yee_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_car_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (car.en > 1 ||
> > +       car.hpf_shft > CAR_HPF_SHIFT_MASK ||
> > +       car.gain1.shft > CAR_GAIN1_SHFT_MASK ||
> > +       car.gain1.gain_min > CAR_GAIN_MIN_MASK ||
> > +       car.gain2.shft > CAR_GAIN2_SHFT_MASK ||
> > +       car.gain2.gain_min > CAR_GAIN_MIN_MASK)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_car_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_car *car_param = (struct prev_car *)param;
> > +
> > +   if (ISNULL(car_param)) {
> > +           /* Copy defaults for ns */
> > +           memcpy((void *)&car,
> > +                  (void *)&dm365_car_defaults,
> > +                  sizeof(struct prev_car));
> > +   } else {
> > +           if (len != sizeof(struct prev_car)) {
> > +                   dev_err(dev,
> > +                           "set_car_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&car, car_param, sizeof(struct prev_car))) {
> > +                   dev_err(dev,
> > +                           "set_car_params: Error in copy from user\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_car_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_car_regs(&car);
> > +
> > +   return 0;
> > +}
> > +static int get_car_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_car *car_param = (struct prev_car *)param;
> > +
> > +   if (ISNULL(car_param)) {
> > +           dev_err(dev, "get_car_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_car)) {
> > +           dev_err(dev,
> > +                   "get_car_params: param struct"
> > +                   " length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(car_param, &car, sizeof(struct prev_car))) {
> > +           dev_err(dev, "get_car_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_cgs_params(struct device *dev)
> > +{
> > +#ifdef CONFIG_IPIPE_PARAM_VALIDATION
> > +   if (cgs.en > 1 ||
> > +       cgs.h_shft > CAR_SHIFT_MASK)
> > +           return -EINVAL;
> > +#endif
> > +   return 0;
> > +}
> > +
> > +static int set_cgs_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_cgs *cgs_param = (struct prev_cgs *)param;
> > +
> > +   if (ISNULL(cgs_param)) {
> > +           /* Copy defaults for ns */
> > +           memcpy((void *)&cgs,
> > +                  (void *)&dm365_cgs_defaults,
> > +                  sizeof(struct prev_cgs));
> > +   } else {
> > +           if (len != sizeof(struct prev_cgs)) {
> > +                   dev_err(dev,
> > +                           "set_cgs_params: param struct"
> > +                           " length mismatch\n");
> > +                   return -EINVAL;
> > +           }
> > +           if (copy_from_user(&cgs, cgs_param, sizeof(struct prev_cgs))) {
> > +                   dev_err(dev,
> > +                           "set_cgs_params: Error in copy from user\n");
> > +                   return -EFAULT;
> > +           }
> > +           if (validate_cgs_params(dev) < 0)
> > +                   return -EINVAL;
> > +   }
> > +
> > +   ipipe_set_cgs_regs(&cgs);
> > +
> > +   return 0;
> > +}
> > +
> > +static int get_cgs_params(struct device *dev, void *param, int len)
> > +{
> > +   struct prev_cgs *cgs_param = (struct prev_cgs *)param;
> > +
> > +   if (ISNULL(cgs_param)) {
> > +           dev_err(dev, "get_cgs_params: invalid user ptr");
> > +           return -EINVAL;
> > +   }
> > +   if (len != sizeof(struct prev_cgs)) {
> > +           dev_err(dev,
> > +                   "get_cgs_params: param struct"
> > +                   " length mismatch\n");
> > +           return -EINVAL;
> > +   }
> > +   if (copy_to_user(cgs_param, &cgs, sizeof(struct prev_cgs))) {
> > +           dev_err(dev, "get_cgs_params: Error in copy from kernel\n");
> > +           return -EFAULT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static struct prev_module_if prev_modules[PREV_MAX_MODULES] = {
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_LUTDPC,
> > +           .module_name = "LUT Defect Correction",
> > +           .control = 0,
> > +           .path = IMP_RAW2RAW | IMP_RAW2YUV,
> > +           .set = set_lutdpc_params,
> > +           .get = get_lutdpc_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_OTFDPC,
> > +           .module_name = "OTF Defect Pixel Correction",
> > +           .control = 0,
> > +           .path = IMP_RAW2RAW | IMP_RAW2YUV,
> > +           .set = set_otfdpc_params,
> > +           .get = get_otfdpc_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_NF1,
> > +           .module_name = "2-D Noise filter - 1",
> > +           .control = 0,
> > +           .path = IMP_RAW2RAW | IMP_RAW2YUV,
> > +           .set = set_nf1_params,
> > +           .get = get_nf1_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_NF2,
> > +           .module_name = "2-D Noise filter - 2",
> > +           .control = 0,
> > +           .path = IMP_RAW2RAW | IMP_RAW2YUV,
> > +           .set = set_nf2_params,
> > +           .get = get_nf2_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_GIC,
> > +           .module_name = "Green Imbalance Correction",
> > +           .control = 0,
> > +           .path = IMP_RAW2RAW | IMP_RAW2YUV,
> > +           .set = set_gic_params,
> > +           .get = get_gic_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_WB,
> > +           .module_name = "White balance",
> > +           .control = 1,
> > +           .path = IMP_RAW2RAW | IMP_RAW2YUV,
> > +           .set = set_wb_params,
> > +           .get = get_wb_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_CFA,
> > +           .module_name = "CFA Interpolation",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_cfa_params,
> > +           .get = get_cfa_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_RGB2RGB_1,
> > +           .module_name = "RGB-RGB Conversion - 1",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_rgb2rgb_1_params,
> > +           .get = get_rgb2rgb_1_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_GAMMA,
> > +           .module_name = "Gamma Correction",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_gamma_params,
> > +           .get = get_gamma_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_RGB2RGB_2,
> > +           .module_name = "RGB-RGB Conversion - 2",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_rgb2rgb_2_params,
> > +           .get = get_rgb2rgb_2_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_3D_LUT,
> > +           .module_name = "3D LUT",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_3d_lut_params,
> > +           .get = get_3d_lut_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_RGB2YUV,
> > +           .module_name = "RGB-YCbCr conversion",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_rgb2yuv_params,
> > +           .get = get_rgb2yuv_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_GBCE,
> > +           .module_name = "Global Brightness,Contrast Control",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_gbce_params,
> > +           .get = get_gbce_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_YUV422_CONV,
> > +           .module_name = "YUV 422 conversion",
> > +           .control = 0,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_yuv422_conv_params,
> > +           .get = get_yuv422_conv_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_LUM_ADJ,
> > +           .module_name = "Luminance Adjustment",
> > +           .control = 1,
> > +           .path = IMP_RAW2YUV,
> > +           .set = set_lum_adj_params,
> > +           .get = get_lum_adj_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_YEE,
> > +           .module_name = "Edge Enhancer",
> > +           .control = 1,
> > +           .path = IMP_RAW2YUV | IMP_YUV2YUV,
> > +           .set = set_yee_params,
> > +           .get = get_yee_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_CAR,
> > +           .module_name = "Chromatic Artifact Reduction",
> > +           .control = 1,
> > +           .path = IMP_RAW2YUV | IMP_YUV2YUV,
> > +           .set = set_car_params,
> > +           .get = get_car_params
> > +   },
> > +   {
> > +           .version = "5.1",
> > +           .module_id = PREV_CGS,
> > +           .module_name = "Chromatic Gain Suppression",
> > +           .control = 1,
> > +           .path = IMP_RAW2YUV | IMP_YUV2YUV,
> > +           .set = set_cgs_params,
> > +           .get = get_cgs_params
> > +   }
> > +};
> > +
> > +static struct prev_module_if *prev_enum_preview_cap(struct device *dev,
> > +                                               int index)
> > +{
> > +   dev_dbg(dev, "prev_enum_preview_cap: index = %d\n", index);
> > +
> > +   if ((index + 1) > PREV_MAX_MODULES)
> > +           return NULL;
>
> if (index < 0 || index >= PREV_MAX_MODULES)
>       return NULL;
>
> You might want to use unsigned for index as well. That avoids some traps.
Sure.

>
> > +   return &prev_modules[index];
> > +}
> > +
> > +static int ipipe_set_oper_mode(unsigned int mode)
> > +{
> > +   if (oper_mode == IMP_MODE_NOT_CONFIGURED)
> > +           oper_mode = mode;
> > +   else {
> > +           printk(KERN_ERR "IPIPE is already active!\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static void ipipe_reset_oper_mode(void)
> > +{
> > +   oper_mode = IMP_MODE_NOT_CONFIGURED;
> > +   oper_state.prev_config_state = STATE_NOT_CONFIGURED;
> > +   oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
> > +   oper_state.rsz_chained = 0;
> > +}
> > +
> > +static unsigned int prev_get_oper_mode(void)
> > +{
> > +   return oper_mode;
> > +}
> > +
> > +static unsigned int ipipe_get_oper_state(void)
> > +{
> > +   return oper_state.state;
> > +}
> > +
> > +static void ipipe_set_oper_state(unsigned int state)
> > +{
> > +   mutex_lock(&oper_state.lock);
> > +   oper_state.state = state;
> > +   mutex_unlock(&oper_state.lock);
> > +}
> > +
> > +static unsigned int ipipe_get_prev_config_state(void)
> > +{
> > +   return oper_state.prev_config_state;
> > +}
> > +
> > +static unsigned int ipipe_get_rsz_config_state(void)
> > +{
> > +   return oper_state.rsz_config_state;
> > +}
> > +
> > +/* function: calculate_normal_f_div_param
> > + * Algorithm to calculate the frame division parameters for resizer.
> > + * in normal mode. Please refer the application note in DM360 functional
> > + * spec for details of the algorithm
> > + */
> > +static int calculate_normal_f_div_param(struct device *dev,
> > +                                   int input_width,
> > +                                   int output_width,
> > +                                   struct ipipe_rsz_rescale_param *param)
> > +{
> > +   /* rsz = R, input_width = H, output width = h in the equation */
> > +   unsigned int val1;
> > +   unsigned int rsz;
> > +   unsigned int val;
> > +   unsigned int h1;
> > +   unsigned int h2;
> > +   unsigned int o;
> > +
> > +   if (output_width > input_width) {
> > +           dev_err(dev, "frame div mode is used for scale down only\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   rsz = (input_width << 8) / output_width;
> > +   val = rsz << 1;
> > +   val = ((input_width << 8) / val) + 1;
> > +   o = 14;
> > +   if (!(val % 2)) {
> > +           h1 = val;
> > +   } else {
> > +           val = (input_width << 7);
> > +           val -= (rsz >> 1);
> > +           val /= (rsz << 1);
> > +           val <<= 1;
> > +           val += 2;
> > +           o += ((CEIL(rsz, 1024)) << 1);
> > +           h1 = val;
> > +   }
> > +   h2 = output_width - h1;
> > +   /* phi */
> > +   val = (h1 * rsz) - (((input_width >> 1) - o) << 8);
> > +   /* skip */
> > +   val1 = ((val - 1024) >> 9) << 1;
> > +   param->f_div.num_passes = IPIPE_MAX_PASSES;
> > +   param->f_div.pass[0].o_hsz = h1 - 1;
> > +   param->f_div.pass[0].i_hps = 0;
> > +   param->f_div.pass[0].h_phs = 0;
> > +   param->f_div.pass[0].src_hps = 0;
> > +   param->f_div.pass[0].src_hsz = (input_width >> 2) + o;
> > +   param->f_div.pass[1].o_hsz = h2 - 1;
> > +   param->f_div.pass[1].i_hps = val1;
> > +   param->f_div.pass[1].h_phs = (val - (val1 << 8));
> > +   param->f_div.pass[1].src_hps = (input_width >> 2) - o;
> > +   param->f_div.pass[1].src_hsz = (input_width >> 2) + o;
> > +
> > +   return 0;
> > +}
> > +
> > +/* function: calculate_down_scale_f_div_param
> > + * Algorithm to calculate the frame division parameters for resizer in
> > + * downscale mode. Please refer the application note in DM360 functional
> > + * spec for details of the algorithm
> > + */
> > +static int calculate_down_scale_f_div_param(struct device *dev,
> > +                                       int input_width,
> > +                                       int output_width,
> > +                                       struct ipipe_rsz_rescale_param
> > +                                       *param)
> > +{
> > +   /* rsz = R, input_width = H, output width = h in the equation */
> > +   unsigned int two_power;
> > +   unsigned int upper_h1;
> > +   unsigned int upper_h2;
> > +   unsigned int val1;
> > +   unsigned int val;
> > +   unsigned int rsz;
> > +   unsigned int h1;
> > +   unsigned int h2;
> > +   unsigned int o;
> > +   unsigned int n;
> > +
> > +   upper_h1 = input_width >> 1;
> > +   n = param->h_dscale_ave_sz;
> > +   /* 2 ^ (scale+1) */
> > +   two_power = 1 << (n + 1);
> > +   upper_h1 = (upper_h1 >> (n + 1)) << (n + 1);
> > +   upper_h2 = input_width - upper_h1;
> > +   if (upper_h2 % two_power) {
> > +           dev_err(dev, "frame halves to be a multiple of 2 power n+1\n");
> > +           return -EINVAL;
> > +   }
> > +   two_power = 1 << n;
> > +   rsz = (input_width << 8) / output_width;
> > +   val = rsz * two_power;
> > +   val = ((upper_h1 << 8) / val) + 1;
> > +   if (!(val % 2))
> > +           h1 = val;
> > +   else {
> > +           val = (upper_h1 << 8);
> > +           val >>= (n + 1);
> > +           val -= (rsz >> 1);
> > +           val /= (rsz << 1);
> > +           val <<= 1;
> > +           val += 2;
> > +           h1 = val;
> > +   }
> > +   o = 10 + (two_power << 2);
> > +   if (((input_width << 7) / rsz) % 2)
> > +           o += (((CEIL(rsz, 1024)) << 1) << n);
> > +   h2 = output_width - h1;
> > +   /* phi */
> > +   val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8);
> > +   /* skip */
> > +   val1 = ((val - 1024) >> 9) << 1;
> > +   param->f_div.num_passes = IPIPE_MAX_PASSES;
> > +   param->f_div.pass[0].o_hsz = h1 - 1;
> > +   param->f_div.pass[0].i_hps = 0;
> > +   param->f_div.pass[0].h_phs = 0;
> > +   param->f_div.pass[0].src_hps = 0;
> > +   param->f_div.pass[0].src_hsz = upper_h1 + o;
> > +   param->f_div.pass[1].o_hsz = h2 - 1;
> > +   param->f_div.pass[1].i_hps = 10 + (val1 * two_power);
> > +   param->f_div.pass[1].h_phs = (val - (val1 << 8));
> > +   param->f_div.pass[1].src_hps = (upper_h1 - o);
> > +   param->f_div.pass[1].src_hsz = (upper_h2 + o);
> > +
> > +   return 0;
> > +}
> > +
> > +/* update the parameter in param for a given input and output width */
> > +static int update_preview_f_div_params(struct device *dev,
> > +                                  int input_width,
> > +                                  int output_width,
> > +                                  struct ipipe_rsz_rescale_param *param)
> > +{
> > +   unsigned int val;
> > +
> > +   val = input_width >> 1;
> > +   if (val < 8) {
> > +           dev_err(dev, "input width must me atleast 16 pixels\n");
> > +           return -EINVAL;
> > +   }
> > +   param->f_div.en = 1;
> > +   param->f_div.num_passes = IPIPE_MAX_PASSES;
> > +   param->f_div.pass[0].o_hsz = val;
> > +   param->f_div.pass[0].i_hps = 0;
> > +   param->f_div.pass[0].h_phs = 0;
> > +   param->f_div.pass[0].src_hps = 0;
> > +   param->f_div.pass[0].src_hsz = val + 10;
> > +   param->f_div.pass[1].o_hsz = val;
> > +   param->f_div.pass[1].i_hps = 0;
> > +   param->f_div.pass[1].h_phs = 0;
> > +   param->f_div.pass[1].src_hps = val - 8;
> > +   param->f_div.pass[1].src_hsz = val + 10;
> > +
> > +   return 0;
> > +}
> > +
> > +/* Use shared to allocate exclusive blocks as required
> > + * by resize applications in single shot mode
> > + */
> > +static void *ipipe_alloc_config_block(struct device *dev)
> > +{
> > +   /* return common data block */
> > +   mutex_lock(&oper_state.lock);
> > +   if (oper_state.resource_in_use) {
> > +           dev_err(dev, "resource in use\n");
> > +           mutex_unlock(&oper_state.lock);
> > +           return NULL;
> > +   }
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return oper_state.shared_config_param;
> > +}
> > +
> > +/* Used to free only non-shared config block allocated through
> > + * imp_alloc_config_block
> > + */
> > +static void ipipe_dealloc_config_block(struct device *dev, void *config_block)
> > +{
> > +   if (config_block) {
> > +           if (config_block != oper_state.shared_config_param)
> > +                   kfree(config_block);
> > +           else
> > +                   dev_err(dev, "Trying to free shared config block\n");
> > +   }
> > +}
> > +
> > +static void ipipe_dealloc_user_config_block(struct device *dev,
> > +                                       void *config_block)
> > +{
> > +   kfree(config_block);
> > +}
> > +
> > +static void *ipipe_alloc_user_config_block(struct device *dev,
> > +                                      enum imp_log_chan_t chan_type,
> > +                                      int *len)
> > +{
> > +   void *config = NULL;
> > +
> > +   if (oper_mode == IMP_MODE_SINGLE_SHOT) {
> > +           if (chan_type == IMP_PREVIEWER) {
> > +                   config =
> > +                       kmalloc(sizeof(struct prev_single_shot_config),
> > +                               GFP_KERNEL);
> > +                   *len = sizeof(struct prev_single_shot_config);
> > +           } else if (chan_type == IMP_RESIZER) {
> > +                   config =
> > +                       kmalloc(sizeof(struct rsz_single_shot_config),
> > +                               GFP_KERNEL);
> > +                   *len = sizeof(struct rsz_single_shot_config);
> > +           }
> > +
> > +   } else {
> > +           if (chan_type == IMP_PREVIEWER) {
> > +                   config =
> > +                       kmalloc(sizeof(struct prev_continuous_config),
> > +                               GFP_KERNEL);
> > +                   *len = sizeof(struct prev_continuous_config);
> > +           } else if (chan_type == IMP_RESIZER) {
> > +                   config =
> > +                       kmalloc(sizeof(struct rsz_continuous_config),
> > +                               GFP_KERNEL);
> > +                   *len = sizeof(struct rsz_continuous_config);
> > +           }
> > +   }
> > +
> > +   return config;
> > +}
> > +
> > +static void ipipe_set_user_config_defaults(struct device *dev,
> > +                                      enum imp_log_chan_t chan_type,
> > +                                      void *config)
> > +{
> > +   dev_dbg(dev, "ipipe_set_user_config_defaults\n");
> > +
> > +   if (oper_mode == IMP_MODE_SINGLE_SHOT) {
> > +           if (chan_type == IMP_PREVIEWER) {
> > +                   dev_dbg(dev, "SS-Preview\n");
> > +                   /* preview channel in single shot mode */
> > +                   memcpy(config,
> > +                          (void *)&dm365_prev_ss_config_defs,
> > +                          sizeof(struct prev_single_shot_config));
> > +           } else {
> > +                   dev_dbg(dev, "SS-Resize\n");
> > +                   /* resizer channel in single shot mode */
> > +                   memcpy(config,
> > +                          (void *)&dm365_rsz_ss_config_defs,
> > +                          sizeof(struct rsz_single_shot_config));
> > +           }
> > +   } else if (oper_mode == IMP_MODE_CONTINUOUS) {
> > +           /* Continuous mode */
> > +           if (chan_type == IMP_PREVIEWER) {
> > +                   dev_dbg(dev, "Cont Preview\n");
> > +                   /* previewer defaults */
> > +                   memcpy(config,
> > +                          (void *)&dm365_prev_cont_config_defs,
> > +                          sizeof(struct prev_continuous_config));
> > +           } else {
> > +                   dev_dbg(dev, "Cont resize\n");
> > +                   /* resizer defaults */
> > +                   memcpy(config,
> > +                          (void *)&dm365_rsz_cont_config_defs,
> > +                          sizeof(struct rsz_continuous_config));
> > +           }
> > +   } else
> > +           dev_err(dev, "Incorrect mode used\n");
> > +}
> > +
> > +/* function :calculate_sdram_offsets()
> > + * This function calculates the offsets from start of buffer for the C
> > + * plane when output format is YUV420SP. It also calculates the offsets
> > + * from the start of the buffer when the image is flipped vertically
> > + * or horizontally for ycbcr/y/c planes
> > + */
> > +static int calculate_sdram_offsets(struct ipipe_params *param, int index)
> > +{
> > +   int bytesperline = 2;
> > +   int image_height;
> > +   int image_width;
> > +   int yuv_420;
> > +   int offset;
> > +
> > +   if (!param->rsz_en[index])
> > +           return -EINVAL;
> > +
> > +   image_height = param->rsz_rsc_param[index].o_vsz + 1;
> > +   image_width = param->rsz_rsc_param[index].o_hsz + 1;
> > +   param->ext_mem_param[index].c_offset = 0;
> > +   param->ext_mem_param[index].flip_ofst_y = 0;
> > +   param->ext_mem_param[index].flip_ofst_c = 0;
> > +   if ((param->ipipe_dpaths_fmt != IPIPE_RAW2RAW) &&
> > +       (param->ipipe_dpaths_fmt != IPIPE_RAW2BOX) &&
>
> No need for extra parenthesis.
Ok.
>
> > +       param->rsz_rsc_param[index].cen &&
> > +       param->rsz_rsc_param[index].yen) {
> > +           /* YUV 420 */
> > +           yuv_420 = 1;
> > +           bytesperline = 1;
>
> bytesperline == 1? Really?
Wrong naming. It should be renamed to bytesperpixel.
>
> > +   }
> > +
> > +   /* set offset value */
> > +   offset = 0;
> > +
> > +   if (param->rsz_rsc_param[index].h_flip)
> > +           /* width * bytesperline - 1 */
> > +           offset = (image_width * bytesperline) - 1;
> > +   if (param->rsz_rsc_param[index].v_flip)
> > +           offset += (image_height - 1) *
> > +                   param->ext_mem_param[index].rsz_sdr_oft_y;
> > +   param->ext_mem_param[index].flip_ofst_y = offset;
> > +   if (yuv_420) {
> > +           offset = 0;
> > +           /* half height for c-plane */
> > +           if (param->rsz_rsc_param[index].h_flip)
> > +                   /* width * bytesperline - 1 */
> > +                   offset = image_width - 1;
> > +           if (param->rsz_rsc_param[index].v_flip)
> > +                   offset += (((image_height >> 1) - 1) *
> > +                   param->ext_mem_param[index].
> > +                   rsz_sdr_oft_c);
> > +           param->ext_mem_param[index].flip_ofst_c =
> > +                   offset;
> > +           param->ext_mem_param[index].c_offset =
> > +               param->ext_mem_param[index].
> > +               rsz_sdr_oft_y * image_height;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static void enable_422_420_conversion(struct ipipe_params *param,
> > +                                 int index, enum enable_disable_t en)
> > +{
> > +   /* Enable 422 to 420 conversion */
> > +   param->rsz_rsc_param[index].cen = en;
> > +   param->rsz_rsc_param[index].yen = en;
> > +}
> > +
> > +static void configure_resizer_out_params(struct ipipe_params *param,
> > +                                   int index,
> > +                                   void *output_spec,
> > +                                   unsigned char partial, unsigned flag)
> > +{
> > +   if (partial) {
> > +           struct rsz_part_output_spec *partial_output =
> > +               (struct rsz_part_output_spec *)output_spec;
> > +           if (partial_output->enable) {
> > +                   param->rsz_en[index] = ENABLE;
> > +                   param->rsz_rsc_param[index].h_flip =
> > +                       partial_output->h_flip;
> > +                   param->rsz_rsc_param[index].v_flip =
> > +                       partial_output->v_flip;
> > +                   param->rsz_rsc_param[index].v_typ_y =
> > +                       partial_output->v_typ_y;
> > +                   param->rsz_rsc_param[index].v_typ_c =
> > +                       partial_output->v_typ_c;
> > +                   param->rsz_rsc_param[index].v_lpf_int_y =
> > +                       partial_output->v_lpf_int_y;
> > +                   param->rsz_rsc_param[index].v_lpf_int_c =
> > +                       partial_output->v_lpf_int_c;
> > +                   param->rsz_rsc_param[index].h_typ_y =
> > +                       partial_output->h_typ_y;
> > +                   param->rsz_rsc_param[index].h_typ_c =
> > +                       partial_output->h_typ_c;
> > +                   param->rsz_rsc_param[index].h_lpf_int_y =
> > +                       partial_output->h_lpf_int_y;
> > +                   param->rsz_rsc_param[index].h_lpf_int_c =
> > +                       partial_output->h_lpf_int_c;
> > +                   param->rsz_rsc_param[index].dscale_en =
> > +                       partial_output->en_down_scale;
> > +                   param->rsz_rsc_param[index].h_dscale_ave_sz =
> > +                       partial_output->h_dscale_ave_sz;
> > +                   param->rsz_rsc_param[index].v_dscale_ave_sz =
> > +                       partial_output->v_dscale_ave_sz;
> > +                   param->ext_mem_param[index].user_y_ofst =
> > +                       (partial_output->user_y_ofst + 31) & ~0x1F;
> > +                   param->ext_mem_param[index].user_c_ofst =
> > +                       (partial_output->user_c_ofst + 31) & ~0x1F;
> > +
> > +           } else
> > +                   param->rsz_en[index] = DISABLE;
> > +
> > +   } else {
> > +           struct rsz_output_spec *output =
> > +               (struct rsz_output_spec *)output_spec;
> > +           if (output->enable) {
> > +                   param->rsz_en[index] = ENABLE;
> > +                   param->rsz_rsc_param[index].o_vsz = output->height - 1;
> > +                   param->rsz_rsc_param[index].o_hsz = output->width - 1;
> > +                   param->ext_mem_param[index].rsz_sdr_ptr_s_y =
> > +                       output->vst_y;
> > +                   param->ext_mem_param[index].rsz_sdr_ptr_e_y =
> > +                       output->height;
> > +                   param->ext_mem_param[index].rsz_sdr_ptr_s_c =
> > +                       output->vst_c;
> > +                   param->ext_mem_param[index].rsz_sdr_ptr_e_c =
> > +                       output->height;
> > +
> > +                   if (flag) {
> > +                           /* update common parameters */
> > +                           param->rsz_rsc_param[index].h_flip =
> > +                               output->h_flip;
> > +                           param->rsz_rsc_param[index].v_flip =
> > +                               output->v_flip;
> > +                           param->rsz_rsc_param[index].v_typ_y =
> > +                               output->v_typ_y;
> > +                           param->rsz_rsc_param[index].v_typ_c =
> > +                               output->v_typ_c;
> > +                           param->rsz_rsc_param[index].v_lpf_int_y =
> > +                               output->v_lpf_int_y;
> > +                           param->rsz_rsc_param[index].v_lpf_int_c =
> > +                               output->v_lpf_int_c;
> > +                           param->rsz_rsc_param[index].h_typ_y =
> > +                               output->h_typ_y;
> > +                           param->rsz_rsc_param[index].h_typ_c =
> > +                               output->h_typ_c;
> > +                           param->rsz_rsc_param[index].h_lpf_int_y =
> > +                               output->h_lpf_int_y;
> > +                           param->rsz_rsc_param[index].h_lpf_int_c =
> > +                               output->h_lpf_int_c;
> > +                           param->rsz_rsc_param[index].dscale_en =
> > +                               output->en_down_scale;
> > +                           param->rsz_rsc_param[index].h_dscale_ave_sz =
> > +                               output->h_dscale_ave_sz;
> > +                           param->rsz_rsc_param[index].v_dscale_ave_sz =
> > +                               output->h_dscale_ave_sz;
> > +                           param->ext_mem_param[index].user_y_ofst =
> > +                               (output->user_y_ofst + 31) & ~0x1F;
> > +                           param->ext_mem_param[index].user_c_ofst =
> > +                               (output->user_c_ofst + 31) & ~0x1F;
> > +                   }
> > +           } else
> > +                   param->rsz_en[index] = DISABLE;
> > +   }
> > +
> > +}
> > +
> > +/* function :calculate_line_length()
> > + * This function calculates the line length of various image
> > + * planes at the input and output
> > + */
> > +static void calculate_line_length(enum ipipe_pix_formats pix,
> > +                            int width,
> > +                            int height, int *line_len, int *line_len_c)
> > +{
> > +   *line_len = 0;
> > +   *line_len_c = 0;
> > +
> > +   if ((pix == IPIPE_UYVY) || (pix == IPIPE_BAYER))
> > +           *line_len = width << 1;
> > +   else if (pix == IPIPE_420SP_Y || pix == IPIPE_420SP_C) {
> > +           *line_len = width;
> > +           *line_len_c = width;
> > +   } else {
> > +           /* YUV 420 */
> > +           /* round width to upper 32 byte boundary */
> > +           *line_len = width;
> > +           *line_len_c = width;
> > +   }
> > +   /* adjust the line len to be a multiple of 32 */
> > +   *line_len += 31;
> > +   *line_len &= ~0x1f;
> > +   *line_len_c += 31;
> > +   *line_len_c &= ~0x1f;
> > +}
> > +
> > +static inline int rsz_validate_input_image_format(struct device *dev,
> > +                                             enum ipipe_pix_formats pix,
> > +                                             int width,
> > +                                             int height, int *line_len)
> > +{
> > +   int val;
> > +
> > +   if (pix != IPIPE_UYVY && pix != IPIPE_420SP_Y &&
> > +           pix != IPIPE_420SP_C) {
> > +           dev_err(dev,
> > +                   "rsz_validate_out_pix_formats"
> > +                   "pix format not supported, %d\n", pix);
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (width == 0 || height == 0) {
> > +           dev_err(dev, "validate_line_length: invalid "
> > +                           "width or height\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (pix == IPIPE_420SP_C)
> > +           calculate_line_length(pix,
> > +                                 width,
> > +                                 height,
> > +                                 &val,
> > +                                 line_len);
> > +   else
> > +           calculate_line_length(pix,
> > +                                 width,
> > +                                 height,
> > +                                 line_len,
> > +                                 &val);
> > +
> > +   return 0;
> > +}
> > +
> > +static inline int rsz_validate_output_image_format(struct device *dev,
> > +                                              enum ipipe_pix_formats pix,
> > +                                              int width,
> > +                                              int height,
> > +                                              int *in_line_len,
> > +                                              int *in_line_len_c)
> > +{
> > +   if (pix != IPIPE_UYVY && pix != IPIPE_420SP_Y &&
> > +           pix != IPIPE_420SP_C && pix != IPIPE_YUV420SP &&
> > +           pix != IPIPE_BAYER) {
> > +           dev_err(dev,
> > +                   "rsz_validate_out_pix_formats"
> > +                   "pix format not supported, %d\n", pix);
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (width == 0 || height == 0) {
> > +           dev_err(dev, "validate_line_length: invalid"
> > +                           " width or height\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   calculate_line_length(pix,
> > +                         width,
> > +                         height, in_line_len, in_line_len_c);
> > +   return 0;
> > +}
> > +
> > +static void configure_common_rsz_params(struct device *dev,
> > +                   struct ipipe_params *param,
> > +                   struct rsz_single_shot_config *ss_config)
> > +{
> > +   param->rsz_common.yuv_y_min = ss_config->yuv_y_min;
> > +   param->rsz_common.yuv_y_max = ss_config->yuv_y_max;
> > +   param->rsz_common.yuv_c_min = ss_config->yuv_c_min;
> > +   param->rsz_common.yuv_c_max = ss_config->yuv_c_max;
> > +   param->rsz_common.out_chr_pos = ss_config->out_chr_pos;
> > +   param->rsz_common.rsz_seq_crv = ss_config->chroma_sample_even;
> > +
> > +}
> > +
> > +static int configure_common_rsz_in_params(struct device *dev,
> > +                                     struct ipipe_params *param,
> > +                                     int flag, int rsz_chained,
> > +                                     void *input_spec)
> > +{
> > +   enum ipipe_pix_formats pix;
> > +
> > +   if (!flag) {
> > +           struct prev_ss_input_spec *in_specs =
> > +               (struct prev_ss_input_spec *)input_spec;
> > +           param->rsz_common.vsz = in_specs->image_height - 1;
> > +           param->rsz_common.hsz = in_specs->image_width - 1;
> > +           pix = in_specs->pix_fmt;
> > +   } else {
> > +           struct rsz_ss_input_spec *in_specs =
> > +               (struct rsz_ss_input_spec *)input_spec;
> > +           if (!rsz_chained) {
> > +                   param->rsz_common.vps = in_specs->vst;
> > +                   param->rsz_common.hps = in_specs->hst;
> > +           }
> > +           param->rsz_common.vsz = in_specs->image_height - 1;
> > +           param->rsz_common.hsz = in_specs->image_width - 1;
> > +           pix = in_specs->pix_fmt;
> > +   }
> > +   switch (pix) {
> > +   case IPIPE_BAYER_8BIT_PACK:
> > +   case IPIPE_BAYER_8BIT_PACK_ALAW:
> > +   case IPIPE_BAYER_8BIT_PACK_DPCM:
> > +   case IPIPE_BAYER_12BIT_PACK:
> > +   case IPIPE_BAYER:
> > +           param->rsz_common.src_img_fmt = RSZ_IMG_422;
> > +           param->rsz_common.source = IPIPE_DATA;
> > +           break;
> > +   case IPIPE_UYVY:
> > +           param->rsz_common.src_img_fmt = RSZ_IMG_422;
> > +           if (rsz_chained)
> > +                   param->rsz_common.source = IPIPE_DATA;
> > +           else
> > +                   param->rsz_common.source = IPIPEIF_DATA;
> > +           param->rsz_common.raw_flip = 0;
> > +           break;
> > +   case IPIPE_420SP_Y:
> > +           param->rsz_common.src_img_fmt = RSZ_IMG_420;
> > +           /* Select y */
> > +           param->rsz_common.y_c = 0;
> > +           param->rsz_common.source = IPIPEIF_DATA;
> > +           param->rsz_common.raw_flip = 0;
> > +           break;
> > +   case IPIPE_420SP_C:
> > +           param->rsz_common.src_img_fmt = RSZ_IMG_420;
> > +           /* Select y */
> > +           param->rsz_common.y_c = 1;
> > +           param->rsz_common.source = IPIPEIF_DATA;
> > +           param->rsz_common.raw_flip = 0;
> > +           break;
> > +   default:
> > +           return -EINVAL;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int validate_ipipeif_decimation(struct device *dev,
> > +                                  enum ipipeif_decimation dec_en,
> > +                                  unsigned char rsz,
> > +                                  unsigned char frame_div_mode_en,
> > +                                  int width)
> > +{
> > +   if (dec_en && frame_div_mode_en) {
> > +           dev_err(dev,
> > +                   "Both dec_en & frame_div_mode_en"
> > +                   "can not enabled simultaneously\n");
> > +           return -EINVAL;
> > +   }
> > +   if (frame_div_mode_en) {
> > +           dev_err(dev, "frame_div_mode mode not supported");
> > +           return -EINVAL;
> > +   }
> > +   if (dec_en) {
> > +           if (width <= IPIPE_MAX_INPUT_WIDTH) {
> > +                   dev_err(dev,
> > +                           "image width to be more than"
> > +                           " %d for decimation\n", IPIPE_MAX_INPUT_WIDTH);
> > +                   return -EINVAL;
> > +           }
> > +           if ((rsz < IPIPEIF_RSZ_MIN) || (rsz > IPIPEIF_RSZ_MAX)) {
> > +                   dev_err(dev, "rsz range is %d to %d\n",
> > +                           IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
> > +                   return -EINVAL;
> > +           }
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int configure_resizer_in_ss_mode(struct device *dev,
> > +                                   void *user_config,
> > +                                   int resizer_chained,
> > +                                   struct ipipe_params *param)
> > +{
> > +   /* resizer in standalone mode. In this mode if serializer
> > +    * is enabled, we need to set config params in the hw.
> > +    */
> > +   struct rsz_single_shot_config *ss_config =
> > +       (struct rsz_single_shot_config *)user_config;
> > +   int line_len_c;
> > +   int line_len;
> > +   int ret;
> > +
> > +   ret = rsz_validate_input_image_format(dev,
> > +                                         ss_config->input.pix_fmt,
> > +                                         ss_config->input.image_width,
> > +                                         ss_config->input.image_height,
> > +                                         &line_len);
> > +
> > +   if (ret)
> > +           return -EINVAL;
> > +
> > +   /* shared block */
> > +   if ((!ss_config->output1.enable) && (!ss_config->output2.enable)) {
> > +           dev_err(dev, "One of the resizer output must be enabled\n");
> > +           return -EINVAL;
> > +   }
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   if (!ss_config->input.line_length)
> > +           param->ipipeif_param.adofs = line_len;
> > +   else {
> > +           param->ipipeif_param.adofs = ss_config->input.line_length;
> > +           param->ipipeif_param.adofs =
> > +                           (param->ipipeif_param.adofs + 31) & ~0x1f;
> > +   }
> > +   if (ss_config->output1.enable) {
> > +           param->rsz_en[RSZ_A] = ENABLE;
> > +           param->rsz_rsc_param[RSZ_A].mode = IPIPEIF_ONE_SHOT;
> > +           ret = rsz_validate_output_image_format(dev,
> > +                                   ss_config->output1.pix_fmt,
> > +                                   ss_config->output1.width,
> > +                                   ss_config->output1.height,
> > +                                   &line_len, &line_len_c);
> > +           if (ret) {
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return ret;
> > +           }
> > +           param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
> > +           param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c;
> > +           configure_resizer_out_params(param,
> > +                                              RSZ_A,
> > +                                              &ss_config->output1,
> > +                                              0,
> > +                                              1);
> > +
> > +           if (ss_config->output1.pix_fmt == IMP_BAYER)
> > +                   param->rsz_common.raw_flip = 1;
> > +           else
> > +                   param->rsz_common.raw_flip = 0;
> > +
> > +           if (ss_config->output1.pix_fmt == IPIPE_YUV420SP)
> > +                   enable_422_420_conversion(param, RSZ_A, ENABLE);
> > +           else
> > +                   enable_422_420_conversion(param, RSZ_A,
> > +                                                     DISABLE);
> > +   }
> > +
> > +   if (ss_config->output2.enable) {
> > +           param->rsz_en[RSZ_A] = ENABLE;
> > +           param->rsz_rsc_param[RSZ_B].mode = IPIPEIF_ONE_SHOT;
> > +           ret = rsz_validate_output_image_format(dev,
> > +                                   ss_config->output2.pix_fmt,
> > +                                   ss_config->output2.width,
> > +                                   ss_config->output2.height,
> > +                                   &line_len, &line_len_c);
> > +           if (ret) {
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return ret;
> > +           }
> > +           param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
> > +           param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
> > +           configure_resizer_out_params(param,
> > +                                              RSZ_B,
> > +                                              &ss_config->output2,
> > +                                              0,
> > +                                              1);
> > +           if (ss_config->output2.pix_fmt == IPIPE_YUV420SP)
> > +                   enable_422_420_conversion(param, RSZ_B, ENABLE);
> > +           else
> > +                   enable_422_420_conversion(param,
> > +                                             RSZ_B,
> > +                                             DISABLE);
> > +   }
> > +   configure_common_rsz_params(dev, param, ss_config);
> > +   if (resizer_chained) {
> > +           oper_state.rsz_chained = 1;
> > +           oper_state.rsz_config_state = STATE_CONFIGURED;
> > +   } else {
> > +           oper_state.rsz_chained = 0;
> > +           ret = validate_ipipeif_decimation(dev,
> > +                                             ss_config->input.dec_en,
> > +                                             ss_config->input.rsz,
> > +                                             ss_config->input.
> > +                                             frame_div_mode_en,
> > +                                             ss_config->input.
> > +                                             image_width);
> > +           if (ret) {
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return ret;
> > +           }
> > +
> > +           if (ipipe_process_pix_fmts(ss_config->input.pix_fmt,
> > +                              ss_config->output1.pix_fmt,
> > +                              param) < 0) {
> > +                   dev_err(dev, "error in input or output pix format\n");
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return -EINVAL;
> > +           }
> > +
> > +           param->ipipeif_param.source = IPIPEIF_SDRAM_YUV;
> > +           param->ipipeif_param.glob_hor_size = ss_config->input.ppln;
> > +           param->ipipeif_param.glob_ver_size = ss_config->input.lpfr;
> > +           param->ipipeif_param.hnum = ss_config->input.image_width;
> > +           param->ipipeif_param.vnum = ss_config->input.image_height;
> > +           param->ipipeif_param.var.if_5_1.clk_div =
> > +               ss_config->input.clk_div;
> > +           if (ss_config->input.dec_en) {
> > +                   param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
> > +                   param->ipipeif_param.rsz = ss_config->input.rsz;
> > +                   param->ipipeif_param.avg_filter =
> > +                       (enum ipipeif_avg_filter)ss_config->input.
> > +                       avg_filter_en;
> > +                   param->ipipe_hsz =
> > +                       (((ss_config->input.image_width *
> > +                          IPIPEIF_RSZ_CONST) / ss_config->input.rsz) - 1);
> > +           }
> > +           if (ss_config->input.pix_fmt == IPIPE_420SP_Y ||
> > +             ss_config->input.pix_fmt == IPIPE_420SP_C) {
> > +                   param->ipipeif_param.var.if_5_1.pack_mode
> > +                           = IPIPEIF_5_1_PACK_8_BIT;
> > +                   param->ipipeif_param.var.if_5_1.source1 = IPIPEIF_CCDC;
> > +                   param->ipipeif_param.var.if_5_1.isif_port.if_type
> > +                           = V4L2_MBUS_FMT_YUYV8_1X16;
> > +                   param->ipipeif_param.var.if_5_1.data_shift
> > +                           = IPIPEIF_5_1_BITS11_0;
> > +
> > +                   param->ipipeif_param.source = IPIPEIF_SDRAM_RAW;
> > +
> > +
> > +           }
> > +           if (ss_config->input.pix_fmt == IPIPE_420SP_C)
> > +                   param->ipipeif_param.var.if_5_1.isif_port.if_type
> > +                           = V4L2_MBUS_FMT_SBGGR10_1X10;
> > +           param->ipipe_hsz = ss_config->input.image_width - 1;
> > +           param->ipipe_vsz = ss_config->input.image_height - 1;
> > +           param->ipipe_vps = ss_config->input.vst;
> > +           param->ipipe_hps = ss_config->input.hst;
> > +           param->ipipe_dpaths_fmt = IPIPE_YUV2YUV;
> > +           configure_common_rsz_in_params(dev, param, 1, resizer_chained,
> > +                                          &ss_config->input);
> > +           if (param->rsz_en[RSZ_A]) {
> > +
> > +                   calculate_resize_ratios(param, RSZ_A);
> > +                   calculate_sdram_offsets(param, RSZ_A);
> > +
> > +                   /* Overriding resize ratio calculation */
> > +                   if (ss_config->input.pix_fmt == IPIPE_420SP_C) {
> > +                           param->rsz_rsc_param[RSZ_A].v_dif =
> > +                               (((param->ipipe_vsz + 1) * 2) * 256) /
> > +                               (param->rsz_rsc_param[RSZ_A].o_vsz + 1);
> > +                   }
> > +           }
> > +
> > +           if (param->rsz_en[RSZ_B]) {
> > +                   calculate_resize_ratios(param, RSZ_B);
> > +                   calculate_sdram_offsets(param, RSZ_B);
> > +
> > +                   /* Overriding resize ratio calculation */
> > +                   if (ss_config->input.pix_fmt == IPIPE_420SP_C) {
> > +                           param->rsz_rsc_param[RSZ_B].v_dif =
> > +                               (((param->ipipe_vsz + 1) * 2) * 256) /
> > +                               (param->rsz_rsc_param[RSZ_B].o_vsz + 1);
> > +                   }
> > +           }
> > +   }
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int configure_resizer_in_cont_mode(struct device *dev,
> > +                                     void *user_config,
> > +                                     int resizer_chained,
> > +                                     struct ipipe_params *param)
> > +{
> > +   /* Continuous mode. This is a shared config block */
> > +   struct rsz_continuous_config *cont_config =
> > +       (struct rsz_continuous_config *)user_config;
> > +   int line_len_c;
> > +   int line_len;
> > +   int ret;
> > +
> > +   if (!resizer_chained) {
> > +           dev_err(dev, "Resizer cannot be configured in standalone"
> > +                   "for continuous mode\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   if (!cont_config->output1.enable) {
> > +           dev_err(dev, "enable resizer - 0\n");
> > +           mutex_unlock(&oper_state.lock);
> > +           return -EINVAL;
> > +   }
> > +   param->rsz_en[RSZ_A] = ENABLE;
> > +   param->rsz_rsc_param[RSZ_A].mode = IPIPEIF_CONTINUOUS;
> > +   configure_resizer_out_params(param,
> > +                                RSZ_A,
> > +                                &cont_config->output1,
> > +                                1,
> > +                                0);
> > +   param->rsz_en[RSZ_B] = DISABLE;
> > +
> > +   if (cont_config->output2.enable) {
> > +           param->rsz_rsc_param[RSZ_B].mode = IPIPEIF_CONTINUOUS;
> > +           ret = rsz_validate_output_image_format(dev,
> > +                                                  cont_config->output2.
> > +                                                  pix_fmt,
> > +                                                  cont_config->output2.
> > +                                                  width,
> > +                                                  cont_config->output2.
> > +                                                  height,
> > +                                                  &line_len,
> > +                                                  &line_len_c);
> > +           if (ret) {
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return ret;
> > +           }
> > +           param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
> > +           param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
> > +           configure_resizer_out_params(param,
> > +                                        RSZ_B,
> > +                                        &cont_config->output2,
> > +                                        0,
> > +                                        1);
> > +           if (cont_config->output2.pix_fmt == IPIPE_YUV420SP)
> > +                   enable_422_420_conversion(param,
> > +                                             RSZ_B, ENABLE);
> > +           else
> > +                   enable_422_420_conversion(param,
> > +                                             RSZ_B, DISABLE);
> > +   }
> > +   oper_state.rsz_chained = 1;
> > +   oper_state.rsz_config_state = STATE_CONFIGURED;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +static int ipipe_set_resize_config(struct device *dev,
> > +                              int resizer_chained,
> > +                              void *user_config, void *config)
> > +{
> > +   struct ipipe_params *param = (struct ipipe_params *)config;
> > +   int ret;
> > +
> > +   dev_dbg(dev, "ipipe_set_resize_config, resizer_chained = %d\n",
> > +           resizer_chained);
> > +   if ((ISNULL(user_config)) || (ISNULL(config))) {
> > +           dev_err(dev, "Invalid user_config or config ptr\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   memcpy((void *)config,
> > +          (void *)&dm365_ipipe_defs,
> > +          sizeof(struct ipipe_params));
> > +
> > +   if (oper_mode != IMP_MODE_SINGLE_SHOT)
> > +           return configure_resizer_in_cont_mode(dev,
> > +                                                 user_config,
> > +                                                 resizer_chained,
> > +                                                 param);
> > +
> > +   ret = configure_resizer_in_ss_mode(dev,
> > +                                       user_config,
> > +                                       resizer_chained,
> > +                                       param);
> > +   if (!ret && (!en_serializer && !resizer_chained))
> > +           ret = ipipe_hw_setup(config);
> > +
> > +   return ret;
> > +}
> > +
> > +static void configure_resize_passthru(struct ipipe_params *param, int bypass)
> > +{
> > +   param->rsz_rsc_param[RSZ_A].cen = DISABLE;
> > +   param->rsz_rsc_param[RSZ_A].yen = DISABLE;
> > +   param->rsz_rsc_param[RSZ_A].v_phs_y = 0;
> > +   param->rsz_rsc_param[RSZ_A].v_phs_c = 0;
> > +   param->rsz_rsc_param[RSZ_A].v_dif = 256;
> > +   param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0;
> > +   param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0;
> > +   param->rsz_rsc_param[RSZ_A].h_phs = 0;
> > +   param->rsz_rsc_param[RSZ_A].h_dif = 256;
> > +   param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0;
> > +   param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0;
> > +   param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE;
> > +   param->rsz2rgb[RSZ_A].rgb_en = DISABLE;
> > +   param->rsz_en[RSZ_A] = ENABLE;
> > +   param->rsz_en[RSZ_B] = DISABLE;
> > +   if (bypass) {
> > +           param->rsz_rsc_param[RSZ_A].i_vps = 0;
> > +           param->rsz_rsc_param[RSZ_A].i_hps = 0;
> > +           /* Raw Bypass */
> > +           param->rsz_common.passthrough = IPIPE_BYPASS_ON;
> > +   }
> > +}
> > +
> > +static inline int prev_validate_output_image_format(struct device *dev,
> > +                                   enum ipipe_pix_formats pix,
> > +                                   int *line_len,
> > +                                   int in_width, int in_height)
> > +{
> > +   if (pix != IPIPE_UYVY && pix != IPIPE_BAYER) {
> > +           dev_err(dev,
> > +                   "prev_validate_output_image_format"
> > +                   "pix format not supported, %d\n", pix);
> > +           return -EINVAL;
> > +   }
> > +
> > +   if ((in_width == 0) || (in_height == 0)) {
> > +           dev_err(dev,
> > +                   "prev_validate_output_image_format:"
> > +                   " invalid width or height\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   *line_len = in_width * 2;
> > +
> > +   /* Adjust line length to be a multiple of 32 */
> > +   *line_len += 31;
> > +   *line_len &= ~0x1f;
> > +
> > +   return 0;
> > +}
> > +
> > +static inline int validate_preview_input_spec(struct device *dev,
> > +                                         enum ipipe_pix_formats pix,
> > +                                         int width,
> > +                                         int height, int *line_len)
> > +{
> > +   if (pix != IPIPE_UYVY && pix != IPIPE_BAYER &&
> > +     pix != IPIPE_BAYER_8BIT_PACK && pix != IPIPE_BAYER_8BIT_PACK_ALAW &&
> > +     pix != IPIPE_BAYER_8BIT_PACK_DPCM &&
> > +     pix != IPIPE_BAYER_12BIT_PACK) {
> > +           dev_err(dev,
> > +                   "validate_preview_input_spec:"
> > +                   "pix format not supported, %d\n", pix);
> > +           return -EINVAL;
> > +   }
> > +   if (width == 0 || height == 0) {
> > +           dev_err(dev,
> > +                   "rsz_validate_out_image_formats: "
> > +                   "invalid width or height\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (pix == IPIPE_UYVY || pix == IPIPE_BAYER)
> > +           *line_len = width * 2;
> > +   else if (pix == IPIPE_BAYER_8BIT_PACK ||
> > +            pix == IPIPE_BAYER_8BIT_PACK_ALAW ||
> > +            pix == IPIPE_BAYER_8BIT_PACK_DPCM)
> > +           *line_len = width;
> > +   else
> > +           /* 12 bit */
> > +           *line_len = width + (width >> 1);
> > +   /* Adjust line length to be a multiple of 32 */
> > +   *line_len += 31;
> > +   *line_len &= ~0x1f;
> > +
> > +   return 0;
> > +}
> > +
> > +static int configure_previewer_in_cont_mode(struct device *dev,
> > +                                       void *user_config,
> > +                                       struct ipipe_params *param)
> > +{
> > +   struct prev_continuous_config *cont_config =
> > +       (struct prev_continuous_config *)user_config;
> > +   int ret;
> > +
> > +   if (cont_config->input.en_df_sub) {
> > +           dev_err(dev, "DF suV4L2_MBUS_FMT_SBGGR10_1X10btraction "
> > +                             "is not supported\n");
> > +           return -EINVAL;
> > +   }
> > +   if (cont_config->input.dec_en && ((cont_config->input.rsz <
> > +           IPIPEIF_RSZ_MIN) || (cont_config->input.rsz >
> > +           IPIPEIF_RSZ_MAX))) {
> > +           dev_err(dev, "rsz range is %d to %d\n",
> > +                   IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
> > +           return -EINVAL;
> > +   }
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   param->rsz_common.passthrough = cont_config->bypass;
> > +   param->ipipeif_param.source = IPIPEIF_CCDC;
> > +   param->ipipeif_param.clock_select = IPIPEIF_PIXCEL_CLK;
> > +   param->ipipeif_param.mode = IPIPEIF_CONTINUOUS;
> > +   if (cont_config->input.dec_en) {
> > +           param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
> > +           param->ipipeif_param.rsz = cont_config->input.rsz;
> > +           param->ipipeif_param.avg_filter =
> > +               (enum ipipeif_avg_filter)cont_config->input.avg_filter_en;
> > +   }
> > +   /* IPIPE mode */
> > +   param->ipipe_mode = IPIPEIF_CONTINUOUS;
> > +   param->ipipe_colpat_olop = cont_config->input.colp_olop;
> > +   param->ipipe_colpat_olep = cont_config->input.colp_olep;
> > +   param->ipipe_colpat_elop = cont_config->input.colp_elop;
> > +   param->ipipe_colpat_elep = cont_config->input.colp_elep;
> > +   param->ipipeif_param.gain = cont_config->input.gain;
> > +   param->ipipeif_param.var.if_5_1.clip = cont_config->input.clip;
> > +   param->ipipeif_param.var.if_5_1.dpc = cont_config->input.dpc;
> > +   param->ipipeif_param.var.if_5_1.align_sync =
> > +       cont_config->input.align_sync;
> > +   param->ipipeif_param.var.if_5_1.rsz_start =
> > +       cont_config->input.rsz_start;
> > +   if (!oper_state.rsz_chained) {
> > +           param->rsz_rsc_param[0].mode = IPIPEIF_CONTINUOUS;
> > +           /* setup bypass resizer */
> > +           configure_resize_passthru(param, 0);
> > +   }
> > +   if (cont_config->bypass)
> > +           configure_resize_passthru(param, 1);
> > +   oper_state.prev_config_state = STATE_CONFIGURED;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int configure_previewer_in_ss_mode(struct device *dev,
> > +                                     void *user_config,
> > +                                     struct ipipe_params *param)
> > +{
> > +   struct prev_single_shot_config *ss_config =
> > +       (struct prev_single_shot_config *)user_config;
> > +   int line_len;
> > +   int ret;
> > +
> > +   ret = validate_preview_input_spec(dev,
> > +                                     ss_config->input.pix_fmt,
> > +                                     ss_config->input.image_width,
> > +                                     ss_config->input.image_height,
> > +                                     &line_len);
> > +   if (ret)
> > +           return -EINVAL;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +
> > +   if (!ss_config->input.line_length)
> > +           param->ipipeif_param.adofs = line_len;
> > +   else {
> > +           param->ipipeif_param.adofs = ss_config->input.line_length;
> > +           param->ipipeif_param.adofs =
> > +                           (param->ipipeif_param.adofs + 31) & ~0x1f;
> > +   }
> > +   if (ss_config->input.dec_en && ss_config->input.frame_div_mode_en) {
> > +           dev_err(dev,
> > +                   "Both dec_en & frame_div_mode_en"
> > +                   "can not enabled simultaneously\n");
> > +           mutex_unlock(&oper_state.lock);
> > +           return -EINVAL;
> > +   }
> > +
> > +   ret = validate_ipipeif_decimation(dev,
> > +                                     ss_config->input.dec_en,
> > +                                     ss_config->input.rsz,
> > +                                     ss_config->input.frame_div_mode_en,
> > +                                     ss_config->input.image_width);
> > +   if (ret) {
> > +           mutex_unlock(&oper_state.lock);
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (!oper_state.rsz_chained) {
> > +           ret = prev_validate_output_image_format(dev,
> > +                                                   ss_config->output.
> > +                                                   pix_fmt, &line_len,
> > +                                                   ss_config->input.
> > +                                                   image_width,
> > +                                                   ss_config->input.
> > +                                                   image_height);
> > +           if (ret) {
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return -EINVAL;
> > +           }
> > +           param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
> > +           if (ss_config->input.frame_div_mode_en)
> > +                   ret = update_preview_f_div_params(dev,
> > +                                   ss_config->input.
> > +                                   image_width,
> > +                                   ss_config->input.
> > +                                   image_width,
> > +                                   &param->
> > +                                   rsz_rsc_param[RSZ_A]);
> > +           if (ret) {
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return -EINVAL;
> > +           }
> > +   } else {
> > +           if (ss_config->input.frame_div_mode_en &&
> > +               param->rsz_en[RSZ_A]) {
> > +                   if (!param->rsz_rsc_param[RSZ_A].dscale_en)
> > +                           ret = calculate_normal_f_div_param(
> > +                                                   dev,
> > +                                                   ss_config->input.
> > +                                                     image_width,
> > +                                                   param->rsz_rsc_param
> > +                                                     [RSZ_A].
> > +                                                     o_vsz + 1,
> > +                                                   &param->rsz_rsc_param
> > +                                                     [RSZ_A]);
> > +                   else
> > +                           ret = calculate_down_scale_f_div_param(
> > +                                                   dev,
> > +                                                   ss_config->
> > +                                                   input.image_width,
> > +                                                   param->rsz_rsc_param
> > +                                                     [RSZ_A].o_vsz + 1,
> > +                                                   &param->rsz_rsc_param
> > +                                                     [RSZ_A]);
> > +                   if (ret) {
> > +                           mutex_unlock(&oper_state.lock);
> > +                           return -EINVAL;
> > +                   }
> > +           }
> > +           if (ss_config->input.frame_div_mode_en &&
> > +               param->rsz_en[RSZ_B]) {
> > +                   if (!param->rsz_rsc_param[RSZ_B].dscale_en)
> > +                           ret = calculate_normal_f_div_param(
> > +                                                   dev,
> > +                                                   ss_config->input.
> > +                                                      image_width,
> > +                                                   param->rsz_rsc_param
> > +                                                      [RSZ_B].o_vsz + 1,
> > +                                                   &param->rsz_rsc_param
> > +                                                      [RSZ_B]);
> > +                   else
> > +                           ret = calculate_down_scale_f_div_param(
> > +                                                   dev,
> > +                                                   ss_config->input.
> > +                                                      image_width,
> > +                                                   param->rsz_rsc_param
> > +                                                      [RSZ_B].o_vsz + 1,
> > +                                                   &param->rsz_rsc_param
> > +                                                      [RSZ_B]);
> > +                   if (ret) {
> > +                           mutex_unlock(&oper_state.lock);
> > +                           return -EINVAL;
> > +                   }
> > +           }
>
> Are there differences between the two above ifs other than the resizer
> number? I don't think so and I don't think this is the only place.
Not sure whether it was done to save on indentation or if both of them
Resizer A and B can be used simultaneously. Will check and currect it either ways.
>
> > +   }
> > +   if (ipipe_process_pix_fmts(ss_config->input.pix_fmt,
> > +                              ss_config->output.pix_fmt,
> > +                              param) < 0) {
> > +           dev_err(dev, "error in input or output pix format\n");
> > +           mutex_unlock(&oper_state.lock);
> > +           return -EINVAL;
> > +   }
> > +   param->ipipeif_param.hnum = ss_config->input.image_width;
> > +   param->ipipeif_param.vnum = ss_config->input.image_height;
> > +   param->ipipeif_param.glob_hor_size = ss_config->input.ppln;
> > +   param->ipipeif_param.glob_ver_size = ss_config->input.lpfr;
> > +   param->ipipeif_param.var.if_5_1.clk_div = ss_config->input.clk_div;
> > +   param->ipipeif_param.var.if_5_1.pix_order = ss_config->input.pix_order;
> > +   param->ipipeif_param.var.if_5_1.align_sync =
> > +       ss_config->input.align_sync;
> > +   param->ipipeif_param.var.if_5_1.rsz_start = ss_config->input.rsz_start;
> > +   if (param->ipipeif_param.var.if_5_1.dpcm.en) {
> > +           param->ipipeif_param.var.if_5_1.dpcm.pred =
> > +               ss_config->input.pred;
> > +           param->ipipeif_param.var.if_5_1.dpcm.type =
> > +           IPIPEIF_DPCM_8BIT_12BIT;
> > +   }
> > +   param->ipipeif_param.var.if_5_1.data_shift =
> > +       ss_config->input.data_shift;
> > +
> > +   param->ipipe_hsz = ss_config->input.image_width - 1;
> > +   if (ss_config->input.dec_en) {
> > +           if ((ss_config->input.rsz < IPIPEIF_RSZ_MIN) ||
> > +               (ss_config->input.rsz > IPIPEIF_RSZ_MAX)) {
> > +                   dev_err(dev, "rsz range is %d to %d\n",
> > +                           IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
> > +                   mutex_unlock(&oper_state.lock);
> > +                   return -EINVAL;
> > +           }
> > +           param->ipipeif_param.decimation = IPIPEIF_DECIMATION_ON;
> > +           param->ipipeif_param.rsz = ss_config->input.rsz;
> > +           param->ipipeif_param.avg_filter =
> > +               (enum ipipeif_avg_filter)ss_config->input.avg_filter_en;
> > +           param->ipipe_hsz =
> > +               (((ss_config->input.image_width * IPIPEIF_RSZ_CONST) /
> > +                 ss_config->input.rsz) - 1);
> > +   }
> > +   param->ipipeif_param.gain = ss_config->input.gain;
> > +   param->ipipeif_param.var.if_5_1.clip = ss_config->input.clip;
> > +   param->ipipeif_param.var.if_5_1.dpc = ss_config->input.dpc;
> > +   param->ipipe_colpat_olop = ss_config->input.colp_olop;
> > +   param->ipipe_colpat_olep = ss_config->input.colp_olep;
> > +   param->ipipe_colpat_elop = ss_config->input.colp_elop;
> > +   param->ipipe_colpat_elep = ss_config->input.colp_elep;
> > +   param->ipipe_vps = ss_config->input.vst;
> > +   param->ipipe_hps = ss_config->input.hst;
> > +   param->ipipe_vsz = ss_config->input.image_height - 1;
> > +   if (ss_config->input.pix_fmt == IPIPE_UYVY)
> > +           param->ipipeif_param.source = IPIPEIF_SDRAM_YUV;
> > +   else
> > +           param->ipipeif_param.source = IPIPEIF_SDRAM_RAW;
> > +
> > +   configure_common_rsz_in_params(dev, param, 1, oper_state.rsz_chained,
> > +                                          &ss_config->input);
> > +
> > +   param->rsz_common.passthrough = ss_config->bypass;
> > +   /* update the resize parameters */
> > +   if (ss_config->bypass == IPIPE_BYPASS_ON ||
> > +       param->ipipe_dpaths_fmt == IPIPE_RAW2RAW)
> > +           /* Bypass resizer */
> > +           configure_resize_passthru(param, 1);
> > +   else {
> > +           if (oper_state.rsz_chained) {
> > +                   if (param->rsz_en[RSZ_A]) {
> > +                           calculate_resize_ratios(param, RSZ_A);
> > +                           calculate_sdram_offsets(param, RSZ_A);
> > +                   }
> > +                   if (param->rsz_en[RSZ_B]) {
> > +                           calculate_resize_ratios(param, RSZ_B);
> > +                           calculate_sdram_offsets(param, RSZ_B);
> > +                   }
> > +           } else {
> > +                   struct rsz_output_spec *output_specs =
> > +                           kmalloc(sizeof(struct rsz_output_spec),
> > +                                   GFP_KERNEL);
> > +                   if (ISNULL(output_specs)) {
> > +                           dev_err(dev, "Memory Alloc failure\n");
> > +                           mutex_unlock(&oper_state.lock);
> > +                           return -EINVAL;
> > +                   }
> > +                           /* Using resizer as pass through */
> > +                   configure_resize_passthru(param, 0);
> > +                   memset((void *)output_specs, 0,
> > +                           sizeof(struct rsz_output_spec));
> > +                   output_specs->enable = 1;
> > +                   output_specs->pix_fmt = IPIPE_UYVY;
> > +                   output_specs->width = ss_config->input.image_width;
> > +                   output_specs->height = ss_config->input.image_height;
> > +                   output_specs->vst_y = ss_config->input.vst;
> > +                   configure_resizer_out_params(param, RSZ_A,
> > +                           output_specs, 0, 0);
> > +                   calculate_sdram_offsets(param, RSZ_A);
> > +                   kfree(output_specs);
> > +           }
> > +   }
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ipipe_reconfig_resizer(struct device *dev,
> > +                           struct rsz_reconfig *reconfig,
> > +                           void *config)
> > +{
> > +   struct ipipe_params *param = (struct ipipe_params *)config;
> > +
> > +   if (ISNULL(reconfig)) {
> > +           dev_err(dev, "Null User ptr received for reconfig");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if ((reconfig->pix_format != IMP_420SP_Y) &&
> > +           (reconfig->pix_format != IMP_420SP_C)) {
> > +           dev_err(dev, "reconfig - pixel format incorrect");
> > +           return -EINVAL;
> > +   }
> > +   if (param->rsz_common.src_img_fmt != RSZ_IMG_420) {
> > +           dev_err(dev, "reconfig - source format originally"
> > +                           "configured is not YUV420SP\n");
> > +           return -EINVAL;
> > +   }
> > +   if ((param->rsz_common.y_c) && (reconfig->pix_format == IMP_420SP_C)) {
> > +           dev_err(dev, "reconfig - channel is already configured"
> > +                           "for YUV420SP - C data\n");
> > +           return -EINVAL;
> > +   }
> > +   if ((!param->rsz_common.y_c) &&
> > +           (reconfig->pix_format == IMP_420SP_Y)) {
> > +           dev_err(dev, "reconfig - channel is already configured"
> > +                           "for YUV420SP - Y data\n");
> > +           return -EINVAL;
> > +   }
> > +   if (reconfig->pix_format == IMP_420SP_Y)
> > +           param->rsz_common.y_c = 0;
> > +   else
> > +           param->rsz_common.y_c = 1;
> > +   if (!en_serializer)
> > +           rsz_set_in_pix_format(param->rsz_common.y_c);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ipipe_set_preview_config(struct device *dev,
> > +                               void *user_config, void *config)
> > +{
> > +   struct ipipe_params *param = (struct ipipe_params *)config;
> > +   int ret;
> > +
> > +   dev_err(dev, "ipipe_set_preview_config\n");
> > +
> > +   if ((ISNULL(user_config)) || (ISNULL(config))) {
> > +           dev_err(dev, "Invalid user_config or config ptr\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (!oper_state.rsz_chained) {
> > +           /* For chained resizer, defaults are set by resizer */
> > +           memcpy((void *)config,
> > +                  (void *)&dm365_ipipe_defs,
> > +                  sizeof(struct ipipe_params));
> > +   }
> > +
> > +   /* continuous mode */
> > +   if (oper_mode == IMP_MODE_CONTINUOUS)
> > +           return configure_previewer_in_cont_mode(dev, user_config,
> > +                                                   param);
> > +
> > +   /* shared block */
> > +   /* previewer in standalone mode. In this mode if serializer
> > +    * is enabled, we need to set config params for hw.
> > +    */
> > +   ret = configure_previewer_in_ss_mode(dev, user_config, param);
> > +
> > +   if ((!ret) && !en_serializer)
> > +           ret = ipipe_hw_setup(config);
> > +
> > +   return ret;
> > +}
> > +
> > +static int ipipe_set_input_win(struct imp_window *win)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +   int ret;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   if (param->ipipeif_param.decimation) {
> > +           param->ipipe_hsz =
> > +               ((win->width * IPIPEIF_RSZ_CONST) /
> > +                param->ipipeif_param.rsz) - 1;
> > +   } else
> > +           param->ipipe_hsz = win->width - 1;
> > +   if (!oper_state.frame_format) {
> > +           param->ipipe_vsz = (win->height >> 1) - 1;
> > +           param->ipipe_vps = (win->vst >> 1);
> > +   } else {
> > +           param->ipipe_vsz = win->height - 1;
> > +           param->ipipe_vps = win->vst;
> > +   }
> > +   param->ipipe_hps = win->hst;
> > +   param->rsz_common.vsz = param->ipipe_vsz;
> > +   param->rsz_common.hsz = param->ipipe_hsz;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +static int ipipe_get_input_win(struct imp_window *win)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +   int ret;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   if (param->ipipeif_param.decimation)
> > +           win->width =
> > +               (((param->ipipe_hsz + 1) * param->ipipeif_param.rsz) >> 4);
> > +   else
> > +           win->width = param->ipipe_hsz + 1;
> > +   if (!oper_state.frame_format) {
> > +           win->height = (param->ipipe_vsz + 1) << 1;
> > +           win->vst = (param->ipipe_vps << 1);
> > +   } else {
> > +           win->height = param->ipipe_vsz + 1;
> > +           win->vst = param->ipipe_vps;
> > +   }
> > +   win->hst = param->ipipe_hps;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ipipe_set_in_pixel_format(enum imp_pix_formats pix_fmt)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +   int ret;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   oper_state.in_pixel_format = pix_fmt;
> > +   param->rsz_common.src_img_fmt = RSZ_IMG_422;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ipipe_set_out_pixel_format(enum imp_pix_formats pix_fmt)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +   int err;
> > +
> > +   /* if image is RAW, preserve raw image format while flipping.
> > +    * otherwise preserve, preserve ycbcr format while flipping
> > +    */
> > +   if (pix_fmt == IMP_BAYER)
> > +           param->rsz_common.raw_flip = 1;
> > +   else
> > +           param->rsz_common.raw_flip = 0;
> > +
> > +   err = mutex_lock_interruptible(&oper_state.lock);
> > +   if (err)
> > +           return err;
> > +   oper_state.out_pixel_format = pix_fmt;
> > +   err = ipipe_process_pix_fmts(oper_state.in_pixel_format,
> > +                                oper_state.out_pixel_format,
> > +                                param);
> > +
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return err;
> > +}
> > +
> > +static int ipipe_set_buftype(unsigned char buf_type)
> > +{
> > +   int ret;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   oper_state.buffer_type = buf_type;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ipipe_set_frame_format(unsigned char frm_fmt)
> > +{
> > +   int ret;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   oper_state.frame_format = frm_fmt;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ipipe_set_output_win(struct imp_window *win)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +   struct rsz_output_spec output_specs;
> > +   int line_len_c;
> > +   int line_len;
> > +   int ret = -EINVAL;
> > +
> > +   if (!param->rsz_en[0]) {
> > +           printk(KERN_ERR "resizer output1 not enabled\n");
> > +           return ret;
> > +   }
> > +   output_specs.enable = 1;
> > +   output_specs.width = win->width;
> > +   /* Always set output height same as in height
> > +      for de-interlacing
> > +    */
> > +   output_specs.height = win->height;
> > +   output_specs.vst_y = win->vst;
> > +   if (oper_state.out_pixel_format == IPIPE_YUV420SP)
> > +           output_specs.vst_c = win->vst;
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   configure_resizer_out_params(param, RSZ_A, &output_specs, 0, 0);
> > +   calculate_line_length(oper_state.out_pixel_format,
> > +                                param->rsz_rsc_param[0].o_hsz + 1,
> > +                                param->rsz_rsc_param[0].o_vsz + 1,
> > +                                &line_len,
> > +                                &line_len_c);
> > +   param->ext_mem_param[0].rsz_sdr_oft_y = line_len;
> > +   param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c;
> > +   calculate_resize_ratios(param, RSZ_A);
> > +   if (param->rsz_en[RSZ_B])
> > +           calculate_resize_ratios(param, RSZ_B);
> > +   if (oper_state.out_pixel_format == IPIPE_YUV420SP)
> > +           enable_422_420_conversion(param, RSZ_A, ENABLE);
> > +   else
> > +           enable_422_420_conversion(param, RSZ_A, DISABLE);
> > +
> > +   ret = calculate_sdram_offsets(param, RSZ_A);
> > +   if (param->rsz_en[RSZ_B])
> > +           ret = calculate_sdram_offsets(param, RSZ_B);
> > +
> > +   if (ret)
> > +           printk(KERN_ERR "error in calculating sdram offsets\n");
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return ret;
> > +}
> > +static int ipipe_get_output_state(unsigned char out_sel)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +
> > +   if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
> > +           return 0;
> > +
> > +   return param->rsz_en[out_sel];
> > +}
> > +
> > +/* This should be called only after setting the output
> > + * window params. This also assumes the corresponding
> > + * output is configured prior to calling this.
> > + */
> > +static int ipipe_get_line_length(unsigned char out_sel)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +
> > +   if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
> > +           return -EINVAL;
> > +   /* assume output is always UYVY. Change this if we
> > +    * support RGB
> > +    */
> > +   if (!param->rsz_en[out_sel])
> > +           return -EINVAL;
> > +
> > +   return param->ext_mem_param[out_sel].rsz_sdr_oft_y;
> > +}
> > +
> > +static int ipipe_get_image_height(unsigned char out_sel)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +
> > +   if ((out_sel != RSZ_A) && (out_sel != RSZ_B))
> > +           return -EINVAL;
> > +   if (!param->rsz_en[out_sel])
> > +           return -EINVAL;
> > +
> > +   return param->rsz_rsc_param[out_sel].o_vsz + 1;
> > +}
> > +
> > +/* Assume valid param ptr */
> > +static int ipipe_set_hw_if_param(struct vpfe_hw_if_param *if_param)
> > +{
> > +   struct ipipe_params *param = oper_state.shared_config_param;
> > +   int ret;
> > +
> > +   ret = mutex_lock_interruptible(&oper_state.lock);
> > +   if (ret)
> > +           return ret;
> > +   param->ipipeif_param.var.if_5_1.isif_port = *if_param;
> > +   mutex_unlock(&oper_state.lock);
> > +
> > +   return 0;
> > +}
> > +
> > +static struct imp_hw_interface dm365_ipipe_interface = {
> > +   .name = "DM365 IPIPE",
> > +   .owner = THIS_MODULE,
> > +   .prev_enum_modules = prev_enum_preview_cap,
> > +   .set_oper_mode = ipipe_set_oper_mode,
> > +   .reset_oper_mode = ipipe_reset_oper_mode,
> > +   .get_oper_mode = prev_get_oper_mode,
> > +   .get_hw_state = ipipe_get_oper_state,
> > +   .set_hw_state = ipipe_set_oper_state,
> > +   .resizer_chain = ipipe_rsz_chain_state,
> > +   .lock_chain = ipipe_lock_chain,
> > +   .unlock_chain = ipipe_unlock_chain,
> > +   .serialize = ipipe_serialize,
> > +   .alloc_config_block = ipipe_alloc_config_block,
> > +   .dealloc_config_block = ipipe_dealloc_config_block,
> > +   .alloc_user_config_block = ipipe_alloc_user_config_block,
> > +   .dealloc_config_block = ipipe_dealloc_user_config_block,
> > +   .set_user_config_defaults = ipipe_set_user_config_defaults,
> > +   .set_preview_config = ipipe_set_preview_config,
> > +   .set_resizer_config = ipipe_set_resize_config,
> > +   .reconfig_resizer = ipipe_reconfig_resizer,
> > +   .update_inbuf_address = ipipe_set_ipipe_if_address,
> > +   .update_outbuf1_address = ipipe_update_outbuf1_address,
> > +   .update_outbuf2_address = ipipe_update_outbuf2_address,
> > +   .enable = ipipe_enable,
> > +   .enable_resize = rsz_src_enable,
> > +   .hw_setup = ipipe_do_hw_setup,
> > +   .get_resizer_config_state = ipipe_get_rsz_config_state,
> > +   .get_previewer_config_state = ipipe_get_prev_config_state,
> > +   .set_input_win = ipipe_set_input_win,
> > +   .get_input_win = ipipe_get_input_win,
> > +   .set_hw_if_param = ipipe_set_hw_if_param,
> > +   .set_in_pixel_format = ipipe_set_in_pixel_format,
> > +   .set_out_pixel_format = ipipe_set_out_pixel_format,
> > +   .set_buftype = ipipe_set_buftype,
> > +   .set_frame_format = ipipe_set_frame_format,
> > +   .set_output_win = ipipe_set_output_win,
> > +   .get_output_state = ipipe_get_output_state,
> > +   .get_line_length = ipipe_get_line_length,
> > +   .get_image_height = ipipe_get_image_height,
> > +   .get_image_height = ipipe_get_image_height,
> > +   .get_max_output_width = ipipe_get_max_output_width,
> > +   .get_max_output_height = ipipe_get_max_output_height,
> > +   .enum_pix = ipipe_enum_pix,
> > +};
> > +
> > +struct imp_hw_interface *imp_get_hw_if(void)
> > +{
> > +   return &dm365_ipipe_interface;
> > +}
> > +
> > +void enable_serializer(int val)
> > +{
> > +   en_serializer = val;
> > +}
> > +
> > +int ipipe_init(void)
> > +{
> > +   oper_state.shared_config_param =
> > +       kmalloc(sizeof(struct ipipe_params), GFP_KERNEL);
> > +
> > +   if (ISNULL(oper_state.shared_config_param)) {
> > +           printk(KERN_ERR
> > +                  "dm365_ipipe_init: failed to allocate memory\n");
> > +           return -ENOMEM;
> > +   }
> > +   memcpy(&dm365_ipipe_defs.ipipeif_param.var.if_5_1,
> > +           &ipipeif_5_1_defaults,
> > +           sizeof(struct ipipeif_5_1));
> > +   lutdpc.table = ipipe_lutdpc_table;
> > +   lut_3d.table = ipipe_3d_lut_table;
> > +   gbce.table = ipipe_gbce_table;
> > +   gamma.table_r = ipipe_gamma_table_r;
> > +   gamma.table_b = ipipe_gamma_table_b;
> > +   gamma.table_g = ipipe_gamma_table_g;
> > +   yee.table = ipipe_yee_table;
> > +   mutex_init(&oper_state.lock);
> > +   oper_state.state = CHANNEL_FREE;
> > +   oper_state.prev_config_state = STATE_NOT_CONFIGURED;
> > +   oper_state.rsz_config_state = STATE_NOT_CONFIGURED;
> > +   oper_state.frame_format = 1;
> > +   oper_state.in_pixel_format = IMP_BAYER;
> > +   oper_state.out_pixel_format = IMP_UYVY;
> > +
> > +   return 0;
> > +}
> > +
> > +void ipipe_cleanup(void)
> > +{
> > +   kfree(oper_state.shared_config_param);
> > +}
> > diff --git a/drivers/media/video/davinci/dm365_ipipe.h b/drivers/media/video/davinci/dm365_ipipe.h
> > new file mode 100644
> > index 0000000..9b5dfae
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/dm365_ipipe.h
> > @@ -0,0 +1,300 @@
> > +/*
> > +* Copyright (C) 2011 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
> > +*
> > +* Feature description
> > +* ===================
> > +*
> > +* VPFE hardware setup
> > +*
> > +* case 1: Capture to SDRAM with out IPIPE
> > +* ****************************************
> > +*
> > +*            parallel
> > +*                port
> > +*
> > +* Image sensor/       ________
> > +* Yuv decoder    ---->| CCDC |--> SDRAM
> > +*                     |______|
> > +*
> > +* case 2: Capture to SDRAM with IPIPE Preview modules in Continuous
> > +*          (On the Fly mode)
> > +*
> > +* Image sensor/       ________    ____________________
> > +* Yuv decoder    ---->| CCDC |--> | Previewer modules |--> SDRAM
> > +*                     |______|    |___________________|
> > +*
> > +* case 3: Capture to SDRAM with IPIPE Preview modules  & Resizer
> > +*         in continuous (On the Fly mode)
> > +*
> > +* Image sensor/       ________    _____________   ___________
> > +* Yuv decoder    ---->| CCDC |--> | Previewer  |->| Resizer  |-> SDRAM
> > +*                     |______|    |____________|  |__________|
> > +*
> > +* case 4: Capture to SDRAM with IPIPE Resizer
> > +*         in continuous (On the Fly mode)
> > +*
> > +* Image sensor/       ________    ___________
> > +* Yuv decoder    ---->| CCDC |--> | Resizer  |-> SDRAM
> > +*                     |______|    |__________|
> > +*
> > +* case 5: Read from SDRAM and do preview and/or Resize
> > +*         in Single shot mode
> > +*
> > +*                   _____________   ___________
> > +*    SDRAM   ----> | Previewer  |->| Resizer  |-> SDRAM
> > +*                  |____________|  |__________|
> > +*
> > +*
> > +* Previewer allows fine tuning of the input image using different
> > +* tuning modules in IPIPE. Some examples :- Noise filter, Defect
> > +* pixel correction etc. It essentially operate on Bayer Raw data
> > +* or YUV raw data. To do image tuning, application call,
> > +* PREV_QUERY_CAP, and then call PREV_SET_PARAM to set parameter
> > +* for a module.
> > +*
> > +*
> > +* Resizer allows upscaling or downscaling a image to a desired
> > +* resolution. There are 2 resizer modules. both operating on the
> > +* same input image, but can have different output resolution.
> > +*/
> > +
> > +#ifndef DM365_IPIPE_H
> > +#define DM365_IPIPE_H
> > +
> > +#ifdef __KERNEL__
> > +#include "imp_common.h"
> > +#include "dm3xx_ipipeif.h"
> > +#include <linux/davinci_vpfe.h>
> > +
> > +/* Used for driver storage */
> > +struct ipipe_otfdpc_2_0 {
> > +   /* 0 - disable, 1 - enable */
> > +   unsigned char en;
> > +   /* defect detection method */
> > +   enum ipipe_otfdpc_det_meth det_method;
> > +   /* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
> > +    * used
> > +    */
> > +   enum ipipe_otfdpc_alg alg;
> > +   struct prev_otfdpc_2_0 otfdpc_2_0;
> > +};
> > +
> > +struct ipipe_otfdpc_3_0 {
> > +   /* 0 - disable, 1 - enable */
> > +   unsigned char en;
> > +   /* defect detection method */
> > +   enum ipipe_otfdpc_det_meth det_method;
> > +   /* Algorith used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
> > +    * used
> > +    */
> > +   enum ipipe_otfdpc_alg alg;
> > +   struct prev_otfdpc_3_0 otfdpc_3_0;
> > +};
> > +
> > +enum enable_disable_t {
> > +   DISABLE,
> > +   ENABLE
> > +};
>
> Does that bring value over using e.g. boolean?
:). I will change it to boolean, and have defines for DISABLE and ENABLE
>
> > +#define CEIL(a, b) (((a) + (b-1)) / (b))
> > +#define IPIPE_MAX_PASSES   2
> > +
> > +struct f_div_pass {
> > +   unsigned int o_hsz;
> > +   unsigned int i_hps;
> > +   unsigned int h_phs;
> > +   unsigned int src_hps;
> > +   unsigned int src_hsz;
> > +};
> > +
> > +struct f_div_param {
> > +   unsigned char en;
> > +   unsigned int num_passes;
> > +   struct f_div_pass pass[IPIPE_MAX_PASSES];
> > +};
> > +
> > +/* Resizer Rescale Parameters*/
> > +struct ipipe_rsz_rescale_param {
> > +   enum ipipe_oper_mode mode;
> > +   enum enable_disable_t h_flip;
> > +   enum enable_disable_t v_flip;
> > +   enum enable_disable_t cen;
> > +   enum enable_disable_t yen;
> > +   unsigned short i_vps;
> > +   unsigned short i_hps;
> > +   unsigned short o_vsz;
> > +   unsigned short o_hsz;
> > +   unsigned short v_phs_y;
> > +   unsigned short v_phs_c;
> > +   unsigned short v_dif;
> > +   /* resize method - Luminance */
> > +   enum rsz_intp_t v_typ_y;
> > +   /* resize method - Chrominance */
> > +   enum rsz_intp_t v_typ_c;
> > +   /* vertical lpf intensity - Luminance */
> > +   unsigned char v_lpf_int_y;
> > +   /* vertical lpf intensity - Chrominance */
> > +   unsigned char v_lpf_int_c;
> > +   unsigned short h_phs;
> > +   unsigned short h_dif;
> > +   /* resize method - Luminance */
> > +   enum rsz_intp_t h_typ_y;
> > +   /* resize method - Chrominance */
> > +   enum rsz_intp_t h_typ_c;
> > +   /* horizontal lpf intensity - Luminance */
> > +   unsigned char h_lpf_int_y;
> > +   /* horizontal lpf intensity - Chrominance */
> > +   unsigned char h_lpf_int_c;
> > +   enum enable_disable_t dscale_en;
> > +   enum down_scale_ave_sz h_dscale_ave_sz;
> > +   enum down_scale_ave_sz v_dscale_ave_sz;
> > +   /* store the calculated frame division parameter */
> > +   struct f_div_param f_div;
> > +};
> > +
> > +enum ipipe_rsz_rgb_t {
> > +   OUTPUT_32BIT,
> > +   OUTPUT_16BIT
> > +};
> > +
> > +enum ipipe_rsz_rgb_msk_t {
> > +   NOMASK,
> > +   MASKLAST2
> > +};
> > +
> > +/* Resizer RGB Conversion Parameters */
> > +struct ipipe_rsz_resize2rgb {
> > +   enum enable_disable_t rgb_en;
> > +   enum ipipe_rsz_rgb_t rgb_typ;
> > +   enum ipipe_rsz_rgb_msk_t rgb_msk0;
> > +   enum ipipe_rsz_rgb_msk_t rgb_msk1;
> > +   unsigned int rgb_alpha_val;
> > +};
> > +
> > +/* Resizer External Memory Parameters */
> > +struct ipipe_ext_mem_param {
> > +   unsigned int rsz_sdr_oft_y;
> > +   unsigned int rsz_sdr_ptr_s_y;
> > +   unsigned int rsz_sdr_ptr_e_y;
> > +   unsigned int rsz_sdr_oft_c;
> > +   unsigned int rsz_sdr_ptr_s_c;
> > +   unsigned int rsz_sdr_ptr_e_c;
> > +   /* offset to be added to buffer start when flipping for y/ycbcr */
> > +   unsigned int flip_ofst_y;
> > +   /* offset to be added to buffer start when flipping for c */
> > +   unsigned int flip_ofst_c;
> > +   /* c offset for YUV 420SP */
> > +   unsigned int c_offset;
> > +   /* User Defined Y offset for YUV 420SP or YUV420ILE data */
> > +   unsigned int user_y_ofst;
> > +   /* User Defined C offset for YUV 420SP data */
> > +   unsigned int user_c_ofst;
> > +};
> > +
> > +enum rsz_data_source {
> > +   IPIPE_DATA,
> > +   IPIPEIF_DATA
> > +};
> > +
> > +/* data paths */
> > +enum ipipe_data_paths {
> > +   IPIPE_RAW2YUV,
> > +   /* Bayer RAW input to YCbCr output */
> > +   IPIPE_RAW2RAW,
> > +   /* Bayer Raw to Bayer output */
> > +   IPIPE_RAW2BOX,
> > +   /* Bayer Raw to Boxcar output */
> > +   IPIPE_YUV2YUV
> > +   /* YUV Raw to YUV Raw output */
> > +};
> > +
> > +enum rsz_src_img_fmt {
> > +   RSZ_IMG_422,
> > +   RSZ_IMG_420
> > +};
> > +
> > +struct rsz_common_params {
> > +   unsigned int vps;
> > +   unsigned int vsz;
> > +   unsigned int hps;
> > +   unsigned int hsz;
> > +   /* 420 or 422 */
> > +   enum rsz_src_img_fmt src_img_fmt;
> > +   /* Y or C when src_fmt is 420, 0 - y, 1 - c */
> > +   unsigned char y_c;
> > +   /* flip raw or ycbcr */
> > +   unsigned char raw_flip;
> > +   /* IPIPE or IPIPEIF data */
> > +   enum rsz_data_source source;
> > +   enum ipipe_dpaths_bypass_t passthrough;
> > +   unsigned char yuv_y_min;
> > +   unsigned char yuv_y_max;
> > +   unsigned char yuv_c_min;
> > +   unsigned char yuv_c_max;
> > +   enum enable_disable_t rsz_seq_crv;
> > +   enum ipipe_chr_pos out_chr_pos;
> > +};
> > +
> > +struct ipipe_params {
> > +   struct ipipeif ipipeif_param;
> > +   enum ipipe_oper_mode ipipe_mode;
> > +   /* input/output datapath through IPIPE */
> > +   enum ipipe_data_paths ipipe_dpaths_fmt;
> > +   /* color pattern register */
> > +   enum ipipe_colpat_t ipipe_colpat_elep;
> > +   enum ipipe_colpat_t ipipe_colpat_elop;
> > +   enum ipipe_colpat_t ipipe_colpat_olep;
> > +   enum ipipe_colpat_t ipipe_colpat_olop;
> > +   /* horizontal/vertical start, horizontal/vertical size
> > +    * for both IPIPE and RSZ input
> > +    */
> > +   unsigned int ipipe_vps;
> > +   unsigned int ipipe_vsz;
> > +   unsigned int ipipe_hps;
> > +   unsigned int ipipe_hsz;
> > +
> > +   struct rsz_common_params rsz_common;
> > +   struct ipipe_rsz_rescale_param rsz_rsc_param[2];
> > +   struct ipipe_rsz_resize2rgb rsz2rgb[2];
> > +   struct ipipe_ext_mem_param ext_mem_param[2];
> > +   enum enable_disable_t rsz_en[2];
> > +};
> > +
> > +void ipipe_set_d2f_regs(unsigned int id, struct prev_nf *noise_filter);
> > +void ipipe_set_rgb2rgb_regs(unsigned int id, struct prev_rgb2rgb *rgb);
> > +void rsz_set_output_address(struct ipipe_params *params,
> > +                         int resize_no, unsigned int address);
> > +void ipipe_set_yuv422_conv_regs(struct prev_yuv422_conv *conv);
> > +void ipipe_set_lum_adj_regs(struct prev_lum_adj *lum_adj);
> > +void ipipe_set_rgb2ycbcr_regs(struct prev_rgb2yuv *yuv);
> > +void ipipe_set_lutdpc_regs(struct prev_lutdpc *lutdpc);
> > +void ipipe_set_otfdpc_regs(struct prev_otfdpc *otfdpc);
> > +void ipipe_set_3d_lut_regs(struct prev_3d_lut *lut_3d);
> > +void ipipe_set_gamma_regs(struct prev_gamma *gamma);
> > +int ipipe_hw_setup(struct ipipe_params *config);
> > +void ipipe_set_gbce_regs(struct prev_gbce *gbce);
> > +void ipipe_set_gic_regs(struct prev_gic *gic);
> > +void ipipe_set_cfa_regs(struct prev_cfa *cfa);
> > +void ipipe_set_car_regs(struct prev_car *car);
> > +void ipipe_set_cgs_regs(struct prev_cgs *cgs);
> > +void rsz_set_in_pix_format(unsigned char y_c);
> > +void ipipe_set_ee_regs(struct prev_yee *ee);
> > +void ipipe_set_wb_regs(struct prev_wb *wb);
> > +int rsz_enable(int rsz_id, int enable);
> > +void rsz_src_enable(int enable);
> > +
> > +#endif
> > +#endif
> > diff --git a/drivers/media/video/davinci/imp_common.h b/drivers/media/video/davinci/imp_common.h
> > new file mode 100644
> > index 0000000..25b2836
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/imp_common.h
> > @@ -0,0 +1,85 @@
> > +/*
> > +* Copyright (C) 2011 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
> > +*
> > +* imp_common.h file
> > +*/
> > +#ifndef _IMP_COMMON_H
> > +#define _IMP_COMMON_H
> > +
> > +#ifdef __KERNEL__
>
> This is a kernel-only header file. No need to check for __KERNEL__.
>
> > +#include <linux/completion.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/device.h>
> > +#include <linux/mutex.h>
> > +#define MAX_CHANNELS               2
> > +#define    MAX_BUFFERS             6
> > +#define    MAX_PRIORITY            5
> > +#define    MIN_PRIORITY            0
> > +#define    DEFAULT_PRIORITY        3
> > +#define ENABLED                    1
> > +#define DISABLED           0
> > +#define CHANNEL_BUSY               1
> > +#define CHANNEL_FREE               0
> > +#define ISNULL(val) ((val == NULL) ? 1 : 0)
> > +
> > +/* driver configured by application */
> > +#define STATE_CONFIGURED   1
> > +/* driver not configured by application */
> > +#define STATE_NOT_CONFIGURED       0
> > +
> > +enum imp_log_chan_t {
> > +   IMP_PREVIEWER,
> > +   IMP_RESIZER,
> > +   IMP_HISTOGRAM,
> > +   IMP_BOXCAR
> > +};
> > +
> > +/* IMP channel structure */
> > +struct imp_logical_channel {
> > +   /* channel type */
> > +   enum imp_log_chan_t type;
> > +   /* If this channel is chained with another channel, this is set */
> > +   char chained;
> > +   /* Set if there is a primary user of this channel */
> > +   char primary_user;
> > +   /* channel configuration for this logial channel */
> > +   void *config;
> > +   /* Size of the user configuration block */
> > +   int user_config_size;
> > +   /* Saves the user configuration */
> > +   void *user_config;
> > +   /* configure State of the channel */
> > +   unsigned int config_state;
> > +};
> > +
> > +/* Where hardware channel is shared, this is used for serialisation */
> > +struct imp_serializer {
> > +   /* channel config array for serialization */
> > +   struct imp_logical_channel *channel_config[MAX_CHANNELS];
> > +   /* number of elements in the array */
> > +   int array_count;
> > +   /* Semaphore for above config array */
> > +   struct mutex array_sem;
> > +   /* Completion semaphore when hw channel is common
> > +    * Use device specific completion semaphore when request is serialized
> > +    */
> > +   struct completion sem_isr;
> > +};
> > +
> > +
> > +
> > +#endif
> > +#endif
> > diff --git a/drivers/media/video/davinci/imp_hw_if.h b/drivers/media/video/davinci/imp_hw_if.h
> > new file mode 100644
> > index 0000000..20a2b7f
> > --- /dev/null
> > +++ b/drivers/media/video/davinci/imp_hw_if.h
> > @@ -0,0 +1,178 @@
> > +/*
> > +* Copyright (C) 2011 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
> > +*/
> > +
> > +#ifndef _IMP_HW_IF_H
> > +#define _IMP_HW_IF_H
> > +
> > +#ifdef __KERNEL__
>
> Same here.
>
> > +#include <linux/davinci_vpfe.h>
> > +#include "imp_common.h"
> > +#include <media/davinci/vpfe.h>
> > +
> > +struct prev_module_if {
> > +   /* Version of the preview module */
> > +   char *version;
> > +   /* Module IDs as defined above */
> > +   unsigned short module_id;
> > +   /* Name of the module */
> > +   char *module_name;
> > +   /* control allowed in continous mode ? 1 - allowed , 0 - not allowed */
> > +   char control;
> > +   /* path in which module sits */
> > +   enum imp_data_paths path;
> > +   int (*set)(struct device *dev, void *param, int len);
> > +   int (*get)(struct device *dev, void *param, int len);
> > +};
> > +
> > +struct imp_hw_interface {
> > +   /* Name of the image processor hardware */
> > +   char *name;
> > +   /* module owner */
> > +   struct module *owner;
> > +   /*
> > +    * enumerate preview modules. Return interface to the
> > +    * the module
> > +    */
> > +   struct prev_module_if *(*prev_enum_modules) (struct device *dev,
> > +                                                int index);
> > +   /*
> > +    * set operating mode for IPIPE; 1-single shot, 0-continous
> > +    */
> > +   int (*set_oper_mode) (unsigned int mode);
> > +   /*
> > +    * reset operating mode for IPIPE;
> > +    */
> > +   void (*reset_oper_mode) (void);
> > +   /*
> > +    *  get IPIPE operation mode
> > +    */
> > +   unsigned int (*get_oper_mode) (void);
> > +   /* check if hw is busy in continuous mode.
> > +    * Used for checking if hw is used by ccdc driver in
> > +    * continuous mode. If streaming is ON, this will be
> > +    * set to busy
> > +    */
> > +   unsigned int (*get_hw_state) (void);
> > +   /* set hw state */
> > +   void (*set_hw_state) (unsigned int state);
> > +   /* is resizer chained ? */
> > +   unsigned int (*resizer_chain) (void);
> > +   /* this is used to lock shared resource */
> > +   void (*lock_chain) (void);
> > +   /* this is used unlock shared resouce */
> > +   void (*unlock_chain) (void);
> > +   /* Allocate a shared or exclusive config block for hardware
> > +    * configuration
> > +    */
> > +   void *(*alloc_config_block) (struct device *dev);
> > +   /* hw serialization enabled ?? */
> > +   int (*serialize) (void);
> > +   /* De-allocate the exclusive config block */
> > +   void (*dealloc_config_block) (struct device *dev, void *config);
> > +   /* Allocate a user confguration block */
> > +   void *(*alloc_user_config_block) (struct device *dev,
> > +                                     enum imp_log_chan_t chan_type,
> > +                                     int *len);
> > +
> > +   /* de-allocate user config block */
> > +   void (*dealloc_user_config_block) (struct device *dev, void *config);
> > +
> > +   /* set default configuration in the config block */
> > +   void (*set_user_config_defaults) (struct device *dev,
> > +                                     enum imp_log_chan_t chan_type,
> > +                                     void *user_config);
> > +   /* set user configuration for preview */
> > +   int (*set_preview_config) (struct device *dev,
> > +                              void *user_config, void *config);
> > +   /* set user configuration for resize */
> > +   int (*set_resizer_config) (struct device *dev,
> > +                              int resizer_chained,
> > +                              void *user_config, void *config);
> > +
> > +   int (*reconfig_resizer) (struct device *dev,
> > +                           struct rsz_reconfig *user_config,
> > +                           void *config);
> > +
> > +   /* update output buffer address for a channel
> > +    * if config is NULL, the shared config is assumed
> > +    * this is used only in single shot mode
> > +    */
> > +   int (*update_inbuf_address) (void *config, unsigned int address);
> > +   /* update output buffer address for a channel
> > +    * if config is NULL, the shared config is assumed
> > +    */
> > +   void (*update_outbuf1_address) (void *config, unsigned int address);
> > +   /* update output buffer address for a channel
> > +    * if config is NULL, the shared config is assumed
> > +    */
> > +   void (*update_outbuf2_address) (void *config, unsigned int address);
> > +   /* enable or disable hw */
> > +   void (*enable) (unsigned char en, void *config);
> > +   /* enable or disable resizer to allow frame by frame resize in
> > +    * continuous mode
> > +    */
> > +   void (*enable_resize) (int en);
> > +   /* setup hardware for processing. if config is NULL,
> > +    * shared channel is assumed
> > +    */
> > +   int (*hw_setup) (struct device *dev, void *config);
> > +   /* Get configuration state of resizer in continuous mode */
> > +   unsigned int (*get_resizer_config_state) (void);
> > +   /* Get configuration state of previewer in continuous mode */
> > +   unsigned int (*get_previewer_config_state) (void);
> > +
> > +   /* Below APIs assume we are using shared configuration since
> > +    * oper mode is continuous
> > +    */
> > +   /* Set the input crop window at the IMP interface and IMP */
> > +   int (*set_input_win) (struct imp_window *win);
> > +   /* Get current input crop window param at the IMP */
> > +   int (*get_input_win) (struct imp_window *win);
> > +   /* Set interface parameter at IPIPEIF. Only valid for DM360 */
> > +   int (*set_hw_if_param) (struct vpfe_hw_if_param *param);
> > +   /* Set input pixel format */
> > +   int (*set_in_pixel_format) (enum imp_pix_formats pix_fmt);
> > +   /* set output pixel format */
> > +   int (*set_out_pixel_format) (enum imp_pix_formats pix_fmt);
> > +   /* 0 - interleaved, 1 - field seperated */
> > +   int (*set_buftype) (unsigned char buf_type);
> > +   /* 0 - interlaced, 1 - progressive */
> > +   int (*set_frame_format) (unsigned char frm_fmt);
> > +   /* Set the output window at the IMP, output selection
> > +    * done by out_sel. 0 - output 1 and 1 - output 2
> > +    */
> > +   int (*set_output_win) (struct imp_window *win);
> > +   /* Get output enable/disable status */
> > +   int (*get_output_state) (unsigned char out_sel);
> > +   /* Get output line lenght */
> > +   int (*get_line_length) (unsigned char out_sel);
> > +   /* Get the output image height */
> > +   int (*get_image_height) (unsigned char out_sel);
> > +   /* Get current output window param at the IMP */
> > +   int (*get_output_win) (struct imp_window *win);
> > +   /* get maximum output width of rsz-a or rsz_b*/
> > +   int (*get_max_output_width) (int rsz);
> > +   /* get maximum output height of rsa-a or rsz-b */
> > +   int (*get_max_output_height) (int rsz);
> > +   /* Enumerate pixel format for a given input format */
> > +   int (*enum_pix) (u32 *output_pix, int index);
> > +};
>
> Are there real benefits from using the above struct? I'm not sure if
> this makes anything clearer. Is it being used elsewhere than in a single
> instance (dm365_ipipe_interface)?
This is a generic interface for interfacing DM355, DM6446 and DM3365.All of them use this interface for configuration. The current patch set has only 365.
>
> > +struct imp_hw_interface *imp_get_hw_if(void);
> > +
> > +#endif
> > +#endif
>
> Regards,
>
> --
> Sakari Ailus
> sakari.ailus@iki.fi
>

Thx,
-Manju

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

end of thread, other threads:[~2011-10-17 14:16 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-29 15:07 [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Manjunath Hadli
2011-08-29 15:07 ` [PATCH v2 1/8] davinci: vpfe: add dm3xx IPIPEIF hardware support module Manjunath Hadli
2011-09-01 20:47   ` Sylwester Nawrocki
2011-09-09 13:20     ` Hadli, Manjunath
2011-08-29 15:07 ` [PATCH v2 2/8] davinci: vpfe: add IPIPE hardware layer support Manjunath Hadli
2011-08-29 15:07 ` [PATCH v2 3/8] davinci: vpfe: add IPIPE support for media controller driver Manjunath Hadli
2011-09-27 14:01   ` Sakari Ailus
2011-10-17 14:16     ` Hadli, Manjunath
2011-08-29 15:07 ` [PATCH v2 4/8] davinci: vpfe: add support for CCDC hardware for dm365 Manjunath Hadli
2011-09-01 21:23   ` Sylwester Nawrocki
2011-09-09 13:30     ` Hadli, Manjunath
2011-09-09 16:39       ` Sylwester Nawrocki
2011-08-29 15:07 ` [PATCH v2 5/8] davinci: vpfe: add ccdc driver with media controller interface Manjunath Hadli
2011-08-29 15:07 ` [PATCH v2 6/8] davinci: vpfe: add v4l2 video driver support Manjunath Hadli
2011-08-29 15:07 ` [PATCH v2 7/8] davinci: vpfe: v4l2 capture driver with media interface Manjunath Hadli
2011-08-29 15:07 ` [PATCH v2 8/8] davinci: vpfe: build infrastructure for dm365 Manjunath Hadli
2011-08-29 15:20 ` [PATCH v2 0/8] RFC for Media Controller capture driver for DM365 Hadli, Manjunath
2011-08-31 21:30 ` Sakari Ailus
2011-09-09 13:40   ` Hadli, Manjunath
2011-09-09 16:19     ` Sakari Ailus
2011-09-10  6:41       ` Hadli, Manjunath
2011-09-12 11:59         ` Sakari Ailus
2011-09-12 14:18           ` Hadli, Manjunath
2011-09-14 19:02           ` Hadli, Manjunath
2011-09-16 21:05             ` Sakari Ailus
2011-09-18 14:35 ` Mauro Carvalho Chehab
2011-09-19  5:09   ` Hadli, Manjunath

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