Camera Bring-up MR1.

Change-Id: I25be173c875491bd8f409fe50a958d96de0efe1a
Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 40995bb..bc1eded 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -16,7 +16,7 @@
 
 #include <asm/mach-types.h>
 
-#include <mach/board.h>
+#include <mach/camera.h>
 #include <mach/msm_bus_board.h>
 #include <mach/gpiomux.h>
 
@@ -323,6 +323,40 @@
 	},
 };
 
+static struct msm_bus_vectors cam_dual_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 348192000,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+};
+
+
 static struct msm_bus_paths cam_bus_client_config[] = {
 	{
 		ARRAY_SIZE(cam_init_vectors),
@@ -348,6 +382,10 @@
 		ARRAY_SIZE(cam_video_ls_vectors),
 		cam_video_ls_vectors,
 	},
+	{
+		ARRAY_SIZE(cam_dual_vectors),
+		cam_dual_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata cam_bus_client_pdata = {
@@ -369,20 +407,13 @@
 	},
 };
 
-static struct camera_vreg_t apq_8064_back_cam_vreg[] = {
+static struct camera_vreg_t apq_8064_cam_vreg[] = {
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
 };
 
-static struct camera_vreg_t apq_8064_front_cam_vreg[] = {
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
 #define CAML_RSTN PM8921_GPIO_PM_TO_SYS(28)
 #define CAMR_RSTN 34
 
@@ -482,8 +513,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.cam_vreg = apq_8064_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(apq_8064_back_cam_vreg),
+	.cam_vreg = apq_8064_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
 	.gpio_conf = &apq8064_back_cam_gpio_conf,
 	.i2c_conf = &apq8064_back_cam_i2c_conf,
 	.csi_lane_params = &imx074_csi_lane_params,
@@ -515,21 +546,14 @@
 	.csi_lane_mask = 0xF,
 };
 
-static struct camera_vreg_t apq_8064_imx091_vreg[] = {
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vio", REG_VS, 0, 0, 0},
-};
-
 static struct msm_camera_sensor_flash_data flash_imx091 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx091 = {
 	.mount_angle	= 0,
-	.cam_vreg = apq_8064_imx091_vreg,
-	.num_vreg = ARRAY_SIZE(apq_8064_imx091_vreg),
+	.cam_vreg = apq_8064_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
 	.gpio_conf = &apq8064_back_cam_gpio_conf,
 	.i2c_conf = &apq8064_back_cam_i2c_conf,
 	.csi_lane_params = &imx091_csi_lane_params,
@@ -556,13 +580,6 @@
 	.eeprom_info = &imx091_eeprom_info,
 };
 
-static struct camera_vreg_t apq_8064_s5k3l1yx_vreg[] = {
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
 static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
 };
@@ -574,8 +591,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
 	.mount_angle	= 90,
-	.cam_vreg = apq_8064_s5k3l1yx_vreg,
-	.num_vreg = ARRAY_SIZE(apq_8064_s5k3l1yx_vreg),
+	.cam_vreg = apq_8064_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
 	.gpio_conf = &apq8064_back_cam_gpio_conf,
 	.i2c_conf = &apq8064_back_cam_i2c_conf,
 	.csi_lane_params = &s5k3l1yx_csi_lane_params,
@@ -591,13 +608,6 @@
 	.sensor_type = BAYER_SENSOR,
 };
 
-static struct camera_vreg_t apq_8064_mt9m114_vreg[] = {
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
@@ -609,8 +619,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = apq_8064_mt9m114_vreg,
-	.num_vreg = ARRAY_SIZE(apq_8064_mt9m114_vreg),
+	.cam_vreg = apq_8064_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
 	.gpio_conf = &apq8064_front_cam_gpio_conf,
 	.i2c_conf = &apq8064_front_cam_i2c_conf,
 	.csi_lane_params = &mt9m114_csi_lane_params,
@@ -637,8 +647,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
 	.mount_angle	= 0,
-	.cam_vreg = apq_8064_front_cam_vreg,
-	.num_vreg = ARRAY_SIZE(apq_8064_front_cam_vreg),
+	.cam_vreg = apq_8064_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
 	.gpio_conf = &apq8064_front_cam_gpio_conf,
 	.i2c_conf = &apq8064_front_cam_i2c_conf,
 	.csi_lane_params = &ov2720_csi_lane_params,
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index d3e37cd..883e04d 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -13,7 +13,7 @@
 
 #include <asm/mach-types.h>
 #include <linux/gpio.h>
-#include <mach/board.h>
+#include <mach/camera.h>
 #include <mach/msm_bus_board.h>
 #include <mach/gpiomux.h>
 #include "devices.h"
@@ -331,6 +331,28 @@
 	},
 };
 
+static struct msm_bus_vectors cam_dual_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 302071680,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+};
+
+
 static struct msm_bus_paths cam_bus_client_config[] = {
 	{
 		ARRAY_SIZE(cam_init_vectors),
@@ -356,6 +378,10 @@
 		ARRAY_SIZE(cam_video_ls_vectors),
 		cam_video_ls_vectors,
 	},
+	{
+		ARRAY_SIZE(cam_dual_vectors),
+		cam_dual_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata cam_bus_client_pdata = {
@@ -377,19 +403,13 @@
 	},
 };
 
-static struct camera_vreg_t msm_8930_back_cam_vreg[] = {
+static struct camera_vreg_t msm_8930_cam_vreg[] = {
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
 };
 
-static struct camera_vreg_t msm_8930_front_cam_vreg[] = {
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-};
-
 static struct gpio msm8930_common_cam_gpio[] = {
 	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
 	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
@@ -466,8 +486,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.cam_vreg = msm_8930_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+	.cam_vreg = msm_8930_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
 	.gpio_conf = &msm_8930_back_cam_gpio_conf,
 	.csi_lane_params = &imx074_csi_lane_params,
 };
@@ -484,13 +504,6 @@
 	.actuator_info = &msm_act_main_cam_0_info,
 };
 
-static struct camera_vreg_t msm_8930_mt9m114_vreg[] = {
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
@@ -502,8 +515,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = msm_8930_mt9m114_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8930_mt9m114_vreg),
+	.cam_vreg = msm_8930_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
 	.gpio_conf = &msm_8930_front_cam_gpio_conf,
 	.csi_lane_params = &mt9m114_csi_lane_params,
 };
@@ -529,8 +542,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
 	.mount_angle	= 0,
-	.cam_vreg = msm_8930_front_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8930_front_cam_vreg),
+	.cam_vreg = msm_8930_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
 	.gpio_conf = &msm_8930_front_cam_gpio_conf,
 	.csi_lane_params = &ov2720_csi_lane_params,
 };
@@ -545,13 +558,6 @@
 	.sensor_type = BAYER_SENSOR,
 };
 
-static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
 static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
 	.flash_type = MSM_CAMERA_FLASH_LED,
 	.flash_src = &msm_flash_src
@@ -564,8 +570,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
 	.mount_angle  = 90,
-	.cam_vreg = msm_8930_s5k3l1yx_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8930_s5k3l1yx_vreg),
+	.cam_vreg = msm_8930_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
 	.gpio_conf = &msm_8930_back_cam_gpio_conf,
 	.csi_lane_params = &s5k3l1yx_csi_lane_params,
 };
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 0bb0b8f..f3b1cfd 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -13,7 +13,7 @@
 
 #include <asm/mach-types.h>
 #include <linux/gpio.h>
-#include <mach/board.h>
+#include <mach/camera.h>
 #include <mach/msm_bus_board.h>
 #include <mach/gpiomux.h>
 #include "devices.h"
@@ -402,6 +402,40 @@
 	},
 };
 
+static struct msm_bus_vectors cam_dual_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 348192000,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+};
+
+
 
 static struct msm_bus_paths cam_bus_client_config[] = {
 	{
@@ -428,6 +462,10 @@
 		ARRAY_SIZE(cam_video_ls_vectors),
 		cam_video_ls_vectors,
 	},
+	{
+		ARRAY_SIZE(cam_dual_vectors),
+		cam_dual_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata cam_bus_client_pdata = {
@@ -454,19 +492,13 @@
 	},
 };
 
-static struct camera_vreg_t msm_8960_back_cam_vreg[] = {
+static struct camera_vreg_t msm_8960_cam_vreg[] = {
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
 };
 
-static struct camera_vreg_t msm_8960_front_cam_vreg[] = {
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-};
-
 static struct gpio msm8960_common_cam_gpio[] = {
 	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
 	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
@@ -551,8 +583,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.cam_vreg = msm_8960_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+	.cam_vreg = msm_8960_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
 	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 	.csi_lane_params = &imx074_csi_lane_params,
 };
@@ -579,13 +611,6 @@
 	.eeprom_info = &imx074_eeprom_info,
 };
 
-static struct camera_vreg_t msm_8960_mt9m114_vreg[] = {
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
-};
-
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
@@ -595,10 +620,16 @@
 	.csi_lane_mask = 0x1,
 };
 
+static struct camera_vreg_t mt9m114_cam_vreg[] = {
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000, 50},
+	{"cam_vio", REG_VS, 0, 0, 0, 50},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600, 50},
+};
+
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = msm_8960_mt9m114_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_mt9m114_vreg),
+	.cam_vreg = mt9m114_cam_vreg,
+	.num_vreg = ARRAY_SIZE(mt9m114_cam_vreg),
 	.gpio_conf = &msm_8960_front_cam_gpio_conf,
 	.csi_lane_params = &mt9m114_csi_lane_params,
 };
@@ -624,8 +655,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
 	.mount_angle	= 0,
-	.cam_vreg = msm_8960_front_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_front_cam_vreg),
+	.cam_vreg = msm_8960_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
 	.gpio_conf = &msm_8960_front_cam_gpio_conf,
 	.csi_lane_params = &ov2720_csi_lane_params,
 };
@@ -640,13 +671,6 @@
 	.sensor_type = BAYER_SENSOR,
 };
 
-static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_VS, 0, 0, 0},
-	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
-};
-
 static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
 	.flash_type = MSM_CAMERA_FLASH_NONE,
 };
@@ -658,8 +682,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
 	.mount_angle  = 0,
-	.cam_vreg = msm_8960_s5k3l1yx_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_s5k3l1yx_vreg),
+	.cam_vreg = msm_8960_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
 	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 	.csi_lane_params = &s5k3l1yx_csi_lane_params,
 };
@@ -688,13 +712,6 @@
 	.csi_lane_mask = 0xF,
 };
 
-static struct camera_vreg_t msm_8960_imx091_vreg[] = {
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
-	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-	{"cam_vio", REG_VS, 0, 0, 0},
-};
-
 static struct msm_camera_sensor_flash_data flash_imx091 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
 #ifdef CONFIG_MSM_CAMERA_FLASH
@@ -704,8 +721,8 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx091 = {
 	.mount_angle	= 0,
-	.cam_vreg = msm_8960_imx091_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_imx091_vreg),
+	.cam_vreg = msm_8960_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
 	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 	.csi_lane_params = &imx091_csi_lane_params,
 };
@@ -717,6 +734,9 @@
 static struct msm_eeprom_info imx091_eeprom_info = {
 	.board_info     = &imx091_eeprom_i2c_info,
 	.bus_id         = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+	.eeprom_i2c_slave_addr = 0xA1,
+	.eeprom_reg_addr = 0x05,
+	.eeprom_read_length = 6,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_imx091_data = {
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 31e8827..f46821f 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5398,16 +5398,11 @@
 	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
 	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
 	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
-#if defined(CONFIG_MACH_LGE)
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		"4-000d"),
-	CLK_LOOKUP("cam_clk",		cam2_clk.c,		"4-006e"),
-#else /* QCT Original */
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-001a"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0034"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0020"),
 	CLK_LOOKUP("cam_clk",		cam1_clk.c,	"4-0048"),
 	CLK_LOOKUP("cam_clk",		cam1_clk.c,	"4-006c"),
-#endif
 	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
 	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		"msm_csid.2"),
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 767137e..83d756c 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2950,26 +2950,6 @@
 struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 0affd05..0586542 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -1098,26 +1098,6 @@
 struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 652c8e8..3b34b2a 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -4091,26 +4091,6 @@
 struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 8422541..306011a 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -64,18 +64,6 @@
 	uint8_t is_vpe;
 	struct msm_bus_scale_pdata *cam_bus_scale_table;
 };
-enum msm_camera_csi_data_format {
-	CSI_8BIT,
-	CSI_10BIT,
-	CSI_12BIT,
-};
-struct msm_camera_csi_params {
-	enum msm_camera_csi_data_format data_format;
-	uint8_t lane_cnt;
-	uint8_t lane_assign;
-	uint8_t settle_cnt;
-	uint8_t dpcm_scheme;
-};
 
 #ifdef CONFIG_SENSORS_MT9T013
 struct msm_camera_legacy_device_platform_data {
@@ -180,21 +168,6 @@
 	YUV_SENSOR,
 };
 
-enum camera_vreg_type {
-	REG_LDO,
-	REG_VS,
-	REG_GPIO,
-	REG_MAX
-};
-
-struct camera_vreg_t {
-	const char *reg_name;
-	enum camera_vreg_type type;
-	int min_voltage;
-	int max_voltage;
-	int op_mode;
-};
-
 struct msm_gpio_set_tbl {
 	unsigned gpio;
 	unsigned long flags;
@@ -204,6 +177,7 @@
 struct msm_camera_csi_lane_params {
 	uint16_t csi_lane_assign;
 	uint16_t csi_lane_mask;
+	uint8_t csi_phy_sel;
 };
 
 struct msm_camera_gpio_conf {
@@ -234,6 +208,13 @@
 	enum msm_camera_i2c_mux_mode i2c_mux_mode;
 };
 
+enum msm_camera_vreg_name_t {
+	CAM_VDIG,
+	CAM_VIO,
+	CAM_VANA,
+	CAM_VAF,
+};
+
 struct msm_camera_sensor_platform_info {
 	int mount_angle;
 	int sensor_reset;
@@ -268,6 +249,9 @@
 struct msm_eeprom_info {
 	struct i2c_board_info const *board_info;
 	int bus_id;
+	int eeprom_reg_addr;
+	int eeprom_read_length;
+	int eeprom_i2c_slave_addr;
 };
 
 struct msm_camera_sensor_info {
@@ -285,7 +269,6 @@
 	uint8_t num_resources;
 	struct msm_camera_sensor_flash_data *flash_data;
 	int csi_if;
-	struct msm_camera_csi_params csi_params;
 	struct msm_camera_sensor_strobe_flash_data *strobe_flash_data;
 	char *eeprom_data;
 	enum msm_camera_type camera_type;
@@ -408,23 +391,13 @@
 	struct msm_bus_scale_pdata *mdp_bus_scale_table;
 #endif
 	int mdp_rev;
-	void *power_on_set_1;
-	void *power_on_set_2;
-	void *power_on_set_3;
-	ssize_t power_on_set_size_1;
-	ssize_t power_on_set_size_2;
-	ssize_t power_on_set_size_3;
-	void *power_off_set_1;
-	void *power_off_set_2;
-	ssize_t power_off_set_size_1;
-	ssize_t power_off_set_size_2;
 	u32 ov0_wb_size;  /* overlay0 writeback size */
 	u32 ov1_wb_size;  /* overlay1 writeback size */
 	u32 mem_hid;
 	char cont_splash_enabled;
+	u32 splash_screen_addr;
+	u32 splash_screen_size;
 	char mdp_iommu_split_domain;
-	void (*bl_pwm_disable)(void);
-	int (*bl_on_status)(void);
 };
 
 
@@ -502,7 +475,6 @@
 	int (*allow_set_offset)(void);
 	char prim_panel_name[PANEL_NAME_MAX_LEN];
 	char ext_panel_name[PANEL_NAME_MAX_LEN];
-	int (*update_lcdc_lut)(void);
 };
 
 struct msm_hdmi_platform_data {
@@ -533,6 +505,7 @@
 	uint32_t gpio_mhl_power;
 	/* GPIO no. for hdmi-mhl mux */
 	uint32_t gpio_hdmi_mhl_mux;
+	bool mhl_enabled;
 };
 
 struct msm_i2c_platform_data {
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 48ed290..9f70ac2 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -24,9 +24,10 @@
 
 #include <mach/board.h>
 #include <media/msm_camera.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/iommu_domains.h>
 
+#define CONFIG_MSM_CAMERA_DEBUG
 #ifdef CONFIG_MSM_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
 #else
@@ -94,6 +95,7 @@
 	VFE_MSG_OUTPUT_SECONDARY,
 	VFE_MSG_OUTPUT_TERTIARY1,
 	VFE_MSG_OUTPUT_TERTIARY2,
+	VFE_MSG_OUTPUT_TERTIARY3,
 };
 
 enum vpe_resp_msg {
@@ -126,30 +128,6 @@
 	uint32_t frame_id;
 };
 
-struct msm_camera_csid_lut_params {
-	uint8_t num_cid;
-	struct msm_camera_csid_vc_cfg *vc_cfg;
-};
-
-struct msm_camera_csid_params {
-	uint8_t lane_cnt;
-	uint16_t lane_assign;
-	uint8_t phy_sel;
-	struct msm_camera_csid_lut_params lut_params;
-};
-
-struct msm_camera_csiphy_params {
-	uint8_t lane_cnt;
-	uint8_t settle_cnt;
-	uint16_t lane_mask;
-	uint8_t combo_mode;
-};
-
-struct msm_camera_csi2_params {
-	struct msm_camera_csid_params csid_params;
-	struct msm_camera_csiphy_params csiphy_params;
-};
-
 #ifndef CONFIG_MSM_CAMERA_V4L2
 #define VFE31_OUTPUT_MODE_PT (0x1 << 0)
 #define VFE31_OUTPUT_MODE_S (0x1 << 1)
@@ -331,21 +309,6 @@
 	uint16_t i2c_queue;
 };
 
-enum msm_camera_i2c_reg_addr_type {
-	MSM_CAMERA_I2C_BYTE_ADDR = 1,
-	MSM_CAMERA_I2C_WORD_ADDR,
-};
-
-enum msm_camera_i2c_data_type {
-	MSM_CAMERA_I2C_BYTE_DATA = 1,
-	MSM_CAMERA_I2C_WORD_DATA,
-	MSM_CAMERA_I2C_SET_BYTE_MASK,
-	MSM_CAMERA_I2C_UNSET_BYTE_MASK,
-	MSM_CAMERA_I2C_SET_WORD_MASK,
-	MSM_CAMERA_I2C_UNSET_WORD_MASK,
-	MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
-};
-
 enum msm_camera_i2c_cmd_type {
 	MSM_CAMERA_I2C_CMD_WRITE,
 	MSM_CAMERA_I2C_CMD_POLL,
@@ -405,6 +368,7 @@
 	atomic_t on_heap;
 	struct timespec ts;
 	uint32_t error_code;
+	uint32_t trans_code;
 };
 
 struct msm_device_queue {
@@ -669,14 +633,10 @@
 	S_STEREO_CAPTURE,
 	S_DEFAULT,
 	S_LIVESHOT,
+	S_DUAL,
 	S_EXIT
 };
 
-struct msm_cam_clk_info {
-	const char *clk_name;
-	long clk_rate;
-};
-
 int msm_camio_enable(struct platform_device *dev);
 int msm_camio_vpe_clk_enable(uint32_t);
 int msm_camio_vpe_clk_disable(void);
@@ -732,12 +692,16 @@
 int msm_cam_core_reset(void);
 
 int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
-		int num_vreg, struct regulator **reg_ptr, int config);
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int config);
 int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
-		int num_vreg, struct regulator **reg_ptr, int enable);
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int enable);
 
 int msm_camera_config_gpio_table
 	(struct msm_camera_sensor_info *sinfo, int gpio_en);
 int msm_camera_request_gpio_table
 	(struct msm_camera_sensor_info *sinfo, int gpio_en);
+void msm_camera_bus_scale_cfg(uint32_t bus_perf_client,
+		enum msm_bus_perf_setting perf_setting);
 #endif
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index f602a3b..e9b4e2b 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -123,53 +123,6 @@
 	---help---
 	  MICRON 5M Bayer Sensor KM modules with Autofocus
 
-config IMX111
-	bool "Sensor IMX111 (Sony 8MP)"
-	depends on MSM_CAMERA
-	select SEKONIX_LENS_ACT
-	default n
-	---help---
-	  Sony 8M Bayer Sensor modules with Autofocus
-
-config IMX111_ACT
-	bool "Actuator imx111 (BAYER 8M)"
-	depends on MSM_CAMERA
-	select MSM_ACTUATOR
-	default n
-	---help---
-	  Actuator for SONY 8 MP Bayer Sensor
-
-config SEKONIX_LENS_ACT
-	bool "Actuator SEKONIX LENS"
-	depends on MSM_CAMERA
-	select MSM_ACTUATOR
-	default n
-	---help---
-	  Actuator for Sekonix Lens
-
-config IMX091
-	bool "Sensor IMX091 (Sony 13MP)"
-	depends on MSM_CAMERA
-	select IMX091_ACT
-	default n
-	---help---
-	  Sony 13M Bayer Sensor modules with Autofocus
-
-config IMX091_ACT
-	bool "Actuator imx091 (BAYER 13M)"
-	depends on MSM_CAMERA
-	select MSM_ACTUATOR
-	default n
-	---help---
-	  Actuator for SONY 13MP Bayer Sensor
-
-config IMX119
-	bool "Sensor IMX119 1.3MP MIPI (Bayer 1.3M)"
-	depends on MSM_CAMERA
-	default n
-	---help---
-	  SONY 1.3M BAYER MIPI Sensor without Autofocus
-
 config MT9E013
 	bool "Sensor mt9e013 module (BAYER 8M)"
 	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A)
@@ -177,13 +130,6 @@
 	---help---
 	  Aptina 8M Bayer Sensor modules with Autofocus
 
-config MSM_CAMERA_FLASH_LM3559
-	bool "Qualcomm MSM camera lm3559 flash support"
-	depends on MSM_CAMERA
-	default n
-	---help---
-	  Enable support for LED flash for msm camera.
-
 config IMX074_ACT
 	bool "Actuator IMX074 (BAYER 13.5M)"
 	depends on MSM_CAMERA
@@ -308,6 +254,15 @@
         ---help---
           Enable support for Mercury Jpeg Engine
 
+config MSM_JPEG
+	tristate "Qualcomm MSM Jpeg Encoder Engine support"
+	depends on MSM_CAMERA && ARCH_MSM8974
+	---help---
+          Enable support for Jpeg Encoder/Decoder
+	  Engine for 8974.
+	  This module serves as the common driver
+	  for the JPEG 1.0 encoder and decoder.
+
 config MSM_VPE
 	tristate "Qualcomm MSM Video Pre-processing Engine support"
 	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60)
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index c673852..5921632 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -20,9 +20,8 @@
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
 obj-$(CONFIG_MSM_CAMERA) += vfe/
-obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/
+obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/ jpeg_10/
 obj-$(CONFIG_MSM_CAMERA_FLASH) += flash.o
-obj-$(CONFIG_MSM_CAMERA_FLASH_LM3559) += flash_lm3559.o
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_ARCH_MSM8X60) += msm_vpe.o
   obj-$(CONFIG_ARCH_MSM7X30) += msm_vpe.o msm_axi_qos.o
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index 9f7811e..b5bdaae 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -13,22 +13,6 @@
 #include <linux/module.h>
 #include "msm_actuator.h"
 
-
-#ifdef CONFIG_SEKONIX_LENS_ACT
-#define CHECK_ACT_WRITE_COUNT
-#define ACT_STOP_POS            10
-#define ACT_MIN_MOVE_RANGE      200
-#define ACT_POSTURE_MARGIN      100
-extern uint8_t imx111_afcalib_data[4];
-#else
-/* modification qct's af calibration routines */
-#define ACTUATOR_EEPROM_SADDR                (0x50 >> 1)
-#define ACTUATOR_START_ADDR                  0x06
-#define ACTUATOR_MACRO_ADDR                  0x08
-#define ACTUATOR_MARGIN                      30
-#define ACTUATOR_MIN_MOVE_RANGE              200 // TBD
-#endif
-
 static struct msm_actuator_ctrl_t msm_actuator_t;
 static struct msm_actuator msm_vcm_actuator_table;
 static struct msm_actuator msm_piezo_actuator_table;
@@ -171,25 +155,6 @@
 	damping_code_step = damping_params->damping_step;
 	wait_time = damping_params->damping_delay;
 
-#ifdef CONFIG_SEKONIX_LENS_ACT
-	CDBG("damping_code_step = %d\n",damping_code_step);
-	CDBG("wait_time = %d\n",wait_time);
-	CDBG("curr_lens_pos = %d\n",curr_lens_pos);
-	CDBG("sign_direction = %d\n",sign_direction);
-	CDBG("code_boundary = %d\n",code_boundary);
-	CDBG("damping_params->hw_params = %d\n",damping_params->hw_params);
-
-	if (damping_code_step ==0) {
-		CDBG("[ERROR][%s] damping_code_step = %d ---> 255\n",
-				__func__,damping_code_step);
-		damping_code_step = 255;
-	}
-	if (wait_time ==0) {
-		CDBG("[ERROR][%s] wait_time = %d ---> 4500\n",
-				__func__,damping_code_step);
-		wait_time = 4500;
-	}
-#endif
 	/* Write code based on damping_code_step in a loop */
 	for (next_lens_pos =
 		curr_lens_pos + (sign_direction * damping_code_step);
@@ -260,15 +225,12 @@
 	int16_t dest_step_pos = move_params->dest_step_pos;
 	uint16_t curr_lens_pos = 0;
 	int dir = move_params->dir;
-#ifdef CONFIG_MSM_CAMERA_DEBUG
 	int32_t num_steps = move_params->num_steps;
-#endif
-#ifdef CHECK_ACT_WRITE_COUNT
-	int count_actuator_write = 0;
-	CDBG("%s: a_ctrl->curr_region_index = %d\n",
-			__func__,a_ctrl->curr_region_index);
-#endif
-	CDBG("%s called, dir %d, num_steps %d\n",__func__,dir,num_steps);
+
+	CDBG("%s called, dir %d, num_steps %d\n",
+		__func__,
+		dir,
+		num_steps);
 
 	if (dest_step_pos == a_ctrl->curr_step_pos)
 		return rc;
@@ -288,8 +250,6 @@
 			target_step_pos = dest_step_pos;
 			target_lens_pos =
 				a_ctrl->step_position_table[target_step_pos];
-			if (curr_lens_pos == target_lens_pos)
-				return rc;
 			rc = a_ctrl->func_tbl->
 				actuator_write_focus(
 					a_ctrl,
@@ -306,17 +266,10 @@
 			}
 			curr_lens_pos = target_lens_pos;
 
-#ifdef CHECK_ACT_WRITE_COUNT
-			count_actuator_write ++;
-			CDBG("%s count_actuator_write = %d\n",__func__,count_actuator_write);
-#endif
-
 		} else {
 			target_step_pos = step_boundary;
 			target_lens_pos =
 				a_ctrl->step_position_table[target_step_pos];
-			if (curr_lens_pos == target_lens_pos)
-				return rc;
 			rc = a_ctrl->func_tbl->
 				actuator_write_focus(
 					a_ctrl,
@@ -334,18 +287,6 @@
 			curr_lens_pos = target_lens_pos;
 
 			a_ctrl->curr_region_index += sign_dir;
-#ifdef CHECK_ACT_WRITE_COUNT
-			if (a_ctrl->curr_region_index >= 2) {
-				CDBG("[ERROR][%s] a_ctrl->curr_region_index = %d ---> 1\n",__func__,a_ctrl->curr_region_index);
-				a_ctrl->curr_region_index = 1;
-			}
-			if (a_ctrl->curr_region_index < 0) {
-				CDBG("[ERROR][%s] a_ctrl->curr_region_index = %d ---> 0\n",__func__,a_ctrl->curr_region_index);
-				a_ctrl->curr_region_index = 0;
-			}
-			count_actuator_write ++;
-			CDBG("%s count_actuator_write = %d\n",__func__,count_actuator_write);
-#endif
 		}
 		a_ctrl->curr_step_pos = target_step_pos;
 	}
@@ -363,7 +304,7 @@
 	return rc;
 }
 
-static int32_t msm_actuator_init_default_step_table(struct msm_actuator_ctrl_t *a_ctrl,
+static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
 	struct msm_actuator_set_info_t *set_info)
 {
 	int16_t code_per_step = 0;
@@ -378,10 +319,8 @@
 	for (; data_size > 0; data_size--)
 		max_code_size *= 2;
 
-	if(a_ctrl->step_position_table){
-		kfree(a_ctrl->step_position_table);
-		a_ctrl->step_position_table = NULL;
-	}
+	kfree(a_ctrl->step_position_table);
+	a_ctrl->step_position_table = NULL;
 
 	/* Fill step position table */
 	a_ctrl->step_position_table =
@@ -424,202 +363,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_SEKONIX_LENS_ACT
-int32_t msm_actuator_init_step_table_use_eeprom(struct msm_actuator_ctrl_t *a_ctrl,
-	struct msm_actuator_set_info_t *set_info)
-{
-	int32_t rc = 0;
-	int16_t cur_code = 0;
-	int16_t step_index = 0;
-	uint32_t max_code_size = 1;
-	uint16_t data_size = set_info->actuator_params.data_size;
-	uint16_t act_start = 0, act_macro = 0, move_range = 0;
-
-	for (; data_size > 0; data_size--)
-		max_code_size *= 2;
-
-	if(a_ctrl->step_position_table){
-		kfree(a_ctrl->step_position_table);
-		a_ctrl->step_position_table = NULL;
-	}
-
-	CDBG("%s called\n", __func__);
-	// set act_start, act_macro
-	act_start = (uint16_t)(imx111_afcalib_data[1] << 8) |
-			imx111_afcalib_data[0];
-	act_macro = ((uint16_t)(imx111_afcalib_data[3] << 8) |
-			imx111_afcalib_data[2])+20;
-	/* Fill step position table */
-	a_ctrl->step_position_table =
-		kmalloc(sizeof(uint16_t) *
-		(set_info->af_tuning_params.total_steps + 1), GFP_KERNEL);
-
-	if (a_ctrl->step_position_table == NULL)
-		return -EFAULT;
-
-	cur_code = set_info->af_tuning_params.initial_code;
-	a_ctrl->step_position_table[step_index++] = cur_code;
-
-	// start code - by calibration data
-	if ( act_start > ACT_POSTURE_MARGIN )
-		a_ctrl->step_position_table[1] = act_start - ACT_POSTURE_MARGIN;
-	else
-		a_ctrl->step_position_table[1] = act_start ;
-
-	move_range = act_macro - a_ctrl->step_position_table[1];
-
-
-	if (move_range < ACT_MIN_MOVE_RANGE)
-		goto act_cal_fail;
-
-	for (step_index = 2;step_index < set_info->af_tuning_params.total_steps;step_index++) {
-		a_ctrl->step_position_table[step_index]
-			= ((step_index - 1) * move_range + ((set_info->af_tuning_params.total_steps - 1) >> 1))
-			/ (set_info->af_tuning_params.total_steps - 1) + a_ctrl->step_position_table[1];
-	}
-
-	for (step_index = 0; step_index < a_ctrl->total_steps; step_index++)
-		CDBG("step_position_table[%d]= %d\n",step_index,
-		a_ctrl->step_position_table[step_index]);
-	return rc;
-
-act_cal_fail:
-	pr_err("%s: calibration to default value not using eeprom data\n", __func__);
-	rc = msm_actuator_init_default_step_table(a_ctrl, set_info);
-	return rc;
-}
-
-#else
-/* add AF calibration parameters */
-int32_t msm_actuator_i2c_read_b_eeprom(struct msm_camera_i2c_client *dev_client,
-            unsigned char saddr, unsigned char *rxdata)
-{
-	int32_t rc = 0;
-	struct i2c_msg msgs[] = {
-		{
-			.addr  = saddr << 1,
-			.flags = 0,
-			.len   = 1,
-			.buf   = rxdata,
-		},
-		{
-			.addr  = saddr << 1,
-			.flags = I2C_M_RD,
-			.len   = 1,
-			.buf   = rxdata,
-		},
-	};
-
-	rc = i2c_transfer(dev_client->client->adapter, msgs, 2);
-	if (rc < 0)
-		CDBG("msm_actuator_i2c_read_b_eeprom failed 0x%x\n", saddr);
-	return rc;
-}
-
-static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
-            struct msm_actuator_set_info_t *set_info)
-{
-	int32_t rc = 0;
-	int16_t cur_code = 0;
-	int16_t step_index = 0;
-	uint32_t max_code_size = 1;
-	uint16_t data_size = set_info->actuator_params.data_size;
-
-	uint16_t act_start = 0, act_macro = 0, move_range = 0;
-	unsigned char buf;
-
-	CDBG("%s called\n", __func__);
-
-	// read from eeprom
-	buf = ACTUATOR_START_ADDR;
-	rc = msm_actuator_i2c_read_b_eeprom(&a_ctrl->i2c_client,
-		ACTUATOR_EEPROM_SADDR, &buf);
-	if (rc < 0)
-		goto act_cal_fail;
-
-	act_start = (buf << 8) & 0xFF00;
-
-	buf = ACTUATOR_START_ADDR + 1;
-	rc = msm_actuator_i2c_read_b_eeprom(&a_ctrl->i2c_client,
-		ACTUATOR_EEPROM_SADDR, &buf);
-
-	if (rc < 0)
-		goto act_cal_fail;
-
-	act_start |= buf & 0xFF;
-	CDBG("%s: act_start = 0x%4x\n", __func__, act_start);
-
-	buf = ACTUATOR_MACRO_ADDR;
-	rc = msm_actuator_i2c_read_b_eeprom(&a_ctrl->i2c_client,
-		ACTUATOR_EEPROM_SADDR, &buf);
-
-	if (rc < 0)
-		goto act_cal_fail;
-
-	act_macro = (buf << 8) & 0xFF00;
-
-	buf = ACTUATOR_MACRO_ADDR + 1;
-	rc = msm_actuator_i2c_read_b_eeprom(&a_ctrl->i2c_client,
-		ACTUATOR_EEPROM_SADDR, &buf);
-
-	if (rc < 0)
-		goto act_cal_fail;
-
-	act_macro |= buf & 0xFF;
-	CDBG("%s: act_macro = 0x%4x\n", __func__, act_macro);
-
-
-	for (; data_size > 0; data_size--)
-		max_code_size *= 2;
-
-	if(a_ctrl->step_position_table){
-		kfree(a_ctrl->step_position_table);
-		a_ctrl->step_position_table = NULL;
-	}
-
-	/* Fill step position table */
-	a_ctrl->step_position_table =
-		kmalloc(sizeof(uint16_t) *
-		(set_info->af_tuning_params.total_steps + 1), GFP_KERNEL);
-
-	if (a_ctrl->step_position_table == NULL)
-		return -EFAULT;
-
-	//intial code
-	cur_code = set_info->af_tuning_params.initial_code;
-	a_ctrl->step_position_table[0] = a_ctrl->initial_code;
-
-	// start code - by calibration data
-	if (act_start > ACTUATOR_MARGIN)
-		a_ctrl->step_position_table[1] = act_start - ACTUATOR_MARGIN;
-	else
-		a_ctrl->step_position_table[1] = act_start;
-
-	move_range = act_macro - a_ctrl->step_position_table[1];
-	CDBG("%s: move_range = %d\n", __func__, move_range);
-
-	if (move_range < ACTUATOR_MIN_MOVE_RANGE)
-		goto act_cal_fail;
-
-	for (step_index = 2;step_index < set_info->af_tuning_params.total_steps;step_index++) {
-		a_ctrl->step_position_table[step_index]
-			= ((step_index - 1) * move_range + ((set_info->af_tuning_params.total_steps - 1) >> 1))
-			/ (set_info->af_tuning_params.total_steps - 1) + a_ctrl->step_position_table[1];
-	}
-
-	a_ctrl->curr_step_pos = 0;
-	a_ctrl->curr_region_index = 0;
-
-	return rc;
-
-act_cal_fail:
-	pr_err("%s:  act_cal_fail, call default_step_table\n", __func__);
-	rc = msm_actuator_init_default_step_table(a_ctrl, set_info);
-	return rc;
-}
-
-#endif
-
 static int32_t msm_actuator_set_default_focus(
 	struct msm_actuator_ctrl_t *a_ctrl,
 	struct msm_actuator_move_params_t *move_params)
@@ -627,28 +370,14 @@
 	int32_t rc = 0;
 	CDBG("%s called\n", __func__);
 
-	if (a_ctrl->curr_step_pos != 0) {
+	if (a_ctrl->curr_step_pos != 0)
 		rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl, move_params);
-	}
-
 	return rc;
 }
 
 static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
 {
 	int32_t rc = 0;
-#ifdef CONFIG_SEKONIX_LENS_ACT
-	int cur_pos = a_ctrl->curr_step_pos;
-	struct msm_actuator_move_params_t *move_params = NULL;
-	if(cur_pos > ACT_STOP_POS) {
-		move_params.sign_dir = MOVE_FAR;
-		move_params.dest_step_pos = ACT_STOP_POS;
-		rc = a_ctrl->func_tbl->actuator_move_focus(
-				a_ctrl, &move_params);
-		msleep(300);
-	}
-#endif
-
 	if (a_ctrl->vcm_enable) {
 		rc = gpio_direction_output(a_ctrl->vcm_pwd, 0);
 		if (!rc)
@@ -719,7 +448,6 @@
 		a_ctrl->reg_tbl_size *
 		sizeof(struct msm_actuator_reg_params_t))) {
 		kfree(a_ctrl->i2c_reg_tbl);
-		a_ctrl->i2c_reg_tbl = NULL;
 		return -EFAULT;
 	}
 
@@ -730,7 +458,6 @@
 				GFP_KERNEL);
 			if (init_settings == NULL) {
 				kfree(a_ctrl->i2c_reg_tbl);
-				a_ctrl->i2c_reg_tbl = NULL;
 				pr_err("%s Error allocating memory for init_settings\n",
 					__func__);
 				return -EFAULT;
@@ -741,7 +468,6 @@
 				sizeof(struct reg_settings_t))) {
 				kfree(init_settings);
 				kfree(a_ctrl->i2c_reg_tbl);
-				a_ctrl->i2c_reg_tbl = NULL;
 				pr_err("%s Error copying init_settings\n",
 					__func__);
 				return -EFAULT;
@@ -753,7 +479,6 @@
 			kfree(init_settings);
 			if (rc < 0) {
 				kfree(a_ctrl->i2c_reg_tbl);
-				a_ctrl->i2c_reg_tbl = NULL;
 				pr_err("%s Error actuator_init_focus\n",
 					__func__);
 				return -EFAULT;
@@ -940,16 +665,12 @@
 static struct msm_actuator msm_vcm_actuator_table = {
 	.act_type = ACTUATOR_VCM,
 	.func_tbl = {
-#ifdef CONFIG_SEKONIX_LENS_ACT
-	.actuator_init_step_table = msm_actuator_init_step_table_use_eeprom,
-#else
-	.actuator_init_step_table = msm_actuator_init_step_table,
-#endif
-	.actuator_move_focus = msm_actuator_move_focus,
-	.actuator_write_focus = msm_actuator_write_focus,
-	.actuator_set_default_focus = msm_actuator_set_default_focus,
-	.actuator_init_focus = msm_actuator_init_focus,
-	.actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
+		.actuator_init_step_table = msm_actuator_init_step_table,
+		.actuator_move_focus = msm_actuator_move_focus,
+		.actuator_write_focus = msm_actuator_write_focus,
+		.actuator_set_default_focus = msm_actuator_set_default_focus,
+		.actuator_init_focus = msm_actuator_init_focus,
+		.actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
 	},
 };
 
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index e9442f5..82157e8 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -91,14 +91,7 @@
 	uint16_t i2c_tbl_index;
 };
 
-#ifdef CONFIG_MSM_ACTUATOR
 struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd);
-#else
-static inline struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd)
-{
-	return NULL;
-}
-#endif
 
 #define VIDIOC_MSM_ACTUATOR_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 11, void __user *)
diff --git a/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h b/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
index 68c78d5..2d489b9 100644
--- a/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
+++ b/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
@@ -26,6 +26,7 @@
 #define CCI_I2C_M0_SDA_CTL_2_ADDR                                   0x0000010c
 #define CCI_I2C_M0_READ_DATA_ADDR                                   0x00000118
 #define CCI_I2C_M0_MISC_CTL_ADDR                                    0x00000110
+#define CCI_I2C_M0_READ_BUF_LEVEL_ADDR                              0x0000011C
 #define CCI_HALT_REQ_ADDR                                           0x00000034
 #define CCI_M0_HALT_REQ_RMSK                                               0x1
 #define CCI_M1_HALT_REQ_RMSK                                              0x01
diff --git a/drivers/media/video/msm/cci/msm_cci.c b/drivers/media/video/msm/cci/msm_cci.c
index ad3cc6a..09dfd7c 100644
--- a/drivers/media/video/msm/cci/msm_cci.c
+++ b/drivers/media/video/msm/cci/msm_cci.c
@@ -24,11 +24,10 @@
 #include "msm_cam_cci_hwreg.h"
 
 #define V4L2_IDENT_CCI 50005
-#define CCI_I2C_QUEUE_0_SIZE 2
+#define CCI_I2C_QUEUE_0_SIZE 64
 #define CCI_I2C_QUEUE_1_SIZE 16
 
-#undef CDBG
-#define CDBG pr_debug
+#define CCI_TIMEOUT msecs_to_jiffies(100)
 
 static void msm_cci_set_clk_param(struct cci_device *cci_dev)
 {
@@ -127,8 +126,9 @@
 		msm_camera_io_w(reg_val, cci_dev->base + CCI_QUEUE_START_ADDR);
 		CDBG("%s line %d wait_for_completion_interruptible\n",
 			__func__, __LINE__);
-		wait_for_completion_interruptible(&cci_dev->
-			cci_master_info[master].reset_complete);
+		wait_for_completion_interruptible_timeout(&cci_dev->
+			cci_master_info[master].reset_complete, CCI_TIMEOUT);
+
 		rc = cci_dev->cci_master_info[master].status;
 		if (rc < 0)
 			pr_err("%s failed rc %d\n", __func__, rc);
@@ -221,7 +221,7 @@
 {
 	uint32_t rc = 0;
 	uint32_t val = 0;
-	int32_t read_bytes = 0;
+	int32_t read_words = 0, exp_words = 0;
 	int32_t index = 0, first_byte = 0;
 	uint32_t i = 0;
 	enum cci_i2c_master_t master;
@@ -234,6 +234,9 @@
 	read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
 	mutex_lock(&cci_dev->cci_master_info[master].mutex);
 	CDBG("%s master %d, queue %d\n", __func__, master, queue);
+	CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+		c_ctrl->cci_info->id_map);
 	val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
 		c_ctrl->cci_info->retries << 16 |
 		c_ctrl->cci_info->id_map << 18;
@@ -285,11 +288,18 @@
 
 	val = 1 << ((master * 2) + queue);
 	msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR);
+	wait_for_completion_interruptible_timeout(&cci_dev->
+		cci_master_info[master].reset_complete, CCI_TIMEOUT);
 
-	wait_for_completion_interruptible(&cci_dev->
-		cci_master_info[master].reset_complete);
-
-	read_bytes = (read_cfg->num_byte / 4) + 1;
+	read_words = msm_camera_io_r(cci_dev->base +
+		CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
+	exp_words = ((read_cfg->num_byte / 4) + 1);
+	if (read_words != exp_words) {
+		pr_err("%s:%d read_words = %d, exp words = %d\n", __func__,
+			__LINE__, read_words, exp_words);
+		memset(read_cfg->data, 0, read_cfg->num_byte);
+		goto ERROR;
+	}
 	index = 0;
 	CDBG("%s index %d num_type %d\n", __func__, index,
 		read_cfg->num_byte);
@@ -311,7 +321,7 @@
 				index++;
 			}
 		}
-	} while (--read_bytes > 0);
+	} while (--read_words > 0);
 ERROR:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 	return rc;
@@ -328,6 +338,9 @@
 	cci_dev = v4l2_get_subdevdata(sd);
 	master = c_ctrl->cci_info->cci_i2c_master;
 	CDBG("%s master %d, queue %d\n", __func__, master, queue);
+	CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+		c_ctrl->cci_info->id_map);
 	mutex_lock(&cci_dev->cci_master_info[master].mutex);
 	val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
 		c_ctrl->cci_info->retries << 16 |
@@ -366,7 +379,7 @@
 
 	val = msm_camera_io_r(cci_dev->base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR +
 		master * 0x200 + queue * 0x100);
-	CDBG("%s line %d size of queue %d\n", __func__, __LINE__, val);
+	CDBG("%s:%d cur word count %d\n", __func__, __LINE__, val);
 	CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR\n", __func__, __LINE__);
 	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR +
 		master * 0x200 + queue * 0x100);
@@ -378,8 +391,9 @@
 
 	CDBG("%s line %d wait_for_completion_interruptible\n",
 		__func__, __LINE__);
-	wait_for_completion_interruptible(&cci_dev->
-		cci_master_info[master].reset_complete);
+	wait_for_completion_interruptible_timeout(&cci_dev->
+		cci_master_info[master].reset_complete, CCI_TIMEOUT);
+
 ERROR:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 	return rc;
@@ -395,7 +409,10 @@
 }
 
 static struct msm_cam_clk_info cci_clk_info[] = {
-	{"cci_clk_src", 19200000},
+	{"camss_top_ahb_clk", -1},
+	{"cci_src_clk", 19200000},
+	{"cci_ahb_clk", -1},
+	{"cci_clk", -1},
 };
 
 static int32_t msm_cci_init(struct v4l2_subdev *sd)
@@ -411,7 +428,7 @@
 	rc = msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
 		cci_dev->cci_clk, ARRAY_SIZE(cci_clk_info), 1);
 	if (rc < 0) {
-		CDBG("%s: regulator enable failed\n", __func__);
+		CDBG("%s: clk enable failed\n", __func__);
 		goto clk_enable_failed;
 	}
 
@@ -421,8 +438,9 @@
 	cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
 	msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_RESET_CMD_ADDR);
 	msm_camera_io_w(0x1, cci_dev->base + CCI_RESET_CMD_ADDR);
-	wait_for_completion_interruptible(&cci_dev->cci_master_info[MASTER_0].
-		reset_complete);
+	wait_for_completion_interruptible_timeout(
+		&cci_dev->cci_master_info[MASTER_0].reset_complete,
+		CCI_TIMEOUT);
 	msm_cci_set_clk_param(cci_dev);
 	msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_IRQ_MASK_0_ADDR);
 	msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
@@ -535,6 +553,12 @@
 		cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE;
 		msm_camera_io_w(CCI_M1_RESET_RMSK,
 			cci_dev->base + CCI_RESET_CMD_ADDR);
+	} else {
+		pr_err("%s unhandled irq 0x%x\n", __func__, irq);
+		cci_dev->cci_master_info[MASTER_0].status = 0;
+		complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+		cci_dev->cci_master_info[MASTER_1].status = 0;
+		complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
 	}
 	return IRQ_HANDLED;
 }
@@ -686,14 +710,11 @@
 		goto cci_release_mem;
 	}
 
-	CDBG("%s line %d cci irq start %d end %d\n", __func__,
-		__LINE__,
-		new_cci_dev->irq->start,
-		new_cci_dev->irq->end);
-
 	new_cci_dev->pdev = pdev;
 	msm_cci_initialize_cci_params(new_cci_dev);
-
+	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (rc)
+		pr_err("%s: failed to add child nodes, rc=%d\n", __func__, rc);
 	CDBG("%s line %d\n", __func__, __LINE__);
 	return 0;
 
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 547eb13..5aaaff7 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,5 +1,5 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm
+ccflags-y += -Idrivers/media/video/msm -Idrivers/media/video/msm/server
 ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
   ccflags-y += -Idrivers/media/video/msm/csi/include/csi2.0
 else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
index c79748c..4682f8f 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
@@ -46,6 +46,7 @@
 #define CSID_RST_DONE_IRQ_BITSHIFT                  11
 #define CSID_RST_STB_ALL                            0x7FFF
 #define CSID_DL_INPUT_SEL_SHIFT                     0x2
-#define CSID_PHY_SEL_SHIFT                          0x17
+#define CSID_PHY_SEL_SHIFT                          17
+#define CSID_VERSION                                0x02000011
 
 #endif
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
index 93d1fc4..2e83101 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
@@ -28,6 +28,7 @@
 #define MIPI_CSIPHY_LNCK_MISC1_ADDR              0x128
 #define MIPI_CSIPHY_GLBL_RESET_ADDR              0x140
 #define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR            0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR            0x164
 #define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR       0x180
 #define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR         0x1A0
 #define MIPI_CSIPHY_INTERRUPT_MASK_VAL           0x6F
@@ -37,5 +38,6 @@
 #define MIPI_CSIPHY_MODE_CONFIG_SHIFT            0x4
 #define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR        0x1E0
 #define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR           0x1E8
+#define CSIPHY_VERSION                           0x0
 
 #endif
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
index c678ea2..d37d67e 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
@@ -64,16 +64,25 @@
 #define MISC_LOGIC_RST_STB           1
 #define STROBED_RST_EN               0
 
+#define ISPIF_RST_CMD_MASK           0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK         0xFC0F1FF9
+
 #define PIX_INTF_0_OVERFLOW_IRQ      12
 #define RAW_INTF_0_OVERFLOW_IRQ      25
 #define RAW_INTF_1_OVERFLOW_IRQ      25
+#define RAW_INTF_2_OVERFLOW_IRQ      12
 #define RESET_DONE_IRQ               27
 
-#define ISPIF_IRQ_STATUS_MASK          0xA493249
-#define ISPIF_IRQ_1_STATUS_MASK        0xA493249
-#define ISPIF_IRQ_STATUS_RDI_SOF_MASK  0x492000
-#define ISPIF_IRQ_STATUS_PIX_SOF_MASK  0x249
-#define ISPIF_IRQ_STATUS_SOF_MASK      0x492249
+#define ISPIF_IRQ_STATUS_MASK        0x0A493249
+#define ISPIF_IRQ_STATUS_1_MASK      0x02493249
+#define ISPIF_IRQ_STATUS_2_MASK      0x00001249
+
+#define ISPIF_IRQ_STATUS_PIX_SOF_MASK	0x249
+#define ISPIF_IRQ_STATUS_RDI0_SOF_MASK	0x492000
+#define ISPIF_IRQ_STATUS_RDI1_SOF_MASK	0x492000
+#define ISPIF_IRQ_STATUS_RDI2_SOF_MASK	0x249
+
+#define ISPIF_IRQ_STATUS_SOF_MASK	0x492249
 #define ISPIF_IRQ_GLOBAL_CLEAR_CMD     0x1
 
 #endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
index 27d5a06..11a04d5 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
@@ -46,6 +46,7 @@
 #define CSID_RST_DONE_IRQ_BITSHIFT                  11
 #define CSID_RST_STB_ALL                            0x7FFF
 #define CSID_DL_INPUT_SEL_SHIFT                     0x4
-#define CSID_PHY_SEL_SHIFT                          0x17
+#define CSID_PHY_SEL_SHIFT                          17
+#define CSID_VERSION                                0x30000000
 
 #endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
index 79791bd..4e640e3 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
@@ -27,15 +27,17 @@
 #define MIPI_CSIPHY_LNCK_MISC1_ADDR              0x128
 #define MIPI_CSIPHY_GLBL_RESET_ADDR              0x140
 #define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR            0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR            0x164
 #define MIPI_CSIPHY_HW_VERSION_ADDR              0x188
 #define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR       0x18C
 #define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR         0x1AC
 #define MIPI_CSIPHY_INTERRUPT_MASK_VAL           0x3F
-#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR          0x1B0
+#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR          0x1AC
 #define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR        0x1CC
-#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR         0x1D0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR         0x1CC
 #define MIPI_CSIPHY_MODE_CONFIG_SHIFT            0x4
 #define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR        0x1EC
 #define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR           0x1F4
+#define CSIPHY_VERSION                           0x10
 
 #endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
index 4b17538..7c09c4f 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
@@ -78,17 +78,25 @@
 #define MISC_LOGIC_RST_STB           1
 #define STROBED_RST_EN               0
 
+#define ISPIF_RST_CMD_MASK           0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK         0xFC0F1FF9
+
 #define PIX_INTF_0_OVERFLOW_IRQ      12
 #define RAW_INTF_0_OVERFLOW_IRQ      25
 #define RAW_INTF_1_OVERFLOW_IRQ      25
+#define RAW_INTF_2_OVERFLOW_IRQ      12
 #define RESET_DONE_IRQ               27
 
-#define ISPIF_IRQ_STATUS_MASK          0xA493249
-#define ISPIF_IRQ_1_STATUS_MASK        0xA493249
-#define ISPIF_IRQ_STATUS_RDI_SOF_MASK  0x492000
-#define ISPIF_IRQ_STATUS_PIX_SOF_MASK  0x249
-#define ISPIF_IRQ_STATUS_SOF_MASK      0x492249
-#define ISPIF_IRQ_GLOBAL_CLEAR_CMD     0x1
+#define ISPIF_IRQ_STATUS_MASK        0x0A493249
+#define ISPIF_IRQ_STATUS_1_MASK      0x02493249
+#define ISPIF_IRQ_STATUS_2_MASK      0x00001249
 
+#define ISPIF_IRQ_STATUS_PIX_SOF_MASK	0x249
+#define ISPIF_IRQ_STATUS_RDI0_SOF_MASK	0x492000
+#define ISPIF_IRQ_STATUS_RDI1_SOF_MASK	0x492000
+#define ISPIF_IRQ_STATUS_RDI2_SOF_MASK	0x249
+
+#define ISPIF_IRQ_STATUS_SOF_MASK	0x492249
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD     0x1
 
 #endif
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index bcb7bb3..c34d9f7 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -137,18 +137,17 @@
 #define MIPI_PWR_CNTL_EN	0x07
 #define MIPI_PWR_CNTL_DIS	0x0
 
-static int msm_csic_config(struct csic_cfg_params *cfg_params)
+static int msm_csic_config(struct v4l2_subdev *sd,
+	struct msm_camera_csi_params *csic_params)
 {
 	int rc = 0;
 	uint32_t val = 0;
 	struct csic_device *csic_dev;
-	struct msm_camera_csi_params *csic_params;
 	void __iomem *csicbase;
 	int i;
 
-	csic_dev = v4l2_get_subdevdata(cfg_params->subdev);
+	csic_dev = v4l2_get_subdevdata(sd);
 	csicbase = csic_dev->base;
-	csic_params = cfg_params->parms;
 
 	/* Enable error correction for DATA lane. Applies to all data lanes */
 	msm_camera_io_w(0x4, csicbase + MIPI_PHY_CONTROL);
@@ -259,7 +258,7 @@
 	{"csi_pclk", -1},
 };
 
-static int msm_csic_init(struct v4l2_subdev *sd, uint32_t *csic_version)
+static int msm_csic_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
 	struct csic_device *csic_dev;
@@ -355,17 +354,40 @@
 	return 0;
 }
 
+static long msm_csic_cmd(struct v4l2_subdev *sd, void *arg)
+{
+	long rc = 0;
+	struct csic_cfg_data cdata;
+	struct msm_camera_csi_params csic_params;
+	if (copy_from_user(&cdata,
+		(void *)arg,
+		sizeof(struct csic_cfg_data)))
+		return -EFAULT;
+	CDBG("%s cfgtype = %d\n", __func__, cdata.cfgtype);
+	switch (cdata.cfgtype) {
+	case CSIC_INIT:
+		rc = msm_csic_init(sd);
+		break;
+	case CSIC_CFG:
+		if (copy_from_user(&csic_params,
+			(void *)cdata.csic_params,
+			sizeof(struct msm_camera_csi_params)))
+			return -EFAULT;
+		rc = msm_csic_config(sd, &csic_params);
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
 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);
+		return msm_csic_cmd(sd, arg);
 	case VIDIOC_MSM_CSIC_RELEASE:
 		return msm_csic_release(sd);
 	default:
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/video/msm/csi/msm_csic.h
index 177e9d1..c8f1f99 100644
--- a/drivers/media/video/msm/csi/msm_csic.h
+++ b/drivers/media/video/msm/csi/msm_csic.h
@@ -33,19 +33,10 @@
 	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*)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_data*)
 
 #define VIDIOC_MSM_CSIC_RELEASE \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
 
 #endif
-
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 6ee87b7..37aa54e 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -11,8 +11,6 @@
  */
 
 #include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <mach/board.h>
@@ -21,11 +19,17 @@
 #include "msm_csid.h"
 #include "msm_csid_hwreg.h"
 #include "msm.h"
+#include "msm_cam_server.h"
 
 #define V4L2_IDENT_CSID                            50002
+#define CSID_VERSION_V2                      0x02000011
+#define CSID_VERSION_V3                      0x30000000
 
 #define DBG_CSID 0
 
+#define TRUE   1
+#define FALSE  0
+
 static int msm_csid_cid_lut(
 	struct msm_camera_csid_lut_params *csid_lut_params,
 	void __iomem *csidbase)
@@ -33,7 +37,17 @@
 	int rc = 0, i = 0;
 	uint32_t val = 0;
 
+	if (!csid_lut_params) {
+		pr_err("%s:%d csid_lut_params NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
 	for (i = 0; i < csid_lut_params->num_cid && i < 16; i++) {
+		CDBG("%s lut params num_cid = %d, cid = %d, dt = %x, df = %d\n",
+			__func__,
+			csid_lut_params->num_cid,
+			csid_lut_params->vc_cfg[i].cid,
+			csid_lut_params->vc_cfg[i].dt,
+			csid_lut_params->vc_cfg[i].decode_format);
 		if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
 			csid_lut_params->vc_cfg[i].dt > 0x37) {
 			CDBG("%s: unsupported data type 0x%x\n",
@@ -47,6 +61,7 @@
 			((csid_lut_params->vc_cfg[i].cid % 4) * 8));
 		msm_camera_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
 			(csid_lut_params->vc_cfg[i].cid >> 2) * 4);
+
 		val = (csid_lut_params->vc_cfg[i].decode_format << 4) | 0x3;
 		msm_camera_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
 			(csid_lut_params->vc_cfg[i].cid * 4));
@@ -68,19 +83,24 @@
 	struct msm_camera_csid_params *csid_params) {}
 #endif
 
-static int msm_csid_config(struct csid_cfg_params *cfg_params)
+static int msm_csid_config(struct csid_device *csid_dev,
+	struct msm_camera_csid_params *csid_params)
 {
 	int rc = 0;
 	uint32_t val = 0;
-	struct csid_device *csid_dev;
-	struct msm_camera_csid_params *csid_params;
 	void __iomem *csidbase;
-	csid_dev = v4l2_get_subdevdata(cfg_params->subdev);
 	csidbase = csid_dev->base;
-	if (csidbase == NULL)
-		return -ENOMEM;
-	csid_params = cfg_params->parms;
+	if (!csidbase || !csid_params) {
+		pr_err("%s:%d csidbase %p, csid params %p\n", __func__,
+			__LINE__, csidbase, csid_params);
+		return -EINVAL;
+	}
 
+	CDBG("%s csid_params, lane_cnt = %d, lane_assign = %x, phy sel = %d\n",
+		__func__,
+		csid_params->lane_cnt,
+		csid_params->lane_assign,
+		csid_params->phy_sel);
 	val = csid_params->lane_cnt - 1;
 	val |= csid_params->lane_assign << CSID_DL_INPUT_SEL_SHIFT;
 	if (csid_dev->hw_version < 0x30000000) {
@@ -98,7 +118,6 @@
 		return rc;
 
 	msm_csid_set_debug_reg(csidbase, csid_params);
-
 	return rc;
 }
 
@@ -106,6 +125,10 @@
 {
 	uint32_t irq;
 	struct csid_device *csid_dev = data;
+	if (!csid_dev||!csid_dev->base) {
+		pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+		return IRQ_HANDLED;
+	}
 	irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
 	CDBG("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
 		 __func__, csid_dev->pdev->id, irq);
@@ -115,6 +138,16 @@
 	return IRQ_HANDLED;
 }
 
+int msm_csid_irq_routine(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+	struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+	irqreturn_t ret;
+	CDBG("%s E\n", __func__);
+	ret = msm_csid_irq(csid_dev->irq->start, csid_dev);
+	*handled = TRUE;
+	return 0;
+}
+
 static void msm_csid_reset(struct csid_device *csid_dev)
 {
 	msm_camera_io_w(CSID_RST_STB_ALL, csid_dev->base + CSID_RST_CMD_ADDR);
@@ -131,53 +164,150 @@
 	return 0;
 }
 
-static struct msm_cam_clk_info csid_clk_info[] = {
+static struct msm_cam_clk_info csid_8960_clk_info[] = {
 	{"csi_src_clk", 177780000},
 	{"csi_clk", -1},
 	{"csi_phy_clk", -1},
 	{"csi_pclk", -1},
 };
 
-static struct camera_vreg_t csid_vreg_info[] = {
+static struct msm_cam_clk_info csid0_8974_clk_info[] = {
+	{"csi0_ahb_clk", -1},
+	{"csi0_src_clk", 200000000},
+	{"csi0_clk", -1},
+	{"csi0_phy_clk", -1},
+	{"csi0_pix_clk", -1},
+	{"csi0_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_info csid1_8974_clk_info[] = {
+	{"csi1_ahb_clk", -1},
+	{"csi1_src_clk", 200000000},
+	{"csi1_clk", -1},
+	{"csi1_phy_clk", -1},
+	{"csi1_pix_clk", -1},
+	{"csi1_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_info csid2_8974_clk_info[] = {
+	{"csi2_ahb_clk", -1},
+	{"csi2_src_clk", 200000000},
+	{"csi2_clk", -1},
+	{"csi2_phy_clk", -1},
+	{"csi2_pix_clk", -1},
+	{"csi2_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_info csid3_8974_clk_info[] = {
+	{"csi3_ahb_clk", -1},
+	{"csi3_src_clk", 200000000},
+	{"csi3_clk", -1},
+	{"csi3_phy_clk", -1},
+	{"csi3_pix_clk", -1},
+	{"csi3_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_setting csid_8974_clk_info[] = {
+	{&csid0_8974_clk_info[0], ARRAY_SIZE(csid0_8974_clk_info)},
+	{&csid1_8974_clk_info[0], ARRAY_SIZE(csid1_8974_clk_info)},
+	{&csid2_8974_clk_info[0], ARRAY_SIZE(csid2_8974_clk_info)},
+	{&csid3_8974_clk_info[0], ARRAY_SIZE(csid3_8974_clk_info)},
+};
+
+static struct camera_vreg_t csid_8960_vreg_info[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
 };
 
-static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
+static struct camera_vreg_t csid_8974_vreg_info[] = {
+	{"mipi_csi_vdd", REG_LDO, 1800000, 1800000, 12000},
+};
+
+static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
 {
 	int rc = 0;
-	struct csid_device *csid_dev;
-	csid_dev = v4l2_get_subdevdata(sd);
-	if (csid_dev == NULL) {
-		rc = -ENOMEM;
+	uint8_t core_id = 0;
+
+	if (!csid_version) {
+		pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
+		rc = -EINVAL;
+		return rc;
+	}
+
+	if (csid_dev->csid_state == CSID_POWER_UP) {
+		pr_err("%s: csid invalid state %d\n", __func__,
+			csid_dev->csid_state);
+		rc = -EINVAL;
 		return rc;
 	}
 
 	csid_dev->base = ioremap(csid_dev->mem->start,
 		resource_size(csid_dev->mem));
 	if (!csid_dev->base) {
+		pr_err("%s csid_dev->base NULL\n", __func__);
 		rc = -ENOMEM;
 		return rc;
 	}
 
-	rc = msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
-		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
-	if (rc < 0) {
-		pr_err("%s: regulator on failed\n", __func__);
-		goto vreg_config_failed;
-	}
+	if (CSID_VERSION <= CSID_VERSION_V2) {
+		rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator on failed\n", __func__);
+			goto vreg_config_failed;
+		}
 
-	rc = msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
-		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
-	if (rc < 0) {
-		pr_err("%s: regulator enable failed\n", __func__);
-		goto vreg_enable_failed;
-	}
+		rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator enable failed\n", __func__);
+			goto vreg_enable_failed;
+		}
 
-	rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
-		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
-	if (rc < 0) {
-		pr_err("%s: regulator enable failed\n", __func__);
-		goto clk_enable_failed;
+		rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+			csid_8960_clk_info, csid_dev->csid_clk,
+			ARRAY_SIZE(csid_8960_clk_info), 1);
+		if (rc < 0) {
+			pr_err("%s: clock enable failed\n", __func__);
+			goto clk_enable_failed;
+		}
+	} else if (CSID_VERSION == CSID_VERSION_V3) {
+		rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator on failed\n", __func__);
+			goto vreg_config_failed;
+		}
+
+		rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator enable failed\n", __func__);
+			goto vreg_enable_failed;
+		}
+
+		rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
+			csid_8974_clk_info[0].num_clk_info, 1);
+		if (rc < 0) {
+			pr_err("%s: clock enable failed\n", __func__);
+			goto csid0_clk_enable_failed;
+		}
+		core_id = csid_dev->pdev->id;
+		if (core_id) {
+			rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+				csid_8974_clk_info[core_id].clk_info,
+				csid_dev->csid_clk,
+				csid_8974_clk_info[core_id].num_clk_info, 1);
+			if (rc < 0) {
+				pr_err("%s: clock enable failed\n",
+					__func__);
+				goto clk_enable_failed;
+			}
+		}
 	}
 
 	csid_dev->hw_version =
@@ -186,68 +316,178 @@
 
 	init_completion(&csid_dev->reset_complete);
 
-	rc = request_irq(csid_dev->irq->start, msm_csid_irq,
-		IRQF_TRIGGER_RISING, "csid", csid_dev);
+	enable_irq(csid_dev->irq->start);
 
 	msm_csid_reset(csid_dev);
+	csid_dev->csid_state = CSID_POWER_UP;
 	return rc;
 
 clk_enable_failed:
-	msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
-		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+	if (CSID_VERSION == CSID_VERSION_V3) {
+		msm_cam_clk_enable(&csid_dev->pdev->dev,
+			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
+			csid_8974_clk_info[0].num_clk_info, 0);
+	}
+csid0_clk_enable_failed:
+	if (CSID_VERSION <= CSID_VERSION_V2) {
+		msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	} else if (CSID_VERSION == CSID_VERSION_V3) {
+		msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	}
 vreg_enable_failed:
-	msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
-		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+	if (CSID_VERSION <= CSID_VERSION_V2) {
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	} else if (CSID_VERSION == CSID_VERSION_V3) {
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	}
 vreg_config_failed:
 	iounmap(csid_dev->base);
 	csid_dev->base = NULL;
 	return rc;
 }
 
-static int msm_csid_release(struct v4l2_subdev *sd)
+static int msm_csid_release(struct csid_device *csid_dev)
 {
 	uint32_t irq;
-	struct csid_device *csid_dev;
-	csid_dev = v4l2_get_subdevdata(sd);
+	uint8_t core_id = 0;
+
+	if (csid_dev->csid_state != CSID_POWER_UP) {
+		pr_err("%s: csid invalid state %d\n", __func__,
+			csid_dev->csid_state);
+		return -EINVAL;
+	}
 
 	irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
 	msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
 	msm_camera_io_w(0, csid_dev->base + CSID_IRQ_MASK_ADDR);
 
-	free_irq(csid_dev->irq->start, csid_dev);
+	disable_irq(csid_dev->irq->start);
 
-	msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
-		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+	if (csid_dev->hw_version <= CSID_VERSION_V2) {
+		msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8960_clk_info,
+			csid_dev->csid_clk, ARRAY_SIZE(csid_8960_clk_info), 0);
 
-	msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
-		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+		msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
 
-	msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
-		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	} else if (csid_dev->hw_version == CSID_VERSION_V3) {
+		core_id = csid_dev->pdev->id;
+		if (core_id)
+			msm_cam_clk_enable(&csid_dev->pdev->dev,
+				csid_8974_clk_info[core_id].clk_info,
+				csid_dev->csid_clk,
+				csid_8974_clk_info[core_id].num_clk_info, 0);
+
+		msm_cam_clk_enable(&csid_dev->pdev->dev,
+			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
+			csid_8974_clk_info[0].num_clk_info, 0);
+
+		msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	}
 
 	iounmap(csid_dev->base);
 	csid_dev->base = NULL;
+	csid_dev->csid_state = CSID_POWER_DOWN;
 	return 0;
 }
 
+static long msm_csid_cmd(struct csid_device *csid_dev, void *arg)
+{
+	int rc = 0;
+	struct csid_cfg_data cdata;
+
+	if (!csid_dev) {
+		pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&cdata,
+		(void *)arg,
+		sizeof(struct csid_cfg_data))) {
+		pr_err("%s: %d failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+	CDBG("%s cfgtype = %d\n", __func__, cdata.cfgtype);
+	switch (cdata.cfgtype) {
+	case CSID_INIT:
+		rc = msm_csid_init(csid_dev, &cdata.cfg.csid_version);
+		if (copy_to_user((void *)arg,
+			&cdata,
+			sizeof(struct csid_cfg_data))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+		}
+		break;
+	case CSID_CFG: {
+		struct msm_camera_csid_params csid_params;
+		struct msm_camera_csid_vc_cfg *vc_cfg = NULL;
+		if (copy_from_user(&csid_params,
+			(void *)cdata.cfg.csid_params,
+			sizeof(struct msm_camera_csid_params))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		vc_cfg = kzalloc(csid_params.lut_params.num_cid *
+			sizeof(struct msm_camera_csid_vc_cfg),
+			GFP_KERNEL);
+		if (!vc_cfg) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(vc_cfg,
+			(void *)csid_params.lut_params.vc_cfg,
+			(csid_params.lut_params.num_cid *
+			sizeof(struct msm_camera_csid_vc_cfg)))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			kfree(vc_cfg);
+			rc = -EFAULT;
+			break;
+		}
+		csid_params.lut_params.vc_cfg = vc_cfg;
+		rc = msm_csid_config(csid_dev, &csid_params);
+		kfree(vc_cfg);
+		break;
+	}
+	default:
+		pr_err("%s: %d failed\n", __func__, __LINE__);
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
 static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int cmd, void *arg)
 {
 	int rc = -ENOIOCTLCMD;
-	struct csid_cfg_params cfg_params;
 	struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
 	mutex_lock(&csid_dev->mutex);
 	switch (cmd) {
 	case VIDIOC_MSM_CSID_CFG:
-		cfg_params.subdev = sd;
-		cfg_params.parms = arg;
-		rc = msm_csid_config((struct csid_cfg_params *)&cfg_params);
-		break;
-	case VIDIOC_MSM_CSID_INIT:
-		rc = msm_csid_init(sd, (uint32_t *)arg);
+		rc = msm_csid_cmd(csid_dev, arg);
 		break;
 	case VIDIOC_MSM_CSID_RELEASE:
-		rc = msm_csid_release(sd);
+		rc = msm_csid_release(csid_dev);
 		break;
 	default:
 		pr_err("%s: command not found\n", __func__);
@@ -261,6 +501,7 @@
 static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
 	.g_chip_ident = &msm_csid_subdev_g_chip_ident,
 	.ioctl = &msm_csid_subdev_ioctl,
+	.interrupt_service_routine = msm_csid_irq_routine,
 };
 
 static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
@@ -271,9 +512,10 @@
 {
 	struct csid_device *new_csid_dev;
 	struct msm_cam_subdev_info sd_info;
+	struct intr_table_entry irq_req;
 
 	int rc = 0;
-	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	CDBG("%s:%d called\n", __func__, __LINE__);
 	new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
 	if (!new_csid_dev) {
 		pr_err("%s: no enough memory\n", __func__);
@@ -293,6 +535,7 @@
 		of_property_read_u32((&pdev->dev)->of_node,
 			"cell-index", &pdev->id);
 
+	CDBG("%s device id %d\n", __func__, pdev->id);
 	new_csid_dev->mem = platform_get_resource_byname(pdev,
 					IORESOURCE_MEM, "csid");
 	if (!new_csid_dev->mem) {
@@ -327,12 +570,51 @@
 	new_csid_dev->subdev.entity.name = pdev->name;
 	new_csid_dev->subdev.entity.revision =
 		new_csid_dev->subdev.devnode->num;
+
+	/* Request for this device irq from the camera server. If the
+	 * IRQ Router is present on this target, the interrupt will be
+	 * handled by the camera server and the interrupt service
+	 * routine called. If the request_irq call returns ENXIO, then
+	 * the IRQ Router hardware is not present on this target. We
+	 * have to request for the irq ourselves and register the
+	 * appropriate interrupt handler. */
+	irq_req.cam_hw_idx       = MSM_CAM_HW_CSI0 + pdev->id;
+	irq_req.dev_name         = "csid";
+	irq_req.irq_idx          = CAMERA_SS_IRQ_2 + pdev->id;
+	irq_req.irq_num          = new_csid_dev->irq->start;
+	irq_req.is_composite     = 0;
+	irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+	irq_req.num_hwcore       = 1;
+	irq_req.subdev_list[0]   = &new_csid_dev->subdev;
+	irq_req.data             = (void *)new_csid_dev;
+	rc = msm_cam_server_request_irq(&irq_req);
+	if (rc == -ENXIO) {
+		/* IRQ Router hardware is not present on this hardware.
+		 * Request for the IRQ and register the interrupt handler. */
+		rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
+			IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+		if (rc < 0) {
+			release_mem_region(new_csid_dev->mem->start,
+				resource_size(new_csid_dev->mem));
+			pr_err("%s: irq request fail\n", __func__);
+			rc = -EBUSY;
+			goto csid_no_resource;
+		}
+		disable_irq(new_csid_dev->irq->start);
+	} else if (rc < 0) {
+		release_mem_region(new_csid_dev->mem->start,
+			resource_size(new_csid_dev->mem));
+		pr_err("%s Error registering irq ", __func__);
+		goto csid_no_resource;
+	}
+
+	new_csid_dev->csid_state = CSID_POWER_DOWN;
 	return 0;
 
 csid_no_resource:
 	mutex_destroy(&new_csid_dev->mutex);
 	kfree(new_csid_dev);
-	return 0;
+	return rc;
 }
 
 static const struct of_device_id msm_csid_dt_match[] = {
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
index 2eae49c..46e8117 100644
--- a/drivers/media/video/msm/csi/msm_csid.h
+++ b/drivers/media/video/msm/csi/msm_csid.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
@@ -16,6 +16,12 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <media/v4l2-subdev.h>
+#include <media/msm_camera.h>
+
+enum msm_csid_state_t {
+	CSID_POWER_UP,
+	CSID_POWER_DOWN,
+};
 
 struct csid_device {
 	struct platform_device *pdev;
@@ -28,23 +34,16 @@
 	struct mutex mutex;
 	struct completion reset_complete;
 	uint32_t hw_version;
+	enum msm_csid_state_t csid_state;
 
-	struct clk *csid_clk[5];
-};
-
-struct csid_cfg_params {
-	struct v4l2_subdev *subdev;
-	void *parms;
+	struct clk *csid0_clk[6];
+	struct clk *csid_clk[6];
 };
 
 #define VIDIOC_MSM_CSID_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csid_cfg_params)
-
-#define VIDIOC_MSM_CSID_INIT \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_data*)
 
 #define VIDIOC_MSM_CSID_RELEASE \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
-
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
 #endif
 
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index bec7ae3..6e4ba78 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -16,7 +16,6 @@
 #include <linux/of.h>
 #include <linux/module.h>
 #include <mach/board.h>
-#include <mach/camera.h>
 #include <mach/vreg.h>
 #include <media/msm_isp.h>
 #include "msm_csiphy.h"
@@ -27,31 +26,35 @@
 #define V4L2_IDENT_CSIPHY                        50003
 #define CSIPHY_VERSION_V3                        0x10
 
-int msm_csiphy_config(struct csiphy_cfg_params *cfg_params)
+int msm_csiphy_lane_config(struct csiphy_device *csiphy_dev,
+	struct msm_camera_csiphy_params *csiphy_params)
 {
 	int rc = 0;
 	int j = 0;
 	uint32_t val = 0;
 	uint8_t lane_cnt = 0;
 	uint16_t lane_mask = 0;
-	struct csiphy_device *csiphy_dev;
-	struct msm_camera_csiphy_params *csiphy_params;
 	void __iomem *csiphybase;
-	csiphy_dev = v4l2_get_subdevdata(cfg_params->subdev);
 	csiphybase = csiphy_dev->base;
-	if (csiphybase == NULL)
-		return -ENOMEM;
+	if (!csiphybase) {
+		pr_err("%s: csiphybase NULL\n", __func__);
+		return -EINVAL;
+	}
 
-	csiphy_params = cfg_params->parms;
 	csiphy_dev->lane_mask[csiphy_dev->pdev->id] |= csiphy_params->lane_mask;
 	lane_mask = csiphy_dev->lane_mask[csiphy_dev->pdev->id];
 	lane_cnt = csiphy_params->lane_cnt;
 	if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
-		CDBG("%s: unsupported lane cnt %d\n",
+		pr_err("%s: unsupported lane cnt %d\n",
 			__func__, csiphy_params->lane_cnt);
 		return rc;
 	}
 
+	CDBG("%s csiphy_params, mask = %x, cnt = %d, settle cnt = %x\n",
+		__func__,
+		csiphy_params->lane_mask,
+		csiphy_params->lane_cnt,
+		csiphy_params->settle_cnt);
 	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
 	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
 
@@ -75,6 +78,7 @@
 			csiphybase + MIPI_CSIPHY_GLBL_RESET_ADDR);
 	}
 
+	lane_mask &= 0x1f;
 	while (lane_mask & 0x1f) {
 		if (!(lane_mask & 0x1)) {
 			j++;
@@ -92,7 +96,7 @@
 		j++;
 		lane_mask >>= 1;
 	}
-
+	msleep(20);
 	return rc;
 }
 
@@ -101,19 +105,25 @@
 	uint32_t irq;
 	int i;
 	struct csiphy_device *csiphy_dev = data;
-
-	for (i = 0; i < 5; i++) {
+	if(!csiphy_dev || !csiphy_dev->base)
+		return IRQ_HANDLED;
+	for (i = 0; i < 8; i++) {
 		irq = msm_camera_io_r(
 			csiphy_dev->base +
 			MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR + 0x4*i);
 		msm_camera_io_w(irq,
 			csiphy_dev->base +
 			MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
-		CDBG("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
+		pr_err("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
 			 __func__, csiphy_dev->pdev->id, i, irq);
+		msm_camera_io_w(0x1, csiphy_dev->base +
+			MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+		msm_camera_io_w(0x0, csiphy_dev->base +
+			MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+		msm_camera_io_w(0x0,
+			csiphy_dev->base +
+			MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
 	}
-	msm_camera_io_w(0x1, csiphy_dev->base + 0x164);
-	msm_camera_io_w(0x0, csiphy_dev->base + 0x164);
 	return IRQ_HANDLED;
 }
 
@@ -133,21 +143,33 @@
 	return 0;
 }
 
-static struct msm_cam_clk_info csiphy_clk_info[] = {
+static struct msm_cam_clk_info csiphy_8960_clk_info[] = {
 	{"csiphy_timer_src_clk", 177780000},
 	{"csiphy_timer_clk", -1},
 };
 
-static int msm_csiphy_init(struct v4l2_subdev *sd)
+static struct msm_cam_clk_info csiphy_8974_clk_info[] = {
+	{"ispif_ahb_clk", -1},
+	{"csiphy_timer_src_clk", 200000000},
+	{"csiphy_timer_clk", -1},
+};
+
+static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
 {
 	int rc = 0;
-	struct csiphy_device *csiphy_dev;
-	csiphy_dev = v4l2_get_subdevdata(sd);
 	if (csiphy_dev == NULL) {
+		pr_err("%s: csiphy_dev NULL\n", __func__);
 		rc = -ENOMEM;
 		return rc;
 	}
 
+	if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) {
+		pr_err("%s: csiphy invalid state %d\n", __func__,
+			csiphy_dev->csiphy_state);
+		rc = -EINVAL;
+		return rc;
+	}
+
 	if (csiphy_dev->ref_count++) {
 		CDBG("%s csiphy refcount = %d\n", __func__,
 			csiphy_dev->ref_count);
@@ -157,15 +179,23 @@
 	csiphy_dev->base = ioremap(csiphy_dev->mem->start,
 		resource_size(csiphy_dev->mem));
 	if (!csiphy_dev->base) {
+		pr_err("%s: csiphy_dev->base NULL\n", __func__);
 		csiphy_dev->ref_count--;
 		rc = -ENOMEM;
 		return rc;
 	}
 
-	rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
-			csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 1);
+	if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8960_clk_info), 1);
+	else
+		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8974_clk_info), 1);
 
 	if (rc < 0) {
+		pr_err("%s: csiphy clk enable failed\n", __func__);
 		csiphy_dev->ref_count--;
 		iounmap(csiphy_dev->base);
 		csiphy_dev->base = NULL;
@@ -180,16 +210,15 @@
 	csiphy_dev->hw_version =
 		msm_camera_io_r(csiphy_dev->base + MIPI_CSIPHY_HW_VERSION_ADDR);
 
+	csiphy_dev->csiphy_state = CSIPHY_POWER_UP;
 	return 0;
 }
 
-static int msm_csiphy_release(struct v4l2_subdev *sd, void *arg)
+static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg)
 {
-	struct csiphy_device *csiphy_dev;
 	int i = 0;
 	struct msm_camera_csi_lane_params *csi_lane_params;
 	uint16_t csi_lane_mask;
-	csiphy_dev = v4l2_get_subdevdata(sd);
 	csi_lane_params = (struct msm_camera_csi_lane_params *)arg;
 	csi_lane_mask = csi_lane_params->csi_lane_mask;
 
@@ -198,6 +227,17 @@
 		return 0;
 	}
 
+	if (csiphy_dev->csiphy_state != CSIPHY_POWER_UP) {
+		pr_err("%s: csiphy invalid state %d\n", __func__,
+			csiphy_dev->csiphy_state);
+		return -EINVAL;
+	}
+
+	CDBG("%s csiphy_params, lane assign %x mask = %x\n",
+		__func__,
+		csi_lane_params->csi_lane_assign,
+		csi_lane_params->csi_lane_mask);
+
 	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
 		for (i = 0; i < 4; i++)
@@ -229,33 +269,70 @@
 #if DBG_CSIPHY
 	disable_irq(csiphy_dev->irq->start);
 #endif
-	msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
-		csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
+	if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8960_clk_info), 0);
+	else
+		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8974_clk_info), 0);
 
 	iounmap(csiphy_dev->base);
 	csiphy_dev->base = NULL;
+	csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
 	return 0;
 }
 
+static long msm_csiphy_cmd(struct csiphy_device *csiphy_dev, void *arg)
+{
+	int rc = 0;
+	struct csiphy_cfg_data cdata;
+	struct msm_camera_csiphy_params csiphy_params;
+	if (!csiphy_dev) {
+		pr_err("%s: csiphy_dev NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (copy_from_user(&cdata,
+		(void *)arg,
+		sizeof(struct csiphy_cfg_data))) {
+		pr_err("%s: %d failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+	switch (cdata.cfgtype) {
+	case CSIPHY_INIT:
+		rc = msm_csiphy_init(csiphy_dev);
+		break;
+	case CSIPHY_CFG:
+		if (copy_from_user(&csiphy_params,
+			(void *)cdata.csiphy_params,
+			sizeof(struct msm_camera_csiphy_params))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = msm_csiphy_lane_config(csiphy_dev, &csiphy_params);
+		break;
+	default:
+		pr_err("%s: %d failed\n", __func__, __LINE__);
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
 static long msm_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int cmd, void *arg)
 {
 	int rc = -ENOIOCTLCMD;
-	struct csiphy_cfg_params cfg_params;
 	struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd);
 	mutex_lock(&csiphy_dev->mutex);
 	switch (cmd) {
 	case VIDIOC_MSM_CSIPHY_CFG:
-		cfg_params.subdev = sd;
-		cfg_params.parms = arg;
-		rc = msm_csiphy_config(
-			(struct csiphy_cfg_params *)&cfg_params);
-		break;
-	case VIDIOC_MSM_CSIPHY_INIT:
-		rc = msm_csiphy_init(sd);
+		rc = msm_csiphy_cmd(csiphy_dev, arg);
 		break;
 	case VIDIOC_MSM_CSIPHY_RELEASE:
-		rc = msm_csiphy_release(sd, arg);
+		rc = msm_csiphy_release(csiphy_dev, arg);
 		break;
 	default:
 		pr_err("%s: command not found\n", __func__);
@@ -281,7 +358,6 @@
 	int rc = 0;
 	struct msm_cam_subdev_info sd_info;
 
-	CDBG("%s: device id = %d\n", __func__, pdev->id);
 	new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
 	if (!new_csiphy_dev) {
 		pr_err("%s: no enough memory\n", __func__);
@@ -301,6 +377,7 @@
 	if (pdev->dev.of_node)
 		of_property_read_u32((&pdev->dev)->of_node,
 			"cell-index", &pdev->id);
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
 
 	new_csiphy_dev->mem = platform_get_resource_byname(pdev,
 					IORESOURCE_MEM, "csiphy");
@@ -348,12 +425,13 @@
 	new_csiphy_dev->subdev.entity.name = pdev->name;
 	new_csiphy_dev->subdev.entity.revision =
 		new_csiphy_dev->subdev.devnode->num;
+	new_csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
 	return 0;
 
 csiphy_no_resource:
 	mutex_destroy(&new_csiphy_dev->mutex);
 	kfree(new_csiphy_dev);
-	return 0;
+	return rc;
 }
 
 static const struct of_device_id msm_csiphy_dt_match[] = {
diff --git a/drivers/media/video/msm/csi/msm_csiphy.h b/drivers/media/video/msm/csi/msm_csiphy.h
index 1fab9c1..2fb21d2 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.h
+++ b/drivers/media/video/msm/csi/msm_csiphy.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
@@ -16,9 +16,15 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <media/v4l2-subdev.h>
+#include <media/msm_camera.h>
 
 #define MAX_CSIPHY 3
 
+enum msm_csiphy_state_t {
+	CSIPHY_POWER_UP,
+	CSIPHY_POWER_DOWN,
+};
+
 struct csiphy_device {
 	struct platform_device *pdev;
 	struct v4l2_subdev subdev;
@@ -28,24 +34,16 @@
 	void __iomem *base;
 	struct mutex mutex;
 	uint32_t hw_version;
+	enum msm_csiphy_state_t csiphy_state;
 
-	struct clk *csiphy_clk[2];
+	struct clk *csiphy_clk[3];
 	uint8_t ref_count;
 	uint16_t lane_mask[MAX_CSIPHY];
 };
 
-struct csiphy_cfg_params {
-	struct v4l2_subdev *subdev;
-	void *parms;
-};
-
 #define VIDIOC_MSM_CSIPHY_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, void *)
-
-#define VIDIOC_MSM_CSIPHY_INIT \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct v4l2_subdev*)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct csiphy_cfg_data*)
 
 #define VIDIOC_MSM_CSIPHY_RELEASE \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, void *)
-
 #endif
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index 956019d..7fb2e8f 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -36,7 +36,6 @@
 {
 	int rc = 0;
 	uint32_t data = (0x1 << STROBED_RST_EN);
-	uint32_t data1 = (0x1 << STROBED_RST_EN);
 	uint16_t intfnum = 0, mask = intfmask;
 
 	while (mask != 0) {
@@ -47,49 +46,32 @@
 		}
 		switch (intfnum) {
 		case PIX0:
-			if (vfe_intf == VFE0)
-				data |= (0x1 << PIX_0_VFE_RST_STB) |
-					(0x1 << PIX_0_CSID_RST_STB);
-			else
-				data1 |= (0x1 << PIX_0_VFE_RST_STB) |
-					(0x1 << PIX_0_CSID_RST_STB);
+			data |= (0x1 << PIX_0_VFE_RST_STB) |
+				(0x1 << PIX_0_CSID_RST_STB);
 			ispif->pix_sof_count = 0;
 			break;
 
 		case RDI0:
-			if (vfe_intf == VFE0)
-				data |= (0x1 << RDI_0_VFE_RST_STB) |
-					(0x1 << RDI_0_CSID_RST_STB);
-			else
-				data1 |= (0x1 << RDI_0_VFE_RST_STB) |
-					(0x1 << RDI_0_CSID_RST_STB);
+			data |= (0x1 << RDI_0_VFE_RST_STB) |
+				(0x1 << RDI_0_CSID_RST_STB);
+			ispif->rdi0_sof_count = 0;
 			break;
 
 		case PIX1:
-			if (vfe_intf == VFE0)
-				data |= (0x1 << PIX_1_VFE_RST_STB) |
-					(0x1 << PIX_1_CSID_RST_STB);
-			else
-				data1 |= (0x1 << PIX_1_VFE_RST_STB) |
-					(0x1 << PIX_1_CSID_RST_STB);
+			data |= (0x1 << PIX_1_VFE_RST_STB) |
+				(0x1 << PIX_1_CSID_RST_STB);
 			break;
 
 		case RDI1:
-			if (vfe_intf == VFE0)
-				data |= (0x1 << RDI_1_VFE_RST_STB) |
-					(0x1 << RDI_1_CSID_RST_STB);
-			else
-				data1 |= (0x1 << RDI_1_VFE_RST_STB) |
-					(0x1 << RDI_1_CSID_RST_STB);
+			data |= (0x1 << RDI_1_VFE_RST_STB) |
+				(0x1 << RDI_1_CSID_RST_STB);
+			ispif->rdi1_sof_count = 0;
 			break;
 
 		case RDI2:
-			if (vfe_intf == VFE0)
-				data |= (0x1 << RDI_2_VFE_RST_STB) |
-					(0x1 << RDI_2_CSID_RST_STB);
-			else
-				data1 |= (0x1 << RDI_2_VFE_RST_STB) |
-					(0x1 << RDI_2_CSID_RST_STB);
+			data |= (0x1 << RDI_2_VFE_RST_STB) |
+				(0x1 << RDI_2_CSID_RST_STB);
+			ispif->rdi2_sof_count = 0;
 			break;
 
 		default:
@@ -99,43 +81,26 @@
 		mask >>= 1;
 		intfnum++;
 	}	/*end while */
-	msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
-	rc = wait_for_completion_interruptible(&ispif->reset_complete);
-	if (ispif->csid_version >= CSID_VERSION_V3 && data1 > 0x1) {
-		msm_camera_io_w(data1,
-			ispif->base + ISPIF_RST_CMD_1_ADDR);
-		rc = wait_for_completion_interruptible(&ispif->
-			reset_complete);
+	if (data > 0x1) {
+		if (vfe_intf == VFE0)
+			msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+		else
+			msm_camera_io_w(data, ispif->base +
+				ISPIF_RST_CMD_1_ADDR);
+		rc = wait_for_completion_interruptible(&ispif->reset_complete);
 	}
-
 	return rc;
 }
 
 static int msm_ispif_reset(struct ispif_device *ispif)
 {
 	int rc = 0;
-	uint32_t data = (0x1 << STROBED_RST_EN) |
-		(0x1 << SW_REG_RST_STB) |
-		(0x1 << MISC_LOGIC_RST_STB) |
-		(0x1 << PIX_0_VFE_RST_STB) |
-		(0x1 << PIX_0_CSID_RST_STB) |
-		(0x1 << RDI_0_VFE_RST_STB) |
-		(0x1 << RDI_0_CSID_RST_STB) |
-		(0x1 << RDI_1_VFE_RST_STB) |
-		(0x1 << RDI_1_CSID_RST_STB);
-
-	if (ispif->csid_version >= CSID_VERSION_V2)
-		data |= (0x1 << PIX_1_VFE_RST_STB) |
-			(0x1 << PIX_1_CSID_RST_STB) |
-			(0x1 << RDI_2_VFE_RST_STB) |
-			(0x1 << RDI_2_CSID_RST_STB);
 	ispif->pix_sof_count = 0;
-	msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+	msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
+	if (ispif->csid_version == CSID_VERSION_V3)
+		msm_camera_io_w(ISPIF_RST_CMD_1_MASK, ispif->base +
+				ISPIF_RST_CMD_1_ADDR);
 	rc = wait_for_completion_interruptible(&ispif->reset_complete);
-	if (ispif->csid_version >= CSID_VERSION_V3) {
-		msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_1_ADDR);
-		rc = wait_for_completion_interruptible(&ispif->reset_complete);
-	}
 	return rc;
 }
 
@@ -152,53 +117,55 @@
 	uint8_t intftype, uint8_t csid, uint8_t vfe_intf)
 {
 	int rc = 0;
-	uint32_t data;
+	uint32_t data = 0;
 
-	if (ispif->ispif_clk[intftype] == NULL) {
-		pr_err("%s: ispif NULL clk\n", __func__);
-		return;
+	if (ispif->csid_version <= CSID_VERSION_V2) {
+		if (ispif->ispif_clk[intftype] == NULL) {
+			pr_err("%s: ispif NULL clk\n", __func__);
+			return;
+		}
+		rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+		if (rc < 0)
+			pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
 	}
-
-	rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
-	if (rc < 0)
-		pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
-
 	data = msm_camera_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR +
 		(0x200 * vfe_intf));
 	switch (intftype) {
 	case PIX0:
-		data &= ~(0xF);
+		data &= ~(0x3);
 		data |= csid;
 		break;
 
 	case RDI0:
-		data &= ~(0xF << 4);
+		data &= ~(0x3 << 4);
 		data |= (csid << 4);
 		break;
 
 	case PIX1:
-		data &= ~(0xF << 8);
+		data &= ~(0x3 << 8);
 		data |= (csid << 8);
 		break;
 
 	case RDI1:
-		data &= ~(0xF << 12);
+		data &= ~(0x3 << 12);
 		data |= (csid << 12);
 		break;
 
 	case RDI2:
-		data &= ~(0xF << 20);
+		data &= ~(0x3 << 20);
 		data |= (csid << 20);
 		break;
 	}
-	msm_camera_io_w(data, ispif->base + ISPIF_INPUT_SEL_ADDR +
-		(0x200 * vfe_intf));
+	if (data) {
+		msm_camera_io_w(data, ispif->base + ISPIF_INPUT_SEL_ADDR +
+			(0x200 * vfe_intf));
+	}
 }
 
 static void msm_ispif_enable_intf_cids(struct ispif_device *ispif,
 	uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf)
 {
-	uint32_t data;
+	uint32_t data = 0;
 	mutex_lock(&ispif->mutex);
 	switch (intftype) {
 	case PIX0:
@@ -248,7 +215,7 @@
 	uint8_t intftype, uint8_t vfe_intf)
 {
 	int32_t rc = 0;
-	uint32_t data;
+	uint32_t data = 0;
 	mutex_lock(&ispif->mutex);
 	switch (intftype) {
 	case PIX0:
@@ -275,10 +242,6 @@
 		data = msm_camera_io_r(ispif->base +
 				ISPIF_RDI_2_STATUS_ADDR + (0x200 * vfe_intf));
 		break;
-	default:
-		data = 0;
-		rc = -EINVAL;
-		break;
 	}
 	if ((data & 0xf) != 0xf)
 		rc = -EBUSY;
@@ -298,11 +261,13 @@
 	ispif_params = params_list->params;
 	CDBG("Enable interface\n");
 	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_ADDR);
+	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_1_ADDR);
+	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_2_ADDR);
 	for (i = 0; i < params_len; i++) {
 		intftype = ispif_params[i].intftype;
 		vfe_intf = ispif_params[i].vfe_intf;
-		CDBG("%s intftype %x, vfe_intf %d\n", __func__, intftype,
-			vfe_intf);
+		CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
+			intftype, vfe_intf, ispif_params[i].csid);
 		if ((intftype >= INTF_MAX) ||
 			(ispif->csid_version <= CSID_VERSION_V2 &&
 			vfe_intf > VFE0) ||
@@ -328,6 +293,14 @@
 					ISPIF_IRQ_MASK_ADDR);
 	msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
 					ISPIF_IRQ_CLEAR_ADDR);
+	msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+					ISPIF_IRQ_MASK_1_ADDR);
+	msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+					ISPIF_IRQ_CLEAR_1_ADDR);
+	msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+					ISPIF_IRQ_MASK_2_ADDR);
+	msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+					ISPIF_IRQ_CLEAR_2_ADDR);
 	msm_camera_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
 		 ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
 	return rc;
@@ -372,10 +345,9 @@
 static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint16_t intfmask,
 	uint8_t intf_cmd_mask, uint8_t vfe_intf)
 {
-	uint8_t vc = 0;
+	uint8_t vc = 0, val = 0;
 	uint16_t mask = intfmask, intfnum = 0;
 	uint32_t cid_mask = 0;
-	uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
 	uint32_t global_intf_cmd_mask1 = 0xFFFFFFFF;
 	while (mask != 0) {
 		if (!(intfmask & (0x1 << intfnum))) {
@@ -389,12 +361,15 @@
 
 		while (cid_mask != 0) {
 			if ((cid_mask & 0xf) != 0x0) {
-				if (intfnum != RDI2)
-					global_intf_cmd_mask &=
-						~((0x3 & ~intf_cmd_mask)
-						<< ((vc * 2) +
+				if (intfnum != RDI2) {
+					val = (intf_cmd_mask>>(vc*2)) & 0x3;
+					ispif->global_intf_cmd_mask |=
+						(0x3 << ((vc * 2) +
 						(intfnum * 8)));
-				else
+					ispif->global_intf_cmd_mask &=
+						~((0x3 & ~val) << ((vc * 2) +
+						(intfnum * 8)));
+				} else
 					global_intf_cmd_mask1 &=
 						~((0x3 & ~intf_cmd_mask)
 						<< ((vc * 2) + 8));
@@ -405,7 +380,7 @@
 		mask >>= 1;
 		intfnum++;
 	}
-	msm_camera_io_w(global_intf_cmd_mask,
+	msm_camera_io_w(ispif->global_intf_cmd_mask,
 		ispif->base + ISPIF_INTF_CMD_ADDR + (0x200 * vfe_intf));
 	if (global_intf_cmd_mask1 != 0xFFFFFFFF)
 		msm_camera_io_w(global_intf_cmd_mask1,
@@ -417,11 +392,20 @@
 	uint16_t intfmask, uint8_t vfe_intf)
 {
 	int rc = 0;
-	uint8_t intf_cmd_mask = 0x02;
+	uint8_t intf_cmd_mask = 0xAA;
+	uint16_t intfnum = 0, mask = intfmask;
 	mutex_lock(&ispif->mutex);
 	CDBG("%s intfmask %x intf_cmd_mask %x\n", __func__, intfmask,
 		intf_cmd_mask);
 	msm_ispif_intf_cmd(ispif, intfmask, intf_cmd_mask, vfe_intf);
+	while (mask != 0) {
+		if (intfmask & (0x1 << intfnum))
+			ispif->global_intf_cmd_mask |= (0xFF << (intfnum * 8));
+		mask >>= 1;
+		intfnum++;
+		if (intfnum == RDI2)
+			break;
+	}
 	mutex_unlock(&ispif->mutex);
 	return rc;
 }
@@ -429,11 +413,11 @@
 static int msm_ispif_start_intf_transfer(struct ispif_device *ispif,
 	uint16_t intfmask, uint8_t vfe_intf)
 {
-	uint8_t intf_cmd_mask = 0x01;
+	uint8_t intf_cmd_mask = 0x55;
 	int rc = 0;
 	mutex_lock(&ispif->mutex);
 	rc = msm_ispif_intf_reset(ispif, intfmask, vfe_intf);
-	CDBG("%s intfmask %x intf_cmd_mask %x\n", __func__, intfmask,
+	CDBG("%s intfmask start after%x intf_cmd_mask %x\n", __func__, intfmask,
 		intf_cmd_mask);
 	msm_ispif_intf_cmd(ispif, intfmask, intf_cmd_mask, vfe_intf);
 	mutex_unlock(&ispif->mutex);
@@ -501,6 +485,9 @@
 			default:
 				break;
 			}
+			if (intfnum != RDI2)
+				ispif->global_intf_cmd_mask |= (0xFF <<
+					(intfnum * 8));
 		}
 		mask >>= 1;
 		intfnum++;
@@ -543,13 +530,24 @@
 	return rc;
 }
 
+static void send_rdi_sof(struct ispif_device *ispif,
+	enum msm_ispif_intftype interface, int count)
+{
+	struct rdi_count_msg sof_msg;
+	sof_msg.rdi_interface = interface;
+	sof_msg.count = count;
+	v4l2_subdev_notify(&ispif->subdev, NOTIFY_AXI_RDI_SOF_COUNT,
+					   (void *)&sof_msg);
+}
+
 static void ispif_do_tasklet(unsigned long data)
 {
 	unsigned long flags;
 
 	struct ispif_isr_queue_cmd *qcmd = NULL;
-	CDBG("=== ispif_do_tasklet start ===\n");
+	struct ispif_device *ispif;
 
+	ispif = (struct ispif_device *)data;
 	while (atomic_read(&ispif_irq_cnt)) {
 		spin_lock_irqsave(&ispif_tasklet_lock, flags);
 		qcmd = list_first_entry(&ispif_tasklet_q,
@@ -564,28 +562,17 @@
 		list_del(&qcmd->list);
 		spin_unlock_irqrestore(&ispif_tasklet_lock,
 			flags);
-		if (qcmd->ispifInterruptStatus0 &
-			ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
-			CDBG("ispif rdi irq status\n");
-		}
-		if (qcmd->ispifInterruptStatus1 &
-			ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
-			CDBG("ispif rdi1 irq status\n");
-		}
+
 		kfree(qcmd);
 	}
-	CDBG("=== ispif_do_tasklet end ===\n");
 }
 
-DECLARE_TASKLET(ispif_tasklet, ispif_do_tasklet, 0);
-
 static void ispif_process_irq(struct ispif_device *ispif,
 	struct ispif_irq_status *out)
 {
 	unsigned long flags;
 	struct ispif_isr_queue_cmd *qcmd;
 
-	CDBG("ispif_process_irq\n");
 	qcmd = kzalloc(sizeof(struct ispif_isr_queue_cmd),
 		GFP_ATOMIC);
 	if (!qcmd) {
@@ -594,12 +581,37 @@
 	}
 	qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
 	qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
+	qcmd->ispifInterruptStatus2 = out->ispifIrqStatus2;
 
-	if (qcmd->ispifInterruptStatus0 & ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
-		CDBG("%s: ispif PIX sof irq\n", __func__);
-		ispif->pix_sof_count++;
-		v4l2_subdev_notify(&ispif->subdev, NOTIFY_VFE_SOF_COUNT,
-			(void *)&ispif->pix_sof_count);
+	if (qcmd->ispifInterruptStatus0 &
+			ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
+			CDBG("%s: ispif PIX irq status\n", __func__);
+			ispif->pix_sof_count++;
+			v4l2_subdev_notify(&ispif->subdev,
+				NOTIFY_VFE_PIX_SOF_COUNT,
+				(void *)&ispif->pix_sof_count);
+	}
+
+	if (qcmd->ispifInterruptStatus0 &
+			ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
+			ispif->rdi0_sof_count++;
+			CDBG("%s: ispif RDI0 irq status, counter = %d",
+				__func__, ispif->rdi0_sof_count);
+			send_rdi_sof(ispif, RDI_0, ispif->rdi0_sof_count);
+	}
+	if (qcmd->ispifInterruptStatus1 &
+		ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
+		ispif->rdi1_sof_count++;
+		CDBG("%s: ispif RDI1 irq status, counter = %d",
+			__func__, ispif->rdi1_sof_count);
+		send_rdi_sof(ispif, RDI_1, ispif->rdi1_sof_count);
+	}
+	if (qcmd->ispifInterruptStatus2 &
+		ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
+		ispif->rdi2_sof_count++;
+		CDBG("%s: ispif RDI2 irq status, counter = %d",
+			__func__, ispif->rdi2_sof_count);
+		send_rdi_sof(ispif, RDI_2, ispif->rdi2_sof_count);
 	}
 
 	spin_lock_irqsave(&ispif_tasklet_lock, flags);
@@ -607,37 +619,64 @@
 
 	atomic_add(1, &ispif_irq_cnt);
 	spin_unlock_irqrestore(&ispif_tasklet_lock, flags);
-	tasklet_schedule(&ispif_tasklet);
+	tasklet_schedule(&ispif->ispif_tasklet);
 	return;
 }
 
 static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
 	void *data)
 {
+	uint32_t status0 = 0, status1 = 0, status2 = 0;
 	struct ispif_device *ispif = (struct ispif_device *)data;
 	out->ispifIrqStatus0 = msm_camera_io_r(ispif->base +
 		ISPIF_IRQ_STATUS_ADDR);
 	out->ispifIrqStatus1 = msm_camera_io_r(ispif->base +
 		ISPIF_IRQ_STATUS_1_ADDR);
+	out->ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_2_ADDR);
 	msm_camera_io_w(out->ispifIrqStatus0,
 		ispif->base + ISPIF_IRQ_CLEAR_ADDR);
 	msm_camera_io_w(out->ispifIrqStatus1,
 		ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+	msm_camera_io_w(out->ispifIrqStatus2,
+		ispif->base + ISPIF_IRQ_CLEAR_2_ADDR);
 
-	CDBG("%s: irq ispif->irq: Irq_status0 = 0x%x\n", __func__,
-		out->ispifIrqStatus0);
-	if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
+	CDBG("%s: irq vfe0 Irq_status0 = 0x%x, 1 = 0x%x, 2 = 0x%x\n",
+		__func__, out->ispifIrqStatus0, out->ispifIrqStatus1,
+		out->ispifIrqStatus2);
+	if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK ||
+		out->ispifIrqStatus1 & ISPIF_IRQ_STATUS_1_MASK ||
+		out->ispifIrqStatus2 & ISPIF_IRQ_STATUS_2_MASK) {
 		if (out->ispifIrqStatus0 & (0x1 << RESET_DONE_IRQ))
 			complete(&ispif->reset_complete);
 		if (out->ispifIrqStatus0 & (0x1 << PIX_INTF_0_OVERFLOW_IRQ))
 			pr_err("%s: pix intf 0 overflow.\n", __func__);
 		if (out->ispifIrqStatus0 & (0x1 << RAW_INTF_0_OVERFLOW_IRQ))
 			pr_err("%s: rdi intf 0 overflow.\n", __func__);
+		if (out->ispifIrqStatus1 & (0x1 << RAW_INTF_1_OVERFLOW_IRQ))
+			pr_err("%s: rdi intf 1 overflow.\n", __func__);
+		if (out->ispifIrqStatus2 & (0x1 << RAW_INTF_2_OVERFLOW_IRQ))
+			pr_err("%s: rdi intf 2 overflow.\n", __func__);
 		if ((out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_SOF_MASK) ||
-			(out->ispifIrqStatus1 &
-				ISPIF_IRQ_STATUS_SOF_MASK)) {
+			(out->ispifIrqStatus1 &	ISPIF_IRQ_STATUS_SOF_MASK) ||
+			(out->ispifIrqStatus2 & ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
 			ispif_process_irq(ispif, out);
-		}
+	}
+	if (ispif->csid_version == CSID_VERSION_V3) {
+		status0 = msm_camera_io_r(ispif->base +
+			ISPIF_IRQ_STATUS_ADDR + 0x200);
+		msm_camera_io_w(status0,
+			ispif->base + ISPIF_IRQ_CLEAR_ADDR + 0x200);
+		status1 = msm_camera_io_r(ispif->base +
+			ISPIF_IRQ_STATUS_1_ADDR + 0x200);
+		msm_camera_io_w(status1,
+			ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
+		status2 = msm_camera_io_r(ispif->base +
+			ISPIF_IRQ_STATUS_2_ADDR + 0x200);
+		msm_camera_io_w(status2,
+			ispif->base + ISPIF_IRQ_CLEAR_2_ADDR + 0x200);
+		CDBG("%s: irq vfe1 Irq_status0 = 0x%x, 1 = 0x%x, 2 = 0x%x\n",
+			__func__, status0, status1, status2);
 	}
 	msm_camera_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
 		ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
@@ -650,7 +689,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct msm_cam_clk_info ispif_clk_info[] = {
+static struct msm_cam_clk_info ispif_8960_clk_info[] = {
 	{"csi_pix_clk", 0},
 	{"csi_rdi_clk", 0},
 	{"csi_pix1_clk", 0},
@@ -663,40 +702,61 @@
 {
 	int rc = 0;
 	CDBG("%s called %d\n", __func__, __LINE__);
+
+	if (ispif->ispif_state == ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+			ispif->ispif_state);
+		rc = -EINVAL;
+		return rc;
+	}
+
 	spin_lock_init(&ispif_tasklet_lock);
 	INIT_LIST_HEAD(&ispif_tasklet_q);
 	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
 		IRQF_TRIGGER_RISING, "ispif", ispif);
+	ispif->global_intf_cmd_mask = 0xFFFFFFFF;
 	init_completion(&ispif->reset_complete);
 
+	tasklet_init(&ispif->ispif_tasklet,
+		ispif_do_tasklet, (unsigned long)ispif);
+
 	ispif->csid_version = *csid_version;
-	if (ispif->csid_version >= CSID_VERSION_V2) {
-		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
-			ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 1);
+	if (ispif->csid_version < CSID_VERSION_V2) {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+			ispif->ispif_clk, 2, 1);
 		if (rc < 0)
 			return rc;
-	} else {
-		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
-			ispif->ispif_clk, 2, 1);
+	} else if (ispif->csid_version == CSID_VERSION_V2) {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 1);
 		if (rc < 0)
 			return rc;
 	}
 	rc = msm_ispif_reset(ispif);
+	ispif->ispif_state = ISPIF_POWER_UP;
 	return rc;
 }
 
 static void msm_ispif_release(struct ispif_device *ispif)
 {
+	if (ispif->ispif_state != ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+			ispif->ispif_state);
+		return;
+	}
+
 	CDBG("%s, free_irq\n", __func__);
 	free_irq(ispif->irq->start, ispif);
-	tasklet_kill(&ispif_tasklet);
+	tasklet_kill(&ispif->ispif_tasklet);
 
-	if (ispif->csid_version == CSID_VERSION_V2)
-		msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
-			ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 0);
-	else
-		msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+	if (ispif->csid_version < CSID_VERSION_V2) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
 			ispif->ispif_clk, 2, 0);
+	} else if (ispif->csid_version == CSID_VERSION_V2) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+	}
+	ispif->ispif_state = ISPIF_POWER_DOWN;
 }
 
 static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
@@ -833,6 +893,7 @@
 	ispif->subdev.entity.group_id = ISPIF_DEV;
 	ispif->subdev.entity.name = pdev->name;
 	ispif->subdev.entity.revision = ispif->subdev.devnode->num;
+	ispif->ispif_state = ISPIF_POWER_DOWN;
 	return 0;
 
 ispif_no_mem:
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index f4ad661..d4ca864 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -20,6 +20,12 @@
 struct ispif_irq_status {
 	uint32_t ispifIrqStatus0;
 	uint32_t ispifIrqStatus1;
+	uint32_t ispifIrqStatus2;
+};
+
+enum msm_ispif_state_t {
+	ISPIF_POWER_UP,
+	ISPIF_POWER_DOWN,
 };
 
 struct ispif_device {
@@ -35,12 +41,19 @@
 	uint32_t csid_version;
 	struct clk *ispif_clk[5];
 	uint32_t pix_sof_count;
+	uint32_t rdi0_sof_count;
+	uint32_t rdi1_sof_count;
+	uint32_t rdi2_sof_count;
+	uint32_t global_intf_cmd_mask;
+	struct tasklet_struct ispif_tasklet;
+	enum msm_ispif_state_t ispif_state;
 };
 
 struct ispif_isr_queue_cmd {
 	struct list_head list;
 	uint32_t    ispifInterruptStatus0;
 	uint32_t    ispifInterruptStatus1;
+	uint32_t    ispifInterruptStatus2;
 };
 
 #define VIDIOC_MSM_ISPIF_CFG \
diff --git a/drivers/media/video/msm/eeprom/imx074_eeprom.c b/drivers/media/video/msm/eeprom/imx074_eeprom.c
index 21cbafa..a99b17e 100644
--- a/drivers/media/video/msm/eeprom/imx074_eeprom.c
+++ b/drivers/media/video/msm/eeprom/imx074_eeprom.c
@@ -47,14 +47,15 @@
 	.core = &imx074_eeprom_subdev_core_ops,
 };
 
-uint8_t imx074_wbcalib_data[6];
-struct msm_calib_wb imx074_wb_data;
+static uint8_t imx074_wbcalib_data[6];
+static struct msm_calib_wb imx074_wb_data;
 
 static struct msm_camera_eeprom_info_t imx074_calib_supp_info = {
 	{FALSE, 0, 0, 1},
 	{TRUE, 6, 0, 1024},
 	{FALSE, 0, 0, 1},
 	{FALSE, 0, 0, 1},
+	{FALSE, 0, 0, 1},
 };
 
 static struct msm_camera_eeprom_read_t imx074_eeprom_read_tbl[] = {
diff --git a/drivers/media/video/msm/eeprom/imx091_eeprom.c b/drivers/media/video/msm/eeprom/imx091_eeprom.c
index 68a2361..c53eb20 100644
--- a/drivers/media/video/msm/eeprom/imx091_eeprom.c
+++ b/drivers/media/video/msm/eeprom/imx091_eeprom.c
@@ -47,16 +47,17 @@
 	.core = &imx091_eeprom_subdev_core_ops,
 };
 
-uint8_t imx091_wbcalib_data[6];
-uint8_t imx091_afcalib_data[6];
-struct msm_calib_wb imx091_wb_data;
-struct msm_calib_af imx091_af_data;
+static uint8_t imx091_wbcalib_data[6];
+static uint8_t imx091_afcalib_data[6];
+static struct msm_calib_wb imx091_wb_data;
+static struct msm_calib_af imx091_af_data;
 
 static struct msm_camera_eeprom_info_t imx091_calib_supp_info = {
 	{TRUE, 6, 1, 1},
 	{TRUE, 6, 0, 32768},
 	{FALSE, 0, 0, 1},
 	{FALSE, 0, 0, 1},
+	{FALSE, 0, 0, 1},
 };
 
 static struct msm_camera_eeprom_read_t imx091_eeprom_read_tbl[] = {
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index 76825bb..54c59f8 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -26,19 +26,12 @@
 struct i2c_client *sx150x_client;
 struct timer_list timer_flash;
 static struct msm_camera_sensor_info *sensor_data;
-#if defined(CONFIG_MSM_CAMERA_FLASH_SC628A) || defined(CONFIG_MSM_CAMERA_FLASH_TPS61310)
 static struct msm_camera_i2c_client i2c_client;
-#endif
 enum msm_cam_flash_stat{
 	MSM_CAM_FLASH_OFF,
 	MSM_CAM_FLASH_ON,
 };
 
-#ifdef CONFIG_MSM_CAMERA_FLASH_LM3559
-extern int lm3559_flash_set_led_state(int state);
-#endif
-
-#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 static struct i2c_client *sc628a_client;
 
 static const struct i2c_device_id sc628a_i2c_id[] = {
@@ -75,9 +68,7 @@
 		.name = "sc628a",
 	},
 };
-#endif
 
-#ifdef CONFIG_MSM_CAMERA_FLASH_TPS61310
 static struct i2c_client *tps61310_client;
 
 static const struct i2c_device_id tps61310_i2c_id[] = {
@@ -122,7 +113,6 @@
 		.name = "tps61310",
 	},
 };
-#endif
 
 static int config_flash_gpio_table(enum msm_cam_flash_stat stat,
 			struct msm_camera_sensor_strobe_flash_data *sfdata)
@@ -293,7 +283,6 @@
 {
 	int rc = 0;
 
-#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 	switch (led_state) {
 
 	case MSM_CAMERA_LED_INIT:
@@ -460,8 +449,6 @@
 		rc = -EFAULT;
 		break;
 	}
-#endif
-
 	return rc;
 }
 
@@ -761,14 +748,9 @@
 	sensor_data = sdata;
 	switch (flash_info->flashtype) {
 	case LED_FLASH:
-
-#ifdef CONFIG_MSM_CAMERA_FLASH_LM3559
-		rc = lm3559_flash_set_led_state(flash_info->ctrl_data.led_state);
-#else
 		rc = msm_camera_flash_set_led_state(sdata->flash_data,
-		    flash_info->ctrl_data.led_state);
-#endif
-		break;
+			flash_info->ctrl_data.led_state);
+			break;
 	case STROBE_FLASH:
 		rc = msm_strobe_flash_ctrl(sdata->strobe_flash_data,
 			&(flash_info->ctrl_data.strobe_ctrl));
diff --git a/drivers/media/video/msm/gemini/msm_gemini_hw.h b/drivers/media/video/msm/gemini/msm_gemini_hw.h
index 233f082..248ba06 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_hw.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_hw.h
@@ -15,7 +15,7 @@
 
 #include <media/msm_gemini.h>
 #include "msm_gemini_hw_reg.h"
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/iommu_domains.h>
 
 struct msm_gemini_hw_buf {
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.h b/drivers/media/video/msm/gemini/msm_gemini_platform.h
index eb6b9f0..d7f81aa 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.h
@@ -15,7 +15,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/iommu.h>
 void msm_gemini_platform_p2v(struct file  *file,
 				struct ion_handle **ionhandle);
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index 82bca02..27ebac5 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -84,6 +84,7 @@
 		cci_ctrl.cci_info = client->cci_client;
 		cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = &reg_conf_tbl;
 		cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+		cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
 		cci_ctrl.cfg.cci_i2c_write_cfg.size = 1;
 		rc = v4l2_subdev_call(client->cci_client->cci_subdev,
 				core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
@@ -336,6 +337,39 @@
 	return rc;
 }
 
+int32_t msm_camera_i2c_write_bayer_table(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_setting *write_setting)
+{
+	int i;
+	int32_t rc = -EFAULT;
+	struct msm_camera_i2c_reg_array *reg_setting;
+
+	if (!client || !write_setting)
+		return rc;
+
+	reg_setting = write_setting->reg_setting;
+	client->addr_type = write_setting->addr_type;
+	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (write_setting->data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& write_setting->data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+	for (i = 0; i < write_setting->size; i++) {
+		rc = msm_camera_i2c_write(client, reg_setting->reg_addr,
+			reg_setting->reg_data, write_setting->data_type);
+		if (rc < 0)
+			break;
+		reg_setting++;
+	}
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+	return rc;
+}
+
 int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
 	struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
 	enum msm_camera_i2c_data_type data_type)
@@ -348,6 +382,7 @@
 		cci_ctrl.cci_info = client->cci_client;
 		cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = reg_conf_tbl;
 		cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+		cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
 		cci_ctrl.cfg.cci_i2c_write_cfg.size = size;
 		rc = v4l2_subdev_call(client->cci_client->cci_subdev,
 				core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 169a0b3..35b3bd4 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <mach/camera.h>
 #include <media/v4l2-subdev.h>
+#include <media/msm_camera.h>
 
 #define CONFIG_MSM_CAMERA_I2C_DBG 0
 
@@ -92,6 +93,10 @@
 	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
 	enum msm_camera_i2c_data_type data_type);
 
+int32_t msm_camera_i2c_write_bayer_table(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_setting *write_setting);
+
 int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
 	struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
 	enum msm_camera_i2c_data_type data_type);
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.c b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
index 60f3e10..1698da7 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c_mux.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
@@ -160,7 +160,7 @@
 i2c_mux_no_resource:
 	mutex_destroy(&mux_device->mutex);
 	kfree(mux_device);
-	return 0;
+	return rc;
 }
 
 static struct platform_driver i2c_mux_driver = {
diff --git a/drivers/media/video/msm/io/msm_camera_io_util.c b/drivers/media/video/msm/io/msm_camera_io_util.c
index 4049266..613850b 100644
--- a/drivers/media/video/msm/io/msm_camera_io_util.c
+++ b/drivers/media/video/msm/io/msm_camera_io_util.c
@@ -20,6 +20,7 @@
 #include <mach/gpiomux.h>
 
 #define BUFF_SIZE_128 128
+static int gpio_ref_count;
 
 void msm_camera_io_w(u32 data, void __iomem *addr)
 {
@@ -133,6 +134,12 @@
 					   clk_info[i].clk_name);
 				goto cam_clk_enable_err;
 			}
+			if (clk_info[i].delay > 20) {
+				msleep(clk_info[i].delay);
+			} else if (clk_info[i].delay) {
+				usleep_range(clk_info[i].delay * 1000,
+					(clk_info[i].delay * 1000) + 1000);
+			}
 		}
 	} else {
 		for (i = num_clk - 1; i >= 0; i--) {
@@ -163,26 +170,41 @@
 }
 
 int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
-		int num_vreg, struct regulator **reg_ptr, int config)
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int config)
 {
-	int i = 0;
+	int i = 0, j = 0;
 	int rc = 0;
 	struct camera_vreg_t *curr_vreg;
+
+	if (num_vreg_seq > num_vreg) {
+		pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	if (!num_vreg_seq)
+		num_vreg_seq = num_vreg;
+
 	if (config) {
-		for (i = 0; i < num_vreg; i++) {
-			curr_vreg = &cam_vreg[i];
-			reg_ptr[i] = regulator_get(dev,
+		for (i = 0; i < num_vreg_seq; i++) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			curr_vreg = &cam_vreg[j];
+			reg_ptr[j] = regulator_get(dev,
 				curr_vreg->reg_name);
-			if (IS_ERR(reg_ptr[i])) {
+			if (IS_ERR(reg_ptr[j])) {
 				pr_err("%s: %s get failed\n",
 					 __func__,
 					 curr_vreg->reg_name);
-				reg_ptr[i] = NULL;
+				reg_ptr[j] = NULL;
 				goto vreg_get_fail;
 			}
 			if (curr_vreg->type == REG_LDO) {
 				rc = regulator_set_voltage(
-					reg_ptr[i],
+					reg_ptr[j],
 					curr_vreg->min_voltage,
 					curr_vreg->max_voltage);
 				if (rc < 0) {
@@ -193,7 +215,7 @@
 				}
 				if (curr_vreg->op_mode >= 0) {
 					rc = regulator_set_optimum_mode(
-						reg_ptr[i],
+						reg_ptr[j],
 						curr_vreg->op_mode);
 					if (rc < 0) {
 						pr_err(
@@ -206,20 +228,26 @@
 			}
 		}
 	} else {
-		for (i = num_vreg-1; i >= 0; i--) {
-			curr_vreg = &cam_vreg[i];
-			if (reg_ptr[i]) {
+		for (i = num_vreg_seq-1; i >= 0; i--) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			curr_vreg = &cam_vreg[j];
+			if (reg_ptr[j]) {
 				if (curr_vreg->type == REG_LDO) {
 					if (curr_vreg->op_mode >= 0) {
 						regulator_set_optimum_mode(
-							reg_ptr[i], 0);
+							reg_ptr[j], 0);
 					}
 					regulator_set_voltage(
-						reg_ptr[i], 0, curr_vreg->
+						reg_ptr[j], 0, curr_vreg->
 						max_voltage);
 				}
-				regulator_put(reg_ptr[i]);
-				reg_ptr[i] = NULL;
+				regulator_put(reg_ptr[j]);
+				reg_ptr[j] = NULL;
 			}
 		}
 	}
@@ -227,52 +255,100 @@
 
 vreg_unconfig:
 if (curr_vreg->type == REG_LDO)
-	regulator_set_optimum_mode(reg_ptr[i], 0);
+	regulator_set_optimum_mode(reg_ptr[j], 0);
 
 vreg_set_opt_mode_fail:
 if (curr_vreg->type == REG_LDO)
-	regulator_set_voltage(reg_ptr[i], 0,
+	regulator_set_voltage(reg_ptr[j], 0,
 		curr_vreg->max_voltage);
 
 vreg_set_voltage_fail:
-	regulator_put(reg_ptr[i]);
-	reg_ptr[i] = NULL;
+	regulator_put(reg_ptr[j]);
+	reg_ptr[j] = NULL;
 
 vreg_get_fail:
 	for (i--; i >= 0; i--) {
-		curr_vreg = &cam_vreg[i];
+		if (vreg_seq) {
+			j = vreg_seq[i];
+			if (j >= num_vreg)
+				continue;
+		} else
+			j = i;
+		curr_vreg = &cam_vreg[j];
 		goto vreg_unconfig;
 	}
 	return -ENODEV;
 }
 
 int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
-		int num_vreg, struct regulator **reg_ptr, int enable)
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int enable)
 {
-	int i = 0, rc = 0;
+	int i = 0, j = 0, rc = 0;
+
+	if (num_vreg_seq > num_vreg) {
+		pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	if (!num_vreg_seq)
+		num_vreg_seq = num_vreg;
+
 	if (enable) {
-		for (i = 0; i < num_vreg; i++) {
-			if (IS_ERR(reg_ptr[i])) {
+		for (i = 0; i < num_vreg_seq; i++) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			if (IS_ERR(reg_ptr[j])) {
 				pr_err("%s: %s null regulator\n",
-					__func__, cam_vreg[i].reg_name);
+					__func__, cam_vreg[j].reg_name);
 				goto disable_vreg;
 			}
-			rc = regulator_enable(reg_ptr[i]);
+			rc = regulator_enable(reg_ptr[j]);
 			if (rc < 0) {
 				pr_err("%s: %s enable failed\n",
-					__func__, cam_vreg[i].reg_name);
+					__func__, cam_vreg[j].reg_name);
 				goto disable_vreg;
 			}
+			if (cam_vreg[j].delay > 20)
+				msleep(cam_vreg[j].delay);
+			else if (cam_vreg[j].delay)
+				usleep_range(cam_vreg[j].delay * 1000,
+					(cam_vreg[j].delay * 1000) + 1000);
 		}
 	} else {
-		for (i = num_vreg-1; i >= 0; i--)
-			regulator_disable(reg_ptr[i]);
+		for (i = num_vreg_seq-1; i >= 0; i--) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			regulator_disable(reg_ptr[j]);
+			if (cam_vreg[j].delay > 20)
+				msleep(cam_vreg[j].delay);
+			else if (cam_vreg[j].delay)
+				usleep_range(cam_vreg[j].delay * 1000,
+					(cam_vreg[j].delay * 1000) + 1000);
+		}
 	}
 	return rc;
 disable_vreg:
 	for (i--; i >= 0; i--) {
-		regulator_disable(reg_ptr[i]);
-		goto disable_vreg;
+		if (vreg_seq) {
+			j = vreg_seq[i];
+			if (j >= num_vreg)
+				continue;
+		} else
+			j = i;
+		regulator_disable(reg_ptr[j]);
+		if (cam_vreg[j].delay > 20)
+			msleep(cam_vreg[j].delay);
+		else if (cam_vreg[j].delay)
+			usleep_range(cam_vreg[j].delay * 1000,
+				(cam_vreg[j].delay * 1000) + 1000);
 	}
 	return rc;
 }
@@ -319,7 +395,7 @@
 		config_gpio_table(gpio_conf);
 
 	if (gpio_en) {
-		if (!gpio_conf->gpio_no_mux) {
+		if (!gpio_conf->gpio_no_mux && !gpio_ref_count) {
 			if (gpio_conf->cam_gpiomux_conf_tbl != NULL) {
 				msm_gpiomux_install(
 					(struct msm_gpiomux_config *)
@@ -334,6 +410,7 @@
 				return rc;
 			}
 		}
+		gpio_ref_count++;
 		if (gpio_conf->cam_gpio_req_tbl_size) {
 			rc = gpio_request_array(gpio_conf->cam_gpio_req_tbl,
 				gpio_conf->cam_gpio_req_tbl_size);
@@ -346,9 +423,10 @@
 			}
 		}
 	} else {
+		gpio_ref_count--;
 		gpio_free_array(gpio_conf->cam_gpio_req_tbl,
 				gpio_conf->cam_gpio_req_tbl_size);
-		if (!gpio_conf->gpio_no_mux)
+		if (!gpio_conf->gpio_no_mux && !gpio_ref_count)
 			gpio_free_array(gpio_conf->cam_gpio_common_tbl,
 				gpio_conf->cam_gpio_common_tbl_size);
 	}
@@ -380,3 +458,39 @@
 	}
 	return rc;
 }
+
+void msm_camera_bus_scale_cfg(uint32_t bus_perf_client,
+		enum msm_bus_perf_setting perf_setting)
+{
+	int rc = 0;
+	if (!bus_perf_client) {
+		pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+		return;
+	}
+
+	switch (perf_setting) {
+	case S_EXIT:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 1);
+		msm_bus_scale_unregister_client(bus_perf_client);
+		break;
+	case S_PREVIEW:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 1);
+		break;
+	case S_VIDEO:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 2);
+		break;
+	case S_CAPTURE:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 3);
+		break;
+	case S_ZSL:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 4);
+		break;
+	case S_LIVESHOT:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 5);
+		break;
+	case S_DEFAULT:
+		break;
+	default:
+		pr_warning("%s: INVALID CASE\n", __func__);
+	}
+}
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/video/msm/io/msm_io_8960.c
index 699425a..808cc32 100644
--- a/drivers/media/video/msm/io/msm_io_8960.c
+++ b/drivers/media/video/msm/io/msm_io_8960.c
@@ -95,6 +95,14 @@
 		} else
 			CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
 		break;
+	case S_DUAL:
+		if (bus_perf_client) {
+			rc = msm_bus_scale_client_update_request(
+				bus_perf_client, 6);
+			CDBG("%s: S_DUAL rc = %d\n", __func__, rc);
+		} else
+			CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
+		break;
 	case S_DEFAULT:
 		break;
 	default:
diff --git a/drivers/media/video/msm/jpeg_10/Makefile b/drivers/media/video/msm/jpeg_10/Makefile
new file mode 100644
index 0000000..d99d1a4
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/Makefile
@@ -0,0 +1,3 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+ccflags-y += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_JPEG) += msm_jpeg_dev.o msm_jpeg_sync.o msm_jpeg_core.o msm_jpeg_hw.o msm_jpeg_platform.o
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
new file mode 100644
index 0000000..88ec1ad
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_JPEG_COMMON_H
+#define MSM_JPEG_COMMON_H
+
+#ifdef MSM_JPEG_DEBUG
+#define JPEG_DBG(fmt, args...) printk(fmt, ##args)
+#else
+#define JPEG_DBG(fmt, args...) do { } while (0)
+#endif
+
+#define JPEG_PR_ERR   pr_err
+
+enum JPEG_MODE {
+	JPEG_MODE_DISABLE,
+	JPEG_MODE_OFFLINE,
+	JPEG_MODE_REALTIME,
+	JPEG_MODE_REALTIME_ROTATION
+};
+
+enum JPEG_ROTATION {
+	JPEG_ROTATION_0,
+	JPEG_ROTATION_90,
+	JPEG_ROTATION_180,
+	JPEG_ROTATION_270
+};
+
+#endif /* MSM_JPEG_COMMON_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
new file mode 100644
index 0000000..7905ff3
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
@@ -0,0 +1,223 @@
+/* Copyright (c) 2012,The Linux Foundation. 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/module.h>
+#include <linux/sched.h>
+#include "msm_jpeg_hw.h"
+#include "msm_jpeg_core.h"
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_common.h"
+
+static struct msm_jpeg_hw_pingpong fe_pingpong_buf;
+static struct msm_jpeg_hw_pingpong we_pingpong_buf;
+static int we_pingpong_index;
+static int reset_done_ack;
+static spinlock_t reset_lock;
+static wait_queue_head_t reset_wait;
+
+int msm_jpeg_core_reset(uint8_t op_mode, void *base, int size)
+{
+	unsigned long flags;
+	int rc = 0;
+	int tm = 500; /*500ms*/
+	memset(&fe_pingpong_buf, 0, sizeof(fe_pingpong_buf));
+	fe_pingpong_buf.is_fe = 1;
+	we_pingpong_index = 0;
+	memset(&we_pingpong_buf, 0, sizeof(we_pingpong_buf));
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 0;
+	msm_jpeg_hw_reset(base, size);
+	spin_unlock_irqrestore(&reset_lock, flags);
+	rc = wait_event_interruptible_timeout(
+			reset_wait,
+			reset_done_ack,
+			msecs_to_jiffies(tm));
+
+	if (!reset_done_ack) {
+		JPEG_DBG("%s: reset ACK failed %d", __func__, rc);
+		return -EBUSY;
+	}
+
+	JPEG_DBG("%s: reset_done_ack rc %d", __func__, rc);
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 0;
+	spin_unlock_irqrestore(&reset_lock, flags);
+
+	return 0;
+}
+
+void msm_jpeg_core_release(int release_buf, int domain_num)
+{
+	int i = 0;
+	for (i = 0; i < 2; i++) {
+		if (we_pingpong_buf.buf_status[i] && release_buf)
+			msm_jpeg_platform_p2v(we_pingpong_buf.buf[i].file,
+				&we_pingpong_buf.buf[i].handle, domain_num);
+		we_pingpong_buf.buf_status[i] = 0;
+	}
+}
+
+void msm_jpeg_core_init(void)
+{
+	init_waitqueue_head(&reset_wait);
+	spin_lock_init(&reset_lock);
+}
+
+int msm_jpeg_core_fe_start(void)
+{
+	msm_jpeg_hw_fe_start();
+	return 0;
+}
+
+/* fetch engine */
+int msm_jpeg_core_fe_buf_update(struct msm_jpeg_core_buf *buf)
+{
+	JPEG_DBG("%s:%d] 0x%08x %d 0x%08x %d\n", __func__, __LINE__,
+		(int) buf->y_buffer_addr, buf->y_len,
+		(int) buf->cbcr_buffer_addr, buf->cbcr_len);
+	return msm_jpeg_hw_pingpong_update(&fe_pingpong_buf, buf);
+}
+
+void *msm_jpeg_core_fe_pingpong_irq(int jpeg_irq_status, void *context)
+{
+	return msm_jpeg_hw_pingpong_irq(&fe_pingpong_buf);
+}
+
+/* write engine */
+int msm_jpeg_core_we_buf_update(struct msm_jpeg_core_buf *buf)
+{
+	JPEG_DBG("%s:%d] 0x%08x 0x%08x %d\n", __func__, __LINE__,
+		(int) buf->y_buffer_addr, (int) buf->cbcr_buffer_addr,
+		buf->y_len);
+	we_pingpong_buf.buf[0] = *buf;
+	we_pingpong_buf.buf_status[0] = 1;
+	msm_jpeg_hw_we_buffer_update(
+			&we_pingpong_buf.buf[0], 0);
+
+	return 0;
+}
+
+int msm_jpeg_core_we_buf_reset(struct msm_jpeg_hw_buf *buf)
+{
+	int i = 0;
+	for (i = 0; i < 2; i++) {
+		if (we_pingpong_buf.buf[i].y_buffer_addr
+					== buf->y_buffer_addr)
+			we_pingpong_buf.buf_status[i] = 0;
+	}
+	return 0;
+}
+
+void *msm_jpeg_core_we_pingpong_irq(int jpeg_irq_status, void *context)
+{
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+
+	return msm_jpeg_hw_pingpong_irq(&we_pingpong_buf);
+}
+
+void *msm_jpeg_core_framedone_irq(int jpeg_irq_status, void *context)
+{
+	struct msm_jpeg_hw_buf *buf_p;
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+
+	buf_p = msm_jpeg_hw_pingpong_active_buffer(&we_pingpong_buf);
+	if (buf_p) {
+		buf_p->framedone_len = msm_jpeg_hw_encode_output_size();
+		JPEG_DBG("%s:%d] framedone_len %d\n", __func__, __LINE__,
+			buf_p->framedone_len);
+	}
+
+	return buf_p;
+}
+
+void *msm_jpeg_core_reset_ack_irq(int jpeg_irq_status, void *context)
+{
+	/* @todo return the status back to msm_jpeg_core_reset */
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	return NULL;
+}
+
+void *msm_jpeg_core_err_irq(int jpeg_irq_status, void *context)
+{
+	JPEG_PR_ERR("%s:%d]\n", __func__, jpeg_irq_status);
+	return NULL;
+}
+
+static int (*msm_jpeg_irq_handler) (int, void *, void *);
+
+irqreturn_t msm_jpeg_core_irq(int irq_num, void *context)
+{
+	void *data = NULL;
+	unsigned long flags;
+	int jpeg_irq_status;
+
+	JPEG_DBG("%s:%d] irq_num = %d\n", __func__, __LINE__, irq_num);
+
+	jpeg_irq_status = msm_jpeg_hw_irq_get_status();
+
+	JPEG_DBG("%s:%d] jpeg_irq_status = %0x\n", __func__, __LINE__,
+		jpeg_irq_status);
+
+	/*For reset and framedone IRQs, clear all bits*/
+	if (jpeg_irq_status & 0x10000000) {
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			JPEG_IRQ_CLEAR_ALL);
+	} else if (jpeg_irq_status & 0x1) {
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			JPEG_IRQ_CLEAR_ALL);
+	} else {
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			jpeg_irq_status);
+	}
+
+	if (msm_jpeg_hw_irq_is_frame_done(jpeg_irq_status)) {
+		data = msm_jpeg_core_framedone_irq(jpeg_irq_status,
+			context);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(
+				MSM_JPEG_HW_MASK_COMP_FRAMEDONE,
+				context, data);
+	}
+	if (msm_jpeg_hw_irq_is_reset_ack(jpeg_irq_status)) {
+		data = msm_jpeg_core_reset_ack_irq(jpeg_irq_status,
+			context);
+		spin_lock_irqsave(&reset_lock, flags);
+		reset_done_ack = 1;
+		spin_unlock_irqrestore(&reset_lock, flags);
+		wake_up(&reset_wait);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(
+				MSM_JPEG_HW_MASK_COMP_RESET_ACK,
+				context, data);
+	}
+
+	/* Unexpected/unintended HW interrupt */
+	if (msm_jpeg_hw_irq_is_err(jpeg_irq_status)) {
+		data = msm_jpeg_core_err_irq(jpeg_irq_status, context);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_ERR,
+				context, data);
+	}
+
+	return IRQ_HANDLED;
+}
+
+void msm_jpeg_core_irq_install(int (*irq_handler) (int, void *, void *))
+{
+	msm_jpeg_irq_handler = irq_handler;
+}
+
+void msm_jpeg_core_irq_remove(void)
+{
+	msm_jpeg_irq_handler = NULL;
+}
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
new file mode 100644
index 0000000..b5c725c
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_JPEG_CORE_H
+#define MSM_JPEG_CORE_H
+
+#include <linux/interrupt.h>
+#include "msm_jpeg_hw.h"
+
+#define msm_jpeg_core_buf msm_jpeg_hw_buf
+
+irqreturn_t msm_jpeg_core_irq(int irq_num, void *context);
+
+void msm_jpeg_core_irq_install(int (*irq_handler) (int, void *, void *));
+void msm_jpeg_core_irq_remove(void);
+
+int msm_jpeg_core_fe_buf_update(struct msm_jpeg_core_buf *buf);
+int msm_jpeg_core_we_buf_update(struct msm_jpeg_core_buf *buf);
+int msm_jpeg_core_we_buf_reset(struct msm_jpeg_hw_buf *buf);
+
+int msm_jpeg_core_reset(uint8_t op_mode, void *base, int size);
+int msm_jpeg_core_fe_start(void);
+
+void msm_jpeg_core_release(int, int);
+void msm_jpeg_core_init(void);
+#endif /* MSM_JPEG_CORE_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
new file mode 100644
index 0000000..45a9a38
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
@@ -0,0 +1,299 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <mach/board.h>
+#include <linux/of.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <media/msm_jpeg.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "msm.h"
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_common.h"
+
+#define MSM_JPEG_NAME "jpeg"
+#define MSM_JPEGE1_NAME "jpege1"
+#define MSM_JPEGD_NAME "jpegd"
+
+
+static int msm_jpeg_open(struct inode *inode, struct file *filp)
+{
+	int rc = 0;
+
+	struct msm_jpeg_device *pgmn_dev = container_of(inode->i_cdev,
+		struct msm_jpeg_device, cdev);
+	filp->private_data = pgmn_dev;
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+
+	rc = __msm_jpeg_open(pgmn_dev);
+
+	JPEG_DBG(KERN_INFO "%s:%d] %s open_count = %d\n", __func__, __LINE__,
+		filp->f_path.dentry->d_name.name, pgmn_dev->open_count);
+
+	return rc;
+}
+
+static int msm_jpeg_release(struct inode *inode, struct file *filp)
+{
+	int rc;
+
+	struct msm_jpeg_device *pgmn_dev = filp->private_data;
+
+	JPEG_DBG(KERN_INFO "%s:%d]\n", __func__, __LINE__);
+
+	rc = __msm_jpeg_release(pgmn_dev);
+
+	JPEG_DBG(KERN_INFO "%s:%d] %s open_count = %d\n", __func__, __LINE__,
+		filp->f_path.dentry->d_name.name, pgmn_dev->open_count);
+	return rc;
+}
+
+static long msm_jpeg_ioctl(struct file *filp, unsigned int cmd,
+	unsigned long arg)
+{
+	int rc;
+	struct msm_jpeg_device *pgmn_dev = filp->private_data;
+
+	JPEG_DBG("%s:%d] cmd=%d pgmn_dev=0x%x arg=0x%x\n", __func__,
+		__LINE__, _IOC_NR(cmd), (uint32_t)pgmn_dev, (uint32_t)arg);
+
+	rc = __msm_jpeg_ioctl(pgmn_dev, cmd, arg);
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	return rc;
+}
+
+static const struct file_operations msm_jpeg_fops = {
+	.owner		= THIS_MODULE,
+	.open		 = msm_jpeg_open,
+	.release	= msm_jpeg_release,
+	.unlocked_ioctl = msm_jpeg_ioctl,
+};
+
+
+int msm_jpeg_subdev_init(struct v4l2_subdev *jpeg_sd)
+{
+	int rc;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *)jpeg_sd->host_priv;
+
+	JPEG_DBG("%s:%d: jpeg_sd=0x%x pgmn_dev=0x%x\n",
+		__func__, __LINE__, (uint32_t)jpeg_sd, (uint32_t)pgmn_dev);
+	rc = __msm_jpeg_open(pgmn_dev);
+	JPEG_DBG("%s:%d: rc=%d\n",
+		__func__, __LINE__, rc);
+	return rc;
+}
+
+static long msm_jpeg_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	long rc;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *)sd->host_priv;
+
+	JPEG_DBG("%s: cmd=%d\n", __func__, cmd);
+
+	JPEG_DBG("%s: pgmn_dev 0x%x", __func__, (uint32_t)pgmn_dev);
+
+	JPEG_DBG("%s: Calling __msm_jpeg_ioctl\n", __func__);
+
+	rc = __msm_jpeg_ioctl(pgmn_dev, cmd, (unsigned long)arg);
+	pr_debug("%s: X\n", __func__);
+	return rc;
+}
+
+void msm_jpeg_subdev_release(struct v4l2_subdev *jpeg_sd)
+{
+	int rc;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *)jpeg_sd->host_priv;
+	JPEG_DBG("%s:pgmn_dev=0x%x", __func__, (uint32_t)pgmn_dev);
+	rc = __msm_jpeg_release(pgmn_dev);
+	JPEG_DBG("%s:rc=%d", __func__, rc);
+}
+
+static const struct v4l2_subdev_core_ops msm_jpeg_subdev_core_ops = {
+	.ioctl = msm_jpeg_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_jpeg_subdev_ops = {
+	.core = &msm_jpeg_subdev_core_ops,
+};
+
+static int msm_jpeg_init_dev(struct platform_device *pdev)
+{
+	int rc = -1;
+	struct device *dev;
+	struct msm_jpeg_device *msm_jpeg_device_p;
+	char devname[10];
+
+	msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC);
+	if (!msm_jpeg_device_p) {
+		JPEG_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+
+	msm_jpeg_device_p->pdev = pdev;
+
+	if (pdev->dev.of_node)
+		of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+								&pdev->id);
+
+	snprintf(devname, sizeof(devname), "%s%d", MSM_JPEG_NAME, pdev->id);
+
+	rc = __msm_jpeg_init(msm_jpeg_device_p);
+	if (rc < -1) {
+		JPEG_PR_ERR("%s: initialization failed\n", __func__);
+		goto fail;
+	}
+
+	v4l2_subdev_init(&msm_jpeg_device_p->subdev, &msm_jpeg_subdev_ops);
+	v4l2_set_subdev_hostdata(&msm_jpeg_device_p->subdev, msm_jpeg_device_p);
+	JPEG_DBG("%s: msm_jpeg_device_p 0x%x", __func__,
+			(uint32_t)msm_jpeg_device_p);
+
+	rc = alloc_chrdev_region(&msm_jpeg_device_p->msm_jpeg_devno, 0, 1,
+				devname);
+	if (rc < 0) {
+		JPEG_PR_ERR("%s: failed to allocate chrdev\n", __func__);
+		goto fail_1;
+	}
+
+	if (!msm_jpeg_device_p->msm_jpeg_class) {
+		msm_jpeg_device_p->msm_jpeg_class =
+				class_create(THIS_MODULE, devname);
+		if (IS_ERR(msm_jpeg_device_p->msm_jpeg_class)) {
+			rc = PTR_ERR(msm_jpeg_device_p->msm_jpeg_class);
+			JPEG_PR_ERR("%s: create device class failed\n",
+				__func__);
+			goto fail_2;
+		}
+	}
+
+	dev = device_create(msm_jpeg_device_p->msm_jpeg_class, NULL,
+		MKDEV(MAJOR(msm_jpeg_device_p->msm_jpeg_devno),
+		MINOR(msm_jpeg_device_p->msm_jpeg_devno)), NULL,
+		"%s%d", MSM_JPEG_NAME, pdev->id);
+	if (IS_ERR(dev)) {
+		JPEG_PR_ERR("%s: error creating device\n", __func__);
+		rc = -ENODEV;
+		goto fail_3;
+	}
+
+	cdev_init(&msm_jpeg_device_p->cdev, &msm_jpeg_fops);
+	msm_jpeg_device_p->cdev.owner = THIS_MODULE;
+	msm_jpeg_device_p->cdev.ops	 =
+		(const struct file_operations *) &msm_jpeg_fops;
+	rc = cdev_add(&msm_jpeg_device_p->cdev,
+			msm_jpeg_device_p->msm_jpeg_devno, 1);
+	if (rc < 0) {
+		JPEG_PR_ERR("%s: error adding cdev\n", __func__);
+		rc = -ENODEV;
+		goto fail_4;
+	}
+
+	platform_set_drvdata(pdev, &msm_jpeg_device_p);
+
+	JPEG_DBG("%s %s%d: success\n", __func__, MSM_JPEG_NAME, pdev->id);
+
+	return rc;
+
+fail_4:
+	device_destroy(msm_jpeg_device_p->msm_jpeg_class,
+			msm_jpeg_device_p->msm_jpeg_devno);
+
+fail_3:
+	class_destroy(msm_jpeg_device_p->msm_jpeg_class);
+
+fail_2:
+	unregister_chrdev_region(msm_jpeg_device_p->msm_jpeg_devno, 1);
+
+fail_1:
+	__msm_jpeg_exit(msm_jpeg_device_p);
+
+fail:
+	kfree(msm_jpeg_device_p);
+	return rc;
+
+}
+
+static void msm_jpeg_exit(struct msm_jpeg_device *msm_jpeg_device_p)
+{
+	cdev_del(&msm_jpeg_device_p->cdev);
+	device_destroy(msm_jpeg_device_p->msm_jpeg_class,
+			msm_jpeg_device_p->msm_jpeg_devno);
+	class_destroy(msm_jpeg_device_p->msm_jpeg_class);
+	unregister_chrdev_region(msm_jpeg_device_p->msm_jpeg_devno, 1);
+
+	__msm_jpeg_exit(msm_jpeg_device_p);
+}
+
+static int __msm_jpeg_probe(struct platform_device *pdev)
+{
+	return msm_jpeg_init_dev(pdev);
+}
+
+static int __msm_jpeg_remove(struct platform_device *pdev)
+{
+	struct msm_jpeg_device *msm_jpegd_device_p;
+
+	msm_jpegd_device_p = platform_get_drvdata(pdev);
+	if (msm_jpegd_device_p)
+		msm_jpeg_exit(msm_jpegd_device_p);
+
+	return 0;
+}
+
+static const struct of_device_id msm_jpeg_dt_match[] = {
+			{.compatible = "qcom,jpeg"},
+};
+
+MODULE_DEVICE_TABLE(of, msm_jpeg_dt_match);
+
+static struct platform_driver msm_jpeg_driver = {
+	.probe	= __msm_jpeg_probe,
+	.remove = __msm_jpeg_remove,
+	.driver = {
+		.name = MSM_JPEG_DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_jpeg_dt_match,
+	},
+};
+
+static int __init msm_jpeg_driver_init(void)
+{
+	int rc;
+	rc = platform_driver_register(&msm_jpeg_driver);
+	return rc;
+}
+
+static void __exit msm_jpeg_driver_exit(void)
+{
+	platform_driver_unregister(&msm_jpeg_driver);
+}
+
+MODULE_DESCRIPTION("msm jpeg jpeg driver");
+
+module_init(msm_jpeg_driver_init);
+module_exit(msm_jpeg_driver_exit);
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
new file mode 100644
index 0000000..0bfb6a8
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
@@ -0,0 +1,380 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/module.h>
+#include <linux/delay.h>
+#include "msm_jpeg_hw.h"
+#include "msm_jpeg_common.h"
+
+#include <linux/io.h>
+
+static void *jpeg_region_base;
+static uint32_t jpeg_region_size;
+
+int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
+	struct msm_jpeg_hw_buf *buf)
+{
+	int buf_free_index = -1;
+
+	if (!pingpong_hw->buf_status[0]) {
+		buf_free_index = 0;
+	} else if (!pingpong_hw->buf_status[1]) {
+		buf_free_index = 1;
+	} else {
+		JPEG_PR_ERR("%s:%d: pingpong buffer busy\n",
+		__func__, __LINE__);
+		return -EBUSY;
+	}
+
+	pingpong_hw->buf[buf_free_index] = *buf;
+	pingpong_hw->buf_status[buf_free_index] = 1;
+
+	if (pingpong_hw->is_fe) {
+		/* it is fe */
+		msm_jpeg_hw_fe_buffer_update(
+			&pingpong_hw->buf[buf_free_index], buf_free_index);
+	} else {
+		/* it is we */
+		msm_jpeg_hw_we_buffer_update(
+			&pingpong_hw->buf[buf_free_index], buf_free_index);
+	}
+	return 0;
+}
+
+void *msm_jpeg_hw_pingpong_irq(struct msm_jpeg_hw_pingpong *pingpong_hw)
+{
+	struct msm_jpeg_hw_buf *buf_p = NULL;
+
+	if (pingpong_hw->buf_status[pingpong_hw->buf_active_index]) {
+		buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
+		pingpong_hw->buf_status[pingpong_hw->buf_active_index] = 0;
+	}
+
+	pingpong_hw->buf_active_index = !pingpong_hw->buf_active_index;
+
+	return (void *) buf_p;
+}
+
+void *msm_jpeg_hw_pingpong_active_buffer(
+	struct msm_jpeg_hw_pingpong *pingpong_hw)
+{
+	struct msm_jpeg_hw_buf *buf_p = NULL;
+
+	if (pingpong_hw->buf_status[pingpong_hw->buf_active_index])
+		buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
+
+	return (void *) buf_p;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_irq_get_status[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_READ, 1, JPEG_IRQ_STATUS_ADDR,
+		JPEG_IRQ_STATUS_BMSK, {0} },
+};
+
+int msm_jpeg_hw_irq_get_status(void)
+{
+	uint32_t n_irq_status = 0;
+	rmb();
+	n_irq_status = msm_jpeg_hw_read(&hw_cmd_irq_get_status[0]);
+	rmb();
+	return n_irq_status;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_encode_output_size[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_READ, 1,
+	JPEG_ENCODE_OUTPUT_SIZE_STATUS_ADDR,
+	JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK, {0} } ,
+};
+
+long msm_jpeg_hw_encode_output_size(void)
+{
+	uint32_t encode_output_size = 0;
+
+	encode_output_size = msm_jpeg_hw_read(&hw_cmd_encode_output_size[0]);
+
+	return encode_output_size;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_irq_clear[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_CLEAR_ADDR,
+		JPEG_IRQ_CLEAR_BMSK, {JPEG_IRQ_CLEAR_ALL} },
+};
+
+void msm_jpeg_hw_irq_clear(uint32_t mask, uint32_t data)
+{
+	JPEG_DBG("%s:%d] mask %0x data %0x", __func__, __LINE__, mask, data);
+	hw_cmd_irq_clear[0].mask = mask;
+	hw_cmd_irq_clear[0].data = data;
+	msm_jpeg_hw_write(&hw_cmd_irq_clear[0]);
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_fe_ping_update[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_CMD_ADDR,
+		JPEG_CMD_BMSK, {JPEG_CMD_CLEAR_WRITE_PLN_QUEUES} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_RD_OFFSET_ADDR,
+		JPEG_PLN0_RD_OFFSET_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_RD_PNTR_ADDR,
+		JPEG_PLN0_RD_PNTR_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_RD_OFFSET_ADDR,
+		JPEG_PLN1_RD_OFFSET_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_RD_PNTR_ADDR,
+		JPEG_PLN1_RD_PNTR_BMSK, {0} },
+};
+
+void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index)
+{
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	if (pingpong_index == 0) {
+		hw_cmd_p = &hw_cmd_fe_ping_update[0];
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		hw_cmd_p->data = p_input->y_buffer_addr;
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		hw_cmd_p->data = p_input->cbcr_buffer_addr;
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+
+	}
+	return;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_fe_start[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_CMD_ADDR,
+		JPEG_CMD_BMSK, {JPEG_OFFLINE_CMD_START} },
+};
+
+void msm_jpeg_hw_fe_start(void)
+{
+	msm_jpeg_hw_write(&hw_cmd_fe_start[0]);
+
+	return;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_we_ping_update[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_WR_PNTR_ADDR,
+		JPEG_PLN0_WR_PNTR_BMSK, {0} },
+};
+
+void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index)
+{
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	if (pingpong_index == 0) {
+		hw_cmd_p = &hw_cmd_we_ping_update[0];
+		hw_cmd_p->data = p_input->y_buffer_addr;
+		JPEG_PR_ERR("%s Output buffer address is %x\n", __func__,
+						p_input->y_buffer_addr);
+		msm_jpeg_hw_write(hw_cmd_p++);
+
+	}
+	return;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_reset[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_DISABLE_ALL} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_CLEAR_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_CLEAR_ALL} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_RESET_CMD_ADDR,
+		JPEG_RESET_CMD_RMSK, {JPEG_RESET_DEFAULT} },
+};
+
+void msm_jpeg_hw_init(void *base, int size)
+{
+	jpeg_region_base = base;
+	jpeg_region_size = size;
+}
+
+void msm_jpeg_hw_reset(void *base, int size)
+{
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	hw_cmd_p = &hw_cmd_reset[0];
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p++);
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p++);
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p++);
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p);
+	wmb();
+
+	return;
+}
+
+uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p)
+{
+	uint32_t *paddr;
+	uint32_t data;
+
+	paddr = jpeg_region_base + hw_cmd_p->offset;
+
+	data = readl_relaxed(paddr);
+	data &= hw_cmd_p->mask;
+
+	return data;
+}
+
+void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p)
+{
+	uint32_t *paddr;
+	uint32_t old_data, new_data;
+
+	paddr = jpeg_region_base + hw_cmd_p->offset;
+
+	if (hw_cmd_p->mask == 0xffffffff) {
+		old_data = 0;
+	} else {
+		old_data = readl_relaxed(paddr);
+		old_data &= ~hw_cmd_p->mask;
+	}
+
+	new_data = hw_cmd_p->data & hw_cmd_p->mask;
+	new_data |= old_data;
+	writel_relaxed(new_data, paddr);
+}
+
+int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us)
+{
+	int tm = hw_cmd_p->n;
+	uint32_t data;
+	uint32_t wait_data = hw_cmd_p->data & hw_cmd_p->mask;
+
+	data = msm_jpeg_hw_read(hw_cmd_p);
+	if (data != wait_data) {
+		while (tm) {
+			udelay(m_us);
+			data = msm_jpeg_hw_read(hw_cmd_p);
+			if (data == wait_data)
+				break;
+			tm--;
+		}
+	}
+	hw_cmd_p->data = data;
+	return tm;
+}
+
+void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us)
+{
+	int tm = hw_cmd_p->n;
+	while (tm) {
+		udelay(m_us);
+		tm--;
+	}
+}
+
+int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds)
+{
+	int is_copy_to_user = -1;
+	uint32_t data;
+
+	while (m_cmds--) {
+		if (hw_cmd_p->offset > jpeg_region_size) {
+			JPEG_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__,
+				__LINE__, hw_cmd_p->offset, jpeg_region_size);
+			return -EFAULT;
+		}
+
+		switch (hw_cmd_p->type) {
+		case MSM_JPEG_HW_CMD_TYPE_READ:
+			hw_cmd_p->data = msm_jpeg_hw_read(hw_cmd_p);
+			is_copy_to_user = 1;
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_WRITE:
+			msm_jpeg_hw_write(hw_cmd_p);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_WRITE_OR:
+			data = msm_jpeg_hw_read(hw_cmd_p);
+			hw_cmd_p->data = (hw_cmd_p->data & hw_cmd_p->mask) |
+				data;
+			msm_jpeg_hw_write(hw_cmd_p);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_UWAIT:
+			msm_jpeg_hw_wait(hw_cmd_p, 1);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_MWAIT:
+			msm_jpeg_hw_wait(hw_cmd_p, 1000);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_UDELAY:
+			msm_jpeg_hw_delay(hw_cmd_p, 1);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_MDELAY:
+			msm_jpeg_hw_delay(hw_cmd_p, 1000);
+			break;
+
+		default:
+			JPEG_PR_ERR("wrong hw command type\n");
+			break;
+		}
+
+		hw_cmd_p++;
+	}
+	return is_copy_to_user;
+}
+
+void msm_jpeg_io_dump(int size)
+{
+	char line_str[128], *p_str;
+	void __iomem *addr = jpeg_region_base;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	JPEG_PR_ERR("%s: %p %d reg_size %d\n", __func__, addr, size,
+							jpeg_region_size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
+		}
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			JPEG_PR_ERR("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
+		}
+	}
+	if (line_str[0] != '\0')
+		JPEG_PR_ERR("%s\n", line_str);
+}
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
new file mode 100644
index 0000000..73a0e27
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
@@ -0,0 +1,101 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_JPEG_HW_H
+#define MSM_JPEG_HW_H
+
+#include <media/msm_jpeg.h>
+#include "msm_jpeg_hw_reg.h"
+#include <linux/ion.h>
+#include <mach/iommu_domains.h>
+
+struct msm_jpeg_hw_buf {
+	struct msm_jpeg_buf vbuf;
+	struct file  *file;
+	uint32_t framedone_len;
+	uint32_t y_buffer_addr;
+	uint32_t y_len;
+	uint32_t cbcr_buffer_addr;
+	uint32_t cbcr_len;
+	uint32_t num_of_mcu_rows;
+	struct ion_handle *handle;
+};
+
+struct msm_jpeg_hw_pingpong {
+	uint8_t is_fe; /* 1: fe; 0: we */
+	struct  msm_jpeg_hw_buf buf[2];
+	int     buf_status[2];
+	int     buf_active_index;
+};
+
+int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
+	struct msm_jpeg_hw_buf *buf);
+void *msm_jpeg_hw_pingpong_irq(struct msm_jpeg_hw_pingpong *pingpong_hw);
+void *msm_jpeg_hw_pingpong_active_buffer(struct msm_jpeg_hw_pingpong
+	*pingpong_hw);
+
+void msm_jpeg_hw_irq_clear(uint32_t, uint32_t);
+int msm_jpeg_hw_irq_get_status(void);
+long msm_jpeg_hw_encode_output_size(void);
+#define MSM_JPEG_HW_MASK_COMP_FRAMEDONE \
+		MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK
+#define MSM_JPEG_HW_MASK_COMP_FE \
+		MSM_JPEG_HW_IRQ_STATUS_FE_RD_DONE_MASK
+#define MSM_JPEG_HW_MASK_COMP_WE \
+		(MSM_JPEG_HW_IRQ_STATUS_WE_Y_PINGPONG_MASK | \
+		 MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK)
+#define MSM_JPEG_HW_MASK_COMP_RESET_ACK \
+		MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK
+#define MSM_JPEG_HW_MASK_COMP_ERR \
+		(MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK)
+
+#define msm_jpeg_hw_irq_is_frame_done(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_FRAMEDONE)
+#define msm_jpeg_hw_irq_is_fe_pingpong(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_FE)
+#define msm_jpeg_hw_irq_is_we_pingpong(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_WE)
+#define msm_jpeg_hw_irq_is_reset_ack(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_RESET_ACK)
+#define msm_jpeg_hw_irq_is_err(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_ERR)
+
+void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index);
+void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index);
+
+void msm_jpeg_hw_we_buffer_cfg(uint8_t is_realtime);
+
+void msm_jpeg_hw_fe_start(void);
+void msm_jpeg_hw_clk_cfg(void);
+
+void msm_jpeg_hw_reset(void *base, int size);
+void msm_jpeg_hw_irq_cfg(void);
+void msm_jpeg_hw_init(void *base, int size);
+
+uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p);
+void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p);
+int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us);
+void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us);
+int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds);
+void msm_jpeg_hw_region_dump(int size);
+void msm_jpeg_io_dump(int size);
+
+#endif /* MSM_JPEG_HW_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
new file mode 100644
index 0000000..ae64c32
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
@@ -0,0 +1,121 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_JPEG_HW_REG_H
+#define MSM_JPEG_HW_REG_H
+
+#define JPEG_REG_BASE 0
+
+#define MSM_JPEG_HW_IRQ_MASK_ADDR 0x00000018
+#define MSM_JPEG_HW_IRQ_MASK_RMSK 0xFFFFFFFF
+#define MSM_JPEG_HW_IRQ_ENABLE 0xFFFFFFFF
+
+#define MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001
+#define MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000
+
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RD_DONE_MASK 0x00000010
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RD_DONE_SHIFT 0x00000001
+
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_MASK 0x00000004
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_SHIFT 0x00000002
+
+#define MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK 0x00000008
+#define MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_SHIFT 0x00000003
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_PINGPONG_MASK 0x00000010
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_PINGPONG_SHIFT 0x00000004
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK 0x00000020
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_SHIFT 0x00000005
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK 0x00000040
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_SHIFT 0x00000006
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK 0x00000080
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_SHIFT 0x00000007
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK 0x00000100
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_SHIFT 0x00000008
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK 0x00000200
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_SHIFT 0x00000009
+
+#define MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000
+#define MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
+
+#define MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
+#define MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
+
+#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK 0x00001000
+#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_SHIFT 0x0000000c
+
+#define JPEG_OFFLINE_CMD_START 0x00000001
+
+#define JPEG_RESET_DEFAULT 0x00000003 /* cfff? */
+
+#define JPEG_IRQ_DISABLE_ALL 0x00000000
+#define JPEG_IRQ_CLEAR_ALL 0xFFFFFFFF
+
+#define JPEG_PLN0_RD_PNTR_ADDR (JPEG_REG_BASE + 0x00000038)
+#define JPEG_PLN0_RD_PNTR_BMSK  0xFFFFFFFF
+
+#define JPEG_PLN0_RD_OFFSET_ADDR 0x0000003C
+#define JPEG_PLN0_RD_OFFSET_BMSK 0x1FFFFFFF
+
+#define JPEG_PLN1_RD_PNTR_ADDR (JPEG_REG_BASE + 0x00000044)
+#define JPEG_PLN1_RD_PNTR_BMSK 0xFFFFFFFF
+
+#define JPEG_PLN1_RD_OFFSET_ADDR 0x00000048
+#define JPEG_PLN1_RD_OFFSET_BMSK 0x1FFFFFFF
+
+#define JPEG_CMD_ADDR (JPEG_REG_BASE + 0x00000010)
+#define JPEG_CMD_BMSK 0x00000FFF
+#define JPEG_CMD_CLEAR_WRITE_PLN_QUEUES 0x700
+
+#define JPEG_PLN0_WR_PNTR_ADDR (JPEG_REG_BASE + 0x000000cc)
+#define JPEG_PLN0_WR_PNTR_BMSK 0xFFFFFFFF
+
+#define JPEG_PLN1_WR_PNTR_ADDR (JPEG_REG_BASE + 0x000000D0)
+#define JPEG_PLN1_WR_PNTR_BMSK 0xFFFFFFFF
+
+#define JPEG_IRQ_MASK_ADDR (JPEG_REG_BASE + 0x00000018)
+#define JPEG_IRQ_MASK_BMSK 0xFFFFFFFF
+#define JPEG_IRQ_ALLSOURCES_ENABLE 0xFFFFFFFF
+
+#define JPEG_IRQ_CLEAR_ADDR (JPEG_REG_BASE + 0x0000001c)
+#define JPEG_IRQ_CLEAR_BMSK 0xFFFFFFFF
+
+#define JPEG_RESET_CMD_ADDR (JPEG_REG_BASE + 0x00000008)
+#define JPEG_RESET_CMD_RMSK 0xFFFFFFFF
+
+#define JPEG_IRQ_STATUS_ADDR (JPEG_REG_BASE + 0x00000020)
+#define JPEG_IRQ_STATUS_BMSK 0xFFFFFFFF
+
+#define JPEG_ENCODE_OUTPUT_SIZE_STATUS_ADDR (JPEG_REG_BASE + 0x00000180)
+#define JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK 0x1FFFFFFF
+
+
+#define VBIF_BASE_ADDRESS                      0xFDA60000
+#define VBIF_REGION_SIZE                       0xC30
+#define JPEG_VBIF_CLKON                        0x4
+#define JPEG_VBIF_IN_RD_LIM_CONF0              0xB0
+#define JPEG_VBIF_IN_RD_LIM_CONF1              0xB4
+#define JPEG_VBIF_IN_RD_LIM_CONF2              0xB8
+#define JPEG_VBIF_IN_WR_LIM_CONF0              0xC0
+#define JPEG_VBIF_IN_WR_LIM_CONF1              0xC4
+#define JPEG_VBIF_IN_WR_LIM_CONF2              0xC8
+#define JPEG_VBIF_OUT_RD_LIM_CONF0             0xD0
+#define JPEG_VBIF_OUT_WR_LIM_CONF0             0xD4
+#define JPEG_VBIF_DDR_OUT_MAX_BURST            0xD8
+#define JPEG_VBIF_OCMEM_OUT_MAX_BURST          0xDC
+
+#endif /* MSM_JPEG_HW_REG_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
new file mode 100644
index 0000000..981c56c
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
@@ -0,0 +1,288 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/module.h>
+#include <linux/pm_qos.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <linux/io.h>
+#include <linux/android_pmem.h>
+#include <mach/camera.h>
+#include <mach/iommu_domains.h>
+
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_common.h"
+#include "msm_jpeg_hw.h"
+
+/* AXI rate in KHz */
+struct ion_client *jpeg_client;
+static void *jpeg_vbif;
+
+void msm_jpeg_platform_p2v(struct file  *file,
+				struct ion_handle **ionhandle, int domain_num)
+{
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_unmap_iommu(jpeg_client, *ionhandle, domain_num, 0);
+	ion_free(jpeg_client, *ionhandle);
+	*ionhandle = NULL;
+#elif CONFIG_ANDROID_PMEM
+	put_pmem_file(file);
+#endif
+}
+
+uint32_t msm_jpeg_platform_v2p(int fd, uint32_t len, struct file **file_p,
+				struct ion_handle **ionhandle, int domain_num)
+{
+	unsigned long paddr;
+	unsigned long size;
+	int rc;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	*ionhandle = ion_import_dma_buf(jpeg_client, fd);
+	if (IS_ERR_OR_NULL(*ionhandle))
+		return 0;
+
+	rc = ion_map_iommu(jpeg_client, *ionhandle, domain_num, 0,
+			 SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED, 0);
+	JPEG_DBG("%s:%d] addr 0x%x size %ld", __func__, __LINE__,
+							(uint32_t)paddr, size);
+
+#elif CONFIG_ANDROID_PMEM
+	unsigned long kvstart;
+	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
+#else
+	rc = 0;
+	paddr = 0;
+	size = 0;
+#endif
+	if (rc < 0) {
+		JPEG_PR_ERR("%s: get_pmem_file fd %d error %d\n", __func__, fd,
+			rc);
+		goto error1;
+	}
+
+	/* validate user input */
+	if (len > size) {
+		JPEG_PR_ERR("%s: invalid offset + len\n", __func__);
+		goto error1;
+	}
+
+	return paddr;
+error1:
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_free(jpeg_client, *ionhandle);
+#endif
+	return 0;
+}
+
+static struct msm_cam_clk_info jpeg_8x_clk_info[] = {
+	{"core_clk", 228570000},
+	{"iface_clk", -1},
+	{"bus_clk0", -1},
+	{"alt_bus_clk", -1},
+	{"camss_top_ahb_clk", -1},
+};
+
+static void set_vbif_params(void *jpeg_vbif_base)
+{
+	writel_relaxed(0x1,
+		jpeg_vbif_base + JPEG_VBIF_CLKON);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF0);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF1);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF2);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF0);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF1);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF2);
+	writel_relaxed(0x00001010,
+		jpeg_vbif_base + JPEG_VBIF_OUT_RD_LIM_CONF0);
+	writel_relaxed(0x00001010,
+		jpeg_vbif_base + JPEG_VBIF_OUT_WR_LIM_CONF0);
+	writel_relaxed(0x00000707,
+		jpeg_vbif_base + JPEG_VBIF_DDR_OUT_MAX_BURST);
+	writel_relaxed(0x00000707,
+		jpeg_vbif_base + JPEG_VBIF_OCMEM_OUT_MAX_BURST);
+}
+
+
+int msm_jpeg_platform_init(struct platform_device *pdev,
+	struct resource **mem,
+	void **base,
+	int *irq,
+	irqreturn_t (*handler) (int, void *),
+	void *context)
+{
+	int rc = -1;
+	int i = 0;
+	int jpeg_irq;
+	struct resource *jpeg_mem, *jpeg_io, *jpeg_irq_res;
+	void *jpeg_base;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *) context;
+
+	jpeg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!jpeg_mem) {
+		JPEG_PR_ERR("%s: no mem resource?\n", __func__);
+		return -ENODEV;
+	}
+
+	jpeg_irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!jpeg_irq_res) {
+		JPEG_PR_ERR("no irq resource?\n");
+		return -ENODEV;
+	}
+	jpeg_irq = jpeg_irq_res->start;
+	JPEG_DBG("%s base address: 0x%x, jpeg irq number: %d\n", __func__,
+						jpeg_mem->start, jpeg_irq);
+
+	jpeg_io = request_mem_region(jpeg_mem->start,
+					resource_size(jpeg_mem), pdev->name);
+	if (!jpeg_io) {
+		JPEG_PR_ERR("%s: region already claimed\n", __func__);
+		return -EBUSY;
+	}
+
+	jpeg_base = ioremap(jpeg_mem->start, resource_size(jpeg_mem));
+	if (!jpeg_base) {
+		rc = -ENOMEM;
+		JPEG_PR_ERR("%s: ioremap failed\n", __func__);
+		goto fail1;
+	}
+
+	jpeg_vbif = ioremap(VBIF_BASE_ADDRESS, VBIF_REGION_SIZE);
+	if (!jpeg_vbif) {
+		rc = -ENOMEM;
+		JPEG_PR_ERR("%s:%d] ioremap failed\n", __func__, __LINE__);
+		goto fail1;
+	}
+	JPEG_DBG("%s:%d] jpeg_vbif 0x%x", __func__, __LINE__,
+						(uint32_t)jpeg_vbif);
+
+	pgmn_dev->jpeg_fs = regulator_get(&pgmn_dev->pdev->dev, "vdd");
+	rc = regulator_enable(pgmn_dev->jpeg_fs);
+	if (rc) {
+		JPEG_PR_ERR("%s:%d]jpeg regulator get failed\n",
+				__func__, __LINE__); }
+
+	pgmn_dev->hw_version = JPEG_8974;
+	rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
+	 pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 1);
+	if (rc < 0) {
+		JPEG_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
+		goto fail2;
+	}
+
+#ifdef CONFIG_MSM_IOMMU
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		rc = iommu_attach_device(pgmn_dev->domain,
+				pgmn_dev->iommu_ctx_arr[i]);
+		if (rc < 0) {
+			rc = -ENODEV;
+			JPEG_PR_ERR("%s: Device attach failed\n", __func__);
+			goto fail;
+		}
+		JPEG_DBG("%s:%d] dom 0x%x ctx 0x%x", __func__, __LINE__,
+					(uint32_t)pgmn_dev->domain,
+					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
+	}
+#endif
+	set_vbif_params(jpeg_vbif);
+
+	msm_jpeg_hw_init(jpeg_base, resource_size(jpeg_mem));
+	rc = request_irq(jpeg_irq, handler, IRQF_TRIGGER_RISING, "jpeg",
+		context);
+	if (rc) {
+		JPEG_PR_ERR("%s: request_irq failed, %d\n", __func__,
+			jpeg_irq);
+		goto fail3;
+	}
+
+	*mem  = jpeg_mem;
+	*base = jpeg_base;
+	*irq  = jpeg_irq;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	jpeg_client = msm_ion_client_create(-1, "camera/jpeg");
+#endif
+	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
+
+	return rc;
+
+fail3:
+	msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
+	pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 0);
+
+	regulator_put(pgmn_dev->jpeg_fs);
+	regulator_disable(pgmn_dev->jpeg_fs);
+	pgmn_dev->jpeg_fs = NULL;
+fail2:
+	iounmap(jpeg_base);
+fail1:
+#ifdef CONFIG_MSM_IOMMU
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		JPEG_PR_ERR("%s:%d] dom 0x%x ctx 0x%x", __func__, __LINE__,
+					(uint32_t)pgmn_dev->domain,
+					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
+		iommu_detach_device(pgmn_dev->domain,
+					pgmn_dev->iommu_ctx_arr[i]);
+	}
+#endif
+fail:
+	release_mem_region(jpeg_mem->start, resource_size(jpeg_mem));
+	JPEG_DBG("%s:%d] fail\n", __func__, __LINE__);
+	return rc;
+}
+
+int msm_jpeg_platform_release(struct resource *mem, void *base, int irq,
+	void *context)
+{
+	int result = 0;
+	int i = 0;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *) context;
+
+	free_irq(irq, context);
+
+#ifdef CONFIG_MSM_IOMMU
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		iommu_detach_device(pgmn_dev->domain,
+				pgmn_dev->iommu_ctx_arr[i]);
+		JPEG_DBG("%s:%d]", __func__, __LINE__);
+	}
+#endif
+
+	msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
+	pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 0);
+	JPEG_DBG("%s:%d] clock disbale done", __func__, __LINE__);
+
+	if (pgmn_dev->jpeg_fs) {
+		regulator_put(pgmn_dev->jpeg_fs);
+		regulator_disable(pgmn_dev->jpeg_fs);
+		pgmn_dev->jpeg_fs = NULL;
+	}
+	iounmap(jpeg_vbif);
+	iounmap(base);
+	release_mem_region(mem->start, resource_size(mem));
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_client_destroy(jpeg_client);
+#endif
+	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
+	return result;
+}
+
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
new file mode 100644
index 0000000..8a37cef
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_JPEG_PLATFORM_H
+#define MSM_JPEG_PLATFORM_H
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/ion.h>
+#include <linux/iommu.h>
+#include <mach/iommu.h>
+
+
+void msm_jpeg_platform_p2v(struct file  *file,
+				struct ion_handle **ionhandle, int domain_num);
+uint32_t msm_jpeg_platform_v2p(int fd, uint32_t len, struct file **file,
+				struct ion_handle **ionhandle, int domain_num);
+
+int msm_jpeg_platform_clk_enable(void);
+int msm_jpeg_platform_clk_disable(void);
+
+int msm_jpeg_platform_init(struct platform_device *pdev,
+	struct resource **mem,
+	void **base,
+	int *irq,
+	irqreturn_t (*handler) (int, void *),
+	void *context);
+int msm_jpeg_platform_release(struct resource *mem, void *base, int irq,
+	void *context);
+
+#endif /* MSM_JPEG_PLATFORM_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
new file mode 100644
index 0000000..6ac4a5e
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
@@ -0,0 +1,897 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/module.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <media/msm_jpeg.h>
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_core.h"
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_common.h"
+
+static int release_buf;
+
+inline void msm_jpeg_q_init(char const *name, struct msm_jpeg_q *q_p)
+{
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, name);
+	q_p->name = name;
+	spin_lock_init(&q_p->lck);
+	INIT_LIST_HEAD(&q_p->q);
+	init_waitqueue_head(&q_p->wait);
+	q_p->unblck = 0;
+}
+
+inline void *msm_jpeg_q_out(struct msm_jpeg_q *q_p)
+{
+	unsigned long flags;
+	struct msm_jpeg_q_entry *q_entry_p = NULL;
+	void *data = NULL;
+
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	spin_lock_irqsave(&q_p->lck, flags);
+	if (!list_empty(&q_p->q)) {
+		q_entry_p = list_first_entry(&q_p->q, struct msm_jpeg_q_entry,
+			list);
+		list_del_init(&q_entry_p->list);
+	}
+	spin_unlock_irqrestore(&q_p->lck, flags);
+
+	if (q_entry_p) {
+		data = q_entry_p->data;
+		kfree(q_entry_p);
+	} else {
+		JPEG_DBG("%s:%d] %s no entry\n", __func__, __LINE__,
+			q_p->name);
+	}
+
+	return data;
+}
+
+inline int msm_jpeg_q_in(struct msm_jpeg_q *q_p, void *data)
+{
+	unsigned long flags;
+
+	struct msm_jpeg_q_entry *q_entry_p;
+
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+
+	q_entry_p = kmalloc(sizeof(struct msm_jpeg_q_entry), GFP_ATOMIC);
+	if (!q_entry_p) {
+		JPEG_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+	q_entry_p->data = data;
+
+	spin_lock_irqsave(&q_p->lck, flags);
+	list_add_tail(&q_entry_p->list, &q_p->q);
+	spin_unlock_irqrestore(&q_p->lck, flags);
+
+	return 0;
+}
+
+inline int msm_jpeg_q_in_buf(struct msm_jpeg_q *q_p,
+	struct msm_jpeg_core_buf *buf)
+{
+	struct msm_jpeg_core_buf *buf_p;
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		JPEG_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+
+	memcpy(buf_p, buf, sizeof(struct msm_jpeg_core_buf));
+
+	msm_jpeg_q_in(q_p, buf_p);
+	return 0;
+}
+
+inline int msm_jpeg_q_wait(struct msm_jpeg_q *q_p)
+{
+	int tm = MAX_SCHEDULE_TIMEOUT; /* 500ms */
+	int rc;
+
+	JPEG_DBG("%s:%d] %s wait\n", __func__, __LINE__, q_p->name);
+	rc = wait_event_interruptible_timeout(q_p->wait,
+		(!list_empty_careful(&q_p->q) || q_p->unblck),
+		msecs_to_jiffies(tm));
+	JPEG_DBG("%s:%d] %s wait done\n", __func__, __LINE__, q_p->name);
+	if (list_empty_careful(&q_p->q)) {
+		if (rc == 0) {
+			rc = -ETIMEDOUT;
+			JPEG_PR_ERR("%s:%d] %s timeout\n", __func__, __LINE__,
+				q_p->name);
+		} else if (q_p->unblck) {
+			JPEG_DBG("%s:%d] %s unblock is true\n", __func__,
+				__LINE__, q_p->name);
+			q_p->unblck = 0;
+			rc = -ECANCELED;
+		} else if (rc < 0) {
+			JPEG_PR_ERR("%s:%d] %s rc %d\n", __func__, __LINE__,
+				q_p->name, rc);
+		}
+	}
+	return rc;
+}
+
+inline int msm_jpeg_q_wakeup(struct msm_jpeg_q *q_p)
+{
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline int msm_jpeg_q_unblock(struct msm_jpeg_q *q_p)
+{
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	q_p->unblck = 1;
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline void msm_jpeg_outbuf_q_cleanup(struct msm_jpeg_q *q_p,
+				int domain_num)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	do {
+		buf_p = msm_jpeg_q_out(q_p);
+		if (buf_p) {
+			msm_jpeg_platform_p2v(buf_p->file,
+				&buf_p->handle, domain_num);
+			JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+			kfree(buf_p);
+		}
+	} while (buf_p);
+	q_p->unblck = 0;
+}
+
+inline void msm_jpeg_q_cleanup(struct msm_jpeg_q *q_p)
+{
+	void *data;
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	do {
+		data = msm_jpeg_q_out(q_p);
+		if (data) {
+			JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+			kfree(data);
+		}
+	} while (data);
+	q_p->unblck = 0;
+}
+
+/*************** event queue ****************/
+
+int msm_jpeg_framedone_irq(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf_in)
+{
+	int rc = 0;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	if (buf_in) {
+		buf_in->vbuf.framedone_len = buf_in->framedone_len;
+		buf_in->vbuf.type = MSM_JPEG_EVT_SESSION_DONE;
+		JPEG_DBG("%s:%d] 0x%08x %d framedone_len %d\n",
+			__func__, __LINE__,
+			(int) buf_in->y_buffer_addr, buf_in->y_len,
+			buf_in->vbuf.framedone_len);
+		rc = msm_jpeg_q_in_buf(&pgmn_dev->evt_q, buf_in);
+	} else {
+		JPEG_PR_ERR("%s:%d] no output return buffer\n",
+			__func__, __LINE__);
+		rc = -1;
+	}
+
+	if (buf_in)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->evt_q);
+
+	return rc;
+}
+
+int msm_jpeg_evt_get(struct msm_jpeg_device *pgmn_dev,
+	void __user *to)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_ctrl_cmd ctrl_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	msm_jpeg_q_wait(&pgmn_dev->evt_q);
+	buf_p = msm_jpeg_q_out(&pgmn_dev->evt_q);
+
+	if (!buf_p) {
+		JPEG_DBG("%s:%d] no buffer\n", __func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	ctrl_cmd.type = buf_p->vbuf.type;
+	kfree(buf_p);
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) ctrl_cmd.value, ctrl_cmd.len);
+
+	if (copy_to_user(to, &ctrl_cmd, sizeof(ctrl_cmd))) {
+		JPEG_PR_ERR("%s:%d]\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_jpeg_evt_get_unblock(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_unblock(&pgmn_dev->evt_q);
+	return 0;
+}
+
+void msm_jpeg_reset_ack_irq(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+}
+
+void msm_jpeg_err_irq(struct msm_jpeg_device *pgmn_dev,
+	int event)
+{
+	int rc = 0;
+	struct msm_jpeg_core_buf buf;
+
+	JPEG_PR_ERR("%s:%d] error: %d\n", __func__, __LINE__, event);
+
+	buf.vbuf.type = MSM_JPEG_EVT_ERR;
+	rc = msm_jpeg_q_in_buf(&pgmn_dev->evt_q, &buf);
+	if (!rc)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->evt_q);
+
+	if (!rc)
+		JPEG_PR_ERR("%s:%d] err err\n", __func__, __LINE__);
+
+	return;
+}
+
+/*************** output queue ****************/
+
+int msm_jpeg_we_pingpong_irq(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf_in)
+{
+	int rc = 0;
+	struct msm_jpeg_core_buf *buf_out;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (buf_in) {
+		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+			(int) buf_in->y_buffer_addr, buf_in->y_len);
+		rc = msm_jpeg_q_in_buf(&pgmn_dev->output_rtn_q, buf_in);
+	} else {
+		JPEG_DBG("%s:%d] no output return buffer\n", __func__,
+			__LINE__);
+		rc = -1;
+		return rc;
+	}
+
+	buf_out = msm_jpeg_q_out(&pgmn_dev->output_buf_q);
+
+	if (buf_out) {
+		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+			(int) buf_out->y_buffer_addr, buf_out->y_len);
+		rc = msm_jpeg_core_we_buf_update(buf_out);
+		kfree(buf_out);
+	} else {
+		msm_jpeg_core_we_buf_reset(buf_in);
+		JPEG_DBG("%s:%d] no output buffer\n", __func__, __LINE__);
+		rc = -2;
+	}
+
+	if (buf_in)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->output_rtn_q);
+
+	return rc;
+}
+
+int msm_jpeg_output_get(struct msm_jpeg_device *pgmn_dev, void __user *to)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_buf buf_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	msm_jpeg_q_wait(&pgmn_dev->output_rtn_q);
+	buf_p = msm_jpeg_q_out(&pgmn_dev->output_rtn_q);
+
+	if (!buf_p) {
+		JPEG_DBG("%s:%d] no output buffer return\n",
+			__func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	buf_cmd = buf_p->vbuf;
+	msm_jpeg_platform_p2v(buf_p->file, &buf_p->handle,
+		pgmn_dev->domain_num);
+	kfree(buf_p);
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) buf_cmd.vaddr, buf_cmd.y_len);
+
+	if (copy_to_user(to, &buf_cmd, sizeof(buf_cmd))) {
+		JPEG_PR_ERR("%s:%d]", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_jpeg_output_get_unblock(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_unblock(&pgmn_dev->output_rtn_q);
+	return 0;
+}
+
+int msm_jpeg_output_buf_enqueue(struct msm_jpeg_device *pgmn_dev,
+	void __user *arg)
+{
+	struct msm_jpeg_buf buf_cmd;
+	struct msm_jpeg_core_buf *buf_p;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		JPEG_PR_ERR("%s:%d] no mem\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	JPEG_DBG("%s:%d] vaddr = 0x%08x y_len = %d\n, fd = %d",
+		__func__, __LINE__, (int) buf_cmd.vaddr, buf_cmd.y_len,
+		buf_cmd.fd);
+
+	buf_p->y_buffer_addr = msm_jpeg_platform_v2p(buf_cmd.fd,
+		buf_cmd.y_len, &buf_p->file, &buf_p->handle,
+		pgmn_dev->domain_num);
+	if (!buf_p->y_buffer_addr) {
+		JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
+		kfree(buf_p);
+		return -EFAULT;
+	}
+	JPEG_DBG("%s:%d]After v2p y_address =0x%08x, handle = %p\n",
+		__func__, __LINE__, buf_p->y_buffer_addr, buf_p->handle);
+	buf_p->y_len = buf_cmd.y_len;
+	buf_p->vbuf = buf_cmd;
+
+	msm_jpeg_q_in(&pgmn_dev->output_buf_q, buf_p);
+	return 0;
+}
+
+/*************** input queue ****************/
+
+int msm_jpeg_fe_pingpong_irq(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf_in)
+{
+	struct msm_jpeg_core_buf *buf_out;
+	int rc = 0;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (buf_in) {
+		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+			(int) buf_in->y_buffer_addr, buf_in->y_len);
+		rc = msm_jpeg_q_in_buf(&pgmn_dev->input_rtn_q, buf_in);
+	} else {
+		JPEG_DBG("%s:%d] no input return buffer\n", __func__,
+			__LINE__);
+		rc = -EFAULT;
+	}
+
+	buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q);
+
+	if (buf_out) {
+		rc = msm_jpeg_core_fe_buf_update(buf_out);
+		kfree(buf_out);
+		msm_jpeg_core_fe_start();
+	} else {
+		JPEG_DBG("%s:%d] no input buffer\n", __func__, __LINE__);
+		rc = -EFAULT;
+	}
+
+	if (buf_in)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->input_rtn_q);
+
+	return rc;
+}
+
+int msm_jpeg_input_get(struct msm_jpeg_device *pgmn_dev, void __user *to)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_buf buf_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_wait(&pgmn_dev->input_rtn_q);
+	buf_p = msm_jpeg_q_out(&pgmn_dev->input_rtn_q);
+
+	if (!buf_p) {
+		JPEG_DBG("%s:%d] no input buffer return\n",
+			__func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	buf_cmd = buf_p->vbuf;
+	msm_jpeg_platform_p2v(buf_p->file, &buf_p->handle,
+					pgmn_dev->domain_num);
+	kfree(buf_p);
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) buf_cmd.vaddr, buf_cmd.y_len);
+
+	if (copy_to_user(to, &buf_cmd, sizeof(buf_cmd))) {
+		JPEG_PR_ERR("%s:%d]\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_jpeg_input_get_unblock(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_unblock(&pgmn_dev->input_rtn_q);
+	return 0;
+}
+
+int msm_jpeg_input_buf_enqueue(struct msm_jpeg_device *pgmn_dev,
+	void __user *arg)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_buf buf_cmd;
+
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		JPEG_PR_ERR("%s:%d] no mem\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) buf_cmd.vaddr, buf_cmd.y_len);
+
+	buf_p->y_buffer_addr    = msm_jpeg_platform_v2p(buf_cmd.fd,
+		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
+		&buf_p->handle, pgmn_dev->domain_num) + buf_cmd.offset
+		+ buf_cmd.y_off;
+	buf_p->y_len          = buf_cmd.y_len;
+	buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + buf_cmd.y_len
+						+ buf_cmd.cbcr_off;
+	buf_p->cbcr_len       = buf_cmd.cbcr_len;
+	buf_p->num_of_mcu_rows = buf_cmd.num_of_mcu_rows;
+	JPEG_DBG("%s: y_addr=%x, y_len=%x, cbcr_addr=%x, cbcr_len=%x, fd =%d\n",
+		__func__, buf_p->y_buffer_addr, buf_p->y_len,
+		buf_p->cbcr_buffer_addr, buf_p->cbcr_len, buf_cmd.fd);
+
+	if (!buf_p->y_buffer_addr || !buf_p->cbcr_buffer_addr) {
+		JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
+		kfree(buf_p);
+		return -EFAULT;
+	}
+	buf_p->vbuf           = buf_cmd;
+
+	msm_jpeg_q_in(&pgmn_dev->input_buf_q, buf_p);
+
+	return 0;
+}
+
+int msm_jpeg_irq(int event, void *context, void *data)
+{
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *) context;
+
+	switch (event) {
+	case MSM_JPEG_EVT_SESSION_DONE:
+		msm_jpeg_framedone_irq(pgmn_dev, data);
+		msm_jpeg_we_pingpong_irq(pgmn_dev, data);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_FE:
+		msm_jpeg_fe_pingpong_irq(pgmn_dev, data);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_WE:
+		msm_jpeg_we_pingpong_irq(pgmn_dev, data);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_RESET_ACK:
+		msm_jpeg_reset_ack_irq(pgmn_dev);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_ERR:
+	default:
+		msm_jpeg_err_irq(pgmn_dev, event);
+		break;
+	}
+
+	return 0;
+}
+
+int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev)
+{
+	int rc;
+
+	mutex_lock(&pgmn_dev->lock);
+	if (pgmn_dev->open_count) {
+		/* only open once */
+		JPEG_PR_ERR("%s:%d] busy\n", __func__, __LINE__);
+		mutex_unlock(&pgmn_dev->lock);
+		return -EBUSY;
+	}
+	pgmn_dev->open_count++;
+	mutex_unlock(&pgmn_dev->lock);
+
+	msm_jpeg_core_irq_install(msm_jpeg_irq);
+	rc = msm_jpeg_platform_init(pgmn_dev->pdev,
+		&pgmn_dev->mem, &pgmn_dev->base,
+		&pgmn_dev->irq, msm_jpeg_core_irq, pgmn_dev);
+	if (rc) {
+		JPEG_PR_ERR("%s:%d] platform_init fail %d\n", __func__,
+			__LINE__, rc);
+		return rc;
+	}
+
+	JPEG_DBG("%s:%d] platform resources - mem %p, base %p, irq %d\n",
+		__func__, __LINE__,
+		pgmn_dev->mem, pgmn_dev->base, pgmn_dev->irq);
+
+	msm_jpeg_q_cleanup(&pgmn_dev->evt_q);
+	msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->output_buf_q,
+	pgmn_dev->domain_num); msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
+	msm_jpeg_q_cleanup(&pgmn_dev->input_buf_q);
+	msm_jpeg_core_init();
+
+	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
+	return rc;
+}
+
+int __msm_jpeg_release(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	mutex_lock(&pgmn_dev->lock);
+	if (!pgmn_dev->open_count) {
+		JPEG_PR_ERR(KERN_ERR "%s: not opened\n", __func__);
+		mutex_unlock(&pgmn_dev->lock);
+		return -EINVAL;
+	}
+	pgmn_dev->open_count--;
+	mutex_unlock(&pgmn_dev->lock);
+
+	msm_jpeg_core_release(release_buf, pgmn_dev->domain_num);
+	msm_jpeg_q_cleanup(&pgmn_dev->evt_q);
+	msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->output_buf_q,
+					pgmn_dev->domain_num);
+	msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->input_buf_q, pgmn_dev->domain_num);
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	if (pgmn_dev->open_count)
+		JPEG_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__);
+
+	msm_jpeg_platform_release(pgmn_dev->mem, pgmn_dev->base,
+		pgmn_dev->irq, pgmn_dev);
+
+	return 0;
+}
+
+int msm_jpeg_ioctl_hw_cmd(struct msm_jpeg_device *pgmn_dev,
+	void * __user arg)
+{
+	struct msm_jpeg_hw_cmd hw_cmd;
+	int is_copy_to_user;
+
+	if (copy_from_user(&hw_cmd, arg, sizeof(struct msm_jpeg_hw_cmd))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	is_copy_to_user = msm_jpeg_hw_exec_cmds(&hw_cmd, 1);
+	JPEG_DBG("%s:%d] type %d, n %d, offset %d, mask %x, data %x,pdata %x\n",
+		__func__, __LINE__, hw_cmd.type, hw_cmd.n, hw_cmd.offset,
+		hw_cmd.mask, hw_cmd.data, (int) hw_cmd.pdata);
+
+	if (is_copy_to_user >= 0) {
+		if (copy_to_user(arg, &hw_cmd, sizeof(hw_cmd))) {
+			JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+int msm_jpeg_ioctl_hw_cmds(struct msm_jpeg_device *pgmn_dev,
+	void * __user arg)
+{
+	int is_copy_to_user;
+	int len;
+	uint32_t m;
+	struct msm_jpeg_hw_cmds *hw_cmds_p;
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	if (copy_from_user(&m, arg, sizeof(m))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	len = sizeof(struct msm_jpeg_hw_cmds) +
+		sizeof(struct msm_jpeg_hw_cmd) * (m - 1);
+	hw_cmds_p = kmalloc(len, GFP_KERNEL);
+	if (!hw_cmds_p) {
+		JPEG_PR_ERR("%s:%d] no mem %d\n", __func__, __LINE__, len);
+		return -EFAULT;
+	}
+
+	if (copy_from_user(hw_cmds_p, arg, len)) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		kfree(hw_cmds_p);
+		return -EFAULT;
+	}
+
+	hw_cmd_p = (struct msm_jpeg_hw_cmd *) &(hw_cmds_p->hw_cmd);
+
+	is_copy_to_user = msm_jpeg_hw_exec_cmds(hw_cmd_p, m);
+
+	if (is_copy_to_user >= 0) {
+		if (copy_to_user(arg, hw_cmds_p, len)) {
+			JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			kfree(hw_cmds_p);
+			return -EFAULT;
+		}
+	}
+	kfree(hw_cmds_p);
+	return 0;
+}
+
+int msm_jpeg_start(struct msm_jpeg_device *pgmn_dev, void * __user arg)
+{
+	struct msm_jpeg_core_buf *buf_out;
+	struct msm_jpeg_core_buf *buf_out_free[2] = {NULL, NULL};
+	int i, rc;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	release_buf = 1;
+	for (i = 0; i < 2; i++) {
+		buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q);
+
+		if (buf_out) {
+			msm_jpeg_core_fe_buf_update(buf_out);
+			kfree(buf_out);
+		} else {
+			JPEG_DBG("%s:%d] no input buffer\n", __func__,
+					__LINE__);
+			break;
+		}
+	}
+
+	for (i = 0; i < 2; i++) {
+		buf_out_free[i] = msm_jpeg_q_out(&pgmn_dev->output_buf_q);
+
+		if (buf_out_free[i]) {
+			msm_jpeg_core_we_buf_update(buf_out_free[i]);
+			release_buf = 0;
+		} else {
+			JPEG_DBG("%s:%d] no output buffer\n",
+			__func__, __LINE__);
+			break;
+		}
+	}
+
+	for (i = 0; i < 2; i++)
+		kfree(buf_out_free[i]);
+
+	rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, arg);
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	return rc;
+}
+
+int msm_jpeg_ioctl_reset(struct msm_jpeg_device *pgmn_dev,
+	void * __user arg)
+{
+	int rc;
+	struct msm_jpeg_ctrl_cmd ctrl_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (copy_from_user(&ctrl_cmd, arg, sizeof(ctrl_cmd))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	pgmn_dev->op_mode = ctrl_cmd.type;
+
+	rc = msm_jpeg_core_reset(pgmn_dev->op_mode, pgmn_dev->base,
+		resource_size(pgmn_dev->mem));
+	return rc;
+}
+
+int msm_jpeg_ioctl_test_dump_region(struct msm_jpeg_device *pgmn_dev,
+	unsigned long arg)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_io_dump(arg);
+	return 0;
+}
+
+long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
+	unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+	switch (cmd) {
+	case MSM_JPEG_IOCTL_GET_HW_VERSION:
+		JPEG_DBG("%s:%d] VERSION 1\n", __func__, __LINE__);
+		rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_RESET:
+		rc = msm_jpeg_ioctl_reset(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_STOP:
+		rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_START:
+		rc = msm_jpeg_start(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE:
+		rc = msm_jpeg_input_buf_enqueue(pgmn_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_INPUT_GET:
+		rc = msm_jpeg_input_get(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_INPUT_GET_UNBLOCK:
+		rc = msm_jpeg_input_get_unblock(pgmn_dev);
+		break;
+
+	case MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE:
+		rc = msm_jpeg_output_buf_enqueue(pgmn_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_OUTPUT_GET:
+		rc = msm_jpeg_output_get(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_OUTPUT_GET_UNBLOCK:
+		rc = msm_jpeg_output_get_unblock(pgmn_dev);
+		break;
+
+	case MSM_JPEG_IOCTL_EVT_GET:
+		rc = msm_jpeg_evt_get(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_EVT_GET_UNBLOCK:
+		rc = msm_jpeg_evt_get_unblock(pgmn_dev);
+		break;
+
+	case MSM_JPEG_IOCTL_HW_CMD:
+		rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_HW_CMDS:
+		rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_TEST_DUMP_REGION:
+		rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg);
+		break;
+
+	default:
+		JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n",
+			__func__, __LINE__, _IOC_NR(cmd));
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+static int camera_register_domain(void)
+{
+	struct msm_iova_partition camera_fw_partition = {
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	};
+
+	struct msm_iova_layout camera_fw_layout = {
+		.partitions = &camera_fw_partition,
+		.npartitions = 1,
+		.client_name = "camera_jpeg",
+		.domain_flags = 0,
+	};
+	return msm_register_domain(&camera_fw_layout);
+}
+#endif
+
+int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev)
+{
+	int rc = 0, i = 0;
+	int idx = 0;
+	char *iommu_name[3] = {"jpeg_enc0", "jpeg_enc1", "jpeg_dec"};
+
+	mutex_init(&pgmn_dev->lock);
+
+	pr_err("%s:%d] Jpeg Device id %d", __func__, __LINE__,
+		   pgmn_dev->pdev->id);
+	idx = pgmn_dev->pdev->id;
+	pgmn_dev->idx = idx;
+	pgmn_dev->iommu_cnt = 1;
+
+	msm_jpeg_q_init("evt_q", &pgmn_dev->evt_q);
+	msm_jpeg_q_init("output_rtn_q", &pgmn_dev->output_rtn_q);
+	msm_jpeg_q_init("output_buf_q", &pgmn_dev->output_buf_q);
+	msm_jpeg_q_init("input_rtn_q", &pgmn_dev->input_rtn_q);
+	msm_jpeg_q_init("input_buf_q", &pgmn_dev->input_buf_q);
+
+#ifdef CONFIG_MSM_IOMMU
+/*get device context for IOMMU*/
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		pgmn_dev->iommu_ctx_arr[i] = msm_iommu_get_ctx(iommu_name[i]);
+		JPEG_DBG("%s:%d] name %s", __func__, __LINE__, iommu_name[i]);
+		JPEG_DBG("%s:%d] ctx 0x%x", __func__, __LINE__,
+					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
+		if (!pgmn_dev->iommu_ctx_arr[i]) {
+			JPEG_PR_ERR("%s: No iommu fw context found\n",
+					__func__);
+			goto error;
+		}
+	}
+	pgmn_dev->domain_num = camera_register_domain();
+	JPEG_DBG("%s:%d] dom_num 0x%x", __func__, __LINE__,
+				pgmn_dev->domain_num);
+	if (pgmn_dev->domain_num < 0) {
+		JPEG_PR_ERR("%s: could not register domain\n", __func__);
+		goto error;
+	}
+	pgmn_dev->domain = msm_get_iommu_domain(pgmn_dev->domain_num);
+	JPEG_DBG("%s:%d] dom 0x%x", __func__, __LINE__,
+					(uint32_t)pgmn_dev->domain);
+	if (!pgmn_dev->domain) {
+		JPEG_PR_ERR("%s: cannot find domain\n", __func__);
+		goto error;
+	}
+#endif
+
+	return rc;
+error:
+	mutex_destroy(&pgmn_dev->lock);
+	return -EFAULT;
+}
+
+int __msm_jpeg_exit(struct msm_jpeg_device *pgmn_dev)
+{
+	mutex_destroy(&pgmn_dev->lock);
+	kfree(pgmn_dev);
+	return 0;
+}
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
new file mode 100644
index 0000000..1d82060
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_JPEG_SYNC_H
+#define MSM_JPEG_SYNC_H
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include "msm_jpeg_core.h"
+
+#define JPEG_7X 0x1
+#define JPEG_8X60 (0x1 << 1)
+#define JPEG_8960 (0x1 << 2)
+#define JPEG_8974 0x1
+
+struct msm_jpeg_q {
+	char const	*name;
+	struct list_head  q;
+	spinlock_t	lck;
+	wait_queue_head_t wait;
+	int	       unblck;
+};
+
+struct msm_jpeg_q_entry {
+	struct list_head list;
+	void   *data;
+};
+
+struct msm_jpeg_device {
+	struct platform_device *pdev;
+	struct resource        *mem;
+	int                     irq;
+	void                   *base;
+	struct clk *jpeg_clk[5];
+	struct regulator *jpeg_fs;
+	uint32_t hw_version;
+
+	struct device *device;
+	struct cdev   cdev;
+	struct mutex  lock;
+	char	  open_count;
+	uint8_t       op_mode;
+
+	/* event queue including frame done & err indications
+	 */
+	struct msm_jpeg_q evt_q;
+
+	/* output return queue
+	 */
+	struct msm_jpeg_q output_rtn_q;
+
+	/* output buf queue
+	 */
+	struct msm_jpeg_q output_buf_q;
+
+	/* input return queue
+	 */
+	struct msm_jpeg_q input_rtn_q;
+
+	/* input buf queue
+	 */
+	struct msm_jpeg_q input_buf_q;
+
+	struct v4l2_subdev subdev;
+
+	struct class *msm_jpeg_class;
+
+	dev_t msm_jpeg_devno;
+
+	/*iommu domain and context*/
+	int domain_num;
+	int idx;
+	struct iommu_domain *domain;
+	struct device *iommu_ctx_arr[3];
+	int iommu_cnt;
+};
+
+int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev);
+int __msm_jpeg_release(struct msm_jpeg_device *pgmn_dev);
+
+long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
+	unsigned int cmd, unsigned long arg);
+
+int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev);
+int __msm_jpeg_exit(struct msm_jpeg_device *pgmn_dev);
+
+#endif /* MSM_JPEG_SYNC_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.h b/drivers/media/video/msm/mercury/msm_mercury_platform.h
index 8f4a7e3..9edbb30 100644
--- a/drivers/media/video/msm/mercury/msm_mercury_platform.h
+++ b/drivers/media/video/msm/mercury/msm_mercury_platform.h
@@ -15,7 +15,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 int msm_mercury_platform_clk_enable(void);
 int msm_mercury_platform_clk_disable(void);
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 60d7cb7..00f099c 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -92,6 +92,20 @@
 	return rc;
 }
 
+static int msm_camera_v4l2_private_general(struct file *f, void *pctx,
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+
+	WARN_ON(pctx != f->private_data);
+
+	rc = msm_server_private_general(pcam, ioctl_ptr);
+	if (rc < 0)
+		pr_err("%s: Private command failed rc %d\n", __func__, rc);
+	return rc;
+}
+
 static int msm_camera_v4l2_private_g_ctrl(struct file *f, void *pctx,
 	struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
 {
@@ -690,6 +704,18 @@
 		return OUTPUT_TYPE_R;
 	case MSM_V4L2_EXT_CAPTURE_MODE_RDI1:
 		return OUTPUT_TYPE_R1;
+	case MSM_V4L2_EXT_CAPTURE_MODE_RDI2:
+		return OUTPUT_TYPE_R2;
+	case MSM_V4L2_EXT_CAPTURE_MODE_AEC:
+		return OUTPUT_TYPE_SAEC;
+	case MSM_V4L2_EXT_CAPTURE_MODE_AF:
+		return OUTPUT_TYPE_SAFC;
+	case MSM_V4L2_EXT_CAPTURE_MODE_AWB:
+		return OUTPUT_TYPE_SAWB;
+	case MSM_V4L2_EXT_CAPTURE_MODE_IHIST:
+		return OUTPUT_TYPE_IHST;
+	case MSM_V4L2_EXT_CAPTURE_MODE_CSTA:
+		return OUTPUT_TYPE_CSTA;
 	case MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT:
 	case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
 	default:
@@ -701,17 +727,22 @@
 				struct v4l2_streamparm *a)
 {
 	int rc = 0;
+	int is_bayer_sensor = 0;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+	SET_DEVID_MODE(pcam_inst->inst_handle, pcam_inst->pcam->vnode_id);
 	SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
 	SET_VIDEO_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
 	pcam_inst->pcam->dev_inst_map[pcam_inst->image_mode] = pcam_inst;
 	pcam_inst->path = msm_vidbuf_get_path(pcam_inst->image_mode);
+	if (pcam_inst->pcam->sdata->sensor_type == BAYER_SENSOR)
+		is_bayer_sensor = 1;
 	rc = msm_cam_server_config_interface_map(pcam_inst->image_mode,
-			pcam_inst->pcam->mctl_handle);
-	D("%spath=%d,rc=%d\n", __func__,
+			pcam_inst->pcam->mctl_handle, pcam_inst->pcam->vnode_id,
+			is_bayer_sensor);
+	D("%s path=%d, rc=%d\n", __func__,
 		pcam_inst->path, rc);
 	return rc;
 }
@@ -730,7 +761,7 @@
 		return -EINVAL;
 	if (sub->type == V4L2_EVENT_ALL)
 		sub->type = V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_EVENT;
-	rc = v4l2_event_subscribe(fh, sub, 50);
+	rc = v4l2_event_subscribe(fh, sub, 30);
 	if (rc < 0)
 		D("%s: failed for evtType = 0x%x, rc = %d\n",
 						__func__, sub->type, rc);
@@ -761,6 +792,7 @@
 {
 	int rc = -EINVAL;
 	struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(file);
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 
 	switch (cmd) {
@@ -770,6 +802,47 @@
 	case MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL:
 		rc = msm_camera_v4l2_private_g_ctrl(file, fh, ioctl_ptr);
 		break;
+	case MSM_CAM_V4L2_IOCTL_PRIVATE_GENERAL:
+		rc = msm_camera_v4l2_private_general(file, fh, ioctl_ptr);
+		break;
+	case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+		struct msm_queue_cmd *event_cmd;
+		void *payload;
+		mutex_lock(&pcam->event_lock);
+		event_cmd = msm_dequeue(&pcam->eventData_q, list_eventdata);
+		if (!event_cmd) {
+			pr_err("%s: No event payload\n", __func__);
+			rc = -EINVAL;
+			mutex_unlock(&pcam->event_lock);
+			return rc;
+		}
+		payload = event_cmd->command;
+		if (event_cmd->trans_code != ioctl_ptr->trans_code) {
+			pr_err("%s: Events don't match\n", __func__);
+			kfree(payload);
+			kfree(event_cmd);
+			rc = -EINVAL;
+			mutex_unlock(&pcam->event_lock);
+			break;
+		}
+		if (ioctl_ptr->len > 0) {
+			if (copy_to_user(ioctl_ptr->ioctl_ptr, payload,
+				 ioctl_ptr->len)) {
+				pr_err("%s Copy to user failed for cmd %d",
+					__func__, cmd);
+				kfree(payload);
+				kfree(event_cmd);
+				rc = -EINVAL;
+				mutex_unlock(&pcam->event_lock);
+				break;
+			}
+		}
+		kfree(payload);
+		kfree(event_cmd);
+		mutex_unlock(&pcam->event_lock);
+		rc = 0;
+		break;
+	}
 	default:
 		pr_err("%s Unsupported ioctl cmd %d ", __func__, cmd);
 		break;
@@ -868,12 +941,11 @@
 			pcam_inst->my_index,
 			pcam->vnode_id, pcam->use_count);
 	pcam->use_count++;
-	D("%s use_count %d\n", __func__, pcam->use_count);
+	D("%s Inst %p use_count %d\n", __func__, pcam_inst, pcam->use_count);
 	if (pcam->use_count == 1) {
 		server_q_idx = msm_find_free_queue();
 		if (server_q_idx < 0)
 			return server_q_idx;
-
 		rc = msm_server_begin_session(pcam, server_q_idx);
 		if (rc < 0) {
 			pr_err("%s error starting server session ", __func__);
@@ -908,6 +980,8 @@
 
 		msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
 			pcam->pvdev);
+		mutex_init(&pcam->event_lock);
+		msm_queue_init(&pcam->eventData_q, "eventData");
 	}
 	pcam_inst->vbqueue_initialized = 0;
 	rc = 0;
@@ -930,6 +1004,7 @@
 	return rc;
 
 msm_send_open_server_failed:
+	msm_drain_eventq(&pcam->eventData_q);
 	msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
 
 	if (pmctl->mctl_release)
@@ -1071,11 +1146,17 @@
 	D("%s index %d nodeid %d count %d\n", __func__, pcam_inst->my_index,
 		pcam->vnode_id, pcam->use_count);
 	pcam->dev_inst[pcam_inst->my_index] = NULL;
-	if (pcam_inst->my_index == 0)
+	if (pcam_inst->my_index == 0) {
+		mutex_lock(&pcam->event_lock);
+		msm_drain_eventq(&pcam->eventData_q);
+		mutex_unlock(&pcam->event_lock);
+		mutex_destroy(&pcam->event_lock);
 		msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
+	}
 
 	CLR_VIDEO_INST_IDX(pcam_inst->inst_handle);
 	CLR_IMG_MODE(pcam_inst->inst_handle);
+	CLR_DEVID_MODE(pcam_inst->inst_handle);
 	mutex_unlock(&pcam_inst->inst_lock);
 	mutex_destroy(&pcam_inst->inst_lock);
 	kfree(pcam_inst);
@@ -1135,24 +1216,60 @@
 	unsigned int cmd, unsigned long evt)
 {
 	struct v4l2_event v4l2_ev;
+	struct v4l2_event_and_payload evt_payload;
 	struct msm_cam_v4l2_device *pcam = NULL;
-
+	int rc = 0;
+	struct msm_queue_cmd *event_qcmd;
+	void *payload;
 	if (!mctl) {
 		pr_err("%s: mctl is NULL\n", __func__);
 		return -EINVAL;
 	}
 
-	if (copy_from_user(&v4l2_ev, (void __user *)evt,
-		sizeof(struct v4l2_event))) {
+	if (copy_from_user(&evt_payload, (void __user *)evt,
+		sizeof(struct v4l2_event_and_payload))) {
 		ERR_COPY_FROM_USER();
 		return -EFAULT;
 	}
 
+	v4l2_ev = evt_payload.evt;
 	v4l2_ev.id = 0;
 	pcam = mctl->pcam_ptr;
 	ktime_get_ts(&v4l2_ev.timestamp);
+	if (evt_payload.payload_length > 0 && evt_payload.payload != NULL) {
+		mutex_lock(&pcam->event_lock);
+		event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+		if (!event_qcmd) {
+			pr_err("%s Insufficient memory. return", __func__);
+			rc = -ENOMEM;
+			goto event_qcmd_alloc_fail;
+		}
+		payload = kzalloc(evt_payload.payload_length, GFP_KERNEL);
+		if (!payload) {
+			pr_err("%s Insufficient memory. return", __func__);
+			rc = -ENOMEM;
+			goto payload_alloc_fail;
+		}
+		if (copy_from_user(payload,
+				(void __user *)evt_payload.payload,
+				evt_payload.payload_length)) {
+			ERR_COPY_FROM_USER();
+			rc = -EFAULT;
+			goto copy_from_user_failed;
+		}
+		event_qcmd->command = payload;
+		event_qcmd->trans_code = evt_payload.transaction_id;
+		msm_enqueue(&pcam->eventData_q, &event_qcmd->list_eventdata);
+		mutex_unlock(&pcam->event_lock);
+	}
 	v4l2_event_queue(pcam->pvdev, &v4l2_ev);
-	return 0;
+	return rc;
+copy_from_user_failed:
+	kfree(payload);
+payload_alloc_fail:
+	kfree(event_qcmd);
+event_qcmd_alloc_fail:
+	return rc;
 }
 
 
@@ -1169,11 +1286,21 @@
 {
 	int rc = -ENOMEM;
 	struct video_device *pvdev = NULL;
-	struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
+	struct i2c_client *client = NULL;
+	struct platform_device *pdev = NULL;
 	D("%s\n", __func__);
 
 	/* first register the v4l2 device */
-	pcam->v4l2_dev.dev = &client->dev;
+	if (pcam->sensor_sdev->flags & V4L2_SUBDEV_FL_IS_I2C) {
+		client = v4l2_get_subdevdata(pcam->sensor_sdev);
+		pcam->v4l2_dev.dev = &client->dev;
+		pcam->media_dev.dev = &client->dev;
+	} else {
+		pdev = v4l2_get_subdevdata(pcam->sensor_sdev);
+		pcam->v4l2_dev.dev = &pdev->dev;
+		pcam->media_dev.dev = &pdev->dev;
+	}
+
 	rc = v4l2_device_register(pcam->v4l2_dev.dev, &pcam->v4l2_dev);
 	if (rc < 0)
 		return -EINVAL;
@@ -1190,7 +1317,6 @@
 
 	strlcpy(pcam->media_dev.model, QCAMERA_NAME,
 			sizeof(pcam->media_dev.model));
-	pcam->media_dev.dev = &client->dev;
 	rc = media_device_register(&pcam->media_dev);
 	pvdev->v4l2_dev = &pcam->v4l2_dev;
 	pcam->v4l2_dev.mdev = &pcam->media_dev;
@@ -1249,7 +1375,7 @@
 
 	D("%s called\n", __func__);
 
-	if (!actuator_info)
+	if (!actuator_info || !actuator_info->board_info)
 		goto probe_fail;
 
 	adapter = i2c_get_adapter(actuator_info->bus_id);
@@ -1292,7 +1418,7 @@
 
 	D("%s called\n", __func__);
 
-	if (!eeprom_info)
+	if (!eeprom_info || !eeprom_info->board_info)
 		goto probe_fail;
 
 	adapter = i2c_get_adapter(eeprom_info->bus_id);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 8c644b8..cb59d68 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -31,8 +31,9 @@
 #include <media/videobuf2-msm-mem.h>
 #include <media/msm_isp.h>
 #include <mach/camera.h>
+#include <mach/iommu.h>
 #include <media/msm_isp.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/iommu.h>
 #include <media/msm_gestures.h>
 
@@ -57,6 +58,7 @@
 #define MSM_VPE_DRV_NAME "msm_vpe"
 #define MSM_GEMINI_DRV_NAME "msm_gemini"
 #define MSM_MERCURY_DRV_NAME "msm_mercury"
+#define MSM_JPEG_DRV_NAME "msm_jpeg"
 #define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
 #define MSM_IRQ_ROUTER_DRV_NAME "msm_cam_irq_router"
 #define MSM_CPP_DRV_NAME "msm_cpp"
@@ -140,22 +142,22 @@
 	uint32_t  frameCounter;
 };
 
+struct rdi_count_msg {
+	uint32_t rdi_interface;
+	uint32_t count;
+};
+
 /* message id for v4l2_subdev_notify*/
 enum msm_camera_v4l2_subdev_notify {
-	NOTIFY_CID_CHANGE, /* arg = msm_camera_csid_params */
 	NOTIFY_ISP_MSG_EVT, /* arg = enum ISP_MESSAGE_ID */
 	NOTIFY_VFE_MSG_OUT, /* arg = struct isp_msg_output */
 	NOTIFY_VFE_MSG_STATS,  /* arg = struct isp_msg_stats */
 	NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
 	NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
-	NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
-	NOTIFY_VPE_MSG_EVT,
 	NOTIFY_VFE_CAMIF_ERROR,
-	NOTIFY_VFE_SOF_COUNT, /*arg = int*/
+	NOTIFY_VFE_PIX_SOF_COUNT, /*arg = int*/
+	NOTIFY_AXI_RDI_SOF_COUNT, /*arg = struct rdi_count_msg*/
 	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_IRQ,
 	NOTIFY_AXI_IRQ,
 	NOTIFY_GESTURE_EVT, /* arg = v4l2_event */
@@ -204,10 +206,36 @@
 	enum v4l2_colorspace colorspace;
 };
 
+struct msm_cam_return_frame_info {
+	int dirty;
+	int node_type;
+	struct timeval timestamp;
+};
+
+struct msm_cam_timestamp {
+	uint8_t present;
+	struct timeval timestamp;
+};
+
+struct msm_cam_buf_map_info {
+	int fd;
+	uint32_t data_offset;
+	unsigned long paddr;
+	unsigned long len;
+	struct file *file;
+	struct ion_handle *handle;
+};
+
+struct msm_cam_meta_frame {
+	struct msm_pp_frame frame;
+	/* Mapping information per plane */
+	struct msm_cam_buf_map_info map[VIDEO_MAX_PLANES];
+};
+
 struct msm_mctl_pp_frame_info {
 	int user_cmd;
-	struct msm_pp_frame src_frame;
-	struct msm_pp_frame dest_frame;
+	struct msm_cam_meta_frame src_frame;
+	struct msm_cam_meta_frame dest_frame;
 	struct msm_mctl_pp_frame_cmd pp_frame_cmd;
 	struct msm_cam_media_controller *p_mctl;
 };
@@ -245,6 +273,10 @@
 	int (*mctl_vbqueue_init)(struct msm_cam_v4l2_dev_inst *pcam,
 				struct vb2_queue *q, enum v4l2_buf_type type);
 	int (*mctl_ufmt_init)(struct msm_cam_media_controller *p_mctl);
+	int (*isp_config)(struct msm_cam_media_controller *pmctl,
+		 unsigned int cmd, unsigned long arg);
+	int (*isp_notify)(struct msm_cam_media_controller *pmctl,
+		struct v4l2_subdev *sd, unsigned int notification, void *arg);
 
 	/* the following reflect the HW topology information*/
 	struct v4l2_subdev *sensor_sdev; /* sensor sub device */
@@ -256,10 +288,10 @@
 	struct v4l2_subdev *gemini_sdev; /* gemini sub device */
 	struct v4l2_subdev *vpe_sdev; /* vpe sub device */
 	struct v4l2_subdev *axi_sdev; /* axi sub device */
+	struct v4l2_subdev *vfe_sdev; /* vfe sub device */
 	struct v4l2_subdev *eeprom_sdev; /* eeprom sub device */
 	struct v4l2_subdev *cpp_sdev;/*cpp sub device*/
 
-	struct msm_isp_ops *isp_sdev;    /* isp sub device : camif/VFE */
 	struct msm_cam_config_dev *config_device;
 
 	/*mctl session control information*/
@@ -285,21 +317,10 @@
 	uint32_t ping_imem_cbcr;
 	uint32_t pong_imem_y;
 	uint32_t pong_imem_cbcr;
-};
 
-/* abstract camera device represents a VFE and connected sensor */
-struct msm_isp_ops {
-	char *config_dev_name;
-
-	int (*isp_config)(struct msm_cam_media_controller *pmctl,
-		 unsigned int cmd, unsigned long arg);
-	int (*isp_notify)(struct v4l2_subdev *sd,
-		unsigned int notification, void *arg);
-	int (*isp_pp_cmd)(struct msm_cam_media_controller *pmctl,
-		 struct msm_mctl_pp_cmd, void *data);
-
-	/* vfe subdevice */
-	struct v4l2_subdev *sd;
+	/*IOMMU domain for this session*/
+	int domain_num;
+	struct iommu_domain *domain;
 };
 
 struct msm_isp_buf_info {
@@ -312,7 +333,7 @@
 	uint32_t data_offset;
 };
 
-#define MSM_DEV_INST_MAX                    16
+#define MSM_DEV_INST_MAX                    24
 struct msm_cam_v4l2_dev_inst {
 	struct v4l2_fh  eventHandle;
 	struct vb2_queue vid_bufq;
@@ -376,6 +397,9 @@
 	struct v4l2_subdev *act_sdev; /* actuator sub device */
 	struct v4l2_subdev *eeprom_sdev; /* actuator sub device */
 	struct msm_camera_sensor_info *sdata;
+
+	struct msm_device_queue eventData_q; /*payload for events sent to app*/
+	struct mutex event_lock;
 };
 
 static inline struct msm_cam_v4l2_device *to_pcam(
@@ -399,6 +423,8 @@
 	struct msm_cam_media_controller *p_mctl;
 	struct msm_mem_map_info mem_map;
 	int dev_num;
+	int domain_num;
+	struct iommu_domain *domain;
 };
 
 struct msm_cam_subdev_info {
@@ -489,12 +515,14 @@
 };
 
 struct interface_map {
-	/* The interafce a particular stream belongs to.
+	/* The interface a particular stream belongs to.
 	 * PIX0, RDI0, RDI1, or RDI2
 	 */
 	int interface;
-	/* The handle of the mctl intstance interface runs on */
+	/* The handle of the mctl instance, interface runs on */
 	uint32_t mctl_handle;
+	int vnode_id;
+	int is_bayer_sensor;
 };
 
 /* abstract camera server device for all sensor successfully probed*/
@@ -513,6 +541,8 @@
 	struct msm_cam_config_dev_info config_info;
 	/* active working camera device - only one allowed at this time*/
 	struct msm_cam_v4l2_device *pcam_active[MAX_NUM_ACTIVE_CAMERA];
+	/* save the opened pcam for finding the mctl when doing buf lookup */
+	struct msm_cam_v4l2_device *opened_pcam[MAX_NUM_ACTIVE_CAMERA];
 	/* number of camera devices opened*/
 	atomic_t number_pcam_active;
 	struct v4l2_queue_util server_command_queue;
@@ -558,6 +588,10 @@
 	 * dispatch the irq to the corresponding subdev. */
 	struct v4l2_subdev *subdev_table[MSM_CAM_HW_MAX];
 	struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
+
+    /*IOMMU domain (Page table)*/
+	int domain_num;
+	struct iommu_domain *domain;
 };
 
 enum msm_cam_buf_lookup_type {
@@ -574,11 +608,13 @@
 
 /* ISP related functions */
 void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
+int msm_isp_config(struct msm_cam_media_controller *pmctl,
+			 unsigned int cmd, unsigned long arg);
+int msm_isp_notify(struct msm_cam_media_controller *pmctl,
+	struct v4l2_subdev *sd, unsigned int notification, void *arg);
 /*
 int msm_isp_register(struct msm_cam_v4l2_device *pcam);
 */
-int msm_isp_register(struct msm_cam_server_dev *psvr);
-void msm_isp_unregister(struct msm_cam_server_dev *psvr);
 int msm_sensor_register(struct v4l2_subdev *);
 int msm_isp_init_module(int g_num_config_nodes);
 
@@ -592,7 +628,8 @@
 	uint32_t frame_id);
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
 	struct msm_cam_buf_handle *buf_handle,
-	struct msm_free_buf *frame, int dirty, int node_type);
+	struct msm_free_buf *frame,
+	struct msm_cam_return_frame_info *ret_frame);
 int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
 	struct msm_cam_v4l2_dev_inst *pcam_inst,
 	struct msm_cam_buf_handle *buf_handle,
@@ -602,9 +639,9 @@
 	struct msm_free_buf *free_buf);
 /*Memory(PMEM) functions*/
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
-	struct ion_client *client);
+	struct ion_client *client, int domain_num);
 int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
-	struct ion_client *client);
+	struct ion_client *client, int domain_num);
 int msm_pmem_region_get_phy_addr(struct hlist_head *ptype,
 	struct msm_mem_map_info *mem_map, int32_t *phyaddr);
 uint8_t msm_pmem_region_lookup(struct hlist_head *ptype,
@@ -626,7 +663,7 @@
 	struct msm_vfe_cfg_cmd *cfgcmd, void *data);
 int msm_vpe_subdev_init(struct v4l2_subdev *sd);
 int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
-void msm_vpe_subdev_release(void);
+void msm_vpe_subdev_release(struct v4l2_subdev *sd);
 void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
 int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
 	int msg_type);
@@ -634,6 +671,8 @@
 	int msg_type, uint32_t y_phy, uint32_t frame_id);
 int msm_mctl_pp_ioctl(struct msm_cam_media_controller *p_mctl,
 	unsigned int cmd, unsigned long arg);
+int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
+	struct msm_mctl_pp_frame_info *pp_frame_info);
 int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
 	int out_type, int node_type);
 struct msm_frame_buffer *msm_mctl_buf_find(
@@ -671,6 +710,10 @@
 	struct msm_cam_buf_handle *buf_handle);
 int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
 	int image_mode, struct msm_frame_buffer *buf);
+int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num);
+int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num);
 int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
 void msm_release_ion_client(struct kref *ref);
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index 2f1d1ab..dce3630 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -34,7 +34,7 @@
 #include <mach/camera.h>
 #include <linux/syscalls.h>
 #include <linux/hrtimer.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/cpuidle.h>
 DEFINE_MUTEX(ctrl_cmd_lock);
diff --git a/drivers/media/video/msm/msm_camirq_router.c b/drivers/media/video/msm/msm_camirq_router.c
index de0ff48..25a561f 100644
--- a/drivers/media/video/msm/msm_camirq_router.c
+++ b/drivers/media/video/msm/msm_camirq_router.c
@@ -242,8 +242,9 @@
 
 static int __exit irqrouter_exit(struct platform_device *pdev)
 {
-	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
-	struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+	struct v4l2_subdev *subdev = dev_get_drvdata(&pdev->dev);
+	struct irqrouter_ctrl_type *irqrouter_ctrl =
+		v4l2_get_subdevdata(subdev);
 	kfree(irqrouter_ctrl);
 	return 0;
 }
diff --git a/drivers/media/video/msm/msm_gesture.c b/drivers/media/video/msm/msm_gesture.c
index c97509b..5777cb5 100644
--- a/drivers/media/video/msm/msm_gesture.c
+++ b/drivers/media/video/msm/msm_gesture.c
@@ -353,9 +353,7 @@
 	v4l2_ctrl_new_custom(&p_gesture_ctrl->ctrl_handler,
 		&msm_gesture_ctrl_filter, p_gesture_ctrl);
 	if (p_gesture_ctrl->ctrl_handler.error) {
-#ifdef CONFIG_MSM_CAMERA_DEBUG
 		int err = p_gesture_ctrl->ctrl_handler.error;
-#endif
 		D("%s: error adding control %d", __func__, err);
 		p_gesture_ctrl->ctrl_handler.error = 0;
 	}
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 3d94afd..9c0ab9a 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -73,7 +73,7 @@
 	struct msm_camvfe_params vfe_params;
 	int rc;
 
-	cfgcmd.cmd_type = CMD_VFE_SOF_COUNT_UPDATE;
+	cfgcmd.cmd_type = CMD_VFE_PIX_SOF_COUNT_UPDATE;
 	cfgcmd.value = NULL;
 	vfe_params.vfe_cfg = &cfgcmd;
 	vfe_params.data = arg;
@@ -86,7 +86,8 @@
 {
 	int image_mode;
 	uint32_t vfe_output_mode = pmctl->vfe_output_mode;
-	vfe_output_mode &= ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+	vfe_output_mode &= ~(VFE_OUTPUTS_RDI0|
+		VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2);
 	if (vfe_msg == VFE_MSG_OUTPUT_PRIMARY) {
 		switch (vfe_output_mode) {
 		case VFE_OUTPUTS_MAIN_AND_PREVIEW:
@@ -148,6 +149,11 @@
 			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_RDI1;
 		else
 			image_mode = -1;
+	} else if (vfe_msg == VFE_MSG_OUTPUT_TERTIARY3) {
+		if (pmctl->vfe_output_mode & VFE_OUTPUTS_RDI2)
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_RDI2;
+		else
+			image_mode = -1;
 	} else
 		image_mode = -1;
 
@@ -156,15 +162,14 @@
 	return image_mode;
 }
 
-static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg)
+static int msm_isp_notify_VFE_BUF_EVT(struct msm_cam_media_controller *pmctl,
+					struct v4l2_subdev *sd, void *arg)
 {
 	int rc = -EINVAL;
 	struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
 	struct msm_free_buf free_buf, temp_free_buf;
 	struct msm_camvfe_params vfe_params;
 	struct msm_vfe_cfg_cmd cfgcmd;
-	struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	struct msm_frame_info *frame_info =
 		(struct msm_frame_info *)vdata->evt_msg.data;
@@ -172,7 +177,7 @@
 	struct msm_cam_buf_handle buf_handle;
 
 	if (!pcam) {
-		pr_debug("%s pcam is null. return\n", __func__);
+		pr_err("%s pcam is null. return\n", __func__);
 		msm_isp_sync_free(vdata);
 		return rc;
 	}
@@ -275,14 +280,12 @@
 /*
  * This function executes in interrupt context.
  */
-static int msm_isp_notify_vfe(struct v4l2_subdev *sd,
-	unsigned int notification,  void *arg)
+static int msm_isp_notify_vfe(struct msm_cam_media_controller *pmctl,
+	struct v4l2_subdev *sd,	unsigned int notification,  void *arg)
 {
 	int rc = 0;
 	struct v4l2_event v4l2_evt;
 	struct msm_isp_event_ctrl *isp_event;
-	struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_free_buf buf;
 
 	if (!pmctl) {
@@ -292,9 +295,9 @@
 	}
 
 	if (notification == NOTIFY_VFE_BUF_EVT)
-		return msm_isp_notify_VFE_BUF_EVT(sd, arg);
+		return msm_isp_notify_VFE_BUF_EVT(pmctl, sd, arg);
 
-	if (notification == NOTIFY_VFE_SOF_COUNT)
+	if (notification == NOTIFY_VFE_PIX_SOF_COUNT)
 		return msm_isp_notify_VFE_SOF_COUNT_EVT(sd, arg);
 
 	isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC);
@@ -353,7 +356,9 @@
 			case MSG_ID_OUTPUT_TERTIARY2:
 				msgid = VFE_MSG_OUTPUT_TERTIARY2;
 				break;
-
+			case MSG_ID_OUTPUT_TERTIARY3:
+				msgid = VFE_MSG_OUTPUT_TERTIARY3;
+				break;
 			default:
 				pr_err("%s: Invalid VFE output id: %d\n",
 					   __func__, isp_output->output_id);
@@ -493,11 +498,12 @@
 	return rc;
 }
 
-static int msm_isp_notify(struct v4l2_subdev *sd,
-	unsigned int notification, void *arg)
+int msm_isp_notify(struct msm_cam_media_controller *pmctl,
+	struct v4l2_subdev *sd,	unsigned int notification, void *arg)
 {
-	return msm_isp_notify_vfe(sd, notification, arg);
+	return msm_isp_notify_vfe(pmctl, sd, notification, arg);
 }
+EXPORT_SYMBOL(msm_isp_notify);
 
 static int msm_config_vfe(struct v4l2_subdev *sd,
 	struct msm_cam_media_controller *mctl, void __user *arg)
@@ -559,6 +565,7 @@
 	case CMD_AXI_STOP:
 	case CMD_AXI_CFG_TERT1:
 	case CMD_AXI_CFG_TERT2:
+	case CMD_AXI_CFG_TERT3:
 		/* Dont need to pass buffer information.
 		 * subdev will get the buffer from media
 		 * controller free queue.
@@ -642,6 +649,7 @@
 {
 	struct msm_vfe_cfg_cmd cfgcmd;
 	int rc = 0;
+	v4l2_set_subdev_hostdata(sd, mctl);
 	switch (cmd) {
 	case MSM_CAM_IOCTL_STATS_REQBUF: {
 		struct msm_stats_reqbuf reqbuf;
@@ -703,14 +711,18 @@
 	return rc;
 }
 /* config function simliar to origanl msm_ioctl_config*/
-static int msm_isp_config(struct msm_cam_media_controller *pmctl,
+int msm_isp_config(struct msm_cam_media_controller *pmctl,
 			 unsigned int cmd, unsigned long arg)
 {
 
 	int rc = -EINVAL;
 	void __user *argp = (void __user *)arg;
-	struct v4l2_subdev *sd = pmctl->isp_sdev->sd;
-
+	struct v4l2_subdev *sd;
+	if (!pmctl->vfe_sdev) {
+		pr_err("%s vfe subdev is NULL\n", __func__);
+		return -ENXIO;
+	}
+	sd = pmctl->vfe_sdev;
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 	switch (cmd) {
 	case MSM_CAM_IOCTL_CONFIG_VFE:
@@ -742,47 +754,7 @@
 
 	return rc;
 }
-
-static struct msm_isp_ops isp_subdev[MSM_MAX_CAMERA_CONFIGS];
-
-/**/
-int msm_isp_init_module(int g_num_config_nodes)
-{
-	int i = 0;
-
-	for (i = 0; i < g_num_config_nodes; i++) {
-		isp_subdev[i].isp_config = msm_isp_config;
-		isp_subdev[i].isp_notify = msm_isp_notify;
-	}
-	return 0;
-}
-EXPORT_SYMBOL(msm_isp_init_module);
-
-/*
-*/
-int msm_isp_register(struct msm_cam_server_dev *psvr)
-{
-	int i = 0;
-
-	D("%s\n", __func__);
-
-	BUG_ON(!psvr);
-
-	/* Initialize notify function for v4l2_dev */
-	for (i = 0; i < psvr->config_info.num_config_nodes; i++)
-		psvr->isp_subdev[i] = &(isp_subdev[i]);
-
-	return 0;
-}
-EXPORT_SYMBOL(msm_isp_register);
-
-/**/
-void msm_isp_unregister(struct msm_cam_server_dev *psvr)
-{
-	int i = 0;
-	for (i = 0; i < psvr->config_info.num_config_nodes; i++)
-		psvr->isp_subdev[i] = NULL;
-}
+EXPORT_SYMBOL(msm_isp_config);
 
 int msm_isp_subdev_ioctl(struct v4l2_subdev *isp_subdev,
 	struct msm_vfe_cfg_cmd *cfgcmd, void *data)
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index cb35a56..3c8563b 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -138,7 +138,38 @@
 	.pxlcode	= V4L2_MBUS_FMT_YUYV8_2X8, /* YUV sensor */
 	.colorspace = V4L2_COLORSPACE_JPEG,
 	},
-
+	{
+	.name	   = "SAEC",
+	.depth	  = 16,
+	.bitsperpxl = 16,
+	.fourcc	 = V4L2_PIX_FMT_STATS_AE,
+	.pxlcode	= V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
+	{
+	.name	   = "SAWB",
+	.depth	  = 16,
+	.bitsperpxl = 16,
+	.fourcc	 = V4L2_PIX_FMT_STATS_AWB,
+	.pxlcode	= V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
+	{
+	.name	   = "SAFC",
+	.depth	  = 16,
+	.bitsperpxl = 16,
+	.fourcc	 = V4L2_PIX_FMT_STATS_AF,
+	.pxlcode	= V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
+	{
+	.name      = "SHST",
+	.depth    = 16,
+	.bitsperpxl = 16,
+	.fourcc  = V4L2_PIX_FMT_STATS_IHST,
+	.pxlcode        = V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
 };
 
 static int msm_get_sensor_info(
@@ -211,6 +242,34 @@
 	return 0;
 }
 
+static int msm_mctl_add_intf_to_mctl_map(
+	struct msm_cam_media_controller *p_mctl,
+	struct intf_mctl_mapping_cfg *intf_map)
+{
+
+	int i;
+	int rc = 0;
+	uint32_t mctl_handle;
+
+	mctl_handle = msm_cam_find_handle_from_mctl_ptr(p_mctl);
+	if (mctl_handle == 0) {
+		pr_err("%s Error in finding handle from mctl_ptr, rc = %d",
+			__func__, rc);
+		return -EFAULT;
+	}
+	for (i = 0; i < intf_map->num_entries; i++) {
+		rc = msm_cam_server_config_interface_map(
+			intf_map->image_modes[i], mctl_handle,
+			intf_map->vnode_id, intf_map->is_bayer_sensor);
+		if (rc < 0) {
+				pr_err("%s Error in INTF MAPPING rc = %d",
+					__func__, rc);
+				return -EINVAL;
+		}
+	}
+	return rc;
+}
+
 /* called by the server or the config nodes to handle user space
 	commands*/
 static int msm_mctl_cmd(struct msm_cam_media_controller *p_mctl,
@@ -388,6 +447,16 @@
 		}
 		break;
 	}
+	case MSM_CAM_IOCTL_INTF_MCTL_MAPPING_CFG: {
+		struct intf_mctl_mapping_cfg intf_map;
+		if (copy_from_user(&intf_map, argp, sizeof(intf_map))) {
+			ERR_COPY_FROM_USER();
+			rc = -EFAULT;
+		} else {
+			rc = msm_mctl_add_intf_to_mctl_map(p_mctl, &intf_map);
+		}
+		break;
+	}
 	case MSM_CAM_IOCTL_PICT_PP:
 		rc = msm_mctl_set_pp_key(p_mctl, (void __user *)arg);
 		break;
@@ -418,21 +487,57 @@
 		break;
 			/* ISFIF config*/
 	case MSM_CAM_IOCTL_AXI_CONFIG:
-		if (p_mctl->axi_sdev)
+		if (p_mctl->axi_sdev) {
+			v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
 			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
 				VIDIOC_MSM_AXI_CFG, (void __user *)arg);
-		else
-			rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
+		} else
+			rc = p_mctl->isp_config(p_mctl, cmd, arg);
 		break;
 	case MSM_CAM_IOCTL_ISPIF_IO_CFG:
 		rc = v4l2_subdev_call(p_mctl->ispif_sdev,
 			core, ioctl, VIDIOC_MSM_ISPIF_CFG, argp);
 		break;
+
+	case MSM_CAM_IOCTL_CSIPHY_IO_CFG:
+		if (p_mctl->csiphy_sdev)
+			rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
+				core, ioctl, VIDIOC_MSM_CSIPHY_CFG, argp);
+		break;
+
+	case MSM_CAM_IOCTL_CSIC_IO_CFG:
+		if (p_mctl->csic_sdev)
+			rc = v4l2_subdev_call(p_mctl->csic_sdev,
+				core, ioctl, VIDIOC_MSM_CSIC_CFG, argp);
+		break;
+
+	case MSM_CAM_IOCTL_CSID_IO_CFG:
+		if (p_mctl->csid_sdev)
+			rc = v4l2_subdev_call(p_mctl->csid_sdev,
+				core, ioctl, VIDIOC_MSM_CSID_CFG, argp);
+		break;
+
+	case MSM_CAM_IOCTL_AXI_INIT:
+		if (p_mctl->axi_sdev) {
+			v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_INIT, (void __user *)arg);
+		}
+		break;
+
+	case MSM_CAM_IOCTL_AXI_RELEASE:
+		if (p_mctl->axi_sdev) {
+			v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_RELEASE, NULL);
+		}
+		break;
+
 	default:
 		/* ISP config*/
 		D("%s:%d: go to default. Calling msm_isp_config\n",
 			__func__, __LINE__);
-		rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
+		rc = p_mctl->isp_config(p_mctl, cmd, arg);
 		break;
 	}
 	D("%s: !!! cmd = %d, rc = %d\n",
@@ -459,8 +564,6 @@
 	/* open sub devices - once only*/
 	if (!p_mctl->opencnt) {
 		struct msm_sensor_csi_info csi_info;
-		uint32_t csid_version;
-		uint32_t csic_version;
 		wake_lock(&p_mctl->wake_lock);
 
 		csid_core = camdev->csid_core;
@@ -486,39 +589,10 @@
 			goto act_power_up_failed;
 		}
 
-		if (p_mctl->csiphy_sdev) {
-			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 csiphy_init_failed;
-			}
-		}
-
-		if (p_mctl->csid_sdev) {
-			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 csid_init_failed;
-			}
-			csi_info.is_csic = 0;
-		}
-
-		if (p_mctl->csic_sdev) {
-			rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
-				VIDIOC_MSM_CSIC_INIT, &csic_version);
-			if (rc < 0) {
-				pr_err("%s: csic initialization failed %d\n",
-					__func__, rc);
-				goto csic_init_failed;
-			}
+		if (p_mctl->csic_sdev)
 			csi_info.is_csic = 1;
-		}
-
-		csi_info.csid_version = csid_version;
+		else
+			csi_info.is_csic = 0;
 		rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
 				VIDIOC_MSM_SENSOR_CSID_INFO, &csi_info);
 		if (rc < 0) {
@@ -541,26 +615,6 @@
 	return rc;
 
 msm_csi_version:
-	if (p_mctl->csic_sdev)
-		if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
-			VIDIOC_MSM_CSIC_RELEASE, NULL) < 0)
-			pr_err("%s: csic release failed %d\n", __func__, rc);
-csic_init_failed:
-	if (p_mctl->csid_sdev)
-		if (v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
-			VIDIOC_MSM_CSID_RELEASE, NULL) < 0)
-			pr_err("%s: csid release failed %d\n", __func__, rc);
-csid_init_failed:
-	if (p_mctl->csiphy_sdev)
-		if (v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
-			VIDIOC_MSM_CSIPHY_RELEASE,
-			sinfo->sensor_platform_info->csi_lane_params) < 0)
-			pr_err("%s: csiphy release failed %d\n", __func__, rc);
-csiphy_init_failed:
-	if (p_mctl->act_sdev)
-		if (v4l2_subdev_call(p_mctl->act_sdev, core,
-			s_power, 0) < 0)
-			pr_err("%s: act power down failed:%d\n", __func__, rc);
 act_power_up_failed:
 	if (v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0) < 0)
 		pr_err("%s: sensor powerdown failed: %d\n", __func__, rc);
@@ -576,7 +630,6 @@
 	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;
-
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
 		VIDIOC_MSM_SENSOR_RELEASE, NULL);
 
@@ -591,6 +644,7 @@
 	}
 
 	if (p_mctl->axi_sdev) {
+		v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
 		v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
 			VIDIOC_MSM_AXI_RELEASE, NULL);
 	}
@@ -708,6 +762,9 @@
 	pmctl->mctl_open = msm_mctl_open;
 	pmctl->mctl_cmd = msm_mctl_cmd;
 	pmctl->mctl_release = msm_mctl_release;
+	pmctl->isp_config = msm_isp_config;
+	pmctl->isp_notify = msm_isp_notify;
+
 	/* init mctl buf */
 	msm_mctl_buf_init(pcam);
 	memset(&pmctl->pp_info, 0, sizeof(pmctl->pp_info));
@@ -897,6 +954,7 @@
 	pcam->mctl_node.dev_inst[pcam_inst->my_index] = NULL;
 	msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
 	CLR_MCTLPP_INST_IDX(pcam_inst->inst_handle);
+	CLR_DEVID_MODE(pcam_inst->inst_handle);
 	CLR_IMG_MODE(pcam_inst->inst_handle);
 	mutex_unlock(&pcam_inst->inst_lock);
 	mutex_destroy(&pcam_inst->inst_lock);
@@ -994,7 +1052,7 @@
 					__func__, pcam_inst);
 			rc = -EFAULT;
 		}
-		D("%s inst %p got plane info: num_planes = %d,"
+		D("%s inst %p got plane info: num_planes = %d," \
 				"plane size = %ld %ld ", __func__, pcam_inst,
 				pcam_inst->plane_info.num_planes,
 				pcam_inst->plane_info.plane[0].size,
@@ -1161,7 +1219,7 @@
 static int msm_mctl_v4l2_dqbuf(struct file *f, void *pctx,
 					struct v4l2_buffer *pb)
 {
-	int rc = 0;
+	int rc = 0, i;
 	/* get the camera device */
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
@@ -1178,6 +1236,26 @@
 	rc = vb2_dqbuf(&pcam_inst->vid_bufq, pb,  f->f_flags & O_NONBLOCK);
 	D("%s, videobuf_dqbuf returns %d\n", __func__, rc);
 
+	if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		/* Reject the buffer if planes array was not allocated */
+		if (pb->m.planes == NULL) {
+			pr_err("%s Planes array is null\n", __func__);
+			mutex_unlock(&pcam_inst->inst_lock);
+			return -EINVAL;
+		}
+		for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
+			pb->m.planes[i].data_offset =
+				pcam_inst->buf_offset[pb->index][i].data_offset;
+			pb->m.planes[i].reserved[0] =
+				pcam_inst->buf_offset[pb->index][i].addr_offset;
+			D("%s update offsets for plane %d as A %d D %d\n",
+				__func__, i, pb->m.planes[i].reserved[0],
+				pb->m.planes[i].data_offset);
+		}
+	} else {
+		pb->reserved = pcam_inst->buf_offset[pb->index][0].addr_offset;
+		D("%s stored reserved info %d\n", __func__, pb->reserved);
+	}
 	mutex_unlock(&pcam_inst->inst_lock);
 	return rc;
 }
@@ -1444,8 +1522,8 @@
 		return OUTPUT_TYPE_R;
 	case MSM_V4L2_EXT_CAPTURE_MODE_RDI1:
 		return OUTPUT_TYPE_R1;
-	case MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT:
-	case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
+	case MSM_V4L2_EXT_CAPTURE_MODE_RDI2:
+		return OUTPUT_TYPE_R2;
 	default:
 		return OUTPUT_TYPE_P;
 	}
@@ -1455,18 +1533,30 @@
 				struct v4l2_streamparm *a)
 {
 	int rc = 0;
+	int is_bayer_sensor = 0;
+	struct msm_cam_media_controller *pmctl = NULL;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+
+	pmctl = msm_cam_server_get_mctl(pcam_inst->pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s: invalid mctl controller", __func__);
+		return -EINVAL;
+	}
+	/* save msm_dev node idx for subdev notify lookup */
+	SET_DEVID_MODE(pcam_inst->inst_handle, pmctl->pcam_ptr->vnode_id);
 	SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
 	SET_MCTLPP_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
 	pcam_inst->pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] =
 		pcam_inst;
 	pcam_inst->path = msm_mctl_vidbuf_get_path(pcam_inst->image_mode);
-
+	if (pcam_inst->pcam->sdata->sensor_type == BAYER_SENSOR)
+		is_bayer_sensor = 1;
 	rc = msm_cam_server_config_interface_map(pcam_inst->image_mode,
-			pcam_inst->pcam->mctl_handle);
+			pcam_inst->pcam->mctl_handle,
+			pcam_inst->pcam->vnode_id, is_bayer_sensor);
 	D("%s path=%d, image mode = %d rc=%d\n", __func__,
 		pcam_inst->path, pcam_inst->image_mode, rc);
 	return rc;
@@ -1485,7 +1575,7 @@
 
 	if (sub->type == V4L2_EVENT_ALL)
 		sub->type = V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_EVENT;
-	rc = v4l2_event_subscribe(fh, sub, 50);
+	rc = v4l2_event_subscribe(fh, sub, 30);
 	if (rc < 0)
 		pr_err("%s: failed for evtType = 0x%x, rc = %d\n",
 						__func__, sub->type, rc);
@@ -1599,12 +1689,20 @@
 {
 	int rc = -EINVAL;
 	struct video_device *pvdev = NULL;
-	struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
-
+	struct i2c_client *client = NULL;
+	struct platform_device *pdev = NULL;
 	D("%s\n", __func__);
 
 	/* first register the v4l2 device */
-	pcam->mctl_node.v4l2_dev.dev = &client->dev;
+	if (pcam->sensor_sdev->flags & V4L2_SUBDEV_FL_IS_I2C) {
+		client = v4l2_get_subdevdata(pcam->sensor_sdev);
+		pcam->mctl_node.v4l2_dev.dev = &client->dev;
+	} else {
+		pdev = v4l2_get_subdevdata(pcam->sensor_sdev);
+		pcam->mctl_node.v4l2_dev.dev = &pdev->dev;
+	}
+
+	/* first register the v4l2 device */
 	rc = v4l2_device_register(pcam->mctl_node.v4l2_dev.dev,
 				&pcam->mctl_node.v4l2_dev);
 	if (rc < 0)
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 9f7f689..97b0ea3 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -411,7 +411,8 @@
 		struct msm_cam_media_controller *pmctl,
 		struct msm_cam_v4l2_dev_inst *pcam_inst,
 		struct msm_free_buf *fbuf,
-		uint32_t *frame_id, int gen_timestamp)
+		uint32_t *frame_id,
+		struct msm_cam_timestamp *cam_ts)
 {
 	struct msm_frame_buffer *buf = NULL;
 	int del_buf = 1;
@@ -422,12 +423,19 @@
 			__func__, fbuf->ch_paddr[0]);
 		return -EINVAL;
 	}
-	if (gen_timestamp) {
+	if (!cam_ts->present) {
 		if (frame_id)
 			buf->vidbuf.v4l2_buf.sequence = *frame_id;
 		msm_mctl_gettimeofday(
 			&buf->vidbuf.v4l2_buf.timestamp);
+	} else {
+		D("%s Copying timestamp as %ld.%ld", __func__,
+			cam_ts->timestamp.tv_sec, cam_ts->timestamp.tv_usec);
+		buf->vidbuf.v4l2_buf.timestamp = cam_ts->timestamp;
 	}
+	CDBG("In Buf_done:Notify user frame id %d img mode %d\n",
+		buf->vidbuf.v4l2_buf.sequence,
+		pcam_inst->image_mode);
 	vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
 	return 0;
 }
@@ -442,6 +450,7 @@
 	int idx, rc;
 	int pp_divert_type = 0, pp_type = 0;
 	uint32_t image_mode;
+	struct msm_cam_timestamp cam_ts;
 
 	if (!p_mctl || !buf_handle || !fbuf) {
 		pr_err("%s Invalid argument. ", __func__);
@@ -507,8 +516,9 @@
 				__func__);
 			return -EINVAL;
 		}
+		memset(&cam_ts, 0, sizeof(cam_ts));
 		rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
-			fbuf, &frame_id, 1);
+			fbuf, &frame_id, &cam_ts);
 	}
 	return rc;
 }
@@ -752,12 +762,14 @@
 
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
 	struct msm_cam_buf_handle *buf_handle,
-	struct msm_free_buf *frame, int dirty, int node_type)
+	struct msm_free_buf *frame,
+	struct msm_cam_return_frame_info *ret_frame)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
 	int rc = 0, idx;
+	struct msm_cam_timestamp cam_ts;
 
-	if (!pmctl || !buf_handle) {
+	if (!pmctl || !buf_handle || !ret_frame) {
 		pr_err("%s Invalid argument ", __func__);
 		return -EINVAL;
 	}
@@ -773,13 +785,13 @@
 		}
 	} else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
 		idx = msm_mctl_img_mode_to_inst_index(pmctl,
-			buf_handle->image_mode, node_type);
+			buf_handle->image_mode, ret_frame->node_type);
 		if (idx < 0) {
 			pr_err("%s Invalid instance, buffer not released\n",
 				__func__);
 			return idx;
 		}
-		if (node_type)
+		if (ret_frame->node_type)
 			pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
 		else
 			pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
@@ -791,12 +803,15 @@
 	}
 
 	D("%s:inst=0x%p, paddr=0x%x, dirty=%d",
-		__func__, pcam_inst, frame->ch_paddr[0], dirty);
-	if (dirty)
+		__func__, pcam_inst, frame->ch_paddr[0], ret_frame->dirty);
+	cam_ts.present = 1;
+	cam_ts.timestamp = ret_frame->timestamp;
+	if (ret_frame->dirty)
 		/* the frame is dirty, not going to disptach to app */
 		rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
 	else
-		rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame, NULL, 0);
+		rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame,
+			NULL, &cam_ts);
 	return rc;
 }
 
@@ -840,3 +855,199 @@
 	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
 	return -EINVAL;
 }
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+/* Unmap using ION APIs */
+static void __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num)
+{
+	int i = 0;
+	for (i = 0; i < meta_frame->frame.num_planes; i++) {
+		D("%s Plane %d handle %p", __func__, i,
+			meta_frame->map[i].handle);
+		ion_unmap_iommu(client, meta_frame->map[i].handle,
+					domain_num, 0);
+		ion_free(client, meta_frame->map[i].handle);
+	}
+}
+
+/* Map using ION APIs */
+static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num)
+{
+	unsigned long paddr = 0;
+	unsigned long len = 0;
+	int i = 0, j = 0;
+
+	for (i = 0; i < meta_frame->frame.num_planes; i++) {
+		meta_frame->map[i].handle = ion_import_dma_buf(client,
+			meta_frame->frame.mp[i].fd);
+		if (IS_ERR_OR_NULL(meta_frame->map[i].handle)) {
+			pr_err("%s: ion_import failed for plane = %d fd = %d",
+				__func__, i, meta_frame->frame.mp[i].fd);
+			/* Roll back previous plane mappings, if any */
+			for (j = i-1; j >= 0; j--) {
+				ion_unmap_iommu(client,
+					meta_frame->map[j].handle,
+					domain_num, 0);
+				ion_free(client, meta_frame->map[j].handle);
+			}
+			return -EACCES;
+		}
+		D("%s Mapping fd %d plane %d handle %p", __func__,
+			meta_frame->frame.mp[i].fd, i,
+			meta_frame->map[i].handle);
+		if (ion_map_iommu(client, meta_frame->map[i].handle,
+				domain_num, 0, SZ_4K,
+				0, &paddr, &len, UNCACHED, 0) < 0) {
+			pr_err("%s: cannot map address plane %d", __func__, i);
+			ion_free(client, meta_frame->map[i].handle);
+			/* Roll back previous plane mappings, if any */
+			for (j = i-1; j >= 0; j--) {
+				if (meta_frame->map[j].handle) {
+					ion_unmap_iommu(client,
+						meta_frame->map[j].handle,
+						domain_num, 0);
+					ion_free(client,
+						meta_frame->map[j].handle);
+				}
+			}
+			return -EFAULT;
+		}
+
+		/* Validate the offsets with the mapped length. */
+		if ((meta_frame->frame.mp[i].addr_offset > len) ||
+			(meta_frame->frame.mp[i].data_offset +
+			meta_frame->frame.mp[i].length > len)) {
+			pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
+				__func__, meta_frame->frame.mp[i].addr_offset,
+				meta_frame->frame.mp[i].data_offset,
+				meta_frame->frame.mp[i].length, len);
+			/* Roll back previous plane mappings, if any */
+			for (j = i; j >= 0; j--) {
+				if (meta_frame->map[j].handle) {
+					ion_unmap_iommu(client,
+						meta_frame->map[j].handle,
+						domain_num, 0);
+					ion_free(client,
+						meta_frame->map[j].handle);
+				}
+			}
+			return -EINVAL;
+		}
+		meta_frame->map[i].data_offset =
+			meta_frame->frame.mp[i].data_offset;
+		/* Add the addr_offset to the paddr here itself. The addr_offset
+		 * will be non-zero only if the user has allocated a buffer with
+		 * a single fd, but logically partitioned it into
+		 * multiple planes or buffers.*/
+		paddr += meta_frame->frame.mp[i].addr_offset;
+		meta_frame->map[i].paddr = paddr;
+		meta_frame->map[i].len = len;
+		D("%s Plane %d fd %d handle %p paddr %x", __func__,
+			i, meta_frame->frame.mp[i].fd,
+			meta_frame->map[i].handle,
+			(uint32_t)meta_frame->map[i].paddr);
+	}
+	D("%s Frame mapped successfully ", __func__);
+	return 0;
+}
+#else
+/* Unmap using PMEM APIs */
+static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num)
+{
+	int i = 0, rc = 0;
+
+	for (i = 0; i < meta_frame->frame.num_planes; i++) {
+		D("%s Plane %d handle %p", __func__, i,
+			meta_frame->map[i].handle);
+		put_pmem_file(meta_frame->map[i].file);
+	}
+}
+
+/* Map using PMEM APIs */
+static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num)
+{
+	unsigned long kvstart = 0;
+	unsigned long paddr = 0;
+	struct file *file = NULL;
+	unsigned long len;
+	int i = 0, j = 0;
+
+	for (i = 0; i < meta_frame->frame.num_planes; i++) {
+		rc = get_pmem_file(meta_frame->frame.mp[i].fd,
+			&paddr, &kvstart, &len, &file);
+		if (rc < 0) {
+			pr_err("%s: get_pmem_file fd %d error %d\n",
+				__func__, meta_frame->frame.mp[i].fd, rc);
+			/* Roll back previous plane mappings, if any */
+			for (j = i-1; j >= 0; j--)
+				if (meta_frame->map[j].file)
+					put_pmem_file(meta_frame->map[j].file);
+
+			return -EACCES;
+		}
+		D("%s Got pmem file for fd %d plane %d as %p", __func__,
+			meta_frame->frame.mp[i].fd, i, file);
+		meta_frame->map[i].file = file;
+		/* Validate the offsets with the mapped length. */
+		if ((meta_frame->frame.mp[i].addr_offset > len) ||
+			(meta_frame->frame.mp[i].data_offset +
+			meta_frame->frame.mp[i].length > len)) {
+			pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
+				__func__, meta_frame->frame.mp[i].addr_offset,
+				meta_frame->frame.mp[i].data_offset,
+				meta_frame->frame.mp[i].length, len);
+			/* Roll back previous plane mappings, if any */
+			for (j = i; j >= 0; j--)
+				if (meta_frame->map[j].file)
+					put_pmem_file(meta_frame->map[j].file);
+
+			return -EINVAL;
+		}
+		meta_frame->map[i].data_offset =
+			meta_frame->frame.mp[i].data_offset;
+		/* Add the addr_offset to the paddr here itself. The addr_offset
+		 * will be non-zero only if the user has allocated a buffer with
+		 * a single fd, but logically partitioned it into
+		 * multiple planes or buffers.*/
+		paddr += meta_frame->frame.mp[i].addr_offset;
+		meta_frame->map[i].paddr = paddr;
+		meta_frame->map[i].len = len;
+		D("%s Plane %d fd %d handle %p paddr %x", __func__,
+			i, meta_frame->frame.mp[i].fd,
+			meta_frame->map[i].handle,
+			(uint32_t)meta_frame->map[i].paddr);
+	}
+	D("%s Frame mapped successfully ", __func__);
+	return 0;
+}
+#endif
+
+int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num)
+{
+
+	if ((NULL == meta_frame) || (NULL == client)) {
+		pr_err("%s Invalid input ", __func__);
+		return -EINVAL;
+	}
+
+	memset(&meta_frame->map[0], 0,
+		sizeof(struct msm_cam_buf_map_info) * VIDEO_MAX_PLANES);
+
+	return __msm_mctl_map_user_frame(meta_frame, client, domain_num);
+}
+
+int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+	struct ion_client *client, int domain_num)
+{
+	if ((NULL == meta_frame) || (NULL == client)) {
+		pr_err("%s Invalid input ", __func__);
+		return -EINVAL;
+	}
+	__msm_mctl_unmap_user_frame(meta_frame, client, domain_num);
+	return 0;
+}
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index dcb7c51..a114b37 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -103,6 +103,10 @@
 		if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
 			*pp_type = OUTPUT_TYPE_T;
 		break;
+	case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
+		if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_R)
+			*pp_type = OUTPUT_TYPE_R;
+		break;
 	default:
 		break;
 	}
@@ -329,6 +333,7 @@
 	pp_frame->frame_id = vb->vidbuf.v4l2_buf.sequence;
 	pp_frame->timestamp = vb->vidbuf.v4l2_buf.timestamp;
 	pp_frame->buf_idx = buf_idx;
+	pp_frame->inst_handle = pcam_inst->inst_handle;
 	/* Get the cookie for 1st plane and store the path.
 	 * Also use this to check the number of planes in
 	 * this buffer.*/
@@ -364,49 +369,6 @@
 	return 0;
 }
 
-static int msm_mctl_pp_copy_timestamp_and_frame_id(
-	uint32_t src_handle, uint32_t dest_handle)
-{
-	struct msm_frame_buffer *src_vb;
-	struct msm_frame_buffer *dest_vb;
-
-	src_vb = (struct msm_frame_buffer *)src_handle;
-	dest_vb = (struct msm_frame_buffer *)dest_handle;
-	dest_vb->vidbuf.v4l2_buf.timestamp =
-		src_vb->vidbuf.v4l2_buf.timestamp;
-	dest_vb->vidbuf.v4l2_buf.sequence =
-		src_vb->vidbuf.v4l2_buf.sequence;
-	D("%s: timestamp=%ld:%ld,frame_id=0x%x", __func__,
-		dest_vb->vidbuf.v4l2_buf.timestamp.tv_sec,
-		dest_vb->vidbuf.v4l2_buf.timestamp.tv_usec,
-		dest_vb->vidbuf.v4l2_buf.sequence);
-	return 0;
-}
-
-static int msm_mctl_pp_path_to_inst_index(struct msm_cam_v4l2_device *pcam,
-					int out_type)
-{
-	int image_mode;
-	switch (out_type) {
-	case OUTPUT_TYPE_P:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
-		break;
-	case OUTPUT_TYPE_V:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
-		break;
-	case OUTPUT_TYPE_S:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
-		break;
-	default:
-		image_mode = -1;
-		break;
-	}
-	if ((image_mode >= 0) && pcam->dev_inst_map[image_mode])
-		return pcam->dev_inst_map[image_mode]->my_index;
-	else
-		return -EINVAL;
-}
-
 static int msm_mctl_pp_path_to_img_mode(int path)
 {
 	switch (path) {
@@ -418,6 +380,16 @@
 		return MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
 	case OUTPUT_TYPE_T:
 		return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+	case OUTPUT_TYPE_SAEC:
+		return MSM_V4L2_EXT_CAPTURE_MODE_AEC;
+	case OUTPUT_TYPE_SAWB:
+		return MSM_V4L2_EXT_CAPTURE_MODE_AWB;
+	case OUTPUT_TYPE_SAFC:
+		return MSM_V4L2_EXT_CAPTURE_MODE_AF;
+	case OUTPUT_TYPE_IHST:
+		return MSM_V4L2_EXT_CAPTURE_MODE_IHIST;
+	case OUTPUT_TYPE_CSTA:
+		return MSM_V4L2_EXT_CAPTURE_MODE_CSTA;
 	default:
 		return -EINVAL;
 	}
@@ -437,8 +409,8 @@
 			ERR_COPY_FROM_USER();
 			return -EFAULT;
 		}
-		D("%s: PP_PATH, path=%d",
-			__func__, divert_pp.path);
+		D("%s: Divert Image mode =%d Enable %d",
+			__func__, divert_pp.path, divert_pp.enable);
 		spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
 		if (divert_pp.enable)
 			p_mctl->pp_info.pp_ctrl.pp_msg_type |= divert_pp.path;
@@ -515,6 +487,8 @@
 		pr_err("%s Instance already closed ", __func__);
 		return -EINVAL;
 	}
+	D("%s Reserving free frame using %p inst handle %x ", __func__,
+		pcam_inst, div_frame.frame.inst_handle);
 	if (div_frame.frame.inst_handle) {
 		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
 		buf_handle.inst_handle = div_frame.frame.inst_handle;
@@ -532,7 +506,7 @@
 			rc = -EFAULT;
 		}
 	}
-	D("%s: reserve free buf got buffer %d from %p rc = %d, phy = 0x%x",
+	D("%s: Got buffer %d from Inst %p rc = %d, phy = 0x%x",
 		__func__, div_frame.frame.buf_idx,
 		pcam_inst, rc, free_buf.ch_paddr[0]);
 	return rc;
@@ -615,6 +589,7 @@
 	struct msm_free_buf buf;
 	unsigned long flags;
 	struct msm_cam_buf_handle buf_handle;
+	struct msm_cam_return_frame_info ret_frame;
 
 	if (copy_from_user(&frame, arg, sizeof(frame))) {
 		ERR_COPY_FROM_USER();
@@ -657,7 +632,11 @@
 			buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
 	}
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
-	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, dirty, 0);
+
+	ret_frame.dirty = dirty;
+	ret_frame.node_type = 0;
+	ret_frame.timestamp = frame.timestamp;
+	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
 	return rc;
 }
 
@@ -666,11 +645,11 @@
 	void __user *arg)
 {
 	struct msm_pp_frame frame;
-	int msg_type, image_mode, rc = 0;
-	int dirty = 0;
+	int rc = 0;
 	struct msm_free_buf buf;
 	unsigned long flags;
 	struct msm_cam_buf_handle buf_handle;
+	struct msm_cam_return_frame_info ret_frame;
 
 	D("%s enter\n", __func__);
 
@@ -680,35 +659,12 @@
 	}
 
 	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
-	D("%s Frame path: %d\n", __func__, frame.path);
-	switch (frame.path) {
-	case OUTPUT_TYPE_P:
-		msg_type = VFE_MSG_OUTPUT_P;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
-		break;
-	case OUTPUT_TYPE_S:
-		msg_type = VFE_MSG_OUTPUT_S;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
-		break;
-	case OUTPUT_TYPE_V:
-		msg_type = VFE_MSG_OUTPUT_V;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
-		break;
-	case OUTPUT_TYPE_T:
-		msg_type = VFE_MSG_OUTPUT_T;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
-		break;
-	default:
-		rc = -EFAULT;
-		goto err;
-	}
-
 	if (frame.inst_handle) {
 		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
 		buf_handle.inst_handle = frame.inst_handle;
 	} else {
 		buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
-		buf_handle.image_mode = image_mode;
+		buf_handle.image_mode = frame.image_type;
 	}
 
 	if (frame.num_planes > 1)
@@ -718,12 +674,12 @@
 		buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
 
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+
+	ret_frame.dirty = 0;
+	ret_frame.node_type = frame.node_type;
+	ret_frame.timestamp = frame.timestamp;
 	D("%s Frame done id: %d\n", __func__, frame.frame_id);
-	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle,
-		&buf, dirty, frame.node_type);
-	return rc;
-err:
-	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
 	return rc;
 }
 
@@ -755,54 +711,3 @@
 
 	return rc;
 }
-
-int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom)
-{
-	struct msm_cam_media_controller *p_mctl;
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	int rc = 0, idx;
-
-	if (!zoom || !zoom->p_mctl) {
-		pr_err("%s Invalid input, not sending buffer to VPE ",
-			__func__);
-		return -EINVAL;
-	}
-	p_mctl = zoom->p_mctl;
-	idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
-		zoom->pp_frame_cmd.path);
-	if (idx < 0) {
-		pr_err("%s Invalid path, returning\n", __func__);
-		return idx;
-	}
-	pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
-	if (!pcam_inst) {
-		pr_err("%s Invalid instance, returning\n", __func__);
-		return -EINVAL;
-	}
-
-	rc = msm_mctl_pp_get_phy_addr(pcam_inst,
-		zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
-	if (rc) {
-		pr_err("%s Error getting buffer address for src frame\n",
-			__func__);
-		return rc;
-	}
-
-	rc = msm_mctl_pp_get_phy_addr(pcam_inst,
-		zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
-	if (rc) {
-		pr_err("%s Error getting buffer address for dest frame\n",
-			__func__);
-		return rc;
-	}
-
-	rc = msm_mctl_pp_copy_timestamp_and_frame_id(
-		zoom->pp_frame_cmd.src_buf_handle,
-		zoom->pp_frame_cmd.dest_buf_handle);
-	if (rc < 0) {
-		pr_err("%s Error copying timestamp info\n",
-			__func__);
-		return rc;
-	}
-	return rc;
-}
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index e2e9d1b..5136d9d 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -116,7 +116,7 @@
 }
 
 static int msm_pmem_table_add(struct hlist_head *ptype,
-	struct msm_pmem_info *info, struct ion_client *client)
+	struct msm_pmem_info *info, struct ion_client *client, int domain_num)
 {
 	unsigned long paddr;
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -135,7 +135,7 @@
 	region->handle = ion_import_dma_buf(client, info->fd);
 	if (IS_ERR_OR_NULL(region->handle))
 		goto out1;
-	if (ion_map_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL,
+	if (ion_map_iommu(client, region->handle, domain_num, 0,
 				  SZ_4K, 0, &paddr, &len, UNCACHED, 0) < 0)
 		goto out2;
 #elif CONFIG_ANDROID_PMEM
@@ -180,7 +180,7 @@
 	return 0;
 out3:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_unmap_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL);
+	ion_unmap_iommu(client, region->handle, domain_num, 0);
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
@@ -195,7 +195,8 @@
 }
 
 static int __msm_register_pmem(struct hlist_head *ptype,
-			struct msm_pmem_info *pinfo, struct ion_client *client)
+			struct msm_pmem_info *pinfo, struct ion_client *client,
+			int domain_num)
 {
 	int rc = 0;
 
@@ -211,7 +212,7 @@
 	case MSM_PMEM_BAYER_GRID:
 	case MSM_PMEM_BAYER_FOCUS:
 	case MSM_PMEM_BAYER_HIST:
-		rc = msm_pmem_table_add(ptype, pinfo, client);
+		rc = msm_pmem_table_add(ptype, pinfo, client, domain_num);
 		break;
 
 	default:
@@ -223,7 +224,8 @@
 }
 
 static int __msm_pmem_table_del(struct hlist_head *ptype,
-			struct msm_pmem_info *pinfo, struct ion_client *client)
+			struct msm_pmem_info *pinfo, struct ion_client *client,
+			int domain_num)
 {
 	int rc = 0;
 	struct msm_pmem_region *region;
@@ -250,7 +252,7 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_unmap_iommu(client, region->handle,
-					CAMERA_DOMAIN, GEN_POOL);
+					domain_num, 0);
 				ion_free(client, region->handle);
 #else
 				put_pmem_file(region->file);
@@ -394,7 +396,8 @@
 }
 
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
-					  struct ion_client *client)
+					struct ion_client *client,
+					int domain_num)
 {
 	struct msm_pmem_info info;
 
@@ -403,12 +406,12 @@
 			return -EFAULT;
 	}
 
-	return __msm_register_pmem(ptype, &info, client);
+	return __msm_register_pmem(ptype, &info, client, domain_num);
 }
 //EXPORT_SYMBOL(msm_register_pmem);
 
 int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
-					   struct ion_client *client)
+			struct ion_client *client, int domain_num)
 {
 	struct msm_pmem_info info;
 
@@ -417,6 +420,6 @@
 		return -EFAULT;
 	}
 
-	return __msm_pmem_table_del(ptype, &info, client);
+	return __msm_pmem_table_del(ptype, &info, client, domain_num);
 }
 //EXPORT_SYMBOL(msm_pmem_table_del);
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index abbdbcd..34fab82 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -36,8 +36,8 @@
 #define D(fmt, args...) do {} while (0)
 #endif
 
-static int vpe_enable(uint32_t);
-static int vpe_disable(void);
+static int vpe_enable(uint32_t, struct msm_cam_media_controller *);
+static int vpe_disable(struct msm_cam_media_controller *);
 static int vpe_update_scaler(struct msm_pp_crop *pcrop);
 struct vpe_ctrl_type *vpe_ctrl;
 static atomic_t vpe_init_done = ATOMIC_INIT(0);
@@ -425,29 +425,37 @@
 	int rc = 0;
 	unsigned long flags;
 	unsigned long srcP0, srcP1, outP0, outP1;
-	struct msm_mctl_pp_frame_info *frame = vpe_ctrl->pp_frame_info;
+	struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
+
+	if (!frame_info) {
+		pr_err("%s Invalid frame", __func__);
+		return -EINVAL;
+	}
 
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
-	if (frame->src_frame.num_planes > 1) {
-		srcP0 = vpe_ctrl->pp_frame_info->src_frame.mp[0].phy_addr +
-			vpe_ctrl->pp_frame_info->src_frame.mp[0].data_offset;
-		srcP1 = vpe_ctrl->pp_frame_info->src_frame.mp[1].phy_addr +
-			vpe_ctrl->pp_frame_info->src_frame.mp[1].data_offset;
-		outP0 = vpe_ctrl->pp_frame_info->dest_frame.mp[0].phy_addr +
-			vpe_ctrl->pp_frame_info->dest_frame.mp[0].data_offset;
-		outP1 = vpe_ctrl->pp_frame_info->dest_frame.mp[1].phy_addr +
-			vpe_ctrl->pp_frame_info->dest_frame.mp[1].data_offset;
+
+	if (frame_info->src_frame.frame.num_planes > 1) {
+		srcP0 = frame_info->src_frame.map[0].paddr +
+			frame_info->src_frame.map[0].data_offset;
+		srcP1 = frame_info->src_frame.map[1].paddr +
+			frame_info->src_frame.map[1].data_offset;
+		outP0 = frame_info->dest_frame.map[0].paddr +
+			frame_info->dest_frame.map[0].data_offset;
+		outP1 = frame_info->dest_frame.map[1].paddr +
+			frame_info->dest_frame.map[1].data_offset;
 	} else {
-		srcP0 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
-			vpe_ctrl->pp_frame_info->src_frame.sp.y_off;
-		srcP1 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
-			vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off;
-		outP0 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
-			vpe_ctrl->pp_frame_info->dest_frame.sp.y_off;
-		outP1 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
-			vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off;
+		srcP0 = frame_info->src_frame.map[0].paddr;
+		srcP1 = frame_info->src_frame.map[0].paddr +
+			frame_info->src_frame.map[0].data_offset;
+		outP0 = frame_info->dest_frame.map[0].paddr;
+		outP1 = frame_info->dest_frame.map[0].paddr +
+			frame_info->dest_frame.map[0].data_offset;
 	}
 
+	D("%s VPE Configured with Src %x, %x Dest %x, %x",
+		__func__, (uint32_t)srcP0, (uint32_t)srcP1,
+		(uint32_t)outP0, (uint32_t)outP1);
+
 	msm_camera_io_w(srcP0, vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
 	msm_camera_io_w(srcP1, vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
 	msm_camera_io_w(outP0, vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
@@ -471,11 +479,6 @@
 		return;
 	}
 	event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
-	if (!event_qcmd) {
-		pr_err("%s: out of memory\n", __func__);
-		spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-		return;
-	}
 	atomic_set(&event_qcmd->on_heap, 1);
 	event_qcmd->command = (void *)vpe_ctrl->pp_frame_info;
 	vpe_ctrl->pp_frame_info = NULL;
@@ -487,7 +490,6 @@
 	v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_MCTL_PP_EVENT;
 	v4l2_evt.id = 0;
 	v4l2_event_queue(vpe_ctrl->subdev.devnode, &v4l2_evt);
-
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 }
 
@@ -503,6 +505,8 @@
 
 static irqreturn_t vpe_parse_irq(int irq_num, void *data)
 {
+	if(!vpe_ctrl || !vpe_ctrl->vpebase)
+		return IRQ_HANDLED;
 	vpe_ctrl->irq_status = msm_camera_io_r_mb(vpe_ctrl->vpebase +
 							VPE_INTR_STATUS_OFFSET);
 	msm_camera_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase +
@@ -518,7 +522,7 @@
 	{"vpe_pclk", -1},
 };
 
-int vpe_enable(uint32_t clk_rate)
+int vpe_enable(uint32_t clk_rate, struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 	unsigned long flags = 0;
@@ -547,8 +551,27 @@
 	if (rc < 0)
 		goto vpe_clk_failed;
 
+#ifdef CONFIG_MSM_IOMMU
+	rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+	if (rc < 0) {
+		pr_err("%s: Device attach failed\n", __func__);
+		goto src_attach_failed;
+	}
+	rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+	if (rc < 0) {
+		pr_err("%s: Device attach failed\n", __func__);
+		goto dst_attach_failed;
+	}
+#endif
 	return rc;
 
+#ifdef CONFIG_MSM_IOMMU
+dst_attach_failed:
+	iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+src_attach_failed:
+#endif
+	msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+		vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
 vpe_clk_failed:
 	if (vpe_ctrl->fs_vpe)
 		regulator_disable(vpe_ctrl->fs_vpe);
@@ -558,7 +581,7 @@
 	return rc;
 }
 
-int vpe_disable(void)
+int vpe_disable(struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 	unsigned long flags = 0;
@@ -570,7 +593,10 @@
 		return rc;
 	}
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-
+#ifdef CONFIG_MSM_IOMMU
+	iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+	iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+#endif
 	disable_irq(vpe_ctrl->vpeirq->start);
 	tasklet_kill(&vpe_tasklet);
 	msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
@@ -601,8 +627,8 @@
 	msm_vpe_cfg_update(
 		&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
 	D("%s Sending frame idx %d id %d to VPE ", __func__,
-		pp_frame_info->src_frame.buf_idx,
-		pp_frame_info->src_frame.frame_id);
+		pp_frame_info->src_frame.frame.buf_idx,
+		pp_frame_info->src_frame.frame.frame_id);
 	rc = msm_send_frame_to_vpe();
 	return rc;
 }
@@ -653,23 +679,25 @@
 	return rc;  /* this rc should have error code. */
 }
 
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
 {
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	if (!atomic_read(&vpe_init_done)) {
 		/* no VPE object created */
 		pr_err("%s: no VPE object to release", __func__);
 		return;
 	}
-
 	vpe_reset();
-	vpe_disable();
+	vpe_disable(mctl);
 	iounmap(vpe_ctrl->vpebase);
 	vpe_ctrl->vpebase = NULL;
 	atomic_set(&vpe_init_done, 0);
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
-static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
+static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd,
+				struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 
@@ -792,19 +820,35 @@
 
 		zoom->user_cmd = vpe_cmd->cmd_type;
 		zoom->p_mctl = v4l2_get_subdev_hostdata(&vpe_ctrl->subdev);
-		D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x",
-			__func__, zoom->pp_frame_cmd.src_buf_handle,
-			zoom->pp_frame_cmd.dest_buf_handle,
-			zoom->pp_frame_cmd.cookie,
+		D("%s: cookie=0x%x,action=0x%x,path=0x%x",
+			__func__, zoom->pp_frame_cmd.cookie,
 			zoom->pp_frame_cmd.vpe_output_action,
 			zoom->pp_frame_cmd.path);
-		rc = msm_mctl_pp_get_vpe_buf_info(zoom);
+
+		D("%s Mapping Source frame ", __func__);
+		zoom->src_frame.frame = zoom->pp_frame_cmd.src_frame;
+		rc = msm_mctl_map_user_frame(&zoom->src_frame,
+			zoom->p_mctl->client, mctl->domain_num);
 		if (rc < 0) {
-			pr_err("%s Error getting buffer info from mctl rc = %d",
+			pr_err("%s Error mapping source buffer rc = %d",
 				__func__, rc);
 			kfree(zoom);
 			break;
 		}
+
+		D("%s Mapping Destination frame ", __func__);
+		zoom->dest_frame.frame = zoom->pp_frame_cmd.dest_frame;
+		rc = msm_mctl_map_user_frame(&zoom->dest_frame,
+			zoom->p_mctl->client, mctl->domain_num);
+		if (rc < 0) {
+			pr_err("%s Error mapping dest buffer rc = %d",
+				__func__, rc);
+			msm_mctl_unmap_user_frame(&zoom->src_frame,
+				zoom->p_mctl->client, mctl->domain_num);
+			kfree(zoom);
+			break;
+		}
+
 		rc = msm_vpe_do_pp(zoom);
 		break;
 		}
@@ -825,13 +869,13 @@
 			return -EFAULT;
 		}
 		turbo_mode = (int)clk_rate.rate;
-		rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
-				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
+		rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE, mctl) :
+				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE, mctl);
 		break;
 		}
 
 	case VPE_CMD_DISABLE:
-		rc = vpe_disable();
+		rc = vpe_disable(mctl);
 		break;
 
 	default:
@@ -846,7 +890,8 @@
 {
 	struct msm_vpe_cfg_cmd *vpe_cmd;
 	int rc = 0;
-
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	switch (cmd) {
 	case VIDIOC_MSM_VPE_INIT: {
 		msm_vpe_subdev_init(sd);
@@ -854,12 +899,12 @@
 		}
 
 	case VIDIOC_MSM_VPE_RELEASE:
-		msm_vpe_subdev_release();
+		msm_vpe_subdev_release(sd);
 		break;
 
 	case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
 		vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
-		rc = msm_vpe_process_vpe_cmd(vpe_cmd);
+		rc = msm_vpe_process_vpe_cmd(vpe_cmd, mctl);
 		if (rc < 0) {
 			pr_err("%s Error processing VPE cmd %d ",
 				__func__, vpe_cmd->cmd_type);
@@ -881,6 +926,14 @@
 			return -EFAULT;
 		}
 		pp_frame_info = event_qcmd->command;
+
+		D("%s Unmapping source and destination buffers ",
+			__func__);
+		msm_mctl_unmap_user_frame(&pp_frame_info->src_frame,
+			pp_frame_info->p_mctl->client, mctl->domain_num);
+		msm_mctl_unmap_user_frame(&pp_frame_info->dest_frame,
+			pp_frame_info->p_mctl->client, mctl->domain_num);
+
 		pp_event_info.event = MCTL_PP_EVENT_CMD_ACK;
 		pp_event_info.ack.cmd = pp_frame_info->user_cmd;
 		pp_event_info.ack.status = 0;
@@ -889,13 +942,11 @@
 			pp_event_info.ack.cmd, pp_event_info.ack.status,
 			pp_event_info.ack.cookie);
 		if (copy_to_user((void __user *)v4l2_ioctl->ioctl_ptr,
-			&pp_event_info,
-			sizeof(struct msm_mctl_pp_event_info)))
-			pr_err("%s EVENTPAYLOAD Copy to user failed ",
-				__func__);
+			&pp_event_info,	sizeof(struct msm_mctl_pp_event_info)))
+			pr_err("%s PAYLOAD Copy to user failed ", __func__);
+
 		kfree(pp_frame_info);
-		event_qcmd->command = NULL;
-		free_qcmd(event_qcmd);
+		kfree(event_qcmd);
 		break;
 		}
 
@@ -948,12 +999,22 @@
 	struct v4l2_subdev_fh *fh)
 {
 	struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
+	struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	if (atomic_read(&vpe_ctrl->active) == 0) {
 		pr_err("%s already closed\n", __func__);
 		return -EINVAL;
 	}
 
 	D("%s E ", __func__);
+	if (frame_info) {
+		D("%s Unmap the pending item from the queue ", __func__);
+		msm_mctl_unmap_user_frame(&frame_info->src_frame,
+			frame_info->p_mctl->client, mctl->domain_num);
+		msm_mctl_unmap_user_frame(&frame_info->dest_frame,
+			frame_info->p_mctl->client, mctl->domain_num);
+	}
 	/* Drain the payload queue. */
 	msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
 	atomic_dec(&vpe_ctrl->active);
@@ -1033,6 +1094,19 @@
 
 	disable_irq(vpe_ctrl->vpeirq->start);
 
+#ifdef CONFIG_MSM_IOMMU
+	/*get device context for IOMMU*/
+	vpe_ctrl->iommu_ctx_src = msm_iommu_get_ctx("vpe_src"); /*re-confirm*/
+	vpe_ctrl->iommu_ctx_dst = msm_iommu_get_ctx("vpe_dst"); /*re-confirm*/
+	if (!vpe_ctrl->iommu_ctx_src || !vpe_ctrl->iommu_ctx_dst) {
+		release_mem_region(vpe_ctrl->vpemem->start,
+			resource_size(vpe_ctrl->vpemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vpe_no_resource;
+	}
+#endif
+
 	atomic_set(&vpe_ctrl->active, 0);
 	vpe_ctrl->pdev = pdev;
 	sd_info.sdev_type = VPE_DEV;
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 6516ea1..aad2380 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -121,6 +121,8 @@
 	struct msm_mctl_pp_frame_info *pp_frame_info;
 	atomic_t active;
 	struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
+	struct device *iommu_ctx_src;
+	struct device *iommu_ctx_dst;
 };
 
 /*
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index bedc5ad..cd228a1 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -3,18 +3,15 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
 EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
-obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
+obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor_common.o msm_sensor.o msm_sensor_bayer.o msm_sensor_init.o
 obj-$(CONFIG_OV5647) += ov5647_v4l2.o
 obj-$(CONFIG_OV8825) += ov8825_v4l2.o
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
 obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
-obj-$(CONFIG_IMX091) += imx091.o
 obj-$(CONFIG_OV2720) += ov2720.o
 obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
 obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
 obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
 obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
 obj-$(CONFIG_OV7692) += ov7692_v4l2.o
-obj-$(CONFIG_IMX111) += imx111.o
-obj-$(CONFIG_IMX119) += imx119_v4l2.o
 obj-$(CONFIG_VX6953) += vx6953.o
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index ddf0754..91d4797 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -168,44 +168,6 @@
 	},
 };
 
-static struct msm_camera_csi_params imx074_csic_params = {
-	.data_format = CSI_10BIT,
-	.lane_cnt    = 4,
-	.lane_assign = 0xe4,
-	.dpcm_scheme = 0,
-	.settle_cnt  = 0x14,
-};
-
-static struct msm_camera_csi_params *imx074_csic_params_array[] = {
-	&imx074_csic_params,
-	&imx074_csic_params,
-};
-
-static struct msm_camera_csid_vc_cfg imx074_cid_cfg[] = {
-	{0, CSI_RAW10, CSI_DECODE_10BIT},
-	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-	{2, CSI_RESERVED_DATA_0, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params imx074_csi_params = {
-	.csid_params = {
-		.lane_cnt = 4,
-		.lut_params = {
-			.num_cid = ARRAY_SIZE(imx074_cid_cfg),
-			.vc_cfg = imx074_cid_cfg,
-		},
-	},
-	.csiphy_params = {
-		.lane_cnt = 4,
-		.settle_cnt = 0x1B,
-	},
-};
-
-static struct msm_camera_csi2_params *imx074_csi_params_array[] = {
-	&imx074_csi_params,
-	&imx074_csi_params,
-};
-
 static struct msm_sensor_output_reg_addr_t imx074_reg_addr = {
 	.x_output = 0x34C,
 	.y_output = 0x34E,
@@ -224,6 +186,13 @@
 	.vert_offset = 3,
 };
 
+static enum msm_camera_vreg_name_t imx074_veg_seq[] = {
+	CAM_VDIG,
+	CAM_VIO,
+	CAM_VANA,
+	CAM_VAF,
+};
+
 static const struct i2c_device_id imx074_i2c_id[] = {
 	{SENSOR_NAME, (kernel_ulong_t)&imx074_s_ctrl},
 	{ }
@@ -302,12 +271,12 @@
 	.msm_sensor_reg = &imx074_regs,
 	.sensor_i2c_client = &imx074_sensor_i2c_client,
 	.sensor_i2c_addr = 0x34,
+	.vreg_seq = imx074_veg_seq,
+	.num_vreg_seq = ARRAY_SIZE(imx074_veg_seq),
 	.sensor_output_reg_addr = &imx074_reg_addr,
 	.sensor_id_info = &imx074_id_info,
 	.sensor_exp_gain_info = &imx074_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csic_params = &imx074_csic_params_array[0],
-	.csi_params = &imx074_csi_params_array[0],
 	.msm_sensor_mutex = &imx074_mut,
 	.sensor_i2c_driver = &imx074_i2c_driver,
 	.sensor_v4l2_subdev_info = imx074_subdev_info,
diff --git a/drivers/media/video/msm/sensors/imx091.h b/drivers/media/video/msm/sensors/imx091.h
new file mode 100644
index 0000000..3618b4c
--- /dev/null
+++ b/drivers/media/video/msm/sensors/imx091.h
@@ -0,0 +1,101 @@
+/* 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.
+ *
+ */
+#define IMX091_SENSOR_NAME "imx091"
+DEFINE_MSM_MUTEX(imx091_mut);
+
+static struct msm_sensor_ctrl_t imx091_s_ctrl;
+
+static struct v4l2_subdev_info imx091_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_sensor_id_info_t imx091_id_info = {
+	.sensor_id_reg_addr = 0x0000,
+	.sensor_id = 0x0091,
+};
+
+static enum msm_camera_vreg_name_t imx091_veg_seq[] = {
+	CAM_VANA,
+	CAM_VAF,
+	CAM_VDIG,
+	CAM_VIO,
+};
+
+static struct msm_camera_power_seq_t imx091_power_seq[] = {
+	{REQUEST_GPIO, 0},
+	{REQUEST_VREG, 0},
+	{ENABLE_VREG, 0},
+	{ENABLE_GPIO, 0},
+	{CONFIG_CLK, 1},
+	{CONFIG_I2C_MUX, 0},
+};
+
+static const struct i2c_device_id imx091_i2c_id[] = {
+	{IMX091_SENSOR_NAME, (kernel_ulong_t)&imx091_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver imx091_i2c_driver = {
+	.id_table = imx091_i2c_id,
+	.probe  = msm_sensor_bayer_i2c_probe,
+	.driver = {
+		.name = IMX091_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client imx091_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static struct v4l2_subdev_core_ops imx091_subdev_core_ops = {
+	.ioctl = msm_sensor_bayer_subdev_ioctl,
+	.s_power = msm_sensor_bayer_power,
+};
+
+static struct v4l2_subdev_video_ops imx091_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_bayer_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops imx091_subdev_ops = {
+	.core = &imx091_subdev_core_ops,
+	.video  = &imx091_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t imx091_func_tbl = {
+	.sensor_config = msm_sensor_bayer_config,
+	.sensor_power_up = msm_sensor_bayer_power_up,
+	.sensor_power_down = msm_sensor_bayer_power_down,
+	.sensor_get_csi_params = msm_sensor_bayer_get_csi_params,
+};
+
+static struct msm_sensor_ctrl_t imx091_s_ctrl = {
+	.sensor_i2c_client = &imx091_sensor_i2c_client,
+	.sensor_i2c_addr = 0x34,
+	.vreg_seq = imx091_veg_seq,
+	.num_vreg_seq = ARRAY_SIZE(imx091_veg_seq),
+	.power_seq = &imx091_power_seq[0],
+	.num_power_seq = ARRAY_SIZE(imx091_power_seq),
+	.sensor_id_info = &imx091_id_info,
+	.msm_sensor_mutex = &imx091_mut,
+	.sensor_v4l2_subdev_info = imx091_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(imx091_subdev_info),
+	.sensor_v4l2_subdev_ops = &imx091_subdev_ops,
+	.func_tbl = &imx091_func_tbl,
+	.clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 9da840e..999783e 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -9,26 +9,20 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 #include "msm_sensor.h"
+#include "msm_sensor_common.h"
 #include "msm.h"
 #include "msm_ispif.h"
 #include "msm_camera_i2c_mux.h"
 
 /*=============================================================*/
-int32_t msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl,
-	uint16_t res)
+void msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	uint16_t cur_line = 0;
 	uint16_t exp_fl_lines = 0;
 	if (s_ctrl->sensor_exp_gain_info) {
-		if (s_ctrl->prev_gain && s_ctrl->prev_line &&
-			s_ctrl->func_tbl->sensor_write_exp_gain)
-			s_ctrl->func_tbl->sensor_write_exp_gain(
-				s_ctrl,
-				s_ctrl->prev_gain,
-				s_ctrl->prev_line);
-
 		msm_camera_i2c_read(s_ctrl->sensor_i2c_client,
 			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
 			&cur_line,
@@ -36,7 +30,7 @@
 		exp_fl_lines = cur_line +
 			s_ctrl->sensor_exp_gain_info->vert_offset;
 		if (exp_fl_lines > s_ctrl->msm_sensor_reg->
-			output_settings[res].frame_length_lines)
+			output_settings[s_ctrl->curr_res].frame_length_lines)
 			msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 				s_ctrl->sensor_output_reg_addr->
 				frame_length_lines,
@@ -44,26 +38,18 @@
 				MSM_CAMERA_I2C_WORD_DATA);
 		CDBG("%s cur_fl_lines %d, exp_fl_lines %d\n", __func__,
 			s_ctrl->msm_sensor_reg->
-			output_settings[res].frame_length_lines,
+			output_settings[s_ctrl->curr_res].frame_length_lines,
 			exp_fl_lines);
 	}
-	return 0;
+	return;
 }
 
-int32_t msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl,
-	uint16_t res)
+void msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	uint16_t cur_line = 0;
 	uint16_t exp_fl_lines = 0;
 	uint8_t int_time[3];
 	if (s_ctrl->sensor_exp_gain_info) {
-		if (s_ctrl->prev_gain && s_ctrl->prev_line &&
-			s_ctrl->func_tbl->sensor_write_exp_gain)
-			s_ctrl->func_tbl->sensor_write_exp_gain(
-				s_ctrl,
-				s_ctrl->prev_gain,
-				s_ctrl->prev_line);
-
 		msm_camera_i2c_read_seq(s_ctrl->sensor_i2c_client,
 			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr-1,
 			&int_time[0], 3);
@@ -73,7 +59,7 @@
 		exp_fl_lines = cur_line +
 			s_ctrl->sensor_exp_gain_info->vert_offset;
 		if (exp_fl_lines > s_ctrl->msm_sensor_reg->
-			output_settings[res].frame_length_lines)
+			output_settings[s_ctrl->curr_res].frame_length_lines)
 			msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 				s_ctrl->sensor_output_reg_addr->
 				frame_length_lines,
@@ -83,10 +69,35 @@
 			__func__,
 			cur_line,
 			s_ctrl->msm_sensor_reg->
-			output_settings[res].frame_length_lines,
+			output_settings[s_ctrl->curr_res].frame_length_lines,
 			exp_fl_lines);
 	}
-	return 0;
+	return;
+}
+
+static void msm_sensor_delay_frames(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	long fps = 0;
+	uint32_t delay = 0;
+
+	if (s_ctrl->curr_res < MSM_SENSOR_INVALID_RES &&
+		s_ctrl->wait_num_frames > 0) {
+		fps = s_ctrl->msm_sensor_reg->
+			output_settings[s_ctrl->curr_res].vt_pixel_clk /
+			s_ctrl->curr_frame_length_lines /
+			s_ctrl->curr_line_length_pclk;
+		if (fps == 0)
+			delay = s_ctrl->min_delay;
+		else
+			delay = (1000 * s_ctrl->wait_num_frames) / fps / Q10;
+	}
+	CDBG("%s fps = %ld, delay = %d, min_delay %d\n", __func__, fps,
+		delay, s_ctrl->min_delay);
+	if (delay > s_ctrl->min_delay)
+		msleep(delay);
+	else if (s_ctrl->min_delay)
+		msleep(s_ctrl->min_delay);
+	return;
 }
 
 int32_t msm_sensor_write_init_settings(struct msm_sensor_ctrl_t *s_ctrl)
@@ -113,9 +124,6 @@
 	if (rc < 0)
 		return rc;
 
-	if (s_ctrl->func_tbl->sensor_adjust_frame_lines)
-		rc = s_ctrl->func_tbl->sensor_adjust_frame_lines(s_ctrl, res);
-
 	return rc;
 }
 
@@ -145,11 +153,18 @@
 
 void msm_sensor_start_stream(struct msm_sensor_ctrl_t *s_ctrl)
 {
+	if (s_ctrl->curr_res >= s_ctrl->msm_sensor_reg->num_conf)
+		return;
+
+	if (s_ctrl->func_tbl->sensor_adjust_frame_lines)
+		s_ctrl->func_tbl->sensor_adjust_frame_lines(s_ctrl);
+
 	msm_camera_i2c_write_tbl(
 		s_ctrl->sensor_i2c_client,
 		s_ctrl->msm_sensor_reg->start_stream_conf,
 		s_ctrl->msm_sensor_reg->start_stream_conf_size,
 		s_ctrl->msm_sensor_reg->default_data_type);
+	msm_sensor_delay_frames(s_ctrl);
 }
 
 void msm_sensor_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
@@ -159,6 +174,7 @@
 		s_ctrl->msm_sensor_reg->stop_stream_conf,
 		s_ctrl->msm_sensor_reg->stop_stream_conf_size,
 		s_ctrl->msm_sensor_reg->default_data_type);
+	msm_sensor_delay_frames(s_ctrl);
 }
 
 void msm_sensor_group_hold_on(struct msm_sensor_ctrl_t *s_ctrl)
@@ -244,78 +260,38 @@
 			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);
+		s_ctrl->func_tbl->sensor_stop_stream(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;
-		}
 		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 			NOTIFY_PCLK_CHANGE,
 			&s_ctrl->sensordata->pdata->ioclk.vfe_clk_rate);
-
-		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)
 {
 	int32_t rc = 0;
-	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
-	msleep(30);
+
 	if (update_type == MSM_SENSOR_REG_INIT) {
-		s_ctrl->curr_csi_params = NULL;
-		msm_sensor_enable_debugfs(s_ctrl);
+		s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 		msm_sensor_write_init_settings(s_ctrl);
 	} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
 		msm_sensor_write_res_settings(s_ctrl, res);
-		if (s_ctrl->curr_csi_params != s_ctrl->csi_params[res]) {
-			s_ctrl->curr_csi_params = s_ctrl->csi_params[res];
-			s_ctrl->curr_csi_params->csid_params.lane_assign =
-				s_ctrl->sensordata->sensor_platform_info->
-				csi_lane_params->csi_lane_assign;
-			s_ctrl->curr_csi_params->csiphy_params.lane_mask =
-				s_ctrl->sensordata->sensor_platform_info->
-				csi_lane_params->csi_lane_mask;
-			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
-				NOTIFY_CSID_CFG,
-				&s_ctrl->curr_csi_params->csid_params);
-			mb();
-			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
-				NOTIFY_CSIPHY_CFG,
-				&s_ctrl->curr_csi_params->csiphy_params);
-			mb();
-			msleep(20);
-		}
-
 		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 			NOTIFY_PCLK_CHANGE, &s_ctrl->msm_sensor_reg->
 			output_settings[res].op_pixel_clk);
-		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
-		msleep(30);
 	}
 	return rc;
 }
@@ -385,21 +361,10 @@
 	return rc;
 }
 
-int32_t msm_sensor_release(struct msm_sensor_ctrl_t *s_ctrl)
+static int32_t msm_sensor_release(struct msm_sensor_ctrl_t *s_ctrl)
 {
-	long fps = 0;
-	uint32_t delay = 0;
 	CDBG("%s called\n", __func__);
 	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
-	if (s_ctrl->curr_res != MSM_SENSOR_INVALID_RES) {
-		fps = s_ctrl->msm_sensor_reg->
-			output_settings[s_ctrl->curr_res].vt_pixel_clk /
-			s_ctrl->curr_frame_length_lines /
-			s_ctrl->curr_line_length_pclk;
-		delay = 1000 / fps;
-		CDBG("%s fps = %ld, delay = %d\n", __func__, fps, delay);
-		msleep(delay);
-	}
 	return 0;
 }
 
@@ -418,7 +383,6 @@
 	case VIDIOC_MSM_SENSOR_CSID_INFO: {
 		struct msm_sensor_csi_info *csi_info =
 			(struct msm_sensor_csi_info *)arg;
-		s_ctrl->csid_version = csi_info->csid_version;
 		s_ctrl->is_csic = csi_info->is_csic;
 		return 0;
 	}
@@ -430,14 +394,21 @@
 int32_t msm_sensor_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
 		struct csi_lane_params_t *sensor_output_info)
 {
-	sensor_output_info->csi_lane_assign = s_ctrl->sensordata->
-		sensor_platform_info->csi_lane_params->csi_lane_assign;
-	sensor_output_info->csi_lane_mask = s_ctrl->sensordata->
-		sensor_platform_info->csi_lane_params->csi_lane_mask;
+	uint8_t index;
+	struct msm_camera_csi_lane_params *csi_lane_params =
+		s_ctrl->sensordata->sensor_platform_info->csi_lane_params;
+	if (csi_lane_params) {
+		sensor_output_info->csi_lane_assign = csi_lane_params->
+			csi_lane_assign;
+		sensor_output_info->csi_lane_mask = csi_lane_params->
+			csi_lane_mask;
+		sensor_output_info->csi_phy_sel = csi_lane_params->csi_phy_sel;
+	}
 	sensor_output_info->csi_if = s_ctrl->sensordata->csi_if;
-	sensor_output_info->csid_core = s_ctrl->sensordata->
-			pdata[0].csid_core;
-	sensor_output_info->csid_version = s_ctrl->csid_version;
+	for (index = 0; index < sensor_output_info->csi_if; index++)
+		sensor_output_info->csid_core[index] = s_ctrl->sensordata->
+			pdata[index].csid_core;
+
 	return 0;
 }
 
@@ -450,9 +421,9 @@
 		sizeof(struct sensor_cfg_data)))
 		return -EFAULT;
 	mutex_lock(s_ctrl->msm_sensor_mutex);
-	CDBG("msm_sensor_config: cfgtype = %d\n",
-	cdata.cfgtype);
-		switch (cdata.cfgtype) {
+	CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__,
+		s_ctrl->sensordata->sensor_name, cdata.cfgtype);
+	switch (cdata.cfgtype) {
 		case CFG_SET_FPS:
 		case CFG_SET_PICT_FPS:
 			if (s_ctrl->func_tbl->
@@ -478,8 +449,6 @@
 					s_ctrl,
 					cdata.cfg.exp_gain.gain,
 					cdata.cfg.exp_gain.line);
-			s_ctrl->prev_gain = cdata.cfg.exp_gain.gain;
-			s_ctrl->prev_line = cdata.cfg.exp_gain.line;
 			break;
 
 		case CFG_SET_PICT_EXP_GAIN:
@@ -573,14 +542,19 @@
 				rc = -EFAULT;
 			break;
 
-		case CFG_GET_CALIB_DATA:
-			if (s_ctrl->func_tbl->sensor_get_eeprom_data == NULL) {
+		case CFG_POWER_UP:
+			pr_err("%s calling power up\n", __func__);
+			if (s_ctrl->func_tbl->sensor_power_up)
+				rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+			else
 				rc = -EFAULT;
-				break;
-			}
-			rc = s_ctrl->func_tbl->sensor_get_eeprom_data(s_ctrl, &cdata);
+			break;
 
-			if (copy_to_user((void *)argp, &cdata, sizeof(cdata)))
+		case CFG_POWER_DOWN:
+			if (s_ctrl->func_tbl->sensor_power_down)
+				rc = s_ctrl->func_tbl->sensor_power_down(
+					s_ctrl);
+			else
 				rc = -EFAULT;
 			break;
 
@@ -594,10 +568,15 @@
 	return rc;
 }
 
-static struct msm_cam_clk_info cam_clk_info[] = {
+static struct msm_cam_clk_info cam_8960_clk_info[] = {
 	{"cam_clk", MSM_SENSOR_MCLK_24HZ},
 };
 
+static struct msm_cam_clk_info cam_8974_clk_info[] = {
+	{"cam_src_clk", 19200000},
+	{"cam_clk", -1},
+};
+
 int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
 {
 	struct v4l2_subdev *i2c_mux_sd =
@@ -631,8 +610,8 @@
 		return -ENOMEM;
 	}
 
-	rc = of_property_read_u32(of_node, "flash_type", &val);
-	CDBG("%s flash_type %d, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,flash-type", &val);
+	CDBG("%s qcom,flash-type %d, rc %d\n", __func__, val, rc);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR;
@@ -651,8 +630,8 @@
 	uint32_t count = 0;
 	uint32_t *val_array = NULL;
 
-	count = of_property_count_strings(of_node, "cam_vreg_name");
-	CDBG("%s cam_vreg_name count %d\n", __func__, count);
+	count = of_property_count_strings(of_node, "qcom,cam-vreg-name");
+	CDBG("%s qcom,cam-vreg-name count %d\n", __func__, count);
 
 	if (!count)
 		return 0;
@@ -666,8 +645,8 @@
 
 	pinfo->num_vreg = count;
 	for (i = 0; i < count; i++) {
-		rc = of_property_read_string_index(of_node, "cam_vreg_name", i,
-			&pinfo->cam_vreg[i].reg_name);
+		rc = of_property_read_string_index(of_node,
+			"qcom,cam-vreg-name", i, &pinfo->cam_vreg[i].reg_name);
 		CDBG("%s reg_name[%d] = %s\n", __func__, i,
 			pinfo->cam_vreg[i].reg_name);
 		if (rc < 0) {
@@ -683,8 +662,8 @@
 		goto ERROR1;
 	}
 
-	rc = of_property_read_u32_array(of_node, "cam_vreg_type", val_array,
-		count);
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-type",
+		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
@@ -695,7 +674,7 @@
 			pinfo->cam_vreg[i].type);
 	}
 
-	rc = of_property_read_u32_array(of_node, "cam_vreg_min_voltage",
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-min-voltage",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -707,7 +686,7 @@
 			i, pinfo->cam_vreg[i].min_voltage);
 	}
 
-	rc = of_property_read_u32_array(of_node, "cam_vreg_max_voltage",
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-max-voltage",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -719,8 +698,8 @@
 			i, pinfo->cam_vreg[i].max_voltage);
 	}
 
-	rc = of_property_read_u32_array(of_node, "cam_vreg_op_mode", val_array,
-		count);
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-op-mode",
+		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
@@ -742,19 +721,25 @@
 }
 
 static int32_t msm_sensor_init_gpio_common_tbl_data(struct device_node *of_node,
-	struct msm_camera_gpio_conf *gconf)
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
 {
 	int32_t rc = 0, i = 0;
 	uint32_t count = 0;
 	uint32_t *val_array = NULL;
 
-	if (!of_get_property(of_node, "gpio_common_tbl_num", &count))
+	if (!of_get_property(of_node, "qcom,gpio-common-tbl-num", &count))
 		return 0;
 
 	count /= sizeof(uint32_t);
-
-	if (!count)
+	if (!count) {
+		pr_err("%s qcom,gpio-common-tbl-num 0\n", __func__);
 		return 0;
+	} else if (count > gpio_array_size) {
+		pr_err("%s gpio common tbl size exceeds gpio array\n",
+			__func__);
+		return -EFAULT;
+	}
 
 	val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
 	if (!val_array) {
@@ -771,19 +756,24 @@
 	}
 	gconf->cam_gpio_common_tbl_size = count;
 
-	rc = of_property_read_u32_array(of_node, "gpio_common_tbl_num",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-common-tbl-num",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
 	}
 	for (i = 0; i < count; i++) {
-		gconf->cam_gpio_common_tbl[i].gpio = val_array[i];
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio common tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_common_tbl[i].gpio = gpio_array[val_array[i]];
 		CDBG("%s cam_gpio_common_tbl[%d].gpio = %d\n", __func__, i,
 			gconf->cam_gpio_common_tbl[i].gpio);
 	}
 
-	rc = of_property_read_u32_array(of_node, "gpio_common_tbl_flags",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-common-tbl-flags",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -797,7 +787,7 @@
 
 	for (i = 0; i < count; i++) {
 		rc = of_property_read_string_index(of_node,
-			"gpio_common_tbl_label", i,
+			"qcom,gpio-common-tbl-label", i,
 			&gconf->cam_gpio_common_tbl[i].label);
 		CDBG("%s cam_gpio_common_tbl[%d].label = %s\n", __func__, i,
 			gconf->cam_gpio_common_tbl[i].label);
@@ -819,19 +809,21 @@
 }
 
 static int32_t msm_sensor_init_gpio_req_tbl_data(struct device_node *of_node,
-	struct msm_camera_gpio_conf *gconf)
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
 {
 	int32_t rc = 0, i = 0;
 	uint32_t count = 0;
 	uint32_t *val_array = NULL;
 
-	if (!of_get_property(of_node, "gpio_req_tbl_num", &count))
+	if (!of_get_property(of_node, "qcom,gpio-req-tbl-num", &count))
 		return 0;
 
 	count /= sizeof(uint32_t);
-
-	if (!count)
+	if (!count) {
+		pr_err("%s qcom,gpio-req-tbl-num 0\n", __func__);
 		return 0;
+	}
 
 	val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
 	if (!val_array) {
@@ -848,19 +840,24 @@
 	}
 	gconf->cam_gpio_req_tbl_size = count;
 
-	rc = of_property_read_u32_array(of_node, "gpio_req_tbl_num",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-num",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
 	}
 	for (i = 0; i < count; i++) {
-		gconf->cam_gpio_req_tbl[i].gpio = val_array[i];
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio req tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
 		CDBG("%s cam_gpio_req_tbl[%d].gpio = %d\n", __func__, i,
 			gconf->cam_gpio_req_tbl[i].gpio);
 	}
 
-	rc = of_property_read_u32_array(of_node, "gpio_req_tbl_flags",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-flags",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -874,7 +871,7 @@
 
 	for (i = 0; i < count; i++) {
 		rc = of_property_read_string_index(of_node,
-			"gpio_req_tbl_label", i,
+			"qcom,gpio-req-tbl-label", i,
 			&gconf->cam_gpio_req_tbl[i].label);
 		CDBG("%s cam_gpio_req_tbl[%d].label = %s\n", __func__, i,
 			gconf->cam_gpio_req_tbl[i].label);
@@ -896,19 +893,21 @@
 }
 
 static int32_t msm_sensor_init_gpio_set_tbl_data(struct device_node *of_node,
-	struct msm_camera_gpio_conf *gconf)
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
 {
 	int32_t rc = 0, i = 0;
 	uint32_t count = 0;
 	uint32_t *val_array = NULL;
 
-	if (!of_get_property(of_node, "gpio_set_tbl_num", &count))
+	if (!of_get_property(of_node, "qcom,gpio-set-tbl-num", &count))
 		return 0;
 
 	count /= sizeof(uint32_t);
-
-	if (!count)
+	if (!count) {
+		pr_err("%s qcom,gpio-set-tbl-num 0\n", __func__);
 		return 0;
+	}
 
 	val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
 	if (!val_array) {
@@ -925,19 +924,24 @@
 	}
 	gconf->cam_gpio_set_tbl_size = count;
 
-	rc = of_property_read_u32_array(of_node, "gpio_set_tbl_num",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-num",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
 	}
 	for (i = 0; i < count; i++) {
-		gconf->cam_gpio_set_tbl[i].gpio = val_array[i];
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio set tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_set_tbl[i].gpio = gpio_array[val_array[i]];
 		CDBG("%s cam_gpio_set_tbl[%d].gpio = %d\n", __func__, i,
 			gconf->cam_gpio_set_tbl[i].gpio);
 	}
 
-	rc = of_property_read_u32_array(of_node, "gpio_set_tbl_flags",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-flags",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -949,7 +953,7 @@
 			gconf->cam_gpio_set_tbl[i].flags);
 	}
 
-	rc = of_property_read_u32_array(of_node, "gpio_set_tbl_delay",
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-delay",
 		val_array, count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -973,7 +977,8 @@
 }
 
 static int32_t msm_sensor_init_gpio_tlmm_tbl_data(struct device_node *of_node,
-	struct msm_camera_gpio_conf *gconf)
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
 {
 	int32_t rc = 0, i = 0;
 	uint32_t count = 0;
@@ -1024,7 +1029,12 @@
 		goto ERROR4;
 	}
 	for (i = 0; i < count; i++) {
-		tlmm_cfg[i].gpio = val_array[i];
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio set tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		tlmm_cfg[i].gpio = gpio_array[val_array[i]];
 		CDBG("%s tlmm_cfg[%d].gpio = %d\n", __func__, i,
 			tlmm_cfg[i].gpio);
 	}
@@ -1100,8 +1110,8 @@
 	struct msm_camera_sensor_platform_info *pinfo =
 		sensordata->sensor_platform_info;
 
-	rc = of_property_read_u32(of_node, "csi_if", &count);
-	CDBG("%s csi_if %d, rc %d\n", __func__, count, rc);
+	rc = of_property_read_u32(of_node, "qcom,csi-if", &count);
+	CDBG("%s qcom,csi-if %d, rc %d\n", __func__, count, rc);
 	if (rc < 0 || !count)
 		return rc;
 	sensordata->csi_if = count;
@@ -1120,25 +1130,27 @@
 		goto ERROR1;
 	}
 
-	rc = of_property_read_u32_array(of_node, "csid_core", val_array, count);
+	rc = of_property_read_u32_array(of_node, "qcom,csid-core", val_array,
+		count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
 	}
 	for (i = 0; i < count; i++) {
 		sensordata->pdata[i].csid_core = val_array[i];
-		CDBG("%s csid_core[%d].csid_core = %d\n", __func__, i,
+		CDBG("%s csi_data[%d].csid_core = %d\n", __func__, i,
 			sensordata->pdata[i].csid_core);
 	}
 
-	rc = of_property_read_u32_array(of_node, "is_vpe", val_array, count);
+	rc = of_property_read_u32_array(of_node, "qcom,is-vpe", val_array,
+		count);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR2;
 	}
 	for (i = 0; i < count; i++) {
 		sensordata->pdata[i].is_vpe = val_array[i];
-		CDBG("%s csid_core[%d].is_vpe = %d\n", __func__, i,
+		CDBG("%s csi_data[%d].is_vpe = %d\n", __func__, i,
 			sensordata->pdata[i].is_vpe);
 	}
 
@@ -1150,22 +1162,30 @@
 		goto ERROR2;
 	}
 
-	rc = of_property_read_u32(of_node, "csi_lane_assign", &val);
-	CDBG("%s csi_lane_assign %x, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,csi-lane-assign", &val);
+	CDBG("%s qcom,csi-lane-assign %x, rc %d\n", __func__, val, rc);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR3;
 	}
 	pinfo->csi_lane_params->csi_lane_assign = val;
 
-	rc = of_property_read_u32(of_node, "csi_lane_mask", &val);
-	CDBG("%s csi_lane_mask %x, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,csi-lane-mask", &val);
+	CDBG("%s qcom,csi-lane-mask %x, rc %d\n", __func__, val, rc);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR3;
 	}
 	pinfo->csi_lane_params->csi_lane_mask = val;
 
+	rc = of_property_read_u32(of_node, "qcom,csi-phy-sel", &val);
+	CDBG("%s qcom,csi-phy-sel %x, rc %d\n", __func__, val, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR3;
+	}
+	pinfo->csi_lane_params->csi_phy_sel = val;
+
 	kfree(val_array);
 	return rc;
 ERROR3:
@@ -1183,8 +1203,8 @@
 	int32_t rc = 0;
 	uint32_t val = 0;
 
-	rc = of_property_read_u32(of_node, "actuator_cam_name", &val);
-	CDBG("%s actuator_cam_name %d, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,actuator-cam-name", &val);
+	CDBG("%s qcom,actuator-cam-name %d, rc %d\n", __func__, val, rc);
 	if (rc < 0)
 		return 0;
 
@@ -1198,13 +1218,13 @@
 
 	sensordata->actuator_info->cam_name = val;
 
-	rc = of_property_read_u32(of_node, "actuator_vcm_pwd", &val);
-	CDBG("%s actuator_vcm_pwd %d, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,actuator-vcm-pwd", &val);
+	CDBG("%s qcom,actuator-vcm-pwd %d, rc %d\n", __func__, val, rc);
 	if (!rc)
 		sensordata->actuator_info->vcm_pwd = val;
 
-	rc = of_property_read_u32(of_node, "actuator_vcm_enable", &val);
-	CDBG("%s actuator_vcm_enable %d, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,actuator-vcm-enable", &val);
+	CDBG("%s qcom,actuator-vcm-enable %d, rc %d\n", __func__, val, rc);
 	if (!rc)
 		sensordata->actuator_info->vcm_enable = val;
 
@@ -1216,12 +1236,14 @@
 static int32_t msm_sensor_init_sensor_data(struct platform_device *pdev,
 	struct msm_sensor_ctrl_t *s_ctrl)
 {
-	int32_t rc = 0;
+	int32_t rc = 0, i = 0;
 	uint32_t val = 0;
 	struct device_node *of_node = pdev->dev.of_node;
 	struct msm_camera_sensor_platform_info *pinfo = NULL;
 	struct msm_camera_gpio_conf *gconf = NULL;
 	struct msm_camera_sensor_info *sensordata = NULL;
+	uint16_t *gpio_array = NULL;
+	uint16_t gpio_array_size = 0;
 
 	s_ctrl->sensordata = kzalloc(sizeof(struct msm_camera_sensor_info),
 		GFP_KERNEL);
@@ -1231,25 +1253,26 @@
 	}
 
 	sensordata = s_ctrl->sensordata;
-	rc = of_property_read_string(of_node, "sensor_name",
+
+	rc = of_property_read_string(of_node, "qcom,sensor-name",
 		&sensordata->sensor_name);
-	CDBG("%s sensor_name %s, rc %d\n", __func__,
+	CDBG("%s qcom,sensor-name %s, rc %d\n", __func__,
 		sensordata->sensor_name, rc);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR1;
 	}
 
-	rc = of_property_read_u32(of_node, "camera_type", &val);
-	CDBG("%s camera_type %d, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,camera-type", &val);
+	CDBG("%s qcom,camera-type %d, rc %d\n", __func__, val, rc);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR1;
 	}
 	sensordata->camera_type = val;
 
-	rc = of_property_read_u32(of_node, "sensor_type", &val);
-	CDBG("%s sensor_type %d, rc %d\n", __func__, val, rc);
+	rc = of_property_read_u32(of_node, "qcom,sensor-type", &val);
+	CDBG("%s qcom,sensor-type %d, rc %d\n", __func__, val, rc);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR1;
@@ -1272,8 +1295,10 @@
 
 	pinfo = sensordata->sensor_platform_info;
 
-	rc = of_property_read_u32(of_node, "mount_angle", &pinfo->mount_angle);
-	CDBG("%s mount_angle %d, rc %d\n", __func__, pinfo->mount_angle, rc);
+	rc = of_property_read_u32(of_node, "qcom,mount-angle",
+		&pinfo->mount_angle);
+	CDBG("%s qcom,mount-angle %d, rc %d\n", __func__, pinfo->mount_angle,
+		rc);
 	if (rc < 0) {
 		/* Set default mount angle */
 		pinfo->mount_angle = 0;
@@ -1300,7 +1325,8 @@
 		goto ERROR4;
 	}
 	gconf = pinfo->gpio_conf;
-	rc = of_property_read_u32(of_node, "gpio_no_mux", &gconf->gpio_no_mux);
+	rc = of_property_read_u32(of_node, "qcom,gpio-no-mux",
+		&gconf->gpio_no_mux);
 	CDBG("%s gconf->gpio_no_mux %d, rc %d\n", __func__,
 		gconf->gpio_no_mux, rc);
 	if (rc < 0) {
@@ -1308,36 +1334,57 @@
 		goto ERROR5;
 	}
 
-	rc = msm_sensor_init_gpio_common_tbl_data(of_node, gconf);
-	if (rc < 0) {
-		pr_err("%s failed %d\n", __func__, __LINE__);
-		goto ERROR5;
-	}
+	gpio_array_size = of_gpio_count(of_node);
+	CDBG("%s gpio count %d\n", __func__, gpio_array_size);
 
-	rc = msm_sensor_init_gpio_req_tbl_data(of_node, gconf);
-	if (rc < 0) {
-		pr_err("%s failed %d\n", __func__, __LINE__);
-		goto ERROR6;
-	}
+	if (gpio_array_size) {
+		gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+			GFP_KERNEL);
+		if (!gpio_array) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR5;
+		}
+		for (i = 0; i < gpio_array_size; i++) {
+			gpio_array[i] = of_get_gpio(of_node, i);
+			CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+				gpio_array[i]);
+		}
 
-	rc = msm_sensor_init_gpio_set_tbl_data(of_node, gconf);
-	if (rc < 0) {
-		pr_err("%s failed %d\n", __func__, __LINE__);
-		goto ERROR7;
-	}
+		rc = msm_sensor_init_gpio_common_tbl_data(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR5;
+		}
 
-	rc = msm_sensor_init_gpio_tlmm_tbl_data(of_node, gconf);
-	if (rc < 0) {
-		pr_err("%s failed %d\n", __func__, __LINE__);
-		goto ERROR8;
-	}
+		rc = msm_sensor_init_gpio_req_tbl_data(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR6;
+		}
 
+		rc = msm_sensor_init_gpio_set_tbl_data(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR7;
+		}
+
+		rc = msm_sensor_init_gpio_tlmm_tbl_data(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR8;
+		}
+	}
 	rc = msm_sensor_init_actuator_data(of_node, sensordata);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		goto ERROR9;
 	}
 
+	kfree(gpio_array);
 	return rc;
 
 ERROR9:
@@ -1366,6 +1413,7 @@
 	kfree(s_ctrl->sensordata->flash_data);
 ERROR1:
 	kfree(s_ctrl->sensordata);
+	kfree(gpio_array);
 	return rc;
 }
 
@@ -1397,15 +1445,17 @@
 {
 	int32_t rc = 0;
 	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
-	CDBG("%s: %d\n", __func__, __LINE__);
+	struct device *dev = NULL;
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE)
+		dev = &s_ctrl->pdev->dev;
+	else
+		dev = &s_ctrl->sensor_i2c_client->client->dev;
+	s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
+			* data->sensor_platform_info->num_vreg, GFP_KERNEL);
 	if (!s_ctrl->reg_ptr) {
-		s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
-				* data->sensor_platform_info->num_vreg, GFP_KERNEL);
-		if (!s_ctrl->reg_ptr) {
-			pr_err("%s: could not allocate mem for regulators\n",
-				__func__);
-			return -ENOMEM;
-		}
+		pr_err("%s: could not allocate mem for regulators\n",
+			__func__);
+		return -ENOMEM;
 	}
 
 	rc = msm_camera_request_gpio_table(data, 1);
@@ -1414,19 +1464,23 @@
 		goto request_gpio_failed;
 	}
 
-	rc = msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
-			s_ctrl->sensordata->sensor_platform_info->cam_vreg,
-			s_ctrl->sensordata->sensor_platform_info->num_vreg,
-			s_ctrl->reg_ptr, 1);
+	rc = msm_camera_config_vreg(dev,
+		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->vreg_seq,
+		s_ctrl->num_vreg_seq,
+		s_ctrl->reg_ptr, 1);
 	if (rc < 0) {
 		pr_err("%s: regulator on failed\n", __func__);
 		goto config_vreg_failed;
 	}
 
-	rc = msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
-			s_ctrl->sensordata->sensor_platform_info->cam_vreg,
-			s_ctrl->sensordata->sensor_platform_info->num_vreg,
-			s_ctrl->reg_ptr, 1);
+	rc = msm_camera_enable_vreg(dev,
+		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->vreg_seq,
+		s_ctrl->num_vreg_seq,
+		s_ctrl->reg_ptr, 1);
 	if (rc < 0) {
 		pr_err("%s: enable regulator failed\n", __func__);
 		goto enable_vreg_failed;
@@ -1438,17 +1492,33 @@
 		goto config_gpio_failed;
 	}
 
-	if (s_ctrl->clk_rate != 0)
-		cam_clk_info->clk_rate = s_ctrl->clk_rate;
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_I2C_DEVICE) {
+		if (s_ctrl->clk_rate != 0)
+			cam_8960_clk_info->clk_rate = s_ctrl->clk_rate;
 
-	rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
-		cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 1);
-	if (rc < 0) {
-		pr_err("%s: clk enable failed\n", __func__);
-		goto enable_clk_failed;
+		rc = msm_cam_clk_enable(dev, cam_8960_clk_info,
+			s_ctrl->cam_clk, ARRAY_SIZE(cam_8960_clk_info), 1);
+		if (rc < 0) {
+			pr_err("%s: clk enable failed\n", __func__);
+			goto enable_clk_failed;
+		}
+	} else {
+		rc = msm_cam_clk_enable(dev, cam_8974_clk_info,
+			s_ctrl->cam_clk, ARRAY_SIZE(cam_8974_clk_info), 1);
+		if (rc < 0) {
+			pr_err("%s: clk enable failed\n", __func__);
+			goto enable_clk_failed;
+		}
 	}
 
-	usleep_range(1000, 2000);
+	if (!s_ctrl->power_seq_delay)
+		usleep_range(1000, 2000);
+	else if (s_ctrl->power_seq_delay < 20)
+		usleep_range((s_ctrl->power_seq_delay * 1000),
+			((s_ctrl->power_seq_delay * 1000) + 1000));
+	else
+		msleep(s_ctrl->power_seq_delay);
+
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(1);
 
@@ -1456,7 +1526,7 @@
 		data->sensor_platform_info->i2c_conf->use_i2c_mux)
 		msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
 
-	if (s_ctrl->sensor_i2c_client->cci_client) {
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
 		rc = msm_sensor_cci_util(s_ctrl->sensor_i2c_client,
 			MSM_CCI_INIT);
 		if (rc < 0) {
@@ -1464,6 +1534,7 @@
 			goto cci_init_failed;
 		}
 	}
+	s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
 	return rc;
 
 cci_init_failed:
@@ -1474,15 +1545,19 @@
 enable_clk_failed:
 		msm_camera_config_gpio_table(data, 0);
 config_gpio_failed:
-	msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+	msm_camera_enable_vreg(dev,
 			s_ctrl->sensordata->sensor_platform_info->cam_vreg,
 			s_ctrl->sensordata->sensor_platform_info->num_vreg,
+			s_ctrl->vreg_seq,
+			s_ctrl->num_vreg_seq,
 			s_ctrl->reg_ptr, 0);
 
 enable_vreg_failed:
-	msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+	msm_camera_config_vreg(dev,
 		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
 		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->vreg_seq,
+		s_ctrl->num_vreg_seq,
 		s_ctrl->reg_ptr, 0);
 config_vreg_failed:
 	msm_camera_request_gpio_table(data, 0);
@@ -1494,8 +1569,12 @@
 int32_t msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
-	CDBG("%s\n", __func__);
-	if (s_ctrl->sensor_i2c_client->cci_client) {
+	struct device *dev = NULL;
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE)
+		dev = &s_ctrl->pdev->dev;
+	else
+		dev = &s_ctrl->sensor_i2c_client->client->dev;
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
 		msm_sensor_cci_util(s_ctrl->sensor_i2c_client,
 			MSM_CCI_RELEASE);
 	}
@@ -1507,20 +1586,28 @@
 
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(0);
-	msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
-		cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 0);
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_I2C_DEVICE)
+		msm_cam_clk_enable(dev, cam_8960_clk_info, s_ctrl->cam_clk,
+			ARRAY_SIZE(cam_8960_clk_info), 0);
+	else
+		msm_cam_clk_enable(dev, cam_8974_clk_info, s_ctrl->cam_clk,
+			ARRAY_SIZE(cam_8974_clk_info), 0);
 	msm_camera_config_gpio_table(data, 0);
-	msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+	msm_camera_enable_vreg(dev,
 		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
 		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->vreg_seq,
+		s_ctrl->num_vreg_seq,
 		s_ctrl->reg_ptr, 0);
-	msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+	msm_camera_config_vreg(dev,
 		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
 		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->vreg_seq,
+		s_ctrl->num_vreg_seq,
 		s_ctrl->reg_ptr, 0);
 	msm_camera_request_gpio_table(data, 0);
 	kfree(s_ctrl->reg_ptr);
-	s_ctrl->reg_ptr = NULL;
+	s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
 	return 0;
 }
 
@@ -1538,7 +1625,7 @@
 		return rc;
 	}
 
-	CDBG("%s msm_sensor id: %x, exp id: %x\n", __func__, chipid,
+	CDBG("%s: read id: %x expected id %x:\n", __func__, chipid,
 		s_ctrl->sensor_id_info->sensor_id);
 	if (chipid != s_ctrl->sensor_id_info->sensor_id) {
 		pr_err("msm_sensor_match_id chip id doesnot match\n");
@@ -1547,11 +1634,6 @@
 	return rc;
 }
 
-struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct msm_sensor_ctrl_t, sensor_v4l2_subdev);
-}
-
 int32_t msm_sensor_i2c_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
@@ -1566,6 +1648,7 @@
 	}
 
 	s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+	s_ctrl->sensor_device_type = MSM_SENSOR_I2C_DEVICE;
 	if (s_ctrl->sensor_i2c_client != NULL) {
 		s_ctrl->sensor_i2c_client->client = client;
 		if (s_ctrl->sensor_i2c_addr != 0)
@@ -1597,6 +1680,10 @@
 	if (rc < 0)
 		goto probe_fail;
 
+	if (!s_ctrl->wait_num_frames)
+		s_ctrl->wait_num_frames = 1 * Q10;
+
+	pr_err("%s %s probe succeeded\n", __func__, client->name);
 	snprintf(s_ctrl->sensor_v4l2_subdev.name,
 		sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
 	v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
@@ -1647,6 +1734,7 @@
 			return rc;
 		}
 	}
+	s_ctrl->sensor_device_type = MSM_SENSOR_PLATFORM_DEVICE;
 	s_ctrl->sensor_i2c_client->cci_client = kzalloc(sizeof(
 		struct msm_camera_cci_client), GFP_KERNEL);
 	if (!s_ctrl->sensor_i2c_client->cci_client) {
@@ -1672,7 +1760,7 @@
 	s_ctrl->sensor_i2c_client->cci_client->cci_i2c_master = MASTER_0;
 	s_ctrl->sensor_i2c_client->cci_client->sid =
 		s_ctrl->sensor_i2c_addr >> 1;
-	s_ctrl->sensor_i2c_client->cci_client->retries = 0;
+	s_ctrl->sensor_i2c_client->cci_client->retries = 3;
 	s_ctrl->sensor_i2c_client->cci_client->id_map = 0;
 
 	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 6c6b33e..7dd0602 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -24,187 +24,14 @@
 #include <linux/uaccess.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <mach/camera.h>
-#include <mach/gpio.h>
 #include <media/msm_camera.h>
 #include <media/v4l2-subdev.h>
 #include "msm_camera_i2c.h"
 #include "msm_camera_eeprom.h"
-#define Q8  0x00000100
-#define Q10 0x00000400
-
-#define MSM_SENSOR_MCLK_8HZ 8000000
-#define MSM_SENSOR_MCLK_16HZ 16000000
-#define MSM_SENSOR_MCLK_24HZ 24000000
-
-struct gpio_tlmm_cfg {
-	uint32_t gpio;
-	uint32_t dir;
-	uint32_t pull;
-	uint32_t drvstr;
-};
-
-enum msm_sensor_reg_update {
-	/* Sensor egisters that need to be updated during initialization */
-	MSM_SENSOR_REG_INIT,
-	/* Sensor egisters that needs periodic I2C writes */
-	MSM_SENSOR_UPDATE_PERIODIC,
-	/* All the sensor Registers will be updated */
-	MSM_SENSOR_UPDATE_ALL,
-	/* Not valid update */
-	MSM_SENSOR_UPDATE_INVALID
-};
-
-enum msm_sensor_cam_mode_t {
-	MSM_SENSOR_MODE_2D_RIGHT,
-	MSM_SENSOR_MODE_2D_LEFT,
-	MSM_SENSOR_MODE_3D,
-	MSM_SENSOR_MODE_INVALID
-};
-
-struct msm_sensor_output_reg_addr_t {
-	uint16_t x_output;
-	uint16_t y_output;
-	uint16_t line_length_pclk;
-	uint16_t frame_length_lines;
-};
-
-struct msm_sensor_id_info_t {
-	uint16_t sensor_id_reg_addr;
-	uint16_t sensor_id;
-};
-
-struct msm_sensor_exp_gain_info_t {
-	uint16_t coarse_int_time_addr;
-	uint16_t global_gain_addr;
-	uint16_t vert_offset;
-};
-
-struct msm_sensor_reg_t {
-	enum msm_camera_i2c_data_type default_data_type;
-	struct msm_camera_i2c_reg_conf *start_stream_conf;
-	uint8_t start_stream_conf_size;
-	struct msm_camera_i2c_reg_conf *stop_stream_conf;
-	uint8_t stop_stream_conf_size;
-	struct msm_camera_i2c_reg_conf *group_hold_on_conf;
-	uint8_t group_hold_on_conf_size;
-	struct msm_camera_i2c_reg_conf *group_hold_off_conf;
-	uint8_t group_hold_off_conf_size;
-	struct msm_camera_i2c_conf_array *init_settings;
-	uint8_t init_size;
-	struct msm_camera_i2c_conf_array *mode_settings;
-	struct msm_camera_i2c_conf_array *no_effect_settings;
-	struct msm_sensor_output_info_t *output_settings;
-	uint8_t num_conf;
-};
-
-struct v4l2_subdev_info {
-	enum v4l2_mbus_pixelcode code;
-	enum v4l2_colorspace colorspace;
-	uint16_t fmt;
-	uint16_t order;
-};
-
-struct msm_sensor_ctrl_t;
-
-struct msm_sensor_v4l2_ctrl_info_t {
-	uint32_t ctrl_id;
-	int16_t min;
-	int16_t max;
-	int16_t step;
-	struct msm_camera_i2c_enum_conf_array *enum_cfg_settings;
-	int (*s_v4l2_ctrl) (struct msm_sensor_ctrl_t *,
-		struct msm_sensor_v4l2_ctrl_info_t *, int);
-};
-
-struct msm_sensor_fn_t {
-	void (*sensor_start_stream) (struct msm_sensor_ctrl_t *);
-	void (*sensor_stop_stream) (struct msm_sensor_ctrl_t *);
-	void (*sensor_group_hold_on) (struct msm_sensor_ctrl_t *);
-	void (*sensor_group_hold_off) (struct msm_sensor_ctrl_t *);
-
-	int32_t (*sensor_set_fps) (struct msm_sensor_ctrl_t *,
-			struct fps_cfg *);
-	int32_t (*sensor_write_exp_gain) (struct msm_sensor_ctrl_t *,
-			uint16_t, uint32_t);
-	int32_t (*sensor_write_snapshot_exp_gain) (struct msm_sensor_ctrl_t *,
-			uint16_t, uint32_t);
-	int32_t (*sensor_setting) (struct msm_sensor_ctrl_t *,
-			int update_type, int rt);
-	int32_t (*sensor_csi_setting) (struct msm_sensor_ctrl_t *,
-			int update_type, int rt);
-	int32_t (*sensor_set_sensor_mode)
-			(struct msm_sensor_ctrl_t *, int, int);
-	int32_t (*sensor_mode_init) (struct msm_sensor_ctrl_t *,
-		int, struct sensor_init_cfg *);
-	int32_t (*sensor_get_output_info) (struct msm_sensor_ctrl_t *,
-		struct sensor_output_info_t *);
-	int (*sensor_config) (struct msm_sensor_ctrl_t *, void __user *);
-	int (*sensor_power_down)
-		(struct msm_sensor_ctrl_t *);
-	int (*sensor_power_up) (struct msm_sensor_ctrl_t *);
-	int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
-	int (*sensor_get_eeprom_data) (struct msm_sensor_ctrl_t *,
-		struct sensor_cfg_data *);
-	int (*sensor_adjust_frame_lines)
-		(struct msm_sensor_ctrl_t *s_ctrl, uint16_t res);
-	int32_t (*sensor_get_csi_params)(struct msm_sensor_ctrl_t *,
-		struct csi_lane_params_t *);
-};
-
-struct msm_sensor_csi_info {
-	uint32_t csid_version;
-	uint8_t is_csic;
-};
-
-enum msm_sensor_state {
-	MSM_SENSOR_POWER_UP,
-	MSM_SENSOR_POWER_DOWN,
-};
-
-struct msm_sensor_ctrl_t {
-	struct  msm_camera_sensor_info *sensordata;
-	struct i2c_client *msm_sensor_client;
-	struct i2c_driver *sensor_i2c_driver;
-	struct msm_camera_i2c_client *sensor_i2c_client;
-	struct platform_device *pdev;
-	uint16_t sensor_i2c_addr;
-
-	struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
-	struct msm_sensor_id_info_t *sensor_id_info;
-	struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
-	struct msm_sensor_reg_t *msm_sensor_reg;
-	struct msm_sensor_v4l2_ctrl_info_t *msm_sensor_v4l2_ctrl_info;
-	uint16_t num_v4l2_ctrl;
-	uint32_t csid_version;
-	uint8_t is_csic;
-
-	uint16_t curr_line_length_pclk;
-	uint16_t curr_frame_length_lines;
-	uint16_t prev_gain;
-	uint16_t prev_line;
-
-	uint32_t fps_divider;
-	enum msm_sensor_resolution_t curr_res;
-	enum msm_sensor_cam_mode_t cam_mode;
-
-	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;
-	uint8_t sensor_v4l2_subdev_info_size;
-	struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
-	struct msm_sensor_fn_t *func_tbl;
-	struct regulator **reg_ptr;
-	struct clk *cam_clk;
-	long clk_rate;
-	enum msm_sensor_state sensor_state;
-};
+#include "msm_sensor_common.h"
 
 void msm_sensor_start_stream(struct msm_sensor_ctrl_t *s_ctrl);
 void msm_sensor_stop_stream(struct msm_sensor_ctrl_t *s_ctrl);
@@ -258,11 +85,9 @@
 int32_t msm_sensor_write_output_settings(struct msm_sensor_ctrl_t *s_ctrl,
 	uint16_t res);
 
-int32_t msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl,
-	uint16_t res);
+void msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl);
 
-int32_t msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl,
-	uint16_t res);
+void msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl);
 
 int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
 			int update_type, int res);
@@ -278,19 +103,11 @@
 int32_t msm_sensor_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
 		struct csi_lane_params_t *sensor_output_info);
 
+struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
 int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl);
 
-#ifdef CONFIG_MSM_CAMERA_SENSOR
-struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
-#else
-static inline struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd)
-{
-	return NULL;
-}
-#endif
-
 #define VIDIOC_MSM_SENSOR_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 10, void __user *)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, void __user *)
 
 #define VIDIOC_MSM_SENSOR_RELEASE \
 	_IO('V', BASE_VIDIOC_PRIVATE + 11)
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.c b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
new file mode 100644
index 0000000..f4ee31f
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
@@ -0,0 +1,907 @@
+/* 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
+ * 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_bayer.h"
+#include "msm.h"
+#include "msm_ispif.h"
+#include "msm_camera_i2c_mux.h"
+#include "msm_camera_i2c.h"
+/*=============================================================*/
+
+long msm_sensor_bayer_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+	void __user *argp = (void __user *)arg;
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_CFG:
+		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+	case VIDIOC_MSM_SENSOR_RELEASE:
+		return 0;
+	case VIDIOC_MSM_SENSOR_CSID_INFO: {
+		struct msm_sensor_csi_info *csi_info =
+			(struct msm_sensor_csi_info *)arg;
+		s_ctrl->is_csic = csi_info->is_csic;
+		return 0;
+	}
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+int32_t msm_sensor_bayer_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
+		struct csi_lane_params_t *sensor_output_info)
+{
+	uint8_t index;
+	struct msm_camera_csi_lane_params *csi_lane_params =
+		s_ctrl->sensordata->sensor_platform_info->csi_lane_params;
+	if (csi_lane_params) {
+		sensor_output_info->csi_lane_assign = csi_lane_params->
+			csi_lane_assign;
+		sensor_output_info->csi_lane_mask = csi_lane_params->
+			csi_lane_mask;
+	}
+	sensor_output_info->csi_if = s_ctrl->sensordata->csi_if;
+	for (index = 0; index < sensor_output_info->csi_if; index++)
+		sensor_output_info->csid_core[index] = s_ctrl->sensordata->
+			pdata[index].csid_core;
+
+	return 0;
+}
+
+int32_t msm_sensor_bayer_config(struct msm_sensor_ctrl_t *s_ctrl,
+	void __user *argp)
+{
+	struct sensor_cfg_data cdata;
+	long rc = 0;
+	if (copy_from_user(&cdata,
+		(void *)argp,
+		sizeof(struct sensor_cfg_data)))
+		return -EFAULT;
+	mutex_lock(s_ctrl->msm_sensor_mutex);
+	CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__,
+		s_ctrl->sensordata->sensor_name, cdata.cfgtype);
+	switch (cdata.cfgtype) {
+	case CFG_WRITE_I2C_ARRAY: {
+		struct msm_camera_i2c_reg_setting conf_array;
+		struct msm_camera_i2c_reg_array *regs = NULL;
+
+		if (copy_from_user(&conf_array,
+			(void *)cdata.cfg.setting,
+			sizeof(struct msm_camera_i2c_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		regs = kzalloc(conf_array.size * sizeof(
+			struct msm_camera_i2c_reg_array),
+			GFP_KERNEL);
+		if (!regs) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		if (copy_from_user(regs, (void *)conf_array.reg_setting,
+			conf_array.size * sizeof(
+			struct msm_camera_i2c_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(regs);
+			rc = -EFAULT;
+			break;
+		}
+
+		conf_array.reg_setting = regs;
+		rc = msm_camera_i2c_write_bayer_table(s_ctrl->sensor_i2c_client,
+			&conf_array);
+		kfree(regs);
+		break;
+	}
+	case CFG_READ_I2C_ARRAY: {
+		struct msm_camera_i2c_reg_setting conf_array;
+		struct msm_camera_i2c_reg_array *regs;
+		int index;
+
+		if (copy_from_user(&conf_array,
+				(void *)cdata.cfg.setting,
+				sizeof(struct msm_camera_i2c_reg_setting))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+		}
+
+		regs = kzalloc(conf_array.size * sizeof(
+				struct msm_camera_i2c_reg_array),
+				GFP_KERNEL);
+		if (!regs) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			kfree(regs);
+			break;
+		}
+
+		if (copy_from_user(regs, (void *)conf_array.reg_setting,
+				conf_array.size * sizeof(
+				struct msm_camera_i2c_reg_array))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				kfree(regs);
+				rc = -EFAULT;
+				break;
+			}
+
+		s_ctrl->sensor_i2c_client->addr_type = conf_array.addr_type;
+		for (index = 0; index < conf_array.size; index++) {
+			msm_camera_i2c_read(s_ctrl->sensor_i2c_client,
+					regs[index].reg_addr,
+					&regs[index].reg_data,
+				conf_array.data_type
+				);
+		}
+
+		if (copy_to_user(conf_array.reg_setting,
+			regs,
+			conf_array.size * sizeof(
+			struct msm_camera_i2c_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(regs);
+			rc = -EFAULT;
+			break;
+		}
+		s_ctrl->sensor_i2c_client->addr_type = conf_array.addr_type;
+		kfree(regs);
+		break;
+	}
+	case CFG_PCLK_CHANGE: {
+		uint32_t pclk = cdata.cfg.pclk;
+		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+			NOTIFY_PCLK_CHANGE, &pclk);
+		break;
+	}
+	case CFG_GPIO_OP: {
+		struct msm_cam_gpio_operation gop;
+		if (copy_from_user(&gop,
+			(void *)cdata.cfg.setting,
+			sizeof(struct msm_cam_gpio_operation))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+		}
+		switch (gop.op_type) {
+		case GPIO_GET_VALUE:
+			gop.value = gpio_get_value(gop.address);
+			if (copy_from_user((void *)cdata.cfg.setting,
+				&gop,
+				sizeof(struct msm_cam_gpio_operation))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+			break;
+		case GPIO_SET_VALUE:
+			gpio_set_value(gop.address, gop.value);
+			break;
+		case GPIO_SET_DIRECTION_INPUT:
+			gpio_direction_input(gop.address);
+			break;
+		case GPIO_SET_DIRECTION_OUTPUT:
+			gpio_direction_output(gop.address, gop.value);
+			break;
+		case GPIO_REQUEST:
+			gpio_request(gop.address, gop.tag);
+			break;
+		case GPIO_FREE:
+			gpio_free(gop.address);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	}
+	case CFG_GET_CSI_PARAMS:
+		if (s_ctrl->func_tbl->sensor_get_csi_params == NULL) {
+			rc = -EFAULT;
+			break;
+		}
+		rc = s_ctrl->func_tbl->sensor_get_csi_params(
+			s_ctrl,
+			&cdata.cfg.csi_lane_params);
+
+		if (copy_to_user((void *)argp,
+			&cdata,
+			sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+
+	case CFG_POWER_UP:
+		if (s_ctrl->func_tbl->sensor_power_up)
+			rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+		else
+			rc = -EFAULT;
+		break;
+
+	case CFG_POWER_DOWN:
+		if (s_ctrl->func_tbl->sensor_power_down)
+			rc = s_ctrl->func_tbl->sensor_power_down(
+				s_ctrl);
+		else
+			rc = -EFAULT;
+		break;
+
+	case CFG_CONFIG_VREG_ARRAY: {
+		struct msm_camera_vreg_setting vreg_setting;
+		struct camera_vreg_t *cam_vreg = NULL;
+
+		if (copy_from_user(&vreg_setting,
+			(void *)cdata.cfg.setting,
+			sizeof(struct msm_camera_vreg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		cam_vreg = kzalloc(vreg_setting.num_vreg * sizeof(
+			struct camera_vreg_t),
+			GFP_KERNEL);
+		if (!cam_vreg) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		if (copy_from_user(cam_vreg, (void *)vreg_setting.cam_vreg,
+			vreg_setting.num_vreg * sizeof(
+			struct camera_vreg_t))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(cam_vreg);
+			rc = -EFAULT;
+			break;
+		}
+		rc = msm_camera_config_vreg(
+			&s_ctrl->sensor_i2c_client->client->dev,
+			cam_vreg,
+			vreg_setting.num_vreg,
+			NULL,
+			0,
+			s_ctrl->reg_ptr,
+			vreg_setting.enable);
+		if (rc < 0) {
+			kfree(cam_vreg);
+			pr_err("%s: regulator on failed\n", __func__);
+			break;
+		}
+
+		rc = msm_camera_enable_vreg(
+			&s_ctrl->sensor_i2c_client->client->dev,
+			cam_vreg,
+			vreg_setting.num_vreg,
+			NULL,
+			0,
+			s_ctrl->reg_ptr,
+			vreg_setting.enable);
+		if (rc < 0) {
+			kfree(cam_vreg);
+			pr_err("%s: enable regulator failed\n", __func__);
+			break;
+		}
+		kfree(cam_vreg);
+		break;
+	}
+	case CFG_CONFIG_CLK_ARRAY: {
+		struct msm_cam_clk_setting clk_setting;
+		struct msm_cam_clk_info *clk_info = NULL;
+
+		if (copy_from_user(&clk_setting,
+			(void *)cdata.cfg.setting,
+			sizeof(struct msm_camera_vreg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		clk_info = kzalloc(clk_setting.num_clk_info * sizeof(
+			struct msm_cam_clk_info),
+			GFP_KERNEL);
+		if (!clk_info) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		if (copy_from_user(clk_info, (void *)clk_setting.clk_info,
+			clk_setting.num_clk_info * sizeof(
+			struct msm_cam_clk_info))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(clk_info);
+			rc = -EFAULT;
+			break;
+		}
+		rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
+			clk_info, s_ctrl->cam_clk,
+			clk_setting.num_clk_info,
+			clk_setting.enable);
+		kfree(clk_info);
+		break;
+	}
+	case CFG_GET_EEPROM_DATA: {
+		if (copy_to_user((void *)cdata.cfg.eeprom_data.eeprom_data,
+			&s_ctrl->eeprom_data, s_ctrl->eeprom_data.length)) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+		}
+		cdata.cfg.eeprom_data.index = s_ctrl->eeprom_data.length;
+		break;
+	}
+	default:
+		rc = -EFAULT;
+		break;
+	}
+
+	mutex_unlock(s_ctrl->msm_sensor_mutex);
+
+	return rc;
+}
+
+static struct msm_cam_clk_info cam_clk_info[] = {
+	{"cam_clk", MSM_SENSOR_MCLK_24HZ},
+};
+
+int32_t msm_sensor_bayer_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_INIT, NULL);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+	return 0;
+}
+
+int32_t msm_sensor_bayer_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+				VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+	return 0;
+}
+
+static struct msm_camera_power_seq_t sensor_power_seq[] = {
+	{REQUEST_GPIO, 0},
+	{REQUEST_VREG, 0},
+	{ENABLE_VREG, 0},
+	{ENABLE_GPIO, 0},
+	{CONFIG_CLK, 0},
+	{CONFIG_EXT_POWER_CTRL, 0},
+	{CONFIG_I2C_MUX, 0},
+};
+
+int32_t msm_sensor_bayer_power_up(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t rc = 0, size = 0, index = 0;
+	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
+	struct msm_camera_power_seq_t *power_seq = NULL;
+	CDBG("%s: %d\n", __func__, __LINE__);
+	if (s_ctrl->power_seq) {
+		power_seq = s_ctrl->power_seq;
+		size = s_ctrl->num_power_seq;
+	} else {
+		power_seq = &sensor_power_seq[0];
+		size = ARRAY_SIZE(sensor_power_seq);
+	}
+
+	s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
+			* data->sensor_platform_info->num_vreg, GFP_KERNEL);
+	if (!s_ctrl->reg_ptr) {
+		pr_err("%s: could not allocate mem for regulators\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	for (index = 0; index < size; index++) {
+		switch (power_seq[index].power_config) {
+		case REQUEST_GPIO:
+			rc = msm_camera_request_gpio_table(data, 1);
+			if (rc < 0) {
+				pr_err("%s: request gpio failed\n", __func__);
+				goto ERROR;
+			}
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		case REQUEST_VREG:
+			rc = msm_camera_config_vreg(
+				&s_ctrl->sensor_i2c_client->client->dev,
+				s_ctrl->sensordata->sensor_platform_info->
+				cam_vreg,
+				s_ctrl->sensordata->sensor_platform_info->
+				num_vreg,
+				s_ctrl->vreg_seq,
+				s_ctrl->num_vreg_seq,
+				s_ctrl->reg_ptr, 1);
+			if (rc < 0) {
+				pr_err("%s: regulator on failed\n", __func__);
+				goto ERROR;
+			}
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		case ENABLE_VREG:
+			rc = msm_camera_enable_vreg(
+				&s_ctrl->sensor_i2c_client->client->dev,
+				s_ctrl->sensordata->sensor_platform_info->
+				cam_vreg,
+				s_ctrl->sensordata->sensor_platform_info->
+				num_vreg,
+				s_ctrl->vreg_seq,
+				s_ctrl->num_vreg_seq,
+				s_ctrl->reg_ptr, 1);
+			if (rc < 0) {
+				pr_err("%s: enable regulator failed\n",
+					__func__);
+				goto ERROR;
+			}
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		case ENABLE_GPIO:
+			rc = msm_camera_config_gpio_table(data, 1);
+			if (rc < 0) {
+				pr_err("%s: config gpio failed\n", __func__);
+				goto ERROR;
+			}
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		case CONFIG_CLK:
+			if (s_ctrl->clk_rate != 0)
+				cam_clk_info->clk_rate = s_ctrl->clk_rate;
+
+			rc = msm_cam_clk_enable(
+				&s_ctrl->sensor_i2c_client->client->dev,
+				cam_clk_info, s_ctrl->cam_clk,
+				ARRAY_SIZE(cam_clk_info), 1);
+			if (rc < 0) {
+				pr_err("%s: clk enable failed\n", __func__);
+				goto ERROR;
+			}
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		case CONFIG_EXT_POWER_CTRL:
+			if (data->sensor_platform_info->ext_power_ctrl != NULL)
+				data->sensor_platform_info->ext_power_ctrl(1);
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		case CONFIG_I2C_MUX:
+			if (data->sensor_platform_info->i2c_conf &&
+				data->sensor_platform_info->i2c_conf->
+				use_i2c_mux)
+				msm_sensor_bayer_enable_i2c_mux(
+					data->sensor_platform_info->i2c_conf);
+			if (power_seq[index].delay)
+				usleep_range(power_seq[index].delay * 1000,
+					(power_seq[index].delay * 1000) + 1000);
+			break;
+		default:
+			pr_err("%s error power config %d\n", __func__,
+				power_seq[index].power_config);
+			rc = -EINVAL;
+			break;
+		}
+	}
+
+	return rc;
+
+ERROR:
+	for (index--; index >= 0; index--) {
+		switch (power_seq[index].power_config) {
+		case CONFIG_I2C_MUX:
+			if (data->sensor_platform_info->i2c_conf &&
+				data->sensor_platform_info->i2c_conf->
+				use_i2c_mux)
+				msm_sensor_bayer_disable_i2c_mux(
+					data->sensor_platform_info->i2c_conf);
+			break;
+		case CONFIG_EXT_POWER_CTRL:
+			if (data->sensor_platform_info->ext_power_ctrl != NULL)
+				data->sensor_platform_info->ext_power_ctrl(0);
+			break;
+		case CONFIG_CLK:
+			msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->
+				dev, cam_clk_info, s_ctrl->cam_clk,
+				ARRAY_SIZE(cam_clk_info), 0);
+			break;
+		case ENABLE_GPIO:
+			msm_camera_config_gpio_table(data, 0);
+			break;
+		case ENABLE_VREG:
+			msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->
+				client->dev,
+				s_ctrl->sensordata->sensor_platform_info->
+				cam_vreg,
+				s_ctrl->sensordata->sensor_platform_info->
+				num_vreg,
+				s_ctrl->vreg_seq,
+				s_ctrl->num_vreg_seq,
+				s_ctrl->reg_ptr, 0);
+			break;
+		case REQUEST_VREG:
+			msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->
+				client->dev,
+				s_ctrl->sensordata->sensor_platform_info->
+				cam_vreg,
+				s_ctrl->sensordata->sensor_platform_info->
+				num_vreg,
+				s_ctrl->vreg_seq,
+				s_ctrl->num_vreg_seq,
+				s_ctrl->reg_ptr, 0);
+			break;
+		case REQUEST_GPIO:
+			msm_camera_request_gpio_table(data, 0);
+			break;
+		default:
+			pr_err("%s error power config %d\n", __func__,
+				power_seq[index].power_config);
+			break;
+		}
+	}
+	kfree(s_ctrl->reg_ptr);
+	return rc;
+}
+
+int32_t msm_sensor_bayer_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t size = 0, index = 0;
+	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
+	struct msm_camera_power_seq_t *power_seq = NULL;
+	CDBG("%s\n", __func__);
+
+	if (s_ctrl->power_seq) {
+		power_seq = s_ctrl->power_seq;
+		size = s_ctrl->num_power_seq;
+	} else {
+		power_seq = &sensor_power_seq[0];
+		size = ARRAY_SIZE(sensor_power_seq);
+	}
+
+	for (index = (size - 1); index >= 0; index--) {
+		switch (power_seq[index].power_config) {
+		case CONFIG_I2C_MUX:
+			if (data->sensor_platform_info->i2c_conf &&
+				data->sensor_platform_info->i2c_conf->
+				use_i2c_mux)
+				msm_sensor_bayer_disable_i2c_mux(
+					data->sensor_platform_info->i2c_conf);
+			break;
+		case CONFIG_EXT_POWER_CTRL:
+			if (data->sensor_platform_info->ext_power_ctrl != NULL)
+				data->sensor_platform_info->ext_power_ctrl(0);
+			break;
+		case CONFIG_CLK:
+			msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->
+				dev, cam_clk_info, s_ctrl->cam_clk,
+				ARRAY_SIZE(cam_clk_info), 0);
+			break;
+		case ENABLE_GPIO:
+			msm_camera_config_gpio_table(data, 0);
+			break;
+		case ENABLE_VREG:
+			msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->
+				client->dev,
+				s_ctrl->sensordata->sensor_platform_info->
+				cam_vreg,
+				s_ctrl->sensordata->sensor_platform_info->
+				num_vreg,
+				s_ctrl->vreg_seq,
+				s_ctrl->num_vreg_seq,
+				s_ctrl->reg_ptr, 0);
+			break;
+		case REQUEST_VREG:
+			msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->
+				client->dev,
+				s_ctrl->sensordata->sensor_platform_info->
+				cam_vreg,
+				s_ctrl->sensordata->sensor_platform_info->
+				num_vreg,
+				s_ctrl->vreg_seq,
+				s_ctrl->num_vreg_seq,
+				s_ctrl->reg_ptr, 0);
+			break;
+		case REQUEST_GPIO:
+			msm_camera_request_gpio_table(data, 0);
+			break;
+		default:
+			pr_err("%s error power config %d\n", __func__,
+				power_seq[index].power_config);
+			break;
+		}
+	}
+	kfree(s_ctrl->reg_ptr);
+	return 0;
+}
+
+int32_t msm_sensor_bayer_match_id(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t rc = 0;
+	uint16_t chipid = 0;
+	rc = msm_camera_i2c_read(
+			s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
+			MSM_CAMERA_I2C_WORD_DATA);
+	if (rc < 0) {
+		pr_err("%s: %s: read id failed\n", __func__,
+			s_ctrl->sensordata->sensor_name);
+		return rc;
+	}
+
+	CDBG("%s: read id: %x expected id %x:\n", __func__, chipid,
+		s_ctrl->sensor_id_info->sensor_id);
+	if (chipid != s_ctrl->sensor_id_info->sensor_id) {
+		pr_err("msm_sensor_match_id chip id doesnot match\n");
+		return -ENODEV;
+	}
+	return rc;
+}
+
+static int32_t msm_sensor_bayer_eeprom_read(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	uint32_t reg_addr = 0;
+	uint8_t *data = s_ctrl->eeprom_data.data;
+	uint32_t num_byte = 0;
+	int rc = 0;
+	uint32_t i2c_addr;
+	struct msm_camera_sensor_info *sensor_info = s_ctrl->sensordata;
+	i2c_addr = sensor_info->eeprom_info->eeprom_i2c_slave_addr;
+	num_byte = s_ctrl->eeprom_data.length = sensor_info->eeprom_info->
+		eeprom_read_length;
+	reg_addr = sensor_info->eeprom_info->eeprom_reg_addr;
+
+	data = kzalloc(num_byte * sizeof(uint8_t), GFP_KERNEL);
+	if (!data) {
+		pr_err("%s:%d failed\n", __func__, __LINE__);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	s_ctrl->sensor_i2c_client->client->addr = i2c_addr;
+	CDBG("eeprom read: i2c addr is %x num byte %d  reg addr %x\n",
+		i2c_addr, num_byte, reg_addr);
+	rc = msm_camera_i2c_read_seq(s_ctrl->sensor_i2c_client, reg_addr, data,
+		num_byte);
+	s_ctrl->sensor_i2c_client->client->addr = s_ctrl->sensor_i2c_addr;
+	return rc;
+}
+
+int32_t msm_sensor_bayer_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc = 0;
+	struct msm_sensor_ctrl_t *s_ctrl;
+	CDBG("%s %s_i2c_probe called\n", __func__, client->name);
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("%s %s i2c_check_functionality failed\n",
+			__func__, client->name);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+	if (s_ctrl->sensor_i2c_client != NULL) {
+		s_ctrl->sensor_i2c_client->client = client;
+		if (s_ctrl->sensor_i2c_addr != 0)
+			s_ctrl->sensor_i2c_client->client->addr =
+				s_ctrl->sensor_i2c_addr;
+	} else {
+		pr_err("%s %s sensor_i2c_client NULL\n",
+			__func__, client->name);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	s_ctrl->sensordata = client->dev.platform_data;
+	if (s_ctrl->sensordata == NULL) {
+		pr_err("%s %s NULL sensor data\n", __func__, client->name);
+		return -EFAULT;
+	}
+
+	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+	if (rc < 0) {
+		pr_err("%s %s power up failed\n", __func__, client->name);
+		return rc;
+	}
+
+	if (s_ctrl->func_tbl->sensor_match_id)
+		rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+	else
+		rc = msm_sensor_bayer_match_id(s_ctrl);
+	if (rc < 0)
+		goto probe_fail;
+
+	if (!s_ctrl->wait_num_frames)
+		s_ctrl->wait_num_frames = 1;
+
+	pr_err("%s %s probe succeeded\n", __func__, client->name);
+	snprintf(s_ctrl->sensor_v4l2_subdev.name,
+		sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
+	v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
+		s_ctrl->sensor_v4l2_subdev_ops);
+	s_ctrl->sensor_v4l2_subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&s_ctrl->sensor_v4l2_subdev.entity, 0, NULL, 0);
+	s_ctrl->sensor_v4l2_subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	s_ctrl->sensor_v4l2_subdev.entity.group_id = SENSOR_DEV;
+	s_ctrl->sensor_v4l2_subdev.entity.name =
+		s_ctrl->sensor_v4l2_subdev.name;
+	msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
+	s_ctrl->sensor_v4l2_subdev.entity.revision =
+		s_ctrl->sensor_v4l2_subdev.devnode->num;
+	msm_sensor_bayer_eeprom_read(s_ctrl);
+	goto power_down;
+probe_fail:
+	pr_err("%s %s_i2c_probe failed\n", __func__, client->name);
+power_down:
+	if (rc > 0)
+		rc = 0;
+	s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	return rc;
+}
+
+int32_t msm_sensor_delay_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc = 0;
+	struct msm_sensor_ctrl_t *s_ctrl;
+	CDBG("%s %s_delay_i2c_probe called\n", __func__, client->name);
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("%s %s i2c_check_functionality failed\n",
+			__func__, client->name);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+	if (s_ctrl->sensor_i2c_client != NULL) {
+		s_ctrl->sensor_i2c_client->client = client;
+		if (s_ctrl->sensor_i2c_addr != 0)
+			s_ctrl->sensor_i2c_client->client->addr =
+				s_ctrl->sensor_i2c_addr;
+	} else {
+		pr_err("%s %s sensor_i2c_client NULL\n",
+			__func__, client->name);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	s_ctrl->sensordata = client->dev.platform_data;
+	if (s_ctrl->sensordata == NULL) {
+		pr_err("%s %s NULL sensor data\n", __func__, client->name);
+		return -EFAULT;
+	}
+
+	if (!s_ctrl->wait_num_frames)
+		s_ctrl->wait_num_frames = 1;
+
+	pr_err("%s %s probe succeeded\n", __func__, client->name);
+	snprintf(s_ctrl->sensor_v4l2_subdev.name,
+		sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
+	v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
+		s_ctrl->sensor_v4l2_subdev_ops);
+	s_ctrl->sensor_v4l2_subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&s_ctrl->sensor_v4l2_subdev.entity, 0, NULL, 0);
+	s_ctrl->sensor_v4l2_subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	s_ctrl->sensor_v4l2_subdev.entity.group_id = SENSOR_DEV;
+	s_ctrl->sensor_v4l2_subdev.entity.name =
+		s_ctrl->sensor_v4l2_subdev.name;
+	msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
+	s_ctrl->sensor_v4l2_subdev.entity.revision =
+		s_ctrl->sensor_v4l2_subdev.devnode->num;
+	if (rc > 0)
+		rc = 0;
+	return rc;
+}
+
+int32_t msm_sensor_bayer_power(struct v4l2_subdev *sd, int on)
+{
+	int rc = 0;
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+	mutex_lock(s_ctrl->msm_sensor_mutex);
+	if (!on)
+		rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	mutex_unlock(s_ctrl->msm_sensor_mutex);
+	return rc;
+}
+
+int32_t msm_sensor_bayer_v4l2_enum_fmt(struct v4l2_subdev *sd,
+	unsigned int index, enum v4l2_mbus_pixelcode *code)
+{
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+
+	if ((unsigned int)index >= s_ctrl->sensor_v4l2_subdev_info_size)
+		return -EINVAL;
+
+	*code = s_ctrl->sensor_v4l2_subdev_info[index].code;
+	return 0;
+}
+
+int32_t msm_sensor_bayer_v4l2_s_ctrl(struct v4l2_subdev *sd,
+	struct v4l2_control *ctrl)
+{
+	int rc = -1, i = 0;
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+	struct msm_sensor_v4l2_ctrl_info_t *v4l2_ctrl =
+		s_ctrl->msm_sensor_v4l2_ctrl_info;
+
+	CDBG("%s\n", __func__);
+	CDBG("%d\n", ctrl->id);
+	if (v4l2_ctrl == NULL)
+		return rc;
+	for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
+		if (v4l2_ctrl[i].ctrl_id == ctrl->id) {
+			if (v4l2_ctrl[i].s_v4l2_ctrl != NULL) {
+				CDBG("\n calling msm_sensor_s_ctrl_by_enum\n");
+				rc = v4l2_ctrl[i].s_v4l2_ctrl(
+					s_ctrl,
+					&s_ctrl->msm_sensor_v4l2_ctrl_info[i],
+					ctrl->value);
+			}
+			break;
+		}
+	}
+
+	return rc;
+}
+
+int32_t msm_sensor_bayer_v4l2_query_ctrl(
+	struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
+{
+	int rc = -1, i = 0;
+	struct msm_sensor_ctrl_t *s_ctrl =
+		(struct msm_sensor_ctrl_t *) sd->dev_priv;
+
+	CDBG("%s\n", __func__);
+	CDBG("%s id: %d\n", __func__, qctrl->id);
+
+	if (s_ctrl->msm_sensor_v4l2_ctrl_info == NULL)
+		return rc;
+
+	for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
+		if (s_ctrl->msm_sensor_v4l2_ctrl_info[i].ctrl_id == qctrl->id) {
+			qctrl->minimum =
+				s_ctrl->msm_sensor_v4l2_ctrl_info[i].min;
+			qctrl->maximum =
+				s_ctrl->msm_sensor_v4l2_ctrl_info[i].max;
+			qctrl->flags = 1;
+			rc = 0;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+int msm_sensor_bayer_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	CDBG("%s enter\n", __func__);
+	rc = msm_sensor_write_enum_conf_array(
+		s_ctrl->sensor_i2c_client,
+		ctrl_info->enum_cfg_settings, value);
+	return rc;
+}
+
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.h b/drivers/media/video/msm/sensors/msm_sensor_bayer.h
new file mode 100644
index 0000000..d12244b
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.h
@@ -0,0 +1,76 @@
+/* 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
+ * 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_SENSOR_BAYER_H
+#define MSM_SENSOR_BAYER_H
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <mach/camera.h>
+#include <mach/gpio.h>
+#include <media/msm_camera.h>
+#include <media/v4l2-subdev.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_eeprom.h"
+#include "msm_sensor_common.h"
+
+struct sensor_driver_t {
+	struct platform_driver *platform_pdriver;
+	int32_t (*platform_probe)(struct platform_device *pdev);
+};
+
+int32_t msm_sensor_bayer_config(struct msm_sensor_ctrl_t *s_ctrl,
+			void __user *argp);
+int32_t msm_sensor_bayer_power_up(struct msm_sensor_ctrl_t *s_ctrl);
+int32_t msm_sensor_bayer_power_down(struct msm_sensor_ctrl_t *s_ctrl);
+
+int32_t msm_sensor_bayer_match_id(struct msm_sensor_ctrl_t *s_ctrl);
+int msm_sensor_bayer_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id);
+int32_t msm_sensor_delay_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id);
+int32_t msm_sensor_bayer_power(struct v4l2_subdev *sd, int on);
+
+int32_t msm_sensor_bayer_v4l2_s_ctrl(struct v4l2_subdev *sd,
+	struct v4l2_control *ctrl);
+
+int32_t msm_sensor_bayer_v4l2_query_ctrl(
+	struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl);
+
+int msm_sensor_bayer_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value);
+
+int msm_sensor_bayer_v4l2_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			enum v4l2_mbus_pixelcode *code);
+
+long msm_sensor_bayer_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg);
+
+int32_t msm_sensor_bayer_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
+		struct csi_lane_params_t *sensor_output_info);
+
+#define VIDIOC_MSM_SENSOR_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, void __user *)
+
+#define VIDIOC_MSM_SENSOR_RELEASE \
+	_IO('V', BASE_VIDIOC_PRIVATE + 11)
+
+#define VIDIOC_MSM_SENSOR_CSID_INFO\
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 12, struct msm_sensor_csi_info *)
+#endif
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.c b/drivers/media/video/msm/sensors/msm_sensor_common.c
new file mode 100644
index 0000000..9dac632
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_common.c
@@ -0,0 +1,18 @@
+/* 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
+ * 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_common.h"
+
+struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct msm_sensor_ctrl_t, sensor_v4l2_subdev);
+}
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.h b/drivers/media/video/msm/sensors/msm_sensor_common.h
new file mode 100644
index 0000000..79fe52e
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_common.h
@@ -0,0 +1,226 @@
+/* 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
+ * 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_SENSOR_COMMON_H
+#define MSM_SENSOR_COMMON_H
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <mach/camera.h>
+#include <media/msm_camera.h>
+#include <media/v4l2-subdev.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_eeprom.h"
+#define Q8  0x00000100
+#define Q10 0x00000400
+
+#define MSM_SENSOR_MCLK_8HZ 8000000
+#define MSM_SENSOR_MCLK_16HZ 16000000
+#define MSM_SENSOR_MCLK_24HZ 24000000
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+	static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+struct gpio_tlmm_cfg {
+	uint32_t gpio;
+	uint32_t dir;
+	uint32_t pull;
+	uint32_t drvstr;
+};
+
+enum msm_sensor_reg_update {
+	/* Sensor egisters that need to be updated during initialization */
+	MSM_SENSOR_REG_INIT,
+	/* Sensor egisters that needs periodic I2C writes */
+	MSM_SENSOR_UPDATE_PERIODIC,
+	/* All the sensor Registers will be updated */
+	MSM_SENSOR_UPDATE_ALL,
+	/* Not valid update */
+	MSM_SENSOR_UPDATE_INVALID
+};
+
+enum msm_sensor_cam_mode_t {
+	MSM_SENSOR_MODE_2D_RIGHT,
+	MSM_SENSOR_MODE_2D_LEFT,
+	MSM_SENSOR_MODE_3D,
+	MSM_SENSOR_MODE_INVALID
+};
+
+enum msm_camera_power_config_t {
+	REQUEST_GPIO,
+	ENABLE_GPIO,
+	REQUEST_VREG,
+	ENABLE_VREG,
+	CONFIG_CLK,
+	CONFIG_EXT_POWER_CTRL,
+	CONFIG_I2C_MUX,
+};
+
+struct msm_camera_power_seq_t {
+	enum msm_camera_power_config_t power_config;
+	uint32_t delay;
+};
+
+struct msm_sensor_id_info_t {
+	uint16_t sensor_id_reg_addr;
+	uint16_t sensor_id;
+};
+
+struct msm_sensor_reg_t {
+	enum msm_camera_i2c_data_type default_data_type;
+	struct msm_camera_i2c_reg_conf *start_stream_conf;
+	uint8_t start_stream_conf_size;
+	struct msm_camera_i2c_reg_conf *stop_stream_conf;
+	uint8_t stop_stream_conf_size;
+	struct msm_camera_i2c_reg_conf *group_hold_on_conf;
+	uint8_t group_hold_on_conf_size;
+	struct msm_camera_i2c_reg_conf *group_hold_off_conf;
+	uint8_t group_hold_off_conf_size;
+	struct msm_camera_i2c_conf_array *init_settings;
+	uint8_t init_size;
+	struct msm_camera_i2c_conf_array *mode_settings;
+	struct msm_camera_i2c_conf_array *no_effect_settings;
+	struct msm_sensor_output_info_t *output_settings;
+	uint8_t num_conf;
+};
+
+enum msm_sensor_device_type_t {
+	MSM_SENSOR_I2C_DEVICE,
+	MSM_SENSOR_PLATFORM_DEVICE,
+};
+
+struct v4l2_subdev_info {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	uint16_t fmt;
+	uint16_t order;
+};
+
+struct msm_sensor_ctrl_t;
+
+struct msm_sensor_v4l2_ctrl_info_t {
+	uint32_t ctrl_id;
+	int16_t min;
+	int16_t max;
+	int16_t step;
+	struct msm_camera_i2c_enum_conf_array *enum_cfg_settings;
+	int (*s_v4l2_ctrl) (struct msm_sensor_ctrl_t *,
+		struct msm_sensor_v4l2_ctrl_info_t *, int);
+};
+
+struct msm_sensor_fn_t {
+	void (*sensor_start_stream) (struct msm_sensor_ctrl_t *);
+	void (*sensor_stop_stream) (struct msm_sensor_ctrl_t *);
+	void (*sensor_group_hold_on) (struct msm_sensor_ctrl_t *);
+	void (*sensor_group_hold_off) (struct msm_sensor_ctrl_t *);
+
+	int32_t (*sensor_set_fps) (struct msm_sensor_ctrl_t *,
+			struct fps_cfg *);
+	int32_t (*sensor_write_exp_gain) (struct msm_sensor_ctrl_t *,
+			uint16_t, uint32_t);
+	int32_t (*sensor_write_snapshot_exp_gain) (struct msm_sensor_ctrl_t *,
+			uint16_t, uint32_t);
+	int32_t (*sensor_setting) (struct msm_sensor_ctrl_t *,
+			int update_type, int rt);
+	int32_t (*sensor_csi_setting) (struct msm_sensor_ctrl_t *,
+			int update_type, int rt);
+	int32_t (*sensor_set_sensor_mode)
+			(struct msm_sensor_ctrl_t *, int, int);
+	int32_t (*sensor_mode_init) (struct msm_sensor_ctrl_t *,
+		int, struct sensor_init_cfg *);
+	int32_t (*sensor_get_output_info) (struct msm_sensor_ctrl_t *,
+		struct sensor_output_info_t *);
+	int (*sensor_config) (struct msm_sensor_ctrl_t *, void __user *);
+	int (*sensor_power_down)
+		(struct msm_sensor_ctrl_t *);
+	int (*sensor_power_up) (struct msm_sensor_ctrl_t *);
+	int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
+	void (*sensor_adjust_frame_lines) (struct msm_sensor_ctrl_t *s_ctrl);
+	int32_t (*sensor_get_csi_params)(struct msm_sensor_ctrl_t *,
+		struct csi_lane_params_t *);
+};
+
+struct msm_sensor_csi_info {
+	uint8_t is_csic;
+};
+
+enum msm_sensor_state {
+	MSM_SENSOR_POWER_UP,
+	MSM_SENSOR_POWER_DOWN,
+};
+
+struct msm_sensor_eeprom_data {
+	uint8_t *data;
+	uint32_t length;
+};
+
+struct msm_sensor_ctrl_t {
+	struct  msm_camera_sensor_info *sensordata;
+	struct i2c_client *msm_sensor_client;
+	struct i2c_driver *sensor_i2c_driver;
+	struct platform_device *pdev;
+	struct msm_camera_i2c_client *sensor_i2c_client;
+	uint16_t sensor_i2c_addr;
+	enum msm_camera_vreg_name_t *vreg_seq;
+	int num_vreg_seq;
+	struct msm_camera_power_seq_t *power_seq;
+	int num_power_seq;
+	enum msm_sensor_device_type_t sensor_device_type;
+
+	struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
+	struct msm_sensor_id_info_t *sensor_id_info;
+	struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
+	struct msm_sensor_reg_t *msm_sensor_reg;
+	struct msm_sensor_v4l2_ctrl_info_t *msm_sensor_v4l2_ctrl_info;
+	uint16_t num_v4l2_ctrl;
+	uint8_t is_csic;
+
+	uint16_t curr_line_length_pclk;
+	uint16_t curr_frame_length_lines;
+
+	uint32_t fps_divider;
+	enum msm_sensor_resolution_t curr_res;
+	enum msm_sensor_cam_mode_t cam_mode;
+
+	struct mutex *msm_sensor_mutex;
+
+	struct v4l2_subdev sensor_v4l2_subdev;
+	struct v4l2_subdev_info *sensor_v4l2_subdev_info;
+	uint8_t sensor_v4l2_subdev_info_size;
+	struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
+	struct msm_sensor_fn_t *func_tbl;
+	struct regulator **reg_ptr;
+	struct clk *cam_clk[2];
+	long clk_rate;
+	enum msm_sensor_state sensor_state;
+	/* Number of frames to delay after start / stop stream in Q10 format.
+	   Initialize to -1 for this value to be ignored */
+	int16_t wait_num_frames;
+	/* minimum delay after stop / stop stream in ms */
+	uint16_t min_delay;
+	/* delay (in ms) after power up sequence */
+	uint16_t power_seq_delay;
+	struct msm_sensor_eeprom_data eeprom_data;
+};
+
+struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
+
+#endif
diff --git a/drivers/media/video/msm/sensors/msm_sensor_init.c b/drivers/media/video/msm/sensors/msm_sensor_init.c
new file mode 100644
index 0000000..41c00eb
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_init.c
@@ -0,0 +1,35 @@
+/* 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"
+#include "msm.h"
+#include "msm_sensor_bayer.h"
+#include "imx091.h"
+
+static struct i2c_driver *sensor_i2c_driver[] = {
+	/* back camera */
+	&imx091_i2c_driver,
+	/* front camera */
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	int index = 0;
+	for (index = 0; index < ARRAY_SIZE(sensor_i2c_driver); index++)
+		i2c_add_driver(sensor_i2c_driver[index]);
+	return 0;
+}
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Sensor driver probe");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index 69a5498..a38cb57 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -325,22 +325,6 @@
 	},
 };
 
-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,
@@ -472,7 +456,6 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
-	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t mt9e013_regs = {
@@ -497,7 +480,6 @@
 	.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,
diff --git a/drivers/media/video/msm/sensors/mt9m114_v4l2.c b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
index 806bcc2..cba9538 100644
--- a/drivers/media/video/msm/sensors/mt9m114_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
@@ -1184,30 +1184,6 @@
 	},
 };
 
-static struct msm_camera_csid_vc_cfg mt9m114_cid_cfg[] = {
-	{0, CSI_YUV422_8, CSI_DECODE_8BIT},
-	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params mt9m114_csi_params = {
-	.csid_params = {
-		.lane_cnt = 1,
-		.lut_params = {
-			.num_cid = 2,
-			.vc_cfg = mt9m114_cid_cfg,
-		},
-	},
-	.csiphy_params = {
-		.lane_cnt = 1,
-		.settle_cnt = 0x14,
-	},
-};
-
-static struct msm_camera_csi2_params *mt9m114_csi_params_array[] = {
-	&mt9m114_csi_params,
-	&mt9m114_csi_params,
-};
-
 static struct msm_sensor_output_reg_addr_t mt9m114_reg_addr = {
 	.x_output = 0xC868,
 	.y_output = 0xC86A,
@@ -1215,6 +1191,12 @@
 	.frame_length_lines = 0xC86A,
 };
 
+static enum msm_camera_vreg_name_t mt9m114_veg_seq[] = {
+	CAM_VIO,
+	CAM_VDIG,
+	CAM_VANA,
+};
+
 static struct msm_sensor_id_info_t mt9m114_id_info = {
 	.sensor_id_reg_addr = 0x0,
 	.sensor_id = 0x2481,
@@ -1288,10 +1270,13 @@
 	.num_v4l2_ctrl = ARRAY_SIZE(mt9m114_v4l2_ctrl_info),
 	.sensor_i2c_client = &mt9m114_sensor_i2c_client,
 	.sensor_i2c_addr = 0x90,
+	.vreg_seq = mt9m114_veg_seq,
+	.num_vreg_seq = ARRAY_SIZE(mt9m114_veg_seq),
 	.sensor_output_reg_addr = &mt9m114_reg_addr,
 	.sensor_id_info = &mt9m114_id_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csi_params = &mt9m114_csi_params_array[0],
+	.min_delay = 30,
+	.power_seq_delay = 60,
 	.msm_sensor_mutex = &mt9m114_mut,
 	.sensor_i2c_driver = &mt9m114_i2c_driver,
 	.sensor_v4l2_subdev_info = mt9m114_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index e08cd0a..bc38f62 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -658,34 +658,6 @@
 	},
 };
 
-static struct msm_camera_csid_vc_cfg ov2720_cid_cfg[] = {
-	{0, CSI_RAW10, CSI_DECODE_10BIT},
-	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params ov2720_csi_params = {
-	.csid_params = {
-		.lane_cnt = 2,
-		.lut_params = {
-			.num_cid = 2,
-			.vc_cfg = ov2720_cid_cfg,
-		},
-	},
-	.csiphy_params = {
-		.lane_cnt = 2,
-		.settle_cnt = 0x1B,
-	},
-};
-
-static struct msm_camera_csi2_params *ov2720_csi_params_array[] = {
-	&ov2720_csi_params,
-	&ov2720_csi_params,
-	&ov2720_csi_params,
-	&ov2720_csi_params,
-	&ov2720_csi_params,
-	&ov2720_csi_params,
-};
-
 static struct msm_sensor_output_reg_addr_t ov2720_reg_addr = {
 	.x_output = 0x3808,
 	.y_output = 0x380a,
@@ -704,6 +676,12 @@
 	.vert_offset = 6,
 };
 
+static enum msm_camera_vreg_name_t ov2720_veg_seq[] = {
+	CAM_VIO,
+	CAM_VANA,
+	CAM_VDIG,
+};
+
 static int32_t ov2720_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
 		uint16_t gain, uint32_t line)
 {
@@ -722,9 +700,15 @@
 	int_time[0] = line >> 12;
 	int_time[1] = line >> 4;
 	int_time[2] = line << 4;
-	msm_camera_i2c_write_seq(s_ctrl->sensor_i2c_client,
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr-1,
-		&int_time[0], 3);
+		int_time[0], MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+		int_time[1], 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,
+		int_time[2], MSM_CAMERA_I2C_BYTE_DATA);
 	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_exp_gain_info->global_gain_addr, gain,
 		MSM_CAMERA_I2C_WORD_DATA);
@@ -849,11 +833,12 @@
 	.msm_sensor_reg = &ov2720_regs,
 	.sensor_i2c_client = &ov2720_sensor_i2c_client,
 	.sensor_i2c_addr = 0x6C,
+	.vreg_seq = ov2720_veg_seq,
+	.num_vreg_seq = ARRAY_SIZE(ov2720_veg_seq),
 	.sensor_output_reg_addr = &ov2720_reg_addr,
 	.sensor_id_info = &ov2720_id_info,
 	.sensor_exp_gain_info = &ov2720_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csi_params = &ov2720_csi_params_array[0],
 	.msm_sensor_mutex = &ov2720_mut,
 	.sensor_i2c_driver = &ov2720_i2c_driver,
 	.sensor_v4l2_subdev_info = ov2720_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index d192563..eb6a8b0 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -159,7 +159,7 @@
 
 static struct msm_camera_i2c_reg_conf ov5647_zsl_settings[] = {
 	{0x3035, 0x21},
-	{0x3036, 0x2f},
+	{0x3036, 0x4f},
 	{0x3821, 0x06},
 	{0x3820, 0x00},
 	{0x3612, 0x0b},
@@ -343,14 +343,6 @@
 	ARRAY_SIZE(ov5647_zsl_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 };
 
-static struct msm_camera_csi_params ov5647_csi_params = {
-	.data_format = CSI_8BIT,
-	.lane_cnt    = 2,
-	.lane_assign = 0xe4,
-	.dpcm_scheme = 0,
-	.settle_cnt  = 10,
-};
-
 static struct v4l2_subdev_info ov5647_subdev_info[] = {
 	{
 		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
@@ -417,14 +409,6 @@
 	.frame_length_lines = 0x380E,
 };
 
-static struct msm_camera_csi_params *ov5647_csi_params_array[] = {
-	&ov5647_csi_params, /* Snapshot */
-	&ov5647_csi_params, /* Preview */
-	&ov5647_csi_params, /* 60fps */
-	&ov5647_csi_params, /* 90fps */
-	&ov5647_csi_params, /* ZSL */
-};
-
 static struct msm_sensor_id_info_t ov5647_id_info = {
 	.sensor_id_reg_addr = 0x300a,
 	.sensor_id = 0x5647,
@@ -572,7 +556,8 @@
 	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
 
 	/* adjust frame rate */
-	if (line > (fl_lines - offset))
+	if ((s_ctrl->curr_res < MSM_SENSOR_RES_2) &&
+		(line > (fl_lines - offset)))
 		fl_lines = line + offset;
 
 	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
@@ -733,13 +718,15 @@
 
 static int32_t vfe_clk = 266667000;
 
-int32_t ov5647_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
-			int update_type, int res)
+static void ov5647_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
 {
-	int32_t rc = 0;
-	static int csi_config;
-	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
-	if (csi_config == 0 || res == 0)
+	msm_camera_i2c_write_tbl(
+		s_ctrl->sensor_i2c_client,
+		s_ctrl->msm_sensor_reg->stop_stream_conf,
+		s_ctrl->msm_sensor_reg->stop_stream_conf_size,
+		s_ctrl->msm_sensor_reg->default_data_type);
+
+	if (s_ctrl->curr_res == MSM_SENSOR_RES_FULL)
 		msleep(66);
 	else
 		msleep(266);
@@ -748,37 +735,31 @@
 			s_ctrl->sensor_i2c_client,
 			0x4800, 0x25,
 			MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+int32_t ov5647_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
+			int update_type, int res)
+{
+	int32_t rc = 0;
 	if (update_type == MSM_SENSOR_REG_INIT) {
 		CDBG("Register INIT\n");
-		s_ctrl->curr_csi_params = NULL;
+		s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 		msm_camera_i2c_write(
 				s_ctrl->sensor_i2c_client,
 				0x103, 0x1,
 				MSM_CAMERA_I2C_BYTE_DATA);
 		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;
 		msm_camera_i2c_write(
 			s_ctrl->sensor_i2c_client,
 			0x100, 0x1,
 			MSM_CAMERA_I2C_BYTE_DATA);
-		}
 		msm_camera_i2c_write(
 			s_ctrl->sensor_i2c_client,
 			0x4800, 0x4,
@@ -788,14 +769,12 @@
 			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 					NOTIFY_PCLK_CHANGE,
 					&vfe_clk);
-		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
-		msleep(50);
 	}
 	return rc;
 }
 static struct msm_sensor_fn_t ov5647_func_tbl = {
 	.sensor_start_stream = msm_sensor_start_stream,
-	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_stop_stream = ov5647_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,
@@ -808,7 +787,6 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = ov5647_sensor_power_up,
 	.sensor_power_down = ov5647_sensor_power_down,
-	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov5647_regs = {
@@ -837,7 +815,6 @@
 	.sensor_id_info = &ov5647_id_info,
 	.sensor_exp_gain_info = &ov5647_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csic_params = &ov5647_csi_params_array[0],
 	.msm_sensor_mutex = &ov5647_mut,
 	.sensor_i2c_driver = &ov5647_i2c_driver,
 	.sensor_v4l2_subdev_info = ov5647_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov7692_v4l2.c b/drivers/media/video/msm/sensors/ov7692_v4l2.c
index 71d436e..e0d4b53f 100644
--- a/drivers/media/video/msm/sensors/ov7692_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_v4l2.c
@@ -821,18 +821,6 @@
 
 };
 
-static struct msm_camera_csi_params ov7692_csi_params = {
-	.data_format = CSI_8BIT,
-	.lane_cnt    = 1,
-	.lane_assign = 0xe4,
-	.dpcm_scheme = 0,
-	.settle_cnt  = 0x14,
-};
-
-static struct msm_camera_csi_params *ov7692_csi_params_array[] = {
-	&ov7692_csi_params,
-};
-
 static struct msm_sensor_output_reg_addr_t ov7692_reg_addr = {
 	.x_output = 0xCC,
 	.y_output = 0xCE,
@@ -899,7 +887,6 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
-	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov7692_regs = {
@@ -925,7 +912,6 @@
 	.sensor_output_reg_addr = &ov7692_reg_addr,
 	.sensor_id_info = &ov7692_id_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csic_params = &ov7692_csi_params_array[0],
 	.msm_sensor_mutex = &ov7692_mut,
 	.sensor_i2c_driver = &ov7692_i2c_driver,
 	.sensor_v4l2_subdev_info = ov7692_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov8825_v4l2.c b/drivers/media/video/msm/sensors/ov8825_v4l2.c
index 1ae3dfd..092ee72 100644
--- a/drivers/media/video/msm/sensors/ov8825_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov8825_v4l2.c
@@ -510,19 +510,6 @@
 	},
 };
 
-static struct msm_camera_csi_params ov8825_csi_params = {
-	.data_format = CSI_10BIT,
-	.lane_cnt    = 2,
-	.lane_assign = 0xe4,
-	.dpcm_scheme = 0,
-	.settle_cnt  = 14,
-};
-
-static struct msm_camera_csi_params *ov8825_csi_params_array[] = {
-	&ov8825_csi_params,
-	&ov8825_csi_params,
-};
-
 static struct msm_sensor_output_reg_addr_t ov8825_reg_addr = {
 	.x_output = 0x3808,
 	.y_output = 0x380a,
@@ -868,13 +855,10 @@
 			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;
+		s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 		msm_sensor_enable_debugfs(s_ctrl);
 		msm_sensor_write_init_settings(s_ctrl);
 		CDBG("Update OTP\n");
@@ -885,30 +869,15 @@
 		usleep_range(10000, 11000);
 		msm_camera_i2c_write(s_ctrl->sensor_i2c_client, 0x100, 0x0,
 		  MSM_CAMERA_I2C_BYTE_DATA);
-		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;
-		}
 		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 			NOTIFY_PCLK_CHANGE,
 			&s_ctrl->sensordata->pdata->ioclk.vfe_clk_rate);
-
-		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
-		msleep(50);
 	}
 	return rc;
 }
@@ -955,7 +924,6 @@
 	.sensor_id_info = &ov8825_id_info,
 	.sensor_exp_gain_info = &ov8825_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csic_params = &ov8825_csi_params_array[0],
 	.msm_sensor_mutex = &ov8825_mut,
 	.sensor_i2c_driver = &ov8825_i2c_driver,
 	.sensor_v4l2_subdev_info = ov8825_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
index 27a8b38..50c13c6 100644
--- a/drivers/media/video/msm/sensors/ov9726_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -155,18 +155,6 @@
 	},
 };
 
-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,
@@ -236,7 +224,6 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
-	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov9726_regs = {
@@ -265,7 +252,6 @@
 	.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,
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 64b004e..6a2372e 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -481,7 +481,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 3052,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 30 fps preview */
@@ -491,7 +491,7 @@
 		.line_length_pclk = 4480,
 		.frame_length_lines = 2412,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 60 fps video */
@@ -501,7 +501,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 992,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 90 fps video */
@@ -511,7 +511,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 664,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 120 fps video */
@@ -521,7 +521,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 514,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 24 fps snapshot */
@@ -536,53 +536,6 @@
 	},
 };
 
-static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_cfg[] = {
-	{0, CSI_RAW10, CSI_DECODE_10BIT},
-	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params s5k3l1yx_csi_params = {
-	.csid_params = {
-		.lane_cnt = 4,
-		.lut_params = {
-			.num_cid = ARRAY_SIZE(s5k3l1yx_cid_cfg),
-			.vc_cfg = s5k3l1yx_cid_cfg,
-		},
-	},
-	.csiphy_params = {
-		.lane_cnt = 4,
-		.settle_cnt = 0x1B,
-	},
-};
-
-static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_dpcm_cfg[] = {
-	{0, CSI_RAW8, CSI_DECODE_DPCM_10_8_10},
-};
-
-static struct msm_camera_csi2_params s5k3l1yx_csi_dpcm_params = {
-	.csid_params = {
-		.lane_assign = 0xe4,
-		.lane_cnt = 4,
-		.lut_params = {
-			.num_cid = ARRAY_SIZE(s5k3l1yx_cid_dpcm_cfg),
-			.vc_cfg = s5k3l1yx_cid_dpcm_cfg,
-		},
-	},
-	.csiphy_params = {
-		.lane_cnt = 4,
-		.settle_cnt = 0x1B,
-	},
-};
-
-static struct msm_camera_csi2_params *s5k3l1yx_csi_params_array[] = {
-	&s5k3l1yx_csi_params,
-	&s5k3l1yx_csi_params,
-	&s5k3l1yx_csi_params,
-	&s5k3l1yx_csi_params,
-	&s5k3l1yx_csi_params,
-	&s5k3l1yx_csi_dpcm_params,
-};
-
 static struct msm_sensor_output_reg_addr_t s5k3l1yx_reg_addr = {
 	.x_output = 0x34C,
 	.y_output = 0x34E,
@@ -590,6 +543,13 @@
 	.frame_length_lines = 0x340,
 };
 
+static enum msm_camera_vreg_name_t s5k3l1yx_veg_seq[] = {
+	CAM_VDIG,
+	CAM_VANA,
+	CAM_VIO,
+	CAM_VAF,
+};
+
 static struct msm_sensor_id_info_t s5k3l1yx_id_info = {
 	.sensor_id_reg_addr = 0x0,
 	.sensor_id = 0x3121,
@@ -717,11 +677,12 @@
 	.msm_sensor_reg = &s5k3l1yx_regs,
 	.sensor_i2c_client = &s5k3l1yx_sensor_i2c_client,
 	.sensor_i2c_addr = 0x6E,
+	.vreg_seq = s5k3l1yx_veg_seq,
+	.num_vreg_seq = ARRAY_SIZE(s5k3l1yx_veg_seq),
 	.sensor_output_reg_addr = &s5k3l1yx_reg_addr,
 	.sensor_id_info = &s5k3l1yx_id_info,
 	.sensor_exp_gain_info = &s5k3l1yx_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csi_params = &s5k3l1yx_csi_params_array[0],
 	.msm_sensor_mutex = &s5k3l1yx_mut,
 	.sensor_i2c_driver = &s5k3l1yx_i2c_driver,
 	.sensor_v4l2_subdev_info = s5k3l1yx_subdev_info,
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
index e90390e..8cdadd8 100644
--- a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -211,19 +211,6 @@
 	},
 };
 
-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,
@@ -487,7 +474,6 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
-	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t s5k4e1_regs = {
@@ -516,7 +502,6 @@
 	.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,
diff --git a/drivers/media/video/msm/sensors/vx6953.c b/drivers/media/video/msm/sensors/vx6953.c
index b43782c..ddc6cee 100644
--- a/drivers/media/video/msm/sensors/vx6953.c
+++ b/drivers/media/video/msm/sensors/vx6953.c
@@ -848,19 +848,6 @@
 	},
 };
 
-static struct msm_camera_csi_params vx6953_csi_params = {
-	.data_format = CSI_8BIT,
-	.lane_cnt    = 1,
-	.lane_assign = 0xe4,
-	.dpcm_scheme = 0,
-	.settle_cnt  = 7,
-};
-
-static struct msm_camera_csi_params *vx6953_csi_params_array[] = {
-	&vx6953_csi_params,
-	&vx6953_csi_params,
-};
-
 static struct msm_sensor_output_reg_addr_t vx6953_reg_addr = {
 	.x_output = 0x034C,
 	.y_output = 0x034E,
@@ -1880,13 +1867,6 @@
 				vx6953_s_ctrl.msm_sensor_reg->
 				default_data_type);
 
-
-			vx6953_s_ctrl.curr_csic_params =
-				vx6953_s_ctrl.csic_params[0];
-			v4l2_subdev_notify(&vx6953_s_ctrl.sensor_v4l2_subdev,
-				NOTIFY_CSIC_CFG,
-				vx6953_s_ctrl.curr_csic_params);
-
 			msleep(vx6953_stm5m0edof_delay_msecs_stdby);
 			if (rt == RES_PREVIEW) {
 				CDBG("%s write mode_tbl for preview\n",
@@ -2042,7 +2022,6 @@
 	.sensor_id_info = &vx6953_id_info,
 	.sensor_exp_gain_info = &vx6953_exp_gain_info,
 	.cam_mode = MSM_SENSOR_MODE_INVALID,
-	.csic_params = &vx6953_csi_params_array[0],
 	.msm_sensor_mutex = &vx6953_mut,
 	.sensor_i2c_driver = &vx6953_i2c_driver,
 	.sensor_v4l2_subdev_info = vx6953_subdev_info,
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index b7898ed..05070a3 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/of.h>
 #include "msm_cam_server.h"
 #include "msm_csid.h"
 #include "msm_csic.h"
@@ -75,12 +76,9 @@
 		isp_event =
 			(struct msm_isp_event_ctrl *)
 			qcmd->command;
-		if (isp_event->isp_data.ctrl.value != NULL) {
+		if (isp_event->isp_data.ctrl.value != NULL)
 			kfree(isp_event->isp_data.ctrl.value);
-			isp_event->isp_data.ctrl.value = NULL;
-		}
 		kfree(qcmd->command);
-		qcmd->command = NULL;
 		free_qcmd(qcmd);
 	}
 	spin_unlock_irqrestore(&queue->lock, flags);
@@ -111,13 +109,20 @@
 	v4l2_fh_exit(eventHandle);
 }
 
-int msm_cam_server_config_interface_map(u32 extendedmode, uint32_t mctl_handle)
+int msm_cam_server_config_interface_map(u32 extendedmode,
+	uint32_t mctl_handle, int vnode_id, int is_bayer_sensor)
 {
 	int i = 0;
 	int rc = 0;
 	int old_handle;
 	int interface;
 
+	if (vnode_id >= MAX_NUM_ACTIVE_CAMERA) {
+		pr_err("%s: invalid msm_dev node id = %d", __func__, vnode_id);
+		return -EINVAL;
+	}
+	D("%s: extendedmode = %d, vnode_id = %d, is_bayer_sensor = %d",
+		__func__, extendedmode, vnode_id, is_bayer_sensor);
 	switch (extendedmode) {
 	case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
 		interface = RDI_0;
@@ -132,21 +137,63 @@
 		interface = PIX_0;
 		break;
 	}
+
 	for (i = 0; i < INTF_MAX; i++) {
 		if (g_server_dev.interface_map_table[i].interface ==
 							interface) {
+			if (is_bayer_sensor && interface == PIX_0) {
+				if (g_server_dev.
+					interface_map_table[i].mctl_handle &&
+					!g_server_dev.interface_map_table[i].
+						is_bayer_sensor) {
+					/* in simultaneous camera usecase
+					 * SoC does not use PIX interface */
+					g_server_dev.interface_map_table[i].
+						mctl_handle = 0;
+				}
+			}
+			if (!is_bayer_sensor && interface == PIX_0) {
+				if (g_server_dev.
+					interface_map_table[i].mctl_handle &&
+					g_server_dev.interface_map_table[i].
+						is_bayer_sensor) {
+					/* in simultaneous camera usecase
+					 * SoC does not use PIX interface */
+					break;
+				}
+			}
 			old_handle =
 				g_server_dev.interface_map_table[i].mctl_handle;
 			if (old_handle == 0) {
 				g_server_dev.interface_map_table[i].mctl_handle
 					= mctl_handle;
-			} else if (old_handle != mctl_handle) {
-				pr_err("%s: interface_map[%d] was set: %d\n",
-					__func__, i, old_handle);
-				rc = -EINVAL;
+				g_server_dev.interface_map_table[i].
+					is_bayer_sensor = is_bayer_sensor;
+				g_server_dev.interface_map_table[i].vnode_id
+					= vnode_id;
+			} else {
+				if (!g_server_dev.interface_map_table[i].
+					is_bayer_sensor &&
+					(extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW ||
+					extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_VIDEO ||
+					extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_MAIN ||
+					extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL)) {
+					D("%s: SoC sensor, image_mode = %d",
+					__func__, extendedmode);
+					break;
+				}
+				if (old_handle != mctl_handle) {
+					pr_err("%s: iface_map[%d] is set: %d\n",
+						__func__, i, old_handle);
+					rc = -EINVAL;
+				}
 			}
 			break;
-		}
+			}
 	}
 
 	if (i == INTF_MAX)
@@ -158,9 +205,20 @@
 {
 	int i;
 	for (i = 0; i < INTF_MAX; i++)
-		if (g_server_dev.interface_map_table[i].mctl_handle ==
-								mctl_handle)
-			g_server_dev.interface_map_table[i].mctl_handle = 0;
+		if (g_server_dev.interface_map_table[i].
+			mctl_handle == mctl_handle)
+			g_server_dev.interface_map_table[i].
+				mctl_handle = 0;
+}
+
+struct iommu_domain *msm_cam_server_get_domain()
+{
+	return g_server_dev.domain;
+}
+
+int msm_cam_server_get_domain_num()
+{
+	return g_server_dev.domain_num;
 }
 
 uint32_t msm_cam_server_get_mctl_handle(void)
@@ -173,7 +231,7 @@
 			g_server_dev.mctl[i].handle =
 				(++g_server_dev.mctl_handle_cnt) << 8 | i;
 			memset(&g_server_dev.mctl[i].mctl,
-				   0, sizeof(g_server_dev.mctl[i].mctl));
+				0, sizeof(g_server_dev.mctl[i].mctl));
 			return g_server_dev.mctl[i].handle;
 		}
 	}
@@ -201,6 +259,18 @@
 	return NULL;
 }
 
+uint32_t msm_cam_find_handle_from_mctl_ptr(
+			struct msm_cam_media_controller *p_mctl)
+{
+	uint32_t idx;
+	struct msm_cam_media_controller *tmp_mctl = NULL;
+	for (idx = 0; idx < MAX_NUM_ACTIVE_CAMERA; idx++) {
+		tmp_mctl = &g_server_dev.mctl[idx].mctl;
+		if (p_mctl == tmp_mctl)
+			return g_server_dev.mctl[idx].handle;
+	}
+	return 0;
+}
 
 static void msm_cam_server_send_error_evt(
 		struct msm_cam_media_controller *pmctl, int evt_type)
@@ -237,7 +307,7 @@
 	if (copy_from_user(command, (void __user *)ioctl_ptr->ioctl_ptr,
 					   sizeof(struct msm_ctrl_cmd))) {
 		pr_err("%s: copy_from_user failed, size=%d\n",
-			   __func__, sizeof(struct msm_ctrl_cmd));
+			__func__, sizeof(struct msm_ctrl_cmd));
 		goto ctrl_cmd_done_error;
 	}
 
@@ -263,7 +333,7 @@
 	if (command->length > 0) {
 		command->value =
 			g_server_dev.server_queue[command->queue_idx].ctrl_data;
-		if (command->length > max_control_command_size) {
+		if (command->length > MAX_SERVER_PAYLOAD_LENGTH) {
 			pr_err("%s: user data %d is too big (max %d)\n",
 				__func__, command->length,
 				max_control_command_size);
@@ -282,7 +352,7 @@
 
 ctrl_cmd_done_error:
 	mutex_unlock(&g_server_dev.server_queue_lock);
-	kfree(qcmd);
+	free_qcmd(qcmd);
 qcmd_alloc_fail:
 	kfree(command);
 command_alloc_fail:
@@ -291,9 +361,10 @@
 
 /* send control command to config and wait for results*/
 static int msm_server_control(struct msm_cam_server_dev *server_dev,
-				struct msm_ctrl_cmd *out)
+				uint32_t id, struct msm_ctrl_cmd *out)
 {
 	int rc = 0;
+	uint8_t wait_count;
 	void *value;
 	struct msm_queue_cmd *rcmd;
 	struct msm_queue_cmd *event_qcmd;
@@ -329,7 +400,7 @@
 	server_dev->server_queue[out->queue_idx].evt_id =
 		server_dev->server_evt_id;
 	v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
-	v4l2_evt.id = 0;
+	v4l2_evt.id = id;
 	v4l2_evt.u.data[0] = out->queue_idx;
 	/* setup event object to transfer the command; */
 	isp_event->resptype = MSM_CAM_RESP_V4L2;
@@ -361,9 +432,20 @@
 
 	/* wait for config return status */
 	D("Waiting for config status\n");
-	rc = wait_event_interruptible_timeout(queue->wait,
-		!list_empty_careful(&queue->list),
-		msecs_to_jiffies(out->timeout_ms));
+	/* wait event may be interrupted by sugnal,
+	 * in this case -ERESTARTSYS is returned and retry is needed.
+	 * Now we only retry once. */
+	wait_count = 2;
+	do {
+		rc = wait_event_interruptible_timeout(queue->wait,
+			!list_empty_careful(&queue->list),
+			msecs_to_jiffies(out->timeout_ms));
+		wait_count--;
+		if (rc != -ERESTARTSYS)
+			break;
+		D("%s: wait_event interrupted by signal, remain_count = %d",
+			__func__, wait_count);
+	} while (wait_count > 0);
 	D("Waiting is over for config status\n");
 	if (list_empty_careful(&queue->list)) {
 		if (!rc)
@@ -390,7 +472,6 @@
 	out->value = value;
 
 	kfree(ctrlcmd);
-	rcmd->command = NULL;
 	free_qcmd(rcmd);
 	D("%s: rc %d\n", __func__, rc);
 	/* rc is the time elapsed. */
@@ -413,6 +494,61 @@
 	return rc;
 }
 
+int msm_server_private_general(struct msm_cam_v4l2_device *pcam,
+		struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+	struct msm_ctrl_cmd ctrlcmd;
+	void *temp_data = NULL;
+	int rc;
+	if (ioctl_ptr->len > 0) {
+		temp_data = kzalloc(ioctl_ptr->len, GFP_KERNEL);
+		if (!temp_data) {
+			pr_err("%s could not allocate memory\n", __func__);
+			rc = -ENOMEM;
+			goto end;
+		}
+		if (copy_from_user((void *)temp_data,
+			(void __user *)ioctl_ptr->ioctl_ptr,
+			ioctl_ptr->len)) {
+			ERR_COPY_FROM_USER();
+			rc = -EFAULT;
+			goto copy_from_user_failed;
+		}
+	}
+
+	mutex_lock(&pcam->vid_lock);
+	ctrlcmd.type = MSM_V4L2_PRIVATE_CMD;
+	ctrlcmd.length = ioctl_ptr->len;
+	ctrlcmd.value = temp_data;
+	ctrlcmd.timeout_ms = 1000;
+	ctrlcmd.status = ioctl_ptr->id;
+	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
+	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+	/* send command to config thread in usersspace, and get return value */
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
+	if (rc < 0)
+		pr_err("%s: send event failed\n", __func__);
+	else {
+		if (ioctl_ptr->len > 0) {
+			if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+				(void *)temp_data,
+				ioctl_ptr->len)) {
+				ERR_COPY_TO_USER();
+				rc = -EFAULT;
+			}
+		}
+	}
+	mutex_unlock(&pcam->vid_lock);
+
+	kfree(temp_data);
+	return rc;
+copy_from_user_failed:
+	kfree(temp_data);
+end:
+return rc;
+}
+
 int msm_server_get_crop(struct msm_cam_v4l2_device *pcam,
 				int idx, struct v4l2_crop *crop)
 {
@@ -432,7 +568,7 @@
 						pcam->server_queue_idx];
 
 	/* send command to config thread in userspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 	D("%s: rc = %d\n", __func__, rc);
 
 	return rc;
@@ -456,7 +592,7 @@
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[idx];
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 
 	return rc;
 }
@@ -478,7 +614,7 @@
 						pcam->server_queue_idx];
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 
 	return rc;
 }
@@ -524,7 +660,7 @@
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 
 	if (rc >= 0) {
 		pcam->dev_inst[idx]->vid_fmt = *pfmt;
@@ -590,7 +726,7 @@
 	ctrlcmd.queue_idx = pcam->server_queue_idx;
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 	if (rc >= 0) {
 		pcam->dev_inst[idx]->vid_fmt = *pfmt;
 		pcam->dev_inst[idx]->sensor_pxlcode
@@ -621,8 +757,7 @@
 
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 	return rc;
 }
 
@@ -642,7 +777,7 @@
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 
 	return rc;
 }
@@ -700,7 +835,7 @@
 	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 	D("%s: msm_server_control rc=%d\n", __func__, rc);
 	if (rc == 0) {
 		if (tmp_cmd.value && tmp_cmd.length > 0 &&
@@ -754,7 +889,7 @@
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 
 	return rc;
 }
@@ -784,7 +919,7 @@
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 
 	ctrl->value = ((struct v4l2_control *)ctrlcmd.value)->value;
 
@@ -811,7 +946,7 @@
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in userspace, and get return value */
-	rc = msm_server_control(&g_server_dev, &ctrlcmd);
+	rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
 	D("%s: rc = %d\n", __func__, rc);
 
 	if (rc >= 0)
@@ -916,7 +1051,7 @@
 		sub->type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_CTRL;
 		D("sub->type start = 0x%x\n", sub->type);
 		do {
-			rc = v4l2_event_subscribe(fh, sub, 50);

+			rc = v4l2_event_subscribe(fh, sub, 30);
 			if (rc < 0) {
 				D("%s: failed for evtType = 0x%x, rc = %d\n",
 						__func__, sub->type, rc);
@@ -933,7 +1068,7 @@
 			V4L2_EVENT_PRIVATE_START + MSM_SVR_RESP_MAX);
 	} else {
 		D("sub->type not V4L2_EVENT_ALL = 0x%x\n", sub->type);
-		rc = v4l2_event_subscribe(fh, sub, 50);

+		rc = v4l2_event_subscribe(fh, sub, 30);
 		if (rc < 0)
 			D("%s: failed for evtType = 0x%x, rc = %d\n",
 						__func__, sub->type, rc);
@@ -978,6 +1113,7 @@
 	}
 	/* book keeping this camera session*/
 	ps->pcam_active[pcam->server_queue_idx] = pcam;
+	ps->opened_pcam[pcam->vnode_id] = pcam;
 	atomic_inc(&ps->number_pcam_active);
 
 	D("config pcam = 0x%p\n", pcam);
@@ -1003,7 +1139,7 @@
 
 	atomic_dec(&ps->number_pcam_active);
 	ps->pcam_active[pcam->server_queue_idx] = NULL;
-
+	ps->opened_pcam[pcam->vnode_id] = NULL;
 	for (i = 0; i < INTF_MAX; i++) {
 		if (ps->interface_map_table[i].mctl_handle ==
 			pcam->mctl_handle)
@@ -1017,7 +1153,7 @@
 {
 	int rc = 0;
 	rc = msm_iommu_map_contig_buffer(
-		(unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		(unsigned long)IMEM_Y_PING_OFFSET, mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
 		SZ_4K, IOMMU_WRITE | IOMMU_READ,
 		(unsigned long *)&mctl->ping_imem_y);
@@ -1029,7 +1165,7 @@
 		mctl->ping_imem_cbcr = 0;
 	}
 	msm_iommu_map_contig_buffer(
-		(unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		(unsigned long)IMEM_Y_PONG_OFFSET, mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
 		SZ_4K, IOMMU_WRITE | IOMMU_READ,
 		(unsigned long *)&mctl->pong_imem_y);
@@ -1046,10 +1182,10 @@
 static void unmap_imem_addresses(struct msm_cam_media_controller *mctl)
 {
 	msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
-		CAMERA_DOMAIN, GEN_POOL,
+		mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
 	msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
-		CAMERA_DOMAIN, GEN_POOL,
+		mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
 	mctl->ping_imem_y = 0;
 	mctl->ping_imem_cbcr = 0;
@@ -1219,6 +1355,7 @@
 		}
 		k_isp_event = (struct msm_isp_event_ctrl *)
 				event_cmd->command;
+		free_qcmd(event_cmd);
 
 		/* Save the pointer of the user allocated command buffer*/
 		u_ctrl_value = u_isp_event.isp_data.ctrl.value;
@@ -1240,31 +1377,23 @@
 				pr_err("%s Copy to user failed for cmd %d",
 					__func__, cmd);
 				kfree(k_isp_event->isp_data.ctrl.value);
-				k_isp_event->isp_data.ctrl.value = NULL;
 				kfree(k_isp_event);
-				event_cmd->command = NULL;
-				free_qcmd(event_cmd);
 				rc = -EINVAL;
 				mutex_unlock(&g_server_dev.server_queue_lock);
 				break;
 			}
 			kfree(k_isp_event->isp_data.ctrl.value);
-			k_isp_event->isp_data.ctrl.value = NULL;
 		}
 		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
 			&u_isp_event, sizeof(struct msm_isp_event_ctrl))) {
 			pr_err("%s Copy to user failed for cmd %d",
 				__func__, cmd);
 			kfree(k_isp_event);
-			event_cmd->command = NULL;
-			free_qcmd(event_cmd);
 			mutex_unlock(&g_server_dev.server_queue_lock);
 			rc = -EINVAL;
 			return rc;
 		}
 		kfree(k_isp_event);
-		event_cmd->command = NULL;
-		free_qcmd(event_cmd);
 		mutex_unlock(&g_server_dev.server_queue_lock);
 		rc = 0;
 		break;
@@ -1274,6 +1403,13 @@
 		rc = msm_server_send_v4l2_evt(arg);
 		break;
 
+	case MSM_CAM_IOCTL_V4L2_EVT_NATIVE_CMD:
+		rc = 0;
+		break;
+	case MSM_CAM_IOCTL_V4L2_EVT_NATIVE_FRONT_CMD:
+		rc = 0;
+		break;
+
 	default:
 		pr_err("%s: Invalid IOCTL = %d", __func__, cmd);
 		break;
@@ -1337,7 +1473,7 @@
 
 	D("%s\n", __func__);
 	poll_wait(fp,
-		 &g_server_dev.server_command_queue.eventHandle.wait,

+		 &g_server_dev.server_command_queue.eventHandle.wait,
 		 wait);
 	if (v4l2_event_pending(&g_server_dev.server_command_queue.eventHandle))
 		rc |= POLLPRI;
@@ -1423,7 +1559,12 @@
 	pcam->server_queue_idx = server_q_idx;
 	queue = &g_server_dev.server_queue[server_q_idx];
 	queue->ctrl_data = kzalloc(sizeof(uint8_t) *
-			max_control_command_size, GFP_KERNEL);
+			MAX_SERVER_PAYLOAD_LENGTH, GFP_KERNEL);
+	if (queue->ctrl_data == NULL) {
+		pr_err("%s: Could not allocate memory\n", __func__);
+		rc = -ENOMEM;
+		goto error;
+	}
 	msm_queue_init(&queue->ctrl_q, "control");
 	msm_queue_init(&queue->eventData_q, "eventdata");
 	queue->queue_active = 1;
@@ -1439,6 +1580,10 @@
 		pr_err("%s: invalid mctl controller", __func__);
 		goto error;
 	}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		pmctl->domain = msm_cam_server_get_domain();
+		pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
 	rc = map_imem_addresses(pmctl);
 	if (rc < 0) {
 		pr_err("%sFailed to map imem addresses %d\n", __func__, rc);
@@ -1515,7 +1660,6 @@
 {
 	int i;
 	uint32_t interface;
-
 	switch (notification) {
 	case NOTIFY_ISP_MSG_EVT:
 		if (((struct isp_msg_event *)arg)->msg_id ==
@@ -1524,6 +1668,9 @@
 		else if (((struct isp_msg_event *)arg)->msg_id ==
 			MSG_ID_RDI1_UPDATE_ACK)
 			interface = RDI_1;
+		else if (((struct isp_msg_event *)arg)->msg_id ==
+			MSG_ID_RDI2_UPDATE_ACK)
+			interface = RDI_2;
 		else
 			interface = PIX_0;
 		break;
@@ -1534,20 +1681,44 @@
 		else if (((struct isp_msg_output *)arg)->output_id ==
 						MSG_ID_OUTPUT_TERTIARY2)
 			interface = RDI_1;
+		else if (((struct isp_msg_output *)arg)->output_id ==
+						MSG_ID_OUTPUT_TERTIARY3)
+			interface = RDI_2;
 		else
 			interface = PIX_0;
 		break;
 	case NOTIFY_VFE_BUF_EVT: {
 		struct msm_vfe_resp *rp;
 		struct msm_frame_info *frame_info;
+		uint8_t vnode_id;
+
 		rp = (struct msm_vfe_resp *)arg;
 		frame_info = rp->evt_msg.data;
-		if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY1)
-			interface = RDI_0;
-		else if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY2)
-			interface = RDI_1;
-		else
-			interface = PIX_0;
+		if (frame_info->inst_handle) {
+			vnode_id = GET_DEVID_MODE(frame_info->inst_handle);
+			if (vnode_id < MAX_NUM_ACTIVE_CAMERA &&
+				g_server_dev.opened_pcam[vnode_id]) {
+				return g_server_dev.
+					opened_pcam[vnode_id]->mctl_handle;
+			} else {
+				pr_err("%s: cannot find mctl handle", __func__);
+				return 0;
+			}
+		} else {
+			if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY1)
+				interface = RDI_0;
+			else if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY2)
+				interface = RDI_1;
+			else if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY3)
+				interface = RDI_2;
+			else
+				interface = PIX_0;
+		}
+		}
+		break;
+	case NOTIFY_AXI_RDI_SOF_COUNT: {
+		struct rdi_count_msg *msg = (struct rdi_count_msg *)arg;
+		interface = msg->rdi_interface;
 		}
 		break;
 	case NOTIFY_VFE_MSG_STATS:
@@ -1557,7 +1728,6 @@
 		interface = PIX_0;
 		break;
 	}
-
 	for (i = 0; i < INTF_MAX; i++) {
 		if (interface == g_server_dev.interface_map_table[i].interface)
 			break;
@@ -1589,16 +1759,14 @@
 	switch (notification) {
 	case NOTIFY_ISP_MSG_EVT:
 	case NOTIFY_VFE_MSG_OUT:
-	case NOTIFY_VFE_SOF_COUNT:
+	case NOTIFY_VFE_PIX_SOF_COUNT:
 	case NOTIFY_VFE_MSG_STATS:
 	case NOTIFY_VFE_MSG_COMP_STATS:
 	case NOTIFY_VFE_BUF_EVT:
 		p_mctl = msm_cam_server_get_mctl(mctl_handle);
-		if (p_mctl->isp_sdev &&
-			p_mctl->isp_sdev->isp_notify
-			&& p_mctl->isp_sdev->sd)
-			rc = p_mctl->isp_sdev->isp_notify(
-				p_mctl->isp_sdev->sd, notification, arg);
+		if (p_mctl->isp_notify && p_mctl->vfe_sdev)
+			rc = p_mctl->isp_notify(p_mctl,
+				p_mctl->vfe_sdev, notification, arg);
 		break;
 	case NOTIFY_VFE_IRQ:{
 		struct msm_vfe_cfg_cmd cfg_cmd;
@@ -1613,30 +1781,21 @@
 	case NOTIFY_AXI_IRQ:
 		rc = v4l2_subdev_call(sd, core, ioctl, VIDIOC_MSM_AXI_IRQ, arg);
 		break;
+	case NOTIFY_AXI_RDI_SOF_COUNT:
+		p_mctl = msm_cam_server_get_mctl(mctl_handle);
+		if (p_mctl->axi_sdev)
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_RDI_COUNT_UPDATE, arg);
+		break;
 	case NOTIFY_PCLK_CHANGE:
 		p_mctl = v4l2_get_subdev_hostdata(sd);
 		if (p_mctl->axi_sdev)
 			rc = v4l2_subdev_call(p_mctl->axi_sdev, video,
 			s_crystal_freq, *(uint32_t *)arg, 0);
 		else
-			rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
+			rc = v4l2_subdev_call(p_mctl->vfe_sdev, video,
 			s_crystal_freq, *(uint32_t *)arg, 0);
 		break;
-	case NOTIFY_CSIPHY_CFG:
-		p_mctl = v4l2_get_subdev_hostdata(sd);
-		rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
-			core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
-		break;
-	case NOTIFY_CSID_CFG:
-		p_mctl = v4l2_get_subdev_hostdata(sd);
-		rc = v4l2_subdev_call(p_mctl->csid_sdev,
-			core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
-		break;
-	case NOTIFY_CSIC_CFG:
-		p_mctl = v4l2_get_subdev_hostdata(sd);
-		rc = v4l2_subdev_call(p_mctl->csic_sdev,
-			core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
-		break;
 	case NOTIFY_GESTURE_EVT:
 		rc = v4l2_subdev_call(g_server_dev.gesture_device,
 			core, ioctl, VIDIOC_MSM_GESTURE_EVT, arg);
@@ -2123,7 +2282,6 @@
 		}
 		cam_hw_idx = MSM_CAM_HW_VFE0 + index;
 		g_server_dev.vfe_device[index] = sd;
-		g_server_dev.isp_subdev[index]->sd = sd;
 		if (g_server_dev.irqr_device) {
 			g_server_dev.subdev_table[cam_hw_idx] = sd;
 			err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
@@ -2141,7 +2299,7 @@
 		break;
 
 	case AXI_DEV:
-		if (index >= MAX_NUM_VPE_DEV) {
+		if (index >= MAX_NUM_AXI_DEV) {
 			pr_err("%s Invalid AXI idx %d", __func__, index);
 			err = -EINVAL;
 			break;
@@ -2190,6 +2348,23 @@
 	return err;
 }
 
+#ifdef CONFIG_MSM_IOMMU
+static int camera_register_domain(void)
+{
+	struct msm_iova_partition camera_fw_partition = {
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	};
+	struct msm_iova_layout camera_fw_layout = {
+		.partitions = &camera_fw_partition,
+		.npartitions = 1,
+		.client_name = "camera_isp",
+		.domain_flags = 0,
+	};
+
+	return msm_register_domain(&camera_fw_layout);
+}
+#endif
 
 static int msm_setup_server_dev(struct platform_device *pdev)
 {
@@ -2266,6 +2441,21 @@
 		g_server_dev.interface_map_table[i].interface = 0x01 << i;
 		g_server_dev.interface_map_table[i].mctl_handle = 0;
 	}
+#ifdef CONFIG_MSM_IOMMU
+	g_server_dev.domain_num = camera_register_domain();
+	if (g_server_dev.domain_num < 0) {
+		pr_err("%s: could not register domain\n", __func__);
+		rc = -ENODEV;
+		return rc;
+	}
+	g_server_dev.domain =
+		msm_get_iommu_domain(g_server_dev.domain_num);
+	if (!g_server_dev.domain) {
+		pr_err("%s: cannot find domain\n", __func__);
+		rc = -ENODEV;
+		return rc;
+	}
+#endif
 	return rc;
 }
 
@@ -2323,6 +2513,11 @@
 		return rc;
 	}
 
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		pmctl->domain = msm_cam_server_get_domain();
+		pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
+
 	D("%s: call mctl_open\n", __func__);
 	rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
 
@@ -2376,7 +2571,11 @@
 	*p_qidx = server_q_idx;
 	queue = &g_server_dev.server_queue[server_q_idx];
 	queue->ctrl_data = kzalloc(sizeof(uint8_t) *
-		max_control_command_size, GFP_KERNEL);
+		MAX_SERVER_PAYLOAD_LENGTH, GFP_KERNEL);
+	if (!queue->ctrl_data) {
+		pr_err("%s: Could not find memory\n", __func__);
+		return -ENOMEM;
+	}
 	msm_queue_init(&queue->ctrl_q, "control");
 	msm_queue_init(&queue->eventData_q, "eventdata");
 	queue->queue_active = 1;
@@ -2485,7 +2684,6 @@
 	out->value = value;
 
 	kfree(ctrlcmd);
-	rcmd->command = NULL;
 	free_qcmd(rcmd);
 	D("%s: rc %d\n", __func__, rc);
 	/* rc is the time elapsed. */
@@ -2534,7 +2732,7 @@
 	D("%s\n", __func__);
 
 	poll_wait(fp,
-	&config->config_stat_event_queue.eventHandle.wait, wait);

+	&config->config_stat_event_queue.eventHandle.wait, wait);
 	if (v4l2_event_pending(&config->config_stat_event_queue.eventHandle))
 		rc |= POLLPRI;
 	return rc;
@@ -2596,6 +2794,7 @@
 		pr_err("%s: cannot find mctl\n", __func__);
 		return -ENODEV;
 	}
+
 	INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
 	spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
 
@@ -2607,21 +2806,10 @@
 	return rc;
 }
 
-static struct msm_isp_ops *find_isp_op(struct v4l2_subdev *sdev)
-{
-	int i;
-	for (i = 0; i < g_server_dev.config_info.num_config_nodes; i++) {
-		if (g_server_dev.isp_subdev[i]->sd == sdev)
-			return g_server_dev.isp_subdev[i];
-	}
-	return NULL;
-}
-
 static int msm_set_mctl_subdev(struct msm_cam_media_controller *pmctl,
 	struct msm_mctl_set_sdev_data *set_data)
 {
 	int rc = 0;
-	struct v4l2_subdev *vfe_sdev = NULL;
 	struct v4l2_subdev *temp_sdev = NULL;
 	switch (set_data->sdev_type) {
 	case CSIPHY_DEV:
@@ -2645,11 +2833,9 @@
 		temp_sdev = pmctl->ispif_sdev;
 		break;
 	case VFE_DEV:
-		vfe_sdev = msm_cam_find_subdev_node
+		pmctl->vfe_sdev = msm_cam_find_subdev_node
 			(&g_server_dev.vfe_device[0], set_data->revision);
-		temp_sdev = vfe_sdev;
-		pmctl->isp_sdev = find_isp_op(vfe_sdev);
-		pmctl->isp_sdev->sd = vfe_sdev;
+		temp_sdev = pmctl->vfe_sdev;
 		break;
 	case AXI_DEV:
 		pmctl->axi_sdev = msm_cam_find_subdev_node
@@ -2690,7 +2876,7 @@
 		pmctl->ispif_sdev = NULL;
 		break;
 	case VFE_DEV:
-		pmctl->isp_sdev = NULL;
+		pmctl->vfe_sdev = NULL;
 		break;
 	case AXI_DEV:
 		pmctl->axi_sdev = NULL;
@@ -2715,20 +2901,22 @@
 	struct v4l2_event_subscription temp_sub;
 
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
-	ev.id = 0;

+	ev.id = 0;
 
 	switch (cmd) {
 	/* memory management shall be handeld here*/
 	case MSM_CAM_IOCTL_REGISTER_PMEM:
 		return msm_register_pmem(
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
-			(void __user *)arg, config_cam->p_mctl->client);
+			(void __user *)arg, config_cam->p_mctl->client,
+			config_cam->p_mctl->domain_num);
 		break;
 
 	case MSM_CAM_IOCTL_UNREGISTER_PMEM:
 		return msm_pmem_table_del(
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
-			(void __user *)arg, config_cam->p_mctl->client);
+			(void __user *)arg, config_cam->p_mctl->client,
+			config_cam->p_mctl->domain_num);
 		break;
 
 	case VIDIOC_SUBSCRIBE_EVENT:
@@ -2822,11 +3010,10 @@
 							k_msg_value,
 					 k_isp_event->isp_data.isp_msg.len)) {
 						rc = -EINVAL;
-						ERR_COPY_TO_USER();
+						break;
 					}
 					kfree(k_msg_value);
-					k_isp_event->isp_data.isp_msg.len = 0;
-					k_isp_event->isp_data.isp_msg.data = NULL;
+					k_msg_value = NULL;
 				}
 			}
 		}
@@ -2836,19 +3023,15 @@
 				(void *)&u_isp_event, sizeof(
 				struct msm_isp_event_ctrl))) {
 			rc = -EINVAL;
-			ERR_COPY_TO_USER();
+			break;
 		}
 		kfree(k_isp_event);
-		*((uint32_t *)ev.u.data) = 0;
-
-		if (rc < 0)
-			break;
+		k_isp_event = NULL;
 
 		/* Copy the v4l2_event structure back to the user*/
 		if (copy_to_user((void __user *)arg, &ev,
 				sizeof(struct v4l2_event))) {
 			rc = -EINVAL;
-			ERR_COPY_TO_USER();
 			break;
 		}
 		}
@@ -2929,13 +3112,9 @@
 			(*((uint32_t *)ev.u.data));
 		if (isp_event) {
 			if (isp_event->isp_data.isp_msg.len != 0 &&
-				isp_event->isp_data.isp_msg.data != NULL) {
+				isp_event->isp_data.isp_msg.data != NULL)
 				kfree(isp_event->isp_data.isp_msg.data);
-				isp_event->isp_data.isp_msg.len = 0;
-				isp_event->isp_data.isp_msg.data = NULL;
-			}
 			kfree(isp_event);
-			*((uint32_t *)ev.u.data) = 0;
 		}
 	}
 	return 0;
@@ -3022,12 +3201,6 @@
 	  put logic here later to know how many configs to create*/
 	g_server_dev.config_info.num_config_nodes = 2;
 
-	rc = msm_isp_init_module(g_server_dev.config_info.num_config_nodes);
-	if (rc < 0) {
-		pr_err("Failed to initialize isp\n");
-		return rc;
-	}
-
 	if (!msm_class) {
 		rc = alloc_chrdev_region(&msm_devno, 0,
 		g_server_dev.config_info.num_config_nodes+1, "msm_camera");
@@ -3063,22 +3236,27 @@
 		}
 	}
 
-	msm_isp_register(&g_server_dev);
 	return rc;
 }
 
 static int __exit msm_camera_exit(struct platform_device *pdev)
 {
-	msm_isp_unregister(&g_server_dev);
 	return 0;
 }
 
+static const struct of_device_id msm_cam_server_dt_match[] = {
+	{.compatible = "qcom,cam_server"},
+}
+
+MODULE_DEVICE_TABLE(of, msm_cam_server_dt_match);
+
 static struct platform_driver msm_cam_server_driver = {
 	.probe = msm_camera_probe,
 	.remove = msm_camera_exit,
 	.driver = {
 		.name = "msm_cam_server",
 		.owner = THIS_MODULE,
+		.of_match_table = msm_cam_server_dt_match,
 	},
 };
 
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index ef5bb8e..a1b4c2a 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -17,9 +17,11 @@
 #include <linux/proc_fs.h>
 #include <linux/ioctl.h>
 #include <mach/camera.h>
-#include "../msm.h"
+#include "msm.h"
 
 uint32_t msm_cam_server_get_mctl_handle(void);
+struct iommu_domain *msm_cam_server_get_domain(void);
+int msm_cam_server_get_domain_num(void);
 struct msm_cam_media_controller *msm_cam_server_get_mctl(uint32_t handle);
 void msm_cam_server_free_mctl(uint32_t handle);
 /* Server session control APIs */
@@ -37,6 +39,8 @@
 int32_t msm_find_free_queue(void);
 int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
 	struct msm_camera_v4l2_ioctl_t *ioctl_ptr, int is_set_cmd);
+int msm_server_private_general(struct msm_cam_v4l2_device *pcam,
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr);
 int msm_server_s_ctrl(struct msm_cam_v4l2_device *pcam,
 	struct v4l2_control *ctrl);
 int msm_server_g_ctrl(struct msm_cam_v4l2_device *pcam,
@@ -65,5 +69,7 @@
 int msm_cam_server_update_irqmap(
 	struct msm_cam_server_irqmap_entry *entry);
 int msm_cam_server_config_interface_map(u32 extendedmode,
-					uint32_t mctl_handle);
+	uint32_t mctl_handle, int vnode_id, int is_bayer_sensor);
+uint32_t msm_cam_find_handle_from_mctl_ptr(
+	struct msm_cam_media_controller *p_mctl);
 #endif /* _MSM_CAM_SERVER_H */
diff --git a/drivers/media/video/msm/vfe/Makefile b/drivers/media/video/msm/vfe/Makefile
index eedbd90..250b55f 100644
--- a/drivers/media/video/msm/vfe/Makefile
+++ b/drivers/media/video/msm/vfe/Makefile
@@ -2,7 +2,7 @@
 ccflags-y += -Idrivers/media/video/msm
 ccflags-y += -Idrivers/media/video/msm/server
 ifeq ($(GCC_VERSION),0404)
-CFLAGS_REMOVE_msm_vfe8x.o = -Wframe-larger-than=${CONFIG_FRAME_WARN}
+CFLAGS_REMOVE_msm_vfe8x.o = -Wframe-larger-than=1024
 endif
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a_v4l2.o
@@ -16,5 +16,5 @@
 obj-$(CONFIG_ARCH_MSM_ARM11) += msm_vfe7x.o
 obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o
 obj-$(CONFIG_ARCH_MSM8960) += msm_vfe32.o
-obj-$(CONFIG_ARCH_MSM8974) += msm_vfe40.o msm_vfe40_axi.o
+obj-$(CONFIG_ARCH_MSM8974) += msm_vfe40.o
 obj-$(CONFIG_MSM_CAMERA_V4L2) += msm_vfe_stats_buf.o
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
index 20ea7fb..de32f1b 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
@@ -401,7 +401,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe31_ctrl->stats_ops.enqueue_buf(
 				vfe31_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 		if (rc < 0) {
 			pr_err("%s: dq stats buf (type = %d) err = %d",
 				__func__, stats_type, rc);
@@ -412,7 +412,7 @@
 }
 
 static unsigned long vfe31_stats_unregbuf(
-	struct msm_stats_reqbuf *req_buf)
+	struct msm_stats_reqbuf *req_buf, int domain_num)
 {
 	int i = 0, rc = 0;
 
@@ -420,7 +420,7 @@
 		rc = vfe31_ctrl->stats_ops.buf_unprepare(
 			vfe31_ctrl->stats_ops.stats_ctrl,
 			req_buf->stats_type, i,
-			vfe31_ctrl->stats_ops.client);
+			vfe31_ctrl->stats_ops.client, domain_num);
 		if (rc < 0) {
 			pr_err("%s: unreg stats buf (type = %d) err = %d",
 				__func__, req_buf->stats_type, rc);
@@ -3296,7 +3296,7 @@
 }
 
 static long vfe_stats_bufq_sub_ioctl(struct msm_vfe_cfg_cmd *cmd,
-	void *ion_client)
+	void *ion_client, int domain_num)
 {
 	long rc = 0;
 	switch (cmd->cmd_type) {
@@ -3344,7 +3344,7 @@
 		}
 		rc = vfe31_ctrl->stats_ops.enqueue_buf(&vfe31_ctrl->stats_ctrl,
 				(struct msm_stats_buf_info *)cmd->value,
-				vfe31_ctrl->stats_ops.client);
+				vfe31_ctrl->stats_ops.client, domain_num);
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ: {
 		struct msm_stats_flush_bufq *flush_req = NULL;
@@ -3376,7 +3376,7 @@
 			rc = -EINVAL ;
 			goto end;
 		}
-		rc = vfe31_stats_unregbuf(req_buf);
+		rc = vfe31_stats_unregbuf(req_buf, domain_num);
 	}
 	break;
 	default:
@@ -3630,7 +3630,8 @@
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 	case VFE_CMD_STATS_UNREGBUF:
 		/* for easy porting put in one envelope */
-		rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data);
+		rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data,
+			pmctl->domain_num);
 		return rc;
 	default:
 		if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -4003,10 +4004,25 @@
 			vfe31_ctrl->vfe_camif_clk,
 			ARRAY_SIZE(vfe_camif_clk_info), 1);
 		if (rc < 0)
-			goto vfe_clk_enable_failed;
+			goto vfe_camif_clk_enable_failed;
 		msm_vfe_camif_pad_reg_reset();
 	}
 
+#ifdef CONFIG_MSM_IOMMU
+	rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+	if (rc < 0) {
+		rc = -ENODEV;
+		pr_err("%s: Device attach failed\n", __func__);
+		goto device_imgwr_attach_failed;
+	}
+	rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_misc);
+	if (rc < 0) {
+		rc = -ENODEV;
+		pr_err("%s: Device attach failed\n", __func__);
+		goto device_misc_attach_failed;
+	}
+#endif
+
 	msm_camio_bus_scale_cfg(
 		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
 	msm_camio_bus_scale_cfg(
@@ -4017,6 +4033,19 @@
 
 	return rc;
 
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+	iommu_detach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+	if (!mctl->sdata->csi_if)
+		msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
+			vfe_camif_clk_info,
+			vfe31_ctrl->vfe_camif_clk,
+			ARRAY_SIZE(vfe_camif_clk_info), 0);
+vfe_camif_clk_enable_failed:
+	msm_cam_clk_enable(&vfe31_ctrl->pdev->dev, vfe_clk_info,
+		vfe31_ctrl->vfe_clk, ARRAY_SIZE(vfe_clk_info), 0);
 vfe_clk_enable_failed:
 	regulator_disable(vfe31_ctrl->fs_vfe);
 vfe_fs_failed:
@@ -4025,7 +4054,6 @@
 camif_remap_failed:
 	iounmap(vfe31_ctrl->vfebase);
 vfe_remap_failed:
-	disable_irq(vfe31_ctrl->vfeirq->start);
 mctl_failed:
 	return rc;
 }
@@ -4037,6 +4065,11 @@
 	disable_irq(vfe31_ctrl->vfeirq->start);
 	tasklet_kill(&vfe31_tasklet);
 
+#ifdef CONFIG_MSM_IOMMU
+	iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_misc);
+	iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+#endif
+
 	if (!pmctl->sdata->csi_if)
 		msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
 			vfe_camif_clk_info,
@@ -4140,6 +4173,25 @@
 
 	disable_irq(vfe31_ctrl->vfeirq->start);
 
+#ifdef CONFIG_MSM_IOMMU
+	/*get device context for IOMMU*/
+	vfe31_ctrl->iommu_ctx_imgwr =
+		msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+	vfe31_ctrl->iommu_ctx_misc =
+		msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+	if (!vfe31_ctrl->iommu_ctx_imgwr || !vfe31_ctrl->iommu_ctx_misc) {
+		if (vfe31_ctrl->camifmem) {
+			release_mem_region(vfe31_ctrl->camifmem->start,
+				resource_size(vfe31_ctrl->camifmem));
+		}
+		release_mem_region(vfe31_ctrl->vfemem->start,
+			resource_size(vfe31_ctrl->vfemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vfe31_no_resource;
+	}
+#endif
+
 	vfe31_ctrl->pdev = pdev;
 	vfe31_ctrl->fs_vfe = regulator_get(&vfe31_ctrl->pdev->dev, "vdd");
 	if (IS_ERR(vfe31_ctrl->fs_vfe)) {
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
index 60db8e5..97ecd6e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
@@ -928,6 +928,8 @@
 	uint32_t snapshot_frame_cnt;
 	struct msm_stats_bufq_ctrl stats_ctrl;
 	struct msm_stats_ops stats_ops;
+	struct device *iommu_ctx_imgwr;
+	struct device *iommu_ctx_misc;
 };
 
 enum VFE31_STATS_NUM {
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index f596695..e3624d3 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -412,36 +412,287 @@
 	}
 }
 
-static void axi_disable_irq(struct axi_ctrl_t *axi_ctrl)
+static void axi_enable_wm_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t irq_mask = 0, irq_comp_mask = 0;
+	uint16_t vfe_output_mode1 = 0;
+
+	uint16_t vfe_output_mode =
+		share_ctrl->outpath.output_mode &
+			~(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2|
+			  VFE32_OUTPUT_MODE_TERTIARY3);
+
+	vfe_output_mode1 =
+		((share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY1)  &&
+		(share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY2));
+
+	if (vfe_output_mode || vfe_output_mode1)
+		irq_comp_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_0);
+
+	if (share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+		if (share_ctrl->current_mode == VFE_OUTPUTS_RAW)
+			irq_comp_mask |= (
+				0x1 << share_ctrl->outpath.out0.ch0);
+		else
+			irq_comp_mask |= (
+				0x1 << share_ctrl->outpath.out0.ch0 |
+				0x1 << share_ctrl->outpath.out0.ch1);
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	} else if (share_ctrl->outpath.output_mode &
+			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		irq_comp_mask |= (
+			0x1 << share_ctrl->outpath.out0.ch0 |
+			0x1 << share_ctrl->outpath.out0.ch1 |
+			0x1 << share_ctrl->outpath.out0.ch2);
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	}
+	if (share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= (
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	} else if (share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask |= (
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch2 + 8));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	}
+
+	if (share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY1) {
+		irq_mask |= (0x1 << (share_ctrl->outpath.out2.ch0 +
+			VFE_WM_OFFSET));
+	}
+
+	if (share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY2) {
+		irq_mask |= (0x1 << (share_ctrl->outpath.out3.ch0 +
+			VFE_WM_OFFSET));
+	}
+	if (share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY3) {
+		irq_mask |= (0x1 << (share_ctrl->outpath.out4.ch0 +
+			VFE_WM_OFFSET));
+	}
+
+	if (vfe_output_mode1) {
+		irq_comp_mask |= (
+		0x1 << (share_ctrl->outpath.out2.ch0 + 16) |
+		0x1 << (share_ctrl->outpath.out3.ch0 + 16));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE2_MASK;
+	}
+
+
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+	if (vfe_output_mode || vfe_output_mode1)
+		msm_camera_io_w(irq_comp_mask,
+			share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+}
+
+static void axi_disable_wm_irq(struct vfe_share_ctrl_t *share_ctrl,
+	uint16_t output_mode)
+{
+	uint32_t irq_mask, irq_comp_mask = 0;
+	uint16_t vfe_output_mode1 = 0;
+	uint16_t vfe_output_mode =
+		output_mode &
+			~(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2|
+			  VFE32_OUTPUT_MODE_TERTIARY3);
+
+	vfe_output_mode1 =
+		(output_mode & VFE32_OUTPUT_MODE_TERTIARY2);
+
+	if (vfe_output_mode || vfe_output_mode1)
+		irq_comp_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_0);
+
+	if (output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask &= ~(
+			0x1 << share_ctrl->outpath.out0.ch0 |
+			0x1 << share_ctrl->outpath.out0.ch1);
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	} else if (output_mode &
+			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		irq_comp_mask &= ~(
+			0x1 << share_ctrl->outpath.out0.ch0 |
+			0x1 << share_ctrl->outpath.out0.ch1 |
+			0x1 << share_ctrl->outpath.out0.ch2);
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	}
+	if (output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask &= ~(
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8));
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	} else if (output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask &= ~(
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch2 + 8));
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	}
+	if (output_mode &
+			VFE32_OUTPUT_MODE_TERTIARY1) {
+			irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
+				VFE_WM_OFFSET));
+	}
+	if (output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY2) {
+		irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
+			VFE_WM_OFFSET));
+	}
+	if (output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY3) {
+		irq_mask &= ~(0x1 << (share_ctrl->outpath.out4.ch0 +
+			VFE_WM_OFFSET));
+	}
+	if (vfe_output_mode1) {
+		irq_comp_mask &= ~(
+		0x1 << (share_ctrl->outpath.out2.ch0 + 16) |
+		0x1 << (share_ctrl->outpath.out3.ch0 + 16));
+		irq_mask |= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE2_MASK;
+	}
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase + VFE_IRQ_MASK_0);
+	if (vfe_output_mode || vfe_output_mode1)
+		msm_camera_io_w(irq_comp_mask,
+			share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+}
+
+static void axi_enable_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t irq_mask, irq_mask1;
+	uint32_t vfe_mode =
+		share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0 |
+			VFE_OUTPUTS_RDI1 | VFE_OUTPUTS_RDI2);
+
+	if (share_ctrl->axi_ref_cnt == 1) {
+		irq_mask1 =
+			msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+
+		irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
+			msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+	}
+
+	if (share_ctrl->current_mode & (VFE_OUTPUTS_RDI0 |
+		VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2)) {
+		irq_mask1 =
+			msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+
+		if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+			irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+
+		if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+			irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+
+		if (share_ctrl->current_mode & VFE_OUTPUTS_RDI2)
+			irq_mask1 |= VFE_IRQ_STATUS1_RDI2_REG_UPDATE_MASK;
+
+		msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+			VFE_IRQ_MASK_1);
+	}
+
+	if (vfe_mode) {
+		irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		irq_mask |= 0x00000021;
+		if (share_ctrl->stats_comp)
+			irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
+		else
+			irq_mask |= 0x000FE000;
+		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		atomic_set(&share_ctrl->vstate, 1);
+	}
+	atomic_set(&share_ctrl->handle_common_irq, 1);
+}
+
+static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl,
+	uint32_t mode)
 {
 
 	/* disable all interrupts.  */
-	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
-	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
-	/* clear all pending interrupts*/
-	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
-	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
-	/* Ensure the write order while writing
-	to the command register using the barrier */
-	msm_camera_io_w_mb(1,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
+	uint32_t irq_mask = 0, irq_mask1 = 0, clear_mask1 = 0;
+	uint32_t vfe_mode =
+		(mode & ~(VFE_OUTPUTS_RDI0|
+			VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2));
+
+	if (mode & (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2)) {
+		irq_mask1 =
+			msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+
+		if (mode & VFE_OUTPUTS_RDI0) {
+			irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK);
+			clear_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+		}
+
+		if (mode & VFE_OUTPUTS_RDI1) {
+			irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK);
+			clear_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+		}
+		if (mode & VFE_OUTPUTS_RDI2) {
+			irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI2_REG_UPDATE_MASK);
+			clear_mask1 |= VFE_IRQ_STATUS1_RDI2_REG_UPDATE_MASK;
+		}
+
+		msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+			VFE_IRQ_MASK_1);
+		msm_camera_io_w(clear_mask1,
+			share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+	}
+
+	if (vfe_mode) {
+		atomic_set(&share_ctrl->vstate, 0);
+		irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		irq_mask &= ~(0x00000021);
+		if (share_ctrl->stats_comp)
+			irq_mask &= ~(VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK);
+		else
+			irq_mask &= ~0x000FE000;
+		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+	}
 }
 
 static void vfe32_stop(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 
-	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
 	/* in either continuous or snapshot mode, stop command can be issued
 	 * at any time. stop camif immediately. */
-	msm_camera_io_w(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+	if (!vfe32_ctrl->share_ctrl->dual_enabled)
+		msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+	else
+		msm_camera_io_w(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
 	vfe32_ctrl->share_ctrl->operation_mode &=
-		~(vfe32_ctrl->share_ctrl->current_mode);
+		(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2);
 }
 
 static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
@@ -467,7 +718,7 @@
 {
 	uint32_t *ch_info;
 	uint32_t *axi_cfg = ao+V32_AXI_BUS_FMT_OFF;
-	int vfe_mode = (mode & ~(OUTPUT_TERT1|OUTPUT_TERT2));
+	int vfe_mode = (mode & ~(OUTPUT_TERT1|OUTPUT_TERT2|OUTPUT_TERT3));
 	uint32_t bus_cmd = *axi_cfg;
 	int i;
 
@@ -497,6 +748,12 @@
 	axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info++;
 	axi_ctrl->share_ctrl->outpath.out3.inst_handle = *ch_info++;
 
+	axi_ctrl->share_ctrl->outpath.out4.ch0 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out4.ch1 =
+		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out4.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out4.inst_handle = *ch_info++;
+
 	axi_ctrl->share_ctrl->outpath.output_mode = 0;
 
 	if (mode & OUTPUT_TERT1)
@@ -505,8 +762,16 @@
 	if (mode & OUTPUT_TERT2)
 		axi_ctrl->share_ctrl->outpath.output_mode |=
 			VFE32_OUTPUT_MODE_TERTIARY2;
-	if (mode == OUTPUT_TERT1 || mode == OUTPUT_TERT1
-		|| mode == (OUTPUT_TERT1|OUTPUT_TERT2))
+	if (mode & OUTPUT_TERT3)
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE32_OUTPUT_MODE_TERTIARY3;
+	if (mode == OUTPUT_TERT1
+		|| mode == OUTPUT_TERT2
+		|| mode == OUTPUT_TERT3
+		|| mode == (OUTPUT_TERT1|OUTPUT_TERT2)
+		|| mode == (OUTPUT_TERT1|OUTPUT_TERT3)
+		|| mode == (OUTPUT_TERT2|OUTPUT_TERT3)
+		|| mode == (OUTPUT_TERT1|OUTPUT_TERT2|OUTPUT_TERT3))
 			goto bus_cfg;
 
 	switch (vfe_mode) {
@@ -550,8 +815,6 @@
 		V32_AXI_BUS_CFG_LEN);
 	axi_cfg += V32_AXI_BUS_CFG_LEN/4;
 	for (i = 0; i < ARRAY_SIZE(vfe32_AXI_WM_CFG); i++) {
-		msm_camera_io_w(*axi_cfg,
-			axi_ctrl->share_ctrl->vfebase+vfe32_AXI_WM_CFG[i]);
 		axi_cfg += 3;
 		msm_camera_io_memcpy(
 			axi_ctrl->share_ctrl->vfebase+vfe32_AXI_WM_CFG[i]+12,
@@ -560,10 +823,58 @@
 	}
 	msm_camera_io_w(bus_cmd, axi_ctrl->share_ctrl->vfebase +
 					V32_AXI_BUS_CMD_OFF);
+	msm_camera_io_w(*ch_info++,
+		axi_ctrl->share_ctrl->vfebase + VFE_PIXEL_IF_CFG);
+	if (msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+		V32_GET_HW_VERSION_OFF) ==
+		VFE33_HW_NUMBER) {
+		msm_camera_io_w(*ch_info++,
+			axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+		msm_camera_io_w(*ch_info++,
+			axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
+	}
 	return 0;
 }
 
 static void axi_reset_internal_variables(
+	struct axi_ctrl_t *axi_ctrl,
+	struct msm_camera_vfe_params_t vfe_params)
+{
+	if (vfe_params.operation_mode & VFE_OUTPUTS_RDI0) {
+		atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+		axi_ctrl->share_ctrl->rdi0_capture_count = -1;
+		axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+		axi_ctrl->share_ctrl->rdi0FrameId = 0;
+		axi_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY1;
+		axi_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI0);
+	}
+
+	if (vfe_params.operation_mode & VFE_OUTPUTS_RDI1) {
+		atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+		axi_ctrl->share_ctrl->rdi1_capture_count = -1;
+		axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+		axi_ctrl->share_ctrl->rdi1FrameId = 0;
+		axi_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY2;
+		axi_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI1);
+	}
+
+	if (vfe_params.operation_mode & VFE_OUTPUTS_RDI2) {
+		atomic_set(&axi_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
+		axi_ctrl->share_ctrl->rdi2_capture_count = -1;
+		axi_ctrl->share_ctrl->outpath.out4.capture_cnt = -1;
+		axi_ctrl->share_ctrl->rdi2FrameId = 0;
+		axi_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY3;
+		axi_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI2);
+	}
+}
+
+static void axi_global_reset_internal_variables(
 	struct axi_ctrl_t *axi_ctrl)
 {
 	unsigned long flags;
@@ -585,6 +896,8 @@
 	axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
 
 	atomic_set(&axi_ctrl->share_ctrl->vstate, 0);
+	atomic_set(&axi_ctrl->share_ctrl->handle_common_irq, 0);
+	atomic_set(&axi_ctrl->share_ctrl->pix0_update_ack_pending, 0);
 	atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
 	atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
 	atomic_set(&axi_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
@@ -593,41 +906,24 @@
 	axi_ctrl->share_ctrl->operation_mode = 0;
 	axi_ctrl->share_ctrl->current_mode = 0;
 	axi_ctrl->share_ctrl->outpath.output_mode = 0;
+	axi_ctrl->share_ctrl->comp_output_mode = 0;
 	axi_ctrl->share_ctrl->vfe_capture_count = 0;
+	axi_ctrl->share_ctrl->rdi0_capture_count = -1;
+	axi_ctrl->share_ctrl->rdi1_capture_count = -1;
+	axi_ctrl->share_ctrl->rdi2_capture_count = -1;
+	axi_ctrl->share_ctrl->outpath.out0.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out1.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out4.capture_cnt = -1;
 
 	/* this is unsigned 32 bit integer. */
 	axi_ctrl->share_ctrl->vfeFrameId = 0;
+	axi_ctrl->share_ctrl->rdi0FrameId = 0;
+	axi_ctrl->share_ctrl->rdi1FrameId = 0;
+	axi_ctrl->share_ctrl->rdi2FrameId = 0;
 }
 
-static void vfe32_reset_internal_variables(
-	struct vfe32_ctrl_type *vfe32_ctrl)
-{
-	/* Stats control variables. */
-	memset(&(vfe32_ctrl->afbfStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	memset(&(vfe32_ctrl->awbStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	memset(&(vfe32_ctrl->aecbgStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	memset(&(vfe32_ctrl->bhistStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	memset(&(vfe32_ctrl->ihistStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	memset(&(vfe32_ctrl->rsStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	memset(&(vfe32_ctrl->csStatsControl), 0,
-		sizeof(struct vfe_stats_control));
-
-	vfe32_ctrl->frame_skip_cnt = 31;
-	vfe32_ctrl->frame_skip_pattern = 0xffffffff;
-	vfe32_ctrl->snapshot_frame_cnt = 0;
-}
 
 static void vfe32_program_dmi_cfg(
 	enum VFE32_DMI_RAM_SEL bankSel,
@@ -685,9 +981,186 @@
 	vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 }
 
-static int axi_reset(struct axi_ctrl_t *axi_ctrl)
+static void vfe32_set_default_reg_values(
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	axi_reset_internal_variables(axi_ctrl);
+	msm_camera_io_w(0x800080,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
+	msm_camera_io_w(0x800080,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+	/* What value should we program CGC_OVERRIDE to? */
+	msm_camera_io_w(0xFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
+
+	/* default frame drop period and pattern */
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_FRAMEDROP_ENC_CBCR_PATTERN);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
+	msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MIN);
+	msm_camera_io_w(0xFFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MAX);
+
+	/* stats UB config */
+	CDBG("%s: Use bayer stats = %d\n", __func__,
+		 vfe32_use_bayer_stats(vfe32_ctrl));
+	if (!vfe32_use_bayer_stats(vfe32_ctrl)) {
+		msm_camera_io_w(0x3980007,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_AEC_BG_UB_CFG);
+		msm_camera_io_w(0x3A00007,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_AF_BF_UB_CFG);
+		msm_camera_io_w(0x3A8000F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_AWB_UB_CFG);
+		msm_camera_io_w(0x3B80007,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_RS_UB_CFG);
+		msm_camera_io_w(0x3C0001F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_CS_UB_CFG);
+		msm_camera_io_w(0x3E0001F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_HIST_UB_CFG);
+	} else {
+		msm_camera_io_w(0x350001F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_HIST_UB_CFG);
+		msm_camera_io_w(0x370002F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_AEC_BG_UB_CFG);
+		msm_camera_io_w(0x3A0002F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_AF_BF_UB_CFG);
+		msm_camera_io_w(0x3D00007,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_RS_UB_CFG);
+		msm_camera_io_w(0x3D8001F,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_CS_UB_CFG);
+		msm_camera_io_w(0x3F80007,
+			vfe32_ctrl->share_ctrl->vfebase +
+				VFE_BUS_STATS_SKIN_BHIST_UB_CFG);
+	}
+	vfe32_reset_dmi_tables(vfe32_ctrl);
+}
+
+static void vfe32_reset_internal_variables(
+	struct vfe32_ctrl_type *vfe32_ctrl)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->update_ack_lock,
+		flags);
+	vfe32_ctrl->share_ctrl->update_ack_pending = FALSE;
+	spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->update_ack_lock,
+		flags);
+	vfe32_ctrl->share_ctrl->vfe_capture_count = 0;
+	/* this is unsigned 32 bit integer. */
+	vfe32_ctrl->share_ctrl->vfeFrameId = 0;
+	vfe32_ctrl->share_ctrl->update_counter = 0;
+
+	/* Stats control variables. */
+	memset(&(vfe32_ctrl->afbfStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe32_ctrl->awbStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe32_ctrl->aecbgStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe32_ctrl->bhistStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe32_ctrl->ihistStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe32_ctrl->rsStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe32_ctrl->csStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+	vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = -1;
+	vfe32_ctrl->share_ctrl->outpath.out1.capture_cnt = -1;
+	vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+	vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+	vfe32_ctrl->share_ctrl->outpath.out4.capture_cnt = -1;
+
+	vfe32_ctrl->share_ctrl->recording_state = VFE_STATE_IDLE;
+	vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->pix0_update_ack_pending, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
+	vfe32_ctrl->frame_skip_cnt = 31;
+	vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+	vfe32_ctrl->snapshot_frame_cnt = 0;
+	vfe32_set_default_reg_values(vfe32_ctrl);
+}
+
+
+static int vfe32_reset(struct vfe32_ctrl_type *vfe32_ctrl)
+{
+	uint32_t irq_mask1, irq_mask;
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+	msm_camera_io_w(VFE_MODULE_RESET_CMD,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+	msm_camera_io_w(0,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+
+	irq_mask =
+		msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+	irq_mask &= ~(0x000FE021|VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK);
+
+	msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
+		VFE_IRQ_MASK_0);
+	vfe32_ctrl->share_ctrl->operation_mode &=
+		(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2);
+	vfe32_ctrl->share_ctrl->comp_output_mode &=
+			(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2|
+			VFE32_OUTPUT_MODE_TERTIARY3);
+
+	/* enable reset_ack interrupt.  */
+	irq_mask1 = msm_camera_io_r(
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+	irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
+	msm_camera_io_w(irq_mask1,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+	msm_camera_io_w_mb(VFE_ONLY_RESET_CMD,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+
+	return wait_for_completion_interruptible(
+			&vfe32_ctrl->share_ctrl->reset_complete);
+}
+
+static int axi_reset(struct axi_ctrl_t *axi_ctrl,
+	struct msm_camera_vfe_params_t vfe_params)
+{
+	int rc = 0;
+	if (vfe_params.skip_reset) {
+		axi_reset_internal_variables(axi_ctrl, vfe_params);
+		return rc;
+	}
+	axi_global_reset_internal_variables(axi_ctrl);
 	/* disable all interrupts.  vfeImaskLocal is also reset to 0
 	* to begin with. */
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -729,7 +1202,6 @@
 {
 	uint32_t *p = cmd;
 
-	vfe32_ctrl->share_ctrl->operation_mode = *p;
 	vfe32_ctrl->share_ctrl->stats_comp = *(++p);
 	vfe32_ctrl->hfr_mode = *(++p);
 
@@ -738,19 +1210,6 @@
 	msm_camera_io_w(*(++p),
 		vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 	msm_camera_io_w(*(++p),
-		vfe32_ctrl->share_ctrl->vfebase + VFE_PIXEL_IF_CFG);
-	if (msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
-		V32_GET_HW_VERSION_OFF) ==
-		VFE33_HW_NUMBER) {
-		msm_camera_io_w(*(++p),
-			vfe32_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
-		msm_camera_io_w(*(++p),
-			vfe32_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
-	}  else {
-		++p;
-		++p;
-	}
-	msm_camera_io_w(*(++p),
 		vfe32_ctrl->share_ctrl->vfebase + VFE_REALIGN_BUF);
 	msm_camera_io_w(*(++p),
 		vfe32_ctrl->share_ctrl->vfebase + VFE_CHROMA_UP);
@@ -802,7 +1261,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe32_ctrl->stats_ops.enqueue_buf(
 				vfe32_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 		if (rc < 0) {
 			pr_err("%s: dq stats buf (type = %d) err = %d",
 				 __func__, stats_type, rc);
@@ -815,7 +1274,7 @@
 
 static unsigned long vfe32_stats_unregbuf(
 	struct vfe32_ctrl_type *vfe32_ctrl,
-	struct msm_stats_reqbuf *req_buf)
+	struct msm_stats_reqbuf *req_buf, int domain_num)
 {
 	int i = 0, rc = 0;
 
@@ -823,7 +1282,7 @@
 		rc = vfe32_ctrl->stats_ops.buf_unprepare(
 			vfe32_ctrl->stats_ops.stats_ctrl,
 			req_buf->stats_type, i,
-			vfe32_ctrl->stats_ops.client);
+			vfe32_ctrl->stats_ops.client, domain_num);
 		if (rc < 0) {
 			pr_err("%s: unreg stats buf (type = %d) err = %d",
 				__func__, req_buf->stats_type, rc);
@@ -1063,70 +1522,11 @@
 
 static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	uint32_t irq_mask = 0x00E00021, irq_mask1, reg_update;
-	uint16_t vfe_operation_mode =
-		vfe32_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
-			VFE_OUTPUTS_RDI1);
-	vfe32_ctrl->share_ctrl->start_ack_pending = TRUE;
 	CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
-		vfe32_ctrl->share_ctrl->current_mode,
+		vfe32_ctrl->share_ctrl->operation_mode,
 		vfe32_ctrl->share_ctrl->outpath.output_mode);
-	if (vfe32_ctrl->share_ctrl->stats_comp)
-		irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
-	else
-		irq_mask |= 0x000FE000;
-	irq_mask |=
-		msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-	msm_camera_io_w(irq_mask,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
-	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
-
-	irq_mask1 =
-		msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
-	reg_update =
-		msm_camera_io_r_mb(vfe32_ctrl->share_ctrl->vfebase +
-			VFE_REG_UPDATE_CMD);
-
-	if (vfe32_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
-		irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
-		msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
-		if (!atomic_cmpxchg(
-			&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending,
-				0, 1)) {
-			msm_camera_io_w_mb(reg_update|0x2,
-				vfe32_ctrl->share_ctrl->vfebase +
-				VFE_REG_UPDATE_CMD);
-		}
-	}
-	if (vfe32_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
-		irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
-		msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
-		if (!atomic_cmpxchg(
-			&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending,
-				0, 1)) {
-			msm_camera_io_w_mb(reg_update|0x4,
-			vfe32_ctrl->share_ctrl->vfebase +
-			VFE_REG_UPDATE_CMD);
-		}
-		msm_camera_io_w_mb(reg_update|0x4, vfe32_ctrl->share_ctrl->
-			vfebase + VFE_REG_UPDATE_CMD);
-	}
-	if (vfe_operation_mode) {
-		msm_camera_io_w_mb(reg_update|0x1, vfe32_ctrl->share_ctrl->
-			vfebase + VFE_REG_UPDATE_CMD);
 		msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
 			VFE_CAMIF_COMMAND);
-	}
-	vfe32_ctrl->share_ctrl->operation_mode |=
-		vfe32_ctrl->share_ctrl->current_mode;
-	/* Ensure the write order while writing
-	to the command register using the barrier */
-	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 1);
 }
 
 static int vfe32_start_recording(
@@ -1176,6 +1576,7 @@
 	struct msm_cam_media_controller *pmctl,
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
+	vfe32_ctrl->share_ctrl->start_ack_pending = TRUE;
 	vfe32_start_common(vfe32_ctrl);
 
 	msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x18C);
@@ -1431,6 +1832,8 @@
 		ch = &share_ctrl->outpath.out2;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
 		ch = &share_ctrl->outpath.out3;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY3)
+		ch = &share_ctrl->outpath.out4;
 	else
 		pr_err("%s: Invalid path %d\n", __func__,
 			path);
@@ -1453,6 +1856,8 @@
 		inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
 		inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY3)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out4.inst_handle;
 
 	vfe32_subdev_notify(id, path, inst_handle,
 		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
@@ -1467,6 +1872,8 @@
 	struct vfe32_output_ch *outch = NULL;
 	int rc = 0;
 	uint32_t inst_handle = 0;
+	static uint32_t ping_t1_ch0_paddr, pong_t1_ch0_paddr;
+
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
 		inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_SECONDARY)
@@ -1475,14 +1882,43 @@
 		inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
 	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
 		inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY3)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out4.inst_handle;
 
-	vfe32_subdev_notify(id, path, inst_handle,
-		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
+	CDBG("%s path %d, inst_handle 0x%x\n", __func__, path, inst_handle);
+
+	if (path != VFE_MSG_OUTPUT_TERTIARY2) {
+		vfe32_subdev_notify(id, path, inst_handle,
+			&axi_ctrl->subdev, axi_ctrl->share_ctrl);
+	}
+
 	outch = vfe32_get_ch(path, axi_ctrl->share_ctrl);
-	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
+
+	if (path == VFE_MSG_OUTPUT_TERTIARY1) {
+		ping_t1_ch0_paddr = outch->ping.ch_paddr[1];
+		pong_t1_ch0_paddr = outch->pong.ch_paddr[1];
+	}
+	if (path == VFE_MSG_OUTPUT_TERTIARY2 && ping_t1_ch0_paddr &&
+			pong_t1_ch0_paddr) {
+		vfe32_put_ch_ping_addr(
+			axi_ctrl->share_ctrl->vfebase, outch->ch0,
+			ping_t1_ch0_paddr);
+		vfe32_put_ch_pong_addr(
+			axi_ctrl->share_ctrl->vfebase, outch->ch0,
+			pong_t1_ch0_paddr);
+		    ping_t1_ch0_paddr = 0;
+			pong_t1_ch0_paddr = 0;
+
+		memset(&outch->ping, 0, sizeof(struct msm_free_buf));
+		memset(&outch->pong, 0, sizeof(struct msm_free_buf));
+	} else if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
 		/* Configure Preview Ping Pong */
-		pr_info("%s Configure ping/pong address for %d",
+		CDBG("%s Configure ping/pong address for %d\n",
 						__func__, path);
+		CDBG("%s Ping/pong address 0x%x, 0x%x, 0x%x, 0x%x\n",
+			__func__, outch->ping.ch_paddr[0],
+			outch->pong.ch_paddr[0], outch->ping.ch_paddr[1],
+			outch->pong.ch_paddr[1]);
 		vfe32_put_ch_ping_addr(
 			axi_ctrl->share_ctrl->vfebase, outch->ch0,
 			outch->ping.ch_paddr[0]);
@@ -1492,7 +1928,8 @@
 
 		if ((axi_ctrl->share_ctrl->current_mode !=
 			VFE_OUTPUTS_RAW) && (path != VFE_MSG_OUTPUT_TERTIARY1)
-			&& (path != VFE_MSG_OUTPUT_TERTIARY2)) {
+			&& (path != VFE_MSG_OUTPUT_TERTIARY2)
+			&& (path != VFE_MSG_OUTPUT_TERTIARY3)) {
 			vfe32_put_ch_ping_addr(
 				axi_ctrl->share_ctrl->vfebase, outch->ch1,
 				outch->ping.ch_paddr[1]);
@@ -1570,7 +2007,8 @@
 	case VFE_CMD_RESET:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		vfe32_reset_internal_variables(vfe32_ctrl);
+		vfe32_ctrl->share_ctrl->vfe_reset_flag = true;
+		vfe32_reset(vfe32_ctrl);
 		break;
 	case VFE_CMD_START:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
@@ -1634,10 +2072,6 @@
 			goto proc_general_done;
 		}
 		cmdp = kmalloc(V32_OPERATION_CFG_LEN, GFP_ATOMIC);
-		if (!cmdp) {
-			rc = -ENOMEM;
-			goto proc_general_done;
-		}
 		if (copy_from_user(cmdp,
 			(void __user *)(cmd->value),
 			V32_OPERATION_CFG_LEN)) {
@@ -2654,8 +3088,6 @@
 				goto proc_general_done;
 		}
 
-		vfe32_ctrl->share_ctrl->current_mode =
-			vfe_params.operation_mode;
 		vfe32_stop(vfe32_ctrl);
 		break;
 
@@ -3030,312 +3462,542 @@
 
 }
 
+void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl,
+	uint32_t vfe_mode, uint8_t cmd_type)
+{
+	uint32_t reg_update = 0x1;
+	switch (cmd_type) {
+	case AXI_CMD_RAW_CAPTURE:
+		msm_camera_io_w(0, share_ctrl->vfebase
+			+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out0.ch0]);
+		break;
+	case AXI_CMD_PREVIEW: {
+		switch (vfe_mode) {
+		case VFE_OUTPUTS_PREVIEW:
+		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+			if (share_ctrl->comp_output_mode &
+				VFE32_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch1]);
+			} else if (share_ctrl->comp_output_mode &
+					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch1]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch2]);
+			}
+			break;
+		default:
+			if (share_ctrl->comp_output_mode &
+				VFE32_OUTPUT_MODE_SECONDARY) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch1]);
+			} else if (share_ctrl->comp_output_mode &
+				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch1]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe32_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch2]);
+			}
+			break;
+			}
+		}
+		break;
+	default:
+		if (share_ctrl->comp_output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch1]);
+		} else if (share_ctrl->comp_output_mode &
+				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch1]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch2]);
+		}
+
+		if (share_ctrl->comp_output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->
+				outpath.out1.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+		} else if (share_ctrl->comp_output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch2]);
+		}
+		break;
+	}
+
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+void axi_stop_rdi0(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t reg_update = 0x2;
+	msm_camera_io_w(0, share_ctrl->vfebase +
+		vfe32_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+void axi_stop_rdi1(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t reg_update = 0x4;
+	msm_camera_io_w(0, share_ctrl->vfebase +
+		vfe32_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+void axi_stop_rdi2(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t reg_update = 0x8; /* bit 3 */
+	msm_camera_io_w(0, share_ctrl->vfebase +
+		vfe32_AXI_WM_CFG[share_ctrl->outpath.out4.ch0]);
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+void axi_stop_process(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t vfe_mode =
+	share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+		VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2);
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		axi_stop_rdi0(share_ctrl);
+		axi_disable_wm_irq(share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY1);
+		share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY1;
+		share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI0);
+	}
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		axi_stop_rdi1(share_ctrl);
+		axi_disable_wm_irq(share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY2);
+		share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY2;
+		share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI1);
+	}
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI2) {
+		axi_stop_rdi2(share_ctrl);
+		axi_disable_wm_irq(share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY3);
+		share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY3;
+		share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI2);
+	}
+	if (vfe_mode) {
+		uint16_t mode = share_ctrl->comp_output_mode &
+			~(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2|
+			  VFE32_OUTPUT_MODE_TERTIARY3);
+		axi_stop_pix(share_ctrl, vfe_mode, share_ctrl->cmd_type);
+		axi_disable_wm_irq(share_ctrl, mode);
+		share_ctrl->comp_output_mode &=
+				(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2|
+				 VFE32_OUTPUT_MODE_TERTIARY3);
+	}
+}
+
 static void vfe32_process_reg_update_irq(
 		struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
+	struct vfe_share_ctrl_t *share_ctrl = vfe32_ctrl->share_ctrl;
+	if (atomic_read(
+		&share_ctrl->pix0_update_ack_pending) == 2) {
+		uint32_t vfe_mode =
+				share_ctrl->operation_mode & ~(VFE_OUTPUTS_RDI0|
+					VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2);
 
-	if (vfe32_ctrl->share_ctrl->recording_state ==
-				VFE_STATE_START_REQUESTED) {
-		if (vfe32_ctrl->share_ctrl->operation_mode &
-				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
-			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-		} else if (vfe32_ctrl->share_ctrl->operation_mode &
-				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
-			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out1.ch1]);
-		}
-		vfe32_ctrl->share_ctrl->recording_state = VFE_STATE_STARTED;
-		msm_camera_io_w_mb(1,
-			vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-		CDBG("start video triggered .\n");
-	} else if (vfe32_ctrl->share_ctrl->recording_state ==
-			VFE_STATE_STOP_REQUESTED) {
-		if (vfe32_ctrl->share_ctrl->operation_mode &
-				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-		} else if (vfe32_ctrl->share_ctrl->operation_mode &
-				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out1.ch1]);
-		}
-		CDBG("stop video triggered .\n");
-	}
-
-	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->start_ack_lock, flags);
-	if (vfe32_ctrl->share_ctrl->start_ack_pending == TRUE) {
-		vfe32_ctrl->share_ctrl->start_ack_pending = FALSE;
-		spin_unlock_irqrestore(
-			&vfe32_ctrl->share_ctrl->start_ack_lock, flags);
-		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
-	} else {
-		spin_unlock_irqrestore(
-			&vfe32_ctrl->share_ctrl->start_ack_lock, flags);
-		if (vfe32_ctrl->share_ctrl->recording_state ==
-				VFE_STATE_STOP_REQUESTED) {
-			vfe32_ctrl->share_ctrl->recording_state =
-						VFE_STATE_STOPPED;
-			/* request a reg update and send STOP_REC_ACK
-			 * when we process the next reg update irq.
-			 */
-			msm_camera_io_w_mb(1,
-			vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-		} else if (vfe32_ctrl->share_ctrl->recording_state ==
-					VFE_STATE_STOPPED) {
-			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-				vfe32_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_STOP_REC_ACK);
-			vfe32_ctrl->share_ctrl->recording_state =
-						VFE_STATE_IDLE;
-		}
-		spin_lock_irqsave(
-			&vfe32_ctrl->share_ctrl->update_ack_lock, flags);
-		if (vfe32_ctrl->share_ctrl->update_ack_pending == TRUE) {
-			vfe32_ctrl->share_ctrl->update_ack_pending = FALSE;
-			spin_unlock_irqrestore(
-				&vfe32_ctrl->share_ctrl->update_ack_lock,
-								flags);
-			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-				vfe32_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_UPDATE_ACK);
+		if (share_ctrl->dual_enabled && !share_ctrl->update_counter) {
+			axi_stop_pix(share_ctrl, vfe_mode,
+				share_ctrl->cmd_type);
+			share_ctrl->update_counter++;
 		} else {
-			spin_unlock_irqrestore(
-				&vfe32_ctrl->share_ctrl->update_ack_lock,
-								flags);
+			uint16_t output_mode =
+				share_ctrl->comp_output_mode &
+				~(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2|
+				  VFE32_OUTPUT_MODE_TERTIARY3);
+			share_ctrl->update_counter = 0;
+			if (!share_ctrl->dual_enabled)
+				axi_stop_pix(share_ctrl, vfe_mode,
+					share_ctrl->cmd_type);
+			axi_disable_wm_irq(share_ctrl, output_mode);
+			axi_disable_irq(share_ctrl, vfe_mode);
+			atomic_set(&share_ctrl->pix0_update_ack_pending, 0);
+			msm_camera_io_w_mb(
+					CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+					share_ctrl->vfebase +
+					VFE_CAMIF_COMMAND);
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				share_ctrl->vfeFrameId,
+				MSG_ID_PIX0_UPDATE_ACK);
+			share_ctrl->comp_output_mode &=
+				(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2|
+				 VFE32_OUTPUT_MODE_TERTIARY3);
 		}
+	}  else {
+		if (share_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
+			if (share_ctrl->operation_mode &
+					VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+				msm_camera_io_w((
+					0x1 << share_ctrl->outpath.out0.ch0 |
+					0x1 << share_ctrl->outpath.out0.ch1),
+					share_ctrl->vfebase + VFE_BUS_CMD);
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch1]);
+			} else if (share_ctrl->operation_mode &
+					VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+				msm_camera_io_w((
+					0x1 << share_ctrl->outpath.out1.ch0 |
+					0x1 << share_ctrl->outpath.out1.ch1),
+					share_ctrl->vfebase + VFE_BUS_CMD);
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out1.ch0]);
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out1.ch1]);
+			}
+			share_ctrl->recording_state = VFE_STATE_STARTED;
+			msm_camera_io_w_mb(1,
+				share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+			CDBG("start video triggered .\n");
+		} else if (share_ctrl->recording_state ==
+					VFE_STATE_STOP_REQUESTED) {
+			if (share_ctrl->operation_mode &
+					VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch1]);
+			} else if (share_ctrl->operation_mode &
+					VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out1.ch0]);
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out1.ch1]);
+			}
+			CDBG("stop video triggered .\n");
+		}
+
+		if (atomic_cmpxchg(
+		&share_ctrl->pix0_update_ack_pending, 1, 0) == 1) {
+			share_ctrl->comp_output_mode |=
+				(share_ctrl->outpath.output_mode
+				& ~(VFE32_OUTPUT_MODE_TERTIARY1|
+					VFE32_OUTPUT_MODE_TERTIARY2|
+					VFE32_OUTPUT_MODE_TERTIARY3));
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				share_ctrl->vfeFrameId, MSG_ID_PIX0_UPDATE_ACK);
+		} else {
+			if (share_ctrl->recording_state ==
+						VFE_STATE_STOP_REQUESTED) {
+				share_ctrl->recording_state = VFE_STATE_STOPPED;
+				/* request a reg update and send STOP_REC_ACK
+				 * when we process the next reg update irq.
+				 */
+				msm_camera_io_w_mb(1, share_ctrl->vfebase +
+							VFE_REG_UPDATE_CMD);
+			} else if (share_ctrl->recording_state ==
+						VFE_STATE_STOPPED) {
+				vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+					share_ctrl->vfeFrameId,
+					MSG_ID_STOP_REC_ACK);
+				share_ctrl->recording_state = VFE_STATE_IDLE;
+			}
+			spin_lock_irqsave(
+				&share_ctrl->update_ack_lock,
+				flags);
+			if (share_ctrl->update_ack_pending == TRUE) {
+				share_ctrl->update_ack_pending = FALSE;
+				spin_unlock_irqrestore(
+					&share_ctrl->update_ack_lock, flags);
+				vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+					share_ctrl->vfeFrameId,
+					MSG_ID_UPDATE_ACK);
+			} else {
+				spin_unlock_irqrestore(
+					&share_ctrl->update_ack_lock, flags);
+			}
+		}
+
+		switch (share_ctrl->liveshot_state) {
+		case VFE_STATE_START_REQUESTED:
+			CDBG("%s enabling liveshot output\n", __func__);
+			if (share_ctrl->comp_output_mode &
+						VFE32_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w((
+					0x1 << share_ctrl->outpath.out0.ch0 |
+					0x1 << share_ctrl->outpath.out0.ch1),
+					share_ctrl->vfebase + VFE_BUS_CMD);
+				msm_camera_io_w(1, share_ctrl->vfebase +
+					vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(1, share_ctrl->vfebase +
+					vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch1]);
+
+				share_ctrl->liveshot_state =
+					VFE_STATE_STARTED;
+			}
+			break;
+		case VFE_STATE_STARTED:
+			share_ctrl->vfe_capture_count--;
+			if (!share_ctrl->vfe_capture_count &&
+				(share_ctrl->comp_output_mode &
+					VFE32_OUTPUT_MODE_PRIMARY)) {
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch1]);
+			}
+			break;
+		case VFE_STATE_STOP_REQUESTED:
+			if (share_ctrl->comp_output_mode &
+					VFE32_OUTPUT_MODE_PRIMARY) {
+				/* Stop requested, stop write masters, and
+				 * trigger REG_UPDATE. Send STOP_LS_ACK in
+				 * next reg update. */
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe32_AXI_WM_CFG[
+					share_ctrl->outpath.out0.ch1]);
+
+				share_ctrl->liveshot_state = VFE_STATE_STOPPED;
+				msm_camera_io_w_mb(1, share_ctrl->vfebase +
+					VFE_REG_UPDATE_CMD);
+			}
+			break;
+		case VFE_STATE_STOPPED:
+			CDBG("%s Sending STOP_LS ACK\n", __func__);
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				share_ctrl->vfeFrameId, MSG_ID_STOP_LS_ACK);
+			share_ctrl->liveshot_state = VFE_STATE_IDLE;
+			break;
+		default:
+			break;
+		}
+
+		if ((share_ctrl->operation_mode & VFE_OUTPUTS_THUMB_AND_MAIN) ||
+			(share_ctrl->operation_mode &
+				VFE_OUTPUTS_MAIN_AND_THUMB) ||
+			(share_ctrl->operation_mode &
+				VFE_OUTPUTS_THUMB_AND_JPEG) ||
+			(share_ctrl->operation_mode &
+				VFE_OUTPUTS_JPEG_AND_THUMB)) {
+			/* in snapshot mode */
+			/* later we need to add check for live snapshot mode. */
+			if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
+				(vfe32_ctrl->snapshot_frame_cnt %
+					vfe32_ctrl->frame_skip_cnt))) {
+				share_ctrl->vfe_capture_count--;
+				/* if last frame to be captured: */
+				if (share_ctrl->vfe_capture_count == 0) {
+					/* stop the bus output: */
+					uint32_t vfe_mode =
+						share_ctrl->operation_mode &
+							~(VFE_OUTPUTS_RDI0|
+							VFE_OUTPUTS_RDI1|
+							VFE_OUTPUTS_RDI2);
+					axi_stop_pix(share_ctrl, vfe_mode,
+						AXI_CMD_CAPTURE);
+					msm_camera_io_w_mb
+					(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+					share_ctrl->vfebase +
+					VFE_CAMIF_COMMAND);
+					vfe32_ctrl->snapshot_frame_cnt = -1;
+					vfe32_ctrl->frame_skip_cnt = 31;
+					vfe32_ctrl->frame_skip_pattern =
+								0xffffffff;
+				} /*if snapshot count is 0*/
+			} /*if frame is not being dropped*/
+			vfe32_ctrl->snapshot_frame_cnt++;
+			/* then do reg_update. */
+			msm_camera_io_w(1,
+				share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+		} /* if snapshot mode. */
 	}
-
-	switch (vfe32_ctrl->share_ctrl->liveshot_state) {
-	case VFE_STATE_START_REQUESTED:
-		CDBG("%s enabling liveshot output\n", __func__);
-		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-
-			vfe32_ctrl->share_ctrl->liveshot_state =
-				VFE_STATE_STARTED;
-		}
-		break;
-	case VFE_STATE_STARTED:
-		vfe32_ctrl->share_ctrl->vfe_capture_count--;
-		if (!vfe32_ctrl->share_ctrl->vfe_capture_count &&
-			(vfe32_ctrl->share_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_PRIMARY)) {
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-		}
-		break;
-	case VFE_STATE_STOP_REQUESTED:
-		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_PRIMARY) {
-			/* Stop requested, stop write masters, and
-			 * trigger REG_UPDATE. Send STOP_LS_ACK in
-			 * next reg update. */
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-
-			vfe32_ctrl->share_ctrl->liveshot_state =
-				VFE_STATE_STOPPED;
-			msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
-				VFE_REG_UPDATE_CMD);
-		}
-		break;
-	case VFE_STATE_STOPPED:
-		CDBG("%s Sending STOP_LS ACK\n", __func__);
-		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-		vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_LS_ACK);
-		vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
-		break;
-	default:
-		break;
-	}
-
-	if ((vfe32_ctrl->share_ctrl->operation_mode &
-			VFE_OUTPUTS_THUMB_AND_MAIN) ||
-		(vfe32_ctrl->share_ctrl->operation_mode &
-			VFE_OUTPUTS_MAIN_AND_THUMB) ||
-		(vfe32_ctrl->share_ctrl->operation_mode &
-			VFE_OUTPUTS_THUMB_AND_JPEG) ||
-		(vfe32_ctrl->share_ctrl->operation_mode &
-			VFE_OUTPUTS_JPEG_AND_THUMB)) {
-		/* in snapshot mode */
-		/* later we need to add check for live snapshot mode. */
-		if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
-			(vfe32_ctrl->snapshot_frame_cnt %
-				vfe32_ctrl->frame_skip_cnt))) {
-			vfe32_ctrl->share_ctrl->vfe_capture_count--;
-			/* if last frame to be captured: */
-			if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
-				/* stop the bus output:write master enable = 0*/
-				if (vfe32_ctrl->share_ctrl->outpath.output_mode
-					& VFE32_OUTPUT_MODE_PRIMARY) {
-					msm_camera_io_w(0,
-						vfe32_ctrl->share_ctrl->vfebase+
-						vfe32_AXI_WM_CFG[vfe32_ctrl->
-						share_ctrl->outpath.out0.ch0]);
-					msm_camera_io_w(0,
-						vfe32_ctrl->share_ctrl->vfebase+
-						vfe32_AXI_WM_CFG[vfe32_ctrl->
-						share_ctrl->outpath.out0.ch1]);
-				}
-				if (vfe32_ctrl->share_ctrl->outpath.output_mode&
-						VFE32_OUTPUT_MODE_SECONDARY) {
-					msm_camera_io_w(0,
-						vfe32_ctrl->share_ctrl->vfebase+
-						vfe32_AXI_WM_CFG[vfe32_ctrl->
-						share_ctrl->outpath.out1.ch0]);
-					msm_camera_io_w(0,
-						vfe32_ctrl->share_ctrl->vfebase+
-						vfe32_AXI_WM_CFG[vfe32_ctrl->
-						share_ctrl->outpath.out1.ch1]);
-				}
-				msm_camera_io_w_mb
-				(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
-				vfe32_ctrl->share_ctrl->vfebase +
-				VFE_CAMIF_COMMAND);
-				vfe32_ctrl->snapshot_frame_cnt = -1;
-				vfe32_ctrl->frame_skip_cnt = 31;
-				vfe32_ctrl->frame_skip_pattern = 0xffffffff;
-			} /*if snapshot count is 0*/
-		} /*if frame is not being dropped*/
-		vfe32_ctrl->snapshot_frame_cnt++;
-		/* then do reg_update. */
-		msm_camera_io_w(1,
-			vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	} /* if snapshot mode. */
 }
 
 static void vfe32_process_rdi0_reg_update_irq(
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	if (atomic_cmpxchg(
-		&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0)) {
+		&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0) == 1) {
+		vfe32_ctrl->share_ctrl->comp_output_mode |=
+			VFE32_OUTPUT_MODE_TERTIARY1;
 		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId,
+			vfe32_ctrl->share_ctrl->rdi0FrameId,
 			MSG_ID_RDI0_UPDATE_ACK);
 	}
+
+	if ((atomic_read(
+		&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending) == 2)
+		|| (vfe32_ctrl->share_ctrl->rdi0_capture_count == 0)) {
+		axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY1);
+		axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI0);
+		atomic_set(&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->rdi0FrameId,
+			MSG_ID_RDI0_UPDATE_ACK);
+
+		if (vfe32_ctrl->share_ctrl->rdi0_capture_count == 0)
+			vfe32_ctrl->share_ctrl->rdi0_capture_count = -1;
+		if (vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt
+			== 0)
+			vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+		vfe32_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY1;
+		vfe32_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI0);
+	}
+
+	if (vfe32_ctrl->share_ctrl->rdi0_capture_count > 0) {
+		vfe32_ctrl->share_ctrl->rdi0_capture_count--;
+		if (!vfe32_ctrl->share_ctrl->rdi0_capture_count)
+			axi_stop_rdi0(vfe32_ctrl->share_ctrl);
+	}
 }
 
 static void vfe32_process_rdi1_reg_update_irq(
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
+
 	if (atomic_cmpxchg(
-		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0)) {
+		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0)
+				== 1) {
+		vfe32_ctrl->share_ctrl->comp_output_mode |=
+			VFE32_OUTPUT_MODE_TERTIARY2;
 		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId,
+			vfe32_ctrl->share_ctrl->rdi1FrameId,
 			MSG_ID_RDI1_UPDATE_ACK);
 	}
+
+	if ((atomic_read(
+		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending) == 2)
+		|| (vfe32_ctrl->share_ctrl->rdi1_capture_count == 0)) {
+		axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY2);
+		axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI1);
+		atomic_set(&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->rdi1FrameId,
+			MSG_ID_RDI1_UPDATE_ACK);
+
+		if (vfe32_ctrl->share_ctrl->rdi1_capture_count == 0)
+			vfe32_ctrl->share_ctrl->rdi1_capture_count = -1;
+		if (vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt
+			== 0)
+			vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+		vfe32_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY2;
+		vfe32_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI1);
+	}
+
+	if (vfe32_ctrl->share_ctrl->rdi1_capture_count > 0) {
+		vfe32_ctrl->share_ctrl->rdi1_capture_count--;
+		if (!vfe32_ctrl->share_ctrl->rdi1_capture_count)
+			axi_stop_rdi1(vfe32_ctrl->share_ctrl);
+	}
 }
 
-static void vfe32_set_default_reg_values(
+static void vfe32_process_rdi2_reg_update_irq(
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	msm_camera_io_w(0x800080,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
-	msm_camera_io_w(0x800080,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
-	/* What value should we program CGC_OVERRIDE to? */
-	msm_camera_io_w(0xFFFFF,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
-
-	/* default frame drop period and pattern */
-	msm_camera_io_w(0x1f,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
-	msm_camera_io_w(0x1f,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
-	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
-	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->share_ctrl->vfebase +
-		VFE_FRAMEDROP_ENC_CBCR_PATTERN);
-	msm_camera_io_w(0x1f,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
-	msm_camera_io_w(0x1f,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
-	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
-	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->share_ctrl->vfebase +
-		VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
-	msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MIN);
-	msm_camera_io_w(0xFFFFFF,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MAX);
-
-	/* stats UB config */
-	CDBG("%s: Use bayer stats = %d\n", __func__,
-		 vfe32_use_bayer_stats(vfe32_ctrl));
-	if (!vfe32_use_bayer_stats(vfe32_ctrl)) {
-		msm_camera_io_w(0x3980007,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_AEC_BG_UB_CFG);
-		msm_camera_io_w(0x3A00007,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_AF_BF_UB_CFG);
-		msm_camera_io_w(0x3A8000F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_AWB_UB_CFG);
-		msm_camera_io_w(0x3B80007,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_RS_UB_CFG);
-		msm_camera_io_w(0x3C0001F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_CS_UB_CFG);
-		msm_camera_io_w(0x3E0001F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_HIST_UB_CFG);
-	} else {
-		msm_camera_io_w(0x350001F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_HIST_UB_CFG);
-		msm_camera_io_w(0x370002F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_AEC_BG_UB_CFG);
-		msm_camera_io_w(0x3A0002F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_AF_BF_UB_CFG);
-		msm_camera_io_w(0x3D00007,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_RS_UB_CFG);
-		msm_camera_io_w(0x3D8001F,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_CS_UB_CFG);
-		msm_camera_io_w(0x3F80007,
-			vfe32_ctrl->share_ctrl->vfebase +
-				VFE_BUS_STATS_SKIN_BHIST_UB_CFG);
+	pr_err("%s: RDI2\n", __func__);
+	if (atomic_cmpxchg(
+		&vfe32_ctrl->share_ctrl->rdi2_update_ack_pending, 1, 0)
+				== 1) {
+		vfe32_ctrl->share_ctrl->comp_output_mode |=
+			VFE32_OUTPUT_MODE_TERTIARY3;
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->rdi2FrameId,
+			MSG_ID_RDI2_UPDATE_ACK);
 	}
-	vfe32_reset_dmi_tables(vfe32_ctrl);
+
+	if ((atomic_read(
+		&vfe32_ctrl->share_ctrl->rdi2_update_ack_pending) == 2)
+		|| (vfe32_ctrl->share_ctrl->rdi2_capture_count == 0)) {
+		axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY3);
+		axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI2);
+		atomic_set(&vfe32_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->rdi2FrameId,
+			MSG_ID_RDI2_UPDATE_ACK);
+
+		if (vfe32_ctrl->share_ctrl->rdi2_capture_count == 0)
+			vfe32_ctrl->share_ctrl->rdi2_capture_count = -1;
+		if (vfe32_ctrl->share_ctrl->outpath.out4.capture_cnt
+			== 0)
+			vfe32_ctrl->share_ctrl->outpath.out4.capture_cnt = -1;
+		vfe32_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY3;
+		vfe32_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI2);
+	}
+
+	if (vfe32_ctrl->share_ctrl->rdi2_capture_count > 0) {
+		vfe32_ctrl->share_ctrl->rdi2_capture_count--;
+		if (!vfe32_ctrl->share_ctrl->rdi2_capture_count)
+			axi_stop_rdi2(vfe32_ctrl->share_ctrl);
+	}
 }
 
 static void vfe32_process_reset_irq(
@@ -3344,23 +4006,33 @@
 	unsigned long flags;
 
 	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->handle_common_irq, 0);
 
 	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
 	if (vfe32_ctrl->share_ctrl->stop_ack_pending) {
 		vfe32_ctrl->share_ctrl->stop_ack_pending = FALSE;
 		spin_unlock_irqrestore(
 			&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
-		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_ACK);
+		if (vfe32_ctrl->share_ctrl->sync_abort)
+			complete(&vfe32_ctrl->share_ctrl->reset_complete);
+		else
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				vfe32_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_STOP_ACK);
 	} else {
 		spin_unlock_irqrestore(
 			&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
 		/* this is from reset command. */
-		vfe32_set_default_reg_values(vfe32_ctrl);
-
-		/* reload all write masters. (frame & line)*/
-		msm_camera_io_w(0x7FFF,
-			vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		vfe32_reset_internal_variables(vfe32_ctrl);
+		if (vfe32_ctrl->share_ctrl->vfe_reset_flag) {
+			vfe32_ctrl->share_ctrl->vfe_reset_flag = false;
+			msm_camera_io_w(0x7F80,
+				vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		} else {
+			/* reload all write masters. (frame & line)*/
+			msm_camera_io_w(0x7FFF,
+				vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		}
 		complete(&vfe32_ctrl->share_ctrl->reset_complete);
 	}
 }
@@ -3368,14 +4040,21 @@
 static void vfe32_process_camif_sof_irq(
 		struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	if (vfe32_ctrl->share_ctrl->operation_mode &
+	if (vfe32_ctrl->share_ctrl->operation_mode ==
 		VFE_OUTPUTS_RAW) {
-		if (vfe32_ctrl->share_ctrl->start_ack_pending) {
+		if (atomic_cmpxchg(
+			&vfe32_ctrl->share_ctrl->pix0_update_ack_pending,
+					1, 0) == 1) {
+			vfe32_ctrl->share_ctrl->comp_output_mode |=
+				(vfe32_ctrl->share_ctrl->outpath.output_mode
+				& ~(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2|
+				VFE32_OUTPUT_MODE_TERTIARY3));
 			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
 				vfe32_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_START_ACK);
-			vfe32_ctrl->share_ctrl->start_ack_pending = FALSE;
+				MSG_ID_PIX0_UPDATE_ACK);
 		}
+
 		vfe32_ctrl->share_ctrl->vfe_capture_count--;
 		/* if last frame to be captured: */
 		if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
@@ -3415,6 +4094,12 @@
 	struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
 {
 	uint32_t reg_value;
+	if (errStatus & VFE32_IMASK_VIOLATION) {
+		pr_err("vfe32_irq: violation interrupt\n");
+		reg_value = msm_camera_io_r(
+			axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
+		pr_err("%s: violationStatus  = 0x%x\n", __func__, reg_value);
+	}
 
 	if (errStatus & VFE32_IMASK_CAMIF_ERROR) {
 		pr_err("vfe32_irq: camif errors\n");
@@ -3445,12 +4130,31 @@
 	if (errStatus & VFE32_IMASK_REALIGN_BUF_CR_OVFL)
 		pr_err("vfe32_irq: realign bug CR overflow\n");
 
-	if (errStatus & VFE32_IMASK_VIOLATION) {
-		pr_err("vfe32_irq: violation interrupt\n");
-		reg_value = msm_camera_io_r(
-			axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
-		pr_err("%s: violationStatus  = 0x%x\n", __func__, reg_value);
-	}
+	if (errStatus & VFE32_IMASK_STATS_AE_BG_BUS_OVFL)
+		pr_err("vfe32_irq: ae/bg stats bus overflow\n");
+
+	if (errStatus & VFE32_IMASK_STATS_AF_BF_BUS_OVFL)
+		pr_err("vfe32_irq: af/bf stats bus overflow\n");
+
+	if (errStatus & VFE32_IMASK_STATS_AWB_BUS_OVFL)
+		pr_err("vfe32_irq: awb stats bus overflow\n");
+
+	if (errStatus & VFE32_IMASK_STATS_RS_BUS_OVFL)
+		pr_err("vfe32_irq: rs stats bus overflow\n");
+
+	if (errStatus & VFE32_IMASK_STATS_CS_BUS_OVFL)
+		pr_err("vfe32_irq: cs stats bus overflow\n");
+
+	if (errStatus & VFE32_IMASK_STATS_IHIST_BUS_OVFL)
+		pr_err("vfe32_irq: ihist stats bus overflow\n");
+
+	if (errStatus & VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
+		pr_err("vfe32_irq: skin/bhist stats bus overflow\n");
+}
+
+static void vfe32_process_common_error_irq(
+	struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
+{
 
 	if (errStatus & VFE32_IMASK_IMG_MAST_0_BUS_OVFL)
 		pr_err("vfe32_irq: image master 0 bus overflow\n");
@@ -3473,31 +4177,11 @@
 	if (errStatus & VFE32_IMASK_IMG_MAST_6_BUS_OVFL)
 		pr_err("vfe32_irq: image master 6 bus overflow\n");
 
-	if (errStatus & VFE32_IMASK_STATS_AE_BG_BUS_OVFL)
-		pr_err("vfe32_irq: ae/bg stats bus overflow\n");
-
-	if (errStatus & VFE32_IMASK_STATS_AF_BF_BUS_OVFL)
-		pr_err("vfe32_irq: af/bf stats bus overflow\n");
-
-	if (errStatus & VFE32_IMASK_STATS_AWB_BUS_OVFL)
-		pr_err("vfe32_irq: awb stats bus overflow\n");
-
-	if (errStatus & VFE32_IMASK_STATS_RS_BUS_OVFL)
-		pr_err("vfe32_irq: rs stats bus overflow\n");
-
-	if (errStatus & VFE32_IMASK_STATS_CS_BUS_OVFL)
-		pr_err("vfe32_irq: cs stats bus overflow\n");
-
-	if (errStatus & VFE32_IMASK_STATS_IHIST_BUS_OVFL)
-		pr_err("vfe32_irq: ihist stats bus overflow\n");
-
-	if (errStatus & VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
-		pr_err("vfe32_irq: skin/bhist stats bus overflow\n");
-
 	if (errStatus & VFE32_IMASK_AXI_ERROR)
 		pr_err("vfe32_irq: axi error\n");
 }
 
+
 static void vfe_send_outmsg(
 	struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
 	uint32_t ch0_paddr, uint32_t ch1_paddr,
@@ -3510,7 +4194,20 @@
 	msg.buf.ch_paddr[0]	= ch0_paddr;
 	msg.buf.ch_paddr[1]	= ch1_paddr;
 	msg.buf.ch_paddr[2]	= ch2_paddr;
-	msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
+	switch (msgid) {
+	case MSG_ID_OUTPUT_TERTIARY1:
+		msg.frameCounter = axi_ctrl->share_ctrl->rdi0FrameId;
+		break;
+	case MSG_ID_OUTPUT_TERTIARY2:
+		msg.frameCounter = axi_ctrl->share_ctrl->rdi1FrameId;
+		break;
+	case MSG_ID_OUTPUT_TERTIARY3:
+		msg.frameCounter = axi_ctrl->share_ctrl->rdi2FrameId;
+		break;
+	default:
+		msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
+		break;
+	}
 
 	v4l2_subdev_notify(&axi_ctrl->subdev,
 			NOTIFY_VFE_MSG_OUT,
@@ -3525,7 +4222,6 @@
 	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
 	uint8_t out_bool = 0;
 	struct msm_free_buf *free_buf = NULL;
-
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 		VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
 
@@ -3536,15 +4232,15 @@
 	free buffer.
 	*/
 	out_bool = (
-		(axi_ctrl->share_ctrl->operation_mode ==
+		(axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_THUMB_AND_MAIN ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_MAIN_AND_THUMB ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_THUMB_AND_JPEG ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_RAW ||
 		axi_ctrl->share_ctrl->liveshot_state ==
 			VFE_STATE_STARTED ||
@@ -3591,15 +4287,15 @@
 					axi_ctrl->share_ctrl->outpath.out0.ch2,
 					free_buf->ch_paddr[2]);
 		}
-		if (axi_ctrl->share_ctrl->operation_mode ==
+		if (axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_THUMB_AND_JPEG ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_JPEG_AND_THUMB ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_RAW ||
 			axi_ctrl->share_ctrl->liveshot_state ==
 				VFE_STATE_STOPPED)
@@ -3627,13 +4323,13 @@
 
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 		VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
-	out_bool = ((axi_ctrl->share_ctrl->operation_mode ==
+	out_bool = ((axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_RAW ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_JPEG_AND_THUMB) &&
 			(axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
 				free_buf;
@@ -3673,13 +4369,13 @@
 					axi_ctrl->share_ctrl->outpath.out1.ch2,
 					free_buf->ch_paddr[2]);
 		}
-		if (axi_ctrl->share_ctrl->operation_mode ==
+		if (axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_RAW ||
-			axi_ctrl->share_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode &
 				VFE_OUTPUTS_JPEG_AND_THUMB)
 			axi_ctrl->share_ctrl->outpath.out1.capture_cnt--;
 
@@ -3694,6 +4390,7 @@
 	}
 }
 
+#if 0 /* Disabled for SOC sensor with Y on RDI0 & CB on RDI1 */
 static void vfe32_process_output_path_irq_rdi0(
 			struct axi_ctrl_t *axi_ctrl)
 {
@@ -3702,10 +4399,12 @@
 	/* this must be rdi image output. */
 	struct msm_free_buf *free_buf = NULL;
 	/*RDI0*/
+	CDBG("rdi0 out irq\n");
 	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
 		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 			VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
-		if (free_buf) {
+		if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt > 0 ||
+							free_buf) {
 			ping_pong = msm_camera_io_r(axi_ctrl->
 				share_ctrl->vfebase +
 				VFE_BUS_PING_PONG_STATUS);
@@ -3718,11 +4417,14 @@
 			pr_debug("%s ch0 = 0x%x\n",
 				__func__, ch0_paddr);
 
-			/* Y channel */
-			vfe32_put_ch_addr(ping_pong,
-				axi_ctrl->share_ctrl->vfebase,
-				axi_ctrl->share_ctrl->outpath.out2.ch0,
-				free_buf->ch_paddr[0]);
+			if (free_buf)
+				vfe32_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out2.ch0,
+					free_buf->ch_paddr[0]);
+			if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 1)
+				axi_ctrl->share_ctrl->
+					outpath.out2.capture_cnt = 0;
 
 			vfe_send_outmsg(axi_ctrl,
 				MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
@@ -3747,7 +4449,8 @@
 	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
 		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 			VFE_MSG_OUTPUT_TERTIARY2, axi_ctrl);
-		if (free_buf) {
+		if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt > 0 ||
+							free_buf) {
 			ping_pong = msm_camera_io_r(axi_ctrl->
 				share_ctrl->vfebase +
 				VFE_BUS_PING_PONG_STATUS);
@@ -3759,11 +4462,15 @@
 			pr_debug("%s ch0 = 0x%x\n",
 				__func__, ch0_paddr);
 
-			/* Y channel */
-			vfe32_put_ch_addr(ping_pong,
-				axi_ctrl->share_ctrl->vfebase,
-				axi_ctrl->share_ctrl->outpath.out3.ch0,
-				free_buf->ch_paddr[0]);
+			if (free_buf)
+				vfe32_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out3.ch0,
+					free_buf->ch_paddr[0]);
+			if (axi_ctrl->share_ctrl->
+					outpath.out3.capture_cnt == 1)
+				axi_ctrl->share_ctrl->
+				outpath.out3.capture_cnt = 0;
 
 			vfe_send_outmsg(axi_ctrl,
 				MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
@@ -3775,6 +4482,113 @@
 		}
 	}
 }
+#endif
+
+static void vfe32_process_output_path_irq_rdi2(
+	struct axi_ctrl_t *axi_ctrl)
+{
+	uint32_t ping_pong;
+	uint32_t ch0_paddr = 0;
+	/* this must be rdi image output. */
+	struct msm_free_buf *free_buf = NULL;
+	/*RDI2*/
+	CDBG("rdi2 out irq\n");
+	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI2) {
+		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+			VFE_MSG_OUTPUT_TERTIARY3, axi_ctrl);
+		if (free_buf) {
+			ping_pong = msm_camera_io_r(axi_ctrl->
+				share_ctrl->vfebase +
+				VFE_BUS_PING_PONG_STATUS);
+
+			/* Y channel */
+			ch0_paddr = vfe32_get_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out4.ch0);
+			CDBG("%s ch0 = 0x%x\n",
+				__func__, free_buf->ch_paddr[0]);
+
+			/* Y channel */
+			vfe32_put_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out4.ch0,
+				free_buf->ch_paddr[0]);
+
+			vfe_send_outmsg(axi_ctrl,
+				MSG_ID_OUTPUT_TERTIARY3, ch0_paddr,
+				0, 0,
+				axi_ctrl->share_ctrl->outpath.out4.inst_handle);
+		} else {
+			axi_ctrl->share_ctrl->outpath.out4.frame_drop_cnt++;
+			pr_err("path_irq irq - no free buffer for rdi2!\n");
+		}
+	}
+}
+static void vfe32_process_output_path_irq_rdi0_and_rdi1(
+	struct axi_ctrl_t *axi_ctrl)
+{
+	uint32_t ping_pong;
+	uint32_t ch0_paddr = 0;
+	uint32_t ch1_paddr = 0;
+	struct msm_free_buf *free_buf = NULL;
+
+	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
+		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+			VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
+		if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt > 0 ||
+							free_buf) {
+			ping_pong = msm_camera_io_r(axi_ctrl->
+				share_ctrl->vfebase +
+				VFE_BUS_PING_PONG_STATUS);
+
+			/* Y only channel */
+			ch0_paddr = vfe32_get_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out2.ch0);
+
+			ch1_paddr = vfe32_get_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out3.ch0);
+
+			CDBG("%s ch0 = 0x%x, ch1 0x%x\n", __func__, ch0_paddr,
+				ch1_paddr);
+
+			if (free_buf) {
+				CDBG("%s buffer address ch0 = 0x%x, ch1 0x%x\n",
+					__func__,
+					free_buf->ch_paddr[0],
+					free_buf->ch_paddr[1]);
+
+				vfe32_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out2.ch0,
+					free_buf->ch_paddr[0]);
+
+				vfe32_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out3.ch0,
+					free_buf->ch_paddr[1]);
+				}
+			if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 1)
+				axi_ctrl->share_ctrl
+				->outpath.out2.capture_cnt = 0;
+
+			if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt == 1)
+				axi_ctrl->share_ctrl
+				->outpath.out3.capture_cnt = 0;
+
+			vfe_send_outmsg(axi_ctrl,
+				MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
+				0, 0,
+				axi_ctrl->share_ctrl->outpath.out2.inst_handle);
+
+		} else {
+			axi_ctrl->share_ctrl->outpath.out2.frame_drop_cnt++;
+			pr_err("path_irq_2 irq - no free buffer for rdi0!\n");
+		}
+	}
+
+}
 
 static uint32_t  vfe32_process_stats_irq_common(
 	struct vfe32_ctrl_type *vfe32_ctrl,
@@ -4260,6 +5074,10 @@
 		CDBG("irq	rdi1 regUpdateIrq\n");
 		vfe32_process_rdi1_reg_update_irq(vfe32_ctrl);
 		break;
+	case VFE_IRQ_STATUS1_RDI2_REG_UPDATE:
+		pr_err("irq	rdi2 regUpdateIrq\n");
+		vfe32_process_rdi2_reg_update_irq(vfe32_ctrl);
+		break;
 	case VFE_IMASK_WHILE_STOPPING_1:
 		CDBG("irq	resetAckIrq\n");
 		vfe32_process_reset_irq(vfe32_ctrl);
@@ -4388,24 +5206,40 @@
 				(void *)VFE_IRQ_STATUS1_RDI1_REG_UPDATE);
 
 		if (qcmd->vfeInterruptStatus1 &
+				VFE_IRQ_STATUS1_RDI2_REG_UPDATE_MASK)
+			v4l2_subdev_notify(&vfe32_ctrl->subdev,
+				NOTIFY_VFE_IRQ,
+				(void *)VFE_IRQ_STATUS1_RDI2_REG_UPDATE);
+
+		if (qcmd->vfeInterruptStatus1 &
 				VFE_IMASK_WHILE_STOPPING_1)
 			v4l2_subdev_notify(&vfe32_ctrl->subdev,
 				NOTIFY_VFE_IRQ,
 				(void *)VFE_IMASK_WHILE_STOPPING_1);
 
-		if (atomic_read(&axi_ctrl->share_ctrl->handle_axi_irq))
+		if (atomic_read(&axi_ctrl->share_ctrl->handle_common_irq)) {
+			if (qcmd->vfeInterruptStatus1 &
+					VFE32_IMASK_COMMON_ERROR_ONLY_1) {
+				pr_err("irq	errorIrq\n");
+				vfe32_process_common_error_irq(
+					axi_ctrl,
+					qcmd->vfeInterruptStatus1 &
+					VFE32_IMASK_COMMON_ERROR_ONLY_1);
+			}
+
 			v4l2_subdev_notify(&axi_ctrl->subdev,
 				NOTIFY_AXI_IRQ,
 				(void *)qcmd->vfeInterruptStatus0);
+		}
 
 		if (atomic_read(&axi_ctrl->share_ctrl->vstate)) {
 			if (qcmd->vfeInterruptStatus1 &
-					VFE32_IMASK_ERROR_ONLY_1) {
+					VFE32_IMASK_VFE_ERROR_ONLY_1) {
 				pr_err("irq	errorIrq\n");
 				vfe32_process_error_irq(
 					axi_ctrl,
 					qcmd->vfeInterruptStatus1 &
-					VFE32_IMASK_ERROR_ONLY_1);
+					VFE32_IMASK_VFE_ERROR_ONLY_1);
 			}
 
 			/* then process stats irq. */
@@ -4494,7 +5328,8 @@
 	struct axi_ctrl_t *axi_ctrl = data;
 
 	CDBG("vfe_parse_irq\n");
-
+	if (!axi_ctrl->share_ctrl->vfebase)
+		return IRQ_HANDLED;
 	vfe32_read_irq_status(axi_ctrl, &irq);
 
 	if ((irq.vfeIrqStatus0 == 0) && (irq.vfeIrqStatus1 == 0)) {
@@ -4544,7 +5379,7 @@
 
 static long vfe_stats_bufq_sub_ioctl(
 	struct vfe32_ctrl_type *vfe_ctrl,
-	struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+	struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
 {
 	long rc = 0;
 	switch (cmd->cmd_type) {
@@ -4593,7 +5428,7 @@
 	rc = vfe_ctrl->stats_ops.enqueue_buf(
 			&vfe_ctrl->stats_ctrl,
 			(struct msm_stats_buf_info *)cmd->value,
-			vfe_ctrl->stats_ops.client);
+			vfe_ctrl->stats_ops.client, domain_num);
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 	{
@@ -4627,7 +5462,7 @@
 			rc = -EINVAL ;
 			goto end;
 		}
-		rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf);
+		rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf, domain_num);
 	}
 	break;
 	default:
@@ -4653,6 +5488,8 @@
 	void *data;
 
 	long rc = 0;
+	struct vfe_cmd_stats_buf *scfg = NULL;
+	struct vfe_cmd_stats_ack *sack = NULL;
 
 	if (!vfe32_ctrl->share_ctrl->vfebase) {
 		pr_err("%s: base address unmapped\n", __func__);
@@ -4680,7 +5517,7 @@
 	case VFE_CMD_STATS_UNREGBUF:
 		/* for easy porting put in one envelope */
 		rc = vfe_stats_bufq_sub_ioctl(vfe32_ctrl,
-				cmd, vfe_params->data);
+				cmd, vfe_params->data, pmctl->domain_num);
 		return rc;
 	default:
 		if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -4695,8 +5532,8 @@
 		cmd->cmd_type != CMD_STATS_BG_BUF_RELEASE &&
 		cmd->cmd_type != CMD_STATS_BF_BUF_RELEASE &&
 		cmd->cmd_type != CMD_STATS_BHIST_BUF_RELEASE &&
-		cmd->cmd_type != CMD_VFE_SOF_COUNT_UPDATE &&
-		cmd->cmd_type != CMD_VFE_COUNT_SOF_ENABLE) {
+		cmd->cmd_type != CMD_VFE_PIX_SOF_COUNT_UPDATE &&
+		cmd->cmd_type != CMD_VFE_COUNT_PIX_SOF_ENABLE) {
 			if (copy_from_user(&vfecmd,
 					(void __user *)(cmd->value),
 					sizeof(vfecmd))) {
@@ -4715,6 +5552,14 @@
 						__func__, cmd->cmd_type);
 					return -EFAULT;
 				}
+				sack = kmalloc(sizeof(struct vfe_cmd_stats_ack),
+							GFP_ATOMIC);
+				if (!sack) {
+					pr_err("%s: no mem for cmd->cmd_type = %d",
+					 __func__, cmd->cmd_type);
+					return -ENOMEM;
+				}
+				sack->nextStatsBuf = *(uint32_t *)data;
 			}
 		}
 	}
@@ -4744,6 +5589,7 @@
 			(cmd->cmd_type == CMD_STATS_RS_ENABLE)    ||
 			(cmd->cmd_type == CMD_STATS_CS_ENABLE)    ||
 			(cmd->cmd_type == CMD_STATS_AEC_ENABLE)) {
+				scfg = NULL;
 				/* individual */
 				goto vfe32_config_done;
 		}
@@ -4767,7 +5613,7 @@
 	case CMD_GENERAL:
 		rc = vfe32_proc_general(pmctl, &vfecmd, vfe32_ctrl);
 	break;
-	case CMD_VFE_COUNT_SOF_ENABLE: {
+	case CMD_VFE_COUNT_PIX_SOF_ENABLE: {
 		int enable = *((int *)cmd->value);
 		if (enable)
 			vfe32_ctrl->vfe_sof_count_enable = TRUE;
@@ -4775,7 +5621,7 @@
 			vfe32_ctrl->vfe_sof_count_enable = false;
 	}
 	break;
-	case CMD_VFE_SOF_COUNT_UPDATE:
+	case CMD_VFE_PIX_SOF_COUNT_UPDATE:
 		if (!vfe32_ctrl->vfe_sof_count_enable)
 			vfe32_ctrl->share_ctrl->vfeFrameId =
 			*((uint32_t *)vfe_params->data);
@@ -4813,6 +5659,8 @@
 	break;
 	}
 vfe32_config_done:
+	kfree(scfg);
+	kfree(sack);
 	CDBG("%s done: rc = %d\n", __func__, (int) rc);
 	return rc;
 }
@@ -4829,7 +5677,10 @@
 	int rc = 0;
 	int round_rate;
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
-
+	if(axi_ctrl->share_ctrl->dual_enabled){
+		CDBG("%s Dual camera Enabled hence returning without clock change\n", __func__);
+		return rc;
+	}
 	round_rate = clk_round_rate(axi_ctrl->vfe_clk[0], freq);
 	if (rc < 0) {
 		pr_err("%s: clk_round_rate failed %d\n",
@@ -4854,17 +5705,22 @@
 	.core = &msm_vfe_subdev_core_ops,
 };
 
-int msm_axi_subdev_init(struct v4l2_subdev *sd)
+int msm_axi_subdev_init(struct v4l2_subdev *sd,
+	uint8_t dual_enabled)
 {
 	int rc = 0;
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
-	struct msm_cam_media_controller *mctl;
-	mctl = v4l2_get_subdev_hostdata(sd);
+	struct msm_cam_media_controller *mctl =
+		v4l2_get_subdev_hostdata(sd);
 	if (mctl == NULL) {
-		pr_err("%s: mctl is NULL\n", __func__);
 		rc = -EINVAL;
 		goto mctl_failed;
 	}
+
+	axi_ctrl->share_ctrl->axi_ref_cnt++;
+	if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
+		return rc;
+	axi_ctrl->share_ctrl->dual_enabled = dual_enabled;
 	spin_lock_init(&axi_ctrl->tasklet_lock);
 	INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
 	spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
@@ -4890,10 +5746,34 @@
 	if (rc < 0)
 		goto clk_enable_failed;
 
+#ifdef CONFIG_MSM_IOMMU
+	rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+	if (rc < 0) {
+		pr_err("%s: imgwr attach failed rc = %d\n", __func__, rc);
+		rc = -ENODEV;
+		goto device_imgwr_attach_failed;
+	}
+	rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_misc);
+	if (rc < 0) {
+		pr_err("%s: misc attach failed rc = %d\n", __func__, rc);
+		rc = -ENODEV;
+		goto device_misc_attach_failed;
+	}
+#endif
+
 	msm_camio_bus_scale_cfg(
 		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
-	msm_camio_bus_scale_cfg(
-		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+
+	CDBG("%s: axi_ctrl->share_ctrl->dual_enabled ? = %d\n", __func__,
+			axi_ctrl->share_ctrl->dual_enabled);
+	if (axi_ctrl->share_ctrl->dual_enabled){
+		pr_info("%s: Scaling bus config for dual bus vectors\n", __func__);
+		msm_camio_bus_scale_cfg(
+			mctl->sdata->pdata->cam_bus_scale_table, S_DUAL);
+	}
+	else
+		msm_camio_bus_scale_cfg(
+			mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 
 	if (msm_camera_io_r(
 		axi_ctrl->share_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
@@ -4902,9 +5782,21 @@
 	else
 		axi_ctrl->share_ctrl->register_total = VFE33_REGISTER_TOTAL;
 
+	spin_lock_init(&axi_ctrl->share_ctrl->stop_flag_lock);
+	spin_lock_init(&axi_ctrl->share_ctrl->update_ack_lock);
+	spin_lock_init(&axi_ctrl->share_ctrl->start_ack_lock);
+
 	enable_irq(axi_ctrl->vfeirq->start);
 
 	return rc;
+
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+	iommu_detach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
+			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
 clk_enable_failed:
 	if (axi_ctrl->fs_vfe)
 		regulator_disable(axi_ctrl->fs_vfe);
@@ -4912,7 +5804,6 @@
 	iounmap(axi_ctrl->share_ctrl->vfebase);
 	axi_ctrl->share_ctrl->vfebase = NULL;
 remap_failed:
-	disable_irq(axi_ctrl->vfeirq->start);
 mctl_failed:
 	return rc;
 }
@@ -4923,11 +5814,7 @@
 	struct vfe32_ctrl_type *vfe32_ctrl =
 		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
 
-	spin_lock_init(&vfe32_ctrl->share_ctrl->stop_flag_lock);
-	spin_lock_init(&vfe32_ctrl->share_ctrl->abort_lock);
 	spin_lock_init(&vfe32_ctrl->state_lock);
-	spin_lock_init(&vfe32_ctrl->share_ctrl->update_ack_lock);
-	spin_lock_init(&vfe32_ctrl->share_ctrl->start_ack_lock);
 	spin_lock_init(&vfe32_ctrl->stats_bufq_lock);
 
 	vfe32_ctrl->update_linear = false;
@@ -4937,7 +5824,8 @@
 	vfe32_ctrl->vfe_sof_count_enable = false;
 	vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
 
-	memset(&vfe32_ctrl->stats_ctrl, 0, sizeof(struct msm_stats_bufq_ctrl));
+	memset(&vfe32_ctrl->stats_ctrl, 0,
+		sizeof(struct msm_stats_bufq_ctrl));
 	memset(&vfe32_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
 
 	return rc;
@@ -4945,17 +5833,25 @@
 
 void msm_axi_subdev_release(struct v4l2_subdev *sd)
 {
-	struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	struct msm_cam_media_controller *pmctl =
+		v4l2_get_subdev_hostdata(sd);
+
 	if (!axi_ctrl->share_ctrl->vfebase) {
 		pr_err("%s: base address unmapped\n", __func__);
 		return;
 	}
 
-	CDBG("%s, free_irq\n", __func__);
+	axi_ctrl->share_ctrl->axi_ref_cnt--;
+	if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
+		return;
+	axi_ctrl->share_ctrl->dual_enabled = 0;
 	disable_irq(axi_ctrl->vfeirq->start);
 	tasklet_kill(&axi_ctrl->vfe32_tasklet);
+#ifdef CONFIG_MSM_IOMMU
+	iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_misc);
+	iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_imgwr);
+#endif
 	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
 			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
 	if (axi_ctrl->fs_vfe)
@@ -4969,20 +5865,26 @@
 
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
+
 }
 
 void msm_vfe_subdev_release(struct v4l2_subdev *sd)
 {
 	struct vfe32_ctrl_type *vfe32_ctrl =
 		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
-	if (!vfe32_ctrl->share_ctrl->vfebase)
-		vfe32_ctrl->share_ctrl->vfebase = NULL;
+	CDBG("vfe subdev release %p\n",
+		vfe32_ctrl->share_ctrl->vfebase);
 }
 
 void axi_abort(struct axi_ctrl_t *axi_ctrl)
 {
 	uint8_t  axi_busy_flag = true;
+	unsigned long flags;
 	/* axi halt command. */
+
+	spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+	axi_ctrl->share_ctrl->stop_ack_pending  = TRUE;
+	spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
 	msm_camera_io_w(AXI_HALT,
 		axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
 	wmb();
@@ -5008,14 +5910,20 @@
 	* to the command register using the barrier */
 	msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
 		axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+	if (axi_ctrl->share_ctrl->sync_abort)
+		wait_for_completion_interruptible(
+			&axi_ctrl->share_ctrl->reset_complete);
 }
 
 int axi_config_buffers(struct axi_ctrl_t *axi_ctrl,
 	struct msm_camera_vfe_params_t vfe_params)
 {
 	uint16_t vfe_mode = axi_ctrl->share_ctrl->current_mode
-			& ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+			& ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1|
+				VFE_OUTPUTS_RDI2);
 	int rc = 0;
+	pr_info("%s: cmd type %d, axi mode %d\n", __func__,
+		vfe_params.cmd_type, axi_ctrl->share_ctrl->current_mode);
 	switch (vfe_params.cmd_type) {
 	case AXI_CMD_PREVIEW:
 		if (vfe_mode) {
@@ -5036,16 +5944,22 @@
 					axi_ctrl);
 		}
 		if (axi_ctrl->share_ctrl->current_mode &
-				VFE_OUTPUTS_RDI0)
+				VFE_OUTPUTS_RDI0){
 			rc = configure_pingpong_buffers(
 				VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY1,
 				axi_ctrl);
+		}
 		if (axi_ctrl->share_ctrl->current_mode &
-				VFE_OUTPUTS_RDI1)
+				VFE_OUTPUTS_RDI1){
 			rc = configure_pingpong_buffers(
 				VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY2,
 				axi_ctrl);
-
+		}
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI2)
+			rc = configure_pingpong_buffers(
+				VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY3,
+				axi_ctrl);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers for preview",
 				__func__);
@@ -5112,39 +6026,58 @@
 		}
 		break;
 	case AXI_CMD_CAPTURE:
-		if (axi_ctrl->share_ctrl->current_mode ==
-			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		axi_ctrl->share_ctrl->current_mode ==
-			VFE_OUTPUTS_THUMB_AND_JPEG) {
+		if (vfe_mode) {
+			if (axi_ctrl->share_ctrl->current_mode ==
+				VFE_OUTPUTS_JPEG_AND_THUMB ||
+			axi_ctrl->share_ctrl->current_mode ==
+				VFE_OUTPUTS_THUMB_AND_JPEG) {
 
-			/* Configure primary channel for JPEG */
+				/* Configure primary channel for JPEG */
+				rc = configure_pingpong_buffers(
+					VFE_MSG_JPEG_CAPTURE,
+					VFE_MSG_OUTPUT_PRIMARY,
+					axi_ctrl);
+			} else {
+				/* Configure primary channel */
+				rc = configure_pingpong_buffers(
+					VFE_MSG_CAPTURE,
+					VFE_MSG_OUTPUT_PRIMARY,
+					axi_ctrl);
+			}
+			if (rc < 0) {
+				pr_err("%s error configuring pingpong buffers for primary output",
+					__func__);
+				rc = -EINVAL;
+				goto config_done;
+			}
+			/* Configure secondary channel */
 			rc = configure_pingpong_buffers(
-				VFE_MSG_JPEG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY,
-				axi_ctrl);
-		} else {
-			/* Configure primary channel */
+					VFE_MSG_CAPTURE,
+					VFE_MSG_OUTPUT_SECONDARY,
+					axi_ctrl);
+			if (rc < 0) {
+				pr_err("%s error configuring pingpong buffers for secondary output",
+					__func__);
+				rc = -EINVAL;
+				goto config_done;
+			}
+		}
+
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI0)
 			rc = configure_pingpong_buffers(
-				VFE_MSG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY,
+				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY1,
 				axi_ctrl);
-		}
-		if (rc < 0) {
-			pr_err("%s error configuring pingpong buffers for primary output",
-				__func__);
-			rc = -EINVAL;
-			goto config_done;
-		}
-		/* Configure secondary channel */
-		rc = configure_pingpong_buffers(
-				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI1)
+			rc = configure_pingpong_buffers(
+				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY2,
 				axi_ctrl);
-		if (rc < 0) {
-			pr_err("%s error configuring pingpong buffers for secondary output",
-				__func__);
-			rc = -EINVAL;
-			goto config_done;
-		}
+		if (axi_ctrl->share_ctrl->current_mode &
+			VFE_OUTPUTS_RDI2)
+			rc = configure_pingpong_buffers(
+				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY3,
+				axi_ctrl);
 		break;
 	default:
 		rc = -EINVAL;
@@ -5158,107 +6091,90 @@
 void axi_start(struct msm_cam_media_controller *pmctl,
 	struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
 {
-	uint32_t irq_comp_mask = 0, irq_mask = 0;
 	int rc = 0;
+	uint32_t reg_update = 0;
+	uint32_t vfe_mode =
+		(axi_ctrl->share_ctrl->current_mode &
+		~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2));
+	CDBG("axi start = %d\n",
+		axi_ctrl->share_ctrl->current_mode);
 	rc = axi_config_buffers(axi_ctrl, vfe_params);
 	if (rc < 0)
 		return;
 
 	switch (vfe_params.cmd_type) {
 	case AXI_CMD_PREVIEW:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 		break;
 	case AXI_CMD_CAPTURE:
 	case AXI_CMD_RAW_CAPTURE:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 		break;
 	case AXI_CMD_RECORD:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 		return;
 	case AXI_CMD_ZSL:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
 		break;
 	case AXI_CMD_LIVESHOT:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_LIVESHOT);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_LIVESHOT);
 		return;
 	default:
 		return;
 	}
-
-	irq_comp_mask =
-		msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_COMP_MASK);
-
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= (
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
-	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
-	}
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_SECONDARY) {
-		irq_comp_mask |= (
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
-	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
-	}
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-		VFE32_OUTPUT_MODE_TERTIARY1) {
-		irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-		irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
-			VFE_WM_OFFSET));
-		msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-	}
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-		VFE32_OUTPUT_MODE_TERTIARY2) {
-		irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-		irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
-			VFE_WM_OFFSET));
-		msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-	}
-
-	msm_camera_io_w(irq_comp_mask,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	axi_enable_wm_irq(axi_ctrl->share_ctrl);
 
 	switch (vfe_params.cmd_type) {
+	case AXI_CMD_RAW_CAPTURE:
+		msm_camera_io_w((
+			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0),
+			axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+			+ vfe32_AXI_WM_CFG[axi_ctrl->
+			share_ctrl->outpath.out0.ch0]);
+		break;
 	case AXI_CMD_PREVIEW: {
-		uint16_t operation_mode =
-		(axi_ctrl->share_ctrl->operation_mode &
-		~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
-
-		switch (operation_mode) {
+		switch (vfe_mode) {
 		case VFE_OUTPUTS_PREVIEW:
 		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
 			if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch1),
+					axi_ctrl->share_ctrl->vfebase +
+							VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out0.ch0]);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out0.ch1]);
+
+
 			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch1 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch2),
+					axi_ctrl->share_ctrl->vfebase +
+							VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out0.ch0]);
@@ -5273,6 +6189,13 @@
 		default:
 			if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_SECONDARY) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+						outpath.out1.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+						outpath.out1.ch1),
+					axi_ctrl->share_ctrl->vfebase +
+						VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out1.ch0]);
@@ -5281,6 +6204,15 @@
 					share_ctrl->outpath.out1.ch1]);
 			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out1.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out1.ch1 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out1.ch2),
+					axi_ctrl->share_ctrl->vfebase +
+							VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out1.ch0]);
@@ -5298,6 +6230,10 @@
 	default:
 		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out0.ch0]);
@@ -5306,6 +6242,11 @@
 				share_ctrl->outpath.out0.ch1]);
 		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out0.ch0]);
@@ -5319,6 +6260,10 @@
 
 		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch1),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out1.ch0]);
@@ -5327,6 +6272,11 @@
 				share_ctrl->outpath.out1.ch1]);
 		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch1 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch2),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out1.ch0]);
@@ -5339,168 +6289,149 @@
 		}
 		break;
 	}
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		axi_ctrl->share_ctrl->outpath.out2.capture_cnt =
+						vfe_params.capture_count;
+		axi_ctrl->share_ctrl->rdi0_capture_count =
+						vfe_params.capture_count;
+		msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out2.ch0),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
 			outpath.out2.ch0]);
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		axi_ctrl->share_ctrl->outpath.out3.capture_cnt =
+						vfe_params.capture_count;
+		axi_ctrl->share_ctrl->rdi1_capture_count =
+						vfe_params.capture_count;
+		msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out3.ch0),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
 			outpath.out3.ch0]);
-	atomic_set(&axi_ctrl->share_ctrl->handle_axi_irq, 1);
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI2) {
+		axi_ctrl->share_ctrl->outpath.out4.capture_cnt =
+						vfe_params.capture_count;
+		axi_ctrl->share_ctrl->rdi2_capture_count =
+						vfe_params.capture_count;
+		msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out4.ch0),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		CDBG("AXI WM configured as frame based\n");
+		msm_camera_io_w(0x3, axi_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+			outpath.out4.ch0]);
+	}
+
+	axi_enable_irq(axi_ctrl->share_ctrl);
+
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
+				0, 1))
+			reg_update |= 0x2;
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
+				0, 1))
+			reg_update |= 0x4;
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI2) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi2_update_ack_pending,
+				0, 1))
+			reg_update |= 0x8;
+	}
+
+	if (vfe_mode) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->pix0_update_ack_pending,
+				0, 1))
+			reg_update |= 0x1;
+	}
+
+	msm_camera_io_w_mb(reg_update,
+			axi_ctrl->share_ctrl->vfebase +
+			VFE_REG_UPDATE_CMD);
+	axi_ctrl->share_ctrl->operation_mode |=
+		axi_ctrl->share_ctrl->current_mode;
 }
 
 void axi_stop(struct msm_cam_media_controller *pmctl,
 	struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
 {
 	uint32_t reg_update = 0;
-	unsigned long flags;
-	uint32_t operation_mode =
+	uint32_t vfe_mode =
 	axi_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
-		VFE_OUTPUTS_RDI1);
-
+		VFE_OUTPUTS_RDI1|VFE_OUTPUTS_RDI2);
 	switch (vfe_params.cmd_type) {
 	case AXI_CMD_PREVIEW:
 	case AXI_CMD_CAPTURE:
 	case AXI_CMD_RAW_CAPTURE:
 	case AXI_CMD_ZSL:
+		axi_ctrl->share_ctrl->cmd_type = vfe_params.cmd_type;
 		break;
 	case AXI_CMD_RECORD:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 		return;
 	case AXI_CMD_LIVESHOT:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 		return;
 	default:
 		return;
 	}
 
-	if (!axi_ctrl->share_ctrl->skip_abort) {
-		atomic_set(&axi_ctrl->share_ctrl->handle_axi_irq, 0);
-		axi_disable_irq(axi_ctrl);
+	if (axi_ctrl->share_ctrl->stop_immediately) {
+		axi_disable_irq(axi_ctrl->share_ctrl,
+			axi_ctrl->share_ctrl->current_mode);
+		axi_stop_process(axi_ctrl->share_ctrl);
+		return;
 	}
 
-	spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
-	axi_ctrl->share_ctrl->stop_ack_pending  = TRUE;
-	spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
-	switch (vfe_params.cmd_type) {
-	case AXI_CMD_PREVIEW: {
-		switch (operation_mode) {
-		case VFE_OUTPUTS_PREVIEW:
-		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
-			if (axi_ctrl->share_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_PRIMARY) {
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out0.ch0]);
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out0.ch1]);
-			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out0.ch0]);
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out0.ch1]);
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out0.ch2]);
-			}
-			break;
-		default:
-			if (axi_ctrl->share_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_SECONDARY) {
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out1.ch0]);
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out1.ch1]);
-			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out1.ch0]);
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out1.ch1]);
-				msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
-					+ vfe32_AXI_WM_CFG[axi_ctrl->
-					share_ctrl->outpath.out1.ch2]);
-			}
-			break;
-			}
-		}
-		break;
-	default:
-		if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch2]);
-		}
-
-		if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_SECONDARY) {
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out1.ch1]);
-		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out1.ch1]);
-			msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out1.ch2]);
-		}
-		break;
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+				outpath.out2.ch0]);
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
+				0, 2))
+			reg_update |= 0x2;
 	}
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
 		msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
-			outpath.out2.ch0]);
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+				outpath.out3.ch0]);
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
+				0, 2))
+			reg_update |= 0x4;
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI2) {
 		msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
-			outpath.out3.ch0]);
-
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
-		reg_update |= 0x2;
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
-		reg_update |= 0x4;
-
-	if (operation_mode)
-		reg_update |= 0x1;
+				outpath.out4.ch0]);
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi2_update_ack_pending,
+				0, 2))
+			reg_update |= 0x8;
+	}
+	if (vfe_mode) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->pix0_update_ack_pending,
+				0, 2))
+			reg_update |= 0x1;
+	}
 	msm_camera_io_w_mb(reg_update,
 		axi_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	if (!axi_ctrl->share_ctrl->skip_abort)
-		axi_abort(axi_ctrl);
-
 }
 
 static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
@@ -5511,7 +6442,6 @@
 	struct msm_cam_media_controller *pmctl =
 		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	int rc = 0, vfe_cmd_type = 0, rdi_mode = 0;
-	unsigned long flags;
 
 	if (!axi_ctrl->share_ctrl->vfebase) {
 		pr_err("%s: base address unmapped\n", __func__);
@@ -5536,7 +6466,7 @@
 	}
 
 	vfe_cmd_type = (cfgcmd.cmd_type & ~(CMD_AXI_CFG_TERT1|
-		CMD_AXI_CFG_TERT2));
+		CMD_AXI_CFG_TERT2 | CMD_AXI_CFG_TERT3));
 	switch (cfgcmd.cmd_type) {
 	case CMD_AXI_CFG_TERT1:{
 		uint32_t *axio = NULL;
@@ -5545,7 +6475,6 @@
 		if (!axio) {
 			return -ENOMEM;
 		}
-
 		if (copy_from_user(axio, (void __user *)(vfecmd.value),
 				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
 			kfree(axio);
@@ -5571,6 +6500,22 @@
 		kfree(axio);
 		return rc;
 		}
+	case CMD_AXI_CFG_TERT3:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe32_config_axi(axi_ctrl, OUTPUT_TERT3, axio);
+		kfree(axio);
+		return rc;
+		}
 	case CMD_AXI_CFG_TERT1|CMD_AXI_CFG_TERT2:{
 		uint32_t *axio = NULL;
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
@@ -5587,11 +6532,62 @@
 		kfree(axio);
 		return rc;
 		}
+	case CMD_AXI_CFG_TERT1|CMD_AXI_CFG_TERT3:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe32_config_axi(axi_ctrl, OUTPUT_TERT1|OUTPUT_TERT3, axio);
+		kfree(axio);
+		return rc;
+		}
+	case CMD_AXI_CFG_TERT2|CMD_AXI_CFG_TERT3:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe32_config_axi(axi_ctrl, OUTPUT_TERT2|OUTPUT_TERT3, axio);
+		kfree(axio);
+		return rc;
+		}
+	case CMD_AXI_CFG_TERT1|CMD_AXI_CFG_TERT2|CMD_AXI_CFG_TERT3:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe32_config_axi(axi_ctrl, OUTPUT_TERT1|OUTPUT_TERT2|
+			OUTPUT_TERT3, axio);
+		kfree(axio);
+		return rc;
+		}
 	default:
 		if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT1)
 			rdi_mode |= OUTPUT_TERT1;
 		if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT2)
 			rdi_mode |= OUTPUT_TERT2;
+		if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT3)
+			rdi_mode |= OUTPUT_TERT3;
 	}
 	switch (vfe_cmd_type) {
 	case CMD_AXI_CFG_PRIM: {
@@ -5707,11 +6703,6 @@
 		}
 		axi_ctrl->share_ctrl->current_mode =
 			vfe_params.operation_mode;
-		spin_lock_irqsave(&axi_ctrl->share_ctrl->abort_lock, flags);
-		axi_ctrl->share_ctrl->skip_abort =
-			vfe_params.skip_abort;
-		spin_unlock_irqrestore(&axi_ctrl->share_ctrl->abort_lock,
-			flags);
 		axi_start(pmctl, axi_ctrl, vfe_params);
 		}
 		break;
@@ -5724,16 +6715,28 @@
 		}
 		axi_ctrl->share_ctrl->current_mode =
 			vfe_params.operation_mode;
-		spin_lock_irqsave(&axi_ctrl->share_ctrl->abort_lock, flags);
-		axi_ctrl->share_ctrl->skip_abort =
-			vfe_params.skip_abort;
-		spin_unlock_irqrestore(&axi_ctrl->share_ctrl->abort_lock,
-			flags);
+		axi_ctrl->share_ctrl->stop_immediately =
+			vfe_params.stop_immediately;
 		axi_stop(pmctl, axi_ctrl, vfe_params);
 		}
 		break;
-	case CMD_AXI_RESET:
-		axi_reset(axi_ctrl);
+	case CMD_AXI_RESET: {
+		struct msm_camera_vfe_params_t vfe_params;
+		if (copy_from_user(&vfe_params,
+				(void __user *)(vfecmd.value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				return -EFAULT;
+		}
+		axi_reset(axi_ctrl, vfe_params);
+		}
+		break;
+	case CMD_AXI_ABORT:
+		if (copy_from_user(&axi_ctrl->share_ctrl->sync_abort,
+				(void __user *)(vfecmd.value),
+				sizeof(uint8_t))) {
+				return -EFAULT;
+		}
+		axi_abort(axi_ctrl);
 		break;
 	default:
 		pr_err("%s Unsupported AXI configuration %x ", __func__,
@@ -5747,12 +6750,12 @@
 {
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
 	uint32_t irqstatus = (uint32_t) arg;
-	unsigned long flags;
 
 	if (!axi_ctrl->share_ctrl->vfebase) {
 		pr_err("%s: base address unmapped\n", __func__);
 		return;
 	}
+
 	/* next, check output path related interrupts. */
 	if (irqstatus &
 		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
@@ -5764,54 +6767,102 @@
 		CDBG("Image composite done 1 irq occured.\n");
 		vfe32_process_output_path_irq_1(axi_ctrl);
 	}
+	if (irqstatus &
+		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE2_MASK) {
+		CDBG("\nImage composite done 2 irq occured.\n");
+		vfe32_process_output_path_irq_rdi0_and_rdi1(axi_ctrl);
+	}
 
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-		VFE32_OUTPUT_MODE_TERTIARY1)
+	if (axi_ctrl->share_ctrl->comp_output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY1) {
+		CDBG("VFE32_OUTPUT_MODE_TERTIARY1\n");
+#if 0
 		if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0
 			+ VFE_WM_OFFSET)))
 			vfe32_process_output_path_irq_rdi0(axi_ctrl);
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-		VFE32_OUTPUT_MODE_TERTIARY2)
+#endif
+	}
+	if (axi_ctrl->share_ctrl->comp_output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY2){
+		CDBG("VFE32_OUTPUT_MODE_TERTIARY2\n");
+#if 0
 		if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0
 			+ VFE_WM_OFFSET)))
 			vfe32_process_output_path_irq_rdi1(axi_ctrl);
+#endif
+	}
+	if (axi_ctrl->share_ctrl->comp_output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY3){
+		pr_err("Before process output path" \
+			"of RDI2 irqstatus %x\n", irqstatus);
+		if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out4.ch0
+			+ VFE_WM_OFFSET)))
+			vfe32_process_output_path_irq_rdi2(axi_ctrl);
+	}
 
 	/* in snapshot mode if done then send
 	snapshot done message */
 	if (
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_THUMB_AND_MAIN ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_MAIN_AND_THUMB ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_THUMB_AND_JPEG ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		axi_ctrl->share_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode &
 			VFE_OUTPUTS_RAW) {
 		if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
 				&& (axi_ctrl->share_ctrl->outpath.out1.
 				capture_cnt == 0)) {
-			msm_camera_io_w_mb(
-				CAMIF_COMMAND_STOP_IMMEDIATELY,
-				axi_ctrl->share_ctrl->vfebase +
-				VFE_CAMIF_COMMAND);
-			spin_lock_irqsave(&axi_ctrl->share_ctrl->abort_lock,
-				flags);
-			if (axi_ctrl->share_ctrl->skip_abort) {
-				spin_unlock_irqrestore(&axi_ctrl->share_ctrl->
-					abort_lock, flags);
-				atomic_set(&axi_ctrl->share_ctrl->
-					handle_axi_irq, 0);
-				axi_disable_irq(axi_ctrl);
-			} else
-				spin_unlock_irqrestore(&axi_ctrl->share_ctrl->
-					abort_lock, flags);
+			uint32_t mode =
+				(axi_ctrl->share_ctrl->operation_mode &
+				~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1|
+				  VFE_OUTPUTS_RDI2));
+			uint16_t output_mode =
+			axi_ctrl->share_ctrl->comp_output_mode &
+				~(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2|
+				  VFE32_OUTPUT_MODE_TERTIARY3);
+			if (!axi_ctrl->share_ctrl->dual_enabled)
+				msm_camera_io_w_mb(
+					CAMIF_COMMAND_STOP_IMMEDIATELY,
+					axi_ctrl->share_ctrl->vfebase +
+					VFE_CAMIF_COMMAND);
+			axi_disable_wm_irq(axi_ctrl->share_ctrl, output_mode);
+			axi_disable_irq(axi_ctrl->share_ctrl, mode);
 			vfe32_send_isp_msg(&axi_ctrl->subdev,
 				axi_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_SNAPSHOT_DONE);
+				MSG_ID_PIX0_UPDATE_ACK);
+			axi_ctrl->share_ctrl->outpath.out0.
+				capture_cnt = -1;
+			axi_ctrl->share_ctrl->outpath.out1.
+				capture_cnt = -1;
+			axi_ctrl->share_ctrl->comp_output_mode &=
+				(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2|
+				 VFE32_OUTPUT_MODE_TERTIARY3);
 		}
 	}
+
+	if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 0) {
+		axi_ctrl->share_ctrl->comp_output_mode &=
+				~VFE32_OUTPUT_MODE_TERTIARY1;
+		axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+	}
+
+	if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt == 0) {
+		axi_ctrl->share_ctrl->comp_output_mode &=
+				~VFE32_OUTPUT_MODE_TERTIARY2;
+		axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+	}
+
+	if (axi_ctrl->share_ctrl->outpath.out4.capture_cnt == 0) {
+		axi_ctrl->share_ctrl->comp_output_mode &=
+				~VFE32_OUTPUT_MODE_TERTIARY3;
+		axi_ctrl->share_ctrl->outpath.out4.capture_cnt = -1;
+	}
 }
 
 static int msm_axi_buf_cfg(struct v4l2_subdev *sd, void __user *arg)
@@ -5866,8 +6917,16 @@
 {
 	int rc = -ENOIOCTLCMD;
 	switch (cmd) {
-	case VIDIOC_MSM_AXI_INIT:
-		rc = msm_axi_subdev_init(sd);
+	case VIDIOC_MSM_AXI_INIT: {
+		uint8_t dual_enabled;
+		if (copy_from_user(&dual_enabled,
+				(void __user *)(arg),
+				sizeof(uint8_t))) {
+				rc = -EFAULT;
+				break;
+		}
+		rc = msm_axi_subdev_init(sd, dual_enabled);
+		}
 		break;
 	case VIDIOC_MSM_AXI_CFG:
 		rc = msm_axi_config(sd, arg);
@@ -5884,6 +6943,29 @@
 		msm_axi_subdev_release(sd);
 		rc = 0;
 		break;
+	case VIDIOC_MSM_AXI_RDI_COUNT_UPDATE: {
+		struct rdi_count_msg *msg = (struct rdi_count_msg *)arg;
+		struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+		switch (msg->rdi_interface) {
+		case RDI_0:
+			axi_ctrl->share_ctrl->rdi0FrameId = msg->count;
+			rc = 0;
+			break;
+		case RDI_1:
+			axi_ctrl->share_ctrl->rdi1FrameId = msg->count;
+			rc = 0;
+			break;
+		case RDI_2:
+			axi_ctrl->share_ctrl->rdi2FrameId = msg->count;
+			rc = 0;
+			break;
+		default:
+			pr_err("%s: Incorrect interface sent\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		break;
+	}
 	default:
 		pr_err("%s: command %d not found\n", __func__,
 						_IOC_NR(cmd));
@@ -5944,7 +7026,7 @@
 	share_ctrl->vfe32_ctrl = vfe32_ctrl;
 	axi_ctrl->share_ctrl = share_ctrl;
 	vfe32_ctrl->share_ctrl = share_ctrl;
-
+	axi_ctrl->share_ctrl->axi_ref_cnt = 0;
 	v4l2_subdev_init(&axi_ctrl->subdev, &msm_axi_subdev_ops);
 	axi_ctrl->subdev.internal_ops = &msm_axi_internal_ops;
 	axi_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -6050,6 +7132,21 @@
 		goto vfe32_no_resource;
 	}
 
+#ifdef CONFIG_MSM_IOMMU
+	/*get device context for IOMMU*/
+	axi_ctrl->iommu_ctx_imgwr =
+		msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+	axi_ctrl->iommu_ctx_misc =
+		msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+	if (!axi_ctrl->iommu_ctx_imgwr || !axi_ctrl->iommu_ctx_misc) {
+		release_mem_region(axi_ctrl->vfemem->start,
+			resource_size(axi_ctrl->vfemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vfe32_no_resource;
+	}
+#endif
+
 	tasklet_init(&axi_ctrl->vfe32_tasklet,
 		axi32_do_tasklet, (unsigned long)axi_ctrl);
 
@@ -6061,7 +7158,7 @@
 vfe32_no_resource:
 	kfree(vfe32_ctrl);
 	kfree(axi_ctrl);
-	return 0;
+	return rc;
 }
 
 static struct platform_driver vfe32_driver = {
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index f4b7edb..d1dcac1 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -62,6 +62,12 @@
  * bit 26-32 = 0, domain reset, bit 0-9 = 1 for module reset. */
 #define VFE_RESET_UPON_RESET_CMD  0x000003ff
 
+/* reset the vfe only when reset command*/
+#define VFE_ONLY_RESET_CMD  0x00000002
+
+/*Vfe module reset command*/
+#define VFE_MODULE_RESET_CMD 0x07ffffff
+
 /* bit 5 is for axi status idle or busy.
  * 1 =  halted,  0 = busy */
 #define AXI_STATUS_BUSY_MASK 0x00000020
@@ -122,6 +128,7 @@
 
 #define VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK  0x4000000 /*bit 26*/
 #define VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK  0x8000000 /*bit 27*/
+#define VFE_IRQ_STATUS1_RDI2_REG_UPDATE_MASK  0x10000000 /*bit 28*/
 
 /*TODOs the irq status passed from axi to vfe irq handler does not account
 * for 2 irq status registers. So below macro is added to differentiate between
@@ -130,6 +137,7 @@
 *status bit*/
 #define VFE_IRQ_STATUS1_RDI0_REG_UPDATE  0x84000000 /*bit 26*/
 #define VFE_IRQ_STATUS1_RDI1_REG_UPDATE  0x88000000 /*bit 27*/
+#define VFE_IRQ_STATUS1_RDI2_REG_UPDATE  0x90000000 /*bit 28*/
 
 /* imask for while waiting for stop ack,  driver has already
  * requested stop, waiting for reset irq, and async timer irq.
@@ -244,11 +252,11 @@
 #define V32_OUT_CLAMP_OFF         0x00000524
 #define V32_OUT_CLAMP_LEN         8
 
-#define V32_OPERATION_CFG_LEN     44
+#define V32_OPERATION_CFG_LEN     32
 
 #define V32_AXI_BUS_CMD_OFF       0x00000038
 #define V32_AXI_OUT_OFF           0x0000003C
-#define V32_AXI_OUT_LEN           240
+#define V32_AXI_OUT_LEN           264
 #define V32_AXI_CFG_LEN           47
 #define V32_AXI_BUS_FMT_OFF       1
 #define V32_AXI_BUS_FMT_LEN       4
@@ -776,7 +784,7 @@
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
-	uint32_t  capture_cnt;
+	int32_t  capture_cnt;
 	uint32_t  frame_drop_cnt;
 	struct msm_free_buf ping;
 	struct msm_free_buf pong;
@@ -787,7 +795,8 @@
 #define VFE32_IMASK_ERROR_ONLY_0  0x0
 /* when normal case, don't want to block error status. */
 /* bit 0-21 are error irq bits */
-#define VFE32_IMASK_ERROR_ONLY_1               0x005FFFFF
+#define VFE32_IMASK_COMMON_ERROR_ONLY_1       0x00407F00
+#define VFE32_IMASK_VFE_ERROR_ONLY_1          0x001F80FF
 #define VFE32_IMASK_CAMIF_ERROR               (0x00000001<<0)
 #define VFE32_IMASK_BHIST_OVWR                (0x00000001<<1)
 #define VFE32_IMASK_STATS_CS_OVWR             (0x00000001<<2)
@@ -821,6 +830,7 @@
 	struct vfe32_output_ch out1; /* snapshot */
 	struct vfe32_output_ch out2; /* rdi0    */
 	struct vfe32_output_ch out3; /* rdi01   */
+	struct vfe32_output_ch out4; /* rdi02   */
 };
 
 struct vfe32_frame_extra {
@@ -928,6 +938,7 @@
 #define VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS	BIT(9)
 #define VFE32_OUTPUT_MODE_TERTIARY1		BIT(10)
 #define VFE32_OUTPUT_MODE_TERTIARY2		BIT(11)
+#define VFE32_OUTPUT_MODE_TERTIARY3		BIT(12)
 
 struct vfe_stats_control {
 	uint32_t droppedStatsFrameCount;
@@ -941,22 +952,35 @@
 	uint32_t register_total;
 
 	atomic_t vstate;
-	atomic_t handle_axi_irq;
+	atomic_t handle_common_irq;
 	uint32_t vfeFrameId;
+	uint32_t rdi0FrameId;
+	uint32_t rdi1FrameId;
+	uint32_t rdi2FrameId;
 	uint32_t stats_comp;
+	spinlock_t  sd_notify_lock;
 	spinlock_t  stop_flag_lock;
-	spinlock_t  abort_lock;
 	int8_t stop_ack_pending;
 	enum vfe_output_state liveshot_state;
 	uint32_t vfe_capture_count;
+	int32_t rdi0_capture_count;
+	int32_t rdi1_capture_count;
+	int32_t rdi2_capture_count;
+	uint8_t update_counter;
 
 	uint32_t operation_mode;     /* streaming or snapshot */
 	uint32_t current_mode;
 	struct vfe32_output_path outpath;
 
 	uint16_t port_info;
-	uint32_t skip_abort;
-	spinlock_t  sd_notify_lock;
+	uint8_t stop_immediately;
+	uint8_t sync_abort;
+	uint16_t cmd_type;
+	uint8_t vfe_reset_flag;
+	uint8_t dual_enabled;
+
+	uint8_t axi_ref_cnt;
+	uint16_t comp_output_mode;
 
 	struct completion reset_complete;
 
@@ -969,9 +993,11 @@
 	int8_t update_ack_pending;
 	enum vfe_output_state recording_state;
 
+	atomic_t pix0_update_ack_pending;
 	atomic_t rdi0_update_ack_pending;
 	atomic_t rdi1_update_ack_pending;
 	atomic_t rdi2_update_ack_pending;
+
 };
 
 struct axi_ctrl_t {
@@ -989,6 +1015,8 @@
 	struct clk *vfe_clk[3];
 	struct tasklet_struct vfe32_tasklet;
 	struct vfe_share_ctrl_t *share_ctrl;
+	struct device *iommu_ctx_imgwr;
+	struct device *iommu_ctx_misc;
 };
 
 struct vfe32_ctrl_type {
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.c b/drivers/media/video/msm/vfe/msm_vfe40.c
index 5a1d488..e958241 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40.c
@@ -15,226 +15,597 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/atomic.h>
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
-#include <linux/of.h>
 #include <mach/irqs.h>
 #include <mach/camera.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
 #include <media/msm_isp.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 
 #include "msm.h"
+#include "msm_cam_server.h"
 #include "msm_vfe40.h"
 
+atomic_t irq_cnt;
+
+#define VFE_WM_CFG_BASE 0x0070
+#define VFE_WM_CFG_LEN 0x0024
+
+#define vfe40_get_ch_ping_addr(base, chn) \
+	(msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
+#define vfe40_get_ch_pong_addr(base, chn) \
+	(msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
+#define vfe40_get_ch_addr(ping_pong, base, chn) \
+	((((ping_pong) & (1 << (chn))) == 0) ? \
+	(vfe40_get_ch_pong_addr((base), chn)) : \
+	(vfe40_get_ch_ping_addr((base), chn)))
+
+#define vfe40_put_ch_ping_addr(base, chn, addr) \
+	(msm_camera_io_w((addr), \
+	(base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
+#define vfe40_put_ch_pong_addr(base, chn, addr) \
+	(msm_camera_io_w((addr), \
+	(base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
+#define vfe40_put_ch_addr(ping_pong, base, chn, addr) \
+	(((ping_pong) & (1 << (chn))) == 0 ?   \
+	vfe40_put_ch_pong_addr((base), (chn), (addr)) : \
+	vfe40_put_ch_ping_addr((base), (chn), (addr)))
+
+static uint32_t vfe_clk_rate;
+static void vfe40_send_isp_msg(struct v4l2_subdev *sd,
+	uint32_t vfeFrameId, uint32_t isp_msg_id);
+
+
 struct vfe40_isr_queue_cmd {
 	struct list_head list;
 	uint32_t                           vfeInterruptStatus0;
 	uint32_t                           vfeInterruptStatus1;
 };
 
-static const char * const vfe40_general_cmd[] = {
-	"DUMMY_0",  /* 0 */
-	"SET_CLK",
-	"RESET",
-	"START",
-	"TEST_GEN_START",
-	"OPERATION_CFG",  /* 5 */
-	"AXI_OUT_CFG",
-	"CAMIF_CFG",
-	"AXI_INPUT_CFG",
-	"BLACK_LEVEL_CFG",
-	"ROLL_OFF_CFG",  /* 10 */
-	"DEMUX_CFG",
-	"FOV_CFG",
-	"MAIN_SCALER_CFG",
-	"WB_CFG",
-	"COLOR_COR_CFG", /* 15 */
-	"RGB_G_CFG",
-	"LA_CFG",
-	"CHROMA_EN_CFG",
-	"CHROMA_SUP_CFG",
-	"MCE_CFG", /* 20 */
-	"SK_ENHAN_CFG",
-	"ASF_CFG",
-	"S2Y_CFG",
-	"S2CbCr_CFG",
-	"CHROMA_SUBS_CFG",  /* 25 */
-	"OUT_CLAMP_CFG",
-	"FRAME_SKIP_CFG",
-	"DUMMY_1",
-	"DUMMY_2",
-	"DUMMY_3",  /* 30 */
-	"UPDATE",
-	"BL_LVL_UPDATE",
-	"DEMUX_UPDATE",
-	"FOV_UPDATE",
-	"MAIN_SCALER_UPDATE",  /* 35 */
-	"WB_UPDATE",
-	"COLOR_COR_UPDATE",
-	"RGB_G_UPDATE",
-	"LA_UPDATE",
-	"CHROMA_EN_UPDATE",  /* 40 */
-	"CHROMA_SUP_UPDATE",
-	"MCE_UPDATE",
-	"SK_ENHAN_UPDATE",
-	"S2CbCr_UPDATE",
-	"S2Y_UPDATE",  /* 45 */
-	"ASF_UPDATE",
-	"FRAME_SKIP_UPDATE",
-	"CAMIF_FRAME_UPDATE",
-	"STATS_AF_UPDATE",
-	"STATS_AE_UPDATE",  /* 50 */
-	"STATS_AWB_UPDATE",
-	"STATS_RS_UPDATE",
-	"STATS_CS_UPDATE",
-	"STATS_SKIN_UPDATE",
-	"STATS_IHIST_UPDATE",  /* 55 */
-	"DUMMY_4",
-	"EPOCH1_ACK",
-	"EPOCH2_ACK",
-	"START_RECORDING",
-	"STOP_RECORDING",  /* 60 */
-	"DUMMY_5",
-	"DUMMY_6",
-	"CAPTURE",
-	"DUMMY_7",
-	"STOP",  /* 65 */
-	"GET_HW_VERSION",
-	"GET_FRAME_SKIP_COUNTS",
-	"OUTPUT1_BUFFER_ENQ",
-	"OUTPUT2_BUFFER_ENQ",
-	"OUTPUT3_BUFFER_ENQ",  /* 70 */
-	"JPEG_OUT_BUF_ENQ",
-	"RAW_OUT_BUF_ENQ",
-	"RAW_IN_BUF_ENQ",
-	"STATS_AF_ENQ",
-	"STATS_AE_ENQ",  /* 75 */
-	"STATS_AWB_ENQ",
-	"STATS_RS_ENQ",
-	"STATS_CS_ENQ",
-	"STATS_SKIN_ENQ",
-	"STATS_IHIST_ENQ",  /* 80 */
-	"DUMMY_8",
-	"JPEG_ENC_CFG",
-	"DUMMY_9",
-	"STATS_AF_START",
-	"STATS_AF_STOP",  /* 85 */
-	"STATS_AE_START",
-	"STATS_AE_STOP",
-	"STATS_AWB_START",
-	"STATS_AWB_STOP",
-	"STATS_RS_START",  /* 90 */
-	"STATS_RS_STOP",
-	"STATS_CS_START",
-	"STATS_CS_STOP",
-	"STATS_SKIN_START",
-	"STATS_SKIN_STOP",  /* 95 */
-	"STATS_IHIST_START",
-	"STATS_IHIST_STOP",
-	"DUMMY_10",
-	"SYNC_TIMER_SETTING",
-	"ASYNC_TIMER_SETTING",  /* 100 */
-	"LIVESHOT",
-	"LA_SETUP",
-	"LINEARIZATION_CFG",
-	"DEMOSAICV3",
-	"DEMOSAICV3_ABCC_CFG", /* 105 */
-	"DEMOSAICV3_DBCC_CFG",
-	"DEMOSAICV3_DBPC_CFG",
-	"DEMOSAICV3_ABF_CFG",
-	"DEMOSAICV3_ABCC_UPDATE",
-	"DEMOSAICV3_DBCC_UPDATE", /* 110 */
-	"DEMOSAICV3_DBPC_UPDATE",
-	"XBAR_CFG",
-	"EZTUNE_CFG",
-	"V40_ZSL",
-	"LINEARIZATION_UPDATE", /*115*/
-	"DEMOSAICV3_ABF_UPDATE",
-	"CLF_CFG",
-	"CLF_LUMA_UPDATE",
-	"CLF_CHROMA_UPDATE",
-	"PCA_ROLL_OFF_CFG", /*120*/
-	"PCA_ROLL_OFF_UPDATE",
-	"GET_REG_DUMP",
-	"GET_LINEARIZATON_TABLE",
-	"GET_MESH_ROLLOFF_TABLE",
-	"GET_PCA_ROLLOFF_TABLE", /*125*/
-	"GET_RGB_G_TABLE",
-	"GET_LA_TABLE",
-	"DEMOSAICV3_UPDATE",
-	"ACTIVE_REGION_CONFIG",
-	"COLOR_PROCESSING_CONFIG", /*130*/
-	"STATS_WB_AEC_CONFIG",
-	"STATS_WB_AEC_UPDATE",
-	"Y_GAMMA_CONFIG",
-	"SCALE_OUTPUT1_CONFIG",
-	"SCALE_OUTPUT2_CONFIG", /*135*/
-	"CAPTURE_RAW",
-	"STOP_LIVESHOT",
-	"RECONFIG_VFE",
-	"STATS_REQBUF_CFG",
-	"STATS_ENQUEUEBUF_CFG",/*140*/
-	"STATS_FLUSH_BUFQ_CFG",
-	"FOV_ENC_CFG",
-	"FOV_VIEW_CFG",
-	"FOV_ENC_UPDATE",
-	"FOV_VIEW_UPDATE",/*145*/
-	"SCALER_ENC_CFG",
-	"SCALER_VIEW_CFG",
-	"SCALER_ENC_UPDATE",
-	"SCALER_VIEW_UPDATE",
-	"COLORXFORM_ENC_CFG",/*150*/
-	"COLORXFORM_VIEW_CFG",
-	"COLORXFORM_ENC_UPDATE",
-	"COLORXFORM_VIEW_UPDATE",
+static struct vfe40_cmd_type vfe40_cmd[] = {
+	[1] = {VFE_CMD_SET_CLK},
+	[2] = {VFE_CMD_RESET},
+	[3] = {VFE_CMD_START},
+	[4] = {VFE_CMD_TEST_GEN_START},
+	[5] = {VFE_CMD_OPERATION_CFG, V40_OPERATION_CFG_LEN},
+	[6] = {VFE_CMD_AXI_OUT_CFG, V40_AXI_OUT_LEN, V40_AXI_BUS_CMD_OFF, 0xFF},
+	[7] = {VFE_CMD_CAMIF_CFG, V40_CAMIF_LEN, V40_CAMIF_OFF, 0xFF},
+	[8] = {VFE_CMD_AXI_INPUT_CFG},
+	[9] = {VFE_CMD_BLACK_LEVEL_CFG},
+	[10] = {VFE_CMD_MESH_ROLL_OFF_CFG, V40_MESH_ROLL_OFF_CFG_LEN,
+		V40_MESH_ROLL_OFF_CFG_OFF, 0xFF},
+	[11] = {VFE_CMD_DEMUX_CFG, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
+	[12] = {VFE_CMD_FOV_CFG},
+	[13] = {VFE_CMD_MAIN_SCALER_CFG},
+	[14] = {VFE_CMD_WB_CFG, V40_WB_LEN, V40_WB_OFF, 0xFF},
+	[15] = {VFE_CMD_COLOR_COR_CFG, V40_COLOR_COR_LEN,
+		V40_COLOR_COR_OFF, 0xFF},
+	[16] = {VFE_CMD_RGB_G_CFG, V40_RGB_G_LEN, V40_RGB_G_OFF, 0xFF},
+	[17] = {VFE_CMD_LA_CFG, V40_LA_LEN, V40_LA_OFF, 0xFF },
+	[18] = {VFE_CMD_CHROMA_EN_CFG, V40_CHROMA_EN_LEN, V40_CHROMA_EN_OFF,
+		0xFF},
+	[19] = {VFE_CMD_CHROMA_SUP_CFG, V40_CHROMA_SUP_LEN,
+		V40_CHROMA_SUP_OFF, 0xFF},
+	[20] = {VFE_CMD_MCE_CFG, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
+	[21] = {VFE_CMD_SK_ENHAN_CFG, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
+	[22] = {VFE_CMD_ASF_CFG, V40_ASF_LEN, V40_ASF_OFF, 0xFF},
+	[23] = {VFE_CMD_S2Y_CFG},
+	[24] = {VFE_CMD_S2CbCr_CFG},
+	[25] = {VFE_CMD_CHROMA_SUBS_CFG},
+	[26] = {VFE_CMD_OUT_CLAMP_CFG, V40_OUT_CLAMP_LEN, V40_OUT_CLAMP_OFF,
+		0xFF},
+	[27] = {VFE_CMD_FRAME_SKIP_CFG},
+	[31] = {VFE_CMD_UPDATE},
+	[32] = {VFE_CMD_BL_LVL_UPDATE},
+	[33] = {VFE_CMD_DEMUX_UPDATE, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
+	[34] = {VFE_CMD_FOV_UPDATE},
+	[35] = {VFE_CMD_MAIN_SCALER_UPDATE},
+	[36] = {VFE_CMD_WB_UPDATE, V40_WB_LEN, V40_WB_OFF, 0xFF},
+	[37] = {VFE_CMD_COLOR_COR_UPDATE, V40_COLOR_COR_LEN,
+		V40_COLOR_COR_OFF, 0xFF},
+	[38] = {VFE_CMD_RGB_G_UPDATE, V40_RGB_G_LEN, V40_CHROMA_EN_OFF, 0xFF},
+	[39] = {VFE_CMD_LA_UPDATE, V40_LA_LEN, V40_LA_OFF, 0xFF },
+	[40] = {VFE_CMD_CHROMA_EN_UPDATE, V40_CHROMA_EN_LEN,
+		V40_CHROMA_EN_OFF, 0xFF},
+	[41] = {VFE_CMD_CHROMA_SUP_UPDATE, V40_CHROMA_SUP_LEN,
+		V40_CHROMA_SUP_OFF, 0xFF},
+	[42] = {VFE_CMD_MCE_UPDATE, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
+	[43] = {VFE_CMD_SK_ENHAN_UPDATE, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
+	[44] = {VFE_CMD_S2CbCr_UPDATE},
+	[45] = {VFE_CMD_S2Y_UPDATE},
+	[46] = {VFE_CMD_ASF_UPDATE, V40_ASF_UPDATE_LEN, V40_ASF_OFF, 0xFF},
+	[47] = {VFE_CMD_FRAME_SKIP_UPDATE},
+	[48] = {VFE_CMD_CAMIF_FRAME_UPDATE},
+	[49] = {VFE_CMD_STATS_AF_UPDATE},
+	[50] = {VFE_CMD_STATS_AE_UPDATE},
+	[51] = {VFE_CMD_STATS_AWB_UPDATE, V40_STATS_AWB_LEN,
+		V40_STATS_AWB_OFF},
+	[52] = {VFE_CMD_STATS_RS_UPDATE, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
+	[53] = {VFE_CMD_STATS_CS_UPDATE, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
+	[54] = {VFE_CMD_STATS_SKIN_UPDATE},
+	[55] = {VFE_CMD_STATS_IHIST_UPDATE, V40_STATS_IHIST_LEN,
+		V40_STATS_IHIST_OFF},
+	[57] = {VFE_CMD_EPOCH1_ACK},
+	[58] = {VFE_CMD_EPOCH2_ACK},
+	[59] = {VFE_CMD_START_RECORDING},
+	[60] = {VFE_CMD_STOP_RECORDING},
+	[63] = {VFE_CMD_CAPTURE, V40_CAPTURE_LEN, 0xFF},
+	[65] = {VFE_CMD_STOP},
+	[66] = {VFE_CMD_GET_HW_VERSION, V40_GET_HW_VERSION_LEN,
+		V40_GET_HW_VERSION_OFF},
+	[67] = {VFE_CMD_GET_FRAME_SKIP_COUNTS},
+	[68] = {VFE_CMD_OUTPUT1_BUFFER_ENQ},
+	[69] = {VFE_CMD_OUTPUT2_BUFFER_ENQ},
+	[70] = {VFE_CMD_OUTPUT3_BUFFER_ENQ},
+	[71] = {VFE_CMD_JPEG_OUT_BUF_ENQ},
+	[72] = {VFE_CMD_RAW_OUT_BUF_ENQ},
+	[73] = {VFE_CMD_RAW_IN_BUF_ENQ},
+	[74] = {VFE_CMD_STATS_AF_ENQ},
+	[75] = {VFE_CMD_STATS_AE_ENQ},
+	[76] = {VFE_CMD_STATS_AWB_ENQ},
+	[77] = {VFE_CMD_STATS_RS_ENQ},
+	[78] = {VFE_CMD_STATS_CS_ENQ},
+	[79] = {VFE_CMD_STATS_SKIN_ENQ},
+	[80] = {VFE_CMD_STATS_IHIST_ENQ},
+	[82] = {VFE_CMD_JPEG_ENC_CFG},
+	[84] = {VFE_CMD_STATS_AF_START},
+	[85] = {VFE_CMD_STATS_AF_STOP},
+	[86] = {VFE_CMD_STATS_AE_START},
+	[87] = {VFE_CMD_STATS_AE_STOP},
+	[88] = {VFE_CMD_STATS_AWB_START, V40_STATS_AWB_LEN, V40_STATS_AWB_OFF},
+	[89] = {VFE_CMD_STATS_AWB_STOP},
+	[90] = {VFE_CMD_STATS_RS_START, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
+	[91] = {VFE_CMD_STATS_RS_STOP},
+	[92] = {VFE_CMD_STATS_CS_START, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
+	[93] = {VFE_CMD_STATS_CS_STOP},
+	[94] = {VFE_CMD_STATS_SKIN_START},
+	[95] = {VFE_CMD_STATS_SKIN_STOP},
+	[96] = {VFE_CMD_STATS_IHIST_START,
+		V40_STATS_IHIST_LEN, V40_STATS_IHIST_OFF},
+	[97] = {VFE_CMD_STATS_IHIST_STOP},
+	[99] = {VFE_CMD_SYNC_TIMER_SETTING, V40_SYNC_TIMER_LEN,
+			V40_SYNC_TIMER_OFF},
+	[100] = {VFE_CMD_ASYNC_TIMER_SETTING, V40_ASYNC_TIMER_LEN,
+		V40_ASYNC_TIMER_OFF},
+	[101] = {VFE_CMD_LIVESHOT},
+	[102] = {VFE_CMD_LA_SETUP},
+	[103] = {VFE_CMD_LINEARIZATION_CFG, V40_LINEARIZATION_LEN1,
+			V40_LINEARIZATION_OFF1},
+	[104] = {VFE_CMD_DEMOSAICV3},
+	[105] = {VFE_CMD_DEMOSAICV3_ABCC_CFG},
+	[106] = {VFE_CMD_DEMOSAICV3_DBCC_CFG, V40_DEMOSAICV3_DBCC_LEN,
+			V40_DEMOSAICV3_DBCC_OFF},
+	[107] = {VFE_CMD_DEMOSAICV3_DBPC_CFG},
+	[108] = {VFE_CMD_DEMOSAICV3_ABF_CFG, V40_DEMOSAICV3_ABF_LEN,
+			V40_DEMOSAICV3_ABF_OFF},
+	[109] = {VFE_CMD_DEMOSAICV3_ABCC_UPDATE},
+	[110] = {VFE_CMD_DEMOSAICV3_DBCC_UPDATE, V40_DEMOSAICV3_DBCC_LEN,
+			V40_DEMOSAICV3_DBCC_OFF},
+	[111] = {VFE_CMD_DEMOSAICV3_DBPC_UPDATE},
+	[112] = {VFE_CMD_XBAR_CFG},
+	[113] = {VFE_CMD_MODULE_CFG, V40_MODULE_CFG_LEN, V40_MODULE_CFG_OFF},
+	[114] = {VFE_CMD_ZSL},
+	[115] = {VFE_CMD_LINEARIZATION_UPDATE, V40_LINEARIZATION_LEN1,
+			V40_LINEARIZATION_OFF1},
+	[116] = {VFE_CMD_DEMOSAICV3_ABF_UPDATE, V40_DEMOSAICV3_ABF_LEN,
+			V40_DEMOSAICV3_ABF_OFF},
+	[117] = {VFE_CMD_CLF_CFG, V40_CLF_CFG_LEN, V40_CLF_CFG_OFF},
+	[118] = {VFE_CMD_CLF_LUMA_UPDATE, V40_CLF_LUMA_UPDATE_LEN,
+			V40_CLF_LUMA_UPDATE_OFF},
+	[119] = {VFE_CMD_CLF_CHROMA_UPDATE, V40_CLF_CHROMA_UPDATE_LEN,
+			V40_CLF_CHROMA_UPDATE_OFF},
+	[120] = {VFE_CMD_PCA_ROLL_OFF_CFG},
+	[121] = {VFE_CMD_PCA_ROLL_OFF_UPDATE},
+	[122] = {VFE_CMD_GET_REG_DUMP},
+	[123] = {VFE_CMD_GET_LINEARIZATON_TABLE},
+	[124] = {VFE_CMD_GET_MESH_ROLLOFF_TABLE},
+	[125] = {VFE_CMD_GET_PCA_ROLLOFF_TABLE},
+	[126] = {VFE_CMD_GET_RGB_G_TABLE},
+	[127] = {VFE_CMD_GET_LA_TABLE},
+	[128] = {VFE_CMD_DEMOSAICV3_UPDATE},
+	[129] = {VFE_CMD_ACTIVE_REGION_CFG},
+	[130] = {VFE_CMD_COLOR_PROCESSING_CONFIG},
+	[131] = {VFE_CMD_STATS_WB_AEC_CONFIG},
+	[132] = {VFE_CMD_STATS_WB_AEC_UPDATE},
+	[133] = {VFE_CMD_Y_GAMMA_CONFIG},
+	[134] = {VFE_CMD_SCALE_OUTPUT1_CONFIG},
+	[135] = {VFE_CMD_SCALE_OUTPUT2_CONFIG},
+	[136] = {VFE_CMD_CAPTURE_RAW},
+	[137] = {VFE_CMD_STOP_LIVESHOT},
+	[138] = {VFE_CMD_RECONFIG_VFE},
+	[139] = {VFE_CMD_STATS_REQBUF},
+	[140] = {VFE_CMD_STATS_ENQUEUEBUF},
+	[141] = {VFE_CMD_STATS_FLUSH_BUFQ},
+	[142] = {VFE_CMD_STATS_UNREGBUF},
+	[143] = {VFE_CMD_STATS_BG_START, V40_STATS_BG_LEN, V40_STATS_BG_OFF},
+	[144] = {VFE_CMD_STATS_BG_STOP},
+	[145] = {VFE_CMD_STATS_BF_START, V40_STATS_BF_LEN, V40_STATS_BF_OFF},
+	[146] = {VFE_CMD_STATS_BF_STOP},
+	[147] = {VFE_CMD_STATS_BHIST_START, V40_STATS_BHIST_LEN,
+			V40_STATS_BHIST_OFF},
+	[148] = {VFE_CMD_STATS_BHIST_STOP},
+	[149] = {VFE_CMD_RESET_2},
+	[150] = {VFE_CMD_FOV_ENC_CFG, V40_FOV_ENC_LEN,
+		V40_FOV_ENC_OFF, 0xFF},
+	[151] = {VFE_CMD_FOV_VIEW_CFG, V40_FOV_VIEW_LEN,
+		V40_FOV_VIEW_OFF, 0xFF},
+	[152] = {VFE_CMD_FOV_ENC_UPDATE, V40_FOV_ENC_LEN,
+		V40_FOV_ENC_OFF, 0xFF},
+	[153] = {VFE_CMD_FOV_VIEW_UPDATE, V40_FOV_VIEW_LEN,
+		V40_FOV_VIEW_OFF, 0xFF},
+	[154] = {VFE_CMD_SCALER_ENC_CFG, V40_SCALER_ENC_LEN,
+		V40_SCALER_ENC_OFF, 0xFF},
+	[155] = {VFE_CMD_SCALER_VIEW_CFG, V40_SCALER_VIEW_LEN,
+		V40_SCALER_VIEW_OFF, 0xFF},
+	[156] = {VFE_CMD_SCALER_ENC_UPDATE, V40_SCALER_ENC_LEN,
+		V40_SCALER_ENC_OFF, 0xFF},
+	[157] = {VFE_CMD_SCALER_VIEW_UPDATE, V40_SCALER_VIEW_LEN,
+		V40_SCALER_VIEW_OFF, 0xFF},
+	[158] = {VFE_CMD_COLORXFORM_ENC_CFG, V40_COLORXFORM_ENC_CFG_LEN,
+		V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
+	[159] = {VFE_CMD_COLORXFORM_VIEW_CFG, V40_COLORXFORM_VIEW_CFG_LEN,
+		V40_COLORXFORM_VIEW_CFG_OFF},
+	[160] = {VFE_CMD_COLORXFORM_ENC_UPDATE, V40_COLORXFORM_ENC_CFG_LEN,
+		V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
+	[161] = {VFE_CMD_COLORXFORM_VIEW_UPDATE, V40_COLORXFORM_VIEW_CFG_LEN,
+		V40_COLORXFORM_VIEW_CFG_OFF, 0xFF},
 };
 
-static void vfe40_stop(struct vfe40_ctrl_type *vfe40_ctrl)
+static const uint32_t vfe40_AXI_WM_CFG[] = {
+	0x0000006C,
+	0x00000090,
+	0x000000B4,
+	0x000000D8,
+	0x000000FC,
+	0x00000120,
+	0x00000144,
+};
+
+static const char * const vfe40_general_cmd[] = {
+	[1] = "SET_CLK",
+	[2] = "RESET",
+	[3] = "START",
+	[4] = "TEST_GEN_START",
+	[5] = "OPERATION_CFG",  /* 5 */
+	[6] = "AXI_OUT_CFG",
+	[7] = "CAMIF_CFG",
+	[8] = "AXI_INPUT_CFG",
+	[9] = "BLACK_LEVEL_CFG",
+	[10] = "ROLL_OFF_CFG",  /* 10 */
+	[11] = "DEMUX_CFG",
+	[12] = "FOV_CFG",
+	[13] = "MAIN_SCALER_CFG",
+	[14] = "WB_CFG",
+	[15] = "COLOR_COR_CFG", /* 15 */
+	[16] = "RGB_G_CFG",
+	[17] = "LA_CFG",
+	[18] = "CHROMA_EN_CFG",
+	[19] = "CHROMA_SUP_CFG",
+	[20] = "MCE_CFG", /* 20 */
+	[21] = "SK_ENHAN_CFG",
+	[22] = "ASF_CFG",
+	[23] = "S2Y_CFG",
+	[24] = "S2CbCr_CFG",
+	[25] = "CHROMA_SUBS_CFG",  /* 25 */
+	[26] = "OUT_CLAMP_CFG",
+	[27] = "FRAME_SKIP_CFG",
+	[31] = "UPDATE",
+	[32] = "BL_LVL_UPDATE",
+	[33] = "DEMUX_UPDATE",
+	[34] = "FOV_UPDATE",
+	[35] = "MAIN_SCALER_UPDATE",  /* 35 */
+	[36] = "WB_UPDATE",
+	[37] = "COLOR_COR_UPDATE",
+	[38] = "RGB_G_UPDATE",
+	[39] = "LA_UPDATE",
+	[40] = "CHROMA_EN_UPDATE",  /* 40 */
+	[41] = "CHROMA_SUP_UPDATE",
+	[42] = "MCE_UPDATE",
+	[43] = "SK_ENHAN_UPDATE",
+	[44] = "S2CbCr_UPDATE",
+	[45] = "S2Y_UPDATE",  /* 45 */
+	[46] = "ASF_UPDATE",
+	[47] = "FRAME_SKIP_UPDATE",
+	[48] = "CAMIF_FRAME_UPDATE",
+	[49] = "STATS_AF_UPDATE",
+	[50] = "STATS_AE_UPDATE",  /* 50 */
+	[51] = "STATS_AWB_UPDATE",
+	[52] = "STATS_RS_UPDATE",
+	[53] = "STATS_CS_UPDATE",
+	[54] = "STATS_SKIN_UPDATE",
+	[55] = "STATS_IHIST_UPDATE",  /* 55 */
+	[57] = "EPOCH1_ACK",
+	[58] = "EPOCH2_ACK",
+	[59] = "START_RECORDING",
+	[60] = "STOP_RECORDING",  /* 60 */
+	[63] = "CAPTURE",
+	[65] = "STOP",  /* 65 */
+	[66] = "GET_HW_VERSION",
+	[67] = "GET_FRAME_SKIP_COUNTS",
+	[68] = "OUTPUT1_BUFFER_ENQ",
+	[69] = "OUTPUT2_BUFFER_ENQ",
+	[70] = "OUTPUT3_BUFFER_ENQ",  /* 70 */
+	[71] = "JPEG_OUT_BUF_ENQ",
+	[72] = "RAW_OUT_BUF_ENQ",
+	[73] = "RAW_IN_BUF_ENQ",
+	[74] = "STATS_AF_ENQ",
+	[75] = "STATS_AE_ENQ",  /* 75 */
+	[76] = "STATS_AWB_ENQ",
+	[77] = "STATS_RS_ENQ",
+	[78] = "STATS_CS_ENQ",
+	[79] = "STATS_SKIN_ENQ",
+	[80] = "STATS_IHIST_ENQ",  /* 80 */
+	[82] = "JPEG_ENC_CFG",
+	[84] = "STATS_AF_START",
+	[85] = "STATS_AF_STOP",  /* 85 */
+	[86] = "STATS_AE_START",
+	[87] = "STATS_AE_STOP",
+	[88] = "STATS_AWB_START",
+	[89] = "STATS_AWB_STOP",
+	[90] = "STATS_RS_START",  /* 90 */
+	[91] = "STATS_RS_STOP",
+	[92] = "STATS_CS_START",
+	[93] = "STATS_CS_STOP",
+	[94] = "STATS_SKIN_START",
+	[95] = "STATS_SKIN_STOP",  /* 95 */
+	[96] = "STATS_IHIST_START",
+	[97] = "STATS_IHIST_STOP",
+	[99] = "SYNC_TIMER_SETTING",
+	[100] = "ASYNC_TIMER_SETTING",  /* 100 */
+	[101] = "LIVESHOT",
+	[102] = "LA_SETUP",
+	[103] = "LINEARIZATION_CFG",
+	[104] = "DEMOSAICV3",
+	[105] = "DEMOSAICV3_ABCC_CFG", /* 105 */
+	[106] = "DEMOSAICV3_DBCC_CFG",
+	[107] = "DEMOSAICV3_DBPC_CFG",
+	[108] = "DEMOSAICV3_ABF_CFG",
+	[109] = "DEMOSAICV3_ABCC_UPDATE",
+	[110] = "DEMOSAICV3_DBCC_UPDATE", /* 110 */
+	[111] = "DEMOSAICV3_DBPC_UPDATE",
+	[112] = "XBAR_CFG",
+	[113] = "EZTUNE_CFG",
+	[114] = "V40_ZSL",
+	[115] = "LINEARIZATION_UPDATE", /*115*/
+	[116] = "DEMOSAICV3_ABF_UPDATE",
+	[117] = "CLF_CFG",
+	[118] = "CLF_LUMA_UPDATE",
+	[119] = "CLF_CHROMA_UPDATE",
+	[120] = "PCA_ROLL_OFF_CFG", /*120*/
+	[121] = "PCA_ROLL_OFF_UPDATE",
+	[122] = "GET_REG_DUMP",
+	[123] = "GET_LINEARIZATON_TABLE",
+	[124] = "GET_MESH_ROLLOFF_TABLE",
+	[125] = "GET_PCA_ROLLOFF_TABLE", /*125*/
+	[126] = "GET_RGB_G_TABLE",
+	[127] = "GET_LA_TABLE",
+	[128] = "DEMOSAICV3_UPDATE",
+	[139] = "STATS_REQBUF",
+	[140] = "STATS_ENQUEUEBUF", /*140*/
+	[141] = "STATS_FLUSH_BUFQ",
+	[142] = "STATS_UNREGBUF",
+	[143] = "STATS_BG_START",
+	[144] = "STATS_BG_STOP",
+	[145] = "STATS_BF_START", /*145*/
+	[146] = "STATS_BF_STOP",
+	[147] = "STATS_BHIST_START",
+	[148] = "STATS_BHIST_STOP",
+	[149] = "RESET_2",
+};
+
+/*Temporary use fixed bus vectors in VFE */
+static struct msm_bus_vectors vfe_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors vfe_preview_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 27648000,
+		.ib  = 110592000,
+	},
+};
+
+static struct msm_bus_vectors vfe_video_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 154275840,
+		.ib  = 617103360,
+	},
+};
+
+static struct msm_bus_vectors vfe_snapshot_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 274423680,
+		.ib  = 1097694720,
+	},
+};
+
+static struct msm_bus_vectors vfe_zsl_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 302071680,
+		.ib  = 1208286720,
+	},
+};
+
+static struct msm_bus_paths vfe_bus_client_config[] = {
+	{
+		ARRAY_SIZE(vfe_init_vectors),
+		vfe_init_vectors,
+	},
+	{
+		ARRAY_SIZE(vfe_preview_vectors),
+		vfe_preview_vectors,
+	},
+	{
+		ARRAY_SIZE(vfe_video_vectors),
+		vfe_video_vectors,
+	},
+	{
+		ARRAY_SIZE(vfe_snapshot_vectors),
+		vfe_snapshot_vectors,
+	},
+	{
+		ARRAY_SIZE(vfe_zsl_vectors),
+		vfe_zsl_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata vfe_bus_client_pdata = {
+		vfe_bus_client_config,
+		ARRAY_SIZE(vfe_bus_client_config),
+		.name = "msm_camera_vfe",
+};
+
+uint8_t vfe40_use_bayer_stats(struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	unsigned long flags;
+	if (vfe40_ctrl->ver_num.main >= 4) {
+		/* VFE 4 or above uses bayer stats */
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
 
-	atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
+static void axi_enable_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t irq_mask;
+	uint16_t vfe_operation_mode =
+		share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+			VFE_OUTPUTS_RDI1);
+	irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
 
-	/* for reset hw modules, and send msg when reset_irq comes.*/
-	spin_lock_irqsave(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
-	vfe40_ctrl->share_ctrl->stop_ack_pending = TRUE;
-	spin_unlock_irqrestore(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
+	irq_mask |= VFE_IMASK_WHILE_STOPPING_0;
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+		irq_mask |= VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK;
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+		irq_mask |= VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK;
+
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+		VFE_IRQ_MASK_0);
+
+	if (vfe_operation_mode) {
+		irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		irq_mask |= 0x00000021;
+		if (share_ctrl->stats_comp)
+			irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0;
+		else
+			irq_mask |= 0x00FF0000;
+		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		atomic_set(&share_ctrl->vstate, 1);
+	}
+	atomic_set(&share_ctrl->handle_common_irq, 1);
+}
+
+static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
 
 	/* disable all interrupts.  */
+
+	uint32_t irq_mask = 0;
+	uint16_t vfe_operation_mode =
+		share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+			VFE_OUTPUTS_RDI1);
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		irq_mask &= ~(VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK);
+		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		msm_camera_io_w(VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK,
+			share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+	}
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		irq_mask &= ~(VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK);
+		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		msm_camera_io_w(VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK,
+			share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+	}
+	if (vfe_operation_mode) {
+		atomic_set(&share_ctrl->vstate, 0);
+		irq_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+		irq_mask &= ~(0x00000011);
+		if (share_ctrl->stats_comp)
+			irq_mask &= ~(VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0);
+		else
+			irq_mask &= ~0x00FF0000;
+		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+	}
+
+	if (share_ctrl->axi_ref_cnt == 1) {
+		atomic_set(&share_ctrl->handle_common_irq, 0);
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
+		share_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-			vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+		share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* clear all pending interrupts*/
-	msm_camera_io_w(VFE_CLEAR_ALL_IRQ0,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
-	msm_camera_io_w(VFE_CLEAR_ALL_IRQ1,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+	msm_camera_io_w(0xFFFFFFFF,
+		share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+	msm_camera_io_w(0xFFFFFFFF,
+		share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(1,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
+		share_ctrl->vfebase + VFE_IRQ_CMD);
+	}
+}
+
+static void vfe40_stop(struct vfe40_ctrl_type *vfe40_ctrl)
+{
 
 	/* in either continuous or snapshot mode, stop command can be issued
 	 * at any time. stop camif immediately. */
 	msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
 		vfe40_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+	vfe40_ctrl->share_ctrl->operation_mode &=
+		~(vfe40_ctrl->share_ctrl->current_mode);
+	vfe40_ctrl->share_ctrl->current_mode = 0;
 }
 
-void vfe40_subdev_notify(int id, int path, int image_mode,
+static void vfe40_subdev_notify(int id, int path, uint32_t inst_handle,
 	struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
 {
 	struct msm_vfe_resp rp;
 	struct msm_frame_info frame_info;
 	unsigned long flags = 0;
 	spin_lock_irqsave(&share_ctrl->sd_notify_lock, flags);
-	CDBG("%s: msgId = %d\n", __func__, id);
+	CDBG("vfe40_subdev_notify : msgId = %d\n", id);
 	memset(&rp, 0, sizeof(struct msm_vfe_resp));
 	rp.evt_msg.type   = MSM_CAMERA_MSG;
-	frame_info.image_mode = image_mode;
+	frame_info.inst_handle = inst_handle;
 	frame_info.path = path;
 	rp.evt_msg.data = &frame_info;
 	rp.type	   = id;
@@ -242,45 +613,249 @@
 	spin_unlock_irqrestore(&share_ctrl->sd_notify_lock, flags);
 }
 
+static int vfe40_config_axi(
+	struct axi_ctrl_t *axi_ctrl, int mode, uint32_t *ao)
+{
+	uint32_t *ch_info;
+	uint32_t *axi_cfg = ao;
+	int vfe_mode = (mode & ~(OUTPUT_TERT1|OUTPUT_TERT2));
+
+	/* Update the corresponding write masters for each output*/
+	ch_info = axi_cfg + V40_AXI_CFG_LEN;
+	axi_ctrl->share_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out0.ch1 =
+		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out0.inst_handle = *ch_info++;
+
+	axi_ctrl->share_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out1.ch1 =
+		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out1.inst_handle = *ch_info++;
+
+	axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out2.ch1 =
+		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out2.inst_handle = *ch_info++;
+
+	axi_ctrl->share_ctrl->outpath.out3.ch0 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out3.ch1 =
+		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out3.inst_handle = *ch_info++;
+
+	axi_ctrl->share_ctrl->outpath.output_mode = 0;
+
+	if (mode & OUTPUT_TERT1)
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_TERTIARY1;
+	if (mode & OUTPUT_TERT2)
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_TERTIARY2;
+	if (mode == OUTPUT_TERT1 || mode == OUTPUT_TERT1
+		|| mode == (OUTPUT_TERT1|OUTPUT_TERT2))
+			goto bus_cfg;
+
+	switch (vfe_mode) {
+	case OUTPUT_PRIM:
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_PRIMARY;
+		break;
+	case OUTPUT_PRIM_ALL_CHNLS:
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+		break;
+	case OUTPUT_PRIM|OUTPUT_SEC:
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_PRIMARY;
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_SECONDARY;
+		break;
+	case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_PRIMARY;
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+		break;
+	case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+		axi_ctrl->share_ctrl->outpath.output_mode |=
+			VFE40_OUTPUT_MODE_SECONDARY;
+		break;
+	default:
+		pr_err("%s Invalid AXI mode %d ", __func__, mode);
+		return -EINVAL;
+	}
+
+bus_cfg:
+	msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
+		vfe40_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
+		V40_AXI_BUS_CFG_LEN);
+	msm_camera_io_w(*ch_info++,
+		axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+	msm_camera_io_w(*ch_info++,
+		axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
+	msm_camera_io_w(*ch_info++,
+		axi_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG);
+	return 0;
+}
+
+static void axi_reset_internal_variables(
+	struct axi_ctrl_t *axi_ctrl)
+{
+	unsigned long flags;
+	/* state control variables */
+	axi_ctrl->share_ctrl->start_ack_pending = FALSE;
+	atomic_set(&irq_cnt, 0);
+
+	spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+	axi_ctrl->share_ctrl->stop_ack_pending  = FALSE;
+	spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+
+	spin_lock_irqsave(&axi_ctrl->share_ctrl->update_ack_lock, flags);
+	axi_ctrl->share_ctrl->update_ack_pending = FALSE;
+	spin_unlock_irqrestore(&axi_ctrl->share_ctrl->update_ack_lock, flags);
+
+	axi_ctrl->share_ctrl->recording_state = VFE_STATE_IDLE;
+	axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+	atomic_set(&axi_ctrl->share_ctrl->vstate, 0);
+	atomic_set(&axi_ctrl->share_ctrl->handle_common_irq, 0);
+	atomic_set(&axi_ctrl->share_ctrl->pix0_update_ack_pending, 0);
+	atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+	atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+	atomic_set(&axi_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
+
+	/* 0 for continuous mode, 1 for snapshot mode */
+	axi_ctrl->share_ctrl->operation_mode = 0;
+	axi_ctrl->share_ctrl->current_mode = 0;
+	axi_ctrl->share_ctrl->outpath.output_mode = 0;
+	axi_ctrl->share_ctrl->comp_output_mode = 0;
+	axi_ctrl->share_ctrl->vfe_capture_count = 0;
+
+	/* this is unsigned 32 bit integer. */
+	axi_ctrl->share_ctrl->vfeFrameId = 0;
+	axi_ctrl->share_ctrl->rdi0FrameId = 0;
+	axi_ctrl->share_ctrl->rdi1FrameId = 0;
+	axi_ctrl->share_ctrl->rdi2FrameId = 0;
+}
+
+static void vfe40_program_dmi_cfg(
+	enum VFE40_DMI_RAM_SEL bankSel,
+	struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	/* set bit 8 for auto increment. */
+	uint32_t value = VFE_DMI_CFG_DEFAULT;
+	value += (uint32_t)bankSel;
+	CDBG("%s: banksel = %d\n", __func__, bankSel);
+
+	msm_camera_io_w(value, vfe40_ctrl->share_ctrl->vfebase +
+		VFE_DMI_CFG);
+	/* by default, always starts with offset 0.*/
+	msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+		VFE_DMI_ADDR);
+}
+
+static void vfe40_reset_dmi_tables(
+	struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	int i = 0;
+
+	/* Reset Histogram LUTs */
+	CDBG("Reset Bayer histogram LUT : 0\n");
+	vfe40_program_dmi_cfg(STATS_BHIST_RAM0, vfe40_ctrl);
+	/* Loop for configuring LUT */
+	for (i = 0; i < 256; i++) {
+		msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_DMI_DATA_HI);
+		msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_DMI_DATA_LO);
+	}
+	vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+
+	CDBG("Reset Bayer Histogram LUT: 1\n");
+	vfe40_program_dmi_cfg(STATS_BHIST_RAM1, vfe40_ctrl);
+	/* Loop for configuring LUT */
+	for (i = 0; i < 256; i++) {
+		msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_DMI_DATA_HI);
+		msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_DMI_DATA_LO);
+	}
+	vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+
+	CDBG("Reset IHistogram LUT\n");
+	vfe40_program_dmi_cfg(STATS_IHIST_RAM, vfe40_ctrl);
+	/* Loop for configuring LUT */
+	for (i = 0; i < 256; i++) {
+		msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_DMI_DATA_HI);
+		msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_DMI_DATA_LO);
+	}
+	vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+}
+
+static void vfe40_set_default_reg_values(
+	struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	msm_camera_io_w(0x800080,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
+	msm_camera_io_w(0x800080,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+	msm_camera_io_w(0x198FFFFF,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
+
+	msm_camera_io_w(0,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MIN);
+	msm_camera_io_w(0xFFFFFF,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MAX);
+	msm_camera_io_w(0,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MIN);
+	msm_camera_io_w(0xFFFFFF,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MAX);
+
+	/* stats UB config */
+	CDBG("%s: Use bayer stats = %d\n", __func__,
+		 vfe40_use_bayer_stats(vfe40_ctrl));
+	msm_camera_io_w(0x350001F,
+	vfe40_ctrl->share_ctrl->vfebase +
+			VFE_BUS_STATS_HIST_WR_UB_CFG);
+	msm_camera_io_w(0x370002F,
+		vfe40_ctrl->share_ctrl->vfebase +
+			VFE_BUS_STATS_BG_WR_UB_CFG);
+	msm_camera_io_w(0x3A0002F,
+		vfe40_ctrl->share_ctrl->vfebase +
+			VFE_BUS_STATS_BF_WR_UB_CFG);
+	msm_camera_io_w(0x3D00007,
+		vfe40_ctrl->share_ctrl->vfebase +
+			VFE_BUS_STATS_RS_WR_UB_CFG);
+	msm_camera_io_w(0x3D8001F,
+		vfe40_ctrl->share_ctrl->vfebase +
+			VFE_BUS_STATS_CS_WR_UB_CFG);
+	msm_camera_io_w(0x3F80007,
+		vfe40_ctrl->share_ctrl->vfebase +
+			VFE_BUS_STATS_SKIN_WR_UB_CFG);
+	vfe40_reset_dmi_tables(vfe40_ctrl);
+}
+
 static void vfe40_reset_internal_variables(
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	unsigned long flags;
-	vfe40_ctrl->vfeImaskCompositePacked = 0;
-	/* state control variables */
-	vfe40_ctrl->start_ack_pending = FALSE;
-	atomic_set(&vfe40_ctrl->share_ctrl->irq_cnt, 0);
-
-	spin_lock_irqsave(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
-	vfe40_ctrl->share_ctrl->stop_ack_pending  = FALSE;
-	spin_unlock_irqrestore(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
-
-	vfe40_ctrl->reset_ack_pending  = FALSE;
-
-	spin_lock_irqsave(&vfe40_ctrl->update_ack_lock, flags);
-	vfe40_ctrl->update_ack_pending = FALSE;
-	spin_unlock_irqrestore(&vfe40_ctrl->update_ack_lock, flags);
-
-	vfe40_ctrl->recording_state = VFE_STATE_IDLE;
-	vfe40_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
-
-	atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
-
-	/* 0 for continuous mode, 1 for snapshot mode */
-	vfe40_ctrl->share_ctrl->operation_mode = 0;
-	vfe40_ctrl->share_ctrl->outpath.output_mode = 0;
-	vfe40_ctrl->share_ctrl->vfe_capture_count = 0;
-
-	/* this is unsigned 32 bit integer. */
-	vfe40_ctrl->share_ctrl->vfeFrameId = 0;
 	/* Stats control variables. */
-	memset(&(vfe40_ctrl->afStatsControl), 0,
+	memset(&(vfe40_ctrl->afbfStatsControl), 0,
 		sizeof(struct vfe_stats_control));
 
 	memset(&(vfe40_ctrl->awbStatsControl), 0,
 		sizeof(struct vfe_stats_control));
 
-	memset(&(vfe40_ctrl->aecStatsControl), 0,
+	memset(&(vfe40_ctrl->aecbgStatsControl), 0,
+		sizeof(struct vfe_stats_control));
+
+	memset(&(vfe40_ctrl->bhistStatsControl), 0,
 		sizeof(struct vfe_stats_control));
 
 	memset(&(vfe40_ctrl->ihistStatsControl), 0,
@@ -295,32 +870,59 @@
 	vfe40_ctrl->frame_skip_cnt = 31;
 	vfe40_ctrl->frame_skip_pattern = 0xffffffff;
 	vfe40_ctrl->snapshot_frame_cnt = 0;
+	vfe40_set_default_reg_values(vfe40_ctrl);
 }
 
-static void vfe40_reset(struct vfe40_ctrl_type *vfe40_ctrl)
+static int vfe40_reset(struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	vfe40_reset_internal_variables(vfe40_ctrl);
+	uint32_t irq_mask;
+	atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
+	msm_camera_io_w(VFE_MODULE_RESET_CMD,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+	msm_camera_io_w(0,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+
+	irq_mask =
+		msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+	irq_mask &= ~(0x00FF0011|VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0);
+
+	/* enable reset_ack interrupt.  */
+	irq_mask |= VFE_IMASK_WHILE_STOPPING_0;
+	msm_camera_io_w(irq_mask, vfe40_ctrl->share_ctrl->vfebase +
+		VFE_IRQ_MASK_0);
+
+	msm_camera_io_w_mb(VFE_ONLY_RESET_CMD,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+
+	return wait_for_completion_interruptible(
+			&vfe40_ctrl->share_ctrl->reset_complete);
+}
+
+static int axi_reset(struct axi_ctrl_t *axi_ctrl)
+{
+	axi_reset_internal_variables(axi_ctrl);
 	/* disable all interrupts.  vfeImaskLocal is also reset to 0
 	* to begin with. */
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
 
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* clear all pending interrupts*/
-	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
-	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+	msm_camera_io_w(VFE_CLEAR_ALL_IRQ0,
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+	msm_camera_io_w(VFE_CLEAR_ALL_IRQ1,
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
 
 	/* Ensure the write order while writing
 	to the command register using the barrier */
-	msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
+	msm_camera_io_w_mb(1, axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
 
 	/* enable reset_ack interrupt.  */
-	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_0,
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
 
 	/* Write to VFE_GLOBAL_RESET_CMD to reset the vfe hardware. Once reset
 	 * is done, hardware interrupt will be generated.  VFE ist processes
@@ -330,24 +932,10 @@
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(VFE_RESET_UPON_RESET_CMD,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+		axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
 
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_0);
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_1);
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_2);
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_3);
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_4);
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_5);
-	msm_camera_io_w(0xAAAAAAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_6);
-	msm_camera_io_w(0x0002AAAA,
-	vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_7);
+	return wait_for_completion_interruptible(
+			&axi_ctrl->share_ctrl->reset_complete);
 }
 
 static int vfe40_operation_config(uint32_t *cmd,
@@ -355,7 +943,6 @@
 {
 	uint32_t *p = cmd;
 
-	vfe40_ctrl->share_ctrl->operation_mode = *p;
 	vfe40_ctrl->share_ctrl->stats_comp = *(++p);
 	vfe40_ctrl->hfr_mode = *(++p);
 
@@ -364,19 +951,6 @@
 	msm_camera_io_w(*(++p),
 		vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 	msm_camera_io_w(*(++p),
-		vfe40_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
-	if (msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase +
-		V40_GET_HW_VERSION_OFF) ==
-		VFE40_HW_NUMBER) {
-		msm_camera_io_w(*(++p),
-			vfe40_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
-		msm_camera_io_w(*(++p),
-			vfe40_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG);
-	}  else {
-		++p;
-		++p;
-	}
-	msm_camera_io_w(*(++p),
 		vfe40_ctrl->share_ctrl->vfebase + VFE_REALIGN_BUF);
 	msm_camera_io_w(*(++p),
 		vfe40_ctrl->share_ctrl->vfebase + VFE_CHROMA_UP);
@@ -428,7 +1002,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe40_ctrl->stats_ops.enqueue_buf(
 				vfe40_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 		if (rc < 0) {
 			pr_err("%s: dq stats buf (type = %d) err = %d",
 				 __func__, stats_type, rc);
@@ -438,6 +1012,26 @@
 	return 0L;
 }
 
+
+static unsigned long vfe40_stats_unregbuf(
+	struct vfe40_ctrl_type *vfe40_ctrl,
+	struct msm_stats_reqbuf *req_buf, int domain_num)
+{
+	int i = 0, rc = 0;
+
+	for (i = 0; i < req_buf->num_buf; i++) {
+		rc = vfe40_ctrl->stats_ops.buf_unprepare(
+			vfe40_ctrl->stats_ops.stats_ctrl,
+			req_buf->stats_type, i,
+			vfe40_ctrl->stats_ops.client, domain_num);
+		if (rc < 0) {
+			pr_err("%s: unreg stats buf (type = %d) err = %d",
+				__func__, req_buf->stats_type, rc);
+		return rc;
+		}
+	}
+	return 0L;
+}
 static int vfe_stats_awb_buf_init(
 	struct vfe40_ctrl_type *vfe40_ctrl,
 	struct vfe_cmd_stats_buf *in)
@@ -469,14 +1063,18 @@
 	return 0;
 }
 
-static int vfe_stats_aec_buf_init(
-	struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_aec_bg_buf_init(
+	struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	uint32_t addr;
 	unsigned long flags;
+	uint32_t stats_type;
 
+	stats_type =
+		(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AEC
+			: MSM_STATS_TYPE_BG;
 	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
-	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AEC);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
 	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
 	if (!addr) {
 		pr_err("%s: dq aec ping buf from free buf queue",
@@ -485,9 +1083,9 @@
 	}
 	msm_camera_io_w(addr,
 		vfe40_ctrl->share_ctrl->vfebase +
-		VFE_BUS_STATS_AEC_WR_PING_ADDR);
+		VFE_BUS_STATS_BG_WR_PING_ADDR);
 	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
-	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AEC);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
 	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
 	if (!addr) {
 		pr_err("%s: dq aec pong buf from free buf queue",
@@ -496,26 +1094,31 @@
 	}
 	msm_camera_io_w(addr,
 		vfe40_ctrl->share_ctrl->vfebase +
-		VFE_BUS_STATS_AEC_WR_PONG_ADDR);
+		VFE_BUS_STATS_BG_WR_PONG_ADDR);
 	return 0;
 }
 
-static int vfe_stats_af_buf_init(
-	struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+static int vfe_stats_af_bf_buf_init(
+	struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	uint32_t addr;
 	unsigned long flags;
 	int rc = 0;
 
+	uint32_t stats_type;
+	stats_type =
+		(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+			: MSM_STATS_TYPE_BF;
+
 	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
-	rc = vfe40_stats_flush_enqueue(vfe40_ctrl, MSM_STATS_TYPE_AF);
+	rc = vfe40_stats_flush_enqueue(vfe40_ctrl, stats_type);
 	if (rc < 0) {
 		pr_err("%s: dq stats buf err = %d",
 			   __func__, rc);
 		spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
 		return -EINVAL;
 	}
-	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AF);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
 	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
 	if (!addr) {
 		pr_err("%s: dq af ping buf from free buf queue", __func__);
@@ -523,9 +1126,9 @@
 	}
 	msm_camera_io_w(addr,
 		vfe40_ctrl->share_ctrl->vfebase +
-		VFE_BUS_STATS_AF_WR_PING_ADDR);
+		VFE_BUS_STATS_BF_WR_PING_ADDR);
 	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
-	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AF);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
 	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
 	if (!addr) {
 		pr_err("%s: dq af pong buf from free buf queue", __func__);
@@ -533,13 +1136,44 @@
 	}
 	msm_camera_io_w(addr,
 		vfe40_ctrl->share_ctrl->vfebase +
-		VFE_BUS_STATS_AF_WR_PONG_ADDR);
+		VFE_BUS_STATS_BF_WR_PONG_ADDR);
+	return 0;
+}
+
+static uint32_t vfe_stats_bhist_buf_init(
+	struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	uint32_t addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_BHIST);
+	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+	if (!addr) {
+		pr_err("%s: dq ihist ping buf from free buf queue",
+			__func__);
+		return -ENOMEM;
+	}
+	msm_camera_io_w(addr,
+		vfe40_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_SKIN_WR_PING_ADDR);
+	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_BHIST);
+	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+	if (!addr) {
+		pr_err("%s: dq ihist pong buf from free buf queue",
+			__func__);
+		return -ENOMEM;
+	}
+	msm_camera_io_w(addr,
+		vfe40_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_SKIN_WR_PONG_ADDR);
 
 	return 0;
 }
 
 static int vfe_stats_ihist_buf_init(
-	struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+	struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	uint32_t addr;
 	unsigned long flags;
@@ -571,7 +1205,7 @@
 }
 
 static int vfe_stats_rs_buf_init(
-	struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+	struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	uint32_t addr;
 	unsigned long flags;
@@ -600,7 +1234,7 @@
 }
 
 static int vfe_stats_cs_buf_init(
-	struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+	struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	uint32_t addr;
 	unsigned long flags;
@@ -627,39 +1261,51 @@
 	return 0;
 }
 
+static void vfe40_cfg_qos_parms(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	void __iomem *vfebase = vfe40_ctrl->share_ctrl->vfebase;
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_0);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_1);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_2);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_3);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_4);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_5);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_6);
+	msm_camera_io_w(0x0002AAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_7);
+}
+
 static void vfe40_start_common(struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	uint32_t irq_mask = 0x1E000011;
-	vfe40_ctrl->start_ack_pending = TRUE;
+	uint16_t vfe_operation_mode =
+		vfe40_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+			VFE_OUTPUTS_RDI1);
 	CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
-		vfe40_ctrl->share_ctrl->operation_mode,
+		vfe40_ctrl->share_ctrl->current_mode,
 		vfe40_ctrl->share_ctrl->outpath.output_mode);
 
-	msm_camera_io_w(irq_mask,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
-	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+	vfe40_cfg_qos_parms(vfe40_ctrl);
 
-	/* Ensure the write order while writing
-	to the command register using the barrier */
+	msm_camera_io_w_mb(0x1,
+			vfe40_ctrl->share_ctrl->vfebase +
+			VFE_REG_UPDATE_CMD);
+
+	msm_camera_io_w_mb(0x00003fff,
+			vfe40_ctrl->share_ctrl->vfebase +
+			V40_AXI_BUS_CMD_OFF);
 	msm_camera_io_w_mb(1,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	msm_camera_io_w_mb(1,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
-	msm_camera_io_dump(vfe40_ctrl->share_ctrl->vfebase,
-		vfe40_ctrl->share_ctrl->register_total*4);
-
-	atomic_set(&vfe40_ctrl->share_ctrl->vstate, 1);
+			vfe40_ctrl->share_ctrl->vfebase +
+			V40_BUS_PM_CMD);
+	if (vfe_operation_mode) {
+		msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_CAMIF_COMMAND);
+	}
 }
 
 static int vfe40_start_recording(
 	struct msm_cam_media_controller *pmctl,
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
-	vfe40_ctrl->recording_state = VFE_STATE_START_REQUESTED;
+	vfe40_ctrl->share_ctrl->recording_state = VFE_STATE_START_REQUESTED;
 	msm_camera_io_w_mb(1,
 		vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	return 0;
@@ -669,11 +1315,9 @@
 	struct msm_cam_media_controller *pmctl,
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	vfe40_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
+	vfe40_ctrl->share_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
 	msm_camera_io_w_mb(1,
 		vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	return 0;
 }
 
@@ -691,100 +1335,22 @@
 		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 }
 
+static void vfe40_stop_liveshot(
+	struct msm_cam_media_controller *pmctl,
+	struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	vfe40_ctrl->share_ctrl->liveshot_state = VFE_STATE_STOP_REQUESTED;
+	msm_camera_io_w_mb(1,
+		vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
 static int vfe40_zsl(
 	struct msm_cam_media_controller *pmctl,
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	uint32_t irq_comp_mask = 0;
-	/* capture command is valid for both idle and active state. */
-	irq_comp_mask	=
-		msm_camera_io_r(vfe40_ctrl->
-		share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
-	CDBG("%s:op mode %d O/P Mode %d\n", __func__,
-		vfe40_ctrl->share_ctrl->operation_mode,
-		vfe40_ctrl->share_ctrl->outpath.output_mode);
-
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-		VFE40_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= (
-			(0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch0)) |
-			(0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch1)));
-	} else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			(0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch0)) |
-			(0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch1)) |
-			(0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch2)));
-	}
-
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-		VFE40_OUTPUT_MODE_SECONDARY) {
-		irq_comp_mask |= ((0x1 << (vfe40_ctrl->
-				share_ctrl->outpath.out1.ch0 + 8)) |
-			(0x1 << (vfe40_ctrl->
-				share_ctrl->outpath.out1.ch1 + 8)));
-	} else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			   VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			(0x1 << (vfe40_ctrl->
-				share_ctrl->outpath.out1.ch0 + 8)) |
-			(0x1 << (vfe40_ctrl->
-				share_ctrl->outpath.out1.ch1 + 8)) |
-			(0x1 << (vfe40_ctrl->
-				share_ctrl->outpath.out1.ch2 + 8)));
-	}
-
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_PRIMARY) {
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out0.ch0]);
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out0.ch1]);
-	} else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-				VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out0.ch0]);
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out0.ch1]);
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out0.ch2]);
-	}
-
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_SECONDARY) {
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out1.ch0]);
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out1.ch1]);
-	} else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-				VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out1.ch0]);
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out1.ch1]);
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out1.ch2]);
-	}
-
-	msm_camera_io_w(irq_comp_mask,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	vfe40_ctrl->share_ctrl->start_ack_pending = TRUE;
 	vfe40_start_common(vfe40_ctrl);
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
 
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x18C);
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x188);
 	return 0;
 }
 static int vfe40_capture_raw(
@@ -792,28 +1358,8 @@
 	struct vfe40_ctrl_type *vfe40_ctrl,
 	uint32_t num_frames_capture)
 {
-	uint32_t irq_comp_mask = 0;
-
 	vfe40_ctrl->share_ctrl->outpath.out0.capture_cnt = num_frames_capture;
 	vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
-
-	irq_comp_mask	=
-		msm_camera_io_r(
-			vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-		VFE40_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |=
-			(0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch0));
-		msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
-			share_ctrl->outpath.out0.ch0]);
-	}
-
-	msm_camera_io_w(irq_comp_mask,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 	vfe40_start_common(vfe40_ctrl);
 	return 0;
 }
@@ -823,79 +1369,25 @@
 	uint32_t num_frames_capture,
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	uint32_t irq_comp_mask = 0;
-
 	/* capture command is valid for both idle and active state. */
 	vfe40_ctrl->share_ctrl->outpath.out1.capture_cnt = num_frames_capture;
-	if (vfe40_ctrl->share_ctrl->operation_mode ==
+	if (vfe40_ctrl->share_ctrl->current_mode ==
 			VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe40_ctrl->share_ctrl->operation_mode ==
+		vfe40_ctrl->share_ctrl->current_mode ==
 			VFE_OUTPUTS_THUMB_AND_MAIN ||
-		vfe40_ctrl->share_ctrl->operation_mode ==
+		vfe40_ctrl->share_ctrl->current_mode ==
 			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe40_ctrl->share_ctrl->operation_mode ==
+		vfe40_ctrl->share_ctrl->current_mode ==
 			VFE_OUTPUTS_THUMB_AND_JPEG) {
 		vfe40_ctrl->share_ctrl->outpath.out0.capture_cnt =
 			num_frames_capture;
 	}
 
 	vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
-	irq_comp_mask = msm_camera_io_r(
-			vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
-	if (vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_THUMB_AND_MAIN) {
-		if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_PRIMARY) {
-			irq_comp_mask |= (0x1 << vfe40_ctrl->
-				share_ctrl->outpath.out0.ch0 |
-				0x1 << vfe40_ctrl->
-				share_ctrl->outpath.out0.ch1);
-		}
-		if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_SECONDARY) {
-			irq_comp_mask |=
-				(0x1 << (vfe40_ctrl->
-					share_ctrl->outpath.out1.ch0 + 8) |
-				0x1 << (vfe40_ctrl->
-					share_ctrl->outpath.out1.ch1 + 8));
-		}
-		if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
-				share_ctrl->outpath.out0.ch1]);
-		}
-		if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_SECONDARY) {
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
-				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
-				share_ctrl->outpath.out1.ch1]);
-		}
-	}
-
-	vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
-
-	msm_camera_io_w(irq_comp_mask,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 
 	vfe40_start_common(vfe40_ctrl);
 	/* for debug */
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x18C);
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x188);
 	return 0;
 }
 
@@ -903,41 +1395,6 @@
 	struct msm_cam_media_controller *pmctl,
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	uint32_t irq_comp_mask = 0;
-	irq_comp_mask	=
-		msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_COMP_MASK);
-
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= (
-			0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch1);
-	} else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			   VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch1 |
-			0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch2);
-	}
-	if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_SECONDARY) {
-		irq_comp_mask |= (
-			0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch1 + 8));
-	} else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
-			0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch2 + 8));
-	}
-	msm_camera_io_w(irq_comp_mask,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
-	/*
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);*/
 	vfe40_start_common(vfe40_ctrl);
 	return 0;
 }
@@ -980,9 +1437,9 @@
 		vfe40_ctrl->update_gamma = false;
 	}
 
-	spin_lock_irqsave(&vfe40_ctrl->update_ack_lock, flags);
-	vfe40_ctrl->update_ack_pending = TRUE;
-	spin_unlock_irqrestore(&vfe40_ctrl->update_ack_lock, flags);
+	spin_lock_irqsave(&vfe40_ctrl->share_ctrl->update_ack_lock, flags);
+	vfe40_ctrl->share_ctrl->update_ack_pending = TRUE;
+	spin_unlock_irqrestore(&vfe40_ctrl->share_ctrl->update_ack_lock, flags);
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(1,
@@ -1044,7 +1501,7 @@
 			 8 + ((vfe40_ctrl->sync_timer_number) * 12));
 	/* Sync Timer Pixel Duration */
 	value = *tbl++;
-	val = vfe40_ctrl->share_ctrl->vfe_clk_rate / 10000;
+	val = vfe_clk_rate / 10000;
 	val = 10000000 / val;
 	val = value * 10000 / val;
 	CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
@@ -1061,19 +1518,7 @@
 		vfe40_ctrl->share_ctrl->vfebase + V40_TIMER_SELECT_OFF);
 }
 
-static void vfe40_program_dmi_cfg(
-	enum VFE40_DMI_RAM_SEL bankSel,
-	struct vfe40_ctrl_type *vfe40_ctrl)
-{
-	/* set bit 8 for auto increment. */
-	uint32_t value = VFE_DMI_CFG_DEFAULT;
-	value += (uint32_t)bankSel;
-	CDBG("%s: banksel = %d\n", __func__, bankSel);
 
-	msm_camera_io_w(value, vfe40_ctrl->share_ctrl->vfebase + VFE_DMI_CFG);
-	/* by default, always starts with offset 0.*/
-	msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
-}
 static void vfe40_write_gamma_cfg(
 	enum VFE40_DMI_RAM_SEL channel_sel,
 	const uint32_t *tbl,
@@ -1132,7 +1577,7 @@
 	vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
 }
 
-struct vfe40_output_ch *vfe40_get_ch(
+static struct vfe40_output_ch *vfe40_get_ch(
 	int path, struct vfe_share_ctrl_t *share_ctrl)
 {
 	struct vfe40_output_ch *ch = NULL;
@@ -1141,6 +1586,10 @@
 		ch = &share_ctrl->outpath.out0;
 	else if (path == VFE_MSG_OUTPUT_SECONDARY)
 		ch = &share_ctrl->outpath.out1;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY1)
+		ch = &share_ctrl->outpath.out2;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+		ch = &share_ctrl->outpath.out3;
 	else
 		pr_err("%s: Invalid path %d\n", __func__,
 			path);
@@ -1148,49 +1597,76 @@
 	BUG_ON(ch == NULL);
 	return ch;
 }
+static struct msm_free_buf *vfe40_check_free_buffer(
+	int id, int path, struct axi_ctrl_t *axi_ctrl)
+{
+	struct vfe40_output_ch *outch = NULL;
+	struct msm_free_buf *b = NULL;
+	uint32_t inst_handle = 0;
 
-static int vfe40_configure_pingpong_buffers(
-	int id, int path, struct vfe40_ctrl_type *vfe40_ctrl)
+	if (path == VFE_MSG_OUTPUT_PRIMARY)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_SECONDARY)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out1.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY1)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
+
+	vfe40_subdev_notify(id, path, inst_handle,
+		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
+	outch = vfe40_get_ch(path, axi_ctrl->share_ctrl);
+	if (outch->free_buf.ch_paddr[0])
+		b = &outch->free_buf;
+	return b;
+}
+static int configure_pingpong_buffers(
+	int id, int path, struct axi_ctrl_t *axi_ctrl)
 {
 	struct vfe40_output_ch *outch = NULL;
 	int rc = 0;
-	uint32_t image_mode = 0;
+	uint32_t inst_handle = 0;
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
-		image_mode = vfe40_ctrl->share_ctrl->outpath.out0.image_mode;
-	else
-		image_mode = vfe40_ctrl->share_ctrl->outpath.out1.image_mode;
+		inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_SECONDARY)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out1.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY1)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
+	else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+		inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
 
-	vfe40_subdev_notify(id, path, image_mode,
-		&vfe40_ctrl->subdev, vfe40_ctrl->share_ctrl);
-	outch = vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+	vfe40_subdev_notify(id, path, inst_handle,
+		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
+	outch = vfe40_get_ch(path, axi_ctrl->share_ctrl);
 	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
 		/* Configure Preview Ping Pong */
-		CDBG("%s Configure ping/pong address for %d",
+		pr_info("%s Configure ping/pong address for %d\n",
 						__func__, path);
 		vfe40_put_ch_ping_addr(
-			vfe40_ctrl->share_ctrl->vfebase, outch->ch0,
+			axi_ctrl->share_ctrl->vfebase, outch->ch0,
 			outch->ping.ch_paddr[0]);
 		vfe40_put_ch_pong_addr(
-			vfe40_ctrl->share_ctrl->vfebase, outch->ch0,
+			axi_ctrl->share_ctrl->vfebase, outch->ch0,
 			outch->pong.ch_paddr[0]);
 
-		if (vfe40_ctrl->share_ctrl->operation_mode !=
-			VFE_OUTPUTS_RAW) {
+		if ((axi_ctrl->share_ctrl->current_mode !=
+			VFE_OUTPUTS_RAW) && (path != VFE_MSG_OUTPUT_TERTIARY1)
+			&& (path != VFE_MSG_OUTPUT_TERTIARY2)) {
 			vfe40_put_ch_ping_addr(
-				vfe40_ctrl->share_ctrl->vfebase, outch->ch1,
+				axi_ctrl->share_ctrl->vfebase, outch->ch1,
 				outch->ping.ch_paddr[1]);
 			vfe40_put_ch_pong_addr(
-				vfe40_ctrl->share_ctrl->vfebase, outch->ch1,
+				axi_ctrl->share_ctrl->vfebase, outch->ch1,
 				outch->pong.ch_paddr[1]);
 		}
 
 		if (outch->ping.num_planes > 2)
 			vfe40_put_ch_ping_addr(
-				vfe40_ctrl->share_ctrl->vfebase, outch->ch2,
+				axi_ctrl->share_ctrl->vfebase, outch->ch2,
 				outch->ping.ch_paddr[2]);
 		if (outch->pong.num_planes > 2)
 			vfe40_put_ch_pong_addr(
-				vfe40_ctrl->share_ctrl->vfebase, outch->ch2,
+				axi_ctrl->share_ctrl->vfebase, outch->ch2,
 				outch->pong.ch_paddr[2]);
 
 		/* avoid stale info */
@@ -1220,7 +1696,7 @@
 	vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
 }
 
-void vfe40_send_isp_msg(
+static void vfe40_send_isp_msg(
 	struct v4l2_subdev *sd,
 	uint32_t vfeFrameId,
 	uint32_t isp_msg_id)
@@ -1240,142 +1716,76 @@
 	struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	int i , rc = 0;
-	uint32_t old_val = 0 , new_val = 0;
+	uint32_t old_val = 0 , new_val = 0, module_val = 0;
 	uint32_t *cmdp = NULL;
 	uint32_t *cmdp_local = NULL;
 	uint32_t snapshot_cnt = 0;
 	uint32_t temp1 = 0, temp2 = 0;
+	struct msm_camera_vfe_params_t vfe_params;
 
 	CDBG("vfe40_proc_general: cmdID = %s, length = %d\n",
 		vfe40_general_cmd[cmd->id], cmd->length);
 	switch (cmd->id) {
 	case VFE_CMD_RESET:
-		CDBG("vfe40_proc_general: cmdID = %s\n",
+		pr_info("vfe40_proc_general: cmdID = %s\n",
 			vfe40_general_cmd[cmd->id]);
+		vfe40_ctrl->share_ctrl->vfe_reset_flag = true;
 		vfe40_reset(vfe40_ctrl);
 		break;
 	case VFE_CMD_START:
-		CDBG("vfe40_proc_general: cmdID = %s\n",
+		pr_info("vfe40_proc_general: cmdID = %s\n",
 			vfe40_general_cmd[cmd->id]);
-		if ((vfe40_ctrl->share_ctrl->operation_mode ==
-				VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
-				(vfe40_ctrl->share_ctrl->operation_mode ==
-				VFE_OUTPUTS_PREVIEW))
-			/* Configure primary channel */
-			rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_START, VFE_MSG_OUTPUT_PRIMARY,
-				vfe40_ctrl);
-		else
-			/* Configure secondary channel */
-			rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_START, VFE_MSG_OUTPUT_SECONDARY,
-				vfe40_ctrl);
-		if (rc < 0) {
-			pr_err(
-				"%s error configuring pingpong buffers for preview",
-				__func__);
-			rc = -EINVAL;
-			goto proc_general_done;
+		if (copy_from_user(&vfe_params,
+				(void __user *)(cmd->value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				rc = -EFAULT;
+				goto proc_general_done;
 		}
 
+		vfe40_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
+
 		rc = vfe40_start(pmctl, vfe40_ctrl);
 		break;
 	case VFE_CMD_UPDATE:
 		vfe40_update(vfe40_ctrl);
 		break;
 	case VFE_CMD_CAPTURE_RAW:
-		CDBG("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
-		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
-				sizeof(uint32_t))) {
-			rc = -EFAULT;
-			goto proc_general_done;
+		pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
+		if (copy_from_user(&vfe_params,
+				(void __user *)(cmd->value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				rc = -EFAULT;
+				goto proc_general_done;
 		}
-		rc = vfe40_configure_pingpong_buffers(
-			VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
-			vfe40_ctrl);
-		if (rc < 0) {
-			pr_err(
-				"%s error configuring pingpong buffers for snapshot",
-				__func__);
-			rc = -EINVAL;
-			goto proc_general_done;
-		}
+
+		snapshot_cnt = vfe_params.capture_count;
+		vfe40_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
 		rc = vfe40_capture_raw(pmctl, vfe40_ctrl, snapshot_cnt);
 		break;
 	case VFE_CMD_CAPTURE:
-		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
-				sizeof(uint32_t))) {
-			rc = -EFAULT;
-			goto proc_general_done;
+		pr_info("%s: cmdID = VFE_CMD_CAPTURE\n", __func__);
+		if (copy_from_user(&vfe_params,
+				(void __user *)(cmd->value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				rc = -EFAULT;
+				goto proc_general_done;
 		}
 
-		if (vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_THUMB_AND_JPEG) {
-			if (snapshot_cnt != 1) {
-				pr_err("only support 1 inline snapshot\n");
-				rc = -EINVAL;
-				goto proc_general_done;
-			}
-			/* Configure primary channel for JPEG */
-			rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_JPEG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY,
-				vfe40_ctrl);
-		} else {
-			/* Configure primary channel */
-			rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY,
-				vfe40_ctrl);
-		}
-		if (rc < 0) {
-			pr_err(
-			"%s error configuring pingpong buffers for primary output",
-			__func__);
-			rc = -EINVAL;
-			goto proc_general_done;
-		}
-		/* Configure secondary channel */
-		rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
-				vfe40_ctrl);
-		if (rc < 0) {
-			pr_err(
-			"%s error configuring pingpong buffers for secondary output",
-			__func__);
-			rc = -EINVAL;
-			goto proc_general_done;
-		}
+		snapshot_cnt = vfe_params.capture_count;
+		vfe40_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
+
 		rc = vfe40_capture(pmctl, snapshot_cnt, vfe40_ctrl);
 		break;
 	case VFE_CMD_START_RECORDING:
-		CDBG("vfe40_proc_general: cmdID = %s\n",
+		pr_info("vfe40_proc_general: cmdID = %s\n",
 			vfe40_general_cmd[cmd->id]);
-		if (vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_PREVIEW_AND_VIDEO)
-			rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_START_RECORDING,
-				VFE_MSG_OUTPUT_SECONDARY,
-				vfe40_ctrl);
-		else if (vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_VIDEO_AND_PREVIEW)
-			rc = vfe40_configure_pingpong_buffers(
-				VFE_MSG_START_RECORDING,
-				VFE_MSG_OUTPUT_PRIMARY,
-				vfe40_ctrl);
-		if (rc < 0) {
-			pr_err(
-				"%s error configuring pingpong buffers for video\n",
-				__func__);
-			rc = -EINVAL;
-			goto proc_general_done;
-		}
 		rc = vfe40_start_recording(pmctl, vfe40_ctrl);
 		break;
 	case VFE_CMD_STOP_RECORDING:
-		CDBG("vfe40_proc_general: cmdID = %s\n",
+		pr_info("vfe40_proc_general: cmdID = %s\n",
 			vfe40_general_cmd[cmd->id]);
 		rc = vfe40_stop_recording(pmctl, vfe40_ctrl);
 		break;
@@ -1396,7 +1806,12 @@
 		break;
 
 	case VFE_CMD_STATS_AE_START: {
-		rc = vfe_stats_aec_buf_init(vfe40_ctrl, NULL);
+		if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		rc = vfe_stats_aec_bg_buf_init(vfe40_ctrl);
 		if (rc < 0) {
 			pr_err("%s: cannot config ping/pong address of AEC",
 				 __func__);
@@ -1425,7 +1840,12 @@
 		}
 		break;
 	case VFE_CMD_STATS_AF_START: {
-		rc = vfe_stats_af_buf_init(vfe40_ctrl, NULL);
+		if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		rc = vfe_stats_af_bf_buf_init(vfe40_ctrl);
 		if (rc < 0) {
 			pr_err("%s: cannot config ping/pong address of AF",
 				__func__);
@@ -1453,8 +1873,12 @@
 			cmdp, (vfe40_cmd[cmd->id].length));
 		}
 		break;
-
 	case VFE_CMD_STATS_AWB_START: {
+		if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
 		rc = vfe_stats_awb_buf_init(vfe40_ctrl, NULL);
 		if (rc < 0) {
 			pr_err("%s: cannot config ping/pong address of AWB",
@@ -1485,7 +1909,7 @@
 		break;
 
 	case VFE_CMD_STATS_IHIST_START: {
-		rc = vfe_stats_ihist_buf_init(vfe40_ctrl, NULL);
+		rc = vfe_stats_ihist_buf_init(vfe40_ctrl);
 		if (rc < 0) {
 			pr_err("%s: cannot config ping/pong address of IHIST",
 				 __func__);
@@ -1516,7 +1940,7 @@
 
 
 	case VFE_CMD_STATS_RS_START: {
-		rc = vfe_stats_rs_buf_init(vfe40_ctrl, NULL);
+		rc = vfe_stats_rs_buf_init(vfe40_ctrl);
 		if (rc < 0) {
 			pr_err("%s: cannot config ping/pong address of RS",
 				__func__);
@@ -1541,7 +1965,7 @@
 		break;
 
 	case VFE_CMD_STATS_CS_START: {
-		rc = vfe_stats_cs_buf_init(vfe40_ctrl, NULL);
+		rc = vfe_stats_cs_buf_init(vfe40_ctrl);
 		if (rc < 0) {
 			pr_err("%s: cannot config ping/pong address of CS",
 				__func__);
@@ -1565,6 +1989,65 @@
 		}
 		break;
 
+	case VFE_CMD_STATS_BG_START:
+	case VFE_CMD_STATS_BF_START:
+	case VFE_CMD_STATS_BHIST_START: {
+		if (!vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		old_val = msm_camera_io_r(
+			vfe40_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
+		module_val = msm_camera_io_r(
+			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
+		if (VFE_CMD_STATS_BG_START == cmd->id) {
+			module_val |= BG_ENABLE_MASK;
+			rc = vfe_stats_aec_bg_buf_init(vfe40_ctrl);
+			if (rc < 0) {
+				pr_err("%s: cannot config ping/pong address of CS",
+					__func__);
+				goto proc_general_done;
+			}
+		} else if (VFE_CMD_STATS_BF_START == cmd->id) {
+			module_val |= BF_ENABLE_MASK;
+			rc = vfe_stats_af_bf_buf_init(vfe40_ctrl);
+			if (rc < 0) {
+				pr_err("%s: cannot config ping/pong address of CS",
+					__func__);
+				goto proc_general_done;
+			}
+		} else {
+			module_val |= BHIST_ENABLE_MASK;
+			old_val |= STATS_BHIST_ENABLE_MASK;
+			rc = vfe_stats_bhist_buf_init(vfe40_ctrl);
+			if (rc < 0) {
+				pr_err("%s: cannot config ping/pong address of CS",
+					__func__);
+				goto proc_general_done;
+			}
+		}
+		msm_camera_io_w(old_val, vfe40_ctrl->share_ctrl->vfebase +
+			VFE_STATS_CFG);
+		msm_camera_io_w(module_val,
+			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
+		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+		if (!cmdp) {
+			rc = -ENOMEM;
+			goto proc_general_done;
+		}
+		if (copy_from_user(cmdp,
+				(void __user *)(cmd->value),
+				cmd->length)) {
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		msm_camera_io_memcpy(
+			vfe40_ctrl->share_ctrl->vfebase +
+			vfe40_cmd[cmd->id].offset,
+			cmdp, (vfe40_cmd[cmd->id].length));
+		}
+		break;
 	case VFE_CMD_MCE_UPDATE:
 	case VFE_CMD_MCE_CFG:{
 		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
@@ -1651,6 +2134,38 @@
 		rc = -EFAULT;
 		goto proc_general_done;
 
+	case VFE_CMD_MESH_ROLL_OFF_CFG: {
+		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+		if (!cmdp) {
+			rc = -ENOMEM;
+			goto proc_general_done;
+		}
+		if (copy_from_user(cmdp,
+			(void __user *)(cmd->value) , cmd->length)) {
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		cmdp_local = cmdp;
+		msm_camera_io_memcpy(
+			vfe40_ctrl->share_ctrl->vfebase +
+			vfe40_cmd[cmd->id].offset,
+			cmdp_local, V40_MESH_ROLL_OFF_CFG_LEN);
+		cmdp_local += 9;
+		vfe40_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe40_ctrl);
+		/* for loop for extrcting table. */
+		for (i = 0; i < (V40_MESH_ROLL_OFF_TABLE_SIZE * 2); i++) {
+			msm_camera_io_w(*cmdp_local,
+				vfe40_ctrl->share_ctrl->vfebase +
+				VFE_DMI_DATA_LO);
+			cmdp_local++;
+		}
+		CDBG("done writing mesh table\n");
+		vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+	}
+	break;
+	case VFE_CMD_GET_MESH_ROLLOFF_TABLE:
+		break;
+
 	case VFE_CMD_LA_CFG:
 		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
 		if (!cmdp) {
@@ -1759,15 +2274,6 @@
 
 	case VFE_CMD_LIVESHOT:
 		/* Configure primary channel */
-		rc = vfe40_configure_pingpong_buffers(VFE_MSG_CAPTURE,
-					VFE_MSG_OUTPUT_PRIMARY, vfe40_ctrl);
-		if (rc < 0) {
-			pr_err(
-			"%s error configuring pingpong buffers for primary output\n",
-			__func__);
-			rc = -EINVAL;
-			goto proc_general_done;
-		}
 		vfe40_start_liveshot(pmctl, vfe40_ctrl);
 		break;
 
@@ -1787,7 +2293,6 @@
 			vfe40_ctrl->share_ctrl->vfebase +
 			V40_LINEARIZATION_OFF1,
 			cmdp_local, V40_LINEARIZATION_LEN1);
-
 		cmdp_local = cmdp + 17;
 		vfe40_write_linear_cfg(BLACK_LUT_RAM_BANK0,
 					cmdp_local, vfe40_ctrl);
@@ -2139,6 +2644,11 @@
 		break;
 
 	case VFE_CMD_STATS_AWB_STOP: {
+		if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
 		old_val = msm_camera_io_r(
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~AWB_ENABLE_MASK;
@@ -2146,27 +2656,30 @@
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
-
 	case VFE_CMD_STATS_AE_STOP: {
+		if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
 		old_val = msm_camera_io_r(
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
-		old_val &= ~BG_ENABLE_MASK;
+		old_val &= BG_ENABLE_MASK;
 		msm_camera_io_w(old_val,
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 	case VFE_CMD_STATS_AF_STOP: {
+		if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
 		old_val = msm_camera_io_r(
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~BF_ENABLE_MASK;
 		msm_camera_io_w(old_val,
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
-		rc = vfe40_stats_flush_enqueue(vfe40_ctrl, MSM_STATS_TYPE_AF);
-		if (rc < 0) {
-			pr_err("%s: dq stats buf err = %d",
-				   __func__, rc);
-			return -EINVAL;
-		}
 		}
 		break;
 
@@ -2196,9 +2709,47 @@
 			vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
+
+	case VFE_CMD_STATS_BG_STOP:
+	case VFE_CMD_STATS_BF_STOP:
+	case VFE_CMD_STATS_BHIST_STOP: {
+		if (!vfe40_use_bayer_stats(vfe40_ctrl)) {
+			/* Error */
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		old_val = msm_camera_io_r(
+			vfe40_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
+
+		if (VFE_CMD_STATS_BHIST_STOP == cmd->id)
+			old_val &= ~STATS_BHIST_ENABLE_MASK;
+
+		msm_camera_io_w(old_val,
+			vfe40_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
+		if (VFE_CMD_STATS_BF_STOP == cmd->id) {
+			rc = vfe40_stats_flush_enqueue(vfe40_ctrl,
+					MSM_STATS_TYPE_BF);
+			if (rc < 0) {
+				pr_err("%s: dq stats buf err = %d",
+					   __func__, rc);
+				return -EINVAL;
+			}
+		}
+		}
+		break;
+
 	case VFE_CMD_STOP:
-		CDBG("vfe40_proc_general: cmdID = %s\n",
+		pr_info("vfe40_proc_general: cmdID = %s\n",
 			vfe40_general_cmd[cmd->id]);
+		if (copy_from_user(&vfe_params,
+				(void __user *)(cmd->value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				rc = -EFAULT;
+				goto proc_general_done;
+		}
+
+		vfe40_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
 		vfe40_stop(vfe40_ctrl);
 		break;
 
@@ -2242,14 +2793,15 @@
 		break;
 
 	case VFE_CMD_ZSL:
-		rc = vfe40_configure_pingpong_buffers(VFE_MSG_START,
-			VFE_MSG_OUTPUT_PRIMARY, vfe40_ctrl);
-		if (rc < 0)
-			goto proc_general_done;
-		rc = vfe40_configure_pingpong_buffers(VFE_MSG_START,
-			VFE_MSG_OUTPUT_SECONDARY, vfe40_ctrl);
-		if (rc < 0)
-			goto proc_general_done;
+		if (copy_from_user(&vfe_params,
+				(void __user *)(cmd->value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				rc = -EFAULT;
+				goto proc_general_done;
+		}
+
+		vfe40_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
 
 		rc = vfe40_zsl(pmctl, vfe40_ctrl);
 		break;
@@ -2344,6 +2896,10 @@
 			*cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
 		vfe40_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
 		break;
+	case VFE_CMD_STOP_LIVESHOT:
+		CDBG("%s Stopping liveshot ", __func__);
+		vfe40_stop_liveshot(pmctl, vfe40_ctrl);
+		break;
 	default:
 		if (cmd->length != vfe40_cmd[cmd->id].length)
 			return -EINVAL;
@@ -2402,176 +2958,435 @@
 
 }
 
+void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t operation_mode =
+	share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+		VFE_OUTPUTS_RDI1);
+	uint32_t irq_comp_mask, irq_mask;
+	uint32_t reg_update = 0x1;
+
+	irq_comp_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+
+	switch (share_ctrl->cmd_type) {
+	case AXI_CMD_PREVIEW: {
+		switch (operation_mode) {
+		case VFE_OUTPUTS_PREVIEW:
+		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+			if (share_ctrl->comp_output_mode &
+				VFE40_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch1]);
+				irq_comp_mask &= ~(
+					0x1 << share_ctrl->outpath.out0.ch0 |
+					0x1 << share_ctrl->outpath.out0.ch1);
+				share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_PRIMARY;
+			} else if (share_ctrl->comp_output_mode &
+					VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch1]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out0.ch2]);
+				irq_comp_mask &= ~(
+					0x1 << share_ctrl->outpath.out0.ch0 |
+					0x1 << share_ctrl->outpath.out0.ch1 |
+					0x1 << share_ctrl->outpath.out0.ch2);
+				share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+			}
+			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+			break;
+		default:
+			if (share_ctrl->comp_output_mode &
+				VFE40_OUTPUT_MODE_SECONDARY) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch1]);
+				irq_comp_mask &= ~(
+					0x1 << share_ctrl->outpath.out1.ch0 |
+					0x1 << share_ctrl->outpath.out1.ch1);
+				share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_SECONDARY;
+			} else if (share_ctrl->comp_output_mode &
+				VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch1]);
+				msm_camera_io_w(0, share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[share_ctrl->
+					outpath.out1.ch2]);
+				irq_comp_mask &= ~(
+					0x1 << share_ctrl->outpath.out1.ch0 |
+					0x1 << share_ctrl->outpath.out1.ch1 |
+					0x1 << share_ctrl->outpath.out1.ch2);
+				share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+			}
+			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+			break;
+			}
+		}
+		break;
+	default:
+		if (share_ctrl->comp_output_mode &
+			VFE40_OUTPUT_MODE_PRIMARY) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch1]);
+			irq_comp_mask &= ~(
+				0x1 << share_ctrl->outpath.out0.ch0 |
+				0x1 << share_ctrl->outpath.out0.ch1);
+			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+			share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_PRIMARY;
+		} else if (share_ctrl->comp_output_mode &
+				VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch1]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->
+				outpath.out0.ch2]);
+			irq_comp_mask &= ~(
+				0x1 << share_ctrl->outpath.out0.ch0 |
+				0x1 << share_ctrl->outpath.out0.ch1 |
+				0x1 << share_ctrl->outpath.out0.ch2);
+			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+			share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+		}
+
+		if (share_ctrl->comp_output_mode &
+			VFE40_OUTPUT_MODE_SECONDARY) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->
+				outpath.out1.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+			irq_comp_mask &= ~(
+				0x1 << share_ctrl->outpath.out1.ch0 |
+				0x1 << share_ctrl->outpath.out1.ch1);
+			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+			share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_SECONDARY;
+		} else if (share_ctrl->comp_output_mode &
+			VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(0, share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch2]);
+			irq_comp_mask &= ~(
+				0x1 << share_ctrl->outpath.out1.ch0 |
+				0x1 << share_ctrl->outpath.out1.ch1 |
+				0x1 << share_ctrl->outpath.out1.ch2);
+			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+			share_ctrl->outpath.output_mode |=
+					VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+		}
+		break;
+	}
+
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w(irq_comp_mask,
+		share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+}
+
+void axi_stop_rdi0(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t reg_update = 0x2;
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		msm_camera_io_w(0, share_ctrl->vfebase +
+			vfe40_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
+		irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
+				VFE_WM_OFFSET));
+	}
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+}
+
+void axi_stop_rdi1(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t reg_update = 0x4;
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		msm_camera_io_w(1, share_ctrl->vfebase +
+			vfe40_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
+		irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
+			VFE_WM_OFFSET));
+	}
+	msm_camera_io_w_mb(reg_update,
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+}
+
+void axi_stop_process(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t operation_mode =
+	share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+		VFE_OUTPUTS_RDI1);
+
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		axi_stop_rdi0(share_ctrl);
+		share_ctrl->comp_output_mode &= ~VFE40_OUTPUT_MODE_TERTIARY1;
+	}
+	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		axi_stop_rdi1(share_ctrl);
+		share_ctrl->comp_output_mode &= ~VFE40_OUTPUT_MODE_TERTIARY2;
+	}
+	if (operation_mode) {
+		axi_stop_pix(share_ctrl);
+		share_ctrl->comp_output_mode &=
+				~(share_ctrl->outpath.output_mode);
+	}
+}
+
 static void vfe40_process_reg_update_irq(
 		struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	unsigned long flags;
+	struct vfe_share_ctrl_t *share_ctrl = vfe40_ctrl->share_ctrl;
 
-	if (vfe40_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
-		if (vfe40_ctrl->share_ctrl->operation_mode ==
+	if (atomic_cmpxchg(
+		&share_ctrl->pix0_update_ack_pending, 2, 0) == 2) {
+		axi_stop_pix(share_ctrl);
+		msm_camera_io_w_mb(
+				CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+				share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+		axi_disable_irq(share_ctrl);
+		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+			share_ctrl->vfeFrameId,
+			MSG_ID_PIX0_UPDATE_ACK);
+		share_ctrl->comp_output_mode &=
+				~(share_ctrl->outpath.output_mode);
+		share_ctrl->current_mode &=
+			(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
+	}  else {
+		if (share_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
+			if (share_ctrl->operation_mode &
 				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch1]);
-		} else if (vfe40_ctrl->share_ctrl->operation_mode ==
+			} else if (share_ctrl->operation_mode &
 				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(1,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out1.ch1]);
 		}
-		vfe40_ctrl->recording_state = VFE_STATE_STARTED;
+			share_ctrl->recording_state = VFE_STATE_STARTED;
 		msm_camera_io_w_mb(1,
-			vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+				share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 		CDBG("start video triggered .\n");
-	} else if (vfe40_ctrl->recording_state ==
+		} else if (share_ctrl->recording_state ==
 			VFE_STATE_STOP_REQUESTED) {
-		if (vfe40_ctrl->share_ctrl->operation_mode ==
+			if (share_ctrl->operation_mode &
 				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
-			msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch1]);
-		} else if (vfe40_ctrl->share_ctrl->operation_mode ==
+			} else if (share_ctrl->operation_mode &
 				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
-			msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(0,
+					share_ctrl->vfebase + vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out1.ch1]);
 		}
 		CDBG("stop video triggered .\n");
 	}
 
-	if (vfe40_ctrl->start_ack_pending == TRUE) {
+		if (atomic_cmpxchg(
+			&share_ctrl->pix0_update_ack_pending, 1, 0) == 1) {
+			share_ctrl->comp_output_mode |=
+				(share_ctrl->outpath.output_mode
+				& ~(VFE40_OUTPUT_MODE_TERTIARY1|
+					VFE40_OUTPUT_MODE_TERTIARY2));
 		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
-			vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
-		vfe40_ctrl->start_ack_pending = FALSE;
+				share_ctrl->vfeFrameId, MSG_ID_PIX0_UPDATE_ACK);
+			share_ctrl->current_mode &=
+				(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
 	} else {
-		if (vfe40_ctrl->recording_state ==
-				VFE_STATE_STOP_REQUESTED) {
-			vfe40_ctrl->recording_state = VFE_STATE_STOPPED;
+		if (share_ctrl->recording_state ==
+			VFE_STATE_STOP_REQUESTED) {
+				share_ctrl->recording_state = VFE_STATE_STOPPED;
 			/* request a reg update and send STOP_REC_ACK
 			 * when we process the next reg update irq.
 			 */
-			msm_camera_io_w_mb(1,
-			vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-		} else if (vfe40_ctrl->recording_state ==
+			msm_camera_io_w_mb(1, share_ctrl->vfebase +
+						VFE_REG_UPDATE_CMD);
+		} else if (share_ctrl->recording_state ==
 					VFE_STATE_STOPPED) {
 			vfe40_send_isp_msg(&vfe40_ctrl->subdev,
-				vfe40_ctrl->share_ctrl->vfeFrameId,
+					share_ctrl->vfeFrameId,
 				MSG_ID_STOP_REC_ACK);
-			vfe40_ctrl->recording_state = VFE_STATE_IDLE;
+				share_ctrl->recording_state = VFE_STATE_IDLE;
 		}
-		spin_lock_irqsave(&vfe40_ctrl->update_ack_lock, flags);
-		if (vfe40_ctrl->update_ack_pending == TRUE) {
-			vfe40_ctrl->update_ack_pending = FALSE;
+		spin_lock_irqsave(&share_ctrl->update_ack_lock, flags);
+		if (share_ctrl->update_ack_pending == TRUE) {
+			share_ctrl->update_ack_pending = FALSE;
 			spin_unlock_irqrestore(
-				&vfe40_ctrl->update_ack_lock, flags);
+				&share_ctrl->update_ack_lock, flags);
 			vfe40_send_isp_msg(&vfe40_ctrl->subdev,
-				vfe40_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_UPDATE_ACK);
+				share_ctrl->vfeFrameId, MSG_ID_UPDATE_ACK);
 		} else {
 			spin_unlock_irqrestore(
-				&vfe40_ctrl->update_ack_lock, flags);
+					&share_ctrl->update_ack_lock, flags);
 		}
 	}
 
-	if (vfe40_ctrl->share_ctrl->liveshot_state ==
-		VFE_STATE_START_REQUESTED) {
+	switch (share_ctrl->liveshot_state) {
+	case VFE_STATE_START_REQUESTED:
 		CDBG("%s enabling liveshot output\n", __func__);
-		if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-				VFE40_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+			if (share_ctrl->comp_output_mode &
+			VFE40_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w(1, share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
-			vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(1, share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch1]);
-			vfe40_ctrl->share_ctrl->liveshot_state =
+
+				share_ctrl->liveshot_state =
 				VFE_STATE_STARTED;
 		}
-	}
-
-	if (vfe40_ctrl->share_ctrl->liveshot_state == VFE_STATE_STARTED) {
-		vfe40_ctrl->share_ctrl->vfe_capture_count--;
-		if (!vfe40_ctrl->share_ctrl->vfe_capture_count)
-			vfe40_ctrl->share_ctrl->liveshot_state =
-				VFE_STATE_STOP_REQUESTED;
-		msm_camera_io_w_mb(1, vfe40_ctrl->
-			share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	} else if (vfe40_ctrl->share_ctrl->liveshot_state ==
-			VFE_STATE_STOP_REQUESTED) {
-		CDBG("%s: disabling liveshot output\n", __func__);
-		if (vfe40_ctrl->share_ctrl->outpath.output_mode &
-			VFE40_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+		break;
+	case VFE_STATE_STARTED:
+			share_ctrl->vfe_capture_count--;
+			if (!share_ctrl->vfe_capture_count &&
+				(share_ctrl->comp_output_mode &
+				VFE40_OUTPUT_MODE_PRIMARY)) {
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[vfe40_ctrl->
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch1]);
-			vfe40_ctrl->share_ctrl->liveshot_state =
-				VFE_STATE_STOPPED;
-			msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase +
+		}
+		break;
+	case VFE_STATE_STOP_REQUESTED:
+		if (share_ctrl->comp_output_mode &
+			VFE40_OUTPUT_MODE_PRIMARY) {
+			/* Stop requested, stop write masters, and
+			 * trigger REG_UPDATE. Send STOP_LS_ACK in
+			 * next reg update. */
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[
+				share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(0, share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[
+				share_ctrl->outpath.out0.ch1]);
+				share_ctrl->liveshot_state = VFE_STATE_STOPPED;
+				msm_camera_io_w_mb(1, share_ctrl->vfebase +
 				VFE_REG_UPDATE_CMD);
 		}
-	} else if (vfe40_ctrl->share_ctrl->liveshot_state ==
-			VFE_STATE_STOPPED) {
-		vfe40_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+		break;
+	case VFE_STATE_STOPPED:
+		CDBG("%s Sending STOP_LS ACK\n", __func__);
+		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+				share_ctrl->vfeFrameId, MSG_ID_STOP_LS_ACK);
+			share_ctrl->liveshot_state = VFE_STATE_IDLE;
+		break;
+	default:
+		break;
 	}
 
-	if ((vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_THUMB_AND_MAIN) ||
-		(vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_MAIN_AND_THUMB) ||
-		(vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_THUMB_AND_JPEG) ||
-		(vfe40_ctrl->share_ctrl->operation_mode ==
-			VFE_OUTPUTS_JPEG_AND_THUMB)) {
+	if ((share_ctrl->operation_mode & VFE_OUTPUTS_THUMB_AND_MAIN) ||
+		(share_ctrl->operation_mode &
+		VFE_OUTPUTS_MAIN_AND_THUMB) ||
+		(share_ctrl->operation_mode &
+		VFE_OUTPUTS_THUMB_AND_JPEG) ||
+		(share_ctrl->operation_mode &
+		VFE_OUTPUTS_JPEG_AND_THUMB)) {
 		/* in snapshot mode */
 		/* later we need to add check for live snapshot mode. */
 		if (vfe40_ctrl->frame_skip_pattern & (0x1 <<
 			(vfe40_ctrl->snapshot_frame_cnt %
 				vfe40_ctrl->frame_skip_cnt))) {
-			vfe40_ctrl->share_ctrl->vfe_capture_count--;
+				share_ctrl->vfe_capture_count--;
 			/* if last frame to be captured: */
-			if (vfe40_ctrl->share_ctrl->vfe_capture_count == 0) {
-				/* stop the bus output:write master enable = 0*/
-				if (vfe40_ctrl->share_ctrl->outpath.output_mode
+				if (share_ctrl->vfe_capture_count == 0) {
+					/* stop the bus output: */
+					if (share_ctrl->comp_output_mode
 					& VFE40_OUTPUT_MODE_PRIMARY) {
-					msm_camera_io_w(0,
-						vfe40_ctrl->share_ctrl->vfebase+
-						vfe40_AXI_WM_CFG[vfe40_ctrl->
-						share_ctrl->outpath.out0.ch0]);
-					msm_camera_io_w(0,
-						vfe40_ctrl->share_ctrl->vfebase+
-						vfe40_AXI_WM_CFG[vfe40_ctrl->
-						share_ctrl->outpath.out0.ch1]);
-				}
-				if (vfe40_ctrl->share_ctrl->outpath.output_mode&
+						msm_camera_io_w(0,
+							share_ctrl->vfebase+
+							vfe40_AXI_WM_CFG[
+							share_ctrl->
+							outpath.out0.ch0]);
+						msm_camera_io_w(0,
+							share_ctrl->vfebase+
+							vfe40_AXI_WM_CFG[
+							share_ctrl->
+							outpath.out0.ch1]);
+					}
+					if (share_ctrl->comp_output_mode &
 						VFE40_OUTPUT_MODE_SECONDARY) {
-					msm_camera_io_w(0,
-						vfe40_ctrl->share_ctrl->vfebase+
-						vfe40_AXI_WM_CFG[vfe40_ctrl->
-						share_ctrl->outpath.out1.ch0]);
-					msm_camera_io_w(0,
-						vfe40_ctrl->share_ctrl->vfebase+
-						vfe40_AXI_WM_CFG[vfe40_ctrl->
-						share_ctrl->outpath.out1.ch1]);
+						msm_camera_io_w(0,
+							share_ctrl->vfebase+
+							vfe40_AXI_WM_CFG[
+							share_ctrl->
+							outpath.out1.ch0]);
+						msm_camera_io_w(0,
+							share_ctrl->vfebase+
+							vfe40_AXI_WM_CFG[
+							share_ctrl->
+							outpath.out1.ch1]);
 				}
 				msm_camera_io_w_mb
 				(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
-				vfe40_ctrl->share_ctrl->vfebase +
-				VFE_CAMIF_COMMAND);
+					share_ctrl->vfebase +
+					VFE_CAMIF_COMMAND);
 				vfe40_ctrl->snapshot_frame_cnt = -1;
 				vfe40_ctrl->frame_skip_cnt = 31;
 				vfe40_ctrl->frame_skip_pattern = 0xffffffff;
@@ -2580,43 +3395,65 @@
 		vfe40_ctrl->snapshot_frame_cnt++;
 		/* then do reg_update. */
 		msm_camera_io_w(1,
-			vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+				share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	} /* if snapshot mode. */
 }
+}
 
-static void vfe40_set_default_reg_values(
-			struct vfe40_ctrl_type *vfe40_ctrl)
+static void vfe40_process_rdi0_reg_update_irq(
+	struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	msm_camera_io_w(0x800080,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
-	msm_camera_io_w(0x800080,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
-	/* What value should we program CGC_OVERRIDE to? */
-	msm_camera_io_w(0xFFFFF,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
+	if (atomic_cmpxchg(
+		&vfe40_ctrl->share_ctrl->rdi0_update_ack_pending, 2, 0) == 2) {
+		axi_stop_rdi0(vfe40_ctrl->share_ctrl);
+		axi_disable_irq(vfe40_ctrl->share_ctrl);
+		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+			vfe40_ctrl->share_ctrl->vfeFrameId,
+			MSG_ID_RDI0_UPDATE_ACK);
+		vfe40_ctrl->share_ctrl->comp_output_mode &=
+			~VFE40_OUTPUT_MODE_TERTIARY1;
+		vfe40_ctrl->share_ctrl->current_mode &=
+			~(VFE_OUTPUTS_RDI0);
+	}
 
-	/* default frame drop period and pattern */
-	msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MIN);
-	msm_camera_io_w(0xFFFFFF,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MAX);
-	msm_camera_io_w(0,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MIN);
-	msm_camera_io_w(0xFFFFFF,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MAX);
+	if (atomic_cmpxchg(
+		&vfe40_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0) == 1) {
+		vfe40_ctrl->share_ctrl->comp_output_mode |=
+			VFE40_OUTPUT_MODE_TERTIARY1;
+		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+			vfe40_ctrl->share_ctrl->vfeFrameId,
+			MSG_ID_RDI0_UPDATE_ACK);
+		vfe40_ctrl->share_ctrl->current_mode &=
+			~(VFE_OUTPUTS_RDI0);
+	}
+}
 
-	/* stats UB config */
-	msm_camera_io_w(0x3980007,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
-	msm_camera_io_w(0x3A00007,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
-	msm_camera_io_w(0x3A8000F,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
-	msm_camera_io_w(0x3B80007,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
-	msm_camera_io_w(0x3C0001F,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
-	msm_camera_io_w(0x3E0001F,
-		vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
+static void vfe40_process_rdi1_reg_update_irq(
+	struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	if (atomic_cmpxchg(
+		&vfe40_ctrl->share_ctrl->rdi1_update_ack_pending, 2, 0) == 2) {
+		axi_stop_rdi1(vfe40_ctrl->share_ctrl);
+		axi_disable_irq(vfe40_ctrl->share_ctrl);
+		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+			vfe40_ctrl->share_ctrl->vfeFrameId,
+			MSG_ID_RDI1_UPDATE_ACK);
+			vfe40_ctrl->share_ctrl->comp_output_mode &=
+				~VFE40_OUTPUT_MODE_TERTIARY2;
+		vfe40_ctrl->share_ctrl->current_mode &=
+			~(VFE_OUTPUTS_RDI1);
+	}
+
+	if (atomic_cmpxchg(
+		&vfe40_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0) == 1) {
+		vfe40_ctrl->share_ctrl->comp_output_mode |=
+			VFE40_OUTPUT_MODE_TERTIARY2;
+		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+			vfe40_ctrl->share_ctrl->vfeFrameId,
+			MSG_ID_RDI1_UPDATE_ACK);
+		vfe40_ctrl->share_ctrl->current_mode &=
+			~(VFE_OUTPUTS_RDI1);
+	}
 }
 
 static void vfe40_process_reset_irq(
@@ -2625,39 +3462,45 @@
 	unsigned long flags;
 
 	atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
+	atomic_set(&vfe40_ctrl->share_ctrl->handle_common_irq, 0);
 
 	spin_lock_irqsave(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
 	if (vfe40_ctrl->share_ctrl->stop_ack_pending) {
 		vfe40_ctrl->share_ctrl->stop_ack_pending = FALSE;
 		spin_unlock_irqrestore(
 			&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
+		if (vfe40_ctrl->share_ctrl->sync_abort)
+			complete(&vfe40_ctrl->share_ctrl->reset_complete);
+		else
 		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
-			vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_ACK);
+				vfe40_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_STOP_ACK);
 	} else {
 		spin_unlock_irqrestore(
 			&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
 		/* this is from reset command. */
-		vfe40_set_default_reg_values(vfe40_ctrl);
-
+		vfe40_reset_internal_variables(vfe40_ctrl);
+		if (vfe40_ctrl->share_ctrl->vfe_reset_flag) {
+			vfe40_ctrl->share_ctrl->vfe_reset_flag = false;
+			msm_camera_io_w(0xFF00,
+				vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		} else {
 		/* reload all write masters. (frame & line)*/
-		msm_camera_io_w(0x7FFF,
+		msm_camera_io_w(0xFF7F,
 			vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
-		vfe40_send_isp_msg(&vfe40_ctrl->subdev,
-			vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_RESET_ACK);
+		}
+		complete(&vfe40_ctrl->share_ctrl->reset_complete);
 	}
 }
 
 static void vfe40_process_camif_sof_irq(
 		struct vfe40_ctrl_type *vfe40_ctrl)
 {
-	if (vfe40_ctrl->share_ctrl->operation_mode ==
+	if (vfe40_ctrl->share_ctrl->operation_mode &
 		VFE_OUTPUTS_RAW) {
-		if (vfe40_ctrl->start_ack_pending) {
-			vfe40_send_isp_msg(&vfe40_ctrl->subdev,
-				vfe40_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_START_ACK);
-			vfe40_ctrl->start_ack_pending = FALSE;
-		}
+		if (vfe40_ctrl->share_ctrl->start_ack_pending)
+			vfe40_ctrl->share_ctrl->start_ack_pending = FALSE;
+
 		vfe40_ctrl->share_ctrl->vfe_capture_count--;
 		/* if last frame to be captured: */
 		if (vfe40_ctrl->share_ctrl->vfe_capture_count == 0) {
@@ -2672,11 +3515,15 @@
 			VFE_MODE_OF_OPERATION_VIDEO) &&
 		(vfe40_ctrl->share_ctrl->vfeFrameId %
 			vfe40_ctrl->hfr_mode != 0)) {
-		vfe40_ctrl->share_ctrl->vfeFrameId++;
+		if (vfe40_ctrl->vfe_sof_count_enable)
+			vfe40_ctrl->share_ctrl->vfeFrameId++;
 		CDBG("Skip the SOF notification when HFR enabled\n");
 		return;
 	}
-	vfe40_ctrl->share_ctrl->vfeFrameId++;
+
+	if (vfe40_ctrl->vfe_sof_count_enable)
+		vfe40_ctrl->share_ctrl->vfeFrameId++;
+
 	vfe40_send_isp_msg(&vfe40_ctrl->subdev,
 		vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_SOF_ACK);
 	CDBG("camif_sof_irq, frameId = %d\n",
@@ -2694,11 +3541,19 @@
 	struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
 {
 	uint32_t reg_value;
+	if (errStatus & VFE40_IMASK_VIOLATION) {
+		pr_err("vfe40_irq: violation interrupt\n");
+		reg_value = msm_camera_io_r(
+			axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
+		pr_err("%s: violationStatus  = 0x%x\n", __func__, reg_value);
+	}
 
 	if (errStatus & VFE40_IMASK_CAMIF_ERROR) {
 		pr_err("vfe40_irq: camif errors\n");
 		reg_value = msm_camera_io_r(
 			axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_STATUS);
+		v4l2_subdev_notify(&axi_ctrl->subdev,
+			NOTIFY_VFE_CAMIF_ERROR, (void *)NULL);
 		pr_err("camifStatus  = 0x%x\n", reg_value);
 		vfe40_send_isp_msg(&axi_ctrl->subdev,
 			axi_ctrl->share_ctrl->vfeFrameId, MSG_ID_CAMIF_ERROR);
@@ -2722,12 +3577,36 @@
 	if (errStatus & VFE40_IMASK_REALIGN_BUF_CR_OVFL)
 		pr_err("vfe40_irq: realign bug CR overflow\n");
 
-	if (errStatus & VFE40_IMASK_VIOLATION) {
-		pr_err("vfe40_irq: violation interrupt\n");
-		reg_value = msm_camera_io_r(
-			axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
-		pr_err("%s: violationStatus  = 0x%x\n", __func__, reg_value);
-	}
+	if (errStatus & VFE40_IMASK_STATS_BE_BUS_OVFL)
+		pr_err("vfe40_irq: be stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_BG_BUS_OVFL)
+		pr_err("vfe40_irq: bg stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_BF_BUS_OVFL)
+		pr_err("vfe40_irq: bf stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_AWB_BUS_OVFL)
+		pr_err("vfe40_irq: awb stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_RS_BUS_OVFL)
+		pr_err("vfe40_irq: rs stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_CS_BUS_OVFL)
+		pr_err("vfe40_irq: cs stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_IHIST_BUS_OVFL)
+		pr_err("vfe40_irq: ihist stats bus overflow\n");
+
+	if (errStatus & VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
+		pr_err("vfe40_irq: skin/bhist stats bus overflow\n");
+}
+
+static void vfe40_process_common_error_irq(
+	struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
+{
+	if (errStatus & VFE40_IMASK_BUS_BDG_HALT_ACK)
+		pr_err("vfe40_irq: BUS BDG HALT ACK\n");
 
 	if (errStatus & VFE40_IMASK_IMG_MAST_0_BUS_OVFL)
 		pr_err("vfe40_irq: image master 0 bus overflow\n");
@@ -2750,29 +3629,294 @@
 	if (errStatus & VFE40_IMASK_IMG_MAST_6_BUS_OVFL)
 		pr_err("vfe40_irq: image master 6 bus overflow\n");
 
-	if (errStatus & VFE40_IMASK_STATS_AE_BG_BUS_OVFL)
-		pr_err("vfe40_irq: ae/bg stats bus overflow\n");
+}
 
-	if (errStatus & VFE40_IMASK_STATS_AF_BF_BUS_OVFL)
-		pr_err("vfe40_irq: af/bf stats bus overflow\n");
+static void vfe_send_outmsg(
+	struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
+	uint32_t ch0_paddr, uint32_t ch1_paddr,
+	uint32_t ch2_paddr, uint32_t inst_handle)
+{
+	struct isp_msg_output msg;
 
-	if (errStatus & VFE40_IMASK_STATS_AWB_BUS_OVFL)
-		pr_err("vfe40_irq: awb stats bus overflow\n");
+	msg.output_id = msgid;
+	msg.buf.inst_handle = inst_handle;
+	msg.buf.ch_paddr[0]	= ch0_paddr;
+	msg.buf.ch_paddr[1]	= ch1_paddr;
+	msg.buf.ch_paddr[2]	= ch2_paddr;
+	switch (msgid) {
+	case MSG_ID_OUTPUT_TERTIARY1:
+		msg.frameCounter = axi_ctrl->share_ctrl->rdi0FrameId;
+		break;
+	case MSG_ID_OUTPUT_TERTIARY2:
+		msg.frameCounter = axi_ctrl->share_ctrl->rdi1FrameId;
+		break;
+	default:
+		msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
+		break;
+	}
 
-	if (errStatus & VFE40_IMASK_STATS_RS_BUS_OVFL)
-		pr_err("vfe40_irq: rs stats bus overflow\n");
+	v4l2_subdev_notify(&axi_ctrl->subdev,
+			NOTIFY_VFE_MSG_OUT,
+			&msg);
+	return;
+}
 
-	if (errStatus & VFE40_IMASK_STATS_CS_BUS_OVFL)
-		pr_err("vfe40_irq: cs stats bus overflow\n");
+static void vfe40_process_output_path_irq_0(
+	struct axi_ctrl_t *axi_ctrl)
+{
+	uint32_t ping_pong;
+	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
+	uint8_t out_bool = 0;
+	struct msm_free_buf *free_buf = NULL;
 
-	if (errStatus & VFE40_IMASK_STATS_IHIST_BUS_OVFL)
-		pr_err("vfe40_irq: ihist stats bus overflow\n");
+	free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+		VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
 
-	if (errStatus & VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
-		pr_err("vfe40_irq: skin/bhist stats bus overflow\n");
+	/* we render frames in the following conditions:
+	1. Continuous mode and the free buffer is avaialable.
+	2. In snapshot shot mode, free buffer is not always available.
+	when pending snapshot count is <=1,  then no need to use
+	free buffer.
+	*/
+	out_bool = (
+		(axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_THUMB_AND_MAIN ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_MAIN_AND_THUMB ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_THUMB_AND_JPEG ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_RAW ||
+		axi_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STARTED ||
+		axi_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STOP_REQUESTED ||
+		axi_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STOPPED) &&
+		(axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+			free_buf;
 
-	if (errStatus & VFE40_IMASK_AXI_ERROR)
-		pr_err("vfe40_irq: axi error\n");
+	if (out_bool) {
+		ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+			VFE_BUS_PING_PONG_STATUS);
+
+		/* Channel 0*/
+		ch0_paddr = vfe40_get_ch_addr(
+			ping_pong, axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch0);
+		/* Channel 1*/
+		ch1_paddr = vfe40_get_ch_addr(
+			ping_pong, axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch1);
+		/* Channel 2*/
+		ch2_paddr = vfe40_get_ch_addr(
+			ping_pong, axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch2);
+
+		CDBG("output path 0, ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+			ch0_paddr, ch1_paddr, ch2_paddr);
+		if (free_buf) {
+			/* Y channel */
+			vfe40_put_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch0,
+			free_buf->ch_paddr[0]);
+			/* Chroma channel */
+			vfe40_put_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch1,
+			free_buf->ch_paddr[1]);
+			if (free_buf->num_planes > 2)
+				vfe40_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out0.ch2,
+					free_buf->ch_paddr[2]);
+		}
+		if (axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_THUMB_AND_MAIN ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_MAIN_AND_THUMB ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_THUMB_AND_JPEG ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_JPEG_AND_THUMB ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_RAW ||
+			axi_ctrl->share_ctrl->liveshot_state ==
+				VFE_STATE_STOPPED)
+			axi_ctrl->share_ctrl->outpath.out0.capture_cnt--;
+
+		vfe_send_outmsg(axi_ctrl,
+			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
+			ch1_paddr, ch2_paddr,
+			axi_ctrl->share_ctrl->outpath.out0.inst_handle);
+
+	} else {
+		axi_ctrl->share_ctrl->outpath.out0.frame_drop_cnt++;
+		CDBG("path_irq_0 - no free buffer!\n");
+	}
+}
+
+static void vfe40_process_output_path_irq_1(
+	struct axi_ctrl_t *axi_ctrl)
+{
+	uint32_t ping_pong;
+	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
+	/* this must be snapshot main image output. */
+	uint8_t out_bool = 0;
+	struct msm_free_buf *free_buf = NULL;
+
+	free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+		VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
+	out_bool = ((axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_THUMB_AND_MAIN ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_MAIN_AND_THUMB ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_RAW ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_JPEG_AND_THUMB) &&
+			(axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+				free_buf;
+
+	if (out_bool) {
+		ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+			VFE_BUS_PING_PONG_STATUS);
+
+		/* Y channel */
+		ch0_paddr = vfe40_get_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch0);
+		/* Chroma channel */
+		ch1_paddr = vfe40_get_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch1);
+		ch2_paddr = vfe40_get_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch2);
+
+		CDBG("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+			__func__, ch0_paddr, ch1_paddr, ch2_paddr);
+		if (free_buf) {
+			/* Y channel */
+			vfe40_put_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch0,
+			free_buf->ch_paddr[0]);
+			/* Chroma channel */
+			vfe40_put_ch_addr(ping_pong,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch1,
+			free_buf->ch_paddr[1]);
+			if (free_buf->num_planes > 2)
+				vfe40_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out1.ch2,
+					free_buf->ch_paddr[2]);
+		}
+		if (axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_THUMB_AND_MAIN ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_MAIN_AND_THUMB ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_RAW ||
+			axi_ctrl->share_ctrl->operation_mode &
+				VFE_OUTPUTS_JPEG_AND_THUMB)
+			axi_ctrl->share_ctrl->outpath.out1.capture_cnt--;
+
+		vfe_send_outmsg(axi_ctrl,
+			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
+			ch1_paddr, ch2_paddr,
+			axi_ctrl->share_ctrl->outpath.out1.inst_handle);
+
+	} else {
+		axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
+		CDBG("path_irq_1 - no free buffer!\n");
+	}
+}
+
+static void vfe40_process_output_path_irq_rdi0(
+			struct axi_ctrl_t *axi_ctrl)
+{
+	uint32_t ping_pong;
+	uint32_t ch0_paddr = 0;
+	/* this must be rdi image output. */
+	struct msm_free_buf *free_buf = NULL;
+	/*RDI0*/
+	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
+		free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+			VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
+		if (free_buf) {
+			ping_pong = msm_camera_io_r(axi_ctrl->
+				share_ctrl->vfebase +
+				VFE_BUS_PING_PONG_STATUS);
+
+			/* Y only channel */
+			ch0_paddr = vfe40_get_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out2.ch0);
+
+			pr_debug("%s ch0 = 0x%x\n",
+				__func__, ch0_paddr);
+
+			/* Y channel */
+			vfe40_put_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out2.ch0,
+				free_buf->ch_paddr[0]);
+
+			vfe_send_outmsg(axi_ctrl,
+				MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
+				0, 0,
+				axi_ctrl->share_ctrl->outpath.out2.inst_handle);
+
+		} else {
+			axi_ctrl->share_ctrl->outpath.out2.frame_drop_cnt++;
+			pr_err("path_irq_2 irq - no free buffer for rdi0!\n");
+		}
+	}
+}
+
+static void vfe40_process_output_path_irq_rdi1(
+	struct axi_ctrl_t *axi_ctrl)
+{
+	uint32_t ping_pong;
+	uint32_t ch0_paddr = 0;
+	/* this must be rdi image output. */
+	struct msm_free_buf *free_buf = NULL;
+	/*RDI1*/
+	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
+		free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+			VFE_MSG_OUTPUT_TERTIARY2, axi_ctrl);
+		if (free_buf) {
+			ping_pong = msm_camera_io_r(axi_ctrl->
+				share_ctrl->vfebase +
+				VFE_BUS_PING_PONG_STATUS);
+
+			/* Y channel */
+			ch0_paddr = vfe40_get_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out3.ch0);
+			pr_debug("%s ch0 = 0x%x\n",
+				__func__, ch0_paddr);
+
+			/* Y channel */
+			vfe40_put_ch_addr(ping_pong,
+				axi_ctrl->share_ctrl->vfebase,
+				axi_ctrl->share_ctrl->outpath.out3.ch0,
+				free_buf->ch_paddr[0]);
+
+			vfe_send_outmsg(axi_ctrl,
+				MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
+				0, 0,
+				axi_ctrl->share_ctrl->outpath.out3.inst_handle);
+		} else {
+			axi_ctrl->share_ctrl->outpath.out3.frame_drop_cnt++;
+			pr_err("path_irq irq - no free buffer for rdi1!\n");
+		}
+	}
 }
 
 static uint32_t  vfe40_process_stats_irq_common(
@@ -2799,8 +3943,8 @@
 	return returnAddr;
 }
 
-static void
-vfe_send_stats_msg(struct vfe40_ctrl_type *vfe40_ctrl,
+static void vfe_send_stats_msg(
+	struct vfe40_ctrl_type *vfe40_ctrl,
 	uint32_t bufAddress, uint32_t statsNum)
 {
 	int rc = 0;
@@ -2809,24 +3953,36 @@
 	/* @todo This is causing issues, need further investigate */
 	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
 	struct isp_msg_stats msgStats;
+	uint32_t stats_type;
 	msgStats.frameCounter = vfe40_ctrl->share_ctrl->vfeFrameId;
+	if (vfe40_ctrl->simultaneous_sof_stat)
+		msgStats.frameCounter--;
 	msgStats.buffer = bufAddress;
-
 	switch (statsNum) {
 	case statsAeNum:{
-		msgStats.id = MSG_ID_STATS_AEC;
+		msgStats.id =
+			(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSG_ID_STATS_AEC
+				: MSG_ID_STATS_BG;
+		stats_type =
+			(!vfe40_use_bayer_stats(vfe40_ctrl)) ?
+				MSM_STATS_TYPE_AEC : MSM_STATS_TYPE_BG;
 		rc = vfe40_ctrl->stats_ops.dispatch(
 				vfe40_ctrl->stats_ops.stats_ctrl,
-				MSM_STATS_TYPE_AEC, bufAddress,
+				stats_type, bufAddress,
 				&msgStats.buf_idx, &vaddr, &msgStats.fd,
 				vfe40_ctrl->stats_ops.client);
 		}
 		break;
 	case statsAfNum:{
-		msgStats.id = MSG_ID_STATS_AF;
+		msgStats.id =
+			(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSG_ID_STATS_AF
+				: MSG_ID_STATS_BF;
+		stats_type =
+			(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+				: MSM_STATS_TYPE_BF;
 		rc = vfe40_ctrl->stats_ops.dispatch(
 				vfe40_ctrl->stats_ops.stats_ctrl,
-				MSM_STATS_TYPE_AF, bufAddress,
+				stats_type, bufAddress,
 				&msgStats.buf_idx, &vaddr, &msgStats.fd,
 				vfe40_ctrl->stats_ops.client);
 		}
@@ -2868,6 +4024,15 @@
 				vfe40_ctrl->stats_ops.client);
 		}
 		break;
+	case statsSkinNum: {
+		msgStats.id = MSG_ID_STATS_BHIST;
+		rc = vfe40_ctrl->stats_ops.dispatch(
+				vfe40_ctrl->stats_ops.stats_ctrl,
+				MSM_STATS_TYPE_BHIST, bufAddress,
+				&msgStats.buf_idx, &vaddr, &msgStats.fd,
+				vfe40_ctrl->stats_ops.client);
+		}
+		break;
 
 	default:
 		goto stats_done;
@@ -2882,7 +4047,7 @@
 			 __func__, msgStats.id, msgStats.buffer);
 	}
 stats_done:
-	spin_unlock_irqrestore(&ctrl->state_lock, flags);
+	/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
 	return;
 }
 
@@ -2893,11 +4058,14 @@
 	uint32_t temp;
 
 	msgStats.frame_id = vfe40_ctrl->share_ctrl->vfeFrameId;
+	if (vfe40_ctrl->simultaneous_sof_stat)
+		msgStats.frame_id--;
+
 	msgStats.status_bits = status_bits;
 
-	msgStats.aec.buff = vfe40_ctrl->aecStatsControl.bufToRender;
+	msgStats.aec.buff = vfe40_ctrl->aecbgStatsControl.bufToRender;
 	msgStats.awb.buff = vfe40_ctrl->awbStatsControl.bufToRender;
-	msgStats.af.buff = vfe40_ctrl->afStatsControl.bufToRender;
+	msgStats.af.buff = vfe40_ctrl->afbfStatsControl.bufToRender;
 
 	msgStats.ihist.buff = vfe40_ctrl->ihistStatsControl.bufToRender;
 	msgStats.rs.buff = vfe40_ctrl->rsStatsControl.bufToRender;
@@ -2912,6 +4080,31 @@
 				&msgStats);
 }
 
+static void vfe40_process_stats_bg_irq(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	unsigned long flags;
+	uint32_t addr;
+	uint32_t stats_type;
+	stats_type =
+		(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AEC
+			: MSM_STATS_TYPE_BG;
+	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
+	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+	if (addr) {
+		vfe40_ctrl->aecbgStatsControl.bufToRender =
+			vfe40_process_stats_irq_common(vfe40_ctrl, statsAeNum,
+			addr);
+
+		vfe_send_stats_msg(vfe40_ctrl,
+			vfe40_ctrl->aecbgStatsControl.bufToRender, statsAeNum);
+	} else{
+		vfe40_ctrl->aecbgStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe40_ctrl->aecbgStatsControl.droppedStatsFrameCount);
+	}
+}
+
 static void vfe40_process_stats_awb_irq(struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	unsigned long flags;
@@ -2933,6 +4126,53 @@
 	}
 }
 
+static void vfe40_process_stats_bf_irq(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	unsigned long flags;
+	uint32_t addr;
+	uint32_t stats_type;
+	stats_type =
+		(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+			: MSM_STATS_TYPE_BF;
+	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
+	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+	if (addr) {
+		vfe40_ctrl->afbfStatsControl.bufToRender =
+			vfe40_process_stats_irq_common(vfe40_ctrl, statsAfNum,
+			addr);
+
+		vfe_send_stats_msg(vfe40_ctrl,
+			vfe40_ctrl->afbfStatsControl.bufToRender, statsAfNum);
+	} else{
+		vfe40_ctrl->afbfStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe40_ctrl->afbfStatsControl.droppedStatsFrameCount);
+	}
+}
+
+static void vfe40_process_stats_bhist_irq(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+	unsigned long flags;
+	uint32_t addr;
+	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+	addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_BHIST);
+	spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+	if (addr) {
+		vfe40_ctrl->bhistStatsControl.bufToRender =
+			vfe40_process_stats_irq_common(vfe40_ctrl,
+				statsSkinNum, addr);
+
+		vfe_send_stats_msg(vfe40_ctrl,
+			vfe40_ctrl->bhistStatsControl.bufToRender,
+			statsSkinNum);
+	} else{
+		vfe40_ctrl->bhistStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe40_ctrl->bhistStatsControl.droppedStatsFrameCount);
+	}
+}
+
 static void vfe40_process_stats_ihist_irq(struct vfe40_ctrl_type *vfe40_ctrl)
 {
 	unsigned long flags;
@@ -2988,8 +4228,9 @@
 			vfe40_process_stats_irq_common(vfe40_ctrl, statsCsNum,
 			addr);
 
-		vfe_send_stats_msg(vfe40_ctrl,
-			vfe40_ctrl->csStatsControl.bufToRender, statsCsNum);
+			vfe_send_stats_msg(vfe40_ctrl,
+				vfe40_ctrl->csStatsControl.bufToRender,
+				statsCsNum);
 	} else {
 		vfe40_ctrl->csStatsControl.droppedStatsFrameCount++;
 		CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3003,9 +4244,30 @@
 	unsigned long flags;
 	int32_t process_stats = false;
 	uint32_t addr;
+	uint32_t stats_type;
 
 	CDBG("%s, stats = 0x%x\n", __func__, status_bits);
 	spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+	stats_type =
+		(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AEC
+			: MSM_STATS_TYPE_BG;
+
+	if (status_bits & VFE_IRQ_STATUS0_STATS_BG) {
+		addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
+				stats_type);
+		if (addr) {
+			vfe40_ctrl->aecbgStatsControl.bufToRender =
+				vfe40_process_stats_irq_common(
+				vfe40_ctrl, statsAeNum,	addr);
+			process_stats = true;
+		} else{
+			vfe40_ctrl->aecbgStatsControl.bufToRender = 0;
+			vfe40_ctrl->aecbgStatsControl.droppedStatsFrameCount++;
+		}
+	} else {
+		vfe40_ctrl->aecbgStatsControl.bufToRender = 0;
+	}
+
 	if (status_bits & VFE_IRQ_STATUS0_STATS_AWB) {
 		addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
 			MSM_STATS_TYPE_AWB);
@@ -3023,6 +4285,26 @@
 		vfe40_ctrl->awbStatsControl.bufToRender = 0;
 	}
 
+	stats_type =
+		(!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+			: MSM_STATS_TYPE_BF;
+	if (status_bits & VFE_IRQ_STATUS0_STATS_BF) {
+		addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
+					stats_type);
+		if (addr) {
+			vfe40_ctrl->afbfStatsControl.bufToRender =
+				vfe40_process_stats_irq_common(
+				vfe40_ctrl, statsAfNum,
+				addr);
+			process_stats = true;
+		} else {
+			vfe40_ctrl->afbfStatsControl.bufToRender = 0;
+			vfe40_ctrl->afbfStatsControl.droppedStatsFrameCount++;
+		}
+	} else {
+		vfe40_ctrl->afbfStatsControl.bufToRender = 0;
+	}
+
 	if (status_bits & VFE_IRQ_STATUS0_STATS_IHIST) {
 		addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
 					MSM_STATS_TYPE_IHIST);
@@ -3084,7 +4366,6 @@
 	struct vfe40_ctrl_type *vfe40_ctrl, uint32_t irqstatus)
 {
 	uint32_t status_bits = VFE_COM_STATUS & irqstatus;
-
 	if ((vfe40_ctrl->hfr_mode != HFR_MODE_OFF) &&
 		(vfe40_ctrl->share_ctrl->vfeFrameId %
 		 vfe40_ctrl->hfr_mode != 0)) {
@@ -3114,14 +4395,34 @@
 		CDBG("irq	regUpdateIrq\n");
 		vfe40_process_reg_update_irq(vfe40_ctrl);
 		break;
+	case VFE_IRQ_STATUS0_RDI0_REG_UPDATE:
+		CDBG("irq	rdi0 regUpdateIrq\n");
+		vfe40_process_rdi0_reg_update_irq(vfe40_ctrl);
+		break;
+	case VFE_IRQ_STATUS0_RDI1_REG_UPDATE:
+		CDBG("irq	rdi1 regUpdateIrq\n");
+		vfe40_process_rdi1_reg_update_irq(vfe40_ctrl);
+		break;
 	case VFE_IMASK_WHILE_STOPPING_0:
 		CDBG("irq	resetAckIrq\n");
 		vfe40_process_reset_irq(vfe40_ctrl);
 		break;
+	case VFE_IRQ_STATUS0_STATS_BG:
+		CDBG("Stats BG irq occured.\n");
+		vfe40_process_stats_bg_irq(vfe40_ctrl);
+		break;
+	case VFE_IRQ_STATUS0_STATS_BF:
+		CDBG("Stats BF irq occured.\n");
+		vfe40_process_stats_bf_irq(vfe40_ctrl);
+		break;
 	case VFE_IRQ_STATUS0_STATS_AWB:
 		CDBG("Stats AWB irq occured.\n");
 		vfe40_process_stats_awb_irq(vfe40_ctrl);
 		break;
+	case VFE_IRQ_STATUS0_STATS_SKIN_BHIST:
+		CDBG("Stats BHIST irq occured.\n");
+		vfe40_process_stats_bhist_irq(vfe40_ctrl);
+		break;
 	case VFE_IRQ_STATUS0_STATS_IHIST:
 		CDBG("Stats IHIST irq occured.\n");
 		vfe40_process_stats_ihist_irq(vfe40_ctrl);
@@ -3161,15 +4462,17 @@
 {
 	unsigned long flags;
 	struct axi_ctrl_t *axi_ctrl = (struct axi_ctrl_t *)data;
+	struct vfe40_ctrl_type *vfe40_ctrl = axi_ctrl->share_ctrl->vfe40_ctrl;
 	struct vfe40_isr_queue_cmd *qcmd = NULL;
+	int stat_interrupt;
 
 	CDBG("=== axi40_do_tasklet start ===\n");
 
-	while (atomic_read(&axi_ctrl->share_ctrl->irq_cnt)) {
+	while (atomic_read(&irq_cnt)) {
 		spin_lock_irqsave(&axi_ctrl->tasklet_lock, flags);
 		qcmd = list_first_entry(&axi_ctrl->tasklet_q,
 			struct vfe40_isr_queue_cmd, list);
-		atomic_sub(1, &axi_ctrl->share_ctrl->irq_cnt);
+		atomic_sub(1, &irq_cnt);
 
 		if (!qcmd) {
 			spin_unlock_irqrestore(&axi_ctrl->tasklet_lock,
@@ -3181,38 +4484,82 @@
 		spin_unlock_irqrestore(&axi_ctrl->tasklet_lock,
 			flags);
 
+		if (axi_ctrl->share_ctrl->stats_comp) {
+			stat_interrupt = (qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0);
+		} else {
+			stat_interrupt =
+				(qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_BG) |
+				(qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_AWB) |
+				(qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_BF) |
+				(qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_IHIST) |
+				(qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_RS) |
+				(qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_CS);
+		}
 		if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_CAMIF_SOF_MASK)
-			v4l2_subdev_notify(&axi_ctrl->subdev,
+				VFE_IRQ_STATUS0_CAMIF_SOF_MASK) {
+			if (stat_interrupt)
+				vfe40_ctrl->simultaneous_sof_stat = 1;
+			v4l2_subdev_notify(&vfe40_ctrl->subdev,
 				NOTIFY_VFE_IRQ,
 				(void *)VFE_IRQ_STATUS0_CAMIF_SOF_MASK);
+		}
 
 		/* interrupt to be processed,  *qcmd has the payload.  */
 		if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_REG_UPDATE_MASK) {
-			v4l2_subdev_notify(&axi_ctrl->subdev,
+				VFE_IRQ_STATUS0_REG_UPDATE_MASK)
+			v4l2_subdev_notify(&vfe40_ctrl->subdev,
 				NOTIFY_VFE_IRQ,
 				(void *)VFE_IRQ_STATUS0_REG_UPDATE_MASK);
-		}
+
+		if (qcmd->vfeInterruptStatus1 &
+				VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK)
+			v4l2_subdev_notify(&vfe40_ctrl->subdev,
+				NOTIFY_VFE_IRQ,
+				(void *)VFE_IRQ_STATUS0_RDI0_REG_UPDATE);
+
+		if (qcmd->vfeInterruptStatus1 &
+				VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK)
+			v4l2_subdev_notify(&vfe40_ctrl->subdev,
+				NOTIFY_VFE_IRQ,
+				(void *)VFE_IRQ_STATUS0_RDI1_REG_UPDATE);
 
 		if (qcmd->vfeInterruptStatus0 &
 				VFE_IMASK_WHILE_STOPPING_0)
-			v4l2_subdev_notify(&axi_ctrl->subdev,
+			v4l2_subdev_notify(&vfe40_ctrl->subdev,
 				NOTIFY_VFE_IRQ,
 				(void *)VFE_IMASK_WHILE_STOPPING_0);
 
+		if (atomic_read(&axi_ctrl->share_ctrl->handle_common_irq)) {
+			if (qcmd->vfeInterruptStatus1 &
+					VFE40_IMASK_COMMON_ERROR_ONLY_1) {
+				pr_err("irq	errorIrq\n");
+				vfe40_process_common_error_irq(
+					axi_ctrl,
+					qcmd->vfeInterruptStatus1 &
+					VFE40_IMASK_COMMON_ERROR_ONLY_1);
+			}
+
+			v4l2_subdev_notify(&axi_ctrl->subdev,
+				NOTIFY_AXI_IRQ,
+				(void *)qcmd->vfeInterruptStatus0);
+		}
+
 		if (atomic_read(&axi_ctrl->share_ctrl->vstate)) {
 			if (qcmd->vfeInterruptStatus1 &
-					VFE40_IMASK_ERROR_ONLY_1) {
+					VFE40_IMASK_VFE_ERROR_ONLY_1) {
 				pr_err("irq	errorIrq\n");
 				vfe40_process_error_irq(
 					axi_ctrl,
 					qcmd->vfeInterruptStatus1 &
-					VFE40_IMASK_ERROR_ONLY_1);
+					VFE40_IMASK_VFE_ERROR_ONLY_1);
 			}
-			v4l2_subdev_notify(&axi_ctrl->subdev,
-				NOTIFY_AXI_IRQ,
-				(void *)qcmd->vfeInterruptStatus0);
 
 			/* then process stats irq. */
 			if (axi_ctrl->share_ctrl->stats_comp) {
@@ -3220,54 +4567,74 @@
 				if (qcmd->vfeInterruptStatus0 &
 					VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0) {
 					CDBG("Stats composite irq occured.\n");
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)qcmd->vfeInterruptStatus0);
 				}
 			} else {
 				/* process individual stats interrupt. */
 				if (qcmd->vfeInterruptStatus0 &
+						VFE_IRQ_STATUS0_STATS_BG)
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_BG);
+
+				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS0_STATS_AWB)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS0_STATS_AWB);
+
+				if (qcmd->vfeInterruptStatus0 &
+						VFE_IRQ_STATUS0_STATS_BF)
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_BF);
+				if (qcmd->vfeInterruptStatus0 &
+					VFE_IRQ_STATUS0_STATS_SKIN_BHIST)
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)
+					VFE_IRQ_STATUS0_STATS_SKIN_BHIST);
+
 				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS0_STATS_IHIST)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS0_STATS_IHIST);
 
 				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS0_STATS_RS)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS0_STATS_RS);
 
 				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS0_STATS_CS)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS0_STATS_CS);
 
 				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS1_SYNC_TIMER0)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS1_SYNC_TIMER0);
 
 				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS1_SYNC_TIMER1)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS1_SYNC_TIMER1);
 
 				if (qcmd->vfeInterruptStatus0 &
 						VFE_IRQ_STATUS1_SYNC_TIMER2)
-					v4l2_subdev_notify(&axi_ctrl->subdev,
+					v4l2_subdev_notify(&vfe40_ctrl->subdev,
 					NOTIFY_VFE_IRQ,
 					(void *)VFE_IRQ_STATUS1_SYNC_TIMER2);
 			}
 		}
+		vfe40_ctrl->simultaneous_sof_stat = 0;
 		kfree(qcmd);
 	}
 	CDBG("=== axi40_do_tasklet end ===\n");
@@ -3312,16 +4679,26 @@
 	spin_lock_irqsave(&axi_ctrl->tasklet_lock, flags);
 	list_add_tail(&qcmd->list, &axi_ctrl->tasklet_q);
 
-	atomic_add(1, &axi_ctrl->share_ctrl->irq_cnt);
+	atomic_add(1, &irq_cnt);
 	spin_unlock_irqrestore(&axi_ctrl->tasklet_lock, flags);
 	tasklet_schedule(&axi_ctrl->vfe40_tasklet);
 	return IRQ_HANDLED;
 }
 
+int msm_axi_subdev_isr_routine(struct v4l2_subdev *sd,
+	u32 status, bool *handled)
+{
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	irqreturn_t ret;
+	CDBG("%s E ", __func__);
+	ret = vfe40_parse_irq(axi_ctrl->vfeirq->start, axi_ctrl);
+	*handled = TRUE;
+	return 0;
+}
 
 static long vfe_stats_bufq_sub_ioctl(
 	struct vfe40_ctrl_type *vfe_ctrl,
-	struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+	struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
 {
 	long rc = 0;
 	switch (cmd->cmd_type) {
@@ -3370,7 +4747,7 @@
 	rc = vfe_ctrl->stats_ops.enqueue_buf(
 			&vfe_ctrl->stats_ctrl,
 			(struct msm_stats_buf_info *)cmd->value,
-			vfe_ctrl->stats_ops.client);
+			vfe_ctrl->stats_ops.client, domain_num);
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 	{
@@ -3391,6 +4768,22 @@
 			vfe_ctrl->stats_ops.client);
 	}
 	break;
+	case VFE_CMD_STATS_UNREGBUF:
+	{
+		struct msm_stats_reqbuf *req_buf = NULL;
+		req_buf = (struct msm_stats_reqbuf *)cmd->value;
+		if (sizeof(struct msm_stats_reqbuf) != cmd->length) {
+			/* error. the length not match */
+			pr_err("%s: stats reqbuf input size = %d,\n"
+				"struct size = %d, mitch match\n",
+				 __func__, cmd->length,
+				sizeof(struct msm_stats_reqbuf));
+			rc = -EINVAL ;
+			goto end;
+		}
+		rc = vfe40_stats_unregbuf(vfe_ctrl, req_buf, domain_num);
+	}
+	break;
 	default:
 		rc = -1;
 		pr_err("%s: cmd_type %d not supported", __func__,
@@ -3409,10 +4802,9 @@
 	struct vfe40_ctrl_type *vfe40_ctrl =
 		(struct vfe40_ctrl_type *)v4l2_get_subdevdata(sd);
 	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;
-	void *data = vfe_params->data;
+	struct msm_camvfe_params *vfe_params;
+	struct msm_vfe_cfg_cmd *cmd;
+	void *data;
 
 	long rc = 0;
 	struct vfe_cmd_stats_buf *scfg = NULL;
@@ -3423,6 +4815,17 @@
 		return -EFAULT;
 	}
 
+	CDBG("%s\n", __func__);
+	if (subdev_cmd == VIDIOC_MSM_VFE_INIT) {
+		CDBG("%s init\n", __func__);
+		return msm_vfe_subdev_init(sd);
+	} else if (subdev_cmd == VIDIOC_MSM_VFE_RELEASE) {
+		msm_vfe_subdev_release(sd);
+		return 0;
+	}
+	vfe_params = (struct msm_camvfe_params *)arg;
+	cmd = vfe_params->vfe_cfg;
+	data = vfe_params->data;
 	switch (cmd->cmd_type) {
 	case CMD_VFE_PROCESS_IRQ:
 		vfe40_process_irq(vfe40_ctrl, (uint32_t) data);
@@ -3430,27 +4833,33 @@
 	case VFE_CMD_STATS_REQBUF:
 	case VFE_CMD_STATS_ENQUEUEBUF:
 	case VFE_CMD_STATS_FLUSH_BUFQ:
+	case VFE_CMD_STATS_UNREGBUF:
 		/* for easy porting put in one envelope */
 		rc = vfe_stats_bufq_sub_ioctl(vfe40_ctrl,
-				cmd, vfe_params->data);
+				cmd, vfe_params->data, pmctl->domain_num);
 		return rc;
 	default:
 		if (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_STATS_AEC_BUF_RELEASE &&
-			cmd->cmd_type != CMD_STATS_AWB_BUF_RELEASE &&
-			cmd->cmd_type != CMD_STATS_IHIST_BUF_RELEASE &&
-			cmd->cmd_type != CMD_STATS_RS_BUF_RELEASE &&
-			cmd->cmd_type != CMD_STATS_CS_BUF_RELEASE &&
-			cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE) {
-				if (copy_from_user(&vfecmd,
+		cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+		cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
+		cmd->cmd_type != CMD_STATS_AEC_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_AWB_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_IHIST_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_RS_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_CS_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_BG_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_BF_BUF_RELEASE &&
+		cmd->cmd_type != CMD_STATS_BHIST_BUF_RELEASE &&
+		cmd->cmd_type != CMD_VFE_PIX_SOF_COUNT_UPDATE &&
+		cmd->cmd_type != CMD_VFE_COUNT_PIX_SOF_ENABLE) {
+			if (copy_from_user(&vfecmd,
 					(void __user *)(cmd->value),
 					sizeof(vfecmd))) {
-						pr_err("%s %d: copy_from_user failed\n",
-							__func__, __LINE__);
-					return -EFAULT;
-				}
+				pr_err("%s %d: copy_from_user failed\n",
+					__func__, __LINE__);
+				return -EFAULT;
+			}
 		} else {
 			/* here eith stats release or frame release. */
 			if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -3472,6 +4881,25 @@
 				sack->nextStatsBuf = *(uint32_t *)data;
 			}
 		}
+	}
+
+	CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
+
+	if ((cmd->cmd_type == CMD_STATS_AF_ENABLE)    ||
+		(cmd->cmd_type == CMD_STATS_AWB_ENABLE)   ||
+		(cmd->cmd_type == CMD_STATS_IHIST_ENABLE) ||
+		(cmd->cmd_type == CMD_STATS_RS_ENABLE)    ||
+		(cmd->cmd_type == CMD_STATS_CS_ENABLE)    ||
+		(cmd->cmd_type == CMD_STATS_AEC_ENABLE)   ||
+		(cmd->cmd_type == CMD_STATS_BG_ENABLE)    ||
+		(cmd->cmd_type == CMD_STATS_BF_ENABLE)    ||
+		(cmd->cmd_type == CMD_STATS_BHIST_ENABLE)) {
+		struct axidata *axid;
+		axid = data;
+		if (!axid) {
+			rc = -EFAULT;
+			goto vfe40_config_done;
+		}
 		CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
 
 		if ((cmd->cmd_type == CMD_STATS_AF_ENABLE)    ||
@@ -3485,39 +4913,69 @@
 				goto vfe40_config_done;
 		}
 		switch (cmd->cmd_type) {
-		case CMD_GENERAL:
-			rc = vfe40_proc_general(pmctl, &vfecmd, vfe40_ctrl);
-		break;
-		case CMD_CONFIG_PING_ADDR: {
-			int path = *((int *)cmd->value);
-			struct vfe40_output_ch *outch =
-				vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
-			outch->ping = *((struct msm_free_buf *)data);
-		}
-		break;
-
-		case CMD_CONFIG_PONG_ADDR: {
-			int path = *((int *)cmd->value);
-			struct vfe40_output_ch *outch =
-				vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
-			outch->pong = *((struct msm_free_buf *)data);
-		}
-		break;
-
-		case CMD_CONFIG_FREE_BUF_ADDR: {
-			int path = *((int *)cmd->value);
-			struct vfe40_output_ch *outch =
-				vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
-			outch->free_buf = *((struct msm_free_buf *)data);
-		}
-		break;
-		case CMD_SNAP_BUF_RELEASE:
-			break;
+		case CMD_STATS_AEC_ENABLE:
+		case CMD_STATS_BG_ENABLE:
+		case CMD_STATS_BF_ENABLE:
+		case CMD_STATS_BHIST_ENABLE:
+		case CMD_STATS_AWB_ENABLE:
+		case CMD_STATS_IHIST_ENABLE:
+		case CMD_STATS_RS_ENABLE:
+		case CMD_STATS_CS_ENABLE:
 		default:
-			pr_err("%s Unsupported AXI configuration %x ", __func__,
-				cmd->cmd_type);
-		break;
+			pr_err("%s Unsupported cmd type %d",
+				__func__, cmd->cmd_type);
+			break;
 		}
+		goto vfe40_config_done;
+	}
+	switch (cmd->cmd_type) {
+	case CMD_GENERAL:
+		rc = vfe40_proc_general(pmctl, &vfecmd, vfe40_ctrl);
+	break;
+	case CMD_VFE_COUNT_PIX_SOF_ENABLE: {
+		int enable = *((int *)cmd->value);
+		if (enable)
+			vfe40_ctrl->vfe_sof_count_enable = TRUE;
+		else
+			vfe40_ctrl->vfe_sof_count_enable = false;
+	}
+	break;
+	case CMD_VFE_PIX_SOF_COUNT_UPDATE:
+		if (!vfe40_ctrl->vfe_sof_count_enable)
+			vfe40_ctrl->share_ctrl->vfeFrameId =
+			*((uint32_t *)vfe_params->data);
+	break;
+	case CMD_CONFIG_PING_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe40_output_ch *outch =
+			vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+		outch->ping = *((struct msm_free_buf *)data);
+	}
+	break;
+
+	case CMD_CONFIG_PONG_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe40_output_ch *outch =
+			vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+		outch->pong = *((struct msm_free_buf *)data);
+	}
+	break;
+
+	case CMD_CONFIG_FREE_BUF_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe40_output_ch *outch =
+			vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+		outch->free_buf = *((struct msm_free_buf *)data);
+	}
+	break;
+
+	case CMD_SNAP_BUF_RELEASE:
+		break;
+
+	default:
+		pr_err("%s Unsupported AXI configuration %x ", __func__,
+			cmd->cmd_type);
+	break;
 	}
 vfe40_config_done:
 	kfree(scfg);
@@ -3526,6 +4984,39 @@
 	return rc;
 }
 
+static struct msm_cam_clk_info vfe40_clk_info[] = {
+	{"camss_top_ahb_clk", -1},
+	{"vfe_clk_src", 266670000},
+	{"camss_vfe_vfe_clk", -1},
+	{"camss_csi_vfe_clk", -1},
+	{"iface_clk", -1},
+	{"bus_clk", -1},
+	{"alt_bus_clk", -1},
+};
+
+static int msm_axi_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+						u32 freq, u32 flags)
+{
+	int rc = 0;
+	int round_rate;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+
+	round_rate = clk_round_rate(axi_ctrl->vfe_clk[1], freq);
+	if (rc < 0) {
+		pr_err("%s: clk_round_rate failed %d\n",
+					__func__, rc);
+		return rc;
+	}
+
+	vfe_clk_rate = round_rate;
+	rc = clk_set_rate(axi_ctrl->vfe_clk[1], round_rate);
+	if (rc < 0)
+		pr_err("%s: clk_set_rate failed %d\n",
+					__func__, rc);
+
+	return rc;
+}
+
 static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
 	.ioctl = msm_vfe_subdev_ioctl,
 };
@@ -3534,46 +5025,1103 @@
 	.core = &msm_vfe_subdev_core_ops,
 };
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl)
+static void msm_vfe40_init_vbif_parms(void __iomem *vfe_vbif_base)
+{
+	msm_camera_io_w_mb(0x1,
+		vfe_vbif_base + VFE40_VBIF_CLKON);
+	msm_camera_io_w_mb(0x1,
+		vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+	msm_camera_io_w_mb(0xFFFF,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+	msm_camera_io_w_mb(0xFFFFFFFF,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+	msm_camera_io_w_mb(0x00001010,
+		vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+	msm_camera_io_w_mb(0x00001010,
+		vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+	msm_camera_io_w_mb(0x00000707,
+		vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+	msm_camera_io_w_mb(0x00000030,
+		vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+	msm_camera_io_w_mb(0x04210842,
+		vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF0);
+	msm_camera_io_w_mb(0x04210842,
+		vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF1);
+}
+
+int msm_axi_subdev_init(struct v4l2_subdev *sd)
+{
+	int rc = 0;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
+	if (mctl == NULL) {
+		pr_err("%s: mctl is NULL\n", __func__);
+		rc = -EINVAL;
+		goto mctl_failed;
+	}
+	axi_ctrl->share_ctrl->axi_ref_cnt++;
+	if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
+		return rc;
+
+	spin_lock_init(&axi_ctrl->tasklet_lock);
+	INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
+	spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
+
+	axi_ctrl->share_ctrl->vfebase = ioremap(axi_ctrl->vfemem->start,
+		resource_size(axi_ctrl->vfemem));
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto remap_failed;
+	}
+
+	axi_ctrl->share_ctrl->vfe_vbif_base =
+		ioremap(axi_ctrl->vfe_vbif_mem->start,
+			resource_size(axi_ctrl->vfe_vbif_mem));
+	if (!axi_ctrl->share_ctrl->vfe_vbif_base) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto remap_failed;
+	}
+
+	if (axi_ctrl->fs_vfe) {
+		rc = regulator_enable(axi_ctrl->fs_vfe);
+		if (rc) {
+			pr_err("%s: Regulator enable failed\n",	__func__);
+			goto fs_failed;
+		}
+	}
+
+	rc = msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe40_clk_info,
+			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe40_clk_info), 1);
+	if (rc < 0)
+		goto clk_enable_failed;
+
+	axi_ctrl->bus_perf_client =
+		msm_bus_scale_register_client(&vfe_bus_client_pdata);
+	if (!axi_ctrl->bus_perf_client) {
+		pr_err("%s: Registration Failed!\n", __func__);
+		axi_ctrl->bus_perf_client = 0;
+		goto bus_scale_register_failed;
+	}
+
+	msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_PREVIEW);
+
+	rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx);
+	if (rc < 0) {
+		pr_err("%s: imgwr attach failed rc = %d\n", __func__, rc);
+		rc = -ENODEV;
+		goto device_imgwr_attach_failed;
+	}
+
+	msm_vfe40_init_vbif_parms(axi_ctrl->share_ctrl->vfe_vbif_base);
+
+	axi_ctrl->share_ctrl->register_total = VFE40_REGISTER_TOTAL;
+
+	spin_lock_init(&axi_ctrl->share_ctrl->stop_flag_lock);
+	spin_lock_init(&axi_ctrl->share_ctrl->update_ack_lock);
+	spin_lock_init(&axi_ctrl->share_ctrl->start_ack_lock);
+	init_completion(&axi_ctrl->share_ctrl->reset_complete);
+
+	if (!axi_ctrl->use_irq_router)
+		enable_irq(axi_ctrl->vfeirq->start);
+
+	return rc;
+
+bus_scale_register_failed:
+	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe40_clk_info,
+		axi_ctrl->vfe_clk, ARRAY_SIZE(vfe40_clk_info), 0);
+clk_enable_failed:
+	if (axi_ctrl->fs_vfe)
+		regulator_disable(axi_ctrl->fs_vfe);
+fs_failed:
+	iounmap(axi_ctrl->share_ctrl->vfebase);
+	axi_ctrl->share_ctrl->vfebase = NULL;
+remap_failed:
+	iommu_detach_device(mctl->domain, axi_ctrl->iommu_ctx);
+device_imgwr_attach_failed:
+	if (!axi_ctrl->use_irq_router)
+		disable_irq(axi_ctrl->vfeirq->start);
+mctl_failed:
+	return rc;
+}
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
 	struct vfe40_ctrl_type *vfe40_ctrl =
 		(struct vfe40_ctrl_type *)v4l2_get_subdevdata(sd);
-	v4l2_set_subdev_hostdata(sd, mctl);
 
-	spin_lock_init(&vfe40_ctrl->share_ctrl->stop_flag_lock);
 	spin_lock_init(&vfe40_ctrl->state_lock);
-	spin_lock_init(&vfe40_ctrl->io_lock);
-	spin_lock_init(&vfe40_ctrl->update_ack_lock);
 	spin_lock_init(&vfe40_ctrl->stats_bufq_lock);
 
-
 	vfe40_ctrl->update_linear = false;
 	vfe40_ctrl->update_rolloff = false;
 	vfe40_ctrl->update_la = false;
 	vfe40_ctrl->update_gamma = false;
+	vfe40_ctrl->vfe_sof_count_enable = true;
 	vfe40_ctrl->hfr_mode = HFR_MODE_OFF;
 
+	memset(&vfe40_ctrl->stats_ctrl, 0,
+		   sizeof(struct msm_stats_bufq_ctrl));
+	memset(&vfe40_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
+
 	return rc;
 }
 
+void msm_axi_subdev_release(struct v4l2_subdev *sd)
+{
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return;
+	}
+
+	CDBG("%s, free_irq\n", __func__);
+	axi_ctrl->share_ctrl->axi_ref_cnt--;
+	if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
+		return;
+	if (!axi_ctrl->use_irq_router)
+		disable_irq(axi_ctrl->vfeirq->start);
+	tasklet_kill(&axi_ctrl->vfe40_tasklet);
+
+	iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx);
+
+	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe40_clk_info,
+			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe40_clk_info), 0);
+	if (axi_ctrl->fs_vfe)
+		regulator_disable(axi_ctrl->fs_vfe);
+
+	iounmap(axi_ctrl->share_ctrl->vfebase);
+	iounmap(axi_ctrl->share_ctrl->vfe_vbif_base);
+	axi_ctrl->share_ctrl->vfebase = NULL;
+
+	if (atomic_read(&irq_cnt))
+		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
+
+	msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_EXIT);
+	axi_ctrl->bus_perf_client = 0;
+
+	msm_vfe_subdev_release(&axi_ctrl->share_ctrl->vfe40_ctrl->subdev);
+}
+
 void msm_vfe_subdev_release(struct v4l2_subdev *sd)
 {
 	struct vfe40_ctrl_type *vfe40_ctrl =
 		(struct vfe40_ctrl_type *)v4l2_get_subdevdata(sd);
-	if (!vfe40_ctrl->share_ctrl->vfebase)
-		vfe40_ctrl->share_ctrl->vfebase = NULL;
+	CDBG("vfe subdev release %p\n",
+		vfe40_ctrl->share_ctrl->vfebase);
 }
 
+void axi_abort(struct axi_ctrl_t *axi_ctrl)
+{
+	uint8_t  axi_busy_flag = true;
+	unsigned long flags;
+	/* axi halt command. */
+
+	spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+	axi_ctrl->share_ctrl->stop_ack_pending  = TRUE;
+	spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+	msm_camera_io_w(AXI_HALT,
+		axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
+	wmb();
+	while (axi_busy_flag) {
+		if (msm_camera_io_r(
+			axi_ctrl->share_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+			axi_busy_flag = false;
+	}
+	/* Ensure the write order while writing
+	* to the command register using the barrier */
+	msm_camera_io_w_mb(AXI_HALT_CLEAR,
+		axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
+
+	/* after axi halt, then ok to apply global reset.
+	* enable reset_ack and async timer interrupt only while
+	* stopping the pipeline.*/
+	msm_camera_io_w(0x80000000,
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
+	msm_camera_io_w(0xF0000000,
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+	/* Ensure the write order while writing
+	* to the command register using the barrier */
+	msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
+		axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+	if (axi_ctrl->share_ctrl->sync_abort)
+		wait_for_completion_interruptible(
+			&axi_ctrl->share_ctrl->reset_complete);
+}
+
+int axi_config_buffers(struct axi_ctrl_t *axi_ctrl,
+	struct msm_camera_vfe_params_t vfe_params)
+{
+	uint16_t vfe_mode = axi_ctrl->share_ctrl->current_mode
+			& ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+	int rc = 0;
+	switch (vfe_params.cmd_type) {
+	case AXI_CMD_PREVIEW:
+		if (vfe_mode) {
+			if ((axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
+				(axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_PREVIEW))
+				/* Configure primary channel */
+				rc = configure_pingpong_buffers(
+					VFE_MSG_START,
+					VFE_MSG_OUTPUT_PRIMARY,
+					axi_ctrl);
+			else
+			/* Configure secondary channel */
+				rc = configure_pingpong_buffers(
+					VFE_MSG_START,
+					VFE_MSG_OUTPUT_SECONDARY,
+					axi_ctrl);
+		}
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI0)
+			rc = configure_pingpong_buffers(
+				VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY1,
+				axi_ctrl);
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI1)
+			rc = configure_pingpong_buffers(
+				VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY2,
+				axi_ctrl);
+
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers for preview",
+				__func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		break;
+	case AXI_CMD_RAW_CAPTURE:
+		rc = configure_pingpong_buffers(
+			VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
+			axi_ctrl);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers for snapshot",
+				__func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		break;
+	case AXI_CMD_ZSL:
+		rc = configure_pingpong_buffers(VFE_MSG_START,
+			VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
+		if (rc < 0)
+			goto config_done;
+		rc = configure_pingpong_buffers(VFE_MSG_START,
+			VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
+		if (rc < 0)
+			goto config_done;
+		break;
+	case AXI_CMD_RECORD:
+		if (axi_ctrl->share_ctrl->current_mode &
+			VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+			axi_ctrl->share_ctrl->outpath.out1.inst_handle =
+				vfe_params.inst_handle;
+			rc = configure_pingpong_buffers(
+				VFE_MSG_START_RECORDING,
+				VFE_MSG_OUTPUT_SECONDARY,
+				axi_ctrl);
+		} else if (axi_ctrl->share_ctrl->current_mode &
+			VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+			axi_ctrl->share_ctrl->outpath.out0.inst_handle =
+				vfe_params.inst_handle;
+			rc = configure_pingpong_buffers(
+				VFE_MSG_START_RECORDING,
+				VFE_MSG_OUTPUT_PRIMARY,
+				axi_ctrl);
+		}
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers for video",
+				__func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		break;
+	case AXI_CMD_LIVESHOT:
+		axi_ctrl->share_ctrl->outpath.out0.inst_handle =
+			vfe_params.inst_handle;
+		rc = configure_pingpong_buffers(VFE_MSG_CAPTURE,
+					VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers for primary output",
+				__func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		break;
+	case AXI_CMD_CAPTURE:
+		if (axi_ctrl->share_ctrl->current_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		axi_ctrl->share_ctrl->current_mode ==
+			VFE_OUTPUTS_THUMB_AND_JPEG) {
+
+			/* Configure primary channel for JPEG */
+			rc = configure_pingpong_buffers(
+				VFE_MSG_JPEG_CAPTURE,
+				VFE_MSG_OUTPUT_PRIMARY,
+				axi_ctrl);
+		} else {
+			/* Configure primary channel */
+			rc = configure_pingpong_buffers(
+				VFE_MSG_CAPTURE,
+				VFE_MSG_OUTPUT_PRIMARY,
+				axi_ctrl);
+		}
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers for primary output",
+				__func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		/* Configure secondary channel */
+		rc = configure_pingpong_buffers(
+				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+				axi_ctrl);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers for secondary output",
+				__func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+
+	}
+config_done:
+	return rc;
+}
+
+void axi_start(struct msm_cam_media_controller *pmctl,
+	struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
+{
+	uint32_t irq_comp_mask = 0, irq_mask = 0;
+	int rc = 0;
+	uint32_t reg_update = 0;
+	uint16_t operation_mode =
+		(axi_ctrl->share_ctrl->current_mode &
+		~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
+	rc = axi_config_buffers(axi_ctrl, vfe_params);
+	if (rc < 0)
+		return;
+
+	switch (vfe_params.cmd_type) {
+	case AXI_CMD_PREVIEW:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_PREVIEW);
+		break;
+	case AXI_CMD_CAPTURE:
+	case AXI_CMD_RAW_CAPTURE:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_CAPTURE);
+		break;
+	case AXI_CMD_RECORD:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_VIDEO);
+		return;
+	case AXI_CMD_ZSL:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_ZSL);
+		break;
+	case AXI_CMD_LIVESHOT:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_LIVESHOT);
+		return;
+	default:
+		return;
+	}
+
+	irq_comp_mask =
+		msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
+	irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+
+	if (axi_ctrl->share_ctrl->outpath.output_mode &
+			VFE40_OUTPUT_MODE_PRIMARY) {
+		if (vfe_params.cmd_type == AXI_CMD_RAW_CAPTURE) {
+			irq_comp_mask |=
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0;
+		} else {
+			irq_comp_mask |= (
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
+		}
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
+			   VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		irq_comp_mask |= (
+			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
+			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	}
+	if (axi_ctrl->share_ctrl->outpath.output_mode &
+			VFE40_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= (
+			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
+			VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask |= (
+			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	}
+	if (axi_ctrl->share_ctrl->outpath.output_mode &
+		VFE40_OUTPUT_MODE_TERTIARY1) {
+		irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
+			VFE_WM_OFFSET));
+	}
+	if (axi_ctrl->share_ctrl->outpath.output_mode &
+		VFE40_OUTPUT_MODE_TERTIARY2) {
+		irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
+			VFE_WM_OFFSET));
+	}
+
+	msm_camera_io_w(irq_comp_mask,
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+
+	switch (vfe_params.cmd_type) {
+	case AXI_CMD_PREVIEW: {
+		switch (operation_mode) {
+		case VFE_OUTPUTS_PREVIEW:
+		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+			if (axi_ctrl->share_ctrl->outpath.output_mode &
+				VFE40_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch1]);
+			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
+					VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch1]);
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch2]);
+			}
+			break;
+		default:
+			if (axi_ctrl->share_ctrl->outpath.output_mode &
+				VFE40_OUTPUT_MODE_SECONDARY) {
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out1.ch0]);
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out1.ch1]);
+			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
+				VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out1.ch0]);
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out1.ch1]);
+				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+					+ vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out1.ch2]);
+			}
+			break;
+			}
+		}
+		break;
+	default:
+		if (axi_ctrl->share_ctrl->outpath.output_mode &
+			VFE40_OUTPUT_MODE_PRIMARY) {
+			if (vfe_params.cmd_type == AXI_CMD_RAW_CAPTURE) {
+				msm_camera_io_w(1,
+					axi_ctrl->share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch0]);
+			} else {
+				msm_camera_io_w(1,
+					axi_ctrl->share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[axi_ctrl
+					->share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(1,
+					axi_ctrl->share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch1]);
+			}
+		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
+				VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch2]);
+		}
+
+		if (axi_ctrl->share_ctrl->outpath.output_mode &
+			VFE40_OUTPUT_MODE_SECONDARY) {
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch1]);
+		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
+			VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe40_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch2]);
+		}
+		break;
+	}
+
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+			vfe40_AXI_WM_CFG[axi_ctrl->share_ctrl->
+			outpath.out2.ch0]);
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+			vfe40_AXI_WM_CFG[axi_ctrl->share_ctrl->
+			outpath.out3.ch0]);
+
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		irq_mask |= VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK;
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
+				0, 1))
+			reg_update |= 0x2;
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		irq_mask |= VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK;
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
+				0, 1))
+			reg_update |= 0x4;
+	}
+	msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+		VFE_IRQ_MASK_0);
+	if (operation_mode) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->pix0_update_ack_pending,
+				0, 1))
+			reg_update |= 0x1;
+	}
+
+	msm_camera_io_w_mb(reg_update,
+			axi_ctrl->share_ctrl->vfebase +
+			VFE_REG_UPDATE_CMD);
+	axi_ctrl->share_ctrl->operation_mode |=
+		axi_ctrl->share_ctrl->current_mode;
+	axi_enable_irq(axi_ctrl->share_ctrl);
+}
+
+void axi_stop(struct msm_cam_media_controller *pmctl,
+	struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
+{
+	uint32_t reg_update = 0;
+	uint32_t operation_mode =
+	axi_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+		VFE_OUTPUTS_RDI1);
+
+	switch (vfe_params.cmd_type) {
+	case AXI_CMD_PREVIEW:
+	case AXI_CMD_CAPTURE:
+	case AXI_CMD_RAW_CAPTURE:
+	case AXI_CMD_ZSL:
+		break;
+	case AXI_CMD_RECORD:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_PREVIEW);
+		return;
+	case AXI_CMD_LIVESHOT:
+		msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_VIDEO);
+		return;
+	default:
+		return;
+	}
+
+	if (axi_ctrl->share_ctrl->stop_immediately) {
+		axi_disable_irq(axi_ctrl->share_ctrl);
+		axi_stop_process(axi_ctrl->share_ctrl);
+		return;
+	}
+
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0, 2))
+			reg_update |= 0x2;
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0, 2))
+			reg_update |= 0x4;
+	}
+	if (operation_mode) {
+		if (!atomic_cmpxchg(
+			&axi_ctrl->share_ctrl->pix0_update_ack_pending, 0, 2))
+			reg_update |= 0x1;
+	}
+	msm_camera_io_w_mb(reg_update,
+		axi_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
+{
+	struct msm_vfe_cfg_cmd cfgcmd;
+	struct msm_isp_cmd vfecmd;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+	int rc = 0, vfe_cmd_type = 0, rdi_mode = 0;
+
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return -EFAULT;
+	}
+	memset(&cfgcmd, 0, sizeof(struct msm_vfe_cfg_cmd));
+	if (NULL != arg) {
+		if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
+			ERR_COPY_FROM_USER();
+			return -EFAULT;
+		}
+	}
+	memset(&vfecmd, 0, sizeof(struct msm_isp_cmd));
+	if (NULL != cfgcmd.value) {
+		if (copy_from_user(&vfecmd,
+				(void __user *)(cfgcmd.value),
+				sizeof(vfecmd))) {
+			pr_err("%s %d: copy_from_user failed\n", __func__,
+				__LINE__);
+			return -EFAULT;
+		}
+	}
+
+	vfe_cmd_type = (cfgcmd.cmd_type & ~(CMD_AXI_CFG_TERT1|
+		CMD_AXI_CFG_TERT2));
+	switch (cfgcmd.cmd_type) {
+	case CMD_AXI_CFG_TERT1:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe40_config_axi(axi_ctrl, OUTPUT_TERT1, axio);
+		kfree(axio);
+		return rc;
+		}
+	case CMD_AXI_CFG_TERT2:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe40_config_axi(axi_ctrl, OUTPUT_TERT2, axio);
+		kfree(axio);
+		return rc;
+		}
+	case CMD_AXI_CFG_TERT1|CMD_AXI_CFG_TERT2:{
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio)
+			return -ENOMEM;
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			return -EFAULT;
+		}
+		vfe40_config_axi(axi_ctrl, OUTPUT_TERT1|OUTPUT_TERT2, axio);
+		kfree(axio);
+		return rc;
+		}
+	default:
+		if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT1)
+			rdi_mode |= OUTPUT_TERT1;
+		if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT2)
+			rdi_mode |= OUTPUT_TERT2;
+	}
+	switch (vfe_cmd_type) {
+	case CMD_AXI_CFG_PRIM: {
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			rc = -EFAULT;
+			break;
+		}
+		vfe40_config_axi(axi_ctrl, rdi_mode|OUTPUT_PRIM, axio);
+		kfree(axio);
+		break;
+		}
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS: {
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			rc = -EFAULT;
+			break;
+		}
+		vfe40_config_axi(axi_ctrl, rdi_mode|OUTPUT_PRIM_ALL_CHNLS,
+			axio);
+		kfree(axio);
+		break;
+		}
+	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC: {
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			rc = -EFAULT;
+			break;
+		}
+		vfe40_config_axi(axi_ctrl,
+			rdi_mode|OUTPUT_PRIM|OUTPUT_SEC, axio);
+		kfree(axio);
+		break;
+		}
+	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS: {
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			rc = -EFAULT;
+			break;
+		}
+		vfe40_config_axi(axi_ctrl,
+			rdi_mode|OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
+		kfree(axio);
+		break;
+		}
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC: {
+		uint32_t *axio = NULL;
+		axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+				vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+			kfree(axio);
+			rc = -EFAULT;
+			break;
+		}
+		vfe40_config_axi(axi_ctrl,
+			rdi_mode|OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
+		kfree(axio);
+		break;
+		}
+
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS:
+		pr_err("%s Invalid/Unsupported AXI configuration %x",
+			__func__, cfgcmd.cmd_type);
+		break;
+	case CMD_AXI_START: {
+		struct msm_camera_vfe_params_t vfe_params;
+		if (copy_from_user(&vfe_params,
+				(void __user *)(vfecmd.value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				return -EFAULT;
+		}
+		axi_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
+		axi_start(pmctl, axi_ctrl, vfe_params);
+		}
+		break;
+	case CMD_AXI_STOP: {
+		struct msm_camera_vfe_params_t vfe_params;
+		if (copy_from_user(&vfe_params,
+				(void __user *)(vfecmd.value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				return -EFAULT;
+		}
+		axi_ctrl->share_ctrl->current_mode =
+			vfe_params.operation_mode;
+		axi_ctrl->share_ctrl->stop_immediately =
+			vfe_params.stop_immediately;
+		axi_stop(pmctl, axi_ctrl, vfe_params);
+		}
+		break;
+	case CMD_AXI_RESET:
+		axi_reset(axi_ctrl);
+		break;
+	case CMD_AXI_ABORT:
+		if (copy_from_user(&axi_ctrl->share_ctrl->sync_abort,
+				(void __user *)(vfecmd.value),
+				sizeof(uint8_t))) {
+				return -EFAULT;
+		}
+		axi_abort(axi_ctrl);
+		break;
+	default:
+		pr_err("%s Unsupported AXI configuration %x ", __func__,
+			cfgcmd.cmd_type);
+		break;
+	}
+	return rc;
+}
+
+static void msm_axi_process_irq(struct v4l2_subdev *sd, void *arg)
+{
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	uint32_t irqstatus = (uint32_t) arg;
+
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return;
+	}
+
+	/* next, check output path related interrupts. */
+	if (irqstatus &
+		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
+		CDBG("Image composite done 0 irq occured.\n");
+		vfe40_process_output_path_irq_0(axi_ctrl);
+	}
+	if (irqstatus &
+		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
+		CDBG("Image composite done 1 irq occured.\n");
+		vfe40_process_output_path_irq_1(axi_ctrl);
+	}
+
+	if (axi_ctrl->share_ctrl->comp_output_mode &
+		VFE40_OUTPUT_MODE_TERTIARY1)
+		if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0
+			+ VFE_WM_OFFSET)))
+			vfe40_process_output_path_irq_rdi0(axi_ctrl);
+	if (axi_ctrl->share_ctrl->comp_output_mode &
+		VFE40_OUTPUT_MODE_TERTIARY2)
+		if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0
+			+ VFE_WM_OFFSET)))
+			vfe40_process_output_path_irq_rdi1(axi_ctrl);
+
+	/* in snapshot mode if done then send
+	snapshot done message */
+	if (
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_THUMB_AND_MAIN ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_MAIN_AND_THUMB ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_THUMB_AND_JPEG ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		axi_ctrl->share_ctrl->operation_mode &
+			VFE_OUTPUTS_RAW) {
+		if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
+				&& (axi_ctrl->share_ctrl->outpath.out1.
+				capture_cnt == 0)) {
+			msm_camera_io_w_mb(
+				CAMIF_COMMAND_STOP_IMMEDIATELY,
+				axi_ctrl->share_ctrl->vfebase +
+				VFE_CAMIF_COMMAND);
+			axi_disable_irq(axi_ctrl->share_ctrl);
+			vfe40_send_isp_msg(&axi_ctrl->subdev,
+				axi_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_PIX0_UPDATE_ACK);
+			vfe40_send_isp_msg(&axi_ctrl->subdev,
+				axi_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_SNAPSHOT_DONE);
+		}
+	}
+}
+
+static int msm_axi_buf_cfg(struct v4l2_subdev *sd, void __user *arg)
+{
+	struct msm_camvfe_params *vfe_params =
+		(struct msm_camvfe_params *)arg;
+	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	void *data = vfe_params->data;
+	int rc = 0;
+
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (cmd->cmd_type) {
+	case CMD_CONFIG_PING_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe40_output_ch *outch =
+			vfe40_get_ch(path, axi_ctrl->share_ctrl);
+		outch->ping = *((struct msm_free_buf *)data);
+	}
+		break;
+
+	case CMD_CONFIG_PONG_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe40_output_ch *outch =
+			vfe40_get_ch(path, axi_ctrl->share_ctrl);
+		outch->pong = *((struct msm_free_buf *)data);
+	}
+		break;
+
+	case CMD_CONFIG_FREE_BUF_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe40_output_ch *outch =
+			vfe40_get_ch(path, axi_ctrl->share_ctrl);
+		outch->free_buf = *((struct msm_free_buf *)data);
+	}
+		break;
+	default:
+		pr_err("%s Unsupported AXI Buf config %x ", __func__,
+			cmd->cmd_type);
+	}
+	return rc;
+};
+
 static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
 
+static long msm_axi_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	int rc = -ENOIOCTLCMD;
+	switch (cmd) {
+	case VIDIOC_MSM_AXI_INIT:
+		rc = msm_axi_subdev_init(sd);
+		break;
+	case VIDIOC_MSM_AXI_CFG:
+		rc = msm_axi_config(sd, arg);
+		break;
+	case VIDIOC_MSM_AXI_IRQ:
+		msm_axi_process_irq(sd, arg);
+		rc = 0;
+		break;
+	case VIDIOC_MSM_AXI_BUF_CFG:
+		msm_axi_buf_cfg(sd, arg);
+		rc = 0;
+		break;
+	case VIDIOC_MSM_AXI_RELEASE:
+		msm_axi_subdev_release(sd);
+		rc = 0;
+		break;
+	case VIDIOC_MSM_AXI_RDI_COUNT_UPDATE: {
+		struct rdi_count_msg *msg = (struct rdi_count_msg *)arg;
+		struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+		switch (msg->rdi_interface) {
+		case RDI_0:
+			axi_ctrl->share_ctrl->rdi0FrameId = msg->count;
+			rc = 0;
+			break;
+		case RDI_1:
+			axi_ctrl->share_ctrl->rdi1FrameId = msg->count;
+			rc = 0;
+			break;
+		case RDI_2:
+			axi_ctrl->share_ctrl->rdi2FrameId = msg->count;
+			rc = 0;
+			break;
+		default:
+			pr_err("%s: Incorrect interface sent\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		break;
+	}
+	default:
+		pr_err("%s: command %d not found\n", __func__,
+						_IOC_NR(cmd));
+		break;
+	}
+	return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_axi_subdev_core_ops = {
+	.ioctl = msm_axi_subdev_ioctl,
+	.interrupt_service_routine = msm_axi_subdev_isr_routine,
+};
+
+static const struct v4l2_subdev_video_ops msm_axi_subdev_video_ops = {
+	.s_crystal_freq = msm_axi_subdev_s_crystal_freq,
+};
+
+static const struct v4l2_subdev_ops msm_axi_subdev_ops = {
+	.core = &msm_axi_subdev_core_ops,
+	.video = &msm_axi_subdev_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_axi_internal_ops;
+
 static int __devinit vfe40_probe(struct platform_device *pdev)
 {
 	int rc = 0;
 	struct axi_ctrl_t *axi_ctrl;
 	struct vfe40_ctrl_type *vfe40_ctrl;
 	struct vfe_share_ctrl_t *share_ctrl;
+	struct intr_table_entry irq_req;
 	struct msm_cam_subdev_info sd_info;
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 
@@ -3606,8 +6154,25 @@
 	share_ctrl->vfe40_ctrl = vfe40_ctrl;
 	axi_ctrl->share_ctrl = share_ctrl;
 	vfe40_ctrl->share_ctrl = share_ctrl;
+	axi_ctrl->share_ctrl->axi_ref_cnt = 0;
+	v4l2_subdev_init(&axi_ctrl->subdev, &msm_axi_subdev_ops);
+	axi_ctrl->subdev.internal_ops = &msm_axi_internal_ops;
+	axi_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(axi_ctrl->subdev.name,
+			 sizeof(axi_ctrl->subdev.name), "axi");
+	v4l2_set_subdevdata(&axi_ctrl->subdev, axi_ctrl);
 	axi_ctrl->pdev = pdev;
-	vfe40_axi_probe(axi_ctrl);
+
+	sd_info.sdev_type = AXI_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = 0;
+	msm_cam_register_subdev_node(&axi_ctrl->subdev, &sd_info);
+
+	media_entity_init(&axi_ctrl->subdev.entity, 0, NULL, 0);
+	axi_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	axi_ctrl->subdev.entity.group_id = AXI_DEV;
+	axi_ctrl->subdev.entity.name = pdev->name;
+	axi_ctrl->subdev.entity.revision = axi_ctrl->subdev.devnode->num;
 
 	v4l2_subdev_init(&vfe40_ctrl->subdev, &msm_vfe_subdev_ops);
 	vfe40_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
@@ -3624,6 +6189,15 @@
 		rc = -ENODEV;
 		goto vfe40_no_resource;
 	}
+
+	axi_ctrl->vfe_vbif_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "vfe_vbif");
+	if (!axi_ctrl->vfe_vbif_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe40_no_resource;
+	}
+
 	axi_ctrl->vfeirq = platform_get_resource_byname(pdev,
 					IORESOURCE_IRQ, "vfe");
 	if (!axi_ctrl->vfeirq) {
@@ -3640,26 +6214,83 @@
 		goto vfe40_no_resource;
 	}
 
-	rc = request_irq(axi_ctrl->vfeirq->start, vfe40_parse_irq,
-		IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
-	if (rc < 0) {
-		release_mem_region(axi_ctrl->vfemem->start,
-			resource_size(axi_ctrl->vfemem));
-		pr_err("%s: irq request fail\n", __func__);
-		rc = -EBUSY;
+	axi_ctrl->fs_vfe = regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(axi_ctrl->fs_vfe)) {
+		pr_err("%s: Regulator get failed %ld\n", __func__,
+			PTR_ERR(axi_ctrl->fs_vfe));
+		axi_ctrl->fs_vfe = NULL;
+	}
+
+	/* Register subdev node before requesting irq since
+	 * irq_num is needed by msm_cam_server */
+	sd_info.sdev_type = VFE_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = axi_ctrl->vfeirq->start;
+	msm_cam_register_subdev_node(&vfe40_ctrl->subdev, &sd_info);
+
+	media_entity_init(&vfe40_ctrl->subdev.entity, 0, NULL, 0);
+	vfe40_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	vfe40_ctrl->subdev.entity.group_id = VFE_DEV;
+	vfe40_ctrl->subdev.entity.name = pdev->name;
+	vfe40_ctrl->subdev.entity.revision = vfe40_ctrl->subdev.devnode->num;
+
+	/* Request for this device irq from the camera server. If the
+	 * IRQ Router is present on this target, the interrupt will be
+	 * handled by the camera server and the interrupt service
+	 * routine called. If the request_irq call returns ENXIO, then
+	 * the IRQ Router hardware is not present on this target. We
+	 * have to request for the irq ourselves and register the
+	 * appropriate interrupt handler. */
+	axi_ctrl->use_irq_router = true;
+	irq_req.cam_hw_idx       = MSM_CAM_HW_VFE0 + pdev->id;
+	irq_req.dev_name         = "vfe";
+	irq_req.irq_idx          = CAMERA_SS_IRQ_8;
+	irq_req.irq_num          = axi_ctrl->vfeirq->start;
+	irq_req.is_composite     = 0;
+	irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+	irq_req.num_hwcore       = 1;
+	irq_req.subdev_list[0]   = &axi_ctrl->subdev;
+	irq_req.data             = (void *)axi_ctrl;
+	rc = msm_cam_server_request_irq(&irq_req);
+	if (rc == -ENXIO) {
+		/* IRQ Router hardware is not present on this hardware.
+		 * Request for the IRQ and register the interrupt handler. */
+		axi_ctrl->use_irq_router = false;
+		rc = request_irq(axi_ctrl->vfeirq->start, vfe40_parse_irq,
+			IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
+		if (rc < 0) {
+			release_mem_region(axi_ctrl->vfemem->start,
+				resource_size(axi_ctrl->vfemem));
+			pr_err("%s: irq request fail\n", __func__);
+			rc = -EBUSY;
+			goto vfe40_no_resource;
+		}
+		disable_irq(axi_ctrl->vfeirq->start);
+	} else if (rc < 0) {
+		pr_err("%s Error registering irq ", __func__);
 		goto vfe40_no_resource;
 	}
 
-	disable_irq(axi_ctrl->vfeirq->start);
+	/*get device context for IOMMU*/
+	if (pdev->id == 0)
+		axi_ctrl->iommu_ctx = msm_iommu_get_ctx("vfe0");
+	else if (pdev->id == 1)
+		axi_ctrl->iommu_ctx = msm_iommu_get_ctx("vfe1");
+	if (!axi_ctrl->iommu_ctx) {
+		release_mem_region(axi_ctrl->vfemem->start,
+			resource_size(axi_ctrl->vfemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vfe40_no_resource;
+	}
 
 	tasklet_init(&axi_ctrl->vfe40_tasklet,
 		axi40_do_tasklet, (unsigned long)axi_ctrl);
 
 	vfe40_ctrl->pdev = pdev;
-	sd_info.sdev_type = VFE_DEV;
-	sd_info.sd_index = pdev->id;
-	sd_info.irq_num = axi_ctrl->vfeirq->start;
-	msm_cam_register_subdev_node(&vfe40_ctrl->subdev, &sd_info);
+	/*disable bayer stats by default*/
+	vfe40_ctrl->ver_num.main = 0;
+
 	return 0;
 
 vfe40_no_resource:
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.h b/drivers/media/video/msm/vfe/msm_vfe40.h
index c8b0cb8..8201d18 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.h
+++ b/drivers/media/video/msm/vfe/msm_vfe40.h
@@ -50,7 +50,16 @@
 
 /* reset the pipeline when reset command.
  * bit 26-32 = 0, domain reset, bit 0-9 = 1 for module reset. */
-#define VFE_RESET_UPON_RESET_CMD  0x000001ff
+#define VFE_RESET_UPON_RESET_CMD  0x000003ff
+
+/* reset the vfe only when reset command*/
+#define VFE_ONLY_RESET_CMD  0x00000002
+
+/*Vfe module reset command*/
+#define VFE_MODULE_RESET_CMD 0x07ffffff
+
+/* wm bit offset for IRQ MASK and IRQ STATUS register */
+#define VFE_WM_OFFSET 6
 
 /* constants for irq registers */
 #define VFE_DISABLE_ALL_IRQS 0
@@ -60,6 +69,9 @@
 
 #define VFE_IRQ_STATUS0_CAMIF_SOF_MASK            (0x00000001<<0)
 #define VFE_IRQ_STATUS0_REG_UPDATE_MASK           (0x00000001<<4)
+#define VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK      (0x00000001<<5)
+#define VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK      (0x00000001<<6)
+#define VFE_IRQ_STATUS0_RDI2_REG_UPDATE_MASK      (0x00000001<<7)
 #define VFE_IRQ_STATUS0_STATS_BE                  (0x00000001<<16)
 #define VFE_IRQ_STATUS0_STATS_BG                  (0x00000001<<17)
 #define VFE_IRQ_STATUS0_STATS_BF                  (0x00000001<<18)
@@ -84,13 +96,22 @@
 #define VFE_IRQ_STATUS1_ASYNC_TIMER2              (0x00000001<<30)
 #define VFE_IRQ_STATUS1_ASYNC_TIMER3              (0x00000001<<31)
 
+/*TODOs the irq status passed from axi to vfe irq handler does not account
+* for 2 irq status registers. So below macro is added to differentiate between
+* same bit set on both irq status registers. This wil be fixed later by passing
+*entire payload to vfe irq handler and parsing there instead of passing just the
+*status bit*/
+
+#define VFE_IRQ_STATUS0_RDI0_REG_UPDATE  VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK
+#define VFE_IRQ_STATUS0_RDI1_REG_UPDATE  VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK
+
 /* imask for while waiting for stop ack,  driver has already
  * requested stop, waiting for reset irq, and async timer irq.
- * For irq_status_0, bit 28-32 are for async timer. For
- * irq_status_1, bit 22 for reset irq, bit 23 for axi_halt_ack
+ * For irq_status_1, bit 28-32 are for async timer. For
+ * irq_status_0, bit 31 for reset irq, bit 23 for axi_halt_ack
    irq */
 #define VFE_IMASK_WHILE_STOPPING_0  0x80000000
-#define VFE_IMASK_WHILE_STOPPING_1  0x00000100
+#define VFE_IMASK_WHILE_STOPPING_1  0xF0000000
 
 /* For ABF bit 4 is set to zero and other's 1 */
 #define ABF_MASK 0xFFFFFFF7
@@ -118,9 +139,12 @@
 #define CS_ENABLE_MASK    (0x00000001<<10)
 #define CLF_ENABLE_MASK   (0x00000001<<12)
 #define IHIST_ENABLE_MASK (0x00000001<<15)
+#define BHIST_ENABLE_MASK (0x00000001<<18)
 #define RS_CS_ENABLE_MASK (RS_ENABLE_MASK|CS_ENABLE_MASK)
 #define STATS_ENABLE_MASK 0x000487E0   /* bit 18,15,10,9,8,7,6,5*/
 
+#define STATS_BHIST_ENABLE_MASK (0x00000001<<1)
+
 #define VFE_DMI_CFG_DEFAULT              0x00000100
 
 #define HFR_MODE_OFF 1
@@ -173,13 +197,14 @@
 #define V40_OUT_CLAMP_OFF         0x00000874
 #define V40_OUT_CLAMP_LEN         16
 
-#define V40_OPERATION_CFG_LEN     44
+#define V40_OPERATION_CFG_LEN     32
 
-#define V40_AXI_OUT_OFF           0x0000004C
-#define V40_AXI_OUT_LEN           412
-#define V40_AXI_CH_INF_LEN        32
+#define V40_AXI_BUS_CMD_OFF       0x0000004C
+#define V40_AXI_BUS_CFG_LEN       284
+#define V40_AXI_OUT_LEN           344
 #define V40_AXI_CFG_LEN           71
 
+#define V40_BUS_PM_CMD            0x00000270
 #define V40_FOV_ENC_OFF           0x00000854
 #define V40_FOV_ENC_LEN           16
 #define V40_FOV_VIEW_OFF          0x00000864
@@ -213,7 +238,6 @@
 #define V40_MESH_ROLL_OFF_CFG_LEN             36
 #define V40_MESH_ROLL_OFF_TABLE_SIZE          130
 
-
 #define V40_COLOR_COR_OFF 0x000005D0
 #define V40_COLOR_COR_LEN 52
 
@@ -309,29 +333,6 @@
 
 #define VFE40_LINEARIZATON_TABLE_LENGTH    36
 
-#define VFE_WM_CFG_BASE 0x0070
-#define VFE_WM_CFG_LEN 0x0024
-
-#define vfe40_get_ch_ping_addr(base, chn) \
-	(msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
-#define vfe40_get_ch_pong_addr(base, chn) \
-	(msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
-#define vfe40_get_ch_addr(ping_pong, base, chn) \
-	((((ping_pong) & (1 << (chn))) == 0) ? \
-	(vfe40_get_ch_pong_addr((base), chn)) : \
-	(vfe40_get_ch_ping_addr((base), chn)))
-
-#define vfe40_put_ch_ping_addr(base, chn, addr) \
-	(msm_camera_io_w((addr), \
-	(base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
-#define vfe40_put_ch_pong_addr(base, chn, addr) \
-	(msm_camera_io_w((addr), \
-	(base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
-#define vfe40_put_ch_addr(ping_pong, base, chn, addr) \
-	(((ping_pong) & (1 << (chn))) == 0 ?   \
-	vfe40_put_ch_pong_addr((base), (chn), (addr)) : \
-	vfe40_put_ch_ping_addr((base), (chn), (addr)))
-
 struct vfe_cmd_hw_version {
 	uint32_t minorVersion;
 	uint32_t majorVersion;
@@ -704,7 +705,7 @@
 struct vfe40_output_ch {
 	struct list_head free_buf_queue;
 	spinlock_t free_buf_lock;
-	uint16_t image_mode;
+	uint32_t inst_handle;
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
@@ -719,7 +720,8 @@
 #define VFE40_IMASK_ERROR_ONLY_0  0x0
 /* when normal case, don't want to block error status. */
 /* bit 0-21 are error irq bits */
-#define VFE40_IMASK_ERROR_ONLY_1               0x005FFFFF
+#define VFE40_IMASK_COMMON_ERROR_ONLY_1       0x0000FF00
+#define VFE40_IMASK_VFE_ERROR_ONLY_1          0x00FF01FF
 #define VFE40_IMASK_CAMIF_ERROR               (0x00000001<<0)
 #define VFE40_IMASK_BHIST_OVWR                (0x00000001<<1)
 #define VFE40_IMASK_STATS_CS_OVWR             (0x00000001<<2)
@@ -728,21 +730,22 @@
 #define VFE40_IMASK_REALIGN_BUF_CB_OVFL       (0x00000001<<5)
 #define VFE40_IMASK_REALIGN_BUF_CR_OVFL       (0x00000001<<6)
 #define VFE40_IMASK_VIOLATION                 (0x00000001<<7)
-#define VFE40_IMASK_IMG_MAST_0_BUS_OVFL       (0x00000001<<8)
-#define VFE40_IMASK_IMG_MAST_1_BUS_OVFL       (0x00000001<<9)
-#define VFE40_IMASK_IMG_MAST_2_BUS_OVFL       (0x00000001<<10)
-#define VFE40_IMASK_IMG_MAST_3_BUS_OVFL       (0x00000001<<11)
-#define VFE40_IMASK_IMG_MAST_4_BUS_OVFL       (0x00000001<<12)
-#define VFE40_IMASK_IMG_MAST_5_BUS_OVFL       (0x00000001<<13)
-#define VFE40_IMASK_IMG_MAST_6_BUS_OVFL       (0x00000001<<14)
-#define VFE40_IMASK_STATS_AE_BG_BUS_OVFL      (0x00000001<<15)
-#define VFE40_IMASK_STATS_AF_BF_BUS_OVFL      (0x00000001<<16)
-#define VFE40_IMASK_STATS_AWB_BUS_OVFL        (0x00000001<<17)
-#define VFE40_IMASK_STATS_RS_BUS_OVFL         (0x00000001<<18)
-#define VFE40_IMASK_STATS_CS_BUS_OVFL         (0x00000001<<19)
-#define VFE40_IMASK_STATS_IHIST_BUS_OVFL      (0x00000001<<20)
-#define VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<21)
-#define VFE40_IMASK_AXI_ERROR                 (0x00000001<<22)
+#define VFE40_IMASK_BUS_BDG_HALT_ACK          (0x00000001<<8)
+#define VFE40_IMASK_IMG_MAST_0_BUS_OVFL       (0x00000001<<9)
+#define VFE40_IMASK_IMG_MAST_1_BUS_OVFL       (0x00000001<<10)
+#define VFE40_IMASK_IMG_MAST_2_BUS_OVFL       (0x00000001<<11)
+#define VFE40_IMASK_IMG_MAST_3_BUS_OVFL       (0x00000001<<12)
+#define VFE40_IMASK_IMG_MAST_4_BUS_OVFL       (0x00000001<<13)
+#define VFE40_IMASK_IMG_MAST_5_BUS_OVFL       (0x00000001<<14)
+#define VFE40_IMASK_IMG_MAST_6_BUS_OVFL       (0x00000001<<15)
+#define VFE40_IMASK_STATS_BE_BUS_OVFL         (0x00000001<<16)
+#define VFE40_IMASK_STATS_BG_BUS_OVFL         (0x00000001<<17)
+#define VFE40_IMASK_STATS_BF_BUS_OVFL         (0x00000001<<18)
+#define VFE40_IMASK_STATS_AWB_BUS_OVFL        (0x00000001<<19)
+#define VFE40_IMASK_STATS_RS_BUS_OVFL         (0x00000001<<10)
+#define VFE40_IMASK_STATS_CS_BUS_OVFL         (0x00000001<<21)
+#define VFE40_IMASK_STATS_IHIST_BUS_OVFL      (0x00000001<<22)
+#define VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<23)
 
 #define VFE_COM_STATUS 0x000FE000
 
@@ -751,7 +754,8 @@
 
 	struct vfe40_output_ch out0; /* preview and thumbnail */
 	struct vfe40_output_ch out1; /* snapshot */
-	struct vfe40_output_ch out2; /* video    */
+	struct vfe40_output_ch out2; /* rdi0    */
+	struct vfe40_output_ch out3; /* rdi01   */
 };
 
 struct vfe40_frame_extra {
@@ -769,9 +773,7 @@
 	uint32_t  frameCounter;
 };
 
-#define VFE_CLEAR_ALL_IRQS              0xffffffff
-
-#define VFE_HW_VERSION			        0x00000000
+#define VFE_HW_VERSION			0x00000000
 #define VFE_GLOBAL_RESET                0x0000000C
 #define VFE_MODULE_RESET                0x00000010
 #define VFE_CGC_OVERRIDE                0x00000014
@@ -786,32 +788,67 @@
 #define VFE_IRQ_STATUS_1                0x0000003C
 #define VFE_IRQ_COMP_MASK               0x00000040
 #define VFE_BUS_CMD                     0x0000004C
-#define VFE_BUS_PING_PONG_STATUS        0x00000180
-#define VFE_AXI_CMD                     0x000001D8
-#define VFE_AXI_STATUS        0x000002C0
-#define VFE_BUS_STATS_PING_PONG_BASE    0x000000F4
+#define VFE_BUS_PING_PONG_STATUS        0x00000268
+#define VFE_AXI_CMD                     0x000002C0
+#define VFE_AXI_STATUS                  0x000002E4
+#define VFE_BUS_STATS_PING_PONG_BASE    0x00000168
 
-#define VFE_BUS_STATS_AEC_WR_PING_ADDR    0x000000F4
-#define VFE_BUS_STATS_AEC_WR_PONG_ADDR    0x000000F8
-#define VFE_BUS_STATS_AEC_UB_CFG          0x000000FC
-#define VFE_BUS_STATS_AF_WR_PING_ADDR     0x00000100
-#define VFE_BUS_STATS_AF_WR_PONG_ADDR     0x00000104
-#define VFE_BUS_STATS_AF_UB_CFG           0x00000108
-#define VFE_BUS_STATS_AWB_WR_PING_ADDR    0x0000010C
-#define VFE_BUS_STATS_AWB_WR_PONG_ADDR    0x00000110
-#define VFE_BUS_STATS_AWB_UB_CFG          0x00000114
-#define VFE_BUS_STATS_RS_WR_PING_ADDR    0x00000118
-#define VFE_BUS_STATS_RS_WR_PONG_ADDR    0x0000011C
-#define VFE_BUS_STATS_RS_UB_CFG          0x00000120
-#define VFE_BUS_STATS_CS_WR_PING_ADDR    0x00000124
-#define VFE_BUS_STATS_CS_WR_PONG_ADDR    0x00000128
-#define VFE_BUS_STATS_CS_UB_CFG          0x0000012C
-#define VFE_BUS_STATS_HIST_WR_PING_ADDR   0x00000130
-#define VFE_BUS_STATS_HIST_WR_PONG_ADDR   0x00000134
-#define VFE_BUS_STATS_HIST_UB_CFG          0x00000138
-#define VFE_BUS_STATS_SKIN_WR_PING_ADDR    0x0000013C
-#define VFE_BUS_STATS_SKIN_WR_PONG_ADDR    0x00000140
-#define VFE_BUS_STATS_SKIN_UB_CFG          0x00000144
+#define VFE_BUS_STATS_BE_WR_PING_ADDR    0x00000168
+#define VFE_BUS_STATS_BE_WR_PONG_ADDR    0x0000016C
+#define VFE_BUS_STATS_BE_WR_ADDR_CFG    0x00000170
+#define VFE_BUS_STATS_BE_UB_CFG          0x00000174
+#define VFE_BUS_STATS_BE_WR_FRAMEDROP_PATTERN  0x00000178
+#define VFE_BUS_STATS_BE_WR_IRQ_SUBSAMPLE_PATTERN 0x0000017C
+
+#define VFE_BUS_STATS_BG_WR_PING_ADDR     0x00000180
+#define VFE_BUS_STATS_BG_WR_PONG_ADDR     0x00000184
+#define VFE_BUS_STATS_BG_WR_ADDR_CFG      0x00000188
+#define VFE_BUS_STATS_BG_WR_UB_CFG        0x0000018C
+#define VFE_BUS_STATS_BG_WR_FRAMEDROP_PATTERN 0x00000190
+#define VFE_BUS_STATS_BG_WR_IRQ_SUBSAMPLE_PATTERN 0x00000194
+
+#define VFE_BUS_STATS_BF_WR_PING_ADDR     0x00000198
+#define VFE_BUS_STATS_BF_WR_PONG_ADDR     0x0000019C
+#define VFE_BUS_STATS_BF_WR_ADDR_CFG      0x000001A0
+#define VFE_BUS_STATS_BF_WR_UB_CFG        0x000001A4
+#define VFE_BUS_STATS_BF_WR_FRAMEDROP_PATTERN  0x000001A8
+#define VFE_BUS_STATS_BF_WR_IRQ_SUBSAMPLE_PATTERN  0x000001AC
+
+#define VFE_BUS_STATS_AWB_WR_PING_ADDR    0x000001B0
+#define VFE_BUS_STATS_AWB_WR_PONG_ADDR    0x000001B4
+#define VFE_BUS_STATS_AWB_WR_ADDR_CFG     0x000001B8
+#define VFE_BUS_STATS_AWB_WR_UB_CFG       0x000001BC
+#define VFE_BUS_STATS_AWB_WR_FRAMEDROP_PATTERN  0x000001C0
+#define VFE_BUS_STATS_AWB_WR_IRQ_SUBSAMPLE_PATTERN  0x000001C4
+
+#define VFE_BUS_STATS_RS_WR_PING_ADDR     0x000001C8
+#define VFE_BUS_STATS_RS_WR_PONG_ADDR     0x000001CC
+#define VFE_BUS_STATS_RS_WR_ADDR_CFG      0x000001D0
+#define VFE_BUS_STATS_RS_WR_UB_CFG    0x000001D4
+#define VFE_BUS_STATS_RS_WR_FRAMEDROP_PATTERN      0x000001D8
+#define VFE_BUS_STATS_RS_WR_IRQ_SUBSAMPLE_PATTERN  0x000001DC
+
+#define VFE_BUS_STATS_CS_WR_PING_ADDR     0x000001E0
+#define VFE_BUS_STATS_CS_WR_PONG_ADDR     0x000001E4
+#define VFE_BUS_STATS_CS_WR_ADDR_CFG      0x000001E8
+#define VFE_BUS_STATS_CS_WR_UB_CFG        0x000001EC
+#define VFE_BUS_STATS_CS_WR_FRAMEDROP_PATTERN     0x000001F0
+#define VFE_BUS_STATS_CS_WR_IRQ_SUBSAMPLE_PATTERN 0x000001F4
+
+#define VFE_BUS_STATS_HIST_WR_PING_ADDR   0x000001F8
+#define VFE_BUS_STATS_HIST_WR_PONG_ADDR   0x000001FC
+#define VFE_BUS_STATS_HIST_WR_ADDR_CFG    0x00000200
+#define VFE_BUS_STATS_HIST_WR_UB_CFG      0x00000204
+#define VFE_BUS_STATS_HIST_WR_FRAMEDROP_PATTERN      0x00000208
+#define VFE_BUS_STATS_HIST_WR_IRQ_SUBSAMPLE_PATTERN  0x0000020C
+
+
+#define VFE_BUS_STATS_SKIN_WR_PING_ADDR   0x00000210
+#define VFE_BUS_STATS_SKIN_WR_PONG_ADDR   0x00000214
+#define VFE_BUS_STATS_SKIN_WR_ADDR_CFG    0x00000218
+#define VFE_BUS_STATS_SKIN_WR_UB_CFG      0x0000021C
+#define VFE_BUS_STATS_SKIN_WR_FRAMEDROP_PATTERN       0x00000220
+#define VFE_BUS_STATS_SKIN_WR_IRQ_SUBSAMPLE_PATTERN   0x00000224
 
 #define VFE_0_BUS_BDG_QOS_CFG_0     0x000002C4
 #define VFE_0_BUS_BDG_QOS_CFG_1     0x000002C8
@@ -839,13 +876,14 @@
 #define VFE_STATS_AWB_SGW_CFG           0x000008CC
 #define VFE_DMI_CFG                     0x00000910
 #define VFE_DMI_ADDR                    0x00000914
+#define VFE_DMI_DATA_HI                 0x00000918
 #define VFE_DMI_DATA_LO                 0x0000091C
 #define VFE_BUS_IO_FORMAT_CFG           0x00000054
 #define VFE_RDI0_CFG                    0x000002E8
 #define VFE_RDI1_CFG                    0x000002EC
 #define VFE_RDI2_CFG                    0x000002F0
 
-#define VFE_VIOLATION_STATUS            0x000007B4
+#define VFE_VIOLATION_STATUS            0x00000048
 
 #define VFE40_DMI_DATA_HI               0x00000918
 #define VFE40_DMI_DATA_LO               0x0000091C
@@ -860,6 +898,25 @@
 #define VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS	BIT(7)
 #define VFE40_OUTPUT_MODE_SECONDARY		BIT(8)
 #define VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS	BIT(9)
+#define VFE40_OUTPUT_MODE_TERTIARY1		BIT(10)
+#define VFE40_OUTPUT_MODE_TERTIARY2		BIT(11)
+
+#define VFE40_VBIF_CLKON				0x4
+#define VFE40_VBIF_IN_RD_LIM_CONF0		0xB0
+#define VFE40_VBIF_IN_RD_LIM_CONF1		0xB4
+#define VFE40_VBIF_IN_RD_LIM_CONF2		0xB8
+#define VFE40_VBIF_IN_WR_LIM_CONF0		0xC0
+#define VFE40_VBIF_IN_WR_LIM_CONF1		0xC4
+#define VFE40_VBIF_IN_WR_LIM_CONF2		0xC8
+#define VFE40_VBIF_OUT_RD_LIM_CONF0		0xD0
+#define VFE40_VBIF_OUT_WR_LIM_CONF0		0xD4
+#define VFE40_VBIF_DDR_OUT_MAX_BURST	0xD8
+#define VFE40_VBIF_ARB_CTL				0xF0
+#define VFE40_VBIF_DDR_ARB_CONF0		0xF4
+#define VFE40_VBIF_DDR_ARB_CONF1		0xF8
+#define VFE40_VBIF_ROUND_ROBIN_QOS_ARB	0x124
+#define VFE40_VBIF_OUT_AXI_AOOO_EN		0x178
+#define VFE40_VBIF_OUT_AXI_AOOO			0x17C
 
 struct vfe_stats_control {
 	uint32_t droppedStatsFrameCount;
@@ -870,26 +927,50 @@
 
 struct vfe_share_ctrl_t {
 	void __iomem *vfebase;
+	void __iomem *vfe_vbif_base;
 	uint32_t register_total;
 
 	atomic_t vstate;
+	atomic_t handle_common_irq;
 	uint32_t vfeFrameId;
+	uint32_t rdi0FrameId;
+	uint32_t rdi1FrameId;
+	uint32_t rdi2FrameId;
 	uint32_t stats_comp;
+	spinlock_t  sd_notify_lock;
 	spinlock_t  stop_flag_lock;
 	int8_t stop_ack_pending;
 	enum vfe_output_state liveshot_state;
 	uint32_t vfe_capture_count;
 
-	uint16_t operation_mode;     /* streaming or snapshot */
+	uint32_t operation_mode;     /* streaming or snapshot */
+	uint32_t current_mode;
 	struct vfe40_output_path outpath;
 
-	uint32_t ref_count;
-	spinlock_t  sd_notify_lock;
-	uint32_t vfe_clk_rate;
+	uint16_t port_info;
+	uint8_t stop_immediately;
+	uint8_t sync_abort;
+	uint16_t cmd_type;
+	uint8_t vfe_reset_flag;
 
-	atomic_t irq_cnt;
+	uint8_t axi_ref_cnt;
+	uint16_t comp_output_mode;
+
+	struct completion reset_complete;
+
+	spinlock_t  update_ack_lock;
+	spinlock_t  start_ack_lock;
+
 	struct axi_ctrl_t *axi_ctrl;
 	struct vfe40_ctrl_type *vfe40_ctrl;
+	int8_t start_ack_pending;
+	int8_t update_ack_pending;
+	enum vfe_output_state recording_state;
+
+	atomic_t pix0_update_ack_pending;
+	atomic_t rdi0_update_ack_pending;
+	atomic_t rdi1_update_ack_pending;
+	atomic_t rdi2_update_ack_pending;
 };
 
 struct axi_ctrl_t {
@@ -902,27 +983,25 @@
 	void *syncdata;
 
 	struct resource	*vfemem;
+	struct resource	*vfe_vbif_mem;
 	struct resource *vfeio;
+	struct resource *vfe_vbif_io;
 	struct regulator *fs_vfe;
-	struct clk *vfe_clk[3];
+	struct clk *vfe_clk[7];
 	struct tasklet_struct vfe40_tasklet;
 	struct vfe_share_ctrl_t *share_ctrl;
+	struct device *iommu_ctx;
+	uint32_t bus_perf_client;
+	uint32_t use_irq_router;
 };
 
 struct vfe40_ctrl_type {
-	uint32_t vfeImaskCompositePacked;
-
-	spinlock_t  update_ack_lock;
 	spinlock_t  state_lock;
-	spinlock_t  io_lock;
 	spinlock_t  stats_bufq_lock;
 	uint32_t extlen;
 	void *extdata;
 
-	int8_t start_ack_pending;
-	int8_t reset_ack_pending;
-	int8_t update_ack_pending;
-	enum vfe_output_state recording_state;
+	int8_t vfe_sof_count_enable;
 	int8_t update_linear;
 	int8_t update_rolloff;
 	int8_t update_la;
@@ -934,18 +1013,14 @@
 	uint32_t sync_timer_state;
 	uint32_t sync_timer_number;
 
-	uint32_t output1Pattern;
-	uint32_t output1Period;
-	uint32_t output2Pattern;
-	uint32_t output2Period;
-	uint32_t vfeFrameSkipCount;
-	uint32_t vfeFrameSkipPeriod;
-	struct vfe_stats_control afStatsControl;
+	struct msm_ver_num_info ver_num;
+	struct vfe_stats_control afbfStatsControl;
 	struct vfe_stats_control awbStatsControl;
-	struct vfe_stats_control aecStatsControl;
+	struct vfe_stats_control aecbgStatsControl;
 	struct vfe_stats_control ihistStatsControl;
 	struct vfe_stats_control rsStatsControl;
 	struct vfe_stats_control csStatsControl;
+	struct vfe_stats_control bhistStatsControl;
 
 	/* v4l2 subdev */
 	struct v4l2_subdev subdev;
@@ -956,6 +1031,8 @@
 	uint32_t snapshot_frame_cnt;
 	struct msm_stats_bufq_ctrl stats_ctrl;
 	struct msm_stats_ops stats_ops;
+
+	uint32_t simultaneous_sof_stat;
 };
 
 #define statsAeNum      0
@@ -976,227 +1053,4 @@
 	uint32_t statsBuf[VFE_STATS_BUFFER_COUNT];
 };
 
-void vfe40_subdev_notify(int id, int path, int image_mode,
-	struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl);
-struct vfe40_output_ch *vfe40_get_ch(
-	int path, struct vfe_share_ctrl_t *share_ctrl);
-void vfe40_send_isp_msg(struct v4l2_subdev *sd,
-	uint32_t vfeFrameId, uint32_t isp_msg_id);
-void vfe40_axi_probe(struct axi_ctrl_t *axi_ctrl);
-
-static const uint32_t vfe40_AXI_WM_CFG[] = {
-	0x0000006C,
-	0x00000090,
-	0x000000B4,
-	0x000000D8,
-	0x000000FC,
-	0x00000120,
-	0x00000144,
-};
-
-static struct vfe40_cmd_type vfe40_cmd[] = {
-/*0*/
-	{VFE_CMD_DUMMY_0},
-	{VFE_CMD_SET_CLK},
-	{VFE_CMD_RESET},
-	{VFE_CMD_START},
-	{VFE_CMD_TEST_GEN_START},
-/*5*/
-	{VFE_CMD_OPERATION_CFG, V40_OPERATION_CFG_LEN},
-	{VFE_CMD_AXI_OUT_CFG, V40_AXI_OUT_LEN, V40_AXI_OUT_OFF, 0xFF},
-	{VFE_CMD_CAMIF_CFG, V40_CAMIF_LEN, V40_CAMIF_OFF, 0xFF},
-	{VFE_CMD_AXI_INPUT_CFG},
-	{VFE_CMD_BLACK_LEVEL_CFG},
-/*10*/
-	{VFE_CMD_MESH_ROLL_OFF_CFG},
-	{VFE_CMD_DEMUX_CFG, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
-	{VFE_CMD_FOV_CFG},
-	{VFE_CMD_MAIN_SCALER_CFG},
-	{VFE_CMD_WB_CFG, V40_WB_LEN, V40_WB_OFF, 0xFF},
-/*15*/
-	{VFE_CMD_COLOR_COR_CFG, V40_COLOR_COR_LEN, V40_COLOR_COR_OFF, 0xFF},
-	{VFE_CMD_RGB_G_CFG, V40_RGB_G_LEN, V40_RGB_G_OFF, 0xFF},
-	{VFE_CMD_LA_CFG, V40_LA_LEN, V40_LA_OFF, 0xFF },
-	{VFE_CMD_CHROMA_EN_CFG, V40_CHROMA_EN_LEN, V40_CHROMA_EN_OFF, 0xFF},
-	{VFE_CMD_CHROMA_SUP_CFG, V40_CHROMA_SUP_LEN, V40_CHROMA_SUP_OFF, 0xFF},
-/*20*/
-	{VFE_CMD_MCE_CFG, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
-	{VFE_CMD_SK_ENHAN_CFG, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
-	{VFE_CMD_ASF_CFG, V40_ASF_LEN, V40_ASF_OFF, 0xFF},
-	{VFE_CMD_S2Y_CFG},
-	{VFE_CMD_S2CbCr_CFG},
-/*25*/
-	{VFE_CMD_CHROMA_SUBS_CFG},
-	{VFE_CMD_OUT_CLAMP_CFG, V40_OUT_CLAMP_LEN, V40_OUT_CLAMP_OFF, 0xFF},
-	{VFE_CMD_FRAME_SKIP_CFG},
-	{VFE_CMD_DUMMY_1},
-	{VFE_CMD_DUMMY_2},
-/*30*/
-	{VFE_CMD_DUMMY_3},
-	{VFE_CMD_UPDATE},
-	{VFE_CMD_BL_LVL_UPDATE},
-	{VFE_CMD_DEMUX_UPDATE, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
-	{VFE_CMD_FOV_UPDATE},
-/*35*/
-	{VFE_CMD_MAIN_SCALER_UPDATE},
-	{VFE_CMD_WB_UPDATE, V40_WB_LEN, V40_WB_OFF, 0xFF},
-	{VFE_CMD_COLOR_COR_UPDATE, V40_COLOR_COR_LEN, V40_COLOR_COR_OFF, 0xFF},
-	{VFE_CMD_RGB_G_UPDATE, V40_RGB_G_LEN, V40_CHROMA_EN_OFF, 0xFF},
-	{VFE_CMD_LA_UPDATE, V40_LA_LEN, V40_LA_OFF, 0xFF },
-/*40*/
-	{VFE_CMD_CHROMA_EN_UPDATE, V40_CHROMA_EN_LEN, V40_CHROMA_EN_OFF, 0xFF},
-	{VFE_CMD_CHROMA_SUP_UPDATE, V40_CHROMA_SUP_LEN,
-		V40_CHROMA_SUP_OFF, 0xFF},
-	{VFE_CMD_MCE_UPDATE, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
-	{VFE_CMD_SK_ENHAN_UPDATE, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
-	{VFE_CMD_S2CbCr_UPDATE},
-/*45*/
-	{VFE_CMD_S2Y_UPDATE},
-	{VFE_CMD_ASF_UPDATE, V40_ASF_UPDATE_LEN, V40_ASF_OFF, 0xFF},
-	{VFE_CMD_FRAME_SKIP_UPDATE},
-	{VFE_CMD_CAMIF_FRAME_UPDATE},
-	{VFE_CMD_STATS_AF_UPDATE},
-/*50*/
-	{VFE_CMD_STATS_AE_UPDATE},
-	{VFE_CMD_STATS_AWB_UPDATE, V40_STATS_AWB_LEN, V40_STATS_AWB_OFF},
-	{VFE_CMD_STATS_RS_UPDATE, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
-	{VFE_CMD_STATS_CS_UPDATE, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
-	{VFE_CMD_STATS_SKIN_UPDATE},
-/*55*/
-	{VFE_CMD_STATS_IHIST_UPDATE, V40_STATS_IHIST_LEN, V40_STATS_IHIST_OFF},
-	{VFE_CMD_DUMMY_4},
-	{VFE_CMD_EPOCH1_ACK},
-	{VFE_CMD_EPOCH2_ACK},
-	{VFE_CMD_START_RECORDING},
-/*60*/
-	{VFE_CMD_STOP_RECORDING},
-	{VFE_CMD_DUMMY_5},
-	{VFE_CMD_DUMMY_6},
-	{VFE_CMD_CAPTURE, V40_CAPTURE_LEN, 0xFF},
-	{VFE_CMD_DUMMY_7},
-/*65*/
-	{VFE_CMD_STOP},
-	{VFE_CMD_GET_HW_VERSION, V40_GET_HW_VERSION_LEN,
-		V40_GET_HW_VERSION_OFF},
-	{VFE_CMD_GET_FRAME_SKIP_COUNTS},
-	{VFE_CMD_OUTPUT1_BUFFER_ENQ},
-	{VFE_CMD_OUTPUT2_BUFFER_ENQ},
-/*70*/
-	{VFE_CMD_OUTPUT3_BUFFER_ENQ},
-	{VFE_CMD_JPEG_OUT_BUF_ENQ},
-	{VFE_CMD_RAW_OUT_BUF_ENQ},
-	{VFE_CMD_RAW_IN_BUF_ENQ},
-	{VFE_CMD_STATS_AF_ENQ},
-/*75*/
-	{VFE_CMD_STATS_AE_ENQ},
-	{VFE_CMD_STATS_AWB_ENQ},
-	{VFE_CMD_STATS_RS_ENQ},
-	{VFE_CMD_STATS_CS_ENQ},
-	{VFE_CMD_STATS_SKIN_ENQ},
-/*80*/
-	{VFE_CMD_STATS_IHIST_ENQ},
-	{VFE_CMD_DUMMY_8},
-	{VFE_CMD_JPEG_ENC_CFG},
-	{VFE_CMD_DUMMY_9},
-	{VFE_CMD_STATS_AF_START},
-/*85*/
-	{VFE_CMD_STATS_AF_STOP},
-	{VFE_CMD_STATS_AE_START},
-	{VFE_CMD_STATS_AE_STOP},
-	{VFE_CMD_STATS_AWB_START, V40_STATS_AWB_LEN, V40_STATS_AWB_OFF},
-	{VFE_CMD_STATS_AWB_STOP},
-/*90*/
-	{VFE_CMD_STATS_RS_START, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
-	{VFE_CMD_STATS_RS_STOP},
-	{VFE_CMD_STATS_CS_START, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
-	{VFE_CMD_STATS_CS_STOP},
-	{VFE_CMD_STATS_SKIN_START},
-/*95*/
-	{VFE_CMD_STATS_SKIN_STOP},
-	{VFE_CMD_STATS_IHIST_START, V40_STATS_IHIST_LEN, V40_STATS_IHIST_OFF},
-	{VFE_CMD_STATS_IHIST_STOP},
-	{VFE_CMD_DUMMY_10},
-	{VFE_CMD_SYNC_TIMER_SETTING, V40_SYNC_TIMER_LEN, V40_SYNC_TIMER_OFF},
-/*100*/
-	{VFE_CMD_ASYNC_TIMER_SETTING, V40_ASYNC_TIMER_LEN, V40_ASYNC_TIMER_OFF},
-	{VFE_CMD_LIVESHOT},
-	{VFE_CMD_LA_SETUP},
-	{VFE_CMD_LINEARIZATION_CFG, V40_LINEARIZATION_LEN1,
-		V40_LINEARIZATION_OFF1},
-	{VFE_CMD_DEMOSAICV3},
-/*105*/
-	{VFE_CMD_DEMOSAICV3_ABCC_CFG},
-	{VFE_CMD_DEMOSAICV3_DBCC_CFG, V40_DEMOSAICV3_DBCC_LEN,
-		V40_DEMOSAICV3_DBCC_OFF},
-	{VFE_CMD_DEMOSAICV3_DBPC_CFG},
-	{VFE_CMD_DEMOSAICV3_ABF_CFG, V40_DEMOSAICV3_ABF_LEN,
-		V40_DEMOSAICV3_ABF_OFF},
-	{VFE_CMD_DEMOSAICV3_ABCC_UPDATE},
-/*110*/
-	{VFE_CMD_DEMOSAICV3_DBCC_UPDATE, V40_DEMOSAICV3_DBCC_LEN,
-		V40_DEMOSAICV3_DBCC_OFF},
-	{VFE_CMD_DEMOSAICV3_DBPC_UPDATE},
-	{VFE_CMD_XBAR_CFG},
-	{VFE_CMD_MODULE_CFG, V40_MODULE_CFG_LEN, V40_MODULE_CFG_OFF},
-	{VFE_CMD_ZSL},
-/*115*/
-	{VFE_CMD_LINEARIZATION_UPDATE, V40_LINEARIZATION_LEN1,
-		V40_LINEARIZATION_OFF1},
-	{VFE_CMD_DEMOSAICV3_ABF_UPDATE, V40_DEMOSAICV3_ABF_LEN,
-		V40_DEMOSAICV3_ABF_OFF},
-	{VFE_CMD_CLF_CFG, V40_CLF_CFG_LEN, V40_CLF_CFG_OFF},
-	{VFE_CMD_CLF_LUMA_UPDATE, V40_CLF_LUMA_UPDATE_LEN,
-		V40_CLF_LUMA_UPDATE_OFF},
-	{VFE_CMD_CLF_CHROMA_UPDATE, V40_CLF_CHROMA_UPDATE_LEN,
-		V40_CLF_CHROMA_UPDATE_OFF},
-/*120*/
-	{VFE_CMD_PCA_ROLL_OFF_CFG},
-	{VFE_CMD_PCA_ROLL_OFF_UPDATE},
-	{VFE_CMD_GET_REG_DUMP},
-	{VFE_CMD_GET_LINEARIZATON_TABLE},
-	{VFE_CMD_GET_MESH_ROLLOFF_TABLE},
-/*125*/
-	{VFE_CMD_GET_PCA_ROLLOFF_TABLE},
-	{VFE_CMD_GET_RGB_G_TABLE},
-	{VFE_CMD_GET_LA_TABLE},
-	{VFE_CMD_DEMOSAICV3_UPDATE},
-	{VFE_CMD_ACTIVE_REGION_CFG},
-/*130*/
-	{VFE_CMD_COLOR_PROCESSING_CONFIG},
-	{VFE_CMD_STATS_WB_AEC_CONFIG},
-	{VFE_CMD_STATS_WB_AEC_UPDATE},
-	{VFE_CMD_Y_GAMMA_CONFIG},
-	{VFE_CMD_SCALE_OUTPUT1_CONFIG},
-/*135*/
-	{VFE_CMD_SCALE_OUTPUT2_CONFIG},
-	{VFE_CMD_CAPTURE_RAW},
-	{VFE_CMD_STOP_LIVESHOT},
-	{VFE_CMD_RECONFIG_VFE},
-	{VFE_CMD_STATS_REQBUF},
-/*140*/
-	{VFE_CMD_STATS_ENQUEUEBUF},
-	{VFE_CMD_STATS_FLUSH_BUFQ},
-	{VFE_CMD_FOV_ENC_CFG, V40_FOV_ENC_LEN, V40_FOV_ENC_OFF, 0xFF},
-	{VFE_CMD_FOV_VIEW_CFG, V40_FOV_VIEW_LEN, V40_FOV_VIEW_OFF, 0xFF},
-	{VFE_CMD_FOV_ENC_UPDATE, V40_FOV_ENC_LEN, V40_FOV_ENC_OFF, 0xFF},
-/*145*/
-	{VFE_CMD_FOV_VIEW_UPDATE, V40_FOV_VIEW_LEN, V40_FOV_VIEW_OFF, 0xFF},
-	{VFE_CMD_SCALER_ENC_CFG, V40_SCALER_ENC_LEN, V40_SCALER_ENC_OFF, 0xFF},
-	{VFE_CMD_SCALER_VIEW_CFG, V40_SCALER_VIEW_LEN,
-		V40_SCALER_VIEW_OFF, 0xFF},
-	{VFE_CMD_SCALER_ENC_UPDATE, V40_SCALER_ENC_LEN,
-		V40_SCALER_ENC_OFF, 0xFF},
-	{VFE_CMD_SCALER_VIEW_UPDATE, V40_SCALER_VIEW_LEN,
-		V40_SCALER_VIEW_OFF, 0xFF},
-/*150*/
-	{VFE_CMD_COLORXFORM_ENC_CFG, V40_COLORXFORM_ENC_CFG_LEN,
-		V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
-	{VFE_CMD_COLORXFORM_VIEW_CFG, V40_COLORXFORM_VIEW_CFG_LEN,
-		V40_COLORXFORM_VIEW_CFG_OFF},
-	{VFE_CMD_COLORXFORM_ENC_UPDATE, V40_COLORXFORM_ENC_CFG_LEN,
-		V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
-	{VFE_CMD_COLORXFORM_VIEW_UPDATE, V40_COLORXFORM_VIEW_CFG_LEN,
-		V40_COLORXFORM_VIEW_CFG_OFF, 0xFF},
-};
-
 #endif /* __MSM_VFE40_H__ */
diff --git a/drivers/media/video/msm/vfe/msm_vfe40_axi.c b/drivers/media/video/msm/vfe/msm_vfe40_axi.c
index 35d5207..41d1cdd 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40_axi.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40_axi.c
@@ -193,6 +193,16 @@
 	msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
 		vfe40_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
 		vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length - V40_AXI_CH_INF_LEN);
+	msm_camera_io_w(*ch_info++,
+		axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+	if (msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+		V40_GET_HW_VERSION_OFF) ==
+		VFE40_HW_NUMBER) {
+		msm_camera_io_w(*ch_info++,
+			axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
+		msm_camera_io_w(*ch_info++,
+			axi_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG);
+	}
 	return 0;
 }
 
@@ -331,6 +341,8 @@
 	case CMD_AXI_STOP:
 		axi_stop(axi_ctrl);
 		break;
+	case CMD_AXI_RESET:
+		break;
 	default:
 		pr_err("%s Unsupported AXI configuration %x ", __func__,
 			cfgcmd.cmd_type);
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 30bec78..15c38af 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -395,7 +395,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe2x_ctrl->stats_ops.enqueue_buf(
 				vfe2x_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 			if (rc < 0) {
 				pr_err("%s: dq stats buf (type = %d) err = %d",
 					 __func__, stats_type, rc);
@@ -414,7 +414,7 @@
 		rc = vfe2x_ctrl->stats_ops.buf_unprepare(
 			vfe2x_ctrl->stats_ops.stats_ctrl,
 			req_buf->stats_type, i,
-			vfe2x_ctrl->stats_ops.client);
+			vfe2x_ctrl->stats_ops.client, -1);
 		if (rc < 0) {
 			pr_err("%s: unreg stats buf (type = %d) err = %d",
 				__func__, req_buf->stats_type, rc);
@@ -473,7 +473,7 @@
 		stats_buf->state == MSM_STATS_BUFFER_STATE_PREPARED) {
 		rc = vfe2x_ctrl->stats_ops.enqueue_buf(
 				&vfe2x_ctrl->stats_ctrl,
-				info, vfe2x_ctrl->stats_ops.client);
+				info, vfe2x_ctrl->stats_ops.client, -1);
 		if (rc < 0) {
 			pr_err("%s: enqueue_buf (type = %d), index : %d, err = %d",
 				 __func__, info->type, info->buf_idx, rc);
@@ -555,7 +555,7 @@
 		rc = vfe2x_ctrl->stats_ops.enqueue_buf(
 				&vfe2x_ctrl->stats_ctrl,
 				(struct msm_stats_buf_info *)cmd->value,
-				vfe2x_ctrl->stats_ops.client);
+				vfe2x_ctrl->stats_ops.client, -1);
 	}
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ: {
@@ -2352,7 +2352,7 @@
 	return 0;
 }
 
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
 {
 	return;
 }
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
index 723463b..ff621c9 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
@@ -119,7 +119,6 @@
 		} else {
 			/* good case. need to de-reqbuf */
 			kfree(stats_ctrl->bufq[idx]->bufs);
-			stats_ctrl->bufq[idx]->bufs = NULL;
 			kfree(stats_ctrl->bufq[idx]);
 			stats_ctrl->bufq[idx] = NULL;
 			goto end;
@@ -183,7 +182,8 @@
 #endif
 
 static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl,
-	struct msm_stats_buf_info *info, struct ion_client *client)
+	struct msm_stats_buf_info *info, struct ion_client *client,
+	int domain_num)
 {
 	unsigned long paddr;
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -220,7 +220,7 @@
 		goto out1;
 	}
 	if (ion_map_iommu(client, stats_buf->handle,
-			CAMERA_DOMAIN, GEN_POOL, SZ_4K,
+			domain_num, 0, SZ_4K,
 			0, &paddr, &len, UNCACHED, 0) < 0) {
 		rc = -EINVAL;
 		pr_err("%s: cannot map address", __func__);
@@ -258,7 +258,7 @@
 	return 0;
 out3:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_unmap_iommu(client, stats_buf->handle, CAMERA_DOMAIN, GEN_POOL);
+	ion_unmap_iommu(client, stats_buf->handle, domain_num, 0);
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
@@ -271,7 +271,7 @@
 }
 static int msm_stats_buf_unprepare(struct msm_stats_bufq_ctrl *stats_ctrl,
 	enum msm_stats_enum_type stats_type, int buf_idx,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	int rc = 0;
 	struct msm_stats_bufq *bufq = NULL;
@@ -293,7 +293,7 @@
 	}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_unmap_iommu(client, stats_buf->handle,
-					CAMERA_DOMAIN, GEN_POOL);
+					domain_num, 0);
 	ion_free(client, stats_buf->handle);
 #else
 	put_pmem_file(stats_buf->file);
@@ -316,7 +316,6 @@
 	struct msm_stats_bufq *bufq = NULL;
 	struct msm_stats_meta_buf *stats_buf = NULL;
 
-	D("%s: type : %d\n", __func__, stats_type);
 	bufq = stats_ctrl->bufq[stats_type];
 
 	for (i = 0; i < bufq->num_bufs; i++) {
@@ -473,12 +472,13 @@
 	return rc;
 }
 static int msm_stats_enqueue_buf(struct msm_stats_bufq_ctrl *stats_ctrl,
-	struct msm_stats_buf_info *info, struct ion_client *client)
+	struct msm_stats_buf_info *info, struct ion_client *client,
+	int domain_num)
 {
 	int rc = 0;
 	D("%s: stats type : %d, idx : %d\n", __func__,
 		info->type, info->buf_idx);
-	rc = msm_stats_buf_prepare(stats_ctrl, info, client);
+	rc = msm_stats_buf_prepare(stats_ctrl, info, client, domain_num);
 	if (rc < 0) {
 		pr_err("%s: buf_prepare failed, rc = %d", __func__, rc);
 		return -EINVAL;
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
index 18fd425..bf3e70e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
@@ -55,8 +55,8 @@
 	struct msm_stats_bufq_ctrl *stats_ctrl;
 	struct ion_client *client;
 	int (*enqueue_buf) (struct msm_stats_bufq_ctrl *stats_ctrl,
-						struct msm_stats_buf_info *info,
-						struct ion_client *client);
+				struct msm_stats_buf_info *info,
+				struct ion_client *client, int domain_num);
 	int (*qbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
 				 enum msm_stats_enum_type stats_type,
 				 int buf_idx);
@@ -69,10 +69,10 @@
 	int (*buf_unprepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
 		enum msm_stats_enum_type stats_type,
 		int buf_idx,
-		struct ion_client *client);
+		struct ion_client *client, int domain_num);
 	int (*buf_prepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
-						struct msm_stats_buf_info *info,
-						struct ion_client *client);
+				struct msm_stats_buf_info *info,
+				struct ion_client *client, int domain_num);
 	int (*reqbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
 				   struct msm_stats_reqbuf *reqbuf,
 				   struct ion_client *client);
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index d1d4eaa..a94dc66 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -16,6 +16,7 @@
 #ifdef MSM_CAMERA_BIONIC
 #include <sys/types.h>
 #endif
+#include <linux/videodev2.h>
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #ifdef __KERNEL__
@@ -27,12 +28,14 @@
 #include <linux/time.h>
 #endif
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #define BIT(nr)   (1UL << (nr))
 
 #define MSM_CAM_IOCTL_MAGIC 'm'
 
+#define MAX_SERVER_PAYLOAD_LENGTH 8192
+
 #define MSM_CAM_IOCTL_GET_SENSOR_INFO \
 	_IOR(MSM_CAM_IOCTL_MAGIC, 1, struct msm_camsensor_info *)
 
@@ -151,7 +154,7 @@
 	_IOW(MSM_CAM_IOCTL_MAGIC, 39, struct msm_camera_st_frame *)
 
 #define MSM_CAM_IOCTL_V4L2_EVT_NOTIFY \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 40, struct v4l2_event *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 40, struct v4l2_event_and_payload)
 
 #define MSM_CAM_IOCTL_SET_MEM_MAP_INFO \
 	_IOR(MSM_CAM_IOCTL_MAGIC, 41, struct msm_mem_map_info *)
@@ -216,6 +219,47 @@
 #define MSM_CAM_IOCTL_STATS_UNREG_BUF \
 	_IOR(MSM_CAM_IOCTL_MAGIC, 61, struct msm_stats_flush_bufq *)
 
+#define MSM_CAM_IOCTL_CSIC_IO_CFG \
+	_IOWR(MSM_CAM_IOCTL_MAGIC, 62, struct csic_cfg_data *)
+
+#define MSM_CAM_IOCTL_CSID_IO_CFG \
+	_IOWR(MSM_CAM_IOCTL_MAGIC, 63, struct csid_cfg_data *)
+
+#define MSM_CAM_IOCTL_CSIPHY_IO_CFG \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 64, struct csiphy_cfg_data *)
+
+#define MSM_CAM_IOCTL_OEM \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 65, struct sensor_cfg_data *)
+
+#define MSM_CAM_IOCTL_AXI_INIT \
+	_IOWR(MSM_CAM_IOCTL_MAGIC, 66, uint8_t *)
+
+#define MSM_CAM_IOCTL_AXI_RELEASE \
+	_IO(MSM_CAM_IOCTL_MAGIC, 67)
+
+#define MSM_CAM_IOCTL_V4L2_EVT_NATIVE_CMD \
+	_IOWR(MSM_CAM_IOCTL_MAGIC, 68, struct msm_camera_v4l2_ioctl_t)
+
+#define MSM_CAM_IOCTL_V4L2_EVT_NATIVE_FRONT_CMD \
+	_IOWR(MSM_CAM_IOCTL_MAGIC, 69, struct msm_camera_v4l2_ioctl_t)
+
+#define MSM_CAM_IOCTL_INTF_MCTL_MAPPING_CFG \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 70, struct intf_mctl_mapping_cfg *)
+
+struct ioctl_native_cmd {
+	unsigned short mode;
+	unsigned short address;
+	unsigned short value_1;
+	unsigned short value_2;
+	unsigned short value_3;
+};
+
+struct v4l2_event_and_payload {
+	struct v4l2_event evt;
+	uint32_t payload_length;
+	uint32_t transaction_id;
+	void *payload;
+};
 
 struct msm_stats_reqbuf {
 	int num_buf;		/* how many buffers requested */
@@ -350,6 +394,27 @@
 	uint32_t inst_handle;
 };
 
+struct msm_pp_crop {
+	uint32_t  src_x;
+	uint32_t  src_y;
+	uint32_t  src_w;
+	uint32_t  src_h;
+	uint32_t  dst_x;
+	uint32_t  dst_y;
+	uint32_t  dst_w;
+	uint32_t  dst_h;
+	uint8_t update_flag;
+};
+
+struct msm_mctl_pp_frame_cmd {
+	uint32_t cookie;
+	uint8_t  vpe_output_action;
+	struct msm_pp_frame src_frame;
+	struct msm_pp_frame dest_frame;
+	struct msm_pp_crop crop;
+	int path;
+};
+
 struct msm_cam_evt_divert_frame {
 	unsigned short image_mode;
 	unsigned short op_mode;
@@ -438,11 +503,11 @@
 #define CMD_STATS_AF_ENABLE		13
 #define CMD_STATS_AEC_ENABLE		14
 #define CMD_STATS_AWB_ENABLE		15
-#define CMD_STATS_ENABLE  		16
+#define CMD_STATS_ENABLE		16
 
 #define CMD_STATS_AXI_CFG		17
 #define CMD_STATS_AEC_AXI_CFG		18
-#define CMD_STATS_AF_AXI_CFG 		19
+#define CMD_STATS_AF_AXI_CFG		19
 #define CMD_STATS_AWB_AXI_CFG		20
 #define CMD_STATS_RS_AXI_CFG		21
 #define CMD_STATS_CS_AXI_CFG		22
@@ -486,8 +551,8 @@
 #define CMD_STATS_BG_BUF_RELEASE 56
 #define CMD_STATS_BF_BUF_RELEASE 57
 #define CMD_STATS_BHIST_BUF_RELEASE 58
-#define CMD_VFE_SOF_COUNT_UPDATE 59
-#define CMD_VFE_COUNT_SOF_ENABLE 60
+#define CMD_VFE_PIX_SOF_COUNT_UPDATE 59
+#define CMD_VFE_COUNT_PIX_SOF_ENABLE 60
 
 #define CMD_AXI_CFG_PRIM               BIT(8)
 #define CMD_AXI_CFG_PRIM_ALL_CHNLS     BIT(9)
@@ -495,10 +560,13 @@
 #define CMD_AXI_CFG_SEC_ALL_CHNLS      BIT(11)
 #define CMD_AXI_CFG_TERT1              BIT(12)
 #define CMD_AXI_CFG_TERT2              BIT(13)
+#define CMD_AXI_CFG_TERT3              BIT(14)
 
 #define CMD_AXI_START  0xE1
 #define CMD_AXI_STOP   0xE2
 #define CMD_AXI_RESET  0xE3
+#define CMD_AXI_ABORT  0xE4
+
 
 
 #define AXI_CMD_PREVIEW      BIT(0)
@@ -583,6 +651,7 @@
 	MSM_STATS_TYPE_BF,  /* Bayer Focus */
 	MSM_STATS_TYPE_BHIST,   /* Bayer Hist */
 	MSM_STATS_TYPE_AE_AW,   /* legacy stats for vfe 2.x*/
+	MSM_STATS_TYPE_COMP, /* Composite stats */
 	MSM_STATS_TYPE_MAX  /* MAX */
 };
 
@@ -645,8 +714,7 @@
 #define OUTPUT_SEC_ALL_CHNLS     BIT(11)
 #define OUTPUT_TERT1             BIT(12)
 #define OUTPUT_TERT2             BIT(13)
-
-
+#define OUTPUT_TERT3             BIT(14)
 
 #define MSM_FRAME_PREV_1	0
 #define MSM_FRAME_PREV_2	1
@@ -662,8 +730,12 @@
 #define OUTPUT_TYPE_ST_D BIT(7)
 #define OUTPUT_TYPE_R    BIT(8)
 #define OUTPUT_TYPE_R1   BIT(9)
-
-
+#define OUTPUT_TYPE_SAEC   BIT(10)
+#define OUTPUT_TYPE_SAFC   BIT(11)
+#define OUTPUT_TYPE_SAWB   BIT(12)
+#define OUTPUT_TYPE_IHST   BIT(13)
+#define OUTPUT_TYPE_CSTA   BIT(14)
+#define OUTPUT_TYPE_R2   BIT(15)
 
 struct fd_roi_info {
 	void *info;
@@ -778,27 +850,39 @@
 /* extendedmode for the thumb nail image in VIDIOC_S_PARM */
 #define MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+4)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
+/* ISP_PIX_OUTPUT1: no pp, directly send output1 buf to user */
+#define MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT1 \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+5)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
+/* ISP_PIX_OUTPUT2: no pp, directly send output2 buf to user */
+#define MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT2 \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+6)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
+/* raw image type */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+7)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
+/* RDI dump */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+8)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AEC \
+/* RDI dump 1 */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+9)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AWB \
+/* RDI dump 2 */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+10)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AF \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AEC \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+11)
-#define MSM_V4L2_EXT_CAPTURE_MODE_IHIST \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AWB \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+12)
-#define MSM_V4L2_EXT_CAPTURE_MODE_CS \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AF \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+13)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RS \
+#define MSM_V4L2_EXT_CAPTURE_MODE_IHIST \
 	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+14)
-#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+15)
+#define MSM_V4L2_EXT_CAPTURE_MODE_CS \
+	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+15)
+#define MSM_V4L2_EXT_CAPTURE_MODE_RS \
+	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+16)
+#define MSM_V4L2_EXT_CAPTURE_MODE_CSTA \
+	(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+17)
+#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+18)
 
 #define MSM_V4L2_PID_MOTION_ISO              V4L2_CID_PRIVATE_BASE
 #define MSM_V4L2_PID_EFFECT                 (V4L2_CID_PRIVATE_BASE+1)
@@ -851,7 +935,8 @@
 #define MSM_V4L2_CLOSE			11
 #define MSM_V4L2_SET_CTRL_CMD	12
 #define MSM_V4L2_EVT_SUB_MASK	13
-#define MSM_V4L2_MAX			14
+#define MSM_V4L2_PRIVATE_CMD    14
+#define MSM_V4L2_MAX			15
 #define V4L2_CAMERA_EXIT		43
 
 struct crop_info {
@@ -918,7 +1003,15 @@
 #define CFG_START_STREAM              44
 #define CFG_STOP_STREAM               45
 #define CFG_GET_CSI_PARAMS            46
-#define CFG_MAX			47
+#define CFG_POWER_UP                  47
+#define CFG_POWER_DOWN                48
+#define CFG_WRITE_I2C_ARRAY           49
+#define CFG_READ_I2C_ARRAY            50
+#define CFG_PCLK_CHANGE               51
+#define CFG_CONFIG_VREG_ARRAY         52
+#define CFG_CONFIG_CLK_ARRAY          53
+#define CFG_GPIO_OP                   54
+#define CFG_MAX                       55
 
 
 #define MOVE_NEAR	0
@@ -1162,7 +1255,7 @@
 	uint16_t gb_gain;
 	uint16_t gain_adjust;
 };
-struct sensor_3d_cali_data_t{
+struct sensor_3d_cali_data_t {
 	unsigned char left_p_matrix[3][4][8];
 	unsigned char right_p_matrix[3][4][8];
 	unsigned char square_len[8];
@@ -1192,17 +1285,6 @@
 	uint8_t pict_res;
 };
 
-#define ROLLOFF_CALDATA_SIZE    (17 * 13)
-typedef struct
-{
-    unsigned short          mesh_rolloff_table_size;     // TableSize
-    uint8_t                 r_gain[ROLLOFF_CALDATA_SIZE];   // RGain
-    uint8_t                 gr_gain[ROLLOFF_CALDATA_SIZE];  // GRGain
-    uint8_t                 gb_gain[ROLLOFF_CALDATA_SIZE];  // GBGain
-    uint8_t                 b_gain[ROLLOFF_CALDATA_SIZE];   // BGain
-    uint8_t                 red_ref[17];
-} rolloff_caldata_array_type;
-
 struct sensor_calib_data {
 	/* Color Related Measurements */
 	uint16_t r_over_g;
@@ -1215,8 +1297,6 @@
 	uint16_t stroke_amt;
 	uint16_t af_pos_1m;
 	uint16_t af_pos_inf;
-	/* Lens Shading Calibration Data */
-	rolloff_caldata_array_type rolloff;
 };
 
 enum msm_sensor_resolution_t {
@@ -1246,6 +1326,33 @@
 	uint16_t num_info;
 };
 
+struct msm_sensor_exp_gain_info_t {
+	uint16_t coarse_int_time_addr;
+	uint16_t global_gain_addr;
+	uint16_t vert_offset;
+};
+
+struct msm_sensor_output_reg_addr_t {
+	uint16_t x_output;
+	uint16_t y_output;
+	uint16_t line_length_pclk;
+	uint16_t frame_length_lines;
+};
+
+struct sensor_driver_params_type {
+	struct msm_camera_i2c_reg_setting *init_settings;
+	uint16_t init_settings_size;
+	struct msm_camera_i2c_reg_setting *mode_settings;
+	uint16_t mode_settings_size;
+	struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
+	struct msm_camera_i2c_reg_setting *start_settings;
+	struct msm_camera_i2c_reg_setting *stop_settings;
+	struct msm_camera_i2c_reg_setting *groupon_settings;
+	struct msm_camera_i2c_reg_setting *groupoff_settings;
+	struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
+	struct msm_sensor_output_info_t *output_info;
+};
+
 struct mirror_flip {
 	int32_t x_mirror;
 	int32_t y_flip;
@@ -1268,11 +1375,82 @@
 };
 
 struct csi_lane_params_t {
-	uint8_t csi_lane_assign;
+	uint16_t csi_lane_assign;
 	uint8_t csi_lane_mask;
 	uint8_t csi_if;
-	uint8_t csid_core;
-	uint32_t csid_version;
+	uint8_t csid_core[2];
+	uint8_t csi_phy_sel;
+};
+
+struct msm_camera_csid_lut_params {
+	uint8_t num_cid;
+	struct msm_camera_csid_vc_cfg *vc_cfg;
+};
+
+struct msm_camera_csid_params {
+	uint8_t lane_cnt;
+	uint16_t lane_assign;
+	uint8_t phy_sel;
+	struct msm_camera_csid_lut_params lut_params;
+};
+
+struct msm_camera_csiphy_params {
+	uint8_t lane_cnt;
+	uint8_t settle_cnt;
+	uint16_t lane_mask;
+	uint8_t combo_mode;
+};
+
+struct msm_camera_csi2_params {
+	struct msm_camera_csid_params csid_params;
+	struct msm_camera_csiphy_params csiphy_params;
+};
+
+enum msm_camera_csi_data_format {
+	CSI_8BIT,
+	CSI_10BIT,
+	CSI_12BIT,
+};
+
+struct msm_camera_csi_params {
+	enum msm_camera_csi_data_format data_format;
+	uint8_t lane_cnt;
+	uint8_t lane_assign;
+	uint8_t settle_cnt;
+	uint8_t dpcm_scheme;
+};
+
+enum csic_cfg_type_t {
+	CSIC_INIT,
+	CSIC_CFG,
+};
+
+struct csic_cfg_data {
+	enum csic_cfg_type_t cfgtype;
+	struct msm_camera_csi_params *csic_params;
+};
+
+enum csid_cfg_type_t {
+	CSID_INIT,
+	CSID_CFG,
+};
+
+struct csid_cfg_data {
+	enum csid_cfg_type_t cfgtype;
+	union {
+		uint32_t csid_version;
+		struct msm_camera_csid_params *csid_params;
+	} cfg;
+};
+
+enum csiphy_cfg_type_t {
+	CSIPHY_INIT,
+	CSIPHY_CFG,
+};
+
+struct csiphy_cfg_data {
+	enum csiphy_cfg_type_t cfgtype;
+	struct msm_camera_csiphy_params *csiphy_params;
 };
 
 #define CSI_EMBED_DATA 0x12
@@ -1281,6 +1459,9 @@
 #define CSI_RAW8    0x2A
 #define CSI_RAW10   0x2B
 #define CSI_RAW12   0x2C
+#define CSI_YUV420_Y_8 0x30
+#define CSI_YUV420_UV_8 0x31
+#define CSI_YUV420_JM_8 0x32
 
 #define CSI_DECODE_6BIT 0
 #define CSI_DECODE_8BIT 1
@@ -1372,6 +1553,81 @@
 	} cfg;
 };
 
+enum msm_camera_i2c_reg_addr_type {
+	MSM_CAMERA_I2C_BYTE_ADDR = 1,
+	MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+struct msm_camera_i2c_reg_array {
+	uint16_t reg_addr;
+	uint16_t reg_data;
+};
+
+enum msm_camera_i2c_data_type {
+	MSM_CAMERA_I2C_BYTE_DATA = 1,
+	MSM_CAMERA_I2C_WORD_DATA,
+	MSM_CAMERA_I2C_SET_BYTE_MASK,
+	MSM_CAMERA_I2C_UNSET_BYTE_MASK,
+	MSM_CAMERA_I2C_SET_WORD_MASK,
+	MSM_CAMERA_I2C_UNSET_WORD_MASK,
+	MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
+};
+
+struct msm_camera_i2c_reg_setting {
+	struct msm_camera_i2c_reg_array *reg_setting;
+	uint16_t size;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+	enum msm_camera_i2c_data_type data_type;
+	uint16_t delay;
+};
+
+enum oem_setting_type {
+	I2C_READ = 1,
+	I2C_WRITE,
+	GPIO_OP,
+	EEPROM_READ,
+	VREG_SET,
+	CLK_SET,
+};
+
+struct sensor_oem_setting {
+	enum oem_setting_type type;
+	void *data;
+};
+
+enum camera_vreg_type {
+	REG_LDO,
+	REG_VS,
+	REG_GPIO,
+};
+
+struct camera_vreg_t {
+	const char *reg_name;
+	enum camera_vreg_type type;
+	int min_voltage;
+	int max_voltage;
+	int op_mode;
+	uint32_t delay;
+};
+
+struct msm_camera_vreg_setting {
+	struct camera_vreg_t *cam_vreg;
+	uint16_t num_vreg;
+	uint8_t enable;
+};
+
+struct msm_cam_clk_info {
+	const char *clk_name;
+	long clk_rate;
+	uint32_t delay;
+};
+
+struct msm_cam_clk_setting {
+	struct msm_cam_clk_info *clk_info;
+	uint16_t num_clk_info;
+	uint8_t enable;
+};
+
 struct sensor_cfg_data {
 	int cfgtype;
 	int mode;
@@ -1408,12 +1664,30 @@
 		int ae_mode;
 		uint8_t wb_val;
 		int8_t exp_compensation;
+		uint32_t pclk;
 		struct cord aec_cord;
 		int is_autoflash;
 		struct mirror_flip mirror_flip;
+		void *setting;
 	} cfg;
 };
 
+enum gpio_operation_type {
+	GPIO_REQUEST,
+	GPIO_FREE,
+	GPIO_SET_DIRECTION_OUTPUT,
+	GPIO_SET_DIRECTION_INPUT,
+	GPIO_GET_VALUE,
+	GPIO_SET_VALUE,
+};
+
+struct msm_cam_gpio_operation {
+	enum gpio_operation_type op_type;
+	unsigned address;
+	int value;
+	const char *tag;
+};
+
 struct damping_params_t {
 	uint32_t damping_step;
 	uint32_t damping_delay;
@@ -1570,11 +1844,17 @@
 	struct pixel_t video_coord[128];
 };
 
+struct msm_calib_raw {
+	uint8_t *data;
+	uint32_t size;
+};
+
 struct msm_camera_eeprom_info_t {
 	struct msm_eeprom_support af;
 	struct msm_eeprom_support wb;
 	struct msm_eeprom_support lsc;
 	struct msm_eeprom_support dpc;
+	struct msm_eeprom_support raw;
 };
 
 struct msm_eeprom_cfg_data {
@@ -1747,6 +2027,9 @@
 #define MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct msm_camera_v4l2_ioctl_t)
 
+#define MSM_CAM_V4L2_IOCTL_PRIVATE_GENERAL \
+	_IOW('V', BASE_VIDIOC_PRIVATE + 10, struct msm_camera_v4l2_ioctl_t)
+
 #define VIDIOC_MSM_VPE_INIT \
 	_IO('V', BASE_VIDIOC_PRIVATE + 15)
 
@@ -1757,7 +2040,7 @@
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 17, struct msm_mctl_pp_params *)
 
 #define VIDIOC_MSM_AXI_INIT \
-	_IO('V', BASE_VIDIOC_PRIVATE + 18)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 18, uint8_t *)
 
 #define VIDIOC_MSM_AXI_RELEASE \
 	_IO('V', BASE_VIDIOC_PRIVATE + 19)
@@ -1771,22 +2054,27 @@
 #define VIDIOC_MSM_AXI_BUF_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 22, void *)
 
+#define VIDIOC_MSM_AXI_RDI_COUNT_UPDATE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct rdi_count_msg)
+
 #define VIDIOC_MSM_VFE_INIT \
-	_IO('V', BASE_VIDIOC_PRIVATE + 22)
+	_IO('V', BASE_VIDIOC_PRIVATE + 24)
 
 #define VIDIOC_MSM_VFE_RELEASE \
-	_IO('V', BASE_VIDIOC_PRIVATE + 23)
+	_IO('V', BASE_VIDIOC_PRIVATE + 25)
 
 struct msm_camera_v4l2_ioctl_t {
 	uint32_t id;
-	void __user *ioctl_ptr;
 	uint32_t len;
+	uint32_t trans_code;
+	void __user *ioctl_ptr;
 };
 
 struct msm_camera_vfe_params_t {
 	uint32_t operation_mode;
 	uint32_t capture_count;
-	uint32_t skip_abort;
+	uint8_t  skip_reset;
+	uint8_t  stop_immediately;
 	uint16_t port_info;
 	uint32_t inst_handle;
 	uint16_t cmd_type;
@@ -1931,6 +2219,13 @@
 	uint32_t rev;
 };
 
+struct intf_mctl_mapping_cfg {
+	int is_bayer_sensor;
+	int vnode_id;
+	int num_entries;
+	uint32_t image_modes[MSM_V4L2_EXT_CAPTURE_MODE_MAX];
+};
+
 #define VIDIOC_MSM_CPP_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_v4l2_ioctl_t)
 
@@ -1950,7 +2245,8 @@
  *      ------------------------------------
  *      Bits    :  Purpose
  *      ------------------------------------
- *      31 - 24 :  Reserved.
+ *      31      :  is Dev ID valid?
+ *      30 - 24 :  Dev ID.
  *      23      :  is Image mode valid?
  *      22 - 16 :  Image mode.
  *      15      :  is MCTL PP inst idx valid?
@@ -1958,6 +2254,12 @@
  *      7       :  is Video inst idx valid?
  *      6 - 0   :  Video inst idx.
  */
+#define CLR_DEVID_MODE(handle)	(handle &= 0x00FFFFFF)
+#define SET_DEVID_MODE(handle, data)	\
+	(handle |= ((0x1 << 31) | ((data & 0x7F) << 24)))
+#define GET_DEVID_MODE(handle)	\
+	((handle & 0x80000000) ? ((handle & 0x7F000000) >> 24) : 0xFF)
+
 #define CLR_IMG_MODE(handle)	(handle &= 0xFF00FFFF)
 #define SET_IMG_MODE(handle, data)	\
 	(handle |= ((0x1 << 23) | ((data & 0x7F) << 16)))
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 9fa5932..bcd670d 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -68,6 +68,10 @@
 #define MSG_ID_RDI0_UPDATE_ACK          49
 #define MSG_ID_RDI1_UPDATE_ACK          50
 #define MSG_ID_RDI2_UPDATE_ACK          51
+#define MSG_ID_PIX0_UPDATE_ACK          52
+#define MSG_ID_PREV_STOP_ACK            53
+#define MSG_ID_OUTPUT_TERTIARY3         54
+
 
 /* ISP command IDs */
 #define VFE_CMD_DUMMY_0                                 0
@@ -324,30 +328,10 @@
 struct msm_vpe_clock_rate {
 	uint32_t rate;
 };
-struct msm_pp_crop {
-	uint32_t  src_x;
-	uint32_t  src_y;
-	uint32_t  src_w;
-	uint32_t  src_h;
-	uint32_t  dst_x;
-	uint32_t  dst_y;
-	uint32_t  dst_w;
-	uint32_t  dst_h;
-	uint8_t update_flag;
-};
+
 #define MSM_MCTL_PP_VPE_FRAME_ACK    (1<<0)
 #define MSM_MCTL_PP_VPE_FRAME_TO_APP (1<<1)
 
-struct msm_mctl_pp_frame_cmd {
-	uint32_t cookie;
-	uint8_t  vpe_output_action;
-	uint32_t src_buf_handle;
-	uint32_t dest_buf_handle;
-	struct msm_pp_crop crop;
-	int path;
-	/* TBD: 3D related */
-};
-
 #define VFE_OUTPUTS_MAIN_AND_PREVIEW    BIT(0)
 #define VFE_OUTPUTS_MAIN_AND_VIDEO      BIT(1)
 #define VFE_OUTPUTS_MAIN_AND_THUMB      BIT(2)
@@ -361,6 +345,7 @@
 #define VFE_OUTPUTS_THUMB_AND_JPEG      BIT(10)
 #define VFE_OUTPUTS_RDI0                BIT(11)
 #define VFE_OUTPUTS_RDI1                BIT(12)
+#define VFE_OUTPUTS_RDI2                BIT(13)
 
 struct msm_frame_info {
 	uint32_t inst_handle;
diff --git a/include/media/msm_jpeg.h b/include/media/msm_jpeg.h
new file mode 100644
index 0000000..ae9c958
--- /dev/null
+++ b/include/media/msm_jpeg.h
@@ -0,0 +1,132 @@
+/* Copyright (c) 2012, The Linux Foundation. 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 __LINUX_MSM_JPEG_H
+#define __LINUX_MSM_JPEG_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define OUTPUT_H2V1  0
+#define OUTPUT_H2V2  1
+#define OUTPUT_BYTE  6
+
+#define MSM_JPEG_IOCTL_MAGIC 'g'
+
+#define MSM_JPEG_IOCTL_GET_HW_VERSION \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 1, struct msm_jpeg_hw_cmd *)
+
+#define MSM_JPEG_IOCTL_RESET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 2, struct msm_jpeg_ctrl_cmd *)
+
+#define MSM_JPEG_IOCTL_STOP \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 3, struct msm_jpeg_hw_cmds *)
+
+#define MSM_JPEG_IOCTL_START \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 4, struct msm_jpeg_hw_cmds *)
+
+#define MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 5, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_INPUT_GET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 6, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_INPUT_GET_UNBLOCK \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 7, int)
+
+#define MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 8, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_OUTPUT_GET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 9, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_OUTPUT_GET_UNBLOCK \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 10, int)
+
+#define MSM_JPEG_IOCTL_EVT_GET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 11, struct msm_jpeg_ctrl_cmd *)
+
+#define MSM_JPEG_IOCTL_EVT_GET_UNBLOCK \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 12, int)
+
+#define MSM_JPEG_IOCTL_HW_CMD \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 13, struct msm_jpeg_hw_cmd *)
+
+#define MSM_JPEG_IOCTL_HW_CMDS \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 14, struct msm_jpeg_hw_cmds *)
+
+#define MSM_JPEG_IOCTL_TEST_DUMP_REGION \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 15, unsigned long)
+
+#define MSM_JPEG_MODE_REALTIME_ENCODE 0
+#define MSM_JPEG_MODE_OFFLINE_ENCODE 1
+#define MSM_JPEG_MODE_REALTIME_ROTATION 2
+#define MSM_JPEG_MODE_OFFLINE_ROTATION 3
+
+struct msm_jpeg_ctrl_cmd {
+	uint32_t type;
+	uint32_t len;
+	void     *value;
+};
+
+#define MSM_JPEG_EVT_RESET 0
+#define MSM_JPEG_EVT_SESSION_DONE	1
+#define MSM_JPEG_EVT_ERR 2
+
+struct msm_jpeg_buf {
+	uint32_t type;
+	int      fd;
+
+	void     *vaddr;
+
+	uint32_t y_off;
+	uint32_t y_len;
+	uint32_t framedone_len;
+
+	uint32_t cbcr_off;
+	uint32_t cbcr_len;
+
+	uint32_t num_of_mcu_rows;
+	uint32_t offset;
+};
+
+#define MSM_JPEG_HW_CMD_TYPE_READ      0
+#define MSM_JPEG_HW_CMD_TYPE_WRITE     1
+#define MSM_JPEG_HW_CMD_TYPE_WRITE_OR  2
+#define MSM_JPEG_HW_CMD_TYPE_UWAIT     3
+#define MSM_JPEG_HW_CMD_TYPE_MWAIT     4
+#define MSM_JPEG_HW_CMD_TYPE_MDELAY    5
+#define MSM_JPEG_HW_CMD_TYPE_UDELAY    6
+struct msm_jpeg_hw_cmd {
+
+	uint32_t type:4;
+
+	/* n microseconds of timeout for WAIT */
+	/* n microseconds of time for DELAY */
+	/* repeat n times for READ/WRITE */
+	/* max is 0xFFF, 4095 */
+	uint32_t n:12;
+	uint32_t offset:16;
+	uint32_t mask;
+	union {
+		uint32_t data;   /* for single READ/WRITE/WAIT, n = 1 */
+		uint32_t *pdata;   /* for multiple READ/WRITE/WAIT, n > 1 */
+	};
+};
+
+struct msm_jpeg_hw_cmds {
+	uint32_t m; /* number of elements in the hw_cmd array */
+	struct msm_jpeg_hw_cmd hw_cmd[1];
+};
+
+#endif /* __LINUX_MSM_JPEG_H */
diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h
index 84e2bea..080ea03 100644
--- a/include/media/videobuf2-msm-mem.h
+++ b/include/media/videobuf2-msm-mem.h
@@ -17,7 +17,7 @@
 
 #include <media/videobuf2-core.h>
 #include <mach/iommu_domains.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 struct videobuf2_mapping {
 	unsigned int count;
@@ -74,7 +74,7 @@
 					uint32_t addr_offset, int path,
 					struct ion_client *client);
 void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
-					struct ion_client *client);
+				struct ion_client *client);
 unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *buf,
 					unsigned int plane_no);