messages.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
  4. //
  5. // Authors: Cezary Rojewski <[email protected]>
  6. // Amadeusz Slawinski <[email protected]>
  7. //
  8. #include <linux/slab.h>
  9. #include "avs.h"
  10. #include "messages.h"
  11. #define AVS_CL_TIMEOUT_MS 5000
  12. int avs_ipc_set_boot_config(struct avs_dev *adev, u32 dma_id, u32 purge)
  13. {
  14. union avs_global_msg msg = AVS_GLOBAL_REQUEST(ROM_CONTROL);
  15. struct avs_ipc_msg request = {{0}};
  16. int ret;
  17. msg.boot_cfg.rom_ctrl_msg_type = AVS_ROM_SET_BOOT_CONFIG;
  18. msg.boot_cfg.dma_id = dma_id;
  19. msg.boot_cfg.purge_request = purge;
  20. request.header = msg.val;
  21. ret = avs_dsp_send_rom_msg(adev, &request);
  22. if (ret)
  23. avs_ipc_err(adev, &request, "set boot config", ret);
  24. return ret;
  25. }
  26. int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids)
  27. {
  28. union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_MULTIPLE_MODULES);
  29. struct avs_ipc_msg request;
  30. int ret;
  31. msg.load_multi_mods.mod_cnt = num_mod_ids;
  32. request.header = msg.val;
  33. request.data = mod_ids;
  34. request.size = sizeof(*mod_ids) * num_mod_ids;
  35. ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS);
  36. if (ret)
  37. avs_ipc_err(adev, &request, "load multiple modules", ret);
  38. return ret;
  39. }
  40. int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids)
  41. {
  42. union avs_global_msg msg = AVS_GLOBAL_REQUEST(UNLOAD_MULTIPLE_MODULES);
  43. struct avs_ipc_msg request;
  44. int ret;
  45. msg.load_multi_mods.mod_cnt = num_mod_ids;
  46. request.header = msg.val;
  47. request.data = mod_ids;
  48. request.size = sizeof(*mod_ids) * num_mod_ids;
  49. ret = avs_dsp_send_msg(adev, &request, NULL);
  50. if (ret)
  51. avs_ipc_err(adev, &request, "unload multiple modules", ret);
  52. return ret;
  53. }
  54. int avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id)
  55. {
  56. union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_LIBRARY);
  57. struct avs_ipc_msg request = {{0}};
  58. int ret;
  59. msg.load_lib.dma_id = dma_id;
  60. msg.load_lib.lib_id = lib_id;
  61. request.header = msg.val;
  62. ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS);
  63. if (ret)
  64. avs_ipc_err(adev, &request, "load library", ret);
  65. return ret;
  66. }
  67. int avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
  68. u8 instance_id, bool lp, u16 attributes)
  69. {
  70. union avs_global_msg msg = AVS_GLOBAL_REQUEST(CREATE_PIPELINE);
  71. struct avs_ipc_msg request = {{0}};
  72. int ret;
  73. msg.create_ppl.ppl_mem_size = req_size;
  74. msg.create_ppl.ppl_priority = priority;
  75. msg.create_ppl.instance_id = instance_id;
  76. msg.ext.create_ppl.lp = lp;
  77. msg.ext.create_ppl.attributes = attributes;
  78. request.header = msg.val;
  79. ret = avs_dsp_send_msg(adev, &request, NULL);
  80. if (ret)
  81. avs_ipc_err(adev, &request, "create pipeline", ret);
  82. return ret;
  83. }
  84. int avs_ipc_delete_pipeline(struct avs_dev *adev, u8 instance_id)
  85. {
  86. union avs_global_msg msg = AVS_GLOBAL_REQUEST(DELETE_PIPELINE);
  87. struct avs_ipc_msg request = {{0}};
  88. int ret;
  89. msg.ppl.instance_id = instance_id;
  90. request.header = msg.val;
  91. ret = avs_dsp_send_msg(adev, &request, NULL);
  92. if (ret)
  93. avs_ipc_err(adev, &request, "delete pipeline", ret);
  94. return ret;
  95. }
  96. int avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id,
  97. enum avs_pipeline_state state)
  98. {
  99. union avs_global_msg msg = AVS_GLOBAL_REQUEST(SET_PIPELINE_STATE);
  100. struct avs_ipc_msg request = {{0}};
  101. int ret;
  102. msg.set_ppl_state.ppl_id = instance_id;
  103. msg.set_ppl_state.state = state;
  104. request.header = msg.val;
  105. ret = avs_dsp_send_msg(adev, &request, NULL);
  106. if (ret)
  107. avs_ipc_err(adev, &request, "set pipeline state", ret);
  108. return ret;
  109. }
  110. int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id,
  111. enum avs_pipeline_state *state)
  112. {
  113. union avs_global_msg msg = AVS_GLOBAL_REQUEST(GET_PIPELINE_STATE);
  114. struct avs_ipc_msg request = {{0}};
  115. struct avs_ipc_msg reply = {{0}};
  116. int ret;
  117. msg.get_ppl_state.ppl_id = instance_id;
  118. request.header = msg.val;
  119. ret = avs_dsp_send_msg(adev, &request, &reply);
  120. if (ret) {
  121. avs_ipc_err(adev, &request, "get pipeline state", ret);
  122. return ret;
  123. }
  124. *state = reply.rsp.ext.get_ppl_state.state;
  125. return ret;
  126. }
  127. /*
  128. * avs_ipc_init_instance - Initialize module instance
  129. *
  130. * @adev: Driver context
  131. * @module_id: Module-type id
  132. * @instance_id: Unique module instance id
  133. * @ppl_id: Parent pipeline id
  134. * @core_id: DSP core to allocate module on
  135. * @domain: Processing domain (low latency or data processing)
  136. * @param: Module-type specific configuration
  137. * @param_size: Size of @param in bytes
  138. *
  139. * Argument verification, as well as pipeline state checks are done by the
  140. * firmware.
  141. *
  142. * Note: @ppl_id and @core_id are independent of each other as single pipeline
  143. * can be composed of module instances located on different DSP cores.
  144. */
  145. int avs_ipc_init_instance(struct avs_dev *adev, u16 module_id, u8 instance_id,
  146. u8 ppl_id, u8 core_id, u8 domain,
  147. void *param, u32 param_size)
  148. {
  149. union avs_module_msg msg = AVS_MODULE_REQUEST(INIT_INSTANCE);
  150. struct avs_ipc_msg request;
  151. int ret;
  152. msg.module_id = module_id;
  153. msg.instance_id = instance_id;
  154. /* firmware expects size provided in dwords */
  155. msg.ext.init_instance.param_block_size = DIV_ROUND_UP(param_size, sizeof(u32));
  156. msg.ext.init_instance.ppl_instance_id = ppl_id;
  157. msg.ext.init_instance.core_id = core_id;
  158. msg.ext.init_instance.proc_domain = domain;
  159. request.header = msg.val;
  160. request.data = param;
  161. request.size = param_size;
  162. ret = avs_dsp_send_msg(adev, &request, NULL);
  163. if (ret)
  164. avs_ipc_err(adev, &request, "init instance", ret);
  165. return ret;
  166. }
  167. /*
  168. * avs_ipc_delete_instance - Delete module instance
  169. *
  170. * @adev: Driver context
  171. * @module_id: Module-type id
  172. * @instance_id: Unique module instance id
  173. *
  174. * Argument verification, as well as pipeline state checks are done by the
  175. * firmware.
  176. *
  177. * Note: only standalone modules i.e. without a parent pipeline shall be
  178. * deleted using this IPC message. In all other cases, pipeline owning the
  179. * modules performs cleanup automatically when it is deleted.
  180. */
  181. int avs_ipc_delete_instance(struct avs_dev *adev, u16 module_id, u8 instance_id)
  182. {
  183. union avs_module_msg msg = AVS_MODULE_REQUEST(DELETE_INSTANCE);
  184. struct avs_ipc_msg request = {{0}};
  185. int ret;
  186. msg.module_id = module_id;
  187. msg.instance_id = instance_id;
  188. request.header = msg.val;
  189. ret = avs_dsp_send_msg(adev, &request, NULL);
  190. if (ret)
  191. avs_ipc_err(adev, &request, "delete instance", ret);
  192. return ret;
  193. }
  194. /*
  195. * avs_ipc_bind - Bind two module instances
  196. *
  197. * @adev: Driver context
  198. * @module_id: Source module-type id
  199. * @instance_id: Source module instance id
  200. * @dst_module_id: Sink module-type id
  201. * @dst_instance_id: Sink module instance id
  202. * @dst_queue: Sink module pin to bind @src_queue with
  203. * @src_queue: Source module pin to bind @dst_queue with
  204. */
  205. int avs_ipc_bind(struct avs_dev *adev, u16 module_id, u8 instance_id,
  206. u16 dst_module_id, u8 dst_instance_id,
  207. u8 dst_queue, u8 src_queue)
  208. {
  209. union avs_module_msg msg = AVS_MODULE_REQUEST(BIND);
  210. struct avs_ipc_msg request = {{0}};
  211. int ret;
  212. msg.module_id = module_id;
  213. msg.instance_id = instance_id;
  214. msg.ext.bind_unbind.dst_module_id = dst_module_id;
  215. msg.ext.bind_unbind.dst_instance_id = dst_instance_id;
  216. msg.ext.bind_unbind.dst_queue = dst_queue;
  217. msg.ext.bind_unbind.src_queue = src_queue;
  218. request.header = msg.val;
  219. ret = avs_dsp_send_msg(adev, &request, NULL);
  220. if (ret)
  221. avs_ipc_err(adev, &request, "bind modules", ret);
  222. return ret;
  223. }
  224. /*
  225. * avs_ipc_unbind - Unbind two module instances
  226. *
  227. * @adev: Driver context
  228. * @module_id: Source module-type id
  229. * @instance_id: Source module instance id
  230. * @dst_module_id: Sink module-type id
  231. * @dst_instance_id: Sink module instance id
  232. * @dst_queue: Sink module pin to unbind @src_queue from
  233. * @src_queue: Source module pin to unbind @dst_queue from
  234. */
  235. int avs_ipc_unbind(struct avs_dev *adev, u16 module_id, u8 instance_id,
  236. u16 dst_module_id, u8 dst_instance_id,
  237. u8 dst_queue, u8 src_queue)
  238. {
  239. union avs_module_msg msg = AVS_MODULE_REQUEST(UNBIND);
  240. struct avs_ipc_msg request = {{0}};
  241. int ret;
  242. msg.module_id = module_id;
  243. msg.instance_id = instance_id;
  244. msg.ext.bind_unbind.dst_module_id = dst_module_id;
  245. msg.ext.bind_unbind.dst_instance_id = dst_instance_id;
  246. msg.ext.bind_unbind.dst_queue = dst_queue;
  247. msg.ext.bind_unbind.src_queue = src_queue;
  248. request.header = msg.val;
  249. ret = avs_dsp_send_msg(adev, &request, NULL);
  250. if (ret)
  251. avs_ipc_err(adev, &request, "unbind modules", ret);
  252. return ret;
  253. }
  254. static int __avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id,
  255. u8 param_id, bool init_block, bool final_block,
  256. u8 *request_data, size_t request_size, size_t off_size)
  257. {
  258. union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_SET);
  259. struct avs_ipc_msg request;
  260. int ret;
  261. msg.module_id = module_id;
  262. msg.instance_id = instance_id;
  263. msg.ext.large_config.data_off_size = off_size;
  264. msg.ext.large_config.large_param_id = param_id;
  265. msg.ext.large_config.final_block = final_block;
  266. msg.ext.large_config.init_block = init_block;
  267. request.header = msg.val;
  268. request.data = request_data;
  269. request.size = request_size;
  270. ret = avs_dsp_send_msg(adev, &request, NULL);
  271. if (ret)
  272. avs_ipc_err(adev, &request, "large config set", ret);
  273. return ret;
  274. }
  275. int avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id,
  276. u8 instance_id, u8 param_id,
  277. u8 *request, size_t request_size)
  278. {
  279. size_t remaining, tx_size;
  280. bool final;
  281. int ret;
  282. remaining = request_size;
  283. tx_size = min_t(size_t, AVS_MAILBOX_SIZE, remaining);
  284. final = (tx_size == remaining);
  285. /* Initial request states total payload size. */
  286. ret = __avs_ipc_set_large_config(adev, module_id, instance_id,
  287. param_id, 1, final, request, tx_size,
  288. request_size);
  289. if (ret)
  290. return ret;
  291. remaining -= tx_size;
  292. /* Loop the rest only when payload exceeds mailbox's size. */
  293. while (remaining) {
  294. size_t offset;
  295. offset = request_size - remaining;
  296. tx_size = min_t(size_t, AVS_MAILBOX_SIZE, remaining);
  297. final = (tx_size == remaining);
  298. ret = __avs_ipc_set_large_config(adev, module_id, instance_id,
  299. param_id, 0, final,
  300. request + offset, tx_size,
  301. offset);
  302. if (ret)
  303. return ret;
  304. remaining -= tx_size;
  305. }
  306. return 0;
  307. }
  308. int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id,
  309. u8 param_id, u8 *request_data, size_t request_size,
  310. u8 **reply_data, size_t *reply_size)
  311. {
  312. union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_GET);
  313. struct avs_ipc_msg request;
  314. struct avs_ipc_msg reply = {{0}};
  315. void *buf;
  316. int ret;
  317. reply.data = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL);
  318. if (!reply.data)
  319. return -ENOMEM;
  320. msg.module_id = module_id;
  321. msg.instance_id = instance_id;
  322. msg.ext.large_config.data_off_size = request_size;
  323. msg.ext.large_config.large_param_id = param_id;
  324. /* final_block is always 0 on request. Updated by fw on reply. */
  325. msg.ext.large_config.final_block = 0;
  326. msg.ext.large_config.init_block = 1;
  327. request.header = msg.val;
  328. request.data = request_data;
  329. request.size = request_size;
  330. reply.size = AVS_MAILBOX_SIZE;
  331. ret = avs_dsp_send_msg(adev, &request, &reply);
  332. if (ret) {
  333. avs_ipc_err(adev, &request, "large config get", ret);
  334. kfree(reply.data);
  335. return ret;
  336. }
  337. buf = krealloc(reply.data, reply.size, GFP_KERNEL);
  338. if (!buf) {
  339. kfree(reply.data);
  340. return -ENOMEM;
  341. }
  342. *reply_data = buf;
  343. *reply_size = reply.size;
  344. return 0;
  345. }
  346. int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup)
  347. {
  348. union avs_module_msg msg = AVS_MODULE_REQUEST(SET_DX);
  349. struct avs_ipc_msg request;
  350. struct avs_dxstate_info dx;
  351. int ret;
  352. dx.core_mask = core_mask;
  353. dx.dx_mask = powerup ? core_mask : 0;
  354. request.header = msg.val;
  355. request.data = &dx;
  356. request.size = sizeof(dx);
  357. ret = avs_dsp_send_pm_msg(adev, &request, NULL, true);
  358. if (ret)
  359. avs_ipc_err(adev, &request, "set dx", ret);
  360. return ret;
  361. }
  362. /*
  363. * avs_ipc_set_d0ix - Set power gating policy (entering D0IX substates)
  364. *
  365. * @enable_pg: Whether to enable or disable power gating
  366. * @streaming: Whether a stream is running when transitioning
  367. */
  368. int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming)
  369. {
  370. union avs_module_msg msg = AVS_MODULE_REQUEST(SET_D0IX);
  371. struct avs_ipc_msg request = {{0}};
  372. int ret;
  373. msg.ext.set_d0ix.wake = enable_pg;
  374. msg.ext.set_d0ix.streaming = streaming;
  375. request.header = msg.val;
  376. ret = avs_dsp_send_pm_msg(adev, &request, NULL, false);
  377. if (ret)
  378. avs_ipc_err(adev, &request, "set d0ix", ret);
  379. return ret;
  380. }
  381. int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg)
  382. {
  383. struct avs_tlv *tlv;
  384. size_t payload_size;
  385. size_t offset = 0;
  386. u8 *payload;
  387. int ret;
  388. ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
  389. AVS_BASEFW_FIRMWARE_CONFIG, NULL, 0,
  390. &payload, &payload_size);
  391. if (ret)
  392. return ret;
  393. /* Non-zero payload expected for FIRMWARE_CONFIG. */
  394. if (!payload_size)
  395. return -EREMOTEIO;
  396. while (offset < payload_size) {
  397. tlv = (struct avs_tlv *)(payload + offset);
  398. switch (tlv->type) {
  399. case AVS_FW_CFG_FW_VERSION:
  400. memcpy(&cfg->fw_version, tlv->value, sizeof(cfg->fw_version));
  401. break;
  402. case AVS_FW_CFG_MEMORY_RECLAIMED:
  403. cfg->memory_reclaimed = *tlv->value;
  404. break;
  405. case AVS_FW_CFG_SLOW_CLOCK_FREQ_HZ:
  406. cfg->slow_clock_freq_hz = *tlv->value;
  407. break;
  408. case AVS_FW_CFG_FAST_CLOCK_FREQ_HZ:
  409. cfg->fast_clock_freq_hz = *tlv->value;
  410. break;
  411. case AVS_FW_CFG_ALH_SUPPORT_LEVEL:
  412. cfg->alh_support = *tlv->value;
  413. break;
  414. case AVS_FW_CFG_IPC_DL_MAILBOX_BYTES:
  415. cfg->ipc_dl_mailbox_bytes = *tlv->value;
  416. break;
  417. case AVS_FW_CFG_IPC_UL_MAILBOX_BYTES:
  418. cfg->ipc_ul_mailbox_bytes = *tlv->value;
  419. break;
  420. case AVS_FW_CFG_TRACE_LOG_BYTES:
  421. cfg->trace_log_bytes = *tlv->value;
  422. break;
  423. case AVS_FW_CFG_MAX_PPL_COUNT:
  424. cfg->max_ppl_count = *tlv->value;
  425. break;
  426. case AVS_FW_CFG_MAX_ASTATE_COUNT:
  427. cfg->max_astate_count = *tlv->value;
  428. break;
  429. case AVS_FW_CFG_MAX_MODULE_PIN_COUNT:
  430. cfg->max_module_pin_count = *tlv->value;
  431. break;
  432. case AVS_FW_CFG_MODULES_COUNT:
  433. cfg->modules_count = *tlv->value;
  434. break;
  435. case AVS_FW_CFG_MAX_MOD_INST_COUNT:
  436. cfg->max_mod_inst_count = *tlv->value;
  437. break;
  438. case AVS_FW_CFG_MAX_LL_TASKS_PER_PRI_COUNT:
  439. cfg->max_ll_tasks_per_pri_count = *tlv->value;
  440. break;
  441. case AVS_FW_CFG_LL_PRI_COUNT:
  442. cfg->ll_pri_count = *tlv->value;
  443. break;
  444. case AVS_FW_CFG_MAX_DP_TASKS_COUNT:
  445. cfg->max_dp_tasks_count = *tlv->value;
  446. break;
  447. case AVS_FW_CFG_MAX_LIBS_COUNT:
  448. cfg->max_libs_count = *tlv->value;
  449. break;
  450. case AVS_FW_CFG_XTAL_FREQ_HZ:
  451. cfg->xtal_freq_hz = *tlv->value;
  452. break;
  453. case AVS_FW_CFG_POWER_GATING_POLICY:
  454. cfg->power_gating_policy = *tlv->value;
  455. break;
  456. /* Known but not useful to us. */
  457. case AVS_FW_CFG_DMA_BUFFER_CONFIG:
  458. case AVS_FW_CFG_SCHEDULER_CONFIG:
  459. case AVS_FW_CFG_CLOCKS_CONFIG:
  460. case AVS_FW_CFG_RESERVED:
  461. break;
  462. default:
  463. dev_info(adev->dev, "Unrecognized fw param: %d\n", tlv->type);
  464. break;
  465. }
  466. offset += sizeof(*tlv) + tlv->length;
  467. }
  468. /* No longer needed, free it as it's owned by the get_large_config() caller. */
  469. kfree(payload);
  470. return ret;
  471. }
  472. int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg)
  473. {
  474. struct avs_tlv *tlv;
  475. size_t payload_size;
  476. size_t size, offset = 0;
  477. u8 *payload;
  478. int ret;
  479. ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
  480. AVS_BASEFW_HARDWARE_CONFIG, NULL, 0,
  481. &payload, &payload_size);
  482. if (ret)
  483. return ret;
  484. /* Non-zero payload expected for HARDWARE_CONFIG. */
  485. if (!payload_size)
  486. return -EREMOTEIO;
  487. while (offset < payload_size) {
  488. tlv = (struct avs_tlv *)(payload + offset);
  489. switch (tlv->type) {
  490. case AVS_HW_CFG_AVS_VER:
  491. cfg->avs_version = *tlv->value;
  492. break;
  493. case AVS_HW_CFG_DSP_CORES:
  494. cfg->dsp_cores = *tlv->value;
  495. break;
  496. case AVS_HW_CFG_MEM_PAGE_BYTES:
  497. cfg->mem_page_bytes = *tlv->value;
  498. break;
  499. case AVS_HW_CFG_TOTAL_PHYS_MEM_PAGES:
  500. cfg->total_phys_mem_pages = *tlv->value;
  501. break;
  502. case AVS_HW_CFG_I2S_CAPS:
  503. cfg->i2s_caps.i2s_version = tlv->value[0];
  504. size = tlv->value[1];
  505. cfg->i2s_caps.ctrl_count = size;
  506. if (!size)
  507. break;
  508. /* Multiply to get entire array size. */
  509. size *= sizeof(*cfg->i2s_caps.ctrl_base_addr);
  510. cfg->i2s_caps.ctrl_base_addr = devm_kmemdup(adev->dev,
  511. &tlv->value[2],
  512. size, GFP_KERNEL);
  513. if (!cfg->i2s_caps.ctrl_base_addr) {
  514. ret = -ENOMEM;
  515. goto exit;
  516. }
  517. break;
  518. case AVS_HW_CFG_GATEWAY_COUNT:
  519. cfg->gateway_count = *tlv->value;
  520. break;
  521. case AVS_HW_CFG_HP_EBB_COUNT:
  522. cfg->hp_ebb_count = *tlv->value;
  523. break;
  524. case AVS_HW_CFG_LP_EBB_COUNT:
  525. cfg->lp_ebb_count = *tlv->value;
  526. break;
  527. case AVS_HW_CFG_EBB_SIZE_BYTES:
  528. cfg->ebb_size_bytes = *tlv->value;
  529. break;
  530. case AVS_HW_CFG_GPDMA_CAPS:
  531. break;
  532. default:
  533. dev_info(adev->dev, "Unrecognized hw config: %d\n", tlv->type);
  534. break;
  535. }
  536. offset += sizeof(*tlv) + tlv->length;
  537. }
  538. exit:
  539. /* No longer needed, free it as it's owned by the get_large_config() caller. */
  540. kfree(payload);
  541. return ret;
  542. }
  543. int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info)
  544. {
  545. size_t payload_size;
  546. u8 *payload;
  547. int ret;
  548. ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
  549. AVS_BASEFW_MODULES_INFO, NULL, 0,
  550. &payload, &payload_size);
  551. if (ret)
  552. return ret;
  553. /* Non-zero payload expected for MODULES_INFO. */
  554. if (!payload_size)
  555. return -EREMOTEIO;
  556. *info = (struct avs_mods_info *)payload;
  557. return 0;
  558. }
  559. int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size)
  560. {
  561. int ret;
  562. ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
  563. AVS_BASEFW_ENABLE_LOGS, log_info, size);
  564. if (ret)
  565. dev_err(adev->dev, "enable logs failed: %d\n", ret);
  566. return ret;
  567. }
  568. int avs_ipc_set_system_time(struct avs_dev *adev)
  569. {
  570. struct avs_sys_time sys_time;
  571. int ret;
  572. u64 us;
  573. /* firmware expects UTC time in micro seconds */
  574. us = ktime_to_us(ktime_get());
  575. sys_time.val_l = us & UINT_MAX;
  576. sys_time.val_u = us >> 32;
  577. ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
  578. AVS_BASEFW_SYSTEM_TIME, (u8 *)&sys_time, sizeof(sys_time));
  579. if (ret)
  580. dev_err(adev->dev, "set system time failed: %d\n", ret);
  581. return ret;
  582. }
  583. int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id,
  584. u8 instance_id, u32 sink_id,
  585. const struct avs_audio_format *src_fmt,
  586. const struct avs_audio_format *sink_fmt)
  587. {
  588. struct avs_copier_sink_format cpr_fmt;
  589. cpr_fmt.sink_id = sink_id;
  590. /* Firmware expects driver to resend copier's input format. */
  591. cpr_fmt.src_fmt = *src_fmt;
  592. cpr_fmt.sink_fmt = *sink_fmt;
  593. return avs_ipc_set_large_config(adev, module_id, instance_id,
  594. AVS_COPIER_SET_SINK_FORMAT,
  595. (u8 *)&cpr_fmt, sizeof(cpr_fmt));
  596. }