Merge "ARM: dts: msm: Add iris camera flash support for sdm845" into dev/msm-4.9-camx
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
index 1127544..cd4d222 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
@@ -180,6 +180,9 @@
   should contain phandle of respective ir-cut node
 - qcom,special-support-sensors: if only some special sensors are supported
   on this board, add sensor name in this property.
+- use-shared-clk : It is booloean property. This property is required
+  if the clk is shared clk between different sensor and ois, if this
+  device need to be opened together.
 - clock-rates: clock rate in Hz.
 - clock-cntl-level: says what all different cloc level node has.
 - clock-cntl-support: Says whether clock control support is present or not
@@ -248,6 +251,9 @@
   required from the regulators mentioned in the regulator-names property
   (in the same order).
 - cam_vaf-supply : should contain regulator from which ois voltage is supplied
+- use-shared-clk : It is booloean property. This property is required
+  if the clk is shared clk between different sensor and ois, if this
+  device need to be opened together.
 
 Example:
 
@@ -354,8 +360,8 @@
          status = "ok";
          shared-gpios = <18 19>;
          pinctrl-names = "cam_res_mgr_default", "cam_res_mgr_suspend";
-         pinctrl-0 = <&cam_res_mgr_active>;
-         pinctrl-1 = <&cam_res_mgr_suspend>;
+         pinctrl-0 = <&cam_shared_clk_active &cam_res_mgr_active>;
+         pinctrl-1 = <&cam_shared_clk_suspend &cam_res_mgr_suspend>;
     };
 
     qcom,cam-sensor@0 {
@@ -374,7 +380,7 @@
          cam_vio-supply = <&pm845_lvs1>;
          cam_vana-supply = <&pmi8998_bob>;
          regulator-names = "cam_vdig", "cam_vio", "cam_vana";
-	 rgltr-cntrl-support;
+         rgltr-cntrl-support;
          rgltr-min-voltage = <0 3312000 1352000>;
          rgltr-max-voltage = <0 3312000 1352000>;
          rgltr-load-current = <0 80000 105000>;
@@ -398,6 +404,7 @@
          sensor-mode = <0>;
          cci-master = <0>;
          status = "ok";
+         use-shared-clk;
          clocks = <&clock_mmss clk_mclk0_clk_src>,
                <&clock_mmss clk_camss_mclk0_clk>;
          clock-names = "cam_src_clk", "cam_clk";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi
index c4ca6c5..8b94ca2 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi
@@ -197,7 +197,7 @@
 		rgltr-cntrl-support;
 		rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
 		rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
-		rgltr-load-current = <105000 0 80000 0>;
+		rgltr-load-current = <105000 0 80000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk1_active
@@ -234,7 +234,7 @@
 		rgltr-cntrl-support;
 		rgltr-min-voltage = <1800000 2850000 1352000 0 2800000>;
 		rgltr-max-voltage = <1800000 2850000 1352000 0 2800000>;
-		rgltr-load-current = <0 80000 105000 0>;
+		rgltr-load-current = <0 80000 105000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk2_active
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi
index c4ca6c5..8b94ca2 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi
@@ -197,7 +197,7 @@
 		rgltr-cntrl-support;
 		rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
 		rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
-		rgltr-load-current = <105000 0 80000 0>;
+		rgltr-load-current = <105000 0 80000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk1_active
@@ -234,7 +234,7 @@
 		rgltr-cntrl-support;
 		rgltr-min-voltage = <1800000 2850000 1352000 0 2800000>;
 		rgltr-max-voltage = <1800000 2850000 1352000 0 2800000>;
-		rgltr-load-current = <0 80000 105000 0>;
+		rgltr-load-current = <0 80000 105000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk2_active
diff --git a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
index 163420a..ef01d73 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
@@ -41,6 +41,12 @@
 	status = "ok";
 };
 
+&pm660l_switch1 {
+	pinctrl-names = "led_enable", "led_disable";
+	pinctrl-0 = <&flash_led3_front_en>;
+	pinctrl-1 = <&flash_led3_front_dis>;
+};
+
 &qupv3_se9_2uart {
 	status = "disabled";
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
index 307444d..845fe73 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
@@ -42,6 +42,12 @@
 	status = "ok";
 };
 
+&pm660l_switch1 {
+	pinctrl-names = "led_enable", "led_disable";
+	pinctrl-0 = <&flash_led3_front_en>;
+	pinctrl-1 = <&flash_led3_front_dis>;
+};
+
 &qupv3_se9_2uart {
 	status = "disabled";
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 188da58..d4953c1 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1558,6 +1558,36 @@
 			};
 		};
 
+		flash_led3_front {
+			flash_led3_front_en: flash_led3_front_en {
+				mux {
+					pins = "gpio21";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio21";
+					drive_strength = <2>;
+					output-high;
+					bias-disable;
+				};
+			};
+
+			flash_led3_front_dis: flash_led3_front_dis {
+				mux {
+					pins = "gpio21";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio21";
+					drive_strength = <2>;
+					output-low;
+					bias-disable;
+				};
+			};
+		};
+
 		/* Pinctrl setting for CAMERA GPIO key */
 		key_cam_snapshot {
 			key_cam_snapshot_default: key_cam_snapshot_default {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index 5a566e3..35a7774 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -777,7 +777,7 @@
 		clock-rates =
 			<0 0 0 0 0 0 384000000 0 0 0 404000000 0>,
 			<0 0 0 0 0 0 538000000 0 0 0 600000000 0>;
-		clock-cntl-level = "svs";
+		clock-cntl-level = "svs", "turbo";
 		src-clock-name = "ife_csid_clk_src";
 		status = "ok";
 	};
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 7447e1d..84402e4 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -196,30 +196,6 @@
 	return rc;
 }
 
-int cam_context_handle_crm_process_evt(struct cam_context *ctx,
-	struct cam_req_mgr_link_evt_data *process_evt)
-{
-	int rc;
-
-	if (!ctx->state_machine) {
-		CAM_ERR(CAM_CORE, "Context is not ready");
-		return -EINVAL;
-	}
-
-	mutex_lock(&ctx->ctx_mutex);
-	if (ctx->state_machine[ctx->state].crm_ops.process_evt) {
-		rc = ctx->state_machine[ctx->state].crm_ops.process_evt(ctx,
-			process_evt);
-	} else {
-		CAM_ERR(CAM_CORE, "No crm process evt in dev %d, state %d",
-			ctx->dev_hdl, ctx->state);
-		rc = -EPROTO;
-	}
-	mutex_unlock(&ctx->ctx_mutex);
-
-	return rc;
-}
-
 int cam_context_handle_acquire_dev(struct cam_context *ctx,
 	struct cam_acquire_dev_cmd *cmd)
 {
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index d536663..6d1589e 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -56,7 +56,6 @@
  * @num_in_acked:          Number of in fence acked
  * @num_out_acked:         Number of out fence acked
  * @flushed:               Request is flushed
- * @error_flag:            Flag an error
  * @ctx:                   The context to which this request belongs
  *
  */
@@ -74,7 +73,6 @@
 	uint32_t                      num_in_acked;
 	uint32_t                      num_out_acked;
 	int                           flushed;
-	bool                          error_flag;
 	struct cam_context           *ctx;
 };
 
@@ -122,8 +120,6 @@
 			struct cam_req_mgr_apply_request *apply);
 	int (*flush_req)(struct cam_context *ctx,
 			struct cam_req_mgr_flush_request *flush);
-	int (*process_evt)(struct cam_context *ctx,
-			struct cam_req_mgr_link_evt_data *evt_data);
 };
 
 
@@ -274,18 +270,6 @@
 		struct cam_req_mgr_flush_request *apply);
 
 /**
- * cam_context_handle_crm_process_evt()
- *
- * @brief:        Handle process event command
- *
- * @ctx:          Object pointer for cam_context
- * @process_evt:  process event command payload
- *
- */
-int cam_context_handle_crm_process_evt(struct cam_context *ctx,
-		struct cam_req_mgr_link_evt_data *process_evt);
-
-/**
  * cam_context_handle_acquire_dev()
  *
  * @brief:        Handle acquire device command
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index 40bab1c..0a1c2cf 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -201,7 +201,6 @@
 		return -EINVAL;
 	}
 
-	cam_context_stop_dev_to_hw(ctx);
 	arg.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
 	arg.active_req = false;
 
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index 3b0adc4..1f0213e 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -309,26 +309,6 @@
 	return cam_context_handle_crm_flush_req(ctx, flush);
 }
 
-static int __cam_node_crm_process_evt(
-	struct cam_req_mgr_link_evt_data *evt_data)
-{
-	struct cam_context *ctx = NULL;
-
-	if (!evt_data) {
-		CAM_ERR(CAM_CORE, "Invalid process event request payload");
-		return -EINVAL;
-	}
-
-	ctx = (struct cam_context *) cam_get_device_priv(evt_data->dev_hdl);
-	if (!ctx) {
-		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
-			evt_data->dev_hdl);
-		return -EINVAL;
-	}
-
-	return cam_context_handle_crm_process_evt(ctx, evt_data);
-}
-
 int cam_node_deinit(struct cam_node *node)
 {
 	if (node)
@@ -381,7 +361,6 @@
 	node->crm_node_intf.get_dev_info = __cam_node_crm_get_dev_info;
 	node->crm_node_intf.link_setup = __cam_node_crm_link_setup;
 	node->crm_node_intf.flush_req = __cam_node_crm_flush_req;
-	node->crm_node_intf.process_evt = __cam_node_crm_process_evt;
 
 	mutex_init(&node->list_mutex);
 	INIT_LIST_HEAD(&node->free_ctx_list);
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index e51d350..a8855ae 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -109,7 +109,19 @@
 			new_write_idx << BYTE_WORD_SHIFT);
 	}
 
+	/*
+	 * To make sure command data in a command queue before
+	 * updating write index
+	 */
+	wmb();
+
 	q->qhdr_write_idx = new_write_idx;
+
+	/*
+	 * Before raising interrupt make sure command data is ready for
+	 * firmware to process
+	 */
+	wmb();
 	cam_io_w((uint32_t)INTR_ENABLE,
 		g_hfi->csr_base + HFI_REG_A5_CSR_HOST2ICPINT);
 err:
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 93926a78..340a1e2 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1644,6 +1644,7 @@
 	for (i = 0; i < CAM_FRAME_CMD_MAX; i++)
 		clear_bit(i, hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap);
 	kfree(hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap);
+	hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap = NULL;
 	cam_icp_hw_mgr_clk_info_update(hw_mgr, &hw_mgr->ctx_data[ctx_id]);
 	hw_mgr->ctx_data[ctx_id].clk_info.curr_fc = 0;
 	hw_mgr->ctx_data[ctx_id].clk_info.base_clk = 0;
@@ -2068,6 +2069,7 @@
 	ctx_data = config_args->ctxt_to_hw_map;
 	mutex_lock(&ctx_data->ctx_mutex);
 	if (!ctx_data->in_use) {
+		mutex_unlock(&ctx_data->ctx_mutex);
 		CAM_ERR(CAM_ICP, "ctx is not in use");
 		return -EINVAL;
 	}
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 5c95dad..cfe5071 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -216,19 +216,7 @@
 			continue;
 		}
 
-		if (req->error_flag || !req_isp->bubble_report) {
-			CAM_DBG(CAM_ISP,
-				"Sync with failure: req %lld res 0x%x fd 0x%x",
-				req->request_id,
-				req_isp->fence_map_out[j].resource_handle,
-				req_isp->fence_map_out[j].sync_id);
-
-			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
-				CAM_SYNC_STATE_SIGNALED_ERROR);
-			if (rc)
-				CAM_ERR(CAM_ISP, "Sync failed with rc = %d",
-					rc);
-		} else if (!bubble_state) {
+		if (!bubble_state) {
 			CAM_DBG(CAM_ISP,
 				"Sync with success: req %lld res 0x%x fd 0x%x",
 				req->request_id,
@@ -239,6 +227,18 @@
 				CAM_SYNC_STATE_SIGNALED_SUCCESS);
 			if (rc)
 				CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
+					 rc);
+		} else if (!req_isp->bubble_report) {
+			CAM_DBG(CAM_ISP,
+				"Sync with failure: req %lld res 0x%x fd 0x%x",
+				req->request_id,
+				req_isp->fence_map_out[j].resource_handle,
+				req_isp->fence_map_out[j].sync_id);
+
+			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+				CAM_SYNC_STATE_SIGNALED_ERROR);
+			if (rc)
+				CAM_ERR(CAM_ISP, "Sync failed with rc = %d",
 					rc);
 		} else {
 			/*
@@ -2091,34 +2091,6 @@
 	return rc;
 }
 
-static int __cam_isp_ctx_process_evt(struct cam_context *ctx,
-	struct cam_req_mgr_link_evt_data *link_evt_data)
-{
-	int rc = 0;
-	struct cam_ctx_request *req_current;
-	struct cam_ctx_request *req_prev;
-	bool req_id_found = false;
-
-	list_for_each_entry_safe(req_current, req_prev,
-		&ctx->pending_req_list, list) {
-		if (link_evt_data->req_id == req_current->request_id) {
-			req_current->error_flag = true;
-			req_id_found = true;
-			CAM_DBG(CAM_ISP,
-				"flagging req_id=%lld as error on link_hdl: %d for dev_hdl: %d",
-				link_evt_data->req_id, link_evt_data->link_hdl,
-				link_evt_data->dev_hdl);
-		}
-	}
-
-	if (!req_id_found) {
-		CAM_ERR(CAM_ISP,
-			"req_id=%lld not found in the pending list ",
-			link_evt_data->req_id);
-		rc = -EINVAL;
-	}
-	return rc;
-}
 static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx,
 	struct cam_req_mgr_core_dev_link_setup *unlink)
 {
@@ -2251,7 +2223,6 @@
 			.unlink = __cam_isp_ctx_unlink_in_activated,
 			.apply_req = __cam_isp_ctx_apply_req,
 			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
-			.process_evt = __cam_isp_ctx_process_evt,
 		},
 		.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
 	},
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 8880cb5..0362758 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -203,7 +203,8 @@
 }
 
 static int cam_ife_hw_mgr_start_hw_res(
-	struct cam_ife_hw_mgr_res   *isp_hw_res)
+	struct cam_ife_hw_mgr_res   *isp_hw_res,
+	struct cam_ife_hw_mgr_ctx   *ctx)
 {
 	int i;
 	int rc = -1;
@@ -214,6 +215,8 @@
 			continue;
 		hw_intf = isp_hw_res->hw_res[i]->hw_intf;
 		if (hw_intf->hw_ops.start) {
+			isp_hw_res->hw_res[i]->rdi_only_ctx =
+				ctx->is_rdi_only_context;
 			rc = hw_intf->hw_ops.start(hw_intf->hw_priv,
 				isp_hw_res->hw_res[i],
 				sizeof(struct cam_isp_resource_node));
@@ -1749,7 +1752,8 @@
 
 	/* start the IFE out devices */
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
-		rc = cam_ife_hw_mgr_start_hw_res(&ctx->res_list_ife_out[i]);
+		rc = cam_ife_hw_mgr_start_hw_res(
+			&ctx->res_list_ife_out[i], ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE OUT (%d)", i);
 			goto err;
@@ -1759,7 +1763,7 @@
 	CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d", ctx->ctx_index);
 	/* Start the IFE mux in devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
-		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)",
 				 hw_mgr_res->res_id);
@@ -1770,7 +1774,7 @@
 	CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
-		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)",
 				 hw_mgr_res->res_id);
@@ -1909,7 +1913,8 @@
 		ctx->ctx_index);
 	/* start the IFE out devices */
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
-		rc = cam_ife_hw_mgr_start_hw_res(&ctx->res_list_ife_out[i]);
+		rc = cam_ife_hw_mgr_start_hw_res(
+			&ctx->res_list_ife_out[i], ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE OUT (%d)",
 				 i);
@@ -1921,7 +1926,7 @@
 		ctx->ctx_index);
 	/* Start the IFE mux in devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
-		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)",
 				 hw_mgr_res->res_id);
@@ -1933,7 +1938,7 @@
 		ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
-		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)",
 				 hw_mgr_res->res_id);
@@ -1945,7 +1950,7 @@
 		ctx->ctx_index);
 	/* Start the IFE CID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
-		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)",
 				hw_mgr_res->res_id);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index b634e38b..257a5ac 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -112,6 +112,7 @@
  * @tasklet_info:                 Tasklet structure that will be used to
  *                                schedule IRQ events related to this resource
  * @irq_handle:                   handle returned on subscribing for IRQ event
+ * @rdi_only_ctx:                 resouce belong to rdi only context or not
  * @init:                         function pointer to init the HW resource
  * @deinit:                       function pointer to deinit the HW resource
  * @start:                        function pointer to start the HW resource
@@ -131,6 +132,7 @@
 	void                          *cdm_ops;
 	void                          *tasklet_info;
 	int                            irq_handle;
+	int                            rdi_only_ctx;
 
 	int (*init)(struct cam_isp_resource_node *rsrc_node,
 		void *init_args, uint32_t arg_size);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index d534607..187aeaf 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -38,7 +38,7 @@
 
 static uint32_t camif_irq_err_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
 	0x00000000,
-	0x0FFF7E80,
+	0x0FFF7EBC,
 };
 
 static uint32_t rdi_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
@@ -531,7 +531,7 @@
 	struct cam_vfe_hw_core_info       *core_info = NULL;
 	struct cam_hw_info                *vfe_hw  = hw_priv;
 	struct cam_isp_resource_node      *isp_res;
-	int rc = -ENODEV;
+	int rc = 0;
 
 	if (!hw_priv || !start_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
@@ -545,39 +545,70 @@
 
 	mutex_lock(&vfe_hw->hw_mutex);
 	if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_IN) {
-		if (isp_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
-			isp_res->irq_handle = cam_irq_controller_subscribe_irq(
-				core_info->vfe_irq_controller,
-				CAM_IRQ_PRIORITY_1,
-				camif_irq_reg_mask, &core_info->irq_payload,
-				cam_vfe_irq_top_half, cam_ife_mgr_do_tasklet,
-				isp_res->tasklet_info, cam_tasklet_enqueue_cmd);
-		else
-			isp_res->irq_handle = cam_irq_controller_subscribe_irq(
-				core_info->vfe_irq_controller,
-				CAM_IRQ_PRIORITY_1,
-				rdi_irq_reg_mask, &core_info->irq_payload,
-				cam_vfe_irq_top_half, cam_ife_mgr_do_tasklet,
-				isp_res->tasklet_info, cam_tasklet_enqueue_cmd);
+		if (isp_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) {
+			isp_res->irq_handle =
+				cam_irq_controller_subscribe_irq(
+					core_info->vfe_irq_controller,
+					CAM_IRQ_PRIORITY_1,
+					camif_irq_reg_mask,
+					&core_info->irq_payload,
+					cam_vfe_irq_top_half,
+					cam_ife_mgr_do_tasklet,
+					isp_res->tasklet_info,
+					cam_tasklet_enqueue_cmd);
+			if (isp_res->irq_handle < 1)
+				rc = -ENOMEM;
+		} else if (isp_res->rdi_only_ctx) {
+			isp_res->irq_handle =
+				cam_irq_controller_subscribe_irq(
+					core_info->vfe_irq_controller,
+					CAM_IRQ_PRIORITY_1,
+					rdi_irq_reg_mask,
+					&core_info->irq_payload,
+					cam_vfe_irq_top_half,
+					cam_ife_mgr_do_tasklet,
+					isp_res->tasklet_info,
+					cam_tasklet_enqueue_cmd);
+			if (isp_res->irq_handle < 1)
+				rc = -ENOMEM;
+		}
 
-		core_info->irq_err_handle = cam_irq_controller_subscribe_irq(
-			core_info->vfe_irq_controller, CAM_IRQ_PRIORITY_0,
-			camif_irq_err_reg_mask, &core_info->irq_payload,
-			cam_vfe_irq_err_top_half, cam_ife_mgr_do_tasklet,
-			core_info->tasklet_info, cam_tasklet_enqueue_cmd);
-
-		if (isp_res->irq_handle > 0)
+		if (rc == 0) {
 			rc = core_info->vfe_top->hw_ops.start(
 				core_info->vfe_top->top_priv, isp_res,
 				sizeof(struct cam_isp_resource_node));
-		else
+			if (rc)
+				CAM_ERR(CAM_ISP, "Start failed. type:%d",
+					isp_res->res_type);
+		} else {
 			CAM_ERR(CAM_ISP,
 				"Error! subscribe irq controller failed");
+		}
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0);
 	} else {
 		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
+		rc = -EFAULT;
 	}
+
+	if (!core_info->irq_err_handle) {
+		core_info->irq_err_handle =
+			cam_irq_controller_subscribe_irq(
+				core_info->vfe_irq_controller,
+				CAM_IRQ_PRIORITY_0,
+				camif_irq_err_reg_mask,
+				&core_info->irq_payload,
+				cam_vfe_irq_err_top_half,
+				cam_ife_mgr_do_tasklet,
+				core_info->tasklet_info,
+				cam_tasklet_enqueue_cmd);
+		if (core_info->irq_err_handle < 1) {
+			CAM_ERR(CAM_ISP, "Error handle subscribe failure");
+			rc = -ENOMEM;
+			core_info->irq_err_handle = 0;
+		}
+	}
+
 	mutex_unlock(&vfe_hw->hw_mutex);
 
 	return rc;
@@ -607,15 +638,19 @@
 			core_info->vfe_top->top_priv, isp_res,
 			sizeof(struct cam_isp_resource_node));
 
-	cam_irq_controller_unsubscribe_irq(
-		core_info->vfe_irq_controller, core_info->irq_err_handle);
-
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
 	} else {
 		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
 	}
 
+	if (core_info->irq_err_handle) {
+		cam_irq_controller_unsubscribe_irq(
+			core_info->vfe_irq_controller,
+			core_info->irq_err_handle);
+		core_info->irq_err_handle = 0;
+	}
+
 	mutex_unlock(&vfe_hw->hw_mutex);
 
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
index 6fcd7f6..4589a22 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
@@ -63,6 +63,20 @@
 	return cam_context_buf_done_from_hw(ctx, done, evt_id);
 }
 
+static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx,
+	struct cam_start_stop_dev_cmd *cmd)
+{
+	int rc;
+
+	rc = cam_context_stop_dev_to_hw(ctx);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Failed in Stop dev, rc=%d", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
 /* top state machine */
 static struct cam_ctx_ops
 	cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = {
@@ -85,6 +99,7 @@
 		.ioctl_ops = {
 			.release_dev = __cam_jpeg_ctx_release_dev_in_acquired,
 			.config_dev = __cam_jpeg_ctx_config_dev_in_acquired,
+			.stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired,
 		},
 		.crm_ops = { },
 		.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index df95100..e401549 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -80,11 +80,23 @@
 
 	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
 
+	mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex);
+
+	p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+
+	if (hw_mgr->device_in_use[dev_type][0] == false ||
+		p_cfg_req == NULL) {
+		CAM_ERR(CAM_JPEG, "irq for old request %d", rc);
+		mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex);
+		return -EINVAL;
+	}
+
 	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
 	irq_cb.data = NULL;
 	irq_cb.b_set_cb = false;
 	if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
 		CAM_ERR(CAM_JPEG, "process_cmd null ");
+		mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex);
 		return -EINVAL;
 	}
 	rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
@@ -93,6 +105,7 @@
 		&irq_cb, sizeof(irq_cb));
 	if (rc) {
 		CAM_ERR(CAM_JPEG, "CMD_SET_IRQ_CB failed %d", rc);
+		mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex);
 		return rc;
 	}
 
@@ -103,9 +116,7 @@
 			CAM_ERR(CAM_JPEG, "Failed to Deinit %d HW", dev_type);
 	}
 
-	mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex);
 	hw_mgr->device_in_use[dev_type][0] = false;
-	p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
 	hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL;
 	mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex);
 
@@ -167,7 +178,6 @@
 
 	list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list);
 
-
 	return rc;
 }
 
@@ -319,8 +329,11 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
 	if (list_empty(&hw_mgr->hw_config_req_list)) {
 		CAM_DBG(CAM_JPEG, "no available request");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		rc = -EFAULT;
 		goto end;
 	}
@@ -329,11 +342,11 @@
 		struct cam_jpeg_hw_cfg_req, list);
 	if (!p_cfg_req) {
 		CAM_ERR(CAM_JPEG, "no request");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		rc = -EFAULT;
 		goto end;
 	}
 
-	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	if (false == hw_mgr->device_in_use[p_cfg_req->dev_type][0]) {
 		hw_mgr->device_in_use[p_cfg_req->dev_type][0] = true;
 		hw_mgr->dev_hw_cfg_args[p_cfg_req->dev_type][0] = p_cfg_req;
@@ -344,6 +357,7 @@
 		rc = -EFAULT;
 		goto end;
 	}
+
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
 	config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args;
@@ -464,7 +478,7 @@
 		hw_mgr->devices[dev_type][0]->hw_priv,
 		NULL, 0);
 	if (rc) {
-		CAM_ERR(CAM_JPEG, "Failed to apply the configs %d",
+		CAM_ERR(CAM_JPEG, "Failed to start hw %d",
 			rc);
 		goto end_callcb;
 	}
@@ -553,12 +567,12 @@
 		goto err_after_dq_free_list;
 	}
 
-	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
 	task_data = (struct cam_jpeg_process_frame_work_data_t *)
 		task->payload;
 	if (!task_data) {
 		CAM_ERR(CAM_JPEG, "task_data is NULL");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		rc = -EINVAL;
 		goto err_after_dq_free_list;
 	}
@@ -567,6 +581,7 @@
 		p_cfg_req->hw_cfg_args.num_hw_update_entries);
 
 	list_add_tail(&p_cfg_req->list, &hw_mgr->hw_config_req_list);
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
 	task_data->data = (void *)(int64_t)p_cfg_req->dev_type;
 	task_data->request_id = request_id;
@@ -719,6 +734,88 @@
 	return rc;
 }
 
+static int cam_jpeg_mgr_flush(void *hw_mgr_priv,
+	struct cam_jpeg_hw_ctx_data *ctx_data)
+{
+	int rc = 0;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	uint32_t dev_type;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+	struct cam_jpeg_hw_cfg_req *cfg_req, *req_temp;
+
+	if (!hw_mgr || !ctx_data) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+	if (hw_mgr->device_in_use[dev_type][0] == true &&
+		p_cfg_req != NULL) {
+		if ((struct cam_jpeg_hw_ctx_data *)p_cfg_req->
+		hw_cfg_args.ctxt_to_hw_map == ctx_data) {
+			/* stop reset Unregister CB and deinit */
+			if (hw_mgr->devices[dev_type][0]->hw_ops.stop) {
+				rc = hw_mgr->devices[dev_type][0]->hw_ops.stop(
+					hw_mgr->devices[dev_type][0]->hw_priv,
+					NULL, 0);
+				if (rc)
+					CAM_ERR(CAM_JPEG, "stop fail %d", rc);
+			} else {
+				CAM_ERR(CAM_JPEG, "op stop null ");
+				rc = -EINVAL;
+			}
+		}
+
+		hw_mgr->device_in_use[dev_type][0] = false;
+		p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+		hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL;
+	}
+
+	list_for_each_entry_safe(cfg_req, req_temp,
+		&hw_mgr->hw_config_req_list, list) {
+		if ((struct cam_jpeg_hw_ctx_data *)cfg_req->
+			hw_cfg_args.ctxt_to_hw_map != ctx_data)
+			continue;
+
+		CAM_INFO(CAM_JPEG, "deleting req %pK", cfg_req);
+		list_del_init(&cfg_req->list);
+	}
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_hw_stop(void *hw_mgr_priv, void *stop_hw_args)
+{
+	int rc;
+	struct cam_hw_stop_args *stop_args =
+		(struct cam_hw_stop_args *)stop_hw_args;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+
+	if (!hw_mgr || !stop_args || !stop_args->ctxt_to_hw_map) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)stop_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+
+	rc = cam_jpeg_mgr_flush(hw_mgr_priv, ctx_data);
+	if ((rc))
+		CAM_ERR(CAM_JPEG, "flush failed %d", rc);
+
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	return rc;
+}
+
 static int cam_jpeg_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
 {
 	int rc;
@@ -1184,6 +1281,7 @@
 	hw_mgr_intf->hw_release = cam_jpeg_mgr_release_hw;
 	hw_mgr_intf->hw_prepare_update = cam_jpeg_mgr_prepare_hw_update;
 	hw_mgr_intf->hw_config = cam_jpeg_mgr_config_hw;
+	hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop;
 
 	mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
 	spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h
index 725af47..2ac4db6 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h
@@ -19,6 +19,9 @@
 #define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000
 #define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
 
+#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK 0x8000000
+#define CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_SHIFT 0x0000001b
+
 #define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
 #define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
 
@@ -63,11 +66,13 @@
 		.int_mask_enable_all = 0xFFFFFFFF,
 		.hw_cmd_start = 0x00000001,
 		.reset_cmd = 0x00032093,
+		.hw_cmd_stop = 0x00000002,
 	},
 	.int_status = {
 		.framedone = CAM_JPEG_HW_MASK_COMP_FRAMEDONE,
 		.resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK,
 		.iserror = CAM_JPEG_HW_MASK_COMP_ERR,
+		.stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK,
 	}
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
index a7c4e06..934b911 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
@@ -37,6 +37,8 @@
 	((jpeg_irq_status) & (hi)->int_status.resetdone)
 #define CAM_JPEG_HW_IRQ_IS_ERR(jpeg_irq_status, hi) \
 	((jpeg_irq_status) & (hi)->int_status.iserror)
+#define CAM_JPEG_HW_IRQ_IS_STOP_DONE(jpeg_irq_status, hi) \
+	((jpeg_irq_status) & (hi)->int_status.stopdone)
 
 #define CAM_JPEG_ENC_RESET_TIMEOUT msecs_to_jiffies(500)
 
@@ -181,7 +183,9 @@
 
 	CAM_DBG(CAM_JPEG, "irq_num %d  irq_status = %x , core_state %d",
 		irq_num, irq_status, core_info->core_state);
+
 	if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) {
+		spin_lock(&jpeg_enc_dev->hw_lock);
 		if (core_info->core_state == CAM_JPEG_ENC_CORE_READY) {
 			encoded_size = cam_io_r_mb(mem_base +
 				core_info->jpeg_enc_hw_info->reg_offset.
@@ -191,22 +195,42 @@
 					encoded_size,
 					core_info->irq_cb.data);
 			} else {
-				CAM_ERR(CAM_JPEG, "unexpected done");
+				CAM_ERR(CAM_JPEG, "unexpected done, no cb");
 			}
+		} else {
+			CAM_ERR(CAM_JPEG, "unexpected done irq");
 		}
-
 		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+		spin_unlock(&jpeg_enc_dev->hw_lock);
 	}
 	if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status, hw_info)) {
+		spin_lock(&jpeg_enc_dev->hw_lock);
 		if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
 			core_info->core_state = CAM_JPEG_ENC_CORE_READY;
 			complete(&jpeg_enc_dev->hw_complete);
 		} else {
 			CAM_ERR(CAM_JPEG, "unexpected reset irq");
 		}
+		spin_unlock(&jpeg_enc_dev->hw_lock);
+	}
+	if (CAM_JPEG_HW_IRQ_IS_STOP_DONE(irq_status, hw_info)) {
+		spin_lock(&jpeg_enc_dev->hw_lock);
+		if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) {
+			core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+			complete(&jpeg_enc_dev->hw_complete);
+			if (core_info->irq_cb.jpeg_hw_mgr_cb) {
+				core_info->irq_cb.jpeg_hw_mgr_cb(irq_status,
+					-1,
+					core_info->irq_cb.data);
+			}
+		} else {
+			CAM_ERR(CAM_JPEG, "unexpected abort irq");
+		}
+		spin_unlock(&jpeg_enc_dev->hw_lock);
 	}
 	/* Unexpected/unintended HW interrupt */
 	if (CAM_JPEG_HW_IRQ_IS_ERR(irq_status, hw_info)) {
+		spin_lock(&jpeg_enc_dev->hw_lock);
 		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
 		CAM_ERR_RATE_LIMIT(CAM_JPEG,
 			"error irq_num %d  irq_status = %x , core_state %d",
@@ -217,6 +241,7 @@
 				-1,
 				core_info->irq_cb.data);
 		}
+		spin_unlock(&jpeg_enc_dev->hw_lock);
 	}
 
 	return IRQ_HANDLED;
@@ -244,14 +269,18 @@
 	hw_info = core_info->jpeg_enc_hw_info;
 	mem_base = soc_info->reg_map[0].mem_base;
 
+	mutex_lock(&core_info->core_mutex);
+	spin_lock(&jpeg_enc_dev->hw_lock);
 	if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
 		CAM_ERR(CAM_JPEG, "alrady resetting");
+		spin_unlock(&jpeg_enc_dev->hw_lock);
+		mutex_unlock(&core_info->core_mutex);
 		return 0;
 	}
 
 	reinit_completion(&jpeg_enc_dev->hw_complete);
-
 	core_info->core_state = CAM_JPEG_ENC_CORE_RESETTING;
+	spin_unlock(&jpeg_enc_dev->hw_lock);
 
 	cam_io_w_mb(hw_info->reg_val.int_mask_disable_all,
 		mem_base + hw_info->reg_offset.int_mask);
@@ -269,6 +298,7 @@
 		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
 	}
 
+	mutex_unlock(&core_info->core_mutex);
 	return 0;
 }
 
@@ -303,6 +333,54 @@
 	return 0;
 }
 
+int cam_jpeg_enc_stop_hw(void *data,
+	void *stop_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+	unsigned long rem_jiffies;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	mutex_unlock(&core_info->core_mutex);
+	spin_lock(&jpeg_enc_dev->hw_lock);
+	if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) {
+		CAM_ERR(CAM_JPEG, "alrady stopping");
+		spin_unlock(&jpeg_enc_dev->hw_lock);
+		mutex_unlock(&core_info->core_mutex);
+		return 0;
+	}
+
+	reinit_completion(&jpeg_enc_dev->hw_complete);
+	core_info->core_state = CAM_JPEG_ENC_CORE_ABORTING;
+	spin_unlock(&jpeg_enc_dev->hw_lock);
+
+	cam_io_w_mb(hw_info->reg_val.hw_cmd_stop,
+		mem_base + hw_info->reg_offset.hw_cmd);
+
+	rem_jiffies = wait_for_completion_timeout(&jpeg_enc_dev->hw_complete,
+		CAM_JPEG_ENC_RESET_TIMEOUT);
+	if (!rem_jiffies) {
+		CAM_ERR(CAM_JPEG, "error Reset Timeout");
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+	}
+
+	mutex_unlock(&core_info->core_mutex);
+	return 0;
+}
+
 int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
 	void *cmd_args, uint32_t arg_size)
 {
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
index 4f5d625..5fa8f21 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
@@ -37,12 +37,14 @@
 	uint32_t int_mask_enable_all;
 	uint32_t hw_cmd_start;
 	uint32_t reset_cmd;
+	uint32_t hw_cmd_stop;
 };
 
 struct cam_jpeg_enc_int_status {
 	uint32_t framedone;
 	uint32_t resetdone;
 	uint32_t iserror;
+	uint32_t stopdone;
 };
 
 struct cam_jpeg_enc_device_hw_info {
@@ -55,6 +57,7 @@
 	CAM_JPEG_ENC_CORE_NOT_READY,
 	CAM_JPEG_ENC_CORE_READY,
 	CAM_JPEG_ENC_CORE_RESETTING,
+	CAM_JPEG_ENC_CORE_ABORTING,
 	CAM_JPEG_ENC_CORE_STATE_MAX,
 };
 
@@ -73,6 +76,8 @@
 	void *init_hw_args, uint32_t arg_size);
 int cam_jpeg_enc_start_hw(void *device_priv,
 	void *start_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_stop_hw(void *device_priv,
+	void *stop_hw_args, uint32_t arg_size);
 int cam_jpeg_enc_reset_hw(void *device_priv,
 	void *reset_hw_args, uint32_t arg_size);
 int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
index 735bd21..2180448 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
@@ -139,6 +139,7 @@
 	jpeg_enc_dev_intf->hw_ops.init = cam_jpeg_enc_init_hw;
 	jpeg_enc_dev_intf->hw_ops.deinit = cam_jpeg_enc_deinit_hw;
 	jpeg_enc_dev_intf->hw_ops.start = cam_jpeg_enc_start_hw;
+	jpeg_enc_dev_intf->hw_ops.stop = cam_jpeg_enc_stop_hw;
 	jpeg_enc_dev_intf->hw_ops.reset = cam_jpeg_enc_reset_hw;
 	jpeg_enc_dev_intf->hw_ops.process_cmd = cam_jpeg_enc_process_cmd;
 	jpeg_enc_dev_intf->hw_type = CAM_JPEG_DEV_ENC;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
index 9eca4c7..d9b43a4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
@@ -259,6 +259,7 @@
 		return -ENOMEM;
 
 	o_ctrl->soc_info.pdev = pdev;
+	o_ctrl->pdev = pdev;
 	o_ctrl->soc_info.dev = &pdev->dev;
 	o_ctrl->soc_info.dev_name = pdev->name;
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
index d588b24..bb3789b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
@@ -51,6 +51,10 @@
 		kfree(flash_res);
 	}
 	mutex_unlock(&cam_res->flash_res_lock);
+
+	mutex_lock(&cam_res->clk_res_lock);
+	cam_res->shared_clk_ref_count = 0;
+	mutex_unlock(&cam_res->clk_res_lock);
 }
 
 void cam_res_mgr_led_trigger_register(const char *name, struct led_trigger **tp)
@@ -243,6 +247,9 @@
 		}
 	}
 
+	if (cam_res->shared_clk_ref_count > 1)
+		hold = true;
+
 	return hold;
 }
 
@@ -258,11 +265,13 @@
 	mutex_lock(&cam_res->gpio_res_lock);
 	if (cam_res->pstatus == PINCTRL_STATUS_PUT) {
 		CAM_DBG(CAM_RES, "The shared pinctrl already been put");
+		mutex_unlock(&cam_res->gpio_res_lock);
 		return;
 	}
 
 	if (cam_res_mgr_shared_pinctrl_check_hold()) {
 		CAM_INFO(CAM_RES, "Need hold put this pinctrl");
+		mutex_unlock(&cam_res->gpio_res_lock);
 		return;
 	}
 
@@ -330,10 +339,12 @@
 	pinctrl_info = &cam_res->dt.pinctrl_info;
 
 	/*
-	 * If no gpio resource in gpio_res_list, it means
-	 * this device don't have shared gpio
+	 * If no gpio resource in gpio_res_list, and
+	 * no shared clk now, it means this device
+	 * don't have shared gpio.
 	 */
-	if (list_empty(&cam_res->gpio_res_list)) {
+	if (list_empty(&cam_res->gpio_res_list) &&
+		cam_res->shared_clk_ref_count < 1) {
 		ret = pinctrl_select_state(pinctrl_info->pinctrl,
 			pinctrl_info->gpio_state_suspend);
 		devm_pinctrl_put(pinctrl_info->pinctrl);
@@ -576,6 +587,20 @@
 }
 EXPORT_SYMBOL(cam_res_mgr_gpio_set_value);
 
+void cam_res_mgr_shared_clk_config(bool value)
+{
+	if (!cam_res)
+		return;
+
+	mutex_lock(&cam_res->clk_res_lock);
+	if (value)
+		cam_res->shared_clk_ref_count++;
+	else
+		cam_res->shared_clk_ref_count--;
+	mutex_unlock(&cam_res->clk_res_lock);
+}
+EXPORT_SYMBOL(cam_res_mgr_shared_clk_config);
+
 static int cam_res_mgr_parse_dt(struct device *dev)
 {
 	int rc = 0;
@@ -649,6 +674,7 @@
 	cam_res->dev = &pdev->dev;
 	mutex_init(&cam_res->flash_res_lock);
 	mutex_init(&cam_res->gpio_res_lock);
+	mutex_init(&cam_res->clk_res_lock);
 
 	rc = cam_res_mgr_parse_dt(&pdev->dev);
 	if (rc) {
@@ -659,6 +685,7 @@
 		cam_res->shared_gpio_enabled = true;
 	}
 
+	cam_res->shared_clk_ref_count = 0;
 	cam_res->pstatus = PINCTRL_STATUS_PUT;
 
 	INIT_LIST_HEAD(&cam_res->gpio_res_list);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h
index 1c4c6c8..7fb13ba 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h
@@ -134,4 +134,15 @@
  */
 int cam_res_mgr_gpio_set_value(unsigned int gpio, int value);
 
+/**
+ * @brief: Config the shared clk ref count
+ *
+ *  Config the shared clk ref count..
+ *
+ * @value   : get or put the shared clk.
+ *
+ * @return None
+ */
+void cam_res_mgr_shared_clk_config(bool value);
+
 #endif /* __CAM_RES_MGR_API_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h
index 4d46c8e..53a8778 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr_private.h
@@ -96,6 +96,7 @@
  * @flash_res_list      : List head of the flash resource
  * @gpio_res_lock       : GPIO resource lock
  * @flash_res_lock      : Flash resource lock
+ * @clk_res_lock        : Clk resource lock
  */
 struct cam_res_mgr {
 	struct device         *dev;
@@ -104,10 +105,13 @@
 	bool                  shared_gpio_enabled;
 	enum pinctrl_status   pstatus;
 
+	uint                  shared_clk_ref_count;
+
 	struct list_head      gpio_res_list;
 	struct list_head      flash_res_list;
 	struct mutex          gpio_res_lock;
 	struct mutex          flash_res_lock;
+	struct mutex          clk_res_lock;
 };
 
 #endif /* __CAM_RES_MGR_PRIVATE_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index b3de092..0a3878e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -1235,6 +1235,9 @@
 		return -EINVAL;
 	}
 
+	if (soc_info->use_shared_clk)
+		cam_res_mgr_shared_clk_config(true);
+
 	ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev);
 	if (ret < 0) {
 		/* Some sensor subdev no pinctrl. */
@@ -1492,6 +1495,7 @@
 				(power_setting->delay * 1000) + 1000);
 		}
 	}
+
 	if (ctrl->cam_pinctrl_status) {
 		ret = pinctrl_select_state(
 				ctrl->pinctrl_info.pinctrl,
@@ -1502,6 +1506,10 @@
 		pinctrl_put(ctrl->pinctrl_info.pinctrl);
 		cam_res_mgr_shared_pinctrl_put();
 	}
+
+	if (soc_info->use_shared_clk)
+		cam_res_mgr_shared_clk_config(false);
+
 	ctrl->cam_pinctrl_status = 0;
 
 	cam_sensor_util_request_gpio_table(soc_info, 0);
@@ -1698,6 +1706,9 @@
 		cam_res_mgr_shared_pinctrl_put();
 	}
 
+	if (soc_info->use_shared_clk)
+		cam_res_mgr_shared_clk_config(false);
+
 	ctrl->cam_pinctrl_status = 0;
 
 	cam_sensor_util_request_gpio_table(soc_info, 0);
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index 2422016..e7dcbe7 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -230,6 +230,8 @@
 				spin_unlock_bh(
 					&sync_dev->row_spinlocks[
 						parent_info->sync_id]);
+				spin_unlock_bh(
+					&sync_dev->row_spinlocks[sync_obj]);
 				return rc;
 			}
 		}
@@ -344,24 +346,8 @@
 
 int cam_sync_destroy(int32_t sync_obj)
 {
-	struct sync_table_row *row = NULL;
-
-	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0)
-		return -EINVAL;
-
-	spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]);
-	row = sync_dev->sync_table + sync_obj;
-	if (row->state == CAM_SYNC_STATE_INVALID) {
-		CAM_ERR(CAM_SYNC,
-			"Error: accessing an uninitialized sync obj: idx = %d",
-			sync_obj);
-		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-		return -EINVAL;
-	}
 
 	cam_sync_deinit_object(sync_dev->sync_table, sync_obj);
-	spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_private.h b/drivers/media/platform/msm/camera/cam_sync/cam_sync_private.h
index ba9bef4..e2a7fcb 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_private.h
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_private.h
@@ -55,6 +55,18 @@
 };
 
 /**
+ * enum sync_list_clean_type - Enum to indicate the type of list clean action
+ * to be peformed, i.e. specific sync ID or all list sync ids.
+ *
+ * @SYNC_CLEAN_ID  : Specific object to be cleaned in the list
+ * @SYNC_CLEAN_ALL : Clean all objects in the list
+ */
+enum sync_list_clean_type {
+	SYNC_LIST_CLEAN_ID,
+	SYNC_LIST_CLEAN_ALL
+};
+
+/**
  * struct sync_parent_info - Single node of information about a parent
  * of a sync object, usually part of the parents linked list
  *
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index f66b882..6aa7c23 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
@@ -145,7 +145,7 @@
 
 		if (!child_info) {
 			cam_sync_util_cleanup_children_list(
-				&row->children_list);
+				&row->children_list, SYNC_LIST_CLEAN_ALL, 0);
 			return -ENOMEM;
 		}
 
@@ -160,9 +160,10 @@
 		parent_info = kzalloc(sizeof(*parent_info), GFP_ATOMIC);
 		if (!parent_info) {
 			cam_sync_util_cleanup_parents_list(
-				&child_row->parents_list);
+				&child_row->parents_list,
+				SYNC_LIST_CLEAN_ALL, 0);
 			cam_sync_util_cleanup_children_list(
-				&row->children_list);
+				&row->children_list, SYNC_LIST_CLEAN_ALL, 0);
 			spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
 			return -ENOMEM;
 		}
@@ -197,27 +198,131 @@
 int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx)
 {
 	struct sync_table_row *row = table + idx;
-	struct sync_child_info *child_info, *temp_child;
+	struct sync_child_info *child_info, *temp_child, *child_copy_info;
 	struct sync_callback_info *sync_cb, *temp_cb;
-	struct sync_parent_info *parent_info, *temp_parent;
+	struct sync_parent_info *parent_info, *temp_parent, *parent_copy_info;
 	struct sync_user_payload *upayload_info, *temp_upayload;
+	struct sync_table_row   *child_row = NULL, *parent_row = NULL;
+	struct list_head child_copy_list, parent_copy_list;
 
 	if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS)
 		return -EINVAL;
 
-	clear_bit(idx, sync_dev->bitmap);
-	list_for_each_entry_safe(child_info, temp_child,
-				&row->children_list, list) {
+	spin_lock_bh(&sync_dev->row_spinlocks[idx]);
+	if (row->state == CAM_SYNC_STATE_INVALID) {
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj: idx = %d",
+			idx);
+		spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
+		return -EINVAL;
+	}
+
+	/* Objects child and parent objects will be added into this list */
+	INIT_LIST_HEAD(&child_copy_list);
+	INIT_LIST_HEAD(&parent_copy_list);
+
+	list_for_each_entry_safe(child_info, temp_child, &row->children_list,
+		list) {
+		if (child_info->sync_id <= 0)
+			continue;
+
+		child_copy_info = kzalloc(sizeof(*child_copy_info), GFP_ATOMIC);
+		if (!child_copy_info) {
+			/* No free memory, clean up the child_copy_list */
+			while (!list_empty(&child_copy_list)) {
+				child_info = list_first_entry(&child_copy_list,
+					struct sync_child_info, list);
+				list_del_init(&child_info->list);
+				kfree(child_info);
+			}
+			spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
+			goto deinit;
+		}
+		child_copy_info->sync_id = child_info->sync_id;
+		list_add_tail(&child_copy_info->list, &child_copy_list);
+	}
+
+	list_for_each_entry_safe(parent_info, temp_parent, &row->parents_list,
+		list) {
+		if (parent_info->sync_id <= 0)
+			continue;
+		parent_copy_info = kzalloc(sizeof(*parent_copy_info),
+			GFP_ATOMIC);
+		if (!parent_copy_info) {
+			/* No free memory, clean up the parent_copy_list */
+			while (!list_empty(&parent_copy_list)) {
+				parent_info = list_first_entry(
+					&parent_copy_list,
+					struct sync_parent_info, list);
+				list_del_init(&parent_info->list);
+				kfree(parent_info);
+			}
+			/* No free memory, clean up the child_copy_list */
+			while (!list_empty(&child_copy_list)) {
+				child_info = list_first_entry(&child_copy_list,
+					struct sync_child_info, list);
+				list_del_init(&child_info->list);
+				kfree(child_info);
+			}
+			spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
+			goto deinit;
+		}
+		parent_copy_info->sync_id = parent_info->sync_id;
+		list_add_tail(&parent_copy_info->list, &parent_copy_list);
+	}
+
+	spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
+	/* Cleanup the child to parent link from child list*/
+	while (!list_empty(&child_copy_list)) {
+		child_info = list_first_entry(&child_copy_list,
+			struct sync_child_info, list);
+		child_row = sync_dev->sync_table + child_info->sync_id;
+		spin_lock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
+		if (child_row->state == CAM_SYNC_STATE_INVALID) {
+			spin_unlock_bh(&sync_dev->row_spinlocks[
+				child_info->sync_id]);
+			list_del_init(&child_info->list);
+			kfree(child_info);
+			continue;
+		}
+
+		cam_sync_util_cleanup_parents_list(&child_row->parents_list,
+			SYNC_LIST_CLEAN_ID, idx);
+
+		spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
 		list_del_init(&child_info->list);
 		kfree(child_info);
 	}
 
-	list_for_each_entry_safe(parent_info, temp_parent,
-				&row->parents_list, list) {
+	/* Cleanup the parent to child link */
+	while (!list_empty(&parent_copy_list)) {
+		parent_info = list_first_entry(&parent_copy_list,
+			struct sync_parent_info, list);
+		parent_row = sync_dev->sync_table + parent_info->sync_id;
+		spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
+		if (parent_row->state == CAM_SYNC_STATE_INVALID) {
+			spin_unlock_bh(&sync_dev->row_spinlocks[
+				parent_info->sync_id]);
+			list_del_init(&parent_info->list);
+			kfree(parent_info);
+			continue;
+		}
+
+		cam_sync_util_cleanup_children_list(&parent_row->children_list,
+			SYNC_LIST_CLEAN_ID, idx);
+
+		spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
 		list_del_init(&parent_info->list);
 		kfree(parent_info);
 	}
 
+deinit:
+	spin_lock_bh(&sync_dev->row_spinlocks[idx]);
+	cam_sync_util_cleanup_children_list(&row->children_list,
+		SYNC_LIST_CLEAN_ALL, 0);
+	cam_sync_util_cleanup_parents_list(&row->parents_list,
+		SYNC_LIST_CLEAN_ALL, 0);
+
 	list_for_each_entry_safe(upayload_info, temp_upayload,
 				&row->user_payload_list, list) {
 		list_del_init(&upayload_info->list);
@@ -232,6 +337,8 @@
 
 	row->state = CAM_SYNC_STATE_INVALID;
 	memset(row, 0, sizeof(*row));
+	clear_bit(idx, sync_dev->bitmap);
+	spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
 
 	return 0;
 }
@@ -350,26 +457,48 @@
 	return result;
 }
 
-void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean)
+void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean,
+	uint32_t list_clean_type, uint32_t sync_obj)
 {
 	struct sync_child_info *child_info = NULL;
 	struct sync_child_info *temp_child_info = NULL;
+	uint32_t                curr_sync_obj;
 
 	list_for_each_entry_safe(child_info,
 			temp_child_info, list_to_clean, list) {
+		if ((list_clean_type == SYNC_LIST_CLEAN_ID) &&
+			(child_info->sync_id != sync_obj))
+			continue;
+
+		curr_sync_obj = child_info->sync_id;
 		list_del_init(&child_info->list);
 		kfree(child_info);
+
+		if ((list_clean_type == SYNC_LIST_CLEAN_ID) &&
+			(curr_sync_obj == sync_obj))
+			break;
 	}
 }
 
-void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean)
+void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean,
+	uint32_t list_clean_type, uint32_t sync_obj)
 {
 	struct sync_parent_info *parent_info = NULL;
 	struct sync_parent_info *temp_parent_info = NULL;
+	uint32_t                 curr_sync_obj;
 
 	list_for_each_entry_safe(parent_info,
 			temp_parent_info, list_to_clean, list) {
+		if ((list_clean_type == SYNC_LIST_CLEAN_ID) &&
+			(parent_info->sync_id != sync_obj))
+			continue;
+
+		curr_sync_obj = parent_info->sync_id;
 		list_del_init(&parent_info->list);
 		kfree(parent_info);
+
+		if ((list_clean_type == SYNC_LIST_CLEAN_ID) &&
+			(curr_sync_obj == sync_obj))
+			break;
 	}
 }
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
index 8b60ce1..1c5c4bf 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
@@ -141,17 +141,25 @@
 /**
  * @brief: Function to clean up the children of a sync object
  * @param list_to_clean : List to clean up
+ * @list_clean_type     : Clean specific object or clean all objects
+ * @sync_obj            : Sync object to be clean if list clean type is
+ *                         SYNC_LIST_CLEAN_ID
  *
  * @return None
  */
-void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean);
+void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean,
+	uint32_t list_clean_type, uint32_t sync_obj);
 
 /**
  * @brief: Function to clean up the parents of a sync object
  * @param list_to_clean : List to clean up
+ * @list_clean_type     : Clean specific object or clean all objects
+ * @sync_obj            : Sync object to be clean if list clean type is
+ *                         SYNC_LIST_CLEAN_ID
  *
  * @return None
  */
-void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean);
+void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean,
+	uint32_t list_clean_type, uint32_t sync_obj);
 
 #endif /* __CAM_SYNC_UTIL_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 611c4e9..07fb944 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -410,6 +410,13 @@
 
 	of_node = soc_info->dev->of_node;
 
+	if (!of_property_read_bool(of_node, "use-shared-clk")) {
+		CAM_DBG(CAM_UTIL, "No shared clk parameter defined");
+		soc_info->use_shared_clk = false;
+	} else {
+		soc_info->use_shared_clk = true;
+	}
+
 	count = of_property_count_strings(of_node, "clock-names");
 
 	CAM_DBG(CAM_UTIL, "count = %d", count);
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 5123ec4..4a87d50 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -180,6 +180,7 @@
 	struct regulator               *rgltr[CAM_SOC_MAX_REGULATOR];
 	uint32_t                        rgltr_delay[CAM_SOC_MAX_REGULATOR];
 
+	uint32_t                        use_shared_clk;
 	uint32_t                        num_clk;
 	const char                     *clk_name[CAM_SOC_MAX_CLK];
 	struct clk                     *clk[CAM_SOC_MAX_CLK];