video: driver: reduce device_tree dependency for video
Only keep minimal entries in dtsi, which is essential for other drivers usage. Move remaining all data into platform resource file. Remove device_tree dependency and maintain platform_data to initialize resources like regulators, interconnects, clocks, reset_clocks, subcaches and context_banks. Read static data like freq_table, firmware_name, pas_id also from platform_data instead of from dtsi. Change-Id: I73a1df10b92c55e55b23e538aea62598a7250ab4 Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
This commit is contained in:
@@ -41,6 +41,61 @@ extern u32 vpe_csc_custom_matrix_coeff[MAX_MATRIX_COEFFS];
|
|||||||
extern u32 vpe_csc_custom_bias_coeff[MAX_BIAS_COEFFS];
|
extern u32 vpe_csc_custom_bias_coeff[MAX_BIAS_COEFFS];
|
||||||
extern u32 vpe_csc_custom_limit_coeff[MAX_LIMIT_COEFFS];
|
extern u32 vpe_csc_custom_limit_coeff[MAX_LIMIT_COEFFS];
|
||||||
|
|
||||||
|
struct bw_table {
|
||||||
|
const char *name;
|
||||||
|
u32 min_kbps;
|
||||||
|
u32 max_kbps;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regulator_table {
|
||||||
|
const char *name;
|
||||||
|
bool hw_trigger;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk_table {
|
||||||
|
const char *name;
|
||||||
|
u32 clk_id;
|
||||||
|
bool scaling;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk_rst_table {
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct subcache_table {
|
||||||
|
const char *name;
|
||||||
|
u32 llcc_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct context_bank_table {
|
||||||
|
const char *name;
|
||||||
|
u32 start;
|
||||||
|
u32 size;
|
||||||
|
bool secure;
|
||||||
|
bool dma_coherant;
|
||||||
|
u32 region;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct freq_table {
|
||||||
|
unsigned long freq;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct reg_preset_table {
|
||||||
|
u32 reg;
|
||||||
|
u32 value;
|
||||||
|
u32 mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msm_vidc_ubwc_config_data {
|
||||||
|
u32 max_channels;
|
||||||
|
u32 mal_length;
|
||||||
|
u32 highest_bank_bit;
|
||||||
|
u32 bank_swzl_level;
|
||||||
|
u32 bank_swz2_level;
|
||||||
|
u32 bank_swz3_level;
|
||||||
|
u32 bank_spreading;
|
||||||
|
};
|
||||||
|
|
||||||
struct codec_info {
|
struct codec_info {
|
||||||
u32 v4l2_codec;
|
u32 v4l2_codec;
|
||||||
enum msm_vidc_codec_type vidc_codec;
|
enum msm_vidc_codec_type vidc_codec;
|
||||||
@@ -112,16 +167,6 @@ struct msm_vidc_efuse_data {
|
|||||||
enum efuse_purpose purpose;
|
enum efuse_purpose purpose;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_vidc_ubwc_config_data {
|
|
||||||
u32 max_channels;
|
|
||||||
u32 mal_length;
|
|
||||||
u32 highest_bank_bit;
|
|
||||||
u32 bank_swzl_level;
|
|
||||||
u32 bank_swz2_level;
|
|
||||||
u32 bank_swz3_level;
|
|
||||||
u32 bank_spreading;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msm_vidc_format_capability {
|
struct msm_vidc_format_capability {
|
||||||
struct codec_info *codec_info;
|
struct codec_info *codec_info;
|
||||||
u32 codec_info_size;
|
u32 codec_info_size;
|
||||||
@@ -136,6 +181,26 @@ struct msm_vidc_format_capability {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msm_vidc_platform_data {
|
struct msm_vidc_platform_data {
|
||||||
|
const struct bw_table *bw_tbl;
|
||||||
|
unsigned int bw_tbl_size;
|
||||||
|
const struct regulator_table *regulator_tbl;
|
||||||
|
unsigned int regulator_tbl_size;
|
||||||
|
const struct clk_table *clk_tbl;
|
||||||
|
unsigned int clk_tbl_size;
|
||||||
|
const struct clk_rst_table *clk_rst_tbl;
|
||||||
|
unsigned int clk_rst_tbl_size;
|
||||||
|
const struct subcache_table *subcache_tbl;
|
||||||
|
unsigned int subcache_tbl_size;
|
||||||
|
const struct context_bank_table *context_bank_tbl;
|
||||||
|
unsigned int context_bank_tbl_size;
|
||||||
|
struct freq_table *freq_tbl;
|
||||||
|
unsigned int freq_tbl_size;
|
||||||
|
const struct reg_preset_table *reg_prst_tbl;
|
||||||
|
unsigned int reg_prst_tbl_size;
|
||||||
|
struct msm_vidc_ubwc_config_data *ubwc_config;
|
||||||
|
const char *fwname;
|
||||||
|
u32 pas_id;
|
||||||
|
bool supports_mmrm;
|
||||||
struct msm_platform_core_capability *core_data;
|
struct msm_platform_core_capability *core_data;
|
||||||
u32 core_data_size;
|
u32 core_data_size;
|
||||||
struct msm_platform_inst_capability *inst_cap_data;
|
struct msm_platform_inst_capability *inst_cap_data;
|
||||||
@@ -143,7 +208,6 @@ struct msm_vidc_platform_data {
|
|||||||
struct msm_platform_inst_cap_dependency *inst_cap_dependency_data;
|
struct msm_platform_inst_cap_dependency *inst_cap_dependency_data;
|
||||||
u32 inst_cap_dependency_data_size;
|
u32 inst_cap_dependency_data_size;
|
||||||
struct msm_vidc_csc_coeff csc_data;
|
struct msm_vidc_csc_coeff csc_data;
|
||||||
struct msm_vidc_ubwc_config_data *ubwc_config;
|
|
||||||
struct msm_vidc_efuse_data *efuse_data;
|
struct msm_vidc_efuse_data *efuse_data;
|
||||||
unsigned int efuse_data_size;
|
unsigned int efuse_data_size;
|
||||||
unsigned int sku_version;
|
unsigned int sku_version;
|
||||||
@@ -155,9 +219,18 @@ struct msm_vidc_platform {
|
|||||||
struct msm_vidc_platform_data data;
|
struct msm_vidc_platform_data data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline bool is_sys_cache_present(struct msm_vidc_core *core)
|
||||||
|
{
|
||||||
|
return !!core->platform->data.subcache_tbl_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_mmrm_supported(struct msm_vidc_core *core)
|
||||||
|
{
|
||||||
|
return !!core->platform->data.supports_mmrm;
|
||||||
|
}
|
||||||
|
|
||||||
int msm_vidc_init_platform(struct platform_device *pdev);
|
int msm_vidc_init_platform(struct platform_device *pdev);
|
||||||
int msm_vidc_deinit_platform(struct platform_device *pdev);
|
int msm_vidc_deinit_platform(struct platform_device *pdev);
|
||||||
int msm_vidc_read_efuse(struct msm_vidc_core *core);
|
int msm_vidc_read_efuse(struct msm_vidc_core *core);
|
||||||
void msm_vidc_sort_table(struct msm_vidc_core *core);
|
|
||||||
|
|
||||||
#endif // _MSM_VIDC_PLATFORM_H_
|
#endif // _MSM_VIDC_PLATFORM_H_
|
||||||
|
@@ -5,7 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/sort.h>
|
#include <linux/of.h>
|
||||||
|
#include <soc/qcom/of_common.h>
|
||||||
|
|
||||||
#include "msm_vidc_platform.h"
|
#include "msm_vidc_platform.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
#include "msm_vidc_vb2.h"
|
#include "msm_vidc_vb2.h"
|
||||||
#include "msm_vidc_control.h"
|
#include "msm_vidc_control.h"
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_internal.h"
|
#include "msm_vidc_internal.h"
|
||||||
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
||||||
@@ -25,9 +25,6 @@
|
|||||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
||||||
#include "msm_vidc_pineapple.h"
|
#include "msm_vidc_pineapple.h"
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
|
||||||
#include "msm_vidc_pineapple.h"
|
|
||||||
#endif
|
|
||||||
#if defined(CONFIG_MSM_VIDC_ANORAK)
|
#if defined(CONFIG_MSM_VIDC_ANORAK)
|
||||||
#include "msm_vidc_anorak.h"
|
#include "msm_vidc_anorak.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -221,7 +218,7 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
|
|||||||
d_vpr_h("%s()\n", __func__);
|
d_vpr_h("%s()\n", __func__);
|
||||||
|
|
||||||
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-waipio")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
|
||||||
rc = msm_vidc_deinit_platform_waipio(core, dev);
|
rc = msm_vidc_deinit_platform_waipio(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -229,7 +226,8 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_KALAMA)
|
#if defined(CONFIG_MSM_VIDC_KALAMA)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-kalama")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
|
||||||
rc = msm_vidc_deinit_platform_kalama(core, dev);
|
rc = msm_vidc_deinit_platform_kalama(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -237,7 +235,7 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-pineapple")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
|
||||||
rc = msm_vidc_deinit_platform_pineapple(core, dev);
|
rc = msm_vidc_deinit_platform_pineapple(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -245,7 +243,7 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_ANORAK)
|
#if defined(CONFIG_MSM_VIDC_ANORAK)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sxr2230p-vidc")) {
|
||||||
rc = msm_vidc_deinit_platform_anorak(core, dev);
|
rc = msm_vidc_deinit_platform_anorak(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -268,7 +266,7 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
|
|||||||
d_vpr_h("%s()\n", __func__);
|
d_vpr_h("%s()\n", __func__);
|
||||||
|
|
||||||
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-waipio")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
|
||||||
rc = msm_vidc_init_platform_waipio(core, dev);
|
rc = msm_vidc_init_platform_waipio(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -276,7 +274,8 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_KALAMA)
|
#if defined(CONFIG_MSM_VIDC_KALAMA)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-kalama")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
|
||||||
rc = msm_vidc_init_platform_kalama(core, dev);
|
rc = msm_vidc_init_platform_kalama(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -284,7 +283,7 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-pineapple")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
|
||||||
rc = msm_vidc_init_platform_pineapple(core, dev);
|
rc = msm_vidc_init_platform_pineapple(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -292,7 +291,7 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_ANORAK)
|
#if defined(CONFIG_MSM_VIDC_ANORAK)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sxr2230p-vidc")) {
|
||||||
rc = msm_vidc_init_platform_anorak(core, dev);
|
rc = msm_vidc_init_platform_anorak(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -315,7 +314,7 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
|
|||||||
d_vpr_h("%s()\n", __func__);
|
d_vpr_h("%s()\n", __func__);
|
||||||
|
|
||||||
#if defined(CONFIG_MSM_VIDC_IRIS2)
|
#if defined(CONFIG_MSM_VIDC_IRIS2)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris2")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
|
||||||
rc = msm_vidc_deinit_iris2(core);
|
rc = msm_vidc_deinit_iris2(core);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -323,7 +322,8 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_IRIS3)
|
#if defined(CONFIG_MSM_VIDC_IRIS3)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris3")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
|
||||||
rc = msm_vidc_deinit_iris3(core);
|
rc = msm_vidc_deinit_iris3(core);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -331,7 +331,7 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_IRIS33)
|
#if defined(CONFIG_MSM_VIDC_IRIS33)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris33")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
|
||||||
rc = msm_vidc_deinit_iris33(core);
|
rc = msm_vidc_deinit_iris33(core);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -351,7 +351,7 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_MSM_VIDC_IRIS2)
|
#if defined(CONFIG_MSM_VIDC_IRIS2)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris2")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
|
||||||
rc = msm_vidc_init_iris2(core);
|
rc = msm_vidc_init_iris2(core);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -359,7 +359,8 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_IRIS3)
|
#if defined(CONFIG_MSM_VIDC_IRIS3)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris3")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
|
||||||
rc = msm_vidc_init_iris3(core);
|
rc = msm_vidc_init_iris3(core);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -367,7 +368,7 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MSM_VIDC_IRIS33)
|
#if defined(CONFIG_MSM_VIDC_IRIS33)
|
||||||
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris33")) {
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
|
||||||
rc = msm_vidc_init_iris33(core);
|
rc = msm_vidc_init_iris33(core);
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
d_vpr_e("%s: failed with %d\n", __func__, rc);
|
||||||
@@ -494,19 +495,3 @@ int msm_vidc_read_efuse(struct msm_vidc_core *core)
|
|||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void msm_vidc_sort_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
u32 i = 0;
|
|
||||||
|
|
||||||
if (!core || !core->dt || !core->dt->allowed_clks_tbl) {
|
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sort(core->dt->allowed_clks_tbl, core->dt->allowed_clks_tbl_size,
|
|
||||||
sizeof(*core->dt->allowed_clks_tbl), cmp, NULL);
|
|
||||||
d_vpr_h("Updated allowed clock rates\n");
|
|
||||||
for (i = 0; i < core->dt->allowed_clks_tbl_size; i++)
|
|
||||||
d_vpr_h(" %d\n", core->dt->allowed_clks_tbl[i]);
|
|
||||||
}
|
|
||||||
|
@@ -4,9 +4,13 @@
|
|||||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <soc/qcom/of_common.h>
|
#include <dt-bindings/clock/qcom,gcc-kalama.h>
|
||||||
|
#include <dt-bindings/clock/qcom,videocc-kalama.h>
|
||||||
|
|
||||||
|
#include <linux/soc/qcom/llcc-qcom.h>
|
||||||
|
#include <soc/qcom/of_common.h>
|
||||||
#include <media/v4l2_vidc_extensions.h>
|
#include <media/v4l2_vidc_extensions.h>
|
||||||
|
|
||||||
#include "msm_vidc_kalama.h"
|
#include "msm_vidc_kalama.h"
|
||||||
#include "msm_vidc_platform.h"
|
#include "msm_vidc_platform.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
@@ -315,7 +319,6 @@ static struct msm_platform_core_capability core_data_kalama[] = {
|
|||||||
{AV_SYNC_WINDOW_SIZE, 40},
|
{AV_SYNC_WINDOW_SIZE, 40},
|
||||||
{NON_FATAL_FAULTS, 1},
|
{NON_FATAL_FAULTS, 1},
|
||||||
{ENC_AUTO_FRAMERATE, 1},
|
{ENC_AUTO_FRAMERATE, 1},
|
||||||
{MMRM, 1},
|
|
||||||
{DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_META_CAPTURE |
|
{DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_META_CAPTURE |
|
||||||
V4L2_CAP_STREAMING},
|
V4L2_CAP_STREAMING},
|
||||||
{SUPPORTS_REQUESTS, 1},
|
{SUPPORTS_REQUESTS, 1},
|
||||||
@@ -2626,7 +2629,128 @@ static struct msm_vidc_format_capability format_data_kalama = {
|
|||||||
.matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_kalama),
|
.matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_kalama),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* name, min_kbps, max_kbps */
|
||||||
|
static const struct bw_table kalama_bw_table[] = {
|
||||||
|
{ "venus-cnoc", 1000, 1000 },
|
||||||
|
{ "venus-ddr", 1000, 15000000 },
|
||||||
|
{ "venus-llcc", 1000, 15000000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* name, hw_trigger */
|
||||||
|
static const struct regulator_table kalama_regulator_table[] = {
|
||||||
|
{ "iris-ctl", 0 },
|
||||||
|
{ "vcodec", 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* name, clock id, scaling */
|
||||||
|
static const struct clk_table kalama_clk_table[] = {
|
||||||
|
{ "gcc_video_axi0", GCC_VIDEO_AXI0_CLK, 0 },
|
||||||
|
{ "core_clk", VIDEO_CC_MVS0C_CLK, 0 },
|
||||||
|
{ "vcodec_clk", VIDEO_CC_MVS0_CLK, 0 },
|
||||||
|
{ "video_cc_mvs0_clk_src", VIDEO_CC_MVS0_CLK_SRC, 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* name */
|
||||||
|
static const struct clk_rst_table kalama_clk_reset_table[] = {
|
||||||
|
{ "video_axi_reset" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* name, llcc_id */
|
||||||
|
static const struct subcache_table kalama_subcache_table[] = {
|
||||||
|
{ "vidsc0", LLCC_VIDSC0 },
|
||||||
|
{ "vidvsp", LLCC_VIDVSP },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* name, start, size, secure, dma_coherant, region */
|
||||||
|
const struct context_bank_table kalama_context_bank_table[] = {
|
||||||
|
{"qcom,vidc,cb-ns", 0x25800000, 0xba800000, 0, 1, MSM_VIDC_NON_SECURE },
|
||||||
|
{"qcom,vidc,cb-ns-pxl", 0x00100000, 0xdff00000, 0, 1, MSM_VIDC_NON_SECURE_PIXEL },
|
||||||
|
{"qcom,vidc,cb-sec-pxl", 0x00500000, 0xdfb00000, 1, 0, MSM_VIDC_SECURE_PIXEL },
|
||||||
|
{"qcom,vidc,cb-sec-non-pxl", 0x01000000, 0x24800000, 1, 0, MSM_VIDC_SECURE_NONPIXEL },
|
||||||
|
{"qcom,vidc,cb-sec-bitstream", 0x00500000, 0xdfb00000, 1, 0, MSM_VIDC_SECURE_BITSTREAM },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* freq */
|
||||||
|
static struct freq_table kalama_freq_table[] = {
|
||||||
|
{481000000}, {444000000}, {366000000}, {338000000}, {240000000}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct freq_table kalama_freq_table_v2[] = {
|
||||||
|
{533333333}, {444000000}, {366000000}, {338000000}, {240000000}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* register, value, mask */
|
||||||
|
static const struct reg_preset_table kalama_reg_preset_table[] = {
|
||||||
|
{ 0xB0088, 0x0, 0x11 },
|
||||||
|
};
|
||||||
|
|
||||||
static const struct msm_vidc_platform_data kalama_data = {
|
static const struct msm_vidc_platform_data kalama_data = {
|
||||||
|
/* resources dependent on other module */
|
||||||
|
.bw_tbl = kalama_bw_table,
|
||||||
|
.bw_tbl_size = ARRAY_SIZE(kalama_bw_table),
|
||||||
|
.regulator_tbl = kalama_regulator_table,
|
||||||
|
.regulator_tbl_size = ARRAY_SIZE(kalama_regulator_table),
|
||||||
|
.clk_tbl = kalama_clk_table,
|
||||||
|
.clk_tbl_size = ARRAY_SIZE(kalama_clk_table),
|
||||||
|
.clk_rst_tbl = kalama_clk_reset_table,
|
||||||
|
.clk_rst_tbl_size = ARRAY_SIZE(kalama_clk_reset_table),
|
||||||
|
.subcache_tbl = kalama_subcache_table,
|
||||||
|
.subcache_tbl_size = ARRAY_SIZE(kalama_subcache_table),
|
||||||
|
|
||||||
|
/* populate context bank */
|
||||||
|
.context_bank_tbl = kalama_context_bank_table,
|
||||||
|
.context_bank_tbl_size = ARRAY_SIZE(kalama_context_bank_table),
|
||||||
|
|
||||||
|
/* platform specific resources */
|
||||||
|
.freq_tbl = kalama_freq_table,
|
||||||
|
.freq_tbl_size = ARRAY_SIZE(kalama_freq_table),
|
||||||
|
.reg_prst_tbl = kalama_reg_preset_table,
|
||||||
|
.reg_prst_tbl_size = ARRAY_SIZE(kalama_reg_preset_table),
|
||||||
|
.fwname = "vpu30_4v",
|
||||||
|
.pas_id = 9,
|
||||||
|
.supports_mmrm = 1,
|
||||||
|
|
||||||
|
/* caps related resorces */
|
||||||
|
.core_data = core_data_kalama,
|
||||||
|
.core_data_size = ARRAY_SIZE(core_data_kalama),
|
||||||
|
.inst_cap_data = instance_cap_data_kalama,
|
||||||
|
.inst_cap_data_size = ARRAY_SIZE(instance_cap_data_kalama),
|
||||||
|
.inst_cap_dependency_data = instance_cap_dependency_data_kalama,
|
||||||
|
.inst_cap_dependency_data_size = ARRAY_SIZE(instance_cap_dependency_data_kalama),
|
||||||
|
.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,
|
||||||
|
.ubwc_config = ubwc_config_kalama,
|
||||||
|
.format_data = &format_data_kalama,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct msm_vidc_platform_data kalama_data_v2 = {
|
||||||
|
/* resources dependent on other module */
|
||||||
|
.bw_tbl = kalama_bw_table,
|
||||||
|
.bw_tbl_size = ARRAY_SIZE(kalama_bw_table),
|
||||||
|
.regulator_tbl = kalama_regulator_table,
|
||||||
|
.regulator_tbl_size = ARRAY_SIZE(kalama_regulator_table),
|
||||||
|
.clk_tbl = kalama_clk_table,
|
||||||
|
.clk_tbl_size = ARRAY_SIZE(kalama_clk_table),
|
||||||
|
.clk_rst_tbl = kalama_clk_reset_table,
|
||||||
|
.clk_rst_tbl_size = ARRAY_SIZE(kalama_clk_reset_table),
|
||||||
|
.subcache_tbl = kalama_subcache_table,
|
||||||
|
.subcache_tbl_size = ARRAY_SIZE(kalama_subcache_table),
|
||||||
|
|
||||||
|
/* populate context bank */
|
||||||
|
.context_bank_tbl = kalama_context_bank_table,
|
||||||
|
.context_bank_tbl_size = ARRAY_SIZE(kalama_context_bank_table),
|
||||||
|
|
||||||
|
/* platform specific resources */
|
||||||
|
.freq_tbl = kalama_freq_table_v2,
|
||||||
|
.freq_tbl_size = ARRAY_SIZE(kalama_freq_table_v2),
|
||||||
|
.reg_prst_tbl = kalama_reg_preset_table,
|
||||||
|
.reg_prst_tbl_size = ARRAY_SIZE(kalama_reg_preset_table),
|
||||||
|
.fwname = "vpu30_4v",
|
||||||
|
.pas_id = 9,
|
||||||
|
.supports_mmrm = 1,
|
||||||
|
|
||||||
|
/* caps related resorces */
|
||||||
.core_data = core_data_kalama,
|
.core_data = core_data_kalama,
|
||||||
.core_data_size = ARRAY_SIZE(core_data_kalama),
|
.core_data_size = ARRAY_SIZE(core_data_kalama),
|
||||||
.inst_cap_data = instance_cap_data_kalama,
|
.inst_cap_data = instance_cap_data_kalama,
|
||||||
@@ -2655,17 +2779,21 @@ int msm_vidc_kalama_check_ddr_type(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_vidc_init_data(struct msm_vidc_core *core)
|
static int msm_vidc_init_data(struct msm_vidc_core *core, struct device *dev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!core || !core->platform) {
|
if (!core || !core->platform || !dev) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
d_vpr_h("%s: initialize kalama data\n", __func__);
|
d_vpr_h("%s: initialize kalama data\n", __func__);
|
||||||
|
|
||||||
core->platform->data = kalama_data;
|
if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2"))
|
||||||
|
core->platform->data = kalama_data_v2;
|
||||||
|
else
|
||||||
|
core->platform->data = kalama_data;
|
||||||
|
|
||||||
rc = msm_vidc_kalama_check_ddr_type();
|
rc = msm_vidc_kalama_check_ddr_type();
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -2677,7 +2805,7 @@ int msm_vidc_init_platform_kalama(struct msm_vidc_core *core, struct device *dev
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
rc = msm_vidc_init_data(core);
|
rc = msm_vidc_init_data(core, dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_variant.h"
|
#include "msm_vidc_variant.h"
|
||||||
|
#include "msm_vidc_platform.h"
|
||||||
|
|
||||||
static void __fatal_error(bool fatal)
|
static void __fatal_error(bool fatal)
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ int __write_register(struct msm_vidc_core *core, u32 reg, u32 value)
|
|||||||
u8 *base_addr;
|
u8 *base_addr;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!core) {
|
if (!core || !core->resource) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ int __write_register(struct msm_vidc_core *core, u32 reg, u32 value)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
base_addr = core->register_base_addr;
|
base_addr = core->resource->register_base_addr;
|
||||||
d_vpr_l("regwrite(%pK + %#x) = %#x\n", base_addr, hwiosymaddr, value);
|
d_vpr_l("regwrite(%pK + %#x) = %#x\n", base_addr, hwiosymaddr, value);
|
||||||
base_addr += hwiosymaddr;
|
base_addr += hwiosymaddr;
|
||||||
writel_relaxed(value, base_addr);
|
writel_relaxed(value, base_addr);
|
||||||
@@ -74,7 +74,7 @@ int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
|
|||||||
u8 *base_addr;
|
u8 *base_addr;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!core) {
|
if (!core || !core->resource) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
base_addr = core->register_base_addr;
|
base_addr = core->resource->register_base_addr;
|
||||||
base_addr += reg;
|
base_addr += reg;
|
||||||
|
|
||||||
prev_val = readl_relaxed(base_addr);
|
prev_val = readl_relaxed(base_addr);
|
||||||
@@ -116,7 +116,7 @@ int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
u8 *base_addr;
|
u8 *base_addr;
|
||||||
|
|
||||||
if (!core || !value) {
|
if (!core || !core->resource || !value) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
base_addr = core->register_base_addr;
|
base_addr = core->resource->register_base_addr;
|
||||||
|
|
||||||
*value = readl_relaxed(base_addr + reg);
|
*value = readl_relaxed(base_addr + reg);
|
||||||
/*
|
/*
|
||||||
@@ -147,7 +147,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
|
|||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
u8 *addr;
|
u8 *addr;
|
||||||
|
|
||||||
if (!core) {
|
if (!core || !core->resource) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = (u8 *)core->register_base_addr + reg;
|
addr = (u8 *)core->resource->register_base_addr + reg;
|
||||||
|
|
||||||
rc = readl_relaxed_poll_timeout(addr, val, ((val & mask) == exp_val), sleep_us, timeout_us);
|
rc = readl_relaxed_poll_timeout(addr, val, ((val & mask) == exp_val), sleep_us, timeout_us);
|
||||||
/*
|
/*
|
||||||
@@ -167,7 +167,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
|
|||||||
rmb();
|
rmb();
|
||||||
d_vpr_l(
|
d_vpr_l(
|
||||||
"regread(%pK + %#x) = %#x. rc %d, mask %#x, exp_val %#x, cond %u, sleep %u, timeout %u\n",
|
"regread(%pK + %#x) = %#x. rc %d, mask %#x, exp_val %#x, cond %u, sleep %u, timeout %u\n",
|
||||||
core->register_base_addr, reg, val, rc, mask, exp_val,
|
core->resource->register_base_addr, reg, val, rc, mask, exp_val,
|
||||||
((val & mask) == exp_val), sleep_us, timeout_us);
|
((val & mask) == exp_val), sleep_us, timeout_us);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -175,19 +175,25 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
|
|||||||
|
|
||||||
int __set_registers(struct msm_vidc_core *core)
|
int __set_registers(struct msm_vidc_core *core)
|
||||||
{
|
{
|
||||||
struct reg_set *reg_set;
|
const struct reg_preset_table *reg_prst;
|
||||||
int i, rc = 0;
|
unsigned int prst_count;
|
||||||
|
int cnt, rc = 0;
|
||||||
|
|
||||||
if (!core || !core->dt) {
|
if (!core || !core->platform) {
|
||||||
d_vpr_e("core resources null, cannot set registers\n");
|
d_vpr_e("core resources null, cannot set registers\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_set = &core->dt->reg_set;
|
reg_prst = core->platform->data.reg_prst_tbl;
|
||||||
for (i = 0; i < reg_set->count; i++) {
|
prst_count = core->platform->data.reg_prst_tbl_size;
|
||||||
rc = __write_register_masked(core, reg_set->reg_tbl[i].reg,
|
|
||||||
reg_set->reg_tbl[i].value,
|
/* skip if there is no preset reg available */
|
||||||
reg_set->reg_tbl[i].mask);
|
if (!reg_prst || !prst_count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (cnt = 0; cnt < prst_count; cnt++) {
|
||||||
|
rc = __write_register_masked(core, reg_prst->reg,
|
||||||
|
reg_prst->value, reg_prst->mask);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
#include "msm_vidc_buffer.h"
|
#include "msm_vidc_buffer.h"
|
||||||
#include "msm_vidc_inst.h"
|
#include "msm_vidc_inst.h"
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_platform.h"
|
|
||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_media_info.h"
|
#include "msm_media_info.h"
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_control.h"
|
#include "msm_vidc_control.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_internal.h"
|
#include "msm_vidc_internal.h"
|
||||||
#include "msm_vidc_buffer.h"
|
#include "msm_vidc_buffer.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
@@ -487,7 +486,7 @@ static int __power_off_iris3(struct msm_vidc_core *core)
|
|||||||
d_vpr_e("%s: failed to unvote buses\n", __func__);
|
d_vpr_e("%s: failed to unvote buses\n", __func__);
|
||||||
|
|
||||||
if (!(core->intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS3))
|
if (!(core->intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS3))
|
||||||
disable_irq_nosync(core->dt->irq);
|
disable_irq_nosync(core->resource->irq);
|
||||||
core->intr_status = 0;
|
core->intr_status = 0;
|
||||||
|
|
||||||
core->power_enabled = false;
|
core->power_enabled = false;
|
||||||
@@ -551,7 +550,7 @@ fail_regulator:
|
|||||||
static int __power_on_iris3(struct msm_vidc_core *core)
|
static int __power_on_iris3(struct msm_vidc_core *core)
|
||||||
{
|
{
|
||||||
const struct msm_vidc_resources_ops *res_ops = core->res_ops;
|
const struct msm_vidc_resources_ops *res_ops = core->res_ops;
|
||||||
struct allowed_clock_rates_table *clk_tbl;
|
struct frequency_table *freq_tbl;
|
||||||
u32 freq = 0;
|
u32 freq = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
@@ -579,9 +578,9 @@ static int __power_on_iris3(struct msm_vidc_core *core)
|
|||||||
/* video controller and hardware powered on successfully */
|
/* video controller and hardware powered on successfully */
|
||||||
core->power_enabled = true;
|
core->power_enabled = true;
|
||||||
|
|
||||||
clk_tbl = core->dt->allowed_clks_tbl;
|
freq_tbl = core->resource->freq_set.freq_tbl;
|
||||||
freq = core->power.clk_freq ? core->power.clk_freq :
|
freq = core->power.clk_freq ? core->power.clk_freq :
|
||||||
clk_tbl[0].clock_rate;
|
freq_tbl[0].freq;
|
||||||
|
|
||||||
rc = res_ops->set_clks(core, freq);
|
rc = res_ops->set_clks(core, freq);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -596,7 +595,7 @@ static int __power_on_iris3(struct msm_vidc_core *core)
|
|||||||
|
|
||||||
__interrupt_init_iris3(core);
|
__interrupt_init_iris3(core);
|
||||||
core->intr_status = 0;
|
core->intr_status = 0;
|
||||||
enable_irq(core->dt->irq);
|
enable_irq(core->resource->irq);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@
|
|||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
|
|
||||||
u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
|
u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
|
||||||
{
|
{
|
||||||
@@ -27,9 +26,10 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
|
|||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
core = inst->core;
|
core = inst->core;
|
||||||
if (!core->dt || !core->dt->allowed_clks_tbl) {
|
|
||||||
|
if (!core->resource || !core->resource->freq_set.freq_tbl ||
|
||||||
|
!core->resource->freq_set.count) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
@@ -151,8 +151,8 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
|
|||||||
u32 bitrate_2stage[2] = {130, 120};
|
u32 bitrate_2stage[2] = {130, 120};
|
||||||
u32 bitrate_1stage = 100;
|
u32 bitrate_1stage = 100;
|
||||||
u32 width, height;
|
u32 width, height;
|
||||||
u32 bitrate_entry, freq_entry, frequency_table_value;
|
u32 bitrate_entry, freq_entry, freq_tbl_value;
|
||||||
struct allowed_clock_rates_table *allowed_clks_tbl;
|
struct frequency_table *freq_tbl;
|
||||||
struct v4l2_format *out_f = &inst->fmts[OUTPUT_PORT];
|
struct v4l2_format *out_f = &inst->fmts[OUTPUT_PORT];
|
||||||
|
|
||||||
width = out_f->fmt.pix_mp.width;
|
width = out_f->fmt.pix_mp.width;
|
||||||
@@ -165,11 +165,11 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
|
|||||||
|
|
||||||
freq_entry = bitrate_entry;
|
freq_entry = bitrate_entry;
|
||||||
|
|
||||||
allowed_clks_tbl = core->dt->allowed_clks_tbl;
|
freq_tbl = core->resource->freq_set.freq_tbl;
|
||||||
frequency_table_value = allowed_clks_tbl[freq_entry].clock_rate / 1000000;
|
freq_tbl_value = freq_tbl[freq_entry].freq / 1000000;
|
||||||
|
|
||||||
input_bitrate_mbps = fps * data_size * 8 / (1024 * 1024);
|
input_bitrate_mbps = fps * data_size * 8 / (1024 * 1024);
|
||||||
vsp_hw_min_frequency = frequency_table_value * 1000 * input_bitrate_mbps;
|
vsp_hw_min_frequency = freq_tbl_value * 1000 * input_bitrate_mbps;
|
||||||
|
|
||||||
if (inst->capabilities->cap[STAGE].value == MSM_VIDC_STAGE_2) {
|
if (inst->capabilities->cap[STAGE].value == MSM_VIDC_STAGE_2) {
|
||||||
vsp_hw_min_frequency +=
|
vsp_hw_min_frequency +=
|
||||||
@@ -233,9 +233,9 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
|
|||||||
* for non-AV1 codecs limit the frequency to NOM only
|
* for non-AV1 codecs limit the frequency to NOM only
|
||||||
* index 0 is TURBO, index 1 is NOM clock rate
|
* index 0 is TURBO, index 1 is NOM clock rate
|
||||||
*/
|
*/
|
||||||
if (core->dt->allowed_clks_tbl_size >= 2 &&
|
if (core->resource->freq_set.count >= 2 &&
|
||||||
freq > core->dt->allowed_clks_tbl[1].clock_rate)
|
freq > core->resource->freq_set.freq_tbl[1].freq)
|
||||||
freq = core->dt->allowed_clks_tbl[1].clock_rate;
|
freq = core->resource->freq_set.freq_tbl[1].freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
i_vpr_p(inst, "%s: filled len %d, required freq %llu, fps %u, mbpf %u\n",
|
i_vpr_p(inst, "%s: filled len %d, required freq %llu, fps %u, mbpf %u\n",
|
||||||
|
@@ -74,9 +74,8 @@ struct msm_vidc_core {
|
|||||||
char fw_version[MAX_NAME_LENGTH];
|
char fw_version[MAX_NAME_LENGTH];
|
||||||
enum msm_vidc_core_state state;
|
enum msm_vidc_core_state state;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct msm_vidc_dt *dt;
|
struct msm_vidc_resource *resource;
|
||||||
struct msm_vidc_platform *platform;
|
struct msm_vidc_platform *platform;
|
||||||
u8 __iomem *register_base_addr;
|
|
||||||
u32 intr_status;
|
u32 intr_status;
|
||||||
u32 spur_count;
|
u32 spur_count;
|
||||||
u32 reg_count;
|
u32 reg_count;
|
||||||
|
@@ -8,228 +8,5 @@
|
|||||||
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/soc/qcom/llcc-qcom.h>
|
#include <linux/soc/qcom/llcc-qcom.h>
|
||||||
#ifdef CONFIG_MSM_MMRM
|
|
||||||
#include <linux/soc/qcom/msm_mmrm.h>
|
|
||||||
#endif
|
|
||||||
#include "msm_vidc_internal.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These are helper macros to iterate over various lists within
|
|
||||||
* msm_vidc_core->dt. The intention is to cut down on a lot of boiler-plate
|
|
||||||
* code
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Read as "for each 'thing' in a set of 'thingies'" */
|
|
||||||
#define venus_hfi_for_each_thing(__device, __thing, __thingy) \
|
|
||||||
venus_hfi_for_each_thing_continue(__device, __thing, __thingy, 0)
|
|
||||||
|
|
||||||
#define venus_hfi_for_each_thing_reverse(__device, __thing, __thingy) \
|
|
||||||
venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
|
||||||
(__device)->dt->__thingy##_set.count - 1)
|
|
||||||
|
|
||||||
/* TODO: the __from parameter technically not required since we can figure it
|
|
||||||
* out with some pointer magic (i.e. __thing - __thing##_tbl[0]). If this macro
|
|
||||||
* sees extensive use, probably worth cleaning it up but for now omitting it
|
|
||||||
* since it introduces unnecessary complexity.
|
|
||||||
*/
|
|
||||||
#define venus_hfi_for_each_thing_continue(__device, __thing, __thingy, __from) \
|
|
||||||
for (__thing = &(__device)->dt->\
|
|
||||||
__thingy##_set.__thingy##_tbl[__from]; \
|
|
||||||
__thing < &(__device)->dt->__thingy##_set.__thingy##_tbl[0] + \
|
|
||||||
((__device)->dt->__thingy##_set.count - __from); \
|
|
||||||
++__thing)
|
|
||||||
|
|
||||||
#define venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
|
||||||
__from) \
|
|
||||||
for (__thing = &(__device)->dt->\
|
|
||||||
__thingy##_set.__thingy##_tbl[__from]; \
|
|
||||||
__thing >= &(__device)->dt->__thingy##_set.__thingy##_tbl[0]; \
|
|
||||||
--__thing)
|
|
||||||
|
|
||||||
/* Regular set helpers */
|
|
||||||
#define venus_hfi_for_each_regulator(__device, __rinfo) \
|
|
||||||
venus_hfi_for_each_thing(__device, __rinfo, regulator)
|
|
||||||
|
|
||||||
#define venus_hfi_for_each_regulator_reverse(__device, __rinfo) \
|
|
||||||
venus_hfi_for_each_thing_reverse(__device, __rinfo, regulator)
|
|
||||||
|
|
||||||
#define venus_hfi_for_each_regulator_reverse_continue(__device, __rinfo, \
|
|
||||||
__from) \
|
|
||||||
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
|
||||||
regulator, __from)
|
|
||||||
|
|
||||||
/* Clock set helpers */
|
|
||||||
#define venus_hfi_for_each_clock(__device, __cinfo) \
|
|
||||||
venus_hfi_for_each_thing(__device, __cinfo, clock)
|
|
||||||
|
|
||||||
#define venus_hfi_for_each_clock_reverse(__device, __cinfo) \
|
|
||||||
venus_hfi_for_each_thing_reverse(__device, __cinfo, clock)
|
|
||||||
|
|
||||||
/* Bus set helpers */
|
|
||||||
#define venus_hfi_for_each_bus(__device, __binfo) \
|
|
||||||
venus_hfi_for_each_thing(__device, __binfo, bus)
|
|
||||||
#define venus_hfi_for_each_bus_reverse(__device, __binfo) \
|
|
||||||
venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
|
|
||||||
|
|
||||||
/* Subcache set helpers */
|
|
||||||
#define venus_hfi_for_each_subcache(__device, __sinfo) \
|
|
||||||
venus_hfi_for_each_thing(__device, __sinfo, subcache)
|
|
||||||
#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
|
|
||||||
venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
|
|
||||||
|
|
||||||
struct reg_value_pair {
|
|
||||||
u32 reg;
|
|
||||||
u32 value;
|
|
||||||
u32 mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct reg_set {
|
|
||||||
struct reg_value_pair *reg_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct addr_range {
|
|
||||||
u32 start;
|
|
||||||
u32 size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct addr_set {
|
|
||||||
struct addr_range *addr_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct context_bank_info {
|
|
||||||
struct list_head list;
|
|
||||||
const char *name;
|
|
||||||
bool is_secure;
|
|
||||||
struct addr_range addr_range;
|
|
||||||
struct device *dev;
|
|
||||||
struct iommu_domain *domain;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct buffer_usage_table {
|
|
||||||
u32 buffer_type;
|
|
||||||
u32 tz_usage;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct buffer_usage_set {
|
|
||||||
struct buffer_usage_table *buffer_usage_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct regulator_info {
|
|
||||||
struct regulator *regulator;
|
|
||||||
bool has_hw_power_collapse;
|
|
||||||
char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct regulator_set {
|
|
||||||
struct regulator_info *regulator_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct clock_info {
|
|
||||||
const char *name;
|
|
||||||
u32 clk_id;
|
|
||||||
struct clk *clk;
|
|
||||||
u32 count;
|
|
||||||
bool has_scaling;
|
|
||||||
bool has_mem_retention;
|
|
||||||
u64 prev;
|
|
||||||
#ifdef CONFIG_MSM_MMRM
|
|
||||||
struct mmrm_client *mmrm_client;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct clock_set {
|
|
||||||
struct clock_info *clock_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bus_info {
|
|
||||||
const char *name;
|
|
||||||
u32 range[2];
|
|
||||||
struct device *dev;
|
|
||||||
struct icc_path *path;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bus_set {
|
|
||||||
struct bus_info *bus_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct reset_info {
|
|
||||||
struct reset_control *rst;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct reset_set {
|
|
||||||
struct reset_info *reset_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct allowed_clock_rates_table {
|
|
||||||
u32 clock_rate;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct clock_profile_entry {
|
|
||||||
u32 codec_mask;
|
|
||||||
u32 vpp_cycles;
|
|
||||||
u32 vsp_cycles;
|
|
||||||
u32 low_power_cycles;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct clock_freq_table {
|
|
||||||
struct clock_profile_entry *clk_prof_entries;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct subcache_info {
|
|
||||||
const char *name;
|
|
||||||
bool isactive;
|
|
||||||
bool isset;
|
|
||||||
struct llcc_slice_desc *subcache;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct subcache_set {
|
|
||||||
struct subcache_info *subcache_tbl;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msm_vidc_dt {
|
|
||||||
void *core;
|
|
||||||
phys_addr_t register_base;
|
|
||||||
u32 register_size;
|
|
||||||
u32 irq;
|
|
||||||
struct allowed_clock_rates_table *allowed_clks_tbl;
|
|
||||||
u32 allowed_clks_tbl_size;
|
|
||||||
struct clock_freq_table clock_freq_tbl;
|
|
||||||
bool sys_cache_present;
|
|
||||||
bool sys_cache_res_set;
|
|
||||||
struct subcache_set subcache_set;
|
|
||||||
struct reg_set reg_set;
|
|
||||||
struct addr_set qdss_addr_set;
|
|
||||||
struct buffer_usage_set buffer_usage_set;
|
|
||||||
struct regulator_set regulator_set;
|
|
||||||
struct clock_set clock_set;
|
|
||||||
struct bus_set bus_set;
|
|
||||||
struct reset_set reset_set;
|
|
||||||
struct list_head context_banks;
|
|
||||||
struct mutex cb_lock;
|
|
||||||
const char *fw_name;
|
|
||||||
int fw_cookie;
|
|
||||||
};
|
|
||||||
|
|
||||||
int msm_vidc_init_dt(struct platform_device *pdev);
|
|
||||||
int msm_vidc_read_context_bank_resources_from_dt(struct platform_device *pdev);
|
|
||||||
void msm_vidc_deinit_dt(struct platform_device *pdev);
|
|
||||||
|
|
||||||
/* A comparator to compare loads (needed later on) */
|
|
||||||
static inline int cmp(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
/* want to sort in reverse so flip the comparison */
|
|
||||||
return ((struct allowed_clock_rates_table *)b)->clock_rate -
|
|
||||||
((struct allowed_clock_rates_table *)a)->clock_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _MSM_VIDC_DT_H_
|
#endif // _MSM_VIDC_DT_H_
|
||||||
|
@@ -244,6 +244,7 @@ enum msm_vidc_buffer_region {
|
|||||||
MSM_VIDC_SECURE_PIXEL,
|
MSM_VIDC_SECURE_PIXEL,
|
||||||
MSM_VIDC_SECURE_NONPIXEL,
|
MSM_VIDC_SECURE_NONPIXEL,
|
||||||
MSM_VIDC_SECURE_BITSTREAM,
|
MSM_VIDC_SECURE_BITSTREAM,
|
||||||
|
MSM_VIDC_REGION_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum msm_vidc_port_type {
|
enum msm_vidc_port_type {
|
||||||
@@ -374,7 +375,6 @@ enum msm_vidc_core_capability_type {
|
|||||||
CLK_FREQ_THRESHOLD,
|
CLK_FREQ_THRESHOLD,
|
||||||
NON_FATAL_FAULTS,
|
NON_FATAL_FAULTS,
|
||||||
ENC_AUTO_FRAMERATE,
|
ENC_AUTO_FRAMERATE,
|
||||||
MMRM,
|
|
||||||
DEVICE_CAPS,
|
DEVICE_CAPS,
|
||||||
SUPPORTS_REQUESTS,
|
SUPPORTS_REQUESTS,
|
||||||
CORE_CAP_MAX,
|
CORE_CAP_MAX,
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
#define _MSM_VIDC_MEMORY_H_
|
#define _MSM_VIDC_MEMORY_H_
|
||||||
|
|
||||||
#include "msm_vidc_internal.h"
|
#include "msm_vidc_internal.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
|
|
||||||
struct msm_vidc_core;
|
struct msm_vidc_core;
|
||||||
struct msm_vidc_inst;
|
struct msm_vidc_inst;
|
||||||
|
@@ -6,11 +6,199 @@
|
|||||||
#ifndef _MSM_VIDC_RESOURCES_H_
|
#ifndef _MSM_VIDC_RESOURCES_H_
|
||||||
#define _MSM_VIDC_RESOURCES_H_
|
#define _MSM_VIDC_RESOURCES_H_
|
||||||
|
|
||||||
|
struct icc_path;
|
||||||
|
struct regulator;
|
||||||
|
struct clk;
|
||||||
|
struct reset_control;
|
||||||
|
struct llcc_slice_desc;
|
||||||
|
struct iommu_domain;
|
||||||
|
struct device;
|
||||||
struct msm_vidc_core;
|
struct msm_vidc_core;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are helper macros to iterate over various lists within
|
||||||
|
* msm_vidc_core->resource. The intention is to cut down on a lot of boiler-plate
|
||||||
|
* code
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Read as "for each 'thing' in a set of 'thingies'" */
|
||||||
|
#define venus_hfi_for_each_thing(__device, __thing, __thingy) \
|
||||||
|
venus_hfi_for_each_thing_continue(__device, __thing, __thingy, 0)
|
||||||
|
|
||||||
|
#define venus_hfi_for_each_thing_reverse(__device, __thing, __thingy) \
|
||||||
|
venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
||||||
|
(__device)->resource->__thingy##_set.count - 1)
|
||||||
|
|
||||||
|
/* TODO: the __from parameter technically not required since we can figure it
|
||||||
|
* out with some pointer magic (i.e. __thing - __thing##_tbl[0]). If this macro
|
||||||
|
* sees extensive use, probably worth cleaning it up but for now omitting it
|
||||||
|
* since it introduces unnecessary complexity.
|
||||||
|
*/
|
||||||
|
#define venus_hfi_for_each_thing_continue(__device, __thing, __thingy, __from) \
|
||||||
|
for (__thing = &(__device)->resource->\
|
||||||
|
__thingy##_set.__thingy##_tbl[__from]; \
|
||||||
|
__thing < &(__device)->resource->__thingy##_set.__thingy##_tbl[0] + \
|
||||||
|
((__device)->resource->__thingy##_set.count - __from); \
|
||||||
|
++__thing)
|
||||||
|
|
||||||
|
#define venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
||||||
|
__from) \
|
||||||
|
for (__thing = &(__device)->resource->\
|
||||||
|
__thingy##_set.__thingy##_tbl[__from]; \
|
||||||
|
__thing >= &(__device)->resource->__thingy##_set.__thingy##_tbl[0]; \
|
||||||
|
--__thing)
|
||||||
|
|
||||||
|
/* Bus set helpers */
|
||||||
|
#define venus_hfi_for_each_bus(__device, __binfo) \
|
||||||
|
venus_hfi_for_each_thing(__device, __binfo, bus)
|
||||||
|
#define venus_hfi_for_each_bus_reverse(__device, __binfo) \
|
||||||
|
venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
|
||||||
|
|
||||||
|
/* Regular set helpers */
|
||||||
|
#define venus_hfi_for_each_regulator(__device, __rinfo) \
|
||||||
|
venus_hfi_for_each_thing(__device, __rinfo, regulator)
|
||||||
|
#define venus_hfi_for_each_regulator_reverse(__device, __rinfo) \
|
||||||
|
venus_hfi_for_each_thing_reverse(__device, __rinfo, regulator)
|
||||||
|
#define venus_hfi_for_each_regulator_reverse_continue(__device, __rinfo, \
|
||||||
|
__from) \
|
||||||
|
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
||||||
|
regulator, __from)
|
||||||
|
|
||||||
|
/* Clock set helpers */
|
||||||
|
#define venus_hfi_for_each_clock(__device, __cinfo) \
|
||||||
|
venus_hfi_for_each_thing(__device, __cinfo, clock)
|
||||||
|
#define venus_hfi_for_each_clock_reverse(__device, __cinfo) \
|
||||||
|
venus_hfi_for_each_thing_reverse(__device, __cinfo, clock)
|
||||||
|
|
||||||
|
/* Reset clock set helpers */
|
||||||
|
#define venus_hfi_for_each_reset_clock(__device, __rcinfo) \
|
||||||
|
venus_hfi_for_each_thing(__device, __rcinfo, reset)
|
||||||
|
#define venus_hfi_for_each_reset_clock_reverse(__device, __rcinfo) \
|
||||||
|
venus_hfi_for_each_thing_reverse(__device, __rcinfo, reset)
|
||||||
|
#define venus_hfi_for_each_reset_clock_reverse_continue(__device, __rinfo, \
|
||||||
|
__from) \
|
||||||
|
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
||||||
|
reset, __from)
|
||||||
|
|
||||||
|
/* Subcache set helpers */
|
||||||
|
#define venus_hfi_for_each_subcache(__device, __sinfo) \
|
||||||
|
venus_hfi_for_each_thing(__device, __sinfo, subcache)
|
||||||
|
#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
|
||||||
|
venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
|
||||||
|
|
||||||
|
/* Contextbank set helpers */
|
||||||
|
#define venus_hfi_for_each_context_bank(__device, __sinfo) \
|
||||||
|
venus_hfi_for_each_thing(__device, __sinfo, context_bank)
|
||||||
|
#define venus_hfi_for_each_context_bank_reverse(__device, __sinfo) \
|
||||||
|
venus_hfi_for_each_thing_reverse(__device, __sinfo, context_bank)
|
||||||
|
|
||||||
|
struct bus_info {
|
||||||
|
struct icc_path *icc;
|
||||||
|
const char *name;
|
||||||
|
u32 min_kbps;
|
||||||
|
u32 max_kbps;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bus_set {
|
||||||
|
struct bus_info *bus_tbl;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regulator_info {
|
||||||
|
struct regulator *regulator;
|
||||||
|
const char *name;
|
||||||
|
bool hw_power_collapse;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regulator_set {
|
||||||
|
struct regulator_info *regulator_tbl;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clock_info {
|
||||||
|
struct clk *clk;
|
||||||
|
const char *name;
|
||||||
|
u32 clk_id;
|
||||||
|
bool has_scaling;
|
||||||
|
u64 prev;
|
||||||
|
#ifdef CONFIG_MSM_MMRM
|
||||||
|
struct mmrm_client *mmrm_client;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clock_set {
|
||||||
|
struct clock_info *clock_tbl;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct reset_info {
|
||||||
|
struct reset_control *rst;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct reset_set {
|
||||||
|
struct reset_info *reset_tbl;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct subcache_info {
|
||||||
|
struct llcc_slice_desc *subcache;
|
||||||
|
const char *name;
|
||||||
|
u32 llcc_id;
|
||||||
|
bool isactive;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct subcache_set {
|
||||||
|
struct subcache_info *subcache_tbl;
|
||||||
|
u32 count;
|
||||||
|
bool set_to_fw;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct addr_range {
|
||||||
|
u32 start;
|
||||||
|
u32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct context_bank_info {
|
||||||
|
const char *name;
|
||||||
|
struct addr_range addr_range;
|
||||||
|
bool secure;
|
||||||
|
bool dma_coherant;
|
||||||
|
struct device *dev;
|
||||||
|
struct iommu_domain *domain;
|
||||||
|
u32 region;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct context_bank_set {
|
||||||
|
struct context_bank_info *context_bank_tbl;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct frequency_table {
|
||||||
|
unsigned long freq;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct freq_set {
|
||||||
|
struct frequency_table *freq_tbl;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msm_vidc_resource {
|
||||||
|
void *core;
|
||||||
|
u8 __iomem *register_base_addr;
|
||||||
|
u32 irq;
|
||||||
|
struct bus_set bus_set;
|
||||||
|
struct regulator_set regulator_set;
|
||||||
|
struct clock_set clock_set;
|
||||||
|
struct reset_set reset_set;
|
||||||
|
struct subcache_set subcache_set;
|
||||||
|
struct context_bank_set context_bank_set;
|
||||||
|
struct freq_set freq_set;
|
||||||
|
int fw_cookie;
|
||||||
|
};
|
||||||
|
|
||||||
struct msm_vidc_resources_ops {
|
struct msm_vidc_resources_ops {
|
||||||
int (*get)(struct msm_vidc_core *core);
|
int (*init)(struct msm_vidc_core *core);
|
||||||
void (*put)(struct msm_vidc_core *core);
|
|
||||||
|
|
||||||
int (*reset_bridge)(struct msm_vidc_core *core);
|
int (*reset_bridge)(struct msm_vidc_core *core);
|
||||||
|
|
||||||
|
@@ -12,9 +12,9 @@
|
|||||||
|
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_events.h"
|
#include "msm_vidc_events.h"
|
||||||
#include "firmware.h"
|
#include "firmware.h"
|
||||||
|
#include "msm_vidc_platform.h"
|
||||||
|
|
||||||
#define MAX_FIRMWARE_NAME_SIZE 128
|
#define MAX_FIRMWARE_NAME_SIZE 128
|
||||||
|
|
||||||
@@ -45,15 +45,15 @@ static int protect_cp_mem(struct msm_vidc_core *core)
|
|||||||
memprot.cp_nonpixel_start = 0x0;
|
memprot.cp_nonpixel_start = 0x0;
|
||||||
memprot.cp_nonpixel_size = 0x0;
|
memprot.cp_nonpixel_size = 0x0;
|
||||||
|
|
||||||
list_for_each_entry(cb, &core->dt->context_banks, list) {
|
venus_hfi_for_each_context_bank(core, cb) {
|
||||||
if (!strcmp(cb->name, "venus_ns")) {
|
if (cb->region == MSM_VIDC_NON_SECURE) {
|
||||||
memprot.cp_size = cb->addr_range.start;
|
memprot.cp_size = cb->addr_range.start;
|
||||||
|
|
||||||
d_vpr_h("%s: memprot.cp_size: %#x\n",
|
d_vpr_h("%s: memprot.cp_size: %#x\n",
|
||||||
__func__, memprot.cp_size);
|
__func__, memprot.cp_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cb->name, "venus_sec_non_pixel")) {
|
if (cb->region == MSM_VIDC_SECURE_NONPIXEL) {
|
||||||
memprot.cp_nonpixel_start = cb->addr_range.start;
|
memprot.cp_nonpixel_start = cb->addr_range.start;
|
||||||
memprot.cp_nonpixel_size = cb->addr_range.size;
|
memprot.cp_nonpixel_size = cb->addr_range.size;
|
||||||
|
|
||||||
@@ -65,7 +65,6 @@ static int protect_cp_mem(struct msm_vidc_core *core)
|
|||||||
|
|
||||||
rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size,
|
rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size,
|
||||||
memprot.cp_nonpixel_start, memprot.cp_nonpixel_size);
|
memprot.cp_nonpixel_start, memprot.cp_nonpixel_size);
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
d_vpr_e("Failed to protect memory(%d)\n", rc);
|
d_vpr_e("Failed to protect memory(%d)\n", rc);
|
||||||
|
|
||||||
@@ -81,6 +80,7 @@ static int __load_fw_to_memory(struct platform_device *pdev,
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
const struct firmware *firmware = NULL;
|
const struct firmware *firmware = NULL;
|
||||||
|
struct msm_vidc_core *core;
|
||||||
char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 };
|
char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 };
|
||||||
struct device_node *node = NULL;
|
struct device_node *node = NULL;
|
||||||
struct resource res = { 0 };
|
struct resource res = { 0 };
|
||||||
@@ -98,14 +98,16 @@ static int __load_fw_to_memory(struct platform_device *pdev,
|
|||||||
d_vpr_e("%s: Invalid fw name\n", __func__);
|
d_vpr_e("%s: Invalid fw name\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core = dev_get_drvdata(&pdev->dev);
|
||||||
|
if (!core) {
|
||||||
|
d_vpr_e("%s: core not found in device %s",
|
||||||
|
__func__, dev_name(&pdev->dev));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name);
|
scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name);
|
||||||
|
|
||||||
rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id);
|
pas_id = core->platform->data.pas_id;
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("%s: failed to read \"pas-id\". error %d\n",
|
|
||||||
__func__, rc);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
|
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
@@ -182,13 +184,13 @@ int fw_load(struct msm_vidc_core *core)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!core->dt->fw_cookie) {
|
if (!core->resource->fw_cookie) {
|
||||||
core->dt->fw_cookie = __load_fw_to_memory(core->pdev,
|
core->resource->fw_cookie = __load_fw_to_memory(core->pdev,
|
||||||
core->dt->fw_name);
|
core->platform->data.fwname);
|
||||||
if (core->dt->fw_cookie <= 0) {
|
if (core->resource->fw_cookie <= 0) {
|
||||||
d_vpr_e("%s: firmware download failed %d\n",
|
d_vpr_e("%s: firmware download failed %d\n",
|
||||||
__func__, core->dt->fw_cookie);
|
__func__, core->resource->fw_cookie);
|
||||||
core->dt->fw_cookie = 0;
|
core->resource->fw_cookie = 0;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,9 +204,9 @@ int fw_load(struct msm_vidc_core *core)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
fail_protect_mem:
|
fail_protect_mem:
|
||||||
if (core->dt->fw_cookie)
|
if (core->resource->fw_cookie)
|
||||||
qcom_scm_pas_shutdown(core->dt->fw_cookie);
|
qcom_scm_pas_shutdown(core->resource->fw_cookie);
|
||||||
core->dt->fw_cookie = 0;
|
core->resource->fw_cookie = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,14 +214,14 @@ int fw_unload(struct msm_vidc_core *core)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!core->dt->fw_cookie)
|
if (!core->resource->fw_cookie)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = qcom_scm_pas_shutdown(core->dt->fw_cookie);
|
ret = qcom_scm_pas_shutdown(core->resource->fw_cookie);
|
||||||
if (ret)
|
if (ret)
|
||||||
d_vpr_e("Firmware unload failed rc=%d\n", ret);
|
d_vpr_e("Firmware unload failed rc=%d\n", ret);
|
||||||
|
|
||||||
core->dt->fw_cookie = 0;
|
core->resource->fw_cookie = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,6 @@
|
|||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc.h"
|
#include "msm_vidc.h"
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_inst.h"
|
#include "msm_vidc_inst.h"
|
||||||
@@ -209,7 +208,7 @@ static ssize_t core_info_read(struct file* file, char __user* buf,
|
|||||||
ssize_t len = 0;
|
ssize_t len = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!core || !core->dt) {
|
if (!core || !core->resource) {
|
||||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -226,10 +225,8 @@ static ssize_t core_info_read(struct file* file, char __user* buf,
|
|||||||
cur += write_str(cur, end - cur,
|
cur += write_str(cur, end - cur,
|
||||||
"FW version : %s\n", core->fw_version);
|
"FW version : %s\n", core->fw_version);
|
||||||
cur += write_str(cur, end - cur,
|
cur += write_str(cur, end - cur,
|
||||||
"register_base: 0x%x\n", core->dt->register_base);
|
"register_base: 0x%x\n", core->resource->register_base_addr);
|
||||||
cur += write_str(cur, end - cur,
|
cur += write_str(cur, end - cur, "irq: %u\n", core->resource->irq);
|
||||||
"register_size: %u\n", core->dt->register_size);
|
|
||||||
cur += write_str(cur, end - cur, "irq: %u\n", core->dt->irq);
|
|
||||||
|
|
||||||
len = simple_read_from_buffer(buf, count, ppos,
|
len = simple_read_from_buffer(buf, count, ppos,
|
||||||
dbuf, cur - dbuf);
|
dbuf, cur - dbuf);
|
||||||
|
@@ -7,976 +7,3 @@
|
|||||||
#include <linux/dma-iommu.h>
|
#include <linux/dma-iommu.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
|
|
||||||
#include "msm_vidc_debug.h"
|
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_internal.h"
|
|
||||||
#include "msm_vidc_core.h"
|
|
||||||
#include "msm_vidc_driver.h"
|
|
||||||
|
|
||||||
static size_t get_u32_array_num_elements(struct device_node *np,
|
|
||||||
char *name)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
size_t num_elements = 0;
|
|
||||||
|
|
||||||
if (!of_get_property(np, name, &len)) {
|
|
||||||
d_vpr_e("Failed to read %s from device tree\n", name);
|
|
||||||
goto fail_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_elements = len / sizeof(u32);
|
|
||||||
if (num_elements <= 0) {
|
|
||||||
d_vpr_e("%s not specified in device tree\n", name);
|
|
||||||
goto fail_read;
|
|
||||||
}
|
|
||||||
return num_elements;
|
|
||||||
|
|
||||||
fail_read:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* msm_vidc_load_u32_table() - load dtsi table entries
|
|
||||||
* @pdev: A pointer to the platform device.
|
|
||||||
* @of_node: A pointer to the device node.
|
|
||||||
* @table_name: A pointer to the dtsi table entry name.
|
|
||||||
* @struct_size: The size of the structure which is nothing but
|
|
||||||
* a single entry in the dtsi table.
|
|
||||||
* @table: A pointer to the table pointer which needs to be
|
|
||||||
* filled by the dtsi table entries.
|
|
||||||
* @num_elements: Number of elements pointer which needs to be filled
|
|
||||||
* with the number of elements in the table.
|
|
||||||
*
|
|
||||||
* This is a generic implementation to load single or multiple array
|
|
||||||
* table from dtsi. The array elements should be of size equal to u32.
|
|
||||||
*
|
|
||||||
* Return: Return '0' for success else appropriate error value.
|
|
||||||
*/
|
|
||||||
static int msm_vidc_load_u32_table(struct platform_device *pdev,
|
|
||||||
struct device_node *of_node, char *table_name, int struct_size,
|
|
||||||
u32 **table, u32 *num_elements)
|
|
||||||
{
|
|
||||||
int rc = 0, num_elemts = 0;
|
|
||||||
u32 *ptbl = NULL;
|
|
||||||
|
|
||||||
if (!of_find_property(of_node, table_name, NULL)) {
|
|
||||||
d_vpr_h("%s not found\n", table_name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_elemts = get_u32_array_num_elements(of_node, table_name);
|
|
||||||
if (!num_elemts) {
|
|
||||||
d_vpr_e("no elements in %s\n", table_name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
num_elemts /= struct_size / sizeof(u32);
|
|
||||||
|
|
||||||
ptbl = devm_kzalloc(&pdev->dev, num_elemts * struct_size, GFP_KERNEL);
|
|
||||||
if (!ptbl) {
|
|
||||||
d_vpr_e("Failed to alloc table %s\n", table_name);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (of_property_read_u32_array(of_node, table_name, ptbl,
|
|
||||||
num_elemts * struct_size / sizeof(u32))) {
|
|
||||||
d_vpr_e("Failed to read %s\n", table_name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*table = ptbl;
|
|
||||||
if (num_elements)
|
|
||||||
*num_elements = num_elemts;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_allowed_clocks_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
dt->allowed_clks_tbl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_reg_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
dt->reg_set.reg_tbl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_qdss_addr_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
dt->qdss_addr_set.addr_tbl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_bus_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
dt->bus_set.bus_tbl = NULL;
|
|
||||||
dt->bus_set.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_buffer_usage_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
dt->buffer_usage_set.buffer_usage_tbl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_regulator_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
for (c = 0; c < dt->regulator_set.count; ++c) {
|
|
||||||
struct regulator_info *rinfo =
|
|
||||||
&dt->regulator_set.regulator_tbl[c];
|
|
||||||
|
|
||||||
rinfo->name = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt->regulator_set.regulator_tbl = NULL;
|
|
||||||
dt->regulator_set.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_vidc_free_clock_table(struct msm_vidc_dt *dt)
|
|
||||||
{
|
|
||||||
dt->clock_set.clock_tbl = NULL;
|
|
||||||
dt->clock_set.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_fw_name(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
|
|
||||||
return of_property_read_string_index(pdev->dev.of_node,
|
|
||||||
"vidc,firmware-name", 0, &core->dt->fw_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_reg_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
struct reg_set *reg_set;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
int i;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (!of_find_property(pdev->dev.of_node, "qcom,reg-presets", NULL)) {
|
|
||||||
/*
|
|
||||||
* qcom,reg-presets is an optional property. It likely won't be
|
|
||||||
* present if we don't have any register settings to program
|
|
||||||
*/
|
|
||||||
d_vpr_h("reg-presets not found\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_set = &dt->reg_set;
|
|
||||||
reg_set->count = get_u32_array_num_elements(pdev->dev.of_node,
|
|
||||||
"qcom,reg-presets");
|
|
||||||
reg_set->count /= sizeof(*reg_set->reg_tbl) / sizeof(u32);
|
|
||||||
|
|
||||||
if (!reg_set->count) {
|
|
||||||
d_vpr_h("no elements in reg set\n");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_set->reg_tbl = devm_kzalloc(&pdev->dev, reg_set->count *
|
|
||||||
sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
|
|
||||||
if (!reg_set->reg_tbl) {
|
|
||||||
d_vpr_e("%s: Failed to alloc register table\n", __func__);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
|
|
||||||
(u32 *)reg_set->reg_tbl, reg_set->count * 3)) {
|
|
||||||
d_vpr_e("Failed to read register table\n");
|
|
||||||
msm_vidc_free_reg_table(core->dt);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
for (i = 0; i < reg_set->count; i++) {
|
|
||||||
d_vpr_h("reg = %#x, value = %#x, mask = %#x\n",
|
|
||||||
reg_set->reg_tbl[i].reg, reg_set->reg_tbl[i].value,
|
|
||||||
reg_set->reg_tbl[i].mask);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
static int msm_vidc_load_qdss_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
struct addr_set *qdss_addr_set;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
int i;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (!of_find_property(pdev->dev.of_node, "qcom,qdss-presets", NULL)) {
|
|
||||||
/*
|
|
||||||
* qcom,qdss-presets is an optional property. It likely won't be
|
|
||||||
* present if we don't have any register settings to program
|
|
||||||
*/
|
|
||||||
d_vpr_h("qdss-presets not found\n");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdss_addr_set = &dt->qdss_addr_set;
|
|
||||||
qdss_addr_set->count = get_u32_array_num_elements(pdev->dev.of_node,
|
|
||||||
"qcom,qdss-presets");
|
|
||||||
qdss_addr_set->count /= sizeof(*qdss_addr_set->addr_tbl) / sizeof(u32);
|
|
||||||
|
|
||||||
if (!qdss_addr_set->count) {
|
|
||||||
d_vpr_h("no elements in qdss reg set\n");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdss_addr_set->addr_tbl = devm_kzalloc(&pdev->dev,
|
|
||||||
qdss_addr_set->count * sizeof(*qdss_addr_set->addr_tbl),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!qdss_addr_set->addr_tbl) {
|
|
||||||
d_vpr_e("%s: Failed to alloc register table\n", __func__);
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_qdss_addr_tbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = of_property_read_u32_array(pdev->dev.of_node, "qcom,qdss-presets",
|
|
||||||
(u32 *)qdss_addr_set->addr_tbl, qdss_addr_set->count * 2);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to read qdss address table\n");
|
|
||||||
msm_vidc_free_qdss_addr_table(core->dt);
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err_qdss_addr_tbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < qdss_addr_set->count; i++) {
|
|
||||||
d_vpr_h("qdss addr = %x, value = %x\n",
|
|
||||||
qdss_addr_set->addr_tbl[i].start,
|
|
||||||
qdss_addr_set->addr_tbl[i].size);
|
|
||||||
}
|
|
||||||
err_qdss_addr_tbl:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_subcache_info(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0, num_subcaches = 0, c;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
struct subcache_set *subcaches = &dt->subcache_set;
|
|
||||||
|
|
||||||
num_subcaches = of_property_count_strings(pdev->dev.of_node,
|
|
||||||
"cache-slice-names");
|
|
||||||
if (num_subcaches <= 0) {
|
|
||||||
d_vpr_h("No subcaches found\n");
|
|
||||||
goto err_load_subcache_table_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
subcaches->subcache_tbl = devm_kzalloc(&pdev->dev,
|
|
||||||
sizeof(*subcaches->subcache_tbl) * num_subcaches, GFP_KERNEL);
|
|
||||||
if (!subcaches->subcache_tbl) {
|
|
||||||
d_vpr_e("Failed to allocate memory for subcache tbl\n");
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_load_subcache_table_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
subcaches->count = num_subcaches;
|
|
||||||
d_vpr_h("Found %d subcaches\n", num_subcaches);
|
|
||||||
|
|
||||||
for (c = 0; c < num_subcaches; ++c) {
|
|
||||||
struct subcache_info *vsc = &dt->subcache_set.subcache_tbl[c];
|
|
||||||
|
|
||||||
of_property_read_string_index(pdev->dev.of_node,
|
|
||||||
"cache-slice-names", c, &vsc->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
dt->sys_cache_present = true;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_load_subcache_table_fail:
|
|
||||||
dt->sys_cache_present = false;
|
|
||||||
subcaches->count = 0;
|
|
||||||
subcaches->subcache_tbl = NULL;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_allowed_clocks_table(
|
|
||||||
struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!of_find_property(pdev->dev.of_node,
|
|
||||||
"qcom,allowed-clock-rates", NULL)) {
|
|
||||||
d_vpr_h("allowed-clock-rates not found\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_load_u32_table(pdev, pdev->dev.of_node,
|
|
||||||
"qcom,allowed-clock-rates",
|
|
||||||
sizeof(*dt->allowed_clks_tbl),
|
|
||||||
(u32 **)&dt->allowed_clks_tbl,
|
|
||||||
&dt->allowed_clks_tbl_size);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("%s: failed to read allowed clocks table\n", __func__);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
sort(dt->allowed_clks_tbl, dt->allowed_clks_tbl_size,
|
|
||||||
sizeof(*dt->allowed_clks_tbl), cmp, NULL);
|
|
||||||
|
|
||||||
d_vpr_h("Found allowed clock rates\n");
|
|
||||||
for (i = 0; i < dt->allowed_clks_tbl_size; i++)
|
|
||||||
d_vpr_h(" %d\n", dt->allowed_clks_tbl[i].clock_rate);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_bus_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
struct bus_set *buses = &dt->bus_set;
|
|
||||||
int c = 0, num_buses = 0;
|
|
||||||
u32 *bus_ranges = NULL;
|
|
||||||
|
|
||||||
num_buses = of_property_count_strings(pdev->dev.of_node,
|
|
||||||
"interconnect-names");
|
|
||||||
if (num_buses <= 0) {
|
|
||||||
d_vpr_e("No buses found\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buses->count = num_buses;
|
|
||||||
d_vpr_h("Found %d bus interconnects\n", num_buses);
|
|
||||||
|
|
||||||
rc = msm_vidc_vmem_alloc(2 * num_buses * sizeof(*bus_ranges),
|
|
||||||
(void **)&bus_ranges, " for bus ranges");
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = of_property_read_u32_array(pdev->dev.of_node,
|
|
||||||
"qcom,bus-range-kbps", bus_ranges,
|
|
||||||
num_buses * 2);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e(
|
|
||||||
"Failed to read bus ranges: defaulting to <0 INT_MAX>\n");
|
|
||||||
for (c = 0; c < num_buses; c++) {
|
|
||||||
bus_ranges[c * 2] = 0;
|
|
||||||
bus_ranges[c * 2 + 1] = INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buses->bus_tbl = devm_kzalloc(&pdev->dev, num_buses *
|
|
||||||
sizeof(*buses->bus_tbl), GFP_KERNEL);
|
|
||||||
if (!buses->bus_tbl) {
|
|
||||||
d_vpr_e("No memory for bus table\n");
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (c = 0; c < num_buses; c++) {
|
|
||||||
struct bus_info *bus = &dt->bus_set.bus_tbl[c];
|
|
||||||
|
|
||||||
of_property_read_string_index(pdev->dev.of_node,
|
|
||||||
"interconnect-names", c, &bus->name);
|
|
||||||
|
|
||||||
bus->dev = &pdev->dev;
|
|
||||||
bus->range[0] = bus_ranges[c * 2];
|
|
||||||
bus->range[1] = bus_ranges[c * 2 + 1];
|
|
||||||
|
|
||||||
d_vpr_h("Found bus %s, range [%d %d]\n", bus->name,
|
|
||||||
bus->range[0], bus->range[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
msm_vidc_vmem_free((void **) &bus_ranges);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: move this to platform data */
|
|
||||||
static int msm_vidc_load_buffer_usage_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
struct buffer_usage_set *buffer_usage_set = &dt->buffer_usage_set;
|
|
||||||
|
|
||||||
if (!of_find_property(pdev->dev.of_node,
|
|
||||||
"qcom,buffer-type-tz-usage-table", NULL)) {
|
|
||||||
/*
|
|
||||||
* qcom,buffer-type-tz-usage-table is an optional property. It
|
|
||||||
* likely won't be present if the core doesn't support content
|
|
||||||
* protection
|
|
||||||
*/
|
|
||||||
d_vpr_h("buffer-type-tz-usage-table not found\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_usage_set->count = get_u32_array_num_elements(
|
|
||||||
pdev->dev.of_node, "qcom,buffer-type-tz-usage-table");
|
|
||||||
buffer_usage_set->count /=
|
|
||||||
sizeof(*buffer_usage_set->buffer_usage_tbl) / sizeof(u32);
|
|
||||||
if (!buffer_usage_set->count) {
|
|
||||||
d_vpr_h("no elements in buffer usage set\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_usage_set->buffer_usage_tbl = devm_kzalloc(&pdev->dev,
|
|
||||||
buffer_usage_set->count *
|
|
||||||
sizeof(*buffer_usage_set->buffer_usage_tbl),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!buffer_usage_set->buffer_usage_tbl) {
|
|
||||||
d_vpr_e("%s: Failed to alloc buffer usage table\n",
|
|
||||||
__func__);
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_load_buf_usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = of_property_read_u32_array(pdev->dev.of_node,
|
|
||||||
"qcom,buffer-type-tz-usage-table",
|
|
||||||
(u32 *)buffer_usage_set->buffer_usage_tbl,
|
|
||||||
buffer_usage_set->count *
|
|
||||||
sizeof(*buffer_usage_set->buffer_usage_tbl) / sizeof(u32));
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to read buffer usage table\n");
|
|
||||||
goto err_load_buf_usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
err_load_buf_usage:
|
|
||||||
msm_vidc_free_buffer_usage_table(core->dt);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_regulator_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
struct regulator_set *regulators = &dt->regulator_set;
|
|
||||||
struct device_node *domains_parent_node = NULL;
|
|
||||||
struct property *domains_property = NULL;
|
|
||||||
int reg_count = 0;
|
|
||||||
|
|
||||||
regulators->count = 0;
|
|
||||||
regulators->regulator_tbl = NULL;
|
|
||||||
|
|
||||||
domains_parent_node = pdev->dev.of_node;
|
|
||||||
for_each_property_of_node(domains_parent_node, domains_property) {
|
|
||||||
const char *search_string = "-supply";
|
|
||||||
char *supply;
|
|
||||||
bool matched = false;
|
|
||||||
|
|
||||||
/* check if current property is possibly a regulator */
|
|
||||||
supply = strnstr(domains_property->name, search_string,
|
|
||||||
strlen(domains_property->name) + 1);
|
|
||||||
matched = supply && (*(supply + strlen(search_string)) == '\0');
|
|
||||||
if (!matched)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
reg_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
regulators->regulator_tbl = devm_kzalloc(&pdev->dev,
|
|
||||||
sizeof(*regulators->regulator_tbl) *
|
|
||||||
reg_count, GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!regulators->regulator_tbl) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
d_vpr_e("Failed to alloc memory for regulator table\n");
|
|
||||||
goto err_reg_tbl_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_each_property_of_node(domains_parent_node, domains_property) {
|
|
||||||
const char *search_string = "-supply";
|
|
||||||
char *supply;
|
|
||||||
bool matched = false;
|
|
||||||
struct device_node *regulator_node = NULL;
|
|
||||||
struct regulator_info *rinfo = NULL;
|
|
||||||
|
|
||||||
/* check if current property is possibly a regulator */
|
|
||||||
supply = strnstr(domains_property->name, search_string,
|
|
||||||
strlen(domains_property->name) + 1);
|
|
||||||
matched = supply && (supply[strlen(search_string)] == '\0');
|
|
||||||
if (!matched)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* make sure prop isn't being misused */
|
|
||||||
regulator_node = of_parse_phandle(domains_parent_node,
|
|
||||||
domains_property->name, 0);
|
|
||||||
if (IS_ERR(regulator_node)) {
|
|
||||||
d_vpr_e("%s is not a phandle\n",
|
|
||||||
domains_property->name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
regulators->count++;
|
|
||||||
|
|
||||||
/* populate regulator info */
|
|
||||||
rinfo = ®ulators->regulator_tbl[regulators->count - 1];
|
|
||||||
rinfo->name = devm_kzalloc(&pdev->dev,
|
|
||||||
(supply - domains_property->name) + 1, GFP_KERNEL);
|
|
||||||
if (!rinfo->name) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
d_vpr_e("Failed to alloc memory for regulator name\n");
|
|
||||||
goto err_reg_name_alloc;
|
|
||||||
}
|
|
||||||
strlcpy(rinfo->name, domains_property->name,
|
|
||||||
(supply - domains_property->name) + 1);
|
|
||||||
|
|
||||||
rinfo->has_hw_power_collapse = of_property_read_bool(
|
|
||||||
regulator_node, "qcom,support-hw-trigger");
|
|
||||||
|
|
||||||
d_vpr_h("Found regulator %s: h/w collapse = %s\n",
|
|
||||||
rinfo->name,
|
|
||||||
rinfo->has_hw_power_collapse ? "yes" : "no");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!regulators->count)
|
|
||||||
d_vpr_h("No regulators found");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_reg_name_alloc:
|
|
||||||
err_reg_tbl_alloc:
|
|
||||||
msm_vidc_free_regulator_table(core->dt);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_clock_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0, num_clocks = 0, c = 0;
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
int *clock_ids = NULL;
|
|
||||||
int *clock_props = NULL;
|
|
||||||
struct clock_set *clocks = &dt->clock_set;
|
|
||||||
|
|
||||||
num_clocks = of_property_count_strings(pdev->dev.of_node,
|
|
||||||
"clock-names");
|
|
||||||
if (num_clocks <= 0) {
|
|
||||||
d_vpr_h("No clocks found\n");
|
|
||||||
clocks->count = 0;
|
|
||||||
rc = 0;
|
|
||||||
goto err_load_clk_table_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_ids = devm_kzalloc(&pdev->dev, num_clocks *
|
|
||||||
sizeof(*clock_ids), GFP_KERNEL);
|
|
||||||
if (!clock_ids) {
|
|
||||||
d_vpr_e("No memory to read clock ids\n");
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_load_clk_table_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = of_property_read_u32_array(pdev->dev.of_node,
|
|
||||||
"clock-ids", clock_ids,
|
|
||||||
num_clocks);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to read clock ids: %d\n", rc);
|
|
||||||
goto err_load_clk_prop_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_props = devm_kzalloc(&pdev->dev, num_clocks *
|
|
||||||
sizeof(*clock_props), GFP_KERNEL);
|
|
||||||
if (!clock_props) {
|
|
||||||
d_vpr_e("No memory to read clock properties\n");
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_load_clk_table_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = of_property_read_u32_array(pdev->dev.of_node,
|
|
||||||
"qcom,clock-configs", clock_props,
|
|
||||||
num_clocks);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to read clock properties: %d\n", rc);
|
|
||||||
goto err_load_clk_prop_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
clocks->clock_tbl = devm_kzalloc(&pdev->dev, sizeof(*clocks->clock_tbl)
|
|
||||||
* num_clocks, GFP_KERNEL);
|
|
||||||
if (!clocks->clock_tbl) {
|
|
||||||
d_vpr_e("Failed to allocate memory for clock tbl\n");
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_load_clk_prop_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
clocks->count = num_clocks;
|
|
||||||
d_vpr_h("Found %d clocks\n", num_clocks);
|
|
||||||
|
|
||||||
for (c = 0; c < num_clocks; ++c) {
|
|
||||||
struct clock_info *vc = &dt->clock_set.clock_tbl[c];
|
|
||||||
|
|
||||||
of_property_read_string_index(pdev->dev.of_node,
|
|
||||||
"clock-names", c, &vc->name);
|
|
||||||
|
|
||||||
vc->clk_id = clock_ids[c];
|
|
||||||
|
|
||||||
if (clock_props[c] & CLOCK_PROP_HAS_SCALING) {
|
|
||||||
vc->has_scaling = true;
|
|
||||||
} else {
|
|
||||||
vc->has_scaling = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clock_props[c] & CLOCK_PROP_HAS_MEM_RETENTION)
|
|
||||||
vc->has_mem_retention = true;
|
|
||||||
else
|
|
||||||
vc->has_mem_retention = false;
|
|
||||||
|
|
||||||
d_vpr_h("Found clock %s: scale-able = %s\n", vc->name,
|
|
||||||
vc->has_scaling ? "yes" : "no");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_load_clk_prop_fail:
|
|
||||||
err_load_clk_table_fail:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_load_reset_table(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
struct platform_device *pdev = core->pdev;
|
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
|
||||||
struct reset_set *rst = &dt->reset_set;
|
|
||||||
int num_clocks = 0, c = 0;
|
|
||||||
|
|
||||||
num_clocks = of_property_count_strings(pdev->dev.of_node,
|
|
||||||
"reset-names");
|
|
||||||
if (num_clocks <= 0) {
|
|
||||||
d_vpr_h("No reset clocks found\n");
|
|
||||||
rst->count = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rst->reset_tbl = devm_kcalloc(&pdev->dev, num_clocks,
|
|
||||||
sizeof(*rst->reset_tbl), GFP_KERNEL);
|
|
||||||
if (!rst->reset_tbl)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
rst->count = num_clocks;
|
|
||||||
d_vpr_h("Found %d reset clocks\n", num_clocks);
|
|
||||||
|
|
||||||
for (c = 0; c < num_clocks; ++c) {
|
|
||||||
struct reset_info *rc = &dt->reset_set.reset_tbl[c];
|
|
||||||
|
|
||||||
of_property_read_string_index(pdev->dev.of_node,
|
|
||||||
"reset-names", c, &rc->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_read_resources_from_dt(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct msm_vidc_core *core;
|
|
||||||
struct msm_vidc_dt *dt;
|
|
||||||
struct resource *kres;
|
|
||||||
|
|
||||||
if (!pdev) {
|
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
core = dev_get_drvdata(&pdev->dev);
|
|
||||||
if (!core || !core->dt) {
|
|
||||||
d_vpr_e("%s: core not found in device %s",
|
|
||||||
__func__, dev_name(&pdev->dev));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
dt = core->dt;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&dt->context_banks);
|
|
||||||
|
|
||||||
kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
dt->register_base = kres ? kres->start : -1;
|
|
||||||
dt->register_size = kres ? (kres->end + 1 - kres->start) : -1;
|
|
||||||
d_vpr_h("%s: register base %pa, size %#x\n",
|
|
||||||
__func__, &dt->register_base, dt->register_size);
|
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0))
|
|
||||||
dt->irq = platform_get_irq(pdev, 0);
|
|
||||||
#else
|
|
||||||
kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
||||||
dt->irq = kres ? kres->start : -1;
|
|
||||||
#endif
|
|
||||||
if (dt->irq < 0)
|
|
||||||
d_vpr_e("%s: get irq failed, %d\n", __func__, dt->irq);
|
|
||||||
|
|
||||||
d_vpr_h("%s: irq %d\n", __func__, dt->irq);
|
|
||||||
|
|
||||||
rc = msm_vidc_load_fw_name(core);
|
|
||||||
if (rc)
|
|
||||||
d_vpr_e("%s: failed to load fw name, rc %d, using default fw\n",
|
|
||||||
__func__, rc);
|
|
||||||
|
|
||||||
rc = msm_vidc_load_subcache_info(core);
|
|
||||||
if (rc)
|
|
||||||
d_vpr_e("Failed to load subcache info: %d\n", rc);
|
|
||||||
|
|
||||||
rc = msm_vidc_load_qdss_table(core);
|
|
||||||
if (rc)
|
|
||||||
d_vpr_e("Failed to load qdss reg table: %d\n", rc);
|
|
||||||
|
|
||||||
rc = msm_vidc_load_reg_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load reg table: %d\n", rc);
|
|
||||||
goto err_load_reg_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move this table to platform
|
|
||||||
rc = msm_vidc_load_buffer_usage_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load buffer usage table: %d\n", rc);
|
|
||||||
goto err_load_buffer_usage_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_load_regulator_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load list of regulators %d\n", rc);
|
|
||||||
goto err_load_regulator_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_load_bus_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load bus table: %d\n", rc);
|
|
||||||
goto err_load_bus_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_load_clock_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load clock table: %d\n", rc);
|
|
||||||
goto err_load_clock_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move this table to platform
|
|
||||||
rc = msm_vidc_load_allowed_clocks_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load allowed clocks table: %d\n", rc);
|
|
||||||
goto err_load_allowed_clocks_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_load_reset_table(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Failed to load reset table: %d\n", rc);
|
|
||||||
goto err_load_reset_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
err_load_reset_table:
|
|
||||||
msm_vidc_free_allowed_clocks_table(core->dt);
|
|
||||||
err_load_allowed_clocks_table:
|
|
||||||
msm_vidc_free_clock_table(core->dt);
|
|
||||||
err_load_clock_table:
|
|
||||||
msm_vidc_free_bus_table(core->dt);
|
|
||||||
err_load_bus_table:
|
|
||||||
msm_vidc_free_regulator_table(core->dt);
|
|
||||||
err_load_regulator_table:
|
|
||||||
msm_vidc_free_buffer_usage_table(core->dt);
|
|
||||||
err_load_buffer_usage_table:
|
|
||||||
msm_vidc_free_reg_table(core->dt);
|
|
||||||
err_load_reg_table:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
|
|
||||||
struct context_bank_info *cb, struct device *dev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct bus_type *bus;
|
|
||||||
|
|
||||||
if (!core || !dev || !cb) {
|
|
||||||
d_vpr_e("%s: Invalid Input params\n", __func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
cb->dev = dev;
|
|
||||||
|
|
||||||
bus = cb->dev->bus;
|
|
||||||
if (IS_ERR_OR_NULL(bus)) {
|
|
||||||
d_vpr_e("%s: failed to get bus type\n", __func__);
|
|
||||||
rc = PTR_ERR(bus) ? PTR_ERR(bus) : -ENODEV;
|
|
||||||
goto remove_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
cb->domain = iommu_get_domain_for_dev(cb->dev);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When memory is fragmented, below configuration increases the
|
|
||||||
* possibility to get a mapping for buffer in the configured CB.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* remove kernel version condition once below api is whitelisted in pineapple */
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,16,0))
|
|
||||||
iommu_dma_enable_best_fit_algo(cb->dev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* configure device segment size and segment boundary to ensure
|
|
||||||
* iommu mapping returns one mapping (which is required for partial
|
|
||||||
* cache operations)
|
|
||||||
*/
|
|
||||||
if (!dev->dma_parms)
|
|
||||||
dev->dma_parms =
|
|
||||||
devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
|
|
||||||
dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
|
|
||||||
dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
|
|
||||||
|
|
||||||
d_vpr_h("Attached %s and created mapping\n", dev_name(dev));
|
|
||||||
d_vpr_h(
|
|
||||||
"Context bank: %s, is_secure: %d, address range start: %#x, size: %#x, dev: %pK, domain: %pK",
|
|
||||||
cb->name, cb->is_secure, cb->addr_range.start,
|
|
||||||
cb->addr_range.size, cb->dev, cb->domain);
|
|
||||||
remove_cb:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_vidc_populate_context_bank(struct device *dev,
|
|
||||||
struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct context_bank_info *cb = NULL;
|
|
||||||
struct device_node *np = NULL;
|
|
||||||
|
|
||||||
if (!dev || !core || !core->dt) {
|
|
||||||
d_vpr_e("%s: invalid inputs\n", __func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
np = dev->of_node;
|
|
||||||
cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL);
|
|
||||||
if (!cb) {
|
|
||||||
d_vpr_e("%s: Failed to allocate cb\n", __func__);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&cb->list);
|
|
||||||
rc = of_property_read_string(np, "label", &cb->name);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_h("Failed to read cb label from device tree\n");
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
d_vpr_h("%s: context bank has name %s\n", __func__, cb->name);
|
|
||||||
rc = of_property_read_u32_array(np, "virtual-addr-pool",
|
|
||||||
(u32 *)&cb->addr_range, 2);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Could not read addr pool: context bank: %s %d\n",
|
|
||||||
cb->name, rc);
|
|
||||||
goto err_setup_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
cb->is_secure = of_property_read_bool(np, "qcom,secure-context-bank");
|
|
||||||
d_vpr_h("context bank %s: secure = %d\n",
|
|
||||||
cb->name, cb->is_secure);
|
|
||||||
|
|
||||||
d_vpr_h("context bank %s address start %x size %x\n",
|
|
||||||
cb->name, cb->addr_range.start,
|
|
||||||
cb->addr_range.size);
|
|
||||||
|
|
||||||
rc = msm_vidc_setup_context_bank(core, cb, dev);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("Cannot setup context bank %d\n", rc);
|
|
||||||
goto err_setup_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
core_lock(core, __func__);
|
|
||||||
list_add_tail(&cb->list, &core->dt->context_banks);
|
|
||||||
core_unlock(core, __func__);
|
|
||||||
|
|
||||||
iommu_set_fault_handler(cb->domain,
|
|
||||||
msm_vidc_smmu_fault_handler, (void *)core);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_setup_cb:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int msm_vidc_read_context_bank_resources_from_dt(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct msm_vidc_core *core;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (!pdev) {
|
|
||||||
d_vpr_e("Invalid platform device\n");
|
|
||||||
return -EINVAL;
|
|
||||||
} else if (!pdev->dev.parent) {
|
|
||||||
d_vpr_e("Failed to find a parent for %s\n",
|
|
||||||
dev_name(&pdev->dev));
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
core = dev_get_drvdata(pdev->dev.parent);
|
|
||||||
if (!core) {
|
|
||||||
d_vpr_e("Failed to find cookie in parent device %s",
|
|
||||||
dev_name(pdev->dev.parent));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_populate_context_bank(&pdev->dev, core);
|
|
||||||
if (rc)
|
|
||||||
d_vpr_e("Failed to probe context bank\n");
|
|
||||||
else
|
|
||||||
d_vpr_h("Successfully probed context bank\n");
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void msm_vidc_deinit_dt(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct msm_vidc_core *core;
|
|
||||||
|
|
||||||
if (!pdev) {
|
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core = dev_get_drvdata(&pdev->dev);
|
|
||||||
if (!core) {
|
|
||||||
d_vpr_e("%s: core not found in device %s",
|
|
||||||
__func__, dev_name(&pdev->dev));
|
|
||||||
return;
|
|
||||||
} else if (!core->dt) {
|
|
||||||
d_vpr_e("%s: invalid dt in device %s",
|
|
||||||
__func__, dev_name(&pdev->dev));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
msm_vidc_free_clock_table(core->dt);
|
|
||||||
msm_vidc_free_regulator_table(core->dt);
|
|
||||||
msm_vidc_free_allowed_clocks_table(core->dt);
|
|
||||||
msm_vidc_free_reg_table(core->dt);
|
|
||||||
msm_vidc_free_qdss_addr_table(core->dt);
|
|
||||||
msm_vidc_free_bus_table(core->dt);
|
|
||||||
msm_vidc_free_buffer_usage_table(core->dt);
|
|
||||||
msm_vidc_vmem_free((void **)&core->dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
int msm_vidc_init_dt(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct msm_vidc_dt *dt = NULL;
|
|
||||||
struct msm_vidc_core *core;
|
|
||||||
|
|
||||||
if (!pdev) {
|
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
core = dev_get_drvdata(&pdev->dev);
|
|
||||||
if (!core) {
|
|
||||||
d_vpr_e("%s: core not found in device %s",
|
|
||||||
__func__, dev_name(&pdev->dev));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_vmem_alloc(sizeof(struct msm_vidc_dt), (void **)&dt, __func__);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
core->dt = dt;
|
|
||||||
dt->core = core;
|
|
||||||
|
|
||||||
rc = msm_vidc_read_resources_from_dt(pdev);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_events.h"
|
#include "msm_vidc_events.h"
|
||||||
|
#include "msm_vidc_platform.h"
|
||||||
#include "venus_hfi.h"
|
#include "venus_hfi.h"
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0))
|
||||||
@@ -30,27 +31,15 @@ struct msm_vidc_buf_region_name {
|
|||||||
struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core,
|
struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core,
|
||||||
enum msm_vidc_buffer_region region)
|
enum msm_vidc_buffer_region region)
|
||||||
{
|
{
|
||||||
const char *name;
|
|
||||||
struct context_bank_info *cb = NULL, *match = NULL;
|
struct context_bank_info *cb = NULL, *match = NULL;
|
||||||
static const struct msm_vidc_buf_region_name buf_region_name[] = {
|
|
||||||
{MSM_VIDC_REGION_NONE, "none" },
|
|
||||||
{MSM_VIDC_NON_SECURE, "venus_ns" },
|
|
||||||
{MSM_VIDC_NON_SECURE_PIXEL, "venus_ns_pixel" },
|
|
||||||
{MSM_VIDC_SECURE_PIXEL, "venus_sec_pixel" },
|
|
||||||
{MSM_VIDC_SECURE_NONPIXEL, "venus_sec_non_pixel" },
|
|
||||||
{MSM_VIDC_SECURE_BITSTREAM, "venus_sec_bitstream" },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!region || region > ARRAY_SIZE(buf_region_name))
|
if (!region || region >= MSM_VIDC_REGION_MAX) {
|
||||||
goto exit;
|
d_vpr_e("Invalid region %#x\n", region);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (buf_region_name[region].region != region)
|
venus_hfi_for_each_context_bank(core, cb) {
|
||||||
goto exit;
|
if (cb->region == region) {
|
||||||
|
|
||||||
name = buf_region_name[region].name;
|
|
||||||
|
|
||||||
list_for_each_entry(cb, &core->dt->context_banks, list) {
|
|
||||||
if (!strcmp(cb->name, name)) {
|
|
||||||
match = cb;
|
match = cb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -59,10 +48,6 @@ struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core,
|
|||||||
d_vpr_e("cb not found for region %#x\n", region);
|
d_vpr_e("cb not found for region %#x\n", region);
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
|
|
||||||
exit:
|
|
||||||
d_vpr_e("Invalid region %#x\n", region);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dma_buf *msm_vidc_memory_get_dmabuf(struct msm_vidc_inst *inst, int fd)
|
struct dma_buf *msm_vidc_memory_get_dmabuf(struct msm_vidc_inst *inst, int fd)
|
||||||
@@ -245,7 +230,7 @@ int msm_vidc_memory_map(struct msm_vidc_core *core, struct msm_vidc_map *map)
|
|||||||
* required buffer size
|
* required buffer size
|
||||||
*/
|
*/
|
||||||
attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
|
attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
|
||||||
if (core->dt->sys_cache_present)
|
if (is_sys_cache_present(core))
|
||||||
attach->dma_map_attrs |=
|
attach->dma_map_attrs |=
|
||||||
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
|
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@
|
|||||||
#include "msm_vidc_internal.h"
|
#include "msm_vidc_internal.h"
|
||||||
#include "msm_vidc_inst.h"
|
#include "msm_vidc_inst.h"
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_platform.h"
|
#include "msm_vidc_platform.h"
|
||||||
#include "msm_vidc_buffer.h"
|
#include "msm_vidc_buffer.h"
|
||||||
@@ -92,7 +91,7 @@ void __dump(struct dump dump[], int len)
|
|||||||
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
|
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
|
||||||
{
|
{
|
||||||
struct msm_vidc_core* core;
|
struct msm_vidc_core* core;
|
||||||
struct allowed_clock_rates_table *allowed_clks_tbl;
|
struct frequency_table *freq_tbl;
|
||||||
u64 freq = 0;
|
u64 freq = 0;
|
||||||
|
|
||||||
if (!inst || !inst->core) {
|
if (!inst || !inst->core) {
|
||||||
@@ -100,12 +99,14 @@ u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
|
|||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
core = inst->core;
|
core = inst->core;
|
||||||
if (!core->dt || !core->dt->allowed_clks_tbl) {
|
|
||||||
i_vpr_e(inst, "%s: invalid params\n", __func__);
|
if (!core->resource || !core->resource->freq_set.freq_tbl ||
|
||||||
|
!core->resource->freq_set.count) {
|
||||||
|
i_vpr_e(inst, "%s: invalid frequency table\n", __func__);
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
allowed_clks_tbl = core->dt->allowed_clks_tbl;
|
freq_tbl = core->resource->freq_set.freq_tbl;
|
||||||
freq = allowed_clks_tbl[0].clock_rate;
|
freq = freq_tbl[0].freq;
|
||||||
|
|
||||||
i_vpr_l(inst, "%s: rate = %llu\n", __func__, freq);
|
i_vpr_l(inst, "%s: rate = %llu\n", __func__, freq);
|
||||||
return freq;
|
return freq;
|
||||||
@@ -267,8 +268,8 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
core = inst->core;
|
core = inst->core;
|
||||||
if (!core->dt) {
|
if (!core->resource) {
|
||||||
i_vpr_e(inst, "%s: invalid dt params\n", __func__);
|
i_vpr_e(inst, "%s: invalid resource params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
vote_data = &inst->bus_data;
|
vote_data = &inst->bus_data;
|
||||||
@@ -347,7 +348,7 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
vote_data->work_mode = inst->capabilities->cap[STAGE].value;
|
vote_data->work_mode = inst->capabilities->cap[STAGE].value;
|
||||||
if (core->dt->sys_cache_res_set)
|
if (core->resource->subcache_set.set_to_fw)
|
||||||
vote_data->use_sys_cache = true;
|
vote_data->use_sys_cache = true;
|
||||||
vote_data->num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
vote_data->num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||||
fill_dynamic_stats(inst, vote_data);
|
fill_dynamic_stats(inst, vote_data);
|
||||||
@@ -382,8 +383,10 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
core = inst->core;
|
core = inst->core;
|
||||||
if (!core->dt || !core->dt->allowed_clks_tbl) {
|
|
||||||
d_vpr_e("%s: invalid dt params\n", __func__);
|
if (!core->resource || !core->resource->freq_set.freq_tbl ||
|
||||||
|
!core->resource->freq_set.count) {
|
||||||
|
d_vpr_e("%s: invalid frequency table\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,8 +425,8 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
|
|||||||
* keep checking from lowest to highest rate until
|
* keep checking from lowest to highest rate until
|
||||||
* table rate >= requested rate
|
* table rate >= requested rate
|
||||||
*/
|
*/
|
||||||
for (i = core->dt->allowed_clks_tbl_size - 1; i >= 0; i--) {
|
for (i = core->resource->freq_set.count - 1; i >= 0; i--) {
|
||||||
rate = core->dt->allowed_clks_tbl[i].clock_rate;
|
rate = core->resource->freq_set.freq_tbl[i].freq;
|
||||||
if (rate >= freq)
|
if (rate >= freq)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -431,10 +434,10 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
|
|||||||
i = 0;
|
i = 0;
|
||||||
if (increment) {
|
if (increment) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
rate = core->dt->allowed_clks_tbl[i - 1].clock_rate;
|
rate = core->resource->freq_set.freq_tbl[i - 1].freq;
|
||||||
} else if (decrement) {
|
} else if (decrement) {
|
||||||
if (i < (int) (core->dt->allowed_clks_tbl_size - 1))
|
if (i < (int) (core->platform->data.freq_tbl_size - 1))
|
||||||
rate = core->dt->allowed_clks_tbl[i + 1].clock_rate;
|
rate = core->resource->freq_set.freq_tbl[i + 1].freq;
|
||||||
}
|
}
|
||||||
core->power.clk_freq = (u32)rate;
|
core->power.clk_freq = (u32)rate;
|
||||||
|
|
||||||
|
@@ -10,11 +10,15 @@
|
|||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/component.h>
|
#include <linux/component.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/iommu.h>
|
||||||
|
#include <linux/dma-iommu.h>
|
||||||
|
#ifdef CONFIG_MSM_MMRM
|
||||||
|
#include <linux/soc/qcom/msm_mmrm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "msm_vidc_internal.h"
|
#include "msm_vidc_internal.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_driver.h"
|
#include "msm_vidc_driver.h"
|
||||||
#include "msm_vidc_dt.h"
|
|
||||||
#include "msm_vidc_platform.h"
|
#include "msm_vidc_platform.h"
|
||||||
#include "msm_vidc_core.h"
|
#include "msm_vidc_core.h"
|
||||||
#include "msm_vidc_memory.h"
|
#include "msm_vidc_memory.h"
|
||||||
@@ -28,62 +32,50 @@ struct msm_vidc_core *g_core;
|
|||||||
const char video_banner[] = "Video-Banner: (" VIDEO_COMPILE_BY "@"
|
const char video_banner[] = "Video-Banner: (" VIDEO_COMPILE_BY "@"
|
||||||
VIDEO_COMPILE_HOST ") (" VIDEO_COMPILE_TIME ")";
|
VIDEO_COMPILE_HOST ") (" VIDEO_COMPILE_TIME ")";
|
||||||
|
|
||||||
static int msm_vidc_deinit_irq(struct msm_vidc_core *core)
|
static inline bool is_video_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct msm_vidc_dt *dt;
|
return !!(of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
|
||||||
if (!core || !core->pdev || !core->dt) {
|
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2") ||
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc"));
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
dt = core->dt;
|
|
||||||
d_vpr_h("%s: reg_base = %pa, reg_size = %#x\n",
|
|
||||||
__func__, &dt->register_base, dt->register_size);
|
|
||||||
|
|
||||||
dt->irq = 0;
|
|
||||||
|
|
||||||
if (core->register_base_addr)
|
|
||||||
devm_iounmap(&core->pdev->dev, core->register_base_addr);
|
|
||||||
core->register_base_addr = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_vidc_init_irq(struct msm_vidc_core *core)
|
static inline bool is_video_context_bank_device(struct device *dev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-pxl") ||
|
||||||
struct msm_vidc_dt *dt;
|
of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-bitstream") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-non-pxl") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns") ||
|
||||||
|
of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns-pxl"));
|
||||||
|
}
|
||||||
|
|
||||||
if (!core || !core->pdev || !core->dt) {
|
static int msm_vidc_init_resources(struct msm_vidc_core *core)
|
||||||
|
{
|
||||||
|
const struct msm_vidc_resources_ops *res_ops;
|
||||||
|
struct msm_vidc_resource *res = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!core) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
dt = core->dt;
|
res_ops = core->res_ops;
|
||||||
|
|
||||||
core->register_base_addr = devm_ioremap(&core->pdev->dev,
|
res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
|
||||||
dt->register_base, dt->register_size);
|
if (!res) {
|
||||||
if (!core->register_base_addr) {
|
d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
|
||||||
d_vpr_e("could not map reg addr %pa of size %d\n",
|
return -ENOMEM;
|
||||||
&dt->register_base, dt->register_size);
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
|
res->core = core;
|
||||||
|
core->resource = res;
|
||||||
|
|
||||||
rc = devm_request_threaded_irq(&core->pdev->dev, dt->irq, venus_hfi_isr,
|
rc = res_ops->init(core);
|
||||||
venus_hfi_isr_handler, IRQF_TRIGGER_HIGH, "msm-vidc", core);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: Failed to allocate venus IRQ\n", __func__);
|
d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
|
||||||
goto exit;
|
return rc;
|
||||||
}
|
}
|
||||||
disable_irq_nosync(dt->irq);
|
|
||||||
|
|
||||||
d_vpr_h("%s: reg_base = %pa, reg_size = %d\n",
|
|
||||||
__func__, &dt->register_base, dt->register_size);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
exit:
|
|
||||||
msm_vidc_deinit_irq(core);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t sku_version_show(struct device *dev,
|
static ssize_t sku_version_show(struct device *dev,
|
||||||
@@ -95,8 +87,7 @@ static ssize_t sku_version_show(struct device *dev,
|
|||||||
* Default sku version: 0
|
* Default sku version: 0
|
||||||
* driver possibly not probed yet or not the main device.
|
* driver possibly not probed yet or not the main device.
|
||||||
*/
|
*/
|
||||||
if (!dev || !dev->driver ||
|
if (!dev || !dev->driver)
|
||||||
!of_device_is_compatible(dev->of_node, "qcom,msm-vidc"))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
core = dev_get_drvdata(dev);
|
core = dev_get_drvdata(dev);
|
||||||
@@ -121,8 +112,15 @@ static struct attribute_group msm_vidc_core_attr_group = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id msm_vidc_dt_match[] = {
|
static const struct of_device_id msm_vidc_dt_match[] = {
|
||||||
{.compatible = "qcom,msm-vidc"},
|
{.compatible = "qcom,sm8450-vidc"},
|
||||||
{.compatible = "qcom,msm-vidc,context-bank"},
|
{.compatible = "qcom,sm8550-vidc"},
|
||||||
|
{.compatible = "qcom,sm8550-vidc-v2"},
|
||||||
|
{.compatible = "qcom,sm8650-vidc"},
|
||||||
|
{.compatible = "qcom,vidc,cb-ns-pxl"},
|
||||||
|
{.compatible = "qcom,vidc,cb-ns"},
|
||||||
|
{.compatible = "qcom,vidc,cb-sec-non-pxl"},
|
||||||
|
{.compatible = "qcom,vidc,cb-sec-bitstream"},
|
||||||
|
{.compatible = "qcom,vidc,cb-sec-pxl"},
|
||||||
MSM_VIDC_EMPTY_BRACE
|
MSM_VIDC_EMPTY_BRACE
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
|
MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
|
||||||
@@ -137,7 +135,7 @@ static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
|
|||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
d_vpr_h("%s()\n", __func__);
|
d_vpr_h("%s: domain %d\n", __func__, type);
|
||||||
|
|
||||||
if (type == MSM_VIDC_DECODER)
|
if (type == MSM_VIDC_DECODER)
|
||||||
index = 0;
|
index = 0;
|
||||||
@@ -163,7 +161,7 @@ static int msm_vidc_register_video_device(struct msm_vidc_core *core,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
int index, media_index;
|
int index, media_index;
|
||||||
|
|
||||||
d_vpr_h("%s()\n", __func__);
|
d_vpr_h("%s: domain %d\n", __func__, type);
|
||||||
|
|
||||||
if (!core || !core->capabilities) {
|
if (!core || !core->capabilities) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
@@ -236,32 +234,32 @@ static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!core || !core->capabilities) {
|
if (!core || !core->platform) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!core->capabilities[MMRM].value)
|
if (!is_mmrm_supported(core))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (!mmrm_client_check_scaling_supported(MMRM_CLIENT_CLOCK, 0)) {
|
if (!mmrm_client_check_scaling_supported(MMRM_CLIENT_CLOCK, 0)) {
|
||||||
d_vpr_e("%s: MMRM not supported\n", __func__);
|
d_vpr_e("%s: MMRM not supported\n", __func__);
|
||||||
core->capabilities[MMRM].value = 0;
|
core->platform->data.supports_mmrm = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
d_vpr_h("%s: %d\n", __func__, core->capabilities[MMRM].value);
|
d_vpr_h("%s: %d\n", __func__, is_mmrm_supported(core));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
|
static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
|
||||||
{
|
{
|
||||||
if (!core || !core->capabilities) {
|
if (!core || !core->platform) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
core->capabilities[MMRM].value = 0;
|
core->platform->data.supports_mmrm = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -358,6 +356,83 @@ exit:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct context_bank_info *get_context_bank(
|
||||||
|
struct msm_vidc_core *core, struct device *dev)
|
||||||
|
{
|
||||||
|
struct context_bank_info *cb = NULL, *match = NULL;
|
||||||
|
|
||||||
|
if (!core || !dev) {
|
||||||
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
venus_hfi_for_each_context_bank(core, cb) {
|
||||||
|
if (of_device_is_compatible(dev->of_node, cb->name)) {
|
||||||
|
match = cb;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match)
|
||||||
|
d_vpr_e("cb not found for dev %s\n", dev_name(dev));
|
||||||
|
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
|
||||||
|
struct device *dev)
|
||||||
|
{
|
||||||
|
struct context_bank_info *cb = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!core || !dev) {
|
||||||
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb = get_context_bank(core, dev);
|
||||||
|
if (!cb) {
|
||||||
|
d_vpr_e("%s: Failed to get context bank device for %s\n",
|
||||||
|
__func__, dev_name(dev));
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* populate dev & domain field */
|
||||||
|
cb->dev = dev;
|
||||||
|
cb->domain = iommu_get_domain_for_dev(cb->dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When memory is fragmented, below configuration increases the
|
||||||
|
* possibility to get a mapping for buffer in the configured CB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* remove kernel version condition once below api is whitelisted in pineapple */
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
|
||||||
|
iommu_dma_enable_best_fit_algo(cb->dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* configure device segment size and segment boundary to ensure
|
||||||
|
* iommu mapping returns one mapping (which is required for partial
|
||||||
|
* cache operations)
|
||||||
|
*/
|
||||||
|
if (!dev->dma_parms)
|
||||||
|
dev->dma_parms =
|
||||||
|
devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
|
||||||
|
dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
|
||||||
|
dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
|
||||||
|
|
||||||
|
iommu_set_fault_handler(cb->domain,
|
||||||
|
msm_vidc_smmu_fault_handler, (void *)core);
|
||||||
|
|
||||||
|
d_vpr_h(
|
||||||
|
"%s: name %s addr start %x size %x secure %d dma_coherant %d region %d dev_name %s domain %pK\n",
|
||||||
|
__func__, cb->name, cb->addr_range.start,
|
||||||
|
cb->addr_range.size, cb->secure, cb->dma_coherant,
|
||||||
|
cb->region, dev_name(cb->dev), cb->domain);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int msm_vidc_component_compare_of(struct device *dev, void *data)
|
static int msm_vidc_component_compare_of(struct device *dev, void *data)
|
||||||
{
|
{
|
||||||
return dev->of_node == data;
|
return dev->of_node == data;
|
||||||
@@ -372,8 +447,35 @@ static void msm_vidc_component_release_of(struct device *dev, void *data)
|
|||||||
static int msm_vidc_component_cb_bind(struct device *dev,
|
static int msm_vidc_component_cb_bind(struct device *dev,
|
||||||
struct device *master, void *data)
|
struct device *master, void *data)
|
||||||
{
|
{
|
||||||
d_vpr_h("%s(): %s\n", __func__, dev_name(dev));
|
struct msm_vidc_core *core;
|
||||||
return 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!dev) {
|
||||||
|
d_vpr_e("%s: invalid device\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (!dev->parent) {
|
||||||
|
d_vpr_e("%s: failed to find a parent for %s\n",
|
||||||
|
__func__, dev_name(dev));
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
core = dev_get_drvdata(dev->parent);
|
||||||
|
if (!core) {
|
||||||
|
d_vpr_e("%s: failed to find cookie in parent device %s",
|
||||||
|
__func__, dev_name(dev->parent));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msm_vidc_setup_context_bank(core, dev);
|
||||||
|
if (rc) {
|
||||||
|
d_vpr_e("%s: Failed to probe context bank - %s\n",
|
||||||
|
__func__, dev_name(dev));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
d_vpr_h("%s: Successfully probed context bank - %s\n",
|
||||||
|
__func__, dev_name(dev));
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_vidc_component_cb_unbind(struct device *dev,
|
static void msm_vidc_component_cb_unbind(struct device *dev,
|
||||||
@@ -391,7 +493,7 @@ static int msm_vidc_component_bind(struct device *dev)
|
|||||||
|
|
||||||
rc = component_bind_all(dev, core);
|
rc = component_bind_all(dev, core);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: sub-device bind failed\n", __func__);
|
d_vpr_e("%s: sub-device bind failed. rc %d\n", __func__, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +566,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
|
|||||||
|
|
||||||
d_vpr_h("depopulating sub devices\n");
|
d_vpr_h("depopulating sub devices\n");
|
||||||
/*
|
/*
|
||||||
* Trigger remove for each sub-device i.e. qcom,msm-vidc,context-bank.
|
* Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
|
||||||
* When msm_vidc_remove is called for each sub-device, destroy
|
* When msm_vidc_remove is called for each sub-device, destroy
|
||||||
* context-bank mappings.
|
* context-bank mappings.
|
||||||
*/
|
*/
|
||||||
@@ -488,9 +590,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
|
|||||||
msm_vidc_deinit_instance_caps(core);
|
msm_vidc_deinit_instance_caps(core);
|
||||||
msm_vidc_deinit_core_caps(core);
|
msm_vidc_deinit_core_caps(core);
|
||||||
|
|
||||||
msm_vidc_deinit_irq(core);
|
|
||||||
msm_vidc_deinit_platform(pdev);
|
msm_vidc_deinit_platform(pdev);
|
||||||
msm_vidc_deinit_dt(pdev);
|
|
||||||
msm_vidc_deinitialize_core(core);
|
msm_vidc_deinitialize_core(core);
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
@@ -504,8 +604,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
|
|||||||
|
|
||||||
static int msm_vidc_remove_context_bank(struct platform_device *pdev)
|
static int msm_vidc_remove_context_bank(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
d_vpr_h("%s(): Detached %s and destroyed mapping\n",
|
d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
|
||||||
__func__, dev_name(&pdev->dev));
|
|
||||||
|
|
||||||
component_del(&pdev->dev, &msm_vidc_component_cb_ops);
|
component_del(&pdev->dev, &msm_vidc_component_cb_ops);
|
||||||
|
|
||||||
@@ -519,12 +618,10 @@ static int msm_vidc_remove(struct platform_device *pdev)
|
|||||||
* after core_deinit(). It return immediately after completing
|
* after core_deinit(). It return immediately after completing
|
||||||
* sub-device remove.
|
* sub-device remove.
|
||||||
*/
|
*/
|
||||||
if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-vidc")) {
|
if (is_video_device(&pdev->dev))
|
||||||
return msm_vidc_remove_video_device(pdev);
|
return msm_vidc_remove_video_device(pdev);
|
||||||
} else if (of_device_is_compatible(pdev->dev.of_node,
|
else if (is_video_context_bank_device(&pdev->dev))
|
||||||
"qcom,msm-vidc,context-bank")) {
|
|
||||||
return msm_vidc_remove_context_bank(pdev);
|
return msm_vidc_remove_context_bank(pdev);
|
||||||
}
|
|
||||||
|
|
||||||
/* How did we end up here? */
|
/* How did we end up here? */
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
@@ -539,7 +636,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
|
|||||||
struct device_node *child = NULL;
|
struct device_node *child = NULL;
|
||||||
int sub_device_count = 0, nr = BASE_DEVICE_NUMBER;
|
int sub_device_count = 0, nr = BASE_DEVICE_NUMBER;
|
||||||
|
|
||||||
d_vpr_h("%s()\n", __func__);
|
d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
|
||||||
|
|
||||||
rc = msm_vidc_vmem_alloc(sizeof(*core), (void **)&core, __func__);
|
rc = msm_vidc_vmem_alloc(sizeof(*core), (void **)&core, __func__);
|
||||||
if (rc)
|
if (rc)
|
||||||
@@ -559,13 +656,6 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
|
|||||||
goto init_core_failed;
|
goto init_core_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = msm_vidc_init_dt(pdev);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("%s: init dt failed with %d\n", __func__, rc);
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto init_dt_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_vidc_init_platform(pdev);
|
rc = msm_vidc_init_platform(pdev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
|
d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
|
||||||
@@ -573,16 +663,16 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
|
|||||||
goto init_plat_failed;
|
goto init_plat_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = msm_vidc_init_irq(core);
|
rc = msm_vidc_init_resources(core);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: init irq failed with %d\n", __func__, rc);
|
d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
|
||||||
goto init_irq_failed;
|
goto init_res_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = msm_vidc_init_core_caps(core);
|
rc = msm_vidc_init_core_caps(core);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
|
d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
|
||||||
goto init_core_caps_fail;
|
goto init_res_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = msm_vidc_init_instance_caps(core);
|
rc = msm_vidc_init_instance_caps(core);
|
||||||
@@ -659,8 +749,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
|
|||||||
/*
|
/*
|
||||||
* Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
|
* Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
|
||||||
* When msm_vidc_probe is called for each sub-device, parse the
|
* When msm_vidc_probe is called for each sub-device, parse the
|
||||||
* context-bank details and store it in core->resources.context_banks
|
* context-bank details.
|
||||||
* list.
|
|
||||||
*/
|
*/
|
||||||
rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
|
rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
|
||||||
&pdev->dev);
|
&pdev->dev);
|
||||||
@@ -698,13 +787,9 @@ init_group_failed:
|
|||||||
msm_vidc_deinit_instance_caps(core);
|
msm_vidc_deinit_instance_caps(core);
|
||||||
init_inst_caps_fail:
|
init_inst_caps_fail:
|
||||||
msm_vidc_deinit_core_caps(core);
|
msm_vidc_deinit_core_caps(core);
|
||||||
init_core_caps_fail:
|
init_res_failed:
|
||||||
msm_vidc_deinit_irq(core);
|
|
||||||
init_irq_failed:
|
|
||||||
msm_vidc_deinit_platform(pdev);
|
msm_vidc_deinit_platform(pdev);
|
||||||
init_plat_failed:
|
init_plat_failed:
|
||||||
msm_vidc_deinit_dt(pdev);
|
|
||||||
init_dt_failed:
|
|
||||||
msm_vidc_deinitialize_core(core);
|
msm_vidc_deinitialize_core(core);
|
||||||
init_core_failed:
|
init_core_failed:
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
@@ -717,13 +802,7 @@ init_core_failed:
|
|||||||
|
|
||||||
static int msm_vidc_probe_context_bank(struct platform_device *pdev)
|
static int msm_vidc_probe_context_bank(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
|
||||||
|
|
||||||
d_vpr_h("%s()\n", __func__);
|
|
||||||
|
|
||||||
rc = msm_vidc_read_context_bank_resources_from_dt(pdev);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return component_add(&pdev->dev, &msm_vidc_component_cb_ops);
|
return component_add(&pdev->dev, &msm_vidc_component_cb_ops);
|
||||||
}
|
}
|
||||||
@@ -737,12 +816,10 @@ static int msm_vidc_probe(struct platform_device *pdev)
|
|||||||
* the end of the probe function after msm-vidc device probe is
|
* the end of the probe function after msm-vidc device probe is
|
||||||
* completed. Return immediately after completing sub-device probe.
|
* completed. Return immediately after completing sub-device probe.
|
||||||
*/
|
*/
|
||||||
if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-vidc")) {
|
if (is_video_device(&pdev->dev))
|
||||||
return msm_vidc_probe_video_device(pdev);
|
return msm_vidc_probe_video_device(pdev);
|
||||||
} else if (of_device_is_compatible(pdev->dev.of_node,
|
else if (is_video_context_bank_device(&pdev->dev))
|
||||||
"qcom,msm-vidc,context-bank")) {
|
|
||||||
return msm_vidc_probe_context_bank(pdev);
|
return msm_vidc_probe_context_bank(pdev);
|
||||||
}
|
|
||||||
|
|
||||||
/* How did we end up here? */
|
/* How did we end up here? */
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
@@ -760,8 +837,7 @@ static int msm_vidc_pm_suspend(struct device *dev)
|
|||||||
* - not the main device. We don't support power management on
|
* - not the main device. We don't support power management on
|
||||||
* subdevices (e.g. context banks)
|
* subdevices (e.g. context banks)
|
||||||
*/
|
*/
|
||||||
if (!dev || !dev->driver ||
|
if (!dev || !dev->driver || !is_video_device(dev))
|
||||||
!of_device_is_compatible(dev->of_node, "qcom,msm-vidc"))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
core = dev_get_drvdata(dev);
|
core = dev_get_drvdata(dev);
|
||||||
@@ -792,8 +868,7 @@ static int msm_vidc_pm_resume(struct device *dev)
|
|||||||
* - not the main device. We don't support power management on
|
* - not the main device. We don't support power management on
|
||||||
* subdevices (e.g. context banks)
|
* subdevices (e.g. context banks)
|
||||||
*/
|
*/
|
||||||
if (!dev || !dev->driver ||
|
if (!dev || !dev->driver || !is_video_device(dev))
|
||||||
!of_device_is_compatible(dev->of_node, "qcom,msm-vidc"))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
core = dev_get_drvdata(dev);
|
core = dev_get_drvdata(dev);
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
#include "msm_venc.h"
|
#include "msm_venc.h"
|
||||||
#include "msm_vidc_debug.h"
|
#include "msm_vidc_debug.h"
|
||||||
#include "msm_vidc_control.h"
|
#include "msm_vidc_control.h"
|
||||||
#include "msm_vidc_dt.h"
|
#include "msm_vidc_platform.h"
|
||||||
|
|
||||||
extern struct msm_vidc_core *g_core;
|
extern struct msm_vidc_core *g_core;
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ void *msm_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
|
|||||||
|
|
||||||
buf->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
|
buf->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
|
||||||
buf->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP;
|
buf->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP;
|
||||||
if (core->dt->sys_cache_present)
|
if (is_sys_cache_present(core))
|
||||||
buf->attach->dma_map_attrs |=
|
buf->attach->dma_map_attrs |=
|
||||||
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
|
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@
|
|||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/qcom_scm.h>
|
#include <linux/qcom_scm.h>
|
||||||
#include <linux/soc/qcom/mdt_loader.h>
|
#include <linux/soc/qcom/mdt_loader.h>
|
||||||
|
#include <linux/soc/qcom/llcc-qcom.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
|
|
||||||
#include "venus_hfi.h"
|
#include "venus_hfi.h"
|
||||||
@@ -63,11 +64,6 @@ bool __core_in_valid_state(struct msm_vidc_core *core)
|
|||||||
return core->state != MSM_VIDC_CORE_DEINIT;
|
return core->state != MSM_VIDC_CORE_DEINIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_sys_cache_present(struct msm_vidc_core *core)
|
|
||||||
{
|
|
||||||
return core->dt->sys_cache_present;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool __valdiate_session(struct msm_vidc_core *core,
|
static bool __valdiate_session(struct msm_vidc_core *core,
|
||||||
struct msm_vidc_inst *inst, const char *func)
|
struct msm_vidc_inst *inst, const char *func)
|
||||||
{
|
{
|
||||||
@@ -394,7 +390,7 @@ static int __release_subcaches(struct msm_vidc_core *core)
|
|||||||
if (msm_vidc_syscache_disable || !is_sys_cache_present(core))
|
if (msm_vidc_syscache_disable || !is_sys_cache_present(core))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!core->dt->sys_cache_res_set) {
|
if (!core->resource->subcache_set.set_to_fw) {
|
||||||
d_vpr_h("Subcaches not set to Venus\n");
|
d_vpr_h("Subcaches not set to Venus\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -409,22 +405,23 @@ static int __release_subcaches(struct msm_vidc_core *core)
|
|||||||
buf.flags = HFI_BUF_HOST_FLAG_RELEASE;
|
buf.flags = HFI_BUF_HOST_FLAG_RELEASE;
|
||||||
|
|
||||||
venus_hfi_for_each_subcache_reverse(core, sinfo) {
|
venus_hfi_for_each_subcache_reverse(core, sinfo) {
|
||||||
if (sinfo->isactive) {
|
if (!sinfo->isactive)
|
||||||
buf.index = sinfo->subcache->slice_id;
|
continue;
|
||||||
buf.buffer_size = sinfo->subcache->slice_size;
|
|
||||||
|
|
||||||
rc = hfi_create_packet(core->packet,
|
buf.index = sinfo->subcache->slice_id;
|
||||||
core->packet_size,
|
buf.buffer_size = sinfo->subcache->slice_size;
|
||||||
HFI_CMD_BUFFER,
|
|
||||||
HFI_BUF_HOST_FLAG_NONE,
|
rc = hfi_create_packet(core->packet,
|
||||||
HFI_PAYLOAD_STRUCTURE,
|
core->packet_size,
|
||||||
HFI_PORT_NONE,
|
HFI_CMD_BUFFER,
|
||||||
core->packet_id++,
|
HFI_BUF_HOST_FLAG_NONE,
|
||||||
&buf,
|
HFI_PAYLOAD_STRUCTURE,
|
||||||
sizeof(buf));
|
HFI_PORT_NONE,
|
||||||
if (rc)
|
core->packet_id++,
|
||||||
return rc;
|
&buf,
|
||||||
}
|
sizeof(buf));
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set resource to Venus for activated subcaches */
|
/* Set resource to Venus for activated subcaches */
|
||||||
@@ -433,15 +430,14 @@ static int __release_subcaches(struct msm_vidc_core *core)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
venus_hfi_for_each_subcache_reverse(core, sinfo) {
|
venus_hfi_for_each_subcache_reverse(core, sinfo) {
|
||||||
if (sinfo->isactive) {
|
if (!sinfo->isactive)
|
||||||
sinfo->isset = false;
|
continue;
|
||||||
d_vpr_h("Release Subcache id %d size %lu done\n",
|
|
||||||
sinfo->subcache->slice_id,
|
|
||||||
sinfo->subcache->slice_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core->dt->sys_cache_res_set = false;
|
d_vpr_h("%s: release Subcache id %d size %lu done\n",
|
||||||
|
__func__, sinfo->subcache->slice_id,
|
||||||
|
sinfo->subcache->slice_size);
|
||||||
|
}
|
||||||
|
core->resource->subcache_set.set_to_fw = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -458,7 +454,7 @@ static int __set_subcaches(struct msm_vidc_core *core)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core->dt->sys_cache_res_set) {
|
if (core->resource->subcache_set.set_to_fw) {
|
||||||
d_vpr_h("Subcaches already set to Venus\n");
|
d_vpr_h("Subcaches already set to Venus\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -473,22 +469,22 @@ static int __set_subcaches(struct msm_vidc_core *core)
|
|||||||
buf.flags = HFI_BUF_HOST_FLAG_NONE;
|
buf.flags = HFI_BUF_HOST_FLAG_NONE;
|
||||||
|
|
||||||
venus_hfi_for_each_subcache(core, sinfo) {
|
venus_hfi_for_each_subcache(core, sinfo) {
|
||||||
if (sinfo->isactive) {
|
if (!sinfo->isactive)
|
||||||
buf.index = sinfo->subcache->slice_id;
|
continue;
|
||||||
buf.buffer_size = sinfo->subcache->slice_size;
|
buf.index = sinfo->subcache->slice_id;
|
||||||
|
buf.buffer_size = sinfo->subcache->slice_size;
|
||||||
|
|
||||||
rc = hfi_create_packet(core->packet,
|
rc = hfi_create_packet(core->packet,
|
||||||
core->packet_size,
|
core->packet_size,
|
||||||
HFI_CMD_BUFFER,
|
HFI_CMD_BUFFER,
|
||||||
HFI_BUF_HOST_FLAG_NONE,
|
HFI_BUF_HOST_FLAG_NONE,
|
||||||
HFI_PAYLOAD_STRUCTURE,
|
HFI_PAYLOAD_STRUCTURE,
|
||||||
HFI_PORT_NONE,
|
HFI_PORT_NONE,
|
||||||
core->packet_id++,
|
core->packet_id++,
|
||||||
&buf,
|
&buf,
|
||||||
sizeof(buf));
|
sizeof(buf));
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_fail_set_subacaches;
|
goto err_fail_set_subacaches;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set resource to Venus for activated subcaches */
|
/* Set resource to Venus for activated subcaches */
|
||||||
@@ -497,15 +493,13 @@ static int __set_subcaches(struct msm_vidc_core *core)
|
|||||||
goto err_fail_set_subacaches;
|
goto err_fail_set_subacaches;
|
||||||
|
|
||||||
venus_hfi_for_each_subcache(core, sinfo) {
|
venus_hfi_for_each_subcache(core, sinfo) {
|
||||||
if (sinfo->isactive) {
|
if (!sinfo->isactive)
|
||||||
sinfo->isset = true;
|
continue;
|
||||||
d_vpr_h("Set Subcache id %d size %lu done\n",
|
d_vpr_h("%s: set Subcache id %d size %lu done\n",
|
||||||
sinfo->subcache->slice_id,
|
__func__, sinfo->subcache->slice_id,
|
||||||
sinfo->subcache->slice_size);
|
sinfo->subcache->slice_size);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
core->resource->subcache_set.set_to_fw = true;
|
||||||
core->dt->sys_cache_res_set = true;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -699,16 +693,10 @@ int __load_fw(struct msm_vidc_core *core)
|
|||||||
core->cpu_watchdog = false;
|
core->cpu_watchdog = false;
|
||||||
|
|
||||||
trace_msm_v4l2_vidc_fw_load("START");
|
trace_msm_v4l2_vidc_fw_load("START");
|
||||||
rc = res_ops->get(core);
|
|
||||||
if (rc) {
|
|
||||||
d_vpr_e("%s: Failed to get resources: %d\n", __func__, rc);
|
|
||||||
goto fail_init_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = __venus_power_on(core);
|
rc = __venus_power_on(core);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: power on failed\n", __func__);
|
d_vpr_e("%s: power on failed\n", __func__);
|
||||||
goto fail_venus_power_on;
|
goto fail_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fw_load(core);
|
rc = fw_load(core);
|
||||||
@@ -727,25 +715,21 @@ int __load_fw(struct msm_vidc_core *core)
|
|||||||
return rc;
|
return rc;
|
||||||
fail_load_fw:
|
fail_load_fw:
|
||||||
__venus_power_off(core);
|
__venus_power_off(core);
|
||||||
fail_venus_power_on:
|
fail_power:
|
||||||
res_ops->put(core);
|
|
||||||
fail_init_res:
|
|
||||||
trace_msm_v4l2_vidc_fw_load("END");
|
trace_msm_v4l2_vidc_fw_load("END");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __unload_fw(struct msm_vidc_core *core)
|
void __unload_fw(struct msm_vidc_core *core)
|
||||||
{
|
{
|
||||||
const struct msm_vidc_resources_ops *res_ops = core->res_ops;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!core->dt->fw_cookie)
|
if (!core->resource->fw_cookie)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cancel_delayed_work(&core->pm_work);
|
cancel_delayed_work(&core->pm_work);
|
||||||
rc = fw_unload(core);
|
rc = fw_unload(core);
|
||||||
__venus_power_off(core);
|
__venus_power_off(core);
|
||||||
res_ops->put(core);
|
|
||||||
|
|
||||||
core->cpu_watchdog = false;
|
core->cpu_watchdog = false;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user