1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright 2020-2021 NXP
4 */
5
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>
12 #include "vpu.h"
13 #include "vpu_core.h"
14 #include "vpu_rpc.h"
15 #include "vpu_mbox.h"
16 #include "vpu_defs.h"
17 #include "vpu_cmds.h"
18 #include "vpu_msgs.h"
19 #include "vpu_v4l2.h"
20
21 #define VPU_PKT_HEADER_LENGTH 3
22
23 struct vpu_msg_handler {
24 u32 id;
25 void (*done)(struct vpu_inst *inst, struct vpu_rpc_event *pkt);
26 };
27
vpu_session_handle_start_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)
29 {
30 vpu_trace(inst->dev, "[%d]\n", inst->id);
31 }
32
vpu_session_handle_mem_request(struct vpu_inst * inst,struct vpu_rpc_event * pkt)33 static void vpu_session_handle_mem_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
34 {
35 struct vpu_pkt_mem_req_data req_data;
36
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",
39 inst->id,
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);
46 call_void_vop(inst, mem_request,
47 req_data.enc_frame_size,
48 req_data.enc_frame_num,
49 req_data.ref_frame_size,
50 req_data.ref_frame_num,
51 req_data.act_buf_size,
52 req_data.act_buf_num);
53 }
54
vpu_session_handle_stop_done(struct vpu_inst * inst,struct vpu_rpc_event * pkt)55 static void vpu_session_handle_stop_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
56 {
57 vpu_trace(inst->dev, "[%d]\n", inst->id);
58
59 call_void_vop(inst, stop_done);
60 }
61
vpu_session_handle_seq_hdr(struct vpu_inst * inst,struct vpu_rpc_event * pkt)62 static void vpu_session_handle_seq_hdr(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
63 {
64 struct vpu_dec_codec_info info;
65 const struct vpu_core_resources *res;
66
67 memset(&info, 0, sizeof(info));
68 res = vpu_get_resource(inst);
69 info.stride = res ? res->stride : 1;
70 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
71 call_void_vop(inst, event_notify, VPU_MSG_ID_SEQ_HDR_FOUND, &info);
72 }
73
vpu_session_handle_resolution_change(struct vpu_inst * inst,struct vpu_rpc_event * pkt)74 static void vpu_session_handle_resolution_change(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
75 {
76 call_void_vop(inst, event_notify, VPU_MSG_ID_RES_CHANGE, NULL);
77 }
78
vpu_session_handle_enc_frame_done(struct vpu_inst * inst,struct vpu_rpc_event * pkt)79 static void vpu_session_handle_enc_frame_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
80 {
81 struct vpu_enc_pic_info info;
82
83 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
84 dev_dbg(inst->dev, "[%d] frame id = %d, wptr = 0x%x, size = %d\n",
85 inst->id, info.frame_id, info.wptr, info.frame_size);
86 call_void_vop(inst, get_one_frame, &info);
87 }
88
vpu_session_handle_frame_request(struct vpu_inst * inst,struct vpu_rpc_event * pkt)89 static void vpu_session_handle_frame_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
90 {
91 struct vpu_fs_info fs;
92
93 vpu_iface_unpack_msg_data(inst->core, pkt, &fs);
94 call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_REQ, &fs);
95 }
96
vpu_session_handle_frame_release(struct vpu_inst * inst,struct vpu_rpc_event * pkt)97 static void vpu_session_handle_frame_release(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
98 {
99 if (inst->core->type == VPU_CORE_TYPE_ENC) {
100 struct vpu_frame_info info;
101
102 memset(&info, 0, sizeof(info));
103 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info.sequence);
104 dev_dbg(inst->dev, "[%d] %d\n", inst->id, info.sequence);
105 info.type = inst->out_format.type;
106 call_void_vop(inst, buf_done, &info);
107 } else if (inst->core->type == VPU_CORE_TYPE_DEC) {
108 struct vpu_fs_info fs;
109
110 vpu_iface_unpack_msg_data(inst->core, pkt, &fs);
111 call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_RELEASE, &fs);
112 }
113 }
114
vpu_session_handle_input_done(struct vpu_inst * inst,struct vpu_rpc_event * pkt)115 static void vpu_session_handle_input_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
116 {
117 dev_dbg(inst->dev, "[%d]\n", inst->id);
118 call_void_vop(inst, input_done);
119 }
120
vpu_session_handle_pic_decoded(struct vpu_inst * inst,struct vpu_rpc_event * pkt)121 static void vpu_session_handle_pic_decoded(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
122 {
123 struct vpu_dec_pic_info info;
124
125 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
126 call_void_vop(inst, get_one_frame, &info);
127 }
128
vpu_session_handle_pic_done(struct vpu_inst * inst,struct vpu_rpc_event * pkt)129 static void vpu_session_handle_pic_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
130 {
131 struct vpu_dec_pic_info info;
132 struct vpu_frame_info frame;
133
134 memset(&frame, 0, sizeof(frame));
135 vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info);
136 if (inst->core->type == VPU_CORE_TYPE_DEC)
137 frame.type = inst->cap_format.type;
138 frame.id = info.id;
139 frame.luma = info.luma;
140 frame.skipped = info.skipped;
141 frame.timestamp = info.timestamp;
142
143 call_void_vop(inst, buf_done, &frame);
144 }
145
vpu_session_handle_eos(struct vpu_inst * inst,struct vpu_rpc_event * pkt)146 static void vpu_session_handle_eos(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
147 {
148 call_void_vop(inst, event_notify, VPU_MSG_ID_PIC_EOS, NULL);
149 }
150
vpu_session_handle_error(struct vpu_inst * inst,struct vpu_rpc_event * pkt)151 static void vpu_session_handle_error(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
152 {
153 char *str = (char *)pkt->data;
154
155 if (strlen(str))
156 dev_err(inst->dev, "instance %d firmware error : %s\n", inst->id, str);
157 else
158 dev_err(inst->dev, "instance %d is unsupported stream\n", inst->id);
159 call_void_vop(inst, event_notify, VPU_MSG_ID_UNSUPPORTED, NULL);
160 vpu_v4l2_set_error(inst);
161 }
162
vpu_session_handle_firmware_xcpt(struct vpu_inst * inst,struct vpu_rpc_event * pkt)163 static void vpu_session_handle_firmware_xcpt(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
164 {
165 char *str = (char *)pkt->data;
166
167 dev_err(inst->dev, "%s firmware xcpt: %s\n",
168 vpu_core_type_desc(inst->core->type), str);
169 call_void_vop(inst, event_notify, VPU_MSG_ID_FIRMWARE_XCPT, NULL);
170 set_bit(inst->id, &inst->core->hang_mask);
171 vpu_v4l2_set_error(inst);
172 }
173
vpu_session_handle_pic_skipped(struct vpu_inst * inst,struct vpu_rpc_event * pkt)174 static void vpu_session_handle_pic_skipped(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
175 {
176 vpu_inst_lock(inst);
177 vpu_skip_frame(inst, 1);
178 vpu_inst_unlock(inst);
179 }
180
181 static struct vpu_msg_handler handlers[] = {
182 {VPU_MSG_ID_START_DONE, vpu_session_handle_start_done},
183 {VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done},
184 {VPU_MSG_ID_MEM_REQUEST, vpu_session_handle_mem_request},
185 {VPU_MSG_ID_SEQ_HDR_FOUND, vpu_session_handle_seq_hdr},
186 {VPU_MSG_ID_RES_CHANGE, vpu_session_handle_resolution_change},
187 {VPU_MSG_ID_FRAME_INPUT_DONE, vpu_session_handle_input_done},
188 {VPU_MSG_ID_FRAME_REQ, vpu_session_handle_frame_request},
189 {VPU_MSG_ID_FRAME_RELEASE, vpu_session_handle_frame_release},
190 {VPU_MSG_ID_ENC_DONE, vpu_session_handle_enc_frame_done},
191 {VPU_MSG_ID_PIC_DECODED, vpu_session_handle_pic_decoded},
192 {VPU_MSG_ID_DEC_DONE, vpu_session_handle_pic_done},
193 {VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos},
194 {VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error},
195 {VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt},
196 {VPU_MSG_ID_PIC_SKIPPED, vpu_session_handle_pic_skipped},
197 };
198
vpu_session_handle_msg(struct vpu_inst * inst,struct vpu_rpc_event * msg)199 static int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg)
200 {
201 int ret;
202 u32 msg_id;
203 struct vpu_msg_handler *handler = NULL;
204 unsigned int i;
205
206 ret = vpu_iface_convert_msg_id(inst->core, msg->hdr.id);
207 if (ret < 0)
208 return -EINVAL;
209
210 msg_id = ret;
211 dev_dbg(inst->dev, "[%d] receive event(0x%x)\n", inst->id, msg_id);
212
213 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
214 if (handlers[i].id == msg_id) {
215 handler = &handlers[i];
216 break;
217 }
218 }
219
220 if (handler && handler->done)
221 handler->done(inst, msg);
222
223 vpu_response_cmd(inst, msg_id, 1);
224
225 return 0;
226 }
227
vpu_inst_receive_msg(struct vpu_inst * inst,struct vpu_rpc_event * pkt)228 static bool vpu_inst_receive_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
229 {
230 unsigned long bytes = sizeof(struct vpu_rpc_event_header);
231 u32 ret;
232
233 memset(pkt, 0, sizeof(*pkt));
234 if (kfifo_len(&inst->msg_fifo) < bytes)
235 return false;
236
237 ret = kfifo_out(&inst->msg_fifo, pkt, bytes);
238 if (ret != bytes)
239 return false;
240
241 if (pkt->hdr.num > 0) {
242 bytes = pkt->hdr.num * sizeof(u32);
243 ret = kfifo_out(&inst->msg_fifo, pkt->data, bytes);
244 if (ret != bytes)
245 return false;
246 }
247
248 return true;
249 }
250
vpu_inst_run_work(struct work_struct * work)251 void vpu_inst_run_work(struct work_struct *work)
252 {
253 struct vpu_inst *inst = container_of(work, struct vpu_inst, msg_work);
254 struct vpu_rpc_event pkt;
255
256 while (vpu_inst_receive_msg(inst, &pkt))
257 vpu_session_handle_msg(inst, &pkt);
258 }
259
vpu_inst_handle_msg(struct vpu_inst * inst,struct vpu_rpc_event * pkt)260 static void vpu_inst_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
261 {
262 unsigned long bytes;
263 u32 id = pkt->hdr.id;
264 int ret;
265
266 if (!inst->workqueue)
267 return;
268
269 bytes = sizeof(pkt->hdr) + pkt->hdr.num * sizeof(u32);
270 ret = kfifo_in(&inst->msg_fifo, pkt, bytes);
271 if (ret != bytes)
272 dev_err(inst->dev, "[%d:%d]overflow: %d\n", inst->core->id, inst->id, id);
273 queue_work(inst->workqueue, &inst->msg_work);
274 }
275
vpu_handle_msg(struct vpu_core * core)276 static int vpu_handle_msg(struct vpu_core *core)
277 {
278 struct vpu_rpc_event pkt;
279 struct vpu_inst *inst;
280 int ret;
281
282 memset(&pkt, 0, sizeof(pkt));
283 while (!vpu_iface_receive_msg(core, &pkt)) {
284 dev_dbg(core->dev, "event index = %d, id = %d, num = %d\n",
285 pkt.hdr.index, pkt.hdr.id, pkt.hdr.num);
286
287 ret = vpu_iface_convert_msg_id(core, pkt.hdr.id);
288 if (ret < 0)
289 continue;
290
291 inst = vpu_core_find_instance(core, pkt.hdr.index);
292 if (inst) {
293 vpu_response_cmd(inst, ret, 0);
294 mutex_lock(&core->cmd_lock);
295 vpu_inst_record_flow(inst, ret);
296 mutex_unlock(&core->cmd_lock);
297
298 vpu_inst_handle_msg(inst, &pkt);
299 vpu_inst_put(inst);
300 }
301 memset(&pkt, 0, sizeof(pkt));
302 }
303
304 return 0;
305 }
306
vpu_isr_thread(struct vpu_core * core,u32 irq_code)307 static int vpu_isr_thread(struct vpu_core *core, u32 irq_code)
308 {
309 dev_dbg(core->dev, "irq code = 0x%x\n", irq_code);
310 switch (irq_code) {
311 case VPU_IRQ_CODE_SYNC:
312 vpu_mbox_send_msg(core, PRC_BUF_OFFSET, core->rpc.phys - core->fw.phys);
313 vpu_mbox_send_msg(core, BOOT_ADDRESS, core->fw.phys);
314 vpu_mbox_send_msg(core, INIT_DONE, 2);
315 break;
316 case VPU_IRQ_CODE_BOOT_DONE:
317 break;
318 case VPU_IRQ_CODE_SNAPSHOT_DONE:
319 break;
320 default:
321 vpu_handle_msg(core);
322 break;
323 }
324
325 return 0;
326 }
327
vpu_core_run_msg_work(struct vpu_core * core)328 static void vpu_core_run_msg_work(struct vpu_core *core)
329 {
330 const unsigned int SIZE = sizeof(u32);
331
332 while (kfifo_len(&core->msg_fifo) >= SIZE) {
333 u32 data = 0;
334
335 if (kfifo_out(&core->msg_fifo, &data, SIZE) == SIZE)
336 vpu_isr_thread(core, data);
337 }
338 }
339
vpu_msg_run_work(struct work_struct * work)340 void vpu_msg_run_work(struct work_struct *work)
341 {
342 struct vpu_core *core = container_of(work, struct vpu_core, msg_work);
343 unsigned long delay = msecs_to_jiffies(10);
344
345 vpu_core_run_msg_work(core);
346 queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay);
347 }
348
vpu_msg_delayed_work(struct work_struct * work)349 void vpu_msg_delayed_work(struct work_struct *work)
350 {
351 struct vpu_core *core;
352 struct delayed_work *dwork;
353 unsigned long bytes = sizeof(u32);
354 u32 i;
355
356 if (!work)
357 return;
358
359 dwork = to_delayed_work(work);
360 core = container_of(dwork, struct vpu_core, msg_delayed_work);
361 if (kfifo_len(&core->msg_fifo) >= bytes)
362 vpu_core_run_msg_work(core);
363
364 bytes = sizeof(struct vpu_rpc_event_header);
365 for (i = 0; i < core->supported_instance_count; i++) {
366 struct vpu_inst *inst = vpu_core_find_instance(core, i);
367
368 if (!inst)
369 continue;
370
371 if (inst->workqueue && kfifo_len(&inst->msg_fifo) >= bytes)
372 queue_work(inst->workqueue, &inst->msg_work);
373
374 vpu_inst_put(inst);
375 }
376 }
377
vpu_isr(struct vpu_core * core,u32 irq)378 int vpu_isr(struct vpu_core *core, u32 irq)
379 {
380 switch (irq) {
381 case VPU_IRQ_CODE_SYNC:
382 break;
383 case VPU_IRQ_CODE_BOOT_DONE:
384 complete(&core->cmp);
385 break;
386 case VPU_IRQ_CODE_SNAPSHOT_DONE:
387 complete(&core->cmp);
388 break;
389 default:
390 break;
391 }
392
393 if (kfifo_in(&core->msg_fifo, &irq, sizeof(irq)) != sizeof(irq))
394 dev_err(core->dev, "[%d]overflow: %d\n", core->id, irq);
395 queue_work(core->workqueue, &core->msg_work);
396
397 return 0;
398 }
399