msm: vidc: support for multiple partitions per context bank

Parsing logic to support new device tree structure that allows
multiple partitions per context bank.

Change-Id: I7ea9e583439ea547d5eccb312b598c1929b69565
Signed-off-by: Eric Ho <yinlokh@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 79a492e..5140a03 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -500,8 +500,13 @@
 	struct smem_client *client = clt;
 	struct iommu_set *iommu_group_set = &client->res->iommu_group_set;
 	int i;
+	int j;
 	bool is_secure = (flags & SMEM_SECURE);
 	struct iommu_info *iommu_map;
+	if (!domain_num || !partition_num) {
+		dprintk(VIDC_DBG, "passed null to get domain partition!");
+		return -EINVAL;
+	}
 
 	*domain_num = -1;
 	*partition_num = -1;
@@ -512,14 +517,14 @@
 
 	for (i = 0; i < iommu_group_set->count; i++) {
 		iommu_map = &iommu_group_set->iommu_maps[i];
-		if ((iommu_map->is_secure == is_secure) &&
-			(iommu_map->buffer_type & buffer_type)) {
-			*domain_num = iommu_map->domain;
-			*partition_num = 0;
-			if ((buffer_type & HAL_BUFFER_INTERNAL_CMD_QUEUE) &&
-				(iommu_map->npartitions == 2))
-				*partition_num = 1;
-			break;
+		if (iommu_map->is_secure == is_secure) {
+			for (j = 0; j < iommu_map->npartitions; j++) {
+				if (iommu_map->buffer_type[j] & buffer_type) {
+					*domain_num = iommu_map->domain;
+					*partition_num = j;
+					break;
+				}
+			}
 		}
 	}
 	dprintk(VIDC_DBG, "domain: %d, partition: %d found!\n",
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index cb08da7..394ecdc5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -386,65 +386,56 @@
 {
 	int rc = 0;
 	struct platform_device *pdev = res->pdev;
-	struct device_node *ctx_node;
+	struct device_node *domains_parent_node = NULL;
+	struct device_node *domains_child_node = NULL;
 	struct iommu_set *iommu_group_set = &res->iommu_group_set;
-	int array_size;
-	int i;
+	int domain_idx = 0;
 	struct iommu_info *iommu_map;
-	u32 *buffer_types = NULL;
+	int array_size = 0;
 
-	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
-				&array_size)) {
-		dprintk(VIDC_DBG, "iommu_groups property not present\n");
-		iommu_group_set->count = 0;
+	domains_parent_node = of_find_node_by_name(pdev->dev.of_node,
+				"qcom,vidc-iommu-domains");
+	if (!domains_parent_node) {
+		dprintk(VIDC_DBG, "Node qcom,vidc-iommu-domains not found.\n");
 		return 0;
 	}
 
-	iommu_group_set->count = array_size / sizeof(u32);
+	iommu_group_set->count = 0;
+	for_each_child_of_node(domains_parent_node, domains_child_node) {
+		iommu_group_set->count++;
+	}
+
 	if (iommu_group_set->count == 0) {
-		dprintk(VIDC_ERR, "No group present in iommu_groups\n");
+		dprintk(VIDC_ERR, "No group present in iommu_domains\n");
 		rc = -ENOENT;
 		goto err_no_of_node;
 	}
-
 	iommu_group_set->iommu_maps = kzalloc(iommu_group_set->count *
 			sizeof(*(iommu_group_set->iommu_maps)), GFP_KERNEL);
+
 	if (!iommu_group_set->iommu_maps) {
-		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n",
-			__func__);
+		dprintk(VIDC_ERR, "Cannot allocate iommu_maps\n");
 		rc = -ENOMEM;
 		goto err_no_of_node;
 	}
 
-	buffer_types = kzalloc(iommu_group_set->count * sizeof(*buffer_types),
-				GFP_KERNEL);
-	if (!buffer_types) {
-		dprintk(VIDC_ERR,
-			"%s Failed to alloc iommu group buffer types\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_load_groups;
-	}
+	/* set up each context bank */
+	for_each_child_of_node(domains_parent_node, domains_child_node) {
+		struct device_node *ctx_node = of_parse_phandle(
+						domains_child_node,
+						"qcom,vidc-domain-phandle",
+						0);
+		if (domain_idx >= iommu_group_set->count)
+			break;
 
-	rc = of_property_read_u32_array(pdev->dev.of_node,
-			"qcom,iommu-group-buffer-types", buffer_types,
-			iommu_group_set->count);
-	if (rc) {
-		dprintk(VIDC_ERR,
-		    "%s Failed to read iommu group buffer types\n", __func__);
-		goto err_load_groups;
-	}
-
-	for (i = 0; i < iommu_group_set->count; i++) {
-		iommu_map = &iommu_group_set->iommu_maps[i];
-		ctx_node = of_parse_phandle(pdev->dev.of_node,
-				"qcom,iommu-groups", i);
+		iommu_map = &iommu_group_set->iommu_maps[domain_idx];
 		if (!ctx_node) {
-			dprintk(VIDC_ERR, "Unable to parse phandle : %u\n", i);
+			dprintk(VIDC_ERR, "Unable to parse pHandle\n");
 			rc = -EBADHANDLE;
 			goto err_load_groups;
 		}
 
+		/* domain info from domains.dtsi */
 		rc = of_property_read_string(ctx_node, "label",
 				&(iommu_map->name));
 		if (rc) {
@@ -452,6 +443,11 @@
 			goto err_load_groups;
 		}
 
+		dprintk(VIDC_DBG,
+				"domain %d has name %s\n",
+				domain_idx,
+				iommu_map->name);
+
 		if (!of_get_property(ctx_node, "qcom,virtual-addr-pool",
 				&array_size)) {
 			dprintk(VIDC_ERR,
@@ -463,25 +459,48 @@
 
 		iommu_map->npartitions = array_size / sizeof(u32) / 2;
 
+		dprintk(VIDC_DBG,
+				"%d partitions in domain %d",
+				iommu_map->npartitions,
+				domain_idx);
+
 		rc = of_property_read_u32_array(ctx_node,
 				"qcom,virtual-addr-pool",
 				(u32 *)iommu_map->addr_range,
 				iommu_map->npartitions * 2);
 		if (rc) {
 			dprintk(VIDC_ERR,
-				"Could not read addr pool for group : %s\n",
-				iommu_map->name);
+				"Could not read addr pool for group : %s (%d)\n",
+				iommu_map->name,
+				rc);
 			goto err_load_groups;
 		}
 
-		iommu_map->buffer_type = buffer_types[i];
 		iommu_map->is_secure =
 			of_property_read_bool(ctx_node,	"qcom,secure-domain");
+
+		dprintk(VIDC_DBG,
+				"domain %s : secure = %d",
+				iommu_map->name,
+				iommu_map->is_secure);
+
+		/* setup partitions and buffer type per partition */
+		rc = of_property_read_u32_array(domains_child_node,
+				"qcom,vidc-partition-buffer-types",
+				iommu_map->buffer_type,
+				iommu_map->npartitions);
+
+		if (rc) {
+			dprintk(VIDC_ERR,
+					"cannot load partition buffertype information (%d)",
+					rc);
+			rc = -ENOENT;
+			goto err_load_groups;
+		}
+		domain_idx++;
 	}
-	kfree(buffer_types);
-	return 0;
+	return rc;
 err_load_groups:
-	kfree(buffer_types);
 	msm_vidc_free_iommu_groups(res);
 err_no_of_node:
 	return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 43af909..8176ea5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -16,6 +16,7 @@
 
 #include <linux/platform_device.h>
 #include <media/msm_vidc.h>
+#define MAX_BUFFER_TYPES 32
 
 struct load_freq_table {
 	u32 load;
@@ -39,11 +40,11 @@
 
 struct iommu_info {
 	const char *name;
-	u32 buffer_type;
+	u32 buffer_type[MAX_BUFFER_TYPES];
 	struct iommu_group *group;
 	int domain;
 	bool is_secure;
-	struct addr_range addr_range[2];
+	struct addr_range addr_range[MAX_BUFFER_TYPES];
 	int npartitions;
 };
 
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 47b88db..5416210 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2804,6 +2804,9 @@
 				iommu_map->addr_range[0].start;
 			memprot.cp_nonpixel_size =
 				iommu_map->addr_range[0].size;
+		} else if (strcmp(iommu_map->name, "venus_cp") == 0) {
+			memprot.cp_nonpixel_start =
+				iommu_map->addr_range[1].start;
 		}
 	}