Przeglądaj źródła

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

Camera Software Integration 4 lat temu
rodzic
commit
73452f0906

+ 55 - 0
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

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

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

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

+ 27 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h

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

+ 96 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c

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