From d707886ae1570d5b1eafe53151cbd8f756b1c7dd Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Mon, 29 Jul 2019 12:03:32 -0700 Subject: [PATCH] msm: camera: isp: Move bw voting functions to common file for vfe Currently, vfe top has different files for different targets. Some of the APIs are unchanged between these files. In order to avoid duplication of code and make sure no change is missed between different versions of vfe top, a common file is added to vfe top for unchanged APIs. With the common top, number of input resources are moved to architecture specific header files to ensure special conditions need not be created for a particular architecture in common code. Move bw voting related APIs to this common file. Change-Id: Ibcb9519a206c25d42c9e7f0336f8d588a8240717 Signed-off-by: Mukund Madhusudan Atre Signed-off-by: Jigarkumar Zala --- .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 3 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 3 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile | 2 +- .../vfe_hw/vfe_top/cam_vfe_top_common.c | 373 ++++++++++++ .../vfe_hw/vfe_top/cam_vfe_top_common.h | 44 ++ .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c | 558 ++++-------------- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h | 6 +- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c | 549 ++++------------- .../isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h | 6 +- 13 files changed, 646 insertions(+), 902 deletions(-) create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.c create mode 100644 drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_common.h 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,