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