1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2021 Intel Corporation. All rights reserved.
4  */
5 
6 /*
7  * This file contains structures that are exact copies of an existing ABI used
8  * by IOT middleware. They are Intel specific and will be used by one middleware.
9  *
10  * Some of the structures may contain programming implementations that makes them
11  * unsuitable for generic use and general usage.
12  *
13  * This code is mostly copied "as-is" from existing C++ interface files hence the use of
14  * different style in places. The intention is to keep the interface as close as possible to
15  * original so it's easier to track changes with IPC host code.
16  */
17 
18 /**
19  * \file include/ipc4/copier.h
20  * \brief IPC4 copier definitions.
21  * NOTE: This ABI uses bit fields and is non portable.
22  */
23 
24 #ifndef __SOF_IPC4_COPIER_H__
25 #define __SOF_IPC4_COPIER_H__
26 
27 #include <stdint.h>
28 #include <ipc4/base-config.h>
29 #include <ipc4/gateway.h>
30 
31 #include <sof/compiler_attributes.h>
32 #include <sof/audio/buffer.h>
33 #include <sof/audio/pcm_converter.h>
34 
35 #define COPIER_GENERIC
36 
37 #if defined(__XCC__)
38 #include <xtensa/config/core-isa.h>
39 
40 #if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4
41 #undef COPIER_GENERIC
42 #endif
43 
44 #endif
45 
46 static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF;
47 
48 /* copier Module Configuration & Interface
49  * UUID: 9BA00C83-CA12-4A83-943C-1FA2E82F9DDA
50  *
51  * Copier may be instantiated and bound in one of following configurations:
52  *
53  * - case 1:
54  * digraph Module_Copier_Module {
55  *   InputGateway
56  *   InputGateway -> Copier
57  *
58  *   DestinationMod
59  *   Copier -> DestinationMod
60  * }
61  *
62  * digraph Module_Copier_Gateways {
63  *   SourceMod
64  *   SourceMod -> Copier
65  *
66  *   OutputGateway
67  *   Copier -> OutputGateway
68  * }
69  * - case 3:
70  * digraph Module_Copier_Module {
71  *   SourceMod
72  *   SourceMod -> Copier
73  *
74  *   DestinationMod
75  *   Copier -> DestinationMod
76  * }
77  *
78  * - case 4:
79  * digraph Module_Copier_Module {
80  *   SourceMod
81  *
82  *   SourceMod -> Copier
83  *
84  *   DestinationMod
85  *   OutputGateway
86  *
87  *   Copier -> OutputGateway
88  *   Copier -> DestinationMod
89  * }
90  *
91  * In cases 1 and 2, the initial configuration must include Gateway Configuration
92  * data along with valid Node ID of the gateway to be connected on either
93  * Copier's end.
94  *
95  * Gateway can only be connected to input pin "0" or output pin "0".
96  *
97  * Initial configuration data allows setup audio format of main Copier's pins,
98  * input pin "0" and output pin "0" and prepare PCM conversion routine if any is
99  * required. However Copier supports up to #COPIER_MODULE_OUTPUT_PINS_COUNT
100  * output pins. Before any additional output pin is used in binding operation,
101  * the host driver has to send run-time parameter to setup sink formwat
102  * (#COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT) first to setup a PCM conversion
103  * routine if any is required.
104  */
105 
106 #define IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT		4
107 
108 /*
109  * Gateway can only be connected to input pin "0" or output pin "0".
110  */
111 #define IPC4_COPIER_GATEWAY_PIN 0
112 
113 enum ipc4_copier_features {
114 	/* ff FAST_MODE bit is set in CopierModuleCfg::copier_feature_mask then
115 	 * copier is able to transfer more than ibs. This bit shall be set only if
116 	 * all sinks are connected to data processing queue.
117 	 */
118 	IPC4_COPIER_FAST_MODE = 0
119 };
120 
121 struct ipc4_copier_gateway_cfg {
122 	/* ID of Gateway Node. If node_id is valid, i.e. != -1, copier instance is connected to the
123 	 * specified gateway using either input pin 0 or output pin 0 depending on
124 	 * the node's direction, otherwise the data in this structure is ignored.
125 	 */
126 	union ipc4_connector_node_id node_id;
127 	/* preferred Gateway DMA buffer size (in bytes).
128 	 * FW attempts to allocate DMA buffer according to this value, however it may
129 	 * fall back to IBS/OBS * 2 in case there is no memory available for deeper
130 	 * buffering.
131 	 */
132 	uint32_t dma_buffer_size;
133 	/* length of gateway node configuration blob specified in #config_data.
134 	 * Length must be specified in number of dwords.
135 	 * Refer to the specific gateway documentation for details on the node
136 	 * configuration blob requirements.
137 	 */
138 	uint32_t config_length;
139 	/* gateway node configuration blob */
140 	uint32_t config_data[1];
141 } __attribute__((packed, aligned(4)));
142 
143 struct ipc4_copier_module_cfg {
144 	struct ipc4_base_module_cfg base;
145 
146 	/* audio format for output pin 0 */
147 	struct ipc4_audio_format out_fmt;
148 	uint32_t copier_feature_mask;
149 	struct ipc4_copier_gateway_cfg  gtw_cfg;
150 } __attribute__((packed, aligned(4)));
151 
152 enum ipc4_copier_module_config_params {
153 	/* Use LARGE_CONFIG_SET to initialize timestamp event. Ipc mailbox must
154 	 * contain properly built CopierConfigTimestampInitData struct.
155 	 */
156 	IPC4_COPIER_MODULE_CFG_PARAM_TIMESTAMP_INIT = 1,
157 	/* Use LARGE_CONFIG_SET to initialize copier sink. Ipc mailbox must contain
158 	 * properly built CopierConfigSetSinkFormat struct.
159 	 */
160 	IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT = 2,
161 	/* Use LARGE_CONFIG_SET to initialize and enable on Copier data segment
162 	 * event. Ipc mailbox must contain properly built DataSegmentEnabled struct.
163 	 */
164 	IPC4_COPIER_MODULE_CFG_PARAM_DATA_SEGMENT_ENABLED = 3,
165 	/* Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non
166 	 * HD-A gateways.
167 	 */
168 	IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING = 4,
169 	/* Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non
170 	 * HD-A gateways and corresponding total processed data
171 	 * Sample code to retrieve LlpReadingExtended:
172 	 * Message::LargeConfigOp message(true, COPIER_MODULE_ID, KPB_INSTANCE_ID);
173 	 * message.GetBits().large_param_id = COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED;
174 	 * message.GetBits().init_block = true;
175 	 * message.GetBits().final_block = true;
176 	 * message.GetBits().data_off_size = IPC_OUTPUT_MAILBOX;
177 	 * LlpReadingExtended* output_mailbox = NULL;
178 	 * send_ipc(message, input_mailbox, (uint8_t**)&output_mailbox);
179 	 */
180 	IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED = 5,
181 	/* Use LARGE_CONFIG_SET to setup attenuation on output pins. Data is just
182 	 * uint32_t. Config is only allowed when output pin is set up for 32bit and
183 	 * source is connected to Gateway
184 	 */
185 	IPC4_COPIER_MODULE_CFG_ATTENUATION = 6
186 };
187 
188 struct ipc4_copier_config_timestamp_init_data {
189 	/* Contains low-level configuration for timestamp init.
190 	 * Passed-through directly into ifc _LOCAL_TS_Control Register of
191 	 * corresponding HW i/f from DSP Timestamping Registers.
192 	 */
193 	uint32_t tsctrl_reg;
194 } __attribute__((packed, aligned(4)));
195 
196 struct ipc4_copier_config_set_sink_format {
197 	uint32_t sink_id;
198 	/* Input format used by the source. Must be the same as present
199 	 * if already initialized.
200 	 */
201 	struct ipc4_audio_format source_fmt;
202 	/* Output format used by the sink */
203 	struct ipc4_audio_format sink_fmt;
204 } __attribute__((packed, aligned(4)));
205 
206 #define IPC4_COPIER_DATA_SEGMENT_DISABLE	(0 << 0)
207 #define IPC4_COPIER_DATA_SEGMENT_ENABLE	(1 << 0)
208 #define IPC4_COPIER_DATA_SEGMENT_RESTART	(1 << 1)
209 
210 struct ipc4_data_segment_enabled {
211 	/* Gateway node id */
212 	uint32_t node_id;
213 	/* Indicates whether notification should be enabled (!=0) or disabled (=0).
214 	 * Carries additional information. If bit 1 is set DS will be restarted
215 	 * immediately.
216 	 * Use only as logic or of COPIER_DATA_SEGMENT_*.
217 	 * To disable:
218 	 *   COPIER_DATA_SEGMENT_DISABLE
219 	 * To enable, but finish previous:
220 	 *   COPIER_DATA_SEGMENT_ENABLE
221 	 * To enable, and apply right away:
222 	 *   COPIER_DATA_SEGMENT_ENABLE | COPIER_DATA_SEGMENT_RESTART
223 	 */
224 	uint32_t enabled;
225 	/* Data segment size (in bytes) */
226 	uint32_t data_seg_size;
227 } __attribute__((packed, aligned(4)));
228 
229 /* One of copy_single_channel_cXX() to mux/demux channels into/from copier multi_endpoint_buffer */
230 typedef void (* channel_copy_func)(struct audio_stream __sparse_cache *dst,
231 				   int dst_channel,
232 				   const struct audio_stream __sparse_cache *src,
233 				   int src_channel, int frame_count);
234 
235 struct copier_data {
236 	/*
237 	 * struct ipc4_copier_module_cfg actually has variable size, but we
238 	 * don't need the variable size array at the end, we won't be copying it
239 	 * from the IPC data.
240 	 */
241 	struct ipc4_copier_module_cfg config;
242 	struct comp_dev *endpoint[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
243 	struct comp_buffer *endpoint_buffer[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
244 	uint32_t endpoint_num;
245 
246 	/* buffer to mux/demux data from/to multiple endpoint buffers for ALH multi-gateway case */
247 	struct comp_buffer *multi_endpoint_buffer;
248 	channel_copy_func copy_single_channel;
249 
250 	bool bsource_buffer;
251 
252 	int direction;
253 	/* sample data >> attenuation in range of [1 - 31] */
254 	uint32_t attenuation;
255 
256 	/* pipeline register offset in memory windows 0 */
257 	uint32_t pipeline_reg_offset;
258 	uint64_t host_position;
259 
260 	struct ipc4_audio_format out_fmt[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
261 	pcm_converter_func converter[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
262 	uint64_t input_total_data_processed;
263 	uint64_t output_total_data_processed;
264 	struct host_data *hd;
265 	bool ipc_gtw;
266 };
267 
268 int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
269 		      struct comp_buffer __sparse_cache *sink, int frame);
270 
271 #endif
272