Loading drivers/cam_cpas/cam_cpas_intf.c +16 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,22 @@ const char *cam_cpas_axi_util_path_type_to_string( case CAM_AXI_PATH_DATA_OPE_WR_REF: return "OPE_WR_REF"; /* SFE Paths */ case CAM_AXI_PATH_DATA_SFE_NRDI: return "SFE_NRDI"; case CAM_AXI_PATH_DATA_SFE_RDI0: return "IFE_RDI0"; case CAM_AXI_PATH_DATA_SFE_RDI1: return "IFE_RDI1"; case CAM_AXI_PATH_DATA_SFE_RDI2: return "IFE_RDI2"; case CAM_AXI_PATH_DATA_SFE_RDI3: return "IFE_RDI3"; case CAM_AXI_PATH_DATA_SFE_RDI4: return "IFE_RDI4"; case CAM_AXI_PATH_DATA_SFE_STATS: return "SFE_STATS"; /* Common Paths */ case CAM_AXI_PATH_DATA_ALL: return "DATA_ALL"; Loading drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +9 −9 Original line number Diff line number Diff line Loading @@ -3472,8 +3472,8 @@ static int cam_isp_classify_vote_info( struct cam_isp_bw_config_v2 *bw_config, struct cam_axi_vote *isp_vote, uint32_t split_idx, bool *camif_l_bw_updated, bool *camif_r_bw_updated) bool *nrdi_l_bw_updated, bool *nrdi_r_bw_updated) { int rc = 0, i, j = 0; Loading @@ -3482,7 +3482,7 @@ static int cam_isp_classify_vote_info( (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_LCR)) { if (split_idx == CAM_ISP_HW_SPLIT_LEFT) { if (*camif_l_bw_updated) if (*nrdi_l_bw_updated) return rc; for (i = 0; i < bw_config->num_paths; i++) { Loading @@ -3497,9 +3497,9 @@ static int cam_isp_classify_vote_info( } isp_vote->num_paths = j; *camif_l_bw_updated = true; *nrdi_l_bw_updated = true; } else { if (*camif_r_bw_updated) if (*nrdi_r_bw_updated) return rc; for (i = 0; i < bw_config->num_paths; i++) { Loading @@ -3514,7 +3514,7 @@ static int cam_isp_classify_vote_info( } isp_vote->num_paths = j; *camif_r_bw_updated = true; *nrdi_r_bw_updated = true; } } else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && (hw_mgr_res->res_id <= Loading Loading @@ -3570,8 +3570,8 @@ static int cam_isp_blob_bw_update_v2( struct cam_vfe_bw_update_args_v2 bw_upd_args; int rc = -EINVAL; uint32_t i, split_idx; bool camif_l_bw_updated = false; bool camif_r_bw_updated = false; bool nrdi_l_bw_updated = false; bool nrdi_r_bw_updated = false; for (i = 0; i < bw_config->num_paths; i++) { CAM_DBG(CAM_PERF, Loading @@ -3598,7 +3598,7 @@ static int cam_isp_blob_bw_update_v2( sizeof(struct cam_axi_vote)); rc = cam_isp_classify_vote_info(hw_mgr_res, bw_config, &bw_upd_args.isp_vote, split_idx, &camif_l_bw_updated, &camif_r_bw_updated); &nrdi_l_bw_updated, &nrdi_r_bw_updated); if (rc) return rc; Loading drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +1 −1 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #define CAM_TFE_RDI_NUM_MAX 3 /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 30 #define CAM_ISP_MAX_PER_PATH_VOTES 40 /** * enum cam_isp_hw_event_type - Collection of the ISP hardware events Loading drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h +23 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "cam_isp_hw.h" #include "cam_isp_hw_mgr_intf.h" #include "cam_cpas_api.h" #define SFE_CORE_BASE_IDX 0 #define SFE_RT_CDM_BASE_IDX 1 Loading Loading @@ -54,6 +55,28 @@ enum cam_sfe_bus_rd_irq_regs { CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX, }; /* * struct cam_sfe_bw_control_args: * * @node_res: Resource node info * @action: Bandwidth control action */ struct cam_sfe_bw_control_args { struct cam_isp_resource_node *node_res; enum cam_sfe_bw_control_action action; }; /* * struct cam_sfe_bw_update_args: * * @node_res: Resource to get the BW * @sfe_vote: Vote info according to usage data (left/right/rdi) */ struct cam_sfe_bw_update_args { struct cam_isp_resource_node *node_res; struct cam_axi_vote sfe_vote; }; /* * struct cam_sfe_fe_update_args: * Loading drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c +287 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ #include "cam_sfe_soc.h" #include "cam_sfe_core.h" #define CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES 18 struct cam_sfe_core_cfg { uint32_t mode_sel; uint32_t ops_mode_cfg; Loading Loading @@ -41,6 +43,7 @@ struct cam_sfe_top_priv { CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES]; enum cam_sfe_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; spinlock_t spin_lock; Loading Loading @@ -82,6 +85,279 @@ static const char *cam_sfe_top_res_id_to_string( } } static struct cam_axi_vote *cam_sfe_top_delay_bw_reduction( struct cam_sfe_top_priv *top_priv, uint64_t *to_be_applied_bw) { uint32_t i, j; int vote_idx = -1; uint64_t max_bw = 0; uint64_t total_bw; struct cam_axi_vote *curr_l_vote; for (i = 0; i < CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; i++) { total_bw = 0; curr_l_vote = &top_priv->last_vote[i]; for (j = 0; j < curr_l_vote->num_paths; j++) { if (total_bw > (U64_MAX - curr_l_vote->axi_path[j].camnoc_bw)) { CAM_ERR(CAM_PERF, "sfe[%d] : Integer overflow at hist idx: %d, path: %d, total_bw = %llu, camnoc_bw = %llu", top_priv->common_data.hw_intf->hw_idx, i, j, total_bw, curr_l_vote->axi_path[j].camnoc_bw); return NULL; } total_bw += curr_l_vote->axi_path[j].camnoc_bw; } if (total_bw > max_bw) { vote_idx = i; max_bw = total_bw; } } if (vote_idx < 0) return NULL; *to_be_applied_bw = max_bw; return &top_priv->last_vote[vote_idx]; } int cam_sfe_top_set_axi_bw_vote(struct cam_sfe_soc_private *soc_private, struct cam_sfe_top_priv *top_priv, bool start_stop) { struct cam_axi_vote agg_vote = {0}; struct cam_axi_vote *to_be_applied_axi_vote = NULL; int rc = 0; uint32_t i; uint32_t num_paths = 0; uint64_t total_bw_new_vote = 0; bool bw_unchanged = true; bool apply_bw_update = false; for (i = 0; i < top_priv->num_in_ports; i++) { if (top_priv->axi_vote_control[i] == CAM_SFE_BW_CONTROL_INCLUDE) { if (num_paths + top_priv->req_axi_vote[i].num_paths > CAM_CPAS_MAX_PATHS_PER_CLIENT) { CAM_ERR(CAM_PERF, "Required paths(%d) more than max(%d)", num_paths + top_priv->req_axi_vote[i].num_paths, CAM_CPAS_MAX_PATHS_PER_CLIENT); return -EINVAL; } memcpy(&agg_vote.axi_path[num_paths], &top_priv->req_axi_vote[i].axi_path[0], top_priv->req_axi_vote[i].num_paths * sizeof( struct cam_axi_per_path_bw_vote)); num_paths += top_priv->req_axi_vote[i].num_paths; } } agg_vote.num_paths = num_paths; for (i = 0; i < agg_vote.num_paths; i++) { CAM_DBG(CAM_PERF, "sfe[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", top_priv->common_data.hw_intf->hw_idx, top_priv->last_counter, cam_cpas_axi_util_path_type_to_string( agg_vote.axi_path[i].path_data_type), cam_cpas_axi_util_trans_type_to_string( agg_vote.axi_path[i].transac_type), agg_vote.axi_path[i].camnoc_bw, agg_vote.axi_path[i].mnoc_ab_bw, agg_vote.axi_path[i].mnoc_ib_bw); total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; } memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, sizeof(struct cam_axi_vote)); top_priv->last_counter = (top_priv->last_counter + 1) % CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || (total_bw_new_vote != top_priv->total_bw_applied)) bw_unchanged = false; CAM_DBG(CAM_PERF, "applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", top_priv->total_bw_applied, total_bw_new_vote, bw_unchanged, start_stop); if (bw_unchanged) { CAM_DBG(CAM_PERF, "BW config unchanged"); return 0; } if (start_stop) { /* need to vote current request immediately */ to_be_applied_axi_vote = &agg_vote; /* Reset everything, we can start afresh */ memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES); top_priv->last_counter = 0; top_priv->last_vote[top_priv->last_counter] = agg_vote; top_priv->last_counter = (top_priv->last_counter + 1) % CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; } else { /* * Find max bw request in last few frames. This will the bw * that we want to vote to CPAS now. */ to_be_applied_axi_vote = cam_sfe_top_delay_bw_reduction(top_priv, &total_bw_new_vote); if (!to_be_applied_axi_vote) { CAM_ERR(CAM_PERF, "to_be_applied_axi_vote is NULL"); return -EINVAL; } } for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { CAM_DBG(CAM_PERF, "sfe[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", top_priv->common_data.hw_intf->hw_idx, cam_cpas_axi_util_path_type_to_string( to_be_applied_axi_vote->axi_path[i].path_data_type), cam_cpas_axi_util_trans_type_to_string( to_be_applied_axi_vote->axi_path[i].transac_type), to_be_applied_axi_vote->axi_path[i].camnoc_bw, to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); } if ((to_be_applied_axi_vote->num_paths != top_priv->applied_axi_vote.num_paths) || (total_bw_new_vote != top_priv->total_bw_applied)) apply_bw_update = true; CAM_DBG(CAM_PERF, "sfe[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", top_priv->common_data.hw_intf->hw_idx, top_priv->total_bw_applied, total_bw_new_vote, apply_bw_update, start_stop); if (apply_bw_update) { rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, to_be_applied_axi_vote); if (!rc) { memcpy(&top_priv->applied_axi_vote, to_be_applied_axi_vote, sizeof(struct cam_axi_vote)); top_priv->total_bw_applied = total_bw_new_vote; } else { CAM_ERR(CAM_PERF, "BW request failed, rc=%d", rc); } } return rc; } int cam_sfe_top_bw_update(struct cam_sfe_soc_private *soc_private, struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) { struct cam_sfe_bw_update_args *bw_update = NULL; struct cam_isp_resource_node *res = NULL; struct cam_hw_info *hw_info = NULL; int rc = 0; int i; bw_update = (struct cam_sfe_bw_update_args *)cmd_args; res = bw_update->node_res; if (!res || !res->hw_intf || !res->hw_intf->hw_priv) return -EINVAL; hw_info = res->hw_intf->hw_priv; if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { CAM_ERR(CAM_SFE, "SFE:%d Invalid res_type:%d res id%d", res->hw_intf->hw_idx, res->res_type, res->res_id); 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], &bw_update->sfe_vote, sizeof(struct cam_axi_vote)); top_priv->axi_vote_control[i] = CAM_SFE_BW_CONTROL_INCLUDE; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { CAM_ERR_RATE_LIMIT(CAM_SFE, "SFE:%d Not ready to set BW yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); } else { rc = cam_sfe_top_set_axi_bw_vote(soc_private, top_priv, false); } return rc; } int cam_sfe_top_bw_control(struct cam_sfe_soc_private *soc_private, struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) { struct cam_sfe_bw_control_args *bw_ctrl = NULL; struct cam_isp_resource_node *res = NULL; struct cam_hw_info *hw_info = NULL; int rc = 0; int i; bw_ctrl = (struct cam_sfe_bw_control_args *)cmd_args; res = bw_ctrl->node_res; if (!res || !res->hw_intf->hw_priv) return -EINVAL; hw_info = res->hw_intf->hw_priv; if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { CAM_ERR(CAM_SFE, "SFE:%d Invalid res_type:%d res id%d", res->hw_intf->hw_idx, res->res_type, res->res_id); 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; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { CAM_ERR_RATE_LIMIT(CAM_SFE, "SFE:%d Not ready to set BW yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); } else { rc = cam_sfe_top_set_axi_bw_vote(soc_private, top_priv, true); } return rc; } static int cam_sfe_top_core_cfg( struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) Loading Loading @@ -292,6 +568,8 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, { int rc = 0; struct cam_sfe_top_priv *top_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_soc_private *soc_private = NULL; if (!priv) { CAM_ERR(CAM_SFE, "Invalid top_priv"); Loading @@ -299,6 +577,13 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, } top_priv = (struct cam_sfe_top_priv *) priv; soc_info = top_priv->common_data.soc_info; soc_private = soc_info->soc_private; if (!soc_private) { CAM_ERR(CAM_SFE, "soc private is NULL"); return -EINVAL; } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: Loading @@ -310,6 +595,8 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: rc = cam_sfe_top_bw_update(soc_private, top_priv, cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: break; Loading drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c +1 −1 File changed.Contains only whitespace changes. Show changes Loading
drivers/cam_cpas/cam_cpas_intf.c +16 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,22 @@ const char *cam_cpas_axi_util_path_type_to_string( case CAM_AXI_PATH_DATA_OPE_WR_REF: return "OPE_WR_REF"; /* SFE Paths */ case CAM_AXI_PATH_DATA_SFE_NRDI: return "SFE_NRDI"; case CAM_AXI_PATH_DATA_SFE_RDI0: return "IFE_RDI0"; case CAM_AXI_PATH_DATA_SFE_RDI1: return "IFE_RDI1"; case CAM_AXI_PATH_DATA_SFE_RDI2: return "IFE_RDI2"; case CAM_AXI_PATH_DATA_SFE_RDI3: return "IFE_RDI3"; case CAM_AXI_PATH_DATA_SFE_RDI4: return "IFE_RDI4"; case CAM_AXI_PATH_DATA_SFE_STATS: return "SFE_STATS"; /* Common Paths */ case CAM_AXI_PATH_DATA_ALL: return "DATA_ALL"; Loading
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +9 −9 Original line number Diff line number Diff line Loading @@ -3472,8 +3472,8 @@ static int cam_isp_classify_vote_info( struct cam_isp_bw_config_v2 *bw_config, struct cam_axi_vote *isp_vote, uint32_t split_idx, bool *camif_l_bw_updated, bool *camif_r_bw_updated) bool *nrdi_l_bw_updated, bool *nrdi_r_bw_updated) { int rc = 0, i, j = 0; Loading @@ -3482,7 +3482,7 @@ static int cam_isp_classify_vote_info( (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_LCR)) { if (split_idx == CAM_ISP_HW_SPLIT_LEFT) { if (*camif_l_bw_updated) if (*nrdi_l_bw_updated) return rc; for (i = 0; i < bw_config->num_paths; i++) { Loading @@ -3497,9 +3497,9 @@ static int cam_isp_classify_vote_info( } isp_vote->num_paths = j; *camif_l_bw_updated = true; *nrdi_l_bw_updated = true; } else { if (*camif_r_bw_updated) if (*nrdi_r_bw_updated) return rc; for (i = 0; i < bw_config->num_paths; i++) { Loading @@ -3514,7 +3514,7 @@ static int cam_isp_classify_vote_info( } isp_vote->num_paths = j; *camif_r_bw_updated = true; *nrdi_r_bw_updated = true; } } else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && (hw_mgr_res->res_id <= Loading Loading @@ -3570,8 +3570,8 @@ static int cam_isp_blob_bw_update_v2( struct cam_vfe_bw_update_args_v2 bw_upd_args; int rc = -EINVAL; uint32_t i, split_idx; bool camif_l_bw_updated = false; bool camif_r_bw_updated = false; bool nrdi_l_bw_updated = false; bool nrdi_r_bw_updated = false; for (i = 0; i < bw_config->num_paths; i++) { CAM_DBG(CAM_PERF, Loading @@ -3598,7 +3598,7 @@ static int cam_isp_blob_bw_update_v2( sizeof(struct cam_axi_vote)); rc = cam_isp_classify_vote_info(hw_mgr_res, bw_config, &bw_upd_args.isp_vote, split_idx, &camif_l_bw_updated, &camif_r_bw_updated); &nrdi_l_bw_updated, &nrdi_r_bw_updated); if (rc) return rc; Loading
drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +1 −1 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #define CAM_TFE_RDI_NUM_MAX 3 /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */ #define CAM_ISP_MAX_PER_PATH_VOTES 30 #define CAM_ISP_MAX_PER_PATH_VOTES 40 /** * enum cam_isp_hw_event_type - Collection of the ISP hardware events Loading
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h +23 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "cam_isp_hw.h" #include "cam_isp_hw_mgr_intf.h" #include "cam_cpas_api.h" #define SFE_CORE_BASE_IDX 0 #define SFE_RT_CDM_BASE_IDX 1 Loading Loading @@ -54,6 +55,28 @@ enum cam_sfe_bus_rd_irq_regs { CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX, }; /* * struct cam_sfe_bw_control_args: * * @node_res: Resource node info * @action: Bandwidth control action */ struct cam_sfe_bw_control_args { struct cam_isp_resource_node *node_res; enum cam_sfe_bw_control_action action; }; /* * struct cam_sfe_bw_update_args: * * @node_res: Resource to get the BW * @sfe_vote: Vote info according to usage data (left/right/rdi) */ struct cam_sfe_bw_update_args { struct cam_isp_resource_node *node_res; struct cam_axi_vote sfe_vote; }; /* * struct cam_sfe_fe_update_args: * Loading
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c +287 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ #include "cam_sfe_soc.h" #include "cam_sfe_core.h" #define CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES 18 struct cam_sfe_core_cfg { uint32_t mode_sel; uint32_t ops_mode_cfg; Loading Loading @@ -41,6 +43,7 @@ struct cam_sfe_top_priv { CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES]; enum cam_sfe_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; spinlock_t spin_lock; Loading Loading @@ -82,6 +85,279 @@ static const char *cam_sfe_top_res_id_to_string( } } static struct cam_axi_vote *cam_sfe_top_delay_bw_reduction( struct cam_sfe_top_priv *top_priv, uint64_t *to_be_applied_bw) { uint32_t i, j; int vote_idx = -1; uint64_t max_bw = 0; uint64_t total_bw; struct cam_axi_vote *curr_l_vote; for (i = 0; i < CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; i++) { total_bw = 0; curr_l_vote = &top_priv->last_vote[i]; for (j = 0; j < curr_l_vote->num_paths; j++) { if (total_bw > (U64_MAX - curr_l_vote->axi_path[j].camnoc_bw)) { CAM_ERR(CAM_PERF, "sfe[%d] : Integer overflow at hist idx: %d, path: %d, total_bw = %llu, camnoc_bw = %llu", top_priv->common_data.hw_intf->hw_idx, i, j, total_bw, curr_l_vote->axi_path[j].camnoc_bw); return NULL; } total_bw += curr_l_vote->axi_path[j].camnoc_bw; } if (total_bw > max_bw) { vote_idx = i; max_bw = total_bw; } } if (vote_idx < 0) return NULL; *to_be_applied_bw = max_bw; return &top_priv->last_vote[vote_idx]; } int cam_sfe_top_set_axi_bw_vote(struct cam_sfe_soc_private *soc_private, struct cam_sfe_top_priv *top_priv, bool start_stop) { struct cam_axi_vote agg_vote = {0}; struct cam_axi_vote *to_be_applied_axi_vote = NULL; int rc = 0; uint32_t i; uint32_t num_paths = 0; uint64_t total_bw_new_vote = 0; bool bw_unchanged = true; bool apply_bw_update = false; for (i = 0; i < top_priv->num_in_ports; i++) { if (top_priv->axi_vote_control[i] == CAM_SFE_BW_CONTROL_INCLUDE) { if (num_paths + top_priv->req_axi_vote[i].num_paths > CAM_CPAS_MAX_PATHS_PER_CLIENT) { CAM_ERR(CAM_PERF, "Required paths(%d) more than max(%d)", num_paths + top_priv->req_axi_vote[i].num_paths, CAM_CPAS_MAX_PATHS_PER_CLIENT); return -EINVAL; } memcpy(&agg_vote.axi_path[num_paths], &top_priv->req_axi_vote[i].axi_path[0], top_priv->req_axi_vote[i].num_paths * sizeof( struct cam_axi_per_path_bw_vote)); num_paths += top_priv->req_axi_vote[i].num_paths; } } agg_vote.num_paths = num_paths; for (i = 0; i < agg_vote.num_paths; i++) { CAM_DBG(CAM_PERF, "sfe[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", top_priv->common_data.hw_intf->hw_idx, top_priv->last_counter, cam_cpas_axi_util_path_type_to_string( agg_vote.axi_path[i].path_data_type), cam_cpas_axi_util_trans_type_to_string( agg_vote.axi_path[i].transac_type), agg_vote.axi_path[i].camnoc_bw, agg_vote.axi_path[i].mnoc_ab_bw, agg_vote.axi_path[i].mnoc_ib_bw); total_bw_new_vote += agg_vote.axi_path[i].camnoc_bw; } memcpy(&top_priv->last_vote[top_priv->last_counter], &agg_vote, sizeof(struct cam_axi_vote)); top_priv->last_counter = (top_priv->last_counter + 1) % CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; if ((agg_vote.num_paths != top_priv->applied_axi_vote.num_paths) || (total_bw_new_vote != top_priv->total_bw_applied)) bw_unchanged = false; CAM_DBG(CAM_PERF, "applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", top_priv->total_bw_applied, total_bw_new_vote, bw_unchanged, start_stop); if (bw_unchanged) { CAM_DBG(CAM_PERF, "BW config unchanged"); return 0; } if (start_stop) { /* need to vote current request immediately */ to_be_applied_axi_vote = &agg_vote; /* Reset everything, we can start afresh */ memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) * CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES); top_priv->last_counter = 0; top_priv->last_vote[top_priv->last_counter] = agg_vote; top_priv->last_counter = (top_priv->last_counter + 1) % CAM_SFE_DELAY_BW_REDUCTION_NUM_FRAMES; } else { /* * Find max bw request in last few frames. This will the bw * that we want to vote to CPAS now. */ to_be_applied_axi_vote = cam_sfe_top_delay_bw_reduction(top_priv, &total_bw_new_vote); if (!to_be_applied_axi_vote) { CAM_ERR(CAM_PERF, "to_be_applied_axi_vote is NULL"); return -EINVAL; } } for (i = 0; i < to_be_applied_axi_vote->num_paths; i++) { CAM_DBG(CAM_PERF, "sfe[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", top_priv->common_data.hw_intf->hw_idx, cam_cpas_axi_util_path_type_to_string( to_be_applied_axi_vote->axi_path[i].path_data_type), cam_cpas_axi_util_trans_type_to_string( to_be_applied_axi_vote->axi_path[i].transac_type), to_be_applied_axi_vote->axi_path[i].camnoc_bw, to_be_applied_axi_vote->axi_path[i].mnoc_ab_bw, to_be_applied_axi_vote->axi_path[i].mnoc_ib_bw); } if ((to_be_applied_axi_vote->num_paths != top_priv->applied_axi_vote.num_paths) || (total_bw_new_vote != top_priv->total_bw_applied)) apply_bw_update = true; CAM_DBG(CAM_PERF, "sfe[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", top_priv->common_data.hw_intf->hw_idx, top_priv->total_bw_applied, total_bw_new_vote, apply_bw_update, start_stop); if (apply_bw_update) { rc = cam_cpas_update_axi_vote(soc_private->cpas_handle, to_be_applied_axi_vote); if (!rc) { memcpy(&top_priv->applied_axi_vote, to_be_applied_axi_vote, sizeof(struct cam_axi_vote)); top_priv->total_bw_applied = total_bw_new_vote; } else { CAM_ERR(CAM_PERF, "BW request failed, rc=%d", rc); } } return rc; } int cam_sfe_top_bw_update(struct cam_sfe_soc_private *soc_private, struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) { struct cam_sfe_bw_update_args *bw_update = NULL; struct cam_isp_resource_node *res = NULL; struct cam_hw_info *hw_info = NULL; int rc = 0; int i; bw_update = (struct cam_sfe_bw_update_args *)cmd_args; res = bw_update->node_res; if (!res || !res->hw_intf || !res->hw_intf->hw_priv) return -EINVAL; hw_info = res->hw_intf->hw_priv; if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { CAM_ERR(CAM_SFE, "SFE:%d Invalid res_type:%d res id%d", res->hw_intf->hw_idx, res->res_type, res->res_id); 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], &bw_update->sfe_vote, sizeof(struct cam_axi_vote)); top_priv->axi_vote_control[i] = CAM_SFE_BW_CONTROL_INCLUDE; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { CAM_ERR_RATE_LIMIT(CAM_SFE, "SFE:%d Not ready to set BW yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); } else { rc = cam_sfe_top_set_axi_bw_vote(soc_private, top_priv, false); } return rc; } int cam_sfe_top_bw_control(struct cam_sfe_soc_private *soc_private, struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) { struct cam_sfe_bw_control_args *bw_ctrl = NULL; struct cam_isp_resource_node *res = NULL; struct cam_hw_info *hw_info = NULL; int rc = 0; int i; bw_ctrl = (struct cam_sfe_bw_control_args *)cmd_args; res = bw_ctrl->node_res; if (!res || !res->hw_intf->hw_priv) return -EINVAL; hw_info = res->hw_intf->hw_priv; if (res->res_type != CAM_ISP_RESOURCE_SFE_IN || res->res_id >= CAM_ISP_HW_SFE_IN_MAX) { CAM_ERR(CAM_SFE, "SFE:%d Invalid res_type:%d res id%d", res->hw_intf->hw_idx, res->res_type, res->res_id); 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; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { CAM_ERR_RATE_LIMIT(CAM_SFE, "SFE:%d Not ready to set BW yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); } else { rc = cam_sfe_top_set_axi_bw_vote(soc_private, top_priv, true); } return rc; } static int cam_sfe_top_core_cfg( struct cam_sfe_top_priv *top_priv, void *cmd_args, uint32_t arg_size) Loading Loading @@ -292,6 +568,8 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, { int rc = 0; struct cam_sfe_top_priv *top_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_soc_private *soc_private = NULL; if (!priv) { CAM_ERR(CAM_SFE, "Invalid top_priv"); Loading @@ -299,6 +577,13 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, } top_priv = (struct cam_sfe_top_priv *) priv; soc_info = top_priv->common_data.soc_info; soc_private = soc_info->soc_private; if (!soc_private) { CAM_ERR(CAM_SFE, "soc private is NULL"); return -EINVAL; } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: Loading @@ -310,6 +595,8 @@ int cam_sfe_top_process_cmd(void *priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: rc = cam_sfe_top_bw_update(soc_private, top_priv, cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: break; Loading
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.c +1 −1 File changed.Contains only whitespace changes. Show changes