Browse Source

msm: camera: common: Add support for cesta based clk scaling

On chipsets having cesta hw block support, for cesta supported clks
clk frequency can be changed during veritcal blanking based on
CSID DRV events. For this to happen, camera clients need to setup
high and low clock votes through hw clients. Use corresponding clk,
crm APIs to setup high, low clk frquencies and do channel switch
to apply newly set rates. Clients can also set clk frequency through
sw client which will set the floor. This feature helps in saving
power for usecases where vertical blanking is high such as
Fast Shutter usecase.

CRs-Fixed: 3294948
Change-Id: I1bcf650b439991a23b2a0f0f9a5162bdcd60dc64
Signed-off-by: Mukund Madhusudan Atre <[email protected]>
Signed-off-by: Pavan Kumar Chilamkurthi <[email protected]>
Mukund Madhusudan Atre 2 years ago
parent
commit
b2def29ddc
56 changed files with 2208 additions and 713 deletions
  1. 6 7
      drivers/cam_cdm/cam_cdm_hw_core.c
  2. 508 249
      drivers/cam_cpas/cam_cpas_hw.c
  3. 11 17
      drivers/cam_cpas/cam_cpas_hw.h
  4. 22 4
      drivers/cam_cpas/cam_cpas_intf.c
  5. 169 22
      drivers/cam_cpas/cam_cpas_soc.c
  6. 6 4
      drivers/cam_cpas/cam_cpas_soc.h
  7. 4 3
      drivers/cam_cpas/cpas_top/cam_cpastop_hw.c
  8. 27 2
      drivers/cam_cpas/include/cam_cpas_api.h
  9. 3 2
      drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.c
  10. 4 3
      drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.c
  11. 3 2
      drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c
  12. 4 3
      drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c
  13. 6 5
      drivers/cam_icp/icp_hw/bps_hw/bps_soc.c
  14. 3 3
      drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.c
  15. 6 5
      drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c
  16. 5 5
      drivers/cam_icp/icp_hw/ofe_hw/ofe_soc.c
  17. 60 16
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
  18. 4 0
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
  19. 5 5
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c
  20. 166 23
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c
  21. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.h
  22. 15 3
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
  23. 4 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
  24. 4 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
  25. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h
  26. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
  27. 4 3
      drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c
  28. 14 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c
  29. 102 50
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c
  30. 3 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c
  31. 1 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c
  32. 6 5
      drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c
  33. 16 5
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
  34. 1 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c
  35. 73 42
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c
  36. 2 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h
  37. 2 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
  38. 2 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c
  39. 16 3
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c
  40. 3 2
      drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c
  41. 3 2
      drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c
  42. 4 3
      drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c
  43. 2 2
      drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c
  44. 6 5
      drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c
  45. 61 0
      drivers/cam_req_mgr/cam_subdev.h
  46. 3 3
      drivers/cam_sensor_module/cam_cci/cam_cci_soc.c
  47. 134 47
      drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
  48. 124 0
      drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
  49. 6 0
      drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
  50. 49 19
      drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
  51. 1 1
      drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
  52. 4 4
      drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
  53. 5 3
      drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c
  54. 2 1
      drivers/cam_utils/cam_common_util.c
  55. 396 102
      drivers/cam_utils/cam_soc_util.c
  56. 112 19
      drivers/cam_utils/cam_soc_util.h

+ 6 - 7
drivers/cam_cdm/cam_cdm_hw_core.c

@@ -1908,7 +1908,7 @@ int cam_hw_cdm_get_cdm_config(struct cam_hw_info *cdm_hw)
 
 	core = (struct cam_cdm *)cdm_hw->core_info;
 	soc_info = &cdm_hw->soc_info;
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 			CAM_SVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_CDM, "Enable platform failed for dev %s",
@@ -1983,8 +1983,7 @@ int cam_hw_cdm_get_cdm_config(struct cam_hw_info *cdm_hw)
 	}
 
 disable_platform_resource:
-	ret = cam_soc_util_disable_platform_resource(soc_info, true, true);
-
+	ret = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (ret) {
 		CAM_ERR(CAM_CDM, "disable platform failed for dev %s",
 				soc_info->dev_name);
@@ -2012,7 +2011,7 @@ int cam_hw_cdm_init(void *hw_priv,
 	soc_info = &cdm_hw->soc_info;
 	cdm_core = (struct cam_cdm *)cdm_hw->core_info;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_CDM, "Enable platform failed for %s%d",
@@ -2054,7 +2053,7 @@ disable_return:
 	flags = cam_hw_util_hw_lock_irqsave(cdm_hw);
 	cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 	cam_hw_util_hw_unlock_irqrestore(cdm_hw, flags);
-	cam_soc_util_disable_platform_resource(soc_info, true, true);
+	cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 end:
 	return rc;
 }
@@ -2102,7 +2101,7 @@ int cam_hw_cdm_pf_deinit(void *hw_priv,
 	cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 	cam_hw_util_hw_unlock_irqrestore(cdm_hw, flags);
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc)
 		CAM_ERR(CAM_CDM, "disable platform failed for %s%u",
 			soc_info->label_name, soc_info->index);
@@ -2178,7 +2177,7 @@ int cam_hw_cdm_deinit(void *hw_priv,
 	flags = cam_hw_util_hw_lock_irqsave(cdm_hw);
 	cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 	cam_hw_util_hw_unlock_irqrestore(cdm_hw, flags);
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc) {
 		CAM_ERR(CAM_CDM, "disable platform failed for %s%u",
 			soc_info->label_name, soc_info->index);

File diff suppressed because it is too large
+ 508 - 249
drivers/cam_cpas/cam_cpas_hw.c


+ 11 - 17
drivers/cam_cpas/cam_cpas_hw.h

@@ -68,14 +68,6 @@ enum cam_cpas_access_type {
 	CAM_REG_TYPE_READ_WRITE,
 };
 
-/**
- * enum cam_cpas_vote_type - Enum for cpas vote type
- */
-enum cam_cpas_vote_type {
-	CAM_CPAS_VOTE_TYPE_HLOS,
-	CAM_CPAS_VOTE_TYPE_DRV,
-};
-
 /**
  * struct cam_cpas_vdd_ahb_mapping : Voltage to ahb level mapping
  *
@@ -91,13 +83,15 @@ struct cam_cpas_vdd_ahb_mapping {
 /**
  * struct cam_cpas_bw_vote : AXI bw vote
  *
- * @ab: AB bw value
- * @ib: IB bw value
+ * @ab:     AB bw value
+ * @ib:     IB bw value
+ * @camnoc: CAMNOC bw value
  *
  */
 struct cam_cpas_bw_vote {
 	uint64_t ab;
 	uint64_t ib;
+	uint64_t camnoc;
 };
 
 /**
@@ -237,7 +231,6 @@ struct cam_cpas_bus_client {
  * @cam_rsc_dev: Cam RSC device for DRV
  * @is_drv_started: Indicates if DRV started for RSC device corresponding to port
  * @curr_bw: Current voted bw after cpas consolidation
- * @camnoc_bw: CAMNOC bw value for this port
  * @additional_bw: Additional bandwidth to cover non-hw cpas clients
  * @applied_bw: Actual applied bw to port
  */
@@ -251,7 +244,6 @@ struct cam_cpas_axi_port {
 	const struct device *cam_rsc_dev;
 	bool is_drv_started;
 	struct cam_cpas_axi_bw_info curr_bw;
-	uint64_t camnoc_bw;
 	uint64_t additional_bw;
 	struct cam_cpas_axi_bw_info applied_bw;
 };
@@ -277,10 +269,10 @@ struct cam_cpas_axi_port_debug_info {
  * struct cam_cpas_monitor : CPAS monitor array
  *
  * @timestamp: Timestamp at which this monitor entry is saved
- * @axi_info: AXI port information
  * @identifier_string: String passed by caller
  * @identifier_value: Identifier value passed by caller
- * @applied_camnoc_clk: Applied camnoc axi clock rate
+ * @axi_info: AXI port information
+ * @applied_camnoc_clk: Applied camnoc axi clock rate with sw, hw clients
  * @applied_ahb_level: Applied camcc ahb level
  * @fe_ddr: RPMH DDR BCM FE (front-end) status register value.
  *          This indicates requested clock plan
@@ -304,7 +296,7 @@ struct cam_cpas_monitor {
 	char                identifier_string[128];
 	int32_t             identifier_value;
 	struct cam_cpas_axi_port_debug_info axi_info[CAM_CPAS_MAX_AXI_PORTS];
-	uint64_t            applied_camnoc_clk;
+	struct cam_soc_util_clk_rates       applied_camnoc_clk;
 	unsigned int        applied_ahb_level;
 	uint32_t            fe_ddr;
 	uint32_t            be_ddr;
@@ -343,7 +335,7 @@ struct cam_cpas_monitor {
  * @irq_count_wq: wait variable to ensure all irq's are handled
  * @dentry: debugfs file entry
  * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus
- * @applied_camnoc_axi_rate: applied camnoc axi clock rate
+ * @applied_camnoc_axi_rate: applied camnoc axi clock rate through sw, hw clients
  * @monitor_head: Monitor array head
  * @monitor_entries: cpas monitor array
  * @camnoc_info: Pointer to camnoc header info
@@ -353,6 +345,7 @@ struct cam_cpas_monitor {
  *                    config issues
  * @smmu_fault_handled: Handled address decode error, on fault at SMMU
  * @force_hlos_drv: Whether to force disable DRV voting
+ * @force_cesta_sw_client: Whether to force voting through cesta sw client
  */
 struct cam_cpas {
 	struct cam_cpas_hw_caps hw_caps;
@@ -375,7 +368,7 @@ struct cam_cpas {
 	wait_queue_head_t irq_count_wq;
 	struct dentry *dentry;
 	bool ahb_bus_scaling_disable;
-	uint64_t applied_camnoc_axi_rate;
+	struct cam_soc_util_clk_rates applied_camnoc_axi_rate;
 	atomic64_t  monitor_head;
 	struct cam_cpas_monitor monitor_entries[CAM_CPAS_MONITOR_MAX_ENTRIES];
 	void *camnoc_info;
@@ -384,6 +377,7 @@ struct cam_cpas {
 	bool slave_err_irq_en;
 	bool smmu_fault_handled;
 	bool force_hlos_drv;
+	bool force_cesta_sw_client;
 };
 
 int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops);

+ 22 - 4
drivers/cam_cpas/cam_cpas_intf.c

@@ -158,7 +158,20 @@ const char *cam_cpas_axi_util_drv_vote_lvl_to_string(
 }
 EXPORT_SYMBOL(cam_cpas_axi_util_drv_vote_lvl_to_string);
 
-int cam_cpas_query_drv_enable(bool *is_drv_enabled)
+const char *cam_cpas_util_vote_type_to_string(enum cam_cpas_vote_type vote_type)
+{
+	switch (vote_type) {
+	case CAM_CPAS_VOTE_TYPE_HLOS:
+		return "VOTE_TYPE_HLOS";
+	case CAM_CPAS_VOTE_TYPE_DRV:
+		return "VOTE_TYPE_DRV";
+	default:
+		return "VOTE_TYPE_INVALID";
+	}
+}
+EXPORT_SYMBOL(cam_cpas_util_vote_type_to_string);
+
+int cam_cpas_query_drv_enable(bool *is_ddr_drv_enabled, bool *is_clk_drv_enabled)
 {
 	struct cam_hw_info *cpas_hw = NULL;
 	struct cam_cpas_private_soc *soc_private = NULL;
@@ -168,15 +181,20 @@ int cam_cpas_query_drv_enable(bool *is_drv_enabled)
 		return -ENODEV;
 	}
 
-	if (!is_drv_enabled) {
-		CAM_ERR(CAM_CPAS, "invalid input %pK", is_drv_enabled);
+	if (!is_ddr_drv_enabled && !is_clk_drv_enabled) {
+		CAM_ERR(CAM_CPAS, "invalid input ddr: %pK clk: %pK", is_ddr_drv_enabled,
+			is_clk_drv_enabled);
 		return -EINVAL;
 	}
 
 	cpas_hw = (struct cam_hw_info  *) g_cpas_intf->hw_intf->hw_priv;
 	soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
 
-	*is_drv_enabled = soc_private->enable_cam_ddr_drv;
+	if (is_ddr_drv_enabled)
+		*is_ddr_drv_enabled = soc_private->enable_cam_ddr_drv;
+
+	if (is_clk_drv_enabled)
+		*is_clk_drv_enabled = soc_private->enable_cam_clk_drv;
 
 	return 0;
 }

+ 169 - 22
drivers/cam_cpas/cam_cpas_soc.c

@@ -24,27 +24,147 @@ module_param(cpas_dump, uint, 0644);
 
 #define CAM_ICP_CLK_NAME "cam_icp_clk"
 
-void cam_cpas_dump_tree_vote_info(const struct cam_cpas_tree_node *tree_node,
-	const char *identifier, int drv_voting_idx)
+void cam_cpas_dump_tree_vote_info(struct cam_hw_info *cpas_hw,
+	const struct cam_cpas_tree_node *tree_node,
+	const char *identifier, int ddr_drv_idx, int cesta_drv_idx)
 {
-	if (!cpas_dump)
+	struct cam_cpas_private_soc *soc_private =
+		(struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
+
+	if ((cpas_dump & BIT(0)) == 0)
 		return;
 
-	if (tree_node->bw_info[drv_voting_idx].vote_type == CAM_CPAS_VOTE_TYPE_DRV)
+	if (cesta_drv_idx > CAM_CPAS_PORT_HLOS_DRV)
+		CAM_INFO(CAM_PERF,
+			"%s node:%s lvl:%d cesta_drv_idx:%d DRV BW camnoc[%llu %llu]",
+			identifier, tree_node->node_name, tree_node->level_idx, cesta_drv_idx,
+			tree_node->bw_info[cesta_drv_idx].drv_vote.high.camnoc,
+			tree_node->bw_info[cesta_drv_idx].drv_vote.low.camnoc);
+	else
+		CAM_INFO(CAM_PERF,
+			"%s node:%s lvl:%d cesta_drv_idx:%d HLOS BW camnoc[%llu]",
+			identifier, tree_node->node_name, tree_node->level_idx, cesta_drv_idx,
+			tree_node->bw_info[cesta_drv_idx].hlos_vote.camnoc);
+
+	if (ddr_drv_idx > CAM_CPAS_PORT_HLOS_DRV)
 		CAM_INFO(CAM_PERF,
-			"%s node:%s lvl:%d drv_idx:%d DRV BW camnoc[%llu] ab[%llu %llu] ib[%llu %llu]",
-			identifier, tree_node->node_name, tree_node->level_idx, drv_voting_idx,
-			tree_node->camnoc_bw, tree_node->bw_info[drv_voting_idx].drv_vote.high.ab,
-			tree_node->bw_info[drv_voting_idx].drv_vote.low.ab,
-			tree_node->bw_info[drv_voting_idx].drv_vote.high.ib,
-			tree_node->bw_info[drv_voting_idx].drv_vote.low.ib);
+			"%s node:%s lvl:%d ddr_drv_idx:%d DRV BW ab[%llu %llu] ib[%llu %llu]",
+			identifier, tree_node->node_name, tree_node->level_idx, ddr_drv_idx,
+			tree_node->bw_info[ddr_drv_idx].drv_vote.high.ab,
+			tree_node->bw_info[ddr_drv_idx].drv_vote.low.ab,
+			tree_node->bw_info[ddr_drv_idx].drv_vote.high.ib,
+			tree_node->bw_info[ddr_drv_idx].drv_vote.low.ib);
 	else
 		CAM_INFO(CAM_PERF,
-			"%s node:%s lvl:%d drv_idx:%d HLOS BW camnoc[%llu] ab[%llu] ib[%llu]",
-			identifier, tree_node->node_name, tree_node->level_idx, drv_voting_idx,
-			tree_node->camnoc_bw, tree_node->bw_info[drv_voting_idx].hlos_vote.ab,
-			tree_node->bw_info[drv_voting_idx].hlos_vote.ib);
+			"%s node:%s lvl:%d ddr_drv_idx:%d HLOS BW ab[%llu] ib[%llu]",
+			identifier, tree_node->node_name, tree_node->level_idx, ddr_drv_idx,
+			tree_node->bw_info[ddr_drv_idx].hlos_vote.ab,
+			tree_node->bw_info[ddr_drv_idx].hlos_vote.ib);
+
+	if (soc_private->enable_cam_ddr_drv) {
+		int i;
+
+		CAM_INFO(CAM_PERF,
+			"%s node:%s lvl:%d drv_idx:%d cesta_drv_idx:%d ==== printing full node state",
+			identifier, tree_node->node_name, tree_node->level_idx,
+			ddr_drv_idx, cesta_drv_idx);
+
+		for (i = 0; i < CAM_CPAS_MAX_DRV_PORTS; i++) {
+
+			if (i == CAM_CPAS_PORT_HLOS_DRV)
+				CAM_INFO(CAM_PERF,
+					"idx[%d] HLOS camnoc[%llu], DDR ab[%llu] ib[%llu]",
+					i,
+					tree_node->bw_info[i].hlos_vote.camnoc,
+					tree_node->bw_info[i].hlos_vote.ab,
+					tree_node->bw_info[i].hlos_vote.ib);
+			else
+				CAM_INFO(CAM_PERF,
+					"idx[%d] DRV camnoc[%llu %llu], DDR ab[%llu %llu] ib[%llu %llu]",
+					i,
+					tree_node->bw_info[i].drv_vote.high.camnoc,
+					tree_node->bw_info[i].drv_vote.low.camnoc,
+					tree_node->bw_info[i].drv_vote.high.ab,
+					tree_node->bw_info[i].drv_vote.low.ab,
+					tree_node->bw_info[i].drv_vote.high.ib,
+					tree_node->bw_info[i].drv_vote.low.ib);
+		}
+	}
+
+}
+
+void cam_cpas_dump_full_tree_state(struct cam_hw_info *cpas_hw, const char *identifier)
+{
+	int j;
+	struct cam_cpas_private_soc *soc_private =
+		(struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
+	struct cam_cpas_tree_node *curr_node;
+
+	if ((cpas_dump & BIT(1)) == 0)
+		return;
+
+	CAM_INFO(CAM_CPAS, "Dumping cpas tree full state start ============== %s", identifier);
+
+	/* This will traverse through all nodes in the tree and print stats*/
+	for (j = 0; j < CAM_CPAS_MAX_TREE_NODES; j++) {
+		if (!soc_private->tree_node[j])
+			continue;
+
+		curr_node = soc_private->tree_node[j];
 
+		if (soc_private->enable_cam_ddr_drv) {
+			int i;
+
+			CAM_INFO(CAM_PERF,
+				"Identifier[%s] node:[%s] cell:%d lvl:%d PortIdx mnoc[%d %d %d %d] camnoc[%d] camnoc_max %d, bus_width:%d, drv_idx:%d",
+				identifier, curr_node->node_name, curr_node->cell_idx,
+				curr_node->level_idx,
+				curr_node->axi_port_idx_arr[CAM_CPAS_PORT_HLOS_DRV],
+				curr_node->axi_port_idx_arr[CAM_CPAS_PORT_DRV_0],
+				curr_node->axi_port_idx_arr[CAM_CPAS_PORT_DRV_1],
+				curr_node->axi_port_idx_arr[CAM_CPAS_PORT_DRV_2],
+				curr_node->camnoc_axi_port_idx,
+				curr_node->camnoc_max_needed,
+				curr_node->bus_width_factor,
+				curr_node->drv_voting_idx);
+
+			for (i = 0; i < CAM_CPAS_MAX_DRV_PORTS; i++) {
+				if (i == CAM_CPAS_PORT_HLOS_DRV)
+					CAM_INFO(CAM_PERF,
+						"    idx[%d] HLOS camnoc[%llu], DDR ab[%llu] ib[%llu]",
+						i,
+						curr_node->bw_info[i].hlos_vote.camnoc,
+						curr_node->bw_info[i].hlos_vote.ab,
+						curr_node->bw_info[i].hlos_vote.ib);
+				else
+					CAM_INFO(CAM_PERF,
+						"    idx[%d] DRV camnoc[%llu %llu], DDR ab[%llu %llu] ib[%llu %llu]",
+						i,
+						curr_node->bw_info[i].drv_vote.high.camnoc,
+						curr_node->bw_info[i].drv_vote.low.camnoc,
+						curr_node->bw_info[i].drv_vote.high.ab,
+						curr_node->bw_info[i].drv_vote.low.ab,
+						curr_node->bw_info[i].drv_vote.high.ib,
+						curr_node->bw_info[i].drv_vote.low.ib);
+			}
+		} else {
+			CAM_INFO(CAM_CPAS,
+				"[%s] Cell[%d] level[%d] PortIdx[%d][%d] camnoc_bw[%d %d %lld %lld] mnoc_bw[%lld %lld]",
+				curr_node->node_name, curr_node->cell_idx,
+				curr_node->level_idx,
+				curr_node->axi_port_idx_arr[CAM_CPAS_PORT_HLOS_DRV],
+				curr_node->camnoc_axi_port_idx,
+				curr_node->camnoc_max_needed,
+				curr_node->bus_width_factor,
+				curr_node->bw_info[CAM_CPAS_PORT_HLOS_DRV].hlos_vote.camnoc,
+				curr_node->bw_info[CAM_CPAS_PORT_HLOS_DRV].hlos_vote.camnoc *
+				curr_node->bus_width_factor,
+				curr_node->bw_info[CAM_CPAS_PORT_HLOS_DRV].hlos_vote.ab,
+				curr_node->bw_info[CAM_CPAS_PORT_HLOS_DRV].hlos_vote.ib);
+		}
+	}
+
+	CAM_INFO(CAM_CPAS, "Dumping cpas tree full state end ============== %s", identifier);
 }
 
 void cam_cpas_dump_axi_vote_info(
@@ -54,7 +174,7 @@ void cam_cpas_dump_axi_vote_info(
 {
 	int i;
 
-	if (!cpas_dump)
+	if ((cpas_dump & BIT(0)) == 0)
 		return;
 
 	if (!axi_vote || (axi_vote->num_paths >
@@ -85,7 +205,7 @@ void cam_cpas_util_debug_parse_data(
 	int i, j;
 	struct cam_cpas_tree_node *curr_node = NULL;
 
-	if (!cpas_dump)
+	if ((cpas_dump & BIT(0)) == 0)
 		return;
 
 	for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) {
@@ -110,8 +230,8 @@ void cam_cpas_util_debug_parse_data(
 			curr_node->path_trans_type), curr_node->drv_voting_idx);
 
 		for (j = 0; j < CAM_CPAS_PATH_DATA_MAX; j++) {
-			CAM_INFO(CAM_CPAS, "Constituent path: %d",
-				curr_node->constituent_paths[j] ? j : -1);
+			if (curr_node->constituent_paths[j])
+				CAM_INFO(CAM_CPAS, "Constituent path: %d", j);
 		}
 	}
 
@@ -609,9 +729,11 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
 							client_name, curr_node_ptr->drv_voting_idx);
 				}
 
-				CAM_DBG(CAM_CPAS, "Client Node Added: %d %d %s %d",
+				CAM_DBG(CAM_CPAS,
+					"Node Added: Client[%s] DataType[%d] TransType[%d] DRV idx[%d]",
+					client_name,
 					curr_node_ptr->path_data_type,
-					curr_node_ptr->path_trans_type, client_name,
+					curr_node_ptr->path_trans_type,
 					curr_node_ptr->drv_voting_idx);
 			}
 
@@ -1462,6 +1584,25 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
 	if (cam_drv_en_mask_val & CAM_DDR_DRV)
 		soc_private->enable_cam_ddr_drv = true;
 
+	if (cam_drv_en_mask_val & CAM_CLK_DRV) {
+		if (!soc_private->enable_cam_ddr_drv) {
+			CAM_ERR(CAM_CPAS, "DDR DRV needs to be enabled for Clock DRV");
+			rc = -EPERM;
+			goto cleanup_clients;
+		}
+
+		soc_private->enable_cam_clk_drv = true;
+		rc = cam_soc_util_cesta_populate_crm_device();
+		if (rc) {
+			CAM_ERR(CAM_CPAS, "Failed to populate camera cesta crm device rc: %d", rc);
+			goto cleanup_clients;
+		}
+	}
+
+	CAM_DBG(CAM_CPAS, "enable_cam_ddr_drv %d enable_cam_clk_drv %d cam_drv_en_mask_val %d",
+		soc_private->enable_cam_ddr_drv, soc_private->enable_cam_clk_drv,
+		cam_drv_en_mask_val);
+
 	rc = cam_cpas_parse_node_tree(cpas_core, of_node, soc_private);
 	if (rc) {
 		CAM_ERR(CAM_CPAS, "Node tree parsing failed rc: %d", rc);
@@ -1593,6 +1734,8 @@ int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info,
 
 	soc_private = (struct cam_cpas_private_soc *)soc_info->soc_private;
 
+	soc_info->is_clk_drv_en = soc_private->enable_cam_clk_drv;
+
 	rc = cam_soc_util_get_option_clk_by_name(soc_info, CAM_ICP_CLK_NAME,
 		&soc_private->icp_clk_index);
 	if (rc) {
@@ -1653,9 +1796,13 @@ int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info)
 int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info,
 	enum cam_vote_level default_level)
 {
+	struct cam_cpas_private_soc *soc_private = soc_info->soc_private;
 	int rc = 0;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	/* set this everytime in order to support debugfs to disable clk drv between runs */
+	soc_info->is_clk_drv_en = soc_private->enable_cam_clk_drv;
+
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		default_level, true);
 	if (rc)
 		CAM_ERR(CAM_CPAS, "enable platform resource failed, rc=%d", rc);
@@ -1668,7 +1815,7 @@ int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info,
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info,
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX,
 		disable_clocks, disable_irq);
 	if (rc)
 		CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc);

+ 6 - 4
drivers/cam_cpas/cam_cpas_soc.h

@@ -28,7 +28,6 @@
  * @path_trans_type: Transaction type info from device tree (rd, wr)
  * @merge_type: Traffic merge type (calculation info) from device tree
  * @bus_width_factor: Factor for accounting bus width in CAMNOC bw calculation
- * @camnoc_bw: CAMNOC bw value at current node
  * @bw_info: AXI BW info for all drv ports
  * @camnoc_max_needed: If node is needed for CAMNOC BW calculation then true
  * @constituent_paths: Constituent paths presence info from device tree
@@ -60,7 +59,6 @@ struct cam_cpas_tree_node {
 	uint32_t path_trans_type;
 	uint32_t merge_type;
 	uint32_t bus_width_factor;
-	uint64_t camnoc_bw;
 	struct cam_cpas_axi_bw_info *bw_info;
 	bool camnoc_max_needed;
 	bool constituent_paths[CAM_CPAS_PATH_DATA_MAX];
@@ -210,6 +208,7 @@ struct cam_cpas_domain_id_support_clks {
  * @llcc_info: Cache info
  * @enable_smart_qos: Whether to enable Smart QoS mechanism on current chipset
  * @enable_cam_ddr_drv: Whether to enable Camera DDR DRV on current chipset
+ * @enable_cam_clk_drv: Whether to enable Camera Clk DRV on current chipset
  * @smart_qos_info: Pointer to smart qos info
  * @icp_clk_index: Index of optional icp clk
  * @domain_id_info: Stores all information related to domain id support
@@ -238,14 +237,17 @@ struct cam_cpas_private_soc {
 	struct cam_sys_cache_info *llcc_info;
 	bool enable_smart_qos;
 	bool enable_cam_ddr_drv;
+	bool enable_cam_clk_drv;
 	struct cam_cpas_smart_qos_info *smart_qos_info;
 	int32_t icp_clk_index;
 	struct cam_cpas_domain_id_info domain_id_info;
 	struct cam_cpas_domain_id_support_clks *domain_id_clks;
 };
 
-void cam_cpas_dump_tree_vote_info(const struct cam_cpas_tree_node *tree_node,
-	const char *identifier, int drv_voting_idx);
+void cam_cpas_dump_tree_vote_info(struct cam_hw_info *cpas_hw,
+	const struct cam_cpas_tree_node *tree_node,
+	const char *identifier, int ddr_drv_idx, int cesta_drv_idx);
+void cam_cpas_dump_full_tree_state(struct cam_hw_info *cpas_hw, const char *identifier);
 
 void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);
 void cam_cpas_dump_axi_vote_info(

+ 4 - 3
drivers/cam_cpas/cpas_top/cam_cpastop_hw.c

@@ -957,8 +957,8 @@ static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw,
 			CAM_ERR(CAM_CPAS,
 				"ICP clock not added as optional clk, qchannel handshake will fail");
 		} else {
-			ret = cam_soc_util_clk_enable(soc_info, true, soc_private->icp_clk_index,
-				-1, NULL);
+			ret = cam_soc_util_clk_enable(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+				soc_private->icp_clk_index, -1);
 			if (ret)
 				CAM_ERR(CAM_CPAS, "Error enable icp clk failed rc=%d", ret);
 			else
@@ -1010,7 +1010,8 @@ static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw,
 		rc = -EBUSY;
 
 	if (icp_clk_enabled) {
-		ret = cam_soc_util_clk_disable(soc_info, true, soc_private->icp_clk_index);
+		ret = cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+			soc_private->icp_clk_index);
 		if (ret)
 			CAM_ERR(CAM_CPAS, "Error disable icp clk failed rc=%d", rc);
 	}

+ 27 - 2
drivers/cam_cpas/include/cam_cpas_api.h

@@ -24,10 +24,22 @@
 #define CAM_CPAS_MAX_PATHS_PER_CLIENT 15
 #define CAM_CPAS_API_PATH_DATA_STD_START 512
 
+#define CAM_CPAS_VOTE_LEVEL_NONE 0
+#define CAM_CPAS_VOTE_LEVEL_MAX 3
+
 /* Qos Selection mask */
 #define CAM_CPAS_QOS_DEFAULT_SETTINGS_MASK 0x1
 #define CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK  0x2
 
+/**
+ * enum cam_cpas_vote_type - Enum for cpas vote type
+ */
+enum cam_cpas_vote_type {
+	CAM_CPAS_VOTE_TYPE_HLOS,
+	CAM_CPAS_VOTE_TYPE_DRV,
+	CAM_CPAS_VOTE_TYPE_MAX,
+};
+
 /**
  * enum cam_cpas_reg_base - Enum for register base identifier. These
  *                          are the identifiers used in generic register
@@ -773,6 +785,18 @@ const char *cam_cpas_axi_util_trans_type_to_string(
 const char *cam_cpas_axi_util_drv_vote_lvl_to_string(
 	uint32_t vote_lvl);
 
+/**
+ * cam_cpas_util_vote_type_to_string()
+ *
+ * @brief: API to get string for given vote type
+ *
+ * @vote_type  : DRV vote level
+ *
+ * @return string.
+ *
+ */
+const char *cam_cpas_util_vote_type_to_string(enum cam_cpas_vote_type vote_type);
+
 /**
  * cam_cpas_log_votes()
  *
@@ -892,12 +916,13 @@ int cam_cpas_csid_process_resume(uint32_t csid_idx);
  * cam_cpas_query_drv_enable()
  *
  * @brief: API to indicate DRV enabled on hw or not
- * @is_drv_enabled: Indication to be set by the API
+ * @is_ddr_drv_enabled: If DDR DRV enabled
+ * @is_clk_drv_enabled: If Clock Cesta DRV enabled
  *
  * @return 0 on success
  *
  */
-int cam_cpas_query_drv_enable(bool *is_drv_enabled);
+int cam_cpas_query_drv_enable(bool *is_ddr_drv_enabled, bool *is_clk_drv_enabled);
 
 /**
  * cam_cpas_query_domain_id_security_support()

+ 3 - 2
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/of.h>
@@ -478,7 +479,7 @@ int cam_cre_process_cmd(void *device_priv, uint32_t cmd_type,
 			(struct cam_cre_dev_clk_update *)cmd_args;
 
 		if (!core_info->clk_enable) {
-			rc = cam_soc_util_clk_enable_default(soc_info,
+			rc = cam_soc_util_clk_enable_default(soc_info, CAM_CLK_SW_CLIENT_IDX,
 				CAM_SVS_VOTE);
 			if (rc) {
 				CAM_ERR(CAM_CRE, "Clock enable is failed");
@@ -494,7 +495,7 @@ int cam_cre_process_cmd(void *device_priv, uint32_t cmd_type,
 		break;
 	case CRE_HW_CLK_DISABLE: {
 		if (core_info->clk_enable)
-			cam_soc_util_clk_disable_default(soc_info);
+			cam_soc_util_clk_disable_default(soc_info, CAM_CLK_SW_CLIENT_IDX);
 
 		core_info->clk_enable = false;
 		}

+ 4 - 3
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -35,7 +36,7 @@ int cam_cre_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, true);
 	if (rc)
 		CAM_ERR(CAM_CRE, "enable platform failed %d", rc);
@@ -47,7 +48,7 @@ int cam_cre_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc)
 		CAM_ERR(CAM_CRE, "disable platform failed %d", rc);
 
@@ -79,5 +80,5 @@ int cam_cre_update_clk_rate(struct cam_hw_soc_info *soc_info,
 
 	CAM_DBG(CAM_CRE, "clk_rate = %u src_clk_index = %d",
 		clk_rate, src_clk_idx);
-	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
 }

+ 3 - 2
drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -130,7 +131,7 @@ int cam_custom_hw_sub_mod_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_LOWSVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_CUSTOM, "Error! enable platform failed rc=%d", rc);
@@ -158,7 +159,7 @@ int cam_custom_hw_sub_mod_disable_soc_resources(
 	}
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc) {
 		CAM_ERR(CAM_CUSTOM, "Disable platform failed rc=%d", rc);
 		return rc;

+ 4 - 3
drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/device.h>
@@ -130,8 +131,8 @@ int cam_fd_soc_enable_resources(struct cam_hw_soc_info *soc_info)
 		return -EFAULT;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_SVS_VOTE,
-		true);
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+		CAM_SVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_FD, "Error enable platform failed, rc=%d", rc);
 		goto stop_cpas;
@@ -158,7 +159,7 @@ int cam_fd_soc_disable_resources(struct cam_hw_soc_info *soc_info)
 	}
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc) {
 		CAM_ERR(CAM_FD, "disable platform resources failed, rc=%d", rc);
 		return rc;

+ 6 - 5
drivers/cam_icp/icp_hw/bps_hw/bps_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -65,7 +66,7 @@ int cam_bps_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, false);
 	if (rc)
 		CAM_ERR(CAM_ICP, "enable platform failed");
@@ -78,7 +79,7 @@ int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info,
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk,
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, disable_clk,
 		false);
 	if (rc)
 		CAM_ERR(CAM_ICP, "disable platform failed");
@@ -155,7 +156,7 @@ int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info,
 		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
 	}
 
-	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
 }
 
 int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
@@ -163,9 +164,9 @@ int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
 	int rc = 0;
 
 	if (clk_enable)
-		rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE);
+		rc = cam_soc_util_clk_enable_default(soc_info, CAM_CLK_SW_CLIENT_IDX, CAM_SVS_VOTE);
 	else
-		cam_soc_util_clk_disable_default(soc_info);
+		cam_soc_util_clk_disable_default(soc_info, CAM_CLK_SW_CLIENT_IDX);
 
 	return rc;
 }

+ 3 - 3
drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.c

@@ -181,7 +181,7 @@ int cam_icp_soc_resources_enable(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, true);
 	if (rc)
 		CAM_ERR(CAM_ICP, "failed to enable soc resources rc=%d", rc);
@@ -193,7 +193,7 @@ int cam_icp_soc_resources_disable(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc)
 		CAM_ERR(CAM_ICP, "failed to disable soc resources rc=%d", rc);
 
@@ -242,7 +242,7 @@ int cam_icp_soc_update_clk_rate(struct cam_hw_soc_info *soc_info,
 		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
 	}
 
-	rc = cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+	rc = cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
 	if (rc)
 		return rc;
 

+ 6 - 5
drivers/cam_icp/icp_hw/ipe_hw/ipe_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -116,7 +117,7 @@ int cam_ipe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, false);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "enable platform failed");
@@ -131,7 +132,7 @@ int cam_ipe_disable_soc_resources(struct cam_hw_soc_info *soc_info,
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk,
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, disable_clk,
 		false);
 	if (rc)
 		CAM_ERR(CAM_ICP, "enable platform failed");
@@ -158,7 +159,7 @@ int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info,
 		*clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
 	}
 
-	return cam_soc_util_set_src_clk_rate(soc_info, *clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, *clk_rate, 0);
 }
 
 int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
@@ -166,9 +167,9 @@ int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
 	int rc = 0;
 
 	if (clk_enable)
-		rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE);
+		rc = cam_soc_util_clk_enable_default(soc_info, CAM_CLK_SW_CLIENT_IDX, CAM_SVS_VOTE);
 	else
-		cam_soc_util_clk_disable_default(soc_info);
+		cam_soc_util_clk_disable_default(soc_info, CAM_CLK_SW_CLIENT_IDX);
 
 	return rc;
 }

+ 5 - 5
drivers/cam_icp/icp_hw/ofe_hw/ofe_soc.c

@@ -66,7 +66,7 @@ int cam_ofe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX,
 		true, CAM_SVS_VOTE, false);
 	if (rc)
 		CAM_ERR(CAM_ICP, "enable platform failed");
@@ -79,7 +79,7 @@ int cam_ofe_disable_soc_resources(struct cam_hw_soc_info *soc_info,
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info,
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX,
 		disable_clk, false);
 	if (rc)
 		CAM_ERR(CAM_ICP, "disable platform failed");
@@ -141,7 +141,7 @@ int cam_ofe_update_clk_rate(struct cam_hw_soc_info *soc_info,
 		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
 	}
 
-	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
 }
 
 int cam_ofe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
@@ -149,9 +149,9 @@ int cam_ofe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
 	int rc = 0;
 
 	if (clk_enable)
-		rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE);
+		rc = cam_soc_util_clk_enable_default(soc_info, CAM_CLK_SW_CLIENT_IDX, CAM_SVS_VOTE);
 	else
-		cam_soc_util_clk_disable_default(soc_info);
+		cam_soc_util_clk_disable_default(soc_info, CAM_CLK_SW_CLIENT_IDX);
 
 	return rc;
 }

+ 60 - 16
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -167,6 +167,10 @@ static int cam_isp_blob_drv_config(struct cam_ife_hw_mgr_ctx         *ctx,
 	drv_config_args.drv_en = drv_config->drv_en;
 	drv_config_args.path_idle_en = drv_config->path_idle_en;
 	drv_config_args.timeout_val = drv_config->timeout_val;
+
+	if (drv_config->drv_en)
+		ctx->drv_path_idle_en = drv_config->path_idle_en;
+
 	for (i = 0; i < ctx->num_base; i++) {
 		if (ctx->base[i].hw_type != CAM_ISP_HW_TYPE_CSID)
 			continue;
@@ -207,11 +211,15 @@ static int cam_ife_mgr_finish_clk_bw_update(
 {
 	int i, rc = 0;
 	struct cam_isp_apply_clk_bw_args clk_bw_args;
+	bool cesta_idx_updated[CAM_CESTA_MAX_CLIENTS] = {0};
 
 	clk_bw_args.request_id = request_id;
 	clk_bw_args.skip_clk_data_rst = skip_clk_data_rst;
+	clk_bw_args.is_drv_config_en = (bool) (ctx->drv_path_idle_en & CAM_ISP_PXL_PATH);
+
 	for (i = 0; i < ctx->num_base; i++) {
 		clk_bw_args.hw_intf = NULL;
+		clk_bw_args.clock_updated = false;
 		CAM_DBG(CAM_PERF,
 			"Clock/BW Update for req_id:%d i:%d num_vfe_out:%d num_sfe_out:%d in_rd:%d",
 			request_id, i, ctx->num_acq_vfe_out, ctx->num_acq_sfe_out,
@@ -226,8 +234,9 @@ static int cam_ife_mgr_finish_clk_bw_update(
 			continue;
 
 		CAM_DBG(CAM_PERF,
-			"Apply Clock/BW for req_id:%d i:%d hw_idx=%d hw_type:%d num_vfe_out:%d num_sfe_out:%d in_rd:%d",
+			"Apply Clock/BW for req_id:%d i:%d hw_idx=%d hw_type:%d inline:%s num_vfe_out:%d num_sfe_out:%d in_rd:%d",
 			request_id, i, clk_bw_args.hw_intf->hw_idx, clk_bw_args.hw_intf->hw_type,
+			CAM_BOOL_TO_YESNO(clk_bw_args.is_drv_config_en),
 			ctx->num_acq_vfe_out, ctx->num_acq_sfe_out,
 			!list_empty(&ctx->res_list_ife_in_rd));
 		rc = clk_bw_args.hw_intf->hw_ops.process_cmd(clk_bw_args.hw_intf->hw_priv,
@@ -239,8 +248,38 @@ static int cam_ife_mgr_finish_clk_bw_update(
 				request_id, i, ctx->base[i].idx, ctx->base[i].hw_type, rc);
 			break;
 		}
+
+		CAM_DBG(CAM_ISP, "clock_updated=%d, hw_idx=%d",
+			clk_bw_args.clock_updated, clk_bw_args.hw_intf->hw_idx);
+
+		if ((clk_bw_args.clock_updated) &&
+			(clk_bw_args.hw_intf->hw_idx < CAM_CESTA_MAX_CLIENTS))
+			cesta_idx_updated[clk_bw_args.hw_intf->hw_idx] = true;
 	}
 
+	if (g_ife_hw_mgr.cam_clk_drv_support) {
+		CAM_DBG(CAM_ISP, "Channel switch for [0]=%s, [1]=%s, [2]=%s",
+			CAM_BOOL_TO_YESNO(cesta_idx_updated[0]),
+			CAM_BOOL_TO_YESNO(cesta_idx_updated[1]),
+			CAM_BOOL_TO_YESNO(cesta_idx_updated[2]));
+
+		for (i = 0; i < CAM_CESTA_MAX_CLIENTS; i++) {
+			if (!cesta_idx_updated[i])
+				continue;
+
+			rc = cam_soc_util_cesta_channel_switch(i, "ife_hw_mgr_update");
+			if (rc) {
+				CAM_ERR(CAM_CSIPHY,
+					"Failed to apply power states for cesta client:%d rc:%d",
+					i, rc);
+				return rc;
+			}
+		}
+	}
+
+	CAM_DBG(CAM_ISP, "Clk, BW update done for Req=%lld, skip_clk_data_rst=%d",
+		request_id, skip_clk_data_rst);
+
 	return rc;
 }
 
@@ -901,7 +940,8 @@ err:
 static int cam_ife_mgr_csid_start_hw(
 	struct   cam_ife_hw_mgr_ctx *ctx,
 	uint32_t primary_rdi_csid_res,
-	bool     is_internal_start)
+	bool     is_internal_start,
+	bool     start_only)
 {
 	struct cam_isp_hw_mgr_res      *hw_mgr_res;
 	struct cam_isp_resource_node   *isp_res;
@@ -963,6 +1003,8 @@ static int cam_ife_mgr_csid_start_hw(
 			start_args.cdm_hw_idx = ctx->cdm_hw_idx;
 			start_args.is_secure = is_secure;
 			start_args.is_internal_start = is_internal_start;
+			start_args.start_only = start_only;
+			start_args.is_drv_config_en = (bool) ctx->drv_path_idle_en;
 			hw_intf->hw_ops.start(hw_intf->hw_priv, &start_args,
 			    sizeof(start_args));
 		}
@@ -5197,6 +5239,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	ife_ctx->common.sec_pf_evt_cb = acquire_args->sec_pf_evt_cb;
 	ife_ctx->try_recovery_cnt = 0;
 	ife_ctx->recovery_req_id = 0;
+	ife_ctx->drv_path_idle_en = 0;
 
 	acquire_hw_info =
 		(struct cam_isp_acquire_hw_info *)acquire_args->acquire_info;
@@ -6945,7 +6988,7 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
 
 	CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
-	rc = cam_ife_mgr_csid_start_hw(ctx, CAM_IFE_PIX_PATH_RES_MAX, false);
+	rc = cam_ife_mgr_csid_start_hw(ctx, CAM_IFE_PIX_PATH_RES_MAX, false, false);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Error in starting CSID HW in ctx id:%d", ctx->ctx_index);
 		goto err;
@@ -7110,6 +7153,13 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
 	CAM_DBG(CAM_ISP, "Enter... ctx id:%d",
 		ctx->ctx_index);
 
+	rc = cam_cpas_query_drv_enable(&g_ife_hw_mgr.cam_ddr_drv_support,
+		&g_ife_hw_mgr.cam_clk_drv_support);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Failed to query DRV enable rc: %d", rc);
+		return -EINVAL;
+	}
+
 	/* update Bandwidth should be done at the hw layer */
 
 	cam_tasklet_start(ctx->common.tasklet_info);
@@ -7219,12 +7269,6 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
 		goto safe_disable;
 	}
 
-	rc = cam_cpas_query_drv_enable(&g_ife_hw_mgr.cam_ddr_drv_support);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "Failed to query DRV enable rc: %d", rc);
-		goto cdm_streamoff;
-	}
-
 start_only:
 
 	atomic_set(&ctx->overflow_pending, 0);
@@ -7343,7 +7387,7 @@ start_only:
 		ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
 	rc = cam_ife_mgr_csid_start_hw(ctx, primary_rdi_csid_res,
-		start_isp->is_internal_start);
+		start_isp->is_internal_start, start_isp->start_only);
 	if (rc)
 		goto err;
 
@@ -7497,6 +7541,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
 	ctx->scratch_buf_info.ife_scratch_config = NULL;
 	ctx->try_recovery_cnt = 0;
 	ctx->recovery_req_id = 0;
+	ctx->drv_path_idle_en = 0;
 
 	memset(&ctx->flags, 0, sizeof(struct cam_ife_hw_mgr_ctx_flags));
 	atomic_set(&ctx->overflow_pending, 0);
@@ -8800,13 +8845,11 @@ static int cam_isp_blob_ife_clock_update(
 
 					camif_r_clk_updated = true;
 				}
-			} else if ((hw_mgr_res->res_id >=
-				CAM_ISP_HW_VFE_IN_RD) && (hw_mgr_res->res_id
-				<= CAM_ISP_HW_VFE_IN_RDI3))
+			} else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RD) &&
+				(hw_mgr_res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) {
 				for (j = 0; j < clock_config->num_rdi; j++)
-					clk_rate = max(clock_config->rdi_hz[j],
-						clk_rate);
-			else
+					clk_rate = max(clock_config->rdi_hz[j], clk_rate);
+			} else {
 				if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_LCR
 					&& hw_mgr_res->hw_res[i]) {
 					CAM_ERR(CAM_ISP, "Invalid res_id %u",
@@ -8814,6 +8857,7 @@ static int cam_isp_blob_ife_clock_update(
 					rc = -EINVAL;
 					return rc;
 				}
+			}
 
 			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
 			if (hw_intf && hw_intf->hw_ops.process_cmd) {

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h

@@ -289,6 +289,7 @@ struct cam_ife_cdm_user_data {
  * @curr_num_exp:           Current num of exposures
  * @try_recovery_cnt:       Retry count for overflow recovery
  * @recovery_req_id:        The request id on which overflow recovery happens
+ * @drv_path_idle_en:       Path idle enable value for DRV
  *
  */
 struct cam_ife_hw_mgr_ctx {
@@ -348,6 +349,7 @@ struct cam_ife_hw_mgr_ctx {
 	uint32_t                                   curr_num_exp;
 	uint32_t                                   try_recovery_cnt;
 	uint64_t                                   recovery_req_id;
+	uint32_t                                   drv_path_idle_en;
 };
 
 /**
@@ -427,6 +429,7 @@ struct cam_isp_sfe_cache_info {
  * @csid_global_reset_en   CSID global reset enable
  * @csid_camif_irq_support CSID camif IRQ support
  * @cam_ddr_drv_support    DDR DRV support
+ * @cam_clk_drv_support    CLK DRV support
  * @isp_caps               Capability of underlying SFE/IFE HW
  * @path_port_map          Mapping of outport to IFE mux
  * @num_caches_found       Number of caches supported
@@ -457,6 +460,7 @@ struct cam_ife_hw_mgr {
 	bool                             csid_global_reset_en;
 	bool                             csid_camif_irq_support;
 	bool                             cam_ddr_drv_support;
+	bool                             cam_clk_drv_support;
 	struct cam_isp_ife_sfe_hw_caps   isp_caps;
 	struct cam_isp_hw_path_port_map  path_port_map;
 

+ 5 - 5
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c

@@ -2640,7 +2640,7 @@ static int cam_ife_csid_ver1_enable_hw(struct cam_ife_csid_ver1_hw *csid_hw)
 	CAM_DBG(CAM_ISP,
 		"CSID[%d] clk lvl %u received clk_rate %u applied clk_rate %lu",
 		csid_hw->hw_intf->hw_idx, clk_lvl, csid_hw->clk_rate,
-		soc_info->applied_src_clk_rate);
+		soc_info->applied_src_clk_rates.sw_client);
 
 	rc = cam_ife_csid_enable_soc_resources(soc_info, clk_lvl);
 
@@ -3987,28 +3987,28 @@ static int cam_ife_csid_ver1_rx_bottom_half_handler(
 			event_type |= CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW;
 			CAM_ERR_BUF(CAM_ISP, log_buf, CAM_IFE_CSID_LOG_BUF_LEN, &len,
 				"RX_ERROR_LANE0_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz\n",
-				soc_info->applied_src_clk_rate);
+				soc_info->applied_src_clk_rates.sw_client);
 		}
 
 		if (irq_status & IFE_CSID_VER1_RX_LANE1_FIFO_OVERFLOW) {
 			event_type |= CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW;
 			CAM_ERR_BUF(CAM_ISP, log_buf, CAM_IFE_CSID_LOG_BUF_LEN, &len,
 				"RX_ERROR_LANE1_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz\n",
-				soc_info->applied_src_clk_rate);
+				soc_info->applied_src_clk_rates.sw_client);
 		}
 
 		if (irq_status & IFE_CSID_VER1_RX_LANE2_FIFO_OVERFLOW) {
 			event_type |= CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW;
 			CAM_ERR_BUF(CAM_ISP, log_buf, CAM_IFE_CSID_LOG_BUF_LEN, &len,
 				"RX_ERROR_LANE2_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz\n",
-				soc_info->applied_src_clk_rate);
+				soc_info->applied_src_clk_rates.sw_client);
 		}
 
 		if (irq_status & IFE_CSID_VER1_RX_LANE3_FIFO_OVERFLOW) {
 			event_type |= CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW;
 			CAM_ERR_BUF(CAM_ISP, log_buf, CAM_IFE_CSID_LOG_BUF_LEN, &len,
 				"RX_ERROR_LANE3_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:%luHz\n",
-				soc_info->applied_src_clk_rate);
+				soc_info->applied_src_clk_rates.sw_client);
 		}
 
 		if (irq_status & IFE_CSID_VER1_RX_TG_FIFO_OVERFLOW) {

+ 166 - 23
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -1231,7 +1231,7 @@ static int cam_ife_csid_ver2_rx_err_bottom_half(
 			event_type |= CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW;
 			CAM_ERR_BUF(CAM_ISP, log_buf, CAM_IFE_CSID_LOG_BUF_LEN, &len,
 				"INPUT_FIFO_OVERFLOW [Lanes:%s]: Skew/Less Data on lanes/ Slow csid clock:%luHz",
-				tmp_buf, soc_info->applied_src_clk_rate);
+				tmp_buf, cam_soc_util_get_applied_src_clk(soc_info, true));
 		}
 
 		if (irq_status & IFE_CSID_VER2_RX_ERROR_CPHY_PH_CRC) {
@@ -1673,17 +1673,17 @@ static int cam_ife_csid_ver2_top_info_irq_bottom_half(
 	}
 
 	if (irq_status & IFE_CSID_VER2_TOP_INFO_VOTE_UP) {
-		cam_cpas_log_votes(true);
 		CAM_INFO(CAM_ISP, "CSID:%d INFO_VOTE_UP timestamp:[%lld.%09lld]",
 			csid_hw->hw_intf->hw_idx, payload->timestamp.tv_sec,
 			payload->timestamp.tv_nsec);
+		cam_cpas_log_votes(true);
 	}
 
 	if (irq_status & IFE_CSID_VER2_TOP_INFO_VOTE_DN) {
-		cam_cpas_log_votes(true);
 		CAM_INFO(CAM_ISP, "CSID:%d INFO_VOTE_DN timestamp:[%lld.%09lld]",
 			csid_hw->hw_intf->hw_idx, payload->timestamp.tv_sec,
 			payload->timestamp.tv_nsec);
+		cam_cpas_log_votes(true);
 	}
 
 	if (irq_status & IFE_CSID_VER2_TOP_ERR_NO_VOTE_DN) {
@@ -4230,6 +4230,44 @@ static int cam_ife_csid_ver2_program_top(
 	return 0;
 }
 
+static int cam_ife_csid_ver2_set_cesta_clk_rate(struct cam_ife_csid_ver2_hw *csid_hw,
+	bool force_channel_switch, const char *identifier)
+{
+	struct cam_hw_soc_info *soc_info = &csid_hw->hw_info->soc_info;
+	bool channel_switch = force_channel_switch;
+	int rc = 0;
+
+	CAM_DBG(CAM_ISP, "CSID:%d clk_rate=%llu, channel_switch=%d, identifier=%s",
+		csid_hw->hw_intf->hw_idx, csid_hw->clk_rate, channel_switch, identifier);
+
+	if (csid_hw->clk_rate) {
+		rc = cam_soc_util_set_src_clk_rate(soc_info, csid_hw->hw_intf->hw_idx,
+			csid_hw->clk_rate,
+			soc_info->clk_rate[CAM_LOWSVS_VOTE][soc_info->src_clk_idx]);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"Failed in setting cesta clk rates[high low]:[%ld %ld] client_idx:%d rc:%d",
+				csid_hw->clk_rate,
+				soc_info->clk_rate[CAM_LOWSVS_VOTE][soc_info->src_clk_idx],
+				csid_hw->hw_intf->hw_idx, rc);
+			return rc;
+		}
+		channel_switch = true;
+	}
+
+	if (channel_switch) {
+		rc = cam_soc_util_cesta_channel_switch(csid_hw->hw_intf->hw_idx, identifier);
+		if (rc) {
+			CAM_ERR(CAM_CSIPHY,
+				"Failed to apply power states for cesta client:%d rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
 static int cam_ife_csid_ver2_enable_core(struct cam_ife_csid_ver2_hw *csid_hw)
 {
 	int rc = 0;
@@ -4237,10 +4275,11 @@ static int cam_ife_csid_ver2_enable_core(struct cam_ife_csid_ver2_hw *csid_hw)
 	const struct cam_ife_csid_ver2_reg_info *csid_reg;
 	uint32_t clk_lvl;
 	uint32_t irq_mask = 0;
+	struct cam_csid_soc_private *soc_private;
 
-	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
-		    csid_hw->core_info->csid_reg;
+	csid_reg = (struct cam_ife_csid_ver2_reg_info *)csid_hw->core_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
+	soc_private = (struct cam_csid_soc_private *)soc_info->soc_private;
 
 	/* overflow check before increment */
 	if (csid_hw->hw_info->open_count == UINT_MAX) {
@@ -4266,20 +4305,42 @@ static int cam_ife_csid_ver2_enable_core(struct cam_ife_csid_ver2_hw *csid_hw)
 			csid_hw->clk_rate);
 	}
 
-	CAM_DBG(CAM_ISP,
-		"CSID[%d] clk lvl %u received clk_rate %u applied clk_rate %lu",
-		csid_hw->hw_intf->hw_idx, clk_lvl, csid_hw->clk_rate,
-		soc_info->applied_src_clk_rate);
+	if (soc_private->is_ife_csid_lite)
+		CAM_DBG(CAM_ISP,
+			"CSID[%d] clk lvl %u received clk_rate %u applied clk_rate :%lu",
+			csid_hw->hw_intf->hw_idx, clk_lvl, csid_hw->clk_rate,
+			soc_info->applied_src_clk_rates.sw_client);
+	else
+		CAM_DBG(CAM_ISP,
+			"CSID[%d] clk lvl %u received clk_rate %u applied clk_rate sw_client:%lu hw_client:[%lu %lu]",
+			csid_hw->hw_intf->hw_idx, clk_lvl, csid_hw->clk_rate,
+			soc_info->applied_src_clk_rates.sw_client,
+			soc_info->applied_src_clk_rates.hw_client[csid_hw->hw_intf->hw_idx].high,
+			soc_info->applied_src_clk_rates.hw_client[csid_hw->hw_intf->hw_idx].low);
 
 	rc = cam_ife_csid_enable_soc_resources(soc_info, clk_lvl);
-
 	if (rc) {
-		CAM_ERR(CAM_ISP,
-			"CSID[%d] Enable soc failed",
-			csid_hw->hw_intf->hw_idx);
+		CAM_ERR(CAM_ISP, "CSID[%d] Enable soc failed", csid_hw->hw_intf->hw_idx);
 		goto err;
 	}
 
+	CAM_DBG(CAM_ISP, "csid %d is_clk_drv_en %d is_drv_config_en %d",
+		csid_hw->hw_intf->hw_idx, soc_info->is_clk_drv_en, csid_hw->is_drv_config_en);
+
+	/*
+	 * cam_ife_csid_enable_soc_resources sets clk_lvl for high, low values, if the usecase
+	 * enables drv config, i.e enabling csid DRV events, overwrite low value with LowSVS to get
+	 * power benefit.
+	 */
+	if (soc_info->is_clk_drv_en && csid_hw->is_drv_config_en) {
+		rc = cam_ife_csid_ver2_set_cesta_clk_rate(csid_hw, false, "csid_init");
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Failed in setting cesta clk rates, client_idx:%d rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+			return rc;
+		}
+	}
+
 	irq_mask = csid_reg->cmn_reg->top_reset_irq_mask;
 
 	csid_hw->reset_irq_handle = cam_irq_controller_subscribe_irq(
@@ -4688,15 +4749,19 @@ static void cam_ife_csid_ver2_send_secure_info(
 int cam_ife_csid_ver2_start(void *hw_priv, void *args,
 			uint32_t arg_size)
 {
-	struct cam_ife_csid_ver2_hw           *csid_hw  = NULL;
-	struct cam_isp_resource_node          *res;
-	struct cam_csid_hw_start_args         *start_args;
-	struct cam_ife_csid_ver2_reg_info     *csid_reg;
-	struct cam_hw_soc_info                *soc_info;
-	struct cam_hw_info                    *hw_info;
-	uint32_t                               rup_aup_mask = 0;
-	int                                    rc = 0, i;
-	bool                                   delay_rdi0_enable = false;
+	struct cam_ife_csid_ver2_hw                 *csid_hw  = NULL;
+	struct cam_isp_resource_node                *res;
+	struct cam_csid_hw_start_args               *start_args;
+	struct cam_ife_csid_ver2_reg_info           *csid_reg;
+	struct cam_hw_soc_info                      *soc_info;
+	struct cam_hw_info                          *hw_info;
+	uint32_t                                     rup_aup_mask = 0;
+	int                                          rc = 0, i;
+	bool                                         delay_rdi0_enable = false;
+	struct cam_subdev_msg_phy_conn_csid_info     conn_csid_info;
+	struct cam_subdev_msg_phy_drv_info           drv_info;
+	struct cam_subdev_msg_phy_halt_resume_info   halt_resume_info;
+	bool                                         cesta_enabled = false;
 
 	if (!hw_priv || !args) {
 		CAM_ERR(CAM_ISP, "CSID Invalid params");
@@ -4720,8 +4785,14 @@ int cam_ife_csid_ver2_start(void *hw_priv, void *args,
 	mutex_lock(&csid_hw->hw_info->hw_mutex);
 	csid_hw->flags.sof_irq_triggered = false;
 	csid_hw->counters.irq_debug_cnt = 0;
+	csid_hw->is_drv_config_en = start_args->is_drv_config_en;
+
+	CAM_DBG(CAM_ISP,
+		"csid %d is_drv_config_en %d start_only %d is_internal_start %d, clk_rate=%lld",
+		csid_hw->hw_intf->hw_idx, csid_hw->is_drv_config_en,
+		start_args->start_only, start_args->is_internal_start, csid_hw->clk_rate);
 
-	if (start_args->is_internal_start) {
+	if (start_args->start_only) {
 		rc = cam_cpas_csid_process_resume(csid_hw->hw_intf->hw_idx);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "CSID:%u Failed to process resume rc: %d",
@@ -4730,6 +4801,32 @@ int cam_ife_csid_ver2_start(void *hw_priv, void *args,
 		}
 	}
 
+	if (soc_info->is_clk_drv_en && csid_hw->is_drv_config_en) {
+		/*
+		 * This will do 2 things :
+		 * 1. At the time of enable_core, we do not have drv info yet populated into
+		 *    csid layer, so we set high, low here will overwrite previously set high, low
+		 * 2. We trigger a channel switch so that we go to high clocks for all including
+		 *    csiphy before calling CSIPHY RESUME, so that we remove sw client vote from
+		 *    csiphy device
+		 */
+		rc = cam_ife_csid_ver2_set_cesta_clk_rate(csid_hw, true, "csid_start");
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Failed in setting cesta clk rates, client_idx:%d rc:%d",
+				csid_hw->hw_intf->hw_idx, rc);
+			return rc;
+		}
+
+		if (csid_hw->sync_mode != CAM_ISP_HW_SYNC_SLAVE) {
+			halt_resume_info.phy_idx = (csid_hw->rx_cfg.phy_sel - 1);
+			halt_resume_info.lane_cfg = csid_hw->rx_cfg.lane_cfg;
+			halt_resume_info.csid_state = CAM_SUBDEV_PHY_CSID_RESUME;
+			cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE,
+				CAM_SUBDEV_MESSAGE_NOTIFY_HALT_RESUME,
+					(void *)&halt_resume_info);
+		}
+	}
+
 	rc = cam_ife_csid_ver2_enable_hw(csid_hw);
 
 	for (i = 0; i < start_args->num_res; i++) {
@@ -4803,6 +4900,40 @@ int cam_ife_csid_ver2_start(void *hw_priv, void *args,
 
 	cam_ife_csid_ver2_enable_csi2(csid_hw);
 
+	if (csid_hw->sync_mode != CAM_ISP_HW_SYNC_SLAVE) {
+		struct cam_csid_soc_private *soc_private =
+			(struct cam_csid_soc_private *)soc_info->soc_private;
+
+		conn_csid_info.phy_idx = (csid_hw->rx_cfg.phy_sel - 1);
+		conn_csid_info.lane_cfg = csid_hw->rx_cfg.lane_cfg;
+		conn_csid_info.core_idx = csid_hw->hw_intf->hw_idx;
+		cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, CAM_SUBDEV_MESSAGE_CONN_CSID_INFO,
+			(void *)&conn_csid_info);
+
+		if (!soc_private->is_ife_csid_lite)
+			cam_cpas_query_drv_enable(NULL, &cesta_enabled);
+
+		if (cesta_enabled) {
+			/* for ifelites, soc_info->is_clk_drv_en is false */
+			drv_info.use_hw_client_voting = soc_info->is_clk_drv_en;
+			drv_info.is_drv_config_en = csid_hw->is_drv_config_en;
+		} else {
+			drv_info.use_hw_client_voting = false;
+			drv_info.is_drv_config_en = false;
+		}
+
+		drv_info.phy_idx = (csid_hw->rx_cfg.phy_sel - 1);
+		drv_info.lane_cfg = csid_hw->rx_cfg.lane_cfg;
+
+		/*
+		 * send this even when cesta is not enabled - to support debugfs to switch between
+		 * cesta and non-cesta between runs. CSIPHY might have stale information if we
+		 * do not send this info everytime
+		 */
+		cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE,
+			CAM_SUBDEV_MESSAGE_DRV_INFO, (void *)&drv_info);
+	}
+
 	for (i = 0; i < start_args->num_res; i++) {
 		res = start_args->node_res[i];
 
@@ -4855,6 +4986,7 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 	uint32_t i;
 	struct cam_csid_hw_stop_args         *csid_stop;
 	struct cam_csid_reset_cfg_args       reset = {0};
+	struct cam_subdev_msg_phy_halt_resume_info halt_resume_info;
 
 	if (!hw_priv || !stop_args ||
 		(arg_size != sizeof(struct cam_csid_hw_stop_args))) {
@@ -4883,6 +5015,15 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
 
 	csid_hw->flags.device_enabled = false;
 
+	if (csid_hw->hw_info->soc_info.is_clk_drv_en && csid_hw->is_drv_config_en) {
+		halt_resume_info.phy_idx = (csid_hw->rx_cfg.phy_sel - 1);
+		halt_resume_info.lane_cfg = csid_hw->rx_cfg.lane_cfg;
+		halt_resume_info.csid_state = CAM_SUBDEV_PHY_CSID_HALT;
+		cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE,
+			CAM_SUBDEV_MESSAGE_NOTIFY_HALT_RESUME,
+				(void *)&halt_resume_info);
+	}
+
 	reset.reset_type = (csid_hw->flags.fatal_err_detected) ? CAM_IFE_CSID_RESET_GLOBAL :
 		CAM_IFE_CSID_RESET_PATH;
 	cam_ife_csid_ver2_reset(hw_priv, &reset,
@@ -5413,6 +5554,8 @@ static int cam_ife_csid_ver2_set_csid_clock(
 
 	csid_hw->clk_rate = clk_update->clk_rate;
 
+	CAM_DBG(CAM_ISP, "CSID:%d, clk_rate=%lld", csid_hw->hw_intf->hw_idx, csid_hw->clk_rate);
+
 	return 0;
 }
 

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.h

@@ -615,6 +615,7 @@ struct cam_ife_csid_ver2_reg_info {
  * @mup:                      MUP for incoming VC of next frame
  * @discard_frame_per_path:   Count of paths dropping initial frames
  * @drv_init_done:            Indicates if drv init config is done
+ * @is_drv_config_en:         If drv config is enabled
  *
  */
 struct cam_ife_csid_ver2_hw {
@@ -659,6 +660,7 @@ struct cam_ife_csid_ver2_hw {
 	uint32_t                               mup;
 	atomic_t                               discard_frame_per_path;
 	bool                                   drv_init_done;
+	bool                                   is_drv_config_en;
 };
 
 /*

+ 15 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c

@@ -176,10 +176,20 @@ int cam_ife_csid_enable_soc_resources(
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	if (!soc_private->is_ife_csid_lite) {
+		/* query this everytime to support debugfs to disable clk drv */
+		rc = cam_cpas_query_drv_enable(NULL, &soc_info->is_clk_drv_en);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Failed to query DRV enable rc:%d", rc);
+			goto stop_cpas;
+		}
+	}
+
+	rc = cam_soc_util_enable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en ? soc_info->index : CAM_CLK_SW_CLIENT_IDX), true,
 		clk_level, true);
 	if (rc) {
-		CAM_ERR(CAM_ISP, "enable platform failed");
+		CAM_ERR(CAM_ISP, "enable platform failed rc %d", rc);
 		goto stop_cpas;
 	}
 
@@ -202,7 +212,9 @@ int cam_ife_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 	}
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info,
+		((soc_info->is_clk_drv_en && (!soc_private->is_ife_csid_lite)) ?
+		soc_info->index : CAM_CLK_SW_CLIENT_IDX), true, true);
 	if (rc)
 		CAM_ERR(CAM_ISP, "Disable platform failed");
 

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h

@@ -303,6 +303,8 @@ struct cam_csid_hw_stop_args {
  * @cdm_hw_idx:         Physical CDM in use together with these resources
  * @is_secure:          If these resources are run in secure session
  * @is_internal_start:  Start triggered internally for reset & recovery
+ * @start_only:         start only, no init required
+ * @is_drv_config_en:   If drv config is enabled
  *
  */
 struct cam_csid_hw_start_args {
@@ -311,6 +313,8 @@ struct cam_csid_hw_start_args {
 	uint32_t                                  cdm_hw_idx;
 	bool                                      is_secure;
 	bool                                      is_internal_start;
+	bool                                      start_only;
+	bool                                      is_drv_config_en;
 };
 
 

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -67,11 +67,15 @@ struct cam_isp_bw_control_args {
  * @hw_intf:             Isp hw intf pointer
  * @request_id:          Request Id
  * @skip_clk_data_rst:   Skip resetting any clk info
+ * @is_drv_config_en:    Enable clk DRV while setting this clk rate
+ * @clock_updated:       If clock is updated for any of the cores
  */
 struct cam_isp_apply_clk_bw_args {
 	struct cam_hw_intf                *hw_intf;
 	uint64_t                           request_id;
 	bool                               skip_clk_data_rst;
+	bool                               is_drv_config_en;
+	bool                               clock_updated;
 };
 
 /*

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h

@@ -120,10 +120,12 @@ struct cam_sfe_fe_update_args {
  *
  * @node_res:                ISP Resource
  * @clk_rate:                Clock rate requested
+ * @vote_level:              DRV vote level corresponding to requested rate
  */
 struct cam_sfe_clock_update_args {
 	struct cam_isp_resource_node      *node_res;
 	uint64_t                           clk_rate;
+	uint32_t                           vote_level;
 };
 
 /*

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h

@@ -222,10 +222,12 @@ struct cam_vfe_acquire_args {
  *
  * @node_res:                Resource to get the time stamp
  * @clk_rate:                Clock rate requested
+ * @vote_level:              DRV vote level corresponding to requested rate
  */
 struct cam_vfe_clock_update_args {
 	struct cam_isp_resource_node      *node_res;
 	uint64_t                           clk_rate;
+	uint32_t                           vote_level;
 };
 
 /*

+ 4 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/iopoll.h>
@@ -76,7 +77,7 @@ static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw  *ppi_hw)
 	}
 
 	for (i = 0; i < soc_info->num_clk; i++) {
-		rc = cam_soc_util_clk_enable(soc_info, false, i, -1, NULL);
+		rc = cam_soc_util_clk_enable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i, -1);
 		if (rc)
 			goto clk_disable;
 	}
@@ -106,7 +107,7 @@ static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw  *ppi_hw)
 	return 0;
 clk_disable:
 	for (--i; i >= 0; i--)
-		cam_soc_util_clk_disable(soc_info, false, i);
+		cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i);
 	ppi_hw->hw_info->open_count--;
 	return rc;
 }
@@ -152,7 +153,7 @@ static int cam_csid_ppi_disable_hw(struct cam_csid_ppi_hw *ppi_hw)
 	ppi_hw->device_enabled = 0;
 
 	for (i = 0; i < soc_info->num_clk; i++)
-		cam_soc_util_clk_disable(soc_info, false, i);
+		cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i);
 
 	return rc;
 }

+ 14 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c

@@ -191,7 +191,18 @@ int cam_sfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_cpas_query_drv_enable(NULL, &soc_info->is_clk_drv_en);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Failed to query DRV enable rc:%d", rc);
+		return rc;
+	}
+
+	/*
+	 * using sfe index - assuming csid and sfe are one to one map on chipsets where
+	 * cesta is present.
+	 */
+	rc = cam_soc_util_enable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en ? soc_info->index : CAM_CLK_SW_CLIENT_IDX), true,
 		CAM_LOWSVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_SFE, "Enable platform failed rc=%d", rc);
@@ -231,7 +242,8 @@ int cam_sfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en ? soc_info->index : CAM_CLK_SW_CLIENT_IDX), true, true);
 	if (rc)
 		CAM_ERR(CAM_SFE, "Disable platform failed rc=%d", rc);
 

+ 102 - 50
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c

@@ -48,11 +48,10 @@ struct cam_sfe_top_priv {
 	struct cam_axi_vote                 req_axi_vote[CAM_SFE_TOP_IN_PORT_MAX];
 	struct cam_axi_vote                 last_bw_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
 	uint64_t                            last_total_bw_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
-	uint64_t                            last_clk_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
+	unsigned long                       last_clk_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
 	enum cam_clk_bw_state               clk_state;
 	enum cam_clk_bw_state               bw_state;
-	enum cam_isp_bw_control_action      axi_vote_control[
-		CAM_SFE_TOP_IN_PORT_MAX];
+	enum cam_isp_bw_control_action      axi_vote_control[CAM_SFE_TOP_IN_PORT_MAX];
 	struct cam_axi_vote                 applied_axi_vote;
 	struct cam_sfe_core_cfg             core_cfg;
 	uint32_t                            sfe_debug_cfg;
@@ -170,31 +169,47 @@ static int cam_sfe_top_set_axi_bw_vote(
 
 }
 
-static int cam_sfe_top_set_hw_clk_rate(
-	struct cam_sfe_top_priv *top_priv, uint64_t final_clk_rate, bool start_stop,
-	uint64_t request_id)
+static int cam_sfe_top_set_hw_clk_rate(struct cam_sfe_top_priv *top_priv,
+	unsigned long final_clk_rate, bool start_stop, uint64_t request_id, bool is_drv_config_en)
 {
 	struct cam_hw_soc_info        *soc_info = NULL;
 	struct cam_sfe_soc_private    *soc_private = NULL;
 	struct cam_ahb_vote            ahb_vote;
 	int rc = 0, clk_lvl = -1;
+	unsigned long cesta_clk_rate_high, cesta_clk_rate_low;
+	int cesta_client_idx = -1;
 
 	soc_info = top_priv->common_data.soc_info;
 	soc_private = (struct cam_sfe_soc_private *)soc_info->soc_private;
 
-	CAM_DBG(CAM_PERF, "Applying SFE:%d Clock name=%s idx=%d clk=%llu req_id=%ld",
+	cesta_clk_rate_high = final_clk_rate;
+	cesta_clk_rate_low = final_clk_rate;
+
+	if (soc_info->is_clk_drv_en) {
+		cesta_client_idx = top_priv->common_data.hw_intf->hw_idx;
+		if (is_drv_config_en)
+			cesta_clk_rate_low =
+				soc_info->clk_rate[CAM_LOWSVS_VOTE][soc_info->src_clk_idx];
+		else
+			cesta_clk_rate_low = final_clk_rate;
+	}
+
+	CAM_DBG(CAM_PERF,
+		"Applying SFE:%d Clock name=%s idx=%d cesta_client_idx:%d req clk[high low]=[%lu %lu] req_id=%ld",
 		top_priv->common_data.hw_intf->hw_idx, soc_info->clk_name[soc_info->src_clk_idx],
-		soc_info->src_clk_idx, final_clk_rate, (start_stop ? -1 : request_id));
+		soc_info->src_clk_idx, cesta_client_idx, cesta_clk_rate_high, cesta_clk_rate_low,
+		(start_stop ? -1 : request_id));
 
-	rc = cam_soc_util_set_src_clk_rate(soc_info, final_clk_rate);
+	rc = cam_soc_util_set_src_clk_rate(soc_info, cesta_client_idx, cesta_clk_rate_high,
+		cesta_clk_rate_low);
 	if (!rc) {
-		top_priv->applied_clk_rate = final_clk_rate;
-		rc = cam_soc_util_get_clk_level(soc_info, final_clk_rate,
+		top_priv->applied_clk_rate = cesta_clk_rate_high;
+		rc = cam_soc_util_get_clk_level(soc_info, cesta_clk_rate_low,
 			soc_info->src_clk_idx, &clk_lvl);
 		if (rc) {
-			CAM_WARN(CAM_SFE,
-				"Failed to get clk level for %s with clk_rate %llu src_idx %d rc %d",
-				soc_info->dev_name, final_clk_rate,
+			CAM_WARN(CAM_ISP,
+				"Failed to get clk level for %s with clk_rate %lu src_idx %d rc %d",
+				soc_info->dev_name, cesta_clk_rate_high,
 				soc_info->src_clk_idx, rc);
 			rc = 0;
 			goto end;
@@ -204,8 +219,10 @@ static int cam_sfe_top_set_hw_clk_rate(
 		ahb_vote.vote.level = clk_lvl;
 		cam_cpas_update_ahb_vote(soc_private->cpas_handle, &ahb_vote);
 	} else {
-		CAM_ERR(CAM_PERF, "SFE:%d Set Clock rate failed, rc=%d",
-			top_priv->common_data.hw_intf->hw_idx, rc);
+		CAM_ERR(CAM_ISP,
+			"SFE:%d cesta_client_idx:%d Failed to set the req clk rate[high low]: [%llu %llu] rc:%d",
+			top_priv->common_data.hw_intf->hw_idx, cesta_client_idx,
+			cesta_clk_rate_high, cesta_clk_rate_low, rc);
 	}
 
 end:
@@ -402,6 +419,13 @@ int cam_sfe_top_calc_axi_bw_vote(struct cam_sfe_top_priv *top_priv,
 	bool bw_unchanged = true;
 	struct cam_axi_vote *final_bw_vote = NULL;
 
+	if (top_priv->num_in_ports > CAM_SFE_TOP_IN_PORT_MAX) {
+		CAM_ERR(CAM_SFE, "Invalid number of ports %d, max %d",
+			top_priv->num_in_ports, CAM_SFE_TOP_IN_PORT_MAX);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	memset(&top_priv->agg_incoming_vote, 0, sizeof(struct cam_axi_vote));
 	for (i = 0; i < top_priv->num_in_ports; i++) {
 		if (top_priv->axi_vote_control[i] ==
@@ -562,6 +586,12 @@ int cam_sfe_top_bw_update(struct cam_sfe_soc_private *soc_private,
 		return -EINVAL;
 	}
 
+	if (top_priv->num_in_ports > CAM_SFE_TOP_IN_PORT_MAX) {
+		CAM_ERR(CAM_SFE, "Invalid number of ports %d, max %d",
+			top_priv->num_in_ports, CAM_SFE_TOP_IN_PORT_MAX);
+		return -EINVAL;
+	}
+
 	for (i = 0; i < top_priv->num_in_ports; i++) {
 		if (top_priv->in_rsrc[i].res_id == res->res_id) {
 			memcpy(&top_priv->req_axi_vote[i],
@@ -602,6 +632,12 @@ int cam_sfe_top_bw_control(struct cam_sfe_soc_private *soc_private,
 		return -EINVAL;
 	}
 
+	if (top_priv->num_in_ports > CAM_SFE_TOP_IN_PORT_MAX) {
+		CAM_ERR(CAM_SFE, "Invalid number of ports %d, max %d",
+			top_priv->num_in_ports, CAM_SFE_TOP_IN_PORT_MAX);
+		return -EINVAL;
+	}
+
 	for (i = 0; i < top_priv->num_in_ports; i++) {
 		if (top_priv->in_rsrc[i].res_id == res->res_id) {
 			top_priv->axi_vote_control[i] = bw_ctrl->action;
@@ -646,7 +682,7 @@ static int cam_sfe_top_core_cfg(
 
 static inline void cam_sfe_top_delay_clk_reduction(
 	struct cam_sfe_top_priv *top_priv,
-	uint64_t *max_clk)
+	unsigned long *max_clk)
 {
 	int i;
 
@@ -658,10 +694,10 @@ static inline void cam_sfe_top_delay_clk_reduction(
 
 int cam_sfe_top_calc_hw_clk_rate(
 	struct cam_sfe_top_priv *top_priv, bool start_stop,
-	uint64_t                       *final_clk_rate, uint64_t request_id)
+	unsigned long *final_clk_rate, uint64_t request_id)
 {
 	int                            i, rc = 0;
-	uint64_t                       max_req_clk_rate = 0;
+	unsigned long                  max_req_clk_rate = 0;
 
 	for (i = 0; i < top_priv->num_in_ports; i++) {
 		if (top_priv->req_clk_rate[i] > max_req_clk_rate)
@@ -675,15 +711,13 @@ int cam_sfe_top_calc_hw_clk_rate(
 		memset(top_priv->last_clk_vote, 0, sizeof(uint64_t) *
 			CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ);
 		top_priv->last_clk_counter = 0;
-		top_priv->last_clk_vote[top_priv->last_clk_counter] =
-			max_req_clk_rate;
+		top_priv->last_clk_vote[top_priv->last_clk_counter] = max_req_clk_rate;
 		top_priv->last_clk_counter = (top_priv->last_clk_counter + 1) %
 			CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ;
 	} else {
-		top_priv->last_clk_vote[top_priv->last_clk_counter] =
-			max_req_clk_rate;
+		top_priv->last_clk_vote[top_priv->last_clk_counter] = max_req_clk_rate;
 		top_priv->last_clk_counter = (top_priv->last_clk_counter + 1) %
-			CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ;
+				CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ;
 
 		/* Find max clk request in last few requests */
 		cam_sfe_top_delay_clk_reduction(top_priv, final_clk_rate);
@@ -701,7 +735,7 @@ int cam_sfe_top_calc_hw_clk_rate(
 		top_priv->clk_state = CAM_CLK_BW_STATE_DECREASE;
 
 	CAM_DBG(CAM_PERF, "SFE:%d Clock state:%s hw_clk_rate:%llu req_id:%ld",
-		top_priv->common_data.hw_intf->hw_idx,
+			top_priv->common_data.hw_intf->hw_idx,
 		cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
 		top_priv->applied_clk_rate, (start_stop ? -1 : request_id));
 
@@ -864,8 +898,10 @@ static int cam_sfe_top_handle_overflow(
 		top_priv->common_data.common_reg->ipp_violation_status);
 
 	CAM_ERR(CAM_ISP,
-		"SFE%d src_clk_rate:%luHz bus_overflow_status:%s violation: %s",
-		soc_info->index, soc_info->applied_src_clk_rate,
+		"SFE%d src_clk_rate sw_client:%lu hw_client:[%lu %lu] bus_overflow_status:%s violation: %s",
+		soc_info->index, soc_info->applied_src_clk_rates.sw_client,
+		soc_info->applied_src_clk_rates.hw_client[soc_info->index].high,
+		soc_info->applied_src_clk_rates.hw_client[soc_info->index].low,
 		CAM_BOOL_TO_YESNO(bus_overflow_status), CAM_BOOL_TO_YESNO(violation_status));
 
 	tmp = bus_overflow_status;
@@ -896,7 +932,7 @@ static int cam_sfe_top_apply_clk_bw_update(struct cam_sfe_top_priv *top_priv,
 	struct cam_hw_intf                   *hw_intf = NULL;
 	struct cam_axi_vote *to_be_applied_axi_vote = NULL;
 	struct cam_isp_apply_clk_bw_args *clk_bw_args = NULL;
-	uint64_t                              final_clk_rate = 0;
+	unsigned long                         final_clk_rate = 0;
 	uint64_t                              total_bw_new_vote = 0;
 	uint64_t                              request_id;
 	int rc = 0;
@@ -952,10 +988,12 @@ static int cam_sfe_top_apply_clk_bw_update(struct cam_sfe_top_priv *top_priv,
 		goto end;
 	}
 
-	CAM_DBG(CAM_PERF, "SFE:%d APPLY CLK/BW req_id:%ld clk_state:%s bw_state:%s ",
+	CAM_DBG(CAM_PERF,
+		"SFE:%d APPLY CLK/BW req_id:%ld clk_state:%s bw_state:%s is_drv_config_en:%s",
 		hw_intf->hw_idx, request_id,
 		cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-		cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+		cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+		CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 
 	/* Determine BW and clock voting sequence according to state */
 	if ((top_priv->clk_state == CAM_CLK_BW_STATE_UNCHANGED) &&
@@ -966,20 +1004,23 @@ static int cam_sfe_top_apply_clk_bw_update(struct cam_sfe_top_priv *top_priv,
 			total_bw_new_vote, false, request_id);
 		if (rc) {
 			CAM_ERR(CAM_SFE,
-				"SFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s",
+				"SFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, total_bw_new_vote,
 				cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else if (top_priv->bw_state == CAM_CLK_BW_STATE_UNCHANGED) {
-		rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, false, request_id);
+		rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, false, request_id,
+			clk_bw_args->is_drv_config_en);
 		if (rc) {
 			CAM_ERR(CAM_SFE,
-				"SFE:%d Failed in voting final clk:%llu clk_state:%s bw_state:%s",
+				"SFE:%d Failed in voting final clk:%lu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, final_clk_rate,
 				cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else if (top_priv->clk_state == CAM_CLK_BW_STATE_INCREASE) {
@@ -988,31 +1029,36 @@ static int cam_sfe_top_apply_clk_bw_update(struct cam_sfe_top_priv *top_priv,
 			total_bw_new_vote, false, request_id);
 		if (rc) {
 			CAM_ERR(CAM_SFE,
-				"SFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s",
+				"SFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, total_bw_new_vote,
 				cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 
-		rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, false, request_id);
+		rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, false, request_id,
+			clk_bw_args->is_drv_config_en);
 		if (rc) {
 			CAM_ERR(CAM_SFE,
-				"SFE:%d Failed in voting final clk:%llu clk_state:%s bw_state:%s",
+				"SFE:%d Failed in voting final clk:%lu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, final_clk_rate,
 				cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else if (top_priv->clk_state == CAM_CLK_BW_STATE_DECREASE) {
 		/* Set Clock first, followed by BW */
-		rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, false, request_id);
+		rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, false, request_id,
+			clk_bw_args->is_drv_config_en);
 		if (rc) {
 			CAM_ERR(CAM_SFE,
-				"SFE:%d Failed in voting final clk:%llu clk_state:%s bw_state:%s",
+				"SFE:%d Failed in voting final clk:%lu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, final_clk_rate,
 				cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 
@@ -1020,20 +1066,26 @@ static int cam_sfe_top_apply_clk_bw_update(struct cam_sfe_top_priv *top_priv,
 			total_bw_new_vote, false, request_id);
 		if (rc) {
 			CAM_ERR(CAM_SFE,
-				"SFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s",
+				"SFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, total_bw_new_vote,
 				cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+				cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else {
-		CAM_ERR(CAM_SFE, "Invalid state to apply CLK/BW clk_state:%s bw_state:%s",
+		CAM_ERR(CAM_SFE,
+			"Invalid state to apply CLK/BW clk_state:%s bw_state:%s is_drv_config_en:%s",
 			cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state),
-			cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state));
+			cam_sfe_top_clk_bw_state_to_string(top_priv->bw_state),
+			CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 		rc = -EINVAL;
 		goto end;
 	}
 
+	if (top_priv->clk_state != CAM_CLK_BW_STATE_UNCHANGED)
+		clk_bw_args->clock_updated = true;
+
 end:
 	top_priv->clk_state = CAM_CLK_BW_STATE_INIT;
 	top_priv->bw_state = CAM_CLK_BW_STATE_INIT;
@@ -1043,7 +1095,7 @@ end:
 static int cam_sfe_top_apply_clock_start_stop(struct cam_sfe_top_priv *top_priv)
 {
 	int rc = 0;
-	uint64_t final_clk_rate = 0;
+	unsigned long final_clk_rate = 0;
 
 	rc = cam_sfe_top_calc_hw_clk_rate(top_priv, true, &final_clk_rate, 0);
 	if (rc) {
@@ -1056,9 +1108,9 @@ static int cam_sfe_top_apply_clock_start_stop(struct cam_sfe_top_priv *top_priv)
 	if (top_priv->clk_state == CAM_CLK_BW_STATE_UNCHANGED)
 		goto end;
 
-	rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, true, 0);
+	rc = cam_sfe_top_set_hw_clk_rate(top_priv, final_clk_rate, true, 0, false);
 	if (rc) {
-		CAM_ERR(CAM_SFE, "SFE:%d Failed in voting final clk:%llu clk_state:%s",
+		CAM_ERR(CAM_SFE, "SFE:%d Failed in voting final clk:%lu clk_state:%s",
 			top_priv->common_data.hw_intf->hw_idx, final_clk_rate,
 			cam_sfe_top_clk_bw_state_to_string(top_priv->clk_state));
 		goto end;

+ 3 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #include <linux/slab.h>
 #include "cam_tfe_csid_soc.h"
@@ -113,7 +114,7 @@ int cam_tfe_csid_enable_soc_resources(
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		clk_level, true);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "enable platform failed");
@@ -139,7 +140,7 @@ int cam_tfe_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 	}
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc)
 		CAM_ERR(CAM_ISP, "Disable platform failed");
 

+ 1 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c

@@ -962,7 +962,7 @@ static int cam_tfe_top_set_hw_clk_rate(
 		soc_info->clk_name[soc_info->src_clk_idx],
 		soc_info->src_clk_idx, max_clk_rate);
 
-	rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate);
+	rc = cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, max_clk_rate, 0);
 
 	if (!rc)
 		top_priv->hw_clk_rate = max_clk_rate;

+ 6 - 5
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -171,7 +172,7 @@ int cam_tfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDXs, true,
 		CAM_LOWSVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Error! enable platform failed rc=%d", rc);
@@ -200,8 +201,8 @@ int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info,
 	soc_private = soc_info->soc_private;
 
 	if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) {
-		rc = cam_soc_util_clk_enable(soc_info, true,
-			soc_private->dsp_clk_index, 0, NULL);
+		rc = cam_soc_util_clk_enable(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+			soc_private->dsp_clk_index, 0);
 		if (rc)
 			CAM_ERR(CAM_ISP,
 			"Error enable dsp clk failed rc=%d", rc);
@@ -224,7 +225,7 @@ int cam_tfe_soc_disable_clk(struct cam_hw_soc_info *soc_info,
 	soc_private = soc_info->soc_private;
 
 	if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) {
-		rc = cam_soc_util_clk_disable(soc_info, true,
+		rc = cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 			soc_private->dsp_clk_index);
 		if (rc)
 			CAM_ERR(CAM_ISP,
@@ -247,7 +248,7 @@ int cam_tfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 	}
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Disable platform failed rc=%d", rc);
 		return rc;

+ 16 - 5
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c

@@ -277,7 +277,16 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	if (!soc_private->is_ife_lite) {
+		rc = cam_cpas_query_drv_enable(NULL, &soc_info->is_clk_drv_en);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Failed to query DRV enable rc:%d", rc);
+			return rc;
+		}
+	}
+
+	rc = cam_soc_util_enable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en ? soc_info->index : CAM_CLK_SW_CLIENT_IDX), true,
 		CAM_LOWSVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Error! enable platform failed rc=%d", rc);
@@ -313,8 +322,8 @@ int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info,
 			goto end;
 		}
 
-		rc = cam_soc_util_clk_enable(soc_info, true,
-			soc_private->dsp_clk_index, 0, NULL);
+		rc = cam_soc_util_clk_enable(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+			soc_private->dsp_clk_index, 0);
 		if (rc)
 			CAM_ERR(CAM_ISP,
 			"Error enable dsp clk failed rc=%d", rc);
@@ -345,7 +354,7 @@ int cam_vfe_soc_disable_clk(struct cam_hw_soc_info *soc_info,
 			goto end;
 		}
 
-		rc = cam_soc_util_clk_disable(soc_info, true,
+		rc = cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 			soc_private->dsp_clk_index);
 		if (rc)
 			CAM_ERR(CAM_ISP,
@@ -367,9 +376,11 @@ int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 		rc = -EINVAL;
 		return rc;
 	}
+
 	soc_private = soc_info->soc_private;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en ? soc_info->index : CAM_CLK_SW_CLIENT_IDX), true, true);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Disable platform failed rc=%d", rc);
 		return rc;

+ 1 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c

@@ -2709,7 +2709,7 @@ static int cam_vfe_bus_ver3_mini_dump(
 	}
 
 	md = (struct cam_vfe_bus_ver3_mini_dump_data *)md_args->start_addr;
-	md->clk_rate = hw_info->soc_info.applied_src_clk_rate;
+	md->clk_rate = cam_soc_util_get_applied_src_clk(&hw_info->soc_info, true);
 	md->hw_idx = bus_priv->common_data.hw_intf->hw_idx;
 	md->hw_state = hw_info->hw_state;
 	bytes_written += sizeof(*md);

+ 73 - 42
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c

@@ -85,31 +85,46 @@ static int cam_vfe_top_set_axi_bw_vote(struct cam_vfe_top_priv_common *top_commo
 }
 
 static int cam_vfe_top_set_hw_clk_rate(struct cam_vfe_top_priv_common *top_common,
-	uint64_t final_clk_rate, bool start_stop, uint64_t request_id)
+	unsigned long final_clk_rate, bool start_stop, uint64_t request_id, bool is_drv_config_en)
 {
 	struct cam_hw_soc_info        *soc_info = NULL;
 	struct cam_vfe_soc_private    *soc_private = NULL;
 	struct cam_ahb_vote            ahb_vote;
 	int rc = 0, clk_lvl = -1;
+	unsigned long cesta_clk_rate_high = 0, cesta_clk_rate_low = 0;
+	int cesta_client_idx = -1;
 
 	soc_info = top_common->soc_info;
 	soc_private = (struct cam_vfe_soc_private *)soc_info->soc_private;
 
-	CAM_DBG(CAM_PERF, "Applying VFE:%d Clock name=%s idx=%d clk=%llu req_id=%ld",
+	cesta_clk_rate_high = final_clk_rate;
+	cesta_clk_rate_low = final_clk_rate;
+
+	if (soc_info->is_clk_drv_en) {
+		cesta_client_idx = top_common->hw_idx;
+		if (is_drv_config_en)
+			cesta_clk_rate_low =
+				soc_info->clk_rate[CAM_LOWSVS_VOTE][soc_info->src_clk_idx];
+		else
+			cesta_clk_rate_low = final_clk_rate;
+	}
+
+	CAM_DBG(CAM_PERF,
+		"Applying VFE:%d Clock name=%s idx=%d cesta_client_idx:%d req clk[high low]=[%lu %lu] req_id=%ld",
 		top_common->hw_idx, soc_info->clk_name[soc_info->src_clk_idx],
-		soc_info->src_clk_idx, final_clk_rate, (start_stop ? -1 : request_id));
+		soc_info->src_clk_idx, cesta_client_idx, cesta_clk_rate_high, cesta_clk_rate_low,
+		(start_stop ? -1 : request_id));
 
-	rc = cam_soc_util_set_src_clk_rate(soc_info, final_clk_rate);
+	rc = cam_soc_util_set_src_clk_rate(soc_info, cesta_client_idx, cesta_clk_rate_high,
+		cesta_clk_rate_low);
 	if (!rc) {
-		soc_private->ife_clk_src = final_clk_rate;
-
-		top_common->applied_clk_rate = final_clk_rate;
-		rc = cam_soc_util_get_clk_level(soc_info, final_clk_rate,
+		top_common->applied_clk_rate = cesta_clk_rate_high;
+		rc = cam_soc_util_get_clk_level(soc_info, cesta_clk_rate_low,
 			soc_info->src_clk_idx, &clk_lvl);
 		if (rc) {
 			CAM_WARN(CAM_ISP,
-				"Failed to get clk level for %s with clk_rate %llu src_idx %d rc %d",
-				soc_info->dev_name, final_clk_rate,
+				"Failed to get clk level for %s with clk_rate %lu src_idx %d rc %d",
+				soc_info->dev_name, cesta_clk_rate_high,
 				soc_info->src_clk_idx, rc);
 			rc = 0;
 			goto end;
@@ -119,8 +134,10 @@ static int cam_vfe_top_set_hw_clk_rate(struct cam_vfe_top_priv_common *top_commo
 		ahb_vote.vote.level = clk_lvl;
 		cam_cpas_update_ahb_vote(soc_private->cpas_handle, &ahb_vote);
 	} else {
-		CAM_ERR(CAM_PERF, "VFE:%d Set Clock rate failed, rc=%d",
-			top_common->hw_idx, rc);
+		CAM_ERR(CAM_ISP,
+			"VFE:%d cesta_client_idx:%d Failed to set the req clk rate[high low]: [%llu %llu] rc:%d",
+			top_common->hw_idx, cesta_client_idx, cesta_clk_rate_high,
+			cesta_clk_rate_low, rc);
 	}
 
 end:
@@ -129,7 +146,7 @@ end:
 
 static inline void cam_vfe_top_delay_clk_reduction(
 	struct cam_vfe_top_priv_common *top_common,
-	uint64_t *max_clk)
+	unsigned long *max_clk)
 {
 	int i;
 
@@ -141,10 +158,10 @@ static inline void cam_vfe_top_delay_clk_reduction(
 
 static int cam_vfe_top_calc_hw_clk_rate(
 	struct cam_vfe_top_priv_common *top_common, bool start_stop,
-	uint64_t                       *final_clk_rate, uint64_t request_id)
+	unsigned long *final_clk_rate, uint64_t request_id)
 {
 	int                            i, rc = 0;
-	uint64_t                       max_req_clk_rate = 0;
+	unsigned long                  max_req_clk_rate = 0;
 
 	for (i = 0; i < top_common->num_mux; i++) {
 		if (top_common->req_clk_rate[i] > max_req_clk_rate)
@@ -158,15 +175,13 @@ static int cam_vfe_top_calc_hw_clk_rate(
 		memset(top_common->last_clk_vote, 0, sizeof(uint64_t) *
 			CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ);
 		top_common->last_clk_counter = 0;
-		top_common->last_clk_vote[top_common->last_clk_counter] =
-			max_req_clk_rate;
+		top_common->last_clk_vote[top_common->last_clk_counter] = max_req_clk_rate;
 		top_common->last_clk_counter = (top_common->last_clk_counter + 1) %
 			CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ;
 	} else {
 		top_common->last_clk_vote[top_common->last_clk_counter] =
 			max_req_clk_rate;
-		top_common->last_clk_counter =
-			(top_common->last_clk_counter + 1) %
+		top_common->last_clk_counter = (top_common->last_clk_counter + 1) %
 			CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ;
 
 		/* Find max clk request in last few requests */
@@ -575,7 +590,7 @@ int cam_vfe_top_apply_clk_bw_update(struct cam_vfe_top_priv_common *top_common,
 	struct cam_hw_intf                   *hw_intf = NULL;
 	struct cam_axi_vote *to_be_applied_axi_vote = NULL;
 	struct cam_isp_apply_clk_bw_args *clk_bw_args = NULL;
-	uint64_t                              final_clk_rate = 0;
+	unsigned long                         final_clk_rate = 0;
 	uint64_t                              total_bw_new_vote = 0;
 	uint64_t                              request_id;
 	int rc = 0;
@@ -630,10 +645,12 @@ int cam_vfe_top_apply_clk_bw_update(struct cam_vfe_top_priv_common *top_common,
 		goto end;
 	}
 
-	CAM_DBG(CAM_PERF, "VFE:%d APPLY CLK/BW req_id:%ld clk_state:%s bw_state:%s ",
+	CAM_DBG(CAM_PERF,
+		"VFE:%d APPLY CLK/BW req_id:%ld clk_state:%s bw_state:%s is_drv_config_en:%s",
 		hw_intf->hw_idx, request_id,
 		cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-		cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+		cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+		CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 
 	/* Determine BW and clock voting sequence according to state */
 	if ((top_common->clk_state == CAM_CLK_BW_STATE_UNCHANGED) &&
@@ -644,20 +661,23 @@ int cam_vfe_top_apply_clk_bw_update(struct cam_vfe_top_priv_common *top_common,
 			total_bw_new_vote, false, request_id);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"VFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s",
+				"VFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, total_bw_new_vote,
 				cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else if (top_common->bw_state == CAM_CLK_BW_STATE_UNCHANGED) {
-		rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, false, request_id);
+		rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, false, request_id,
+			clk_bw_args->is_drv_config_en);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"VFE:%d Failed in voting final clk:%llu clk_state:%s bw_state:%s",
+				"VFE:%d Failed in voting final clk:%lu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, final_clk_rate,
 				cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else if (top_common->clk_state == CAM_CLK_BW_STATE_INCREASE) {
@@ -666,31 +686,36 @@ int cam_vfe_top_apply_clk_bw_update(struct cam_vfe_top_priv_common *top_common,
 			total_bw_new_vote, false, request_id);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"VFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s",
+				"VFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, total_bw_new_vote,
 				cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 
-		rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, false, 0);
+		rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, false, 0,
+			clk_bw_args->is_drv_config_en);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"VFE:%d Failed in voting final clk:%llu clk_state:%s bw_state:%s",
+				"VFE:%d Failed in voting final clk:%lu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, final_clk_rate,
 				cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else if (top_common->clk_state == CAM_CLK_BW_STATE_DECREASE) {
 		/* Set Clock first, followed by BW */
-		rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, false, request_id);
+		rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, false, request_id,
+			clk_bw_args->is_drv_config_en);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"VFE:%d Failed in voting final clk:%llu clk_state:%s bw_state:%s",
+				"VFE:%d Failed in voting final clk:%lu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, final_clk_rate,
 				cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 
@@ -698,20 +723,26 @@ int cam_vfe_top_apply_clk_bw_update(struct cam_vfe_top_priv_common *top_common,
 			total_bw_new_vote, false, request_id);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"VFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s",
+				"VFE:%d Failed in voting final bw:%llu clk_state:%s bw_state:%s is_drv_config_en:%s",
 				hw_intf->hw_idx, total_bw_new_vote,
 				cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+				cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+				CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 			goto end;
 		}
 	} else {
-		CAM_ERR(CAM_ISP, "Invalid state to apply CLK/BW clk_state:%s bw_state:%s",
+		CAM_ERR(CAM_ISP,
+			"Invalid state to apply CLK/BW clk_state:%s bw_state:%s is_drv_config_en:%s",
 			cam_vfe_top_clk_bw_state_to_string(top_common->clk_state),
-			cam_vfe_top_clk_bw_state_to_string(top_common->bw_state));
+			cam_vfe_top_clk_bw_state_to_string(top_common->bw_state),
+			CAM_BOOL_TO_YESNO(clk_bw_args->is_drv_config_en));
 		rc = -EINVAL;
 		goto end;
 	}
 
+	if (top_common->clk_state != CAM_CLK_BW_STATE_UNCHANGED)
+		clk_bw_args->clock_updated = true;
+
 end:
 	top_common->clk_state = CAM_CLK_BW_STATE_INIT;
 	top_common->bw_state = CAM_CLK_BW_STATE_INIT;
@@ -721,7 +752,7 @@ end:
 int cam_vfe_top_apply_clock_start_stop(struct cam_vfe_top_priv_common *top_common)
 {
 	int rc = 0;
-	uint64_t final_clk_rate = 0;
+	unsigned long final_clk_rate = 0;
 
 	rc = cam_vfe_top_calc_hw_clk_rate(top_common, true, &final_clk_rate, 0);
 	if (rc) {
@@ -734,9 +765,9 @@ int cam_vfe_top_apply_clock_start_stop(struct cam_vfe_top_priv_common *top_commo
 	if (top_common->clk_state == CAM_CLK_BW_STATE_UNCHANGED)
 		goto end;
 
-	rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, true, 0);
+	rc = cam_vfe_top_set_hw_clk_rate(top_common, final_clk_rate, true, 0, false);
 	if (rc) {
-		CAM_ERR(CAM_ISP, "VFE:%d Failed in voting final clk:%llu clk_state:%s",
+		CAM_ERR(CAM_ISP, "VFE:%d Failed in voting final clk:%lu clk_state:%s",
 			top_common->hw_idx, final_clk_rate,
 			cam_vfe_top_clk_bw_state_to_string(top_common->clk_state));
 		goto end;

+ 2 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_VFE_TOP_COMMON_H_
@@ -26,7 +27,7 @@ struct cam_vfe_top_priv_common {
 	struct cam_axi_vote             last_bw_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
 	uint64_t                        last_total_bw_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
 	uint32_t                        last_bw_counter;
-	uint64_t                        last_clk_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
+	unsigned long                   last_clk_vote[CAM_DELAY_CLK_BW_REDUCTION_NUM_REQ];
 	uint32_t                        last_clk_counter;
 	uint64_t                        total_bw_applied;
 	enum cam_clk_bw_state           clk_state;

+ 2 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -99,7 +100,7 @@ static int cam_vfe_top_dump_info(
 	switch (cmd_type) {
 	case CAM_ISP_HW_NOTIFY_OVERFLOW:
 		CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE%d src_clk_rate:%luHz",
-			soc_info->index, soc_info->applied_src_clk_rate);
+			soc_info->index, soc_info->applied_src_clk_rates.sw_client);
 		break;
 	default:
 		CAM_ERR(CAM_ISP, "cmd_type: %u not supported", cmd_type);

+ 2 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -118,7 +119,7 @@ static int cam_vfe_top_ver3_dump_info(
 	switch (cmd_type) {
 	case CAM_ISP_HW_NOTIFY_OVERFLOW:
 		CAM_INFO_RATE_LIMIT(CAM_ISP, "VFE%d src_clk_rate:%luHz",
-			soc_info->index, soc_info->applied_src_clk_rate);
+			soc_info->index, soc_info->applied_src_clk_rates.sw_client);
 		break;
 	default:
 		CAM_ERR(CAM_ISP, "cmd_type: %u not supported", cmd_type);

+ 16 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver4.c

@@ -540,9 +540,22 @@ static int cam_vfe_top_ver4_print_overflow_debug_info(
 	violation_status = cam_io_r(soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base +
 		    common_data->common_reg->bus_violation_status);
 
-	CAM_ERR(CAM_ISP, "VFE[%d] sof_cnt:%d src_clk:%luMHz overflow:%s violation:%s",
-		soc_info->index, top_priv->sof_cnt, soc_info->applied_src_clk_rate / 1000000,
-		CAM_BOOL_TO_YESNO(bus_overflow_status), CAM_BOOL_TO_YESNO(violation_status));
+	if (soc_private->is_ife_lite)
+		CAM_ERR(CAM_ISP,
+			"VFE[%d] sof_cnt:%d src_clk:%lu overflow:%s violation:%s",
+			soc_info->index, top_priv->sof_cnt,
+			soc_info->applied_src_clk_rates.sw_client,
+			CAM_BOOL_TO_YESNO(bus_overflow_status),
+			CAM_BOOL_TO_YESNO(violation_status));
+	else
+		CAM_ERR(CAM_ISP,
+			"VFE[%d] sof_cnt:%d src_clk sw_client:%lu hw_client:[%lu %lu] overflow:%s violation:%s",
+			soc_info->index, top_priv->sof_cnt,
+			soc_info->applied_src_clk_rates.sw_client,
+			soc_info->applied_src_clk_rates.hw_client[soc_info->index].high,
+			soc_info->applied_src_clk_rates.hw_client[soc_info->index].low,
+			CAM_BOOL_TO_YESNO(bus_overflow_status),
+			CAM_BOOL_TO_YESNO(violation_status));
 
 	if (bus_overflow_status) {
 		overflow_info->is_bus_overflow = true;

+ 3 - 2
drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -69,7 +70,7 @@ int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, true);
 	if (rc)
 		CAM_ERR(CAM_JPEG, "enable platform failed %d", rc);
@@ -81,7 +82,7 @@ int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc)
 		CAM_ERR(CAM_JPEG, "disable platform failed %d", rc);
 

+ 3 - 2
drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -68,7 +69,7 @@ int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, true);
 	if (rc)
 		CAM_ERR(CAM_JPEG, "enable platform failed %d", rc);
@@ -80,7 +81,7 @@ int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc)
 		CAM_ERR(CAM_JPEG, "disable platform failed %d", rc);
 

+ 4 - 3
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/device.h>
@@ -43,8 +44,8 @@ int cam_lrme_soc_enable_resources(struct cam_hw_info *lrme_hw)
 		return -EFAULT;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_SVS_VOTE,
-		true);
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+		CAM_SVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_LRME,
 			"Failed to enable platform resource, rc %d", rc);
@@ -72,7 +73,7 @@ int cam_lrme_soc_disable_resources(struct cam_hw_info *lrme_hw)
 
 	cam_lrme_set_irq(lrme_hw, CAM_LRME_IRQ_DISABLE);
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc) {
 		CAM_ERR(CAM_LRME, "Failed to disable platform resource");
 		return rc;

+ 2 - 2
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c

@@ -1688,7 +1688,7 @@ int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type,
 			(struct cam_ope_dev_clk_update *)cmd_args;
 
 		if (core_info->clk_enable == false) {
-			rc = cam_soc_util_clk_enable_default(soc_info,
+			rc = cam_soc_util_clk_enable_default(soc_info, CAM_CLK_SW_CLIENT_IDX,
 				CAM_SVS_VOTE);
 			if (rc) {
 				CAM_ERR(CAM_OPE, "Clock enable is failed");
@@ -1704,7 +1704,7 @@ int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type,
 		break;
 	case OPE_HW_CLK_DISABLE: {
 		if (core_info->clk_enable == true)
-			cam_soc_util_clk_disable_default(soc_info);
+			cam_soc_util_clk_disable_default(soc_info, CAM_CLK_SW_CLIENT_IDX);
 
 		core_info->clk_enable = false;
 		}

+ 6 - 5
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -96,7 +97,7 @@ int cam_ope_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_SVS_VOTE, true);
 	if (rc) {
 		CAM_ERR(CAM_OPE, "enable platform failed");
@@ -111,7 +112,7 @@ int cam_ope_disable_soc_resources(struct cam_hw_soc_info *soc_info,
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk,
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, disable_clk,
 		true);
 	if (rc)
 		CAM_ERR(CAM_OPE, "enable platform failed");
@@ -144,7 +145,7 @@ int cam_ope_update_clk_rate(struct cam_hw_soc_info *soc_info,
 
 	CAM_DBG(CAM_OPE, "clk_rate = %u src_clk_index = %d",
 		clk_rate, src_clk_idx);
-	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
 }
 
 int cam_ope_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
@@ -152,9 +153,9 @@ int cam_ope_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
 	int rc = 0;
 
 	if (clk_enable)
-		rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE);
+		rc = cam_soc_util_clk_enable_default(soc_info, CAM_CLK_SW_CLIENT_IDX, CAM_SVS_VOTE);
 	else
-		cam_soc_util_clk_disable_default(soc_info);
+		cam_soc_util_clk_disable_default(soc_info, CAM_CLK_SW_CLIENT_IDX);
 
 	return rc;
 }

+ 61 - 0
drivers/cam_req_mgr/cam_subdev.h

@@ -17,10 +17,71 @@
 
 #define CAM_SUBDEVICE_EVENT_MAX 30
 
+
+/* Enum for indicating CSID event */
+enum cam_subdev_phy_csid_state {
+	CAM_SUBDEV_PHY_CSID_HALT = 1,
+	CAM_SUBDEV_PHY_CSID_RESUME,
+};
+
+/**
+ * struct cam_subdev_msg_phy_conn_csid_info: Contains phy num and connected CSID info
+ *
+ * @phy_idx:          Phy idx value indicating which phy is connected to csid core
+ * @lane_cfg:         This value is similar to lane_assign in the PHY
+ *                    driver, and is used to identify the particular
+ *                    PHY instance with which this IFE session is
+ *                    connected to.
+ * @core_idx:         Primary(in case of dual ife) core idx for the csid to which the phy
+ *                    is connected, -1 while disconnecting
+ */
+struct cam_subdev_msg_phy_conn_csid_info {
+	uint32_t phy_idx;
+	uint32_t lane_cfg;
+	int32_t core_idx;
+};
+
+/**
+ * struct cam_subdev_msg_phy_drv_info: Contains drv config info
+ *
+ * @phy_idx:               Phy idx value indicating which phy is connected to csid core
+ * @lane_cfg:              This value is similar to lane_assign in the PHY
+ *                         driver, and is used to identify the particular
+ *                         PHY instance with which this IFE session is
+ *                         connected to.
+ * @use_hw_client_voting:  Whether to use hw client voting for csiphy clk
+ * @is_drv_config_en:      If DRV config is enabled in CSID
+ */
+struct cam_subdev_msg_phy_drv_info {
+	uint32_t phy_idx;
+	uint32_t lane_cfg;
+	bool     use_hw_client_voting;
+	bool     is_drv_config_en;
+};
+
+/**
+ * struct cam_subdev_msg_phy_halt_resume_info: Contains csid halt resume info
+ *
+ * @phy_idx:     Phy idx value indicating which phy is connected to csid core
+ * @lane_cfg:    This value is similar to lane_assign in the PHY
+ *               driver, and is used to identify the particular
+ *               PHY instance with which this IFE session is
+ *               connected to.
+ * @csid_state:  Notification of CSID state
+ */
+struct cam_subdev_msg_phy_halt_resume_info {
+	uint32_t                       phy_idx;
+	uint32_t                       lane_cfg;
+	enum cam_subdev_phy_csid_state csid_state;
+};
+
 enum cam_subdev_message_type_t {
 	CAM_SUBDEV_MESSAGE_REG_DUMP = 0x1,
 	CAM_SUBDEV_MESSAGE_APPLY_CSIPHY_AUX,
 	CAM_SUBDEV_MESSAGE_DOMAIN_ID_SECURE_PARAMS,
+	CAM_SUBDEV_MESSAGE_CONN_CSID_INFO,
+	CAM_SUBDEV_MESSAGE_DRV_INFO,
+	CAM_SUBDEV_MESSAGE_NOTIFY_HALT_RESUME,
 };
 
 /* Enum for close sequence priority */

+ 3 - 3
drivers/cam_sensor_module/cam_cci/cam_cci_soc.c

@@ -176,7 +176,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
 	cam_cci_get_clk_rates(cci_dev, c_ctrl);
 
 	/* Enable Regulators and IRQ*/
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		CAM_LOWSVS_VOTE, true);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "CCI%d_I2C_M%d request platform resources failed, rc: %d",
@@ -220,7 +220,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
 	return 0;
 
 reset_complete_failed:
-	cam_soc_util_disable_platform_resource(soc_info, true, true);
+	cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 platform_enable_failed:
 	cci_dev->ref_count--;
 	cam_cpas_stop(cci_dev->cpas_handle);
@@ -456,7 +456,7 @@ int cam_cci_soc_release(struct cci_device *cci_dev,
 		cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES;
 	}
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 	if (rc) {
 		CAM_ERR(CAM_CCI, "CCI%d_I2C_M%d platform resources disable failed, rc: %d",
 			cci_dev->soc_info.index, master, rc);

+ 134 - 47
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c

@@ -161,6 +161,9 @@ static void cam_csiphy_reset_phyconfig_param(struct csiphy_device *csiphy_dev,
 	csiphy_dev->csiphy_info[index].mipi_flags = 0;
 	csiphy_dev->csiphy_info[index].hdl_data.device_hdl = -1;
 	csiphy_dev->csiphy_info[index].csiphy_3phase = -1;
+	csiphy_dev->csiphy_info[index].conn_csid_idx = -1;
+	csiphy_dev->csiphy_info[index].use_hw_client_voting = false;
+	csiphy_dev->csiphy_info[index].is_drv_config_en = false;
 }
 
 static inline void cam_csiphy_apply_onthego_reg_values(void __iomem *csiphybase, uint8_t csiphy_idx)
@@ -1401,7 +1404,9 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
 {
 	struct cam_hw_soc_info *soc_info;
 	struct csiphy_reg_parms_t *csiphy_reg;
+	struct cam_csiphy_param *param;
 	int32_t i = 0;
+	int rc = 0;
 
 	if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT)
 		return;
@@ -1423,13 +1428,31 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
 		soc_info = &csiphy_dev->soc_info;
 
 		for (i = 0; i < csiphy_dev->acquire_count; i++) {
-			if (csiphy_dev->csiphy_info[i].secure_mode)
-				cam_csiphy_program_secure_mode(
-					csiphy_dev,
+			param = &csiphy_dev->csiphy_info[i];
+
+			if (param->secure_mode)
+				cam_csiphy_program_secure_mode(csiphy_dev,
 					CAM_SECURE_MODE_NON_SECURE, i);
 
-			csiphy_dev->csiphy_info[i].secure_mode =
-				CAM_SECURE_MODE_NON_SECURE;
+			param->secure_mode = CAM_SECURE_MODE_NON_SECURE;
+
+			if (soc_info->is_clk_drv_en && param->use_hw_client_voting) {
+				rc = cam_soc_util_set_src_clk_rate(soc_info, param->conn_csid_idx,
+					0, 0);
+				if (rc) {
+					CAM_ERR(CAM_CSIPHY,
+						"[%d] Failed in setting clk rate for %d",
+						soc_info->index, param->conn_csid_idx);
+				} else {
+					rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx,
+						"csiphy_shutdown");
+					if (rc) {
+						CAM_ERR(CAM_CSIPHY,
+							"Failed to apply power states for cesta client:%d rc:%d",
+							param->conn_csid_idx, rc);
+					}
+				}
+			}
 
 			cam_csiphy_reset_phyconfig_param(csiphy_dev, i);
 		}
@@ -1445,7 +1468,7 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
 		}
 
 		cam_csiphy_reset(csiphy_dev);
-		cam_soc_util_disable_platform_resource(soc_info, true, true);
+		cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
 
 		cam_cpas_stop(csiphy_dev->cpas_handle);
 		csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE;
@@ -2092,6 +2115,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			csiphy_acq_dev.session_handle;
 		csiphy_dev->csiphy_info[index].csiphy_3phase =
 			csiphy_acq_params.csiphy_3phase;
+		csiphy_dev->csiphy_info[index].conn_csid_idx = -1;
+		csiphy_dev->csiphy_info[index].use_hw_client_voting = false;
+		csiphy_dev->csiphy_info[index].is_drv_config_en = false;
 
 		CAM_DBG(CAM_CSIPHY, "Add dev_handle:0x%x at index: %d ",
 			csiphy_dev->csiphy_info[index].hdl_data.device_hdl,
@@ -2151,6 +2177,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 	case CAM_STOP_DEV: {
 		int32_t offset, rc = 0;
 		struct cam_start_stop_dev_cmd config;
+		struct cam_csiphy_param *param;
 
 		rc = copy_from_user(&config, (void __user *)cmd->handle,
 					sizeof(config));
@@ -2173,40 +2200,52 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			goto release_mutex;
 		}
 
+		param = &csiphy_dev->csiphy_info[offset];
+
 		if (--csiphy_dev->start_dev_count) {
-			if (csiphy_dev->csiphy_info[offset].secure_mode)
-				cam_csiphy_program_secure_mode(
-					csiphy_dev,
+			if (param->secure_mode)
+				cam_csiphy_program_secure_mode(csiphy_dev,
 					CAM_SECURE_MODE_NON_SECURE, offset);
 
-			csiphy_dev->csiphy_info[offset].secure_mode =
-				CAM_SECURE_MODE_NON_SECURE;
-			csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask
-				= 0;
+			param->secure_mode = CAM_SECURE_MODE_NON_SECURE;
+			param->csiphy_cpas_cp_reg_mask = 0;
 
 			cam_csiphy_update_lane_selection(csiphy_dev, offset, false);
 
+			if (soc_info->is_clk_drv_en && param->use_hw_client_voting) {
+				rc = cam_soc_util_set_src_clk_rate(soc_info, param->conn_csid_idx,
+					0, 0);
+				if (rc) {
+					CAM_ERR(CAM_CSIPHY,
+						"[%d] Failed in setting clk rate for %d",
+						soc_info->index, param->conn_csid_idx);
+				} else {
+					rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx,
+						"csiphy_stop_dev");
+					if (rc) {
+						CAM_ERR(CAM_CSIPHY,
+							"Failed to apply power states for cesta client:%d rc:%d",
+							param->conn_csid_idx, rc);
+					}
+				}
+			}
+
 			CAM_INFO(CAM_CSIPHY,
-				"CAM_STOP_PHYDEV: %d, Type: %s, dev_cnt: %u, slot: %d, Datarate: %llu, Settletime: %llu",
-				soc_info->index,
+				"CAM_STOP_PHYDEV: %d, CSID:%d, Type: %s, dev_cnt: %u, slot: %d, Datarate: %llu, Settletime: %llu",
+				soc_info->index, param->conn_csid_idx,
 				g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
-				csiphy_dev->start_dev_count,
-				offset,
-				csiphy_dev->csiphy_info[offset].data_rate,
-				csiphy_dev->csiphy_info[offset].settle_time);
+				csiphy_dev->start_dev_count, offset, param->data_rate,
+				param->settle_time);
 
 			goto release_mutex;
 		}
 
-		if (csiphy_dev->csiphy_info[offset].secure_mode)
-			cam_csiphy_program_secure_mode(
-				csiphy_dev,
-				CAM_SECURE_MODE_NON_SECURE, offset);
-
-		csiphy_dev->csiphy_info[offset].secure_mode =
-			CAM_SECURE_MODE_NON_SECURE;
+		if (param->secure_mode)
+			cam_csiphy_program_secure_mode(csiphy_dev, CAM_SECURE_MODE_NON_SECURE,
+				offset);
 
-		csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0;
+		param->secure_mode = CAM_SECURE_MODE_NON_SECURE;
+		param->csiphy_cpas_cp_reg_mask = 0x0;
 
 		if (csiphy_dev->prgm_cmn_reg_across_csiphy) {
 			mutex_lock(&active_csiphy_cnt_mutex);
@@ -2225,7 +2264,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 
 		cam_csiphy_update_lane_selection(csiphy_dev, offset, false);
 
-		rc = cam_csiphy_disable_hw(csiphy_dev);
+		rc = cam_csiphy_disable_hw(csiphy_dev, offset);
 		if (rc < 0)
 			CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
 
@@ -2237,12 +2276,10 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 		csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE;
 
 		CAM_INFO(CAM_CSIPHY,
-			"CAM_STOP_PHYDEV: %u, Type: %s, slot: %d, Datarate: %llu, Settletime: %llu",
-			soc_info->index,
+			"CAM_STOP_PHYDEV: %u, CSID:%d, Type: %s, slot: %d, Datarate: %llu, Settletime: %llu",
+			soc_info->index, param->conn_csid_idx,
 			g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
-			offset,
-			csiphy_dev->csiphy_info[offset].data_rate,
-			csiphy_dev->csiphy_info[offset].settle_time);
+			offset, param->data_rate, param->settle_time);
 	}
 		break;
 	case CAM_RELEASE_DEV: {
@@ -2350,9 +2387,11 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 		break;
 	}
 	case CAM_START_DEV: {
+		struct cam_csiphy_param *param;
 		struct cam_start_stop_dev_cmd config;
 		int32_t offset;
-		int clk_vote_level = -1;
+		int clk_vote_level_high = -1;
+		int clk_vote_level_low = -1;
 		uint8_t data_rate_variant_idx = 0;
 
 		CAM_DBG(CAM_CSIPHY, "START_DEV Called");
@@ -2382,17 +2421,63 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			goto release_mutex;
 		}
 
+		param = &csiphy_dev->csiphy_info[offset];
+
+		rc = cam_cpas_query_drv_enable(NULL, &soc_info->is_clk_drv_en);
+		if (rc) {
+			CAM_ERR(CAM_CSIPHY, "Failed to query DRV enable rc: %d", rc);
+			goto release_mutex;
+		}
+
 		if (csiphy_dev->start_dev_count) {
-			clk_vote_level =
-				csiphy_dev->ctrl_reg->getclockvoting(
-					csiphy_dev, offset);
-			rc = cam_soc_util_set_clk_rate_level(
-				&csiphy_dev->soc_info, clk_vote_level, false);
-			if (rc) {
-				CAM_WARN(CAM_CSIPHY,
-					"Failed to set the clk_rate level: %d",
-					clk_vote_level);
-				rc = 0;
+			clk_vote_level_high =
+				csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, offset);
+			clk_vote_level_low = clk_vote_level_high;
+
+			CAM_DBG(CAM_CSIPHY,
+				"CSIPHY[%d] is_clk_drv_en[%d] conn_csid_idx[%d] use_hw_client_voting[%d] is_drv_config_en[%d]",
+				csiphy_dev->soc_info.index, soc_info->is_clk_drv_en,
+				param->conn_csid_idx, param->use_hw_client_voting,
+				param->is_drv_config_en);
+
+			if (soc_info->is_clk_drv_en && param->use_hw_client_voting) {
+				if (param->is_drv_config_en)
+					clk_vote_level_low = CAM_LOWSVS_VOTE;
+
+				rc = cam_soc_util_set_clk_rate_level(&csiphy_dev->soc_info,
+					param->conn_csid_idx, clk_vote_level_high,
+					clk_vote_level_low, false);
+				if (rc) {
+					CAM_ERR(CAM_CSIPHY,
+						"Failed to set the req clk_rate level[high low]: [%s %s] cesta_client_idx: %d rc: %d",
+						cam_soc_util_get_string_from_level(
+						clk_vote_level_high),
+						cam_soc_util_get_string_from_level(
+						clk_vote_level_low), param->conn_csid_idx, rc);
+					rc = -EINVAL;
+					goto release_mutex;
+				}
+
+				rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx,
+					"csiphy_combo");
+				if (rc) {
+					CAM_ERR(CAM_CSIPHY,
+						"Failed to apply power states for crm client:%d rc:%d",
+						param->conn_csid_idx, rc);
+					rc = 0;
+				}
+			} else {
+				rc = cam_soc_util_set_clk_rate_level(&csiphy_dev->soc_info,
+					CAM_CLK_SW_CLIENT_IDX, clk_vote_level_high, 0, false);
+				if (rc) {
+					CAM_WARN(CAM_CSIPHY,
+						"Failed to set the req clk_rate level: %s",
+						cam_soc_util_get_string_from_level(
+						clk_vote_level_high));
+					rc = -EINVAL;
+					goto release_mutex;
+
+				}
 			}
 
 			if (csiphy_dev->csiphy_info[offset].secure_mode == 1) {
@@ -2440,8 +2525,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			csiphy_dev->start_dev_count++;
 
 			CAM_INFO(CAM_CSIPHY,
-				"CAM_START_PHYDEV: %d, Type: %s, dev_cnt: %u, slot: %d, combo: %u, cphy+dphy: %u, sec_mode: %d, Datarate: %llu, Settletime: %llu",
+				"CAM_START_PHYDEV: %d, CSID:%d, Type: %s, dev_cnt: %u, slot: %d, combo: %u, cphy+dphy: %u, sec_mode: %d, Datarate: %llu, Settletime: %llu",
 				soc_info->index,
+				csiphy_dev->csiphy_info[offset].conn_csid_idx,
 				g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
 				csiphy_dev->start_dev_count,
 				offset,
@@ -2505,7 +2591,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 		rc = cam_csiphy_config_dev(csiphy_dev, config.dev_handle, data_rate_variant_idx);
 		if (rc < 0) {
 			CAM_ERR(CAM_CSIPHY, "cam_csiphy_config_dev failed");
-			cam_csiphy_disable_hw(csiphy_dev);
+			cam_csiphy_disable_hw(csiphy_dev, offset);
 			goto hw_cnt_decrement;
 		}
 
@@ -2549,8 +2635,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 		csiphy_dev->csiphy_state = CAM_CSIPHY_START;
 
 		CAM_INFO(CAM_CSIPHY,
-			"CAM_START_PHYDEV: %d, Type: %s, slot: %d, sec_mode: %d, Datarate: %llu, Settletime: %llu, combo: %u, cphy+dphy: %u",
+			"CAM_START_PHYDEV: %d, CSID:%d, Type: %s, slot: %d, sec_mode: %d, Datarate: %llu, Settletime: %llu, combo: %u, cphy+dphy: %u",
 			soc_info->index,
+			csiphy_dev->csiphy_info[offset].conn_csid_idx,
 			g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
 			offset,
 			csiphy_dev->csiphy_info[offset].secure_mode,

+ 124 - 0
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c

@@ -85,6 +85,22 @@ int cam_csiphy_format_secure_phy_lane_info(
 
 }
 
+static int cam_csiphy_get_session_index(struct csiphy_device *csiphy_dev,
+	uint32_t lane_assign)
+{
+	int i = 0;
+	struct cam_csiphy_param *param;
+
+	for (i = 0; i < CSIPHY_MAX_INSTANCES_PER_PHY; i++) {
+		param = &csiphy_dev->csiphy_info[i];
+
+		if (param->lane_assign == lane_assign)
+			break;
+	}
+
+	return i;
+}
+
 static void cam_csiphy_populate_secure_info(
 	struct csiphy_device *csiphy_dev, void *data)
 {
@@ -136,6 +152,7 @@ static void cam_csiphy_subdev_handle_message(struct v4l2_subdev *sd,
 {
 	struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd);
 	uint32_t phy_idx;
+	int rc = 0;
 
 	if (!data) {
 		CAM_ERR(CAM_CSIPHY, "Empty Payload");
@@ -172,6 +189,110 @@ static void cam_csiphy_subdev_handle_message(struct v4l2_subdev *sd,
 
 		break;
 	}
+	case CAM_SUBDEV_MESSAGE_CONN_CSID_INFO: {
+		struct cam_subdev_msg_phy_conn_csid_info *conn_csid_info =
+			(struct cam_subdev_msg_phy_conn_csid_info *) data;
+		int idx;
+		struct cam_csiphy_param *param;
+
+		idx = cam_csiphy_get_session_index(csiphy_dev, conn_csid_info->lane_cfg);
+		if (idx >= CSIPHY_MAX_INSTANCES_PER_PHY) {
+			CAM_ERR(CAM_CSIPHY, "Phy session not found %d %d",
+				csiphy_dev->soc_info.index, conn_csid_info->lane_cfg);
+			rc = -EBADR;
+			break;
+		}
+
+		param = &csiphy_dev->csiphy_info[idx];
+		param->conn_csid_idx = conn_csid_info->core_idx;
+
+		CAM_DBG(CAM_CSIPHY, "PHY: %d, CSID: %d connected", csiphy_dev->soc_info.index,
+			param->conn_csid_idx);
+		break;
+	}
+	case CAM_SUBDEV_MESSAGE_DRV_INFO: {
+		struct cam_subdev_msg_phy_drv_info *drv_info =
+			(struct cam_subdev_msg_phy_drv_info *) data;
+		int idx;
+		struct cam_csiphy_param *param;
+
+		idx = cam_csiphy_get_session_index(csiphy_dev, drv_info->lane_cfg);
+		if (idx >= CSIPHY_MAX_INSTANCES_PER_PHY) {
+			CAM_ERR(CAM_CSIPHY, "Phy session not found %d %d",
+				csiphy_dev->soc_info.index, drv_info->lane_cfg);
+			rc = -EBADR;
+			break;
+		}
+
+		param = &csiphy_dev->csiphy_info[idx];
+		param->is_drv_config_en = drv_info->is_drv_config_en;
+		param->use_hw_client_voting = drv_info->use_hw_client_voting;
+
+		CAM_DBG(CAM_CSIPHY,
+			"PHY: %d, CSID: %d DRV info : use hw client %d, enable drv config %d",
+			csiphy_dev->soc_info.index, param->conn_csid_idx,
+			param->use_hw_client_voting, param->is_drv_config_en);
+
+		break;
+	}
+	case CAM_SUBDEV_MESSAGE_NOTIFY_HALT_RESUME: {
+		int drv_idx;
+		struct cam_subdev_msg_phy_halt_resume_info *halt_resume_info =
+			(struct cam_subdev_msg_phy_halt_resume_info *) data;
+		int idx;
+		struct cam_csiphy_param *param;
+		unsigned long clk_rate;
+
+		idx = cam_csiphy_get_session_index(csiphy_dev, halt_resume_info->lane_cfg);
+		if (idx >= CSIPHY_MAX_INSTANCES_PER_PHY) {
+			CAM_ERR(CAM_CSIPHY, "Phy session not found %d %d",
+				csiphy_dev->soc_info.index, halt_resume_info->lane_cfg);
+			rc = -EBADR;
+			break;
+		}
+
+		param = &csiphy_dev->csiphy_info[idx];
+		drv_idx = param->conn_csid_idx;
+
+		if (!csiphy_dev->soc_info.is_clk_drv_en || !param->use_hw_client_voting ||
+			!param->is_drv_config_en)
+			break;
+
+		CAM_DBG(CAM_CSIPHY,
+			"PHY: %d, CSID: %d DRV info : use hw client %d, enable drv config %d, op=%s",
+			csiphy_dev->soc_info.index, param->conn_csid_idx,
+			param->use_hw_client_voting, param->is_drv_config_en,
+			(halt_resume_info->csid_state == CAM_SUBDEV_PHY_CSID_HALT) ? "HALT" :
+			"RESUME");
+
+		if (halt_resume_info->csid_state == CAM_SUBDEV_PHY_CSID_HALT) {
+			clk_rate =
+				csiphy_dev->soc_info.applied_src_clk_rates.hw_client[drv_idx].high;
+
+			rc = cam_soc_util_set_src_clk_rate(&csiphy_dev->soc_info,
+				CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
+			if (rc)
+				CAM_ERR(CAM_CSIPHY,
+					"PHY[%d] CSID HALT: csiphy set_rate %ld failed rc: %d",
+					phy_idx, clk_rate, rc);
+		} else if (halt_resume_info->csid_state == CAM_SUBDEV_PHY_CSID_RESUME) {
+			int32_t src_idx = csiphy_dev->soc_info.src_clk_idx;
+
+			clk_rate = csiphy_dev->soc_info.clk_rate[CAM_LOWSVS_VOTE][src_idx];
+
+			rc = cam_soc_util_set_src_clk_rate(&csiphy_dev->soc_info,
+				CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
+			if (rc)
+				CAM_ERR(CAM_CSIPHY,
+					"PHY[%d] CSID RESUME: csiphy _set_rate %ld failed rc: %d",
+					phy_idx, clk_rate, rc);
+		} else {
+			CAM_ERR(CAM_CSIPHY,
+				"CSIPHY:%d Failed to handle CSID halt resume csid_state: %d",
+				phy_idx, halt_resume_info->csid_state);
+		}
+		break;
+	}
 	default:
 		break;
 	}
@@ -431,6 +552,9 @@ static int cam_csiphy_component_bind(struct device *dev,
 		new_csiphy_dev->csiphy_info[i].lane_assign = 0;
 		new_csiphy_dev->csiphy_info[i].lane_enable = 0;
 		new_csiphy_dev->csiphy_info[i].mipi_flags = 0;
+		new_csiphy_dev->csiphy_info[i].conn_csid_idx = -1;
+		new_csiphy_dev->csiphy_info[i].use_hw_client_voting = false;
+		new_csiphy_dev->csiphy_info[i].is_drv_config_en = false;
 	}
 
 	new_csiphy_dev->ops.get_dev_info = NULL;

+ 6 - 0
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h

@@ -334,6 +334,9 @@ struct csiphy_ctrl_t {
  *                                format for scm call
  * @secure_info_updated        :  If all information in the secure_info struct above
  *                                is passed and formatted properly from CSID driver
+ * @conn_csid_idx              : Connected CSID core idx (Primary csid in case of dual ife)
+ * @use_hw_client_voting       : Whether to use hw client voting for clk on chipsets with cesta
+ * @is_drv_config_en           : If drv is configured in CSID
  */
 struct cam_csiphy_param {
 	uint16_t                         lane_assign;
@@ -348,6 +351,9 @@ struct cam_csiphy_param {
 	struct csiphy_hdl_tbl            hdl_data;
 	struct cam_csiphy_tz_secure_info secure_info;
 	bool                             secure_info_updated;
+	int32_t                          conn_csid_idx;
+	bool                             use_hw_client_voting;
+	bool                             is_drv_config_en;
 };
 
 struct csiphy_work_queue {

+ 49 - 19
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c

@@ -179,53 +179,80 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index)
 {
 	int32_t rc = 0;
 	struct cam_hw_soc_info   *soc_info;
-	enum cam_vote_level vote_level = CAM_SVS_VOTE;
+	enum cam_vote_level vote_level;
+	struct cam_csiphy_param *param = &csiphy_dev->csiphy_info[index];
 
 	soc_info = &csiphy_dev->soc_info;
 
 	if (csiphy_dev->ref_count++) {
 		CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d",
 			csiphy_dev->ref_count);
-		return rc;
+		goto end;
 	}
 
 	vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, index);
-	rc = cam_soc_util_enable_platform_resource(soc_info, true,
-		vote_level, true);
-	if (rc < 0) {
-		CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d",
-			rc);
-		return rc;
+
+	rc = cam_soc_util_enable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en && param->use_hw_client_voting) ?
+		param->conn_csid_idx : CAM_CLK_SW_CLIENT_IDX, true, vote_level, true);
+	if (rc) {
+		CAM_ERR(CAM_CSIPHY,
+			"[%s] failed to enable platform resources, clk_drv_en=%d, use_hw_client=%d conn_csid_idx=%d, rc=%d",
+			soc_info->dev_name, soc_info->is_clk_drv_en, param->use_hw_client_voting,
+			param->conn_csid_idx, rc);
+		goto end;
 	}
 
-	rc = cam_soc_util_set_src_clk_rate(soc_info,
-		soc_info->clk_rate[0][soc_info->src_clk_idx]);
+	if (soc_info->is_clk_drv_en && param->use_hw_client_voting && param->is_drv_config_en) {
+		int clk_vote_level_high = vote_level;
+		int clk_vote_level_low = CAM_LOWSVS_VOTE;
+
+		rc = cam_soc_util_set_clk_rate_level(soc_info, param->conn_csid_idx,
+			clk_vote_level_high, clk_vote_level_low, false);
+		if (rc) {
+			CAM_ERR(CAM_CSIPHY,
+				"Failed to set the req clk_rate level[high low]: [%s %s] cesta_client_idx: %d rc: %d",
+				cam_soc_util_get_string_from_level(clk_vote_level_high),
+				cam_soc_util_get_string_from_level(clk_vote_level_low),
+				param->conn_csid_idx, rc);
+			rc = -EINVAL;
+			goto disable_platform_resource;
+		}
+
+		rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx, "csiphy_start");
+		if (rc) {
+			CAM_ERR(CAM_CSIPHY,
+				"[%s] Failed to apply power states for crm client:%d rc:%d",
+				soc_info->dev_name, param->conn_csid_idx, rc);
+			goto disable_platform_resource;
+		}
 
-	if (rc < 0) {
-		CAM_ERR(CAM_CSIPHY, "csiphy_clk_set_rate failed rc: %d", rc);
-		goto csiphy_disable_platform_resource;
 	}
 
 	cam_csiphy_reset(csiphy_dev);
 
 	return rc;
 
-
-csiphy_disable_platform_resource:
-	cam_soc_util_disable_platform_resource(soc_info, true, true);
-
+disable_platform_resource:
+	cam_soc_util_disable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en && param->use_hw_client_voting) ?
+		param->conn_csid_idx : CAM_CLK_SW_CLIENT_IDX,
+		true, true);
+end:
 	return rc;
 }
 
-int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev)
+int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev, int32_t index)
 {
 	struct cam_hw_soc_info   *soc_info;
+	struct cam_csiphy_param *param;
 
 	if (!csiphy_dev || !csiphy_dev->ref_count) {
 		CAM_ERR(CAM_CSIPHY, "csiphy dev NULL / ref_count ZERO");
 		return 0;
 	}
 	soc_info = &csiphy_dev->soc_info;
+	param = &csiphy_dev->csiphy_info[index];
 
 	if (--csiphy_dev->ref_count) {
 		CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d",
@@ -235,7 +262,10 @@ int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev)
 
 	cam_csiphy_reset(csiphy_dev);
 
-	cam_soc_util_disable_platform_resource(soc_info, true, true);
+	cam_soc_util_disable_platform_resource(soc_info,
+		(soc_info->is_clk_drv_en && param->use_hw_client_voting) ?
+		param->conn_csid_idx : CAM_CLK_SW_CLIENT_IDX,
+		true, true);
 
 	return 0;
 }

+ 1 - 1
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h

@@ -65,7 +65,7 @@ int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index);
  *
  * This API disables SOC related parameters
  */
-int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev);
+int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev, int32_t index);
 
 /**
  * @soc_info: Soc info of cam hw driver module

+ 4 - 4
drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c

@@ -2174,8 +2174,8 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
 					power_setting->config_val;
 
 			for (j = 0; j < soc_info->num_clk; j++) {
-				rc = cam_soc_util_clk_enable(soc_info, false,
-					j, 0, NULL);
+				rc = cam_soc_util_clk_enable(soc_info, CAM_CLK_SW_CLIENT_IDX,
+					false, j, 0);
 				if (rc) {
 					CAM_ERR(CAM_UTIL,
 						"Failed in clk enable %d", i);
@@ -2318,7 +2318,7 @@ power_up_failed:
 		switch (power_setting->seq_type) {
 		case SENSOR_MCLK:
 			for (i = soc_info->num_clk - 1; i >= 0; i--) {
-				cam_soc_util_clk_disable(soc_info, false, i);
+				cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i);
 			}
 			ret = cam_config_mclk_reg(ctrl, soc_info, index);
 			if (ret < 0) {
@@ -2475,7 +2475,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
 		switch (pd->seq_type) {
 		case SENSOR_MCLK:
 			for (i = soc_info->num_clk - 1; i >= 0; i--) {
-				cam_soc_util_clk_disable(soc_info, false, i);
+				cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i);
 			}
 
 			ret = cam_config_mclk_reg(ctrl, soc_info, index);

+ 5 - 3
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c

@@ -307,7 +307,8 @@ static int tpg_hw_soc_disable(struct tpg_hw *hw)
 		return -EINVAL;
 	}
 
-	rc = cam_soc_util_disable_platform_resource(hw->soc_info, true, false);
+	rc = cam_soc_util_disable_platform_resource(hw->soc_info, CAM_CLK_SW_CLIENT_IDX, true,
+		false);
 	if (rc) {
 		CAM_ERR(CAM_TPG, "TPG[%d] Disable platform failed %d",
 			hw->hw_idx, rc);
@@ -356,7 +357,7 @@ static int tpg_hw_soc_enable(
 		goto end;
 	}
 
-	rc = cam_soc_util_enable_platform_resource(hw->soc_info, true,
+	rc = cam_soc_util_enable_platform_resource(hw->soc_info, CAM_CLK_SW_CLIENT_IDX, true,
 		clk_level, false);
 	if (rc) {
 		CAM_ERR(CAM_TPG, "TPG[%d] enable platform failed",
@@ -963,7 +964,8 @@ int tpg_hw_reset(struct tpg_hw *hw)
 	/* disable the hw */
 	mutex_lock(&hw->mutex);
 	if (hw->state != TPG_HW_STATE_HW_DISABLED) {
-		rc = cam_soc_util_disable_platform_resource(hw->soc_info, true, false);
+		rc = cam_soc_util_disable_platform_resource(hw->soc_info, CAM_CLK_SW_CLIENT_IDX,
+			true, false);
 		if (rc) {
 			CAM_ERR(CAM_TPG, "TPG[%d] Disable platform failed %d", hw->hw_idx, rc);
 			return rc;

+ 2 - 1
drivers/cam_utils/cam_common_util.c

@@ -283,7 +283,8 @@ void *cam_common_user_dump_clock(
 	}
 
 	addr = (uint64_t *)addr_ptr;
-	*addr++ = hw_info->soc_info.applied_src_clk_rate;
+	*addr++ = cam_soc_util_get_applied_src_clk(&hw_info->soc_info, true);
+
 	return addr;
 }
 

+ 396 - 102
drivers/cam_utils/cam_soc_util.c

@@ -16,6 +16,11 @@
 #include "cam_presil_hw_access.h"
 #include "cam_compat.h"
 
+#if IS_ENABLED(CONFIG_QCOM_CRM)
+#include <soc/qcom/crm.h>
+#include <linux/clk/qcom.h>
+#endif
+
 #define CAM_TO_MASK(bitn)          (1 << (int)(bitn))
 #define CAM_IS_BIT_SET(mask, bit)  ((mask) & CAM_TO_MASK(bit))
 #define CAM_SET_BIT(mask, bit)     ((mask) |= CAM_TO_MASK(bit))
@@ -86,6 +91,135 @@ static char supported_clk_info[256];
 static DEFINE_MUTEX(wrapper_lock);
 static LIST_HEAD(wrapper_clk_list);
 
+#define CAM_IS_VALID_CESTA_IDX(idx) ((idx >= 0) && (idx < CAM_CESTA_MAX_CLIENTS))
+
+#define CAM_CRM_DEV_IDENTIFIER "cam_crm"
+
+const struct device *cam_cesta_crm_dev;
+
+#if IS_ENABLED(CONFIG_QCOM_CRM)
+inline int cam_soc_util_cesta_populate_crm_device(void)
+{
+	cam_cesta_crm_dev =  crm_get_device(CAM_CRM_DEV_IDENTIFIER);
+	if (!cam_cesta_crm_dev) {
+		CAM_ERR(CAM_UTIL, "Failed to get cesta crm dev for %s", CAM_CRM_DEV_IDENTIFIER);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+int cam_soc_util_cesta_channel_switch(uint32_t cesta_client_idx, const char *identifier)
+{
+	int rc = 0;
+
+	if (!cam_cesta_crm_dev) {
+		CAM_ERR(CAM_UTIL, "camera cesta crm device is null");
+		return -EINVAL;
+	}
+
+	if (!CAM_IS_VALID_CESTA_IDX(cesta_client_idx)) {
+		CAM_ERR(CAM_UTIL, "Invalid client index for camera cesta idx: %d max: %d",
+			cesta_client_idx, CAM_CESTA_MAX_CLIENTS);
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_PERF, "CESTA Channel switch : hw client idx %d identifier=%s",
+		cesta_client_idx, identifier);
+
+	rc = crm_write_pwr_states(cam_cesta_crm_dev, cesta_client_idx);
+	if (rc) {
+		CAM_ERR(CAM_UTIL,
+			"Failed to trigger cesta channel switch cesta_client_idx: %u rc: %d",
+			cesta_client_idx, rc);
+		return rc;
+	}
+
+	return rc;
+}
+#else
+inline int cam_soc_util_cesta_populate_crm_device(void)
+{
+	CAM_ERR(CAM_UTIL, "Not supported");
+
+	return -EOPNOTSUPP;
+}
+
+inline int cam_soc_util_cesta_channel_switch(uint32_t cesta_client_idx, const char *identifier)
+{
+	CAM_ERR(CAM_UTIL, "Not supported, cesta_client_idx=%d, identifier=%s",
+		cesta_client_idx, identifier);
+
+	return -EOPNOTSUPP;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_QCOM_CRM) && IS_ENABLED(CONFIG_SPECTRA_USE_CLK_CRM_API)
+static int cam_soc_util_set_cesta_clk_rate(struct cam_hw_soc_info *soc_info,
+	uint32_t cesta_client_idx, unsigned long high_val, unsigned long low_val,
+	unsigned long *applied_high_val, unsigned long *applied_low_val)
+{
+	int32_t src_clk_idx;
+	struct clk *clk = NULL;
+	int rc = 0;
+
+	if (!soc_info || (soc_info->src_clk_idx < 0) ||
+		(soc_info->src_clk_idx >= CAM_SOC_MAX_CLK)) {
+		CAM_ERR(CAM_UTIL, "Invalid src_clk_idx: %d",
+			soc_info ? soc_info->src_clk_idx : -1);
+		return -EINVAL;
+	}
+
+	if (!CAM_IS_VALID_CESTA_IDX(cesta_client_idx)) {
+		CAM_ERR(CAM_UTIL, "Invalid client index for camera cesta idx: %d max: %d",
+			cesta_client_idx, CAM_CESTA_MAX_CLIENTS);
+		return -EINVAL;
+	}
+
+	/* Only source clocks are supported by this API to set HW client clock votes */
+	src_clk_idx = soc_info->src_clk_idx;
+	clk = soc_info->clk[src_clk_idx];
+
+	CAM_DBG(CAM_UTIL, "%s Requested clk rate [high low]: [%llu %llu] cesta_client_idx: %d",
+		soc_info->clk_name[src_clk_idx], high_val, low_val, cesta_client_idx);
+
+	rc = qcom_clk_crm_set_rate(clk, CRM_HW_DRV, cesta_client_idx, CRM_PWR_STATE1, high_val);
+	if (rc) {
+		CAM_ERR(CAM_UTIL,
+			"Failed in setting cesta high clk rate, client idx: %u pwr state: %u clk_val: %llu rc: %d",
+			cesta_client_idx, CRM_PWR_STATE1, high_val, rc);
+		return rc;
+	}
+
+	rc = qcom_clk_crm_set_rate(clk, CRM_HW_DRV, cesta_client_idx, CRM_PWR_STATE0, low_val);
+	if (rc) {
+		CAM_ERR(CAM_UTIL,
+			"Failed in setting cesta low clk rate, client idx: %u pwr state: %u clk_val: %llu rc: %d",
+			cesta_client_idx, CRM_PWR_STATE0, low_val, rc);
+		return rc;
+	}
+
+	if (applied_high_val)
+		*applied_high_val = high_val;
+
+	if (applied_low_val)
+		*applied_low_val = low_val;
+
+	return rc;
+}
+
+#else
+static inline int cam_soc_util_set_cesta_clk_rate(struct cam_hw_soc_info *soc_info,
+	uint32_t cesta_client_idx, unsigned long high_val, unsigned long low_val,
+	unsigned long *applied_high_val, unsigned long *applied_low_val)
+{
+	CAM_ERR(CAM_UTIL, "Not supported, dev=%s, cesta_client_idx=%d, high_val=%ld, low_val=%ld",
+		soc_info->dev_name, cesta_client_idx, high_val, low_val);
+
+	return -EOPNOTSUPP;
+}
+#endif
+
 #if IS_REACHABLE(CONFIG_MSM_MMRM)
 bool cam_is_mmrm_supported_on_current_chip(void)
 {
@@ -559,17 +693,7 @@ int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
 	return -EINVAL;
 }
 
-/**
- * cam_soc_util_get_string_from_level()
- *
- * @brief:     Returns the string for a given clk level
- *
- * @level:     Clock level
- *
- * @return:    String corresponding to the clk level
- */
-static const char *cam_soc_util_get_string_from_level(
-	enum cam_vote_level level)
+const char *cam_soc_util_get_string_from_level(enum cam_vote_level level)
 {
 	switch (level) {
 	case CAM_SUSPEND_VOTE:
@@ -648,32 +772,64 @@ static const struct file_operations cam_soc_util_clk_lvl_options = {
 	.read = cam_soc_util_clk_lvl_options_read,
 };
 
-static int cam_soc_util_set_clk_lvl(void *data, u64 val)
+static int cam_soc_util_set_clk_lvl_override(void *data, u64 val)
+{
+	struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data;
+
+	if ((val <= CAM_SUSPEND_VOTE) || (val >= CAM_MAX_VOTE)) {
+		CAM_WARN(CAM_UTIL, "Invalid clk lvl override %d", val);
+		return 0;
+	}
+
+	if (soc_info->clk_level_valid[val])
+		soc_info->clk_level_override_high = val;
+	else
+		soc_info->clk_level_override_high = 0;
+
+	return 0;
+}
+
+static int cam_soc_util_get_clk_lvl_override(void *data, u64 *val)
+{
+	struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data;
+
+	*val = soc_info->clk_level_override_high;
+
+	return 0;
+}
+
+static int cam_soc_util_set_clk_lvl_override_low(void *data, u64 val)
 {
 	struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data;
 
-	if (val <= CAM_SUSPEND_VOTE || val >= CAM_MAX_VOTE)
+	if ((val <= CAM_SUSPEND_VOTE) || (val >= CAM_MAX_VOTE)) {
+		CAM_WARN(CAM_UTIL, "Invalid clk lvl override %d", val);
 		return 0;
+	}
 
-	if (soc_info->clk_level_valid[val] == true)
-		soc_info->clk_level_override = val;
+	if (soc_info->clk_level_valid[val])
+		soc_info->clk_level_override_low = val;
 	else
-		soc_info->clk_level_override = 0;
+		soc_info->clk_level_override_low = 0;
 
 	return 0;
 }
 
-static int cam_soc_util_get_clk_lvl(void *data, u64 *val)
+static int cam_soc_util_get_clk_lvl_override_low(void *data, u64 *val)
 {
 	struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data;
 
-	*val = soc_info->clk_level_override;
+	*val = soc_info->clk_level_override_low;
 
 	return 0;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control,
-	cam_soc_util_get_clk_lvl, cam_soc_util_set_clk_lvl, "%08llu");
+	cam_soc_util_get_clk_lvl_override, cam_soc_util_set_clk_lvl_override, "%08llu");
+
+DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control_low,
+	cam_soc_util_get_clk_lvl_override_low, cam_soc_util_set_clk_lvl_override_low, "%08llu");
+
 
 /**
  * cam_soc_util_create_clk_lvl_debugfs()
@@ -722,6 +878,8 @@ static int cam_soc_util_create_clk_lvl_debugfs(struct cam_hw_soc_info *soc_info)
 		soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_options);
 	dbgfileptr = debugfs_create_file("clk_lvl_control", 0644,
 		soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control);
+	dbgfileptr = debugfs_create_file("clk_lvl_control_low", 0644,
+		soc_info->dentry, soc_info, &cam_soc_util_clk_lvl_control_low);
 	rc = PTR_ERR_OR_ZERO(dbgfileptr);
 end:
 	return rc;
@@ -799,8 +957,9 @@ static int cam_soc_util_get_clk_level_to_apply(
 		}
 	}
 
-	CAM_DBG(CAM_UTIL, "Req level %d, Applying %d",
-		req_level, *apply_level);
+	CAM_DBG(CAM_UTIL, "Req level %s, Applying %s",
+		cam_soc_util_get_string_from_level(req_level),
+		cam_soc_util_get_string_from_level(*apply_level));
 
 	return 0;
 }
@@ -961,8 +1120,8 @@ static int cam_soc_util_set_clk_rate(struct cam_hw_soc_info *soc_info,
 	return rc;
 }
 
-int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
-	int64_t clk_rate)
+int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
+	unsigned long clk_rate_high, unsigned long clk_rate_low)
 {
 	int rc = 0;
 	int i = 0;
@@ -970,7 +1129,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 	int32_t scl_clk_idx;
 	struct clk *clk = NULL;
 	int32_t apply_level;
-	uint32_t clk_level_override = 0;
+	uint32_t clk_level_override_high = 0, clk_level_override_low = 0;
 
 	if (!soc_info || (soc_info->src_clk_idx < 0) ||
 		(soc_info->src_clk_idx >= CAM_SOC_MAX_CLK)) {
@@ -980,40 +1139,59 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 	}
 
 	src_clk_idx = soc_info->src_clk_idx;
-	clk_level_override = soc_info->clk_level_override;
-	if (clk_level_override && clk_rate)
-		clk_rate =
-			soc_info->clk_rate[clk_level_override][src_clk_idx];
+	clk_level_override_high = soc_info->clk_level_override_high;
+	clk_level_override_low = soc_info->clk_level_override_low;
+
+	if (clk_level_override_high && clk_rate_high)
+		clk_rate_high = soc_info->clk_rate[clk_level_override_high][src_clk_idx];
+
+	if (clk_level_override_low && clk_rate_low)
+		clk_rate_low = soc_info->clk_rate[clk_level_override_low][src_clk_idx];
 
 	clk = soc_info->clk[src_clk_idx];
-	rc = cam_soc_util_get_clk_level(soc_info, clk_rate, src_clk_idx,
+	rc = cam_soc_util_get_clk_level(soc_info, clk_rate_high, src_clk_idx,
 		&apply_level);
 	if (rc || (apply_level < 0) || (apply_level >= CAM_MAX_VOTE)) {
 		CAM_ERR(CAM_UTIL,
 			"set %s, rate %lld dev_name = %s apply level = %d",
-			soc_info->clk_name[src_clk_idx], clk_rate,
+			soc_info->clk_name[src_clk_idx], clk_rate_high,
 			soc_info->dev_name, apply_level);
 			return -EINVAL;
 	}
 
-	CAM_DBG(CAM_UTIL, "set %s, rate %lld dev_name = %s apply level = %d",
-		soc_info->clk_name[src_clk_idx], clk_rate,
+	CAM_DBG(CAM_UTIL,
+		"set %s, cesta_client_idx: %d rate [%ld %ld] dev_name = %s apply level = %d",
+		soc_info->clk_name[src_clk_idx], cesta_client_idx, clk_rate_high, clk_rate_low,
 		soc_info->dev_name, apply_level);
 
-	if ((soc_info->cam_cx_ipeak_enable) && (clk_rate >= 0)) {
+	if ((soc_info->cam_cx_ipeak_enable) && (clk_rate_high > 0)) {
 		cam_cx_ipeak_update_vote_cx_ipeak(soc_info,
 			apply_level);
 	}
 
+	if (soc_info->is_clk_drv_en && CAM_IS_VALID_CESTA_IDX(cesta_client_idx)) {
+		rc = cam_soc_util_set_cesta_clk_rate(soc_info, cesta_client_idx, clk_rate_high,
+			clk_rate_low,
+			&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].high,
+			&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].low);
+		if (rc) {
+			CAM_ERR(CAM_UTIL,
+				"Failed in setting cesta clk rates[high low]:[%ld %ld] client_idx:%d rc:%d",
+				clk_rate_high, clk_rate_low, cesta_client_idx, rc);
+			return rc;
+		}
+		goto end;
+	}
+
 	rc = cam_soc_util_set_clk_rate(soc_info, clk,
-		soc_info->clk_name[src_clk_idx], clk_rate,
+		soc_info->clk_name[src_clk_idx], clk_rate_high,
 		CAM_IS_BIT_SET(soc_info->shared_clk_mask, src_clk_idx),
 		true, soc_info->clk_id[src_clk_idx],
-		&soc_info->applied_src_clk_rate);
+		&soc_info->applied_src_clk_rates.sw_client);
 	if (rc) {
 		CAM_ERR(CAM_UTIL,
 			"SET_RATE Failed: src clk: %s, rate %lld, dev_name = %s rc: %d",
-			soc_info->clk_name[src_clk_idx], clk_rate,
+			soc_info->clk_name[src_clk_idx], clk_rate_high,
 			soc_info->dev_name, rc);
 		return rc;
 	}
@@ -1042,6 +1220,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 		}
 	}
 
+end:
 	return 0;
 }
 
@@ -1199,14 +1378,13 @@ error:
 	return rc;
 }
 
-int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
-	bool optional_clk, int32_t clk_idx, int32_t apply_level,
-	unsigned long *applied_clock_rate)
+int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
+	bool optional_clk, int32_t clk_idx, int32_t apply_level)
 {
 	int rc = 0;
 	struct clk *clk;
 	const char *clk_name;
-	int32_t clk_rate;
+	unsigned long clk_rate;
 	uint32_t shared_clk_mask;
 	uint32_t clk_id;
 	bool is_src_clk = false;
@@ -1235,12 +1413,37 @@ int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
 	}
 	if (!clk)
 		return 0;
-	rc = cam_soc_util_set_clk_rate(soc_info, clk, clk_name, clk_rate,
-		CAM_IS_BIT_SET(shared_clk_mask, clk_idx), is_src_clk, clk_id,
-		applied_clock_rate);
-	if (rc)
-		return rc;
 
+	if (is_src_clk && soc_info->is_clk_drv_en && CAM_IS_VALID_CESTA_IDX(cesta_client_idx)) {
+		rc = cam_soc_util_set_cesta_clk_rate(soc_info, cesta_client_idx, clk_rate, clk_rate,
+			&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].high,
+			&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].low);
+		if (rc) {
+			CAM_ERR(CAM_UTIL,
+				"[%s] Failed in setting cesta clk rates[high low]:[%ld %ld] client_idx:%d rc:%d",
+				soc_info->dev_name, clk_rate, clk_rate, cesta_client_idx, rc);
+			return rc;
+		}
+
+		rc = cam_soc_util_cesta_channel_switch(cesta_client_idx, soc_info->dev_name);
+		if (rc) {
+			CAM_ERR(CAM_UTIL,
+				"[%s] Failed to apply power states for cesta client:%d rc:%d",
+				soc_info->dev_name, cesta_client_idx, rc);
+			return rc;
+		}
+	} else {
+		rc = cam_soc_util_set_clk_rate(soc_info, clk, clk_name, clk_rate,
+			CAM_IS_BIT_SET(shared_clk_mask, clk_idx), is_src_clk, clk_id,
+			&soc_info->applied_src_clk_rates.sw_client);
+		if (rc) {
+			CAM_ERR(CAM_UTIL, "[%s] Failed in setting clk rate %ld rc:%d",
+				soc_info->dev_name, clk_rate, rc);
+			return rc;
+		}
+	}
+
+	CAM_DBG(CAM_UTIL, "[%s] : clk enable %s", soc_info->dev_name, clk_name);
 	rc = clk_prepare_enable(clk);
 	if (rc) {
 		CAM_ERR(CAM_UTIL, "enable failed for %s: rc(%d)", clk_name, rc);
@@ -1250,10 +1453,10 @@ int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
 	return rc;
 }
 
-int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info,
+int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
 	bool optional_clk, int32_t clk_idx)
 {
-
+	int rc = 0;
 	struct clk *clk;
 	const char *clk_name;
 	uint32_t shared_clk_mask;
@@ -1279,21 +1482,43 @@ int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info,
 	CAM_DBG(CAM_UTIL, "disable %s", clk_name);
 	if (!clk)
 		return 0;
+
 	clk_disable_unprepare(clk);
 
-	if (CAM_IS_BIT_SET(shared_clk_mask, clk_idx)) {
-		CAM_DBG(CAM_UTIL,
-			"Dev %s clk %s Disabling Shared clk, set 0 rate",
-			soc_info->dev_name, clk_name);
-		cam_soc_util_clk_wrapper_set_clk_rate(clk_id, soc_info, clk, 0);
-	} else if (soc_info->mmrm_handle && (!skip_mmrm_set_rate) &&
-			(soc_info->src_clk_idx == clk_idx)) {
-		CAM_DBG(CAM_UTIL,
-			"Dev %s Disabling %s clk, set 0 rate", soc_info->dev_name, clk_name);
-		cam_soc_util_set_rate_through_mmrm(
-			soc_info->mmrm_handle,
-			soc_info->is_nrt_dev,
-			0, 0, 1);
+	if ((clk_idx == soc_info->src_clk_idx) && soc_info->is_clk_drv_en &&
+		CAM_IS_VALID_CESTA_IDX(cesta_client_idx)) {
+		rc = cam_soc_util_set_cesta_clk_rate(soc_info, cesta_client_idx, 0, 0,
+			&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].high,
+			&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].low);
+		if (rc) {
+			CAM_ERR(CAM_UTIL,
+				"Failed in setting cesta clk rates[high low]:[0 0] client_idx:%d rc:%d",
+				cesta_client_idx, rc);
+			return rc;
+		}
+
+		rc = cam_soc_util_cesta_channel_switch(cesta_client_idx, soc_info->dev_name);
+		if (rc) {
+			CAM_ERR(CAM_CSIPHY,
+				"Failed to apply power states for cesta_client_idx:%d rc:%d",
+				cesta_client_idx, rc);
+			return rc;
+		}
+	} else {
+		if (CAM_IS_BIT_SET(shared_clk_mask, clk_idx)) {
+			CAM_DBG(CAM_UTIL,
+				"Dev %s clk %s Disabling Shared clk, set 0 rate",
+				soc_info->dev_name, clk_name);
+			cam_soc_util_clk_wrapper_set_clk_rate(clk_id, soc_info, clk, 0);
+		} else if (soc_info->mmrm_handle && (!skip_mmrm_set_rate) &&
+				(soc_info->src_clk_idx == clk_idx)) {
+			CAM_DBG(CAM_UTIL, "Dev %s Disabling %s clk, set 0 rate",
+				soc_info->dev_name, clk_name);
+			cam_soc_util_set_rate_through_mmrm(
+				soc_info->mmrm_handle,
+				soc_info->is_nrt_dev,
+				0, 0, 1);
+		}
 	}
 
 	return 0;
@@ -1306,16 +1531,16 @@ int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info,
  *                      in soc_info
  *
  * @soc_info:           Device soc struct to be populated
+ * @cesta_client_idx:   CESTA Client idx for hw client based src clocks
  * @clk_level:          Clk level to apply while enabling
  *
  * @return:             success or failure
  */
 int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
-	enum cam_vote_level clk_level)
+	int cesta_client_idx, enum cam_vote_level clk_level)
 {
 	int                          i, rc = 0;
 	enum cam_vote_level          apply_level;
-	unsigned long                applied_clk_rate;
 
 	if ((soc_info->num_clk == 0) ||
 		(soc_info->num_clk >= CAM_SOC_MAX_CLK)) {
@@ -1326,29 +1551,35 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
 
 	rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level,
 		&apply_level);
-	if (rc)
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "[%s] : failed to get level clk_level=%d, rc=%d",
+			soc_info->dev_name, clk_level, rc);
 		return rc;
+	}
 
 	if (soc_info->cam_cx_ipeak_enable)
 		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
 
-	for (i = 0; i < soc_info->num_clk; i++) {
-		rc = cam_soc_util_clk_enable(soc_info, false, i, apply_level,
-			&applied_clk_rate);
-		if (rc)
-			goto clk_disable;
+	CAM_DBG(CAM_UTIL, "Dev[%s] : cesta client %d, request level %s, apply level %s",
+		soc_info->dev_name, cesta_client_idx,
+		cam_soc_util_get_string_from_level(clk_level),
+		cam_soc_util_get_string_from_level(apply_level));
 
-		if (i == soc_info->src_clk_idx)
-			soc_info->applied_src_clk_rate = applied_clk_rate;
+	memset(&soc_info->applied_src_clk_rates, 0, sizeof(struct cam_soc_util_clk_rates));
 
-		if (soc_info->cam_cx_ipeak_enable) {
-			CAM_DBG(CAM_UTIL,
-			"dev name = %s clk name = %s idx = %d\n"
-			"apply_level = %d clc idx = %d",
-			soc_info->dev_name, soc_info->clk_name[i], i,
-			apply_level, i);
+	for (i = 0; i < soc_info->num_clk; i++) {
+		rc = cam_soc_util_clk_enable(soc_info, cesta_client_idx, false, i, apply_level);
+		if (rc) {
+			CAM_ERR(CAM_UTIL,
+				"[%s] : failed to enable clk apply_level=%d, rc=%d, cesta_client_idx=%d",
+				soc_info->dev_name, apply_level, rc, cesta_client_idx);
+			goto clk_disable;
 		}
 
+		if (soc_info->cam_cx_ipeak_enable)
+			CAM_DBG(CAM_UTIL,
+				"dev name = %s clk name = %s idx = %d apply_level = %d clc idx = %d",
+				soc_info->dev_name, soc_info->clk_name[i], i, apply_level, i);
 	}
 
 	return rc;
@@ -1357,7 +1588,7 @@ clk_disable:
 	if (soc_info->cam_cx_ipeak_enable)
 		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
 	for (i--; i >= 0; i--) {
-		cam_soc_util_clk_disable(soc_info, false, i);
+		cam_soc_util_clk_disable(soc_info, cesta_client_idx, false, i);
 	}
 
 	return rc;
@@ -1370,10 +1601,12 @@ clk_disable:
  *                      in soc_info
  *
  * @soc_info:           device soc struct to be populated
+ * @cesta_client_idx:   CESTA Client idx for hw client based src clocks
  *
  * @return:             success or failure
  */
-void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
+void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info,
+	int cesta_client_idx)
 {
 	int i;
 
@@ -1383,7 +1616,7 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
 	if (soc_info->cam_cx_ipeak_enable)
 		cam_cx_ipeak_unvote_cx_ipeak(soc_info);
 	for (i = soc_info->num_clk - 1; i >= 0; i--)
-		cam_soc_util_clk_disable(soc_info, false, i);
+		cam_soc_util_clk_disable(soc_info, cesta_client_idx, false, i);
 }
 
 /**
@@ -1650,26 +1883,40 @@ end:
 }
 
 int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
-	enum cam_vote_level clk_level, bool do_not_set_src_clk)
+	int cesta_client_idx, enum cam_vote_level clk_level_high,
+	enum cam_vote_level clk_level_low, bool do_not_set_src_clk)
 {
 	int i, rc = 0;
-	enum cam_vote_level apply_level;
+	enum cam_vote_level apply_level_high;
+	enum cam_vote_level apply_level_low = CAM_LOWSVS_VOTE;
 	unsigned long applied_clk_rate;
 
 	if ((soc_info->num_clk == 0) ||
 		(soc_info->num_clk >= CAM_SOC_MAX_CLK)) {
-		CAM_ERR(CAM_UTIL, "Invalid number of clock %d",
-			soc_info->num_clk);
+		CAM_ERR(CAM_UTIL, "Invalid number of clock %d", soc_info->num_clk);
 		return -EINVAL;
 	}
 
-	rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level,
-		&apply_level);
-	if (rc)
+	rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level_high,
+		&apply_level_high);
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "[%s] : failed to get level clk_level_high=%d, rc=%d",
+			soc_info->dev_name, clk_level_high, rc);
 		return rc;
+	}
+
+	if (soc_info->is_clk_drv_en && CAM_IS_VALID_CESTA_IDX(cesta_client_idx)) {
+		rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level_low,
+			&apply_level_low);
+		if (rc) {
+			CAM_ERR(CAM_UTIL, "[%s] : failed to get level clk_level_low=%d, rc=%d",
+				soc_info->dev_name, clk_level_low, rc);
+			return rc;
+		}
+	}
 
 	if (soc_info->cam_cx_ipeak_enable)
-		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level_high);
 
 	for (i = 0; i < soc_info->num_clk; i++) {
 		if (do_not_set_src_clk && (i == soc_info->src_clk_idx)) {
@@ -1678,30 +1925,47 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
 			continue;
 		}
 
-		CAM_DBG(CAM_UTIL, "Set rate for clk %s rate %d",
-			soc_info->clk_name[i],
-			soc_info->clk_rate[apply_level][i]);
+		if (soc_info->is_clk_drv_en && CAM_IS_VALID_CESTA_IDX(cesta_client_idx) &&
+			(i == soc_info->src_clk_idx)) {
+			rc = cam_soc_util_set_cesta_clk_rate(soc_info, cesta_client_idx,
+				soc_info->clk_rate[apply_level_high][i],
+				soc_info->clk_rate[apply_level_low][i],
+				&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].high,
+				&soc_info->applied_src_clk_rates.hw_client[cesta_client_idx].low);
+			if (rc) {
+				CAM_ERR(CAM_UTIL,
+					"Failed to set the req clk level[high low]: [%s %s] cesta_client_idx: %d",
+					cam_soc_util_get_string_from_level(apply_level_high),
+					cam_soc_util_get_string_from_level(apply_level_low),
+					cesta_client_idx);
+				break;
+			}
+
+			continue;
+		}
+
+		CAM_DBG(CAM_UTIL, "Set rate for clk %s rate %d", soc_info->clk_name[i],
+			soc_info->clk_rate[apply_level_high][i]);
 
 		rc = cam_soc_util_set_clk_rate(soc_info, soc_info->clk[i],
 			soc_info->clk_name[i],
-			soc_info->clk_rate[apply_level][i],
+			soc_info->clk_rate[apply_level_high][i],
 			CAM_IS_BIT_SET(soc_info->shared_clk_mask, i),
 			(i == soc_info->src_clk_idx) ? true : false,
 			soc_info->clk_id[i],
 			&applied_clk_rate);
 		if (rc < 0) {
 			CAM_DBG(CAM_UTIL,
-				"dev name = %s clk_name = %s idx = %d\n"
-				"apply_level = %d",
+				"dev name = %s clk_name = %s idx = %d apply_level = %s",
 				soc_info->dev_name, soc_info->clk_name[i],
-				i, apply_level);
+				i, cam_soc_util_get_string_from_level(apply_level_high));
 			if (soc_info->cam_cx_ipeak_enable)
 				cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
 			break;
 		}
 
 		if (i == soc_info->src_clk_idx)
-			soc_info->applied_src_clk_rate = applied_clk_rate;
+			soc_info->applied_src_clk_rates.sw_client = applied_clk_rate;
 	}
 
 	return rc;
@@ -2182,8 +2446,8 @@ int cam_soc_util_regulator_enable(struct regulator *rgltr,
 	}
 
 	if (regulator_count_voltages(rgltr) > 0) {
-		CAM_DBG(CAM_UTIL, "voltage min=%d, max=%d",
-			rgltr_min_volt, rgltr_max_volt);
+		CAM_DBG(CAM_UTIL, "[%s] voltage min=%d, max=%d",
+			rgltr_name, rgltr_min_volt, rgltr_max_volt);
 
 		rc = regulator_set_voltage(
 			rgltr, rgltr_min_volt, rgltr_max_volt);
@@ -2410,6 +2674,8 @@ static int cam_soc_util_regulator_enable_default(
 	}
 
 	for (j = 0; j < num_rgltr; j++) {
+		CAM_DBG(CAM_UTIL, "[%s] : start regulator %s enable, rgltr_ctrl_support %d",
+			soc_info->dev_name, soc_info->rgltr_name[j], soc_info->rgltr_ctrl_support);
 		if (soc_info->rgltr_ctrl_support == true) {
 			rc = cam_soc_util_regulator_enable(soc_info->rgltr[j],
 				soc_info->rgltr_name[j],
@@ -2851,7 +3117,8 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info)
 }
 
 int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
-	bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq)
+	int cesta_client_idx, bool enable_clocks, enum cam_vote_level clk_level,
+	bool enable_irq)
 {
 	int rc = 0;
 
@@ -2865,7 +3132,7 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
 	}
 
 	if (enable_clocks) {
-		rc = cam_soc_util_clk_enable_default(soc_info, clk_level);
+		rc = cam_soc_util_clk_enable_default(soc_info, cesta_client_idx, clk_level);
 		if (rc)
 			goto disable_regulator;
 	}
@@ -2880,7 +3147,7 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
 
 disable_clk:
 	if (enable_clocks)
-		cam_soc_util_clk_disable_default(soc_info);
+		cam_soc_util_clk_disable_default(soc_info, cesta_client_idx);
 
 disable_regulator:
 	cam_soc_util_regulator_disable_default(soc_info);
@@ -2889,7 +3156,7 @@ disable_regulator:
 }
 
 int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info,
-	bool disable_clocks, bool disable_irq)
+	int cesta_client_idx, bool disable_clocks, bool disable_irq)
 {
 	int rc = 0;
 
@@ -2900,7 +3167,7 @@ int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info,
 		rc |= cam_soc_util_irq_disable(soc_info);
 
 	if (disable_clocks)
-		cam_soc_util_clk_disable_default(soc_info);
+		cam_soc_util_clk_disable_default(soc_info, cesta_client_idx);
 
 	cam_soc_util_regulator_disable_default(soc_info);
 
@@ -3649,6 +3916,33 @@ int cam_soc_util_print_clk_freq(struct cam_hw_soc_info *soc_info)
 	return 0;
 }
 
+inline unsigned long cam_soc_util_get_applied_src_clk(
+	struct cam_hw_soc_info *soc_info, bool is_max)
+{
+	unsigned long clk_rate;
+
+	/*
+	 * For CRMC type, exa - ife, csid, cphy
+	 *     final clk = max(hw_client_0, hw_client_1, hw_client_2, sw_client)
+	 * For CRMB type, exa - camnoc axi
+	 *     final clk = max(hw_client_0 + hw_client_1 + hw_client_2, sw_client)
+	 */
+
+	if (is_max) {
+		clk_rate = max(soc_info->applied_src_clk_rates.hw_client[0].high,
+			soc_info->applied_src_clk_rates.hw_client[1].high);
+		clk_rate = max(clk_rate, soc_info->applied_src_clk_rates.hw_client[2].high);
+		clk_rate = max(clk_rate, soc_info->applied_src_clk_rates.sw_client);
+	} else {
+		clk_rate = max((soc_info->applied_src_clk_rates.hw_client[0].high +
+			soc_info->applied_src_clk_rates.hw_client[1].high +
+			soc_info->applied_src_clk_rates.hw_client[2].high),
+			soc_info->applied_src_clk_rates.sw_client);
+	}
+
+	return clk_rate;
+}
+
 int cam_soc_util_regulators_enabled(struct cam_hw_soc_info *soc_info)
 {
 	int j = 0, rc = 0;

+ 112 - 19
drivers/cam_utils/cam_soc_util.h

@@ -57,6 +57,9 @@
 /* Maximum length of tag while dumping */
 #define CAM_SOC_HW_DUMP_TAG_MAX_LEN 32
 
+/* Client index to be used to vote clk frequency through sw client */
+#define CAM_CLK_SW_CLIENT_IDX -1
+
 /**
  * enum cam_vote_level - Enum for voting level
  *
@@ -86,6 +89,30 @@ enum cam_vote_level {
 #define CAM_SOC_PINCTRL_STATE_SLEEP "cam_suspend"
 #define CAM_SOC_PINCTRL_STATE_DEFAULT "cam_default"
 
+#define CAM_CESTA_MAX_CLIENTS       3
+
+/**
+ * struct cam_soc_util_hw_client_clk_rates:   Information about HW client clock vote
+ *
+ * @high:               HW client clock vote high value
+ * @low:                HW client clock vote low value
+ **/
+struct cam_soc_util_hw_client_clk_rates {
+	unsigned long high;
+	unsigned long low;
+};
+
+/**
+ * struct cam_soc_util_clk_rates:   Information about clock vote for SW and HW clients
+ *
+ * @sw_client:               SW client clock vote
+ * @hw_client:               HW client clock vote
+ **/
+struct cam_soc_util_clk_rates {
+	unsigned long sw_client;
+	struct cam_soc_util_hw_client_clk_rates hw_client[CAM_CESTA_MAX_CLIENTS];
+};
+
 /**
  * struct cam_soc_reg_map:   Information about the mapped register space
  *
@@ -187,7 +214,7 @@ struct cam_soc_gpio_data {
  *                          through camera clk wrapper for aggregation.
  * @prev_clk_level          Last vote level
  * @src_clk_idx:            Source clock index that is rate-controllable
- * @applied_src_clk_rate    Current clock rate of the core source clk
+ * @applied_src_clk_rates:  Applied src clock rates for SW and HW client
  * @clk_level_valid:        Indicates whether corresponding level is valid
  * @lowest_clk_level:       Lowest clock level that has valid freq info
  * @scl_clk_count:          Number of scalable clocks present
@@ -201,9 +228,13 @@ struct cam_soc_gpio_data {
  *                           through camera clk wrapper for aggregation.
  * @gpio_data:              Pointer to gpio info
  * @mmrm_handle:            MMRM Client handle for src clock
+ * @is_clk_drv_en:          If clock drv is enabled in hw
  * @pinctrl_info:           Pointer to pinctrl info
  * @dentry:                 Debugfs entry
- * @clk_level_override:     Clk level set from debugfs
+ * @clk_level_override_high:Clk level set from debugfs. When cesta is enabled, used to override
+ *                          high clk value
+ * @clk_level_override_high:Low clk level set from debugfs when cesta is enabled, used to override
+ *                          low clk value
  * @clk_control:            Enable/disable clk rate control through debugfs
  * @cam_cx_ipeak_enable     cx-ipeak enable/disable flag
  * @cam_cx_ipeak_bit        cx-ipeak mask for driver
@@ -250,7 +281,7 @@ struct cam_hw_soc_info {
 	uint32_t                        shared_clk_mask;
 	int32_t                         prev_clk_level;
 	int32_t                         src_clk_idx;
-	unsigned long                   applied_src_clk_rate;
+	struct cam_soc_util_clk_rates   applied_src_clk_rates;
 	bool                            clk_level_valid[CAM_MAX_VOTE];
 	uint32_t                        lowest_clk_level;
 	int32_t                         scl_clk_count;
@@ -263,11 +294,14 @@ struct cam_hw_soc_info {
 
 	void                           *mmrm_handle;
 
+	bool                            is_clk_drv_en;
+
 	struct cam_soc_gpio_data       *gpio_data;
 	struct cam_soc_pinctrl_info     pinctrl_info;
 
 	struct dentry                  *dentry;
-	uint32_t                        clk_level_override;
+	uint32_t                        clk_level_override_high;
+	uint32_t                        clk_level_override_low;
 	bool                            clk_control_enable;
 	bool                            cam_cx_ipeak_enable;
 	int32_t                         cam_cx_ipeak_bit;
@@ -410,6 +444,7 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info);
  * @brief:              Enable regulator, irq resources
  *
  * @soc_info:           Device soc information
+ * @cesta_client_idx:   CESTA Client idx for hw client based src clocks
  * @enable_clocks:      Boolean flag:
  *                          TRUE: Enable all clocks in soc_info Now.
  *                          False: Don't enable clocks Now. Driver will
@@ -425,7 +460,8 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info);
  * @return:             Success or failure
  */
 int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
-	bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq);
+	int cesta_client_idx, bool enable_clocks, enum cam_vote_level clk_level,
+	bool enable_irq);
 
 /**
  * cam_soc_util_disable_platform_resource()
@@ -433,6 +469,7 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
  * @brief:              Disable regulator, irq resources
  *
  * @soc_info:           Device soc information
+ * @cesta_client_idx:   CESTA Client idx for hw client based src clocks
  * @disable_irq:        Boolean flag:
  *                          TRUE: Disable IRQ in soc_info Now.
  *                          False: Don't disable IRQ Now. Driver will
@@ -441,7 +478,7 @@ int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
  * @return:             Success or failure
  */
 int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info,
-	bool disable_clocks, bool disable_irq);
+	int cesta_client_idx, bool disable_clocks, bool disable_irq);
 
 /**
  * cam_soc_util_get_clk_round_rate()
@@ -461,15 +498,21 @@ long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info,
 /**
  * cam_soc_util_set_src_clk_rate()
  *
- * @brief:              Set the rate on the source clock.
+ * @brief:              Set the rate on the source clock for sw or hw clients. Requires a valid
+ *                      CESTA client idx for hw client voting.
  *
  * @soc_info:           Device soc information
- * @clk_rate:           Clock rate associated with the src clk
+ * @cesta_client_idx:   CESTA client idx if src clock belongs to cesta client, otherwise -1
+ * @clk_rate_high:      High clock rate associated with the src clk, applies to sw client vote
+ *                      if not cesta client
+ * @clk_rate_low:       Low clock rate associated with the src clk, only applies to cesta based
+ *                      hw client vote
  *
  * @return:             success or failure
  */
-int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
-	int64_t clk_rate);
+int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
+	unsigned long clk_rate_high, unsigned long clk_rate_low);
+
 
 /**
  * cam_soc_util_get_option_clk_by_name()
@@ -505,6 +548,7 @@ int cam_soc_util_put_optional_clk(struct cam_hw_soc_info *soc_info,
  * @brief:              Enable clock specified in params
  *
  * @soc_info:           Device soc information
+ * @cesta_client_idx:   CESTA Client idx for hw client based src clocks
  * @optional_clk:       Whether to set optional clk or normal clk with
  *                      the idx given
  * @clk_idx:            Clock index to set
@@ -513,13 +557,11 @@ int cam_soc_util_put_optional_clk(struct cam_hw_soc_info *soc_info,
  *                      any other value indicate level for normal clocks
  *                      For optional clocks any other value means the rate saved
  *                      in soc_info
- * @applied_clock_rate  Final Clock rate applied to the clk
  *
  * @return:             Success or failure
  */
-int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
-	bool optional_clk, int32_t clk_idx, int32_t apply_level,
-	unsigned long *applied_clock_rate);
+int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
+	bool optional_clk, int32_t clk_idx, int32_t apply_level);
 
 /**
  * cam_soc_util_set_clk_rate_level()
@@ -529,13 +571,16 @@ int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
  *                      the clocks listed in DT based on their values.
  *
  * @soc_info:           Device soc information
- * @clk_level:          Clock level number to set
+ * @cesta_client_idx:   CESTA client idx for HW client based src clocks
+ * @clk_level_high:     Clock level number to set, high value if crm based src clock
+ * @clk_level_low:      Low clock level value if crm based src clock
  * @do_not_set_src_clk: If true, set clock rates except the src clk
  *
  * @return:             Success or failure
  */
 int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
-	enum cam_vote_level clk_level, bool do_not_set_src_clk);
+	int cesta_client_idx, enum cam_vote_level clk_level_high,
+	enum cam_vote_level clk_level_low, bool do_not_set_src_clk);
 
 /**
  * cam_soc_util_clk_disable()
@@ -543,13 +588,14 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
  * @brief:              Disable clock specified in params
  *
  * @soc_info:           Device soc information
+ * @cesta_client_idx:   CESTA Client idx for hw client based src clocks
  * @optional_clk:       Whether to set optional clk or normal clk with
  *                      the idx given
  * @clk_idx:            Clock index to disable
  *
  * @return:             Success or failure
  */
-int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info,
+int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
 	bool optional_clk, int32_t clk_idx);
 
 /**
@@ -716,9 +762,10 @@ static inline uint32_t cam_soc_util_r_mb(struct cam_hw_soc_info *soc_info,
 int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info,
 	uint32_t base_index, uint32_t offset, int size);
 
-void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info);
+void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info,
+	int cesta_client_idx);
 
-int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
+int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info, int cesta_client_idx,
 	enum cam_vote_level clk_level);
 
 int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
@@ -788,4 +835,50 @@ int cam_soc_util_select_pinctrl_state(
  */
 int cam_soc_util_regulators_enabled(struct cam_hw_soc_info *soc_info);
 
+/**
+ * cam_soc_util_cesta_populate_crm_device()
+ *
+ * @brief:              This function populates the camera cesta crm device in soc util
+ *
+ * @return:             success or failure
+ */
+inline int cam_soc_util_cesta_populate_crm_device(void);
+
+/**
+ * cam_soc_util_cesta_channel_switch()
+ *
+ * @brief:              This function triggers the application of power states to crm
+ *                      and channel switch operation in hw. Also, for camera it applies
+ *                      the high vote of the active channel
+ * @cesta_client_idx:   CESTA client index through which power states need to be applied
+ * @identifier:         Identifying the caller triggerring channel switch
+ *
+ * @return:             success or failure
+ */
+int cam_soc_util_cesta_channel_switch(uint32_t cesta_client_idx, const char *identifier);
+
+/**
+ * cam_soc_util_get_applied_src_clk()
+ *
+ * @brief:              Inline function to get applied src clk rate.
+
+ * @soc_info:           Device soc struct to be populated
+ * @is_max:             Is max of all hw clients if cesta is enabled
+ *
+ * @return:             success or failure
+ */
+inline unsigned long cam_soc_util_get_applied_src_clk(
+	struct cam_hw_soc_info *soc_info, bool is_max);
+
+/**
+ * cam_soc_util_get_string_from_level()
+ *
+ * @brief:     Returns the string for a given clk level
+ *
+ * @level:     Clock level
+ *
+ * @return:    String corresponding to the clk level
+ */
+const char *cam_soc_util_get_string_from_level(enum cam_vote_level level);
+
 #endif /* _CAM_SOC_UTIL_H_ */

Some files were not shown because too many files changed in this diff