summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVikram Sharma <vikramsa@codeaurora.org>2020-04-16 15:49:42 +0530
committerNick Chung <nickchung@google.com>2020-06-17 00:52:47 +0800
commit6de20ff6cc291fc6a3c0911edca3cac478794af8 (patch)
treeac8c1b269ab0fa580635c160f3dd963a4a96807c
parent67efec335d354e06f68f81d8dd8725ea352ed013 (diff)
downloadcamera-kernel-6de20ff6cc291fc6a3c0911edca3cac478794af8.tar.gz
msm: camera: isp: Change csid stop sequence during flush
This change takes care of a race which we see when we halt master csid immediately and slave csid halt to follow. In some scenarios after master csid halt, slave gives violation errors. With this change we are first changing the mode of slave to master then issue halt commands to both master and slave. Bug: 159088802 Test: GCA, CTS/ITS CRs-Fixed: 2662825 Change-Id: Id5cd7e1bdf469f43da23af151b99c9f481830cfa Signed-off-by: Vikram Sharma <vikramsa@codeaurora.org>
-rw-r--r--drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c55
-rw-r--r--drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c96
-rw-r--r--drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h27
-rw-r--r--drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h1
4 files changed, 178 insertions, 1 deletions
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 70de7b5..7703eea 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
@@ -824,6 +824,47 @@ static void cam_ife_hw_mgr_dump_acq_data(
}
}
+static int cam_ife_mgr_csid_change_halt_mode(struct list_head *halt_list,
+ uint32_t base_idx, enum cam_ife_csid_halt_mode halt_mode)
+{
+ struct cam_ife_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_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_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)
@@ -3865,6 +3906,19 @@ 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) {
+ for (i = 0; i < ctx->num_base; i++) {
+ if (ctx->base[i].idx == master_base_idx)
+ continue;
+ cam_ife_mgr_csid_change_halt_mode(
+ &ctx->res_list_ife_csid,
+ ctx->base[i].idx,
+ CAM_CSID_HALT_MODE_INTERNAL);
+ }
+ }
+
CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx);
/* Stop the master CSID path first */
@@ -6962,7 +7016,6 @@ static int cam_ife_hw_mgr_handle_hw_rup(
CAM_DBG(CAM_ISP, "RUP done for VFE:%d source %d", event_info->hw_idx,
event_info->res_id);
-
return 0;
}
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 42daa02..c70ee14 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
@@ -2128,6 +2128,64 @@ static int cam_ife_csid_enable_pxl_path(
return 0;
}
+
+static void cam_ife_csid_change_pxl_halt_mode(
+ struct cam_ife_csid_hw *csid_hw,
+ struct cam_isp_resource_node *res,
+ enum cam_ife_csid_halt_mode halt_mode)
+{
+ uint32_t val = 0;
+ const struct cam_ife_csid_reg_offset *csid_reg;
+ struct cam_hw_soc_info *soc_info;
+ struct cam_ife_csid_path_cfg *path_data;
+ const struct cam_ife_csid_pxl_reg_offset *pxl_reg;
+ bool is_ipp;
+
+ path_data = (struct cam_ife_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_IFE_PIX_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_IFE_PIX_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, (is_ipp) ? "IPP" : "PPP",
+ 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_ife_csid_disable_pxl_path(
struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res,
@@ -3693,6 +3751,41 @@ 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_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_IFE_PIX_PATH_RES_IPP)
+ cam_ife_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;
+}
+
int cam_ife_csid_stop(void *hw_priv,
void *stop_args, uint32_t arg_size)
{
@@ -4090,6 +4183,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv,
case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG:
rc = cam_ife_csid_set_sensor_dimension(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 5afc0b7..498854b 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
@@ -154,6 +154,33 @@ enum cam_ife_csid_halt_cmd {
};
/**
+ * enum cam_ife_csid_halt_mode_cmd - 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_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_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
* if stop command set to Halt immediately,driver will stop
diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index fc6951b..59e2e2f 100644
--- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -106,6 +106,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA,
CAM_ISP_HW_CMD_DUMP_HW,
CAM_ISP_HW_CMD_FE_TRIGGER_CMD,
+ CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE,
CAM_ISP_HW_CMD_MAX,
};