162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Authors: Cezary Rojewski <cezary.rojewski@intel.com> 662306a36Sopenharmony_ci// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include "avs.h" 1162306a36Sopenharmony_ci#include "messages.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define AVS_CL_TIMEOUT_MS 5000 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciint avs_ipc_set_boot_config(struct avs_dev *adev, u32 dma_id, u32 purge) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(ROM_CONTROL); 1862306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 1962306a36Sopenharmony_ci int ret; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci msg.boot_cfg.rom_ctrl_msg_type = AVS_ROM_SET_BOOT_CONFIG; 2262306a36Sopenharmony_ci msg.boot_cfg.dma_id = dma_id; 2362306a36Sopenharmony_ci msg.boot_cfg.purge_request = purge; 2462306a36Sopenharmony_ci request.header = msg.val; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci ret = avs_dsp_send_rom_msg(adev, &request); 2762306a36Sopenharmony_ci if (ret) 2862306a36Sopenharmony_ci avs_ipc_err(adev, &request, "set boot config", ret); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci return ret; 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciint avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_MULTIPLE_MODULES); 3662306a36Sopenharmony_ci struct avs_ipc_msg request; 3762306a36Sopenharmony_ci int ret; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci msg.load_multi_mods.mod_cnt = num_mod_ids; 4062306a36Sopenharmony_ci request.header = msg.val; 4162306a36Sopenharmony_ci request.data = mod_ids; 4262306a36Sopenharmony_ci request.size = sizeof(*mod_ids) * num_mod_ids; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); 4562306a36Sopenharmony_ci if (ret) 4662306a36Sopenharmony_ci avs_ipc_err(adev, &request, "load multiple modules", ret); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return ret; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciint avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(UNLOAD_MULTIPLE_MODULES); 5462306a36Sopenharmony_ci struct avs_ipc_msg request; 5562306a36Sopenharmony_ci int ret; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci msg.load_multi_mods.mod_cnt = num_mod_ids; 5862306a36Sopenharmony_ci request.header = msg.val; 5962306a36Sopenharmony_ci request.data = mod_ids; 6062306a36Sopenharmony_ci request.size = sizeof(*mod_ids) * num_mod_ids; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 6362306a36Sopenharmony_ci if (ret) 6462306a36Sopenharmony_ci avs_ipc_err(adev, &request, "unload multiple modules", ret); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return ret; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciint avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_LIBRARY); 7262306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 7362306a36Sopenharmony_ci int ret; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci msg.load_lib.dma_id = dma_id; 7662306a36Sopenharmony_ci msg.load_lib.lib_id = lib_id; 7762306a36Sopenharmony_ci request.header = msg.val; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); 8062306a36Sopenharmony_ci if (ret) 8162306a36Sopenharmony_ci avs_ipc_err(adev, &request, "load library", ret); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return ret; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciint avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, 8762306a36Sopenharmony_ci u8 instance_id, bool lp, u16 attributes) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(CREATE_PIPELINE); 9062306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 9162306a36Sopenharmony_ci int ret; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci msg.create_ppl.ppl_mem_size = req_size; 9462306a36Sopenharmony_ci msg.create_ppl.ppl_priority = priority; 9562306a36Sopenharmony_ci msg.create_ppl.instance_id = instance_id; 9662306a36Sopenharmony_ci msg.ext.create_ppl.lp = lp; 9762306a36Sopenharmony_ci msg.ext.create_ppl.attributes = attributes; 9862306a36Sopenharmony_ci request.header = msg.val; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 10162306a36Sopenharmony_ci if (ret) 10262306a36Sopenharmony_ci avs_ipc_err(adev, &request, "create pipeline", ret); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return ret; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciint avs_ipc_delete_pipeline(struct avs_dev *adev, u8 instance_id) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(DELETE_PIPELINE); 11062306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 11162306a36Sopenharmony_ci int ret; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci msg.ppl.instance_id = instance_id; 11462306a36Sopenharmony_ci request.header = msg.val; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 11762306a36Sopenharmony_ci if (ret) 11862306a36Sopenharmony_ci avs_ipc_err(adev, &request, "delete pipeline", ret); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return ret; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciint avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id, 12462306a36Sopenharmony_ci enum avs_pipeline_state state) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(SET_PIPELINE_STATE); 12762306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 12862306a36Sopenharmony_ci int ret; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci msg.set_ppl_state.ppl_id = instance_id; 13162306a36Sopenharmony_ci msg.set_ppl_state.state = state; 13262306a36Sopenharmony_ci request.header = msg.val; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 13562306a36Sopenharmony_ci if (ret) 13662306a36Sopenharmony_ci avs_ipc_err(adev, &request, "set pipeline state", ret); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return ret; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciint avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, 14262306a36Sopenharmony_ci enum avs_pipeline_state *state) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci union avs_global_msg msg = AVS_GLOBAL_REQUEST(GET_PIPELINE_STATE); 14562306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 14662306a36Sopenharmony_ci struct avs_ipc_msg reply = {{0}}; 14762306a36Sopenharmony_ci int ret; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci msg.get_ppl_state.ppl_id = instance_id; 15062306a36Sopenharmony_ci request.header = msg.val; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, &reply); 15362306a36Sopenharmony_ci if (ret) { 15462306a36Sopenharmony_ci avs_ipc_err(adev, &request, "get pipeline state", ret); 15562306a36Sopenharmony_ci return ret; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci *state = reply.rsp.ext.get_ppl_state.state; 15962306a36Sopenharmony_ci return ret; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* 16362306a36Sopenharmony_ci * avs_ipc_init_instance - Initialize module instance 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * @adev: Driver context 16662306a36Sopenharmony_ci * @module_id: Module-type id 16762306a36Sopenharmony_ci * @instance_id: Unique module instance id 16862306a36Sopenharmony_ci * @ppl_id: Parent pipeline id 16962306a36Sopenharmony_ci * @core_id: DSP core to allocate module on 17062306a36Sopenharmony_ci * @domain: Processing domain (low latency or data processing) 17162306a36Sopenharmony_ci * @param: Module-type specific configuration 17262306a36Sopenharmony_ci * @param_size: Size of @param in bytes 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * Argument verification, as well as pipeline state checks are done by the 17562306a36Sopenharmony_ci * firmware. 17662306a36Sopenharmony_ci * 17762306a36Sopenharmony_ci * Note: @ppl_id and @core_id are independent of each other as single pipeline 17862306a36Sopenharmony_ci * can be composed of module instances located on different DSP cores. 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ciint avs_ipc_init_instance(struct avs_dev *adev, u16 module_id, u8 instance_id, 18162306a36Sopenharmony_ci u8 ppl_id, u8 core_id, u8 domain, 18262306a36Sopenharmony_ci void *param, u32 param_size) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(INIT_INSTANCE); 18562306a36Sopenharmony_ci struct avs_ipc_msg request; 18662306a36Sopenharmony_ci int ret; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci msg.module_id = module_id; 18962306a36Sopenharmony_ci msg.instance_id = instance_id; 19062306a36Sopenharmony_ci /* firmware expects size provided in dwords */ 19162306a36Sopenharmony_ci msg.ext.init_instance.param_block_size = DIV_ROUND_UP(param_size, sizeof(u32)); 19262306a36Sopenharmony_ci msg.ext.init_instance.ppl_instance_id = ppl_id; 19362306a36Sopenharmony_ci msg.ext.init_instance.core_id = core_id; 19462306a36Sopenharmony_ci msg.ext.init_instance.proc_domain = domain; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci request.header = msg.val; 19762306a36Sopenharmony_ci request.data = param; 19862306a36Sopenharmony_ci request.size = param_size; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 20162306a36Sopenharmony_ci if (ret) 20262306a36Sopenharmony_ci avs_ipc_err(adev, &request, "init instance", ret); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci return ret; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* 20862306a36Sopenharmony_ci * avs_ipc_delete_instance - Delete module instance 20962306a36Sopenharmony_ci * 21062306a36Sopenharmony_ci * @adev: Driver context 21162306a36Sopenharmony_ci * @module_id: Module-type id 21262306a36Sopenharmony_ci * @instance_id: Unique module instance id 21362306a36Sopenharmony_ci * 21462306a36Sopenharmony_ci * Argument verification, as well as pipeline state checks are done by the 21562306a36Sopenharmony_ci * firmware. 21662306a36Sopenharmony_ci * 21762306a36Sopenharmony_ci * Note: only standalone modules i.e. without a parent pipeline shall be 21862306a36Sopenharmony_ci * deleted using this IPC message. In all other cases, pipeline owning the 21962306a36Sopenharmony_ci * modules performs cleanup automatically when it is deleted. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ciint avs_ipc_delete_instance(struct avs_dev *adev, u16 module_id, u8 instance_id) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(DELETE_INSTANCE); 22462306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 22562306a36Sopenharmony_ci int ret; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci msg.module_id = module_id; 22862306a36Sopenharmony_ci msg.instance_id = instance_id; 22962306a36Sopenharmony_ci request.header = msg.val; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 23262306a36Sopenharmony_ci if (ret) 23362306a36Sopenharmony_ci avs_ipc_err(adev, &request, "delete instance", ret); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return ret; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/* 23962306a36Sopenharmony_ci * avs_ipc_bind - Bind two module instances 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * @adev: Driver context 24262306a36Sopenharmony_ci * @module_id: Source module-type id 24362306a36Sopenharmony_ci * @instance_id: Source module instance id 24462306a36Sopenharmony_ci * @dst_module_id: Sink module-type id 24562306a36Sopenharmony_ci * @dst_instance_id: Sink module instance id 24662306a36Sopenharmony_ci * @dst_queue: Sink module pin to bind @src_queue with 24762306a36Sopenharmony_ci * @src_queue: Source module pin to bind @dst_queue with 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ciint avs_ipc_bind(struct avs_dev *adev, u16 module_id, u8 instance_id, 25062306a36Sopenharmony_ci u16 dst_module_id, u8 dst_instance_id, 25162306a36Sopenharmony_ci u8 dst_queue, u8 src_queue) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(BIND); 25462306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 25562306a36Sopenharmony_ci int ret; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci msg.module_id = module_id; 25862306a36Sopenharmony_ci msg.instance_id = instance_id; 25962306a36Sopenharmony_ci msg.ext.bind_unbind.dst_module_id = dst_module_id; 26062306a36Sopenharmony_ci msg.ext.bind_unbind.dst_instance_id = dst_instance_id; 26162306a36Sopenharmony_ci msg.ext.bind_unbind.dst_queue = dst_queue; 26262306a36Sopenharmony_ci msg.ext.bind_unbind.src_queue = src_queue; 26362306a36Sopenharmony_ci request.header = msg.val; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 26662306a36Sopenharmony_ci if (ret) 26762306a36Sopenharmony_ci avs_ipc_err(adev, &request, "bind modules", ret); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return ret; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci/* 27362306a36Sopenharmony_ci * avs_ipc_unbind - Unbind two module instances 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * @adev: Driver context 27662306a36Sopenharmony_ci * @module_id: Source module-type id 27762306a36Sopenharmony_ci * @instance_id: Source module instance id 27862306a36Sopenharmony_ci * @dst_module_id: Sink module-type id 27962306a36Sopenharmony_ci * @dst_instance_id: Sink module instance id 28062306a36Sopenharmony_ci * @dst_queue: Sink module pin to unbind @src_queue from 28162306a36Sopenharmony_ci * @src_queue: Source module pin to unbind @dst_queue from 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_ciint avs_ipc_unbind(struct avs_dev *adev, u16 module_id, u8 instance_id, 28462306a36Sopenharmony_ci u16 dst_module_id, u8 dst_instance_id, 28562306a36Sopenharmony_ci u8 dst_queue, u8 src_queue) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(UNBIND); 28862306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 28962306a36Sopenharmony_ci int ret; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci msg.module_id = module_id; 29262306a36Sopenharmony_ci msg.instance_id = instance_id; 29362306a36Sopenharmony_ci msg.ext.bind_unbind.dst_module_id = dst_module_id; 29462306a36Sopenharmony_ci msg.ext.bind_unbind.dst_instance_id = dst_instance_id; 29562306a36Sopenharmony_ci msg.ext.bind_unbind.dst_queue = dst_queue; 29662306a36Sopenharmony_ci msg.ext.bind_unbind.src_queue = src_queue; 29762306a36Sopenharmony_ci request.header = msg.val; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 30062306a36Sopenharmony_ci if (ret) 30162306a36Sopenharmony_ci avs_ipc_err(adev, &request, "unbind modules", ret); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return ret; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic int __avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id, 30762306a36Sopenharmony_ci u8 param_id, bool init_block, bool final_block, 30862306a36Sopenharmony_ci u8 *request_data, size_t request_size, size_t off_size) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_SET); 31162306a36Sopenharmony_ci struct avs_ipc_msg request; 31262306a36Sopenharmony_ci int ret; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci msg.module_id = module_id; 31562306a36Sopenharmony_ci msg.instance_id = instance_id; 31662306a36Sopenharmony_ci msg.ext.large_config.data_off_size = off_size; 31762306a36Sopenharmony_ci msg.ext.large_config.large_param_id = param_id; 31862306a36Sopenharmony_ci msg.ext.large_config.final_block = final_block; 31962306a36Sopenharmony_ci msg.ext.large_config.init_block = init_block; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci request.header = msg.val; 32262306a36Sopenharmony_ci request.data = request_data; 32362306a36Sopenharmony_ci request.size = request_size; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, NULL); 32662306a36Sopenharmony_ci if (ret) 32762306a36Sopenharmony_ci avs_ipc_err(adev, &request, "large config set", ret); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci return ret; 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ciint avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, 33362306a36Sopenharmony_ci u8 instance_id, u8 param_id, 33462306a36Sopenharmony_ci u8 *request, size_t request_size) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci size_t remaining, tx_size; 33762306a36Sopenharmony_ci bool final; 33862306a36Sopenharmony_ci int ret; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci remaining = request_size; 34162306a36Sopenharmony_ci tx_size = min_t(size_t, AVS_MAILBOX_SIZE, remaining); 34262306a36Sopenharmony_ci final = (tx_size == remaining); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* Initial request states total payload size. */ 34562306a36Sopenharmony_ci ret = __avs_ipc_set_large_config(adev, module_id, instance_id, 34662306a36Sopenharmony_ci param_id, 1, final, request, tx_size, 34762306a36Sopenharmony_ci request_size); 34862306a36Sopenharmony_ci if (ret) 34962306a36Sopenharmony_ci return ret; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci remaining -= tx_size; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* Loop the rest only when payload exceeds mailbox's size. */ 35462306a36Sopenharmony_ci while (remaining) { 35562306a36Sopenharmony_ci size_t offset; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci offset = request_size - remaining; 35862306a36Sopenharmony_ci tx_size = min_t(size_t, AVS_MAILBOX_SIZE, remaining); 35962306a36Sopenharmony_ci final = (tx_size == remaining); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci ret = __avs_ipc_set_large_config(adev, module_id, instance_id, 36262306a36Sopenharmony_ci param_id, 0, final, 36362306a36Sopenharmony_ci request + offset, tx_size, 36462306a36Sopenharmony_ci offset); 36562306a36Sopenharmony_ci if (ret) 36662306a36Sopenharmony_ci return ret; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci remaining -= tx_size; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci return 0; 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ciint avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id, 37562306a36Sopenharmony_ci u8 param_id, u8 *request_data, size_t request_size, 37662306a36Sopenharmony_ci u8 **reply_data, size_t *reply_size) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_GET); 37962306a36Sopenharmony_ci struct avs_ipc_msg request; 38062306a36Sopenharmony_ci struct avs_ipc_msg reply = {{0}}; 38162306a36Sopenharmony_ci void *buf; 38262306a36Sopenharmony_ci int ret; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci reply.data = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); 38562306a36Sopenharmony_ci if (!reply.data) 38662306a36Sopenharmony_ci return -ENOMEM; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci msg.module_id = module_id; 38962306a36Sopenharmony_ci msg.instance_id = instance_id; 39062306a36Sopenharmony_ci msg.ext.large_config.data_off_size = request_size; 39162306a36Sopenharmony_ci msg.ext.large_config.large_param_id = param_id; 39262306a36Sopenharmony_ci /* final_block is always 0 on request. Updated by fw on reply. */ 39362306a36Sopenharmony_ci msg.ext.large_config.final_block = 0; 39462306a36Sopenharmony_ci msg.ext.large_config.init_block = 1; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci request.header = msg.val; 39762306a36Sopenharmony_ci request.data = request_data; 39862306a36Sopenharmony_ci request.size = request_size; 39962306a36Sopenharmony_ci reply.size = AVS_MAILBOX_SIZE; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci ret = avs_dsp_send_msg(adev, &request, &reply); 40262306a36Sopenharmony_ci if (ret) { 40362306a36Sopenharmony_ci avs_ipc_err(adev, &request, "large config get", ret); 40462306a36Sopenharmony_ci kfree(reply.data); 40562306a36Sopenharmony_ci return ret; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci buf = krealloc(reply.data, reply.size, GFP_KERNEL); 40962306a36Sopenharmony_ci if (!buf) { 41062306a36Sopenharmony_ci kfree(reply.data); 41162306a36Sopenharmony_ci return -ENOMEM; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci *reply_data = buf; 41562306a36Sopenharmony_ci *reply_size = reply.size; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return 0; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ciint avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(SET_DX); 42362306a36Sopenharmony_ci struct avs_ipc_msg request; 42462306a36Sopenharmony_ci struct avs_dxstate_info dx; 42562306a36Sopenharmony_ci int ret; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci dx.core_mask = core_mask; 42862306a36Sopenharmony_ci dx.dx_mask = powerup ? core_mask : 0; 42962306a36Sopenharmony_ci request.header = msg.val; 43062306a36Sopenharmony_ci request.data = &dx; 43162306a36Sopenharmony_ci request.size = sizeof(dx); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci ret = avs_dsp_send_pm_msg(adev, &request, NULL, true); 43462306a36Sopenharmony_ci if (ret) 43562306a36Sopenharmony_ci avs_ipc_err(adev, &request, "set dx", ret); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci return ret; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci/* 44162306a36Sopenharmony_ci * avs_ipc_set_d0ix - Set power gating policy (entering D0IX substates) 44262306a36Sopenharmony_ci * 44362306a36Sopenharmony_ci * @enable_pg: Whether to enable or disable power gating 44462306a36Sopenharmony_ci * @streaming: Whether a stream is running when transitioning 44562306a36Sopenharmony_ci */ 44662306a36Sopenharmony_ciint avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci union avs_module_msg msg = AVS_MODULE_REQUEST(SET_D0IX); 44962306a36Sopenharmony_ci struct avs_ipc_msg request = {{0}}; 45062306a36Sopenharmony_ci int ret; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci msg.ext.set_d0ix.wake = enable_pg; 45362306a36Sopenharmony_ci msg.ext.set_d0ix.streaming = streaming; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci request.header = msg.val; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ret = avs_dsp_send_pm_msg(adev, &request, NULL, false); 45862306a36Sopenharmony_ci if (ret) 45962306a36Sopenharmony_ci avs_ipc_err(adev, &request, "set d0ix", ret); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci return ret; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ciint avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct avs_tlv *tlv; 46762306a36Sopenharmony_ci size_t payload_size; 46862306a36Sopenharmony_ci size_t offset = 0; 46962306a36Sopenharmony_ci u8 *payload; 47062306a36Sopenharmony_ci int ret; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, 47362306a36Sopenharmony_ci AVS_BASEFW_FIRMWARE_CONFIG, NULL, 0, 47462306a36Sopenharmony_ci &payload, &payload_size); 47562306a36Sopenharmony_ci if (ret) 47662306a36Sopenharmony_ci return ret; 47762306a36Sopenharmony_ci /* Non-zero payload expected for FIRMWARE_CONFIG. */ 47862306a36Sopenharmony_ci if (!payload_size) 47962306a36Sopenharmony_ci return -EREMOTEIO; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci while (offset < payload_size) { 48262306a36Sopenharmony_ci tlv = (struct avs_tlv *)(payload + offset); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci switch (tlv->type) { 48562306a36Sopenharmony_ci case AVS_FW_CFG_FW_VERSION: 48662306a36Sopenharmony_ci memcpy(&cfg->fw_version, tlv->value, sizeof(cfg->fw_version)); 48762306a36Sopenharmony_ci break; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci case AVS_FW_CFG_MEMORY_RECLAIMED: 49062306a36Sopenharmony_ci cfg->memory_reclaimed = *tlv->value; 49162306a36Sopenharmony_ci break; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci case AVS_FW_CFG_SLOW_CLOCK_FREQ_HZ: 49462306a36Sopenharmony_ci cfg->slow_clock_freq_hz = *tlv->value; 49562306a36Sopenharmony_ci break; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci case AVS_FW_CFG_FAST_CLOCK_FREQ_HZ: 49862306a36Sopenharmony_ci cfg->fast_clock_freq_hz = *tlv->value; 49962306a36Sopenharmony_ci break; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci case AVS_FW_CFG_ALH_SUPPORT_LEVEL: 50262306a36Sopenharmony_ci cfg->alh_support = *tlv->value; 50362306a36Sopenharmony_ci break; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci case AVS_FW_CFG_IPC_DL_MAILBOX_BYTES: 50662306a36Sopenharmony_ci cfg->ipc_dl_mailbox_bytes = *tlv->value; 50762306a36Sopenharmony_ci break; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci case AVS_FW_CFG_IPC_UL_MAILBOX_BYTES: 51062306a36Sopenharmony_ci cfg->ipc_ul_mailbox_bytes = *tlv->value; 51162306a36Sopenharmony_ci break; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci case AVS_FW_CFG_TRACE_LOG_BYTES: 51462306a36Sopenharmony_ci cfg->trace_log_bytes = *tlv->value; 51562306a36Sopenharmony_ci break; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci case AVS_FW_CFG_MAX_PPL_COUNT: 51862306a36Sopenharmony_ci cfg->max_ppl_count = *tlv->value; 51962306a36Sopenharmony_ci break; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci case AVS_FW_CFG_MAX_ASTATE_COUNT: 52262306a36Sopenharmony_ci cfg->max_astate_count = *tlv->value; 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci case AVS_FW_CFG_MAX_MODULE_PIN_COUNT: 52662306a36Sopenharmony_ci cfg->max_module_pin_count = *tlv->value; 52762306a36Sopenharmony_ci break; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci case AVS_FW_CFG_MODULES_COUNT: 53062306a36Sopenharmony_ci cfg->modules_count = *tlv->value; 53162306a36Sopenharmony_ci break; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci case AVS_FW_CFG_MAX_MOD_INST_COUNT: 53462306a36Sopenharmony_ci cfg->max_mod_inst_count = *tlv->value; 53562306a36Sopenharmony_ci break; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci case AVS_FW_CFG_MAX_LL_TASKS_PER_PRI_COUNT: 53862306a36Sopenharmony_ci cfg->max_ll_tasks_per_pri_count = *tlv->value; 53962306a36Sopenharmony_ci break; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci case AVS_FW_CFG_LL_PRI_COUNT: 54262306a36Sopenharmony_ci cfg->ll_pri_count = *tlv->value; 54362306a36Sopenharmony_ci break; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci case AVS_FW_CFG_MAX_DP_TASKS_COUNT: 54662306a36Sopenharmony_ci cfg->max_dp_tasks_count = *tlv->value; 54762306a36Sopenharmony_ci break; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci case AVS_FW_CFG_MAX_LIBS_COUNT: 55062306a36Sopenharmony_ci cfg->max_libs_count = *tlv->value; 55162306a36Sopenharmony_ci break; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci case AVS_FW_CFG_XTAL_FREQ_HZ: 55462306a36Sopenharmony_ci cfg->xtal_freq_hz = *tlv->value; 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci case AVS_FW_CFG_POWER_GATING_POLICY: 55862306a36Sopenharmony_ci cfg->power_gating_policy = *tlv->value; 55962306a36Sopenharmony_ci break; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci /* Known but not useful to us. */ 56262306a36Sopenharmony_ci case AVS_FW_CFG_DMA_BUFFER_CONFIG: 56362306a36Sopenharmony_ci case AVS_FW_CFG_SCHEDULER_CONFIG: 56462306a36Sopenharmony_ci case AVS_FW_CFG_CLOCKS_CONFIG: 56562306a36Sopenharmony_ci case AVS_FW_CFG_RESERVED: 56662306a36Sopenharmony_ci break; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci default: 56962306a36Sopenharmony_ci dev_info(adev->dev, "Unrecognized fw param: %d\n", tlv->type); 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci offset += sizeof(*tlv) + tlv->length; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /* No longer needed, free it as it's owned by the get_large_config() caller. */ 57762306a36Sopenharmony_ci kfree(payload); 57862306a36Sopenharmony_ci return ret; 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ciint avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct avs_tlv *tlv; 58462306a36Sopenharmony_ci size_t payload_size; 58562306a36Sopenharmony_ci size_t size, offset = 0; 58662306a36Sopenharmony_ci u8 *payload; 58762306a36Sopenharmony_ci int ret; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, 59062306a36Sopenharmony_ci AVS_BASEFW_HARDWARE_CONFIG, NULL, 0, 59162306a36Sopenharmony_ci &payload, &payload_size); 59262306a36Sopenharmony_ci if (ret) 59362306a36Sopenharmony_ci return ret; 59462306a36Sopenharmony_ci /* Non-zero payload expected for HARDWARE_CONFIG. */ 59562306a36Sopenharmony_ci if (!payload_size) 59662306a36Sopenharmony_ci return -EREMOTEIO; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci while (offset < payload_size) { 59962306a36Sopenharmony_ci tlv = (struct avs_tlv *)(payload + offset); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci switch (tlv->type) { 60262306a36Sopenharmony_ci case AVS_HW_CFG_AVS_VER: 60362306a36Sopenharmony_ci cfg->avs_version = *tlv->value; 60462306a36Sopenharmony_ci break; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci case AVS_HW_CFG_DSP_CORES: 60762306a36Sopenharmony_ci cfg->dsp_cores = *tlv->value; 60862306a36Sopenharmony_ci break; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci case AVS_HW_CFG_MEM_PAGE_BYTES: 61162306a36Sopenharmony_ci cfg->mem_page_bytes = *tlv->value; 61262306a36Sopenharmony_ci break; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci case AVS_HW_CFG_TOTAL_PHYS_MEM_PAGES: 61562306a36Sopenharmony_ci cfg->total_phys_mem_pages = *tlv->value; 61662306a36Sopenharmony_ci break; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci case AVS_HW_CFG_I2S_CAPS: 61962306a36Sopenharmony_ci cfg->i2s_caps.i2s_version = tlv->value[0]; 62062306a36Sopenharmony_ci size = tlv->value[1]; 62162306a36Sopenharmony_ci cfg->i2s_caps.ctrl_count = size; 62262306a36Sopenharmony_ci if (!size) 62362306a36Sopenharmony_ci break; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /* Multiply to get entire array size. */ 62662306a36Sopenharmony_ci size *= sizeof(*cfg->i2s_caps.ctrl_base_addr); 62762306a36Sopenharmony_ci cfg->i2s_caps.ctrl_base_addr = devm_kmemdup(adev->dev, 62862306a36Sopenharmony_ci &tlv->value[2], 62962306a36Sopenharmony_ci size, GFP_KERNEL); 63062306a36Sopenharmony_ci if (!cfg->i2s_caps.ctrl_base_addr) { 63162306a36Sopenharmony_ci ret = -ENOMEM; 63262306a36Sopenharmony_ci goto exit; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci break; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci case AVS_HW_CFG_GATEWAY_COUNT: 63762306a36Sopenharmony_ci cfg->gateway_count = *tlv->value; 63862306a36Sopenharmony_ci break; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci case AVS_HW_CFG_HP_EBB_COUNT: 64162306a36Sopenharmony_ci cfg->hp_ebb_count = *tlv->value; 64262306a36Sopenharmony_ci break; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci case AVS_HW_CFG_LP_EBB_COUNT: 64562306a36Sopenharmony_ci cfg->lp_ebb_count = *tlv->value; 64662306a36Sopenharmony_ci break; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci case AVS_HW_CFG_EBB_SIZE_BYTES: 64962306a36Sopenharmony_ci cfg->ebb_size_bytes = *tlv->value; 65062306a36Sopenharmony_ci break; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci case AVS_HW_CFG_GPDMA_CAPS: 65362306a36Sopenharmony_ci break; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci default: 65662306a36Sopenharmony_ci dev_info(adev->dev, "Unrecognized hw config: %d\n", tlv->type); 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci offset += sizeof(*tlv) + tlv->length; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ciexit: 66462306a36Sopenharmony_ci /* No longer needed, free it as it's owned by the get_large_config() caller. */ 66562306a36Sopenharmony_ci kfree(payload); 66662306a36Sopenharmony_ci return ret; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ciint avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci size_t payload_size; 67262306a36Sopenharmony_ci u8 *payload; 67362306a36Sopenharmony_ci int ret; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, 67662306a36Sopenharmony_ci AVS_BASEFW_MODULES_INFO, NULL, 0, 67762306a36Sopenharmony_ci &payload, &payload_size); 67862306a36Sopenharmony_ci if (ret) 67962306a36Sopenharmony_ci return ret; 68062306a36Sopenharmony_ci /* Non-zero payload expected for MODULES_INFO. */ 68162306a36Sopenharmony_ci if (!payload_size) 68262306a36Sopenharmony_ci return -EREMOTEIO; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci *info = (struct avs_mods_info *)payload; 68562306a36Sopenharmony_ci return 0; 68662306a36Sopenharmony_ci} 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ciint avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, 68962306a36Sopenharmony_ci u8 instance_id, u32 sink_id, 69062306a36Sopenharmony_ci const struct avs_audio_format *src_fmt, 69162306a36Sopenharmony_ci const struct avs_audio_format *sink_fmt) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci struct avs_copier_sink_format cpr_fmt; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci cpr_fmt.sink_id = sink_id; 69662306a36Sopenharmony_ci /* Firmware expects driver to resend copier's input format. */ 69762306a36Sopenharmony_ci cpr_fmt.src_fmt = *src_fmt; 69862306a36Sopenharmony_ci cpr_fmt.sink_fmt = *sink_fmt; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, module_id, instance_id, 70162306a36Sopenharmony_ci AVS_COPIER_SET_SINK_FORMAT, 70262306a36Sopenharmony_ci (u8 *)&cpr_fmt, sizeof(cpr_fmt)); 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ciint avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 70662306a36Sopenharmony_ci struct avs_volume_cfg *vol) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_VOLUME, (u8 *)vol, 70962306a36Sopenharmony_ci sizeof(*vol)); 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ciint avs_ipc_peakvol_get_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 71362306a36Sopenharmony_ci struct avs_volume_cfg **vols, size_t *num_vols) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci size_t payload_size; 71662306a36Sopenharmony_ci u8 *payload; 71762306a36Sopenharmony_ci int ret; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci ret = avs_ipc_get_large_config(adev, module_id, instance_id, AVS_PEAKVOL_VOLUME, NULL, 0, 72062306a36Sopenharmony_ci &payload, &payload_size); 72162306a36Sopenharmony_ci if (ret) 72262306a36Sopenharmony_ci return ret; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci /* Non-zero payload expected for PEAKVOL_VOLUME. */ 72562306a36Sopenharmony_ci if (!payload_size) 72662306a36Sopenharmony_ci return -EREMOTEIO; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci *vols = (struct avs_volume_cfg *)payload; 72962306a36Sopenharmony_ci *num_vols = payload_size / sizeof(**vols); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci return 0; 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 73562306a36Sopenharmony_ciint avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size) 73662306a36Sopenharmony_ci{ 73762306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, 73862306a36Sopenharmony_ci AVS_BASEFW_ENABLE_LOGS, log_info, size); 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ciint avs_ipc_set_system_time(struct avs_dev *adev) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci struct avs_sys_time sys_time; 74462306a36Sopenharmony_ci u64 us; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci /* firmware expects UTC time in micro seconds */ 74762306a36Sopenharmony_ci us = ktime_to_us(ktime_get()); 74862306a36Sopenharmony_ci sys_time.val_l = us & UINT_MAX; 74962306a36Sopenharmony_ci sys_time.val_u = us >> 32; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, 75262306a36Sopenharmony_ci AVS_BASEFW_SYSTEM_TIME, (u8 *)&sys_time, sizeof(sys_time)); 75362306a36Sopenharmony_ci} 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ciint avs_ipc_probe_get_dma(struct avs_dev *adev, struct avs_probe_dma **dmas, size_t *num_dmas) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci size_t payload_size; 75862306a36Sopenharmony_ci u32 module_id; 75962306a36Sopenharmony_ci u8 *payload; 76062306a36Sopenharmony_ci int ret; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci ret = avs_ipc_get_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_INJECTION_DMA, 76562306a36Sopenharmony_ci NULL, 0, &payload, &payload_size); 76662306a36Sopenharmony_ci if (ret) 76762306a36Sopenharmony_ci return ret; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci *dmas = (struct avs_probe_dma *)payload; 77062306a36Sopenharmony_ci *num_dmas = payload_size / sizeof(**dmas); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci return 0; 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ciint avs_ipc_probe_attach_dma(struct avs_dev *adev, struct avs_probe_dma *dmas, size_t num_dmas) 77662306a36Sopenharmony_ci{ 77762306a36Sopenharmony_ci u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_INJECTION_DMA, 78062306a36Sopenharmony_ci (u8 *)dmas, array_size(sizeof(*dmas), num_dmas)); 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ciint avs_ipc_probe_detach_dma(struct avs_dev *adev, union avs_connector_node_id *node_ids, 78462306a36Sopenharmony_ci size_t num_node_ids) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, 78962306a36Sopenharmony_ci AVS_PROBE_INJECTION_DMA_DETACH, (u8 *)node_ids, 79062306a36Sopenharmony_ci array_size(sizeof(*node_ids), num_node_ids)); 79162306a36Sopenharmony_ci} 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ciint avs_ipc_probe_get_points(struct avs_dev *adev, struct avs_probe_point_desc **descs, 79462306a36Sopenharmony_ci size_t *num_descs) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci size_t payload_size; 79762306a36Sopenharmony_ci u32 module_id; 79862306a36Sopenharmony_ci u8 *payload; 79962306a36Sopenharmony_ci int ret; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci ret = avs_ipc_get_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_POINTS, NULL, 80462306a36Sopenharmony_ci 0, &payload, &payload_size); 80562306a36Sopenharmony_ci if (ret) 80662306a36Sopenharmony_ci return ret; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci *descs = (struct avs_probe_point_desc *)payload; 80962306a36Sopenharmony_ci *num_descs = payload_size / sizeof(**descs); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci return 0; 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ciint avs_ipc_probe_connect_points(struct avs_dev *adev, struct avs_probe_point_desc *descs, 81562306a36Sopenharmony_ci size_t num_descs) 81662306a36Sopenharmony_ci{ 81762306a36Sopenharmony_ci u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_POINTS, 82062306a36Sopenharmony_ci (u8 *)descs, array_size(sizeof(*descs), num_descs)); 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ciint avs_ipc_probe_disconnect_points(struct avs_dev *adev, union avs_probe_point_id *ids, 82462306a36Sopenharmony_ci size_t num_ids) 82562306a36Sopenharmony_ci{ 82662306a36Sopenharmony_ci u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, 82962306a36Sopenharmony_ci AVS_PROBE_POINTS_DISCONNECT, (u8 *)ids, 83062306a36Sopenharmony_ci array_size(sizeof(*ids), num_ids)); 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci#endif 833