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

This commit is contained in:
Camera Software Integration 2020-10-16 13:17:17 -07:00 • committed by Gerrit - the friendly Code Review server
commit 4e289c6238
6 changed files with 227 additions and 65 deletions

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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;
};
/**

View file

@ -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,