162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2020-2021 NXP 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/init.h> 762306a36Sopenharmony_ci#include <linux/interconnect.h> 862306a36Sopenharmony_ci#include <linux/ioctl.h> 962306a36Sopenharmony_ci#include <linux/list.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <linux/delay.h> 1662306a36Sopenharmony_ci#include <linux/vmalloc.h> 1762306a36Sopenharmony_ci#include "vpu.h" 1862306a36Sopenharmony_ci#include "vpu_defs.h" 1962306a36Sopenharmony_ci#include "vpu_cmds.h" 2062306a36Sopenharmony_ci#include "vpu_rpc.h" 2162306a36Sopenharmony_ci#include "vpu_mbox.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct vpu_cmd_request { 2462306a36Sopenharmony_ci u32 request; 2562306a36Sopenharmony_ci u32 response; 2662306a36Sopenharmony_ci u32 handled; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct vpu_cmd_t { 3062306a36Sopenharmony_ci struct list_head list; 3162306a36Sopenharmony_ci u32 id; 3262306a36Sopenharmony_ci struct vpu_cmd_request *request; 3362306a36Sopenharmony_ci struct vpu_rpc_event *pkt; 3462306a36Sopenharmony_ci unsigned long key; 3562306a36Sopenharmony_ci atomic_long_t *last_response_cmd; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic struct vpu_cmd_request vpu_cmd_requests[] = { 3962306a36Sopenharmony_ci { 4062306a36Sopenharmony_ci .request = VPU_CMD_ID_CONFIGURE_CODEC, 4162306a36Sopenharmony_ci .response = VPU_MSG_ID_MEM_REQUEST, 4262306a36Sopenharmony_ci .handled = 1, 4362306a36Sopenharmony_ci }, 4462306a36Sopenharmony_ci { 4562306a36Sopenharmony_ci .request = VPU_CMD_ID_START, 4662306a36Sopenharmony_ci .response = VPU_MSG_ID_START_DONE, 4762306a36Sopenharmony_ci .handled = 0, 4862306a36Sopenharmony_ci }, 4962306a36Sopenharmony_ci { 5062306a36Sopenharmony_ci .request = VPU_CMD_ID_STOP, 5162306a36Sopenharmony_ci .response = VPU_MSG_ID_STOP_DONE, 5262306a36Sopenharmony_ci .handled = 0, 5362306a36Sopenharmony_ci }, 5462306a36Sopenharmony_ci { 5562306a36Sopenharmony_ci .request = VPU_CMD_ID_ABORT, 5662306a36Sopenharmony_ci .response = VPU_MSG_ID_ABORT_DONE, 5762306a36Sopenharmony_ci .handled = 0, 5862306a36Sopenharmony_ci }, 5962306a36Sopenharmony_ci { 6062306a36Sopenharmony_ci .request = VPU_CMD_ID_RST_BUF, 6162306a36Sopenharmony_ci .response = VPU_MSG_ID_BUF_RST, 6262306a36Sopenharmony_ci .handled = 1, 6362306a36Sopenharmony_ci }, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int vpu_cmd_send(struct vpu_core *core, struct vpu_rpc_event *pkt) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci int ret = 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ret = vpu_iface_send_cmd(core, pkt); 7162306a36Sopenharmony_ci if (ret) 7262306a36Sopenharmony_ci return ret; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /*write cmd data to cmd buffer before trigger a cmd interrupt*/ 7562306a36Sopenharmony_ci mb(); 7662306a36Sopenharmony_ci vpu_mbox_send_type(core, COMMAND); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return ret; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic struct vpu_cmd_t *vpu_alloc_cmd(struct vpu_inst *inst, u32 id, void *data) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct vpu_cmd_t *cmd; 8462306a36Sopenharmony_ci int i; 8562306a36Sopenharmony_ci int ret; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci cmd = vzalloc(sizeof(*cmd)); 8862306a36Sopenharmony_ci if (!cmd) 8962306a36Sopenharmony_ci return NULL; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci cmd->pkt = vzalloc(sizeof(*cmd->pkt)); 9262306a36Sopenharmony_ci if (!cmd->pkt) { 9362306a36Sopenharmony_ci vfree(cmd); 9462306a36Sopenharmony_ci return NULL; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci cmd->id = id; 9862306a36Sopenharmony_ci ret = vpu_iface_pack_cmd(inst->core, cmd->pkt, inst->id, id, data); 9962306a36Sopenharmony_ci if (ret) { 10062306a36Sopenharmony_ci dev_err(inst->dev, "iface pack cmd %s fail\n", vpu_id_name(id)); 10162306a36Sopenharmony_ci vfree(cmd->pkt); 10262306a36Sopenharmony_ci vfree(cmd); 10362306a36Sopenharmony_ci return NULL; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(vpu_cmd_requests); i++) { 10662306a36Sopenharmony_ci if (vpu_cmd_requests[i].request == id) { 10762306a36Sopenharmony_ci cmd->request = &vpu_cmd_requests[i]; 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return cmd; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic void vpu_free_cmd(struct vpu_cmd_t *cmd) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci if (!cmd) 11862306a36Sopenharmony_ci return; 11962306a36Sopenharmony_ci if (cmd->last_response_cmd) 12062306a36Sopenharmony_ci atomic_long_set(cmd->last_response_cmd, cmd->key); 12162306a36Sopenharmony_ci vfree(cmd->pkt); 12262306a36Sopenharmony_ci vfree(cmd); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic int vpu_session_process_cmd(struct vpu_inst *inst, struct vpu_cmd_t *cmd) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci int ret; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci dev_dbg(inst->dev, "[%d]send cmd %s\n", inst->id, vpu_id_name(cmd->id)); 13062306a36Sopenharmony_ci vpu_iface_pre_send_cmd(inst); 13162306a36Sopenharmony_ci ret = vpu_cmd_send(inst->core, cmd->pkt); 13262306a36Sopenharmony_ci if (!ret) { 13362306a36Sopenharmony_ci vpu_iface_post_send_cmd(inst); 13462306a36Sopenharmony_ci vpu_inst_record_flow(inst, cmd->id); 13562306a36Sopenharmony_ci } else { 13662306a36Sopenharmony_ci dev_err(inst->dev, "[%d] iface send cmd %s fail\n", inst->id, vpu_id_name(cmd->id)); 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return ret; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic void vpu_process_cmd_request(struct vpu_inst *inst) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct vpu_cmd_t *cmd; 14562306a36Sopenharmony_ci struct vpu_cmd_t *tmp; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (!inst || inst->pending) 14862306a36Sopenharmony_ci return; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci list_for_each_entry_safe(cmd, tmp, &inst->cmd_q, list) { 15162306a36Sopenharmony_ci list_del_init(&cmd->list); 15262306a36Sopenharmony_ci if (vpu_session_process_cmd(inst, cmd)) 15362306a36Sopenharmony_ci dev_err(inst->dev, "[%d] process cmd %s fail\n", 15462306a36Sopenharmony_ci inst->id, vpu_id_name(cmd->id)); 15562306a36Sopenharmony_ci if (cmd->request) { 15662306a36Sopenharmony_ci inst->pending = (void *)cmd; 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci vpu_free_cmd(cmd); 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int vpu_request_cmd(struct vpu_inst *inst, u32 id, void *data, 16462306a36Sopenharmony_ci unsigned long *key, int *sync) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci struct vpu_core *core; 16762306a36Sopenharmony_ci struct vpu_cmd_t *cmd; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (!inst || !inst->core) 17062306a36Sopenharmony_ci return -EINVAL; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci core = inst->core; 17362306a36Sopenharmony_ci cmd = vpu_alloc_cmd(inst, id, data); 17462306a36Sopenharmony_ci if (!cmd) 17562306a36Sopenharmony_ci return -ENOMEM; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci mutex_lock(&core->cmd_lock); 17862306a36Sopenharmony_ci cmd->key = ++inst->cmd_seq; 17962306a36Sopenharmony_ci cmd->last_response_cmd = &inst->last_response_cmd; 18062306a36Sopenharmony_ci if (key) 18162306a36Sopenharmony_ci *key = cmd->key; 18262306a36Sopenharmony_ci if (sync) 18362306a36Sopenharmony_ci *sync = cmd->request ? true : false; 18462306a36Sopenharmony_ci list_add_tail(&cmd->list, &inst->cmd_q); 18562306a36Sopenharmony_ci vpu_process_cmd_request(inst); 18662306a36Sopenharmony_ci mutex_unlock(&core->cmd_lock); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return 0; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic void vpu_clear_pending(struct vpu_inst *inst) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci if (!inst || !inst->pending) 19462306a36Sopenharmony_ci return; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci vpu_free_cmd(inst->pending); 19762306a36Sopenharmony_ci wake_up_all(&inst->core->ack_wq); 19862306a36Sopenharmony_ci inst->pending = NULL; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic bool vpu_check_response(struct vpu_cmd_t *cmd, u32 response, u32 handled) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct vpu_cmd_request *request; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (!cmd || !cmd->request) 20662306a36Sopenharmony_ci return false; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci request = cmd->request; 20962306a36Sopenharmony_ci if (request->response != response) 21062306a36Sopenharmony_ci return false; 21162306a36Sopenharmony_ci if (request->handled != handled) 21262306a36Sopenharmony_ci return false; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci return true; 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ciint vpu_response_cmd(struct vpu_inst *inst, u32 response, u32 handled) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci struct vpu_core *core; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (!inst || !inst->core) 22262306a36Sopenharmony_ci return -EINVAL; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci core = inst->core; 22562306a36Sopenharmony_ci mutex_lock(&core->cmd_lock); 22662306a36Sopenharmony_ci if (vpu_check_response(inst->pending, response, handled)) 22762306a36Sopenharmony_ci vpu_clear_pending(inst); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci vpu_process_cmd_request(inst); 23062306a36Sopenharmony_ci mutex_unlock(&core->cmd_lock); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return 0; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_civoid vpu_clear_request(struct vpu_inst *inst) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct vpu_cmd_t *cmd; 23862306a36Sopenharmony_ci struct vpu_cmd_t *tmp; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci mutex_lock(&inst->core->cmd_lock); 24162306a36Sopenharmony_ci if (inst->pending) 24262306a36Sopenharmony_ci vpu_clear_pending(inst); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci list_for_each_entry_safe(cmd, tmp, &inst->cmd_q, list) { 24562306a36Sopenharmony_ci list_del_init(&cmd->list); 24662306a36Sopenharmony_ci vpu_free_cmd(cmd); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci mutex_unlock(&inst->core->cmd_lock); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic bool check_is_responsed(struct vpu_inst *inst, unsigned long key) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci unsigned long last_response = atomic_long_read(&inst->last_response_cmd); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (key <= last_response && (last_response - key) < (ULONG_MAX >> 1)) 25662306a36Sopenharmony_ci return true; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return false; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic int sync_session_response(struct vpu_inst *inst, unsigned long key, long timeout, int try) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci struct vpu_core *core; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (!inst || !inst->core) 26662306a36Sopenharmony_ci return -EINVAL; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci core = inst->core; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci call_void_vop(inst, wait_prepare); 27162306a36Sopenharmony_ci wait_event_timeout(core->ack_wq, check_is_responsed(inst, key), timeout); 27262306a36Sopenharmony_ci call_void_vop(inst, wait_finish); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (!check_is_responsed(inst, key)) { 27562306a36Sopenharmony_ci if (try) 27662306a36Sopenharmony_ci return -EINVAL; 27762306a36Sopenharmony_ci dev_err(inst->dev, "[%d] sync session timeout\n", inst->id); 27862306a36Sopenharmony_ci set_bit(inst->id, &core->hang_mask); 27962306a36Sopenharmony_ci mutex_lock(&inst->core->cmd_lock); 28062306a36Sopenharmony_ci vpu_clear_pending(inst); 28162306a36Sopenharmony_ci mutex_unlock(&inst->core->cmd_lock); 28262306a36Sopenharmony_ci return -EINVAL; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic void vpu_core_keep_active(struct vpu_core *core) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci struct vpu_rpc_event pkt; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 29362306a36Sopenharmony_ci vpu_iface_pack_cmd(core, &pkt, 0, VPU_CMD_ID_NOOP, NULL); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci dev_dbg(core->dev, "try to wake up\n"); 29662306a36Sopenharmony_ci mutex_lock(&core->cmd_lock); 29762306a36Sopenharmony_ci if (vpu_cmd_send(core, &pkt)) 29862306a36Sopenharmony_ci dev_err(core->dev, "fail to keep active\n"); 29962306a36Sopenharmony_ci mutex_unlock(&core->cmd_lock); 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic int vpu_session_send_cmd(struct vpu_inst *inst, u32 id, void *data) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci unsigned long key; 30562306a36Sopenharmony_ci int sync = false; 30662306a36Sopenharmony_ci int ret; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (inst->id < 0) 30962306a36Sopenharmony_ci return -EINVAL; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci ret = vpu_request_cmd(inst, id, data, &key, &sync); 31262306a36Sopenharmony_ci if (ret) 31362306a36Sopenharmony_ci goto exit; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* workaround for a firmware issue, 31662306a36Sopenharmony_ci * firmware should be waked up by start or configure command, 31762306a36Sopenharmony_ci * but there is a very small change that firmware failed to wakeup. 31862306a36Sopenharmony_ci * in such case, try to wakeup firmware again by sending a noop command 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ci if (sync && (id == VPU_CMD_ID_CONFIGURE_CODEC || id == VPU_CMD_ID_START)) { 32162306a36Sopenharmony_ci if (sync_session_response(inst, key, VPU_TIMEOUT_WAKEUP, 1)) 32262306a36Sopenharmony_ci vpu_core_keep_active(inst->core); 32362306a36Sopenharmony_ci else 32462306a36Sopenharmony_ci goto exit; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (sync) 32862306a36Sopenharmony_ci ret = sync_session_response(inst, key, VPU_TIMEOUT, 0); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ciexit: 33162306a36Sopenharmony_ci if (ret) 33262306a36Sopenharmony_ci dev_err(inst->dev, "[%d] send cmd %s fail\n", inst->id, vpu_id_name(id)); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return ret; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ciint vpu_session_configure_codec(struct vpu_inst *inst) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_CONFIGURE_CODEC, NULL); 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ciint vpu_session_start(struct vpu_inst *inst) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci vpu_trace(inst->dev, "[%d]\n", inst->id); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_START, NULL); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciint vpu_session_stop(struct vpu_inst *inst) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci int ret; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci vpu_trace(inst->dev, "[%d]\n", inst->id); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci ret = vpu_session_send_cmd(inst, VPU_CMD_ID_STOP, NULL); 35662306a36Sopenharmony_ci /* workaround for a firmware bug, 35762306a36Sopenharmony_ci * if the next command is too close after stop cmd, 35862306a36Sopenharmony_ci * the firmware may enter wfi wrongly. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci usleep_range(3000, 5000); 36162306a36Sopenharmony_ci return ret; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ciint vpu_session_encode_frame(struct vpu_inst *inst, s64 timestamp) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_FRAME_ENCODE, ×tamp); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ciint vpu_session_alloc_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_FS_ALLOC, fs); 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ciint vpu_session_release_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_FS_RELEASE, fs); 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ciint vpu_session_abort(struct vpu_inst *inst) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_ABORT, NULL); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ciint vpu_session_rst_buf(struct vpu_inst *inst) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_RST_BUF, NULL); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ciint vpu_session_fill_timestamp(struct vpu_inst *inst, struct vpu_ts_info *info) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_TIMESTAMP, info); 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ciint vpu_session_update_parameters(struct vpu_inst *inst, void *arg) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci if (inst->type & VPU_CORE_TYPE_DEC) 39762306a36Sopenharmony_ci vpu_iface_set_decode_params(inst, arg, 1); 39862306a36Sopenharmony_ci else 39962306a36Sopenharmony_ci vpu_iface_set_encode_params(inst, arg, 1); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_UPDATE_PARAMETER, arg); 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ciint vpu_session_debug(struct vpu_inst *inst) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci return vpu_session_send_cmd(inst, VPU_CMD_ID_DEBUG, NULL); 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ciint vpu_core_snapshot(struct vpu_core *core) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct vpu_inst *inst; 41262306a36Sopenharmony_ci int ret; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci if (!core || list_empty(&core->instances)) 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci inst = list_first_entry(&core->instances, struct vpu_inst, list); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci reinit_completion(&core->cmp); 42062306a36Sopenharmony_ci ret = vpu_session_send_cmd(inst, VPU_CMD_ID_SNAPSHOT, NULL); 42162306a36Sopenharmony_ci if (ret) 42262306a36Sopenharmony_ci return ret; 42362306a36Sopenharmony_ci ret = wait_for_completion_timeout(&core->cmp, VPU_TIMEOUT); 42462306a36Sopenharmony_ci if (!ret) { 42562306a36Sopenharmony_ci dev_err(core->dev, "snapshot timeout\n"); 42662306a36Sopenharmony_ci return -EINVAL; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci return 0; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ciint vpu_core_sw_reset(struct vpu_core *core) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci struct vpu_rpc_event pkt; 43562306a36Sopenharmony_ci int ret; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 43862306a36Sopenharmony_ci vpu_iface_pack_cmd(core, &pkt, 0, VPU_CMD_ID_FIRM_RESET, NULL); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci reinit_completion(&core->cmp); 44162306a36Sopenharmony_ci mutex_lock(&core->cmd_lock); 44262306a36Sopenharmony_ci ret = vpu_cmd_send(core, &pkt); 44362306a36Sopenharmony_ci mutex_unlock(&core->cmd_lock); 44462306a36Sopenharmony_ci if (ret) 44562306a36Sopenharmony_ci return ret; 44662306a36Sopenharmony_ci ret = wait_for_completion_timeout(&core->cmp, VPU_TIMEOUT); 44762306a36Sopenharmony_ci if (!ret) { 44862306a36Sopenharmony_ci dev_err(core->dev, "sw reset timeout\n"); 44962306a36Sopenharmony_ci return -EINVAL; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci return 0; 45362306a36Sopenharmony_ci} 454