diff --git a/driver/platform/common/inc/msm_vidc_platform.h b/driver/platform/common/inc/msm_vidc_platform.h index 2468ff8cba..66738f520a 100644 --- a/driver/platform/common/inc/msm_vidc_platform.h +++ b/driver/platform/common/inc/msm_vidc_platform.h @@ -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_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 { u32 v4l2_codec; enum msm_vidc_codec_type vidc_codec; @@ -112,16 +167,6 @@ struct msm_vidc_efuse_data { 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 codec_info *codec_info; u32 codec_info_size; @@ -136,6 +181,26 @@ struct msm_vidc_format_capability { }; 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; u32 core_data_size; 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; u32 inst_cap_dependency_data_size; struct msm_vidc_csc_coeff csc_data; - struct msm_vidc_ubwc_config_data *ubwc_config; struct msm_vidc_efuse_data *efuse_data; unsigned int efuse_data_size; unsigned int sku_version; @@ -155,9 +219,18 @@ struct msm_vidc_platform { 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_deinit_platform(struct platform_device *pdev); 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_ diff --git a/driver/platform/common/src/msm_vidc_platform.c b/driver/platform/common/src/msm_vidc_platform.c index f3fc3de4a6..169f61c04c 100644 --- a/driver/platform/common/src/msm_vidc_platform.c +++ b/driver/platform/common/src/msm_vidc_platform.c @@ -5,7 +5,8 @@ */ #include -#include +#include +#include #include "msm_vidc_platform.h" #include "msm_vidc_debug.h" @@ -13,7 +14,6 @@ #include "msm_vidc_vb2.h" #include "msm_vidc_control.h" #include "msm_vidc_core.h" -#include "msm_vidc_dt.h" #include "msm_vidc_debug.h" #include "msm_vidc_internal.h" #if defined(CONFIG_MSM_VIDC_WAIPIO) @@ -25,9 +25,6 @@ #if defined(CONFIG_MSM_VIDC_PINEAPPLE) #include "msm_vidc_pineapple.h" #endif -#if defined(CONFIG_MSM_VIDC_PINEAPPLE) -#include "msm_vidc_pineapple.h" -#endif #if defined(CONFIG_MSM_VIDC_ANORAK) #include "msm_vidc_anorak.h" #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__); #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); if (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 #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); if (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 #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); if (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 #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); if (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__); #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); if (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 #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); if (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 #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); if (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 #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); if (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__); #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); if (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 #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); if (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 #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); if (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 (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); if (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 #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); if (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 #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); if (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; } - -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]); -} diff --git a/driver/platform/kalama/src/msm_vidc_kalama.c b/driver/platform/kalama/src/msm_vidc_kalama.c index f71cda4ada..8b0196d7ce 100644 --- a/driver/platform/kalama/src/msm_vidc_kalama.c +++ b/driver/platform/kalama/src/msm_vidc_kalama.c @@ -4,9 +4,13 @@ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. */ -#include +#include +#include +#include +#include #include + #include "msm_vidc_kalama.h" #include "msm_vidc_platform.h" #include "msm_vidc_debug.h" @@ -315,7 +319,6 @@ static struct msm_platform_core_capability core_data_kalama[] = { {AV_SYNC_WINDOW_SIZE, 40}, {NON_FATAL_FAULTS, 1}, {ENC_AUTO_FRAMERATE, 1}, - {MMRM, 1}, {DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING}, {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), }; +/* 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 = { + /* 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_size = ARRAY_SIZE(core_data_kalama), .inst_cap_data = instance_cap_data_kalama, @@ -2655,17 +2779,21 @@ int msm_vidc_kalama_check_ddr_type(void) 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; - if (!core || !core->platform) { + if (!core || !core->platform || !dev) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } 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(); if (rc) return rc; @@ -2677,7 +2805,7 @@ int msm_vidc_init_platform_kalama(struct msm_vidc_core *core, struct device *dev { int rc = 0; - rc = msm_vidc_init_data(core); + rc = msm_vidc_init_data(core, dev); if (rc) return rc; diff --git a/driver/variant/common/src/msm_vidc_variant.c b/driver/variant/common/src/msm_vidc_variant.c index fafdbaafcc..293099d4c7 100644 --- a/driver/variant/common/src/msm_vidc_variant.c +++ b/driver/variant/common/src/msm_vidc_variant.c @@ -9,8 +9,8 @@ #include "msm_vidc_core.h" #include "msm_vidc_debug.h" -#include "msm_vidc_dt.h" #include "msm_vidc_variant.h" +#include "msm_vidc_platform.h" 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; int rc = 0; - if (!core) { + if (!core || !core->resource) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } @@ -49,7 +49,7 @@ int __write_register(struct msm_vidc_core *core, u32 reg, u32 value) 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); base_addr += hwiosymaddr; 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; int rc = 0; - if (!core) { + if (!core || !core->resource) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } @@ -89,7 +89,7 @@ int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value, return -EINVAL; } - base_addr = core->register_base_addr; + base_addr = core->resource->register_base_addr; base_addr += reg; 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; u8 *base_addr; - if (!core || !value) { + if (!core || !core->resource || !value) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } @@ -126,7 +126,7 @@ int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value) return -EINVAL; } - base_addr = core->register_base_addr; + base_addr = core->resource->register_base_addr; *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; u8 *addr; - if (!core) { + if (!core || !core->resource) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } @@ -157,7 +157,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg, 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); /* @@ -167,7 +167,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg, rmb(); d_vpr_l( "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); 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) { - struct reg_set *reg_set; - int i, rc = 0; + const struct reg_preset_table *reg_prst; + 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"); return -EINVAL; } - reg_set = &core->dt->reg_set; - for (i = 0; i < reg_set->count; i++) { - rc = __write_register_masked(core, reg_set->reg_tbl[i].reg, - reg_set->reg_tbl[i].value, - reg_set->reg_tbl[i].mask); + reg_prst = core->platform->data.reg_prst_tbl; + prst_count = core->platform->data.reg_prst_tbl_size; + + /* skip if there is no preset reg available */ + 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) return rc; } diff --git a/driver/variant/iris3/src/msm_vidc_buffer_iris3.c b/driver/variant/iris3/src/msm_vidc_buffer_iris3.c index 6f844dbd58..5fb631f554 100644 --- a/driver/variant/iris3/src/msm_vidc_buffer_iris3.c +++ b/driver/variant/iris3/src/msm_vidc_buffer_iris3.c @@ -10,7 +10,6 @@ #include "msm_vidc_buffer.h" #include "msm_vidc_inst.h" #include "msm_vidc_core.h" -#include "msm_vidc_platform.h" #include "msm_vidc_driver.h" #include "msm_vidc_debug.h" #include "msm_media_info.h" diff --git a/driver/variant/iris3/src/msm_vidc_iris3.c b/driver/variant/iris3/src/msm_vidc_iris3.c index 0758d6cfe6..eaf023b3c5 100644 --- a/driver/variant/iris3/src/msm_vidc_iris3.c +++ b/driver/variant/iris3/src/msm_vidc_iris3.c @@ -12,7 +12,6 @@ #include "msm_vidc_core.h" #include "msm_vidc_driver.h" #include "msm_vidc_control.h" -#include "msm_vidc_dt.h" #include "msm_vidc_internal.h" #include "msm_vidc_buffer.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__); 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->power_enabled = false; @@ -551,7 +550,7 @@ fail_regulator: static int __power_on_iris3(struct msm_vidc_core *core) { 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; int rc = 0; @@ -579,9 +578,9 @@ static int __power_on_iris3(struct msm_vidc_core *core) /* video controller and hardware powered on successfully */ 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 : - clk_tbl[0].clock_rate; + freq_tbl[0].freq; rc = res_ops->set_clks(core, freq); if (rc) { @@ -596,7 +595,7 @@ static int __power_on_iris3(struct msm_vidc_core *core) __interrupt_init_iris3(core); core->intr_status = 0; - enable_irq(core->dt->irq); + enable_irq(core->resource->irq); return rc; diff --git a/driver/variant/iris3/src/msm_vidc_power_iris3.c b/driver/variant/iris3/src/msm_vidc_power_iris3.c index e9f34df721..5e42551ecb 100644 --- a/driver/variant/iris3/src/msm_vidc_power_iris3.c +++ b/driver/variant/iris3/src/msm_vidc_power_iris3.c @@ -9,7 +9,6 @@ #include "msm_vidc_core.h" #include "msm_vidc_driver.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) { @@ -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__); return freq; } - 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__); 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_1stage = 100; u32 width, height; - u32 bitrate_entry, freq_entry, frequency_table_value; - struct allowed_clock_rates_table *allowed_clks_tbl; + u32 bitrate_entry, freq_entry, freq_tbl_value; + struct frequency_table *freq_tbl; struct v4l2_format *out_f = &inst->fmts[OUTPUT_PORT]; 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; - allowed_clks_tbl = core->dt->allowed_clks_tbl; - frequency_table_value = allowed_clks_tbl[freq_entry].clock_rate / 1000000; + freq_tbl = core->resource->freq_set.freq_tbl; + freq_tbl_value = freq_tbl[freq_entry].freq / 1000000; 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) { 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 * index 0 is TURBO, index 1 is NOM clock rate */ - if (core->dt->allowed_clks_tbl_size >= 2 && - freq > core->dt->allowed_clks_tbl[1].clock_rate) - freq = core->dt->allowed_clks_tbl[1].clock_rate; + if (core->resource->freq_set.count >= 2 && + freq > core->resource->freq_set.freq_tbl[1].freq) + 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", diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index 884ae61efa..0623bdfbe9 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -74,9 +74,8 @@ struct msm_vidc_core { char fw_version[MAX_NAME_LENGTH]; enum msm_vidc_core_state state; struct mutex lock; - struct msm_vidc_dt *dt; + struct msm_vidc_resource *resource; struct msm_vidc_platform *platform; - u8 __iomem *register_base_addr; u32 intr_status; u32 spur_count; u32 reg_count; diff --git a/driver/vidc/inc/msm_vidc_dt.h b/driver/vidc/inc/msm_vidc_dt.h index dd68affc5b..8045727ae8 100644 --- a/driver/vidc/inc/msm_vidc_dt.h +++ b/driver/vidc/inc/msm_vidc_dt.h @@ -8,228 +8,5 @@ #include #include -#ifdef CONFIG_MSM_MMRM -#include -#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_ diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index f8fb7bc9f9..3144b5b14e 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -244,6 +244,7 @@ enum msm_vidc_buffer_region { MSM_VIDC_SECURE_PIXEL, MSM_VIDC_SECURE_NONPIXEL, MSM_VIDC_SECURE_BITSTREAM, + MSM_VIDC_REGION_MAX, }; enum msm_vidc_port_type { @@ -374,7 +375,6 @@ enum msm_vidc_core_capability_type { CLK_FREQ_THRESHOLD, NON_FATAL_FAULTS, ENC_AUTO_FRAMERATE, - MMRM, DEVICE_CAPS, SUPPORTS_REQUESTS, CORE_CAP_MAX, diff --git a/driver/vidc/inc/msm_vidc_memory.h b/driver/vidc/inc/msm_vidc_memory.h index 2ee8517aed..c01dae35f1 100644 --- a/driver/vidc/inc/msm_vidc_memory.h +++ b/driver/vidc/inc/msm_vidc_memory.h @@ -7,7 +7,6 @@ #define _MSM_VIDC_MEMORY_H_ #include "msm_vidc_internal.h" -#include "msm_vidc_dt.h" struct msm_vidc_core; struct msm_vidc_inst; diff --git a/driver/vidc/inc/resources.h b/driver/vidc/inc/resources.h index d32d457182..9c2f926a2c 100644 --- a/driver/vidc/inc/resources.h +++ b/driver/vidc/inc/resources.h @@ -6,11 +6,199 @@ #ifndef _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; +/* + * 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 { - int (*get)(struct msm_vidc_core *core); - void (*put)(struct msm_vidc_core *core); + int (*init)(struct msm_vidc_core *core); int (*reset_bridge)(struct msm_vidc_core *core); diff --git a/driver/vidc/src/firmware.c b/driver/vidc/src/firmware.c index 963eb7a5f3..b4051a76f2 100644 --- a/driver/vidc/src/firmware.c +++ b/driver/vidc/src/firmware.c @@ -12,9 +12,9 @@ #include "msm_vidc_core.h" #include "msm_vidc_debug.h" -#include "msm_vidc_dt.h" #include "msm_vidc_events.h" #include "firmware.h" +#include "msm_vidc_platform.h" #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_size = 0x0; - list_for_each_entry(cb, &core->dt->context_banks, list) { - if (!strcmp(cb->name, "venus_ns")) { + venus_hfi_for_each_context_bank(core, cb) { + if (cb->region == MSM_VIDC_NON_SECURE) { memprot.cp_size = cb->addr_range.start; d_vpr_h("%s: memprot.cp_size: %#x\n", __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_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, memprot.cp_nonpixel_start, memprot.cp_nonpixel_size); - if (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; const struct firmware *firmware = NULL; + struct msm_vidc_core *core; char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 }; struct device_node *node = NULL; 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__); 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); - rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id); - if (rc) { - d_vpr_e("%s: failed to read \"pas-id\". error %d\n", - __func__, rc); - goto exit; - } + pas_id = core->platform->data.pas_id; node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); if (!node) { @@ -182,13 +184,13 @@ int fw_load(struct msm_vidc_core *core) { int rc; - if (!core->dt->fw_cookie) { - core->dt->fw_cookie = __load_fw_to_memory(core->pdev, - core->dt->fw_name); - if (core->dt->fw_cookie <= 0) { + if (!core->resource->fw_cookie) { + core->resource->fw_cookie = __load_fw_to_memory(core->pdev, + core->platform->data.fwname); + if (core->resource->fw_cookie <= 0) { d_vpr_e("%s: firmware download failed %d\n", - __func__, core->dt->fw_cookie); - core->dt->fw_cookie = 0; + __func__, core->resource->fw_cookie); + core->resource->fw_cookie = 0; return -ENOMEM; } } @@ -202,9 +204,9 @@ int fw_load(struct msm_vidc_core *core) return rc; fail_protect_mem: - if (core->dt->fw_cookie) - qcom_scm_pas_shutdown(core->dt->fw_cookie); - core->dt->fw_cookie = 0; + if (core->resource->fw_cookie) + qcom_scm_pas_shutdown(core->resource->fw_cookie); + core->resource->fw_cookie = 0; return rc; } @@ -212,14 +214,14 @@ int fw_unload(struct msm_vidc_core *core) { int ret; - if (!core->dt->fw_cookie) + if (!core->resource->fw_cookie) return -EINVAL; - ret = qcom_scm_pas_shutdown(core->dt->fw_cookie); + ret = qcom_scm_pas_shutdown(core->resource->fw_cookie); if (ret) d_vpr_e("Firmware unload failed rc=%d\n", ret); - core->dt->fw_cookie = 0; + core->resource->fw_cookie = 0; return ret; } diff --git a/driver/vidc/src/msm_vidc_debug.c b/driver/vidc/src/msm_vidc_debug.c index 81e6ee03ee..13ea7c374d 100644 --- a/driver/vidc/src/msm_vidc_debug.c +++ b/driver/vidc/src/msm_vidc_debug.c @@ -5,7 +5,6 @@ #define CREATE_TRACE_POINTS #include "msm_vidc_debug.h" #include "msm_vidc_driver.h" -#include "msm_vidc_dt.h" #include "msm_vidc.h" #include "msm_vidc_core.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; int rc = 0; - if (!core || !core->dt) { + if (!core || !core->resource) { d_vpr_e("%s: invalid params %pK\n", __func__, core); return 0; } @@ -226,10 +225,8 @@ static ssize_t core_info_read(struct file* file, char __user* buf, cur += write_str(cur, end - cur, "FW version : %s\n", core->fw_version); cur += write_str(cur, end - cur, - "register_base: 0x%x\n", core->dt->register_base); - cur += write_str(cur, end - cur, - "register_size: %u\n", core->dt->register_size); - cur += write_str(cur, end - cur, "irq: %u\n", core->dt->irq); + "register_base: 0x%x\n", core->resource->register_base_addr); + cur += write_str(cur, end - cur, "irq: %u\n", core->resource->irq); len = simple_read_from_buffer(buf, count, ppos, dbuf, cur - dbuf); diff --git a/driver/vidc/src/msm_vidc_dt.c b/driver/vidc/src/msm_vidc_dt.c index 114165890b..0266347170 100644 --- a/driver/vidc/src/msm_vidc_dt.c +++ b/driver/vidc/src/msm_vidc_dt.c @@ -7,976 +7,3 @@ #include #include #include - -#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; -} diff --git a/driver/vidc/src/msm_vidc_memory.c b/driver/vidc/src/msm_vidc_memory.c index 729b2195c2..06c81cd6ec 100644 --- a/driver/vidc/src/msm_vidc_memory.c +++ b/driver/vidc/src/msm_vidc_memory.c @@ -16,6 +16,7 @@ #include "msm_vidc_driver.h" #include "msm_vidc_core.h" #include "msm_vidc_events.h" +#include "msm_vidc_platform.h" #include "venus_hfi.h" #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, enum msm_vidc_buffer_region region) { - const char *name; 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)) - goto exit; + if (!region || region >= MSM_VIDC_REGION_MAX) { + d_vpr_e("Invalid region %#x\n", region); + return NULL; + } - if (buf_region_name[region].region != region) - goto exit; - - name = buf_region_name[region].name; - - list_for_each_entry(cb, &core->dt->context_banks, list) { - if (!strcmp(cb->name, name)) { + venus_hfi_for_each_context_bank(core, cb) { + if (cb->region == region) { match = cb; 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); 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) @@ -245,7 +230,7 @@ int msm_vidc_memory_map(struct msm_vidc_core *core, struct msm_vidc_map *map) * required buffer size */ 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 |= DMA_ATTR_IOMMU_USE_UPSTREAM_HINT; diff --git a/driver/vidc/src/msm_vidc_power.c b/driver/vidc/src/msm_vidc_power.c index 12841edb44..6a45130c9d 100644 --- a/driver/vidc/src/msm_vidc_power.c +++ b/driver/vidc/src/msm_vidc_power.c @@ -9,7 +9,6 @@ #include "msm_vidc_internal.h" #include "msm_vidc_inst.h" #include "msm_vidc_core.h" -#include "msm_vidc_dt.h" #include "msm_vidc_driver.h" #include "msm_vidc_platform.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) { struct msm_vidc_core* core; - struct allowed_clock_rates_table *allowed_clks_tbl; + struct frequency_table *freq_tbl; u64 freq = 0; if (!inst || !inst->core) { @@ -100,12 +99,14 @@ u64 msm_vidc_max_freq(struct msm_vidc_inst *inst) return freq; } 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; } - allowed_clks_tbl = core->dt->allowed_clks_tbl; - freq = allowed_clks_tbl[0].clock_rate; + freq_tbl = core->resource->freq_set.freq_tbl; + freq = freq_tbl[0].freq; i_vpr_l(inst, "%s: rate = %llu\n", __func__, freq); return freq; @@ -267,8 +268,8 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst) return -EINVAL; } core = inst->core; - if (!core->dt) { - i_vpr_e(inst, "%s: invalid dt params\n", __func__); + if (!core->resource) { + i_vpr_e(inst, "%s: invalid resource params\n", __func__); return -EINVAL; } 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; - if (core->dt->sys_cache_res_set) + if (core->resource->subcache_set.set_to_fw) vote_data->use_sys_cache = true; vote_data->num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value; fill_dynamic_stats(inst, vote_data); @@ -382,8 +383,10 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst) return -EINVAL; } 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; } @@ -422,8 +425,8 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst) * keep checking from lowest to highest rate until * table rate >= requested rate */ - for (i = core->dt->allowed_clks_tbl_size - 1; i >= 0; i--) { - rate = core->dt->allowed_clks_tbl[i].clock_rate; + for (i = core->resource->freq_set.count - 1; i >= 0; i--) { + rate = core->resource->freq_set.freq_tbl[i].freq; if (rate >= freq) break; } @@ -431,10 +434,10 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst) i = 0; if (increment) { 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) { - if (i < (int) (core->dt->allowed_clks_tbl_size - 1)) - rate = core->dt->allowed_clks_tbl[i + 1].clock_rate; + if (i < (int) (core->platform->data.freq_tbl_size - 1)) + rate = core->resource->freq_set.freq_tbl[i + 1].freq; } core->power.clk_freq = (u32)rate; diff --git a/driver/vidc/src/msm_vidc_probe.c b/driver/vidc/src/msm_vidc_probe.c index be446d4129..147e85d3d0 100644 --- a/driver/vidc/src/msm_vidc_probe.c +++ b/driver/vidc/src/msm_vidc_probe.c @@ -10,11 +10,15 @@ #include #include #include +#include +#include +#ifdef CONFIG_MSM_MMRM +#include +#endif #include "msm_vidc_internal.h" #include "msm_vidc_debug.h" #include "msm_vidc_driver.h" -#include "msm_vidc_dt.h" #include "msm_vidc_platform.h" #include "msm_vidc_core.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 "@" 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; - - if (!core || !core->pdev || !core->dt) { - d_vpr_e("%s: invalid params\n", __func__); - 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; + return !!(of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc") || + of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") || + of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2") || + of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")); } -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; - struct msm_vidc_dt *dt; + return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-pxl") || + 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__); return -EINVAL; } - dt = core->dt; + res_ops = core->res_ops; - core->register_base_addr = devm_ioremap(&core->pdev->dev, - dt->register_base, dt->register_size); - if (!core->register_base_addr) { - d_vpr_e("could not map reg addr %pa of size %d\n", - &dt->register_base, dt->register_size); - rc = -EINVAL; - goto exit; + res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL); + if (!res) { + d_vpr_e("%s: failed to alloc memory for resource\n", __func__); + return -ENOMEM; } + res->core = core; + core->resource = res; - rc = devm_request_threaded_irq(&core->pdev->dev, dt->irq, venus_hfi_isr, - venus_hfi_isr_handler, IRQF_TRIGGER_HIGH, "msm-vidc", core); + rc = res_ops->init(core); if (rc) { - d_vpr_e("%s: Failed to allocate venus IRQ\n", __func__); - goto exit; + d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc); + 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; - -exit: - msm_vidc_deinit_irq(core); - return rc; } 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 * driver possibly not probed yet or not the main device. */ - if (!dev || !dev->driver || - !of_device_is_compatible(dev->of_node, "qcom,msm-vidc")) + if (!dev || !dev->driver) return 0; 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[] = { - {.compatible = "qcom,msm-vidc"}, - {.compatible = "qcom,msm-vidc,context-bank"}, + {.compatible = "qcom,sm8450-vidc"}, + {.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 }; 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; - d_vpr_h("%s()\n", __func__); + d_vpr_h("%s: domain %d\n", __func__, type); if (type == MSM_VIDC_DECODER) index = 0; @@ -163,7 +161,7 @@ static int msm_vidc_register_video_device(struct msm_vidc_core *core, int rc = 0; int index, media_index; - d_vpr_h("%s()\n", __func__); + d_vpr_h("%s: domain %d\n", __func__, type); if (!core || !core->capabilities) { 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; - if (!core || !core->capabilities) { + if (!core || !core->platform) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - if (!core->capabilities[MMRM].value) + if (!is_mmrm_supported(core)) goto exit; if (!mmrm_client_check_scaling_supported(MMRM_CLIENT_CLOCK, 0)) { d_vpr_e("%s: MMRM not supported\n", __func__); - core->capabilities[MMRM].value = 0; + core->platform->data.supports_mmrm = 0; } 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; } #else 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__); return -EINVAL; } - core->capabilities[MMRM].value = 0; + core->platform->data.supports_mmrm = 0; return 0; } @@ -358,6 +356,83 @@ exit: 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) { 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, struct device *master, void *data) { - d_vpr_h("%s(): %s\n", __func__, dev_name(dev)); - return 0; + struct msm_vidc_core *core; + 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, @@ -391,7 +493,7 @@ static int msm_vidc_component_bind(struct device *dev) rc = component_bind_all(dev, core); 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; } @@ -464,7 +566,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev) 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 * 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_core_caps(core); - msm_vidc_deinit_irq(core); msm_vidc_deinit_platform(pdev); - msm_vidc_deinit_dt(pdev); msm_vidc_deinitialize_core(core); 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) { - d_vpr_h("%s(): Detached %s and destroyed mapping\n", - __func__, dev_name(&pdev->dev)); + d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev)); 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 * 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); - } else if (of_device_is_compatible(pdev->dev.of_node, - "qcom,msm-vidc,context-bank")) { + else if (is_video_context_bank_device(&pdev->dev)) return msm_vidc_remove_context_bank(pdev); - } /* How did we end up here? */ WARN_ON(1); @@ -539,7 +636,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev) struct device_node *child = NULL; 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__); if (rc) @@ -559,13 +656,6 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev) 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); if (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; } - rc = msm_vidc_init_irq(core); + rc = msm_vidc_init_resources(core); if (rc) { - d_vpr_e("%s: init irq failed with %d\n", __func__, rc); - goto init_irq_failed; + d_vpr_e("%s: init resource failed with %d\n", __func__, rc); + goto init_res_failed; } rc = msm_vidc_init_core_caps(core); if (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); @@ -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. * When msm_vidc_probe is called for each sub-device, parse the - * context-bank details and store it in core->resources.context_banks - * list. + * context-bank details. */ rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL, &pdev->dev); @@ -698,13 +787,9 @@ init_group_failed: msm_vidc_deinit_instance_caps(core); init_inst_caps_fail: msm_vidc_deinit_core_caps(core); -init_core_caps_fail: - msm_vidc_deinit_irq(core); -init_irq_failed: +init_res_failed: msm_vidc_deinit_platform(pdev); init_plat_failed: - msm_vidc_deinit_dt(pdev); -init_dt_failed: msm_vidc_deinitialize_core(core); init_core_failed: dev_set_drvdata(&pdev->dev, NULL); @@ -717,13 +802,7 @@ init_core_failed: static int msm_vidc_probe_context_bank(struct platform_device *pdev) { - int rc = 0; - - d_vpr_h("%s()\n", __func__); - - rc = msm_vidc_read_context_bank_resources_from_dt(pdev); - if (rc) - return rc; + d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev)); 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 * 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); - } else if (of_device_is_compatible(pdev->dev.of_node, - "qcom,msm-vidc,context-bank")) { + else if (is_video_context_bank_device(&pdev->dev)) return msm_vidc_probe_context_bank(pdev); - } /* How did we end up here? */ 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 * subdevices (e.g. context banks) */ - if (!dev || !dev->driver || - !of_device_is_compatible(dev->of_node, "qcom,msm-vidc")) + if (!dev || !dev->driver || !is_video_device(dev)) return 0; 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 * subdevices (e.g. context banks) */ - if (!dev || !dev->driver || - !of_device_is_compatible(dev->of_node, "qcom,msm-vidc")) + if (!dev || !dev->driver || !is_video_device(dev)) return 0; core = dev_get_drvdata(dev); diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index bfeafa8480..f74565326d 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -16,7 +16,7 @@ #include "msm_venc.h" #include "msm_vidc_debug.h" #include "msm_vidc_control.h" -#include "msm_vidc_dt.h" +#include "msm_vidc_platform.h" 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_DELAYED_UNMAP; - if (core->dt->sys_cache_present) + if (is_sys_cache_present(core)) buf->attach->dma_map_attrs |= DMA_ATTR_IOMMU_USE_UPSTREAM_HINT; diff --git a/driver/vidc/src/resources.c b/driver/vidc/src/resources.c index 99d5db2abb..b1dcbd3ec6 100644 --- a/driver/vidc/src/resources.c +++ b/driver/vidc/src/resources.c @@ -4,14 +4,19 @@ */ /* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include #include +#include +#ifdef CONFIG_MSM_MMRM +#include +#endif #include "msm_vidc_core.h" #include "msm_vidc_debug.h" -#include "msm_vidc_dt.h" #include "msm_vidc_power.h" +#include "msm_vidc_platform.h" #include "venus_hfi.h" /* Less than 50MBps is treated as trivial BW change */ @@ -31,203 +36,611 @@ static void __fatal_error(bool fatal) WARN_ON(fatal); } -static bool is_sys_cache_present(struct msm_vidc_core *core) +static void devm_llcc_release(struct device *dev, void *res) { - return core->dt->sys_cache_present; + d_vpr_h("%s()\n", __func__); + llcc_slice_putd(*(struct llcc_slice_desc **)res); } -static void __deinit_clocks(struct msm_vidc_core *core) +static struct llcc_slice_desc *devm_llcc_get(struct device *dev, u32 id) { - struct clock_info *cl; + struct llcc_slice_desc **ptr, *llcc; - core->power.clk_freq = 0; - venus_hfi_for_each_clock_reverse(core, cl) { - if (cl->clk) { - clk_put(cl->clk); - cl->clk = NULL; - } + ptr = devres_alloc(devm_llcc_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + llcc = llcc_slice_getd(id); + if (!IS_ERR(llcc)) { + *ptr = llcc; + devres_add(dev, ptr); + } else { + devres_free(ptr); } + + return llcc; } -static int __init_clocks(struct msm_vidc_core *core) +#ifdef CONFIG_MSM_MMRM +static void devm_mmrm_release(struct device *dev, void *res) { - int rc = 0; - struct clock_info *cl = NULL; + d_vpr_h("%s()\n", __func__); + mmrm_client_deregister(*(struct mmrm_client **)res); +} - if (!core) { +static struct mmrm_client *devm_mmrm_get(struct device *dev, struct mmrm_client_desc *desc) +{ + struct mmrm_client **ptr, *mmrm; + + ptr = devres_alloc(devm_mmrm_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + mmrm = mmrm_client_register(desc); + if (!IS_ERR(mmrm)) { + *ptr = mmrm; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return mmrm; +} +#endif + +/* 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 freq_table *)b)->freq - + ((struct freq_table *)a)->freq; +} + +static int __init_register_base(struct msm_vidc_core *core) +{ + struct msm_vidc_resource *res; + + if (!core || !core->pdev || !core->resource) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + res = core->resource; - venus_hfi_for_each_clock(core, cl) { - d_vpr_h("%s: scalable? %d, count %d\n", - cl->name, cl->has_scaling, cl->count); + res->register_base_addr = devm_platform_ioremap_resource(core->pdev, 0); + if (IS_ERR(res->register_base_addr)) { + d_vpr_e("%s: map reg addr failed %d\n", + __func__, PTR_ERR(res->register_base_addr)); + return -EINVAL; } + d_vpr_h("%s: reg_base %#x\n", __func__, res->register_base_addr); - venus_hfi_for_each_clock(core, cl) { - if (!cl->clk) { - cl->clk = clk_get(&core->pdev->dev, cl->name); - if (IS_ERR_OR_NULL(cl->clk)) { - d_vpr_e("Failed to get clock: %s\n", cl->name); - rc = PTR_ERR(cl->clk) ? - PTR_ERR(cl->clk) : -EINVAL; - cl->clk = NULL; - goto err_clk_get; - } - } - } - core->power.clk_freq = 0; return 0; - -err_clk_get: - __deinit_clocks(core); - return rc; } -static int __handle_reset_clk(struct msm_vidc_core *core, - int reset_index, enum reset_state state) +static int __init_irq(struct msm_vidc_core *core) { + struct msm_vidc_resource *res; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)) + struct resource *kres; +#endif int rc = 0; - struct msm_vidc_dt *dt = core->dt; - struct reset_control *rst; - struct reset_set *rst_set = &dt->reset_set; - if (!rst_set->reset_tbl) - return 0; - - rst = rst_set->reset_tbl[reset_index].rst; - d_vpr_h("reset_clk: name %s reset_state %d rst %pK\n", - rst_set->reset_tbl[reset_index].name, state, rst); - - switch (state) { - case INIT: - if (rst) - goto skip_reset_init; - - rst = devm_reset_control_get(&core->pdev->dev, - rst_set->reset_tbl[reset_index].name); - if (IS_ERR(rst)) - rc = PTR_ERR(rst); - - rst_set->reset_tbl[reset_index].rst = rst; - break; - case ASSERT: - if (!rst) { - rc = PTR_ERR(rst); - goto failed_to_reset; - } - - rc = reset_control_assert(rst); - break; - case DEASSERT: - if (!rst) { - rc = PTR_ERR(rst); - goto failed_to_reset; - } - rc = reset_control_deassert(rst); - break; - default: - d_vpr_e("%s: invalid reset request\n", __func__); - if (rc) - goto failed_to_reset; - } - - return 0; - -skip_reset_init: -failed_to_reset: - return rc; -} - -static int __reset_ahb2axi_bridge(struct msm_vidc_core *core) -{ - int rc, i; - - if (!core) { + if (!core || !core->pdev || !core->resource) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + res = core->resource; - for (i = 0; i < core->dt->reset_set.count; i++) { - rc = __handle_reset_clk(core, i, ASSERT); - if (rc) { - d_vpr_e("failed to assert reset clocks\n"); - goto failed_to_reset; - } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)) + res->irq = platform_get_irq(core->pdev, 0); +#else + kres = platform_get_resource(core->pdev, IORESOURCE_IRQ, 0); + res->irq = kres ? kres->start : -1; +#endif + if (res->irq < 0) + d_vpr_e("%s: get irq failed, %d\n", __func__, res->irq); - /* wait for deassert */ - usleep_range(1000, 1100); + d_vpr_h("%s: irq %d\n", __func__, res->irq); + + rc = devm_request_threaded_irq(&core->pdev->dev, res->irq, venus_hfi_isr, + venus_hfi_isr_handler, IRQF_TRIGGER_HIGH, "msm-vidc", core); + if (rc) { + d_vpr_e("%s: Failed to allocate venus IRQ\n", __func__); + return rc; } + disable_irq_nosync(res->irq); - for (i = 0; i < core->dt->reset_set.count; i++) { - rc = __handle_reset_clk(core, i, DEASSERT); - if (rc) { - d_vpr_e("failed to deassert reset clocks\n"); - goto failed_to_reset; - } - } - - return 0; - -failed_to_reset: return rc; } -static void __deinit_bus(struct msm_vidc_core *core) -{ - struct bus_info *bus = NULL; - - if (!core) - return; - - core->power.bw_ddr = 0; - core->power.bw_llcc = 0; - - venus_hfi_for_each_bus_reverse(core, bus) { - if (!bus->path) - continue; - icc_put(bus->path); - bus->path = NULL; - } -} - static int __init_bus(struct msm_vidc_core *core) { - struct bus_info *bus = NULL; + const struct bw_table *bus_tbl; + struct bus_set *interconnects; + struct bus_info *binfo = NULL; + u32 bus_count = 0, cnt = 0; int rc = 0; - if (!core) { - d_vpr_e("%s: invalid param\n", __func__); + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + interconnects = &core->resource->bus_set; + + bus_tbl = core->platform->data.bw_tbl; + bus_count = core->platform->data.bw_tbl_size; + + if (!bus_tbl || !bus_count) { + d_vpr_e("%s: invalid bus tbl %#x or count %d\n", + __func__, bus_tbl, bus_count); return -EINVAL; } - venus_hfi_for_each_bus(core, bus) { - if (!strcmp(bus->name, "venus-llcc")) { + /* allocate bus_set */ + interconnects->bus_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*interconnects->bus_tbl) * bus_count, GFP_KERNEL); + if (!interconnects->bus_tbl) { + d_vpr_e("%s: failed to alloc memory for bus table\n", __func__); + return -ENOMEM; + } + interconnects->count = bus_count; + + /* populate bus field from platform data */ + for (cnt = 0; cnt < interconnects->count; cnt++) { + interconnects->bus_tbl[cnt].name = bus_tbl[cnt].name; + interconnects->bus_tbl[cnt].min_kbps = bus_tbl[cnt].min_kbps; + interconnects->bus_tbl[cnt].max_kbps = bus_tbl[cnt].max_kbps; + } + + /* print bus fields */ + venus_hfi_for_each_bus(core, binfo) { + d_vpr_h("%s: name %s min_kbps %u max_kbps %u\n", + __func__, binfo->name, binfo->min_kbps, binfo->max_kbps); + } + + /* get interconnect handle */ + venus_hfi_for_each_bus(core, binfo) { + if (!strcmp(binfo->name, "venus-llcc")) { if (msm_vidc_syscache_disable) { - d_vpr_h("Skipping LLC bus init: %s\n", - bus->name); + d_vpr_h("%s: skipping LLC bus init: %s\n", __func__, + binfo->name); continue; } } - bus->path = of_icc_get(bus->dev, bus->name); - if (IS_ERR_OR_NULL(bus->path)) { - rc = PTR_ERR(bus->path) ? - PTR_ERR(bus->path) : -EBADHANDLE; - - d_vpr_e("Failed to register bus %s: %d\n", - bus->name, rc); - bus->path = NULL; - goto err_add_dev; + binfo->icc = devm_of_icc_get(&core->pdev->dev, binfo->name); + if (IS_ERR_OR_NULL(binfo->icc)) { + d_vpr_e("%s: failed to get bus: %s\n", __func__, binfo->name); + rc = PTR_ERR(binfo->icc) ? + PTR_ERR(binfo->icc) : -EBADHANDLE; + binfo->icc = NULL; + return rc; } } - return 0; - -err_add_dev: - __deinit_bus(core); return rc; } +static int __init_regulators(struct msm_vidc_core *core) +{ + const struct regulator_table *regulator_tbl; + struct regulator_set *regulators; + struct regulator_info *rinfo = NULL; + u32 regulator_count = 0, cnt = 0; + int rc = 0; + + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + regulators = &core->resource->regulator_set; + + regulator_tbl = core->platform->data.regulator_tbl; + regulator_count = core->platform->data.regulator_tbl_size; + + if (!regulator_tbl || !regulator_count) { + d_vpr_e("%s: invalid regulator tbl %#x or count %d\n", + __func__, regulator_tbl, regulator_count); + return -EINVAL; + } + + /* allocate regulator_set */ + regulators->regulator_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*regulators->regulator_tbl) * regulator_count, GFP_KERNEL); + if (!regulators->regulator_tbl) { + d_vpr_e("%s: failed to alloc memory for regulator table\n", __func__); + return -ENOMEM; + } + regulators->count = regulator_count; + + /* populate regulator fields */ + for (cnt = 0; cnt < regulators->count; cnt++) { + regulators->regulator_tbl[cnt].name = regulator_tbl[cnt].name; + regulators->regulator_tbl[cnt].hw_power_collapse = regulator_tbl[cnt].hw_trigger; + } + + /* print regulator fields */ + venus_hfi_for_each_regulator(core, rinfo) { + d_vpr_h("%s: name %s hw_power_collapse %d\n", + __func__, rinfo->name, rinfo->hw_power_collapse); + } + + /* get regulator handle */ + venus_hfi_for_each_regulator(core, rinfo) { + rinfo->regulator = devm_regulator_get(&core->pdev->dev, rinfo->name); + if (IS_ERR_OR_NULL(rinfo->regulator)) { + rc = PTR_ERR(rinfo->regulator) ? + PTR_ERR(rinfo->regulator) : -EBADHANDLE; + d_vpr_e("%s: failed to get regulator: %s\n", __func__, rinfo->name); + rinfo->regulator = NULL; + return rc; + } + } + + return rc; +} + +static int __init_clocks(struct msm_vidc_core *core) +{ + const struct clk_table *clk_tbl; + struct clock_set *clocks; + struct clock_info *cinfo = NULL; + u32 clk_count = 0, cnt = 0; + int rc = 0; + + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + clocks = &core->resource->clock_set; + + clk_tbl = core->platform->data.clk_tbl; + clk_count = core->platform->data.clk_tbl_size; + + if (!clk_tbl || !clk_count) { + d_vpr_e("%s: invalid clock tbl %#x or count %d\n", + __func__, clk_tbl, clk_count); + return -EINVAL; + } + + /* allocate clock_set */ + clocks->clock_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*clocks->clock_tbl) * clk_count, GFP_KERNEL); + if (!clocks->clock_tbl) { + d_vpr_e("%s: failed to alloc memory for clock table\n", __func__); + return -ENOMEM; + } + clocks->count = clk_count; + + /* populate clock field from platform data */ + for (cnt = 0; cnt < clocks->count; cnt++) { + clocks->clock_tbl[cnt].name = clk_tbl[cnt].name; + clocks->clock_tbl[cnt].clk_id = clk_tbl[cnt].clk_id; + clocks->clock_tbl[cnt].has_scaling = clk_tbl[cnt].scaling; + } + + /* print clock fields */ + venus_hfi_for_each_clock(core, cinfo) { + d_vpr_h("%s: clock name %s clock id %#x scaling %d\n", + __func__, cinfo->name, cinfo->clk_id, cinfo->has_scaling); + } + + /* get clock handle */ + venus_hfi_for_each_clock(core, cinfo) { + cinfo->clk = devm_clk_get(&core->pdev->dev, cinfo->name); + if (IS_ERR_OR_NULL(cinfo->clk)) { + d_vpr_e("%s: failed to get clock: %s\n", __func__, cinfo->name); + rc = PTR_ERR(cinfo->clk) ? + PTR_ERR(cinfo->clk) : -EINVAL; + cinfo->clk = NULL; + return rc; + } + } + + return rc; +} + +static int __init_reset_clocks(struct msm_vidc_core *core) +{ + const struct clk_rst_table *rst_tbl; + struct reset_set *rsts; + struct reset_info *rinfo = NULL; + u32 rst_count = 0, cnt = 0; + int rc = 0; + + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + rsts = &core->resource->reset_set; + + rst_tbl = core->platform->data.clk_rst_tbl; + rst_count = core->platform->data.clk_rst_tbl_size; + + if (!rst_tbl || !rst_count) { + d_vpr_e("%s: invalid reset tbl %#x or count %d\n", + __func__, rst_tbl, rst_count); + return -EINVAL; + } + + /* allocate reset_set */ + rsts->reset_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*rsts->reset_tbl) * rst_count, GFP_KERNEL); + if (!rsts->reset_tbl) { + d_vpr_e("%s: failed to alloc memory for reset table\n", __func__); + return -ENOMEM; + } + rsts->count = rst_count; + + /* populate clock field from platform data */ + for (cnt = 0; cnt < rsts->count; cnt++) + rsts->reset_tbl[cnt].name = rst_tbl[cnt].name; + + /* print reset clock fields */ + venus_hfi_for_each_reset_clock(core, rinfo) { + d_vpr_h("%s: reset clk %s\n", __func__, rinfo->name); + } + + /* get reset clock handle */ + venus_hfi_for_each_reset_clock(core, rinfo) { + rinfo->rst = devm_reset_control_get(&core->pdev->dev, rinfo->name); + if (IS_ERR_OR_NULL(rinfo->rst)) { + d_vpr_e("%s: failed to get reset clock: %s\n", __func__, rinfo->name); + rc = PTR_ERR(rinfo->rst) ? + PTR_ERR(rinfo->rst) : -EINVAL; + rinfo->rst = NULL; + return rc; + } + } + + return rc; +} + +static int __init_subcaches(struct msm_vidc_core *core) +{ + const struct subcache_table *llcc_tbl; + struct subcache_set *caches; + struct subcache_info *sinfo = NULL; + u32 llcc_count = 0, cnt = 0; + int rc = 0; + + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + caches = &core->resource->subcache_set; + + /* skip init if subcache not available */ + if (!is_sys_cache_present(core)) + return 0; + + llcc_tbl = core->platform->data.subcache_tbl; + llcc_count = core->platform->data.subcache_tbl_size; + + if (!llcc_tbl || !llcc_count) { + d_vpr_e("%s: invalid llcc tbl %#x or count %d\n", + __func__, llcc_tbl, llcc_count); + return -EINVAL; + } + + /* allocate clock_set */ + caches->subcache_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*caches->subcache_tbl) * llcc_count, GFP_KERNEL); + if (!caches->subcache_tbl) { + d_vpr_e("%s: failed to alloc memory for subcache table\n", __func__); + return -ENOMEM; + } + caches->count = llcc_count; + + /* populate subcache fields from platform data */ + for (cnt = 0; cnt < caches->count; cnt++) { + caches->subcache_tbl[cnt].name = llcc_tbl[cnt].name; + caches->subcache_tbl[cnt].llcc_id = llcc_tbl[cnt].llcc_id; + } + + /* print subcache fields */ + venus_hfi_for_each_subcache(core, sinfo) { + d_vpr_h("%s: name %s subcache id %d\n", + __func__, sinfo->name, sinfo->llcc_id); + } + + /* get subcache/llcc handle */ + venus_hfi_for_each_subcache(core, sinfo) { + sinfo->subcache = devm_llcc_get(&core->pdev->dev, sinfo->llcc_id); + if (IS_ERR_OR_NULL(sinfo->subcache)) { + d_vpr_e("%s: failed to get subcache: %d\n", __func__, sinfo->llcc_id); + rc = PTR_ERR(sinfo->subcache) ? + PTR_ERR(sinfo->subcache) : -EBADHANDLE; + sinfo->subcache = NULL; + return rc; + } + } + + return rc; +} + +static int __init_freq_table(struct msm_vidc_core *core) +{ + struct freq_table *freq_tbl; + struct freq_set *clks; + u32 freq_count = 0, cnt = 0; + int rc = 0; + + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + clks = &core->resource->freq_set; + + freq_tbl = core->platform->data.freq_tbl; + freq_count = core->platform->data.freq_tbl_size; + + if (!freq_tbl || !freq_count) { + d_vpr_e("%s: invalid freq tbl %#x or count %d\n", + __func__, freq_tbl, freq_count); + return -EINVAL; + } + + /* allocate freq_set */ + clks->freq_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*clks->freq_tbl) * freq_count, GFP_KERNEL); + if (!clks->freq_tbl) { + d_vpr_e("%s: failed to alloc memory for freq table\n", __func__); + return -ENOMEM; + } + clks->count = freq_count; + + /* populate freq field from platform data */ + for (cnt = 0; cnt < clks->count; cnt++) + clks->freq_tbl[cnt].freq = freq_tbl[cnt].freq; + + /* sort freq table */ + sort(clks->freq_tbl, clks->count, sizeof(*clks->freq_tbl), cmp, NULL); + + /* print freq field freq_set */ + d_vpr_h("%s: updated freq table\n", __func__); + for (cnt = 0; cnt < clks->count; cnt++) + d_vpr_h("%s:\t %u\n", __func__, clks->freq_tbl[cnt].freq); + + return rc; +} + +static int __init_context_banks(struct msm_vidc_core *core) +{ + const struct context_bank_table *cb_tbl; + struct context_bank_set *cbs; + struct context_bank_info *cbinfo = NULL; + u32 cb_count = 0, cnt = 0; + int rc = 0; + + if (!core || !core->resource || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + cbs = &core->resource->context_bank_set; + + cb_tbl = core->platform->data.context_bank_tbl; + cb_count = core->platform->data.context_bank_tbl_size; + + if (!cb_tbl || !cb_count) { + d_vpr_e("%s: invalid context bank tbl %#x or count %d\n", + __func__, cb_tbl, cb_count); + return -EINVAL; + } + + /* allocate context_bank table */ + cbs->context_bank_tbl = devm_kzalloc(&core->pdev->dev, + sizeof(*cbs->context_bank_tbl) * cb_count, GFP_KERNEL); + if (!cbs->context_bank_tbl) { + d_vpr_e("%s: failed to alloc memory for context_bank table\n", __func__); + return -ENOMEM; + } + cbs->count = cb_count; + + /** + * populate context bank field from platform data except + * dev & domain which are assigned as part of context bank + * probe sequence + */ + for (cnt = 0; cnt < cbs->count; cnt++) { + cbs->context_bank_tbl[cnt].name = cb_tbl[cnt].name; + cbs->context_bank_tbl[cnt].addr_range.start = cb_tbl[cnt].start; + cbs->context_bank_tbl[cnt].addr_range.size = cb_tbl[cnt].size; + cbs->context_bank_tbl[cnt].secure = cb_tbl[cnt].secure; + cbs->context_bank_tbl[cnt].dma_coherant = cb_tbl[cnt].dma_coherant; + cbs->context_bank_tbl[cnt].region = cb_tbl[cnt].region; + } + + /* print context_bank fiels */ + venus_hfi_for_each_context_bank(core, cbinfo) { + d_vpr_h("%s: name %s addr start %#x size %#x secure %d coherant %d region %d\n", + __func__, cbinfo->name, cbinfo->addr_range.start, + cbinfo->addr_range.size, cbinfo->secure, + cbinfo->dma_coherant, cbinfo->region); + } + + return rc; +} + +#ifdef CONFIG_MSM_MMRM +static int __register_mmrm(struct msm_vidc_core *core) +{ + int rc = 0; + struct clock_info *cl; + + if (!core || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + /* skip if platform does not support mmrm */ + if (!is_mmrm_supported(core)) { + d_vpr_h("%s: MMRM not supported\n", __func__); + return 0; + } + + /* get mmrm handle for each clock sources */ + venus_hfi_for_each_clock(core, cl) { + struct mmrm_client_desc desc; + char *name = (char *)desc.client_info.desc.name; + + // TODO: set notifier data vals + struct mmrm_client_notifier_data notifier_data = { + MMRM_CLIENT_RESOURCE_VALUE_CHANGE, + {{0, 0}}, + NULL}; + + // TODO: add callback fn + desc.notifier_callback_fn = NULL; + + if (!cl->has_scaling) + continue; + + if (IS_ERR_OR_NULL(cl->clk)) { + d_vpr_e("%s: Invalid clock: %s\n", __func__, cl->name); + return PTR_ERR(cl->clk) ? PTR_ERR(cl->clk) : -EINVAL; + } + + desc.client_type = MMRM_CLIENT_CLOCK; + desc.client_info.desc.client_domain = MMRM_CLIENT_DOMAIN_VIDEO; + desc.client_info.desc.client_id = cl->clk_id; + strscpy(name, cl->name, sizeof(desc.client_info.desc.name)); + desc.client_info.desc.clk = cl->clk; + desc.priority = MMRM_CLIENT_PRIOR_LOW; + desc.pvt_data = notifier_data.pvt_data; + + d_vpr_h("%s: domain(%d) cid(%d) name(%s) clk(%pK)\n", + __func__, + desc.client_info.desc.client_domain, + desc.client_info.desc.client_id, + desc.client_info.desc.name, + desc.client_info.desc.clk); + + d_vpr_h("%s: type(%d) pri(%d) pvt(%pK) notifier(%pK)\n", + __func__, + desc.client_type, + desc.priority, + desc.pvt_data, + desc.notifier_callback_fn); + + cl->mmrm_client = devm_mmrm_get(&core->pdev->dev, &desc); + if (!cl->mmrm_client) { + d_vpr_e("%s: Failed to register clk(%s): %d\n", + __func__, cl->name, rc); + return -EINVAL; + } + } + + return rc; +} +#else +static int __register_mmrm(struct msm_vidc_core *core) +{ + return 0; +} +#endif + + + static int __acquire_regulator(struct msm_vidc_core *core, struct regulator_info *rinfo) { @@ -238,7 +651,7 @@ static int __acquire_regulator(struct msm_vidc_core *core, return -EINVAL; } - if (rinfo->has_hw_power_collapse) { + if (rinfo->hw_power_collapse) { if (!rinfo->regulator) { d_vpr_e("%s: invalid regulator\n", __func__); rc = -EINVAL; @@ -297,7 +710,7 @@ static int __hand_off_regulator(struct msm_vidc_core *core, { int rc = 0; - if (rinfo->has_hw_power_collapse) { + if (rinfo->hw_power_collapse) { if (!rinfo->regulator) { d_vpr_e("%s: invalid regulator\n", __func__); return -EINVAL; @@ -443,221 +856,6 @@ static int __enable_regulator(struct msm_vidc_core *core, const char *reg_name) return rc; } -#ifdef CONFIG_MSM_MMRM -static void __deregister_mmrm(struct msm_vidc_core *core) -{ - struct clock_info *cl; - - if (!core || !core->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return; - } - - if (!core->capabilities[MMRM].value) { - d_vpr_h("%s: MMRM not supported\n", __func__); - return; - } - - venus_hfi_for_each_clock(core, cl) { - if (cl->has_scaling && cl->mmrm_client) { - mmrm_client_deregister(cl->mmrm_client); - cl->mmrm_client = NULL; - } - } -} -#else -static void __deregister_mmrm(struct msm_vidc_core *core) -{ -} -#endif - -#ifdef CONFIG_MSM_MMRM -static int __register_mmrm(struct msm_vidc_core *core) -{ - int rc = 0; - struct clock_info *cl; - - if (!core ||!core->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!core->capabilities[MMRM].value) { - d_vpr_h("%s: MMRM not supported\n", __func__); - return 0; - } - - venus_hfi_for_each_clock(core, cl) { - struct mmrm_client_desc desc; - char *name = (char *)desc.client_info.desc.name; - - // TODO: set notifier data vals - struct mmrm_client_notifier_data notifier_data = { - MMRM_CLIENT_RESOURCE_VALUE_CHANGE, - {{0, 0}}, - NULL}; - - // TODO: add callback fn - desc.notifier_callback_fn = NULL; - - if (!cl->has_scaling) - continue; - - if (IS_ERR_OR_NULL(cl->clk)) { - d_vpr_e("%s: Invalid clock: %s\n", __func__, cl->name); - rc = PTR_ERR(cl->clk) ? PTR_ERR(cl->clk) : -EINVAL; - goto err_register_mmrm; - } - - desc.client_type = MMRM_CLIENT_CLOCK; - desc.client_info.desc.client_domain = MMRM_CLIENT_DOMAIN_VIDEO; - desc.client_info.desc.client_id = cl->clk_id; - strlcpy(name, cl->name, sizeof(desc.client_info.desc.name)); - desc.client_info.desc.clk = cl->clk; - desc.priority = MMRM_CLIENT_PRIOR_LOW; - desc.pvt_data = notifier_data.pvt_data; - - d_vpr_h("%s: domain(%d) cid(%d) name(%s) clk(%pK)\n", - __func__, - desc.client_info.desc.client_domain, - desc.client_info.desc.client_id, - desc.client_info.desc.name, - desc.client_info.desc.clk); - - d_vpr_h("%s: type(%d) pri(%d) pvt(%pK) notifier(%pK)\n", - __func__, - desc.client_type, - desc.priority, - desc.pvt_data, - desc.notifier_callback_fn); - - cl->mmrm_client = mmrm_client_register(&desc); - if (!cl->mmrm_client) { - d_vpr_e("%s: Failed to register clk(%s): %d\n", - __func__, cl->name, rc); - rc = -EINVAL; - goto err_register_mmrm; - } - } - - return 0; - -err_register_mmrm: - __deregister_mmrm(core); - return rc; -} -#else -static int __register_mmrm(struct msm_vidc_core *core) -{ - return 0; -} -#endif - -static void __deinit_regulators(struct msm_vidc_core *core) -{ - struct regulator_info *rinfo = NULL; - - venus_hfi_for_each_regulator_reverse(core, rinfo) { - if (rinfo->regulator) { - regulator_put(rinfo->regulator); - rinfo->regulator = NULL; - } - } -} - -static int __init_regulators(struct msm_vidc_core *core) -{ - int rc = 0; - struct regulator_info *rinfo = NULL; - - venus_hfi_for_each_regulator(core, rinfo) { - rinfo->regulator = regulator_get(&core->pdev->dev, rinfo->name); - if (IS_ERR_OR_NULL(rinfo->regulator)) { - rc = PTR_ERR(rinfo->regulator) ? - PTR_ERR(rinfo->regulator) : -EBADHANDLE; - d_vpr_e("Failed to get regulator: %s\n", rinfo->name); - rinfo->regulator = NULL; - goto err_reg_get; - } - } - - return 0; - -err_reg_get: - __deinit_regulators(core); - return rc; -} - -static void __deinit_subcaches(struct msm_vidc_core *core) -{ - struct subcache_info *sinfo = NULL; - - if (!core) { - d_vpr_e("%s: invalid params\n", __func__); - goto exit; - } - - if (!is_sys_cache_present(core)) - goto exit; - - venus_hfi_for_each_subcache_reverse(core, sinfo) { - if (sinfo->subcache) { - d_vpr_h("deinit_subcaches: %s\n", sinfo->name); - llcc_slice_putd(sinfo->subcache); - sinfo->subcache = NULL; - } - } - -exit: - return; -} - -static int __init_subcaches(struct msm_vidc_core *core) -{ - int rc = 0; - struct subcache_info *sinfo = NULL; - - if (!core) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!is_sys_cache_present(core)) - return 0; - - venus_hfi_for_each_subcache(core, sinfo) { - if (!strcmp("vidsc0", sinfo->name)) { - sinfo->subcache = llcc_slice_getd(LLCC_VIDSC0); - } else if (!strcmp("vidsc1", sinfo->name)) { - sinfo->subcache = llcc_slice_getd(LLCC_VIDSC1); - } else if (!strcmp("vidscfw", sinfo->name)) { - sinfo->subcache = llcc_slice_getd(LLCC_VIDFW); - }else if (!strcmp("vidvsp", sinfo->name)) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)) - sinfo->subcache = llcc_slice_getd(LLCC_VIDVSP); -#endif - } else { - d_vpr_e("Invalid subcache name %s\n", - sinfo->name); - } - if (IS_ERR_OR_NULL(sinfo->subcache)) { - rc = PTR_ERR(sinfo->subcache) ? - PTR_ERR(sinfo->subcache) : -EBADHANDLE; - d_vpr_e("init_subcaches: invalid subcache: %s rc %d\n", - sinfo->name, rc); - sinfo->subcache = NULL; - goto err_subcache_get; - } - d_vpr_h("init_subcaches: %s\n", sinfo->name); - } - - return 0; - -err_subcache_get: - __deinit_subcaches(core); - return rc; -} - static int __disable_subcaches(struct msm_vidc_core *core) { struct subcache_info *sinfo; @@ -668,16 +866,16 @@ static int __disable_subcaches(struct msm_vidc_core *core) /* De-activate subcaches */ venus_hfi_for_each_subcache_reverse(core, sinfo) { - if (sinfo->isactive) { - d_vpr_h("De-activate subcache %s\n", - sinfo->name); - rc = llcc_slice_deactivate(sinfo->subcache); - if (rc) { - d_vpr_e("Failed to de-activate %s: %d\n", - sinfo->name, rc); - } - sinfo->isactive = false; + if (!sinfo->isactive) + continue; + + d_vpr_h("%s: De-activate subcache %s\n", __func__, sinfo->name); + rc = llcc_slice_deactivate(sinfo->subcache); + if (rc) { + d_vpr_e("Failed to de-activate %s: %d\n", + sinfo->name, rc); } + sinfo->isactive = false; } return 0; @@ -730,14 +928,14 @@ static int __vote_bandwidth(struct bus_info *bus, unsigned long bw_kbps) { int rc = 0; - if (!bus->path) { + if (!bus->icc) { d_vpr_e("%s: invalid bus\n", __func__); return -EINVAL; } d_vpr_p("Voting bus %s to ab %lu kBps\n", bus->name, bw_kbps); - rc = icc_set_bw(bus->path, bw_kbps, 0); + rc = icc_set_bw(bus->icc, bw_kbps, 0); if (rc) d_vpr_e("Failed voting bus %s to ab %lu, rc=%d\n", bus->name, bw_kbps, rc); @@ -782,7 +980,7 @@ static int __vote_buses(struct msm_vidc_core *core, } venus_hfi_for_each_bus(core, bus) { - if (bus && bus->path) { + if (bus && bus->icc) { type = get_type_frm_name(bus->name); if (type == DDR) { @@ -792,14 +990,14 @@ static int __vote_buses(struct msm_vidc_core *core, bw_kbps = bw_llcc; bw_prev = core->power.bw_llcc; } else { - bw_kbps = bus->range[1]; + bw_kbps = bus->max_kbps; bw_prev = core->power.bw_ddr ? bw_kbps : 0; } /* ensure freq is within limits */ bw_kbps = clamp_t(typeof(bw_kbps), bw_kbps, - bus->range[0], bus->range[1]); + bus->min_kbps, bus->max_kbps); if (TRIVIAL_BW_CHANGE(bw_kbps, bw_prev) && bw_prev) { d_vpr_l("Skip voting bus %s to %lu kBps\n", @@ -839,12 +1037,12 @@ static int __set_clk_rate(struct msm_vidc_core *core, struct clock_info *cl, struct mmrm_client *client; /* not registered */ - if (!core || !cl || !core->capabilities) { + if (!core || !cl || !core->platform) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - if (core->capabilities[MMRM].value && !cl->mmrm_client) { + if (is_mmrm_supported(core) && !cl->mmrm_client) { d_vpr_e("%s: invalid mmrm client\n", __func__); return -EINVAL; } @@ -863,7 +1061,7 @@ static int __set_clk_rate(struct msm_vidc_core *core, struct clock_info *cl, d_vpr_p("Scaling clock %s to %llu, prev %llu\n", cl->name, rate, cl->prev); - if (core->capabilities[MMRM].value) { + if (is_mmrm_supported(core)) { /* set clock rate to mmrm driver */ client = cl->mmrm_client; memset(&client_data, 0, sizeof(client_data)); @@ -1042,71 +1240,118 @@ static int __prepare_enable_clock(struct msm_vidc_core *core, static int __init_resources(struct msm_vidc_core *core) { - int i, rc = 0; + int rc = 0; - rc = __init_regulators(core); - if (rc) { - d_vpr_e("Failed to get all regulators\n"); - return -ENODEV; - } + rc = __init_register_base(core); + if (rc) + return rc; - rc = __init_clocks(core); - if (rc) { - d_vpr_e("Failed to init clocks\n"); - rc = -ENODEV; - goto err_init_clocks; - } - - rc = __register_mmrm(core); - if (rc) { - d_vpr_e("Failed to register mmrm\n"); - rc = -ENODEV; - goto err_init_mmrm; - } - - for (i = 0; i < core->dt->reset_set.count; i++) { - rc = __handle_reset_clk(core, i, INIT); - if (rc) { - d_vpr_e("Failed to init reset clocks\n"); - rc = -ENODEV; - goto err_init_reset_clk; - } - } + rc = __init_irq(core); + if (rc) + return rc; rc = __init_bus(core); - if (rc) { - d_vpr_e("Failed to init bus: %d\n", rc); - goto err_init_bus; - } + if (rc) + return rc; + + rc = __init_regulators(core); + if (rc) + return rc; + + rc = __init_clocks(core); + if (rc) + return rc; + + rc = __init_reset_clocks(core); + if (rc) + return rc; rc = __init_subcaches(core); if (rc) - d_vpr_e("Failed to init subcaches: %d\n", rc); + return rc; - return rc; + rc = __init_freq_table(core); + if (rc) + return rc; + + rc = __init_context_banks(core); + if (rc) + return rc; + + rc = __register_mmrm(core); + if (rc) + return rc; -err_init_reset_clk: -err_init_bus: - __deregister_mmrm(core); -err_init_mmrm: - __deinit_clocks(core); -err_init_clocks: - __deinit_regulators(core); return rc; } -static void __deinit_resources(struct msm_vidc_core *core) +static int __reset_control_deassert(struct msm_vidc_core *core) { - __deinit_subcaches(core); - __deinit_bus(core); - __deregister_mmrm(core); - __deinit_clocks(core); - __deinit_regulators(core); + struct reset_info *rcinfo = NULL; + int rc = 0; + + venus_hfi_for_each_reset_clock(core, rcinfo) { + rc = reset_control_deassert(rcinfo->rst); + if (rc) { + d_vpr_e("%s: deassert reset control failed. rc = %d\n", __func__, rc); + continue; + } + d_vpr_h("%s: deassert reset control %s\n", __func__, rcinfo->name); + } + + return rc; +} + +static int __reset_control_assert(struct msm_vidc_core *core) +{ + struct reset_info *rcinfo = NULL; + int rc = 0, cnt = 0; + + venus_hfi_for_each_reset_clock(core, rcinfo) { + if (!rcinfo->rst) { + d_vpr_e("%s: invalid reset clock %s\n", + __func__, rcinfo->name); + return -EINVAL; + } + rc = reset_control_assert(rcinfo->rst); + if (rc) { + d_vpr_e("%s: failed to assert reset control %s, rc = %d\n", + __func__, rcinfo->name, rc); + goto deassert_reset_control; + } + cnt++; + d_vpr_h("%s: assert reset control %s, count %d\n", __func__, rcinfo->name, cnt); + + usleep_range(1000, 1100); + } + + return rc; +deassert_reset_control: + venus_hfi_for_each_reset_clock_reverse_continue(core, rcinfo, cnt) { + d_vpr_e("%s: deassert reset control %s\n", __func__, rcinfo->name); + reset_control_deassert(rcinfo->rst); + } + + return rc; +} + +static int __reset_ahb2axi_bridge(struct msm_vidc_core *core) +{ + int rc = 0; + + rc = __reset_control_assert(core); + if (rc) + return rc; + + rc = __reset_control_deassert(core); + if (rc) + return rc; + + return rc; } static const struct msm_vidc_resources_ops res_ops = { - .get = __init_resources, - .put = __deinit_resources, + .init = __init_resources, .reset_bridge = __reset_ahb2axi_bridge, .gdsc_on = __enable_regulator, .gdsc_off = __disable_regulator, diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index 44561e90f7..f1e7529f90 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #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; } -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, 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)) 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"); return 0; } @@ -409,22 +405,23 @@ static int __release_subcaches(struct msm_vidc_core *core) buf.flags = HFI_BUF_HOST_FLAG_RELEASE; venus_hfi_for_each_subcache_reverse(core, sinfo) { - if (sinfo->isactive) { - buf.index = sinfo->subcache->slice_id; - buf.buffer_size = sinfo->subcache->slice_size; + if (!sinfo->isactive) + continue; - rc = hfi_create_packet(core->packet, - core->packet_size, - HFI_CMD_BUFFER, - HFI_BUF_HOST_FLAG_NONE, - HFI_PAYLOAD_STRUCTURE, - HFI_PORT_NONE, - core->packet_id++, - &buf, - sizeof(buf)); - if (rc) - return rc; - } + buf.index = sinfo->subcache->slice_id; + buf.buffer_size = sinfo->subcache->slice_size; + + rc = hfi_create_packet(core->packet, + core->packet_size, + HFI_CMD_BUFFER, + HFI_BUF_HOST_FLAG_NONE, + HFI_PAYLOAD_STRUCTURE, + HFI_PORT_NONE, + core->packet_id++, + &buf, + sizeof(buf)); + if (rc) + return rc; } /* Set resource to Venus for activated subcaches */ @@ -433,15 +430,14 @@ static int __release_subcaches(struct msm_vidc_core *core) return rc; venus_hfi_for_each_subcache_reverse(core, sinfo) { - if (sinfo->isactive) { - sinfo->isset = false; - d_vpr_h("Release Subcache id %d size %lu done\n", - sinfo->subcache->slice_id, - sinfo->subcache->slice_size); - } - } + if (!sinfo->isactive) + continue; - 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; } @@ -458,7 +454,7 @@ static int __set_subcaches(struct msm_vidc_core *core) 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"); return 0; } @@ -473,22 +469,22 @@ static int __set_subcaches(struct msm_vidc_core *core) buf.flags = HFI_BUF_HOST_FLAG_NONE; venus_hfi_for_each_subcache(core, sinfo) { - if (sinfo->isactive) { - buf.index = sinfo->subcache->slice_id; - buf.buffer_size = sinfo->subcache->slice_size; + if (!sinfo->isactive) + continue; + buf.index = sinfo->subcache->slice_id; + buf.buffer_size = sinfo->subcache->slice_size; - rc = hfi_create_packet(core->packet, - core->packet_size, - HFI_CMD_BUFFER, - HFI_BUF_HOST_FLAG_NONE, - HFI_PAYLOAD_STRUCTURE, - HFI_PORT_NONE, - core->packet_id++, - &buf, - sizeof(buf)); - if (rc) - goto err_fail_set_subacaches; - } + rc = hfi_create_packet(core->packet, + core->packet_size, + HFI_CMD_BUFFER, + HFI_BUF_HOST_FLAG_NONE, + HFI_PAYLOAD_STRUCTURE, + HFI_PORT_NONE, + core->packet_id++, + &buf, + sizeof(buf)); + if (rc) + goto err_fail_set_subacaches; } /* 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; venus_hfi_for_each_subcache(core, sinfo) { - if (sinfo->isactive) { - sinfo->isset = true; - d_vpr_h("Set Subcache id %d size %lu done\n", - sinfo->subcache->slice_id, - sinfo->subcache->slice_size); - } + if (!sinfo->isactive) + continue; + d_vpr_h("%s: set Subcache id %d size %lu done\n", + __func__, sinfo->subcache->slice_id, + sinfo->subcache->slice_size); } - - core->dt->sys_cache_res_set = true; + core->resource->subcache_set.set_to_fw = true; return 0; @@ -699,16 +693,10 @@ int __load_fw(struct msm_vidc_core *core) core->cpu_watchdog = false; 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); if (rc) { d_vpr_e("%s: power on failed\n", __func__); - goto fail_venus_power_on; + goto fail_power; } rc = fw_load(core); @@ -727,25 +715,21 @@ int __load_fw(struct msm_vidc_core *core) return rc; fail_load_fw: __venus_power_off(core); -fail_venus_power_on: - res_ops->put(core); -fail_init_res: +fail_power: trace_msm_v4l2_vidc_fw_load("END"); return rc; } void __unload_fw(struct msm_vidc_core *core) { - const struct msm_vidc_resources_ops *res_ops = core->res_ops; int rc = 0; - if (!core->dt->fw_cookie) + if (!core->resource->fw_cookie) return; cancel_delayed_work(&core->pm_work); rc = fw_unload(core); __venus_power_off(core); - res_ops->put(core); core->cpu_watchdog = false;