video: driver: reduce device_tree dependency for video

Only keep minimal entries in dtsi, which is essential for
other drivers usage. Move remaining all data into platform
resource file.

Remove device_tree dependency and maintain platform_data
to initialize resources like regulators, interconnects,
clocks, reset_clocks, subcaches and context_banks.

Read static data like freq_table, firmware_name, pas_id
also from platform_data instead of from dtsi.

Change-Id: I73a1df10b92c55e55b23e538aea62598a7250ab4
Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
This commit is contained in:
Govindaraj Rajagopal
2022-10-12 19:05:36 +05:30
parent b0f6be067e
commit 21eb38981e
21 changed files with 1430 additions and 1959 deletions

View File

@@ -41,6 +41,61 @@ extern u32 vpe_csc_custom_matrix_coeff[MAX_MATRIX_COEFFS];
extern u32 vpe_csc_custom_bias_coeff[MAX_BIAS_COEFFS]; extern u32 vpe_csc_custom_bias_coeff[MAX_BIAS_COEFFS];
extern u32 vpe_csc_custom_limit_coeff[MAX_LIMIT_COEFFS]; extern u32 vpe_csc_custom_limit_coeff[MAX_LIMIT_COEFFS];
struct bw_table {
const char *name;
u32 min_kbps;
u32 max_kbps;
};
struct regulator_table {
const char *name;
bool hw_trigger;
};
struct clk_table {
const char *name;
u32 clk_id;
bool scaling;
};
struct clk_rst_table {
const char *name;
};
struct subcache_table {
const char *name;
u32 llcc_id;
};
struct context_bank_table {
const char *name;
u32 start;
u32 size;
bool secure;
bool dma_coherant;
u32 region;
};
struct freq_table {
unsigned long freq;
};
struct reg_preset_table {
u32 reg;
u32 value;
u32 mask;
};
struct msm_vidc_ubwc_config_data {
u32 max_channels;
u32 mal_length;
u32 highest_bank_bit;
u32 bank_swzl_level;
u32 bank_swz2_level;
u32 bank_swz3_level;
u32 bank_spreading;
};
struct codec_info { struct codec_info {
u32 v4l2_codec; u32 v4l2_codec;
enum msm_vidc_codec_type vidc_codec; enum msm_vidc_codec_type vidc_codec;
@@ -112,16 +167,6 @@ struct msm_vidc_efuse_data {
enum efuse_purpose purpose; enum efuse_purpose purpose;
}; };
struct msm_vidc_ubwc_config_data {
u32 max_channels;
u32 mal_length;
u32 highest_bank_bit;
u32 bank_swzl_level;
u32 bank_swz2_level;
u32 bank_swz3_level;
u32 bank_spreading;
};
struct msm_vidc_format_capability { struct msm_vidc_format_capability {
struct codec_info *codec_info; struct codec_info *codec_info;
u32 codec_info_size; u32 codec_info_size;
@@ -136,6 +181,26 @@ struct msm_vidc_format_capability {
}; };
struct msm_vidc_platform_data { struct msm_vidc_platform_data {
const struct bw_table *bw_tbl;
unsigned int bw_tbl_size;
const struct regulator_table *regulator_tbl;
unsigned int regulator_tbl_size;
const struct clk_table *clk_tbl;
unsigned int clk_tbl_size;
const struct clk_rst_table *clk_rst_tbl;
unsigned int clk_rst_tbl_size;
const struct subcache_table *subcache_tbl;
unsigned int subcache_tbl_size;
const struct context_bank_table *context_bank_tbl;
unsigned int context_bank_tbl_size;
struct freq_table *freq_tbl;
unsigned int freq_tbl_size;
const struct reg_preset_table *reg_prst_tbl;
unsigned int reg_prst_tbl_size;
struct msm_vidc_ubwc_config_data *ubwc_config;
const char *fwname;
u32 pas_id;
bool supports_mmrm;
struct msm_platform_core_capability *core_data; struct msm_platform_core_capability *core_data;
u32 core_data_size; u32 core_data_size;
struct msm_platform_inst_capability *inst_cap_data; struct msm_platform_inst_capability *inst_cap_data;
@@ -143,7 +208,6 @@ struct msm_vidc_platform_data {
struct msm_platform_inst_cap_dependency *inst_cap_dependency_data; struct msm_platform_inst_cap_dependency *inst_cap_dependency_data;
u32 inst_cap_dependency_data_size; u32 inst_cap_dependency_data_size;
struct msm_vidc_csc_coeff csc_data; struct msm_vidc_csc_coeff csc_data;
struct msm_vidc_ubwc_config_data *ubwc_config;
struct msm_vidc_efuse_data *efuse_data; struct msm_vidc_efuse_data *efuse_data;
unsigned int efuse_data_size; unsigned int efuse_data_size;
unsigned int sku_version; unsigned int sku_version;
@@ -155,9 +219,18 @@ struct msm_vidc_platform {
struct msm_vidc_platform_data data; struct msm_vidc_platform_data data;
}; };
static inline bool is_sys_cache_present(struct msm_vidc_core *core)
{
return !!core->platform->data.subcache_tbl_size;
}
static inline bool is_mmrm_supported(struct msm_vidc_core *core)
{
return !!core->platform->data.supports_mmrm;
}
int msm_vidc_init_platform(struct platform_device *pdev); int msm_vidc_init_platform(struct platform_device *pdev);
int msm_vidc_deinit_platform(struct platform_device *pdev); int msm_vidc_deinit_platform(struct platform_device *pdev);
int msm_vidc_read_efuse(struct msm_vidc_core *core); int msm_vidc_read_efuse(struct msm_vidc_core *core);
void msm_vidc_sort_table(struct msm_vidc_core *core);
#endif // _MSM_VIDC_PLATFORM_H_ #endif // _MSM_VIDC_PLATFORM_H_

View File

@@ -5,7 +5,8 @@
*/ */
#include <linux/io.h> #include <linux/io.h>
#include <linux/sort.h> #include <linux/of.h>
#include <soc/qcom/of_common.h>
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
@@ -13,7 +14,6 @@
#include "msm_vidc_vb2.h" #include "msm_vidc_vb2.h"
#include "msm_vidc_control.h" #include "msm_vidc_control.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#if defined(CONFIG_MSM_VIDC_WAIPIO) #if defined(CONFIG_MSM_VIDC_WAIPIO)
@@ -25,9 +25,6 @@
#if defined(CONFIG_MSM_VIDC_PINEAPPLE) #if defined(CONFIG_MSM_VIDC_PINEAPPLE)
#include "msm_vidc_pineapple.h" #include "msm_vidc_pineapple.h"
#endif #endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
#include "msm_vidc_pineapple.h"
#endif
#if defined(CONFIG_MSM_VIDC_ANORAK) #if defined(CONFIG_MSM_VIDC_ANORAK)
#include "msm_vidc_anorak.h" #include "msm_vidc_anorak.h"
#endif #endif
@@ -221,7 +218,7 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
d_vpr_h("%s()\n", __func__); d_vpr_h("%s()\n", __func__);
#if defined(CONFIG_MSM_VIDC_WAIPIO) #if defined(CONFIG_MSM_VIDC_WAIPIO)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-waipio")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
rc = msm_vidc_deinit_platform_waipio(core, dev); rc = msm_vidc_deinit_platform_waipio(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -229,7 +226,8 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_KALAMA) #if defined(CONFIG_MSM_VIDC_KALAMA)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-kalama")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
rc = msm_vidc_deinit_platform_kalama(core, dev); rc = msm_vidc_deinit_platform_kalama(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -237,7 +235,7 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE) #if defined(CONFIG_MSM_VIDC_PINEAPPLE)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-pineapple")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
rc = msm_vidc_deinit_platform_pineapple(core, dev); rc = msm_vidc_deinit_platform_pineapple(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -245,7 +243,7 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_ANORAK) #if defined(CONFIG_MSM_VIDC_ANORAK)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) { if (of_device_is_compatible(dev->of_node, "qcom,sxr2230p-vidc")) {
rc = msm_vidc_deinit_platform_anorak(core, dev); rc = msm_vidc_deinit_platform_anorak(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -268,7 +266,7 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
d_vpr_h("%s()\n", __func__); d_vpr_h("%s()\n", __func__);
#if defined(CONFIG_MSM_VIDC_WAIPIO) #if defined(CONFIG_MSM_VIDC_WAIPIO)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-waipio")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
rc = msm_vidc_init_platform_waipio(core, dev); rc = msm_vidc_init_platform_waipio(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -276,7 +274,8 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_KALAMA) #if defined(CONFIG_MSM_VIDC_KALAMA)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-kalama")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
rc = msm_vidc_init_platform_kalama(core, dev); rc = msm_vidc_init_platform_kalama(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -284,7 +283,7 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE) #if defined(CONFIG_MSM_VIDC_PINEAPPLE)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-pineapple")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
rc = msm_vidc_init_platform_pineapple(core, dev); rc = msm_vidc_init_platform_pineapple(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -292,7 +291,7 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_ANORAK) #if defined(CONFIG_MSM_VIDC_ANORAK)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) { if (of_device_is_compatible(dev->of_node, "qcom,sxr2230p-vidc")) {
rc = msm_vidc_init_platform_anorak(core, dev); rc = msm_vidc_init_platform_anorak(core, dev);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -315,7 +314,7 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
d_vpr_h("%s()\n", __func__); d_vpr_h("%s()\n", __func__);
#if defined(CONFIG_MSM_VIDC_IRIS2) #if defined(CONFIG_MSM_VIDC_IRIS2)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris2")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
rc = msm_vidc_deinit_iris2(core); rc = msm_vidc_deinit_iris2(core);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -323,7 +322,8 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS3) #if defined(CONFIG_MSM_VIDC_IRIS3)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris3")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
rc = msm_vidc_deinit_iris3(core); rc = msm_vidc_deinit_iris3(core);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -331,7 +331,7 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS33) #if defined(CONFIG_MSM_VIDC_IRIS33)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris33")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
rc = msm_vidc_deinit_iris33(core); rc = msm_vidc_deinit_iris33(core);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -351,7 +351,7 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
} }
#if defined(CONFIG_MSM_VIDC_IRIS2) #if defined(CONFIG_MSM_VIDC_IRIS2)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris2")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc")) {
rc = msm_vidc_init_iris2(core); rc = msm_vidc_init_iris2(core);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -359,7 +359,8 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS3) #if defined(CONFIG_MSM_VIDC_IRIS3)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris3")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2")) {
rc = msm_vidc_init_iris3(core); rc = msm_vidc_init_iris3(core);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -367,7 +368,7 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS33) #if defined(CONFIG_MSM_VIDC_IRIS33)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris33")) { if (of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc")) {
rc = msm_vidc_init_iris33(core); rc = msm_vidc_init_iris33(core);
if (rc) if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc); d_vpr_e("%s: failed with %d\n", __func__, rc);
@@ -494,19 +495,3 @@ int msm_vidc_read_efuse(struct msm_vidc_core *core)
} }
return rc; return rc;
} }
void msm_vidc_sort_table(struct msm_vidc_core *core)
{
u32 i = 0;
if (!core || !core->dt || !core->dt->allowed_clks_tbl) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
sort(core->dt->allowed_clks_tbl, core->dt->allowed_clks_tbl_size,
sizeof(*core->dt->allowed_clks_tbl), cmp, NULL);
d_vpr_h("Updated allowed clock rates\n");
for (i = 0; i < core->dt->allowed_clks_tbl_size; i++)
d_vpr_h(" %d\n", core->dt->allowed_clks_tbl[i]);
}

View File

@@ -4,9 +4,13 @@
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#include <soc/qcom/of_common.h> #include <dt-bindings/clock/qcom,gcc-kalama.h>
#include <dt-bindings/clock/qcom,videocc-kalama.h>
#include <linux/soc/qcom/llcc-qcom.h>
#include <soc/qcom/of_common.h>
#include <media/v4l2_vidc_extensions.h> #include <media/v4l2_vidc_extensions.h>
#include "msm_vidc_kalama.h" #include "msm_vidc_kalama.h"
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
@@ -315,7 +319,6 @@ static struct msm_platform_core_capability core_data_kalama[] = {
{AV_SYNC_WINDOW_SIZE, 40}, {AV_SYNC_WINDOW_SIZE, 40},
{NON_FATAL_FAULTS, 1}, {NON_FATAL_FAULTS, 1},
{ENC_AUTO_FRAMERATE, 1}, {ENC_AUTO_FRAMERATE, 1},
{MMRM, 1},
{DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_META_CAPTURE | {DEVICE_CAPS, V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_META_CAPTURE |
V4L2_CAP_STREAMING}, V4L2_CAP_STREAMING},
{SUPPORTS_REQUESTS, 1}, {SUPPORTS_REQUESTS, 1},
@@ -2626,7 +2629,128 @@ static struct msm_vidc_format_capability format_data_kalama = {
.matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_kalama), .matrix_coeff_info_size = ARRAY_SIZE(matrix_coeff_data_kalama),
}; };
/* name, min_kbps, max_kbps */
static const struct bw_table kalama_bw_table[] = {
{ "venus-cnoc", 1000, 1000 },
{ "venus-ddr", 1000, 15000000 },
{ "venus-llcc", 1000, 15000000 },
};
/* name, hw_trigger */
static const struct regulator_table kalama_regulator_table[] = {
{ "iris-ctl", 0 },
{ "vcodec", 1 },
};
/* name, clock id, scaling */
static const struct clk_table kalama_clk_table[] = {
{ "gcc_video_axi0", GCC_VIDEO_AXI0_CLK, 0 },
{ "core_clk", VIDEO_CC_MVS0C_CLK, 0 },
{ "vcodec_clk", VIDEO_CC_MVS0_CLK, 0 },
{ "video_cc_mvs0_clk_src", VIDEO_CC_MVS0_CLK_SRC, 1 },
};
/* name */
static const struct clk_rst_table kalama_clk_reset_table[] = {
{ "video_axi_reset" },
};
/* name, llcc_id */
static const struct subcache_table kalama_subcache_table[] = {
{ "vidsc0", LLCC_VIDSC0 },
{ "vidvsp", LLCC_VIDVSP },
};
/* name, start, size, secure, dma_coherant, region */
const struct context_bank_table kalama_context_bank_table[] = {
{"qcom,vidc,cb-ns", 0x25800000, 0xba800000, 0, 1, MSM_VIDC_NON_SECURE },
{"qcom,vidc,cb-ns-pxl", 0x00100000, 0xdff00000, 0, 1, MSM_VIDC_NON_SECURE_PIXEL },
{"qcom,vidc,cb-sec-pxl", 0x00500000, 0xdfb00000, 1, 0, MSM_VIDC_SECURE_PIXEL },
{"qcom,vidc,cb-sec-non-pxl", 0x01000000, 0x24800000, 1, 0, MSM_VIDC_SECURE_NONPIXEL },
{"qcom,vidc,cb-sec-bitstream", 0x00500000, 0xdfb00000, 1, 0, MSM_VIDC_SECURE_BITSTREAM },
};
/* freq */
static struct freq_table kalama_freq_table[] = {
{481000000}, {444000000}, {366000000}, {338000000}, {240000000}
};
static struct freq_table kalama_freq_table_v2[] = {
{533333333}, {444000000}, {366000000}, {338000000}, {240000000}
};
/* register, value, mask */
static const struct reg_preset_table kalama_reg_preset_table[] = {
{ 0xB0088, 0x0, 0x11 },
};
static const struct msm_vidc_platform_data kalama_data = { static const struct msm_vidc_platform_data kalama_data = {
/* resources dependent on other module */
.bw_tbl = kalama_bw_table,
.bw_tbl_size = ARRAY_SIZE(kalama_bw_table),
.regulator_tbl = kalama_regulator_table,
.regulator_tbl_size = ARRAY_SIZE(kalama_regulator_table),
.clk_tbl = kalama_clk_table,
.clk_tbl_size = ARRAY_SIZE(kalama_clk_table),
.clk_rst_tbl = kalama_clk_reset_table,
.clk_rst_tbl_size = ARRAY_SIZE(kalama_clk_reset_table),
.subcache_tbl = kalama_subcache_table,
.subcache_tbl_size = ARRAY_SIZE(kalama_subcache_table),
/* populate context bank */
.context_bank_tbl = kalama_context_bank_table,
.context_bank_tbl_size = ARRAY_SIZE(kalama_context_bank_table),
/* platform specific resources */
.freq_tbl = kalama_freq_table,
.freq_tbl_size = ARRAY_SIZE(kalama_freq_table),
.reg_prst_tbl = kalama_reg_preset_table,
.reg_prst_tbl_size = ARRAY_SIZE(kalama_reg_preset_table),
.fwname = "vpu30_4v",
.pas_id = 9,
.supports_mmrm = 1,
/* caps related resorces */
.core_data = core_data_kalama,
.core_data_size = ARRAY_SIZE(core_data_kalama),
.inst_cap_data = instance_cap_data_kalama,
.inst_cap_data_size = ARRAY_SIZE(instance_cap_data_kalama),
.inst_cap_dependency_data = instance_cap_dependency_data_kalama,
.inst_cap_dependency_data_size = ARRAY_SIZE(instance_cap_dependency_data_kalama),
.csc_data.vpe_csc_custom_bias_coeff = vpe_csc_custom_bias_coeff,
.csc_data.vpe_csc_custom_matrix_coeff = vpe_csc_custom_matrix_coeff,
.csc_data.vpe_csc_custom_limit_coeff = vpe_csc_custom_limit_coeff,
.ubwc_config = ubwc_config_kalama,
.format_data = &format_data_kalama,
};
static const struct msm_vidc_platform_data kalama_data_v2 = {
/* resources dependent on other module */
.bw_tbl = kalama_bw_table,
.bw_tbl_size = ARRAY_SIZE(kalama_bw_table),
.regulator_tbl = kalama_regulator_table,
.regulator_tbl_size = ARRAY_SIZE(kalama_regulator_table),
.clk_tbl = kalama_clk_table,
.clk_tbl_size = ARRAY_SIZE(kalama_clk_table),
.clk_rst_tbl = kalama_clk_reset_table,
.clk_rst_tbl_size = ARRAY_SIZE(kalama_clk_reset_table),
.subcache_tbl = kalama_subcache_table,
.subcache_tbl_size = ARRAY_SIZE(kalama_subcache_table),
/* populate context bank */
.context_bank_tbl = kalama_context_bank_table,
.context_bank_tbl_size = ARRAY_SIZE(kalama_context_bank_table),
/* platform specific resources */
.freq_tbl = kalama_freq_table_v2,
.freq_tbl_size = ARRAY_SIZE(kalama_freq_table_v2),
.reg_prst_tbl = kalama_reg_preset_table,
.reg_prst_tbl_size = ARRAY_SIZE(kalama_reg_preset_table),
.fwname = "vpu30_4v",
.pas_id = 9,
.supports_mmrm = 1,
/* caps related resorces */
.core_data = core_data_kalama, .core_data = core_data_kalama,
.core_data_size = ARRAY_SIZE(core_data_kalama), .core_data_size = ARRAY_SIZE(core_data_kalama),
.inst_cap_data = instance_cap_data_kalama, .inst_cap_data = instance_cap_data_kalama,
@@ -2655,17 +2779,21 @@ int msm_vidc_kalama_check_ddr_type(void)
return 0; return 0;
} }
static int msm_vidc_init_data(struct msm_vidc_core *core) static int msm_vidc_init_data(struct msm_vidc_core *core, struct device *dev)
{ {
int rc = 0; int rc = 0;
if (!core || !core->platform) { if (!core || !core->platform || !dev) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
d_vpr_h("%s: initialize kalama data\n", __func__); d_vpr_h("%s: initialize kalama data\n", __func__);
if (of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2"))
core->platform->data = kalama_data_v2;
else
core->platform->data = kalama_data; core->platform->data = kalama_data;
rc = msm_vidc_kalama_check_ddr_type(); rc = msm_vidc_kalama_check_ddr_type();
if (rc) if (rc)
return rc; return rc;
@@ -2677,7 +2805,7 @@ int msm_vidc_init_platform_kalama(struct msm_vidc_core *core, struct device *dev
{ {
int rc = 0; int rc = 0;
rc = msm_vidc_init_data(core); rc = msm_vidc_init_data(core, dev);
if (rc) if (rc)
return rc; return rc;

View File

@@ -9,8 +9,8 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_variant.h" #include "msm_vidc_variant.h"
#include "msm_vidc_platform.h"
static void __fatal_error(bool fatal) static void __fatal_error(bool fatal)
{ {
@@ -35,7 +35,7 @@ int __write_register(struct msm_vidc_core *core, u32 reg, u32 value)
u8 *base_addr; u8 *base_addr;
int rc = 0; int rc = 0;
if (!core) { if (!core || !core->resource) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -49,7 +49,7 @@ int __write_register(struct msm_vidc_core *core, u32 reg, u32 value)
return -EINVAL; return -EINVAL;
} }
base_addr = core->register_base_addr; base_addr = core->resource->register_base_addr;
d_vpr_l("regwrite(%pK + %#x) = %#x\n", base_addr, hwiosymaddr, value); d_vpr_l("regwrite(%pK + %#x) = %#x\n", base_addr, hwiosymaddr, value);
base_addr += hwiosymaddr; base_addr += hwiosymaddr;
writel_relaxed(value, base_addr); writel_relaxed(value, base_addr);
@@ -74,7 +74,7 @@ int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
u8 *base_addr; u8 *base_addr;
int rc = 0; int rc = 0;
if (!core) { if (!core || !core->resource) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -89,7 +89,7 @@ int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
return -EINVAL; return -EINVAL;
} }
base_addr = core->register_base_addr; base_addr = core->resource->register_base_addr;
base_addr += reg; base_addr += reg;
prev_val = readl_relaxed(base_addr); prev_val = readl_relaxed(base_addr);
@@ -116,7 +116,7 @@ int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value)
int rc = 0; int rc = 0;
u8 *base_addr; u8 *base_addr;
if (!core || !value) { if (!core || !core->resource || !value) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -126,7 +126,7 @@ int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value)
return -EINVAL; return -EINVAL;
} }
base_addr = core->register_base_addr; base_addr = core->resource->register_base_addr;
*value = readl_relaxed(base_addr + reg); *value = readl_relaxed(base_addr + reg);
/* /*
@@ -147,7 +147,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
u32 val = 0; u32 val = 0;
u8 *addr; u8 *addr;
if (!core) { if (!core || !core->resource) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -157,7 +157,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
return -EINVAL; return -EINVAL;
} }
addr = (u8 *)core->register_base_addr + reg; addr = (u8 *)core->resource->register_base_addr + reg;
rc = readl_relaxed_poll_timeout(addr, val, ((val & mask) == exp_val), sleep_us, timeout_us); rc = readl_relaxed_poll_timeout(addr, val, ((val & mask) == exp_val), sleep_us, timeout_us);
/* /*
@@ -167,7 +167,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
rmb(); rmb();
d_vpr_l( d_vpr_l(
"regread(%pK + %#x) = %#x. rc %d, mask %#x, exp_val %#x, cond %u, sleep %u, timeout %u\n", "regread(%pK + %#x) = %#x. rc %d, mask %#x, exp_val %#x, cond %u, sleep %u, timeout %u\n",
core->register_base_addr, reg, val, rc, mask, exp_val, core->resource->register_base_addr, reg, val, rc, mask, exp_val,
((val & mask) == exp_val), sleep_us, timeout_us); ((val & mask) == exp_val), sleep_us, timeout_us);
return rc; return rc;
@@ -175,19 +175,25 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
int __set_registers(struct msm_vidc_core *core) int __set_registers(struct msm_vidc_core *core)
{ {
struct reg_set *reg_set; const struct reg_preset_table *reg_prst;
int i, rc = 0; unsigned int prst_count;
int cnt, rc = 0;
if (!core || !core->dt) { if (!core || !core->platform) {
d_vpr_e("core resources null, cannot set registers\n"); d_vpr_e("core resources null, cannot set registers\n");
return -EINVAL; return -EINVAL;
} }
reg_set = &core->dt->reg_set; reg_prst = core->platform->data.reg_prst_tbl;
for (i = 0; i < reg_set->count; i++) { prst_count = core->platform->data.reg_prst_tbl_size;
rc = __write_register_masked(core, reg_set->reg_tbl[i].reg,
reg_set->reg_tbl[i].value, /* skip if there is no preset reg available */
reg_set->reg_tbl[i].mask); if (!reg_prst || !prst_count)
return 0;
for (cnt = 0; cnt < prst_count; cnt++) {
rc = __write_register_masked(core, reg_prst->reg,
reg_prst->value, reg_prst->mask);
if (rc) if (rc)
return rc; return rc;
} }

View File

@@ -10,7 +10,6 @@
#include "msm_vidc_buffer.h" #include "msm_vidc_buffer.h"
#include "msm_vidc_inst.h" #include "msm_vidc_inst.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_platform.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_media_info.h" #include "msm_media_info.h"

View File

@@ -12,7 +12,6 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_control.h" #include "msm_vidc_control.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#include "msm_vidc_buffer.h" #include "msm_vidc_buffer.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
@@ -487,7 +486,7 @@ static int __power_off_iris3(struct msm_vidc_core *core)
d_vpr_e("%s: failed to unvote buses\n", __func__); d_vpr_e("%s: failed to unvote buses\n", __func__);
if (!(core->intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS3)) if (!(core->intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS3))
disable_irq_nosync(core->dt->irq); disable_irq_nosync(core->resource->irq);
core->intr_status = 0; core->intr_status = 0;
core->power_enabled = false; core->power_enabled = false;
@@ -551,7 +550,7 @@ fail_regulator:
static int __power_on_iris3(struct msm_vidc_core *core) static int __power_on_iris3(struct msm_vidc_core *core)
{ {
const struct msm_vidc_resources_ops *res_ops = core->res_ops; const struct msm_vidc_resources_ops *res_ops = core->res_ops;
struct allowed_clock_rates_table *clk_tbl; struct frequency_table *freq_tbl;
u32 freq = 0; u32 freq = 0;
int rc = 0; int rc = 0;
@@ -579,9 +578,9 @@ static int __power_on_iris3(struct msm_vidc_core *core)
/* video controller and hardware powered on successfully */ /* video controller and hardware powered on successfully */
core->power_enabled = true; core->power_enabled = true;
clk_tbl = core->dt->allowed_clks_tbl; freq_tbl = core->resource->freq_set.freq_tbl;
freq = core->power.clk_freq ? core->power.clk_freq : freq = core->power.clk_freq ? core->power.clk_freq :
clk_tbl[0].clock_rate; freq_tbl[0].freq;
rc = res_ops->set_clks(core, freq); rc = res_ops->set_clks(core, freq);
if (rc) { if (rc) {
@@ -596,7 +595,7 @@ static int __power_on_iris3(struct msm_vidc_core *core)
__interrupt_init_iris3(core); __interrupt_init_iris3(core);
core->intr_status = 0; core->intr_status = 0;
enable_irq(core->dt->irq); enable_irq(core->resource->irq);
return rc; return rc;

View File

@@ -9,7 +9,6 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_dt.h"
u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size) u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
{ {
@@ -27,9 +26,10 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return freq; return freq;
} }
core = inst->core; core = inst->core;
if (!core->dt || !core->dt->allowed_clks_tbl) {
if (!core->resource || !core->resource->freq_set.freq_tbl ||
!core->resource->freq_set.count) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return freq; return freq;
} }
@@ -151,8 +151,8 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
u32 bitrate_2stage[2] = {130, 120}; u32 bitrate_2stage[2] = {130, 120};
u32 bitrate_1stage = 100; u32 bitrate_1stage = 100;
u32 width, height; u32 width, height;
u32 bitrate_entry, freq_entry, frequency_table_value; u32 bitrate_entry, freq_entry, freq_tbl_value;
struct allowed_clock_rates_table *allowed_clks_tbl; struct frequency_table *freq_tbl;
struct v4l2_format *out_f = &inst->fmts[OUTPUT_PORT]; struct v4l2_format *out_f = &inst->fmts[OUTPUT_PORT];
width = out_f->fmt.pix_mp.width; width = out_f->fmt.pix_mp.width;
@@ -165,11 +165,11 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
freq_entry = bitrate_entry; freq_entry = bitrate_entry;
allowed_clks_tbl = core->dt->allowed_clks_tbl; freq_tbl = core->resource->freq_set.freq_tbl;
frequency_table_value = allowed_clks_tbl[freq_entry].clock_rate / 1000000; freq_tbl_value = freq_tbl[freq_entry].freq / 1000000;
input_bitrate_mbps = fps * data_size * 8 / (1024 * 1024); input_bitrate_mbps = fps * data_size * 8 / (1024 * 1024);
vsp_hw_min_frequency = frequency_table_value * 1000 * input_bitrate_mbps; vsp_hw_min_frequency = freq_tbl_value * 1000 * input_bitrate_mbps;
if (inst->capabilities->cap[STAGE].value == MSM_VIDC_STAGE_2) { if (inst->capabilities->cap[STAGE].value == MSM_VIDC_STAGE_2) {
vsp_hw_min_frequency += vsp_hw_min_frequency +=
@@ -233,9 +233,9 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
* for non-AV1 codecs limit the frequency to NOM only * for non-AV1 codecs limit the frequency to NOM only
* index 0 is TURBO, index 1 is NOM clock rate * index 0 is TURBO, index 1 is NOM clock rate
*/ */
if (core->dt->allowed_clks_tbl_size >= 2 && if (core->resource->freq_set.count >= 2 &&
freq > core->dt->allowed_clks_tbl[1].clock_rate) freq > core->resource->freq_set.freq_tbl[1].freq)
freq = core->dt->allowed_clks_tbl[1].clock_rate; freq = core->resource->freq_set.freq_tbl[1].freq;
} }
i_vpr_p(inst, "%s: filled len %d, required freq %llu, fps %u, mbpf %u\n", i_vpr_p(inst, "%s: filled len %d, required freq %llu, fps %u, mbpf %u\n",

View File

@@ -74,9 +74,8 @@ struct msm_vidc_core {
char fw_version[MAX_NAME_LENGTH]; char fw_version[MAX_NAME_LENGTH];
enum msm_vidc_core_state state; enum msm_vidc_core_state state;
struct mutex lock; struct mutex lock;
struct msm_vidc_dt *dt; struct msm_vidc_resource *resource;
struct msm_vidc_platform *platform; struct msm_vidc_platform *platform;
u8 __iomem *register_base_addr;
u32 intr_status; u32 intr_status;
u32 spur_count; u32 spur_count;
u32 reg_count; u32 reg_count;

View File

@@ -8,228 +8,5 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/soc/qcom/llcc-qcom.h> #include <linux/soc/qcom/llcc-qcom.h>
#ifdef CONFIG_MSM_MMRM
#include <linux/soc/qcom/msm_mmrm.h>
#endif
#include "msm_vidc_internal.h"
/*
* These are helper macros to iterate over various lists within
* msm_vidc_core->dt. The intention is to cut down on a lot of boiler-plate
* code
*/
/* Read as "for each 'thing' in a set of 'thingies'" */
#define venus_hfi_for_each_thing(__device, __thing, __thingy) \
venus_hfi_for_each_thing_continue(__device, __thing, __thingy, 0)
#define venus_hfi_for_each_thing_reverse(__device, __thing, __thingy) \
venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
(__device)->dt->__thingy##_set.count - 1)
/* TODO: the __from parameter technically not required since we can figure it
* out with some pointer magic (i.e. __thing - __thing##_tbl[0]). If this macro
* sees extensive use, probably worth cleaning it up but for now omitting it
* since it introduces unnecessary complexity.
*/
#define venus_hfi_for_each_thing_continue(__device, __thing, __thingy, __from) \
for (__thing = &(__device)->dt->\
__thingy##_set.__thingy##_tbl[__from]; \
__thing < &(__device)->dt->__thingy##_set.__thingy##_tbl[0] + \
((__device)->dt->__thingy##_set.count - __from); \
++__thing)
#define venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
__from) \
for (__thing = &(__device)->dt->\
__thingy##_set.__thingy##_tbl[__from]; \
__thing >= &(__device)->dt->__thingy##_set.__thingy##_tbl[0]; \
--__thing)
/* Regular set helpers */
#define venus_hfi_for_each_regulator(__device, __rinfo) \
venus_hfi_for_each_thing(__device, __rinfo, regulator)
#define venus_hfi_for_each_regulator_reverse(__device, __rinfo) \
venus_hfi_for_each_thing_reverse(__device, __rinfo, regulator)
#define venus_hfi_for_each_regulator_reverse_continue(__device, __rinfo, \
__from) \
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
regulator, __from)
/* Clock set helpers */
#define venus_hfi_for_each_clock(__device, __cinfo) \
venus_hfi_for_each_thing(__device, __cinfo, clock)
#define venus_hfi_for_each_clock_reverse(__device, __cinfo) \
venus_hfi_for_each_thing_reverse(__device, __cinfo, clock)
/* Bus set helpers */
#define venus_hfi_for_each_bus(__device, __binfo) \
venus_hfi_for_each_thing(__device, __binfo, bus)
#define venus_hfi_for_each_bus_reverse(__device, __binfo) \
venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
/* Subcache set helpers */
#define venus_hfi_for_each_subcache(__device, __sinfo) \
venus_hfi_for_each_thing(__device, __sinfo, subcache)
#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
struct reg_value_pair {
u32 reg;
u32 value;
u32 mask;
};
struct reg_set {
struct reg_value_pair *reg_tbl;
u32 count;
};
struct addr_range {
u32 start;
u32 size;
};
struct addr_set {
struct addr_range *addr_tbl;
u32 count;
};
struct context_bank_info {
struct list_head list;
const char *name;
bool is_secure;
struct addr_range addr_range;
struct device *dev;
struct iommu_domain *domain;
};
struct buffer_usage_table {
u32 buffer_type;
u32 tz_usage;
};
struct buffer_usage_set {
struct buffer_usage_table *buffer_usage_tbl;
u32 count;
};
struct regulator_info {
struct regulator *regulator;
bool has_hw_power_collapse;
char *name;
};
struct regulator_set {
struct regulator_info *regulator_tbl;
u32 count;
};
struct clock_info {
const char *name;
u32 clk_id;
struct clk *clk;
u32 count;
bool has_scaling;
bool has_mem_retention;
u64 prev;
#ifdef CONFIG_MSM_MMRM
struct mmrm_client *mmrm_client;
#endif
};
struct clock_set {
struct clock_info *clock_tbl;
u32 count;
};
struct bus_info {
const char *name;
u32 range[2];
struct device *dev;
struct icc_path *path;
};
struct bus_set {
struct bus_info *bus_tbl;
u32 count;
};
struct reset_info {
struct reset_control *rst;
const char *name;
};
struct reset_set {
struct reset_info *reset_tbl;
u32 count;
};
struct allowed_clock_rates_table {
u32 clock_rate;
};
struct clock_profile_entry {
u32 codec_mask;
u32 vpp_cycles;
u32 vsp_cycles;
u32 low_power_cycles;
};
struct clock_freq_table {
struct clock_profile_entry *clk_prof_entries;
u32 count;
};
struct subcache_info {
const char *name;
bool isactive;
bool isset;
struct llcc_slice_desc *subcache;
};
struct subcache_set {
struct subcache_info *subcache_tbl;
u32 count;
};
struct msm_vidc_dt {
void *core;
phys_addr_t register_base;
u32 register_size;
u32 irq;
struct allowed_clock_rates_table *allowed_clks_tbl;
u32 allowed_clks_tbl_size;
struct clock_freq_table clock_freq_tbl;
bool sys_cache_present;
bool sys_cache_res_set;
struct subcache_set subcache_set;
struct reg_set reg_set;
struct addr_set qdss_addr_set;
struct buffer_usage_set buffer_usage_set;
struct regulator_set regulator_set;
struct clock_set clock_set;
struct bus_set bus_set;
struct reset_set reset_set;
struct list_head context_banks;
struct mutex cb_lock;
const char *fw_name;
int fw_cookie;
};
int msm_vidc_init_dt(struct platform_device *pdev);
int msm_vidc_read_context_bank_resources_from_dt(struct platform_device *pdev);
void msm_vidc_deinit_dt(struct platform_device *pdev);
/* A comparator to compare loads (needed later on) */
static inline int cmp(const void *a, const void *b)
{
/* want to sort in reverse so flip the comparison */
return ((struct allowed_clock_rates_table *)b)->clock_rate -
((struct allowed_clock_rates_table *)a)->clock_rate;
}
#endif // _MSM_VIDC_DT_H_ #endif // _MSM_VIDC_DT_H_

View File

@@ -244,6 +244,7 @@ enum msm_vidc_buffer_region {
MSM_VIDC_SECURE_PIXEL, MSM_VIDC_SECURE_PIXEL,
MSM_VIDC_SECURE_NONPIXEL, MSM_VIDC_SECURE_NONPIXEL,
MSM_VIDC_SECURE_BITSTREAM, MSM_VIDC_SECURE_BITSTREAM,
MSM_VIDC_REGION_MAX,
}; };
enum msm_vidc_port_type { enum msm_vidc_port_type {
@@ -374,7 +375,6 @@ enum msm_vidc_core_capability_type {
CLK_FREQ_THRESHOLD, CLK_FREQ_THRESHOLD,
NON_FATAL_FAULTS, NON_FATAL_FAULTS,
ENC_AUTO_FRAMERATE, ENC_AUTO_FRAMERATE,
MMRM,
DEVICE_CAPS, DEVICE_CAPS,
SUPPORTS_REQUESTS, SUPPORTS_REQUESTS,
CORE_CAP_MAX, CORE_CAP_MAX,

View File

@@ -7,7 +7,6 @@
#define _MSM_VIDC_MEMORY_H_ #define _MSM_VIDC_MEMORY_H_
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#include "msm_vidc_dt.h"
struct msm_vidc_core; struct msm_vidc_core;
struct msm_vidc_inst; struct msm_vidc_inst;

View File

@@ -6,11 +6,199 @@
#ifndef _MSM_VIDC_RESOURCES_H_ #ifndef _MSM_VIDC_RESOURCES_H_
#define _MSM_VIDC_RESOURCES_H_ #define _MSM_VIDC_RESOURCES_H_
struct icc_path;
struct regulator;
struct clk;
struct reset_control;
struct llcc_slice_desc;
struct iommu_domain;
struct device;
struct msm_vidc_core; struct msm_vidc_core;
/*
* These are helper macros to iterate over various lists within
* msm_vidc_core->resource. The intention is to cut down on a lot of boiler-plate
* code
*/
/* Read as "for each 'thing' in a set of 'thingies'" */
#define venus_hfi_for_each_thing(__device, __thing, __thingy) \
venus_hfi_for_each_thing_continue(__device, __thing, __thingy, 0)
#define venus_hfi_for_each_thing_reverse(__device, __thing, __thingy) \
venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
(__device)->resource->__thingy##_set.count - 1)
/* TODO: the __from parameter technically not required since we can figure it
* out with some pointer magic (i.e. __thing - __thing##_tbl[0]). If this macro
* sees extensive use, probably worth cleaning it up but for now omitting it
* since it introduces unnecessary complexity.
*/
#define venus_hfi_for_each_thing_continue(__device, __thing, __thingy, __from) \
for (__thing = &(__device)->resource->\
__thingy##_set.__thingy##_tbl[__from]; \
__thing < &(__device)->resource->__thingy##_set.__thingy##_tbl[0] + \
((__device)->resource->__thingy##_set.count - __from); \
++__thing)
#define venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
__from) \
for (__thing = &(__device)->resource->\
__thingy##_set.__thingy##_tbl[__from]; \
__thing >= &(__device)->resource->__thingy##_set.__thingy##_tbl[0]; \
--__thing)
/* Bus set helpers */
#define venus_hfi_for_each_bus(__device, __binfo) \
venus_hfi_for_each_thing(__device, __binfo, bus)
#define venus_hfi_for_each_bus_reverse(__device, __binfo) \
venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
/* Regular set helpers */
#define venus_hfi_for_each_regulator(__device, __rinfo) \
venus_hfi_for_each_thing(__device, __rinfo, regulator)
#define venus_hfi_for_each_regulator_reverse(__device, __rinfo) \
venus_hfi_for_each_thing_reverse(__device, __rinfo, regulator)
#define venus_hfi_for_each_regulator_reverse_continue(__device, __rinfo, \
__from) \
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
regulator, __from)
/* Clock set helpers */
#define venus_hfi_for_each_clock(__device, __cinfo) \
venus_hfi_for_each_thing(__device, __cinfo, clock)
#define venus_hfi_for_each_clock_reverse(__device, __cinfo) \
venus_hfi_for_each_thing_reverse(__device, __cinfo, clock)
/* Reset clock set helpers */
#define venus_hfi_for_each_reset_clock(__device, __rcinfo) \
venus_hfi_for_each_thing(__device, __rcinfo, reset)
#define venus_hfi_for_each_reset_clock_reverse(__device, __rcinfo) \
venus_hfi_for_each_thing_reverse(__device, __rcinfo, reset)
#define venus_hfi_for_each_reset_clock_reverse_continue(__device, __rinfo, \
__from) \
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
reset, __from)
/* Subcache set helpers */
#define venus_hfi_for_each_subcache(__device, __sinfo) \
venus_hfi_for_each_thing(__device, __sinfo, subcache)
#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
/* Contextbank set helpers */
#define venus_hfi_for_each_context_bank(__device, __sinfo) \
venus_hfi_for_each_thing(__device, __sinfo, context_bank)
#define venus_hfi_for_each_context_bank_reverse(__device, __sinfo) \
venus_hfi_for_each_thing_reverse(__device, __sinfo, context_bank)
struct bus_info {
struct icc_path *icc;
const char *name;
u32 min_kbps;
u32 max_kbps;
};
struct bus_set {
struct bus_info *bus_tbl;
u32 count;
};
struct regulator_info {
struct regulator *regulator;
const char *name;
bool hw_power_collapse;
};
struct regulator_set {
struct regulator_info *regulator_tbl;
u32 count;
};
struct clock_info {
struct clk *clk;
const char *name;
u32 clk_id;
bool has_scaling;
u64 prev;
#ifdef CONFIG_MSM_MMRM
struct mmrm_client *mmrm_client;
#endif
};
struct clock_set {
struct clock_info *clock_tbl;
u32 count;
};
struct reset_info {
struct reset_control *rst;
const char *name;
};
struct reset_set {
struct reset_info *reset_tbl;
u32 count;
};
struct subcache_info {
struct llcc_slice_desc *subcache;
const char *name;
u32 llcc_id;
bool isactive;
};
struct subcache_set {
struct subcache_info *subcache_tbl;
u32 count;
bool set_to_fw;
};
struct addr_range {
u32 start;
u32 size;
};
struct context_bank_info {
const char *name;
struct addr_range addr_range;
bool secure;
bool dma_coherant;
struct device *dev;
struct iommu_domain *domain;
u32 region;
};
struct context_bank_set {
struct context_bank_info *context_bank_tbl;
u32 count;
};
struct frequency_table {
unsigned long freq;
};
struct freq_set {
struct frequency_table *freq_tbl;
u32 count;
};
struct msm_vidc_resource {
void *core;
u8 __iomem *register_base_addr;
u32 irq;
struct bus_set bus_set;
struct regulator_set regulator_set;
struct clock_set clock_set;
struct reset_set reset_set;
struct subcache_set subcache_set;
struct context_bank_set context_bank_set;
struct freq_set freq_set;
int fw_cookie;
};
struct msm_vidc_resources_ops { struct msm_vidc_resources_ops {
int (*get)(struct msm_vidc_core *core); int (*init)(struct msm_vidc_core *core);
void (*put)(struct msm_vidc_core *core);
int (*reset_bridge)(struct msm_vidc_core *core); int (*reset_bridge)(struct msm_vidc_core *core);

View File

@@ -12,9 +12,9 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_events.h" #include "msm_vidc_events.h"
#include "firmware.h" #include "firmware.h"
#include "msm_vidc_platform.h"
#define MAX_FIRMWARE_NAME_SIZE 128 #define MAX_FIRMWARE_NAME_SIZE 128
@@ -45,15 +45,15 @@ static int protect_cp_mem(struct msm_vidc_core *core)
memprot.cp_nonpixel_start = 0x0; memprot.cp_nonpixel_start = 0x0;
memprot.cp_nonpixel_size = 0x0; memprot.cp_nonpixel_size = 0x0;
list_for_each_entry(cb, &core->dt->context_banks, list) { venus_hfi_for_each_context_bank(core, cb) {
if (!strcmp(cb->name, "venus_ns")) { if (cb->region == MSM_VIDC_NON_SECURE) {
memprot.cp_size = cb->addr_range.start; memprot.cp_size = cb->addr_range.start;
d_vpr_h("%s: memprot.cp_size: %#x\n", d_vpr_h("%s: memprot.cp_size: %#x\n",
__func__, memprot.cp_size); __func__, memprot.cp_size);
} }
if (!strcmp(cb->name, "venus_sec_non_pixel")) { if (cb->region == MSM_VIDC_SECURE_NONPIXEL) {
memprot.cp_nonpixel_start = cb->addr_range.start; memprot.cp_nonpixel_start = cb->addr_range.start;
memprot.cp_nonpixel_size = cb->addr_range.size; memprot.cp_nonpixel_size = cb->addr_range.size;
@@ -65,7 +65,6 @@ static int protect_cp_mem(struct msm_vidc_core *core)
rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size, rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size,
memprot.cp_nonpixel_start, memprot.cp_nonpixel_size); memprot.cp_nonpixel_start, memprot.cp_nonpixel_size);
if (rc) if (rc)
d_vpr_e("Failed to protect memory(%d)\n", rc); d_vpr_e("Failed to protect memory(%d)\n", rc);
@@ -81,6 +80,7 @@ static int __load_fw_to_memory(struct platform_device *pdev,
{ {
int rc = 0; int rc = 0;
const struct firmware *firmware = NULL; const struct firmware *firmware = NULL;
struct msm_vidc_core *core;
char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 }; char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 };
struct device_node *node = NULL; struct device_node *node = NULL;
struct resource res = { 0 }; struct resource res = { 0 };
@@ -98,14 +98,16 @@ static int __load_fw_to_memory(struct platform_device *pdev,
d_vpr_e("%s: Invalid fw name\n", __func__); d_vpr_e("%s: Invalid fw name\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = dev_get_drvdata(&pdev->dev);
if (!core) {
d_vpr_e("%s: core not found in device %s",
__func__, dev_name(&pdev->dev));
return -EINVAL;
}
scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name); scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name);
rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id); pas_id = core->platform->data.pas_id;
if (rc) {
d_vpr_e("%s: failed to read \"pas-id\". error %d\n",
__func__, rc);
goto exit;
}
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
if (!node) { if (!node) {
@@ -182,13 +184,13 @@ int fw_load(struct msm_vidc_core *core)
{ {
int rc; int rc;
if (!core->dt->fw_cookie) { if (!core->resource->fw_cookie) {
core->dt->fw_cookie = __load_fw_to_memory(core->pdev, core->resource->fw_cookie = __load_fw_to_memory(core->pdev,
core->dt->fw_name); core->platform->data.fwname);
if (core->dt->fw_cookie <= 0) { if (core->resource->fw_cookie <= 0) {
d_vpr_e("%s: firmware download failed %d\n", d_vpr_e("%s: firmware download failed %d\n",
__func__, core->dt->fw_cookie); __func__, core->resource->fw_cookie);
core->dt->fw_cookie = 0; core->resource->fw_cookie = 0;
return -ENOMEM; return -ENOMEM;
} }
} }
@@ -202,9 +204,9 @@ int fw_load(struct msm_vidc_core *core)
return rc; return rc;
fail_protect_mem: fail_protect_mem:
if (core->dt->fw_cookie) if (core->resource->fw_cookie)
qcom_scm_pas_shutdown(core->dt->fw_cookie); qcom_scm_pas_shutdown(core->resource->fw_cookie);
core->dt->fw_cookie = 0; core->resource->fw_cookie = 0;
return rc; return rc;
} }
@@ -212,14 +214,14 @@ int fw_unload(struct msm_vidc_core *core)
{ {
int ret; int ret;
if (!core->dt->fw_cookie) if (!core->resource->fw_cookie)
return -EINVAL; return -EINVAL;
ret = qcom_scm_pas_shutdown(core->dt->fw_cookie); ret = qcom_scm_pas_shutdown(core->resource->fw_cookie);
if (ret) if (ret)
d_vpr_e("Firmware unload failed rc=%d\n", ret); d_vpr_e("Firmware unload failed rc=%d\n", ret);
core->dt->fw_cookie = 0; core->resource->fw_cookie = 0;
return ret; return ret;
} }

View File

@@ -5,7 +5,6 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_dt.h"
#include "msm_vidc.h" #include "msm_vidc.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_inst.h" #include "msm_vidc_inst.h"
@@ -209,7 +208,7 @@ static ssize_t core_info_read(struct file* file, char __user* buf,
ssize_t len = 0; ssize_t len = 0;
int rc = 0; int rc = 0;
if (!core || !core->dt) { if (!core || !core->resource) {
d_vpr_e("%s: invalid params %pK\n", __func__, core); d_vpr_e("%s: invalid params %pK\n", __func__, core);
return 0; return 0;
} }
@@ -226,10 +225,8 @@ static ssize_t core_info_read(struct file* file, char __user* buf,
cur += write_str(cur, end - cur, cur += write_str(cur, end - cur,
"FW version : %s\n", core->fw_version); "FW version : %s\n", core->fw_version);
cur += write_str(cur, end - cur, cur += write_str(cur, end - cur,
"register_base: 0x%x\n", core->dt->register_base); "register_base: 0x%x\n", core->resource->register_base_addr);
cur += write_str(cur, end - cur, cur += write_str(cur, end - cur, "irq: %u\n", core->resource->irq);
"register_size: %u\n", core->dt->register_size);
cur += write_str(cur, end - cur, "irq: %u\n", core->dt->irq);
len = simple_read_from_buffer(buf, count, ppos, len = simple_read_from_buffer(buf, count, ppos,
dbuf, cur - dbuf); dbuf, cur - dbuf);

View File

@@ -7,976 +7,3 @@
#include <linux/dma-iommu.h> #include <linux/dma-iommu.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/sort.h> #include <linux/sort.h>
#include "msm_vidc_debug.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_internal.h"
#include "msm_vidc_core.h"
#include "msm_vidc_driver.h"
static size_t get_u32_array_num_elements(struct device_node *np,
char *name)
{
int len;
size_t num_elements = 0;
if (!of_get_property(np, name, &len)) {
d_vpr_e("Failed to read %s from device tree\n", name);
goto fail_read;
}
num_elements = len / sizeof(u32);
if (num_elements <= 0) {
d_vpr_e("%s not specified in device tree\n", name);
goto fail_read;
}
return num_elements;
fail_read:
return 0;
}
/**
* msm_vidc_load_u32_table() - load dtsi table entries
* @pdev: A pointer to the platform device.
* @of_node: A pointer to the device node.
* @table_name: A pointer to the dtsi table entry name.
* @struct_size: The size of the structure which is nothing but
* a single entry in the dtsi table.
* @table: A pointer to the table pointer which needs to be
* filled by the dtsi table entries.
* @num_elements: Number of elements pointer which needs to be filled
* with the number of elements in the table.
*
* This is a generic implementation to load single or multiple array
* table from dtsi. The array elements should be of size equal to u32.
*
* Return: Return '0' for success else appropriate error value.
*/
static int msm_vidc_load_u32_table(struct platform_device *pdev,
struct device_node *of_node, char *table_name, int struct_size,
u32 **table, u32 *num_elements)
{
int rc = 0, num_elemts = 0;
u32 *ptbl = NULL;
if (!of_find_property(of_node, table_name, NULL)) {
d_vpr_h("%s not found\n", table_name);
return 0;
}
num_elemts = get_u32_array_num_elements(of_node, table_name);
if (!num_elemts) {
d_vpr_e("no elements in %s\n", table_name);
return 0;
}
num_elemts /= struct_size / sizeof(u32);
ptbl = devm_kzalloc(&pdev->dev, num_elemts * struct_size, GFP_KERNEL);
if (!ptbl) {
d_vpr_e("Failed to alloc table %s\n", table_name);
return -ENOMEM;
}
if (of_property_read_u32_array(of_node, table_name, ptbl,
num_elemts * struct_size / sizeof(u32))) {
d_vpr_e("Failed to read %s\n", table_name);
return -EINVAL;
}
*table = ptbl;
if (num_elements)
*num_elements = num_elemts;
return rc;
}
static void msm_vidc_free_allowed_clocks_table(struct msm_vidc_dt *dt)
{
dt->allowed_clks_tbl = NULL;
}
static void msm_vidc_free_reg_table(struct msm_vidc_dt *dt)
{
dt->reg_set.reg_tbl = NULL;
}
static void msm_vidc_free_qdss_addr_table(struct msm_vidc_dt *dt)
{
dt->qdss_addr_set.addr_tbl = NULL;
}
static void msm_vidc_free_bus_table(struct msm_vidc_dt *dt)
{
dt->bus_set.bus_tbl = NULL;
dt->bus_set.count = 0;
}
static void msm_vidc_free_buffer_usage_table(struct msm_vidc_dt *dt)
{
dt->buffer_usage_set.buffer_usage_tbl = NULL;
}
static void msm_vidc_free_regulator_table(struct msm_vidc_dt *dt)
{
int c = 0;
for (c = 0; c < dt->regulator_set.count; ++c) {
struct regulator_info *rinfo =
&dt->regulator_set.regulator_tbl[c];
rinfo->name = NULL;
}
dt->regulator_set.regulator_tbl = NULL;
dt->regulator_set.count = 0;
}
static void msm_vidc_free_clock_table(struct msm_vidc_dt *dt)
{
dt->clock_set.clock_tbl = NULL;
dt->clock_set.count = 0;
}
static int msm_vidc_load_fw_name(struct msm_vidc_core *core)
{
struct platform_device *pdev = core->pdev;
return of_property_read_string_index(pdev->dev.of_node,
"vidc,firmware-name", 0, &core->dt->fw_name);
}
static int msm_vidc_load_reg_table(struct msm_vidc_core *core)
{
struct reg_set *reg_set;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
int i;
int rc = 0;
if (!of_find_property(pdev->dev.of_node, "qcom,reg-presets", NULL)) {
/*
* qcom,reg-presets is an optional property. It likely won't be
* present if we don't have any register settings to program
*/
d_vpr_h("reg-presets not found\n");
return 0;
}
reg_set = &dt->reg_set;
reg_set->count = get_u32_array_num_elements(pdev->dev.of_node,
"qcom,reg-presets");
reg_set->count /= sizeof(*reg_set->reg_tbl) / sizeof(u32);
if (!reg_set->count) {
d_vpr_h("no elements in reg set\n");
return rc;
}
reg_set->reg_tbl = devm_kzalloc(&pdev->dev, reg_set->count *
sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
if (!reg_set->reg_tbl) {
d_vpr_e("%s: Failed to alloc register table\n", __func__);
return -ENOMEM;
}
if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
(u32 *)reg_set->reg_tbl, reg_set->count * 3)) {
d_vpr_e("Failed to read register table\n");
msm_vidc_free_reg_table(core->dt);
return -EINVAL;
}
for (i = 0; i < reg_set->count; i++) {
d_vpr_h("reg = %#x, value = %#x, mask = %#x\n",
reg_set->reg_tbl[i].reg, reg_set->reg_tbl[i].value,
reg_set->reg_tbl[i].mask);
}
return rc;
}
static int msm_vidc_load_qdss_table(struct msm_vidc_core *core)
{
struct addr_set *qdss_addr_set;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
int i;
int rc = 0;
if (!of_find_property(pdev->dev.of_node, "qcom,qdss-presets", NULL)) {
/*
* qcom,qdss-presets is an optional property. It likely won't be
* present if we don't have any register settings to program
*/
d_vpr_h("qdss-presets not found\n");
return rc;
}
qdss_addr_set = &dt->qdss_addr_set;
qdss_addr_set->count = get_u32_array_num_elements(pdev->dev.of_node,
"qcom,qdss-presets");
qdss_addr_set->count /= sizeof(*qdss_addr_set->addr_tbl) / sizeof(u32);
if (!qdss_addr_set->count) {
d_vpr_h("no elements in qdss reg set\n");
return rc;
}
qdss_addr_set->addr_tbl = devm_kzalloc(&pdev->dev,
qdss_addr_set->count * sizeof(*qdss_addr_set->addr_tbl),
GFP_KERNEL);
if (!qdss_addr_set->addr_tbl) {
d_vpr_e("%s: Failed to alloc register table\n", __func__);
rc = -ENOMEM;
goto err_qdss_addr_tbl;
}
rc = of_property_read_u32_array(pdev->dev.of_node, "qcom,qdss-presets",
(u32 *)qdss_addr_set->addr_tbl, qdss_addr_set->count * 2);
if (rc) {
d_vpr_e("Failed to read qdss address table\n");
msm_vidc_free_qdss_addr_table(core->dt);
rc = -EINVAL;
goto err_qdss_addr_tbl;
}
for (i = 0; i < qdss_addr_set->count; i++) {
d_vpr_h("qdss addr = %x, value = %x\n",
qdss_addr_set->addr_tbl[i].start,
qdss_addr_set->addr_tbl[i].size);
}
err_qdss_addr_tbl:
return rc;
}
static int msm_vidc_load_subcache_info(struct msm_vidc_core *core)
{
int rc = 0, num_subcaches = 0, c;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
struct subcache_set *subcaches = &dt->subcache_set;
num_subcaches = of_property_count_strings(pdev->dev.of_node,
"cache-slice-names");
if (num_subcaches <= 0) {
d_vpr_h("No subcaches found\n");
goto err_load_subcache_table_fail;
}
subcaches->subcache_tbl = devm_kzalloc(&pdev->dev,
sizeof(*subcaches->subcache_tbl) * num_subcaches, GFP_KERNEL);
if (!subcaches->subcache_tbl) {
d_vpr_e("Failed to allocate memory for subcache tbl\n");
rc = -ENOMEM;
goto err_load_subcache_table_fail;
}
subcaches->count = num_subcaches;
d_vpr_h("Found %d subcaches\n", num_subcaches);
for (c = 0; c < num_subcaches; ++c) {
struct subcache_info *vsc = &dt->subcache_set.subcache_tbl[c];
of_property_read_string_index(pdev->dev.of_node,
"cache-slice-names", c, &vsc->name);
}
dt->sys_cache_present = true;
return 0;
err_load_subcache_table_fail:
dt->sys_cache_present = false;
subcaches->count = 0;
subcaches->subcache_tbl = NULL;
return rc;
}
static int msm_vidc_load_allowed_clocks_table(
struct msm_vidc_core *core)
{
int rc = 0;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
int i;
if (!of_find_property(pdev->dev.of_node,
"qcom,allowed-clock-rates", NULL)) {
d_vpr_h("allowed-clock-rates not found\n");
return 0;
}
rc = msm_vidc_load_u32_table(pdev, pdev->dev.of_node,
"qcom,allowed-clock-rates",
sizeof(*dt->allowed_clks_tbl),
(u32 **)&dt->allowed_clks_tbl,
&dt->allowed_clks_tbl_size);
if (rc) {
d_vpr_e("%s: failed to read allowed clocks table\n", __func__);
return rc;
}
sort(dt->allowed_clks_tbl, dt->allowed_clks_tbl_size,
sizeof(*dt->allowed_clks_tbl), cmp, NULL);
d_vpr_h("Found allowed clock rates\n");
for (i = 0; i < dt->allowed_clks_tbl_size; i++)
d_vpr_h(" %d\n", dt->allowed_clks_tbl[i].clock_rate);
return 0;
}
static int msm_vidc_load_bus_table(struct msm_vidc_core *core)
{
int rc = 0;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
struct bus_set *buses = &dt->bus_set;
int c = 0, num_buses = 0;
u32 *bus_ranges = NULL;
num_buses = of_property_count_strings(pdev->dev.of_node,
"interconnect-names");
if (num_buses <= 0) {
d_vpr_e("No buses found\n");
return -EINVAL;
}
buses->count = num_buses;
d_vpr_h("Found %d bus interconnects\n", num_buses);
rc = msm_vidc_vmem_alloc(2 * num_buses * sizeof(*bus_ranges),
(void **)&bus_ranges, " for bus ranges");
if (rc)
return rc;
rc = of_property_read_u32_array(pdev->dev.of_node,
"qcom,bus-range-kbps", bus_ranges,
num_buses * 2);
if (rc) {
d_vpr_e(
"Failed to read bus ranges: defaulting to <0 INT_MAX>\n");
for (c = 0; c < num_buses; c++) {
bus_ranges[c * 2] = 0;
bus_ranges[c * 2 + 1] = INT_MAX;
}
}
buses->bus_tbl = devm_kzalloc(&pdev->dev, num_buses *
sizeof(*buses->bus_tbl), GFP_KERNEL);
if (!buses->bus_tbl) {
d_vpr_e("No memory for bus table\n");
rc = -ENOMEM;
goto exit;
}
for (c = 0; c < num_buses; c++) {
struct bus_info *bus = &dt->bus_set.bus_tbl[c];
of_property_read_string_index(pdev->dev.of_node,
"interconnect-names", c, &bus->name);
bus->dev = &pdev->dev;
bus->range[0] = bus_ranges[c * 2];
bus->range[1] = bus_ranges[c * 2 + 1];
d_vpr_h("Found bus %s, range [%d %d]\n", bus->name,
bus->range[0], bus->range[1]);
}
exit:
msm_vidc_vmem_free((void **) &bus_ranges);
return rc;
}
/* TODO: move this to platform data */
static int msm_vidc_load_buffer_usage_table(struct msm_vidc_core *core)
{
int rc = 0;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
struct buffer_usage_set *buffer_usage_set = &dt->buffer_usage_set;
if (!of_find_property(pdev->dev.of_node,
"qcom,buffer-type-tz-usage-table", NULL)) {
/*
* qcom,buffer-type-tz-usage-table is an optional property. It
* likely won't be present if the core doesn't support content
* protection
*/
d_vpr_h("buffer-type-tz-usage-table not found\n");
return 0;
}
buffer_usage_set->count = get_u32_array_num_elements(
pdev->dev.of_node, "qcom,buffer-type-tz-usage-table");
buffer_usage_set->count /=
sizeof(*buffer_usage_set->buffer_usage_tbl) / sizeof(u32);
if (!buffer_usage_set->count) {
d_vpr_h("no elements in buffer usage set\n");
return 0;
}
buffer_usage_set->buffer_usage_tbl = devm_kzalloc(&pdev->dev,
buffer_usage_set->count *
sizeof(*buffer_usage_set->buffer_usage_tbl),
GFP_KERNEL);
if (!buffer_usage_set->buffer_usage_tbl) {
d_vpr_e("%s: Failed to alloc buffer usage table\n",
__func__);
rc = -ENOMEM;
goto err_load_buf_usage;
}
rc = of_property_read_u32_array(pdev->dev.of_node,
"qcom,buffer-type-tz-usage-table",
(u32 *)buffer_usage_set->buffer_usage_tbl,
buffer_usage_set->count *
sizeof(*buffer_usage_set->buffer_usage_tbl) / sizeof(u32));
if (rc) {
d_vpr_e("Failed to read buffer usage table\n");
goto err_load_buf_usage;
}
return 0;
err_load_buf_usage:
msm_vidc_free_buffer_usage_table(core->dt);
return rc;
}
static int msm_vidc_load_regulator_table(struct msm_vidc_core *core)
{
int rc = 0;
struct platform_device *pdev = core->pdev;
struct msm_vidc_dt *dt = core->dt;
struct regulator_set *regulators = &dt->regulator_set;
struct device_node *domains_parent_node = NULL;
struct property *domains_property = NULL;
int reg_count = 0;
regulators->count = 0;
regulators->regulator_tbl = NULL;
domains_parent_node = pdev->dev.of_node;
for_each_property_of_node(domains_parent_node, domains_property) {
const char *search_string = "-supply";
char *supply;
bool matched = false;
/* check if current property is possibly a regulator */
supply = strnstr(domains_property->name, search_string,
strlen(domains_property->name) + 1);
matched = supply && (*(supply + strlen(search_string)) == '\0');
if (!matched)
continue;
reg_count++;
}
regulators->regulator_tbl = devm_kzalloc(&pdev->dev,
sizeof(*regulators->regulator_tbl) *
reg_count, GFP_KERNEL);
if (!regulators->regulator_tbl) {
rc = -ENOMEM;
d_vpr_e("Failed to alloc memory for regulator table\n");
goto err_reg_tbl_alloc;
}
for_each_property_of_node(domains_parent_node, domains_property) {
const char *search_string = "-supply";
char *supply;
bool matched = false;
struct device_node *regulator_node = NULL;
struct regulator_info *rinfo = NULL;
/* check if current property is possibly a regulator */
supply = strnstr(domains_property->name, search_string,
strlen(domains_property->name) + 1);
matched = supply && (supply[strlen(search_string)] == '\0');
if (!matched)
continue;
/* make sure prop isn't being misused */
regulator_node = of_parse_phandle(domains_parent_node,
domains_property->name, 0);
if (IS_ERR(regulator_node)) {
d_vpr_e("%s is not a phandle\n",
domains_property->name);
continue;
}
regulators->count++;
/* populate regulator info */
rinfo = &regulators->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;
}

View File

@@ -16,6 +16,7 @@
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_events.h" #include "msm_vidc_events.h"
#include "msm_vidc_platform.h"
#include "venus_hfi.h" #include "venus_hfi.h"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0))
@@ -30,27 +31,15 @@ struct msm_vidc_buf_region_name {
struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core, struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core,
enum msm_vidc_buffer_region region) enum msm_vidc_buffer_region region)
{ {
const char *name;
struct context_bank_info *cb = NULL, *match = NULL; struct context_bank_info *cb = NULL, *match = NULL;
static const struct msm_vidc_buf_region_name buf_region_name[] = {
{MSM_VIDC_REGION_NONE, "none" },
{MSM_VIDC_NON_SECURE, "venus_ns" },
{MSM_VIDC_NON_SECURE_PIXEL, "venus_ns_pixel" },
{MSM_VIDC_SECURE_PIXEL, "venus_sec_pixel" },
{MSM_VIDC_SECURE_NONPIXEL, "venus_sec_non_pixel" },
{MSM_VIDC_SECURE_BITSTREAM, "venus_sec_bitstream" },
};
if (!region || region > ARRAY_SIZE(buf_region_name)) if (!region || region >= MSM_VIDC_REGION_MAX) {
goto exit; d_vpr_e("Invalid region %#x\n", region);
return NULL;
}
if (buf_region_name[region].region != region) venus_hfi_for_each_context_bank(core, cb) {
goto exit; if (cb->region == region) {
name = buf_region_name[region].name;
list_for_each_entry(cb, &core->dt->context_banks, list) {
if (!strcmp(cb->name, name)) {
match = cb; match = cb;
break; break;
} }
@@ -59,10 +48,6 @@ struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core,
d_vpr_e("cb not found for region %#x\n", region); d_vpr_e("cb not found for region %#x\n", region);
return match; return match;
exit:
d_vpr_e("Invalid region %#x\n", region);
return NULL;
} }
struct dma_buf *msm_vidc_memory_get_dmabuf(struct msm_vidc_inst *inst, int fd) struct dma_buf *msm_vidc_memory_get_dmabuf(struct msm_vidc_inst *inst, int fd)
@@ -245,7 +230,7 @@ int msm_vidc_memory_map(struct msm_vidc_core *core, struct msm_vidc_map *map)
* required buffer size * required buffer size
*/ */
attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
if (core->dt->sys_cache_present) if (is_sys_cache_present(core))
attach->dma_map_attrs |= attach->dma_map_attrs |=
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT; DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;

View File

@@ -9,7 +9,6 @@
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#include "msm_vidc_inst.h" #include "msm_vidc_inst.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
#include "msm_vidc_buffer.h" #include "msm_vidc_buffer.h"
@@ -92,7 +91,7 @@ void __dump(struct dump dump[], int len)
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst) u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
{ {
struct msm_vidc_core* core; struct msm_vidc_core* core;
struct allowed_clock_rates_table *allowed_clks_tbl; struct frequency_table *freq_tbl;
u64 freq = 0; u64 freq = 0;
if (!inst || !inst->core) { if (!inst || !inst->core) {
@@ -100,12 +99,14 @@ u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
return freq; return freq;
} }
core = inst->core; core = inst->core;
if (!core->dt || !core->dt->allowed_clks_tbl) {
i_vpr_e(inst, "%s: invalid params\n", __func__); if (!core->resource || !core->resource->freq_set.freq_tbl ||
!core->resource->freq_set.count) {
i_vpr_e(inst, "%s: invalid frequency table\n", __func__);
return freq; return freq;
} }
allowed_clks_tbl = core->dt->allowed_clks_tbl; freq_tbl = core->resource->freq_set.freq_tbl;
freq = allowed_clks_tbl[0].clock_rate; freq = freq_tbl[0].freq;
i_vpr_l(inst, "%s: rate = %llu\n", __func__, freq); i_vpr_l(inst, "%s: rate = %llu\n", __func__, freq);
return freq; return freq;
@@ -267,8 +268,8 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
core = inst->core; core = inst->core;
if (!core->dt) { if (!core->resource) {
i_vpr_e(inst, "%s: invalid dt params\n", __func__); i_vpr_e(inst, "%s: invalid resource params\n", __func__);
return -EINVAL; return -EINVAL;
} }
vote_data = &inst->bus_data; vote_data = &inst->bus_data;
@@ -347,7 +348,7 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
} }
} }
vote_data->work_mode = inst->capabilities->cap[STAGE].value; vote_data->work_mode = inst->capabilities->cap[STAGE].value;
if (core->dt->sys_cache_res_set) if (core->resource->subcache_set.set_to_fw)
vote_data->use_sys_cache = true; vote_data->use_sys_cache = true;
vote_data->num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value; vote_data->num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
fill_dynamic_stats(inst, vote_data); fill_dynamic_stats(inst, vote_data);
@@ -382,8 +383,10 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
return -EINVAL; return -EINVAL;
} }
core = inst->core; core = inst->core;
if (!core->dt || !core->dt->allowed_clks_tbl) {
d_vpr_e("%s: invalid dt params\n", __func__); if (!core->resource || !core->resource->freq_set.freq_tbl ||
!core->resource->freq_set.count) {
d_vpr_e("%s: invalid frequency table\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -422,8 +425,8 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
* keep checking from lowest to highest rate until * keep checking from lowest to highest rate until
* table rate >= requested rate * table rate >= requested rate
*/ */
for (i = core->dt->allowed_clks_tbl_size - 1; i >= 0; i--) { for (i = core->resource->freq_set.count - 1; i >= 0; i--) {
rate = core->dt->allowed_clks_tbl[i].clock_rate; rate = core->resource->freq_set.freq_tbl[i].freq;
if (rate >= freq) if (rate >= freq)
break; break;
} }
@@ -431,10 +434,10 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
i = 0; i = 0;
if (increment) { if (increment) {
if (i > 0) if (i > 0)
rate = core->dt->allowed_clks_tbl[i - 1].clock_rate; rate = core->resource->freq_set.freq_tbl[i - 1].freq;
} else if (decrement) { } else if (decrement) {
if (i < (int) (core->dt->allowed_clks_tbl_size - 1)) if (i < (int) (core->platform->data.freq_tbl_size - 1))
rate = core->dt->allowed_clks_tbl[i + 1].clock_rate; rate = core->resource->freq_set.freq_tbl[i + 1].freq;
} }
core->power.clk_freq = (u32)rate; core->power.clk_freq = (u32)rate;

View File

@@ -10,11 +10,15 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iommu.h>
#include <linux/dma-iommu.h>
#ifdef CONFIG_MSM_MMRM
#include <linux/soc/qcom/msm_mmrm.h>
#endif
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_dt.h"
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_memory.h" #include "msm_vidc_memory.h"
@@ -28,62 +32,50 @@ struct msm_vidc_core *g_core;
const char video_banner[] = "Video-Banner: (" VIDEO_COMPILE_BY "@" const char video_banner[] = "Video-Banner: (" VIDEO_COMPILE_BY "@"
VIDEO_COMPILE_HOST ") (" VIDEO_COMPILE_TIME ")"; VIDEO_COMPILE_HOST ") (" VIDEO_COMPILE_TIME ")";
static int msm_vidc_deinit_irq(struct msm_vidc_core *core) static inline bool is_video_device(struct device *dev)
{ {
struct msm_vidc_dt *dt; return !!(of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc") ||
of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
if (!core || !core->pdev || !core->dt) { of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2") ||
d_vpr_e("%s: invalid params\n", __func__); of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc"));
return -EINVAL;
}
dt = core->dt;
d_vpr_h("%s: reg_base = %pa, reg_size = %#x\n",
__func__, &dt->register_base, dt->register_size);
dt->irq = 0;
if (core->register_base_addr)
devm_iounmap(&core->pdev->dev, core->register_base_addr);
core->register_base_addr = 0;
return 0;
} }
static int msm_vidc_init_irq(struct msm_vidc_core *core) static inline bool is_video_context_bank_device(struct device *dev)
{ {
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"));
}
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; int rc = 0;
struct msm_vidc_dt *dt;
if (!core || !core->pdev || !core->dt) { if (!core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
dt = core->dt; res_ops = core->res_ops;
core->register_base_addr = devm_ioremap(&core->pdev->dev, res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
dt->register_base, dt->register_size); if (!res) {
if (!core->register_base_addr) { d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
d_vpr_e("could not map reg addr %pa of size %d\n", return -ENOMEM;
&dt->register_base, dt->register_size);
rc = -EINVAL;
goto exit;
} }
res->core = core;
core->resource = res;
rc = devm_request_threaded_irq(&core->pdev->dev, dt->irq, venus_hfi_isr, rc = res_ops->init(core);
venus_hfi_isr_handler, IRQF_TRIGGER_HIGH, "msm-vidc", core);
if (rc) { if (rc) {
d_vpr_e("%s: Failed to allocate venus IRQ\n", __func__); d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
goto exit; return rc;
} }
disable_irq_nosync(dt->irq);
d_vpr_h("%s: reg_base = %pa, reg_size = %d\n",
__func__, &dt->register_base, dt->register_size);
return 0; return 0;
exit:
msm_vidc_deinit_irq(core);
return rc;
} }
static ssize_t sku_version_show(struct device *dev, static ssize_t sku_version_show(struct device *dev,
@@ -95,8 +87,7 @@ static ssize_t sku_version_show(struct device *dev,
* Default sku version: 0 * Default sku version: 0
* driver possibly not probed yet or not the main device. * driver possibly not probed yet or not the main device.
*/ */
if (!dev || !dev->driver || if (!dev || !dev->driver)
!of_device_is_compatible(dev->of_node, "qcom,msm-vidc"))
return 0; return 0;
core = dev_get_drvdata(dev); core = dev_get_drvdata(dev);
@@ -121,8 +112,15 @@ static struct attribute_group msm_vidc_core_attr_group = {
}; };
static const struct of_device_id msm_vidc_dt_match[] = { static const struct of_device_id msm_vidc_dt_match[] = {
{.compatible = "qcom,msm-vidc"}, {.compatible = "qcom,sm8450-vidc"},
{.compatible = "qcom,msm-vidc,context-bank"}, {.compatible = "qcom,sm8550-vidc"},
{.compatible = "qcom,sm8550-vidc-v2"},
{.compatible = "qcom,sm8650-vidc"},
{.compatible = "qcom,vidc,cb-ns-pxl"},
{.compatible = "qcom,vidc,cb-ns"},
{.compatible = "qcom,vidc,cb-sec-non-pxl"},
{.compatible = "qcom,vidc,cb-sec-bitstream"},
{.compatible = "qcom,vidc,cb-sec-pxl"},
MSM_VIDC_EMPTY_BRACE MSM_VIDC_EMPTY_BRACE
}; };
MODULE_DEVICE_TABLE(of, msm_vidc_dt_match); MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
@@ -137,7 +135,7 @@ static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
{ {
int index; int index;
d_vpr_h("%s()\n", __func__); d_vpr_h("%s: domain %d\n", __func__, type);
if (type == MSM_VIDC_DECODER) if (type == MSM_VIDC_DECODER)
index = 0; index = 0;
@@ -163,7 +161,7 @@ static int msm_vidc_register_video_device(struct msm_vidc_core *core,
int rc = 0; int rc = 0;
int index, media_index; int index, media_index;
d_vpr_h("%s()\n", __func__); d_vpr_h("%s: domain %d\n", __func__, type);
if (!core || !core->capabilities) { if (!core || !core->capabilities) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
@@ -236,32 +234,32 @@ static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
{ {
int rc = 0; int rc = 0;
if (!core || !core->capabilities) { if (!core || !core->platform) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (!core->capabilities[MMRM].value) if (!is_mmrm_supported(core))
goto exit; goto exit;
if (!mmrm_client_check_scaling_supported(MMRM_CLIENT_CLOCK, 0)) { if (!mmrm_client_check_scaling_supported(MMRM_CLIENT_CLOCK, 0)) {
d_vpr_e("%s: MMRM not supported\n", __func__); d_vpr_e("%s: MMRM not supported\n", __func__);
core->capabilities[MMRM].value = 0; core->platform->data.supports_mmrm = 0;
} }
exit: exit:
d_vpr_h("%s: %d\n", __func__, core->capabilities[MMRM].value); d_vpr_h("%s: %d\n", __func__, is_mmrm_supported(core));
return rc; return rc;
} }
#else #else
static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core) static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
{ {
if (!core || !core->capabilities) { if (!core || !core->platform) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core->capabilities[MMRM].value = 0; core->platform->data.supports_mmrm = 0;
return 0; return 0;
} }
@@ -358,6 +356,83 @@ exit:
return rc; return rc;
} }
static struct context_bank_info *get_context_bank(
struct msm_vidc_core *core, struct device *dev)
{
struct context_bank_info *cb = NULL, *match = NULL;
if (!core || !dev) {
d_vpr_e("%s: invalid params\n", __func__);
return NULL;
}
venus_hfi_for_each_context_bank(core, cb) {
if (of_device_is_compatible(dev->of_node, cb->name)) {
match = cb;
break;
}
}
if (!match)
d_vpr_e("cb not found for dev %s\n", dev_name(dev));
return match;
}
static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
struct device *dev)
{
struct context_bank_info *cb = NULL;
int rc = 0;
if (!core || !dev) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
cb = get_context_bank(core, dev);
if (!cb) {
d_vpr_e("%s: Failed to get context bank device for %s\n",
__func__, dev_name(dev));
return -EIO;
}
/* populate dev & domain field */
cb->dev = dev;
cb->domain = iommu_get_domain_for_dev(cb->dev);
/*
* When memory is fragmented, below configuration increases the
* possibility to get a mapping for buffer in the configured CB.
*/
/* remove kernel version condition once below api is whitelisted in pineapple */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
iommu_dma_enable_best_fit_algo(cb->dev);
#endif
/*
* configure device segment size and segment boundary to ensure
* iommu mapping returns one mapping (which is required for partial
* cache operations)
*/
if (!dev->dma_parms)
dev->dma_parms =
devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
iommu_set_fault_handler(cb->domain,
msm_vidc_smmu_fault_handler, (void *)core);
d_vpr_h(
"%s: name %s addr start %x size %x secure %d dma_coherant %d region %d dev_name %s domain %pK\n",
__func__, cb->name, cb->addr_range.start,
cb->addr_range.size, cb->secure, cb->dma_coherant,
cb->region, dev_name(cb->dev), cb->domain);
return rc;
}
static int msm_vidc_component_compare_of(struct device *dev, void *data) static int msm_vidc_component_compare_of(struct device *dev, void *data)
{ {
return dev->of_node == data; return dev->of_node == data;
@@ -372,8 +447,35 @@ static void msm_vidc_component_release_of(struct device *dev, void *data)
static int msm_vidc_component_cb_bind(struct device *dev, static int msm_vidc_component_cb_bind(struct device *dev,
struct device *master, void *data) struct device *master, void *data)
{ {
d_vpr_h("%s(): %s\n", __func__, dev_name(dev)); struct msm_vidc_core *core;
return 0; int rc = 0;
if (!dev) {
d_vpr_e("%s: invalid device\n", __func__);
return -EINVAL;
} else if (!dev->parent) {
d_vpr_e("%s: failed to find a parent for %s\n",
__func__, dev_name(dev));
return -ENODEV;
}
core = dev_get_drvdata(dev->parent);
if (!core) {
d_vpr_e("%s: failed to find cookie in parent device %s",
__func__, dev_name(dev->parent));
return -EINVAL;
}
rc = msm_vidc_setup_context_bank(core, dev);
if (rc) {
d_vpr_e("%s: Failed to probe context bank - %s\n",
__func__, dev_name(dev));
return rc;
}
d_vpr_h("%s: Successfully probed context bank - %s\n",
__func__, dev_name(dev));
return rc;
} }
static void msm_vidc_component_cb_unbind(struct device *dev, static void msm_vidc_component_cb_unbind(struct device *dev,
@@ -391,7 +493,7 @@ static int msm_vidc_component_bind(struct device *dev)
rc = component_bind_all(dev, core); rc = component_bind_all(dev, core);
if (rc) { if (rc) {
d_vpr_e("%s: sub-device bind failed\n", __func__); d_vpr_e("%s: sub-device bind failed. rc %d\n", __func__, rc);
return rc; return rc;
} }
@@ -464,7 +566,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
d_vpr_h("depopulating sub devices\n"); d_vpr_h("depopulating sub devices\n");
/* /*
* Trigger remove for each sub-device i.e. qcom,msm-vidc,context-bank. * Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
* When msm_vidc_remove is called for each sub-device, destroy * When msm_vidc_remove is called for each sub-device, destroy
* context-bank mappings. * context-bank mappings.
*/ */
@@ -488,9 +590,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
msm_vidc_deinit_instance_caps(core); msm_vidc_deinit_instance_caps(core);
msm_vidc_deinit_core_caps(core); msm_vidc_deinit_core_caps(core);
msm_vidc_deinit_irq(core);
msm_vidc_deinit_platform(pdev); msm_vidc_deinit_platform(pdev);
msm_vidc_deinit_dt(pdev);
msm_vidc_deinitialize_core(core); msm_vidc_deinitialize_core(core);
dev_set_drvdata(&pdev->dev, NULL); dev_set_drvdata(&pdev->dev, NULL);
@@ -504,8 +604,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
static int msm_vidc_remove_context_bank(struct platform_device *pdev) static int msm_vidc_remove_context_bank(struct platform_device *pdev)
{ {
d_vpr_h("%s(): Detached %s and destroyed mapping\n", d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
__func__, dev_name(&pdev->dev));
component_del(&pdev->dev, &msm_vidc_component_cb_ops); component_del(&pdev->dev, &msm_vidc_component_cb_ops);
@@ -519,12 +618,10 @@ static int msm_vidc_remove(struct platform_device *pdev)
* after core_deinit(). It return immediately after completing * after core_deinit(). It return immediately after completing
* sub-device remove. * sub-device remove.
*/ */
if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-vidc")) { if (is_video_device(&pdev->dev))
return msm_vidc_remove_video_device(pdev); return msm_vidc_remove_video_device(pdev);
} else if (of_device_is_compatible(pdev->dev.of_node, else if (is_video_context_bank_device(&pdev->dev))
"qcom,msm-vidc,context-bank")) {
return msm_vidc_remove_context_bank(pdev); return msm_vidc_remove_context_bank(pdev);
}
/* How did we end up here? */ /* How did we end up here? */
WARN_ON(1); WARN_ON(1);
@@ -539,7 +636,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
struct device_node *child = NULL; struct device_node *child = NULL;
int sub_device_count = 0, nr = BASE_DEVICE_NUMBER; int sub_device_count = 0, nr = BASE_DEVICE_NUMBER;
d_vpr_h("%s()\n", __func__); d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
rc = msm_vidc_vmem_alloc(sizeof(*core), (void **)&core, __func__); rc = msm_vidc_vmem_alloc(sizeof(*core), (void **)&core, __func__);
if (rc) if (rc)
@@ -559,13 +656,6 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
goto init_core_failed; goto init_core_failed;
} }
rc = msm_vidc_init_dt(pdev);
if (rc) {
d_vpr_e("%s: init dt failed with %d\n", __func__, rc);
rc = -EINVAL;
goto init_dt_failed;
}
rc = msm_vidc_init_platform(pdev); rc = msm_vidc_init_platform(pdev);
if (rc) { if (rc) {
d_vpr_e("%s: init platform failed with %d\n", __func__, rc); d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
@@ -573,16 +663,16 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
goto init_plat_failed; goto init_plat_failed;
} }
rc = msm_vidc_init_irq(core); rc = msm_vidc_init_resources(core);
if (rc) { if (rc) {
d_vpr_e("%s: init irq failed with %d\n", __func__, rc); d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
goto init_irq_failed; goto init_res_failed;
} }
rc = msm_vidc_init_core_caps(core); rc = msm_vidc_init_core_caps(core);
if (rc) { if (rc) {
d_vpr_e("%s: init core caps failed with %d\n", __func__, rc); d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
goto init_core_caps_fail; goto init_res_failed;
} }
rc = msm_vidc_init_instance_caps(core); rc = msm_vidc_init_instance_caps(core);
@@ -659,8 +749,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
/* /*
* Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank. * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
* When msm_vidc_probe is called for each sub-device, parse the * When msm_vidc_probe is called for each sub-device, parse the
* context-bank details and store it in core->resources.context_banks * context-bank details.
* list.
*/ */
rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL, rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
&pdev->dev); &pdev->dev);
@@ -698,13 +787,9 @@ init_group_failed:
msm_vidc_deinit_instance_caps(core); msm_vidc_deinit_instance_caps(core);
init_inst_caps_fail: init_inst_caps_fail:
msm_vidc_deinit_core_caps(core); msm_vidc_deinit_core_caps(core);
init_core_caps_fail: init_res_failed:
msm_vidc_deinit_irq(core);
init_irq_failed:
msm_vidc_deinit_platform(pdev); msm_vidc_deinit_platform(pdev);
init_plat_failed: init_plat_failed:
msm_vidc_deinit_dt(pdev);
init_dt_failed:
msm_vidc_deinitialize_core(core); msm_vidc_deinitialize_core(core);
init_core_failed: init_core_failed:
dev_set_drvdata(&pdev->dev, NULL); dev_set_drvdata(&pdev->dev, NULL);
@@ -717,13 +802,7 @@ init_core_failed:
static int msm_vidc_probe_context_bank(struct platform_device *pdev) static int msm_vidc_probe_context_bank(struct platform_device *pdev)
{ {
int rc = 0; d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
d_vpr_h("%s()\n", __func__);
rc = msm_vidc_read_context_bank_resources_from_dt(pdev);
if (rc)
return rc;
return component_add(&pdev->dev, &msm_vidc_component_cb_ops); return component_add(&pdev->dev, &msm_vidc_component_cb_ops);
} }
@@ -737,12 +816,10 @@ static int msm_vidc_probe(struct platform_device *pdev)
* the end of the probe function after msm-vidc device probe is * the end of the probe function after msm-vidc device probe is
* completed. Return immediately after completing sub-device probe. * completed. Return immediately after completing sub-device probe.
*/ */
if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-vidc")) { if (is_video_device(&pdev->dev))
return msm_vidc_probe_video_device(pdev); return msm_vidc_probe_video_device(pdev);
} else if (of_device_is_compatible(pdev->dev.of_node, else if (is_video_context_bank_device(&pdev->dev))
"qcom,msm-vidc,context-bank")) {
return msm_vidc_probe_context_bank(pdev); return msm_vidc_probe_context_bank(pdev);
}
/* How did we end up here? */ /* How did we end up here? */
WARN_ON(1); WARN_ON(1);
@@ -760,8 +837,7 @@ static int msm_vidc_pm_suspend(struct device *dev)
* - not the main device. We don't support power management on * - not the main device. We don't support power management on
* subdevices (e.g. context banks) * subdevices (e.g. context banks)
*/ */
if (!dev || !dev->driver || if (!dev || !dev->driver || !is_video_device(dev))
!of_device_is_compatible(dev->of_node, "qcom,msm-vidc"))
return 0; return 0;
core = dev_get_drvdata(dev); core = dev_get_drvdata(dev);
@@ -792,8 +868,7 @@ static int msm_vidc_pm_resume(struct device *dev)
* - not the main device. We don't support power management on * - not the main device. We don't support power management on
* subdevices (e.g. context banks) * subdevices (e.g. context banks)
*/ */
if (!dev || !dev->driver || if (!dev || !dev->driver || !is_video_device(dev))
!of_device_is_compatible(dev->of_node, "qcom,msm-vidc"))
return 0; return 0;
core = dev_get_drvdata(dev); core = dev_get_drvdata(dev);

View File

@@ -16,7 +16,7 @@
#include "msm_venc.h" #include "msm_venc.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_control.h" #include "msm_vidc_control.h"
#include "msm_vidc_dt.h" #include "msm_vidc_platform.h"
extern struct msm_vidc_core *g_core; extern struct msm_vidc_core *g_core;
@@ -101,7 +101,7 @@ void *msm_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
buf->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; buf->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
buf->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; buf->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP;
if (core->dt->sys_cache_present) if (is_sys_cache_present(core))
buf->attach->dma_map_attrs |= buf->attach->dma_map_attrs |=
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT; DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/qcom_scm.h> #include <linux/qcom_scm.h>
#include <linux/soc/qcom/mdt_loader.h> #include <linux/soc/qcom/mdt_loader.h>
#include <linux/soc/qcom/llcc-qcom.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include "venus_hfi.h" #include "venus_hfi.h"
@@ -63,11 +64,6 @@ bool __core_in_valid_state(struct msm_vidc_core *core)
return core->state != MSM_VIDC_CORE_DEINIT; return core->state != MSM_VIDC_CORE_DEINIT;
} }
static bool is_sys_cache_present(struct msm_vidc_core *core)
{
return core->dt->sys_cache_present;
}
static bool __valdiate_session(struct msm_vidc_core *core, static bool __valdiate_session(struct msm_vidc_core *core,
struct msm_vidc_inst *inst, const char *func) struct msm_vidc_inst *inst, const char *func)
{ {
@@ -394,7 +390,7 @@ static int __release_subcaches(struct msm_vidc_core *core)
if (msm_vidc_syscache_disable || !is_sys_cache_present(core)) if (msm_vidc_syscache_disable || !is_sys_cache_present(core))
return 0; return 0;
if (!core->dt->sys_cache_res_set) { if (!core->resource->subcache_set.set_to_fw) {
d_vpr_h("Subcaches not set to Venus\n"); d_vpr_h("Subcaches not set to Venus\n");
return 0; return 0;
} }
@@ -409,7 +405,9 @@ static int __release_subcaches(struct msm_vidc_core *core)
buf.flags = HFI_BUF_HOST_FLAG_RELEASE; buf.flags = HFI_BUF_HOST_FLAG_RELEASE;
venus_hfi_for_each_subcache_reverse(core, sinfo) { venus_hfi_for_each_subcache_reverse(core, sinfo) {
if (sinfo->isactive) { if (!sinfo->isactive)
continue;
buf.index = sinfo->subcache->slice_id; buf.index = sinfo->subcache->slice_id;
buf.buffer_size = sinfo->subcache->slice_size; buf.buffer_size = sinfo->subcache->slice_size;
@@ -425,7 +423,6 @@ static int __release_subcaches(struct msm_vidc_core *core)
if (rc) if (rc)
return rc; return rc;
} }
}
/* Set resource to Venus for activated subcaches */ /* Set resource to Venus for activated subcaches */
rc = __cmdq_write(core, core->packet); rc = __cmdq_write(core, core->packet);
@@ -433,15 +430,14 @@ static int __release_subcaches(struct msm_vidc_core *core)
return rc; return rc;
venus_hfi_for_each_subcache_reverse(core, sinfo) { venus_hfi_for_each_subcache_reverse(core, sinfo) {
if (sinfo->isactive) { if (!sinfo->isactive)
sinfo->isset = false; continue;
d_vpr_h("Release Subcache id %d size %lu done\n",
sinfo->subcache->slice_id, d_vpr_h("%s: release Subcache id %d size %lu done\n",
__func__, sinfo->subcache->slice_id,
sinfo->subcache->slice_size); sinfo->subcache->slice_size);
} }
} core->resource->subcache_set.set_to_fw = false;
core->dt->sys_cache_res_set = false;
return 0; return 0;
} }
@@ -458,7 +454,7 @@ static int __set_subcaches(struct msm_vidc_core *core)
return 0; return 0;
} }
if (core->dt->sys_cache_res_set) { if (core->resource->subcache_set.set_to_fw) {
d_vpr_h("Subcaches already set to Venus\n"); d_vpr_h("Subcaches already set to Venus\n");
return 0; return 0;
} }
@@ -473,7 +469,8 @@ static int __set_subcaches(struct msm_vidc_core *core)
buf.flags = HFI_BUF_HOST_FLAG_NONE; buf.flags = HFI_BUF_HOST_FLAG_NONE;
venus_hfi_for_each_subcache(core, sinfo) { venus_hfi_for_each_subcache(core, sinfo) {
if (sinfo->isactive) { if (!sinfo->isactive)
continue;
buf.index = sinfo->subcache->slice_id; buf.index = sinfo->subcache->slice_id;
buf.buffer_size = sinfo->subcache->slice_size; buf.buffer_size = sinfo->subcache->slice_size;
@@ -489,7 +486,6 @@ static int __set_subcaches(struct msm_vidc_core *core)
if (rc) if (rc)
goto err_fail_set_subacaches; goto err_fail_set_subacaches;
} }
}
/* Set resource to Venus for activated subcaches */ /* Set resource to Venus for activated subcaches */
rc = __cmdq_write(core, core->packet); rc = __cmdq_write(core, core->packet);
@@ -497,15 +493,13 @@ static int __set_subcaches(struct msm_vidc_core *core)
goto err_fail_set_subacaches; goto err_fail_set_subacaches;
venus_hfi_for_each_subcache(core, sinfo) { venus_hfi_for_each_subcache(core, sinfo) {
if (sinfo->isactive) { if (!sinfo->isactive)
sinfo->isset = true; continue;
d_vpr_h("Set Subcache id %d size %lu done\n", d_vpr_h("%s: set Subcache id %d size %lu done\n",
sinfo->subcache->slice_id, __func__, sinfo->subcache->slice_id,
sinfo->subcache->slice_size); sinfo->subcache->slice_size);
} }
} core->resource->subcache_set.set_to_fw = true;
core->dt->sys_cache_res_set = true;
return 0; return 0;
@@ -699,16 +693,10 @@ int __load_fw(struct msm_vidc_core *core)
core->cpu_watchdog = false; core->cpu_watchdog = false;
trace_msm_v4l2_vidc_fw_load("START"); trace_msm_v4l2_vidc_fw_load("START");
rc = res_ops->get(core);
if (rc) {
d_vpr_e("%s: Failed to get resources: %d\n", __func__, rc);
goto fail_init_res;
}
rc = __venus_power_on(core); rc = __venus_power_on(core);
if (rc) { if (rc) {
d_vpr_e("%s: power on failed\n", __func__); d_vpr_e("%s: power on failed\n", __func__);
goto fail_venus_power_on; goto fail_power;
} }
rc = fw_load(core); rc = fw_load(core);
@@ -727,25 +715,21 @@ int __load_fw(struct msm_vidc_core *core)
return rc; return rc;
fail_load_fw: fail_load_fw:
__venus_power_off(core); __venus_power_off(core);
fail_venus_power_on: fail_power:
res_ops->put(core);
fail_init_res:
trace_msm_v4l2_vidc_fw_load("END"); trace_msm_v4l2_vidc_fw_load("END");
return rc; return rc;
} }
void __unload_fw(struct msm_vidc_core *core) void __unload_fw(struct msm_vidc_core *core)
{ {
const struct msm_vidc_resources_ops *res_ops = core->res_ops;
int rc = 0; int rc = 0;
if (!core->dt->fw_cookie) if (!core->resource->fw_cookie)
return; return;
cancel_delayed_work(&core->pm_work); cancel_delayed_work(&core->pm_work);
rc = fw_unload(core); rc = fw_unload(core);
__venus_power_off(core); __venus_power_off(core);
res_ops->put(core);
core->cpu_watchdog = false; core->cpu_watchdog = false;