msm: camera: Add support to V4L2 architecture

New targets are following V4L2 architecture for
camera. Update 7x27a camera drivers to support
new V4L2 architecture to unify all camera drivers
in the same architecture.

Signed-off-by: Suresh Vankadara <svankada@codeaurora.org>
Change-Id: Ie23ac982375041c06b68537d5784d8cdbbc9bf04
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 8961c79..1abfd7b 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -87,6 +87,8 @@
 	VFE_MSG_V32_START_RECORDING,
 	VFE_MSG_V32_CAPTURE,
 	VFE_MSG_OUTPUT_IRQ,
+	VFE_MSG_V2X_PREVIEW,
+	VFE_MSG_V2X_CAPTURE,
 };
 
 enum vpe_resp_msg {
diff --git a/arch/arm/mach-msm/qdsp5/adsp_info.c b/arch/arm/mach-msm/qdsp5/adsp_info.c
index 62e385d..dea52bb 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_info.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_info.c
@@ -1,6 +1,6 @@
 /* arch/arm/mach-msm/adsp_info.c
  *
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -89,7 +89,7 @@
 	QDSP_MODULE(RMTASK, NULL, 0, NULL, NULL),
 #if !defined(CONFIG_ARCH_MSM7X30)
 	QDSP_MODULE(AUDRECTASK, NULL, 0, NULL, NULL),
-	QDSP_MODULE(VFETASK, "vfe_clk", 0, adsp_vfe_verify_cmd,
+	QDSP_MODULE(VFETASK, NULL, 0, adsp_vfe_verify_cmd,
 		adsp_vfe_patch_event),
 	QDSP_MODULE(QCAMTASK, NULL, 0, NULL, NULL),
 	QDSP_MODULE(LPMTASK, NULL, 0, adsp_lpm_verify_cmd, NULL),
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index aa0e392..b1dc87e 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -62,7 +62,7 @@
 	  Omni Vision VGA YUV Sensor.
 config WEBCAM_OV9726
 	bool "Sensor OV9726 (VGA Bayer)"
-	depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM7X27A) && !MSM_CAMERA_V4L2
+	depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM7X27A)
 	default n
 	---help---
 	  Omni Vision VGA Bayer Sensor.
@@ -113,7 +113,7 @@
 
 config MT9E013
 	bool "Sensor mt9e013 module (BAYER 8M)"
-	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A) && !MSM_CAMERA_V4L2
+	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A)
 	default n
 	---help---
 	  Aptina 8M Bayer Sensor modules with Autofocus
@@ -149,6 +149,13 @@
 	  two mipi lanes, required for msm7x2xA platform.
 	  Say Y here if this is msm7x2xA variant platform.
 
+config DW9712_ACT
+	bool "Lens actuator dw9721"
+	depends on MSM_CAMERA && S5K4E1
+	---help---
+	  dw9721 lens actuator driver for S5K4E1.
+	  Say Y here if this is msm7627A variant platform.
+
 config MSM_CAMERA_FLASH_SC628A
 	bool "Qualcomm MSM camera sc628a flash support"
 	depends on MSM_CAMERA
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 5454763..b91449a 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -15,7 +15,11 @@
 obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/
 obj-$(CONFIG_MSM_CAMERA_FLASH) += flash.o
 obj-$(CONFIG_ARCH_MSM_ARM11) += msm_vfe7x.o msm_io7x.o
-obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
+ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+  obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a_v4l2.o msm_io_7x27a_v4l2.o
+else
+  obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
+endif
 obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
 obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o
 obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
@@ -26,20 +30,20 @@
 obj-$(CONFIG_MSM_CAMERA_AF_FOXCONN) += mt9p012_fox.o
 obj-$(CONFIG_MSM_CAMERA_AF_BAM) += mt9p012_bam.o
 obj-$(CONFIG_MT9P012_KM) += mt9p012_km.o mt9p012_km_reg.o
-obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
 obj-$(CONFIG_S5K3E2FX) += s5k3e2fx.o
-obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
 #FIXME: Merge the two ifeq causes VX6953 preview not coming up.
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_VX6953) += vx6953_v4l2.o vx6953_reg_v4l2.o
 else
   obj-$(CONFIG_VX6953) += vx6953.o vx6953_reg.o
   obj-$(CONFIG_IMX074) += imx074.o imx074_reg.o
+  obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
+  obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+  obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
 endif
 obj-$(CONFIG_QS_S5K4E1) += qs_s5k4e1.o qs_s5k4e1_reg.o
 obj-$(CONFIG_VB6801) += vb6801.o
 obj-$(CONFIG_IMX072) += imx072.o imx072_reg.o
-obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
 obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
 obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
 obj-$(CONFIG_OV5640) += ov5640.o
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
index 4f4d5ee..f0a0c69 100644
--- a/drivers/media/video/msm/actuators/Makefile
+++ b/drivers/media/video/msm/actuators/Makefile
@@ -3,3 +3,4 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
 obj-$(CONFIG_IMX074_ACT) += imx074_act.o
+obj-$(CONFIG_DW9712_ACT) += dw9712_act.o
diff --git a/drivers/media/video/msm/actuators/dw9712_act.c b/drivers/media/video/msm/actuators/dw9712_act.c
new file mode 100644
index 0000000..562290f
--- /dev/null
+++ b/drivers/media/video/msm/actuators/dw9712_act.c
@@ -0,0 +1,277 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_actuator.h"
+#include "msm_camera_i2c.h"
+
+#define	DW9712_TOTAL_STEPS_NEAR_TO_FAR			32
+DEFINE_MUTEX(dw9712_act_mutex);
+static struct msm_actuator_ctrl_t dw9712_act_t;
+
+static struct region_params_t g_regions[] = {
+	/* step_bound[0] - macro side boundary
+	 * step_bound[1] - infinity side boundary
+	 */
+	/* Region 1 */
+	{
+		.step_bound = {DW9712_TOTAL_STEPS_NEAR_TO_FAR, 0},
+		.code_per_step = 2,
+	},
+};
+
+static uint16_t g_scenario[] = {
+	/* MOVE_NEAR and MOVE_FAR dir*/
+	DW9712_TOTAL_STEPS_NEAR_TO_FAR,
+};
+
+static int32_t dw9712_af_i2c_txdata(unsigned short saddr,
+				unsigned char *txdata, int length,
+				struct msm_actuator_ctrl_t *a_ctrl)
+{
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		},
+	};
+	if (i2c_transfer(a_ctrl->i2c_client.client->adapter, msg, 1) < 0) {
+		pr_err("s5k4e1_af_i2c_txdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int32_t dw9712_af_i2c_write_b_sensor(struct msm_actuator_ctrl_t *a_ctrl,
+			      uint8_t waddr, uint8_t bdata)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[2];
+
+	memset(buf, 0, sizeof(buf));
+	buf[0] = waddr;
+	buf[1] = bdata;
+	rc = dw9712_af_i2c_txdata(a_ctrl->i2c_addr, buf, 2, a_ctrl);
+	if (rc < 0) {
+		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+				waddr, bdata);
+	}
+	return rc;
+}
+
+static int32_t dw9712_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+	int16_t next_lens_position, void *params)
+{
+	uint8_t msb, lsb;
+
+	msb = (next_lens_position & 0xFF00) >> 8;
+	lsb = next_lens_position & 0xFF;
+	dw9712_af_i2c_write_b_sensor(a_ctrl, msb, lsb);
+
+	return 0;
+}
+
+int32_t msm_dw9712_act_move_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	int dir,
+	int32_t num_steps)
+{
+	int32_t rc = 0;
+	int8_t sign_dir = 0;
+	int16_t dest_step_pos = 0;
+	uint8_t code_val_msb, code_val_lsb;
+	uint16_t code_val;
+
+	LINFO("%s called, dir %d, num_steps %d\n",
+		__func__,
+		dir,
+		num_steps);
+
+	/* Determine sign direction */
+	if (dir == MOVE_NEAR)
+		sign_dir = 1;
+	else if (dir == MOVE_FAR)
+		sign_dir = -1;
+	else {
+		pr_err("Illegal focus direction\n");
+		rc = -EINVAL;
+		return rc;
+	}
+
+	/* Determine destination step position */
+	dest_step_pos = a_ctrl->curr_step_pos +
+		(sign_dir * num_steps);
+
+	if (dest_step_pos < 0)
+		dest_step_pos = 0;
+	else if (dest_step_pos > 1023)
+		dest_step_pos = 1023;
+
+	if (dest_step_pos == a_ctrl->curr_step_pos)
+		return rc;
+
+	code_val_msb = dest_step_pos >> 4;
+	code_val_lsb = (dest_step_pos & 0x000F) << 4;
+	code_val = (code_val_msb << 8) | (code_val_lsb);
+	rc = dw9712_wrapper_i2c_write(a_ctrl, code_val, NULL);
+	if (rc >= 0) {
+		rc = 0;
+		a_ctrl->curr_step_pos = dest_step_pos;
+	}
+	return 0;
+}
+
+static int32_t dw9712_set_default_focus(
+	struct msm_actuator_ctrl_t *a_ctrl)
+{
+	int32_t rc = 0;
+
+	if (!a_ctrl->step_position_table)
+		a_ctrl->func_tbl.actuator_init_table(a_ctrl);
+
+	if (a_ctrl->curr_step_pos != 0) {
+		rc = a_ctrl->func_tbl.actuator_move_focus(a_ctrl,
+				MOVE_FAR, a_ctrl->curr_step_pos);
+		a_ctrl->curr_step_pos = 0;
+	} else
+		rc = dw9712_wrapper_i2c_write(a_ctrl, 0x00, NULL);
+		if (rc >= 0)
+			rc = 0;
+	return rc;
+}
+
+static const struct i2c_device_id dw9712_act_i2c_id[] = {
+	{"dw9712_act", (kernel_ulong_t)&dw9712_act_t},
+	{ }
+};
+
+static int dw9712_act_config(void __user *argp)
+{
+	LINFO("%s called\n", __func__);
+	return (int) msm_actuator_config(&dw9712_act_t, argp);
+}
+
+static int dw9712_i2c_add_driver_table(void)
+{
+	LINFO("%s called\n", __func__);
+	return (int) msm_actuator_init_table(&dw9712_act_t);
+}
+
+static struct i2c_driver dw9712_act_i2c_driver = {
+	.id_table = dw9712_act_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(dw9712_act_i2c_remove),
+	.driver = {
+		.name = "dw9712_act",
+	},
+};
+
+static int __init dw9712_i2c_add_driver(void)
+{
+	int rc = 0;
+
+	LINFO("%s called :%x\n", __func__, dw9712_act_t.i2c_addr);
+	rc = i2c_add_driver(dw9712_act_t.i2c_driver);
+	LINFO("%s called:%d %x\n", __func__, rc, dw9712_act_t.i2c_addr);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops dw9712_act_subdev_core_ops;
+
+static struct v4l2_subdev_ops dw9712_act_subdev_ops = {
+	.core = &dw9712_act_subdev_core_ops,
+};
+
+static int32_t dw9712_act_create_subdevice(
+	void *board_info,
+	void *sdev)
+{
+	int rc = 0;
+
+	struct msm_actuator_info *ptr;
+	LINFO("%s called\n", __func__);
+
+	ptr = board_info;
+	dw9712_act_t.vcm_pwd = ptr->vcm_pwd;
+	dw9712_act_t.vcm_enable = ptr->vcm_enable;
+	LINFO("vcm info: %x %x\n", dw9712_act_t.vcm_pwd,
+				dw9712_act_t.vcm_enable);
+	if (dw9712_act_t.vcm_enable) {
+		rc = gpio_request(dw9712_act_t.vcm_pwd, "dw9712_af");
+		if (!rc) {
+			LINFO("Enable VCM PWD\n");
+			gpio_direction_output(dw9712_act_t.vcm_pwd, 1);
+		}
+	}
+	return (int) msm_actuator_create_subdevice(&dw9712_act_t,
+		ptr->board_info,
+		(struct v4l2_subdev *)sdev);
+}
+
+static struct msm_actuator_ctrl_t dw9712_act_t = {
+	.i2c_driver = &dw9712_act_i2c_driver,
+	.i2c_addr = 0x8C,
+	.act_v4l2_subdev_ops = &dw9712_act_subdev_ops,
+	.actuator_ext_ctrl = {
+		.a_init_table = dw9712_i2c_add_driver_table,
+		.a_create_subdevice = dw9712_act_create_subdevice,
+		.a_config = dw9712_act_config,
+	},
+
+	.i2c_client = {
+		.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+	},
+
+	.set_info = {
+		.total_steps = DW9712_TOTAL_STEPS_NEAR_TO_FAR,
+	},
+
+	.curr_step_pos = 0,
+	.curr_region_index = 0,
+	.initial_code = 0x0,
+	.actuator_mutex = &dw9712_act_mutex,
+
+	.func_tbl = {
+		.actuator_init_table = msm_actuator_init_table,
+		.actuator_move_focus = msm_dw9712_act_move_focus,
+		.actuator_set_default_focus = dw9712_set_default_focus,
+		.actuator_i2c_write = dw9712_wrapper_i2c_write,
+	},
+
+	.get_info = {
+		.focal_length_num = 46,
+		.focal_length_den = 10,
+		.f_number_num = 265,
+		.f_number_den = 100,
+		.f_pix_num = 14,
+		.f_pix_den = 10,
+		.total_f_dist_num = 197681,
+		.total_f_dist_den = 1000,
+	},
+
+	/* Initialize scenario */
+	.ringing_scenario[MOVE_NEAR] = g_scenario,
+	.scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
+	.ringing_scenario[MOVE_FAR] = g_scenario,
+	.scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
+
+	/* Initialize region params */
+	.region_params = g_regions,
+	.region_size = ARRAY_SIZE(g_regions),
+};
+
+subsys_initcall(dw9712_i2c_add_driver);
+MODULE_DESCRIPTION("DW9712 actuator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index e01d2c7..e4d340d4 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -186,13 +186,14 @@
 };
 
 static int32_t imx074_act_create_subdevice(
-	void *board_info,
+	void *act_info,
 	void *sdev)
 {
+	struct msm_actuator_info *info = (struct msm_actuator_info *)act_info;
 	LINFO("%s called\n", __func__);
 
 	return (int) msm_actuator_create_subdevice(&imx074_act_t,
-		(struct i2c_board_info const *)board_info,
+		(struct i2c_board_info const *)info->board_info,
 		(struct v4l2_subdev *)sdev);
 }
 
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 6fad8dd..9c90282 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,7 @@
 
 #include <linux/i2c.h>
 #include <mach/camera.h>
+#include <mach/gpio.h>
 #include <media/v4l2-subdev.h>
 #include <media/msm_camera.h>
 #include "msm_camera_i2c.h"
@@ -100,6 +101,8 @@
 	uint16_t region_size;
 	struct damping_t *damping[2];
 	void *user_data;
+	uint32_t vcm_pwd;
+	uint32_t vcm_enable;
 };
 
 int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 3ce81af..6e8eb122 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,3 +1,4 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 EXTRA_CFLAGS += -Idrivers/media/video/msm
 obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o msm_ispif.o
+obj-$(CONFIG_ARCH_MSM7X27A) += msm_csic.o
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
new file mode 100644
index 0000000..476615d
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -0,0 +1,430 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <media/msm_isp.h>
+#include "msm_csic.h"
+#include "msm.h"
+
+#define DBG_CSIC 0
+
+#define V4L2_IDENT_CSIC			50004
+/* MIPI	CSI controller registers */
+#define	MIPI_PHY_CONTROL		0x00000000
+#define	MIPI_PROTOCOL_CONTROL		0x00000004
+#define	MIPI_INTERRUPT_STATUS		0x00000008
+#define	MIPI_INTERRUPT_MASK		0x0000000C
+#define	MIPI_CAMERA_CNTL		0x00000024
+#define	MIPI_CALIBRATION_CONTROL	0x00000018
+#define	MIPI_PHY_D0_CONTROL2		0x00000038
+#define	MIPI_PHY_D1_CONTROL2		0x0000003C
+#define	MIPI_PHY_D2_CONTROL2		0x00000040
+#define	MIPI_PHY_D3_CONTROL2		0x00000044
+#define	MIPI_PHY_CL_CONTROL		0x00000048
+#define	MIPI_PHY_D0_CONTROL		0x00000034
+#define	MIPI_PHY_D1_CONTROL		0x00000020
+#define	MIPI_PHY_D2_CONTROL		0x0000002C
+#define	MIPI_PHY_D3_CONTROL		0x00000030
+#define	MIPI_PWR_CNTL			0x00000054
+
+/*
+ * MIPI_PROTOCOL_CONTROL register bits to enable/disable the features of
+ * CSI Rx Block
+ */
+
+/* DPCM scheme */
+#define	MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT			0x1e
+/* SW_RST to issue a SW reset to the CSI core */
+#define	MIPI_PROTOCOL_CONTROL_SW_RST_BMSK			0x8000000
+/* To Capture Long packet Header Info in MIPI_PROTOCOL_STATUS register */
+#define	MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK	0x200000
+/* Data format for unpacking purpose */
+#define	MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT			0x13
+/* Enable decoding of payload based on data type filed of packet hdr */
+#define	MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK			0x00000
+/* Enable error correction on packet headers */
+#define	MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK			0x20000
+
+/*
+ * MIPI_CALIBRATION_CONTROL register contains control info for
+ * calibration impledence controller
+*/
+
+/* Enable bit for calibration pad */
+#define	MIPI_CALIBRATION_CONTROL_SWCAL_CAL_EN_SHFT		0x16
+/* With SWCAL_STRENGTH_OVERRIDE_EN, SW_CAL_EN and MANUAL_OVERRIDE_EN
+ * the hardware calibration circuitry associated with CAL_SW_HW_MODE
+ * is bypassed
+*/
+#define	MIPI_CALIBRATION_CONTROL_SWCAL_STRENGTH_OVERRIDE_EN_SHFT	0x15
+/* To indicate the Calibration process is in the control of HW/SW */
+#define	MIPI_CALIBRATION_CONTROL_CAL_SW_HW_MODE_SHFT		0x14
+/* When this is set the strength value of the data and clk lane impedence
+ * termination is updated with MANUAL_STRENGTH settings and calibration
+ * sensing logic is idle.
+*/
+#define	MIPI_CALIBRATION_CONTROL_MANUAL_OVERRIDE_EN_SHFT	0x7
+
+/* Data lane0 control */
+/* T-hs Settle count value  for Rx */
+#define	MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT			0x18
+/* Rx termination control */
+#define	MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT			0x10
+/* LP Rx enable */
+#define	MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT			0x4
+/*
+ * Enable for error in sync sequence
+ * 1 - one bit error in sync seq
+ * 0 - requires all 8 bit correct seq
+*/
+#define	MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* Comments are same as D0 */
+#define	MIPI_PHY_D1_CONTROL2_SETTLE_COUNT_SHFT			0x18
+#define	MIPI_PHY_D1_CONTROL2_HS_TERM_IMP_SHFT			0x10
+#define	MIPI_PHY_D1_CONTROL2_LP_REC_EN_SHFT			0x4
+#define	MIPI_PHY_D1_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* Comments are same as D0 */
+#define	MIPI_PHY_D2_CONTROL2_SETTLE_COUNT_SHFT			0x18
+#define	MIPI_PHY_D2_CONTROL2_HS_TERM_IMP_SHFT			0x10
+#define	MIPI_PHY_D2_CONTROL2_LP_REC_EN_SHFT			0x4
+#define	MIPI_PHY_D2_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* Comments are same as D0 */
+#define	MIPI_PHY_D3_CONTROL2_SETTLE_COUNT_SHFT			0x18
+#define	MIPI_PHY_D3_CONTROL2_HS_TERM_IMP_SHFT			0x10
+#define	MIPI_PHY_D3_CONTROL2_LP_REC_EN_SHFT			0x4
+#define	MIPI_PHY_D3_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* PHY_CL_CTRL programs the parameters of clk lane of CSIRXPHY */
+/* HS Rx termination control */
+#define	MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT			0x18
+/* Start signal for T-hs delay */
+#define	MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT			0x2
+
+/* PHY DATA lane 0 control */
+/*
+ * HS RX equalizer strength control
+ * 00 - 0db 01 - 3db 10 - 5db 11 - 7db
+*/
+#define	MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT			0x1c
+/* PHY DATA lane 1 control */
+/* Shutdown signal for MIPI clk phy line */
+#define	MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT		0x9
+/* Shutdown signal for MIPI data phy line */
+#define	MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT	0x8
+
+#define MSM_AXI_QOS_PREVIEW 200000
+#define MSM_AXI_QOS_SNAPSHOT 200000
+#define MSM_AXI_QOS_RECORDING 200000
+
+#define MIPI_PWR_CNTL_ENA	0x07
+#define MIPI_PWR_CNTL_DIS	0x0
+
+static int msm_csic_config(struct csic_cfg_params *cfg_params)
+{
+	int rc = 0;
+	uint32_t val = 0;
+	struct csic_device *csic_dev;
+	struct msm_camera_csi_params *csic_params;
+	void __iomem *csicbase;
+
+	csic_dev = v4l2_get_subdevdata(cfg_params->subdev);
+	csicbase = csic_dev->base;
+	csic_params = cfg_params->parms;
+
+	/* Enable error correction for DATA lane. Applies to all data lanes */
+	msm_io_w(0x4, csicbase + MIPI_PHY_CONTROL);
+
+	msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
+		csicbase + MIPI_PROTOCOL_CONTROL);
+
+	val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
+		MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
+		MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
+	val |= (uint32_t)(csic_params->data_format) <<
+		MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
+	val |= csic_params->dpcm_scheme <<
+		MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
+	CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PROTOCOL_CONTROL);
+
+	val = (0x1 << MIPI_CALIBRATION_CONTROL_SWCAL_CAL_EN_SHFT) |
+		(0x1 <<
+		MIPI_CALIBRATION_CONTROL_SWCAL_STRENGTH_OVERRIDE_EN_SHFT) |
+		(0x1 << MIPI_CALIBRATION_CONTROL_CAL_SW_HW_MODE_SHFT) |
+		(0x1 << MIPI_CALIBRATION_CONTROL_MANUAL_OVERRIDE_EN_SHFT);
+	CDBG("%s MIPI_CALIBRATION_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_CALIBRATION_CONTROL);
+
+	val = (csic_params->settle_cnt <<
+		MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
+		(0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
+		(0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
+		(0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
+	CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PHY_D0_CONTROL2);
+	msm_io_w(val, csicbase + MIPI_PHY_D1_CONTROL2);
+	msm_io_w(val, csicbase + MIPI_PHY_D2_CONTROL2);
+	msm_io_w(val, csicbase + MIPI_PHY_D3_CONTROL2);
+
+
+	val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
+		(0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
+	CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PHY_CL_CONTROL);
+
+	val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
+	msm_io_w(val, csicbase + MIPI_PHY_D0_CONTROL);
+
+	val = (0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
+		(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
+	CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PHY_D1_CONTROL);
+
+	msm_io_w(0x00000000, csicbase + MIPI_PHY_D2_CONTROL);
+	msm_io_w(0x00000000, csicbase + MIPI_PHY_D3_CONTROL);
+
+	/* program number of lanes and lane mapping */
+	switch (csic_params->lane_cnt) {
+	case 1:
+		msm_io_w(csic_params->lane_assign << 8 | 0x4,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	case 2:
+		msm_io_w(csic_params->lane_assign << 8 | 0x5,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	case 3:
+		msm_io_w(csic_params->lane_assign << 8 | 0x6,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	case 4:
+		msm_io_w(csic_params->lane_assign << 8 | 0x7,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	}
+
+	msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_MASK);
+	/*clear IRQ bits - write 1 clears the status*/
+	msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_STATUS);
+
+	return rc;
+}
+
+static irqreturn_t msm_csic_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	struct csic_device *csic_dev = data;
+
+	pr_info("msm_csic_irq: %x\n", (unsigned int)csic_dev->base);
+	irq = msm_io_r(csic_dev->base + MIPI_INTERRUPT_STATUS);
+	pr_info("%s MIPI_INTERRUPT_STATUS = 0x%x\n", __func__, irq);
+	msm_io_w(irq, csic_dev->base + MIPI_INTERRUPT_STATUS);
+
+	/* TODO: Needs to send this info to upper layers */
+	if ((irq >> 19) & 0x1)
+		pr_info("Unsupported packet format is received\n");
+	return IRQ_HANDLED;
+}
+
+static int msm_csic_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CSIC;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info csic_clk_info[] = {
+	{"csi_clk", 400000000},
+	{"csi_vfe_clk", -1},
+	{"csi_pclk", -1},
+};
+
+static int msm_csic_init(struct v4l2_subdev *sd, uint32_t *csic_version)
+{
+	int rc = 0;
+	struct csic_device *csic_dev;
+	csic_dev = v4l2_get_subdevdata(sd);
+	if (csic_dev == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	csic_dev->base = ioremap(csic_dev->mem->start,
+		resource_size(csic_dev->mem));
+	if (!csic_dev->base) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	pr_info("msm_cam_clk_enable: enable csi_pclk, csi_clk, csi_vfe_clk\n");
+	rc = msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
+		csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 1);
+	if (rc < 0) {
+		iounmap(csic_dev->base);
+		return rc;
+	}
+
+#if DBG_CSIC
+	enable_irq(csic_dev->irq->start);
+#endif
+
+	return 0;
+}
+
+static int msm_csic_release(struct v4l2_subdev *sd)
+{
+	struct csic_device *csic_dev;
+	csic_dev = v4l2_get_subdevdata(sd);
+
+#if DBG_CSIC
+	disable_irq(csic_dev->irq->start);
+#endif
+
+	pr_info("msm_cam_clk_enable: disble csi_pclk, csi_clk, csi_vfe_clk\n");
+	msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
+		csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 0);
+
+	iounmap(csic_dev->base);
+	return 0;
+}
+
+static long msm_csic_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct csic_cfg_params cfg_params;
+	switch (cmd) {
+	case VIDIOC_MSM_CSIC_CFG:
+		cfg_params.subdev = sd;
+		cfg_params.parms = arg;
+		return msm_csic_config((struct csic_cfg_params *)&cfg_params);
+	case VIDIOC_MSM_CSIC_INIT:
+		return msm_csic_init(sd, (uint32_t *)arg);
+	case VIDIOC_MSM_CSIC_RELEASE:
+		return msm_csic_release(sd);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct v4l2_subdev_core_ops msm_csic_subdev_core_ops = {
+	.g_chip_ident = &msm_csic_subdev_g_chip_ident,
+	.ioctl = &msm_csic_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csic_subdev_ops = {
+	.core = &msm_csic_subdev_core_ops,
+};
+
+static int __devinit csic_probe(struct platform_device *pdev)
+{
+	struct csic_device *new_csic_dev;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	new_csic_dev = kzalloc(sizeof(struct csic_device), GFP_KERNEL);
+	if (!new_csic_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&new_csic_dev->subdev, &msm_csic_subdev_ops);
+	v4l2_set_subdevdata(&new_csic_dev->subdev, new_csic_dev);
+	platform_set_drvdata(pdev, &new_csic_dev->subdev);
+	mutex_init(&new_csic_dev->mutex);
+
+	new_csic_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "csic");
+	if (!new_csic_dev->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto csic_no_resource;
+	}
+	new_csic_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "csic");
+	if (!new_csic_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto csic_no_resource;
+	}
+	new_csic_dev->io = request_mem_region(new_csic_dev->mem->start,
+		resource_size(new_csic_dev->mem), pdev->name);
+	if (!new_csic_dev->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto csic_no_resource;
+	}
+
+	rc = request_irq(new_csic_dev->irq->start, msm_csic_irq,
+		IRQF_TRIGGER_RISING, "csic", new_csic_dev);
+	if (rc < 0) {
+		release_mem_region(new_csic_dev->mem->start,
+			resource_size(new_csic_dev->mem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto csic_no_resource;
+	}
+	disable_irq(new_csic_dev->irq->start);
+	pr_info("msm_cam_clk_enable: enable csi_pclk\n");
+	msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
+				new_csic_dev->csic_clk, 1, 1);
+	new_csic_dev->base = ioremap(new_csic_dev->mem->start,
+		resource_size(new_csic_dev->mem));
+	if (!new_csic_dev->base) {
+		rc = -ENOMEM;
+		goto csic_no_resource;
+	}
+
+	msm_io_w(MIPI_PWR_CNTL_DIS, new_csic_dev->base + MIPI_PWR_CNTL_DIS);
+	pr_info("msm_cam_clk_enable: disable csi_pclk\n");
+	msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
+					new_csic_dev->csic_clk, 1, 0);
+	iounmap(new_csic_dev->base);
+
+	new_csic_dev->pdev = pdev;
+	return 0;
+
+csic_no_resource:
+	mutex_destroy(&new_csic_dev->mutex);
+	kfree(new_csic_dev);
+	return 0;
+}
+
+static struct platform_driver csic_driver = {
+	.probe = csic_probe,
+	.driver = {
+		.name = MSM_CSIC_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_csic_init_module(void)
+{
+	return platform_driver_register(&csic_driver);
+}
+
+static void __exit msm_csic_exit_module(void)
+{
+	platform_driver_unregister(&csic_driver);
+}
+
+module_init(msm_csic_init_module);
+module_exit(msm_csic_exit_module);
+MODULE_DESCRIPTION("MSM csic driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/video/msm/csi/msm_csic.h
new file mode 100644
index 0000000..08dde52
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSIC_H
+#define MSM_CSIC_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csic_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+	struct mutex mutex;
+	uint32_t hw_version;
+
+	struct clk *csic_clk[5];
+};
+
+struct csic_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_CSIC_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_params)
+
+#define VIDIOC_MSM_CSIC_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSIC_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+
+#endif
+
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 363e437..a9aa28b 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1478,15 +1478,14 @@
 				__func__, rc);
 			return rc;
 		}
-		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-					pcam->mctl.isp_sdev->sd_vpe);
-		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
-			pr_err("%s: vpe v4l2_device_register_subdev failed rc = %d\n",
-				__func__, rc);
-			return rc;
+		if (pcam->mctl.isp_sdev->sd_vpe) {
+			rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
+						pcam->mctl.isp_sdev->sd_vpe);
+			if (rc < 0) {
+				mutex_unlock(&pcam->vid_lock);
+				return rc;
+			}
 		}
-
 		rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
 							pcam->pvdev);
 		if (rc < 0) {
@@ -2395,7 +2394,7 @@
 		goto client_fail;
 
 	*actctrl = *a_ext_ctrl;
-	a_ext_ctrl->a_create_subdevice((void *)actuator_info->board_info,
+	a_ext_ctrl->a_create_subdevice((void *)actuator_info,
 				       (void *)act_sdev);
 	return rc;
 
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 5fc3e6a..cc2e8b4 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -43,6 +43,7 @@
 
 #define MSM_CSIPHY_DRV_NAME "msm_csiphy"
 #define MSM_CSID_DRV_NAME "msm_csid"
+#define MSM_CSIC_DRV_NAME "msm_csic"
 #define MSM_ISPIF_DRV_NAME "msm_ispif"
 #define MSM_VFE_DRV_NAME "msm_vfe"
 #define MSM_VPE_DRV_NAME "msm_vpe"
@@ -121,6 +122,8 @@
 	NOTIFY_PCLK_CHANGE, /* arg = pclk */
 	NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
 	NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
+	NOTIFY_CSIC_CFG, /* arg = msm_camera_csic_params */
+	NOTIFY_VFE_BUF_FREE_EVT, /* arg = msm_camera_csic_params */
 	NOTIFY_INVALID
 };
 
@@ -225,6 +228,7 @@
 	struct msm_cam_config_dev *config_device;
 	struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
 	struct v4l2_subdev *csid_sdev; /*csid sub device*/
+	struct v4l2_subdev *csic_sdev; /*csid sub device*/
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *act_sdev; /* actuator sub device */
 
diff --git a/drivers/media/video/msm/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
new file mode 100644
index 0000000..bee9f49
--- /dev/null
+++ b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
@@ -0,0 +1,258 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pm_qos_params.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/camera.h>
+#include <mach/clk.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+
+
+#define MSM_AXI_QOS_PREVIEW 200000
+#define MSM_AXI_QOS_SNAPSHOT 200000
+#define MSM_AXI_QOS_RECORDING 200000
+
+static struct clk *camio_cam_clk;
+static struct resource *clk_ctrl_mem;
+static struct msm_camera_io_clk camio_clk;
+void __iomem *appbase;
+
+void msm_io_w(u32 data, void __iomem *addr)
+{
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	writel_relaxed((data), (addr));
+}
+
+u32 msm_io_r(void __iomem *addr)
+{
+	uint32_t data = readl_relaxed(addr);
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	return data;
+}
+
+void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
+{
+	clk_set_rate(clk, rate);
+}
+int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
+{
+	int rc = 0;
+	struct clk *clk = NULL;
+
+	switch (clktype) {
+	case CAMIO_CAM_MCLK_CLK:
+		clk = clk_get(NULL, "cam_m_clk");
+		camio_cam_clk = clk;
+		msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
+		break;
+	default:
+		break;
+	}
+
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+	else
+		rc = -1;
+	return rc;
+}
+
+int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
+{
+	int rc = 0;
+	struct clk *clk = NULL;
+
+	switch (clktype) {
+	case CAMIO_CAM_MCLK_CLK:
+		clk = camio_cam_clk;
+		break;
+	default:
+		break;
+	}
+
+	if (!IS_ERR(clk)) {
+		clk_disable(clk);
+		clk_put(clk);
+	} else
+		rc = -1;
+	return rc;
+}
+
+void msm_camio_clk_rate_set(int rate)
+{
+	struct clk *clk = camio_cam_clk;
+	clk_set_rate(clk, rate);
+}
+
+int msm_sensor_probe_on(struct device *dev)
+{
+	int rc = 0;
+	struct msm_camera_sensor_info *sinfo = dev->platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+	camio_clk = camdev->ioclk;
+
+	rc = camdev->camera_gpio_on();
+	if (rc < 0)
+		return rc;
+
+	rc = msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
+	if (rc < 0)
+		camdev->camera_gpio_off();
+
+	return rc;
+}
+
+int msm_sensor_probe_off(struct device *dev)
+{
+	struct msm_camera_sensor_info *sinfo = dev->platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+	camdev->camera_gpio_off();
+	return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+}
+
+void msm_camio_vfe_blk_reset(void)
+{
+	uint32_t val;
+
+	/* do apps reset */
+	val = readl_relaxed(appbase + 0x00000210);
+	val |= 0x1;
+	writel_relaxed(val, appbase + 0x00000210);
+	usleep_range(10000, 11000);
+
+	val = readl_relaxed(appbase + 0x00000210);
+	val &= ~0x1;
+	writel_relaxed(val, appbase + 0x00000210);
+	usleep_range(10000, 11000);
+
+	/* do axi reset */
+	val = readl_relaxed(appbase + 0x00000208);
+	val |= 0x1;
+	writel_relaxed(val, appbase + 0x00000208);
+	usleep_range(10000, 11000);
+
+	val = readl_relaxed(appbase + 0x00000208);
+	val &= ~0x1;
+	writel_relaxed(val, appbase + 0x00000208);
+	mb();
+	usleep_range(10000, 11000);
+}
+
+int msm_camio_probe_on(struct platform_device *pdev)
+{
+	int rc = 0;
+	const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+	camio_clk = camdev->ioclk;
+
+	rc = camdev->camera_gpio_on();
+	if (rc < 0)
+		return rc;
+	return msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
+}
+
+int msm_camio_probe_off(struct platform_device *pdev)
+{
+	const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+	camdev->camera_gpio_off();
+	return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+}
+
+void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
+{
+	switch (perf_setting) {
+	case S_INIT:
+		add_axi_qos();
+		break;
+	case S_PREVIEW:
+		update_axi_qos(MSM_AXI_QOS_PREVIEW);
+		break;
+	case S_VIDEO:
+		update_axi_qos(MSM_AXI_QOS_RECORDING);
+		break;
+	case S_CAPTURE:
+		update_axi_qos(MSM_AXI_QOS_SNAPSHOT);
+		break;
+	case S_DEFAULT:
+		update_axi_qos(PM_QOS_DEFAULT_VALUE);
+		break;
+	case S_EXIT:
+		release_axi_qos();
+		break;
+	default:
+		CDBG("%s: INVALID CASE\n", __func__);
+	}
+}
+
+static int __devinit clkctl_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	clk_ctrl_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "clk_ctl");
+	if (!clk_ctrl_mem) {
+		pr_err("%s: no mem resource:3?\n", __func__);
+		return -ENODEV;
+	}
+
+	appbase = ioremap(clk_ctrl_mem->start,
+		resource_size(clk_ctrl_mem));
+	if (!appbase) {
+		pr_err("clkctl_probe: appbase:err\n");
+		rc = -ENOMEM;
+		goto ioremap_fail;
+	}
+	return 0;
+
+ioremap_fail:
+	msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+	return rc;
+}
+
+static int clkctl_remove(struct platform_device *pdev)
+{
+	if (clk_ctrl_mem)
+		iounmap(clk_ctrl_mem);
+
+	return 0;
+}
+
+static struct platform_driver clkctl_driver = {
+	.probe  = clkctl_probe,
+	.remove = clkctl_remove,
+	.driver = {
+		.name = "msm_clk_ctl",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_clkctl_init_module(void)
+{
+	return platform_driver_register(&clkctl_driver);
+}
+
+static void __exit msm_clkctl_exit_module(void)
+{
+	platform_driver_unregister(&clkctl_driver);
+}
+
+module_init(msm_clkctl_init_module);
+module_exit(msm_clkctl_exit_module);
+MODULE_DESCRIPTION("CAM IO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 0a1516b..6a9d7c4 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,20 @@
 	}
 }
 
+static int msm_isp_notify_VFE_BUF_FREE_EVT(struct v4l2_subdev *sd, void *arg)
+{
+	struct msm_vfe_cfg_cmd cfgcmd;
+	struct msm_camvfe_params vfe_params;
+	int rc;
+
+	cfgcmd.cmd_type = CMD_VFE_BUFFER_RELEASE;
+	cfgcmd.value = NULL;
+	vfe_params.vfe_cfg = &cfgcmd;
+	vfe_params.data = NULL;
+	rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+	return 0;
+}
+
 static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg)
 {
 	int rc = -EINVAL;
@@ -89,6 +103,7 @@
 	switch (vdata->type) {
 	case VFE_MSG_V32_START:
 	case VFE_MSG_V32_START_RECORDING:
+	case VFE_MSG_V2X_PREVIEW:
 		D("%s Got V32_START_*: Getting ping addr id = %d",
 						__func__, vfe_id);
 		msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
@@ -105,6 +120,7 @@
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		break;
 	case VFE_MSG_V32_CAPTURE:
+	case VFE_MSG_V2X_CAPTURE:
 		pr_err("%s Got V32_CAPTURE: getting buffer for id = %d",
 						__func__, vfe_id);
 		msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
@@ -161,6 +177,9 @@
 	if (notification == NOTIFY_VFE_BUF_EVT)
 		return msm_isp_notify_VFE_BUF_EVT(sd, arg);
 
+	if (notification == NOTIFY_VFE_BUF_FREE_EVT)
+		return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg);
+
 	isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC);
 	if (!isp_event) {
 		pr_err("%s Insufficient memory. return", __func__);
@@ -376,6 +395,19 @@
 		axi_data.region = &region[0];
 		return msm_isp_subdev_ioctl(sd, &cfgcmd,
 							&axi_data);
+	case CMD_STATS_AEC_AWB_ENABLE:
+		axi_data.bufnum1 =
+			msm_pmem_region_lookup(&sync->pmem_stats,
+			MSM_PMEM_AEC_AWB, &region[0],
+			NUM_STAT_OUTPUT_BUFFERS);
+		if (!axi_data.bufnum1) {
+			pr_err("%s %d: pmem region lookup error\n",
+				__func__, __LINE__);
+			return -EINVAL;
+		}
+		axi_data.region = &region[0];
+		return msm_isp_subdev_ioctl(sd, &cfgcmd,
+							&axi_data);
 	case CMD_STATS_IHIST_ENABLE:
 		axi_data.bufnum1 =
 			msm_pmem_region_lookup(&sync->pmem_stats,
@@ -614,6 +646,8 @@
 			cfgcmd.cmd_type = CMD_STATS_RS_BUF_RELEASE;
 		else if (buf.type == STAT_CS)
 			cfgcmd.cmd_type = CMD_STATS_CS_BUF_RELEASE;
+		else if (buf.type == STAT_AEAW)
+			cfgcmd.cmd_type = CMD_STATS_BUF_RELEASE;
 
 		else {
 			pr_err("%s: invalid buf type %d\n",
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e13dd62..e76b1d2 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -29,6 +29,7 @@
 
 #include "msm.h"
 #include "msm_csid.h"
+#include "msm_csic.h"
 #include "msm_csiphy.h"
 #include "msm_ispif.h"
 #include "msm_sensor.h"
@@ -92,6 +93,14 @@
 	.colorspace = V4L2_COLORSPACE_JPEG,
 	},
 	{
+	.name	   = "NV21BAYER",
+	.depth	  = 8,
+	.bitsperpxl = 8,
+	.fourcc	 = V4L2_PIX_FMT_NV21,
+	.pxlcode	= V4L2_MBUS_FMT_SGRBG10_1X10, /* Bayer sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
+	{
 	.name	   = "YU12BAYER",
 	.depth	  = 8,
 	.bitsperpxl = 8,
@@ -107,6 +116,14 @@
 	.pxlcode	= V4L2_MBUS_FMT_SBGGR10_1X10, /* Bayer sensor */
 	.colorspace = V4L2_COLORSPACE_JPEG,
 	},
+	{
+	.name	   = "RAWBAYER",
+	.depth	  = 10,
+	.bitsperpxl = 10,
+	.fourcc	 = V4L2_PIX_FMT_SBGGR10,
+	.pxlcode	= V4L2_MBUS_FMT_SGRBG10_1X10, /* Bayer sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
 
 };
 
@@ -225,6 +242,7 @@
 	case NOTIFY_VFE_MSG_OUT:
 	case NOTIFY_VFE_MSG_STATS:
 	case NOTIFY_VFE_BUF_EVT:
+	case NOTIFY_VFE_BUF_FREE_EVT:
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
 			rc = p_mctl->isp_sdev->isp_notify(
 				p_mctl->isp_sdev->sd, notification, arg);
@@ -248,6 +266,10 @@
 		rc = v4l2_subdev_call(p_mctl->csid_sdev,
 			core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
 		break;
+	case NOTIFY_CSIC_CFG:
+		rc = v4l2_subdev_call(p_mctl->csic_sdev,
+			core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+		break;
 	default:
 		break;
 	}
@@ -416,44 +438,70 @@
 	struct device *dev;
 	int rc = -ENODEV;
 
-	/* register csiphy subdev */
-	driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
+	struct msm_camera_sensor_info *sinfo =
+		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
+	struct msm_camera_device_platform_data *pdata = sinfo->pdata;
 
-	dev = driver_find_device(driver, NULL, (void *)core_index,
+	if (pdata->is_csiphy) {
+		/* register csiphy subdev */
+		driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
+
+		dev = driver_find_device(driver, NULL, (void *)core_index,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->csiphy_sdev = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
-	/* register csid subdev */
-	driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	if (pdata->is_csic) {
+		/* register csic subdev */
+		driver = driver_find(MSM_CSIC_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
 
-	dev = driver_find_device(driver, NULL, (void *)core_index,
+		dev = driver_find_device(driver, NULL, (void *)core_index,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->csid_sdev = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->csic_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
-	/* register ispif subdev */
-	driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	if (pdata->is_csid) {
+		/* register csid subdev */
+		driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
 
-	dev = driver_find_device(driver, NULL, 0,
+		dev = driver_find_device(driver, NULL, (void *)core_index,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->ispif_sdev = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->csid_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
+
+	if (pdata->is_ispif) {
+		/* register ispif subdev */
+		driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
+
+		dev = driver_find_device(driver, NULL, 0,
+				msm_mctl_subdev_match_core);
+		if (!dev)
+			goto out_put_driver;
+
+		p_mctl->ispif_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
 	/* register vfe subdev */
 	driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
@@ -468,18 +516,20 @@
 	p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
 	put_driver(driver);
 
-	/* register vfe subdev */
-	driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	if (pdata->is_vpe) {
+		/* register vfe subdev */
+		driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
 
-	dev = driver_find_device(driver, NULL, 0,
+		dev = driver_find_device(driver, NULL, 0,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
 	rc = 0;
 	return rc;
@@ -522,20 +572,33 @@
 			goto msm_open_done;
 		}
 
-		rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
-			VIDIOC_MSM_CSIPHY_INIT, NULL);
-		if (rc < 0) {
-			pr_err("%s: csiphy initialization failed %d\n",
+		if (camdev->is_csiphy) {
+			rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+				VIDIOC_MSM_CSIPHY_INIT, NULL);
+			if (rc < 0) {
+				pr_err("%s: csiphy initialization failed %d\n",
 				__func__, rc);
-			goto msm_open_done;
+				goto msm_open_done;
+			}
 		}
 
-		rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
-			VIDIOC_MSM_CSID_INIT, &csid_version);
-		if (rc < 0) {
-			pr_err("%s: csid initialization failed %d\n",
+		if (camdev->is_csid) {
+			rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+				VIDIOC_MSM_CSID_INIT, &csid_version);
+			if (rc < 0) {
+				pr_err("%s: csid initialization failed %d\n",
 				__func__, rc);
-			goto msm_open_done;
+				goto msm_open_done;
+			}
+		}
+		if (camdev->is_csic) {
+			rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+				VIDIOC_MSM_CSIC_INIT, &csid_version);
+			if (rc < 0) {
+				pr_err("%s: csic initialization failed %d\n",
+				__func__, rc);
+				goto msm_open_done;
+			}
 		}
 
 		/* ISP first*/
@@ -548,12 +611,14 @@
 			goto msm_open_done;
 		}
 
-		rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-			VIDIOC_MSM_ISPIF_INIT, &csid_version);
-		if (rc < 0) {
-			pr_err("%s: ispif initialization failed %d\n",
+		if (camdev->is_ispif) {
+			rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+				VIDIOC_MSM_ISPIF_INIT, &csid_version);
+			if (rc < 0) {
+				pr_err("%s: ispif initialization failed %d\n",
 				__func__, rc);
-			goto msm_open_done;
+				goto msm_open_done;
+			}
 		}
 
 		/* then sensor - move sub dev later*/
@@ -563,7 +628,6 @@
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
 		}
-
 		if (sync->actctrl.a_power_up)
 			rc = sync->actctrl.a_power_up(
 				sync->sdata->actuator_info);
@@ -573,12 +637,13 @@
 			goto msm_open_done;
 		}
 
-		pm_qos_add_request(&p_mctl->pm_qos_req_list,
+		if (camdev->is_ispif) {
+			pm_qos_add_request(&p_mctl->pm_qos_req_list,
 					PM_QOS_CPU_DMA_LATENCY,
 					PM_QOS_DEFAULT_VALUE);
-		pm_qos_update_request(&p_mctl->pm_qos_req_list,
+			pm_qos_update_request(&p_mctl->pm_qos_req_list,
 					MSM_V4L2_SWFI_LATENCY);
-
+		}
 		sync->apps_id = apps_id;
 		sync->opencnt++;
 	}
@@ -591,28 +656,44 @@
 static int msm_mctl_release(struct msm_cam_media_controller *p_mctl)
 {
 	int rc = 0;
-	v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-		VIDIOC_MSM_ISPIF_RELEASE, NULL);
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
+	struct msm_camera_sensor_info *sinfo =
+		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+	if (camdev->is_ispif) {
+		v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+			VIDIOC_MSM_ISPIF_RELEASE, NULL);
+	}
 
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
 		p_mctl->isp_sdev->isp_release(&p_mctl->sync);
 
-	v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
-		VIDIOC_MSM_CSID_RELEASE, NULL);
+	if (camdev->is_csid) {
+		v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+			VIDIOC_MSM_CSID_RELEASE, NULL);
+	}
 
-	v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
-		VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+	if (camdev->is_csic) {
+		v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+			VIDIOC_MSM_CSIC_RELEASE, NULL);
+	}
+
+	if (camdev->is_csiphy) {
+		v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+			VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+	}
 
 	if (p_mctl->sync.actctrl.a_power_down)
 		p_mctl->sync.actctrl.a_power_down(
 			p_mctl->sync.sdata->actuator_info);
 
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
-
-	pm_qos_update_request(&p_mctl->pm_qos_req_list,
+	if (camdev->is_ispif) {
+		pm_qos_update_request(&p_mctl->pm_qos_req_list,
 				PM_QOS_DEFAULT_VALUE);
-	pm_qos_remove_request(&p_mctl->pm_qos_req_list);
-
+		pm_qos_remove_request(&p_mctl->pm_qos_req_list);
+	}
 	wake_unlock(&p_mctl->sync.wake_lock);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index b631981..0ba1c0f 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -220,6 +220,7 @@
 	case MSM_PMEM_CS:
 	case MSM_PMEM_IHIST:
 	case MSM_PMEM_SKIN:
+	case MSM_PMEM_AEC_AWB:
 		rc = msm_pmem_table_add(ptype, pinfo, client);
 		break;
 
@@ -246,6 +247,7 @@
 	case MSM_PMEM_CS:
 	case MSM_PMEM_IHIST:
 	case MSM_PMEM_SKIN:
+	case MSM_PMEM_AEC_AWB:
 		hlist_for_each_entry_safe(region, node, n,
 				ptype, list) {
 
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
new file mode 100644
index 0000000..638c51d
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -0,0 +1,1353 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/msm_adsp.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/android_pmem.h>
+#include <linux/slab.h>
+#include <linux/pm_qos_params.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_isp.h>
+#include <mach/msm_adsp.h>
+#include <mach/clk.h>
+#include <mach/camera.h>
+#include "msm_vfe7x27a_v4l2.h"
+#include "msm.h"
+
+/* ADSP Messages */
+#define MSG_RESET_ACK  0
+#define MSG_STOP_ACK  1
+#define MSG_SNAPSHOT  2
+#define MSG_ILLEGAL_COMMAND  3
+#define MSG_START_ACK  4
+#define MSG_UPDATE_ACK  5
+#define MSG_OUTPUT1  6
+#define MSG_OUTPUT2  7
+#define MSG_STATS_AF  8
+#define MSG_STATS_WE  9
+#define MSG_STATS_HISTOGRAM  10
+#define MSG_EPOCH1  11
+#define MSG_EPOCH2  12
+#define MSG_VFE_ERROR 13
+#define MSG_SYNC_TIMER1_DONE  14
+#define MSG_SYNC_TIMER2_DONE  15
+#define MSG_ASYNC_TIMER1_DONE  16
+#define MSG_ASYNC_TIMER2_DONE  17
+#define MSG_CAPTURE_COMPLETE  18
+#define MSG_TABLE_CMD_ACK  19
+#define MSG_EXP_TIMEOUT_ACK  20
+#define MSG_SOF  21
+#define MSG_OUTPUT_T  22
+#define MSG_OUTPUT_S  23
+
+#define VFE_ADSP_EVENT 0xFFFF
+#define SNAPSHOT_MASK_MODE 0x00000001
+#define MSM_AXI_QOS_PREVIEW	122000
+#define MSM_AXI_QOS_SNAPSHOT	192000
+
+
+#define QDSP_CMDQUEUE 25
+#define QDSP_SCALEQUEUE 26
+#define QDSP_TABLEQUEUE 27
+
+/* ADSP Scler queue Cmd IDs */
+#define VFE_SCALE_OUTPUT1_CONFIG  0
+#define VFE_SCALE_OUTPUT2_CONFIG  1
+#define VFE_SCALE_MAX  0xFFFFFFFF
+
+/* ADSP table queue Cmd IDs */
+#define VFE_AXI_INPUT_CONFIG  0
+#define VFE_AXI_OUTPUT_CONFIG  1
+#define VFE_RGB_GAMMA_CONFIG  2
+#define VFE_Y_GAMMA_CONFIG  3
+#define VFE_ROLL_OFF_CONFIG  4
+#define VFE_DEMOSAICv3_BPC_CFG  6
+#define VFE_DEMOSAICv3_ABF_CFG  7
+#define VFE_DEMOSAICv3_CFG  8
+#define VFE_MAX  0xFFFFFFFF
+
+/* ADSP cfg queue cmd IDs */
+#define VFE_RESET  0
+#define VFE_START  1
+#define VFE_STOP  2
+#define VFE_UPDATE  3
+#define VFE_CAMIF_CONFIG  4
+#define VFE_ACTIVE_REGION_CONFIG  5
+#define VFE_DEMOSAIC_CONFIG  6
+#define VFE_INPUT_FORMAT_CONFIG  7
+#define VFE_OUTPUT_CLAMP_CONFIG  8
+#define VFE_CHROMA_SUBSAMPLE_CONFIG  9
+#define VFE_BLACK_LEVEL_CONFIG  10
+#define VFE_WHITE_BALANCE_CONFIG  11
+#define VFE_COLOR_PROCESSING_CONFIG  12
+#define VFE_ADAPTIVE_FILTER_CONFIG  13
+#define VFE_FRAME_SKIP_CONFIG  14
+#define VFE_FOV_CROP  15
+#define VFE_STATS_AUTOFOCUS_CONFIG  16
+#define VFE_STATS_WB_EXP_CONFIG  17
+#define VFE_STATS_HISTOGRAM_CONFIG  18
+#define VFE_OUTPUT1_ACK  19
+#define VFE_OUTPUT2_ACK  20
+#define VFE_STATS_AUTOFOCUS_ACK  21
+#define VFE_STATS_WB_EXP_ACK  22
+#define VFE_EPOCH1_ACK  23
+#define VFE_EPOCH2_ACK  24
+#define VFE_UPDATE_CAMIF_FRAME_CONFIG  25
+#define VFE_SYNC_TIMER1_CONFIG  26
+#define VFE_SYNC_TIMER2_CONFIG  27
+#define VFE_ASYNC_TIMER1_START  28
+#define VFE_ASYNC_TIMER2_START  29
+#define VFE_STATS_AUTOFOCUS_UPDATE  30
+#define VFE_STATS_WB_EXP_UPDATE  31
+#define VFE_ROLL_OFF_UPDATE  33
+#define VFE_DEMOSAICv3_BPC_UPDATE  34
+#define VFE_TESTGEN_START  35
+#define VFE_STATS_MA  0xFFFFFFFF
+
+struct msg_id_map msgs_map[] = {
+	{MSG_RESET_ACK, MSG_ID_RESET_ACK},
+	{MSG_STOP_ACK, MSG_ID_STOP_ACK},
+	{MSG_SNAPSHOT, MSG_ID_SNAPSHOT_DONE},
+	{MSG_ILLEGAL_COMMAND, VFE_MAX},
+	{MSG_START_ACK, MSG_ID_START_ACK},
+	{MSG_UPDATE_ACK, MSG_ID_UPDATE_ACK},
+	{MSG_OUTPUT1, VFE_MAX},
+	{MSG_OUTPUT2, VFE_MAX},
+	{MSG_STATS_AF, MSG_ID_STATS_AF},
+	{MSG_STATS_WE, MSG_ID_STATS_AWB_AEC},
+	{MSG_STATS_HISTOGRAM, MSG_ID_STATS_IHIST},
+	{MSG_EPOCH1, MSG_ID_EPOCH1},
+	{MSG_EPOCH2, MSG_ID_EPOCH2},
+	{MSG_VFE_ERROR, MSG_ID_CAMIF_ERROR},
+	{MSG_SYNC_TIMER1_DONE, MSG_ID_SYNC_TIMER1_DONE},
+	{MSG_SYNC_TIMER2_DONE, MSG_ID_SYNC_TIMER2_DONE},
+	{MSG_ASYNC_TIMER1_DONE, MSG_ID_ASYNC_TIMER1_DONE},
+	{MSG_ASYNC_TIMER2_DONE, MSG_ID_ASYNC_TIMER2_DONE},
+	{MSG_CAPTURE_COMPLETE, MSG_CAPTURE_COMPLETE},
+	{MSG_TABLE_CMD_ACK, MSG_TABLE_CMD_ACK},
+	{MSG_EXP_TIMEOUT_ACK, MSG_EXP_TIMEOUT_ACK},
+	{MSG_SOF, MSG_ID_SOF_ACK},
+	{MSG_OUTPUT_T, MSG_ID_OUTPUT_T},
+	{MSG_OUTPUT_S, MSG_ID_OUTPUT_S},
+};
+
+struct cmd_id_map cmds_map[] = {
+	{VFE_CMD_DUMMY_0, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SET_CLK, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RESET, VFE_RESET, QDSP_CMDQUEUE,
+			"VFE_CMD_RESET", "VFE_RESET"},
+	{VFE_CMD_START, VFE_START, QDSP_CMDQUEUE,
+			"VFE_CMD_START", "VFE_START"},
+	{VFE_CMD_TEST_GEN_START, VFE_TESTGEN_START, QDSP_CMDQUEUE,
+		"VFE_CMD_TEST_GEN_START", "VFE_TESTGEN_START"},
+	{VFE_CMD_OPERATION_CFG, VFE_MAX , VFE_MAX},
+	{VFE_CMD_AXI_OUT_CFG, VFE_AXI_OUTPUT_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_AXI_OUT_CFG", "VFE_AXI_OUTPUT_CONFIG"},
+	{VFE_CMD_CAMIF_CFG, VFE_CAMIF_CONFIG, QDSP_CMDQUEUE,
+			"VFE_CMD_CAMIF_CFG", "VFE_CAMIF_CONFIG"},
+	{VFE_CMD_AXI_INPUT_CFG, VFE_AXI_INPUT_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_AXI_INPUT_CFG", "VFE_AXI_INPUT_CONFIG"},
+	{VFE_CMD_BLACK_LEVEL_CFG, VFE_BLACK_LEVEL_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_BLACK_LEVEL_CFG", "VFE_BLACK_LEVEL_CONFIG"},
+	{VFE_CMD_MESH_ROLL_OFF_CFG, VFE_ROLL_OFF_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_MESH_ROLL_OFF_CFG", "VFE_ROLL_OFF_CONFIG"},
+	{VFE_CMD_DEMUX_CFG, VFE_INPUT_FORMAT_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_DEMUX_CFG", "VFE_INPUT_FORMAT_CONFIG"},
+	{VFE_CMD_FOV_CFG, VFE_FOV_CROP, QDSP_CMDQUEUE,
+		"VFE_CMD_FOV_CFG", "VFE_FOV_CROP"},
+	{VFE_CMD_MAIN_SCALER_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_WB_CFG, VFE_WHITE_BALANCE_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_WB_CFG", "VFE_WHITE_BALANCE_CONFIG"},
+	{VFE_CMD_COLOR_COR_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RGB_G_CFG, VFE_RGB_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_RGB_G_CFG", "VFE_RGB_GAMMA_CONFIG"},
+	{VFE_CMD_LA_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_EN_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_SUP_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MCE_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SK_ENHAN_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ASF_CFG, VFE_ADAPTIVE_FILTER_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_ASF_CFG", "VFE_ADAPTIVE_FILTER_CONFIG"},
+	{VFE_CMD_S2Y_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_S2CbCr_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_SUBS_CFG, VFE_CHROMA_SUBSAMPLE_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_CHROMA_SUBS_CFG", "VFE_CHROMA_SUBSAMPLE_CONFIG"},
+	{VFE_CMD_OUT_CLAMP_CFG, VFE_OUTPUT_CLAMP_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_OUT_CLAMP_CFG", "VFE_OUTPUT_CLAMP_CONFIG"},
+	{VFE_CMD_FRAME_SKIP_CFG, VFE_FRAME_SKIP_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_FRAME_SKIP_CFG", "VFE_FRAME_SKIP_CONFIG"},
+	{VFE_CMD_DUMMY_1, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_2, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_3, VFE_MAX, VFE_MAX},
+	{VFE_CMD_UPDATE, VFE_UPDATE, QDSP_CMDQUEUE,
+		"VFE_CMD_UPDATE", "VFE_UPDATE"},
+	{VFE_CMD_BL_LVL_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMUX_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_FOV_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MAIN_SCALER_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_WB_UPDATE, VFE_WHITE_BALANCE_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_WB_UPDATE", "VFE_WHITE_BALANCE_CONFIG"},
+	{VFE_CMD_COLOR_COR_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RGB_G_UPDATE, VFE_RGB_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_RGB_G_UPDATE", "VFE_RGB_GAMMA_CONFIG"},
+	{VFE_CMD_LA_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_EN_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_SUP_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MCE_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SK_ENHAN_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_S2CbCr_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_S2Y_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ASF_UPDATE, VFE_ADAPTIVE_FILTER_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_ASF_UPDATE", "VFE_ADAPTIVE_FILTER_CONFIG"},
+	{VFE_CMD_FRAME_SKIP_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CAMIF_FRAME_UPDATE, VFE_UPDATE_CAMIF_FRAME_CONFIG,
+		QDSP_CMDQUEUE, "VFE_CMD_CAMIF_FRAME_UPDATE",
+		"VFE_UPDATE_CAMIF_FRAME_CONFIG"},
+	{VFE_CMD_STATS_AF_UPDATE, VFE_STATS_AUTOFOCUS_UPDATE, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_AF_UPDATE", "VFE_STATS_AUTOFOCUS_UPDATE"},
+	{VFE_CMD_STATS_AE_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_IHIST_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_4, VFE_MAX, VFE_MAX},
+	{VFE_CMD_EPOCH1_ACK, VFE_EPOCH1_ACK, QDSP_CMDQUEUE,
+			"VFE_CMD_EPOCH1_ACK", "VFE_EPOCH1_ACK"},
+	{VFE_CMD_EPOCH2_ACK, VFE_EPOCH2_ACK, QDSP_CMDQUEUE,
+			"VFE_CMD_EPOCH2_ACK", "VFE_EPOCH2_ACK"},
+	{VFE_CMD_START_RECORDING, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STOP_RECORDING, VFE_MAX , VFE_MAX},
+	{VFE_CMD_DUMMY_5, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_6, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CAPTURE, VFE_START, QDSP_CMDQUEUE,
+			"VFE_CMD_CAPTURE", "VFE_START"},
+	{VFE_CMD_DUMMY_7, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STOP, VFE_STOP, QDSP_CMDQUEUE, "VFE_CMD_STOP", "VFE_STOP"},
+	{VFE_CMD_GET_HW_VERSION, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_FRAME_SKIP_COUNTS, VFE_MAX, VFE_MAX},
+	{VFE_CMD_OUTPUT1_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_OUTPUT2_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_OUTPUT3_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_JPEG_OUT_BUF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RAW_OUT_BUF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RAW_IN_BUF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AE_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_IHIST_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_8, VFE_MAX, VFE_MAX},
+	{VFE_CMD_JPEG_ENC_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_9, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AF_START, VFE_STATS_AUTOFOCUS_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_AF_START", "VFE_STATS_AUTOFOCUS_CONFIG"},
+	{VFE_CMD_STATS_AF_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AE_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AE_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_IHIST_START, VFE_STATS_HISTOGRAM_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_IHIST_START", "VFE_STATS_HISTOGRAM_CONFIG"},
+	{VFE_CMD_STATS_IHIST_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_10, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SYNC_TIMER_SETTING, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ASYNC_TIMER_SETTING, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LIVESHOT, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LA_SETUP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LINEARIZATION_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3, VFE_DEMOSAICv3_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3", "VFE_DEMOSAICv3_CFG"},
+	{VFE_CMD_DEMOSAICV3_ABCC_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBCC_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBPC_CFG, VFE_DEMOSAICv3_BPC_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3_DBPC_CFG", "VFE_DEMOSAICv3_BPC_CFG"},
+	{VFE_CMD_DEMOSAICV3_ABF_CFG, VFE_DEMOSAICv3_ABF_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3_ABF_CFG", "VFE_DEMOSAICv3_ABF_CFG"},
+	{VFE_CMD_DEMOSAICV3_ABCC_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBCC_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBPC_UPDATE, VFE_DEMOSAICv3_BPC_UPDATE,
+		QDSP_CMDQUEUE, "VFE_CMD_DEMOSAICV3_DBPC_UPDATE",
+		"VFE_DEMOSAICv3_BPC_UPDATE"},
+	{VFE_CMD_XBAR_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MODULE_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ZSL, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LINEARIZATION_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_ABF_UPDATE, VFE_DEMOSAICv3_ABF_CFG,
+		QDSP_TABLEQUEUE, "VFE_CMD_DEMOSAICV3_ABF_UPDATE",
+		"VFE_DEMOSAICv3_ABF_CFG"},
+	{VFE_CMD_CLF_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CLF_LUMA_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CLF_CHROMA_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_PCA_ROLL_OFF_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_PCA_ROLL_OFF_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_REG_DUMP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_LINEARIZATON_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_MESH_ROLLOFF_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_PCA_ROLLOFF_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_RGB_G_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_LA_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_UPDATE, VFE_DEMOSAICv3_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3_UPDATE", "VFE_DEMOSAICv3_CFG"},
+	{VFE_CMD_ACTIVE_REGION_CFG, VFE_ACTIVE_REGION_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_ACTIVE_REGION_CFG", "VFE_ACTIVE_REGION_CONFIG"},
+	{VFE_CMD_COLOR_PROCESSING_CONFIG, VFE_COLOR_PROCESSING_CONFIG,
+		QDSP_CMDQUEUE, "VFE_CMD_COLOR_PROCESSING_CONFIG",
+		"VFE_COLOR_PROCESSING_CONFIG"},
+	{VFE_CMD_STATS_WB_AEC_CONFIG, VFE_STATS_WB_EXP_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_WB_AEC_CONFIG", "VFE_STATS_WB_EXP_CONFIG"},
+	{VFE_CMD_STATS_WB_AEC_UPDATE, VFE_STATS_WB_EXP_UPDATE, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_WB_AEC_UPDATE", "VFE_STATS_WB_EXP_UPDATE"},
+	{VFE_CMD_Y_GAMMA_CONFIG, VFE_Y_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_Y_GAMMA_CONFIG", "VFE_Y_GAMMA_CONFIG"},
+	{VFE_CMD_SCALE_OUTPUT1_CONFIG, VFE_SCALE_OUTPUT1_CONFIG,
+		QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT1_CONFIG",
+		"VFE_SCALE_OUTPUT1_CONFIG"},
+	{VFE_CMD_SCALE_OUTPUT2_CONFIG, VFE_SCALE_OUTPUT2_CONFIG,
+		QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT2_CONFIG",
+		"VFE_SCALE_OUTPUT2_CONFIG"},
+};
+
+
+static struct msm_adsp_module *qcam_mod;
+static struct msm_adsp_module *vfe_mod;
+static void *extdata;
+static uint32_t extlen;
+
+struct mutex vfe_lock;
+static void     *vfe_syncdata;
+static uint8_t vfestopped;
+
+static struct stop_event stopevent;
+
+static uint32_t op_mode;
+static uint32_t raw_mode;
+static struct vfe2x_ctrl_type *vfe2x_ctrl;
+
+static void vfe2x_send_isp_msg(
+	struct vfe2x_ctrl_type *vctrl,
+	uint32_t isp_msg_id)
+{
+	struct isp_msg_event isp_msg_evt;
+
+	isp_msg_evt.msg_id = isp_msg_id;
+	isp_msg_evt.sof_count = vfe2x_ctrl->vfeFrameId;
+	v4l2_subdev_notify(&vctrl->subdev,
+			NOTIFY_ISP_MSG_EVT,
+			(void *)&isp_msg_evt);
+}
+
+static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
+		uint32_t ch0_paddr, uint32_t ch1_paddr)
+{
+	struct isp_msg_output msg;
+
+	msg.output_id = msgid;
+	msg.buf.ch_paddr[0]     = ch0_paddr;
+	msg.buf.ch_paddr[1]     = ch1_paddr;
+	msg.frameCounter = vfe2x_ctrl->vfeFrameId;
+
+	v4l2_subdev_notify(&vfe2x_ctrl->subdev,
+			NOTIFY_VFE_MSG_OUT,
+			&msg);
+	return;
+}
+
+static void vfe_send_stats_msg(uint32_t buf_addr, uint32_t msg_id)
+{
+	struct isp_msg_stats msg_stats;
+
+	msg_stats.frameCounter = vfe2x_ctrl->vfeFrameId;
+	msg_stats.buffer       = buf_addr;
+	msg_stats.id           = msg_id;
+
+	v4l2_subdev_notify(&vfe2x_ctrl->subdev,
+				NOTIFY_VFE_MSG_STATS,
+				&msg_stats);
+}
+
+static void vfe_7x_ops(void *driver_data, unsigned id, size_t len,
+		void (*getevent)(void *ptr, size_t len))
+{
+	uint32_t evt_buf[3];
+	void *data;
+	struct buf_info *outch = NULL;
+	uint32_t y_phy, cbcr_phy;
+	struct table_cmd *table_pending = NULL;
+	unsigned long flags;
+	void   *cmd_data = NULL;
+	unsigned char buf[256];
+	struct msm_free_buf *free_buf = NULL;
+	struct vfe_outputack fack;
+
+	CDBG("%s:id=%d\n", __func__, id);
+
+	if (id != VFE_ADSP_EVENT) {
+		data = kzalloc(len, GFP_KERNEL);
+		if (!data) {
+			pr_err("%s: rp: cannot allocate buffer\n", __func__);
+			return;
+		}
+	}
+	if (id == VFE_ADSP_EVENT) {
+		/* event */
+		getevent(evt_buf, sizeof(evt_buf));
+		CDBG("%s:event:msg_id=%d\n", __func__, id);
+	} else {
+		/* messages */
+		getevent(data, len);
+		CDBG("%s:messages:msg_id=%d\n", __func__, id);
+
+		switch (id) {
+		case MSG_SNAPSHOT:
+			msm_camio_set_perf_lvl(S_PREVIEW);
+			vfe_7x_ops(driver_data, MSG_OUTPUT_S, len, getevent);
+			if (!raw_mode)
+				vfe_7x_ops(driver_data, MSG_OUTPUT_T,
+						len, getevent);
+			vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SNAPSHOT_DONE);
+			return;
+		case MSG_OUTPUT_S:
+			outch = &vfe2x_ctrl->snap;
+			y_phy = outch->ping.ch_paddr[0];
+			cbcr_phy = outch->ping.ch_paddr[1];
+			CDBG("MSG_OUTPUT_S: %x %x\n",
+				(unsigned int)y_phy, (unsigned int)cbcr_phy);
+			vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_S,
+							y_phy, cbcr_phy);
+			break;
+		case MSG_OUTPUT_T:
+			outch = &vfe2x_ctrl->thumb;
+			y_phy = outch->ping.ch_paddr[0];
+			cbcr_phy = outch->ping.ch_paddr[1];
+			CDBG("MSG_OUTPUT_T: %x %x\n",
+				(unsigned int)y_phy, (unsigned int)cbcr_phy);
+			vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_T,
+							y_phy, cbcr_phy);
+			break;
+		case MSG_OUTPUT1:
+		case MSG_OUTPUT2:
+			if (op_mode & SNAPSHOT_MASK_MODE) {
+				kfree(data);
+				return;
+			} else {
+				free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_P);
+			      CDBG("free_buf = %x\n", (unsigned int) free_buf);
+			      if (free_buf) {
+					fack.header = VFE_OUTPUT2_ACK;
+
+					fack.output2newybufferaddress =
+						(void *)(free_buf->ch_paddr[0]);
+
+					fack.output2newcbcrbufferaddress =
+						(void *)(free_buf->ch_paddr[1]);
+
+					cmd_data = &fack;
+					len = sizeof(fack);
+					msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+							cmd_data, len);
+			      } else {
+					fack.header = VFE_OUTPUT2_ACK;
+					fack.output2newybufferaddress =
+					(void *)
+				((struct vfe_endframe *)data)->y_address;
+					fack.output2newcbcrbufferaddress =
+					(void *)
+				((struct vfe_endframe *)data)->cbcr_address;
+					cmd_data = &fack;
+					len = sizeof(fack);
+					msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+						cmd_data, len);
+				}
+			}
+			y_phy = ((struct vfe_endframe *)data)->y_address;
+			cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address;
+
+
+			CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
+				 y_phy, cbcr_phy);
+
+			memcpy(((struct vfe_frame_extra *)extdata),
+				&((struct vfe_endframe *)data)->extra,
+				sizeof(struct vfe_frame_extra));
+
+			vfe2x_ctrl->vfeFrameId =
+				((struct vfe_frame_extra *)extdata)->frame_id;
+			vfe_send_outmsg(&vfe2x_ctrl->subdev,
+							MSG_ID_OUTPUT_P,
+							y_phy, cbcr_phy);
+			break;
+		case MSG_RESET_ACK:
+		case MSG_START_ACK:
+		case MSG_UPDATE_ACK:
+		case MSG_VFE_ERROR:
+		case MSG_SYNC_TIMER1_DONE:
+		case MSG_SYNC_TIMER2_DONE:
+			vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
+			if (id == MSG_START_ACK)
+				vfe2x_ctrl->vfe_started = 1;
+			break;
+		case MSG_SOF:
+			vfe2x_ctrl->vfeFrameId++;
+			if (vfe2x_ctrl->vfeFrameId == 0)
+				vfe2x_ctrl->vfeFrameId = 1; /* wrapped back */
+			vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SOF_ACK);
+			if (raw_mode)
+				vfe2x_send_isp_msg(vfe2x_ctrl,
+						MSG_ID_START_ACK);
+			break;
+		case MSG_STOP_ACK:
+			stopevent.state = 1;
+			vfe2x_ctrl->vfe_started = 0;
+			wake_up(&stopevent.wait);
+			vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_STOP_ACK);
+			break;
+		case MSG_STATS_AF:
+		case MSG_STATS_WE:
+			vfe_send_stats_msg(*(uint32_t *)data,
+						msgs_map[id].isp_id);
+			break;
+		default:
+			vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
+			break;
+		}
+	}
+	if (MSG_TABLE_CMD_ACK == id) {
+		spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+		if (list_empty(&vfe2x_ctrl->table_q)) {
+			if (vfe2x_ctrl->start_pending) {
+				CDBG("Send START\n");
+				cmd_data = buf;
+				*(uint32_t *)cmd_data = VFE_START;
+				memcpy(((char *)cmd_data) + 4,
+					&vfe2x_ctrl->start_cmd,
+					sizeof(vfe2x_ctrl->start_cmd));
+				/* Send Start cmd here */
+				len  = sizeof(vfe2x_ctrl->start_cmd) + 4;
+				msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+						cmd_data, len);
+				vfe2x_ctrl->start_pending = 0;
+			}
+			vfe2x_ctrl->tableack_pending = 0;
+			spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+			return;
+		}
+		table_pending = list_first_entry(&vfe2x_ctrl->table_q,
+					struct table_cmd, list);
+		if (!table_pending) {
+			vfe2x_ctrl->tableack_pending = 0;
+			spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+			return;
+		}
+		msm_adsp_write(vfe_mod, table_pending->queue,
+				table_pending->cmd, table_pending->size);
+		list_del(&table_pending->list);
+		kfree(table_pending->cmd);
+		vfe2x_ctrl->tableack_pending = 1;
+		spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+	} else if (!vfe2x_ctrl->tableack_pending) {
+		if (!list_empty(&vfe2x_ctrl->table_q))
+			return;
+	}
+}
+
+static struct msm_adsp_ops vfe_7x_sync = {
+	.event = vfe_7x_ops,
+};
+
+static int vfe_7x_config_axi(int mode,
+	struct buf_info *ad, struct axiout *ao)
+{
+	unsigned long *bptr;
+	int    cnt;
+	int rc = 0;
+
+
+	if (mode == OUTPUT_1) {
+		ao->output1buffer1_y_phy = ad->ping.ch_paddr[0];
+		ao->output1buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+		ao->output1buffer2_y_phy = ad->pong.ch_paddr[0];
+		ao->output1buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+		bptr = &ao->output1buffer3_y_phy;
+		for (cnt = 0; cnt < 6; cnt++) {
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+			*bptr = ad->pong.ch_paddr[1];
+			bptr++;
+		}
+	}
+
+	if (mode == OUTPUT_2) {
+		ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+		ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+		ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+		ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+		ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
+		ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+		bptr = &ao->output2buffer4_y_phy;
+		for (cnt = 0; cnt < 5; cnt++) {
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+			*bptr = ad->pong.ch_paddr[1];
+			bptr++;
+		}
+	}
+
+	if (mode == OUTPUT_1_AND_2) {
+		if (raw_mode) {
+			ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+			ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[0];
+			ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+			ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[0];
+		} else {
+			ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+			ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+			ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+			ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+	}
+		bptr = &ao->output2buffer3_y_phy;
+		for (cnt = 0; cnt < 6; cnt++) {
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+		}
+	}
+
+	return rc;
+}
+
+static void vfe2x_subdev_notify(int id, int path)
+{
+	struct msm_vfe_resp *rp;
+	unsigned long flags = 0;
+	spin_lock_irqsave(&vfe2x_ctrl->sd_notify_lock, flags);
+	rp = msm_isp_sync_alloc(sizeof(struct msm_vfe_resp), GFP_ATOMIC);
+	if (!rp) {
+		CDBG("rp: cannot allocate buffer\n");
+		return;
+	}
+	CDBG("vfe2x_subdev_notify : msgId = %d\n", id);
+	rp->evt_msg.type   = MSM_CAMERA_MSG;
+	rp->evt_msg.msg_id = path;
+	rp->type	   = id;
+	v4l2_subdev_notify(&vfe2x_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+	spin_unlock_irqrestore(&vfe2x_ctrl->sd_notify_lock, flags);
+}
+
+static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path)
+{
+	struct buf_info *outch = NULL;
+
+	vfe2x_subdev_notify(id, path);
+	if (op_mode & SNAPSHOT_MASK_MODE) {
+		if (path == VFE_MSG_OUTPUT_S)
+			outch = &vfe2x_ctrl->snap;
+		else if (path == VFE_MSG_OUTPUT_T)
+			outch = &vfe2x_ctrl->thumb;
+	} else {
+		if (path == VFE_MSG_OUTPUT_P)
+			outch = &vfe2x_ctrl->prev;
+	}
+	if (outch->free_buf.ch_paddr[0])
+		return &outch->free_buf;
+
+	return NULL;
+}
+
+static int vfe2x_configure_pingpong_buffers(int id, int path)
+{
+	struct buf_info *outch = NULL;
+	int rc = 0;
+
+	vfe2x_subdev_notify(id, path);
+
+	CDBG("Opmode = %d\n", op_mode);
+	if (op_mode & SNAPSHOT_MASK_MODE) {
+		if (path == VFE_MSG_OUTPUT_S)
+			outch = &vfe2x_ctrl->snap;
+		else if (path == VFE_MSG_OUTPUT_T)
+			outch = &vfe2x_ctrl->thumb;
+	} else {
+		if (path == VFE_MSG_OUTPUT_P)
+			outch = &vfe2x_ctrl->prev;
+	}
+	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
+		/* Configure Preview Ping Pong */
+		CDBG("%s Configure ping/pong address for %d",
+						__func__, path);
+	} else {
+		pr_err("%s ping/pong addr is null!!", __func__);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static struct buf_info *vfe2x_get_ch(int path)
+{
+	struct buf_info *ch = NULL;
+
+	CDBG("path = %d op_mode = %d\n", path, op_mode);
+	if (op_mode & SNAPSHOT_MASK_MODE) {
+		if (path == VFE_MSG_OUTPUT_T)
+			ch = &vfe2x_ctrl->thumb;
+		else if (path == VFE_MSG_OUTPUT_S)
+			ch = &vfe2x_ctrl->snap;
+	} else {
+		if (path == VFE_MSG_OUTPUT_P)
+			ch = &vfe2x_ctrl->prev;
+	}
+
+	BUG_ON(ch == NULL);
+	return ch;
+}
+
+static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int subdev_cmd, void *arg)
+{
+	struct msm_isp_cmd vfecmd;
+	struct msm_camvfe_params *vfe_params =
+		(struct msm_camvfe_params *)arg;
+	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+	struct table_cmd *table_pending;
+	long rc = 0;
+	void *data = vfe_params->data;
+
+	struct msm_pmem_region *regptr;
+	unsigned char buf[256];
+
+	struct vfe_stats_ack sack;
+	struct axidata *axid;
+	uint32_t i;
+	uint32_t header = 0;
+	uint32_t queue = 0;
+	struct vfe_stats_we_cfg *scfg = NULL;
+	struct vfe_stats_af_cfg *sfcfg = NULL;
+
+	struct axiout *axio = NULL;
+	void   *cmd_data = NULL;
+	void   *cmd_data_alloc = NULL;
+	unsigned long flags;
+	struct msm_free_buf *free_buf = NULL;
+	struct vfe_outputack fack;
+
+	CDBG("msm_vfe_subdev_ioctl is called\n");
+	if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
+	    cmd->cmd_type != CMD_STATS_BUF_RELEASE &&
+	    cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE &&
+		cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+		cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+		cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
+		cmd->cmd_type != CMD_VFE_BUFFER_RELEASE) {
+		if (copy_from_user(&vfecmd,
+				(void __user *)(cmd->value),
+				sizeof(vfecmd))) {
+			pr_err("copy_from_user in msm_vfe_subdev_ioctl fail\n");
+			return -EFAULT;
+		}
+	}
+
+	switch (cmd->cmd_type) {
+	case CMD_VFE_BUFFER_RELEASE: {
+		if (!(vfe2x_ctrl->vfe_started) || op_mode == 1)
+			return 0;
+		if (op_mode & SNAPSHOT_MASK_MODE) {
+			free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_T);
+		} else {
+			free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_P);
+			if (free_buf) {
+				fack.header = VFE_OUTPUT2_ACK;
+
+				fack.output2newybufferaddress =
+						(void *)(free_buf->ch_paddr[0]);
+
+				fack.output2newcbcrbufferaddress =
+						(void *)(free_buf->ch_paddr[1]);
+
+				cmd_data = &fack;
+				vfecmd.length = sizeof(fack) - 4;
+				queue = QDSP_CMDQUEUE;
+			}
+		}
+	}
+	break;
+	case CMD_CONFIG_PING_ADDR: {
+		int path = *((int *)cmd->value);
+		struct buf_info *outch = vfe2x_get_ch(path);
+		outch->ping = *((struct msm_free_buf *)data);
+	}
+		return 0;
+	case CMD_CONFIG_PONG_ADDR: {
+		int path = *((int *)cmd->value);
+		struct buf_info *outch = vfe2x_get_ch(path);
+		outch->pong = *((struct msm_free_buf *)data);
+	}
+		return 0;
+
+	case CMD_CONFIG_FREE_BUF_ADDR: {
+		int path = *((int *)cmd->value);
+		struct buf_info *outch = vfe2x_get_ch(path);
+		outch->free_buf = *((struct msm_free_buf *)data);
+	}
+		return 0;
+
+	case CMD_STATS_AEC_AWB_ENABLE:
+	case CMD_STATS_AXI_CFG: {
+		axid = data;
+		if (!axid) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		scfg =
+			kmalloc(sizeof(struct vfe_stats_we_cfg),
+				GFP_ATOMIC);
+		if (!scfg) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)scfg + 4,
+					(void __user *)(vfecmd.value),
+					vfecmd.length)) {
+
+			rc = -EFAULT;
+			goto config_done;
+		}
+
+		CDBG("STATS_ENABLE: bufnum = %d, enabling = %d\n",
+			axid->bufnum1, scfg->wb_expstatsenable);
+
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+		*(uint32_t *)scfg = header;
+		if (axid->bufnum1 > 0) {
+			regptr = axid->region;
+
+			for (i = 0; i < axid->bufnum1; i++) {
+
+				CDBG("STATS_ENABLE, phy = 0x%lx\n",
+					regptr->paddr);
+
+				scfg->wb_expstatoutputbuffer[i] =
+					(void *)regptr->paddr;
+				regptr++;
+			}
+
+			cmd_data = scfg;
+
+		} else {
+			rc = -EINVAL;
+			goto config_done;
+		}
+	}
+		break;
+	case CMD_STATS_AF_ENABLE:
+	case CMD_STATS_AF_AXI_CFG: {
+		axid = data;
+		if (!axid) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		sfcfg =
+			kmalloc(sizeof(struct vfe_stats_af_cfg),
+				GFP_ATOMIC);
+
+		if (!sfcfg) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)sfcfg + 4,
+					(void __user *)(vfecmd.value),
+					vfecmd.length)) {
+
+			rc = -EFAULT;
+			goto config_done;
+		}
+
+		CDBG("AF_ENABLE: bufnum = %d, enabling = %d\n",
+			axid->bufnum1, sfcfg->af_enable);
+
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+		*(uint32_t *)sfcfg = header;
+		if (axid->bufnum1 > 0) {
+			regptr = &axid->region[0];
+
+			for (i = 0; i < axid->bufnum1; i++) {
+
+				CDBG("STATS_ENABLE, phy = 0x%lx\n",
+					regptr->paddr);
+
+				sfcfg->af_outbuf[i] =
+					(void *)regptr->paddr;
+
+				regptr++;
+			}
+
+			cmd_data = sfcfg;
+
+		} else {
+			rc = -EINVAL;
+			goto config_done;
+		}
+	}
+		break;
+	case CMD_SNAP_BUF_RELEASE:
+		break;
+	case CMD_STATS_BUF_RELEASE: {
+		CDBG("vfe_7x_config: CMD_STATS_BUF_RELEASE\n");
+		if (!data) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		sack.header = VFE_STATS_WB_EXP_ACK;
+		sack.bufaddr = (void *)*(uint32_t *)data;
+
+		queue  = QDSP_CMDQUEUE;
+		vfecmd.length = sizeof(struct vfe_stats_ack) - 4;
+		cmd_data = &sack;
+	}
+		break;
+	case CMD_STATS_AF_BUF_RELEASE: {
+		CDBG("vfe_7x_config: CMD_STATS_AF_BUF_RELEASE\n");
+		if (!data) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		sack.header = VFE_STATS_AUTOFOCUS_ACK;
+		sack.bufaddr = (void *)*(uint32_t *)data;
+
+		queue  = QDSP_CMDQUEUE;
+		vfecmd.length = sizeof(struct vfe_stats_ack) - 4;
+		cmd_data = &sack;
+	}
+		break;
+	case CMD_GENERAL:
+	case CMD_STATS_DISABLE: {
+		CDBG("CMD_GENERAL:%d %d\n", vfecmd.id, vfecmd.length);
+		if (vfecmd.id == VFE_CMD_OPERATION_CFG) {
+			if (copy_from_user(&vfe2x_ctrl->start_cmd,
+						(void __user *)(vfecmd.value),
+							vfecmd.length))
+				rc = -EFAULT;
+			op_mode = vfe2x_ctrl->start_cmd.mode_of_operation;
+			return rc;
+		}
+		if (vfecmd.length > 256 - 4) {
+			cmd_data_alloc =
+			cmd_data = kmalloc(vfecmd.length + 4, GFP_ATOMIC);
+			if (!cmd_data) {
+				rc = -ENOMEM;
+				goto config_failure;
+			}
+		} else
+			cmd_data = buf;
+
+		if (copy_from_user(((char *)cmd_data) + 4,
+					(void __user *)(vfecmd.value),
+					vfecmd.length)) {
+
+			rc = -EFAULT;
+			goto config_done;
+		}
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		CDBG("%s %s\n", cmds_map[vfecmd.id].isp_id_name,
+			cmds_map[vfecmd.id].vfe_id_name);
+		*(uint32_t *)cmd_data = header;
+		if (queue == QDSP_CMDQUEUE) {
+			switch (vfecmd.id) {
+			case VFE_CMD_RESET:
+				msm_adsp_enable(qcam_mod);
+				msm_adsp_enable(vfe_mod);
+				msm_camio_vfe_blk_reset();
+				vfestopped = 0;
+				break;
+			case VFE_CMD_START:
+			case VFE_CMD_CAPTURE:
+				spin_lock_irqsave(&vfe2x_ctrl->table_lock,
+									flags);
+				if (!list_empty(&vfe2x_ctrl->table_q)) {
+					vfe2x_ctrl->start_pending = 1;
+					spin_unlock_irqrestore(
+						&vfe2x_ctrl->table_lock,
+								flags);
+					return 0;
+				}
+				spin_unlock_irqrestore(&vfe2x_ctrl->table_lock,
+									flags);
+				vfecmd.length = sizeof(vfe2x_ctrl->start_cmd);
+				memcpy(((char *)cmd_data) + 4,
+					&vfe2x_ctrl->start_cmd,
+					sizeof(vfe2x_ctrl->start_cmd));
+				if (op_mode & SNAPSHOT_MASK_MODE)
+					msm_camio_set_perf_lvl(S_CAPTURE);
+				else
+					msm_camio_set_perf_lvl(S_PREVIEW);
+				vfestopped = 0;
+				break;
+			case VFE_CMD_STOP:
+				vfestopped = 1;
+				vfe2x_ctrl->vfe_started = 0;
+				goto config_send;
+
+			default:
+				break;
+			}
+		} /* QDSP_CMDQUEUE */
+	}
+		break;
+	case CMD_AXI_CFG_PREVIEW: {
+		CDBG("CMD_AXI_CFG_PREVIEW\n");
+		raw_mode = 0;
+		axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+		if (!axio) {
+			pr_err("NULL axio\n");
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)axio + 4,
+					(void __user *)(vfecmd.value),
+					sizeof(struct axiout))) {
+			pr_err("copy_from_user failed\n");
+			rc = -EFAULT;
+			goto config_done;
+		}
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_PREVIEW,
+							VFE_MSG_OUTPUT_P);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+
+		free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_P);
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		*(uint32_t *)axio = header;
+		vfe_7x_config_axi(OUTPUT_2, &vfe2x_ctrl->prev, axio);
+		cmd_data = axio;
+	}
+		break;
+	case CMD_RAW_PICT_AXI_CFG: {
+		CDBG("CMD_RAW_PICT_AXI_CFG:%d\n", op_mode);
+		raw_mode = 1;
+		axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)axio + 4,
+					(void __user *)(vfecmd.value),
+					sizeof(struct axiout))) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+							VFE_MSG_OUTPUT_S);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		*(uint32_t *)axio = header;
+		vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
+		cmd_data = axio;
+	}
+		break;
+	case CMD_AXI_CFG_SNAP: {
+		raw_mode = 0;
+		CDBG("CMD_AXI_CFG_SNAP :%d\n", op_mode);
+		axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)axio + 4,
+					(void __user *)(vfecmd.value),
+					sizeof(struct axiout))) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+							VFE_MSG_OUTPUT_S);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		*(uint32_t *)axio = header;
+		vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+							VFE_MSG_OUTPUT_T);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		vfe_7x_config_axi(OUTPUT_1, &vfe2x_ctrl->thumb, axio);
+		cmd_data = axio;
+	}
+		break;
+	default:
+		break;
+	}
+
+	if (vfestopped)
+		goto config_done;
+
+config_send:
+	CDBG("send adsp command = %d\n", *(uint32_t *)cmd_data);
+	if (queue == QDSP_TABLEQUEUE &&
+			vfe2x_ctrl->tableack_pending) {
+		table_pending = kzalloc(sizeof(struct table_cmd), GFP_ATOMIC);
+		if (!table_pending) {
+			rc = -ENOMEM;
+			goto config_done;
+		}
+		table_pending->cmd = kzalloc(vfecmd.length + 4, GFP_ATOMIC);
+		if (!table_pending->cmd) {
+			kfree(table_pending);
+			rc = -ENOMEM;
+			goto config_done;
+		}
+		memcpy(table_pending->cmd, cmd_data, vfecmd.length + 4);
+		table_pending->queue = queue;
+		table_pending->size = vfecmd.length + 4;
+		spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+		list_add_tail(&table_pending->list, &vfe2x_ctrl->table_q);
+		spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+	} else {
+		if (queue == QDSP_TABLEQUEUE) {
+			spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+			rc = msm_adsp_write(vfe_mod, queue,
+				cmd_data, vfecmd.length + 4);
+			vfe2x_ctrl->tableack_pending = 1;
+			spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+		} else {
+			if (*(uint32_t *)cmd_data == VFE_OUTPUT2_ACK) {
+				uint32_t *ptr = cmd_data;
+				CDBG("%x %x %x\n", ptr[0], ptr[1], ptr[2]);
+			}
+			rc = msm_adsp_write(vfe_mod, queue,
+				cmd_data, vfecmd.length + 4);
+			CDBG("%x\n", vfecmd.length + 4);
+		}
+	}
+
+config_done:
+	kfree(cmd_data_alloc);
+
+config_failure:
+	kfree(scfg);
+	kfree(axio);
+	return rc;
+}
+
+static struct msm_cam_clk_info vfe2x_clk_info[] = {
+	{"vfe_clk", 192000000},
+};
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
+	struct platform_device *pdev)
+{
+	int rc = 0;
+	v4l2_set_subdev_hostdata(sd, data);
+	vfe_syncdata = data;
+
+	spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
+	spin_lock_init(&vfe2x_ctrl->table_lock);
+	spin_lock_init(&vfe2x_ctrl->vfe_msg_lock);
+	init_waitqueue_head(&stopevent.wait);
+	INIT_LIST_HEAD(&vfe2x_ctrl->table_q);
+	INIT_LIST_HEAD(&vfe2x_ctrl->vfe_msg_q);
+	stopevent.timeout = 200;
+	stopevent.state = 0;
+	vfe2x_ctrl->vfe_started = 0;
+
+
+	CDBG("msm_cam_clk_enable: enable vfe_clk\n");
+	rc = msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
+			vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 1);
+	if (rc < 0)
+		return rc;
+
+	msm_camio_set_perf_lvl(S_INIT);
+
+	/* TODO : check is it required */
+	extlen = sizeof(struct vfe_frame_extra);
+
+	extdata = kmalloc(extlen, GFP_ATOMIC);
+	if (!extdata) {
+		rc = -ENOMEM;
+		goto init_fail;
+	}
+
+	rc = msm_adsp_get("QCAMTASK", &qcam_mod, &vfe_7x_sync, NULL);
+	if (rc) {
+		rc = -EBUSY;
+		goto get_qcam_fail;
+	}
+
+	rc = msm_adsp_get("VFETASK", &vfe_mod, &vfe_7x_sync, NULL);
+	if (rc) {
+		rc = -EBUSY;
+		goto get_vfe_fail;
+	}
+	return 0;
+
+get_vfe_fail:
+	msm_adsp_put(qcam_mod);
+get_qcam_fail:
+	kfree(extdata);
+init_fail:
+	extlen = 0;
+	return rc;
+}
+
+int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
+	struct platform_device *pdev)
+{
+	return 0;
+}
+
+void msm_vpe_subdev_release(struct platform_device *pdev)
+{
+	return;
+}
+
+void msm_vfe_subdev_release(struct platform_device *pdev)
+{
+	msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
+			vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
+	vfe_syncdata = NULL;
+
+	msm_adsp_disable(qcam_mod);
+	msm_adsp_disable(vfe_mod);
+
+	msm_adsp_put(qcam_mod);
+	msm_adsp_put(vfe_mod);
+
+	kfree(extdata);
+	msm_camio_set_perf_lvl(S_EXIT);
+	return;
+}
+
+static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
+	.ioctl = msm_vfe_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
+	.core = &msm_vfe_subdev_core_ops,
+};
+
+static int __devinit vfe2x_probe(struct platform_device *pdev)
+{
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	vfe2x_ctrl = kzalloc(sizeof(struct vfe2x_ctrl_type), GFP_KERNEL);
+	if (!vfe2x_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&vfe2x_ctrl->subdev, &msm_vfe_subdev_ops);
+	snprintf(vfe2x_ctrl->subdev.name,
+			 sizeof(vfe2x_ctrl->subdev.name), "vfe2.x");
+	v4l2_set_subdevdata(&vfe2x_ctrl->subdev, vfe2x_ctrl);
+	platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
+
+	vfe2x_ctrl->pdev = pdev;
+	return 0;
+}
+
+static struct platform_driver vfe2x_driver = {
+	.probe = vfe2x_probe,
+	.driver = {
+		.name = MSM_VFE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_vfe2x_init_module(void)
+{
+	return platform_driver_register(&vfe2x_driver);
+}
+
+static void __exit msm_vfe2x_exit_module(void)
+{
+	platform_driver_unregister(&vfe2x_driver);
+}
+
+module_init(msm_vfe2x_init_module);
+module_exit(msm_vfe2x_exit_module);
+MODULE_DESCRIPTION("VFE 2.x driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.h b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
new file mode 100644
index 0000000..0f7fb60
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
@@ -0,0 +1,385 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_VFE7X_H__
+#define __MSM_VFE7X_H__
+#include <media/msm_camera.h>
+#include <mach/camera.h>
+#include <linux/list.h>
+#include "msm.h"
+
+struct cmd_id_map {
+	uint32_t isp_id;
+	uint32_t vfe_id;
+	uint32_t queue;
+	char isp_id_name[64];
+	char vfe_id_name[64];
+} __packed;
+
+struct msg_id_map {
+	uint32_t vfe_id;
+	uint32_t isp_id;
+} __packed;
+
+struct table_cmd {
+	struct list_head list;
+	void *cmd;
+	int size;
+	int queue;
+} __packed;
+
+struct vfe_msg {
+	struct list_head list;
+	void *cmd;
+	int len;
+	int id;
+} __packed;
+
+struct buf_info {
+	/* Buffer */
+	struct msm_free_buf ping;
+	struct msm_free_buf pong;
+	struct msm_free_buf free_buf;
+} __packed;
+
+struct vfe_cmd_start {
+	uint32_t input_source:1;
+	uint32_t mode_of_operation:1;
+	uint32_t snap_number:4;
+	uint32_t /* reserved */ : 26;
+
+	/* Image Pipeline Modules */
+	uint32_t blacklevel_correction_enable:1;
+	uint32_t lens_rolloff_correction_enable:1;
+	uint32_t white_balance_enable:1;
+	uint32_t rgb_gamma_enable:1;
+	uint32_t luma_noise_reductionpath_enable:1;
+	uint32_t adaptive_spatialfilter_enable:1;
+	uint32_t chroma_subsample_enable:1;
+	uint32_t /* reserved */ : 25;
+
+	/* The dimension fed to the statistics module */
+	uint32_t last_pixel:12;
+	uint32_t /* reserved */ : 4;
+	uint32_t last_line:12;
+	uint32_t /* reserved */ : 4;
+} __packed;
+
+struct vfe2x_ctrl_type {
+	struct buf_info prev;
+	struct buf_info snap;
+	struct buf_info raw;
+	struct buf_info thumb;
+
+	spinlock_t  table_lock;
+	struct list_head table_q;
+	uint32_t tableack_pending;
+	uint32_t vfeFrameId;
+
+	spinlock_t vfe_msg_lock;
+	struct list_head vfe_msg_q;
+
+	struct vfe_cmd_start start_cmd;
+	uint32_t start_pending;
+	uint32_t vfe_started;
+
+	/* v4l2 subdev */
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+	struct clk *vfe_clk[3];
+	spinlock_t  sd_notify_lock;
+} __packed;
+
+struct vfe_frame_extra {
+	uint32_t	bl_evencol:23;
+	uint32_t	rvd1:9;
+	uint32_t	bl_oddcol:23;
+	uint32_t	rvd2:9;
+
+	uint32_t	d_dbpc_stats_hot:16;
+	uint32_t	d_dbpc_stats_cold:16;
+
+	uint32_t	d_dbpc_stats_0_hot:10;
+	uint32_t	rvd3:6;
+	uint32_t	d_dbpc_stats_0_cold:10;
+	uint32_t	rvd4:6;
+	uint32_t	d_dbpc_stats_1_hot:10;
+	uint32_t	rvd5:6;
+	uint32_t	d_dbpc_stats_1_cold:10;
+	uint32_t	rvd6:6;
+
+	uint32_t	asf_max_edge;
+
+	uint32_t	e_y_wm_pm_stats_0:21;
+	uint32_t	rvd7:11;
+	uint32_t	e_y_wm_pm_stats_1_bl:8;
+	uint32_t	rvd8:8;
+	uint32_t	e_y_wm_pm_stats_1_nl:12;
+	uint32_t	rvd9:4;
+
+	uint32_t	e_cbcr_wm_pm_stats_0:21;
+	uint32_t	rvd10:11;
+	uint32_t	e_cbcr_wm_pm_stats_1_bl:8;
+	uint32_t	rvd11:8;
+	uint32_t	e_cbcr_wm_pm_stats_1_nl:12;
+	uint32_t	rvd12:4;
+
+	uint32_t	v_y_wm_pm_stats_0:21;
+	uint32_t	rvd13:11;
+	uint32_t	v_y_wm_pm_stats_1_bl:8;
+	uint32_t	rvd14:8;
+	uint32_t	v_y_wm_pm_stats_1_nl:12;
+	uint32_t	rvd15:4;
+
+	uint32_t	v_cbcr_wm_pm_stats_0:21;
+	uint32_t	rvd16:11;
+	uint32_t	v_cbcr_wm_pm_stats_1_bl:8;
+	uint32_t	rvd17:8;
+	uint32_t	v_cbcr_wm_pm_stats_1_nl:12;
+	uint32_t	rvd18:4;
+
+	uint32_t      frame_id;
+} __packed;
+
+struct vfe_endframe {
+	uint32_t      y_address;
+	uint32_t      cbcr_address;
+
+	struct vfe_frame_extra extra;
+} __packed;
+
+struct vfe_outputack {
+	uint32_t  header;
+	void      *output2newybufferaddress;
+	void      *output2newcbcrbufferaddress;
+} __packed;
+
+struct vfe_stats_ack {
+	uint32_t header;
+	/* MUST BE 64 bit ALIGNED */
+	void     *bufaddr;
+} __packed;
+
+/* AXI Output Config Command sent to DSP */
+struct axiout {
+	uint32_t            cmdheader:32;
+	int                 outputmode:3;
+	uint8_t             format:2;
+	uint32_t            /* reserved */ : 27;
+
+	/* AXI Output 1 Y Configuration, Part 1 */
+	uint32_t            out1yimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out1yimagewidthin64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 1 Y Configuration, Part 2 */
+	uint8_t             out1yburstlen:2;
+	uint32_t            out1ynumrows:12;
+	uint32_t            out1yrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 1 CbCr Configuration, Part 1 */
+	uint32_t            out1cbcrimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out1cbcrimagewidthin64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 1 CbCr Configuration, Part 2 */
+	uint8_t             out1cbcrburstlen:2;
+	uint32_t            out1cbcrnumrows:12;
+	uint32_t            out1cbcrrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 Y Configuration, Part 1 */
+	uint32_t            out2yimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out2yimagewidthin64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 Y Configuration, Part 2 */
+	uint8_t             out2yburstlen:2;
+	uint32_t            out2ynumrows:12;
+	uint32_t            out2yrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 CbCr Configuration, Part 1 */
+	uint32_t            out2cbcrimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out2cbcrimagewidtein64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 CbCr Configuration, Part 2 */
+	uint8_t             out2cbcrburstlen:2;
+	uint32_t            out2cbcrnumrows:12;
+	uint32_t            out2cbcrrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* Address configuration:
+	 * output1 phisycal address */
+	unsigned long   output1buffer1_y_phy;
+	unsigned long   output1buffer1_cbcr_phy;
+	unsigned long   output1buffer2_y_phy;
+	unsigned long   output1buffer2_cbcr_phy;
+	unsigned long   output1buffer3_y_phy;
+	unsigned long   output1buffer3_cbcr_phy;
+	unsigned long   output1buffer4_y_phy;
+	unsigned long   output1buffer4_cbcr_phy;
+	unsigned long   output1buffer5_y_phy;
+	unsigned long   output1buffer5_cbcr_phy;
+	unsigned long   output1buffer6_y_phy;
+	unsigned long   output1buffer6_cbcr_phy;
+	unsigned long   output1buffer7_y_phy;
+	unsigned long   output1buffer7_cbcr_phy;
+	unsigned long   output1buffer8_y_phy;
+	unsigned long   output1buffer8_cbcr_phy;
+
+	/* output2 phisycal address */
+	unsigned long   output2buffer1_y_phy;
+	unsigned long   output2buffer1_cbcr_phy;
+	unsigned long   output2buffer2_y_phy;
+	unsigned long   output2buffer2_cbcr_phy;
+	unsigned long   output2buffer3_y_phy;
+	unsigned long   output2buffer3_cbcr_phy;
+	unsigned long   output2buffer4_y_phy;
+	unsigned long   output2buffer4_cbcr_phy;
+	unsigned long   output2buffer5_y_phy;
+	unsigned long   output2buffer5_cbcr_phy;
+	unsigned long   output2buffer6_y_phy;
+	unsigned long   output2buffer6_cbcr_phy;
+	unsigned long   output2buffer7_y_phy;
+	unsigned long   output2buffer7_cbcr_phy;
+	unsigned long   output2buffer8_y_phy;
+	unsigned long   output2buffer8_cbcr_phy;
+} __packed;
+
+struct vfe_stats_we_cfg {
+	uint32_t       header;
+
+	/* White Balance/Exposure Statistic Selection */
+	uint8_t        wb_expstatsenable:1;
+	uint8_t        wb_expstatbuspriorityselection:1;
+	unsigned int   wb_expstatbuspriorityvalue:4;
+	unsigned int   /* reserved */ : 26;
+
+	/* White Balance/Exposure Statistic Configuration, Part 1 */
+	uint8_t        exposurestatregions:1;
+	uint8_t        exposurestatsubregions:1;
+	unsigned int   /* reserved */ : 14;
+
+	unsigned int   whitebalanceminimumy:8;
+	unsigned int   whitebalancemaximumy:8;
+
+	/* White Balance/Exposure Statistic Configuration, Part 2 */
+	uint8_t wb_expstatslopeofneutralregionline[
+		NUM_WB_EXP_NEUTRAL_REGION_LINES];
+
+	/* White Balance/Exposure Statistic Configuration, Part 3 */
+	unsigned int   wb_expstatcrinterceptofneutralregionline2:12;
+	unsigned int   /* reserved */ : 4;
+	unsigned int   wb_expstatcbinterceptofneutralreginnline1:12;
+	unsigned int    /* reserved */ : 4;
+
+	/* White Balance/Exposure Statistic Configuration, Part 4 */
+	unsigned int   wb_expstatcrinterceptofneutralregionline4:12;
+	unsigned int   /* reserved */ : 4;
+	unsigned int   wb_expstatcbinterceptofneutralregionline3:12;
+	unsigned int   /* reserved */ : 4;
+
+	/* White Balance/Exposure Statistic Output Buffer Header */
+	unsigned int   wb_expmetricheaderpattern:8;
+	unsigned int   /* reserved */ : 24;
+
+	/* White Balance/Exposure Statistic Output Buffers-MUST
+	* BE 64 bit ALIGNED */
+	void  *wb_expstatoutputbuffer[NUM_WB_EXP_STAT_OUTPUT_BUFFERS];
+} __packed;
+
+struct vfe_stats_af_cfg {
+	uint32_t header;
+
+	/* Autofocus Statistic Selection */
+	uint8_t       af_enable:1;
+	uint8_t       af_busprioritysel:1;
+	unsigned int  af_buspriorityval:4;
+	unsigned int  /* reserved */ : 26;
+
+	/* Autofocus Statistic Configuration, Part 1 */
+	unsigned int  af_singlewinvoffset:12;
+	unsigned int  /* reserved */ : 4;
+	unsigned int  af_singlewinhoffset:12;
+	unsigned int  /* reserved */ : 3;
+	uint8_t       af_winmode:1;
+
+	/* Autofocus Statistic Configuration, Part 2 */
+	unsigned int  af_singglewinvh:11;
+	unsigned int  /* reserved */ : 5;
+	unsigned int  af_singlewinhw:11;
+	unsigned int  /* reserved */ : 5;
+
+	/* Autofocus Statistic Configuration, Parts 3-6 */
+	uint8_t       af_multiwingrid[NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS];
+
+	/* Autofocus Statistic Configuration, Part 7 */
+	signed int    af_metrichpfcoefa00:5;
+	signed int    af_metrichpfcoefa04:5;
+	unsigned int  af_metricmaxval:11;
+	uint8_t       af_metricsel:1;
+	unsigned int  /* reserved */ : 10;
+
+	/* Autofocus Statistic Configuration, Part 8 */
+	signed int    af_metrichpfcoefa20:5;
+	signed int    af_metrichpfcoefa21:5;
+	signed int    af_metrichpfcoefa22:5;
+	signed int    af_metrichpfcoefa23:5;
+	signed int    af_metrichpfcoefa24:5;
+	unsigned int  /* reserved */ : 7;
+
+	/* Autofocus Statistic Output Buffer Header */
+	unsigned int  af_metrichp:8;
+	unsigned int  /* reserved */ : 24;
+
+	/* Autofocus Statistic Output Buffers - MUST BE 64 bit ALIGNED!!! */
+	void *af_outbuf[NUM_AF_STAT_OUTPUT_BUFFERS];
+} __packed; /* VFE_StatsAutofocusConfigCmdType */
+
+struct msm_camera_frame_msg {
+	unsigned long   output_y_address;
+	unsigned long   output_cbcr_address;
+
+	unsigned int    blacklevelevenColumn:23;
+	uint16_t        reserved1:9;
+	unsigned int    blackleveloddColumn:23;
+	uint16_t        reserved2:9;
+
+	uint16_t        greendefectpixelcount:8;
+	uint16_t        reserved3:8;
+	uint16_t        redbluedefectpixelcount:8;
+	uint16_t        reserved4:8;
+} __packed;
+
+/* New one for 7k */
+struct msm_vfe_command_7k {
+	uint16_t queue;
+	uint16_t length;
+	void     *value;
+};
+
+struct stop_event {
+	wait_queue_head_t wait;
+	int state;
+	int timeout;
+};
+
+static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path);
+
+#endif /* __MSM_VFE7X_H__ */
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 7b22592..a9b7bc6 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -6,3 +6,6 @@
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
 obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
 obj-$(CONFIG_OV2720) += ov2720.o
+obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
+obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
+obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d31de14..227e606 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -172,6 +172,42 @@
 	return 0;
 }
 
+int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
+			int update_type, int res)
+{
+	int32_t rc = 0;
+	static int csi_config;
+
+	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+	msleep(30);
+	if (update_type == MSM_SENSOR_REG_INIT) {
+		CDBG("Register INIT\n");
+		s_ctrl->curr_csi_params = NULL;
+		msm_sensor_enable_debugfs(s_ctrl);
+		msm_sensor_write_init_settings(s_ctrl);
+		csi_config = 0;
+	} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
+		CDBG("PERIODIC : %d\n", res);
+		msm_sensor_write_conf_array(
+			s_ctrl->sensor_i2c_client,
+			s_ctrl->msm_sensor_reg->mode_settings, res);
+		msleep(30);
+		if (!csi_config) {
+			s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
+			CDBG("CSI config in progress\n");
+			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+				NOTIFY_CSIC_CFG,
+				s_ctrl->curr_csic_params);
+			CDBG("CSI config is done\n");
+			mb();
+			msleep(30);
+			csi_config = 1;
+		}
+		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
+		msleep(50);
+	}
+	return rc;
+}
 int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
 			int update_type, int res)
 {
@@ -532,6 +568,8 @@
 probe_fail:
 	CDBG("%s_i2c_probe failed\n", client->name);
 power_down:
+	if (rc > 0)
+		rc = 0;
 	s_ctrl->func_tbl->sensor_power_down(s_ctrl);
 	return rc;
 }
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index e06f628..ba366e6 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -158,6 +158,8 @@
 	struct mutex *msm_sensor_mutex;
 	struct msm_camera_csi2_params *curr_csi_params;
 	struct msm_camera_csi2_params **csi_params;
+	struct msm_camera_csi_params **csic_params;
+	struct msm_camera_csi_params *curr_csic_params;
 
 	struct v4l2_subdev sensor_v4l2_subdev;
 	struct v4l2_subdev_info *sensor_v4l2_subdev_info;
@@ -218,6 +220,9 @@
 int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
 			int update_type, int res);
 
+int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
+			int update_type, int res);
+
 int msm_sensor_enable_debugfs(struct msm_sensor_ctrl_t *s_ctrl);
 
 long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
new file mode 100644
index 0000000..924cbc9
--- /dev/null
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -0,0 +1,507 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "mt9e013"
+#define PLATFORM_DRIVER_NAME "msm_camera_mt9e013"
+#define mt9e013_obj mt9e013_##obj
+
+DEFINE_MUTEX(mt9e013_mut);
+static struct msm_sensor_ctrl_t mt9e013_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf mt9e013_groupon_settings[] = {
+	{0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_groupoff_settings[] = {
+	{0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_prev_settings[] = {
+	{0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x003A},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	/*Output Size (1632x1224)*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0CC9},/*X_ADDR_END*/
+	{0x0346, 0x0008},/*Y_ADDR_START*/
+	{0x034A, 0x0999},/*Y_ADDR_END*/
+	{0x034C, 0x0660},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x04C8},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFCB0},/*DATAPATH_SELECT*/
+	{0x3040, 0x04C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0002},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x1018},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x055B},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x0557},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x0846},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0130},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_snap_settings[] = {
+	{0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x003A},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	/*Output Size (3264x2448)*/
+	{0x0344, 0x0000},/*X_ADDR_START */
+	{0x0348, 0x0CCF},/*X_ADDR_END*/
+	{0x0346, 0x0000},/*Y_ADDR_START */
+	{0x034A, 0x099F},/*Y_ADDR_END*/
+	{0x034C, 0x0CD0},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x09A0},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x0041},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x13F8},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x0A2F},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x0A1F},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_ */
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr60_settings[] = {
+	{0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x0029},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0685},/*X_ADDR_END*/
+	{0x0346, 0x013a},/*Y_ADDR_START*/
+	{0x034A, 0x055B},/*Y_ADDR_END*/
+	{0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x00C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr90_settings[] = {
+	{0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x003D},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0685},/*X_ADDR_END*/
+	{0x0346, 0x013a},/*Y_ADDR_START*/
+	{0x034A, 0x055B},/*Y_ADDR_END*/
+	{0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x00C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr120_settings[] = {
+	{0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x0052},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0685},/*X_ADDR_END*/
+	{0x0346, 0x013a},/*Y_ADDR_START*/
+	{0x034A, 0x055B},/*Y_ADDR_END*/
+	{0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x00C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_recommend_settings[] = {
+	/*Disable embedded data*/
+	{0x3064, 0x7800},/*SMIA_TEST*/
+	/*configure 2-lane MIPI*/
+	{0x31AE, 0x0202},/*SERIAL_FORMAT*/
+	{0x31B8, 0x0E3F},/*MIPI_TIMING_2*/
+	/*set data to RAW10 format*/
+	{0x0112, 0x0A0A},/*CCP_DATA_FORMAT*/
+	{0x30F0, 0x8000},/*VCM CONTROL*/
+
+	{0x3044, 0x0590},
+	{0x306E, 0xFC80},
+	{0x30B2, 0xC000},
+	{0x30D6, 0x0800},
+	{0x316C, 0xB42F},
+	{0x316E, 0x869C},
+	{0x3170, 0x210E},
+	{0x317A, 0x010E},
+	{0x31E0, 0x1FB9},
+	{0x31E6, 0x07FC},
+	{0x37C0, 0x0000},
+	{0x37C2, 0x0000},
+	{0x37C4, 0x0000},
+	{0x37C6, 0x0000},
+	{0x3E02, 0x8801},
+	{0x3E04, 0x2301},
+	{0x3E06, 0x8449},
+	{0x3E08, 0x6841},
+	{0x3E0A, 0x400C},
+	{0x3E0C, 0x1001},
+	{0x3E0E, 0x2103},
+	{0x3E10, 0x4B41},
+	{0x3E12, 0x4B26},
+	{0x3E16, 0x8802},
+	{0x3E18, 0x84FF},
+	{0x3E1A, 0x8601},
+	{0x3E1C, 0x8401},
+	{0x3E1E, 0x840A},
+	{0x3E20, 0xFF00},
+	{0x3E22, 0x8401},
+	{0x3E24, 0x00FF},
+	{0x3E26, 0x0088},
+	{0x3E28, 0x2E8A},
+	{0x3E32, 0x8801},
+	{0x3E34, 0x4024},
+	{0x3E38, 0x8469},
+	{0x3E3C, 0x2301},
+	{0x3E3E, 0x3E25},
+	{0x3E40, 0x1C01},
+	{0x3E42, 0x8486},
+	{0x3E44, 0x8401},
+	{0x3E46, 0x00FF},
+	{0x3E48, 0x8401},
+	{0x3E4A, 0x8601},
+	{0x3E4C, 0x8402},
+	{0x3E4E, 0x00FF},
+	{0x3E50, 0x6623},
+	{0x3E52, 0x8340},
+	{0x3E54, 0x00FF},
+	{0x3E56, 0x4A42},
+	{0x3E58, 0x2203},
+	{0x3E5A, 0x674D},
+	{0x3E5C, 0x3F25},
+	{0x3E5E, 0x846A},
+	{0x3E60, 0x4C01},
+	{0x3E62, 0x8401},
+	{0x3E66, 0x3901},
+	{0x3ECC, 0x00EB},
+	{0x3ED0, 0x1E24},
+	{0x3ED4, 0xAFC4},
+	{0x3ED6, 0x909B},
+	{0x3ED8, 0x0006},
+	{0x3EDA, 0xCFC6},
+	{0x3EDC, 0x4FE4},
+	{0x3EE0, 0x2424},
+	{0x3EE2, 0x9797},
+	{0x3EE4, 0xC100},
+	{0x3EE6, 0x0540}
+};
+
+static struct v4l2_subdev_info mt9e013_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array mt9e013_init_conf[] = {
+	{&mt9e013_recommend_settings[0],
+	ARRAY_SIZE(mt9e013_recommend_settings), 0, MSM_CAMERA_I2C_WORD_DATA}
+};
+
+static struct msm_camera_i2c_conf_array mt9e013_confs[] = {
+	{&mt9e013_snap_settings[0],
+	ARRAY_SIZE(mt9e013_snap_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_prev_settings[0],
+	ARRAY_SIZE(mt9e013_prev_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_hfr60_settings[0],
+	ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_hfr90_settings[0],
+	ARRAY_SIZE(mt9e013_hfr90_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_hfr120_settings[0],
+	ARRAY_SIZE(mt9e013_hfr120_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+};
+
+static struct msm_sensor_output_info_t mt9e013_dimensions[] = {
+	{
+		.x_output = 0xCD0,
+		.y_output = 0x9A0,
+		.line_length_pclk = 0x13F8,
+		.frame_length_lines = 0xA2F,
+		.vt_pixel_clk = 174000000,
+		.op_pixel_clk = 174000000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x660,
+		.y_output = 0x4C8,
+		.line_length_pclk = 0x1018,
+		.frame_length_lines = 0x55B,
+		.vt_pixel_clk = 174000000,
+		.op_pixel_clk = 174000000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x340,
+		.y_output = 0x212,
+		.line_length_pclk = 0x970,
+		.frame_length_lines = 0x2A1,
+		.vt_pixel_clk = 98400000,
+		.op_pixel_clk = 98400000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x340,
+		.y_output = 0x212,
+		.line_length_pclk = 0x970,
+		.frame_length_lines = 0x2A1,
+		.vt_pixel_clk = 146400000,
+		.op_pixel_clk = 146400000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x340,
+		.y_output = 0x212,
+		.line_length_pclk = 0x970,
+		.frame_length_lines = 0x2A1,
+		.vt_pixel_clk = 196800000,
+		.op_pixel_clk = 196800000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csi_params mt9e013_csi_params = {
+	.data_format = CSI_10BIT,
+	.lane_cnt    = 2,
+	.lane_assign = 0xe4,
+	.dpcm_scheme = 0,
+	.settle_cnt  = 0x18,
+};
+
+static struct msm_camera_csi_params *mt9e013_csi_params_array[] = {
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t mt9e013_reg_addr = {
+	.x_output = 0x34C,
+	.y_output = 0x34E,
+	.line_length_pclk = 0x342,
+	.frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t mt9e013_id_info = {
+	.sensor_id_reg_addr = 0x0,
+	.sensor_id = 0x4B00,
+};
+
+static struct msm_sensor_exp_gain_info_t mt9e013_exp_gain_info = {
+	.coarse_int_time_addr = 0x202,
+	.global_gain_addr = 0x305E,
+	.vert_offset = 0,
+};
+
+static int32_t mt9e013_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+		uint16_t gain, uint32_t line)
+{
+	uint32_t fl_lines;
+	fl_lines =
+		(s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
+
+	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr, gain | 0x1000,
+		MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+		MSM_CAMERA_I2C_WORD_DATA);
+	s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	return 0;
+}
+
+static int32_t mt9e013_write_exp_snapshot_gain(struct msm_sensor_ctrl_t *s_ctrl,
+		uint16_t gain, uint32_t line)
+{
+	uint32_t fl_lines;
+	fl_lines =
+		(s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
+
+	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr, gain | 0x1000,
+		MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+		MSM_CAMERA_I2C_WORD_DATA);
+	s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, (0x065C|0x2), MSM_CAMERA_I2C_WORD_DATA);
+
+	return 0;
+}
+static void mt9e013_start_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x8250, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x8650, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x8658, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x0104, 0x00, MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x065C, MSM_CAMERA_I2C_WORD_DATA);
+}
+
+static void mt9e013_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x0058, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x0050, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x0104, 0x01, MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+static const struct i2c_device_id mt9e013_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&mt9e013_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver mt9e013_i2c_driver = {
+	.id_table = mt9e013_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client mt9e013_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&mt9e013_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops mt9e013_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops mt9e013_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops mt9e013_subdev_ops = {
+	.core = &mt9e013_subdev_core_ops,
+	.video  = &mt9e013_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t mt9e013_func_tbl = {
+	.sensor_start_stream = mt9e013_start_stream,
+	.sensor_stop_stream = mt9e013_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = mt9e013_write_exp_gain,
+	.sensor_write_snapshot_exp_gain = mt9e013_write_exp_snapshot_gain,
+	.sensor_setting = msm_sensor_setting1,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t mt9e013_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.group_hold_on_conf = mt9e013_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(mt9e013_groupon_settings),
+	.group_hold_off_conf = mt9e013_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(mt9e013_groupoff_settings),
+	.init_settings = &mt9e013_init_conf[0],
+	.init_size = ARRAY_SIZE(mt9e013_init_conf),
+	.mode_settings = &mt9e013_confs[0],
+	.output_settings = &mt9e013_dimensions[0],
+	.num_conf = ARRAY_SIZE(mt9e013_confs),
+};
+
+static struct msm_sensor_ctrl_t mt9e013_s_ctrl = {
+	.msm_sensor_reg = &mt9e013_regs,
+	.sensor_i2c_client = &mt9e013_sensor_i2c_client,
+	.sensor_i2c_addr = 0x6C,
+	.sensor_output_reg_addr = &mt9e013_reg_addr,
+	.sensor_id_info = &mt9e013_id_info,
+	.sensor_exp_gain_info = &mt9e013_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csic_params = &mt9e013_csi_params_array[0],
+	.msm_sensor_mutex = &mt9e013_mut,
+	.sensor_i2c_driver = &mt9e013_i2c_driver,
+	.sensor_v4l2_subdev_info = mt9e013_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(mt9e013_subdev_info),
+	.sensor_v4l2_subdev_ops = &mt9e013_subdev_ops,
+	.func_tbl = &mt9e013_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Aptina 8MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
new file mode 100644
index 0000000..e345717
--- /dev/null
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -0,0 +1,280 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "ov9726"
+#define PLATFORM_DRIVER_NAME "msm_camera_ov9726"
+#define ov9726_obj ov9726_##obj
+
+DEFINE_MUTEX(ov9726_mut);
+static struct msm_sensor_ctrl_t ov9726_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf ov9726_start_settings[] = {
+	{0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_stop_settings[] = {
+	{0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_groupon_settings[] = {
+	{0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_groupoff_settings[] = {
+	{0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_prev_settings[] = {
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_recommend_settings[] = {
+	{0x0103, 0x01}, /* SOFTWARE_RESET */
+	{0x3026, 0x00}, /* OUTPUT_SELECT01 */
+	{0x3027, 0x00}, /* OUTPUT_SELECT02 */
+	{0x3002, 0xe8}, /* IO_CTRL00 */
+	{0x3004, 0x03}, /* IO_CTRL01 */
+	{0x3005, 0xff}, /* IO_CTRL02 */
+	{0x3703, 0x42},
+	{0x3704, 0x10},
+	{0x3705, 0x45},
+	{0x3603, 0xaa},
+	{0x3632, 0x2f},
+	{0x3620, 0x66},
+	{0x3621, 0xc0},
+	{0x0340, 0x03}, /* FRAME_LENGTH_LINES_HI */
+	{0x0341, 0xC1}, /* FRAME_LENGTH_LINES_LO */
+	{0x0342, 0x06}, /* LINE_LENGTH_PCK_HI */
+	{0x0343, 0x80}, /* LINE_LENGTH_PCK_LO */
+	{0x0202, 0x03}, /* COARSE_INTEGRATION_TIME_HI */
+	{0x0203, 0x43}, /* COARSE_INTEGRATION_TIME_LO */
+	{0x3833, 0x04},
+	{0x3835, 0x02},
+	{0x4702, 0x04},
+	{0x4704, 0x00}, /* DVP_CTRL01 */
+	{0x4706, 0x08},
+	{0x5052, 0x01},
+	{0x3819, 0x6e},
+	{0x3817, 0x94},
+	{0x3a18, 0x00}, /* AEC_GAIN_CEILING_HI */
+	{0x3a19, 0x7f}, /* AEC_GAIN_CEILING_LO */
+	{0x404e, 0x7e},
+	{0x3631, 0x52},
+	{0x3633, 0x50},
+	{0x3630, 0xd2},
+	{0x3604, 0x08},
+	{0x3601, 0x40},
+	{0x3602, 0x14},
+	{0x3610, 0xa0},
+	{0x3612, 0x20},
+	{0x034c, 0x05}, /* X_OUTPUT_SIZE_HI */
+	{0x034d, 0x10}, /* X_OUTPUT_SIZE_LO */
+	{0x034e, 0x03}, /* Y_OUTPUT_SIZE_HI */
+	{0x034f, 0x28}, /* Y_OUTPUT_SIZE_LO */
+	{0x0340, 0x03}, /* FRAME_LENGTH_LINES_HI */
+	{0x0341, 0xC1}, /* FRAME_LENGTH_LINES_LO */
+	{0x0342, 0x06}, /* LINE_LENGTH_PCK_HI */
+	{0x0343, 0x80}, /* LINE_LENGTH_PCK_LO */
+	{0x0202, 0x03}, /* COARSE_INTEGRATION_TIME_HI */
+	{0x0203, 0x43}, /* COARSE_INTEGRATION_TIME_LO */
+	{0x0303, 0x01}, /* VT_SYS_CLK_DIV_LO */
+	{0x3002, 0x00}, /* IO_CTRL00 */
+	{0x3004, 0x00}, /* IO_CTRL01 */
+	{0x3005, 0x00}, /* IO_CTRL02 */
+	{0x4801, 0x0f}, /* MIPI_CTRL01 */
+	{0x4803, 0x05}, /* MIPI_CTRL03 */
+	{0x4601, 0x16}, /* VFIFO_READ_CONTROL */
+	{0x3014, 0x05}, /* SC_CMMN_MIPI / SC_CTRL00 */
+	{0x3104, 0x80},
+	{0x0305, 0x04}, /* PRE_PLL_CLK_DIV_LO */
+	{0x0307, 0x64}, /* PLL_MULTIPLIER_LO */
+	{0x300c, 0x02},
+	{0x300d, 0x20},
+	{0x300e, 0x01},
+	{0x3010, 0x01},
+	{0x460e, 0x81}, /* VFIFO_CONTROL00 */
+	{0x0101, 0x01}, /* IMAGE_ORIENTATION */
+	{0x3707, 0x14},
+	{0x3622, 0x9f},
+	{0x5047, 0x3D}, /* ISP_CTRL47 */
+	{0x4002, 0x45}, /* BLC_CTRL02 */
+	{0x5000, 0x06}, /* ISP_CTRL0 */
+	{0x5001, 0x00}, /* ISP_CTRL1 */
+	{0x3406, 0x00}, /* AWB_MANUAL_CTRL */
+	{0x3503, 0x13}, /* AEC_ENABLE */
+	{0x4005, 0x18}, /* BLC_CTRL05 */
+	{0x4837, 0x21},
+	{0x0100, 0x01}, /* MODE_SELECT */
+	{0x3a0f, 0x64}, /* AEC_CTRL0F */
+	{0x3a10, 0x54}, /* AEC_CTRL10 */
+	{0x3a11, 0xc2}, /* AEC_CTRL11 */
+	{0x3a1b, 0x64}, /* AEC_CTRL1B */
+	{0x3a1e, 0x54}, /* AEC_CTRL1E */
+	{0x3a1a, 0x05}, /* AEC_DIFF_MAX */
+};
+
+static struct v4l2_subdev_info ov9726_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array ov9726_init_conf[] = {
+	{&ov9726_recommend_settings[0],
+	ARRAY_SIZE(ov9726_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array ov9726_confs[] = {
+	{&ov9726_prev_settings[0],
+	ARRAY_SIZE(ov9726_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t ov9726_dimensions[] = {
+	{
+		.x_output = 0x510, /* 1296 */
+		.y_output = 0x328, /* 808 */
+		.line_length_pclk = 0x680, /* 1664 */
+		.frame_length_lines = 0x3C1, /* 961 */
+		.vt_pixel_clk = 320000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csi_params ov9726_csi_params = {
+	       .data_format = CSI_10BIT,
+	       .lane_cnt    = 1,
+	       .lane_assign = 0xe4,
+	       .dpcm_scheme = 0,
+	       .settle_cnt  = 7,
+};
+
+static struct msm_camera_csi_params *ov9726_csi_params_array[] = {
+	&ov9726_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t ov9726_reg_addr = {
+	.x_output = 0x034c,
+	.y_output = 0x034e,
+	.line_length_pclk = 0x0342,
+	.frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t ov9726_id_info = {
+	.sensor_id_reg_addr = 0x0000,
+	.sensor_id = 0x9726,
+};
+
+static struct msm_sensor_exp_gain_info_t ov9726_exp_gain_info = {
+	.coarse_int_time_addr = 0x0202,
+	.global_gain_addr = 0x0204,
+	.vert_offset = 6,
+};
+
+static const struct i2c_device_id ov9726_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&ov9726_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver ov9726_i2c_driver = {
+	.id_table = ov9726_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov9726_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&ov9726_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops ov9726_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops ov9726_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops ov9726_subdev_ops = {
+	.core = &ov9726_subdev_core_ops,
+	.video  = &ov9726_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t ov9726_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_setting = msm_sensor_setting1,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t ov9726_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = ov9726_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(ov9726_start_settings),
+	.stop_stream_conf = ov9726_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(ov9726_stop_settings),
+	.group_hold_on_conf = ov9726_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(ov9726_groupon_settings),
+	.group_hold_off_conf = ov9726_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(ov9726_groupoff_settings),
+	.init_settings = &ov9726_init_conf[0],
+	.init_size = ARRAY_SIZE(ov9726_init_conf),
+	.mode_settings = &ov9726_confs[0],
+	.output_settings = &ov9726_dimensions[0],
+	.num_conf = ARRAY_SIZE(ov9726_confs),
+};
+
+static struct msm_sensor_ctrl_t ov9726_s_ctrl = {
+	.msm_sensor_reg = &ov9726_regs,
+	.sensor_i2c_client = &ov9726_sensor_i2c_client,
+	.sensor_i2c_addr = 0x20,
+	.sensor_output_reg_addr = &ov9726_reg_addr,
+	.sensor_id_info = &ov9726_id_info,
+	.sensor_exp_gain_info = &ov9726_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csic_params = &ov9726_csi_params_array[0],
+	.msm_sensor_mutex = &ov9726_mut,
+	.sensor_i2c_driver = &ov9726_i2c_driver,
+	.sensor_v4l2_subdev_info = ov9726_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov9726_subdev_info),
+	.sensor_v4l2_subdev_ops = &ov9726_subdev_ops,
+	.func_tbl = &ov9726_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Omnivision WXGA Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
new file mode 100644
index 0000000..1f99119
--- /dev/null
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -0,0 +1,503 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "s5k4e1"
+#define PLATFORM_DRIVER_NAME "msm_camera_s5k4e1"
+#define s5k4e1_obj s5k4e1_##obj
+#define MSB                             1
+#define LSB                             0
+
+DEFINE_MUTEX(s5k4e1_mut);
+static struct msm_sensor_ctrl_t s5k4e1_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf s5k4e1_start_settings[] = {
+	{0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_stop_settings[] = {
+	{0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_groupon_settings[] = {
+	{0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_groupoff_settings[] = {
+	{0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_prev_settings[] = {
+	/* output size (1304 x 980) */
+	{0x30A9, 0x02},/* Horizontal Binning On */
+	{0x300E, 0xEB},/* Vertical Binning On */
+	{0x0387, 0x03},/* y_odd_inc 03(10b AVG) */
+	{0x0344, 0x00},/* x_addr_start 0 */
+	{0x0345, 0x00},
+	{0x0348, 0x0A},/* x_addr_end 2607 */
+	{0x0349, 0x2F},
+	{0x0346, 0x00},/* y_addr_start 0 */
+	{0x0347, 0x00},
+	{0x034A, 0x07},/* y_addr_end 1959 */
+	{0x034B, 0xA7},
+	{0x0380, 0x00},/* x_even_inc 1 */
+	{0x0381, 0x01},
+	{0x0382, 0x00},/* x_odd_inc 1 */
+	{0x0383, 0x01},
+	{0x0384, 0x00},/* y_even_inc 1 */
+	{0x0385, 0x01},
+	{0x0386, 0x00},/* y_odd_inc 3 */
+	{0x0387, 0x03},
+	{0x034C, 0x05},/* x_output_size 1304 */
+	{0x034D, 0x18},
+	{0x034E, 0x03},/* y_output_size 980 */
+	{0x034F, 0xd4},
+	{0x30BF, 0xAB},/* outif_enable[7], data_type[5:0](2Bh = bayer 10bit} */
+	{0x30C0, 0xA0},/* video_offset[7:4] 3260%12 */
+	{0x30C8, 0x06},/* video_data_length 1600 = 1304 * 1.25 */
+	{0x30C9, 0x5E},
+	/* Timing Configuration */
+	{0x0202, 0x03},
+	{0x0203, 0x14},
+	{0x0204, 0x00},
+	{0x0205, 0x80},
+	{0x0340, 0x03},/* Frame Length */
+	{0x0341, 0xE0},
+	{0x0342, 0x0A},/* 2738  Line Length */
+	{0x0343, 0xB2},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_snap_settings[] = {
+	/*Output Size (2608x1960)*/
+	{0x30A9, 0x03},/* Horizontal Binning Off */
+	{0x300E, 0xE8},/* Vertical Binning Off */
+	{0x0387, 0x01},/* y_odd_inc */
+	{0x034C, 0x0A},/* x_output size */
+	{0x034D, 0x30},
+	{0x034E, 0x07},/* y_output size */
+	{0x034F, 0xA8},
+	{0x30BF, 0xAB},/* outif_enable[7], data_type[5:0](2Bh = bayer 10bit} */
+	{0x30C0, 0x80},/* video_offset[7:4] 3260%12 */
+	{0x30C8, 0x0C},/* video_data_length 3260 = 2608 * 1.25 */
+	{0x30C9, 0xBC},
+	/*Timing configuration*/
+	{0x0202, 0x06},
+	{0x0203, 0x28},
+	{0x0204, 0x00},
+	{0x0205, 0x80},
+	{0x0340, 0x07},/* Frame Length */
+	{0x0341, 0xB4},
+	{0x0342, 0x0A},/* 2738 Line Length */
+	{0x0343, 0xB2},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_recommend_settings[] = {
+	/* Reset setting */
+	{0x0103, 0x01},
+	/* MIPI settings */
+	{0x30BD, 0x00},/* SEL_CCP[0] */
+	{0x3084, 0x15},/* SYNC Mode */
+	{0x30BE, 0x1A},/* M_PCLKDIV_AUTO[4], M_DIV_PCLK[3:0] */
+	{0x30C1, 0x01},/* pack video enable [0] */
+	{0x30EE, 0x02},/* DPHY enable [ 1] */
+	{0x3111, 0x86},/* Embedded data off [5] */
+
+	/* REC Settings */
+	/*CDS timing setting ... */
+	{0x3000, 0x05},
+	{0x3001, 0x03},
+	{0x3002, 0x08},
+	{0x3003, 0x0A},
+	{0x3004, 0x50},
+	{0x3005, 0x0E},
+	{0x3006, 0x5E},
+	{0x3007, 0x00},
+	{0x3008, 0x78},
+	{0x3009, 0x78},
+	{0x300A, 0x50},
+	{0x300B, 0x08},
+	{0x300C, 0x14},
+	{0x300D, 0x00},
+	{0x300E, 0xE8},
+	{0x300F, 0x82},
+	{0x301B, 0x77},
+
+	/* CDS option setting ... */
+	{0x3010, 0x00},
+	{0x3011, 0x3A},
+	{0x3029, 0x04},
+	{0x3012, 0x30},
+	{0x3013, 0xA0},
+	{0x3014, 0x00},
+	{0x3015, 0x00},
+	{0x3016, 0x30},
+	{0x3017, 0x94},
+	{0x3018, 0x70},
+	{0x301D, 0xD4},
+	{0x3021, 0x02},
+	{0x3022, 0x24},
+	{0x3024, 0x40},
+	{0x3027, 0x08},
+
+	/* Pixel option setting ...   */
+	{0x301C, 0x04},
+	{0x30D8, 0x3F},
+	{0x302B, 0x01},
+
+	{0x3070, 0x5F},
+	{0x3071, 0x00},
+	{0x3080, 0x04},
+	{0x3081, 0x38},
+
+	/* PLL settings */
+	{0x0305, 0x04},
+	{0x0306, 0x00},
+	{0x0307, 0x44},
+	{0x30B5, 0x00},
+	{0x30E2, 0x01},/* num lanes[1:0] = 2 */
+	{0x30F1, 0xB0},
+};
+
+static struct v4l2_subdev_info s5k4e1_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SGRBG10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array s5k4e1_init_conf[] = {
+	{&s5k4e1_recommend_settings[0],
+	ARRAY_SIZE(s5k4e1_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array s5k4e1_confs[] = {
+	{&s5k4e1_snap_settings[0],
+	ARRAY_SIZE(s5k4e1_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k4e1_prev_settings[0],
+	ARRAY_SIZE(s5k4e1_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t s5k4e1_dimensions[] = {
+	{
+		.x_output = 0xA30,
+		.y_output = 0x7A8,
+		.line_length_pclk = 0xAB2,
+		.frame_length_lines = 0x7B4,
+		.vt_pixel_clk = 816000000,
+		.op_pixel_clk = 816000000,
+		.binning_factor = 0,
+	},
+	{
+		.x_output = 0x518,
+		.y_output = 0x3D4,
+		.line_length_pclk = 0xAB2,
+		.frame_length_lines = 0x3E0,
+		.vt_pixel_clk = 816000000,
+		.op_pixel_clk = 816000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csi_params s5k4e1_csi_params = {
+	.data_format = CSI_10BIT,
+	.lane_cnt    = 1,
+	.lane_assign = 0xe4,
+	.dpcm_scheme = 0,
+	.settle_cnt  = 24,
+};
+
+static struct msm_camera_csi_params *s5k4e1_csi_params_array[] = {
+	&s5k4e1_csi_params,
+	&s5k4e1_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t s5k4e1_reg_addr = {
+	.x_output = 0x034C,
+	.y_output = 0x034E,
+	.line_length_pclk = 0x0342,
+	.frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t s5k4e1_id_info = {
+	.sensor_id_reg_addr = 0x0000,
+	.sensor_id = 0x4E10,
+};
+
+static struct msm_sensor_exp_gain_info_t s5k4e1_exp_gain_info = {
+	.coarse_int_time_addr = 0x0202,
+	.global_gain_addr = 0x0204,
+	.vert_offset = 4,
+};
+
+static inline uint8_t s5k4e1_byte(uint16_t word, uint8_t offset)
+{
+	return word >> (offset * BITS_PER_BYTE);
+}
+
+static int32_t s5k4e1_write_prev_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+						uint16_t gain, uint32_t line)
+{
+	uint16_t max_legal_gain = 0x0200;
+	int32_t rc = 0;
+	static uint32_t fl_lines, offset;
+
+	pr_info("s5k4e1_write_prev_exp_gain :%d %d\n", gain, line);
+	offset = s_ctrl->sensor_exp_gain_info->vert_offset;
+	if (gain > max_legal_gain) {
+		CDBG("Max legal gain Line:%d\n", __LINE__);
+		gain = max_legal_gain;
+	}
+
+	/* Analogue Gain */
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr,
+		s5k4e1_byte(gain, MSB),
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+		s5k4e1_byte(gain, LSB),
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	if (line > (s_ctrl->curr_frame_length_lines - offset)) {
+		fl_lines = line + offset;
+		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines,
+			s5k4e1_byte(fl_lines, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
+			s5k4e1_byte(fl_lines, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		/* Coarse Integration Time */
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+			s5k4e1_byte(line, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+			s5k4e1_byte(line, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	} else if (line < (fl_lines - offset)) {
+		fl_lines = line + offset;
+		if (fl_lines < s_ctrl->curr_frame_length_lines)
+			fl_lines = s_ctrl->curr_frame_length_lines;
+
+		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+		/* Coarse Integration Time */
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+			s5k4e1_byte(line, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+			s5k4e1_byte(line, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines,
+			s5k4e1_byte(fl_lines, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
+			s5k4e1_byte(fl_lines, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	} else {
+		fl_lines = line+4;
+		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+		/* Coarse Integration Time */
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+			s5k4e1_byte(line, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+			s5k4e1_byte(line, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	}
+	return rc;
+}
+
+static int32_t s5k4e1_write_pict_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+		uint16_t gain, uint32_t line)
+{
+	uint16_t max_legal_gain = 0x0200;
+	uint16_t min_ll_pck = 0x0AB2;
+	uint32_t ll_pck, fl_lines;
+	uint32_t ll_ratio;
+	uint8_t gain_msb, gain_lsb;
+	uint8_t intg_time_msb, intg_time_lsb;
+	uint8_t ll_pck_msb, ll_pck_lsb;
+
+	if (gain > max_legal_gain) {
+		CDBG("Max legal gain Line:%d\n", __LINE__);
+		gain = max_legal_gain;
+	}
+
+	gain = 32;
+	line = 1465;
+	pr_info("s5k4e1_write_exp_gain : gain = %d line = %d\n", gain, line);
+	line = (uint32_t) (line * s_ctrl->fps_divider);
+	fl_lines = s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider / Q10;
+	ll_pck = s_ctrl->curr_line_length_pclk;
+
+	if (fl_lines < (line / Q10))
+		ll_ratio = (line / (fl_lines - 4));
+	else
+		ll_ratio = Q10;
+
+	ll_pck = ll_pck * ll_ratio / Q10;
+	line = line / ll_ratio;
+	if (ll_pck < min_ll_pck)
+		ll_pck = min_ll_pck;
+
+	gain_msb = (uint8_t) ((gain & 0xFF00) >> 8);
+	gain_lsb = (uint8_t) (gain & 0x00FF);
+
+	intg_time_msb = (uint8_t) ((line & 0xFF00) >> 8);
+	intg_time_lsb = (uint8_t) (line & 0x00FF);
+
+	ll_pck_msb = (uint8_t) ((ll_pck & 0xFF00) >> 8);
+	ll_pck_lsb = (uint8_t) (ll_pck & 0x00FF);
+
+	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr,
+		gain_msb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+		gain_lsb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_output_reg_addr->line_length_pclk,
+		ll_pck_msb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_output_reg_addr->line_length_pclk + 1,
+		ll_pck_lsb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	/* Coarse Integration Time */
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+		intg_time_msb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+		intg_time_lsb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+
+	return 0;
+}
+
+static const struct i2c_device_id s5k4e1_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&s5k4e1_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver s5k4e1_i2c_driver = {
+	.id_table = s5k4e1_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client s5k4e1_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&s5k4e1_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops s5k4e1_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops s5k4e1_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops s5k4e1_subdev_ops = {
+	.core = &s5k4e1_subdev_core_ops,
+	.video  = &s5k4e1_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t s5k4e1_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = s5k4e1_write_prev_exp_gain,
+	.sensor_write_snapshot_exp_gain = s5k4e1_write_pict_exp_gain,
+	.sensor_setting = msm_sensor_setting1,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t s5k4e1_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = s5k4e1_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(s5k4e1_start_settings),
+	.stop_stream_conf = s5k4e1_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(s5k4e1_stop_settings),
+	.group_hold_on_conf = s5k4e1_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(s5k4e1_groupon_settings),
+	.group_hold_off_conf = s5k4e1_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(s5k4e1_groupoff_settings),
+	.init_settings = &s5k4e1_init_conf[0],
+	.init_size = ARRAY_SIZE(s5k4e1_init_conf),
+	.mode_settings = &s5k4e1_confs[0],
+	.output_settings = &s5k4e1_dimensions[0],
+	.num_conf = ARRAY_SIZE(s5k4e1_confs),
+};
+
+static struct msm_sensor_ctrl_t s5k4e1_s_ctrl = {
+	.msm_sensor_reg = &s5k4e1_regs,
+	.sensor_i2c_client = &s5k4e1_sensor_i2c_client,
+	.sensor_i2c_addr = 0x6C,
+	.sensor_output_reg_addr = &s5k4e1_reg_addr,
+	.sensor_id_info = &s5k4e1_id_info,
+	.sensor_exp_gain_info = &s5k4e1_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csic_params = &s5k4e1_csi_params_array[0],
+	.msm_sensor_mutex = &s5k4e1_mut,
+	.sensor_i2c_driver = &s5k4e1_i2c_driver,
+	.sensor_v4l2_subdev_info = s5k4e1_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k4e1_subdev_info),
+	.sensor_v4l2_subdev_ops = &s5k4e1_subdev_ops,
+	.func_tbl = &s5k4e1_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Samsung 5MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index a984943..d905b22 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -401,6 +401,7 @@
 #define CMD_CONFIG_FREE_BUF_ADDR 48
 #define CMD_AXI_CFG_ZSL_ALL_CHNLS 49
 #define CMD_AXI_CFG_VIDEO_ALL_CHNLS 50
+#define CMD_VFE_BUFFER_RELEASE 51
 
 /* vfe config command: config command(from config thread)*/
 struct msm_vfe_cfg_cmd {
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 4694b78..dae4a12 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -41,6 +41,7 @@
 #define MSG_ID_BUS_OVERFLOW             36
 #define MSG_ID_SOF_ACK                  37
 #define MSG_ID_STOP_REC_ACK             38
+#define MSG_ID_STATS_AWB_AEC            39
 
 /* ISP command IDs */
 #define VFE_CMD_DUMMY_0                                 0
@@ -172,6 +173,13 @@
 #define VFE_CMD_GET_RGB_G_TABLE                         126
 #define VFE_CMD_GET_LA_TABLE                            127
 #define VFE_CMD_DEMOSAICV3_UPDATE                       128
+#define VFE_CMD_ACTIVE_REGION_CFG                       129
+#define VFE_CMD_COLOR_PROCESSING_CONFIG                 130
+#define VFE_CMD_STATS_WB_AEC_CONFIG                     131
+#define VFE_CMD_STATS_WB_AEC_UPDATE                     132
+#define VFE_CMD_Y_GAMMA_CONFIG                          133
+#define VFE_CMD_SCALE_OUTPUT1_CONFIG                    134
+#define VFE_CMD_SCALE_OUTPUT2_CONFIG                    135
 
 struct msm_isp_cmd {
 	int32_t  id;
@@ -179,7 +187,6 @@
 	void     *value;
 };
 
-
 #define VPE_CMD_DUMMY_0                                 0
 #define VPE_CMD_INIT                                    1
 #define VPE_CMD_DEINIT                                  2