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/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index d61606a..f0549cb 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -7,9 +7,11 @@
- 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
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;