diff options
Diffstat (limited to 'drivers/media/platform/qcom/venus')
-rw-r--r-- | drivers/media/platform/qcom/venus/core.c | 20 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/core.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/dbgfs.c | 9 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/dbgfs.h | 13 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/helpers.c | 6 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_cmds.c | 9 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_cmds.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_helper.h | 20 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_parser.c | 6 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_platform.c | 22 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_platform.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/hfi_venus.c | 26 |
12 files changed, 129 insertions, 7 deletions
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 877eca125803..990a1519f968 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -265,6 +265,19 @@ static void venus_assign_register_offsets(struct venus_core *core) } } +static irqreturn_t venus_isr_thread(int irq, void *dev_id) +{ + struct venus_core *core = dev_id; + irqreturn_t ret; + + ret = hfi_isr_thread(irq, dev_id); + + if (ret == IRQ_HANDLED && venus_fault_inject_ssr()) + hfi_core_trigger_ssr(core, HFI_TEST_SSR_SW_ERR_FATAL); + + return ret; +} + static int venus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -320,7 +333,7 @@ static int venus_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&core->work, venus_sys_error_handler); init_waitqueue_head(&core->sys_err_done); - ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, hfi_isr_thread, + ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "venus", core); if (ret) @@ -832,6 +845,10 @@ static const struct reg_val sm7280_reg_preset[] = { { 0xb0088, 0 }, }; +static const struct hfi_ubwc_config sc7280_ubwc_config = { + 0, 0, {1, 1, 1, 0, 0, 0}, 8, 32, 14, 0, 0, {0, 0} +}; + static const struct venus_resources sc7280_res = { .freq_tbl = sc7280_freq_table, .freq_tbl_size = ARRAY_SIZE(sc7280_freq_table), @@ -841,6 +858,7 @@ static const struct venus_resources sc7280_res = { .bw_tbl_enc_size = ARRAY_SIZE(sc7280_bw_table_enc), .bw_tbl_dec = sc7280_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sc7280_bw_table_dec), + .ubwc_conf = &sc7280_ubwc_config, .clks = {"core", "bus", "iface"}, .clks_num = 3, .vcodec0_clks = {"vcodec_core", "vcodec_bus"}, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index d33825553edc..32551c2602a9 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -16,6 +16,7 @@ #include "dbgfs.h" #include "hfi.h" #include "hfi_platform.h" +#include "hfi_helper.h" #define VDBGL "VenusLow : " #define VDBGM "VenusMed : " @@ -57,6 +58,7 @@ struct venus_resources { unsigned int bw_tbl_dec_size; const struct reg_val *reg_tbl; unsigned int reg_tbl_size; + const struct hfi_ubwc_config *ubwc_conf; const char * const clks[VIDC_CLKS_NUM_MAX]; unsigned int clks_num; const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX]; diff --git a/drivers/media/platform/qcom/venus/dbgfs.c b/drivers/media/platform/qcom/venus/dbgfs.c index 52de47f2ca88..726f4b730e69 100644 --- a/drivers/media/platform/qcom/venus/dbgfs.c +++ b/drivers/media/platform/qcom/venus/dbgfs.c @@ -4,13 +4,22 @@ */ #include <linux/debugfs.h> +#include <linux/fault-inject.h> #include "core.h" +#ifdef CONFIG_FAULT_INJECTION +DECLARE_FAULT_ATTR(venus_ssr_attr); +#endif + void venus_dbgfs_init(struct venus_core *core) { core->root = debugfs_create_dir("venus", NULL); debugfs_create_x32("fw_level", 0644, core->root, &venus_fw_debug); + +#ifdef CONFIG_FAULT_INJECTION + fault_create_debugfs_attr("fail_ssr", core->root, &venus_ssr_attr); +#endif } void venus_dbgfs_deinit(struct venus_core *core) diff --git a/drivers/media/platform/qcom/venus/dbgfs.h b/drivers/media/platform/qcom/venus/dbgfs.h index b7b621a8472f..c87c1355d039 100644 --- a/drivers/media/platform/qcom/venus/dbgfs.h +++ b/drivers/media/platform/qcom/venus/dbgfs.h @@ -4,8 +4,21 @@ #ifndef __VENUS_DBGFS_H__ #define __VENUS_DBGFS_H__ +#include <linux/fault-inject.h> + struct venus_core; +#ifdef CONFIG_FAULT_INJECTION +extern struct fault_attr venus_ssr_attr; +static inline bool venus_fault_inject_ssr(void) +{ + return should_fail(&venus_ssr_attr, 1); +} +#else +static inline bool venus_fault_inject_ssr(void) { return false; } +#endif + + void venus_dbgfs_init(struct venus_core *core); void venus_dbgfs_deinit(struct venus_core *core); diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 5c1104379c49..60de4200375d 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -671,8 +671,7 @@ int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, unsigned int i; int ret; - if (req) - memset(req, 0, sizeof(*req)); + memset(req, 0, sizeof(*req)); if (type == HFI_BUFFER_OUTPUT || type == HFI_BUFFER_OUTPUT2) req->count_min = inst->fw_min_cnt; @@ -694,8 +693,7 @@ int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, if (hprop.bufreq[i].type != type) continue; - if (req) - memcpy(req, &hprop.bufreq[i], sizeof(*req)); + memcpy(req, &hprop.bufreq[i], sizeof(*req)); ret = 0; break; } diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 4ecd444050bb..930b743f225e 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -58,6 +58,15 @@ void pkt_sys_coverage_config(struct hfi_sys_set_property_pkt *pkt, u32 mode) pkt->data[1] = mode; } +void pkt_sys_ubwc_config(struct hfi_sys_set_property_pkt *pkt, const struct hfi_ubwc_config *hfi) +{ + pkt->hdr.size = struct_size(pkt, data, 1) + sizeof(*hfi); + pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; + pkt->num_properties = 1; + pkt->data[0] = HFI_PROPERTY_SYS_UBWC_CONFIG; + memcpy(&pkt->data[1], hfi, sizeof(*hfi)); +} + int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt, u32 id, u32 size, u32 addr, void *cookie) { diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index 327ed90a2788..99bc0b6db67c 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -256,6 +256,7 @@ void pkt_sys_init(struct hfi_sys_init_pkt *pkt, u32 arch_type); void pkt_sys_pc_prep(struct hfi_sys_pc_prep_pkt *pkt); void pkt_sys_idle_indicator(struct hfi_sys_set_property_pkt *pkt, u32 enable); void pkt_sys_power_control(struct hfi_sys_set_property_pkt *pkt, u32 enable); +void pkt_sys_ubwc_config(struct hfi_sys_set_property_pkt *pkt, const struct hfi_ubwc_config *hfi); int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt, u32 id, u32 size, u32 addr, void *cookie); int pkt_sys_unset_resource(struct hfi_sys_release_resource_pkt *pkt, u32 id, diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 2daa88e3df9f..d2d6719a2ba4 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -427,6 +427,7 @@ #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 #define HFI_PROPERTY_SYS_CONFIG_COVERAGE 0x7 +#define HFI_PROPERTY_SYS_UBWC_CONFIG 0x8 /* * HFI_PROPERTY_PARAM_COMMON_START @@ -626,6 +627,25 @@ struct hfi_debug_config { u32 mode; }; +struct hfi_ubwc_config { + u32 size; + u32 packet_type; + struct { + u32 max_channel_override : 1; + u32 mal_length_override : 1; + u32 hb_override : 1; + u32 bank_swzl_level_override : 1; + u32 bank_spreading_override : 1; + u32 reserved : 27; + } override_bit_info; + u32 max_channels; + u32 mal_length; + u32 highest_bank_bit; + u32 bank_swzl_level; + u32 bank_spreading; + u32 reserved[2]; +}; + struct hfi_enable { u32 enable; }; diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 5b8389b98299..6cf74b2bc5ae 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -234,6 +234,7 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) const struct hfi_plat_caps *caps = NULL; u32 enc_codecs, dec_codecs, count = 0; unsigned int entries; + int ret; plat = hfi_platform_get(core->res->hfi_version); if (!plat) @@ -242,8 +243,9 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) if (inst) return 0; - if (plat->codecs) - plat->codecs(&enc_codecs, &dec_codecs, &count); + ret = hfi_platform_get_codecs(core, &enc_codecs, &dec_codecs, &count); + if (ret) + return ret; if (plat->capabilities) caps = plat->capabilities(&entries); diff --git a/drivers/media/platform/qcom/venus/hfi_platform.c b/drivers/media/platform/qcom/venus/hfi_platform.c index f16f8962273c..f07f554bc5fe 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.c +++ b/drivers/media/platform/qcom/venus/hfi_platform.c @@ -2,7 +2,9 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +#include <linux/of_device.h> #include "hfi_platform.h" +#include "core.h" const struct hfi_platform *hfi_platform_get(enum hfi_version version) { @@ -66,3 +68,23 @@ hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_ return freq; } +int +hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, u32 *count) +{ + const struct hfi_platform *plat; + + plat = hfi_platform_get(core->res->hfi_version); + if (!plat) + return -EINVAL; + + if (plat->codecs) + plat->codecs(enc_codecs, dec_codecs, count); + + if (of_device_is_compatible(core->dev->of_node, "qcom,sc7280-venus")) { + *enc_codecs &= ~HFI_VIDEO_CODEC_VP8; + *dec_codecs &= ~HFI_VIDEO_CODEC_VP8; + } + + return 0; +} + diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h index 1dcf4085928c..ec89a90a8129 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.h +++ b/drivers/media/platform/qcom/venus/hfi_platform.h @@ -66,4 +66,6 @@ unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 code u32 session_type); unsigned long hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_type); +int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, + u32 *count); #endif diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 9a34662fea38..2ad40b3945b0 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -904,6 +904,24 @@ static int venus_sys_set_power_control(struct venus_hfi_device *hdev, return 0; } +static int venus_sys_set_ubwc_config(struct venus_hfi_device *hdev) +{ + struct hfi_sys_set_property_pkt *pkt; + u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; + const struct venus_resources *res = hdev->core->res; + int ret; + + pkt = (struct hfi_sys_set_property_pkt *)packet; + + pkt_sys_ubwc_config(pkt, res->ubwc_conf); + + ret = venus_iface_cmdq_write(hdev, pkt, false); + if (ret) + return ret; + + return 0; +} + static int venus_get_queue_size(struct venus_hfi_device *hdev, unsigned int index) { @@ -922,6 +940,7 @@ static int venus_get_queue_size(struct venus_hfi_device *hdev, static int venus_sys_set_default_properties(struct venus_hfi_device *hdev) { struct device *dev = hdev->core->dev; + const struct venus_resources *res = hdev->core->res; int ret; ret = venus_sys_set_debug(hdev, venus_fw_debug); @@ -945,6 +964,13 @@ static int venus_sys_set_default_properties(struct venus_hfi_device *hdev) dev_warn(dev, "setting hw power collapse ON failed (%d)\n", ret); + /* For specific venus core, it is mandatory to set the UBWC configuration */ + if (res->ubwc_conf) { + ret = venus_sys_set_ubwc_config(hdev); + if (ret) + dev_warn(dev, "setting ubwc config failed (%d)\n", ret); + } + return ret; } |