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