msm: camera: isp: Change Start flow of CSID paths

Enable RX after starting path and change the call
flow of start from hw manager to csid driver.

CRs-Fixed: 2841729
Change-Id: Ie758b1f8cd1137baf1f4eec3d38319e8b4f6e959
Signed-off-by: Gaurav Jindal <gjindal@codeaurora.org>
This commit is contained in:
Gaurav Jindal
2021-04-30 22:39:50 +05:30
committed by Gerrit - the friendly Code Review server
parent c9002665c5
commit afc2f5cbfe
4 changed files with 206 additions and 169 deletions

View File

@@ -639,6 +639,50 @@ err:
return rc;
}
static int cam_ife_mgr_csid_start_hw(
struct cam_ife_hw_mgr_ctx *ctx)
{
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct cam_isp_resource_node *isp_res;
struct cam_isp_resource_node *res[CAM_IFE_PIX_PATH_RES_MAX - 1];
struct cam_csid_hw_start_args start_args;
struct cam_hw_intf *hw_intf;
uint32_t cnt;
int j;
for (j = ctx->num_base - 1 ; j >= 0; j--) {
cnt = 0;
if (ctx->base[j].hw_type != CAM_ISP_HW_TYPE_CSID)
continue;
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
isp_res = hw_mgr_res->hw_res[ctx->base[j].split_id];
if (!isp_res || ctx->base[j].idx != isp_res->hw_intf->hw_idx)
continue;
CAM_DBG(CAM_ISP, "csid[%u] res:%s res_id %d cnt %u",
isp_res->hw_intf->hw_idx,
isp_res->res_name, isp_res->res_id, cnt);
res[cnt] = isp_res;
cnt++;
}
if (cnt) {
hw_intf = res[0]->hw_intf;
start_args.num_res = cnt;
start_args.node_res = res;
hw_intf->hw_ops.start(hw_intf->hw_priv, &start_args,
sizeof(start_args));
}
}
return 0;
}
static int cam_ife_hw_mgr_start_hw_res(
struct cam_isp_hw_mgr_res *isp_hw_res,
struct cam_ife_hw_mgr_ctx *ctx)
@@ -1569,9 +1613,6 @@ static int cam_ife_mgr_process_base_info(
csid_caps = &hw_mgr->csid_hw_caps[res->hw_intf->hw_idx];
if (!csid_caps->need_separate_base)
continue;
cam_ife_mgr_add_base_info(ctx, i,
res->hw_intf->hw_idx,
CAM_ISP_HW_TYPE_CSID);
@@ -6096,14 +6137,7 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", ctx->ctx_index);
/* Start the IFE CSID HW devices */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)",
hw_mgr_res->res_id);
goto err;
}
}
cam_ife_mgr_csid_start_hw(ctx);
/* Start IFE root node: do nothing */
CAM_DBG(CAM_ISP, "Exit...(success)");
@@ -6435,18 +6469,7 @@ start_only:
CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d",
ctx->ctx_index);
/* Start the IFE CSID HW devices */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
if (primary_rdi_csid_res == hw_mgr_res->res_id) {
hw_mgr_res->hw_res[0]->rdi_only_ctx =
ctx->flags.is_rdi_only_context;
}
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)",
hw_mgr_res->res_id);
goto err;
}
}
cam_ife_mgr_csid_start_hw(ctx);
if (ctx->flags.is_tpg) {
CAM_DBG(CAM_ISP, "START TPG HW ... in ctx id:%d",

View File

@@ -2956,70 +2956,70 @@ int cam_ife_csid_ver1_deinit_hw(void *hw_priv,
return rc;
}
int cam_ife_csid_ver1_start(void *hw_priv, void *start_args,
int cam_ife_csid_ver1_start(void *hw_priv, void *args,
uint32_t arg_size)
{
struct cam_ife_csid_ver1_hw *csid_hw = NULL;
struct cam_isp_resource_node *res;
struct cam_hw_info *hw_info;
struct cam_csid_hw_start_args *start_args;
int rc = 0;
uint32_t i = 0;
hw_info = (struct cam_hw_info *)hw_priv;
csid_hw = (struct cam_ife_csid_ver1_hw *)hw_info->core_info;
res = (struct cam_isp_resource_node *)start_args;
if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) {
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
rc = -EINVAL;
goto end;
}
if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
CAM_ERR(CAM_ISP, "CSID:%d Invalid res tpe:%d res id:%d",
csid_hw->hw_intf->hw_idx, res->res_type,
res->res_id);
rc = -EINVAL;
goto end;
}
start_args = (struct cam_csid_hw_start_args *)args;
csid_hw->flags.sof_irq_triggered = false;
csid_hw->counters.irq_debug_cnt = 0;
CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d",
csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
CAM_DBG(CAM_ISP, "CSID:%d num_res %u",
csid_hw->hw_intf->hw_idx, start_args->num_res);
cam_ife_csid_ver1_enable_csi2(csid_hw);
if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG)
cam_ife_csid_ver1_tpg_start(csid_hw);
switch (res->res_id) {
case CAM_IFE_PIX_PATH_RES_IPP:
case CAM_IFE_PIX_PATH_RES_PPP:
rc = cam_ife_csid_ver1_start_pix_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_RDI_0:
case CAM_IFE_PIX_PATH_RES_RDI_1:
case CAM_IFE_PIX_PATH_RES_RDI_2:
case CAM_IFE_PIX_PATH_RES_RDI_3:
case CAM_IFE_PIX_PATH_RES_RDI_4:
rc = cam_ife_csid_ver1_start_rdi_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_UDI_0:
case CAM_IFE_PIX_PATH_RES_UDI_1:
case CAM_IFE_PIX_PATH_RES_UDI_2:
rc = cam_ife_csid_ver1_start_udi_path(csid_hw, res);
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
rc = -EINVAL;
break;
for (i = 0; i < start_args->num_res; i++) {
res = start_args->node_res[i];
if (!res || res->res_type != CAM_ISP_RESOURCE_PIX_PATH) {
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
rc = -EINVAL;
goto end;
}
CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res: %s",
csid_hw->hw_intf->hw_idx, res->res_type,
res->res_name);
switch (res->res_id) {
case CAM_IFE_PIX_PATH_RES_IPP:
case CAM_IFE_PIX_PATH_RES_PPP:
rc = cam_ife_csid_ver1_start_pix_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_RDI_0:
case CAM_IFE_PIX_PATH_RES_RDI_1:
case CAM_IFE_PIX_PATH_RES_RDI_2:
case CAM_IFE_PIX_PATH_RES_RDI_3:
case CAM_IFE_PIX_PATH_RES_RDI_4:
rc = cam_ife_csid_ver1_start_rdi_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_UDI_0:
case CAM_IFE_PIX_PATH_RES_UDI_1:
case CAM_IFE_PIX_PATH_RES_UDI_2:
rc = cam_ife_csid_ver1_start_udi_path(csid_hw, res);
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
rc = -EINVAL;
break;
}
}
if (rc)
if (rc && res)
CAM_ERR(CAM_ISP, "CSID:%d start fail res type:%d res id:%d",
csid_hw->hw_intf->hw_idx, res->res_type,
res->res_id);

View File

@@ -2696,7 +2696,6 @@ static int cam_ife_csid_ver2_init_config_pxl_path(
}
res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
return rc;
}
@@ -2735,7 +2734,7 @@ static inline int cam_ife_csid_ver2_subscribe_sof_for_discard(
return rc;
}
static int cam_ife_csid_ver2_start_rdi_path(
static int cam_ife_csid_ver2_program_rdi_path(
struct cam_ife_csid_ver2_hw *csid_hw,
struct cam_isp_resource_node *res)
{
@@ -2760,15 +2759,6 @@ static int cam_ife_csid_ver2_start_rdi_path(
return rc;
}
if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
res->res_id > CAM_IFE_PIX_PATH_RES_RDI_4) {
CAM_ERR(CAM_ISP,
"CSID:%d %s path res type:%d res_id:%d Invalid state%d",
csid_hw->hw_intf->hw_idx,
res->res_type, res->res_id, res->res_state);
return -EINVAL;
}
soc_info = &csid_hw->hw_info->soc_info;
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
csid_hw->core_info->csid_reg;
@@ -2784,11 +2774,6 @@ static int cam_ife_csid_ver2_start_rdi_path(
mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
if (!csid_hw->flags.offline_mode) {
/* Resume at frame boundary if skip not requested */
if (!path_cfg->discard_init_frames)
cam_io_w_mb(path_reg->resume_frame_boundary,
mem_base + path_reg->ctrl_addr);
CAM_DBG(CAM_ISP, "CSID:%d Rdi res: %d",
csid_hw->hw_intf->hw_idx, res->res_id);
@@ -2901,7 +2886,7 @@ end:
}
static int cam_ife_csid_ver2_start_ipp_path(
static int cam_ife_csid_ver2_program_ipp_path(
struct cam_ife_csid_ver2_hw *csid_hw,
struct cam_isp_resource_node *res)
{
@@ -2926,15 +2911,6 @@ static int cam_ife_csid_ver2_start_ipp_path(
return rc;
}
if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
res->res_id != CAM_IFE_PIX_PATH_RES_IPP) {
CAM_ERR(CAM_ISP,
"CSID:%d %s path res type:%d res_id:%d Invalid state%d",
csid_hw->hw_intf->hw_idx,
res->res_type, res->res_id, res->res_state);
return -EINVAL;
}
soc_info = &csid_hw->hw_info->soc_info;
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
csid_hw->core_info->csid_reg;
@@ -3041,16 +3017,6 @@ static int cam_ife_csid_ver2_start_ipp_path(
val = 0;
}
/*
* Resume at frame boundary if Master or No Sync.
* Slave will get resume command from Master.
* If init frame drop requested skip resume
*/
if ((!path_cfg->discard_init_frames) &&
(path_cfg->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
path_cfg->sync_mode == CAM_ISP_HW_SYNC_NONE))
val |= path_reg->resume_frame_boundary;
cam_io_w_mb(val, mem_base + path_reg->ctrl_addr);
CAM_DBG(CAM_ISP, "CSID:%d Pix res: %d ctrl val: 0x%x",
@@ -3071,7 +3037,73 @@ end:
return rc;
}
static int cam_ife_csid_ver2_start_ppp_path(
static int cam_ife_csid_ver2_enable_path(
struct cam_ife_csid_ver2_hw *csid_hw,
struct cam_isp_resource_node *res)
{
const struct cam_ife_csid_ver2_reg_info *csid_reg;
struct cam_hw_soc_info *soc_info;
const struct cam_ife_csid_ver2_pxl_reg_info *pxl_reg = NULL;
const struct cam_ife_csid_ver2_rdi_reg_info *rdi_reg;
uint32_t val = 0;
uint32_t ctrl_addr = 0;
struct cam_ife_csid_ver2_path_cfg *path_cfg;
void __iomem *mem_base;
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
csid_hw->core_info->csid_reg;
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
soc_info = &csid_hw->hw_info->soc_info;
mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
if (path_cfg->discard_init_frames) {
CAM_DBG(CAM_ISP, "CSID[%u] skip start cmd for res: %s",
csid_hw->hw_intf->hw_idx, res->res_id);
goto end;
}
switch (res->res_id) {
case CAM_IFE_PIX_PATH_RES_IPP:
if (path_cfg->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
return 0;
pxl_reg = csid_reg->ipp_reg;
val = pxl_reg->resume_frame_boundary;
ctrl_addr = pxl_reg->ctrl_addr;
break;
case CAM_IFE_PIX_PATH_RES_PPP:
if (path_cfg->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
return 0;
pxl_reg = csid_reg->ppp_reg;
val = pxl_reg->resume_frame_boundary;
ctrl_addr = pxl_reg->ctrl_addr;
break;
case CAM_IFE_PIX_PATH_RES_RDI_0:
case CAM_IFE_PIX_PATH_RES_RDI_1:
case CAM_IFE_PIX_PATH_RES_RDI_2:
case CAM_IFE_PIX_PATH_RES_RDI_3:
case CAM_IFE_PIX_PATH_RES_RDI_4:
if (csid_hw->flags.offline_mode)
return 0;
rdi_reg = csid_reg->rdi_reg[res->res_id];
val = rdi_reg->resume_frame_boundary;
ctrl_addr = rdi_reg->ctrl_addr;
break;
default:
return -EINVAL;
}
val |= cam_io_r_mb(mem_base + ctrl_addr);
cam_io_w_mb(val, mem_base + ctrl_addr);
CAM_DBG(CAM_ISP, "CSID[%u] start cmd programmed for res: %s",
csid_hw->hw_intf->hw_idx, res->res_id);
end:
/* Change state even if we don't configure start cmd */
res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
return 0;
}
static int cam_ife_csid_ver2_program_ppp_path(
struct cam_ife_csid_ver2_hw *csid_hw,
struct cam_isp_resource_node *res)
{
@@ -3096,15 +3128,6 @@ static int cam_ife_csid_ver2_start_ppp_path(
return rc;
}
if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
res->res_id != CAM_IFE_PIX_PATH_RES_PPP) {
CAM_ERR(CAM_ISP,
"CSID:%d %s path res type:%d res_id:%d Invalid state%d",
csid_hw->hw_intf->hw_idx,
res->res_type, res->res_id, res->res_state);
return -EINVAL;
}
soc_info = &csid_hw->hw_info->soc_info;
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
csid_hw->core_info->csid_reg;
@@ -3152,16 +3175,6 @@ static int cam_ife_csid_ver2_start_ppp_path(
path_reg->start_master_sel_shift;
}
/*
* Resume at frame boundary if Master or No Sync.
* Slave will get resume command from Master.
* If init frame drop requested skip resume
*/
if ((!path_cfg->discard_init_frames) &&
(csid_hw->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
csid_hw->sync_mode == CAM_ISP_HW_SYNC_NONE))
val |= path_reg->resume_frame_boundary;
cam_io_w_mb(val, mem_base + path_reg->ctrl_addr);
CAM_DBG(CAM_ISP, "CSID:%d Pix res: %d ctrl val: 0x%x",
@@ -3176,7 +3189,6 @@ static int cam_ife_csid_ver2_start_ppp_path(
val = csid_hw->debug_info.path_mask;
res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
irq_mask[CAM_IFE_CSID_IRQ_REG_TOP] = top_irq_mask;
irq_mask[path_cfg->irq_reg_idx] = val;
@@ -3786,72 +3798,68 @@ disable_hw:
return rc;
}
int cam_ife_csid_ver2_start(void *hw_priv, void *start_args,
int cam_ife_csid_ver2_start(void *hw_priv, void *args,
uint32_t arg_size)
{
struct cam_ife_csid_ver2_hw *csid_hw = NULL;
struct cam_isp_resource_node *res;
struct cam_isp_resource_node *res;
struct cam_csid_hw_start_args *start_args;
struct cam_hw_info *hw_info;
int rc = 0;
int rc = 0, i;
if (!hw_priv || !start_args) {
if (!hw_priv || !args) {
CAM_ERR(CAM_ISP, "CSID Invalid params");
return -EINVAL;
}
hw_info = (struct cam_hw_info *)hw_priv;
csid_hw = (struct cam_ife_csid_ver2_hw *)hw_info->core_info;
res = (struct cam_isp_resource_node *)start_args;
if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH) {
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
rc = -EINVAL;
goto end;
}
if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
CAM_ERR(CAM_ISP, "CSID:%d Invalid res tpe:%d res id:%d",
csid_hw->hw_intf->hw_idx, res->res_type,
res->res_id);
rc = -EINVAL;
goto end;
}
start_args = (struct cam_csid_hw_start_args *)args;
mutex_lock(&csid_hw->hw_info->hw_mutex);
csid_hw->flags.sof_irq_triggered = false;
csid_hw->counters.irq_debug_cnt = 0;
CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d",
csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
mutex_lock(&csid_hw->hw_info->hw_mutex);
rc = cam_ife_csid_ver2_enable_hw(csid_hw);
cam_ife_csid_ver2_enable_csi2(csid_hw);
switch (res->res_id) {
case CAM_IFE_PIX_PATH_RES_IPP:
rc = cam_ife_csid_ver2_start_ipp_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_PPP:
rc = cam_ife_csid_ver2_start_ppp_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_RDI_0:
case CAM_IFE_PIX_PATH_RES_RDI_1:
case CAM_IFE_PIX_PATH_RES_RDI_2:
case CAM_IFE_PIX_PATH_RES_RDI_3:
case CAM_IFE_PIX_PATH_RES_RDI_4:
rc = cam_ife_csid_ver2_start_rdi_path(csid_hw, res);
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
break;
for (i = 0; i < start_args->num_res; i++) {
res = start_args->node_res[i];
CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d",
csid_hw->hw_intf->hw_idx, res->res_type,
res->res_id);
switch (res->res_id) {
case CAM_IFE_PIX_PATH_RES_IPP:
rc = cam_ife_csid_ver2_program_ipp_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_PPP:
rc = cam_ife_csid_ver2_program_ppp_path(csid_hw, res);
break;
case CAM_IFE_PIX_PATH_RES_RDI_0:
case CAM_IFE_PIX_PATH_RES_RDI_1:
case CAM_IFE_PIX_PATH_RES_RDI_2:
case CAM_IFE_PIX_PATH_RES_RDI_3:
case CAM_IFE_PIX_PATH_RES_RDI_4:
rc = cam_ife_csid_ver2_program_rdi_path(csid_hw, res);
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
csid_hw->hw_intf->hw_idx, res->res_type);
break;
}
}
mutex_unlock(&csid_hw->hw_info->hw_mutex);
for (i = 0; i < start_args->num_res; i++) {
res = start_args->node_res[i];
CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d",
csid_hw->hw_intf->hw_idx, res->res_type,
res->res_id);
cam_ife_csid_ver2_enable_path(csid_hw, res);
}
end:
cam_ife_csid_ver2_enable_csi2(csid_hw);
mutex_unlock(&csid_hw->hw_info->hw_mutex);
return rc;
}

View File

@@ -250,6 +250,12 @@ struct cam_csid_hw_stop_args {
uint32_t num_res;
};
struct cam_csid_hw_start_args {
struct cam_isp_resource_node **node_res;
uint32_t num_res;
};
/**
* enum cam_ife_csid_reset_type - Specify the reset type
*/