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