Merge "msm: camera: tfe: Change csid stop sequence during flush" into camera-kernel.lnx.4.0

This commit is contained in:
Camera Software Integration 2020-09-22 14:32:09 -07:00 • committed by Gerrit - the friendly Code Review server
commit 73452f0906
4 changed files with 179 additions and 1 deletions

View file

@ -529,6 +529,48 @@ 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)
{
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;
uint32_t i;
int rc = 0;
list_for_each_entry(hw_mgr_res, halt_list, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
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 ==
CAM_TFE_CSID_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_csid_hw_halt_args));
if (rc)
CAM_ERR(CAM_ISP, "Halt update failed");
break;
}
}
}
return rc;
}
static int cam_tfe_mgr_csid_stop_hw(
struct cam_tfe_hw_mgr_ctx *ctx, struct list_head *stop_list,
uint32_t base_idx, uint32_t stop_cmd)
@ -2650,6 +2692,19 @@ static int cam_tfe_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) {
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);
}
}
CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx);
/* Stop the master CSID path first */

View file

@ -129,6 +129,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_BLANKING_UPDATE,
CAM_ISP_HW_CMD_CSID_CLOCK_DUMP,
CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD,
CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE,
CAM_ISP_HW_CMD_MAX,
};

View file

@ -95,6 +95,33 @@ enum cam_tfe_csid_halt_cmd {
CAM_TFE_CSID_HALT_MAX,
};
/**
* enum cam_tfe_csid_halt_mode_cmd - Specify the halt command type
*/
enum cam_tfe_csid_halt_mode {
CAM_TFE_CSID_HALT_MODE_INTERNAL,
CAM_TFE_CSID_HALT_MODE_GLOBAL,
CAM_TFE_CSID_HALT_MODE_MASTER,
CAM_TFE_CSID_HALT_MODE_SLAVE,
CAM_TFE_CSID_HALT_MODE_MAX,
};
/**
* struct cam_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_csid_hw_halt_args {
enum cam_tfe_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

View file

@ -1246,6 +1246,63 @@ 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)
{
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;
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",
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;
}
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_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 |= (halt_mode << 2);
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
pxl_reg->csid_pxl_ctrl_addr);
end:
return;
}
static int cam_tfe_csid_disable_pxl_path(
struct cam_tfe_csid_hw *csid_hw,
struct cam_isp_resource_node *res,
@ -2088,6 +2145,41 @@ end:
return rc;
}
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;
if (!csid_hw || !halt_args) {
CAM_ERR(CAM_ISP, "CSID: Invalid args");
return -EINVAL;
}
csid_halt = (struct cam_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);
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",
csid_hw->hw_intf->hw_idx,
res->res_type);
break;
}
return 0;
}
static int cam_tfe_csid_stop(void *hw_priv,
void *stop_args, uint32_t arg_size)
{
@ -2095,7 +2187,7 @@ static int cam_tfe_csid_stop(void *hw_priv,
struct cam_tfe_csid_hw *csid_hw;
struct cam_hw_info *csid_hw_info;
struct cam_isp_resource_node *res;
struct cam_tfe_csid_hw_stop_args *csid_stop;
struct cam_tfe_csid_hw_stop_args *csid_stop;
uint32_t i;
uint32_t res_mask = 0;
@ -2472,6 +2564,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv,
case CAM_ISP_HW_CMD_DUMP_HW:
rc = cam_tfe_csid_dump_hw(csid_hw, cmd_args);
break;
case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE:
rc = cam_tfe_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);