Переглянути джерело

msm: camera: icp: Add V2 Query Capability Support

Fill out ICP v2 query cap request from UMD based on v2 query
cap structure. With the query cap info, UMD can know which HW
devices (IPE/BPS/OFE/...) supported by the ICP v4l2 device.

CRs-Fixed: 3364226
Change-Id: I775f6248a4971b47eb7f832e2e6b6b3d3ab9952e
Signed-off-by: Petar Ivanov <[email protected]>
Signed-off-by: Sokchetra Eung <[email protected]>
Petar Ivanov 2 роки тому
батько
коміт
542c0759e8

+ 9 - 0
drivers/cam_icp/fw_inc/hfi_intf.h

@@ -146,6 +146,15 @@ int cam_hfi_unregister(int *client_handle);
  */
 int hfi_get_hw_caps(void *query_caps);
 
+/**
+ * hfi_get_hw_caps_v2() - hardware capabilities from firmware, used for v2 query cap
+ * @client_handle: client handle
+ * @query_caps: holds query information from hfi
+ *
+ * Returns success(zero)/failure(non zero)
+ */
+int hfi_get_hw_caps_v2(int client_handle, void *query_caps);
+
 /**
  * hfi_send_system_cmd() - send hfi system command to firmware
  * @client_handle: client handle

+ 2 - 0
drivers/cam_icp/fw_inc/hfi_reg.h

@@ -283,6 +283,7 @@ struct hfi_qtbl {
  * @msg_q_state: State of message queue
  * @priv: device private data
  * @dbg_lvl: debug level set to FW
+ * @fw_version: firmware version
  * @client_name: hfi client's name
  */
 struct hfi_info {
@@ -298,6 +299,7 @@ struct hfi_info {
 	bool msg_q_state;
 	void *priv;
 	u64 dbg_lvl;
+	uint32_t fw_version;
 	char client_name[HFI_CLIENT_NAME_LEN];
 };
 

+ 32 - 6
drivers/cam_icp/hfi.c

@@ -759,12 +759,38 @@ int hfi_get_hw_caps(void *query_buf)
 	return 0;
 }
 
+int hfi_get_hw_caps_v2(int client_handle, void *query_buf)
+{
+	struct cam_icp_query_cap_cmd_v2 *query_cmd = NULL;
+	struct hfi_info *hfi;
+	int rc = 0;
+
+	rc = hfi_get_client_info(client_handle, &hfi);
+	if (rc) {
+		CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d",
+			rc, client_handle);
+		return rc;
+	}
+
+	if (!query_buf) {
+		CAM_ERR(CAM_HFI, "[%s] query cap buf is NULL", hfi->client_name);
+		return -EINVAL;
+	}
+
+	query_cmd = (struct cam_icp_query_cap_cmd_v2 *)query_buf;
+	query_cmd->fw_version.major = (hfi->fw_version & 0xFF000000) >> 24;
+	query_cmd->fw_version.minor = (hfi->fw_version & 0x00FF0000) >> 16;
+	query_cmd->fw_version.revision = (hfi->fw_version & 0xFFFF);
+
+	return 0;
+}
+
 int cam_hfi_resume(int client_handle)
 {
 	int rc = 0;
 	struct hfi_info *hfi;
 	struct hfi_mem_info *hfi_mem;
-	uint32_t fw_version, status = 0;
+	uint32_t status = 0;
 	void __iomem *icp_base = NULL;
 
 	rc = hfi_get_client_info(client_handle, &hfi);
@@ -793,9 +819,8 @@ int cam_hfi_resume(int client_handle)
 
 	hfi_irq_enable(hfi);
 
-	fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
-	CAM_DBG(CAM_HFI, "[%s] hfi hdl: %d fw version : [%x]",
-		hfi->client_name, client_handle, fw_version);
+	CAM_DBG(CAM_HFI, "[%s] hfi hdl: %d fw version : [0x%x]",
+		hfi->client_name, client_handle, hfi->fw_version);
 
 	hfi_mem = &hfi->map;
 	cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
@@ -1098,8 +1123,9 @@ int cam_hfi_init(int client_handle, struct hfi_mem_info *hfi_mem,
 		goto regions_fail;
 	}
 
-	CAM_DBG(CAM_HFI, "ICP fw version: 0x%x",
-		cam_io_r(icp_base + HFI_REG_FW_VERSION));
+	hfi->fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
+	CAM_DBG(CAM_HFI, "[%s] ICP fw version: 0x%x",
+		hfi->client_name, hfi->fw_version);
 
 	hfi->cmd_q_state = true;
 	hfi->msg_q_state = true;

+ 107 - 8
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -7140,6 +7140,7 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
 	int rc = 0;
 	struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
 	struct cam_query_cap_cmd *query_cap = hw_caps_args;
+	struct cam_icp_query_cap_cmd icp_caps;
 
 	if ((!hw_mgr_priv) || (!hw_caps_args)) {
 		CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", hw_mgr_priv, hw_caps_args);
@@ -7148,31 +7149,128 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
 
 	if (sizeof(struct cam_icp_query_cap_cmd) != query_cap->size) {
 		CAM_ERR(CAM_ICP,
-			"Input query cap size:%u does not match expected query cap size: %u",
-			query_cap->size, sizeof(struct cam_icp_query_cap_cmd));
+			"[%s] Input query cap size:%u does not match expected query cap size: %u",
+			hw_mgr->hw_mgr_name, query_cap->size,
+			sizeof(struct cam_icp_query_cap_cmd));
 		return -EFAULT;
 	}
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
-	if (copy_from_user(&hw_mgr->icp_caps,
+	if (copy_from_user(&icp_caps,
 		u64_to_user_ptr(query_cap->caps_handle),
 		sizeof(struct cam_icp_query_cap_cmd))) {
-		CAM_ERR(CAM_ICP, "[%s] copy_from_user failed", hw_mgr->hw_mgr_name);
+		CAM_ERR(CAM_ICP, "[%s] copy from_user failed", hw_mgr->hw_mgr_name);
 		rc = -EFAULT;
 		goto end;
 	}
 
-	rc = hfi_get_hw_caps(&hw_mgr->icp_caps);
+	rc = hfi_get_hw_caps(&icp_caps);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "[%s] Fail to get hfi caps", hw_mgr->hw_mgr_name);
 		goto end;
 	}
 
-	hw_mgr->icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl;
-	hw_mgr->icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl;
+	icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl;
+	icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl;
 
 	if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle),
-		&hw_mgr->icp_caps, sizeof(struct cam_icp_query_cap_cmd))) {
+		&icp_caps, sizeof(struct cam_icp_query_cap_cmd))) {
+		CAM_ERR(CAM_ICP, "[%s] copy_to_user failed", hw_mgr->hw_mgr_name);
+		rc = -EFAULT;
+	}
+end:
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	return rc;
+}
+
+static int cam_icp_mgr_get_hw_caps_v2(void *hw_mgr_priv, void *hw_caps_args)
+{
+	int rc = 0;
+	struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_query_cap_cmd *query_cap = hw_caps_args;
+	struct cam_icp_query_cap_cmd_v2 query_cmd;
+	uint32_t supported_hw_dev, num_supported_device = 0;
+	int i;
+
+	if ((!hw_mgr_priv) || (!hw_caps_args)) {
+		CAM_ERR(CAM_ICP, "Invalid params: %pK %pK",
+			hw_mgr_priv, hw_caps_args);
+		return -EINVAL;
+	}
+
+	if (sizeof(struct cam_icp_query_cap_cmd_v2) != query_cap->size) {
+		CAM_ERR(CAM_ICP,
+			"[%s] Input query cap size:%u does not match expected query cap size: %ud",
+			hw_mgr->hw_mgr_name, query_cap->size,
+			sizeof(struct cam_icp_query_cap_cmd_v2));
+		return -EFAULT;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	if (copy_from_user(&query_cmd, u64_to_user_ptr(query_cap->caps_handle),
+		sizeof(struct cam_icp_query_cap_cmd_v2))) {
+		CAM_ERR(CAM_ICP, "[%s] copy from user failed", hw_mgr->hw_mgr_name);
+		rc = -EFAULT;
+		goto end;
+	}
+	memset(&query_cmd.dev_info, 0,
+		(CAM_ICP_MAX_NUM_OF_DEV_TYPES * sizeof(struct cam_icp_device_info)));
+
+	for (i = 0; i < CAM_ICP_HW_MAX; i++) {
+		if (!CAM_ICP_IS_DEV_HW_EXIST(hw_mgr->hw_cap_mask, i))
+			continue;
+
+		switch (i) {
+		case CAM_ICP_HW_ICP_V1:
+			fallthrough;
+		case CAM_ICP_HW_ICP_V2:
+			supported_hw_dev = CAM_ICP_DEV_TYPE_ICP;
+			break;
+		case CAM_ICP_DEV_IPE:
+			supported_hw_dev = CAM_ICP_DEV_TYPE_IPE;
+			break;
+		case CAM_ICP_DEV_BPS:
+			supported_hw_dev = CAM_ICP_DEV_TYPE_BPS;
+			break;
+		case CAM_ICP_DEV_OFE:
+			supported_hw_dev = CAM_ICP_DEV_TYPE_OFE;
+			break;
+		default:
+			CAM_ERR(CAM_ICP, "[%s] Invalid icp hw type: %u",
+				hw_mgr->hw_mgr_name, i);
+			rc = -EBADSLT;
+			goto end;
+		}
+
+		if (num_supported_device >= CAM_ICP_MAX_NUM_OF_DEV_TYPES) {
+			CAM_ERR(CAM_ICP,
+				"[%s] number of supported hw devices:%u exceeds maximum number of devices supported by query cap struct: %u",
+				hw_mgr->hw_mgr_name, num_supported_device,
+				CAM_ICP_MAX_NUM_OF_DEV_TYPES);
+			rc = -EFAULT;
+			goto end;
+		}
+
+		query_cmd.dev_info[num_supported_device].dev_type = supported_hw_dev;
+		query_cmd.dev_info[num_supported_device].num_devices = hw_mgr->hw_dev_cnt[i];
+
+		num_supported_device++;
+	}
+
+	query_cmd.num_dev_info = num_supported_device;
+
+	rc = hfi_get_hw_caps_v2(hw_mgr->hfi_handle, &query_cmd);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "[%s] Fail to get hfi caps rc:%d",
+			hw_mgr->hw_mgr_name, rc);
+		goto end;
+	}
+
+	query_cmd.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl;
+	query_cmd.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl;
+
+	if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle),
+		&query_cmd, sizeof(struct cam_icp_query_cap_cmd_v2))) {
 		CAM_ERR(CAM_ICP, "[%s] copy_to_user failed", hw_mgr->hw_mgr_name);
 		rc = -EFAULT;
 	}
@@ -7713,6 +7811,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
 
 	hw_mgr_intf->hw_mgr_priv = hw_mgr;
 	hw_mgr_intf->hw_get_caps = cam_icp_mgr_get_hw_caps;
+	hw_mgr_intf->hw_get_caps_v2 = cam_icp_mgr_get_hw_caps_v2;
 	hw_mgr_intf->hw_acquire = cam_icp_mgr_acquire_hw;
 	hw_mgr_intf->hw_release = cam_icp_mgr_release_hw;
 	hw_mgr_intf->hw_prepare_update = cam_icp_mgr_prepare_hw_update;

+ 0 - 2
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h

@@ -408,7 +408,6 @@ struct cam_icp_clk_info {
  * @icp_dev_intf: ICP device interface
  * @hw_dev_cnt: count number of each hw type
  * @ctx_data: Context data
- * @icp_caps: ICP capabilities
  * @mini_dump_cb: Mini dump cb
  * @hw_mgr_name: name of the hw mgr
  * @hw_mgr_id: ID of the hw mgr, equivalent to hw mgr index
@@ -462,7 +461,6 @@ struct cam_icp_hw_mgr {
 	struct cam_hw_intf *icp_dev_intf;
 	uint32_t hw_dev_cnt[CAM_ICP_HW_MAX];
 	struct cam_icp_hw_ctx_data ctx_data[CAM_ICP_CTX_MAX];
-	struct cam_icp_query_cap_cmd icp_caps;
 	cam_icp_mini_dump_cb mini_dump_cb;
 	char hw_mgr_name[CAM_ICP_HW_MGR_NAME_SIZE];
 	uint32_t hw_mgr_id;