Explorar o código

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 halt mode of slave to
internal so that dependency on master is removed and
then issue halt commands to both master and slave.

CRs-Fixed: 2830502
Change-Id: I05fd1d07298c7dddf3d5024e0c0cacdf15e2f69d
Signed-off-by: Chandan Kumar Jha <[email protected]>
Chandan Kumar Jha %!s(int64=4) %!d(string=hai) anos
pai
achega
7aa7a04e80

+ 87 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver1.c

@@ -3099,6 +3099,90 @@ static int cam_ife_csid_poll_stop_status(
 	return rc;
 }
 
+static int cam_ife_csid_change_pxl_halt_mode(
+	struct cam_ife_csid_ver1_hw       *csid_hw,
+	struct cam_ife_csid_hw_halt_args  *csid_halt)
+{
+	uint32_t val = 0;
+	const struct cam_ife_csid_ver1_reg_info    *csid_reg;
+	struct cam_hw_soc_info                     *soc_info;
+	struct cam_isp_resource_node               *res;
+
+	res = csid_halt->node_res;
+
+	csid_reg = csid_hw->core_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;
+	}
+
+
+	cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+		csid_reg->ipp_reg->irq_mask_addr);
+
+	/* configure Halt for slave */
+	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+		csid_reg->ipp_reg->ctrl_addr);
+	val &= ~0xC;
+	val |= (csid_halt->halt_mode << 2);
+	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+		csid_reg->ipp_reg->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;
+}
+
+int cam_ife_csid_halt(struct cam_ife_csid_ver1_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_ver1_stop(void *hw_priv,
 	void *stop_args, uint32_t arg_size)
 {
@@ -3727,6 +3811,9 @@ static int cam_ife_csid_ver1_process_cmd(void *hw_priv,
 	case CAM_IFE_CSID_LOG_ACQUIRE_DATA:
 		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);