vpu_msgs.c 11 KB

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