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 "vpu.h" 1362306a36Sopenharmony_ci#include "vpu_core.h" 1462306a36Sopenharmony_ci#include "vpu_rpc.h" 1562306a36Sopenharmony_ci#include "vpu_mbox.h" 1662306a36Sopenharmony_ci#include "vpu_defs.h" 1762306a36Sopenharmony_ci#include "vpu_cmds.h" 1862306a36Sopenharmony_ci#include "vpu_msgs.h" 1962306a36Sopenharmony_ci#include "vpu_v4l2.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define VPU_PKT_HEADER_LENGTH 3 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct vpu_msg_handler { 2462306a36Sopenharmony_ci u32 id; 2562306a36Sopenharmony_ci void (*done)(struct vpu_inst *inst, struct vpu_rpc_event *pkt); 2662306a36Sopenharmony_ci u32 is_str; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic void vpu_session_handle_start_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci vpu_trace(inst->dev, "[%d]\n", inst->id); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic void vpu_session_handle_mem_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct vpu_pkt_mem_req_data req_data = { 0 }; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&req_data); 3962306a36Sopenharmony_ci vpu_trace(inst->dev, "[%d] %d:%d %d:%d %d:%d\n", 4062306a36Sopenharmony_ci inst->id, 4162306a36Sopenharmony_ci req_data.enc_frame_size, 4262306a36Sopenharmony_ci req_data.enc_frame_num, 4362306a36Sopenharmony_ci req_data.ref_frame_size, 4462306a36Sopenharmony_ci req_data.ref_frame_num, 4562306a36Sopenharmony_ci req_data.act_buf_size, 4662306a36Sopenharmony_ci req_data.act_buf_num); 4762306a36Sopenharmony_ci vpu_inst_lock(inst); 4862306a36Sopenharmony_ci call_void_vop(inst, mem_request, 4962306a36Sopenharmony_ci req_data.enc_frame_size, 5062306a36Sopenharmony_ci req_data.enc_frame_num, 5162306a36Sopenharmony_ci req_data.ref_frame_size, 5262306a36Sopenharmony_ci req_data.ref_frame_num, 5362306a36Sopenharmony_ci req_data.act_buf_size, 5462306a36Sopenharmony_ci req_data.act_buf_num); 5562306a36Sopenharmony_ci vpu_inst_unlock(inst); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void vpu_session_handle_stop_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci vpu_trace(inst->dev, "[%d]\n", inst->id); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci call_void_vop(inst, stop_done); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic void vpu_session_handle_seq_hdr(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct vpu_dec_codec_info info; 6862306a36Sopenharmony_ci const struct vpu_core_resources *res; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci memset(&info, 0, sizeof(info)); 7162306a36Sopenharmony_ci res = vpu_get_resource(inst); 7262306a36Sopenharmony_ci info.stride = res ? res->stride : 1; 7362306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 7462306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_SEQ_HDR_FOUND, &info); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic void vpu_session_handle_resolution_change(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_RES_CHANGE, NULL); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic void vpu_session_handle_enc_frame_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci struct vpu_enc_pic_info info = { 0 }; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 8762306a36Sopenharmony_ci dev_dbg(inst->dev, "[%d] frame id = %d, wptr = 0x%x, size = %d\n", 8862306a36Sopenharmony_ci inst->id, info.frame_id, info.wptr, info.frame_size); 8962306a36Sopenharmony_ci call_void_vop(inst, get_one_frame, &info); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void vpu_session_handle_frame_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct vpu_fs_info fs = { 0 }; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, &fs); 9762306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_REQ, &fs); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void vpu_session_handle_frame_release(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci if (inst->core->type == VPU_CORE_TYPE_ENC) { 10362306a36Sopenharmony_ci struct vpu_frame_info info; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci memset(&info, 0, sizeof(info)); 10662306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info.sequence); 10762306a36Sopenharmony_ci dev_dbg(inst->dev, "[%d] %d\n", inst->id, info.sequence); 10862306a36Sopenharmony_ci info.type = inst->out_format.type; 10962306a36Sopenharmony_ci call_void_vop(inst, buf_done, &info); 11062306a36Sopenharmony_ci } else if (inst->core->type == VPU_CORE_TYPE_DEC) { 11162306a36Sopenharmony_ci struct vpu_fs_info fs = { 0 }; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, &fs); 11462306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_RELEASE, &fs); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic void vpu_session_handle_input_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci dev_dbg(inst->dev, "[%d]\n", inst->id); 12162306a36Sopenharmony_ci call_void_vop(inst, input_done); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic void vpu_session_handle_pic_decoded(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct vpu_dec_pic_info info = { 0 }; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 12962306a36Sopenharmony_ci call_void_vop(inst, get_one_frame, &info); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic void vpu_session_handle_pic_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci struct vpu_dec_pic_info info = { 0 }; 13562306a36Sopenharmony_ci struct vpu_frame_info frame; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci memset(&frame, 0, sizeof(frame)); 13862306a36Sopenharmony_ci vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 13962306a36Sopenharmony_ci if (inst->core->type == VPU_CORE_TYPE_DEC) 14062306a36Sopenharmony_ci frame.type = inst->cap_format.type; 14162306a36Sopenharmony_ci frame.id = info.id; 14262306a36Sopenharmony_ci frame.luma = info.luma; 14362306a36Sopenharmony_ci frame.skipped = info.skipped; 14462306a36Sopenharmony_ci frame.timestamp = info.timestamp; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci call_void_vop(inst, buf_done, &frame); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic void vpu_session_handle_eos(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_PIC_EOS, NULL); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic void vpu_session_handle_error(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci char *str = (char *)pkt->data; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (*str) 15962306a36Sopenharmony_ci dev_err(inst->dev, "instance %d firmware error : %s\n", inst->id, str); 16062306a36Sopenharmony_ci else 16162306a36Sopenharmony_ci dev_err(inst->dev, "instance %d is unsupported stream\n", inst->id); 16262306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_UNSUPPORTED, NULL); 16362306a36Sopenharmony_ci vpu_v4l2_set_error(inst); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic void vpu_session_handle_firmware_xcpt(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci char *str = (char *)pkt->data; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci dev_err(inst->dev, "%s firmware xcpt: %s\n", 17162306a36Sopenharmony_ci vpu_core_type_desc(inst->core->type), str); 17262306a36Sopenharmony_ci call_void_vop(inst, event_notify, VPU_MSG_ID_FIRMWARE_XCPT, NULL); 17362306a36Sopenharmony_ci set_bit(inst->id, &inst->core->hang_mask); 17462306a36Sopenharmony_ci vpu_v4l2_set_error(inst); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic void vpu_session_handle_pic_skipped(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci vpu_inst_lock(inst); 18062306a36Sopenharmony_ci vpu_skip_frame(inst, 1); 18162306a36Sopenharmony_ci vpu_inst_unlock(inst); 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic void vpu_session_handle_dbg_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci char *str = (char *)pkt->data; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (*str) 18962306a36Sopenharmony_ci dev_info(inst->dev, "instance %d firmware dbg msg : %s\n", inst->id, str); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic void vpu_terminate_string_msg(struct vpu_rpc_event *pkt) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci if (pkt->hdr.num == ARRAY_SIZE(pkt->data)) 19562306a36Sopenharmony_ci pkt->hdr.num--; 19662306a36Sopenharmony_ci pkt->data[pkt->hdr.num] = 0; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic struct vpu_msg_handler handlers[] = { 20062306a36Sopenharmony_ci {VPU_MSG_ID_START_DONE, vpu_session_handle_start_done}, 20162306a36Sopenharmony_ci {VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done}, 20262306a36Sopenharmony_ci {VPU_MSG_ID_MEM_REQUEST, vpu_session_handle_mem_request}, 20362306a36Sopenharmony_ci {VPU_MSG_ID_SEQ_HDR_FOUND, vpu_session_handle_seq_hdr}, 20462306a36Sopenharmony_ci {VPU_MSG_ID_RES_CHANGE, vpu_session_handle_resolution_change}, 20562306a36Sopenharmony_ci {VPU_MSG_ID_FRAME_INPUT_DONE, vpu_session_handle_input_done}, 20662306a36Sopenharmony_ci {VPU_MSG_ID_FRAME_REQ, vpu_session_handle_frame_request}, 20762306a36Sopenharmony_ci {VPU_MSG_ID_FRAME_RELEASE, vpu_session_handle_frame_release}, 20862306a36Sopenharmony_ci {VPU_MSG_ID_ENC_DONE, vpu_session_handle_enc_frame_done}, 20962306a36Sopenharmony_ci {VPU_MSG_ID_PIC_DECODED, vpu_session_handle_pic_decoded}, 21062306a36Sopenharmony_ci {VPU_MSG_ID_DEC_DONE, vpu_session_handle_pic_done}, 21162306a36Sopenharmony_ci {VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos}, 21262306a36Sopenharmony_ci {VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error, true}, 21362306a36Sopenharmony_ci {VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt, true}, 21462306a36Sopenharmony_ci {VPU_MSG_ID_PIC_SKIPPED, vpu_session_handle_pic_skipped}, 21562306a36Sopenharmony_ci {VPU_MSG_ID_DBG_MSG, vpu_session_handle_dbg_msg, true}, 21662306a36Sopenharmony_ci}; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci int ret; 22162306a36Sopenharmony_ci u32 msg_id; 22262306a36Sopenharmony_ci struct vpu_msg_handler *handler = NULL; 22362306a36Sopenharmony_ci unsigned int i; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci ret = vpu_iface_convert_msg_id(inst->core, msg->hdr.id); 22662306a36Sopenharmony_ci if (ret < 0) 22762306a36Sopenharmony_ci return -EINVAL; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci msg_id = ret; 23062306a36Sopenharmony_ci dev_dbg(inst->dev, "[%d] receive event(%s)\n", inst->id, vpu_id_name(msg_id)); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(handlers); i++) { 23362306a36Sopenharmony_ci if (handlers[i].id == msg_id) { 23462306a36Sopenharmony_ci handler = &handlers[i]; 23562306a36Sopenharmony_ci break; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (handler) { 24062306a36Sopenharmony_ci if (handler->is_str) 24162306a36Sopenharmony_ci vpu_terminate_string_msg(msg); 24262306a36Sopenharmony_ci if (handler->done) 24362306a36Sopenharmony_ci handler->done(inst, msg); 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci vpu_response_cmd(inst, msg_id, 1); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci return 0; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic bool vpu_inst_receive_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci unsigned long bytes = sizeof(struct vpu_rpc_event_header); 25462306a36Sopenharmony_ci u32 ret; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci memset(pkt, 0, sizeof(*pkt)); 25762306a36Sopenharmony_ci if (kfifo_len(&inst->msg_fifo) < bytes) 25862306a36Sopenharmony_ci return false; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci ret = kfifo_out(&inst->msg_fifo, pkt, bytes); 26162306a36Sopenharmony_ci if (ret != bytes) 26262306a36Sopenharmony_ci return false; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci if (pkt->hdr.num > 0) { 26562306a36Sopenharmony_ci bytes = pkt->hdr.num * sizeof(u32); 26662306a36Sopenharmony_ci ret = kfifo_out(&inst->msg_fifo, pkt->data, bytes); 26762306a36Sopenharmony_ci if (ret != bytes) 26862306a36Sopenharmony_ci return false; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci return true; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_civoid vpu_inst_run_work(struct work_struct *work) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct vpu_inst *inst = container_of(work, struct vpu_inst, msg_work); 27762306a36Sopenharmony_ci struct vpu_rpc_event pkt; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci while (vpu_inst_receive_msg(inst, &pkt)) 28062306a36Sopenharmony_ci vpu_session_handle_msg(inst, &pkt); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic void vpu_inst_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci unsigned long bytes; 28662306a36Sopenharmony_ci u32 id = pkt->hdr.id; 28762306a36Sopenharmony_ci int ret; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if (!inst->workqueue) 29062306a36Sopenharmony_ci return; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci bytes = sizeof(pkt->hdr) + pkt->hdr.num * sizeof(u32); 29362306a36Sopenharmony_ci ret = kfifo_in(&inst->msg_fifo, pkt, bytes); 29462306a36Sopenharmony_ci if (ret != bytes) 29562306a36Sopenharmony_ci dev_err(inst->dev, "[%d:%d]overflow: %d\n", inst->core->id, inst->id, id); 29662306a36Sopenharmony_ci queue_work(inst->workqueue, &inst->msg_work); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic int vpu_handle_msg(struct vpu_core *core) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct vpu_rpc_event pkt; 30262306a36Sopenharmony_ci struct vpu_inst *inst; 30362306a36Sopenharmony_ci int ret; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 30662306a36Sopenharmony_ci while (!vpu_iface_receive_msg(core, &pkt)) { 30762306a36Sopenharmony_ci dev_dbg(core->dev, "event index = %d, id = %d, num = %d\n", 30862306a36Sopenharmony_ci pkt.hdr.index, pkt.hdr.id, pkt.hdr.num); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci ret = vpu_iface_convert_msg_id(core, pkt.hdr.id); 31162306a36Sopenharmony_ci if (ret < 0) 31262306a36Sopenharmony_ci continue; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci inst = vpu_core_find_instance(core, pkt.hdr.index); 31562306a36Sopenharmony_ci if (inst) { 31662306a36Sopenharmony_ci vpu_response_cmd(inst, ret, 0); 31762306a36Sopenharmony_ci mutex_lock(&core->cmd_lock); 31862306a36Sopenharmony_ci vpu_inst_record_flow(inst, ret); 31962306a36Sopenharmony_ci mutex_unlock(&core->cmd_lock); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci vpu_inst_handle_msg(inst, &pkt); 32262306a36Sopenharmony_ci vpu_inst_put(inst); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return 0; 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic int vpu_isr_thread(struct vpu_core *core, u32 irq_code) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci dev_dbg(core->dev, "irq code = 0x%x\n", irq_code); 33362306a36Sopenharmony_ci switch (irq_code) { 33462306a36Sopenharmony_ci case VPU_IRQ_CODE_SYNC: 33562306a36Sopenharmony_ci vpu_mbox_send_msg(core, PRC_BUF_OFFSET, core->rpc.phys - core->fw.phys); 33662306a36Sopenharmony_ci vpu_mbox_send_msg(core, BOOT_ADDRESS, core->fw.phys); 33762306a36Sopenharmony_ci vpu_mbox_send_msg(core, INIT_DONE, 2); 33862306a36Sopenharmony_ci break; 33962306a36Sopenharmony_ci case VPU_IRQ_CODE_BOOT_DONE: 34062306a36Sopenharmony_ci break; 34162306a36Sopenharmony_ci case VPU_IRQ_CODE_SNAPSHOT_DONE: 34262306a36Sopenharmony_ci break; 34362306a36Sopenharmony_ci default: 34462306a36Sopenharmony_ci vpu_handle_msg(core); 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci return 0; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic void vpu_core_run_msg_work(struct vpu_core *core) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci const unsigned int SIZE = sizeof(u32); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci while (kfifo_len(&core->msg_fifo) >= SIZE) { 35662306a36Sopenharmony_ci u32 data = 0; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (kfifo_out(&core->msg_fifo, &data, SIZE) == SIZE) 35962306a36Sopenharmony_ci vpu_isr_thread(core, data); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_civoid vpu_msg_run_work(struct work_struct *work) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct vpu_core *core = container_of(work, struct vpu_core, msg_work); 36662306a36Sopenharmony_ci unsigned long delay = msecs_to_jiffies(10); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci vpu_core_run_msg_work(core); 36962306a36Sopenharmony_ci queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay); 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_civoid vpu_msg_delayed_work(struct work_struct *work) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci struct vpu_core *core; 37562306a36Sopenharmony_ci struct delayed_work *dwork; 37662306a36Sopenharmony_ci unsigned long bytes = sizeof(u32); 37762306a36Sopenharmony_ci u32 i; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (!work) 38062306a36Sopenharmony_ci return; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci dwork = to_delayed_work(work); 38362306a36Sopenharmony_ci core = container_of(dwork, struct vpu_core, msg_delayed_work); 38462306a36Sopenharmony_ci if (kfifo_len(&core->msg_fifo) >= bytes) 38562306a36Sopenharmony_ci vpu_core_run_msg_work(core); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci bytes = sizeof(struct vpu_rpc_event_header); 38862306a36Sopenharmony_ci for (i = 0; i < core->supported_instance_count; i++) { 38962306a36Sopenharmony_ci struct vpu_inst *inst = vpu_core_find_instance(core, i); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (!inst) 39262306a36Sopenharmony_ci continue; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (inst->workqueue && kfifo_len(&inst->msg_fifo) >= bytes) 39562306a36Sopenharmony_ci queue_work(inst->workqueue, &inst->msg_work); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci vpu_inst_put(inst); 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ciint vpu_isr(struct vpu_core *core, u32 irq) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci switch (irq) { 40462306a36Sopenharmony_ci case VPU_IRQ_CODE_SYNC: 40562306a36Sopenharmony_ci break; 40662306a36Sopenharmony_ci case VPU_IRQ_CODE_BOOT_DONE: 40762306a36Sopenharmony_ci complete(&core->cmp); 40862306a36Sopenharmony_ci break; 40962306a36Sopenharmony_ci case VPU_IRQ_CODE_SNAPSHOT_DONE: 41062306a36Sopenharmony_ci complete(&core->cmp); 41162306a36Sopenharmony_ci break; 41262306a36Sopenharmony_ci default: 41362306a36Sopenharmony_ci break; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (kfifo_in(&core->msg_fifo, &irq, sizeof(irq)) != sizeof(irq)) 41762306a36Sopenharmony_ci dev_err(core->dev, "[%d]overflow: %d\n", core->id, irq); 41862306a36Sopenharmony_ci queue_work(core->workqueue, &core->msg_work); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return 0; 42162306a36Sopenharmony_ci} 422