msm: vidc: Add changes to read efuse, dt and platform data

Add changes to read efuse and sku version.

For multiple sku variants, common_data will be initialized
with version-0 common_data, if sku version is set, this
will be overridden with version-1 in vidc_get_drv_data().

If sku-index is present in dtsi file, parse device tree
parameters only if sku-index and sku_version matches.

CRs-Fixed: 2100821
Change-Id: I1f1c4d2704c2d74e259e0597abfff0dd041e1278
Signed-off-by: Manikanta Kanamarlapudi <kmanikan@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 56f9675..fa40091 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -448,14 +448,14 @@
 static DEVICE_ATTR(thermal_level, 0644, show_thermal_level,
 		store_thermal_level);
 
-static ssize_t show_platform_version(struct device *dev,
+static ssize_t show_sku_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d",
-			vidc_driver->platform_version);
+			vidc_driver->sku_version);
 }
 
-static ssize_t store_platform_version(struct device *dev,
+static ssize_t store_sku_version(struct device *dev,
 		struct device_attribute *attr, const char *buf,
 		size_t count)
 {
@@ -463,13 +463,13 @@
 	return count;
 }
 
-static DEVICE_ATTR(platform_version, 0444, show_platform_version,
-		store_platform_version);
+static DEVICE_ATTR(sku_version, 0444, show_sku_version,
+		store_sku_version);
 
 static struct attribute *msm_vidc_core_attrs[] = {
 		&dev_attr_pwr_collapse_delay.attr,
 		&dev_attr_thermal_level.attr,
-		&dev_attr_platform_version.attr,
+		&dev_attr_sku_version.attr,
 		NULL
 };
 
@@ -487,8 +487,6 @@
 static int msm_vidc_probe_vidc_device(struct platform_device *pdev)
 {
 	int rc = 0;
-	void __iomem *base;
-	struct resource *res;
 	struct msm_vidc_core *core;
 	struct device *dev;
 	int nr = BASE_DEVICE_NUMBER;
@@ -605,32 +603,7 @@
 	core->debugfs_root = msm_vidc_debugfs_init_core(
 		core, vidc_driver->debugfs_root);
 
-	vidc_driver->platform_version = 0;
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse");
-	if (!res) {
-		dprintk(VIDC_DBG, "failed to get efuse resource\n");
-	} else {
-		base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-		if (!base) {
-			dprintk(VIDC_ERR,
-				"failed efuse ioremap: res->start %#x, size %d\n",
-				(u32)res->start, (u32)resource_size(res));
-		} else {
-			u32 efuse = 0;
-			struct platform_version_table *pf_ver_tbl =
-				core->resources.pf_ver_tbl;
-
-			efuse = readl_relaxed(base);
-			vidc_driver->platform_version =
-				(efuse & pf_ver_tbl->version_mask) >>
-				pf_ver_tbl->version_shift;
-			dprintk(VIDC_DBG,
-				"efuse 0x%x, platform version 0x%x\n",
-				efuse, vidc_driver->platform_version);
-
-			devm_iounmap(&pdev->dev, base);
-		}
-	}
+	vidc_driver->sku_version = core->resources.sku_version;
 
 	dprintk(VIDC_DBG, "populating sub devices\n");
 	/*
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index a0f7d2e..c4e3ab2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -195,12 +195,33 @@
 	int low_power_cycles;
 };
 
+enum efuse_purpose {
+	SKU_VERSION = 0,
+};
+
+enum sku_version {
+	SKU_VERSION_0 = 0,
+	SKU_VERSION_1,
+	SKU_VERSION_2,
+};
+
+struct msm_vidc_efuse_data {
+	u32 start_address;
+	u32 size;
+	u32 mask;
+	u32 shift;
+	enum efuse_purpose purpose;
+};
+
 struct msm_vidc_platform_data {
 	struct msm_vidc_common_data *common_data;
 	unsigned int common_data_length;
 	struct msm_vidc_codec_data *codec_data;
 	unsigned int codec_data_length;
 	struct msm_vidc_csc_coeff csc_data;
+	struct msm_vidc_efuse_data *efuse_data;
+	unsigned int efuse_data_length;
+	unsigned int sku_version;
 };
 
 struct msm_vidc_format {
@@ -218,7 +239,7 @@
 	int num_cores;
 	struct dentry *debugfs_root;
 	int thermal_level;
-	u32 platform_version;
+	u32 sku_version;
 };
 
 struct msm_video_device {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index 0fe09e2..3554998 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -24,6 +24,7 @@
 #include <linux/version.h>
 #include <linux/io.h>
 #include "msm_vidc_internal.h"
+#include "msm_vidc_debug.h"
 
 
 #define CODEC_ENTRY(n, p, vsp, vpp, lp) \
@@ -35,6 +36,15 @@
 	.low_power_cycles = lp	\
 }
 
+#define EFUSE_ENTRY(sa, s, m, sh, p) \
+{	\
+	.start_address = sa,		\
+	.size = s,	\
+	.mask = m,	\
+	.shift = sh,	\
+	.purpose = p	\
+}
+
 static struct msm_vidc_codec_data default_codec_data[] =  {
 	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_ENCODER, 125, 675, 320),
 	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_DECODER, 125, 675, 320),
@@ -52,6 +62,17 @@
 	CODEC_ENTRY(V4L2_PIX_FMT_VP9, MSM_VIDC_DECODER, 50, 200, 200),
 };
 
+static struct msm_vidc_codec_data sdm670_codec_data[] =  {
+	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_ENCODER, 125, 675, 320),
+	CODEC_ENTRY(V4L2_PIX_FMT_HEVC, MSM_VIDC_ENCODER, 125, 675, 320),
+	CODEC_ENTRY(V4L2_PIX_FMT_VP8, MSM_VIDC_ENCODER, 125, 675, 320),
+	CODEC_ENTRY(V4L2_PIX_FMT_MPEG2, MSM_VIDC_DECODER, 50, 200, 200),
+	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_DECODER, 50, 200, 200),
+	CODEC_ENTRY(V4L2_PIX_FMT_HEVC, MSM_VIDC_DECODER, 50, 200, 200),
+	CODEC_ENTRY(V4L2_PIX_FMT_VP8, MSM_VIDC_DECODER, 50, 200, 200),
+	CODEC_ENTRY(V4L2_PIX_FMT_VP9, MSM_VIDC_DECODER, 50, 200, 200),
+};
+
 /*
  * Custom conversion coefficients for resolution: 176x144 negative
  * coeffs are converted to s4.9 format
@@ -130,6 +151,95 @@
 	},
 };
 
+static struct msm_vidc_common_data sdm670_common_data_v0[] = {
+	{
+		.key = "qcom,never-unload-fw",
+		.value = 1,
+	},
+	{
+		.key = "qcom,sw-power-collapse",
+		.value = 1,
+	},
+	{
+		.key = "qcom,max-secure-instances",
+		.value = 5,
+	},
+	{
+		.key = "qcom,max-hw-load",
+		.value = 1944000,
+	},
+	{
+		.key = "qcom,max-hq-mbs-per-frame",
+		.value = 8160,
+	},
+	{
+		.key = "qcom,max-hq-frames-per-sec",
+		.value = 60,
+	},
+	{
+		.key = "qcom,max-b-frame-size",
+		.value = 8160,
+	},
+	{
+		.key = "qcom,max-b-frames-per-sec",
+		.value = 60,
+	},
+	{
+		.key = "qcom,power-collapse-delay",
+		.value = 500,
+	},
+	{
+		.key = "qcom,hw-resp-timeout",
+		.value = 250,
+	},
+};
+
+static struct msm_vidc_common_data sdm670_common_data_v1[] = {
+	{
+		.key = "qcom,never-unload-fw",
+		.value = 1,
+	},
+	{
+		.key = "qcom,sw-power-collapse",
+		.value = 1,
+	},
+	{
+		.key = "qcom,max-secure-instances",
+		.value = 5,
+	},
+	{
+		.key = "qcom,max-hw-load",
+		.value = 1216800,
+	},
+	{
+		.key = "qcom,max-hq-mbs-per-frame",
+		.value = 8160,
+	},
+	{
+		.key = "qcom,max-hq-frames-per-sec",
+		.value = 60,
+	},
+	{
+		.key = "qcom,max-b-frame-size",
+		.value = 8160,
+	},
+	{
+		.key = "qcom,max-b-frames-per-sec",
+		.value = 60,
+	},
+	{
+		.key = "qcom,power-collapse-delay",
+		.value = 500,
+	},
+	{
+		.key = "qcom,hw-resp-timeout",
+		.value = 250,
+	},
+};
+
+static struct msm_vidc_efuse_data sdm670_efuse_data[] = {
+	EFUSE_ENTRY(0x007801A0, 4, 0x00008000, 0x0f, SKU_VERSION),
+};
 
 static struct msm_vidc_platform_data default_data = {
 	.codec_data = default_codec_data,
@@ -139,6 +249,9 @@
 	.csc_data.vpe_csc_custom_bias_coeff = vpe_csc_custom_bias_coeff,
 	.csc_data.vpe_csc_custom_matrix_coeff = vpe_csc_custom_matrix_coeff,
 	.csc_data.vpe_csc_custom_limit_coeff = vpe_csc_custom_limit_coeff,
+	.efuse_data = NULL,
+	.efuse_data_length = 0,
+	.sku_version = 0,
 };
 
 static struct msm_vidc_platform_data sdm845_data = {
@@ -149,6 +262,22 @@
 	.csc_data.vpe_csc_custom_bias_coeff = vpe_csc_custom_bias_coeff,
 	.csc_data.vpe_csc_custom_matrix_coeff = vpe_csc_custom_matrix_coeff,
 	.csc_data.vpe_csc_custom_limit_coeff = vpe_csc_custom_limit_coeff,
+	.efuse_data = NULL,
+	.efuse_data_length = 0,
+	.sku_version = 0,
+};
+
+static struct msm_vidc_platform_data sdm670_data = {
+	.codec_data = sdm670_codec_data,
+	.codec_data_length =  ARRAY_SIZE(sdm670_codec_data),
+	.common_data = sdm670_common_data_v0,
+	.common_data_length =  ARRAY_SIZE(sdm670_common_data_v0),
+	.csc_data.vpe_csc_custom_bias_coeff = vpe_csc_custom_bias_coeff,
+	.csc_data.vpe_csc_custom_matrix_coeff = vpe_csc_custom_matrix_coeff,
+	.csc_data.vpe_csc_custom_limit_coeff = vpe_csc_custom_limit_coeff,
+	.efuse_data = sdm670_efuse_data,
+	.efuse_data_length = ARRAY_SIZE(sdm670_efuse_data),
+	.sku_version = 0,
 };
 
 static const struct of_device_id msm_vidc_dt_match[] = {
@@ -156,15 +285,62 @@
 		.compatible = "qcom,sdm845-vidc",
 		.data = &sdm845_data,
 	},
-	{},
+	{
+		.compatible = "qcom,sdm670-vidc",
+		.data = &sdm670_data,
+	},
 };
 
 MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
 
+static int msm_vidc_read_efuse(
+		struct msm_vidc_platform_data *data, struct device *dev)
+{
+	void __iomem *base;
+	uint32_t i;
+	struct msm_vidc_efuse_data *efuse_data = data->efuse_data;
+	uint32_t efuse_data_count = data->efuse_data_length;
+
+	for (i = 0; i < efuse_data_count; i++) {
+
+		switch ((efuse_data[i]).purpose) {
+
+		case SKU_VERSION:
+			base = devm_ioremap(dev, (efuse_data[i]).start_address,
+					(efuse_data[i]).size);
+			if (!base) {
+				dprintk(VIDC_ERR,
+					"failed efuse ioremap: res->start %#x, size %d\n",
+					(efuse_data[i]).start_address,
+					(efuse_data[i]).size);
+					return -EINVAL;
+			} else {
+				u32 efuse = 0;
+
+				efuse = readl_relaxed(base);
+				data->sku_version =
+					(efuse & (efuse_data[i]).mask) >>
+					(efuse_data[i]).shift;
+				dprintk(VIDC_DBG,
+					"efuse 0x%x, platform version 0x%x\n",
+					efuse, data->sku_version);
+
+				devm_iounmap(dev, base);
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
 void *vidc_get_drv_data(struct device *dev)
 {
 	struct msm_vidc_platform_data *driver_data = NULL;
 	const struct of_device_id *match;
+	int rc = 0;
 
 	if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) {
 		driver_data = &default_data;
@@ -176,6 +352,21 @@
 	if (match)
 		driver_data = (struct msm_vidc_platform_data *)match->data;
 
+	if (!of_find_property(dev->of_node, "sku-index", NULL) ||
+			!driver_data) {
+		goto exit;
+	} else if (!strcmp(match->compatible, "qcom,sdm670-vidc")) {
+		rc = msm_vidc_read_efuse(driver_data, dev);
+		if (rc)
+			goto exit;
+
+		if (driver_data->sku_version == SKU_VERSION_1) {
+			driver_data->common_data = sdm670_common_data_v1;
+			driver_data->common_data_length =
+					ARRAY_SIZE(sdm670_common_data_v1);
+		}
+	}
+
 exit:
 	return driver_data;
 }
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 f343939..a0214a2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -73,12 +73,6 @@
 	res->clock_freq_tbl.clk_prof_entries = NULL;
 }
 
-static inline void msm_vidc_free_platform_version_table(
-		struct msm_vidc_platform_resources *res)
-{
-	res->pf_ver_tbl = NULL;
-}
-
 static inline void msm_vidc_free_reg_table(
 			struct msm_vidc_platform_resources *res)
 {
@@ -133,7 +127,6 @@
 {
 	msm_vidc_free_clock_table(res);
 	msm_vidc_free_regulator_table(res);
-	msm_vidc_free_platform_version_table(res);
 	msm_vidc_free_allowed_clocks_table(res);
 	msm_vidc_free_reg_table(res);
 	msm_vidc_free_qdss_addr_table(res);
@@ -344,33 +337,6 @@
 }
 EXPORT_SYMBOL(msm_vidc_load_u32_table);
 
-static int msm_vidc_load_platform_version_table(
-		struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	struct platform_device *pdev = res->pdev;
-
-	if (!of_find_property(pdev->dev.of_node,
-			"qcom,platform-version", NULL)) {
-		dprintk(VIDC_DBG, "qcom,platform-version not found\n");
-		return 0;
-	}
-
-	rc = msm_vidc_load_u32_table(pdev, pdev->dev.of_node,
-			"qcom,platform-version",
-			sizeof(*res->pf_ver_tbl),
-			(u32 **)&res->pf_ver_tbl,
-			NULL);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"%s: failed to read platform version table\n",
-			__func__);
-		return rc;
-	}
-
-	return 0;
-}
-
 /* A comparator to compare loads (needed later on) */
 static int cmp(const void *a, const void *b)
 {
@@ -712,6 +678,29 @@
 	return rc;
 }
 
+static int msm_decide_dt_node(
+		struct msm_vidc_platform_resources *res) {
+	struct platform_device *pdev = res->pdev;
+	int rc = 0;
+	u32 sku_index = 0;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "sku-index",
+			&sku_index);
+	if (rc) {
+		dprintk(VIDC_DBG, "'sku_index' not found in node\n");
+		return 0;
+	}
+
+	if (sku_index != res->sku_version) {
+		dprintk(VIDC_DBG,
+			"Failed to parser dt: sku_index %d res->sku_version - %d\n",
+			sku_index, res->sku_version);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int find_key_value(struct msm_vidc_platform_data *platform_data,
 	const char *key)
 {
@@ -743,6 +732,8 @@
 	res->codec_data_count = platform_data->codec_data_length;
 	res->codec_data = platform_data->codec_data;
 
+	res->sku_version = platform_data->sku_version;
+
 	res->fw_name = "venus";
 
 	dprintk(VIDC_DBG, "Firmware filename: %s\n", res->fw_name);
@@ -805,6 +796,11 @@
 		return -ENOENT;
 	}
 
+	rc = msm_decide_dt_node(res);
+	if (rc)
+		return rc;
+
+
 	INIT_LIST_HEAD(&res->context_banks);
 
 	res->firmware_base = (phys_addr_t)firmware_base;
@@ -816,10 +812,6 @@
 	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	res->irq = kres ? kres->start : -1;
 
-	rc = msm_vidc_load_platform_version_table(res);
-	if (rc)
-		dprintk(VIDC_ERR, "Failed to load pf version table: %d\n", rc);
-
 	rc = msm_vidc_load_subcache_info(res);
 	if (rc)
 		dprintk(VIDC_WARN, "Failed to load subcache info: %d\n", rc);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 8309fce..99b4e30 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -21,11 +21,6 @@
 
 #define MAX_BUFFER_TYPES 32
 
-struct platform_version_table {
-	u32 version_mask;
-	u32 version_shift;
-};
-
 struct dcvs_table {
 	u32 load;
 	u32 load_low;
@@ -153,7 +148,7 @@
 	phys_addr_t register_base;
 	uint32_t register_size;
 	uint32_t irq;
-	struct platform_version_table *pf_ver_tbl;
+	uint32_t sku_version;
 	struct allowed_clock_rates_table *allowed_clks_tbl;
 	u32 allowed_clks_tbl_size;
 	struct clock_freq_table clock_freq_tbl;