Bladeren bron

msm: camera: cpas: Add fuse MP limit support

If MP limit fuse feature is enabled in DTSI then
read the fuse register to get information about maximum
allowed resolution. According to that restrict CSID acquire.
Also if only DTSI based max_width is enabled then restrict acquire
with maximum allowed width.

CRs-Fixed: 2785460
Depends-on: 3349044
Change-Id: If861289aebe2921183276780a086dfa1b1d5f372
Signed-off-by: Wyes Karny <[email protected]>
Wyes Karny 4 jaren geleden
bovenliggende
commit
c37f48cfc5

+ 34 - 6
drivers/cam_cpas/cam_cpas_intf.c

@@ -119,28 +119,56 @@ const char *cam_cpas_axi_util_trans_type_to_string(
 }
 EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string);
 
-int cam_cpas_is_feature_supported(uint32_t flag)
+bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
+	uint32_t *fuse_val)
 {
 	struct cam_hw_info *cpas_hw = NULL;
 	struct cam_cpas_private_soc *soc_private = NULL;
-	uint32_t feature_mask;
+	bool supported = true;
+	int32_t i;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
 		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
-		return -ENODEV;
+		return false;
 	}
 
 	cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
 	soc_private =
 		(struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
-	feature_mask = soc_private->feature_mask;
 
 	if (flag >= CAM_CPAS_FUSE_FEATURE_MAX) {
 		CAM_ERR(CAM_CPAS, "Unknown feature flag %x", flag);
-		return -EINVAL;
+		return false;
+	}
+
+	for (i = 0; i < soc_private->num_feature_info; i++)
+		if (soc_private->feature_info[i].feature == flag)
+			break;
+
+	if (i == soc_private->num_feature_info) {
+		CAM_INFO(CAM_CPAS, "Feature not found, no of featues: %d",
+			soc_private->num_feature_info);
+		goto end;
+	}
+
+	if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE
+		|| (soc_private->feature_info[i].type ==
+		CAM_CPAS_FEATURE_TYPE_ENABLE)) {
+		if ((soc_private->feature_info[i].hw_map & hw_map) == hw_map)
+			supported = soc_private->feature_info[i].enable;
+		else
+			supported = !soc_private->feature_info[i].enable;
+	} else {
+		if (!fuse_val) {
+			CAM_ERR(CAM_CPAS,
+				"Invalid arg fuse_val");
+		} else {
+			*fuse_val = soc_private->feature_info[i].value;
+		}
 	}
 
-	return feature_mask & flag ? 1 : 0;
+end:
+	return supported;
 }
 EXPORT_SYMBOL(cam_cpas_is_feature_supported);
 

+ 125 - 59
drivers/cam_cpas/cam_cpas_soc.c

@@ -466,87 +466,155 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
 	return 0;
 }
 
-int cam_cpas_get_hw_fuse(struct platform_device *pdev,
-	struct cam_cpas_private_soc *soc_private)
-{
-	struct device_node *of_node;
-	void *fuse;
-	uint32_t fuse_addr, fuse_bit;
-	uint32_t fuse_val = 0, feature_bit_pos;
-	int count = 0, i = 0;
-
-	memset(&soc_private->fuse_info, 0, sizeof(soc_private->fuse_info));
 
-	of_node = pdev->dev.of_node;
-	count   = of_property_count_u32_elems(of_node, "cam_hw_fuse");
-	if (count <= 0) {
-		CAM_INFO(CAM_CPAS, "no or invalid fuse enrties %d", count);
-		return 0;
-	} else if (count%3 != 0) {
-		CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 3 %d",
-			count);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < count; i = i + 3) {
-		of_property_read_u32_index(of_node, "cam_hw_fuse", i,
-				&feature_bit_pos);
-		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1,
-				&fuse_addr);
-		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2,
-				&fuse_bit);
-		CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d",
-			feature_bit_pos, fuse_addr, fuse_bit);
-		fuse = ioremap(fuse_addr, 4);
-		if (fuse) {
-			fuse_val = cam_io_r(fuse);
-			soc_private->fuse_info.fuse_val[i].fuse_id = fuse_addr;
-			soc_private->fuse_info.fuse_val[i].fuse_val = fuse_val;
-		}
-		CAM_INFO(CAM_CPAS, "fuse_addr 0x%x, fuse_val %x",
-			fuse_addr, fuse_val);
-		soc_private->fuse_info.num_fuses++;
-		iounmap(fuse);
-	}
-
-	return 0;
-}
 
 int cam_cpas_get_hw_features(struct platform_device *pdev,
 	struct cam_cpas_private_soc *soc_private)
 {
 	struct device_node *of_node;
 	void *fuse;
-	uint32_t fuse_addr, fuse_bit;
-	uint32_t fuse_val = 0, feature_bit_pos;
-	int count = 0, i = 0;
+	uint32_t fuse_addr, fuse_mask, fuse_shift;
+	uint32_t val = 0, fuse_val = 0, feature;
+	uint32_t enable_type = 0, hw_map = 0;
+	int count = 0, i = 0, j = 0,  num_feature = 0, num_fuse = 0;
+	struct cam_cpas_feature_info *feature_info;
 
 	of_node = pdev->dev.of_node;
 	count = of_property_count_u32_elems(of_node, "cam_hw_fuse");
 
-	for (i = 0; (i + 3) <= count; i = i + 3) {
+	CAM_DBG(CAM_CPAS, "fuse info elements count %d", count);
+
+	if (count <= 0) {
+		CAM_INFO(CAM_CPAS, "No or invalid fuse entries count: %d",
+			count);
+		goto end;
+	} else if (count%5 != 0) {
+		CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 5 %d",
+			count);
+		goto end;
+	}
+
+	for (i = 0; (i + 5) <= count; i = i + 5) {
 		of_property_read_u32_index(of_node, "cam_hw_fuse", i,
-				&feature_bit_pos);
+				&feature);
 		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1,
 				&fuse_addr);
 		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2,
-				&fuse_bit);
-		CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d",
-				feature_bit_pos, fuse_addr, fuse_bit);
+				&fuse_mask);
+		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 3,
+				&enable_type);
+		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 4,
+				&hw_map);
+		val = ffs(fuse_mask);
+		if (val == 0) {
+			CAM_ERR(CAM_CPAS, "fuse_mask not valid 0x%x",
+				fuse_mask);
+			fuse_shift = 0;
+		} else {
+			fuse_shift = val - 1;
+		}
+		CAM_INFO(CAM_CPAS,
+			"feature 0x%x addr 0x%x, mask 0x%x, shift 0x%x type 0x%x hw_map 0x%x",
+			feature, fuse_addr, fuse_mask, fuse_shift, enable_type,
+			hw_map);
 
 		fuse = ioremap(fuse_addr, 4);
 		if (fuse) {
 			fuse_val = cam_io_r(fuse);
-			if (fuse_val & BIT(fuse_bit))
-				soc_private->feature_mask |= feature_bit_pos;
+			for (j = 0; (j < num_fuse) && (j < CAM_CPAS_FUSES_MAX);
+				j++) {
+				if (soc_private->fuse_info.fuse_val[j].fuse_id
+					== fuse_addr)
+					break;
+			}
+			if (j >= CAM_CPAS_FUSES_MAX) {
+				CAM_ERR(CAM_CPAS,
+					"fuse_info array overflow! %d", j);
+				goto end;
+			}
+			if (j == num_fuse) {
+				soc_private->fuse_info.fuse_val[j].fuse_id =
+					fuse_addr;
+				soc_private->fuse_info.fuse_val[j].fuse_val =
+					fuse_val;
+				CAM_INFO(CAM_CPAS,
+					"fuse_addr 0x%x, fuse_val %x",
+					fuse_addr, fuse_val);
+				num_fuse++;
+			}
+		} else {
+			/* if fuse ioremap is failed, disable the feature */
+			CAM_ERR(CAM_CPAS,
+				"fuse register io remap failed fuse_addr:0x%x feature0x%x ",
+				fuse_addr, feature);
+
+			if (enable_type == CAM_CPAS_FEATURE_TYPE_ENABLE ||
+				enable_type == CAM_CPAS_FEATURE_TYPE_DISABLE)
+				fuse_val = (enable_type) ? ~fuse_mask :
+					fuse_mask;
 			else
-				soc_private->feature_mask &= ~feature_bit_pos;
+				fuse_val = 0;
+		}
+
+		if (num_feature >= CAM_CPAS_MAX_FUSE_FEATURE) {
+			CAM_ERR(CAM_CPAS, "feature_info array overflow %d",
+				num_feature);
+			goto end;
 		}
-		CAM_INFO(CAM_CPAS, "fuse %pK, fuse_val %x, feature_mask %x",
-				fuse, fuse_val, soc_private->feature_mask);
 
+		soc_private->feature_info[num_feature].feature =
+			feature;
+		soc_private->feature_info[num_feature].hw_map = hw_map;
+		soc_private->feature_info[num_feature].type = enable_type;
+		feature_info = &soc_private->feature_info[num_feature];
+
+		if (enable_type != CAM_CPAS_FEATURE_TYPE_VALUE) {
+			if (enable_type == CAM_CPAS_FEATURE_TYPE_ENABLE) {
+				/*
+				 * fuse is for enable feature
+				 * if fust bit is set means feature is enabled
+				 * or HW is enabled
+				 */
+				if (fuse_val & fuse_mask)
+					feature_info->enable = true;
+				else
+					feature_info->enable = false;
+			} else if (enable_type ==
+				CAM_CPAS_FEATURE_TYPE_DISABLE){
+				/*
+				 * fuse is for disable feature
+				 * if fust bit is set means feature is disabled
+				 * or HW is disabled
+				 */
+				if (fuse_val & fuse_mask)
+					feature_info->enable = false;
+				else
+					feature_info->enable = true;
+			} else {
+				CAM_ERR(CAM_CPAS,
+					"Feature type not valid, type: %d",
+					enable_type);
+				goto end;
+			}
+			CAM_INFO(CAM_CPAS,
+				"feature 0x%x enable=%d hw_map=0x%x",
+				feature_info->feature, feature_info->enable,
+				feature_info->hw_map);
+		} else {
+			feature_info->value =
+				(fuse_val & fuse_mask) >> fuse_shift;
+			CAM_INFO(CAM_CPAS,
+				"feature 0x%x value=0x%x hw_map=0x%x",
+				feature_info->feature, feature_info->value,
+				feature_info->hw_map);
+		}
+		num_feature++;
+		iounmap(fuse);
 	}
 
+end:
+	soc_private->fuse_info.num_fuses = num_fuse;
+	soc_private->num_feature_info = num_feature;
 	return 0;
 }
 
@@ -565,7 +633,6 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
 	}
 
 	of_node = pdev->dev.of_node;
-	soc_private->feature_mask = 0xFFFFFFFF;
 
 	rc = of_property_read_string(of_node, "arch-compat",
 		&soc_private->arch_compat);
@@ -576,7 +643,6 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
 	}
 
 	cam_cpas_get_hw_features(pdev, soc_private);
-	cam_cpas_get_hw_fuse(pdev, soc_private);
 
 	soc_private->camnoc_axi_min_ib_bw = 0;
 	rc = of_property_read_u64(of_node,

+ 22 - 2
drivers/cam_cpas/cam_cpas_soc.h

@@ -11,6 +11,7 @@
 
 #define CAM_REGULATOR_LEVEL_MAX 16
 #define CAM_CPAS_MAX_TREE_NODES 50
+#define CAM_CPAS_MAX_FUSE_FEATURE 10
 
 /**
  * struct cam_cpas_vdd_ahb_mapping : Voltage to ahb level mapping
@@ -71,6 +72,23 @@ struct cam_cpas_tree_node {
 	struct cam_cpas_tree_node *parent_node;
 };
 
+/**
+ * struct cam_cpas_feature_info : CPAS fuse feature info
+ * @feature: Identifier for feature
+ * @type: Type of feature
+ * @value: Fuse value
+ * @enable: Feature enable or disable
+ * @hw_map: Each bit position indicates if the hw_id for the feature
+ */
+
+struct cam_cpas_feature_info {
+	uint32_t feature;
+	uint32_t type;
+	uint32_t value;
+	bool enable;
+	uint32_t hw_map;
+};
+
 /**
  * struct cam_cpas_private_soc : CPAS private DT info
  *
@@ -90,9 +108,10 @@ struct cam_cpas_tree_node {
  * @camnoc_axi_clk_bw_margin : BW Margin in percentage to add while calculating
  *      camnoc axi clock
  * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target
- * @feature_mask: feature mask value for hw supported features
  * @fuse_info: fuse information
  * @rpmh_info: RPMH BCM info
+ * @num_feature_info: number of feature_info entries
+ * @feature_info: Structure for storing feature information
  */
 struct cam_cpas_private_soc {
 	const char *arch_compat;
@@ -109,9 +128,10 @@ struct cam_cpas_private_soc {
 	uint32_t camnoc_bus_width;
 	uint32_t camnoc_axi_clk_bw_margin;
 	uint64_t camnoc_axi_min_ib_bw;
-	uint32_t feature_mask;
 	struct cam_cpas_fuse_info fuse_info;
 	uint32_t rpmh_info[CAM_RPMH_BCM_INFO_MAX];
+	uint32_t num_feature_info;
+	struct cam_cpas_feature_info  feature_info[CAM_CPAS_MAX_FUSE_FEATURE];
 };
 
 void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);

+ 22 - 2
drivers/cam_cpas/include/cam_cpas_api.h

@@ -37,6 +37,22 @@ enum cam_cpas_reg_base {
 	CAM_CPAS_REG_MAX
 };
 
+/**
+ * enum cam_cpas_hw_index  - Enum for identify HW index
+ */
+enum cam_cpas_hw_index {
+	CAM_CPAS_HW_IDX_ANY = 0,
+	CAM_CPAS_HW_IDX_0 = 1<<0,
+	CAM_CPAS_HW_IDX_1 = 1<<1,
+	CAM_CPAS_HW_IDX_2 = 1<<2,
+	CAM_CPAS_HW_IDX_3 = 1<<3,
+	CAM_CPAS_HW_IDX_4 = 1<<4,
+	CAM_CPAS_HW_IDX_5 = 1<<5,
+	CAM_CPAS_HW_IDX_6 = 1<<6,
+	CAM_CPAS_HW_IDX_7 = 1<<7,
+	CAM_CPAS_HW_IDX_MAX = 1<<8
+};
+
 /**
  * enum cam_cpas_camera_version Enum for Titan Camera Versions
  */
@@ -608,11 +624,15 @@ int cam_cpas_get_cpas_hw_version(
  *
  * @flag  : Camera hw features to check
  *
+ * @hw_map : To indicate which HWs are supported
+ *
+ * @fule_val : Return fule value in case of value type feature
+ *
  * @return 1 if feature is supported
  *
  */
-int cam_cpas_is_feature_supported(
-	uint32_t flag);
+bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
+	uint32_t *fuse_val);
 
 /**
  * cam_cpas_axi_util_path_type_to_string()

+ 133 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c

@@ -1002,6 +1002,116 @@ end:
 	return rc;
 }
 
+bool cam_ife_csid_is_resolution_supported_by_fuse(uint32_t width)
+{
+	bool supported = true;
+	uint32_t hw_version, fuse_val = UINT_MAX;
+	int rc = 0;
+
+	rc = cam_cpas_get_cpas_hw_version(&hw_version);
+
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Could not get CPAS version");
+		return supported;
+	}
+
+	switch (hw_version) {
+	case CAM_CPAS_TITAN_570_V200:
+		cam_cpas_is_feature_supported(CAM_CPAS_MP_LIMIT_FUSE,
+			CAM_CPAS_HW_IDX_ANY, &fuse_val);
+		switch (fuse_val) {
+		case 0x0:
+			if (width > CAM_CSID_RESOLUTION_22MP_WIDTH) {
+				CAM_ERR(CAM_ISP,
+					"Resolution not supported required_width: %d max_supported_width: %d",
+					width, CAM_CSID_RESOLUTION_22MP_WIDTH);
+				supported = false;
+			}
+			break;
+		case  0x1:
+			if (width > CAM_CSID_RESOLUTION_25MP_WIDTH) {
+				CAM_ERR(CAM_ISP,
+					"Resolution not supported required_width: %d max_supported_width: %d",
+					width, CAM_CSID_RESOLUTION_25MP_WIDTH);
+				supported  = false;
+			}
+			break;
+		case 0x2:
+			if (width > CAM_CSID_RESOLUTION_28MP_WIDTH) {
+				CAM_ERR(CAM_ISP,
+					"Resolution not supported required_width: %d max_supported_width: %d",
+					width, CAM_CSID_RESOLUTION_28MP_WIDTH);
+				supported = false;
+			}
+			break;
+		case UINT_MAX:
+			CAM_WARN(CAM_ISP, "Fuse value not updated");
+			break;
+		default:
+			CAM_ERR(CAM_ISP,
+				"Fuse value not defined, fuse_val: 0x%x",
+				fuse_val);
+			supported = false;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+	return supported;
+}
+
+bool cam_ife_csid_is_resolution_supported_by_dt(struct cam_ife_csid_hw *csid_hw,
+	uint32_t width)
+{
+	bool supported = true;
+	struct cam_hw_soc_info soc_info;
+	struct cam_csid_soc_private *soc_private = NULL;
+
+	if (!csid_hw || !csid_hw->hw_info) {
+		CAM_ERR(CAM_ISP, "Argument parsing error!");
+		supported = false;
+		goto end;
+	}
+
+	soc_info = csid_hw->hw_info->soc_info;
+
+	soc_private = (struct cam_csid_soc_private *)soc_info.soc_private;
+
+	if (!soc_private) {
+		CAM_ERR(CAM_ISP, "soc_private not found");
+		supported = false;
+		goto end;
+	}
+
+	if (soc_private->max_width_enabled) {
+		if (width > soc_private->max_width) {
+			CAM_ERR(CAM_ISP,
+				"Resolution not supported required_width: %d max_supported_width: %d",
+				width, soc_private->max_width);
+			supported = false;
+		}
+	}
+end:
+	return supported;
+}
+
+bool cam_ife_csid_is_resolution_supported(struct cam_ife_csid_hw *csid_hw,
+	uint32_t width)
+{
+	bool supported = false;
+
+	if (!csid_hw) {
+		CAM_ERR(CAM_ISP, "csid_hw is NULL");
+		return supported;
+	}
+
+	if (cam_ife_csid_is_resolution_supported_by_fuse(width) &&
+		cam_ife_csid_is_resolution_supported_by_dt(csid_hw, width))
+		supported = true;
+	return supported;
+}
+
 int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
 	struct cam_csid_hw_reserve_resource_args  *reserve)
 {
@@ -1179,6 +1289,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
 	}
 
 	if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
+		if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) &&
+			!(cam_ife_csid_is_resolution_supported(csid_hw,
+			reserve->in_port->left_stop -
+			reserve->in_port->left_start + 1))) {
+			rc = -EINVAL;
+			goto end;
+		}
 		path_data->start_pixel = reserve->in_port->left_start;
 		path_data->end_pixel = reserve->in_port->left_stop;
 		path_data->width  = reserve->in_port->left_width;
@@ -1198,6 +1315,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
 			csid_hw->hw_intf->hw_idx, reserve->res_id,
 			path_data->start_line, path_data->end_line);
 	} else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) {
+		if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) &&
+			!(cam_ife_csid_is_resolution_supported(csid_hw,
+			reserve->in_port->right_stop -
+			reserve->in_port->right_start + 1))) {
+			rc = -EINVAL;
+			goto end;
+		}
 		path_data->master_idx = reserve->master_idx;
 		CAM_DBG(CAM_ISP, "CSID:%d master_idx=%d",
 			csid_hw->hw_intf->hw_idx, path_data->master_idx);
@@ -1214,6 +1338,13 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
 			csid_hw->hw_intf->hw_idx, reserve->res_id,
 			path_data->start_line, path_data->end_line);
 	} else {
+		if ((reserve->res_id == CAM_IFE_PIX_PATH_RES_IPP) &&
+			!(cam_ife_csid_is_resolution_supported(csid_hw,
+			reserve->in_port->left_stop -
+			reserve->in_port->left_start + 1))) {
+			rc = -EINVAL;
+			goto end;
+		}
 		path_data->width  = reserve->in_port->left_width;
 		path_data->start_pixel = reserve->in_port->left_start;
 		path_data->end_pixel = reserve->in_port->left_stop;
@@ -5188,7 +5319,8 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf  *csid_hw_intf,
 		goto err;
 	}
 
-	if (cam_cpas_is_feature_supported(CAM_CPAS_QCFA_BINNING_ENABLE) == 1)
+	if (cam_cpas_is_feature_supported(CAM_CPAS_QCFA_BINNING_ENABLE,
+		CAM_CPAS_HW_IDX_ANY, NULL))
 		ife_csid_hw->binning_enable = 1;
 
 	ife_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_ife_csid_get_hw_caps;

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h

@@ -76,6 +76,10 @@
 #define CAM_CSID_EVT_PAYLOAD_MAX                  10
 #define CAM_CSID_MIN_HBI_CFG_MAX_VAL              0xF
 
+#define CAM_CSID_RESOLUTION_22MP_WIDTH            5612
+#define CAM_CSID_RESOLUTION_25MP_WIDTH            6048
+#define CAM_CSID_RESOLUTION_28MP_WIDTH            7308
+
 /* enum cam_csid_path_halt_mode select the path halt mode control */
 enum cam_csid_path_halt_mode {
 	CSID_HALT_MODE_INTERNAL,

+ 10 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c

@@ -21,6 +21,16 @@ static int cam_ife_csid_get_dt_properties(struct cam_hw_soc_info *soc_info)
 
 	soc_private = (struct cam_csid_soc_private *)soc_info->soc_private;
 
+	rc = of_property_read_u32(of_node, "max-width",
+		&soc_private->max_width);
+	if (rc) {
+		CAM_DBG(CAM_ISP, "No max-width declared");
+		soc_private->max_width_enabled = false;
+		rc = 0;
+	} else {
+		soc_private->max_width_enabled = true;
+	}
+
 	soc_private->is_ife_csid_lite = false;
 	if (strnstr(soc_info->compatible, "lite",
 		strlen(soc_info->compatible)) != NULL) {

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h

@@ -17,10 +17,14 @@
  *                           This handle is used for all further interface
  *                           with CPAS.
  * @is_ife_csid_lite:        Flag to indicate Whether a full csid or a Lite csid
+ * @max_width_enabled:       Flag to enable max width restriction
+ * @max_width:               Maxinum allowed width
  */
 struct cam_csid_soc_private {
 	uint32_t cpas_handle;
 	bool     is_ife_csid_lite;
+	bool     max_width_enabled;
+	uint32_t max_width;
 };
 
 /**

+ 6 - 4
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c

@@ -1347,8 +1347,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			}
 
 			if (csiphy_dev->csiphy_info[offset].secure_mode == 1) {
-				if (cam_cpas_is_feature_supported(
-					CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) {
+				if (!cam_cpas_is_feature_supported(
+					CAM_CPAS_SECURE_CAMERA_ENABLE,
+					CAM_CPAS_HW_IDX_ANY, NULL)) {
 					CAM_ERR(CAM_CSIPHY,
 						"sec_cam: camera fuse bit not set");
 					goto release_mutex;
@@ -1411,8 +1412,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 		}
 
 		if (csiphy_dev->csiphy_info[offset].secure_mode == 1) {
-			if (cam_cpas_is_feature_supported(
-					CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) {
+			if (!cam_cpas_is_feature_supported(
+					CAM_CPAS_SECURE_CAMERA_ENABLE,
+					CAM_CPAS_HW_IDX_ANY, NULL)) {
 				CAM_ERR(CAM_CSIPHY,
 					"sec_cam: camera fuse bit not set");
 				cam_cpas_stop(csiphy_dev->cpas_handle);