Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ff858de authored by Manikanta Kanamarlapudi's avatar Manikanta Kanamarlapudi Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarManikanta Kanamarlapudi <kmanikan@codeaurora.org>
parent 84a47e8c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7,9 +7,11 @@ Required properties:
- compatible : one of:
	- "qcom,msm-vidc"
        - "qcom,sdm845-vidc" : Invokes driver specific data for SDM845.
        - "qcom,sdm670-vidc" : Invokes driver specific data for SDM670.

Optional properties:
- reg : offset and length of the register set for the device.
- sku-index : sku version of the hardware.
- interrupts : should contain the vidc interrupt.
- qcom,reg-presets : list of offset-value pairs for registers to be written.
  The offsets are from the base offset specified in 'reg'. This is mainly
+7 −34
Original line number Diff line number Diff line
@@ -448,14 +448,14 @@ static ssize_t store_thermal_level(struct device *dev,
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 @@ static ssize_t store_platform_version(struct device *dev,
	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 const struct of_device_id msm_vidc_dt_match[] = {
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 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev)
	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");
	/*
+22 −1
Original line number Diff line number Diff line
@@ -195,12 +195,33 @@ struct msm_vidc_codec_data {
	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 @@ struct msm_vidc_drv {
	int num_cores;
	struct dentry *debugfs_root;
	int thermal_level;
	u32 platform_version;
	u32 sku_version;
};

struct msm_video_device {
+192 −1
Original line number Diff line number Diff line
@@ -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 @@ static struct msm_vidc_codec_data sdm845_codec_data[] = {
	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 sdm845_common_data[] = {
	},
};

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 @@ static struct msm_vidc_platform_data default_data = {
	.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 @@ static struct msm_vidc_platform_data sdm845_data = {
	.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 @@ static const struct of_device_id msm_vidc_dt_match[] = {
		.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 @@ void *vidc_get_drv_data(struct device *dev)
	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;
}
+30 −38
Original line number Diff line number Diff line
@@ -73,12 +73,6 @@ static inline void msm_vidc_free_cycles_per_mb_table(
	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 @@ void msm_vidc_free_platform_resources(
{
	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 @@ int msm_vidc_load_u32_table(struct platform_device *pdev,
}
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 @@ static int msm_vidc_load_clock_table(
	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 @@ int read_platform_resources_from_drv_data(
	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 @@ int read_platform_resources_from_dt(
		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 @@ int read_platform_resources_from_dt(
	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);
Loading