diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index 748c324f5496..663bc247b27f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE170_H_ @@ -166,6 +166,7 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { NULL, }, }, + .num_mux = 4, .mux_type = { CAM_VFE_CAMIF_VER_2_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index db61bfbdc84b..6823b6386b91 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -201,6 +201,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = { NULL, }, }, + .num_mux = 5, .mux_type = { CAM_VFE_CAMIF_VER_2_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 03a6409324d8..8acd77d1f1e2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -254,6 +254,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = { .fe_reg = &vfe175_130_fe_reg, .reg_data = &vfe_175_130_fe_reg_data, }, + .num_mux = 6, .mux_type = { CAM_VFE_CAMIF_VER_2_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 48eb7f1b028d..ae65df7c1126 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -304,6 +304,7 @@ static struct cam_vfe_top_ver3_hw_info vfe480_top_hw_info = { .camif_lite_reg = &vfe480_camif_lcr, .reg_data = &vfe480_camif_lcr_reg_data, }, + .num_mux = 6, .mux_type = { CAM_VFE_CAMIF_VER_3_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index 0c94b63be2e0..f356d6c24b20 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE17X_H_ @@ -97,6 +97,7 @@ static struct cam_vfe_top_ver2_hw_info vfe17x_top_hw_info = { &vfe17x_rdi_3_data, }, }, + .num_mux = 4, .mux_type = { CAM_VFE_RDI_VER_1_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 221c372f72b1..c19ade50bec9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -199,6 +199,7 @@ static struct cam_vfe_top_ver3_hw_info vfe48x_top_hw_info = { .rdi_hw_info[1] = &vfe48x_rdi_hw_info[1], .rdi_hw_info[2] = &vfe48x_rdi_hw_info[2], .rdi_hw_info[3] = &vfe48x_rdi_hw_info[3], + .num_mux = 4, .mux_type = { CAM_VFE_RDI_VER_1_0, CAM_VFE_RDI_VER_1_0, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile index 0ed6a870efa9..2ab4651e4271 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile @@ -13,6 +13,6 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw -obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o cam_vfe_top.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o cam_vfe_top.o cam_vfe_top_common.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_top_ver3.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_ver3.o cam_vfe_rdi.o cam_vfe_fe_ver1.o cam_vfe_camif_lite_ver3.o diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c new file mode 100644 index 000000000000..2eae53205c8c --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include "cam_vfe_top_common.h" +#include "cam_debug_util.h" + +static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( + struct cam_vfe_top_priv_common *top_common, + 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_VFE_DELAY_BW_REDUCTION_NUM_FRAMES; i++) { + total_bw = 0; + curr_l_vote = &top_common->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, + "ife[%d] : Integer overflow at hist idx: %d, path: %d, total_bw = %llu, camnoc_bw = %llu", + top_common->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_common->last_vote[vote_idx]; +} + +int cam_vfe_top_set_axi_bw_vote(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, 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_common->num_mux; i++) { + if (top_common->axi_vote_control[i] == + CAM_VFE_BW_CONTROL_INCLUDE) { + if (num_paths + + top_common->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_common->req_axi_vote[i].num_paths, + CAM_CPAS_MAX_PATHS_PER_CLIENT); + return -EINVAL; + } + + memcpy(&agg_vote.axi_path[num_paths], + &top_common->req_axi_vote[i].axi_path[0], + top_common->req_axi_vote[i].num_paths * + sizeof( + struct cam_axi_per_path_bw_vote)); + num_paths += top_common->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, + "ife[%d] : New BW Vote : counter[%d] [%s][%s] [%llu %llu %llu]", + top_common->hw_idx, + top_common->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_common->last_vote[top_common->last_counter], &agg_vote, + sizeof(struct cam_axi_vote)); + top_common->last_counter = (top_common->last_counter + 1) % + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES; + + if ((agg_vote.num_paths != top_common->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_common->total_bw_applied)) + bw_unchanged = false; + + CAM_DBG(CAM_PERF, + "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", + top_common->hw_idx, top_common->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_common->last_vote, 0x0, sizeof(struct cam_axi_vote) * + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); + top_common->last_counter = 0; + top_common->last_vote[top_common->last_counter] = agg_vote; + top_common->last_counter = (top_common->last_counter + 1) % + CAM_VFE_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_vfe_top_delay_bw_reduction(top_common, + &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, + "ife[%d] : Apply BW Vote : [%s][%s] [%llu %llu %llu]", + top_common->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_common->applied_axi_vote.num_paths) || + (total_bw_new_vote != top_common->total_bw_applied)) + apply_bw_update = true; + + CAM_DBG(CAM_PERF, + "ife[%d] : Delayed update: applied_total=%lld, new_total=%lld apply_bw_update=%d, start_stop=%d", + top_common->hw_idx, top_common->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_common->applied_axi_vote, + to_be_applied_axi_vote, + sizeof(struct cam_axi_vote)); + top_common->total_bw_applied = total_bw_new_vote; + } else { + CAM_ERR(CAM_PERF, "BW request failed, rc=%d", rc); + } + } + + return rc; +} + +int cam_vfe_top_bw_update_v2(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bw_update_args_v2 *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_vfe_bw_update_args_v2 *)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_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%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_common->num_mux; i++) { + if (top_common->mux_rsrc[i].res_id == res->res_id) { + memcpy(&top_common->req_axi_vote[i], + &bw_update->isp_vote, + sizeof(struct cam_axi_vote)); + top_common->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_PERF, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(soc_private, top_common, + false); + } + + return rc; +} + +int cam_vfe_top_bw_update(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_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; + struct cam_axi_vote *mux_axi_vote; + bool vid_exists = false; + bool rdi_exists = false; + + bw_update = (struct cam_vfe_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; + + CAM_DBG(CAM_PERF, "res_id=%d, BW=[%lld %lld]", + res->res_id, bw_update->camnoc_bw_bytes, + bw_update->external_bw_bytes); + + if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%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_common->num_mux; i++) { + mux_axi_vote = &top_common->req_axi_vote[i]; + if (top_common->mux_rsrc[i].res_id == res->res_id) { + mux_axi_vote->num_paths = 1; + if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && + (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_RDI0 + + (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); + } else { + /* + * Vote all bw into VIDEO path as we cannot + * differentiate to which path this has to go + */ + mux_axi_vote->axi_path[0].path_data_type = + CAM_AXI_PATH_DATA_IFE_VID; + } + + mux_axi_vote->axi_path[0].transac_type = + CAM_AXI_TRANSACTION_WRITE; + mux_axi_vote->axi_path[0].camnoc_bw = + bw_update->camnoc_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].mnoc_ib_bw = + bw_update->external_bw_bytes; + /* Make ddr bw same as mnoc bw */ + mux_axi_vote->axi_path[0].ddr_ab_bw = + bw_update->external_bw_bytes; + mux_axi_vote->axi_path[0].ddr_ib_bw = + bw_update->external_bw_bytes; + + top_common->axi_vote_control[i] = + CAM_VFE_BW_CONTROL_INCLUDE; + break; + } + + if (mux_axi_vote->num_paths == 1) { + if (mux_axi_vote->axi_path[0].path_data_type == + CAM_AXI_PATH_DATA_IFE_VID) + vid_exists = true; + else if ((mux_axi_vote->axi_path[0].path_data_type >= + CAM_AXI_PATH_DATA_IFE_RDI0) && + (mux_axi_vote->axi_path[0].path_data_type <= + CAM_AXI_PATH_DATA_IFE_RDI3)) + rdi_exists = true; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_PERF, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(soc_private, top_common, + false); + } + + return rc; +} + +int cam_vfe_top_bw_control(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_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_vfe_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_VFE_IN || + res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { + CAM_ERR(CAM_ISP, "VFE:%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_common->num_mux; i++) { + if (top_common->mux_rsrc[i].res_id == res->res_id) { + top_common->axi_vote_control[i] = bw_ctrl->action; + break; + } + } + + if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR_RATE_LIMIT(CAM_PERF, + "VFE:%d Not ready to set BW yet :%d", + res->hw_intf->hw_idx, + hw_info->hw_state); + } else { + rc = cam_vfe_top_set_axi_bw_vote(soc_private, top_common, true); + } + + return rc; +} diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h new file mode 100644 index 000000000000..03be713e6068 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_VFE_TOP_COMMON_H_ +#define _CAM_VFE_TOP_COMMON_H_ + +#define CAM_VFE_TOP_MUX_MAX 6 +#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 18 + +#include "cam_cpas_api.h" +#include "cam_vfe_hw_intf.h" +#include "cam_vfe_soc.h" + +struct cam_vfe_top_priv_common { + struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_MUX_MAX]; + uint32_t num_mux; + uint32_t hw_idx; + struct cam_axi_vote applied_axi_vote; + struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_MUX_MAX]; + struct cam_axi_vote last_vote[ + CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; + uint32_t last_counter; + uint64_t total_bw_applied; + enum cam_vfe_bw_control_action axi_vote_control[CAM_VFE_TOP_MUX_MAX]; +}; + +int cam_vfe_top_set_axi_bw_vote(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, bool start_stop); + +int cam_vfe_top_bw_update_v2(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size); + +int cam_vfe_top_bw_update(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size); + +int cam_vfe_top_bw_control(struct cam_vfe_soc_private *soc_private, + struct cam_vfe_top_priv_common *top_common, void *cmd_args, + uint32_t arg_size); + +#endif /* _CAM_VFE_TOP_COMMON_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 78a72eb6846a..e057b15aee43 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -10,12 +10,10 @@ #include "cam_vfe_top.h" #include "cam_vfe_top_ver2.h" #include "cam_debug_util.h" -#include "cam_cpas_api.h" #include "cam_vfe_soc.h" #define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00003F9F #define CAM_VFE_HW_RESET_HW_VAL 0x00003F87 -#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 struct cam_vfe_top_ver2_common_data { struct cam_hw_soc_info *soc_info; @@ -25,17 +23,10 @@ struct cam_vfe_top_ver2_common_data { struct cam_vfe_top_ver2_priv { struct cam_vfe_top_ver2_common_data common_data; - struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER2_MUX_MAX]; unsigned long hw_clk_rate; - struct cam_axi_vote applied_axi_vote; - struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX]; - unsigned long req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX]; - struct cam_axi_vote last_vote[CAM_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; - uint32_t last_counter; - uint64_t total_bw_applied; - enum cam_vfe_bw_control_action - axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX]; + unsigned long req_clk_rate[ + CAM_VFE_TOP_MUX_MAX]; + struct cam_vfe_top_priv_common top_common; }; static int cam_vfe_top_mux_get_base(struct cam_vfe_top_ver2_priv *top_priv, @@ -94,14 +85,14 @@ static int cam_vfe_top_set_hw_clk_rate( soc_info = top_priv->common_data.soc_info; - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) max_clk_rate = top_priv->req_clk_rate[i]; } if (max_clk_rate == top_priv->hw_clk_rate) return 0; - CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu", + CAM_DBG(CAM_PERF, "VFE: Clock name=%s idx=%d clk=%llu", soc_info->clk_name[soc_info->src_clk_idx], soc_info->src_clk_idx, max_clk_rate); @@ -110,196 +101,7 @@ static int cam_vfe_top_set_hw_clk_rate( if (!rc) top_priv->hw_clk_rate = max_clk_rate; else - CAM_ERR(CAM_ISP, "Set Clock rate failed, rc=%d", rc); - - return rc; -} - -static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( - struct cam_vfe_top_ver2_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_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_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_ISP, "Overflow at idx: %d", j); - 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]; -} - -static int cam_vfe_top_set_axi_bw_vote( - struct cam_vfe_top_ver2_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; - struct cam_hw_soc_info *soc_info = - top_priv->common_data.soc_info; - struct cam_vfe_soc_private *soc_private = - soc_info->soc_private; - bool apply_bw_update = false; - - if (!soc_private) { - CAM_ERR(CAM_ISP, "Error soc_private NULL"); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->axi_vote_control[i] == - CAM_VFE_BW_CONTROL_INCLUDE) { - if (num_paths + - top_priv->req_axi_vote[i].num_paths > - CAM_CPAS_MAX_PATHS_PER_CLIENT) { - CAM_ERR(CAM_ISP, - "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, - "ife[%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_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_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, - "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", - top_priv->common_data.hw_intf->hw_idx, - top_priv->total_bw_applied, total_bw_new_vote, - bw_unchanged, start_stop); - - if (bw_unchanged) { - CAM_DBG(CAM_ISP, "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_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_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_VFE_TOP_VER2_MUX_MAX * - CAM_VFE_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_vfe_top_delay_bw_reduction(top_priv, - &total_bw_new_vote); - if (!to_be_applied_axi_vote) { - CAM_ERR(CAM_ISP, "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, - "ife[%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, - "ife[%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_ISP, "BW request failed, rc=%d", rc); - } - } + CAM_ERR(CAM_PERF, "Set Clock rate failed, rc=%d", rc); return rc; } @@ -331,7 +133,7 @@ static int cam_vfe_top_clock_update( res = clk_update->node_res; if (!res || !res->hw_intf->hw_priv) { - CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + CAM_ERR(CAM_PERF, "Invalid input res %pK", res); return -EINVAL; } @@ -339,21 +141,21 @@ static int cam_vfe_top_clock_update( if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + CAM_ERR(CAM_PERF, "VFE:%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 < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == res->res_id) { top_priv->req_clk_rate[i] = clk_update->clk_rate; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_DBG(CAM_ISP, + CAM_DBG(CAM_PERF, "VFE:%d Not ready to set clocks yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); @@ -363,193 +165,6 @@ static int cam_vfe_top_clock_update( return rc; } -static int cam_vfe_top_bw_update_v2( - struct cam_vfe_top_ver2_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_update_args_v2 *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_vfe_bw_update_args_v2 *)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_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%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 < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, - sizeof(struct cam_axi_vote)); - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - -static int cam_vfe_top_bw_update( - struct cam_vfe_top_ver2_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_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; - struct cam_axi_vote *mux_axi_vote; - bool vid_exists = false; - bool rdi_exists = false; - - bw_update = (struct cam_vfe_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; - - CAM_DBG(CAM_ISP, "res_id=%d, BW=[%lld %lld]", - res->res_id, bw_update->camnoc_bw_bytes, - bw_update->external_bw_bytes); - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%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 < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - mux_axi_vote = &top_priv->req_axi_vote[i]; - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - mux_axi_vote->num_paths = 1; - if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && - (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_RDI0 + - (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); - } else { - /* - * Vote all bw into VIDEO path as we cannot - * differentiate to which path this has to go - */ - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_VID; - } - - mux_axi_vote->axi_path[0].transac_type = - CAM_AXI_TRANSACTION_WRITE; - mux_axi_vote->axi_path[0].camnoc_bw = - bw_update->camnoc_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ib_bw = - bw_update->external_bw_bytes; - /* Make ddr bw same as mnoc bw */ - mux_axi_vote->axi_path[0].ddr_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].ddr_ib_bw = - bw_update->external_bw_bytes; - - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - - if (mux_axi_vote->num_paths == 1) { - if (mux_axi_vote->axi_path[0].path_data_type == - CAM_AXI_PATH_DATA_IFE_VID) - vid_exists = true; - else if ((mux_axi_vote->axi_path[0].path_data_type >= - CAM_AXI_PATH_DATA_IFE_RDI0) && - (mux_axi_vote->axi_path[0].path_data_type <= - CAM_AXI_PATH_DATA_IFE_RDI3)) - rdi_exists = true; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - -static int cam_vfe_top_bw_control( - struct cam_vfe_top_ver2_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_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_vfe_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_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%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 < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_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_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); - } - - return rc; -} - static int cam_vfe_top_mux_get_reg_update( struct cam_vfe_top_ver2_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -638,14 +253,15 @@ int cam_vfe_top_reserve(void *device_priv, acquire_args = &args->vfe_in; - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == acquire_args->res_id && - top_priv->mux_rsrc[i].res_state == + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + acquire_args->res_id && + top_priv->top_common.mux_rsrc[i].res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { rc = cam_vfe_camif_ver2_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -654,7 +270,7 @@ int cam_vfe_top_reserve(void *device_priv, if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_PDLIB) { rc = cam_vfe_camif_lite_ver2_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -662,18 +278,20 @@ int cam_vfe_top_reserve(void *device_priv, if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) { rc = cam_vfe_fe_ver1_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; } - top_priv->mux_rsrc[i].cdm_ops = acquire_args->cdm_ops; - top_priv->mux_rsrc[i].tasklet_info = args->tasklet; - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].cdm_ops = + acquire_args->cdm_ops; + top_priv->top_common.mux_rsrc[i].tasklet_info = + args->tasklet; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_RESERVED; acquire_args->rsrc_node = - &top_priv->mux_rsrc[i]; + &top_priv->top_common.mux_rsrc[i]; rc = 0; break; @@ -715,6 +333,8 @@ int cam_vfe_top_start(void *device_priv, struct cam_vfe_top_ver2_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int rc = 0; if (!device_priv || !start_args) { @@ -723,6 +343,13 @@ int cam_vfe_top_start(void *device_priv, } top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } + mux_res = (struct cam_isp_resource_node *)start_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; @@ -734,7 +361,8 @@ int cam_vfe_top_start(void *device_priv, return rc; } - rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); + rc = cam_vfe_top_set_axi_bw_vote(soc_private, + &top_priv->top_common, true); if (rc) { CAM_ERR(CAM_ISP, "set_axi_bw_vote failed, rc=%d", rc); @@ -785,17 +413,18 @@ int cam_vfe_top_stop(void *device_priv, } if (!rc) { - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == mux_res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + mux_res->res_id) { top_priv->req_clk_rate[i] = 0; top_priv->req_clk_rate[i] = 0; - top_priv->req_axi_vote[i].axi_path[0].camnoc_bw - = 0; - top_priv->req_axi_vote[i].axi_path[0].mnoc_ab_bw - = 0; - top_priv->req_axi_vote[i].axi_path[0].mnoc_ib_bw - = 0; - top_priv->axi_vote_control[i] = + top_priv->top_common.req_axi_vote[i] + .axi_path[0].camnoc_bw = 0; + top_priv->top_common.req_axi_vote[i] + .axi_path[0].mnoc_ab_bw = 0; + top_priv->top_common.req_axi_vote[i] + .axi_path[0].mnoc_ib_bw = 0; + top_priv->top_common.axi_vote_control[i] = CAM_VFE_BW_CONTROL_EXCLUDE; break; } @@ -822,12 +451,20 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, { int rc = 0; struct cam_vfe_top_ver2_priv *top_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; if (!device_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Error! Invalid arguments"); return -EINVAL; } top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: @@ -846,15 +483,16 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE: - rc = cam_vfe_top_bw_update(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: - rc = cam_vfe_top_bw_update_v2(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update_v2(soc_private, + &top_priv->top_common, cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: - rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size); + rc = cam_vfe_top_bw_control(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; default: rc = -EINVAL; @@ -891,56 +529,69 @@ int cam_vfe_top_ver2_init( rc = -ENOMEM; goto free_vfe_top; } + vfe_top->top_priv = top_priv; top_priv->hw_clk_rate = 0; + if (ver2_hw_info->num_mux > CAM_VFE_TOP_MUX_MAX) { + CAM_ERR(CAM_ISP, "Invalid number of input rsrc: %d, max: %d", + ver2_hw_info->num_mux, CAM_VFE_TOP_MUX_MAX); + rc = -EINVAL; + goto free_top_priv; + } - for (i = 0, j = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN; - top_priv->mux_rsrc[i].hw_intf = hw_intf; - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.num_mux = ver2_hw_info->num_mux; + + for (i = 0, j = 0; i < top_priv->top_common.num_mux; i++) { + top_priv->top_common.mux_rsrc[i].res_type = + CAM_ISP_RESOURCE_VFE_IN; + top_priv->top_common.mux_rsrc[i].hw_intf = hw_intf; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; top_priv->req_clk_rate[i] = 0; if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) { - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_CAMIF; rc = cam_vfe_camif_ver2_init(hw_intf, soc_info, &ver2_hw_info->camif_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_LITE_VER_2_0) { - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_PDLIB; rc = cam_vfe_camif_lite_ver2_init(hw_intf, soc_info, &ver2_hw_info->camif_lite_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver2_hw_info->mux_type[i] == CAM_VFE_RDI_VER_1_0) { /* set the RDI resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RDI0 + j++; rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info, &ver2_hw_info->rdi_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver2_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { /* set the RD resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RD; rc = cam_vfe_fe_ver1_init(hw_intf, soc_info, &ver2_hw_info->fe_hw_info, - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) goto deinit_resources; } else { @@ -963,6 +614,7 @@ int cam_vfe_top_ver2_init( top_priv->common_data.soc_info = soc_info; top_priv->common_data.hw_intf = hw_intf; + top_priv->top_common.hw_idx = hw_intf->hw_idx; top_priv->common_data.common_reg = ver2_hw_info->common_reg; return rc; @@ -970,26 +622,30 @@ int cam_vfe_top_ver2_init( deinit_resources: for (--i; i >= 0; i--) { if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) { - if (cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_camif_ver2_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif Deinit failed"); } else if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_LITE_VER_2_0) { if (cam_vfe_camif_lite_ver2_deinit( - &top_priv->mux_rsrc[i])) + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif lite deinit failed"); } else if (ver2_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { - if (cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "VFE FE deinit failed"); } else { - if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_rdi_ver2_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "RDI Deinit failed"); } - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; } - kfree(vfe_top->top_priv); +free_top_priv: + kfree(vfe_top->top_priv); free_vfe_top: kfree(vfe_top); end: @@ -1020,35 +676,39 @@ int cam_vfe_top_ver2_deinit(struct cam_vfe_top **vfe_top_ptr) goto free_vfe_top; } - for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) { - top_priv->mux_rsrc[i].res_state = + for (i = 0; i < top_priv->top_common.num_mux; i++) { + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; - if (top_priv->mux_rsrc[i].res_type == + if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_CAMIF_VER_2_0) { - rc = cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_camif_ver2_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_CAMIF_LITE_VER_2_0) { rc = cam_vfe_camif_lite_ver2_deinit( - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif lite deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_RDI_VER_1_0) { - rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_rdi_ver2_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "RDI deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_IN_RD_VER_1_0) { - rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); } } + kfree(vfe_top->top_priv); free_vfe_top: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h index 82e30b4285a5..961bf954aaa1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h @@ -10,8 +10,7 @@ #include "cam_vfe_camif_lite_ver2.h" #include "cam_vfe_rdi.h" #include "cam_vfe_fe_ver1.h" - -#define CAM_VFE_TOP_VER2_MUX_MAX 6 +#include "cam_vfe_top_common.h" enum cam_vfe_top_ver2_module_type { CAM_VFE_TOP_VER2_MODULE_LENS, @@ -50,7 +49,8 @@ struct cam_vfe_top_ver2_hw_info { struct cam_vfe_camif_lite_ver2_hw_info camif_lite_hw_info; struct cam_vfe_rdi_ver2_hw_info rdi_hw_info; struct cam_vfe_fe_ver1_hw_info fe_hw_info; - uint32_t mux_type[CAM_VFE_TOP_VER2_MUX_MAX]; + uint32_t num_mux; + uint32_t mux_type[CAM_VFE_TOP_MUX_MAX]; }; int cam_vfe_top_ver2_init(struct cam_hw_soc_info *soc_info, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index 578b0771821f..a4fbe67aa955 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -10,14 +10,12 @@ #include "cam_vfe_top.h" #include "cam_vfe_top_ver3.h" #include "cam_debug_util.h" -#include "cam_cpas_api.h" #include "cam_vfe_soc.h" #define CAM_VFE_HW_RESET_HW_AND_REG_VAL 0x00000003 #define CAM_VFE_HW_RESET_HW_VAL 0x007F0000 #define CAM_VFE_LITE_HW_RESET_AND_REG_VAL 0x00000002 #define CAM_VFE_LITE_HW_RESET_HW_VAL 0x0000003D -#define CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES 3 struct cam_vfe_top_ver3_common_data { struct cam_hw_soc_info *soc_info; @@ -27,17 +25,10 @@ struct cam_vfe_top_ver3_common_data { struct cam_vfe_top_ver3_priv { struct cam_vfe_top_ver3_common_data common_data; - struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER3_MUX_MAX]; unsigned long hw_clk_rate; - struct cam_axi_vote applied_axi_vote; - struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER3_MUX_MAX]; - unsigned long req_clk_rate[CAM_VFE_TOP_VER3_MUX_MAX]; - struct cam_axi_vote last_vote[CAM_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES]; - uint32_t last_counter; - uint64_t total_bw_applied; - enum cam_vfe_bw_control_action - axi_vote_control[CAM_VFE_TOP_VER3_MUX_MAX]; + unsigned long req_clk_rate[ + CAM_VFE_TOP_MUX_MAX]; + struct cam_vfe_top_priv_common top_common; }; static int cam_vfe_top_ver3_mux_get_base(struct cam_vfe_top_ver3_priv *top_priv, @@ -96,14 +87,14 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( soc_info = top_priv->common_data.soc_info; - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) max_clk_rate = top_priv->req_clk_rate[i]; } if (max_clk_rate == top_priv->hw_clk_rate) return 0; - CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu", + CAM_DBG(CAM_PERF, "VFE: Clock name=%s idx=%d clk=%llu", soc_info->clk_name[soc_info->src_clk_idx], soc_info->src_clk_idx, max_clk_rate); @@ -112,196 +103,7 @@ static int cam_vfe_top_ver3_set_hw_clk_rate( if (!rc) top_priv->hw_clk_rate = max_clk_rate; else - CAM_ERR(CAM_ISP, "Set Clock rate failed, rc=%d", rc); - - return rc; -} - -static struct cam_axi_vote *cam_vfe_top_delay_bw_reduction( - struct cam_vfe_top_ver3_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_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_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_ISP, "Overflow at idx: %d", j); - 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]; -} - -static int cam_vfe_top_ver3_set_axi_bw_vote( - struct cam_vfe_top_ver3_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; - struct cam_hw_soc_info *soc_info = - top_priv->common_data.soc_info; - struct cam_vfe_soc_private *soc_private = - soc_info->soc_private; - bool apply_bw_update = false; - - if (!soc_private) { - CAM_ERR(CAM_ISP, "Error soc_private NULL"); - return -EINVAL; - } - - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->axi_vote_control[i] == - CAM_VFE_BW_CONTROL_INCLUDE) { - if (num_paths + - top_priv->req_axi_vote[i].num_paths > - CAM_CPAS_MAX_PATHS_PER_CLIENT) { - CAM_ERR(CAM_ISP, - "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, - "ife[%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_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_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, - "ife[%d] : applied_total=%lld, new_total=%lld unchanged=%d, start_stop=%d", - top_priv->common_data.hw_intf->hw_idx, - top_priv->total_bw_applied, total_bw_new_vote, - bw_unchanged, start_stop); - - if (bw_unchanged) { - CAM_DBG(CAM_ISP, "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_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_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_VFE_TOP_VER3_MUX_MAX * - CAM_VFE_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_vfe_top_delay_bw_reduction(top_priv, - &total_bw_new_vote); - if (!to_be_applied_axi_vote) { - CAM_ERR(CAM_ISP, "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, - "ife[%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, - "ife[%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_ISP, "BW request failed, rc=%d", rc); - } - } + CAM_ERR(CAM_PERF, "Set Clock rate failed, rc=%d", rc); return rc; } @@ -333,7 +135,7 @@ static int cam_vfe_top_ver3_clock_update( res = clk_update->node_res; if (!res || !res->hw_intf->hw_priv) { - CAM_ERR(CAM_ISP, "Invalid input res %pK", res); + CAM_ERR(CAM_PERF, "Invalid input res %pK", res); return -EINVAL; } @@ -341,21 +143,21 @@ static int cam_vfe_top_ver3_clock_update( if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d", + CAM_ERR(CAM_PERF, "VFE:%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 < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == res->res_id) { top_priv->req_clk_rate[i] = clk_update->clk_rate; break; } } if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_DBG(CAM_ISP, + CAM_DBG(CAM_PERF, "VFE:%d Not ready to set clocks yet :%d", res->hw_intf->hw_idx, hw_info->hw_state); @@ -365,148 +167,6 @@ static int cam_vfe_top_ver3_clock_update( return rc; } -static int cam_vfe_top_ver3_bw_update_v2( - struct cam_vfe_top_ver3_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_bw_update_args_v2 *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_vfe_bw_update_args_v2 *)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_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%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 < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - memcpy(&top_priv->req_axi_vote[i], &bw_update->isp_vote, - sizeof(struct cam_axi_vote)); - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - -static int cam_vfe_top_ver3_bw_update( - struct cam_vfe_top_ver3_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_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; - struct cam_axi_vote *mux_axi_vote; - bool vid_exists = false; - bool rdi_exists = false; - - bw_update = (struct cam_vfe_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; - - CAM_DBG(CAM_ISP, "res_id=%d, BW=[%lld %lld]", - res->res_id, bw_update->camnoc_bw_bytes, - bw_update->external_bw_bytes); - - if (res->res_type != CAM_ISP_RESOURCE_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%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 < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - mux_axi_vote = &top_priv->req_axi_vote[i]; - if (top_priv->mux_rsrc[i].res_id == res->res_id) { - mux_axi_vote->num_paths = 1; - if ((res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) && - (res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) { - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_RDI0 + - (res->res_id - CAM_ISP_HW_VFE_IN_RDI0); - } else { - /* - * Vote all bw into VIDEO path as we cannot - * differentiate to which path this has to go - */ - mux_axi_vote->axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_IFE_VID; - } - - mux_axi_vote->axi_path[0].transac_type = - CAM_AXI_TRANSACTION_WRITE; - mux_axi_vote->axi_path[0].camnoc_bw = - bw_update->camnoc_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].mnoc_ib_bw = - bw_update->external_bw_bytes; - /* Make ddr bw same as mnoc bw */ - mux_axi_vote->axi_path[0].ddr_ab_bw = - bw_update->external_bw_bytes; - mux_axi_vote->axi_path[0].ddr_ib_bw = - bw_update->external_bw_bytes; - - top_priv->axi_vote_control[i] = - CAM_VFE_BW_CONTROL_INCLUDE; - break; - } - - if (mux_axi_vote->num_paths == 1) { - if (mux_axi_vote->axi_path[0].path_data_type == - CAM_AXI_PATH_DATA_IFE_VID) - vid_exists = true; - else if ((mux_axi_vote->axi_path[0].path_data_type >= - CAM_AXI_PATH_DATA_IFE_RDI0) && - (mux_axi_vote->axi_path[0].path_data_type <= - CAM_AXI_PATH_DATA_IFE_RDI3)) - rdi_exists = true; - } - } - - if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) { - CAM_ERR_RATE_LIMIT(CAM_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, false); - } - - return rc; -} - static int cam_vfe_core_config_control( struct cam_vfe_top_ver3_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -520,51 +180,6 @@ static int cam_vfe_core_config_control( return -EINVAL; } -static int cam_vfe_top_ver3_bw_control( - struct cam_vfe_top_ver3_priv *top_priv, - void *cmd_args, uint32_t arg_size) -{ - struct cam_vfe_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_vfe_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_VFE_IN || - res->res_id >= CAM_ISP_HW_VFE_IN_MAX) { - CAM_ERR(CAM_ISP, "VFE:%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 < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_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_ISP, - "VFE:%d Not ready to set BW yet :%d", - res->hw_intf->hw_idx, - hw_info->hw_state); - } else { - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, true); - } - - return rc; -} - static int cam_vfe_top_ver3_mux_get_reg_update( struct cam_vfe_top_ver3_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -680,14 +295,15 @@ int cam_vfe_top_ver3_reserve(void *device_priv, CAM_DBG(CAM_ISP, "res id %d", acquire_args->res_id); - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == acquire_args->res_id && - top_priv->mux_rsrc[i].res_state == + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + acquire_args->res_id && + top_priv->top_common.mux_rsrc[i].res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { rc = cam_vfe_camif_ver3_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -696,7 +312,7 @@ int cam_vfe_top_ver3_reserve(void *device_priv, if (acquire_args->res_id >= CAM_ISP_HW_VFE_IN_RDI0 && acquire_args->res_id < CAM_ISP_HW_VFE_IN_MAX) { rc = cam_vfe_camif_lite_ver3_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; @@ -704,18 +320,20 @@ int cam_vfe_top_ver3_reserve(void *device_priv, if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) { rc = cam_vfe_fe_ver1_acquire_resource( - &top_priv->mux_rsrc[i], + &top_priv->top_common.mux_rsrc[i], args); if (rc) break; } - top_priv->mux_rsrc[i].cdm_ops = acquire_args->cdm_ops; - top_priv->mux_rsrc[i].tasklet_info = args->tasklet; - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].cdm_ops = + acquire_args->cdm_ops; + top_priv->top_common.mux_rsrc[i].tasklet_info = + args->tasklet; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_RESERVED; acquire_args->rsrc_node = - &top_priv->mux_rsrc[i]; + &top_priv->top_common.mux_rsrc[i]; rc = 0; break; @@ -757,6 +375,8 @@ int cam_vfe_top_ver3_start(void *device_priv, struct cam_vfe_top_ver3_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int rc = 0; if (!device_priv || !start_args) { @@ -765,6 +385,13 @@ int cam_vfe_top_ver3_start(void *device_priv, } top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } + mux_res = (struct cam_isp_resource_node *)start_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; @@ -776,7 +403,8 @@ int cam_vfe_top_ver3_start(void *device_priv, return rc; } - rc = cam_vfe_top_ver3_set_axi_bw_vote(top_priv, true); + rc = cam_vfe_top_set_axi_bw_vote(soc_private, + &top_priv->top_common, true); if (rc) { CAM_ERR(CAM_ISP, "set_axi_bw_vote failed, rc=%d", rc); @@ -823,12 +451,13 @@ int cam_vfe_top_ver3_stop(void *device_priv, } if (!rc) { - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - if (top_priv->mux_rsrc[i].res_id == mux_res->res_id) { + for (i = 0; i < top_priv->top_common.num_mux; i++) { + if (top_priv->top_common.mux_rsrc[i].res_id == + mux_res->res_id) { top_priv->req_clk_rate[i] = 0; - memset(&top_priv->req_axi_vote[i], 0, - sizeof(struct cam_axi_vote)); - top_priv->axi_vote_control[i] = + memset(&top_priv->top_common.req_axi_vote[i], + 0, sizeof(struct cam_axi_vote)); + top_priv->top_common.axi_vote_control[i] = CAM_VFE_BW_CONTROL_EXCLUDE; break; } @@ -855,12 +484,21 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, { int rc = 0; struct cam_vfe_top_ver3_priv *top_priv; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; if (!device_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Error, Invalid arguments"); return -EINVAL; } + top_priv = (struct cam_vfe_top_ver3_priv *)device_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Error soc_private NULL"); + return -EINVAL; + } switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: @@ -880,15 +518,16 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE: - rc = cam_vfe_top_ver3_bw_update(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_UPDATE_V2: - rc = cam_vfe_top_ver3_bw_update_v2(top_priv, cmd_args, - arg_size); + rc = cam_vfe_top_bw_update_v2(soc_private, + &top_priv->top_common, cmd_args, arg_size); break; case CAM_ISP_HW_CMD_BW_CONTROL: - rc = cam_vfe_top_ver3_bw_control(top_priv, cmd_args, arg_size); + rc = cam_vfe_top_bw_control(soc_private, &top_priv->top_common, + cmd_args, arg_size); break; case CAM_ISP_HW_CMD_CORE_CONFIG: rc = cam_vfe_core_config_control(top_priv, cmd_args, arg_size); @@ -928,68 +567,82 @@ int cam_vfe_top_ver3_init( rc = -ENOMEM; goto free_vfe_top; } + vfe_top->top_priv = top_priv; top_priv->hw_clk_rate = 0; + if (ver3_hw_info->num_mux > CAM_VFE_TOP_MUX_MAX) { + CAM_ERR(CAM_ISP, "Invalid number of input rsrc: %d, max: %d", + ver3_hw_info->num_mux, CAM_VFE_TOP_MUX_MAX); + rc = -EINVAL; + goto free_top_priv; + } - for (i = 0, j = 0; i < CAM_VFE_TOP_VER3_MUX_MAX && + top_priv->top_common.num_mux = ver3_hw_info->num_mux; + + for (i = 0, j = 0; i < top_priv->top_common.num_mux && j < CAM_VFE_RDI_VER2_MAX; i++) { - top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN; - top_priv->mux_rsrc[i].hw_intf = hw_intf; - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].res_type = + CAM_ISP_RESOURCE_VFE_IN; + top_priv->top_common.mux_rsrc[i].hw_intf = hw_intf; + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; top_priv->req_clk_rate[i] = 0; if (ver3_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_3_0) { - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_CAMIF; rc = cam_vfe_camif_ver3_init(hw_intf, soc_info, &ver3_hw_info->camif_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_PDLIB_VER_1_0) { /* set the PDLIB resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_PDLIB; rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, &ver3_hw_info->pdlib_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { /* set the RD resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RD; rc = cam_vfe_fe_ver1_init(hw_intf, soc_info, &ver3_hw_info->fe_hw_info, - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_RDI_VER_1_0) { /* set the RDI resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_RDI0 + j; rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, ver3_hw_info->rdi_hw_info[j++], - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else if (ver3_hw_info->mux_type[i] == CAM_VFE_LCR_VER_1_0) { /* set the LCR resource id */ - top_priv->mux_rsrc[i].res_id = + top_priv->top_common.mux_rsrc[i].res_id = CAM_ISP_HW_VFE_IN_LCR; rc = cam_vfe_camif_lite_ver3_init(hw_intf, soc_info, &ver3_hw_info->lcr_hw_info, - &top_priv->mux_rsrc[i], vfe_irq_controller); + &top_priv->top_common.mux_rsrc[i], + vfe_irq_controller); if (rc) goto deinit_resources; } else { @@ -1012,6 +665,7 @@ int cam_vfe_top_ver3_init( top_priv->common_data.soc_info = soc_info; top_priv->common_data.hw_intf = hw_intf; + top_priv->top_common.hw_idx = hw_intf->hw_idx; top_priv->common_data.common_reg = ver3_hw_info->common_reg; return rc; @@ -1019,22 +673,26 @@ int cam_vfe_top_ver3_init( deinit_resources: for (--i; i >= 0; i--) { if (ver3_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_3_0) { - if (cam_vfe_camif_ver3_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_camif_ver3_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif Deinit failed"); } else if (ver3_hw_info->mux_type[i] == CAM_VFE_IN_RD_VER_1_0) { - if (cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i])) + if (cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif fe Deinit failed"); } else { if (cam_vfe_camif_lite_ver3_deinit( - &top_priv->mux_rsrc[i])) + &top_priv->top_common.mux_rsrc[i])) CAM_ERR(CAM_ISP, "Camif lite res id %d Deinit failed", - top_priv->mux_rsrc[i].res_id); + top_priv->top_common.mux_rsrc[i] + .res_id); } - top_priv->mux_rsrc[i].res_state = + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; } +free_top_priv: kfree(vfe_top->top_priv); free_vfe_top: kfree(vfe_top); @@ -1066,28 +724,31 @@ int cam_vfe_top_ver3_deinit(struct cam_vfe_top **vfe_top_ptr) goto free_vfe_top; } - for (i = 0; i < CAM_VFE_TOP_VER3_MUX_MAX; i++) { - top_priv->mux_rsrc[i].res_state = + for (i = 0; i < top_priv->top_common.num_mux; i++) { + top_priv->top_common.mux_rsrc[i].res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE; - if (top_priv->mux_rsrc[i].res_type == + if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_CAMIF_VER_3_0) { - rc = cam_vfe_camif_ver3_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_camif_ver3_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); - } else if (top_priv->mux_rsrc[i].res_type == + } else if (top_priv->top_common.mux_rsrc[i].res_type == CAM_VFE_IN_RD_VER_1_0) { - rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]); + rc = cam_vfe_fe_ver1_deinit( + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d", rc); } else { rc = cam_vfe_camif_lite_ver3_deinit( - &top_priv->mux_rsrc[i]); + &top_priv->top_common.mux_rsrc[i]); if (rc) CAM_ERR(CAM_ISP, "Camif lite res id %d Deinit failed", - top_priv->mux_rsrc[i].res_id); + top_priv->top_common.mux_rsrc[i] + .res_id); } } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h index dd0bb94c42c7..14c96097cdf6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -9,8 +9,7 @@ #include "cam_vfe_camif_ver3.h" #include "cam_vfe_camif_lite_ver3.h" #include "cam_vfe_fe_ver1.h" - -#define CAM_VFE_TOP_VER3_MUX_MAX 6 +#include "cam_vfe_top_common.h" #define CAM_SHIFT_TOP_CORE_CFG_MUXSEL_PDAF 31 #define CAM_SHIFT_TOP_CORE_CFG_VID_DS16_R2PD 30 @@ -86,7 +85,8 @@ struct cam_vfe_top_ver3_hw_info { *rdi_hw_info[CAM_VFE_RDI_VER2_MAX]; struct cam_vfe_camif_lite_ver3_hw_info lcr_hw_info; struct cam_vfe_fe_ver1_hw_info fe_hw_info; - uint32_t mux_type[CAM_VFE_TOP_VER3_MUX_MAX]; + uint32_t num_mux; + uint32_t mux_type[CAM_VFE_TOP_MUX_MAX]; }; int cam_vfe_top_ver3_init(struct cam_hw_soc_info *soc_info,