Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Intel: avs: Add data probing requests

Data probing is a cAVS firmware functionality that allows for data
extraction and injection directly from or to DMA stream. To support it,
new functions and types are added. These facilitate communication
with the firmware.

Total of eight IPCs:
- probe module initialization and cleanup
- addition and removal of probe points
- addition and removal of injection DMAs
- dumping list of currently connected probe points or enlisted DMAs

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://lore.kernel.org/r/20221202152841.672536-10-cezary.rojewski@intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Cezary Rojewski and committed by
Mark Brown
dab8d000 f7de161f

+178 -1
+1 -1
sound/soc/intel/avs/Makefile
··· 10 10 CFLAGS_trace.o := -I$(src) 11 11 12 12 ifneq ($(CONFIG_DEBUG_FS),) 13 - snd-soc-avs-objs += debugfs.o 13 + snd-soc-avs-objs += probes.o debugfs.o 14 14 endif 15 15 16 16 obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o
+78
sound/soc/intel/avs/messages.c
··· 722 722 return avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, 723 723 AVS_BASEFW_SYSTEM_TIME, (u8 *)&sys_time, sizeof(sys_time)); 724 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 + } 725 803 #endif
+53
sound/soc/intel/avs/messages.h
··· 802 802 const struct avs_audio_format *src_fmt, 803 803 const struct avs_audio_format *sink_fmt); 804 804 805 + #define AVS_PROBE_INST_ID 0 806 + 807 + enum avs_probe_runtime_param { 808 + AVS_PROBE_INJECTION_DMA = 1, 809 + AVS_PROBE_INJECTION_DMA_DETACH, 810 + AVS_PROBE_POINTS, 811 + AVS_PROBE_POINTS_DISCONNECT, 812 + }; 813 + 814 + struct avs_probe_dma { 815 + union avs_connector_node_id node_id; 816 + u32 dma_buffer_size; 817 + } __packed; 818 + 819 + enum avs_probe_type { 820 + AVS_PROBE_TYPE_INPUT = 0, 821 + AVS_PROBE_TYPE_OUTPUT, 822 + AVS_PROBE_TYPE_INTERNAL 823 + }; 824 + 825 + union avs_probe_point_id { 826 + u32 value; 827 + struct { 828 + u32 module_id:16; 829 + u32 instance_id:8; 830 + u32 type:2; 831 + u32 index:6; 832 + } id; 833 + } __packed; 834 + 835 + enum avs_connection_purpose { 836 + AVS_CONNECTION_PURPOSE_EXTRACT = 0, 837 + AVS_CONNECTION_PURPOSE_INJECT, 838 + AVS_CONNECTION_PURPOSE_INJECT_REEXTRACT, 839 + }; 840 + 841 + struct avs_probe_point_desc { 842 + union avs_probe_point_id id; 843 + u32 purpose; 844 + union avs_connector_node_id node_id; 845 + } __packed; 846 + 847 + int avs_ipc_probe_get_dma(struct avs_dev *adev, struct avs_probe_dma **dmas, size_t *num_dmas); 848 + int avs_ipc_probe_attach_dma(struct avs_dev *adev, struct avs_probe_dma *dmas, size_t num_dmas); 849 + int avs_ipc_probe_detach_dma(struct avs_dev *adev, union avs_connector_node_id *node_ids, 850 + size_t num_node_ids); 851 + int avs_ipc_probe_get_points(struct avs_dev *adev, struct avs_probe_point_desc **descs, 852 + size_t *num_descs); 853 + int avs_ipc_probe_connect_points(struct avs_dev *adev, struct avs_probe_point_desc *descs, 854 + size_t num_descs); 855 + int avs_ipc_probe_disconnect_points(struct avs_dev *adev, union avs_probe_point_id *ids, 856 + size_t num_ids); 857 + 805 858 #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */
+46
sound/soc/intel/avs/probes.c
··· 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 "avs.h" 10 + #include "messages.h" 11 + 12 + __maybe_unused 13 + static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id node_id, 14 + size_t buffer_size) 15 + 16 + { 17 + struct avs_probe_cfg cfg = {{0}}; 18 + struct avs_module_entry mentry; 19 + u16 dummy; 20 + 21 + avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); 22 + 23 + /* 24 + * Probe module uses no cycles, audio data format and input and output 25 + * frame sizes are unused. It is also not owned by any pipeline. 26 + */ 27 + cfg.base.ibs = 1; 28 + /* BSS module descriptor is always segment of index=2. */ 29 + cfg.base.is_pages = mentry.segments[2].flags.length; 30 + cfg.gtw_cfg.node_id = node_id; 31 + cfg.gtw_cfg.dma_buffer_size = buffer_size; 32 + 33 + return avs_dsp_init_module(adev, mentry.module_id, INVALID_PIPELINE_ID, 0, 0, &cfg, 34 + sizeof(cfg), &dummy); 35 + } 36 + 37 + __maybe_unused 38 + static void avs_dsp_delete_probe(struct avs_dev *adev) 39 + { 40 + struct avs_module_entry mentry; 41 + 42 + avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); 43 + 44 + /* There is only ever one probe module instance. */ 45 + avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0); 46 + }