diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d8a3806bbe43..eefe16c1e6f5 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -897,6 +897,52 @@ static void cam_ife_hw_mgr_dump_acq_data( } } +static int cam_ife_mgr_csid_change_halt_mode(struct cam_ife_hw_mgr_ctx *ctx, + enum cam_ife_csid_halt_mode halt_mode) +{ + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_ife_csid_hw_halt_args halt; + struct cam_hw_intf *hw_intf; + uint32_t i; + int rc = 0; + + if (!ctx->is_dual) + return 0; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (i == CAM_ISP_HW_SPLIT_LEFT) + continue; + + if (!hw_mgr_res->hw_res[i] || + (hw_mgr_res->hw_res[i]->res_state != + CAM_ISP_RESOURCE_STATE_STREAMING)) + continue; + + isp_res = hw_mgr_res->hw_res[i]; + + if ((isp_res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && + (isp_res->res_id == CAM_IFE_PIX_PATH_RES_IPP)) { + hw_intf = isp_res->hw_intf; + halt.node_res = isp_res; + halt.halt_mode = halt_mode; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, + &halt, + sizeof( + struct cam_ife_csid_hw_halt_args)); + if (rc) + CAM_ERR(CAM_ISP, "Halt update failed"); + break; + } + } + } + + return rc; +} + static int cam_ife_mgr_csid_stop_hw( struct cam_ife_hw_mgr_ctx *ctx, struct list_head *stop_list, uint32_t base_idx, uint32_t stop_cmd) @@ -4074,6 +4120,13 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) */ if (i == ctx->num_base) master_base_idx = ctx->base[0].idx; + + /*Change slave mode*/ + if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) + cam_ife_mgr_csid_change_halt_mode(ctx, + CAM_CSID_HALT_MODE_INTERNAL); + + CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); /* Stop the master CSID path first */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 5f05ef93a1b2..c159c9d64694 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -532,26 +532,30 @@ static int cam_tfe_hw_mgr_free_hw_res( return 0; } -static int cam_tfe_mgr_csid_change_halt_mode(struct list_head *halt_list, - uint32_t base_idx, enum cam_tfe_csid_halt_mode halt_mode) +static int cam_tfe_mgr_csid_change_halt_mode(struct cam_tfe_hw_mgr_ctx *ctx, + enum cam_tfe_csid_halt_mode halt_mode) { - struct cam_isp_hw_mgr_res *hw_mgr_res; - struct cam_isp_resource_node *isp_res; - struct cam_csid_hw_halt_args halt; - struct cam_hw_intf *hw_intf; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *isp_res; + struct cam_tfe_csid_hw_halt_args halt; + struct cam_hw_intf *hw_intf; uint32_t i; int rc = 0; - list_for_each_entry(hw_mgr_res, halt_list, list) { + if (!ctx->is_dual) + return 0; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (i == CAM_ISP_HW_SPLIT_LEFT) + continue; + if (!hw_mgr_res->hw_res[i] || (hw_mgr_res->hw_res[i]->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) continue; isp_res = hw_mgr_res->hw_res[i]; - if (isp_res->hw_intf->hw_idx != base_idx) - continue; if ((isp_res->res_type == CAM_ISP_RESOURCE_PIX_PATH) && (isp_res->res_id == @@ -563,7 +567,8 @@ static int cam_tfe_mgr_csid_change_halt_mode(struct list_head *halt_list, hw_intf->hw_priv, CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, &halt, - sizeof(struct cam_csid_hw_halt_args)); + sizeof( + struct cam_tfe_csid_hw_halt_args)); if (rc) CAM_ERR(CAM_ISP, "Halt update failed"); break; @@ -2798,16 +2803,9 @@ static int cam_tfe_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) master_base_idx = ctx->base[0].idx; /*Change slave mode*/ - if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) { - for (i = 0; i < ctx->num_base; i++) { - if (ctx->base[i].idx == master_base_idx) - continue; - cam_tfe_mgr_csid_change_halt_mode( - &ctx->res_list_tfe_csid, - ctx->base[i].idx, - CAM_TFE_CSID_HALT_MODE_INTERNAL); - } - } + if (csid_halt_type == CAM_CSID_HALT_IMMEDIATELY) + cam_tfe_mgr_csid_change_halt_mode(ctx, + CAM_TFE_CSID_HALT_MODE_INTERNAL); CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index f54356f3ee3a..6a1554bbeeac 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -2344,6 +2344,52 @@ static int cam_ife_csid_enable_pxl_path( return 0; } + +static int cam_ife_csid_change_pxl_halt_mode( + struct cam_ife_csid_hw *csid_hw, + struct cam_ife_csid_hw_halt_args *csid_halt) +{ + uint32_t val = 0; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + const struct cam_ife_csid_pxl_reg_offset *pxl_reg; + struct cam_isp_resource_node *res; + + res = csid_halt->node_res; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_id != CAM_IFE_PIX_PATH_RES_IPP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id %d", + csid_hw->hw_intf->hw_idx, res->res_id); + return -EINVAL; + } + + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { + CAM_ERR(CAM_ISP, "CSID:%d Res:%d in invalid state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return -EINVAL; + } + + pxl_reg = csid_reg->ipp_reg; + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + + /* configure Halt for slave */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val &= ~0xC; + val |= (csid_halt->halt_mode << 2); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + CAM_DBG(CAM_ISP, "CSID:%d IPP path Res halt mode:%d configured:%x", + csid_hw->hw_intf->hw_idx, csid_halt->halt_mode, val); + + return 0; +} + static int cam_ife_csid_disable_pxl_path( struct cam_ife_csid_hw *csid_hw, struct cam_isp_resource_node *res, @@ -3977,6 +4023,47 @@ end: return rc; } +int cam_ife_csid_halt(struct cam_ife_csid_hw *csid_hw, + void *halt_args) +{ + struct cam_isp_resource_node *res; + struct cam_ife_csid_hw_halt_args *csid_halt; + int rc = 0; + + if (!csid_hw || !halt_args) { + CAM_ERR(CAM_ISP, "CSID: Invalid args"); + return -EINVAL; + } + + csid_halt = (struct cam_ife_csid_hw_halt_args *)halt_args; + + /* Change the halt mode */ + res = csid_halt->node_res; + CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_type, res->res_id); + + 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); + return -EINVAL; + } + + switch (res->res_id) { + case CAM_IFE_PIX_PATH_RES_IPP: + rc = cam_ife_csid_change_pxl_halt_mode(csid_hw, csid_halt); + break; + default: + CAM_DBG(CAM_ISP, "CSID:%d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_id); + break; + } + + return rc; +} + int cam_ife_csid_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { @@ -4450,6 +4537,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_LOG_ACQUIRE_DATA: rc = cam_ife_csid_log_acquire_data(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE: + rc = cam_ife_csid_halt(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 28e0c14b3761..0d6e0513d423 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -156,6 +156,33 @@ enum cam_ife_csid_halt_cmd { CAM_CSID_HALT_MAX, }; +/** + * enum cam_ife_csid_halt_mode - Specify the halt command type + */ +enum cam_ife_csid_halt_mode { + CAM_CSID_HALT_MODE_INTERNAL, + CAM_CSID_HALT_MODE_GLOBAL, + CAM_CSID_HALT_MODE_MASTER, + CAM_CSID_HALT_MODE_SLAVE, + CAM_CSID_HALT_MODE_MAX, +}; + +/** + * struct cam_ife_csid_hw_halt_args + * @halt_mode : Applicable only for PATH resources + * 0 Internal : The CSID responds to the HALT_CMD + * 1 Global : The CSID responds to the GLOBAL_HALT_CMD + * 2 Master : The CSID responds to the HALT_CMD + * 3 Slave : The CSID responds to the external halt command + * and not the HALT_CMD register + * @node_res : reource pointer array( ie cid or CSID) + * + */ +struct cam_ife_csid_hw_halt_args { + enum cam_ife_csid_halt_mode halt_mode; + struct cam_isp_resource_node *node_res; +}; + /** * struct cam_csid_hw_stop- stop all resources * @stop_cmd : Applicable only for PATH resources diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h index 37094775db62..1f274be9eb0b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h @@ -96,7 +96,7 @@ enum cam_tfe_csid_halt_cmd { }; /** - * enum cam_tfe_csid_halt_mode_cmd - Specify the halt command type + * enum cam_tfe_csid_halt_mode - Specify the halt command type */ enum cam_tfe_csid_halt_mode { CAM_TFE_CSID_HALT_MODE_INTERNAL, @@ -107,7 +107,7 @@ enum cam_tfe_csid_halt_mode { }; /** - * struct cam_csid_hw_halt_args + * struct cam_tfe_csid_hw_halt_args * @halt_mode : Applicable only for PATH resources * 0 Internal : The CSID responds to the HALT_CMD * 1 Global : The CSID responds to the GLOBAL_HALT_CMD @@ -117,9 +117,9 @@ enum cam_tfe_csid_halt_mode { * @node_res : reource pointer array( ie cid or CSID) * */ -struct cam_csid_hw_halt_args { - enum cam_tfe_csid_halt_mode halt_mode; - struct cam_isp_resource_node *node_res; +struct cam_tfe_csid_hw_halt_args { + enum cam_tfe_csid_halt_mode halt_mode; + struct cam_isp_resource_node *node_res; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 6cd9a9d758c6..4aa783286a6f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1257,49 +1257,35 @@ static int cam_tfe_csid_enable_pxl_path( return 0; } -static void cam_tfe_csid_change_pxl_halt_mode( - struct cam_tfe_csid_hw *csid_hw, - struct cam_isp_resource_node *res, - enum cam_tfe_csid_halt_mode halt_mode) +static int cam_tfe_csid_change_pxl_halt_mode( + struct cam_tfe_csid_hw *csid_hw, + struct cam_tfe_csid_hw_halt_args *csid_halt) { uint32_t val = 0; const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; - struct cam_tfe_csid_path_cfg *path_data; const struct cam_tfe_csid_pxl_reg_offset *pxl_reg; - bool is_ipp; + struct cam_isp_resource_node *res; + + res = csid_halt->node_res; - path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; - if (res->res_id >= CAM_TFE_CSID_PATH_RES_MAX) { - CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d", + if (res->res_id != CAM_TFE_CSID_PATH_RES_IPP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res id %d", csid_hw->hw_intf->hw_idx, res->res_id); - goto end; - } - - if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW || - res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { - CAM_ERR(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d", - csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); - goto end; - } - - if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) { - is_ipp = true; - pxl_reg = csid_reg->ipp_reg; - } else { - goto end; + return -EINVAL; } if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) { - CAM_ERR(CAM_ISP, "CSID:%d %s path Res:%d Invalid state%d", - csid_hw->hw_intf->hw_idx, "IPP", - res->res_id, res->res_state); - goto end; + CAM_ERR(CAM_ISP, "CSID:%d Res:%d in invalid state:%d", + csid_hw->hw_intf->hw_idx, res->res_id, res->res_state); + return -EINVAL; } + pxl_reg = csid_reg->ipp_reg; + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_mask_addr); @@ -1307,11 +1293,13 @@ static void cam_tfe_csid_change_pxl_halt_mode( val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_ctrl_addr); val &= ~0xC; - val |= (halt_mode << 2); + val |= (csid_halt->halt_mode << 2); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_ctrl_addr); -end: - return; + CAM_DBG(CAM_ISP, "CSID:%d IPP path Res halt mode:%d configured:%x", + csid_hw->hw_intf->hw_idx, csid_halt->halt_mode, val); + + return 0; } static int cam_tfe_csid_disable_pxl_path( @@ -2211,14 +2199,15 @@ int cam_tfe_csid_halt(struct cam_tfe_csid_hw *csid_hw, void *halt_args) { struct cam_isp_resource_node *res; - struct cam_csid_hw_halt_args *csid_halt; + struct cam_tfe_csid_hw_halt_args *csid_halt; + int rc = 0; if (!csid_hw || !halt_args) { CAM_ERR(CAM_ISP, "CSID: Invalid args"); return -EINVAL; } - csid_halt = (struct cam_csid_hw_halt_args *)halt_args; + csid_halt = (struct cam_tfe_csid_hw_halt_args *)halt_args; /* Change the halt mode */ res = csid_halt->node_res; @@ -2226,20 +2215,25 @@ int cam_tfe_csid_halt(struct cam_tfe_csid_hw *csid_hw, csid_hw->hw_intf->hw_idx, res->res_type, res->res_id); - switch (res->res_type) { - case CAM_ISP_RESOURCE_PIX_PATH: - if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) - cam_tfe_csid_change_pxl_halt_mode(csid_hw, res, - csid_halt->halt_mode); - break; - default: - CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d", + 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); + return -EINVAL; + } + + switch (res->res_id) { + case CAM_TFE_CSID_PATH_RES_IPP: + rc = cam_tfe_csid_change_pxl_halt_mode(csid_hw, csid_halt); + break; + default: + CAM_DBG(CAM_ISP, "CSID:%d res_id %d", + csid_hw->hw_intf->hw_idx, + res->res_id); break; } - return 0; + return rc; } static int cam_tfe_csid_stop(void *hw_priv,