瀏覽代碼

msm: camera: csid: Add fuse support for MP limit

This change limit the resolution for the single camera based on fuse.
Acquire will fail in case width is greater than the supported width.

CRs-Fixed: 3679491
Change-Id: I4f3e8dfdbe80aee994ca66f12bbbcdc7cda77676
Signed-off-by: Dharmender Sharma <[email protected]>
Dharmender Sharma 1 年之前
父節點
當前提交
1e193cd952

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid860.h

@@ -81,6 +81,9 @@ static struct cam_ife_csid_ver2_reg_info cam_ife_csid_860_reg_info = {
 	.num_path_err_irqs  = ARRAY_SIZE(cam_ife_csid_880_path_irq_desc),
 	.num_top_regs       = 1,
 	.num_rx_regs        = 1,
+	.width_fuse_max_val = 1,
+	.fused_max_dualife_width = {7296, 5344, UINT_MAX},
+	.fused_max_width = {7296, 7296, UINT_MAX},
 };
 
 #endif /*_CAM_IFE_CSID_860_H_ */

+ 79 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -3215,6 +3215,82 @@ end:
 	return rc;
 }
 
+static bool cam_ife_csid_ver2_is_width_valid_by_fuse(
+	struct cam_csid_hw_reserve_resource_args  *reserve,
+	struct cam_ife_csid_ver2_hw *csid_hw,
+	uint32_t width)
+{
+	struct cam_ife_csid_ver2_reg_info *csid_reg;
+	uint32_t fuse_val = UINT_MAX;
+
+	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
+		csid_hw->core_info->csid_reg;
+
+	cam_cpas_is_feature_supported(CAM_CPAS_MP_LIMIT_FUSE, CAM_CPAS_HW_IDX_ANY, &fuse_val);
+	if (fuse_val == UINT_MAX) {
+		CAM_DBG(CAM_ISP, "CSID[%u] MP limit fuse not present",
+			csid_hw->hw_intf->hw_idx);
+		return true;
+	}
+
+	if ((fuse_val > csid_reg->width_fuse_max_val) ||
+		(fuse_val >= CAM_IFE_CSID_WIDTH_FUSE_VAL_MAX)) {
+		CAM_ERR(CAM_ISP, "Invalid fuse value %u", fuse_val);
+		return false;
+	}
+
+	if (((reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) ||
+		(reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER)) &&
+		(width > csid_reg->fused_max_dualife_width[fuse_val])) {
+		CAM_ERR(CAM_ISP,
+			"CSID[%u] Resolution not supported required_width dualife: %d max_supported_width: %d",
+			csid_hw->hw_intf->hw_idx,
+			width, csid_reg->fused_max_dualife_width[fuse_val]);
+		return false;
+
+	} else if (width > csid_reg->fused_max_width[fuse_val]) {
+		CAM_ERR(CAM_ISP,
+			"CSID[%u] Resolution not supported required_width: %d max_supported_width: %d",
+			csid_hw->hw_intf->hw_idx,
+			width, csid_reg->fused_max_width[fuse_val]);
+		return false;
+	}
+
+	return true;
+}
+
+bool cam_ife_csid_ver2_is_width_valid(
+	struct cam_csid_hw_reserve_resource_args  *reserve,
+	struct cam_ife_csid_ver2_hw *csid_hw)
+{
+	uint32_t width = 0;
+	struct cam_csid_soc_private *soc_private;
+
+	soc_private = (struct cam_csid_soc_private *)csid_hw->hw_info->soc_info.soc_private;
+
+	if ((reserve->res_id != CAM_IFE_PIX_PATH_RES_IPP) || soc_private->is_ife_csid_lite)
+		return true;
+
+	if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
+		reserve->sync_mode == CAM_ISP_HW_SYNC_NONE)
+		width = reserve->in_port->left_stop -
+			reserve->in_port->left_start + 1;
+	else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
+		width = reserve->in_port->right_stop -
+			reserve->in_port->right_start + 1;
+
+	if (reserve->in_port->horizontal_bin || reserve->in_port->qcfa_bin)
+		width /= 2;
+
+	if (!cam_ife_csid_ver2_is_width_valid_by_fuse(reserve, csid_hw, width)) {
+		CAM_ERR(CAM_ISP, "CSID[%u] width limited by fuse",
+			csid_hw->hw_intf->hw_idx);
+		return false;
+	}
+
+	return true;
+}
+
 static int cam_ife_csid_ver2_in_port_validate(
 	struct cam_csid_hw_reserve_resource_args  *reserve,
 	struct cam_ife_csid_ver2_hw     *csid_hw)
@@ -3229,6 +3305,9 @@ static int cam_ife_csid_ver2_in_port_validate(
 			goto err;
 	}
 
+	if (!cam_ife_csid_ver2_is_width_valid(reserve, csid_hw))
+		goto err;
+
 	if (csid_hw->counters.csi2_reserve_cnt) {
 
 		if (csid_hw->token != reserve->cb_priv) {

+ 5 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.h

@@ -742,6 +742,11 @@ struct cam_ife_csid_ver2_reg_info {
 	const uint32_t                                    num_path_err_irqs;
 	const uint32_t                                    num_top_regs;
 	const uint32_t                                    num_rx_regs;
+	const uint32_t                                    fused_max_dualife_width[
+		   CAM_IFE_CSID_WIDTH_FUSE_VAL_MAX];
+	const uint32_t                                    fused_max_width[
+		   CAM_IFE_CSID_WIDTH_FUSE_VAL_MAX];
+	const uint32_t                                    width_fuse_max_val;
 };
 
 /*