GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / media / platform / amphion / vpu_msgs.c
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
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
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
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
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
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
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
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
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
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
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
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
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
151 static void vpu_session_handle_error(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
152 {
153         dev_err(inst->dev, "unsupported stream\n");
154         call_void_vop(inst, event_notify, VPU_MSG_ID_UNSUPPORTED, NULL);
155         vpu_v4l2_set_error(inst);
156 }
157
158 static void vpu_session_handle_firmware_xcpt(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
159 {
160         char *str = (char *)pkt->data;
161
162         dev_err(inst->dev, "%s firmware xcpt: %s\n",
163                 vpu_core_type_desc(inst->core->type), str);
164         call_void_vop(inst, event_notify, VPU_MSG_ID_FIRMWARE_XCPT, NULL);
165         set_bit(inst->id, &inst->core->hang_mask);
166         vpu_v4l2_set_error(inst);
167 }
168
169 static void vpu_session_handle_pic_skipped(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
170 {
171         vpu_inst_lock(inst);
172         vpu_skip_frame(inst, 1);
173         vpu_inst_unlock(inst);
174 }
175
176 static struct vpu_msg_handler handlers[] = {
177         {VPU_MSG_ID_START_DONE, vpu_session_handle_start_done},
178         {VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done},
179         {VPU_MSG_ID_MEM_REQUEST, vpu_session_handle_mem_request},
180         {VPU_MSG_ID_SEQ_HDR_FOUND, vpu_session_handle_seq_hdr},
181         {VPU_MSG_ID_RES_CHANGE, vpu_session_handle_resolution_change},
182         {VPU_MSG_ID_FRAME_INPUT_DONE, vpu_session_handle_input_done},
183         {VPU_MSG_ID_FRAME_REQ, vpu_session_handle_frame_request},
184         {VPU_MSG_ID_FRAME_RELEASE, vpu_session_handle_frame_release},
185         {VPU_MSG_ID_ENC_DONE, vpu_session_handle_enc_frame_done},
186         {VPU_MSG_ID_PIC_DECODED, vpu_session_handle_pic_decoded},
187         {VPU_MSG_ID_DEC_DONE, vpu_session_handle_pic_done},
188         {VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos},
189         {VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error},
190         {VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt},
191         {VPU_MSG_ID_PIC_SKIPPED, vpu_session_handle_pic_skipped},
192 };
193
194 static int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg)
195 {
196         int ret;
197         u32 msg_id;
198         struct vpu_msg_handler *handler = NULL;
199         unsigned int i;
200
201         ret = vpu_iface_convert_msg_id(inst->core, msg->hdr.id);
202         if (ret < 0)
203                 return -EINVAL;
204
205         msg_id = ret;
206         dev_dbg(inst->dev, "[%d] receive event(0x%x)\n", inst->id, msg_id);
207
208         for (i = 0; i < ARRAY_SIZE(handlers); i++) {
209                 if (handlers[i].id == msg_id) {
210                         handler = &handlers[i];
211                         break;
212                 }
213         }
214
215         if (handler && handler->done)
216                 handler->done(inst, msg);
217
218         vpu_response_cmd(inst, msg_id, 1);
219
220         return 0;
221 }
222
223 static bool vpu_inst_receive_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
224 {
225         unsigned long bytes = sizeof(struct vpu_rpc_event_header);
226         u32 ret;
227
228         memset(pkt, 0, sizeof(*pkt));
229         if (kfifo_len(&inst->msg_fifo) < bytes)
230                 return false;
231
232         ret = kfifo_out(&inst->msg_fifo, pkt, bytes);
233         if (ret != bytes)
234                 return false;
235
236         if (pkt->hdr.num > 0) {
237                 bytes = pkt->hdr.num * sizeof(u32);
238                 ret = kfifo_out(&inst->msg_fifo, pkt->data, bytes);
239                 if (ret != bytes)
240                         return false;
241         }
242
243         return true;
244 }
245
246 void vpu_inst_run_work(struct work_struct *work)
247 {
248         struct vpu_inst *inst = container_of(work, struct vpu_inst, msg_work);
249         struct vpu_rpc_event pkt;
250
251         while (vpu_inst_receive_msg(inst, &pkt))
252                 vpu_session_handle_msg(inst, &pkt);
253 }
254
255 static void vpu_inst_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
256 {
257         unsigned long bytes;
258         u32 id = pkt->hdr.id;
259         int ret;
260
261         if (!inst->workqueue)
262                 return;
263
264         bytes = sizeof(pkt->hdr) + pkt->hdr.num * sizeof(u32);
265         ret = kfifo_in(&inst->msg_fifo, pkt, bytes);
266         if (ret != bytes)
267                 dev_err(inst->dev, "[%d:%d]overflow: %d\n", inst->core->id, inst->id, id);
268         queue_work(inst->workqueue, &inst->msg_work);
269 }
270
271 static int vpu_handle_msg(struct vpu_core *core)
272 {
273         struct vpu_rpc_event pkt;
274         struct vpu_inst *inst;
275         int ret;
276
277         memset(&pkt, 0, sizeof(pkt));
278         while (!vpu_iface_receive_msg(core, &pkt)) {
279                 dev_dbg(core->dev, "event index = %d, id = %d, num = %d\n",
280                         pkt.hdr.index, pkt.hdr.id, pkt.hdr.num);
281
282                 ret = vpu_iface_convert_msg_id(core, pkt.hdr.id);
283                 if (ret < 0)
284                         continue;
285
286                 inst = vpu_core_find_instance(core, pkt.hdr.index);
287                 if (inst) {
288                         vpu_response_cmd(inst, ret, 0);
289                         mutex_lock(&core->cmd_lock);
290                         vpu_inst_record_flow(inst, ret);
291                         mutex_unlock(&core->cmd_lock);
292
293                         vpu_inst_handle_msg(inst, &pkt);
294                         vpu_inst_put(inst);
295                 }
296                 memset(&pkt, 0, sizeof(pkt));
297         }
298
299         return 0;
300 }
301
302 static int vpu_isr_thread(struct vpu_core *core, u32 irq_code)
303 {
304         dev_dbg(core->dev, "irq code = 0x%x\n", irq_code);
305         switch (irq_code) {
306         case VPU_IRQ_CODE_SYNC:
307                 vpu_mbox_send_msg(core, PRC_BUF_OFFSET, core->rpc.phys - core->fw.phys);
308                 vpu_mbox_send_msg(core, BOOT_ADDRESS, core->fw.phys);
309                 vpu_mbox_send_msg(core, INIT_DONE, 2);
310                 break;
311         case VPU_IRQ_CODE_BOOT_DONE:
312                 break;
313         case VPU_IRQ_CODE_SNAPSHOT_DONE:
314                 break;
315         default:
316                 vpu_handle_msg(core);
317                 break;
318         }
319
320         return 0;
321 }
322
323 static void vpu_core_run_msg_work(struct vpu_core *core)
324 {
325         const unsigned int SIZE = sizeof(u32);
326
327         while (kfifo_len(&core->msg_fifo) >= SIZE) {
328                 u32 data = 0;
329
330                 if (kfifo_out(&core->msg_fifo, &data, SIZE) == SIZE)
331                         vpu_isr_thread(core, data);
332         }
333 }
334
335 void vpu_msg_run_work(struct work_struct *work)
336 {
337         struct vpu_core *core = container_of(work, struct vpu_core, msg_work);
338         unsigned long delay = msecs_to_jiffies(10);
339
340         vpu_core_run_msg_work(core);
341         queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay);
342 }
343
344 void vpu_msg_delayed_work(struct work_struct *work)
345 {
346         struct vpu_core *core;
347         struct delayed_work *dwork;
348         unsigned long bytes = sizeof(u32);
349         u32 i;
350
351         if (!work)
352                 return;
353
354         dwork = to_delayed_work(work);
355         core = container_of(dwork, struct vpu_core, msg_delayed_work);
356         if (kfifo_len(&core->msg_fifo) >= bytes)
357                 vpu_core_run_msg_work(core);
358
359         bytes = sizeof(struct vpu_rpc_event_header);
360         for (i = 0; i < core->supported_instance_count; i++) {
361                 struct vpu_inst *inst = vpu_core_find_instance(core, i);
362
363                 if (!inst)
364                         continue;
365
366                 if (inst->workqueue && kfifo_len(&inst->msg_fifo) >= bytes)
367                         queue_work(inst->workqueue, &inst->msg_work);
368
369                 vpu_inst_put(inst);
370         }
371 }
372
373 int vpu_isr(struct vpu_core *core, u32 irq)
374 {
375         switch (irq) {
376         case VPU_IRQ_CODE_SYNC:
377                 break;
378         case VPU_IRQ_CODE_BOOT_DONE:
379                 complete(&core->cmp);
380                 break;
381         case VPU_IRQ_CODE_SNAPSHOT_DONE:
382                 complete(&core->cmp);
383                 break;
384         default:
385                 break;
386         }
387
388         if (kfifo_in(&core->msg_fifo, &irq, sizeof(irq)) != sizeof(irq))
389                 dev_err(core->dev, "[%d]overflow: %d\n", core->id, irq);
390         queue_work(core->workqueue, &core->msg_work);
391
392         return 0;
393 }