1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2020-2021 NXP
6 #include <linux/init.h>
7 #include <linux/interconnect.h>
8 #include <linux/ioctl.h>
9 #include <linux/list.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
21 #define VPU_PKT_HEADER_LENGTH 3
23 struct vpu_msg_handler {
25 void (*done)(struct vpu_inst *inst, struct vpu_rpc_event *pkt);
28 static void vpu_session_handle_start_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
30 vpu_trace(inst->dev, "[%d]\n", inst->id);
33 static void vpu_session_handle_mem_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
35 struct vpu_pkt_mem_req_data req_data;
37 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&req_data);
38 vpu_trace(inst->dev, "[%d] %d:%d %d:%d %d:%d\n",
40 req_data.enc_frame_size,
41 req_data.enc_frame_num,
42 req_data.ref_frame_size,
43 req_data.ref_frame_num,
44 req_data.act_buf_size,
45 req_data.act_buf_num);
47 call_void_vop(inst, mem_request,
48 req_data.enc_frame_size,
49 req_data.enc_frame_num,
50 req_data.ref_frame_size,
51 req_data.ref_frame_num,
52 req_data.act_buf_size,
53 req_data.act_buf_num);
54 vpu_inst_unlock(inst);
57 static void vpu_session_handle_stop_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
59 vpu_trace(inst->dev, "[%d]\n", inst->id);
61 call_void_vop(inst, stop_done);
64 static void vpu_session_handle_seq_hdr(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
66 struct vpu_dec_codec_info info;
67 const struct vpu_core_resources *res;
69 memset(&info, 0, sizeof(info));
70 res = vpu_get_resource(inst);
71 info.stride = res ? res->stride : 1;
72 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
73 call_void_vop(inst, event_notify, VPU_MSG_ID_SEQ_HDR_FOUND, &info);
76 static void vpu_session_handle_resolution_change(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
78 call_void_vop(inst, event_notify, VPU_MSG_ID_RES_CHANGE, NULL);
81 static void vpu_session_handle_enc_frame_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
83 struct vpu_enc_pic_info info;
85 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
86 dev_dbg(inst->dev, "[%d] frame id = %d, wptr = 0x%x, size = %d\n",
87 inst->id, info.frame_id, info.wptr, info.frame_size);
88 call_void_vop(inst, get_one_frame, &info);
91 static void vpu_session_handle_frame_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
93 struct vpu_fs_info fs;
95 vpu_iface_unpack_msg_data(inst->core, pkt, &fs);
96 call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_REQ, &fs);
99 static void vpu_session_handle_frame_release(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
101 if (inst->core->type == VPU_CORE_TYPE_ENC) {
102 struct vpu_frame_info info;
104 memset(&info, 0, sizeof(info));
105 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info.sequence);
106 dev_dbg(inst->dev, "[%d] %d\n", inst->id, info.sequence);
107 info.type = inst->out_format.type;
108 call_void_vop(inst, buf_done, &info);
109 } else if (inst->core->type == VPU_CORE_TYPE_DEC) {
110 struct vpu_fs_info fs;
112 vpu_iface_unpack_msg_data(inst->core, pkt, &fs);
113 call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_RELEASE, &fs);
117 static void vpu_session_handle_input_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
119 dev_dbg(inst->dev, "[%d]\n", inst->id);
120 call_void_vop(inst, input_done);
123 static void vpu_session_handle_pic_decoded(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
125 struct vpu_dec_pic_info info;
127 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
128 call_void_vop(inst, get_one_frame, &info);
131 static void vpu_session_handle_pic_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
133 struct vpu_dec_pic_info info;
134 struct vpu_frame_info frame;
136 memset(&frame, 0, sizeof(frame));
137 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
138 if (inst->core->type == VPU_CORE_TYPE_DEC)
139 frame.type = inst->cap_format.type;
141 frame.luma = info.luma;
142 frame.skipped = info.skipped;
143 frame.timestamp = info.timestamp;
145 call_void_vop(inst, buf_done, &frame);
148 static void vpu_session_handle_eos(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
150 call_void_vop(inst, event_notify, VPU_MSG_ID_PIC_EOS, NULL);
153 static void vpu_session_handle_error(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
155 char *str = (char *)pkt->data;
158 dev_err(inst->dev, "instance %d firmware error : %s\n", inst->id, str);
160 dev_err(inst->dev, "instance %d is unsupported stream\n", inst->id);
161 call_void_vop(inst, event_notify, VPU_MSG_ID_UNSUPPORTED, NULL);
162 vpu_v4l2_set_error(inst);
165 static void vpu_session_handle_firmware_xcpt(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
167 char *str = (char *)pkt->data;
169 dev_err(inst->dev, "%s firmware xcpt: %s\n",
170 vpu_core_type_desc(inst->core->type), str);
171 call_void_vop(inst, event_notify, VPU_MSG_ID_FIRMWARE_XCPT, NULL);
172 set_bit(inst->id, &inst->core->hang_mask);
173 vpu_v4l2_set_error(inst);
176 static void vpu_session_handle_pic_skipped(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
179 vpu_skip_frame(inst, 1);
180 vpu_inst_unlock(inst);
183 static struct vpu_msg_handler handlers[] = {
184 {VPU_MSG_ID_START_DONE, vpu_session_handle_start_done},
185 {VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done},
186 {VPU_MSG_ID_MEM_REQUEST, vpu_session_handle_mem_request},
187 {VPU_MSG_ID_SEQ_HDR_FOUND, vpu_session_handle_seq_hdr},
188 {VPU_MSG_ID_RES_CHANGE, vpu_session_handle_resolution_change},
189 {VPU_MSG_ID_FRAME_INPUT_DONE, vpu_session_handle_input_done},
190 {VPU_MSG_ID_FRAME_REQ, vpu_session_handle_frame_request},
191 {VPU_MSG_ID_FRAME_RELEASE, vpu_session_handle_frame_release},
192 {VPU_MSG_ID_ENC_DONE, vpu_session_handle_enc_frame_done},
193 {VPU_MSG_ID_PIC_DECODED, vpu_session_handle_pic_decoded},
194 {VPU_MSG_ID_DEC_DONE, vpu_session_handle_pic_done},
195 {VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos},
196 {VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error},
197 {VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt},
198 {VPU_MSG_ID_PIC_SKIPPED, vpu_session_handle_pic_skipped},
201 static int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg)
205 struct vpu_msg_handler *handler = NULL;
208 ret = vpu_iface_convert_msg_id(inst->core, msg->hdr.id);
213 dev_dbg(inst->dev, "[%d] receive event(0x%x)\n", inst->id, msg_id);
215 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
216 if (handlers[i].id == msg_id) {
217 handler = &handlers[i];
222 if (handler && handler->done)
223 handler->done(inst, msg);
225 vpu_response_cmd(inst, msg_id, 1);
230 static bool vpu_inst_receive_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
232 unsigned long bytes = sizeof(struct vpu_rpc_event_header);
235 memset(pkt, 0, sizeof(*pkt));
236 if (kfifo_len(&inst->msg_fifo) < bytes)
239 ret = kfifo_out(&inst->msg_fifo, pkt, bytes);
243 if (pkt->hdr.num > 0) {
244 bytes = pkt->hdr.num * sizeof(u32);
245 ret = kfifo_out(&inst->msg_fifo, pkt->data, bytes);
253 void vpu_inst_run_work(struct work_struct *work)
255 struct vpu_inst *inst = container_of(work, struct vpu_inst, msg_work);
256 struct vpu_rpc_event pkt;
258 while (vpu_inst_receive_msg(inst, &pkt))
259 vpu_session_handle_msg(inst, &pkt);
262 static void vpu_inst_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
265 u32 id = pkt->hdr.id;
268 if (!inst->workqueue)
271 bytes = sizeof(pkt->hdr) + pkt->hdr.num * sizeof(u32);
272 ret = kfifo_in(&inst->msg_fifo, pkt, bytes);
274 dev_err(inst->dev, "[%d:%d]overflow: %d\n", inst->core->id, inst->id, id);
275 queue_work(inst->workqueue, &inst->msg_work);
278 static int vpu_handle_msg(struct vpu_core *core)
280 struct vpu_rpc_event pkt;
281 struct vpu_inst *inst;
284 memset(&pkt, 0, sizeof(pkt));
285 while (!vpu_iface_receive_msg(core, &pkt)) {
286 dev_dbg(core->dev, "event index = %d, id = %d, num = %d\n",
287 pkt.hdr.index, pkt.hdr.id, pkt.hdr.num);
289 ret = vpu_iface_convert_msg_id(core, pkt.hdr.id);
293 inst = vpu_core_find_instance(core, pkt.hdr.index);
295 vpu_response_cmd(inst, ret, 0);
296 mutex_lock(&core->cmd_lock);
297 vpu_inst_record_flow(inst, ret);
298 mutex_unlock(&core->cmd_lock);
300 vpu_inst_handle_msg(inst, &pkt);
303 memset(&pkt, 0, sizeof(pkt));
309 static int vpu_isr_thread(struct vpu_core *core, u32 irq_code)
311 dev_dbg(core->dev, "irq code = 0x%x\n", irq_code);
313 case VPU_IRQ_CODE_SYNC:
314 vpu_mbox_send_msg(core, PRC_BUF_OFFSET, core->rpc.phys - core->fw.phys);
315 vpu_mbox_send_msg(core, BOOT_ADDRESS, core->fw.phys);
316 vpu_mbox_send_msg(core, INIT_DONE, 2);
318 case VPU_IRQ_CODE_BOOT_DONE:
320 case VPU_IRQ_CODE_SNAPSHOT_DONE:
323 vpu_handle_msg(core);
330 static void vpu_core_run_msg_work(struct vpu_core *core)
332 const unsigned int SIZE = sizeof(u32);
334 while (kfifo_len(&core->msg_fifo) >= SIZE) {
337 if (kfifo_out(&core->msg_fifo, &data, SIZE) == SIZE)
338 vpu_isr_thread(core, data);
342 void vpu_msg_run_work(struct work_struct *work)
344 struct vpu_core *core = container_of(work, struct vpu_core, msg_work);
345 unsigned long delay = msecs_to_jiffies(10);
347 vpu_core_run_msg_work(core);
348 queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay);
351 void vpu_msg_delayed_work(struct work_struct *work)
353 struct vpu_core *core;
354 struct delayed_work *dwork;
355 unsigned long bytes = sizeof(u32);
361 dwork = to_delayed_work(work);
362 core = container_of(dwork, struct vpu_core, msg_delayed_work);
363 if (kfifo_len(&core->msg_fifo) >= bytes)
364 vpu_core_run_msg_work(core);
366 bytes = sizeof(struct vpu_rpc_event_header);
367 for (i = 0; i < core->supported_instance_count; i++) {
368 struct vpu_inst *inst = vpu_core_find_instance(core, i);
373 if (inst->workqueue && kfifo_len(&inst->msg_fifo) >= bytes)
374 queue_work(inst->workqueue, &inst->msg_work);
380 int vpu_isr(struct vpu_core *core, u32 irq)
383 case VPU_IRQ_CODE_SYNC:
385 case VPU_IRQ_CODE_BOOT_DONE:
386 complete(&core->cmp);
388 case VPU_IRQ_CODE_SNAPSHOT_DONE:
389 complete(&core->cmp);
395 if (kfifo_in(&core->msg_fifo, &irq, sizeof(irq)) != sizeof(irq))
396 dev_err(core->dev, "[%d]overflow: %d\n", core->id, irq);
397 queue_work(core->workqueue, &core->msg_work);