~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/avs/messages.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php