mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 21:59:12 -04:00
Merge "msm: camera: isp: Move bw voting functions to common file for vfe" into camera-kernel.lnx.1.0
This commit is contained in:
commit
41fdede6bd
13 changed files with 646 additions and 902 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue