From 852608fcc3f877490c0cf59f8155efc7d34b434c Mon Sep 17 00:00:00 2001 From: Chinmay Sawarkar Date: Wed, 13 Jan 2021 17:45:43 -0800 Subject: [PATCH] waipio: driver: Add support for fw unload and power collapse If required, Firmware can be unloaded after every session. Power collapse is enabled by default. Change-Id: Ie014a26ae600816d8713cd34826f1f9a77088e4a Signed-off-by: Chinmay Sawarkar --- driver/platform/waipio/src/msm_vidc_waipio.c | 6 +-- driver/vidc/inc/msm_vidc_driver.h | 3 +- driver/vidc/src/msm_vidc.c | 6 +++ driver/vidc/src/msm_vidc_driver.c | 47 +++++++++++++++++--- driver/vidc/src/venus_hfi_response.c | 2 +- 5 files changed, 52 insertions(+), 12 deletions(-) diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index fde836d1dd..ecb58aada1 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -61,10 +61,10 @@ static struct msm_platform_core_capability core_data_waipio[] = { {MAX_MBPF_B_FRAME, 32640}, /* 3840x2176/256 */ {MAX_MBPS_B_FRAME, 1958400}, /* 3840x2176/256 MBs@60fps */ {NUM_VPP_PIPE, 4}, - {SW_PC, 0}, - {SW_PC_DELAY, 1500}, /* 1500 ms */ + {SW_PC, 1}, + {SW_PC_DELAY, 20000}, /* 20000 ms (>HW_RESPONSE_TIMEOUT)*/ {FW_UNLOAD, 0}, - {FW_UNLOAD_DELAY, 1000}, /* 1000 ms */ + {FW_UNLOAD_DELAY, 25000}, /* 25000 ms (>PC_DELAY)*/ {HW_RESPONSE_TIMEOUT, 15000}, /* 1000 ms */ {DEBUG_TIMEOUT, 0}, // TODO: review below entries, and if required rename as PREFETCH diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index fef4fb7454..f8100a3314 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -226,7 +226,7 @@ int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst); int msm_vidc_change_core_state(struct msm_vidc_core *core, enum msm_vidc_core_state request_state, const char *func); int msm_vidc_core_init(struct msm_vidc_core *core); -int msm_vidc_core_deinit(struct msm_vidc_core *core); +int msm_vidc_core_deinit(struct msm_vidc_core *core, bool force); int msm_vidc_core_timeout(struct msm_vidc_core *core); int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *data); @@ -298,5 +298,6 @@ void inst_lock(struct msm_vidc_inst *inst, const char *function); void inst_unlock(struct msm_vidc_inst *inst, const char *function); bool inst_lock_check(struct msm_vidc_inst *inst, const char *function); int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst); +void msm_vidc_schedule_core_deinit(struct msm_vidc_core *core); #endif // _MSM_VIDC_DRIVER_H_ diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 31cbe069e2..47739399dc 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -817,11 +817,15 @@ int msm_vidc_close(void *instance) { int rc = 0; struct msm_vidc_inst *inst = instance; + struct msm_vidc_core *core; if (!inst) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + + core = inst->core; + s_vpr_h(inst->sid, "%s()\n", __func__); mutex_lock(&inst->lock); msm_vidc_session_close(inst); @@ -829,6 +833,8 @@ int msm_vidc_close(void *instance) msm_vidc_destroy_buffers(inst); mutex_unlock(&inst->lock); put_inst(inst); + msm_vidc_schedule_core_deinit(core); + return rc; } EXPORT_SYMBOL(msm_vidc_close); diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 9dad8957bc..a6517e1c27 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -442,11 +442,6 @@ int msm_vidc_change_core_state(struct msm_vidc_core *core, return -EINVAL; } - if (!request_state) { - d_vpr_e("%s: invalid core request state\n", func); - return -EINVAL; - } - d_vpr_h("%s: core state changed from %s to %s\n", func, core_state_name(core->state), core_state_name(request_state)); @@ -2457,7 +2452,7 @@ error: return rc; } -int msm_vidc_core_deinit(struct msm_vidc_core *core) +int msm_vidc_core_deinit(struct msm_vidc_core *core, bool force) { int rc = 0; struct msm_vidc_inst *inst, *dummy; @@ -2466,10 +2461,14 @@ int msm_vidc_core_deinit(struct msm_vidc_core *core) d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + mutex_lock(&core->lock); d_vpr_h("%s()\n", __func__); if (core->state == MSM_VIDC_CORE_DEINIT) goto unlock; + if (!force) + if (!list_empty(&core->instances)) + goto unlock; venus_hfi_core_deinit(core); msm_vidc_deinit_instance_caps(core); @@ -2542,7 +2541,7 @@ unlock: int msm_vidc_core_timeout(struct msm_vidc_core *core) { - return msm_vidc_core_deinit(core); + return msm_vidc_core_deinit(core, true); } int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, @@ -2567,6 +2566,20 @@ void msm_vidc_pm_work_handler(struct work_struct *work) void msm_vidc_fw_unload_handler(struct work_struct *work) { + struct msm_vidc_core *core = NULL; + int rc = 0; + + core = container_of(work, struct msm_vidc_core, fw_unload_work.work); + if (!core) { + d_vpr_e("%s: invalid work or core handle\n", __func__); + return; + } + + d_vpr_h("%s: deinitializing video core\n",__func__); + rc = msm_vidc_core_deinit(core, false); + if (rc) + d_vpr_e("%s: Failed to deinit core\n", __func__); + } void msm_vidc_batch_handler(struct work_struct *work) @@ -2811,3 +2824,23 @@ int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst) } return 0; } + +void msm_vidc_schedule_core_deinit(struct msm_vidc_core *core) +{ + if (!core) + return; + + if (!core->capabilities[FW_UNLOAD].value) + return; + + cancel_delayed_work(&core->fw_unload_work); + + schedule_delayed_work(&core->fw_unload_work, + msecs_to_jiffies(core->capabilities[FW_UNLOAD_DELAY].value)); + + d_vpr_h("firmware unload delayed by %u ms\n", + core->capabilities[FW_UNLOAD_DELAY].value); + + return; +} + diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index 92095e64c9..84a3757736 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -230,7 +230,7 @@ static int handle_system_error(struct msm_vidc_core *core, struct hfi_packet *pkt) { d_vpr_e("%s: system error received\n", __func__); - msm_vidc_core_deinit(core); + msm_vidc_core_deinit(core, true); return 0; }